UPSTREAM: 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
f268eedddf35 ("squashfs: extend "page actor" to handle missing pages")
Link: https://lkml.kernel.org/r/20220822215430.15933-1-phillip@squashfs.org.uk
Fixes: f268eedddf35 ("squashfs: extend "page actor" to handle missing pages")
Reported-by: Chris Murphy <lists@colorremedies.com>
Signed-off-by: Phillip Lougher <phillip@squashfs.org.uk>
Cc: <stable@vger.kernel.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Bug: 290900323
(cherry picked from commit 1f13dff09ffc8bcf6aa20639b638d813379c7f6b)
Change-Id: I1363aff27964ab2c7753630e5b7501dc9db8bb00
Signed-off-by: Lecopzer Chen <lecopzer.chen@mediatek.com>
This commit is contained in:
committed by
Lecopzer Chen
parent
357f4067df
commit
d35f75a39f
@@ -591,7 +591,7 @@ static void squashfs_readahead(struct readahead_control *ractl)
|
||||
|
||||
res = squashfs_read_data(inode->i_sb, block, bsize, NULL, actor);
|
||||
|
||||
kfree(actor);
|
||||
squashfs_page_actor_free(actor);
|
||||
|
||||
if (res == expected) {
|
||||
int bytes;
|
||||
|
||||
@@ -74,7 +74,7 @@ int squashfs_readpage_block(struct page *target_page, u64 block, int bsize,
|
||||
/* Decompress directly into the page cache buffers */
|
||||
res = squashfs_read_data(inode->i_sb, block, bsize, NULL, actor);
|
||||
|
||||
kfree(actor);
|
||||
squashfs_page_actor_free(actor);
|
||||
|
||||
if (res < 0)
|
||||
goto mark_errored;
|
||||
|
||||
@@ -52,6 +52,7 @@ struct squashfs_page_actor *squashfs_page_actor_init(void **buffer,
|
||||
actor->buffer = buffer;
|
||||
actor->pages = pages;
|
||||
actor->next_page = 0;
|
||||
actor->tmp_buffer = NULL;
|
||||
actor->squashfs_first_page = cache_first_page;
|
||||
actor->squashfs_next_page = cache_next_page;
|
||||
actor->squashfs_finish_page = cache_finish_page;
|
||||
@@ -68,20 +69,9 @@ static void *handle_next_page(struct squashfs_page_actor *actor)
|
||||
|
||||
if ((actor->next_page == actor->pages) ||
|
||||
(actor->next_index != actor->page[actor->next_page]->index)) {
|
||||
if (actor->alloc_buffer) {
|
||||
void *tmp_buffer = kmalloc(PAGE_SIZE, GFP_KERNEL);
|
||||
|
||||
if (tmp_buffer) {
|
||||
actor->tmp_buffer = tmp_buffer;
|
||||
actor->next_index++;
|
||||
actor->returned_pages++;
|
||||
return tmp_buffer;
|
||||
}
|
||||
}
|
||||
|
||||
actor->next_index++;
|
||||
actor->returned_pages++;
|
||||
return ERR_PTR(-ENOMEM);
|
||||
return actor->alloc_buffer ? actor->tmp_buffer : ERR_PTR(-ENOMEM);
|
||||
}
|
||||
|
||||
actor->next_index++;
|
||||
@@ -96,11 +86,10 @@ static void *direct_first_page(struct squashfs_page_actor *actor)
|
||||
|
||||
static void *direct_next_page(struct squashfs_page_actor *actor)
|
||||
{
|
||||
if (actor->pageaddr)
|
||||
if (actor->pageaddr) {
|
||||
kunmap_local(actor->pageaddr);
|
||||
|
||||
kfree(actor->tmp_buffer);
|
||||
actor->pageaddr = actor->tmp_buffer = NULL;
|
||||
actor->pageaddr = NULL;
|
||||
}
|
||||
|
||||
return handle_next_page(actor);
|
||||
}
|
||||
@@ -109,8 +98,6 @@ static void direct_finish_page(struct squashfs_page_actor *actor)
|
||||
{
|
||||
if (actor->pageaddr)
|
||||
kunmap_local(actor->pageaddr);
|
||||
|
||||
kfree(actor->tmp_buffer);
|
||||
}
|
||||
|
||||
struct squashfs_page_actor *squashfs_page_actor_init_special(struct squashfs_sb_info *msblk,
|
||||
@@ -121,6 +108,16 @@ struct squashfs_page_actor *squashfs_page_actor_init_special(struct squashfs_sb_
|
||||
if (actor == NULL)
|
||||
return NULL;
|
||||
|
||||
if (msblk->decompressor->alloc_buffer) {
|
||||
actor->tmp_buffer = kmalloc(PAGE_SIZE, GFP_KERNEL);
|
||||
|
||||
if (actor->tmp_buffer == NULL) {
|
||||
kfree(actor);
|
||||
return NULL;
|
||||
}
|
||||
} else
|
||||
actor->tmp_buffer = NULL;
|
||||
|
||||
actor->length = length ? : pages * PAGE_SIZE;
|
||||
actor->page = page;
|
||||
actor->pages = pages;
|
||||
@@ -128,7 +125,6 @@ struct squashfs_page_actor *squashfs_page_actor_init_special(struct squashfs_sb_
|
||||
actor->returned_pages = 0;
|
||||
actor->next_index = page[0]->index & ~((1 << (msblk->block_log - PAGE_SHIFT)) - 1);
|
||||
actor->pageaddr = NULL;
|
||||
actor->tmp_buffer = NULL;
|
||||
actor->alloc_buffer = msblk->decompressor->alloc_buffer;
|
||||
actor->squashfs_first_page = direct_first_page;
|
||||
actor->squashfs_next_page = direct_next_page;
|
||||
|
||||
@@ -74,6 +74,11 @@ extern struct squashfs_page_actor *squashfs_page_actor_init(void **buffer,
|
||||
extern struct squashfs_page_actor *squashfs_page_actor_init_special(
|
||||
struct squashfs_sb_info *msblk,
|
||||
struct page **page, int pages, int length);
|
||||
static inline void squashfs_page_actor_free(struct squashfs_page_actor *actor)
|
||||
{
|
||||
kfree(actor->tmp_buffer);
|
||||
kfree(actor);
|
||||
}
|
||||
static inline void *squashfs_first_page(struct squashfs_page_actor *actor)
|
||||
{
|
||||
return actor->squashfs_first_page(actor);
|
||||
|
||||
Reference in New Issue
Block a user