Commit d9ac19c3 authored by Josef Bacik's avatar Josef Bacik Committed by David Sterba

btrfs: add truncate control struct

I'm going to be adding more arguments and counters to
btrfs_truncate_inode_items, so add a control struct to handle all of the
extra arguments to make it easier to follow.
Reviewed-by: default avatarFilipe Manana <fdmanana@suse.com>
Signed-off-by: default avatarJosef Bacik <josef@toxicpanda.com>
Reviewed-by: default avatarDavid Sterba <dsterba@suse.com>
Signed-off-by: default avatarDavid Sterba <dsterba@suse.com>
parent 7097a941
...@@ -291,6 +291,10 @@ int btrfs_truncate_free_space_cache(struct btrfs_trans_handle *trans, ...@@ -291,6 +291,10 @@ int btrfs_truncate_free_space_cache(struct btrfs_trans_handle *trans,
struct btrfs_block_group *block_group, struct btrfs_block_group *block_group,
struct inode *vfs_inode) 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_inode *inode = BTRFS_I(vfs_inode);
struct btrfs_root *root = inode->root; struct btrfs_root *root = inode->root;
struct extent_state *cached_state = NULL; struct extent_state *cached_state = NULL;
...@@ -333,8 +337,7 @@ int btrfs_truncate_free_space_cache(struct btrfs_trans_handle *trans, ...@@ -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 * We skip the throttling logic for free space cache inodes, so we don't
* need to check for -EAGAIN. * need to check for -EAGAIN.
*/ */
ret = btrfs_truncate_inode_items(trans, root, inode, 0, ret = btrfs_truncate_inode_items(trans, root, inode, &control);
BTRFS_EXTENT_DATA_KEY, NULL);
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;
......
...@@ -425,16 +425,8 @@ int btrfs_lookup_inode(struct btrfs_trans_handle *trans, struct btrfs_root ...@@ -425,16 +425,8 @@ int btrfs_lookup_inode(struct btrfs_trans_handle *trans, struct btrfs_root
* @trans: A transaction handle. * @trans: A transaction handle.
* @root: The root from which to remove items. * @root: The root from which to remove items.
* @inode: The inode whose items we want to remove. * @inode: The inode whose items we want to remove.
* @new_size: The new i_size for the inode. This is only applicable when * @control: The btrfs_truncate_control to control how and what we
* @min_type is BTRFS_EXTENT_DATA_KEY, must be 0 otherwise. * are truncating.
* @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.
* *
* Remove all keys associated with the inode from the given root that have a key * 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 * 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 ...@@ -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, int btrfs_truncate_inode_items(struct btrfs_trans_handle *trans,
struct btrfs_root *root, struct btrfs_root *root,
struct btrfs_inode *inode, struct btrfs_inode *inode,
u64 new_size, u32 min_type, struct btrfs_truncate_control *control)
u64 *extents_found)
{ {
struct btrfs_fs_info *fs_info = root->fs_info; struct btrfs_fs_info *fs_info = root->fs_info;
struct btrfs_path *path; struct btrfs_path *path;
...@@ -457,6 +448,7 @@ int btrfs_truncate_inode_items(struct btrfs_trans_handle *trans, ...@@ -457,6 +448,7 @@ int btrfs_truncate_inode_items(struct btrfs_trans_handle *trans,
struct btrfs_file_extent_item *fi; struct btrfs_file_extent_item *fi;
struct btrfs_key key; struct btrfs_key key;
struct btrfs_key found_key; struct btrfs_key found_key;
u64 new_size = control->new_size;
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;
...@@ -472,7 +464,7 @@ int btrfs_truncate_inode_items(struct btrfs_trans_handle *trans, ...@@ -472,7 +464,7 @@ int btrfs_truncate_inode_items(struct btrfs_trans_handle *trans,
bool be_nice = false; bool be_nice = false;
bool should_throttle = 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 * For shareable roots we want to back off from time to time, this turns
...@@ -525,7 +517,7 @@ int btrfs_truncate_inode_items(struct btrfs_trans_handle *trans, ...@@ -525,7 +517,7 @@ int btrfs_truncate_inode_items(struct btrfs_trans_handle *trans,
if (found_key.objectid != ino) if (found_key.objectid != ino)
break; break;
if (found_type < min_type) if (found_type < control->min_type)
break; break;
item_end = found_key.offset; item_end = found_key.offset;
...@@ -548,7 +540,7 @@ int btrfs_truncate_inode_items(struct btrfs_trans_handle *trans, ...@@ -548,7 +540,7 @@ int btrfs_truncate_inode_items(struct btrfs_trans_handle *trans,
} }
item_end--; item_end--;
} }
if (found_type > min_type) { if (found_type > control->min_type) {
del_item = 1; del_item = 1;
} else { } else {
if (item_end < new_size) if (item_end < new_size)
...@@ -563,8 +555,7 @@ int btrfs_truncate_inode_items(struct btrfs_trans_handle *trans, ...@@ -563,8 +555,7 @@ int btrfs_truncate_inode_items(struct btrfs_trans_handle *trans,
if (found_type != BTRFS_EXTENT_DATA_KEY) if (found_type != BTRFS_EXTENT_DATA_KEY)
goto delete; goto delete;
if (extents_found != NULL) control->extents_found++;
(*extents_found)++;
if (extent_type != BTRFS_FILE_EXTENT_INLINE) { if (extent_type != BTRFS_FILE_EXTENT_INLINE) {
u64 num_dec; u64 num_dec;
......
...@@ -19,10 +19,24 @@ struct extent_buffer; ...@@ -19,10 +19,24 @@ struct extent_buffer;
*/ */
#define BTRFS_NEED_TRUNCATE_BLOCK 1 #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, int btrfs_truncate_inode_items(struct btrfs_trans_handle *trans,
struct btrfs_root *root, struct btrfs_root *root,
struct btrfs_inode *inode, u64 new_size, struct btrfs_inode *inode,
u32 min_type, u64 *extents_found); struct btrfs_truncate_control *control);
int btrfs_insert_inode_ref(struct btrfs_trans_handle *trans, int btrfs_insert_inode_ref(struct btrfs_trans_handle *trans,
struct btrfs_root *root, struct btrfs_root *root,
const char *name, int name_len, const char *name, int name_len,
......
...@@ -5251,6 +5251,11 @@ void btrfs_evict_inode(struct inode *inode) ...@@ -5251,6 +5251,11 @@ void btrfs_evict_inode(struct inode *inode)
btrfs_i_size_write(BTRFS_I(inode), 0); btrfs_i_size_write(BTRFS_I(inode), 0);
while (1) { while (1) {
struct btrfs_truncate_control control = {
.new_size = 0,
.min_type = 0,
};
trans = evict_refill_and_join(root, rsv); trans = evict_refill_and_join(root, rsv);
if (IS_ERR(trans)) if (IS_ERR(trans))
goto free_rsv; goto free_rsv;
...@@ -5258,7 +5263,7 @@ void btrfs_evict_inode(struct inode *inode) ...@@ -5258,7 +5263,7 @@ void btrfs_evict_inode(struct inode *inode)
trans->block_rsv = rsv; trans->block_rsv = rsv;
ret = btrfs_truncate_inode_items(trans, root, BTRFS_I(inode), ret = btrfs_truncate_inode_items(trans, root, BTRFS_I(inode),
0, 0, NULL); &control);
trans->block_rsv = &fs_info->trans_block_rsv; trans->block_rsv = &fs_info->trans_block_rsv;
btrfs_end_transaction(trans); btrfs_end_transaction(trans);
btrfs_btree_balance_dirty(fs_info); btrfs_btree_balance_dirty(fs_info);
...@@ -8527,6 +8532,9 @@ vm_fault_t btrfs_page_mkwrite(struct vm_fault *vmf) ...@@ -8527,6 +8532,9 @@ vm_fault_t btrfs_page_mkwrite(struct vm_fault *vmf)
static int btrfs_truncate(struct inode *inode, bool skip_writeback) 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_fs_info *fs_info = btrfs_sb(inode->i_sb);
struct btrfs_root *root = BTRFS_I(inode)->root; struct btrfs_root *root = BTRFS_I(inode)->root;
struct btrfs_block_rsv *rsv; struct btrfs_block_rsv *rsv;
...@@ -8534,7 +8542,6 @@ static int btrfs_truncate(struct inode *inode, bool skip_writeback) ...@@ -8534,7 +8542,6 @@ static int btrfs_truncate(struct inode *inode, bool skip_writeback)
struct btrfs_trans_handle *trans; struct btrfs_trans_handle *trans;
u64 mask = fs_info->sectorsize - 1; u64 mask = fs_info->sectorsize - 1;
u64 min_size = btrfs_calc_metadata_size(fs_info, 1); u64 min_size = btrfs_calc_metadata_size(fs_info, 1);
u64 extents_found = 0;
if (!skip_writeback) { if (!skip_writeback) {
ret = btrfs_wait_ordered_range(inode, inode->i_size & (~mask), ret = btrfs_wait_ordered_range(inode, inode->i_size & (~mask),
...@@ -8599,6 +8606,7 @@ static int btrfs_truncate(struct inode *inode, bool skip_writeback) ...@@ -8599,6 +8606,7 @@ static int btrfs_truncate(struct inode *inode, bool skip_writeback)
const u64 new_size = inode->i_size; const u64 new_size = inode->i_size;
const u64 lock_start = ALIGN_DOWN(new_size, fs_info->sectorsize); 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, lock_extent_bits(&BTRFS_I(inode)->io_tree, lock_start, (u64)-1,
&cached_state); &cached_state);
/* /*
...@@ -8611,9 +8619,7 @@ static int btrfs_truncate(struct inode *inode, bool skip_writeback) ...@@ -8611,9 +8619,7 @@ static int btrfs_truncate(struct inode *inode, bool skip_writeback)
(u64)-1, 0); (u64)-1, 0);
ret = btrfs_truncate_inode_items(trans, root, BTRFS_I(inode), ret = btrfs_truncate_inode_items(trans, root, BTRFS_I(inode),
inode->i_size, &control);
BTRFS_EXTENT_DATA_KEY,
&extents_found);
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);
...@@ -8692,7 +8698,7 @@ static int btrfs_truncate(struct inode *inode, bool skip_writeback) ...@@ -8692,7 +8698,7 @@ static int btrfs_truncate(struct inode *inode, bool skip_writeback)
* between the old i_size and the new i_size, and there were no prealloc * between the old i_size and the new i_size, and there were no prealloc
* extents beyond i_size to drop. * 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); set_bit(BTRFS_INODE_NEEDS_FULL_SYNC, &BTRFS_I(inode)->runtime_flags);
return ret; return ret;
......
...@@ -4098,11 +4098,15 @@ static int truncate_inode_items(struct btrfs_trans_handle *trans, ...@@ -4098,11 +4098,15 @@ static int truncate_inode_items(struct btrfs_trans_handle *trans,
struct btrfs_inode *inode, struct btrfs_inode *inode,
u64 new_size, u32 min_type) u64 new_size, u32 min_type)
{ {
struct btrfs_truncate_control control = {
.new_size = new_size,
.min_type = min_type,
};
int ret; int ret;
do { do {
ret = btrfs_truncate_inode_items(trans, log_root, inode, ret = btrfs_truncate_inode_items(trans, log_root, inode,
new_size, min_type, NULL); &control);
} while (ret == -EAGAIN); } while (ret == -EAGAIN);
return ret; return ret;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment