From: Phillip Lougher phillip@squashfs.org.uk
commit c9199de82bad03bceb94ec3c5195c879d7e11911 upstream.
The readahead code will try to extend readahead to the entire size of the Squashfs data block.
But, it didn't take into account that the last block at the end of the file may not be a whole block. In this case, the code would extend readahead to beyond the end of the file, leaving trailing pages.
Fix this by only requesting the expected number of pages.
Link: https://lkml.kernel.org/r/20221020223616.7571-3-phillip@squashfs.org.uk Fixes: 8fc78b6fe24c ("squashfs: implement readahead") Signed-off-by: Phillip Lougher phillip@squashfs.org.uk Tested-by: Bagas Sanjaya bagasdotme@gmail.com Reported-by: Marc Miltenberger marcmiltenberger@gmail.com Cc: Dimitri John Ledkov dimitri.ledkov@canonical.com Cc: Hsin-Yi Wang hsinyi@chromium.org Cc: Mirsad Goran Todorovac mirsad.todorovac@alu.unizg.hr Cc: Slade Watkins srw@sladewatkins.net Cc: Thorsten Leemhuis regressions@leemhuis.info Cc: stable@vger.kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org
Signed-off-by: Andrew Morton akpm@linux-foundation.org --- fs/squashfs/file.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-)
diff --git a/fs/squashfs/file.c b/fs/squashfs/file.c index e526eb7a1658..f0afd4d6fd30 100644 --- a/fs/squashfs/file.c +++ b/fs/squashfs/file.c @@ -559,6 +559,12 @@ static void squashfs_readahead(struct readahead_control *ractl) unsigned int expected; struct page *last_page;
+ expected = start >> msblk->block_log == file_end ? + (i_size_read(inode) & (msblk->block_size - 1)) : + msblk->block_size; + + max_pages = (expected + PAGE_SIZE - 1) >> PAGE_SHIFT; + nr_pages = __readahead_batch(ractl, pages, max_pages); if (!nr_pages) break; @@ -567,13 +573,10 @@ static void squashfs_readahead(struct readahead_control *ractl) goto skip_pages;
index = pages[0]->index >> shift; + if ((pages[nr_pages - 1]->index >> shift) != index) goto skip_pages;
- expected = index == file_end ? - (i_size_read(inode) & (msblk->block_size - 1)) : - msblk->block_size; - if (index == file_end && squashfs_i(inode)->fragment_block != SQUASHFS_INVALID_BLK) { res = squashfs_readahead_fragment(pages, nr_pages,