Linux Btrfs filesystem development
 help / color / mirror / Atom feed
* [PATCH] btrfs-progs: logical-resolve: fix the subvolume path resolution
@ 2023-04-17  9:48 Qu Wenruo
  2023-04-17 21:17 ` Torstein Eide
  2023-04-18 23:55 ` David Sterba
  0 siblings, 2 replies; 9+ messages in thread
From: Qu Wenruo @ 2023-04-17  9:48 UTC (permalink / raw)
  To: linux-btrfs; +Cc: Torstein Eide

[BUG]
There is a bug report that "btrfs inspect logical-resolve" can not even
handle any file inside non-top-level subvolumes:

 # mkfs.btrfs $dev
 # mount $dev $mnt
 # btrfs subvol create $mnt/subv1
 # xfs_io -f -c "pwrite 0 16k" $mnt/subv1/file
 # sync
 # btrfs inspect logical-resolve 13631488 $mnt
 inode 257 subvol subv1 could not be accessed: not mounted

This means the command "btrfs inspect logical-resolve" is almost useless
for resolving logical bytenr to files.

[CAUSE]
"btrfs inspect logical-resolve" firstly resolve the logical bytenr to
root/ino pairs, then call btrfs_subvolid_resolve() to resolve the path
to the subvolume.

Then to handle cases where the subvolume is already mounted somewhere
else, we call find_mount_fsroot().

But if that target subvolume is not yet mounted, we just error out, even
if the @path is the top-level subvolume, and we have already know the
path to the subvolume.

[FIX]
Instead of doing unnecessary subvolume mount point check, just require
the @path to be the mount point of the top-level subvolume.

So that we can access all subvolumes without mounting each one.

Now the command works as expected:

 # ./btrfs inspect logical-resolve 13631488 $mnt
 /mnt/btrfs/subv1/file

And since we're changing the behavior of "logical-resolve" (to a more
user-friendly one), we have to update the test case misc/042 to reflect
that.

Reported-by: Torstein Eide <torsteine@gmail.com>
Signed-off-by: Qu Wenruo <wqu@suse.com>
---
 Documentation/btrfs-inspect-internal.rst      |  3 ++
 cmds/inspect.c                                | 54 ++++++++-----------
 .../test.sh                                   | 25 ---------
 3 files changed, 24 insertions(+), 58 deletions(-)

diff --git a/Documentation/btrfs-inspect-internal.rst b/Documentation/btrfs-inspect-internal.rst
index 4265fab6..69da468a 100644
--- a/Documentation/btrfs-inspect-internal.rst
+++ b/Documentation/btrfs-inspect-internal.rst
@@ -149,6 +149,9 @@ logical-resolve [-Pvo] [-s <bufsize>] <logical> <path>
 
         resolve paths to all files at given *logical* address in the linear filesystem space
 
+        User should make sure *path* is the mount point of the top-level
+        subvolume (subvolid 5).
+
         ``Options``
 
         -P
diff --git a/cmds/inspect.c b/cmds/inspect.c
index 20f433b9..dc0e587f 100644
--- a/cmds/inspect.c
+++ b/cmds/inspect.c
@@ -158,6 +158,9 @@ static int cmd_inspect_logical_resolve(const struct cmd_struct *cmd,
 	int ret;
 	int fd;
 	int i;
+	const char *top_subvol = "/";
+	const char *top_subvolid = "5";
+	char *mounted = NULL;
 	bool getpath = true;
 	int bytes_left;
 	struct btrfs_ioctl_logical_ino_args loi = { 0 };
@@ -216,6 +219,23 @@ static int cmd_inspect_logical_resolve(const struct cmd_struct *cmd,
 		goto out;
 	}
 
+	/*
+	 * For logical-resolve, we want the mount point to be top level
+	 * subvolume (5), so that we can access all subvolumes.
+	 */
+	ret = find_mount_fsroot(top_subvol, top_subvolid, &mounted);
+	if (ret) {
+		error("failed to parse mountinfo");
+		goto out;
+	}
+	if (!mounted) {
+		ret = -ENOENT;
+		error("mount point \"%s\" is not the top-level subvolume",
+		      argv[optind + 1]);
+		goto out;
+	}
+	free(mounted);
+
 	ret = ioctl(fd, request, &loi);
 	if (ret < 0) {
 		error("logical ino ioctl: %m");
@@ -258,39 +278,7 @@ static int cmd_inspect_logical_resolve(const struct cmd_struct *cmd,
 				path_fd = fd;
 				strncpy(mount_path, full_path, PATH_MAX);
 			} else {
-				char *mounted = NULL;
-				char subvol[PATH_MAX];
-				char subvolid[PATH_MAX];
-
-				/*
-				 * btrfs_subvolid_resolve returns the full
-				 * path to the subvolume pointed by root, but the
-				 * subvolume can be mounted in a directory name
-				 * different from the subvolume name. In this
-				 * case we need to find the correct mount point
-				 * using same subvolume path and subvol id found
-				 * before.
-				 */
-
-				snprintf(subvol, PATH_MAX, "/%s", name);
-				snprintf(subvolid, PATH_MAX, "%llu", root);
-
-				ret = find_mount_fsroot(subvol, subvolid, &mounted);
-
-				if (ret) {
-					error("failed to parse mountinfo");
-					goto out;
-				}
-
-				if (!mounted) {
-					printf(
-			"inode %llu subvol %s could not be accessed: not mounted\n",
-						inum, name);
-					continue;
-				}
-
-				strncpy(mount_path, mounted, PATH_MAX);
-				free(mounted);
+				snprintf(mount_path, PATH_MAX, "%s%s", full_path, name);
 
 				path_fd = btrfs_open_dir(mount_path, &dirs, 1);
 				if (path_fd < 0) {
diff --git a/tests/misc-tests/042-inspect-internal-logical-resolve/test.sh b/tests/misc-tests/042-inspect-internal-logical-resolve/test.sh
index 2ba7331e..d20d5f74 100755
--- a/tests/misc-tests/042-inspect-internal-logical-resolve/test.sh
+++ b/tests/misc-tests/042-inspect-internal-logical-resolve/test.sh
@@ -51,34 +51,9 @@ run_check $SUDO_HELPER "$TOP/btrfs" subvolume snapshot "$TEST_MNT/@/vol1/subvol1
 
 run_check "$TOP/btrfs" filesystem sync "$TEST_MNT"
 
-run_check_umount_test_dev
-
-run_check $SUDO_HELPER mount -o subvol=/@/vol1 "$TEST_DEV" "$TEST_MNT"
-# Create a bind mount to vol1. logical-resolve should avoid bind mounts,
-# otherwise the test will fail
-run_check $SUDO_HELPER mkdir -p "$TEST_MNT/dir"
-run_check mkdir -p mnt2
-run_check $SUDO_HELPER mount --bind "$TEST_MNT/dir" mnt2
-# Create another bind mount to confuse logical-resolve even more.
-# logical-resolve can return the original mount or mnt3, both are valid
-run_check mkdir -p mnt3
-run_check $SUDO_HELPER mount --bind "$TEST_MNT" mnt3
-
 for offset in $("$TOP/btrfs" inspect-internal dump-tree -t "$vol1id" "$TEST_DEV" |
 		awk '/disk byte/ { print $5 }'); do
 	check_logical_offset_filename "$offset"
 done
 
-run_check_umount_test_dev mnt3
-run_check rmdir -- mnt3
-run_check_umount_test_dev mnt2
-run_check rmdir -- mnt2
-run_check_umount_test_dev
-
-run_check $SUDO_HELPER mount -o subvol="/@/vol1/subvol1" "$TEST_DEV" "$TEST_MNT"
-for offset in $("$TOP/btrfs" inspect-internal dump-tree -t "$subvol1id" "$TEST_DEV" |
-		awk '/disk byte/ { print $5 }'); do
-	check_logical_offset_filename "$offset"
-done
-
 run_check_umount_test_dev
-- 
2.39.0


^ permalink raw reply related	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2023-04-19 10:38 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2023-04-17  9:48 [PATCH] btrfs-progs: logical-resolve: fix the subvolume path resolution Qu Wenruo
2023-04-17 21:17 ` Torstein Eide
2023-04-17 22:51   ` Qu Wenruo
2023-04-18 23:55 ` David Sterba
2023-04-19  8:04   ` Qu Wenruo
2023-04-19  8:55   ` Andrei Borzenkov
2023-04-19  9:50     ` Torstein Eide
2023-04-19  9:50     ` Qu Wenruo
2023-04-19 10:37       ` Andrei Borzenkov

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox