]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
btrfs: defrag: replace hard coded PAGE_SIZE with sectorsize
authorQu Wenruo <wqu@suse.com>
Fri, 6 Aug 2021 08:12:34 +0000 (16:12 +0800)
committerDavid Sterba <dsterba@suse.com>
Tue, 26 Oct 2021 17:06:15 +0000 (19:06 +0200)
When testing subpage defrag support, I always find some strange inode
nbytes error, after a lot of debugging, it turns out that
defrag_lookup_extent() is using PAGE_SIZE as size for
lookup_extent_mapping().

Since lookup_extent_mapping() is calling __lookup_extent_mapping() with
@strict == 1, this means any extent map smaller than one page will be
ignored, prevent subpage defrag to grab a correct extent map.

There are quite some PAGE_SIZE usage in ioctl.c, but most of them are
correct usages, and can be one of the following cases:

- ioctl structure size check
  We want ioctl structure to be contained inside one page.

- real page operations

The remaining cases in defrag_lookup_extent() and
check_defrag_in_cache() will be addressed in this patch.

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/ioctl.c

index b8b30e11a226851b8c831a2c5bf4d50aab6523bc..8e9c51acc9c76caf5e0c0004b9e4482afddddf57 100644 (file)
@@ -997,10 +997,11 @@ static int check_defrag_in_cache(struct inode *inode, u64 offset, u32 thresh)
        struct extent_io_tree *io_tree = &BTRFS_I(inode)->io_tree;
        struct extent_map *em = NULL;
        struct extent_map_tree *em_tree = &BTRFS_I(inode)->extent_tree;
+       const u32 sectorsize = btrfs_sb(inode->i_sb)->sectorsize;
        u64 end;
 
        read_lock(&em_tree->lock);
-       em = lookup_extent_mapping(em_tree, offset, PAGE_SIZE);
+       em = lookup_extent_mapping(em_tree, offset, sectorsize);
        read_unlock(&em_tree->lock);
 
        if (em) {
@@ -1090,23 +1091,23 @@ static struct extent_map *defrag_lookup_extent(struct inode *inode, u64 start)
        struct extent_map_tree *em_tree = &BTRFS_I(inode)->extent_tree;
        struct extent_io_tree *io_tree = &BTRFS_I(inode)->io_tree;
        struct extent_map *em;
-       u64 len = PAGE_SIZE;
+       const u32 sectorsize = BTRFS_I(inode)->root->fs_info->sectorsize;
 
        /*
         * hopefully we have this extent in the tree already, try without
         * the full extent lock
         */
        read_lock(&em_tree->lock);
-       em = lookup_extent_mapping(em_tree, start, len);
+       em = lookup_extent_mapping(em_tree, start, sectorsize);
        read_unlock(&em_tree->lock);
 
        if (!em) {
                struct extent_state *cached = NULL;
-               u64 end = start + len - 1;
+               u64 end = start + sectorsize - 1;
 
                /* get the big lock and read metadata off disk */
                lock_extent_bits(io_tree, start, end, &cached);
-               em = btrfs_get_extent(BTRFS_I(inode), NULL, 0, start, len);
+               em = btrfs_get_extent(BTRFS_I(inode), NULL, 0, start, sectorsize);
                unlock_extent_cached(io_tree, start, end, &cached);
 
                if (IS_ERR(em))