Skip to content

Commit 1f13dff

Browse files
plougherakpm00
authored andcommitted
squashfs: don't call kmalloc in decompressors
The decompressors may be called while in an atomic section. So move the kmalloc() out of this path, and into the "page actor" init function. This fixes a regression introduced by commit f268eed ("squashfs: extend "page actor" to handle missing pages") Link: https://lkml.kernel.org/r/[email protected] Fixes: f268eed ("squashfs: extend "page actor" to handle missing pages") Reported-by: Chris Murphy <[email protected]> Signed-off-by: Phillip Lougher <[email protected]> Cc: <[email protected]> Signed-off-by: Andrew Morton <[email protected]>
1 parent d26f607 commit 1f13dff

File tree

4 files changed

+22
-21
lines changed

4 files changed

+22
-21
lines changed

fs/squashfs/file.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -593,7 +593,7 @@ static void squashfs_readahead(struct readahead_control *ractl)
593593

594594
res = squashfs_read_data(inode->i_sb, block, bsize, NULL, actor);
595595

596-
kfree(actor);
596+
squashfs_page_actor_free(actor);
597597

598598
if (res == expected) {
599599
int bytes;

fs/squashfs/file_direct.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ int squashfs_readpage_block(struct page *target_page, u64 block, int bsize,
7474
/* Decompress directly into the page cache buffers */
7575
res = squashfs_read_data(inode->i_sb, block, bsize, NULL, actor);
7676

77-
kfree(actor);
77+
squashfs_page_actor_free(actor);
7878

7979
if (res < 0)
8080
goto mark_errored;

fs/squashfs/page_actor.c

Lines changed: 15 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ struct squashfs_page_actor *squashfs_page_actor_init(void **buffer,
5252
actor->buffer = buffer;
5353
actor->pages = pages;
5454
actor->next_page = 0;
55+
actor->tmp_buffer = NULL;
5556
actor->squashfs_first_page = cache_first_page;
5657
actor->squashfs_next_page = cache_next_page;
5758
actor->squashfs_finish_page = cache_finish_page;
@@ -68,20 +69,9 @@ static void *handle_next_page(struct squashfs_page_actor *actor)
6869

6970
if ((actor->next_page == actor->pages) ||
7071
(actor->next_index != actor->page[actor->next_page]->index)) {
71-
if (actor->alloc_buffer) {
72-
void *tmp_buffer = kmalloc(PAGE_SIZE, GFP_KERNEL);
73-
74-
if (tmp_buffer) {
75-
actor->tmp_buffer = tmp_buffer;
76-
actor->next_index++;
77-
actor->returned_pages++;
78-
return tmp_buffer;
79-
}
80-
}
81-
8272
actor->next_index++;
8373
actor->returned_pages++;
84-
return ERR_PTR(-ENOMEM);
74+
return actor->alloc_buffer ? actor->tmp_buffer : ERR_PTR(-ENOMEM);
8575
}
8676

8777
actor->next_index++;
@@ -96,11 +86,10 @@ static void *direct_first_page(struct squashfs_page_actor *actor)
9686

9787
static void *direct_next_page(struct squashfs_page_actor *actor)
9888
{
99-
if (actor->pageaddr)
89+
if (actor->pageaddr) {
10090
kunmap_local(actor->pageaddr);
101-
102-
kfree(actor->tmp_buffer);
103-
actor->pageaddr = actor->tmp_buffer = NULL;
91+
actor->pageaddr = NULL;
92+
}
10493

10594
return handle_next_page(actor);
10695
}
@@ -109,8 +98,6 @@ static void direct_finish_page(struct squashfs_page_actor *actor)
10998
{
11099
if (actor->pageaddr)
111100
kunmap_local(actor->pageaddr);
112-
113-
kfree(actor->tmp_buffer);
114101
}
115102

116103
struct squashfs_page_actor *squashfs_page_actor_init_special(struct squashfs_sb_info *msblk,
@@ -121,14 +108,23 @@ struct squashfs_page_actor *squashfs_page_actor_init_special(struct squashfs_sb_
121108
if (actor == NULL)
122109
return NULL;
123110

111+
if (msblk->decompressor->alloc_buffer) {
112+
actor->tmp_buffer = kmalloc(PAGE_SIZE, GFP_KERNEL);
113+
114+
if (actor->tmp_buffer == NULL) {
115+
kfree(actor);
116+
return NULL;
117+
}
118+
} else
119+
actor->tmp_buffer = NULL;
120+
124121
actor->length = length ? : pages * PAGE_SIZE;
125122
actor->page = page;
126123
actor->pages = pages;
127124
actor->next_page = 0;
128125
actor->returned_pages = 0;
129126
actor->next_index = page[0]->index & ~((1 << (msblk->block_log - PAGE_SHIFT)) - 1);
130127
actor->pageaddr = NULL;
131-
actor->tmp_buffer = NULL;
132128
actor->alloc_buffer = msblk->decompressor->alloc_buffer;
133129
actor->squashfs_first_page = direct_first_page;
134130
actor->squashfs_next_page = direct_next_page;

fs/squashfs/page_actor.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,11 @@ extern struct squashfs_page_actor *squashfs_page_actor_init(void **buffer,
2929
extern struct squashfs_page_actor *squashfs_page_actor_init_special(
3030
struct squashfs_sb_info *msblk,
3131
struct page **page, int pages, int length);
32+
static inline void squashfs_page_actor_free(struct squashfs_page_actor *actor)
33+
{
34+
kfree(actor->tmp_buffer);
35+
kfree(actor);
36+
}
3237
static inline void *squashfs_first_page(struct squashfs_page_actor *actor)
3338
{
3439
return actor->squashfs_first_page(actor);

0 commit comments

Comments
 (0)