diff mbox series

[v2,2/2] btrfs-progs: mkfs-tests: add hardlink related tests for --subvol

Message ID 0349bf78a0029b7596f3ba47e6defef1e949852f.1724125282.git.wqu@suse.com (mailing list archive)
State New
Headers show
Series btrfs-progs: mkfs/rootdir: add hard link support | expand

Commit Message

Qu Wenruo Aug. 20, 2024, 3:45 a.m. UTC
This introduces two new cases:

- 3 hardlinks without any subvolume
  This should results 3 hard links inside the btrfs.

- 3 hardlinks, but a subvolume will split 2 of them
  Then the 2 inside the same subvolume should still report 2 nlinks,
  but the lone one inside the new subvolume can only report 1 nlink.

Signed-off-by: Qu Wenruo <wqu@suse.com>
---
 mkfs/rootdir.c                              |  8 +--
 tests/mkfs-tests/036-rootdir-subvol/test.sh | 78 +++++++++++++++++----
 2 files changed, 68 insertions(+), 18 deletions(-)
diff mbox series

Patch

diff --git a/mkfs/rootdir.c b/mkfs/rootdir.c
index e1ca00f57e60..a24afe0715bb 100644
--- a/mkfs/rootdir.c
+++ b/mkfs/rootdir.c
@@ -721,7 +721,7 @@  static int ftw_add_inode(const char *full_path, const struct stat *st,
 	parent = rootdir_path_last(&current_path);
 	root = parent->root;
 
-	/* For non-directory inode, check if there is already any hard link. */
+	/* Check if there is already a hard link record for this. */
 	if (have_hard_links) {
 		struct hardlink_entry *found;
 
@@ -767,6 +767,7 @@  static int ftw_add_inode(const char *full_path, const struct stat *st,
 		error("failed to insert inode item %llu for '%s': %m", ino, full_path);
 		return ret;
 	}
+
 	ret = btrfs_add_link(g_trans, root, ino, parent->ino,
 			     full_path + ftwbuf->base,
 			     strlen(full_path) - ftwbuf->base,
@@ -778,10 +779,7 @@  static int ftw_add_inode(const char *full_path, const struct stat *st,
 		return ret;
 	}
 
-	/*
-	 * Found a possible hard link, add it into the hard link rb tree for
-	 * future detection.
-	 */
+	/* Record this new hard link. */
 	if (have_hard_links) {
 		ret = add_hard_link(root, ino, st);
 		if (ret < 0) {
diff --git a/tests/mkfs-tests/036-rootdir-subvol/test.sh b/tests/mkfs-tests/036-rootdir-subvol/test.sh
index 63ba928f348a..38491332170d 100755
--- a/tests/mkfs-tests/036-rootdir-subvol/test.sh
+++ b/tests/mkfs-tests/036-rootdir-subvol/test.sh
@@ -11,23 +11,75 @@  prepare_test_dev
 
 tmp=$(_mktemp_dir mkfs-rootdir)
 
-run_check touch "$tmp/foo"
-run_check mkdir "$tmp/dir"
-run_check mkdir "$tmp/dir/subvol"
-run_check touch "$tmp/dir/subvol/bar"
+basic()
+{
+	run_check touch "$tmp/foo"
+	run_check mkdir "$tmp/dir"
+	run_check mkdir "$tmp/dir/subvol"
+	run_check touch "$tmp/dir/subvol/bar"
 
-run_check_mkfs_test_dev --rootdir "$tmp" --subvol dir/subvol
-run_check $SUDO_HELPER "$TOP/btrfs" check "$TEST_DEV"
+	run_check_mkfs_test_dev --rootdir "$tmp" --subvol dir/subvol
+	run_check $SUDO_HELPER "$TOP/btrfs" check "$TEST_DEV"
 
-run_check_mount_test_dev
-run_check_stdout $SUDO_HELPER "$TOP/btrfs" subvolume list "$TEST_MNT" | \
+	run_check_mount_test_dev
+	run_check_stdout $SUDO_HELPER "$TOP/btrfs" subvolume list "$TEST_MNT" | \
 	cut -d\  -f9 > "$tmp/output"
-run_check_umount_test_dev
+	run_check_umount_test_dev
 
-result=$(cat "$tmp/output")
+	result=$(cat "$tmp/output")
 
-if [ "$result" != "dir/subvol" ]; then
-	_fail "dir/subvol not in subvolume list"
-fi
+	if [ "$result" != "dir/subvol" ]; then
+		_fail "dir/subvol not in subvolume list"
+	fi
+	rm -rf -- "$tmp/foo" "$tmp/dir"
+}
 
+basic_hardlinks()
+{
+	run_check touch "$tmp/hl1"
+	run_check ln "$tmp/hl1" "$tmp/hl2"
+	run_check mkdir "$tmp/dir"
+	run_check ln "$tmp/hl1" "$tmp/dir/hl3"
+
+	run_check_mkfs_test_dev --rootdir "$tmp"
+	run_check $SUDO_HELPER "$TOP/btrfs" check "$TEST_DEV"
+
+	run_check_mount_test_dev
+	nr_hardlink=$(run_check_stdout $SUDO_HELPER stat -c "%h" "$TEST_MNT/hl1")
+
+	if [ "$nr_hardlink" -ne 3 ]; then
+		_fail "hard link number incorrect, has ${nr_hardlink} expect 3"
+	fi
+	run_check_umount_test_dev
+	rm -rf -- "$tmp/hl1" "$tmp/hl2" "$tmp/dir"
+}
+
+split_by_subvolume_hardlinks()
+{
+	run_check touch "$tmp/hl1"
+	run_check ln "$tmp/hl1" "$tmp/hl2"
+	run_check mkdir "$tmp/subv"
+	run_check ln "$tmp/hl1" "$tmp/subv/hl3"
+
+	run_check_mkfs_test_dev --rootdir "$tmp" --subvol subv
+	run_check $SUDO_HELPER "$TOP/btrfs" check "$TEST_DEV"
+
+	run_check_mount_test_dev
+	nr_hardlink=$(run_check_stdout $SUDO_HELPER stat -c "%h" "$TEST_MNT/hl1")
+
+	if [ $nr_hardlink -ne 2 ]; then
+		_fail "hard link number incorrect for hl1, has ${nr_hardlink} expect 2"
+	fi
+
+	nr_hardlink=$(run_check_stdout $SUDO_HELPER stat -c "%h" "$TEST_MNT/subv/hl3")
+	if [ $nr_hardlink -ne 1 ]; then
+		_fail "hard link number incorrect for subv/hl3, has ${nr_hardlink} expect 1"
+	fi
+	run_check_umount_test_dev
+	rm -rf -- "$tmp/hl1" "$tmp/hl2" "$tmp/dir"
+}
+
+basic
+basic_hardlinks
+split_by_subvolume_hardlinks
 rm -rf -- "$tmp"