[PATCH] NFSD: Add server support for NFSv3 ACLs.
This adds functions for encoding and decoding POSIX ACLs for the NFSACL protocol extension, and the GETACL and SETACL RPCs. The implementation is compatible with NFSACL in Solaris. Signed-off-by: Andreas Gruenbacher <agruen@suse.de> Acked-by: Olaf Kirch <okir@suse.de> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
This commit is contained in:

committed by
Trond Myklebust

parent
9ba02638e4
commit
a257cdd0e2
107
fs/nfsd/vfs.c
107
fs/nfsd/vfs.c
@@ -46,8 +46,9 @@
|
||||
#include <linux/nfsd/nfsfh.h>
|
||||
#include <linux/quotaops.h>
|
||||
#include <linux/dnotify.h>
|
||||
#ifdef CONFIG_NFSD_V4
|
||||
#include <linux/xattr_acl.h>
|
||||
#include <linux/posix_acl.h>
|
||||
#ifdef CONFIG_NFSD_V4
|
||||
#include <linux/posix_acl_xattr.h>
|
||||
#include <linux/xattr_acl.h>
|
||||
#include <linux/xattr.h>
|
||||
@@ -1857,3 +1858,107 @@ nfsd_racache_init(int cache_size)
|
||||
nfsdstats.ra_size = cache_size;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_NFSD_V2_ACL) || defined(CONFIG_NFSD_V3_ACL)
|
||||
struct posix_acl *
|
||||
nfsd_get_posix_acl(struct svc_fh *fhp, int type)
|
||||
{
|
||||
struct inode *inode = fhp->fh_dentry->d_inode;
|
||||
char *name;
|
||||
void *value = NULL;
|
||||
ssize_t size;
|
||||
struct posix_acl *acl;
|
||||
|
||||
if (!IS_POSIXACL(inode) || !inode->i_op || !inode->i_op->getxattr)
|
||||
return ERR_PTR(-EOPNOTSUPP);
|
||||
switch(type) {
|
||||
case ACL_TYPE_ACCESS:
|
||||
name = XATTR_NAME_ACL_ACCESS;
|
||||
break;
|
||||
case ACL_TYPE_DEFAULT:
|
||||
name = XATTR_NAME_ACL_DEFAULT;
|
||||
break;
|
||||
default:
|
||||
return ERR_PTR(-EOPNOTSUPP);
|
||||
}
|
||||
|
||||
size = inode->i_op->getxattr(fhp->fh_dentry, name, NULL, 0);
|
||||
|
||||
if (size < 0) {
|
||||
acl = ERR_PTR(size);
|
||||
goto getout;
|
||||
} else if (size > 0) {
|
||||
value = kmalloc(size, GFP_KERNEL);
|
||||
if (!value) {
|
||||
acl = ERR_PTR(-ENOMEM);
|
||||
goto getout;
|
||||
}
|
||||
size = inode->i_op->getxattr(fhp->fh_dentry, name, value, size);
|
||||
if (size < 0) {
|
||||
acl = ERR_PTR(size);
|
||||
goto getout;
|
||||
}
|
||||
}
|
||||
acl = posix_acl_from_xattr(value, size);
|
||||
|
||||
getout:
|
||||
kfree(value);
|
||||
return acl;
|
||||
}
|
||||
|
||||
int
|
||||
nfsd_set_posix_acl(struct svc_fh *fhp, int type, struct posix_acl *acl)
|
||||
{
|
||||
struct inode *inode = fhp->fh_dentry->d_inode;
|
||||
char *name;
|
||||
void *value = NULL;
|
||||
size_t size;
|
||||
int error;
|
||||
|
||||
if (!IS_POSIXACL(inode) || !inode->i_op ||
|
||||
!inode->i_op->setxattr || !inode->i_op->removexattr)
|
||||
return -EOPNOTSUPP;
|
||||
switch(type) {
|
||||
case ACL_TYPE_ACCESS:
|
||||
name = XATTR_NAME_ACL_ACCESS;
|
||||
break;
|
||||
case ACL_TYPE_DEFAULT:
|
||||
name = XATTR_NAME_ACL_DEFAULT;
|
||||
break;
|
||||
default:
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
if (acl && acl->a_count) {
|
||||
size = xattr_acl_size(acl->a_count);
|
||||
value = kmalloc(size, GFP_KERNEL);
|
||||
if (!value)
|
||||
return -ENOMEM;
|
||||
size = posix_acl_to_xattr(acl, value, size);
|
||||
if (size < 0) {
|
||||
error = size;
|
||||
goto getout;
|
||||
}
|
||||
} else
|
||||
size = 0;
|
||||
|
||||
if (!fhp->fh_locked)
|
||||
fh_lock(fhp); /* unlocking is done automatically */
|
||||
if (size)
|
||||
error = inode->i_op->setxattr(fhp->fh_dentry, name,
|
||||
value, size, 0);
|
||||
else {
|
||||
if (!S_ISDIR(inode->i_mode) && type == ACL_TYPE_DEFAULT)
|
||||
error = 0;
|
||||
else {
|
||||
error = inode->i_op->removexattr(fhp->fh_dentry, name);
|
||||
if (error == -ENODATA)
|
||||
error = 0;
|
||||
}
|
||||
}
|
||||
|
||||
getout:
|
||||
kfree(value);
|
||||
return error;
|
||||
}
|
||||
#endif /* defined(CONFIG_NFSD_V2_ACL) || defined(CONFIG_NFSD_V3_ACL) */
|
||||
|
Reference in New Issue
Block a user