| |
@@ -0,0 +1,92 @@
|
| |
+ From 6aae7985eb8ecb6faecb20376500f1026960a801 Mon Sep 17 00:00:00 2001
|
| |
+ From: Sweet Tea Dorminy <sweettea-kernel@dorminy.me>
|
| |
+ Date: Mon, 4 Mar 2024 12:20:19 -0500
|
| |
+ Subject: [PATCH] fall back to user ioctl for ino path lookup
|
| |
+
|
| |
+ ---
|
| |
+ cmds/receive.c | 2 +-
|
| |
+ cmds/subvolume-list.c | 48 +++++++++++++++++++++++++++++++++++++++++++
|
| |
+ 2 files changed, 49 insertions(+), 1 deletion(-)
|
| |
+
|
| |
+ diff --git a/cmds/receive.c b/cmds/receive.c
|
| |
+ index e4430b07..051eca6a 100644
|
| |
+ --- a/cmds/receive.c
|
| |
+ +++ b/cmds/receive.c
|
| |
+ @@ -1285,7 +1285,7 @@ static int process_encoded_write(const char *path, const void *data, u64 offset,
|
| |
+ if (ret >= 0)
|
| |
+ return 0;
|
| |
+ /* Fall back for these errors, fail hard for anything else. */
|
| |
+ - if (errno != ENOSPC && errno != ENOTTY && errno != EINVAL) {
|
| |
+ + if (errno != ENOSPC && errno != ENOTTY && errno != EINVAL && errno != EPERM) {
|
| |
+ ret = -errno;
|
| |
+ error("encoded_write: writing to %s failed: %m", path);
|
| |
+ return ret;
|
| |
+ diff --git a/cmds/subvolume-list.c b/cmds/subvolume-list.c
|
| |
+ index 5a91f41d..c3bc7b70 100644
|
| |
+ --- a/cmds/subvolume-list.c
|
| |
+ +++ b/cmds/subvolume-list.c
|
| |
+ @@ -759,6 +759,49 @@ static int resolve_root(struct rb_root *rl, struct root_info *ri,
|
| |
+ return 0;
|
| |
+ }
|
| |
+
|
| |
+ +/*
|
| |
+ + * as user, for a single root_info, ask the kernel to give us a path name
|
| |
+ + * inside it's ref_root for the dir_id where it lives.
|
| |
+ + *
|
| |
+ + * This fills in root_info->path with the path to the directory and and
|
| |
+ + * appends this root's name.
|
| |
+ + */
|
| |
+ +static int lookup_ino_path_user(int fd, struct root_info *ri)
|
| |
+ +{
|
| |
+ + struct btrfs_ioctl_ino_lookup_user_args args;
|
| |
+ + int ret;
|
| |
+ +
|
| |
+ + if (ri->path)
|
| |
+ + return 0;
|
| |
+ +
|
| |
+ + if (!ri->ref_tree)
|
| |
+ + return -ENOENT;
|
| |
+ +
|
| |
+ + memset(&args, 0, sizeof(args));
|
| |
+ + args.treeid = ri->ref_tree;
|
| |
+ + args.dirid = ri->dir_id;
|
| |
+ +
|
| |
+ + ret = ioctl(fd, BTRFS_IOC_INO_LOOKUP_USER, &args);
|
| |
+ + if (ret < 0) {
|
| |
+ + if (errno == ENOENT) {
|
| |
+ + ri->ref_tree = 0;
|
| |
+ + return -ENOENT;
|
| |
+ + }
|
| |
+ + error("failed to lookup path for root %llu: %m", ri->ref_tree);
|
| |
+ + return ret;
|
| |
+ + }
|
| |
+ +
|
| |
+ + ri->path = malloc(strlen(args.name) + strlen(args.path) + 1);
|
| |
+ + if (!ri->path) {
|
| |
+ + error_msg(ERROR_MSG_MEMORY, NULL);
|
| |
+ + exit(1);
|
| |
+ + }
|
| |
+ +
|
| |
+ + strcpy(ri->path, args.path);
|
| |
+ + strcat(ri->path, args.name);
|
| |
+ + return 0;
|
| |
+ +}
|
| |
+ +
|
| |
+ /*
|
| |
+ * for a single root_info, ask the kernel to give us a path name
|
| |
+ * inside it's ref_root for the dir_id where it lives.
|
| |
+ @@ -783,6 +826,11 @@ static int lookup_ino_path(int fd, struct root_info *ri)
|
| |
+
|
| |
+ ret = ioctl(fd, BTRFS_IOC_INO_LOOKUP, &args);
|
| |
+ if (ret < 0) {
|
| |
+ + if (errno == EPERM) {
|
| |
+ + /* Let's try again with the user ioctl */
|
| |
+ + return lookup_ino_path_user(fd, ri);
|
| |
+ + }
|
| |
+ +
|
| |
+ if (errno == ENOENT) {
|
| |
+ ri->ref_tree = 0;
|
| |
+ return -ENOENT;
|
| |
+ --
|
| |
+ 2.44.0
|
| |
+
|
| |
To deal with a couple of user namespace permission issues, we would like to allow the btrfs command to fall back to user ino path lookup if root ino path lookup fails, and we would like to fall back to normal writes if encoded writes fail. This change adds a patch which does so.