Skip to contentSkip to conversation

btrfs-progs: mkfs: fix garbage in QGROUP_LIMIT

PATCH New Qu Wenruo 1 participant 3 messages Nov 10 Btrfs file system

lore
Share & tools
lore

Qu Wenruo

author
#0 lore raw

cover btrfs-progs: mkfs: fix garbage in QGROUP_LIMIT

Running "mkfs.btrfs -O quota" will result garbage values in QGROUP_LIMIT items.

This is inspired by recent tree-checker changes to check QGROUP_LIMIT and QGROUP_INFO.

And a new test case for it.

Qu Wenruo (2):
btrfs-progs: mkfs: fix garbage in the QGROUP_LIMIT item
btrfs-progs: tests: add test for zeroed QGROUP_LIMIT item from mkfs

 mkfs/main.c                                   |  6 ++++
 .../046-qgroup-limit-zeroed/test.sh           | 30 +++++++++++++++++++
 2 files changed, 36 insertions(+)
 create mode 100755 tests/mkfs-tests/046-qgroup-limit-zeroed/test.sh

--
2.56.0

author
#1 lore raw

PATCH 1/2 btrfs-progs: mkfs: fix garbage in the QGROUP_LIMIT item

[BUG]
If using "-O quota" option of mkfs.btrfs, the resulted image will have garbage in the QGROUP_LIMIT item:

quota tree key (QUOTA_TREE ROOT_ITEM 0)
leaf 30474240 items 3 free space 16088 generation 11 owner QUOTA_TREE leaf 30474240 flags 0x1(WRITTEN) backref revision 1
item 0 key (0 QGROUP_STATUS 0) itemoff 16243 itemsize 40
version 1 generation 11 flags ON scan 0
item 1 key (0 QGROUP_INFO 0/5) itemoff 16203 itemsize 40
generation 10
referenced 16384 referenced_compressed 16384 exclusive 16384 exclusive_compressed 16384
item 2 key (0 QGROUP_LIMIT 0/5) itemoff 16163 itemsize 40
flags 500000
max_referenced 8388608 max_exclusive 8954665512184738474 rsv_referenced 5153854573009882032 rsv_exclusive 3

                               ^^^^^^^^^^^^^^^^^^^

[CAUSE]
The QGROUP_INFO and QGROUP_LIMIT items are inserted using btrfs_insert_empty_item(), which will not do any cleanup for the new item, so it will reuse whatever is left in the tree block.

For QGROUP_INFO it's not a big deal as later repair_qgroups() will update the item, but QGROUP_LIMIT garbage is left there.

[FIX]
Zero the newly inserted empty items for both QGROUP_INFO and QGROUP_LIMIT.

---
 mkfs/main.c | 6 ++++++
 1 file changed, 6 insertions(+)
mkfs/main.c +6 -0
index d61af04e055e..74b98fccf3f6 100644
@@ -897,6 +897,9 @@ static int insert_qgroup_items(struct btrfs_trans_handle *trans,
 
 	ret = btrfs_insert_empty_item(trans, quota_root, &path, &key,
 				      sizeof(struct btrfs_qgroup_info_item));
+	memset_extent_buffer(path.nodes[0], 0,
+			     btrfs_item_ptr_offset(path.nodes[0], path.slots[0]),
+			     btrfs_item_size(path.nodes[0], path.slots[0]));
 	btrfs_release_path(&path);
 	if (ret < 0)
 		return ret;
@@ -906,6 +909,9 @@ static int insert_qgroup_items(struct btrfs_trans_handle *trans,
 	key.offset = qgroupid;
 	ret = btrfs_insert_empty_item(trans, quota_root, &path, &key,
 				      sizeof(struct btrfs_qgroup_limit_item));
+	memset_extent_buffer(path.nodes[0], 0,
+			     btrfs_item_ptr_offset(path.nodes[0], path.slots[0]),
+			     btrfs_item_size(path.nodes[0], path.slots[0]));
 	return ret;
 }
 
Signature · 1 line
2.56.0
author
#2 lore raw

PATCH 2/2 btrfs-progs: tests: add test for zeroed QGROUP_LIMIT item from mkfs

In reply to Qu Wenruo

Add a mkfs test that creates a filesystem with '-O quota' and verifies all members of the QGROUP_LIMIT items are zero.

This covers the garbage fix in the previous commit.

Assisted-by LLM (generate the test case)
---
 .../046-qgroup-limit-zeroed/test.sh           | 30 +++++++++++++++++++
 1 file changed, 30 insertions(+)
 create mode 100755 tests/mkfs-tests/046-qgroup-limit-zeroed/test.sh
tests/mkfs-tests/046-qgroup-limit-zeroed/test.sh new file +30 -0
new file mode 100755
index 000000000000..54b66927a842
@@ -0,0 +1,30 @@
+#!/bin/bash
+# Verify that mkfs -O quota zeroes all members of the QGROUP_LIMIT items.
+
+source "$TEST_TOP/common" || exit
+
+check_prereq mkfs.btrfs
+check_prereq btrfs
+
+setup_root_helper
+prepare_test_dev
+
+run_check $SUDO_HELPER "$TOP/mkfs.btrfs" -f -O quota "$TEST_DEV"
+
+# A good limit item should looks like:
+#
+# item 2 key (0 QGROUP_LIMIT 0/5) itemoff 16027 itemsize 40
+#         flags 0
+#         max_referenced 0 max_exclusive 0
+#         rsv_referenced 0 rsv_exclusive 0
+output=$(run_check_stdout $SUDO_HELPER "$TOP/btrfs" inspect-internal dump-tree -t quota "$TEST_DEV" | \
+	grep -A 3 "QGROUP_LIMIT")
+
+if [ -z "$output" ]; then
+	_fail "no QGROUP_LIMIT item found"
+fi
+
+for member in flags max_referenced max_exclusive rsv_referenced rsv_exclusive; do
+	echo "$output" | grep -q -w "$member 0" ||
+		_fail "QGROUP_LIMIT member $member is not zero"
+done
Signature · 1 line
2.56.0