diff mbox series

btrfs-progs: inspect: Fix logical-resolve by starting the lookup from root_id

Message ID 20201112011400.6866-1-marcos@mpdesouza.com (mailing list archive)
State New, archived
Headers show
Series btrfs-progs: inspect: Fix logical-resolve by starting the lookup from root_id | expand

Commit Message

Marcos Paulo de Souza Nov. 12, 2020, 1:14 a.m. UTC
From: Marcos Paulo de Souza <mpdesouza@suse.com>

logical-resolve is currently broken on systems that have a child
subvolume being mounted without access to the parent subvolume.
This is the default for SLE/openSUSE installations, since we have the
subvolume '@' not being mounted, only it's child subovlumes (var, root, ...).

If we try to look for a file on /var, this happens:

btrfs inspect-internal logical-resolve -v 339570688 /
ioctl ret=0, total_size=4096, bytes_left=4056, bytes_missing=0, cnt=3, missed=0
ERROR: cannot access '//@/var': No such file or directory

Since subvolume '@' isn't mounted, the normal file lookup fails. The fix
in this case is the start the file lookup in the subvolume that contains
the file, and not from the top subvolume of the system.

To not break current subvol_uuid_search_init function calling
btrfs_list_path_for_root, a new argument was added to switch between the
old behavior and the new one. With the fix in place, logical-resolve
works as expected:

btrfs inspect-internal logical-resolve -v 339570688 /
ioctl ret=0, total_size=65536, bytes_left=65496, bytes_missing=0, cnt=3, missed=0
ioctl ret=0, bytes_left=4055, bytes_missing=0 cnt=1, missed=0
//var/log/zypp/history

Signed-off-by: Marcos Paulo de Souza <mpdesouza@suse.com>
---
 btrfs-list.c        | 11 ++++++++---
 btrfs-list.h        |  2 +-
 cmds/inspect.c      |  2 +-
 common/send-utils.c |  2 +-
 4 files changed, 11 insertions(+), 6 deletions(-)
diff mbox series

Patch

diff --git a/btrfs-list.c b/btrfs-list.c
index 4b95bcdf..abe36da8 100644
--- a/btrfs-list.c
+++ b/btrfs-list.c
@@ -1801,7 +1801,7 @@  int btrfs_list_find_updated_files(int fd, u64 root_id, u64 oldest_gen)
 	return ret;
 }
 
-char *btrfs_list_path_for_root(int fd, u64 root)
+char *btrfs_list_path_for_root(int fd, u64 root, bool full_path)
 {
 	struct root_lookup root_lookup;
 	struct rb_node *n;
@@ -1832,8 +1832,13 @@  char *btrfs_list_path_for_root(int fd, u64 root)
 			break;
 		}
 		if (entry->root_id == root) {
-			ret_path = entry->full_path;
-			entry->full_path = NULL;
+			if (full_path) {
+				ret_path = entry->full_path;
+				entry->full_path = NULL;
+			} else {
+				ret_path = entry->name;
+				entry->name = NULL;
+			}
 		}
 
 		n = rb_prev(n);
diff --git a/btrfs-list.h b/btrfs-list.h
index ea06e663..3043d2ac 100644
--- a/btrfs-list.h
+++ b/btrfs-list.h
@@ -172,7 +172,7 @@  int btrfs_list_subvols_print(int fd, struct btrfs_list_filter_set *filter_set,
 		       const char *raw_prefix);
 int btrfs_list_find_updated_files(int fd, u64 root_id, u64 oldest_gen);
 int btrfs_list_get_default_subvolume(int fd, u64 *default_id);
-char *btrfs_list_path_for_root(int fd, u64 root);
+char *btrfs_list_path_for_root(int fd, u64 root, bool full_path);
 int btrfs_list_get_path_rootid(int fd, u64 *treeid);
 int btrfs_get_subvol(int fd, struct root_info *the_ri);
 int btrfs_get_toplevel_subvol(int fd, struct root_info *the_ri);
diff --git a/cmds/inspect.c b/cmds/inspect.c
index 2530b904..828e38e2 100644
--- a/cmds/inspect.c
+++ b/cmds/inspect.c
@@ -236,7 +236,7 @@  static int cmd_inspect_logical_resolve(const struct cmd_struct *cmd,
 		DIR *dirs = NULL;
 
 		if (getpath) {
-			name = btrfs_list_path_for_root(fd, root);
+			name = btrfs_list_path_for_root(fd, root, false);
 			if (IS_ERR(name)) {
 				ret = PTR_ERR(name);
 				goto out;
diff --git a/common/send-utils.c b/common/send-utils.c
index 58eca58f..ddb15261 100644
--- a/common/send-utils.c
+++ b/common/send-utils.c
@@ -657,7 +657,7 @@  int subvol_uuid_search_init(int mnt_fd, struct subvol_uuid_search *s)
 					goto skip;
 
 				path = btrfs_list_path_for_root(mnt_fd,
-					btrfs_search_header_objectid(sh));
+					btrfs_search_header_objectid(sh), true);
 				if (!path)
 					path = strdup("");
 				if (IS_ERR(path)) {