On 08/07/2016 07:39 PM, Qu Wenruo wrote:
> 
> 
> At 08/07/2016 01:19 AM, Goldwyn Rodrigues wrote:
>> Thanks Qu,
>>
>> This patch set fixes all the reported problems. However, I have some
>> minor issues with coding style.
>>
> 
> Thanks for the test.
> 
>>
>> On 08/04/2016 09:29 PM, Qu Wenruo wrote:
>>> Refactor btrfs_qgroup_insert_dirty_extent() function, to two functions:
>>> 1. _btrfs_qgroup_insert_dirty_extent()
>>>    Almost the same with original code.
>>>    For delayed_ref usage, which has delayed refs locked.
>>>
>>>    Change the return value type to int, since caller never needs the
>>>    pointer, but only needs to know if they need to free the allocated
>>>    memory.
>>>
>>> 2. btrfs_qgroup_record_dirty_extent()
>>>    The more encapsulated version.
>>>
>>>    Will do the delayed_refs lock, memory allocation, quota enabled check
>>>    and other misc things.
>>>
>>> The original design is to keep exported functions to minimal, but since
>>> more btrfs hacks exposed, like replacing path in balance, needs us to
>>> record dirty extents manually, so we have to add such functions.
>>>
>>> Also, add comment for both functions, to info developers how to keep
>>> qgroup correct when doing hacks.
>>>
>>> Cc: Mark Fasheh <mfas...@suse.de>
>>> Signed-off-by: Qu Wenruo <quwen...@cn.fujitsu.com>
>>> ---
>>>  fs/btrfs/delayed-ref.c |  5 +----
>>>  fs/btrfs/extent-tree.c | 36 +++++-------------------------------
>>>  fs/btrfs/qgroup.c      | 39 ++++++++++++++++++++++++++++++++++-----
>>>  fs/btrfs/qgroup.h      | 44
>>> +++++++++++++++++++++++++++++++++++++++++---
>>>  4 files changed, 81 insertions(+), 43 deletions(-)
>>>
>>> diff --git a/fs/btrfs/delayed-ref.c b/fs/btrfs/delayed-ref.c
>>> index 430b368..5eed597 100644
>>> --- a/fs/btrfs/delayed-ref.c
>>> +++ b/fs/btrfs/delayed-ref.c
>>> @@ -541,7 +541,6 @@ add_delayed_ref_head(struct btrfs_fs_info *fs_info,
>>>      struct btrfs_delayed_ref_head *existing;
>>>      struct btrfs_delayed_ref_head *head_ref = NULL;
>>>      struct btrfs_delayed_ref_root *delayed_refs;
>>> -    struct btrfs_qgroup_extent_record *qexisting;
>>>      int count_mod = 1;
>>>      int must_insert_reserved = 0;
>>>
>>> @@ -606,9 +605,7 @@ add_delayed_ref_head(struct btrfs_fs_info *fs_info,
>>>          qrecord->num_bytes = num_bytes;
>>>          qrecord->old_roots = NULL;
>>>
>>> -        qexisting = btrfs_qgroup_insert_dirty_extent(delayed_refs,
>>> -                                 qrecord);
>>> -        if (qexisting)
>>> +        if(_btrfs_qgroup_insert_dirty_extent(delayed_refs, qrecord))
>>>              kfree(qrecord);
>>>      }
>>>
>>> diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c
>>> index 9fcb8c9..47c85ff 100644
>>> --- a/fs/btrfs/extent-tree.c
>>> +++ b/fs/btrfs/extent-tree.c
>>> @@ -8519,34 +8519,6 @@ reada:
>>>      wc->reada_slot = slot;
>>>  }
>>>
>>> -/*
>>> - * These may not be seen by the usual inc/dec ref code so we have to
>>> - * add them here.
>>> - */
>>> -static int record_one_subtree_extent(struct btrfs_trans_handle *trans,
>>> -                     struct btrfs_root *root, u64 bytenr,
>>> -                     u64 num_bytes)
>>> -{
>>> -    struct btrfs_qgroup_extent_record *qrecord;
>>> -    struct btrfs_delayed_ref_root *delayed_refs;
>>> -
>>> -    qrecord = kmalloc(sizeof(*qrecord), GFP_NOFS);
>>> -    if (!qrecord)
>>> -        return -ENOMEM;
>>> -
>>> -    qrecord->bytenr = bytenr;
>>> -    qrecord->num_bytes = num_bytes;
>>> -    qrecord->old_roots = NULL;
>>> -
>>> -    delayed_refs = &trans->transaction->delayed_refs;
>>> -    spin_lock(&delayed_refs->lock);
>>> -    if (btrfs_qgroup_insert_dirty_extent(delayed_refs, qrecord))
>>> -        kfree(qrecord);
>>> -    spin_unlock(&delayed_refs->lock);
>>> -
>>> -    return 0;
>>> -}
>>> -
>>>  static int account_leaf_items(struct btrfs_trans_handle *trans,
>>>                    struct btrfs_root *root,
>>>                    struct extent_buffer *eb)
>>> @@ -8580,7 +8552,8 @@ static int account_leaf_items(struct
>>> btrfs_trans_handle *trans,
>>>
>>>          num_bytes = btrfs_file_extent_disk_num_bytes(eb, fi);
>>>
>>> -        ret = record_one_subtree_extent(trans, root, bytenr,
>>> num_bytes);
>>> +        ret = btrfs_qgroup_record_dirty_extent(trans, root->fs_info,
>>> +                bytenr, num_bytes, GFP_NOFS);
>>>          if (ret)
>>>              return ret;
>>>      }
>>> @@ -8729,8 +8702,9 @@ walk_down:
>>>              btrfs_set_lock_blocking_rw(eb, BTRFS_READ_LOCK);
>>>              path->locks[level] = BTRFS_READ_LOCK_BLOCKING;
>>>
>>> -            ret = record_one_subtree_extent(trans, root, child_bytenr,
>>> -                            root->nodesize);
>>> +            ret = btrfs_qgroup_record_dirty_extent(trans,
>>> +                    root->fs_info, child_bytenr,
>>> +                    root->nodesize, GFP_NOFS);
>>>              if (ret)
>>>                  goto out;
>>>          }
>>> diff --git a/fs/btrfs/qgroup.c b/fs/btrfs/qgroup.c
>>> index 9d4c05b..76d4f67 100644
>>> --- a/fs/btrfs/qgroup.c
>>> +++ b/fs/btrfs/qgroup.c
>>> @@ -1453,9 +1453,9 @@ int btrfs_qgroup_prepare_account_extents(struct
>>> btrfs_trans_handle *trans,
>>>      return ret;
>>>  }
>>>
>>> -struct btrfs_qgroup_extent_record
>>> -*btrfs_qgroup_insert_dirty_extent(struct btrfs_delayed_ref_root
>>> *delayed_refs,
>>> -                  struct btrfs_qgroup_extent_record *record)
>>> +int _btrfs_qgroup_insert_dirty_extent(
>>> +        struct btrfs_delayed_ref_root *delayed_refs,
>>> +        struct btrfs_qgroup_extent_record *record)
>>
>> Why do you rename the function preceding with an underscore? just leave
>> it as it is.
> 
> Because these two functions have different usage.

Where is the "other" function used? AFAICS, you are replacing the
function name.

> 
> the underscore one are used when caller has already acquired needed
> lock, which is used by delayed-refs code.
> 
> And the one without underscore is for other usage.

What/Where is the "other usage"? Please don't say "previous".

> 
> Despite the lock, these two functions are all the same.
> 
> So I prefer to use underscore.

BTW, you missed include/trace/events/btrfs.h, the reference to
btrfs_qgroup_insert_dirty_extent in DEFINE_EVENT.

> 
>>
>>>  {
>>>      struct rb_node **p = &delayed_refs->dirty_extent_root.rb_node;
>>>      struct rb_node *parent_node = NULL;
>>> @@ -1474,12 +1474,41 @@ struct btrfs_qgroup_extent_record
>>>          else if (bytenr > entry->bytenr)
>>>              p = &(*p)->rb_right;
>>>          else
>>> -            return entry;
>>> +            return 1;
>>
>> return -EALREADY?
> 
> Since the existing case is quite common, I prefer to use >=0 return
> value, other than minus return value which is more common for error case.
> 
> Thanks,
> Qu
> 
>>
>>>      }
>>>
>>>      rb_link_node(&record->node, parent_node, p);
>>>      rb_insert_color(&record->node, &delayed_refs->dirty_extent_root);
>>> -    return NULL;
>>> +    return 0;
>>> +}
>>> +
>>> +int btrfs_qgroup_record_dirty_extent(struct btrfs_trans_handle *trans,
>>> +        struct btrfs_fs_info *fs_info, u64 bytenr, u64 num_bytes,
>>> +        gfp_t gfp_flag)
>>> +{
>>> +    struct btrfs_qgroup_extent_record *record;
>>> +    struct btrfs_delayed_ref_root *delayed_refs;
>>> +    int ret;
>>> +
>>> +    if (!fs_info->quota_enabled || bytenr == 0 || num_bytes == 0)
>>> +        return 0;
>>> +    if (WARN_ON(trans == NULL))
>>> +        return -EINVAL;
>>> +    record = kmalloc(sizeof(*record), gfp_flag);
>>> +    if (!record)
>>> +        return -ENOMEM;
>>> +
>>> +    delayed_refs = &trans->transaction->delayed_refs;
>>> +    record->bytenr = bytenr;
>>> +    record->num_bytes = num_bytes;
>>> +    record->old_roots = NULL;
>>> +
>>> +    spin_lock(&delayed_refs->lock);
>>> +    ret = _btrfs_qgroup_insert_dirty_extent(delayed_refs, record);
>>> +    spin_unlock(&delayed_refs->lock);
>>> +    if (ret > 0)
>>> +        kfree(record);
>>> +    return 0;
>>>  }
>>>
>>>  #define UPDATE_NEW    0
>>> diff --git a/fs/btrfs/qgroup.h b/fs/btrfs/qgroup.h
>>> index ecb2c14..f6691e3 100644
>>> --- a/fs/btrfs/qgroup.h
>>> +++ b/fs/btrfs/qgroup.h
>>> @@ -63,9 +63,47 @@ void btrfs_free_qgroup_config(struct btrfs_fs_info
>>> *fs_info);
>>>  struct btrfs_delayed_extent_op;
>>>  int btrfs_qgroup_prepare_account_extents(struct btrfs_trans_handle
>>> *trans,
>>>                       struct btrfs_fs_info *fs_info);
>>> -struct btrfs_qgroup_extent_record
>>> -*btrfs_qgroup_insert_dirty_extent(struct btrfs_delayed_ref_root
>>> *delayed_refs,
>>> -                  struct btrfs_qgroup_extent_record *record);
>>> +
>>> +/*
>>> + * Insert one dirty extent record into delayed_refs for qgroup.
>>> + * Caller must ensure the delayed_refs are already locked and quota
>>> is enabled.
>>> + *
>>> + * Return 0 if there is no existing dirty extent record for that
>>> bytenr, and
>>> + * insert that record into delayed_refs.
>>> + * Return > 0 if there is already existing dirty extent record for
>>> that bytenr.
>>> + * Caller then can free the record structure.
>>> + * Error is not possible
>>
>> You can remove this if you intend to return EALREADY.
>>
>>> + *
>>> + * For caller needs better encapsulated interface, call
>>> + * btrfs_qgroup_record_dirty_extent(), which will handle locks and
>>> memory
>>> + * allocation.
>>> + */
>>> +int _btrfs_qgroup_insert_dirty_extent(
>>> +        struct btrfs_delayed_ref_root *delayed_refs,
>>> +        struct btrfs_qgroup_extent_record *record);
>>> +
>>> +/*
>>> + * Info qgroup to track one extent, so at trans commit time qgroup can
>>> + * update qgroup accounts for that extent.
>>> + *
>>> + * That extent can be either meta or data.
>>> + * This function can be called several times for any extent and
>>> won't cause
>>> + * any qgroup incorrectness.
>>> + * As long as dirty extent is recorded, qgroup can hardly go wrong.
>>> + *
>>> + * This function should be called when owner of extent is changed
>>> and the
>>> + * code uses hack to avoid normal inc/dev_extent_ref().
>>> + * For example, swapping two tree blocks in balance or modifying
>>> file extent
>>> + * disk bytenr manually.
>>> + *
>>> + * Return 0 if the operation is done.
>>> + * Return <0 for error, like memory allocation failure or invalid
>>> parameter
>>> + * (NULL trans)
>>> + */
>>> +int btrfs_qgroup_record_dirty_extent(struct btrfs_trans_handle *trans,
>>> +        struct btrfs_fs_info *fs_info, u64 bytenr, u64 num_bytes,
>>> +        gfp_t gfp_flag);
>>> +
>>>  int
>>>  btrfs_qgroup_account_extent(struct btrfs_trans_handle *trans,
>>>                  struct btrfs_fs_info *fs_info,
>>>
>>
> 
> 
> 

-- 
Goldwyn
--
To unsubscribe from this list: send the line "unsubscribe linux-btrfs" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to