Skip to content

Commit

Permalink
ANDROID: fuse: Add support for d_canonical_path
Browse files Browse the repository at this point in the history
Allows FUSE to report to inotify that it is acting
as a layered filesystem. The userspace component
returns a string representing the location of the
underlying file. If the string cannot be resolved
into a path, the top level path is returned instead.

bug: 23904372
Change-Id: Iabdca0bbedfbff59e9c820c58636a68ef9683d9f
Signed-off-by: Daniel Rosenberg <drosen@google.com>
(cherry picked from commit e780170a456178a676720f1b846332cd0cf0bd00)
Reviewed-on: https://chromium-review.googlesource.com/342353
Commit-Ready: Andrew Bresticker <abrestic@chromium.org>
Tested-by: Andrew Bresticker <abrestic@chromium.org>
Reviewed-by: Andrew Bresticker <abrestic@chromium.org>
(cherry picked from commit b71ff5160c9bbdbbb15339cd937d0a23867d4cf1)
Reviewed-on: https://chromium-review.googlesource.com/342620
Commit-Queue: Andrew Bresticker <abrestic@chromium.org>
  • Loading branch information
Daniel Rosenberg authored and Andrew Bresticker committed May 4, 2016
1 parent 2066483 commit ca42956
Show file tree
Hide file tree
Showing 4 changed files with 54 additions and 0 deletions.
5 changes: 5 additions & 0 deletions fs/fuse/dev.c
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#include <linux/poll.h>
#include <linux/uio.h>
#include <linux/miscdevice.h>
#include <linux/namei.h>
#include <linux/pagemap.h>
#include <linux/file.h>
#include <linux/slab.h>
Expand Down Expand Up @@ -1865,6 +1866,10 @@ static ssize_t fuse_dev_do_write(struct fuse_conn *fc,
spin_unlock(&fc->lock);

err = copy_out_args(cs, &req->out, nbytes);
if (req->in.h.opcode == FUSE_CANONICAL_PATH) {
req->out.h.error = kern_path((char *)req->out.args[0].value, 0,
req->canonical_path);
}
fuse_copy_finish(cs);

spin_lock(&fc->lock);
Expand Down
45 changes: 45 additions & 0 deletions fs/fuse/dir.c
Original file line number Diff line number Diff line change
Expand Up @@ -277,13 +277,58 @@ static int fuse_dentry_revalidate(struct dentry *entry, unsigned int flags)
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;
}

const struct dentry_operations fuse_dentry_operations = {
.d_revalidate = fuse_dentry_revalidate,
.d_canonical_path = fuse_dentry_canonical_path,
};

int fuse_valid_type(int m)
Expand Down
3 changes: 3 additions & 0 deletions fs/fuse/fuse_i.h
Original file line number Diff line number Diff line change
Expand Up @@ -351,6 +351,9 @@ struct fuse_req {
/** Inode used in the request or NULL */
struct inode *inode;

/** Path used for completing d_canonical_path */
struct path *canonical_path;

/** AIO control block */
struct fuse_io_priv *io;

Expand Down
1 change: 1 addition & 0 deletions include/uapi/linux/fuse.h
Original file line number Diff line number Diff line change
Expand Up @@ -358,6 +358,7 @@ enum fuse_opcode {
FUSE_FALLOCATE = 43,
FUSE_READDIRPLUS = 44,
FUSE_RENAME2 = 45,
FUSE_CANONICAL_PATH= 2016,

/* CUSE specific operations */
CUSE_INIT = 4096,
Expand Down

0 comments on commit ca42956

Please sign in to comment.