btrfs: fix wrong start offset for delalloc space release during mmap write
authorFilipe Manana <fdmanana@suse.com>
Wed, 14 May 2025 09:30:58 +0000 (10:30 +0100)
committerDavid Sterba <dsterba@suse.com>
Thu, 15 May 2025 16:24:07 +0000 (18:24 +0200)
If we're doing a mmap write against a folio that has i_size somewhere in
the middle and we have multiple sectors in the folio, we may have to
release excess space previously reserved, for the range going from the
rounded up (to sector size) i_size to the folio's end offset. We are
calculating the right amount to release and passing it to
btrfs_delalloc_release_space(), but we are passing the wrong start offset
of that range - we're passing the folio's start offset instead of the
end offset, plus 1, of the range for which we keep the reservation. This
may result in releasing more space then we should and eventually trigger
an underflow of the data space_info's bytes_may_use counter.

So fix this by passing the start offset as 'end + 1' instead of
'page_start' to btrfs_delalloc_release_space().

Fixes: d0b7da88f640 ("Btrfs: btrfs_page_mkwrite: Reserve space in sectorsized units")
Reviewed-by: Qu Wenruo <wqu@suse.com>
Signed-off-by: Filipe Manana <fdmanana@suse.com>
Reviewed-by: David Sterba <dsterba@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
fs/btrfs/file.c

index 660a73b6af90236edae4b005aee3b3e58673b817..32aad1b02b01ad4235b2267c56bf735d142b093a 100644 (file)
@@ -1918,7 +1918,7 @@ again:
                if (reserved_space < fsize) {
                        end = page_start + reserved_space - 1;
                        btrfs_delalloc_release_space(BTRFS_I(inode),
-                                       data_reserved, page_start,
+                                       data_reserved, end + 1,
                                        fsize - reserved_space, true);
                }
        }