diff options
Diffstat (limited to 'fs/btrfs')
-rw-r--r-- | fs/btrfs/free-space-cache.c | 7 | ||||
-rw-r--r-- | fs/btrfs/inode-item.c | 25 | ||||
-rw-r--r-- | fs/btrfs/inode-item.h | 18 | ||||
-rw-r--r-- | fs/btrfs/inode.c | 18 | ||||
-rw-r--r-- | fs/btrfs/tree-log.c | 6 |
5 files changed, 46 insertions, 28 deletions
diff --git a/fs/btrfs/free-space-cache.c b/fs/btrfs/free-space-cache.c index 28b9c63ba536..a05dd3d29695 100644 --- a/fs/btrfs/free-space-cache.c +++ b/fs/btrfs/free-space-cache.c @@ -291,6 +291,10 @@ int btrfs_truncate_free_space_cache(struct btrfs_trans_handle *trans, struct btrfs_block_group *block_group, struct inode *vfs_inode) { + struct btrfs_truncate_control control = { + .new_size = 0, + .min_type = BTRFS_EXTENT_DATA_KEY, + }; struct btrfs_inode *inode = BTRFS_I(vfs_inode); struct btrfs_root *root = inode->root; struct extent_state *cached_state = NULL; @@ -333,8 +337,7 @@ int btrfs_truncate_free_space_cache(struct btrfs_trans_handle *trans, * We skip the throttling logic for free space cache inodes, so we don't * need to check for -EAGAIN. */ - ret = btrfs_truncate_inode_items(trans, root, inode, 0, - BTRFS_EXTENT_DATA_KEY, NULL); + ret = btrfs_truncate_inode_items(trans, root, inode, &control); unlock_extent_cached(&inode->io_tree, 0, (u64)-1, &cached_state); if (ret) goto fail; diff --git a/fs/btrfs/inode-item.c b/fs/btrfs/inode-item.c index b79578895d3b..0946a3912afd 100644 --- a/fs/btrfs/inode-item.c +++ b/fs/btrfs/inode-item.c @@ -425,16 +425,8 @@ int btrfs_lookup_inode(struct btrfs_trans_handle *trans, struct btrfs_root * @trans: A transaction handle. * @root: The root from which to remove items. * @inode: The inode whose items we want to remove. - * @new_size: The new i_size for the inode. This is only applicable when - * @min_type is BTRFS_EXTENT_DATA_KEY, must be 0 otherwise. - * @min_type: The minimum key type to remove. All keys with a type - * greater than this value are removed and all keys with - * this type are removed only if their offset is >= @new_size. - * @extents_found: Output parameter that will contain the number of file - * extent items that were removed or adjusted to the new - * inode i_size. The caller is responsible for initializing - * the counter. Also, it can be NULL if the caller does not - * need this counter. + * @control: The btrfs_truncate_control to control how and what we + * are truncating. * * Remove all keys associated with the inode from the given root that have a key * with a type greater than or equals to @min_type. When @min_type has a value of @@ -448,8 +440,7 @@ int btrfs_lookup_inode(struct btrfs_trans_handle *trans, struct btrfs_root int btrfs_truncate_inode_items(struct btrfs_trans_handle *trans, struct btrfs_root *root, struct btrfs_inode *inode, - u64 new_size, u32 min_type, - u64 *extents_found) + struct btrfs_truncate_control *control) { struct btrfs_fs_info *fs_info = root->fs_info; struct btrfs_path *path; @@ -457,6 +448,7 @@ int btrfs_truncate_inode_items(struct btrfs_trans_handle *trans, struct btrfs_file_extent_item *fi; struct btrfs_key key; struct btrfs_key found_key; + u64 new_size = control->new_size; u64 extent_num_bytes = 0; u64 extent_offset = 0; u64 item_end = 0; @@ -472,7 +464,7 @@ int btrfs_truncate_inode_items(struct btrfs_trans_handle *trans, bool be_nice = false; bool should_throttle = false; - BUG_ON(new_size > 0 && min_type != BTRFS_EXTENT_DATA_KEY); + BUG_ON(new_size > 0 && control->min_type != BTRFS_EXTENT_DATA_KEY); /* * For shareable roots we want to back off from time to time, this turns @@ -525,7 +517,7 @@ search_again: if (found_key.objectid != ino) break; - if (found_type < min_type) + if (found_type < control->min_type) break; item_end = found_key.offset; @@ -548,7 +540,7 @@ search_again: } item_end--; } - if (found_type > min_type) { + if (found_type > control->min_type) { del_item = 1; } else { if (item_end < new_size) @@ -563,8 +555,7 @@ search_again: if (found_type != BTRFS_EXTENT_DATA_KEY) goto delete; - if (extents_found != NULL) - (*extents_found)++; + control->extents_found++; if (extent_type != BTRFS_FILE_EXTENT_INLINE) { u64 num_dec; diff --git a/fs/btrfs/inode-item.h b/fs/btrfs/inode-item.h index 4464d7026180..beefba1f26bc 100644 --- a/fs/btrfs/inode-item.h +++ b/fs/btrfs/inode-item.h @@ -19,10 +19,24 @@ struct extent_buffer; */ #define BTRFS_NEED_TRUNCATE_BLOCK 1 +struct btrfs_truncate_control { + /* IN: the size we're truncating to. */ + u64 new_size; + + /* OUT: the number of extents truncated. */ + u64 extents_found; + + /* + * IN: minimum key type to remove. All key types with this type are + * removed only if their offset >= new_size. + */ + u32 min_type; +}; + int btrfs_truncate_inode_items(struct btrfs_trans_handle *trans, struct btrfs_root *root, - struct btrfs_inode *inode, u64 new_size, - u32 min_type, u64 *extents_found); + struct btrfs_inode *inode, + struct btrfs_truncate_control *control); int btrfs_insert_inode_ref(struct btrfs_trans_handle *trans, struct btrfs_root *root, const char *name, int name_len, diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 7aabf419e967..9eb57d90ff59 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c @@ -5251,6 +5251,11 @@ void btrfs_evict_inode(struct inode *inode) btrfs_i_size_write(BTRFS_I(inode), 0); while (1) { + struct btrfs_truncate_control control = { + .new_size = 0, + .min_type = 0, + }; + trans = evict_refill_and_join(root, rsv); if (IS_ERR(trans)) goto free_rsv; @@ -5258,7 +5263,7 @@ void btrfs_evict_inode(struct inode *inode) trans->block_rsv = rsv; ret = btrfs_truncate_inode_items(trans, root, BTRFS_I(inode), - 0, 0, NULL); + &control); trans->block_rsv = &fs_info->trans_block_rsv; btrfs_end_transaction(trans); btrfs_btree_balance_dirty(fs_info); @@ -8527,6 +8532,9 @@ out_noreserve: static int btrfs_truncate(struct inode *inode, bool skip_writeback) { + struct btrfs_truncate_control control = { + .min_type = BTRFS_EXTENT_DATA_KEY, + }; struct btrfs_fs_info *fs_info = btrfs_sb(inode->i_sb); struct btrfs_root *root = BTRFS_I(inode)->root; struct btrfs_block_rsv *rsv; @@ -8534,7 +8542,6 @@ static int btrfs_truncate(struct inode *inode, bool skip_writeback) struct btrfs_trans_handle *trans; u64 mask = fs_info->sectorsize - 1; u64 min_size = btrfs_calc_metadata_size(fs_info, 1); - u64 extents_found = 0; if (!skip_writeback) { ret = btrfs_wait_ordered_range(inode, inode->i_size & (~mask), @@ -8599,6 +8606,7 @@ static int btrfs_truncate(struct inode *inode, bool skip_writeback) const u64 new_size = inode->i_size; const u64 lock_start = ALIGN_DOWN(new_size, fs_info->sectorsize); + control.new_size = new_size; lock_extent_bits(&BTRFS_I(inode)->io_tree, lock_start, (u64)-1, &cached_state); /* @@ -8611,9 +8619,7 @@ static int btrfs_truncate(struct inode *inode, bool skip_writeback) (u64)-1, 0); ret = btrfs_truncate_inode_items(trans, root, BTRFS_I(inode), - inode->i_size, - BTRFS_EXTENT_DATA_KEY, - &extents_found); + &control); unlock_extent_cached(&BTRFS_I(inode)->io_tree, lock_start, (u64)-1, &cached_state); @@ -8692,7 +8698,7 @@ out: * between the old i_size and the new i_size, and there were no prealloc * extents beyond i_size to drop. */ - if (extents_found > 0) + if (control.extents_found > 0) set_bit(BTRFS_INODE_NEEDS_FULL_SYNC, &BTRFS_I(inode)->runtime_flags); return ret; diff --git a/fs/btrfs/tree-log.c b/fs/btrfs/tree-log.c index 64b42f4b11f2..c732a429a1c6 100644 --- a/fs/btrfs/tree-log.c +++ b/fs/btrfs/tree-log.c @@ -4098,11 +4098,15 @@ static int truncate_inode_items(struct btrfs_trans_handle *trans, struct btrfs_inode *inode, u64 new_size, u32 min_type) { + struct btrfs_truncate_control control = { + .new_size = new_size, + .min_type = min_type, + }; int ret; do { ret = btrfs_truncate_inode_items(trans, log_root, inode, - new_size, min_type, NULL); + &control); } while (ret == -EAGAIN); return ret; |