diff options
author | Miklos Szeredi <mszeredi@redhat.com> | 2024-08-28 15:55:17 +0200 |
---|---|---|
committer | Miklos Szeredi <mszeredi@redhat.com> | 2024-08-28 18:10:29 +0200 |
commit | 76a51ac00ca2a72fe3e168b7fb0e70f75ba6f512 (patch) | |
tree | 6c032a85fcb95bcc21c7861d04683880c98d9453 /fs/fuse/dev.c | |
parent | fuse: fix memory leak in fuse_create_open (diff) | |
download | linux-76a51ac00ca2a72fe3e168b7fb0e70f75ba6f512.tar.xz linux-76a51ac00ca2a72fe3e168b7fb0e70f75ba6f512.zip |
fuse: clear PG_uptodate when using a stolen page
Originally when a stolen page was inserted into fuse's page cache by
fuse_try_move_page(), it would be marked uptodate. Then
fuse_readpages_end() would call SetPageUptodate() again on the already
uptodate page.
Commit 413e8f014c8b ("fuse: Convert fuse_readpages_end() to use
folio_end_read()") changed that by replacing the SetPageUptodate() +
unlock_page() combination with folio_end_read(), which does mostly the
same, except it sets the uptodate flag with an xor operation, which in the
above scenario resulted in the uptodate flag being cleared, which in turn
resulted in EIO being returned on the read.
Fix by clearing PG_uptodate instead of setting it in fuse_try_move_page(),
conforming to the expectation of folio_end_read().
Reported-by: Jürg Billeter <j@bitron.ch>
Debugged-by: Matthew Wilcox <willy@infradead.org>
Fixes: 413e8f014c8b ("fuse: Convert fuse_readpages_end() to use folio_end_read()")
Cc: <stable@vger.kernel.org> # v6.10
Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
Diffstat (limited to '')
-rw-r--r-- | fs/fuse/dev.c | 5 |
1 files changed, 1 insertions, 4 deletions
diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c index a11461ef6022..67443ef07285 100644 --- a/fs/fuse/dev.c +++ b/fs/fuse/dev.c @@ -775,7 +775,6 @@ static int fuse_check_folio(struct folio *folio) (folio->flags & PAGE_FLAGS_CHECK_AT_PREP & ~(1 << PG_locked | 1 << PG_referenced | - 1 << PG_uptodate | 1 << PG_lru | 1 << PG_active | 1 << PG_workingset | @@ -820,9 +819,7 @@ static int fuse_try_move_page(struct fuse_copy_state *cs, struct page **pagep) newfolio = page_folio(buf->page); - if (!folio_test_uptodate(newfolio)) - folio_mark_uptodate(newfolio); - + folio_clear_uptodate(newfolio); folio_clear_mappedtodisk(newfolio); if (fuse_check_folio(newfolio) != 0) |