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:
Родитель
d9ac19c380
Коммит
c2ddb612a8
|
@ -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);
|
||||||
|
|
||||||
|
|
Загрузка…
Ссылка в новой задаче