| From: Phillip Lougher <phillip@squashfs.org.uk> |
| Subject: squashfs: fix extending readahead beyond end of file |
| Date: Thu, 20 Oct 2022 23:36:15 +0100 |
| |
| 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: Andrew Morton <akpm@linux-foundation.org> |
| --- |
| |
| |
| --- a/fs/squashfs/file.c~squashfs-fix-extending-readahead-beyond-end-of-file |
| +++ a/fs/squashfs/file.c |
| @@ -559,6 +559,12 @@ static void squashfs_readahead(struct re |
| 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 re |
| 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, |
| _ |