Commit 31d40d74 authored by Miklos Szeredi's avatar Miklos Szeredi Committed by Linus Torvalds

[PATCH] FUSE: add access call

Add a new access call, which will only be called if ->permission is invoked
from sys_access().  In all other cases permission checking is delayed until
the actual filesystem operation.
Signed-off-by: default avatarMiklos Szeredi <miklos@szeredi.hu>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent 5b62073d
...@@ -461,6 +461,38 @@ static int fuse_revalidate(struct dentry *entry) ...@@ -461,6 +461,38 @@ static int fuse_revalidate(struct dentry *entry)
return fuse_do_getattr(inode); return fuse_do_getattr(inode);
} }
static int fuse_access(struct inode *inode, int mask)
{
struct fuse_conn *fc = get_fuse_conn(inode);
struct fuse_req *req;
struct fuse_access_in inarg;
int err;
if (fc->no_access)
return 0;
req = fuse_get_request(fc);
if (!req)
return -EINTR;
memset(&inarg, 0, sizeof(inarg));
inarg.mask = mask;
req->in.h.opcode = FUSE_ACCESS;
req->in.h.nodeid = get_node_id(inode);
req->inode = inode;
req->in.numargs = 1;
req->in.args[0].size = sizeof(inarg);
req->in.args[0].value = &inarg;
request_send(fc, req);
err = req->out.h.error;
fuse_put_request(fc, req);
if (err == -ENOSYS) {
fc->no_access = 1;
err = 0;
}
return err;
}
static int fuse_permission(struct inode *inode, int mask, struct nameidata *nd) static int fuse_permission(struct inode *inode, int mask, struct nameidata *nd)
{ {
struct fuse_conn *fc = get_fuse_conn(inode); struct fuse_conn *fc = get_fuse_conn(inode);
...@@ -493,6 +525,9 @@ static int fuse_permission(struct inode *inode, int mask, struct nameidata *nd) ...@@ -493,6 +525,9 @@ static int fuse_permission(struct inode *inode, int mask, struct nameidata *nd)
int mode = inode->i_mode; int mode = inode->i_mode;
if ((mask & MAY_EXEC) && !S_ISDIR(mode) && !(mode & S_IXUGO)) if ((mask & MAY_EXEC) && !S_ISDIR(mode) && !(mode & S_IXUGO))
return -EACCES; return -EACCES;
if (nd && (nd->flags & LOOKUP_ACCESS))
return fuse_access(inode, mask);
return 0; return 0;
} }
} }
......
...@@ -266,6 +266,9 @@ struct fuse_conn { ...@@ -266,6 +266,9 @@ struct fuse_conn {
/** Is removexattr not implemented by fs? */ /** Is removexattr not implemented by fs? */
unsigned no_removexattr : 1; unsigned no_removexattr : 1;
/** Is access not implemented by fs? */
unsigned no_access : 1;
/** Backing dev info */ /** Backing dev info */
struct backing_dev_info bdi; struct backing_dev_info bdi;
}; };
......
...@@ -99,7 +99,8 @@ enum fuse_opcode { ...@@ -99,7 +99,8 @@ enum fuse_opcode {
FUSE_OPENDIR = 27, FUSE_OPENDIR = 27,
FUSE_READDIR = 28, FUSE_READDIR = 28,
FUSE_RELEASEDIR = 29, FUSE_RELEASEDIR = 29,
FUSE_FSYNCDIR = 30 FUSE_FSYNCDIR = 30,
FUSE_ACCESS = 34
}; };
/* Conservative buffer size for the client */ /* Conservative buffer size for the client */
...@@ -222,6 +223,11 @@ struct fuse_getxattr_out { ...@@ -222,6 +223,11 @@ struct fuse_getxattr_out {
__u32 padding; __u32 padding;
}; };
struct fuse_access_in {
__u32 mask;
__u32 padding;
};
struct fuse_init_in_out { struct fuse_init_in_out {
__u32 major; __u32 major;
__u32 minor; __u32 minor;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment