btrfs: only update i_size in truncate paths that care
authorJosef Bacik <josef@toxicpanda.com>
Fri, 3 Dec 2021 22:18:10 +0000 (17:18 -0500)
committerDavid Sterba <dsterba@suse.com>
Fri, 7 Jan 2022 13:18:24 +0000 (14:18 +0100)
We currently will update the i_size of the inode as we truncate it down,
however we skip this if we're calling btrfs_truncate_inode_items from
the tree log code.  However we also don't care about this in the case of
evict.  Instead keep track of this value in the btrfs_truncate_control
and then have btrfs_truncate() and the free space cache truncate path
both do the i_size update themselves.

Reviewed-by: Filipe Manana <fdmanana@suse.com>
Signed-off-by: Josef Bacik <josef@toxicpanda.com>
Reviewed-by: David Sterba <dsterba@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
fs/btrfs/free-space-cache.c
fs/btrfs/inode-item.c
fs/btrfs/inode-item.h
fs/btrfs/inode.c

index a05dd3d..fd469be 100644 (file)
@@ -338,6 +338,9 @@ int btrfs_truncate_free_space_cache(struct btrfs_trans_handle *trans,
         * need to check for -EAGAIN.
         */
        ret = btrfs_truncate_inode_items(trans, root, inode, &control);
+
+       btrfs_inode_safe_disk_i_size_write(inode, control.last_size);
+
        unlock_extent_cached(&inode->io_tree, 0, (u64)-1, &cached_state);
        if (ret)
                goto fail;
index 0946a39..7bb9f55 100644 (file)
@@ -452,7 +452,6 @@ int btrfs_truncate_inode_items(struct btrfs_trans_handle *trans,
        u64 extent_num_bytes = 0;
        u64 extent_offset = 0;
        u64 item_end = 0;
-       u64 last_size = new_size;
        u32 found_type = (u8)-1;
        int del_item;
        int pending_del_nr = 0;
@@ -466,6 +465,8 @@ int btrfs_truncate_inode_items(struct btrfs_trans_handle *trans,
 
        BUG_ON(new_size > 0 && control->min_type != BTRFS_EXTENT_DATA_KEY);
 
+       control->last_size = new_size;
+
        /*
         * For shareable roots we want to back off from time to time, this turns
         * out to be subvolume roots, reloc roots, and data reloc roots.
@@ -644,9 +645,9 @@ delete:
                }
 
                if (del_item)
-                       last_size = found_key.offset;
+                       control->last_size = found_key.offset;
                else
-                       last_size = new_size;
+                       control->last_size = new_size;
                if (del_item) {
                        if (!pending_del_nr) {
                                /* No pending yet, add ourselves */
@@ -739,12 +740,10 @@ out:
                        ret = err;
                }
        }
-       if (root->root_key.objectid != BTRFS_TREE_LOG_OBJECTID) {
-               ASSERT(last_size >= new_size);
-               if (!ret && last_size > new_size)
-                       last_size = new_size;
-               btrfs_inode_safe_disk_i_size_write(inode, last_size);
-       }
+
+       ASSERT(control->last_size >= new_size);
+       if (!ret && control->last_size > new_size)
+               control->last_size = new_size;
 
        btrfs_free_path(path);
        return ret;
index beefba1..883e150 100644 (file)
@@ -26,6 +26,9 @@ struct btrfs_truncate_control {
        /* OUT: the number of extents truncated. */
        u64 extents_found;
 
+       /* OUT: the last size we truncated this inode to. */
+       u64 last_size;
+
        /*
         * IN: minimum key type to remove.  All key types with this type are
         * removed only if their offset >= new_size.
index 9eb57d9..f653242 100644 (file)
@@ -8620,6 +8620,9 @@ static int btrfs_truncate(struct inode *inode, bool skip_writeback)
 
                ret = btrfs_truncate_inode_items(trans, root, BTRFS_I(inode),
                                                 &control);
+
+               btrfs_inode_safe_disk_i_size_write(BTRFS_I(inode), control.last_size);
+
                unlock_extent_cached(&BTRFS_I(inode)->io_tree, lock_start,
                                     (u64)-1, &cached_state);