diff options
author | Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com> | 2010-09-27 22:57:40 +0400 |
---|---|---|
committer | Eric Van Hensbergen <ericvh@gmail.com> | 2010-10-28 18:08:46 +0400 |
commit | 22d8dcdf8f8a3882d98757e78169014bb0bc6b23 (patch) | |
tree | ee7c2f6842b329cfc0652400e83cb166dbead331 /fs/9p/acl.c | |
parent | 7a4566b0b8fa67c7cd7be9f2969a085920356abb (diff) | |
download | linux-22d8dcdf8f8a3882d98757e78169014bb0bc6b23.tar.xz |
fs/9p: Implement setting posix acl
This patch also update mode bits, as a normal file system.
I am not sure wether we should do that, considering that
a setxattr on the server will again update the ACL/mode value
Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
Signed-off-by: Venkateswararao Jujjuri <jvrao@linux.vnet.ibm.com>
Signed-off-by: Eric Van Hensbergen <ericvh@gmail.com>
Diffstat (limited to 'fs/9p/acl.c')
-rw-r--r-- | fs/9p/acl.c | 74 |
1 files changed, 73 insertions, 1 deletions
diff --git a/fs/9p/acl.c b/fs/9p/acl.c index 4293b4599ff6..cad38bc1710e 100644 --- a/fs/9p/acl.c +++ b/fs/9p/acl.c @@ -17,9 +17,11 @@ #include <net/9p/9p.h> #include <net/9p/client.h> #include <linux/slab.h> +#include <linux/sched.h> #include <linux/posix_acl_xattr.h> #include "xattr.h" #include "acl.h" +#include "v9fs_vfs.h" static struct posix_acl *__v9fs_get_acl(struct p9_fid *fid, char *name) { @@ -119,7 +121,77 @@ static int v9fs_xattr_set_acl(struct dentry *dentry, const char *name, const void *value, size_t size, int flags, int type) { - return 0; + int retval; + struct posix_acl *acl; + struct inode *inode = dentry->d_inode; + + if (strcmp(name, "") != 0) + return -EINVAL; + if (S_ISLNK(inode->i_mode)) + return -EOPNOTSUPP; + if (!is_owner_or_cap(inode)) + return -EPERM; + if (value) { + /* update the cached acl value */ + acl = posix_acl_from_xattr(value, size); + if (IS_ERR(acl)) + return PTR_ERR(acl); + else if (acl) { + retval = posix_acl_valid(acl); + if (retval) + goto err_out; + } + } else + acl = NULL; + + switch (type) { + case ACL_TYPE_ACCESS: + name = POSIX_ACL_XATTR_ACCESS; + if (acl) { + mode_t mode = inode->i_mode; + retval = posix_acl_equiv_mode(acl, &mode); + if (retval < 0) + goto err_out; + else { + struct iattr iattr; + if (retval == 0) { + /* + * ACL can be represented + * by the mode bits. So don't + * update ACL. + */ + acl = NULL; + value = NULL; + size = 0; + } + /* Updte the mode bits */ + iattr.ia_mode = ((mode & S_IALLUGO) | + (inode->i_mode & ~S_IALLUGO)); + iattr.ia_valid = ATTR_MODE; + /* FIXME should we update ctime ? + * What is the following setxattr update the + * mode ? + */ + v9fs_vfs_setattr_dotl(dentry, &iattr); + } + } + break; + case ACL_TYPE_DEFAULT: + name = POSIX_ACL_XATTR_DEFAULT; + if (!S_ISDIR(inode->i_mode)) { + retval = -EINVAL; + goto err_out; + } + break; + default: + BUG(); + } + retval = v9fs_xattr_set(dentry, name, value, size, flags); + if (!retval) + set_cached_acl(inode, type, acl); +err_out: + posix_acl_release(acl); + return retval; } const struct xattr_handler v9fs_xattr_acl_access_handler = { |