btrfs: only update i_size in truncate paths that care

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>
This commit is contained in:
Josef Bacik 2021-12-03 17:18:10 -05:00 коммит произвёл David Sterba
Родитель d9ac19c380
Коммит c2ddb612a8
4 изменённых файлов: 17 добавлений и 9 удалений

Просмотреть файл

@ -338,6 +338,9 @@ int btrfs_truncate_free_space_cache(struct btrfs_trans_handle *trans,
* need to check for -EAGAIN. * need to check for -EAGAIN.
*/ */
ret = btrfs_truncate_inode_items(trans, root, inode, &control); 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); unlock_extent_cached(&inode->io_tree, 0, (u64)-1, &cached_state);
if (ret) if (ret)
goto fail; goto fail;

Просмотреть файл

@ -452,7 +452,6 @@ int btrfs_truncate_inode_items(struct btrfs_trans_handle *trans,
u64 extent_num_bytes = 0; u64 extent_num_bytes = 0;
u64 extent_offset = 0; u64 extent_offset = 0;
u64 item_end = 0; u64 item_end = 0;
u64 last_size = new_size;
u32 found_type = (u8)-1; u32 found_type = (u8)-1;
int del_item; int del_item;
int pending_del_nr = 0; 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); 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 * 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. * out to be subvolume roots, reloc roots, and data reloc roots.
@ -644,9 +645,9 @@ delete:
} }
if (del_item) if (del_item)
last_size = found_key.offset; control->last_size = found_key.offset;
else else
last_size = new_size; control->last_size = new_size;
if (del_item) { if (del_item) {
if (!pending_del_nr) { if (!pending_del_nr) {
/* No pending yet, add ourselves */ /* No pending yet, add ourselves */
@ -739,12 +740,10 @@ out:
ret = err; ret = err;
} }
} }
if (root->root_key.objectid != BTRFS_TREE_LOG_OBJECTID) {
ASSERT(last_size >= new_size); ASSERT(control->last_size >= new_size);
if (!ret && last_size > new_size) if (!ret && control->last_size > new_size)
last_size = new_size; control->last_size = new_size;
btrfs_inode_safe_disk_i_size_write(inode, last_size);
}
btrfs_free_path(path); btrfs_free_path(path);
return ret; return ret;

Просмотреть файл

@ -26,6 +26,9 @@ struct btrfs_truncate_control {
/* OUT: the number of extents truncated. */ /* OUT: the number of extents truncated. */
u64 extents_found; 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 * IN: minimum key type to remove. All key types with this type are
* removed only if their offset >= new_size. * removed only if their offset >= new_size.

Просмотреть файл

@ -8620,6 +8620,9 @@ static int btrfs_truncate(struct inode *inode, bool skip_writeback)
ret = btrfs_truncate_inode_items(trans, root, BTRFS_I(inode), ret = btrfs_truncate_inode_items(trans, root, BTRFS_I(inode),
&control); &control);
btrfs_inode_safe_disk_i_size_write(BTRFS_I(inode), control.last_size);
unlock_extent_cached(&BTRFS_I(inode)->io_tree, lock_start, unlock_extent_cached(&BTRFS_I(inode)->io_tree, lock_start,
(u64)-1, &cached_state); (u64)-1, &cached_state);