diff --git a/mkfs/rootdir.c b/mkfs/rootdir.c index 0a2154b6..70cf0f84 100644 --- a/mkfs/rootdir.c +++ b/mkfs/rootdir.c @@ -725,7 +725,7 @@ static int ftw_add_inode(const char *full_path, const struct stat *st, parent = rootdir_path_last(¤t_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; @@ -771,6 +771,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, @@ -782,10 +783,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 63ba928f..e4ae604e 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"