diff mbox series

btrfs-progs: cmds/qgroup: use sysfs to detect inconsistent status early

Message ID 7171b8a518e70a5b2e8e791dd078d7cc4f643b83.1739420945.git.wqu@suse.com (mailing list archive)
State New
Headers show
Series btrfs-progs: cmds/qgroup: use sysfs to detect inconsistent status early | expand

Commit Message

Qu Wenruo Feb. 13, 2025, 4:29 a.m. UTC
Currently if "btrfs qgroup show" detects the qgroup is in an inconsistent,
it will output a warning:

  WARNING: qgroup data inconsistent, rescan recommended

But the detection is based on the tree search ioctl, and qgroup tree is
only updated at transaction commit time.

This means if qgroup is marked inconsistent, and the transaction is not
commit, there can be a huge window as long as 30s before "btrfs qgroup
show" to give a proper warning about inconsistent qgroup numbers.

To address this window, use the
'/sys/fs/btrfs/<fsid>/qgroup/inconsistent' file to do extra check.

That file is updated at real time, thus there is no delay, and can give
an early warning about inconsistent qgroup numbers.

Link: https://bugzilla.suse.com/show_bug.cgi?id=1235765
Signed-off-by: Qu Wenruo <wqu@suse.com>
---
 cmds/qgroup.c | 30 ++++++++++++++++++++++++++++++
 1 file changed, 30 insertions(+)
diff mbox series

Patch

diff --git a/cmds/qgroup.c b/cmds/qgroup.c
index a612130c94b8..45439953be14 100644
--- a/cmds/qgroup.c
+++ b/cmds/qgroup.c
@@ -36,6 +36,7 @@ 
 #include "kernel-shared/uapi/btrfs.h"
 #include "kernel-shared/ctree.h"
 #include "common/open-utils.h"
+#include "common/sysfs-utils.h"
 #include "common/utils.h"
 #include "common/help.h"
 #include "common/units.h"
@@ -1610,6 +1611,33 @@  static void print_all_qgroups_json(struct qgroup_lookup *qgroup_lookup)
 	fmt_end(&fctx);
 }
 
+/*
+ * Tree search based inconsistent flag is only updated at transaction commit
+ * time.
+ * Thus even if the qgroup_status flag shows consistent, the qgroup may already
+ * be in an inconsistent status.
+ */
+static void check_qgroup_sysfs_inconsistent(int fd,
+		const struct qgroup_lookup *qgroup_lookup)
+{
+	u64 value;
+	int sysfs_fd;
+	int ret;
+
+	if (qgroup_lookup->flags & BTRFS_QGROUP_STATUS_FLAG_INCONSISTENT)
+		return;
+	sysfs_fd = sysfs_open_fsid_file(fd, "qgroups/inconsistent");
+	if (fd < 0)
+		return;
+	ret = sysfs_read_fsid_file_u64(fd, "qgroups/inconsistent", &value);
+	if (ret < 0)
+		goto out;
+	if (value)
+		warning("qgroup data inconsistent, rescan recommended");
+out:
+	close(sysfs_fd);
+}
+
 static int show_qgroups(int fd,
 		       struct btrfs_qgroup_filter_set *filter_set,
 		       struct btrfs_qgroup_comparer_set *comp_set)
@@ -1622,6 +1650,8 @@  static int show_qgroups(int fd,
 	ret = qgroups_search_all(fd, &qgroup_lookup);
 	if (ret)
 		return ret;
+
+	check_qgroup_sysfs_inconsistent(fd, &qgroup_lookup);
 	__filter_and_sort_qgroups(&qgroup_lookup, &sort_tree,
 				  filter_set, comp_set);
 	if (bconf.output_format == CMD_FORMAT_JSON)