Btrfs: improve the noflush reservation
PATCH 2/2 Btrfs: improve the noflush reservation
In some places(such as: evicting inode), we just can not flush the reserved space of delalloc, flushing the delayed directory index and delayed inode is OK, but we don't try to flush those things and just go back when there is no enough space to be reserved. This patch fixes this problem.
We defined 3 types of the flush operations: NO_FLUSH, FLUSH_LIMIT and FLUSH_ALL. If we can in the transaction, we should not flush anything, or the deadlock would happen, so use NO_FLUSH. If we flushing the reserved space of delalloc would cause deadlock, use FLUSH_LIMIT. In the other cases, FLUSH_ALL is used, and we will flush all things.
Signed-off-by Miao Xie <[email protected]>
--- fs/btrfs/ctree.h | 26 ++++++++----- fs/btrfs/delayed-inode.c | 6 ++- fs/btrfs/extent-tree.c | 97 +++++++++++++++++++++++----------------------- fs/btrfs/inode-map.c | 5 +- fs/btrfs/inode.c | 5 +- fs/btrfs/relocation.c | 12 ++++-- fs/btrfs/transaction.c | 30 +++++++-------- fs/btrfs/transaction.h | 2 +- 8 files changed, 97 insertions(+), 86 deletions(-)
fs/btrfs/ctree.h +16 -10
@@ -2900,6 +2900,18 @@ void btrfs_create_pending_block_groups(struct btrfs_trans_handle *trans,u64 btrfs_reduce_alloc_profile (struct btrfs_root *root,u64 flags);u64 btrfs_get_alloc_profile (struct btrfs_root *root,int data);void btrfs_clear_space_info_full (struct btrfs_fs_info *info); + +enum btrfs_reserve_flush_enum { +/* If we are in the transaction, we can't flush anything.*/ +BTRFS_RESERVE_NO_FLUSH , +/* +* Flushing delalloc may cause deadlock somewhere, in this +* case, use FLUSH LIMIT +*/ +BTRFS_RESERVE_FLUSH_LIMIT , +BTRFS_RESERVE_FLUSH_ALL , +}; +int btrfs_check_data_free_space (struct inode *inode,u64 bytes);void btrfs_free_reserved_data_space (struct inode *inode,u64 bytes); void btrfs_trans_release_metadata(struct btrfs_trans_handle *trans,
@@ -2919,19 +2931,13 @@ struct btrfs_block_rsv *btrfs_alloc_block_rsv(struct btrfs_root *root,void btrfs_free_block_rsv (struct btrfs_root *root,struct btrfs_block_rsv *rsv);int btrfs_block_rsv_add (struct btrfs_root *root, -struct btrfs_block_rsv *block_rsv, -u64 num_bytes); -int btrfs_block_rsv_add_noflush (struct btrfs_root *root, -struct btrfs_block_rsv *block_rsv, -u64 num_bytes); +struct btrfs_block_rsv *block_rsv,u64 num_bytes, +enum btrfs_reserve_flush_enum flush);int btrfs_block_rsv_check (struct btrfs_root *root,struct btrfs_block_rsv *block_rsv,int min_factor);int btrfs_block_rsv_refill (struct btrfs_root *root, -struct btrfs_block_rsv *block_rsv, -u64 min_reserved); -int btrfs_block_rsv_refill_noflush (struct btrfs_root *root, -struct btrfs_block_rsv *block_rsv, -u64 min_reserved); +struct btrfs_block_rsv *block_rsv,u64 min_reserved, +enum btrfs_reserve_flush_enum flush);int btrfs_block_rsv_migrate (struct btrfs_block_rsv *src_rsv,struct btrfs_block_rsv *dst_rsv,u64 num_bytes);
fs/btrfs/delayed-inode.c +4 -2
@@ -651,7 +651,8 @@ static int btrfs_delayed_inode_reserve_metadata(*/ if (!src_rsv || (!trans->bytes_reserved && src_rsv->type !=BTRFS_BLOCK_RSV_DELALLOC )) { - ret =btrfs_block_rsv_add_noflush (root, dst_rsv, num_bytes); + ret =btrfs_block_rsv_add (root, dst_rsv, num_bytes, +BTRFS_RESERVE_NO_FLUSH );/* * Since we're under a transaction reserve_metadata_bytes could * try to commit the transaction which will make it return
@@ -686,7 +687,8 @@ static int btrfs_delayed_inode_reserve_metadata(* reserve something strictly for us. If not be a pain and try * to steal from the delalloc block rsv. */ - ret =btrfs_block_rsv_add_noflush (root, dst_rsv, num_bytes); + ret =btrfs_block_rsv_add (root, dst_rsv, num_bytes, +BTRFS_RESERVE_NO_FLUSH );if (!ret) goto out;
fs/btrfs/extent-tree.c +48 -49
202 lines not on this page · raw message
fs/btrfs/inode-map.c +3 -2
@@ -434,8 +434,9 @@ int btrfs_save_ino_cache(struct btrfs_root *root,* 3 items for pre-allocation */ trans->bytes_reserved =btrfs_calc_trans_metadata_size (root,8 ); - ret =btrfs_block_rsv_add_noflush (root, trans->block_rsv, - trans->bytes_reserved); + ret =btrfs_block_rsv_add (root, trans->block_rsv, + trans->bytes_reserved, +BTRFS_RESERVE_NO_FLUSH );if (ret) goto out; trace_btrfs_space_reservation(root->fs_info, "ino_cache",
fs/btrfs/inode.c +3 -2
@@ -4446,7 +4446,8 @@ void btrfs_evict_inode(struct inode *inode)* inode item when doing the truncate. */ while (1 ) { - ret =btrfs_block_rsv_refill_noflush (root, rsv, min_size); + ret =btrfs_block_rsv_refill (root, rsv, min_size, +BTRFS_RESERVE_FLUSH_LIMIT );/* * Try and steal from the global reserve since we will
@@ -4464,7 +4465,7 @@ void btrfs_evict_inode(struct inode *inode) goto no_delete; } - trans =btrfs_start_transaction_noflush (root,1 ); + trans =btrfs_start_transaction_lflush (root,1 );if (IS_ERR (trans)) {btrfs_orphan_del (NULL , inode);btrfs_free_block_rsv (root, rsv);
fs/btrfs/relocation.c +8 -4
@@ -2074,7 +2074,8 @@ static noinline_for_stack int merge_reloc_root(struct reloc_control *rc,BUG_ON (IS_ERR (trans)); trans->block_rsv = rc->block_rsv; - ret =btrfs_block_rsv_refill (root, rc->block_rsv, min_reserved); + ret =btrfs_block_rsv_refill (root, rc->block_rsv, min_reserved, +BTRFS_RESERVE_FLUSH_ALL );if (ret) {BUG_ON (ret != -EAGAIN ); ret =btrfs_commit_transaction (trans, root);
@@ -2184,7 +2185,8 @@ int prepare_to_merge(struct reloc_control *rc, int err) again:if (!err) { num_bytes = rc->merging_rsv_size; - ret =btrfs_block_rsv_add (root, rc->block_rsv, num_bytes); + ret =btrfs_block_rsv_add (root, rc->block_rsv, num_bytes, +BTRFS_RESERVE_FLUSH_ALL );if (ret) err = ret; }
@@ -2459,7 +2461,8 @@ static int reserve_metadata_space(struct btrfs_trans_handle *trans, num_bytes =calcu_metadata_size (rc, node,1 ) *2 ; trans->block_rsv = rc->block_rsv; - ret =btrfs_block_rsv_add (root, rc->block_rsv, num_bytes); + ret =btrfs_block_rsv_add (root, rc->block_rsv, num_bytes, +BTRFS_RESERVE_FLUSH_ALL );if (ret) {if (ret == -EAGAIN ) rc->commit_transaction =1 ;
@@ -3685,7 +3688,8 @@ int prepare_to_relocate(struct reloc_control *rc)* is no reservation in transaction handle. */ ret =btrfs_block_rsv_add (rc->extent_root, rc->block_rsv, - rc->extent_root->nodesize *256 ); + rc->extent_root->nodesize *256 , +BTRFS_RESERVE_FLUSH_ALL );if (ret)return ret;
fs/btrfs/transaction.c +14 -16
@@ -295,9 +295,9 @@ static int may_wait_transaction(struct btrfs_root *root, int type)return 0 ; } -static struct btrfs_trans_handle *start_transaction (struct btrfs_root *root, -u64 num_items,int type, -int noflush) +static struct btrfs_trans_handle * +start_transaction (struct btrfs_root *root,u64 num_items,int type, +enum btrfs_reserve_flush_enum flush) {struct btrfs_trans_handle *h;struct btrfs_transaction *cur_trans;
@@ -331,14 +331,9 @@ static struct btrfs_trans_handle *start_transaction(struct btrfs_root *root, } num_bytes =btrfs_calc_trans_metadata_size (root, num_items); -if (noflush) - ret =btrfs_block_rsv_add_noflush (root, - &root->fs_info->trans_block_rsv, - num_bytes); -else - ret =btrfs_block_rsv_add (root, - &root->fs_info->trans_block_rsv, - num_bytes); + ret =btrfs_block_rsv_add (root, + &root->fs_info->trans_block_rsv, + num_bytes, flush);if (ret)return ERR_PTR (ret); }
@@ -422,13 +417,15 @@ got_it:struct btrfs_trans_handle *btrfs_start_transaction (struct btrfs_root *root,int num_items) { -return start_transaction (root, num_items,TRANS_START ,0 ); +return start_transaction (root, num_items,TRANS_START , +BTRFS_RESERVE_FLUSH_ALL ); } -struct btrfs_trans_handle *btrfs_start_transaction_noflush ( +struct btrfs_trans_handle *btrfs_start_transaction_lflush (struct btrfs_root *root,int num_items) { -return start_transaction (root, num_items,TRANS_START ,1 ); +return start_transaction (root, num_items,TRANS_START , +BTRFS_RESERVE_FLUSH_LIMIT ); }struct btrfs_trans_handle *btrfs_join_transaction (struct btrfs_root *root)
@@ -1032,8 +1029,9 @@ static noinline int create_pending_snapshot(struct btrfs_trans_handle *trans,btrfs_reloc_pre_snapshot (trans, pending, &to_reserve);if (to_reserve >0 ) { - ret =btrfs_block_rsv_add_noflush (root, &pending->block_rsv, - to_reserve); + ret =btrfs_block_rsv_add (root, &pending->block_rsv, + to_reserve, +BTRFS_RESERVE_NO_FLUSH );if (ret) { pending->error = ret; goto no_free_objectid;
fs/btrfs/transaction.h +1 -1
@@ -105,7 +105,7 @@ int btrfs_end_transaction(struct btrfs_trans_handle *trans, struct btrfs_root *root);struct btrfs_trans_handle *btrfs_start_transaction (struct btrfs_root *root,int num_items); -struct btrfs_trans_handle *btrfs_start_transaction_noflush ( +struct btrfs_trans_handle *btrfs_start_transaction_lflush (struct btrfs_root *root,int num_items);struct btrfs_trans_handle *btrfs_join_transaction (struct btrfs_root *root);struct btrfs_trans_handle *btrfs_join_transaction_nolock (struct btrfs_root *root);
Signature · 1 line
1.7.6.5