diff options
Diffstat (limited to 'fs/nfsd/nfs2acl.c')
| -rw-r--r-- | fs/nfsd/nfs2acl.c | 106 | 
1 files changed, 66 insertions, 40 deletions
diff --git a/fs/nfsd/nfs2acl.c b/fs/nfsd/nfs2acl.c index 6aa5590c367..12b023a7ab7 100644 --- a/fs/nfsd/nfs2acl.c +++ b/fs/nfsd/nfs2acl.c @@ -30,8 +30,9 @@ nfsacld_proc_null(struct svc_rqst *rqstp, void *argp, void *resp)  static __be32 nfsacld_proc_getacl(struct svc_rqst * rqstp,  		struct nfsd3_getaclargs *argp, struct nfsd3_getaclres *resp)  { -	svc_fh *fh;  	struct posix_acl *acl; +	struct inode *inode; +	svc_fh *fh;  	__be32 nfserr = 0;  	dprintk("nfsd: GETACL(2acl)   %s\n", SVCFH_fmt(&argp->fh)); @@ -41,26 +42,24 @@ static __be32 nfsacld_proc_getacl(struct svc_rqst * rqstp,  	if (nfserr)  		RETURN_STATUS(nfserr); +	inode = fh->fh_dentry->d_inode; +  	if (argp->mask & ~(NFS_ACL|NFS_ACLCNT|NFS_DFACL|NFS_DFACLCNT))  		RETURN_STATUS(nfserr_inval);  	resp->mask = argp->mask; +	nfserr = fh_getattr(fh, &resp->stat); +	if (nfserr) +		goto fail; +  	if (resp->mask & (NFS_ACL|NFS_ACLCNT)) { -		acl = nfsd_get_posix_acl(fh, ACL_TYPE_ACCESS); +		acl = get_acl(inode, ACL_TYPE_ACCESS);  		if (IS_ERR(acl)) { -			int err = PTR_ERR(acl); - -			if (err == -ENODATA || err == -EOPNOTSUPP) -				acl = NULL; -			else { -				nfserr = nfserrno(err); -				goto fail; -			} +			nfserr = nfserrno(PTR_ERR(acl)); +			goto fail;  		}  		if (acl == NULL) {  			/* Solaris returns the inode's minimum ACL. */ - -			struct inode *inode = fh->fh_dentry->d_inode;  			acl = posix_acl_from_mode(inode->i_mode, GFP_KERNEL);  		}  		resp->acl_access = acl; @@ -68,17 +67,10 @@ static __be32 nfsacld_proc_getacl(struct svc_rqst * rqstp,  	if (resp->mask & (NFS_DFACL|NFS_DFACLCNT)) {  		/* Check how Solaris handles requests for the Default ACL  		   of a non-directory! */ - -		acl = nfsd_get_posix_acl(fh, ACL_TYPE_DEFAULT); +		acl = get_acl(inode, ACL_TYPE_DEFAULT);  		if (IS_ERR(acl)) { -			int err = PTR_ERR(acl); - -			if (err == -ENODATA || err == -EOPNOTSUPP) -				acl = NULL; -			else { -				nfserr = nfserrno(err); -				goto fail; -			} +			nfserr = nfserrno(PTR_ERR(acl)); +			goto fail;  		}  		resp->acl_default = acl;  	} @@ -99,28 +91,51 @@ static __be32 nfsacld_proc_setacl(struct svc_rqst * rqstp,  		struct nfsd3_setaclargs *argp,  		struct nfsd_attrstat *resp)  { +	struct inode *inode;  	svc_fh *fh;  	__be32 nfserr = 0; +	int error;  	dprintk("nfsd: SETACL(2acl)   %s\n", SVCFH_fmt(&argp->fh));  	fh = fh_copy(&resp->fh, &argp->fh);  	nfserr = fh_verify(rqstp, &resp->fh, 0, NFSD_MAY_SATTR); +	if (nfserr) +		goto out; -	if (!nfserr) { -		nfserr = nfserrno( nfsd_set_posix_acl( -			fh, ACL_TYPE_ACCESS, argp->acl_access) ); -	} -	if (!nfserr) { -		nfserr = nfserrno( nfsd_set_posix_acl( -			fh, ACL_TYPE_DEFAULT, argp->acl_default) ); +	inode = fh->fh_dentry->d_inode; +	if (!IS_POSIXACL(inode) || !inode->i_op->set_acl) { +		error = -EOPNOTSUPP; +		goto out_errno;  	} +	error = fh_want_write(fh); +	if (error) +		goto out_errno; + +	error = inode->i_op->set_acl(inode, argp->acl_access, ACL_TYPE_ACCESS); +	if (error) +		goto out_drop_write; +	error = inode->i_op->set_acl(inode, argp->acl_default, +				     ACL_TYPE_DEFAULT); +	if (error) +		goto out_drop_write; + +	fh_drop_write(fh); + +	nfserr = fh_getattr(fh, &resp->stat); + +out:  	/* argp->acl_{access,default} may have been allocated in  	   nfssvc_decode_setaclargs. */  	posix_acl_release(argp->acl_access);  	posix_acl_release(argp->acl_default);  	return nfserr; +out_drop_write: +	fh_drop_write(fh); +out_errno: +	nfserr = nfserrno(error); +	goto out;  }  /* @@ -129,10 +144,15 @@ static __be32 nfsacld_proc_setacl(struct svc_rqst * rqstp,  static __be32 nfsacld_proc_getattr(struct svc_rqst * rqstp,  		struct nfsd_fhandle *argp, struct nfsd_attrstat *resp)  { +	__be32 nfserr;  	dprintk("nfsd: GETATTR  %s\n", SVCFH_fmt(&argp->fh));  	fh_copy(&resp->fh, &argp->fh); -	return fh_verify(rqstp, &resp->fh, 0, NFSD_MAY_NOP); +	nfserr = fh_verify(rqstp, &resp->fh, 0, NFSD_MAY_NOP); +	if (nfserr) +		return nfserr; +	nfserr = fh_getattr(&resp->fh, &resp->stat); +	return nfserr;  }  /* @@ -150,6 +170,9 @@ static __be32 nfsacld_proc_access(struct svc_rqst *rqstp, struct nfsd3_accessarg  	fh_copy(&resp->fh, &argp->fh);  	resp->access = argp->access;  	nfserr = nfsd_access(rqstp, &resp->fh, &resp->access, NULL); +	if (nfserr) +		return nfserr; +	nfserr = fh_getattr(&resp->fh, &resp->stat);  	return nfserr;  } @@ -159,7 +182,8 @@ static __be32 nfsacld_proc_access(struct svc_rqst *rqstp, struct nfsd3_accessarg  static int nfsaclsvc_decode_getaclargs(struct svc_rqst *rqstp, __be32 *p,  		struct nfsd3_getaclargs *argp)  { -	if (!(p = nfs2svc_decode_fh(p, &argp->fh))) +	p = nfs2svc_decode_fh(p, &argp->fh); +	if (!p)  		return 0;  	argp->mask = ntohl(*p); p++; @@ -174,7 +198,8 @@ static int nfsaclsvc_decode_setaclargs(struct svc_rqst *rqstp, __be32 *p,  	unsigned int base;  	int n; -	if (!(p = nfs2svc_decode_fh(p, &argp->fh))) +	p = nfs2svc_decode_fh(p, &argp->fh); +	if (!p)  		return 0;  	argp->mask = ntohl(*p++);  	if (argp->mask & ~(NFS_ACL|NFS_ACLCNT|NFS_DFACL|NFS_DFACLCNT) || @@ -195,7 +220,8 @@ static int nfsaclsvc_decode_setaclargs(struct svc_rqst *rqstp, __be32 *p,  static int nfsaclsvc_decode_fhandleargs(struct svc_rqst *rqstp, __be32 *p,  		struct nfsd_fhandle *argp)  { -	if (!(p = nfs2svc_decode_fh(p, &argp->fh))) +	p = nfs2svc_decode_fh(p, &argp->fh); +	if (!p)  		return 0;  	return xdr_argsize_check(rqstp, p);  } @@ -203,7 +229,8 @@ static int nfsaclsvc_decode_fhandleargs(struct svc_rqst *rqstp, __be32 *p,  static int nfsaclsvc_decode_accessargs(struct svc_rqst *rqstp, __be32 *p,  		struct nfsd3_accessargs *argp)  { -	if (!(p = nfs2svc_decode_fh(p, &argp->fh))) +	p = nfs2svc_decode_fh(p, &argp->fh); +	if (!p)  		return 0;  	argp->access = ntohl(*p++); @@ -218,8 +245,7 @@ static int nfsaclsvc_decode_accessargs(struct svc_rqst *rqstp, __be32 *p,   * There must be an encoding function for void results so svc_process   * will work properly.   */ -int -nfsaclsvc_encode_voidres(struct svc_rqst *rqstp, __be32 *p, void *dummy) +static int nfsaclsvc_encode_voidres(struct svc_rqst *rqstp, __be32 *p, void *dummy)  {  	return xdr_ressize_check(rqstp, p);  } @@ -244,7 +270,7 @@ static int nfsaclsvc_encode_getaclres(struct svc_rqst *rqstp, __be32 *p,  		return 0;  	inode = dentry->d_inode; -	p = nfs2svc_encode_fattr(rqstp, p, &resp->fh); +	p = nfs2svc_encode_fattr(rqstp, p, &resp->fh, &resp->stat);  	*p++ = htonl(resp->mask);  	if (!xdr_ressize_check(rqstp, p))  		return 0; @@ -254,7 +280,7 @@ static int nfsaclsvc_encode_getaclres(struct svc_rqst *rqstp, __be32 *p,  		(resp->mask & NFS_ACL)   ? resp->acl_access  : NULL,  		(resp->mask & NFS_DFACL) ? resp->acl_default : NULL);  	while (w > 0) { -		if (!rqstp->rq_respages[rqstp->rq_resused++]) +		if (!*(rqstp->rq_next_page++))  			return 0;  		w -= PAGE_SIZE;  	} @@ -275,7 +301,7 @@ static int nfsaclsvc_encode_getaclres(struct svc_rqst *rqstp, __be32 *p,  static int nfsaclsvc_encode_attrstatres(struct svc_rqst *rqstp, __be32 *p,  		struct nfsd_attrstat *resp)  { -	p = nfs2svc_encode_fattr(rqstp, p, &resp->fh); +	p = nfs2svc_encode_fattr(rqstp, p, &resp->fh, &resp->stat);  	return xdr_ressize_check(rqstp, p);  } @@ -283,7 +309,7 @@ static int nfsaclsvc_encode_attrstatres(struct svc_rqst *rqstp, __be32 *p,  static int nfsaclsvc_encode_accessres(struct svc_rqst *rqstp, __be32 *p,  		struct nfsd3_accessres *resp)  { -	p = nfs2svc_encode_fattr(rqstp, p, &resp->fh); +	p = nfs2svc_encode_fattr(rqstp, p, &resp->fh, &resp->stat);  	*p++ = htonl(resp->access);  	return xdr_ressize_check(rqstp, p);  }  | 
