diff mbox series

[4/4] btrfs-progs: cmds/qgroup: add more special status for qgroups

Message ID 6b7f2367322a05e6442fd8f5aedac23490b32b1c.1715245781.git.wqu@suse.com (mailing list archive)
State New
Headers show
Series btrfs-progs: cmds/qgroup: enhance stale qgroups handling | expand

Commit Message

Qu Wenruo May 9, 2024, 9:12 a.m. UTC
Currently `btrfs qgroup show` command shows any 0 level qgroup withou a
root backref as `<stale>`, which is not correct.

There are several more cases:

- Under deletion
  The subvolume is not yet full dropped, but unlinked.
  In that case we would not have a root backref item, but the qgroup is
  not stale.

- Squota space holder
  This is for squota mode, that a fully dropped subvolume still have
  extents accounting on the already-gone subvolume.
  In this case it's not stale either, and future accounting relies on
  it.

This patch would add above special cases, and add an extra `SPECIAL
PATHS` section to explain all the cases, including `<stale>`.

Signed-off-by: Qu Wenruo <wqu@suse.com>
---
 Documentation/btrfs-qgroup.rst | 24 ++++++++++++++++++++++++
 cmds/qgroup.c                  | 32 ++++++++++++++++++++++++++------
 2 files changed, 50 insertions(+), 6 deletions(-)
diff mbox series

Patch

diff --git a/Documentation/btrfs-qgroup.rst b/Documentation/btrfs-qgroup.rst
index 343626767eb5..0e47c336619f 100644
--- a/Documentation/btrfs-qgroup.rst
+++ b/Documentation/btrfs-qgroup.rst
@@ -153,6 +153,30 @@  show [options] <path>
                 To retrieve information after updating the state of qgroups,
                 force sync of the filesystem identified by *path* before getting information.
 
+SPECIAL PATHS
+-------------
+For `btrfs qgroup show` subcommand, the ``path`` column may has some special
+strings:
+
+`<toplevel>`
+	The toplevel subvolume
+
+`<under deletion>`
+	The subvolume is unlinked, but not yet fully deleted.
+
+`<squota space holder>`
+	For simple quota mode only.
+	By its design, a fully deleted subvolume may still have accounting on
+	it, so even the subvolume is gone, the numbers are still here for future
+	accounting.
+
+`<stale>`
+	The qgroup has no corresponding subvolume anymore, and the qgroup
+	can be cleaned up under most cases.
+	The only exception is that, if the qgroup numbers are inconsistent and
+	the qgroup numbers are not all zeros, some older kernels may refuse to
+	delete such qgroups until a full rescan.
+
 QUOTA RESCAN
 ------------
 
diff --git a/cmds/qgroup.c b/cmds/qgroup.c
index 70a306117ebd..928c432ca432 100644
--- a/cmds/qgroup.c
+++ b/cmds/qgroup.c
@@ -71,6 +71,8 @@  struct qgroup_lookup {
 };
 
 struct btrfs_qgroup {
+	struct qgroup_lookup *lookup;
+
 	struct rb_node rb_node;
 	struct rb_node sort_node;
 	/*
@@ -321,6 +323,26 @@  static void print_qgroup_column_add_blank(enum btrfs_qgroup_column_enum column,
 		printf(" ");
 }
 
+static const char *get_qgroup_path(struct btrfs_qgroup *qgroup)
+{
+	if (qgroup->path)
+		return qgroup->path;
+
+	/* No path but not stale either, the qgroup is being deleted. */
+	if (!qgroup->stale)
+		return "<under deletion>";
+	/*
+	 * Squota mode stale qgroup, but not empty.
+	 * This is fully deleted but still necessary.
+	 */
+	if (qgroup->stale &&
+	    (qgroup->lookup->flags & BTRFS_QGROUP_STATUS_FLAG_SIMPLE_MODE) &&
+	    !is_qgroup_empty(qgroup))
+		return "<squota space holder>";
+
+	return "<stale>";
+}
+
 static void print_path_column(struct btrfs_qgroup *qgroup)
 {
 	struct btrfs_qgroup_list *list = NULL;
@@ -338,11 +360,8 @@  static void print_path_column(struct btrfs_qgroup *qgroup)
 			if (count)
 				pr_verbose(LOG_DEFAULT, " ");
 			if (level == 0) {
-				const char *path = member->path;
-
-				if (!path)
-					path = "<stale>";
-				pr_verbose(LOG_DEFAULT, "%s", path);
+				pr_verbose(LOG_DEFAULT, "%s",
+					   get_qgroup_path(qgroup));
 			} else {
 				pr_verbose(LOG_DEFAULT, "%llu/%llu", level, sid);
 			}
@@ -353,7 +372,7 @@  static void print_path_column(struct btrfs_qgroup *qgroup)
 	} else if (qgroup->path) {
 		pr_verbose(LOG_DEFAULT, "%s%s", (*qgroup->path ? "" : "<toplevel>"), qgroup->path);
 	} else {
-		pr_verbose(LOG_DEFAULT, "<stale>");
+		pr_verbose(LOG_DEFAULT, "%s", get_qgroup_path(qgroup));
 	}
 }
 
@@ -805,6 +824,7 @@  static struct btrfs_qgroup *get_or_add_qgroup(int fd,
 		return ERR_PTR(-ENOMEM);
 	}
 
+	bq->lookup = qgroup_lookup;
 	bq->qgroupid = qgroupid;
 	INIT_LIST_HEAD(&bq->qgroups);
 	INIT_LIST_HEAD(&bq->members);