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