btrfs: use folio_contains() for EOF detection
authorQu Wenruo <wqu@suse.com>
Thu, 3 Apr 2025 23:40:51 +0000 (10:10 +1030)
committerDavid Sterba <dsterba@suse.com>
Thu, 15 May 2025 12:30:43 +0000 (14:30 +0200)
Currently we use the following pattern to detect if the folio contains
the end of a file:

if (folio->index == end_index)
folio_zero_range();

But that only works if the folio is page sized.

For the following case, it will not work and leave the range beyond EOF
uninitialized:

  The page size is 4K, and the fs block size is also 4K.

16K        20K       24K
        |          |     |   |
                 |
                         EOF at 22K

And we have a large folio sized 8K at file offset 16K.

In that case, the old "folio->index == end_index" will not work, thus
the range [22K, 24K) will not be zeroed out.

Fix the following call sites which use the above pattern:

- add_ra_bio_pages()

- extent_writepage()

Reviewed-by: Filipe Manana <fdmanana@suse.com>
Signed-off-by: Qu Wenruo <wqu@suse.com>
Reviewed-by: David Sterba <dsterba@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
fs/btrfs/compression.c
fs/btrfs/extent_io.c

index 56d970434b4b86028d560087044fef5fa663b1b4..74edd2dd92ff62bc9a93f8ebb02ffd2c42dde8a7 100644 (file)
@@ -523,7 +523,7 @@ static noinline int add_ra_bio_pages(struct inode *inode,
                free_extent_map(em);
                unlock_extent(tree, cur, page_end, NULL);
 
-               if (folio->index == end_index) {
+               if (folio_contains(folio, end_index)) {
                        size_t zero_offset = offset_in_folio(folio, isize);
 
                        if (zero_offset) {
index 12a668dd5e5ec700f95d2a937b4f0efa78bcf6dc..ba067d3461e62e05010901abd2258ad91893907a 100644 (file)
@@ -221,7 +221,7 @@ static void __process_folios_contig(struct address_space *mapping,
 }
 
 static noinline void unlock_delalloc_folio(const struct inode *inode,
-                                          const struct folio *locked_folio,
+                                          struct folio *locked_folio,
                                           u64 start, u64 end)
 {
        ASSERT(locked_folio);
@@ -231,7 +231,7 @@ static noinline void unlock_delalloc_folio(const struct inode *inode,
 }
 
 static noinline int lock_delalloc_folios(struct inode *inode,
-                                        const struct folio *locked_folio,
+                                        struct folio *locked_folio,
                                         u64 start, u64 end)
 {
        struct btrfs_fs_info *fs_info = inode_to_fs_info(inode);
@@ -1707,7 +1707,7 @@ static int extent_writepage(struct folio *folio, struct btrfs_bio_ctrl *bio_ctrl
                return 0;
        }
 
-       if (folio->index == end_index)
+       if (folio_contains(folio, end_index))
                folio_zero_range(folio, pg_offset, folio_size(folio) - pg_offset);
 
        /*