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