mirror of https://github.com/OpenIPC/firmware.git
69 lines
2.0 KiB
Diff
69 lines
2.0 KiB
Diff
diff -drupN a/fs/fuse/dir.c b/fs/fuse/dir.c
|
|
--- a/fs/fuse/dir.c 2018-08-06 17:23:04.000000000 +0300
|
|
+++ b/fs/fuse/dir.c 2022-06-12 05:28:14.000000000 +0300
|
|
@@ -262,6 +262,50 @@ invalid:
|
|
goto out;
|
|
}
|
|
|
|
+/*
|
|
+ * Get the canonical path. Since we must translate to a path, this must be done
|
|
+ * in the context of the userspace daemon, however, the userspace daemon cannot
|
|
+ * look up paths on its own. Instead, we handle the lookup as a special case
|
|
+ * inside of the write request.
|
|
+ */
|
|
+static void fuse_dentry_canonical_path(const struct path *path, struct path *canonical_path) {
|
|
+ struct inode *inode = path->dentry->d_inode;
|
|
+ struct fuse_conn *fc = get_fuse_conn(inode);
|
|
+ struct fuse_req *req;
|
|
+ int err;
|
|
+ char *path_name;
|
|
+
|
|
+ req = fuse_get_req(fc, 1);
|
|
+ err = PTR_ERR(req);
|
|
+ if (IS_ERR(req))
|
|
+ goto default_path;
|
|
+
|
|
+ path_name = (char*)__get_free_page(GFP_KERNEL);
|
|
+ if (!path_name) {
|
|
+ fuse_put_request(fc, req);
|
|
+ goto default_path;
|
|
+ }
|
|
+
|
|
+ req->in.h.opcode = FUSE_CANONICAL_PATH;
|
|
+ req->in.h.nodeid = get_node_id(inode);
|
|
+ req->in.numargs = 0;
|
|
+ req->out.numargs = 1;
|
|
+ req->out.args[0].size = PATH_MAX;
|
|
+ req->out.args[0].value = path_name;
|
|
+ req->canonical_path = canonical_path;
|
|
+ req->out.argvar = 1;
|
|
+ fuse_request_send(fc, req);
|
|
+ err = req->out.h.error;
|
|
+ fuse_put_request(fc, req);
|
|
+ free_page((unsigned long)path_name);
|
|
+ if (!err)
|
|
+ return;
|
|
+default_path:
|
|
+ canonical_path->dentry = path->dentry;
|
|
+ canonical_path->mnt = path->mnt;
|
|
+ path_get(canonical_path);
|
|
+}
|
|
+
|
|
static int invalid_nodeid(u64 nodeid)
|
|
{
|
|
return !nodeid || nodeid == FUSE_ROOT_ID;
|
|
@@ -284,11 +328,13 @@ const struct dentry_operations fuse_dent
|
|
.d_revalidate = fuse_dentry_revalidate,
|
|
.d_init = fuse_dentry_init,
|
|
.d_release = fuse_dentry_release,
|
|
+ .d_canonical_path = fuse_dentry_canonical_path,
|
|
};
|
|
|
|
const struct dentry_operations fuse_root_dentry_operations = {
|
|
.d_init = fuse_dentry_init,
|
|
.d_release = fuse_dentry_release,
|
|
+ .d_canonical_path = fuse_dentry_canonical_path,
|
|
};
|
|
|
|
int fuse_valid_type(int m)
|