linux-btrfs.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v2] btrfs-progs: qgroup-verify: Check if qgroup limit is exceeded
@ 2018-12-18  5:28 Qu Wenruo
  0 siblings, 0 replies; only message in thread
From: Qu Wenruo @ 2018-12-18  5:28 UTC (permalink / raw)
  To: linux-btrfs

[ENHANCEMENT]
This patch will enhance qgroup verify code to report qgroup number
exceeding its limit as error.

For test case fstests/btrfs/139, it will fail if the system has less
than 2G ram, resulting qgroup numbers exceeding its limit, and the test
case itself will detect such exceeding.

However it would be time consuming to make every qgroup test detect limit
exceeding, so enhancing btrfs check to detect such problem is a pretty
natural move.

[IMPLEMENTATION]
- Read out the qgroup limit number at load_quota_info()
  Here we will ignore certain unsupported limit flags.

- Compare limit to the calculated number

- Report error if we exceed the limit

Signed-off-by: Qu Wenruo <wqu@suse.com>
---
changelog:
v2:
  Update commit message to show more details of this modification.
---
 qgroup-verify.c | 82 +++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 82 insertions(+)

diff --git a/qgroup-verify.c b/qgroup-verify.c
index 3f2ce14a51a9..d59b40e4d3e0 100644
--- a/qgroup-verify.c
+++ b/qgroup-verify.c
@@ -54,6 +54,11 @@ struct qgroup_info {
 	u64 exclusive_compressed;
 };
 
+struct qgroup_limit {
+	u64 max_rfer;
+	u64 max_excl;
+};
+
 struct qgroup_count {
 	u64 qgroupid;
 	int subvol_exists;
@@ -63,6 +68,8 @@ struct qgroup_count {
 
 	struct qgroup_info info;
 
+	struct qgroup_limit limit;
+
 	struct rb_node rb_node;
 
 	/* Parents when we are a child group */
@@ -926,6 +933,48 @@ static void read_qgroup_status(struct extent_buffer *eb, int slot,
 	counts->scan_progress = btrfs_qgroup_status_rescan(eb, status_item);
 }
 
+static void read_qgroup_limit(struct extent_buffer *leaf, int slot)
+{
+	struct btrfs_key key;
+	struct btrfs_qgroup_limit_item *qli;
+	struct qgroup_count *count;
+	u64 flags;
+
+	btrfs_item_key_to_cpu(leaf, &key, slot);
+	qli = btrfs_item_ptr(leaf, slot, struct btrfs_qgroup_limit_item);
+	flags = btrfs_qgroup_limit_flags(leaf, qli);
+
+	/*
+	 * Despite the deprecated LIMIT_RSV_* flags, for CMPR (compressed)
+	 * limit it doesn't really work either.
+	 * As qgroup works at extent level, all numbers are at compressed size
+	 * already.
+	 */
+	if (flags & (BTRFS_QGROUP_LIMIT_RSV_RFER |
+		     BTRFS_QGROUP_LIMIT_RSV_EXCL |
+		     BTRFS_QGROUP_LIMIT_RFER_CMPR |
+		     BTRFS_QGROUP_LIMIT_EXCL_CMPR)) {
+		warning("ignoring deprecated limit flags for qgroup %llu/%llu",
+			btrfs_qgroup_level(key.offset),
+			btrfs_qgroup_subvid(key.offset));
+	}
+	count = find_count(key.offset);
+	if (!count) {
+		warning(
+	"found orphan QGROUP_LIMIT item, qgroup %llu/%llu doesn't exist",
+			btrfs_qgroup_level(key.offset),
+			btrfs_qgroup_subvid(key.offset));
+		return;
+	}
+	memset(&count->limit, 0, sizeof(struct qgroup_limit));
+	if (flags & BTRFS_QGROUP_LIMIT_MAX_RFER)
+		count->limit.max_rfer =
+			btrfs_qgroup_limit_max_referenced(leaf, qli);
+	if (flags & BTRFS_QGROUP_LIMIT_MAX_EXCL)
+		count->limit.max_excl =
+			btrfs_qgroup_limit_max_exclusive(leaf, qli);
+}
+
 static int load_quota_info(struct btrfs_fs_info *info)
 {
 	int ret;
@@ -979,6 +1028,10 @@ loop:
 				continue;
 			}
 
+			if (key.type == BTRFS_QGROUP_LIMIT_KEY) {
+				read_qgroup_limit(leaf, i);
+				continue;
+			}
 			if (key.type == BTRFS_QGROUP_STATUS_KEY) {
 				read_qgroup_status(leaf, i, &counts);
 				continue;
@@ -1308,6 +1361,31 @@ static int report_qgroup_difference(struct qgroup_count *count, int verbose)
 	return is_different;
 }
 
+bool report_qgroup_limit_error(struct qgroup_count *count)
+{
+	struct qgroup_info *info = &count->info;
+	struct qgroup_limit *limit = &count->limit;
+	bool ret = false;
+
+	if (limit->max_excl && limit->max_excl < info->exclusive) {
+		printf("Exclusive limit for qgroup id: %llu/%llu is exceeded\n",
+			btrfs_qgroup_level(count->qgroupid),
+			btrfs_qgroup_subvid(count->qgroupid));
+		print_fields(limit->max_excl, info->exclusive, "limit",
+			     "exclusive");
+		ret = true;
+	}
+	if (limit->max_rfer && limit->max_rfer < info->referenced) {
+		printf("Referenced limit for qgroup id: %llu/%llu is exceeded\n",
+			btrfs_qgroup_level(count->qgroupid),
+			btrfs_qgroup_subvid(count->qgroupid));
+		print_fields(limit->max_rfer, info->referenced, "limit",
+			     "referenced");
+		ret = true;
+	}
+	return ret;
+}
+
 /*
  * Report qgroups errors
  * Return 0 if nothing wrong.
@@ -1352,6 +1430,10 @@ int report_qgroups(int all)
 			list_add_tail(&c->bad_list, &bad_qgroups);
 			found_err = true;
 		}
+		if (report_qgroup_limit_error(c)) {
+			list_add_tail(&c->bad_list, &bad_qgroups);
+			found_err = true;
+		}
 
 		node = rb_next(node);
 	}
-- 
2.20.0


^ permalink raw reply related	[flat|nested] only message in thread

only message in thread, other threads:[~2018-12-18  5:28 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-12-18  5:28 [PATCH v2] btrfs-progs: qgroup-verify: Check if qgroup limit is exceeded Qu Wenruo

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).