@@ -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;
@@ -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.
@@ -649,9 +650,9 @@ int btrfs_truncate_inode_items(struct btrfs_trans_handle *trans,
}
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 */
@@ -744,12 +745,10 @@ int btrfs_truncate_inode_items(struct btrfs_trans_handle *trans,
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;
@@ -16,6 +16,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.
@@ -8620,6 +8620,10 @@ 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);
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. Signed-off-by: Josef Bacik <josef@toxicpanda.com> --- fs/btrfs/free-space-cache.c | 3 +++ fs/btrfs/inode-item.c | 17 ++++++++--------- fs/btrfs/inode-item.h | 3 +++ fs/btrfs/inode.c | 4 ++++ 4 files changed, 18 insertions(+), 9 deletions(-)