Skip to content

Commit c306346

Browse files
adam900710kdave
authored andcommitted
btrfs: add extra warning when qgroup is marked inconsistent
Unlike qgroup rescan, which always shows whether it cleared the inconsistent flag, we do not have a proper way to show if qgroup is marked inconsistent. This was not a big deal before as there aren't that many locations that can mark qgroup inconsistent. But with the introduction of drop_subtree_threshold, qgroup can be marked inconsistent very frequently, especially when dropping subvolumes. Although most user space tools relying on qgroup should do their own checks and queue a rescan if needed, we have no idea when qgroup is marked inconsistent, and will be much harder to debug. So this patch will add an extra warning (btrfs_warn_rl()) when the qgroup flag is flipped into inconsistent for the first time. And add extra reason why qgroup flips inconsistent. This means we can move the error message immediately before qgroup_inconsistent_warning() into that function. For call sites without an obvious reason, or is a shared error handling, output the function that failed and the error code instead. Reviewed-by: Filipe Manana <fdmanana@suse.com> Signed-off-by: Qu Wenruo <wqu@suse.com> Signed-off-by: David Sterba <dsterba@suse.com>
1 parent 9e0cc5e commit c306346

File tree

1 file changed

+44
-39
lines changed

1 file changed

+44
-39
lines changed

fs/btrfs/qgroup.c

Lines changed: 44 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -346,13 +346,27 @@ int btrfs_verify_qgroup_counts(const struct btrfs_fs_info *fs_info, u64 qgroupid
346346
}
347347
#endif
348348

349-
static void qgroup_mark_inconsistent(struct btrfs_fs_info *fs_info)
349+
__printf(2, 3)
350+
static void qgroup_mark_inconsistent(struct btrfs_fs_info *fs_info, const char *fmt, ...)
350351
{
352+
const u64 old_flags = fs_info->qgroup_flags;
353+
351354
if (btrfs_qgroup_mode(fs_info) == BTRFS_QGROUP_MODE_SIMPLE)
352355
return;
353356
fs_info->qgroup_flags |= (BTRFS_QGROUP_STATUS_FLAG_INCONSISTENT |
354357
BTRFS_QGROUP_RUNTIME_FLAG_CANCEL_RESCAN |
355358
BTRFS_QGROUP_RUNTIME_FLAG_NO_ACCOUNTING);
359+
if (!(old_flags & BTRFS_QGROUP_STATUS_FLAG_INCONSISTENT)) {
360+
struct va_format vaf;
361+
va_list args;
362+
363+
va_start(args, fmt);
364+
vaf.fmt = fmt;
365+
vaf.va = &args;
366+
367+
btrfs_warn_rl(fs_info, "qgroup marked inconsistent, %pV", &vaf);
368+
va_end(args);
369+
}
356370
}
357371

358372
static void qgroup_read_enable_gen(struct btrfs_fs_info *fs_info,
@@ -431,13 +445,10 @@ int btrfs_read_qgroup_config(struct btrfs_fs_info *fs_info)
431445
goto out;
432446
}
433447
fs_info->qgroup_flags = btrfs_qgroup_status_flags(l, ptr);
434-
if (fs_info->qgroup_flags & BTRFS_QGROUP_STATUS_FLAG_SIMPLE_MODE) {
448+
if (fs_info->qgroup_flags & BTRFS_QGROUP_STATUS_FLAG_SIMPLE_MODE)
435449
qgroup_read_enable_gen(fs_info, l, slot, ptr);
436-
} else if (btrfs_qgroup_status_generation(l, ptr) != fs_info->generation) {
437-
qgroup_mark_inconsistent(fs_info);
438-
btrfs_err(fs_info,
439-
"qgroup generation mismatch, marked as inconsistent");
440-
}
450+
else if (btrfs_qgroup_status_generation(l, ptr) != fs_info->generation)
451+
qgroup_mark_inconsistent(fs_info, "qgroup generation mismatch");
441452
rescan_progress = btrfs_qgroup_status_rescan(l, ptr);
442453
goto next1;
443454
}
@@ -448,10 +459,8 @@ int btrfs_read_qgroup_config(struct btrfs_fs_info *fs_info)
448459

449460
qgroup = find_qgroup_rb(fs_info, found_key.offset);
450461
if ((qgroup && found_key.type == BTRFS_QGROUP_INFO_KEY) ||
451-
(!qgroup && found_key.type == BTRFS_QGROUP_LIMIT_KEY)) {
452-
btrfs_err(fs_info, "inconsistent qgroup config");
453-
qgroup_mark_inconsistent(fs_info);
454-
}
462+
(!qgroup && found_key.type == BTRFS_QGROUP_LIMIT_KEY))
463+
qgroup_mark_inconsistent(fs_info, "inconsistent qgroup config");
455464
if (!qgroup) {
456465
struct btrfs_qgroup *prealloc;
457466
struct btrfs_root *tree_root = fs_info->tree_root;
@@ -1841,13 +1850,12 @@ int btrfs_remove_qgroup(struct btrfs_trans_handle *trans, u64 qgroupid)
18411850
if (qgroup->rfer || qgroup->excl ||
18421851
qgroup->rfer_cmpr || qgroup->excl_cmpr) {
18431852
DEBUG_WARN();
1844-
btrfs_warn_rl(fs_info,
1845-
"to be deleted qgroup %u/%llu has non-zero numbers, rfer %llu rfer_cmpr %llu excl %llu excl_cmpr %llu",
1846-
btrfs_qgroup_level(qgroup->qgroupid),
1847-
btrfs_qgroup_subvolid(qgroup->qgroupid),
1848-
qgroup->rfer, qgroup->rfer_cmpr,
1849-
qgroup->excl, qgroup->excl_cmpr);
1850-
qgroup_mark_inconsistent(fs_info);
1853+
qgroup_mark_inconsistent(fs_info,
1854+
"to be deleted qgroup %u/%llu has non-zero numbers, rfer %llu rfer_cmpr %llu excl %llu excl_cmpr %llu",
1855+
btrfs_qgroup_level(qgroup->qgroupid),
1856+
btrfs_qgroup_subvolid(qgroup->qgroupid),
1857+
qgroup->rfer, qgroup->rfer_cmpr,
1858+
qgroup->excl, qgroup->excl_cmpr);
18511859
}
18521860
}
18531861
del_qgroup_rb(fs_info, qgroupid);
@@ -1965,11 +1973,8 @@ int btrfs_limit_qgroup(struct btrfs_trans_handle *trans, u64 qgroupid,
19651973
spin_unlock(&fs_info->qgroup_lock);
19661974

19671975
ret = update_qgroup_limit_item(trans, qgroup);
1968-
if (ret) {
1969-
qgroup_mark_inconsistent(fs_info);
1970-
btrfs_info(fs_info, "unable to update quota limit for %llu",
1971-
qgroupid);
1972-
}
1976+
if (ret)
1977+
qgroup_mark_inconsistent(fs_info, "qgroup item update error %d", ret);
19731978

19741979
out:
19751980
mutex_unlock(&fs_info->qgroup_ioctl_lock);
@@ -2024,7 +2029,7 @@ int btrfs_qgroup_trace_extent_nolock(struct btrfs_fs_info *fs_info,
20242029
ret = __xa_store(&delayed_refs->dirty_extents, index, record, GFP_ATOMIC);
20252030
xa_unlock(&delayed_refs->dirty_extents);
20262031
if (xa_is_err(ret)) {
2027-
qgroup_mark_inconsistent(fs_info);
2032+
qgroup_mark_inconsistent(fs_info, "xarray insert error: %d", xa_err(ret));
20282033
return xa_err(ret);
20292034
}
20302035

@@ -2091,10 +2096,8 @@ int btrfs_qgroup_trace_extent_post(struct btrfs_trans_handle *trans,
20912096

20922097
ret = btrfs_find_all_roots(&ctx, true);
20932098
if (ret < 0) {
2094-
qgroup_mark_inconsistent(fs_info);
2095-
btrfs_warn(fs_info,
2096-
"error accounting new delayed refs extent (err code: %d), quota inconsistent",
2097-
ret);
2099+
qgroup_mark_inconsistent(fs_info,
2100+
"error accounting new delayed refs extent: %d", ret);
20982101
return 0;
20992102
}
21002103

@@ -2586,7 +2589,7 @@ static int qgroup_trace_subtree_swap(struct btrfs_trans_handle *trans,
25862589
out:
25872590
btrfs_free_path(dst_path);
25882591
if (ret < 0)
2589-
qgroup_mark_inconsistent(fs_info);
2592+
qgroup_mark_inconsistent(fs_info, "%s error: %d", __func__, ret);
25902593
return ret;
25912594
}
25922595

@@ -2630,7 +2633,7 @@ int btrfs_qgroup_trace_subtree(struct btrfs_trans_handle *trans,
26302633
* mark qgroup inconsistent.
26312634
*/
26322635
if (root_level >= drop_subptree_thres) {
2633-
qgroup_mark_inconsistent(fs_info);
2636+
qgroup_mark_inconsistent(fs_info, "subtree level reached threshold");
26342637
return 0;
26352638
}
26362639

@@ -3130,10 +3133,12 @@ int btrfs_run_qgroups(struct btrfs_trans_handle *trans)
31303133
spin_unlock(&fs_info->qgroup_lock);
31313134
ret = update_qgroup_info_item(trans, qgroup);
31323135
if (ret)
3133-
qgroup_mark_inconsistent(fs_info);
3136+
qgroup_mark_inconsistent(fs_info,
3137+
"qgroup info item update error %d", ret);
31343138
ret = update_qgroup_limit_item(trans, qgroup);
31353139
if (ret)
3136-
qgroup_mark_inconsistent(fs_info);
3140+
qgroup_mark_inconsistent(fs_info,
3141+
"qgroup limit item update error %d", ret);
31373142
spin_lock(&fs_info->qgroup_lock);
31383143
}
31393144
if (btrfs_qgroup_enabled(fs_info))
@@ -3144,7 +3149,8 @@ int btrfs_run_qgroups(struct btrfs_trans_handle *trans)
31443149

31453150
ret = update_qgroup_status_item(trans);
31463151
if (ret)
3147-
qgroup_mark_inconsistent(fs_info);
3152+
qgroup_mark_inconsistent(fs_info,
3153+
"qgroup status item update error %d", ret);
31483154

31493155
return ret;
31503156
}
@@ -3551,7 +3557,7 @@ int btrfs_qgroup_inherit(struct btrfs_trans_handle *trans, u64 srcid,
35513557
if (!committing)
35523558
mutex_unlock(&fs_info->qgroup_ioctl_lock);
35533559
if (need_rescan)
3554-
qgroup_mark_inconsistent(fs_info);
3560+
qgroup_mark_inconsistent(fs_info, "qgroup inherit needs a rescan");
35553561
if (qlist_prealloc) {
35563562
for (int i = 0; i < inherit->num_qgroups; i++)
35573563
kfree(qlist_prealloc[i]);
@@ -4785,7 +4791,7 @@ int btrfs_qgroup_add_swapped_blocks(struct btrfs_root *subvol_root,
47854791
spin_unlock(&blocks->lock);
47864792
out:
47874793
if (ret < 0)
4788-
qgroup_mark_inconsistent(fs_info);
4794+
qgroup_mark_inconsistent(fs_info, "%s error: %d", __func__, ret);
47894795
return ret;
47904796
}
47914797

@@ -4863,10 +4869,9 @@ int btrfs_qgroup_trace_subtree_after_cow(struct btrfs_trans_handle *trans,
48634869
free_extent_buffer(reloc_eb);
48644870
out:
48654871
if (ret < 0) {
4866-
btrfs_err_rl(fs_info,
4867-
"failed to account subtree at bytenr %llu: %d",
4868-
subvol_eb->start, ret);
4869-
qgroup_mark_inconsistent(fs_info);
4872+
qgroup_mark_inconsistent(fs_info,
4873+
"failed to account subtree at bytenr %llu: %d",
4874+
subvol_eb->start, ret);
48704875
}
48714876
return ret;
48724877
}

0 commit comments

Comments
 (0)