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>

authored by Phillip Lougher and committed by Andrew Morton 1f13dff0 d26f6070

Changed files
+22 -21
fs
+1 -1
fs/squashfs/file.c
··· 593 593 594 594 res = squashfs_read_data(inode->i_sb, block, bsize, NULL, actor); 595 595 596 - kfree(actor); 596 + squashfs_page_actor_free(actor); 597 597 598 598 if (res == expected) { 599 599 int bytes;
+1 -1
fs/squashfs/file_direct.c
··· 74 74 /* Decompress directly into the page cache buffers */ 75 75 res = squashfs_read_data(inode->i_sb, block, bsize, NULL, actor); 76 76 77 - kfree(actor); 77 + squashfs_page_actor_free(actor); 78 78 79 79 if (res < 0) 80 80 goto mark_errored;
+15 -19
fs/squashfs/page_actor.c
··· 52 52 actor->buffer = buffer; 53 53 actor->pages = pages; 54 54 actor->next_page = 0; 55 + actor->tmp_buffer = NULL; 55 56 actor->squashfs_first_page = cache_first_page; 56 57 actor->squashfs_next_page = cache_next_page; 57 58 actor->squashfs_finish_page = cache_finish_page; ··· 69 68 70 69 if ((actor->next_page == actor->pages) || 71 70 (actor->next_index != actor->page[actor->next_page]->index)) { 72 - if (actor->alloc_buffer) { 73 - void *tmp_buffer = kmalloc(PAGE_SIZE, GFP_KERNEL); 74 - 75 - if (tmp_buffer) { 76 - actor->tmp_buffer = tmp_buffer; 77 - actor->next_index++; 78 - actor->returned_pages++; 79 - return tmp_buffer; 80 - } 81 - } 82 - 83 71 actor->next_index++; 84 72 actor->returned_pages++; 85 - return ERR_PTR(-ENOMEM); 73 + return actor->alloc_buffer ? actor->tmp_buffer : ERR_PTR(-ENOMEM); 86 74 } 87 75 88 76 actor->next_index++; ··· 86 96 87 97 static void *direct_next_page(struct squashfs_page_actor *actor) 88 98 { 89 - if (actor->pageaddr) 99 + if (actor->pageaddr) { 90 100 kunmap_local(actor->pageaddr); 91 - 92 - kfree(actor->tmp_buffer); 93 - actor->pageaddr = actor->tmp_buffer = NULL; 101 + actor->pageaddr = NULL; 102 + } 94 103 95 104 return handle_next_page(actor); 96 105 } ··· 98 109 { 99 110 if (actor->pageaddr) 100 111 kunmap_local(actor->pageaddr); 101 - 102 - kfree(actor->tmp_buffer); 103 112 } 104 113 105 114 struct squashfs_page_actor *squashfs_page_actor_init_special(struct squashfs_sb_info *msblk, ··· 108 121 if (actor == NULL) 109 122 return NULL; 110 123 124 + if (msblk->decompressor->alloc_buffer) { 125 + actor->tmp_buffer = kmalloc(PAGE_SIZE, GFP_KERNEL); 126 + 127 + if (actor->tmp_buffer == NULL) { 128 + kfree(actor); 129 + return NULL; 130 + } 131 + } else 132 + actor->tmp_buffer = NULL; 133 + 111 134 actor->length = length ? : pages * PAGE_SIZE; 112 135 actor->page = page; 113 136 actor->pages = pages; ··· 125 128 actor->returned_pages = 0; 126 129 actor->next_index = page[0]->index & ~((1 << (msblk->block_log - PAGE_SHIFT)) - 1); 127 130 actor->pageaddr = NULL; 128 - actor->tmp_buffer = NULL; 129 131 actor->alloc_buffer = msblk->decompressor->alloc_buffer; 130 132 actor->squashfs_first_page = direct_first_page; 131 133 actor->squashfs_next_page = direct_next_page;
+5
fs/squashfs/page_actor.h
··· 29 29 extern struct squashfs_page_actor *squashfs_page_actor_init_special( 30 30 struct squashfs_sb_info *msblk, 31 31 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 + } 32 37 static inline void *squashfs_first_page(struct squashfs_page_actor *actor) 33 38 { 34 39 return actor->squashfs_first_page(actor);