On 3.12.18 г. 17:20 ч., Josef Bacik wrote:
> Now with the delayed_refs_rsv we can now know exactly how much pending
> delayed refs space we need.  This means we can drastically simplify

IMO it will be helpful if there is a sentence here referring back to
btrfs_update_delayed_refs_rsv to put your first sentence into context.
But I guess this is something David can also do.

> btrfs_check_space_for_delayed_refs by simply checking how much space we
> have reserved for the global rsv (which acts as a spill over buffer) and
> the delayed refs rsv.  If our total size is beyond that amount then we
> know it's time to commit the transaction and stop any more delayed refs
> from being generated.
> 
> Signed-off-by: Josef Bacik <jo...@toxicpanda.com>

Reviewed-by: Nikolay Borisov <nbori...@suse.com>

> ---
>  fs/btrfs/ctree.h       |  2 +-
>  fs/btrfs/extent-tree.c | 48 ++++++++++++++++++------------------------------
>  fs/btrfs/inode.c       |  4 ++--
>  fs/btrfs/transaction.c |  2 +-
>  4 files changed, 22 insertions(+), 34 deletions(-)
> 
> diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h
> index 2eba398c722b..30da075c042e 100644
> --- a/fs/btrfs/ctree.h
> +++ b/fs/btrfs/ctree.h
> @@ -2631,7 +2631,7 @@ static inline u64 btrfs_calc_trunc_metadata_size(struct 
> btrfs_fs_info *fs_info,
>  }
>  
>  int btrfs_should_throttle_delayed_refs(struct btrfs_trans_handle *trans);
> -int btrfs_check_space_for_delayed_refs(struct btrfs_trans_handle *trans);
> +bool btrfs_check_space_for_delayed_refs(struct btrfs_fs_info *fs_info);
>  void btrfs_dec_block_group_reservations(struct btrfs_fs_info *fs_info,
>                                        const u64 start);
>  void btrfs_wait_block_group_reservations(struct btrfs_block_group_cache *bg);
> diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c
> index 5a2d0b061f57..07ef1b8087f7 100644
> --- a/fs/btrfs/extent-tree.c
> +++ b/fs/btrfs/extent-tree.c
> @@ -2839,40 +2839,28 @@ u64 btrfs_csum_bytes_to_leaves(struct btrfs_fs_info 
> *fs_info, u64 csum_bytes)
>       return num_csums;
>  }
>  
> -int btrfs_check_space_for_delayed_refs(struct btrfs_trans_handle *trans)
> +bool btrfs_check_space_for_delayed_refs(struct btrfs_fs_info *fs_info)
>  {
> -     struct btrfs_fs_info *fs_info = trans->fs_info;
> -     struct btrfs_block_rsv *global_rsv;
> -     u64 num_heads = trans->transaction->delayed_refs.num_heads_ready;
> -     u64 csum_bytes = trans->transaction->delayed_refs.pending_csums;
> -     unsigned int num_dirty_bgs = trans->transaction->num_dirty_bgs;
> -     u64 num_bytes, num_dirty_bgs_bytes;
> -     int ret = 0;
> +     struct btrfs_block_rsv *delayed_refs_rsv = &fs_info->delayed_refs_rsv;
> +     struct btrfs_block_rsv *global_rsv = &fs_info->global_block_rsv;
> +     bool ret = false;
> +     u64 reserved;
>  
> -     num_bytes = btrfs_calc_trans_metadata_size(fs_info, 1);
> -     num_heads = heads_to_leaves(fs_info, num_heads);
> -     if (num_heads > 1)
> -             num_bytes += (num_heads - 1) * fs_info->nodesize;
> -     num_bytes <<= 1;
> -     num_bytes += btrfs_csum_bytes_to_leaves(fs_info, csum_bytes) *
> -                                                     fs_info->nodesize;
> -     num_dirty_bgs_bytes = btrfs_calc_trans_metadata_size(fs_info,
> -                                                          num_dirty_bgs);
> -     global_rsv = &fs_info->global_block_rsv;
> +     spin_lock(&global_rsv->lock);
> +     reserved = global_rsv->reserved;
> +     spin_unlock(&global_rsv->lock);
>  
>       /*
> -      * If we can't allocate any more chunks lets make sure we have _lots_ of
> -      * wiggle room since running delayed refs can create more delayed refs.
> +      * Since the global reserve is just kind of magic we don't really want
> +      * to rely on it to save our bacon, so if our size is more than the
> +      * delayed_refs_rsv and the global rsv then it's time to think about
> +      * bailing.
>        */
> -     if (global_rsv->space_info->full) {
> -             num_dirty_bgs_bytes <<= 1;
> -             num_bytes <<= 1;
> -     }
> -
> -     spin_lock(&global_rsv->lock);
> -     if (global_rsv->reserved <= num_bytes + num_dirty_bgs_bytes)
> -             ret = 1;
> -     spin_unlock(&global_rsv->lock);
> +     spin_lock(&delayed_refs_rsv->lock);
> +     reserved += delayed_refs_rsv->reserved;
> +     if (delayed_refs_rsv->size >= reserved)
> +             ret = true;
> +     spin_unlock(&delayed_refs_rsv->lock);
>       return ret;
>  }
>  
> @@ -2891,7 +2879,7 @@ int btrfs_should_throttle_delayed_refs(struct 
> btrfs_trans_handle *trans)
>       if (val >= NSEC_PER_SEC / 2)
>               return 2;
>  
> -     return btrfs_check_space_for_delayed_refs(trans);
> +     return btrfs_check_space_for_delayed_refs(trans->fs_info);
>  }
>  
>  struct async_delayed_refs {
> diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
> index a097f5fde31d..8532a2eb56d1 100644
> --- a/fs/btrfs/inode.c
> +++ b/fs/btrfs/inode.c
> @@ -5326,8 +5326,8 @@ static struct btrfs_trans_handle 
> *evict_refill_and_join(struct btrfs_root *root,
>                * Try to steal from the global reserve if there is space for
>                * it.
>                */
> -             if (!btrfs_check_space_for_delayed_refs(trans) &&
> -                 !btrfs_block_rsv_migrate(global_rsv, rsv, rsv->size, false))
> +             if (!btrfs_check_space_for_delayed_refs(fs_info) &&
> +                 !btrfs_block_rsv_migrate(global_rsv, rsv, rsv->size, 0))
>                       return trans;
>  
>               /* If not, commit and try again. */
> diff --git a/fs/btrfs/transaction.c b/fs/btrfs/transaction.c
> index a21c4defad92..2d8401bf8df9 100644
> --- a/fs/btrfs/transaction.c
> +++ b/fs/btrfs/transaction.c
> @@ -789,7 +789,7 @@ static int should_end_transaction(struct 
> btrfs_trans_handle *trans)
>  {
>       struct btrfs_fs_info *fs_info = trans->fs_info;
>  
> -     if (btrfs_check_space_for_delayed_refs(trans))
> +     if (btrfs_check_space_for_delayed_refs(fs_info))
>               return 1;
>  
>       return !!btrfs_block_rsv_check(&fs_info->global_block_rsv, 5);
> 

Reply via email to