aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChristoph Hellwig <hch@infradead.org>2013-12-20 08:16:55 -0500
committerAl Viro <viro@zeniv.linux.org.uk>2014-01-26 08:26:41 -0500
commit4ac7249ea5a0ceef9f8269f63f33cc873c3fac61 (patch)
treef12c9d14720d981270c45b207748e215f7a3dca3
parentfeda821e76f3bbbba4bd54d30b4d4005a7848aa5 (diff)
nfsd: use get_acl and ->set_acl
Remove the boilerplate code to marshall and unmarhall ACL objects into xattrs and operate on the posix_acl objects directly. Also move all the ACL handling code into nfs?acl.c where it belongs. Signed-off-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
-rw-r--r--fs/nfsd/acl.h16
-rw-r--r--fs/nfsd/nfs2acl.c72
-rw-r--r--fs/nfsd/nfs3acl.c62
-rw-r--r--fs/nfsd/nfs4acl.c120
-rw-r--r--fs/nfsd/nfs4proc.c1
-rw-r--r--fs/nfsd/vfs.c241
-rw-r--r--fs/nfsd/vfs.h8
7 files changed, 173 insertions, 347 deletions
diff --git a/fs/nfsd/acl.h b/fs/nfsd/acl.h
index 8b186a4955cc..8b68218e2c1c 100644
--- a/fs/nfsd/acl.h
+++ b/fs/nfsd/acl.h
@@ -35,7 +35,9 @@
35#ifndef LINUX_NFS4_ACL_H 35#ifndef LINUX_NFS4_ACL_H
36#define LINUX_NFS4_ACL_H 36#define LINUX_NFS4_ACL_H
37 37
38#include <linux/posix_acl.h> 38struct nfs4_acl;
39struct svc_fh;
40struct svc_rqst;
39 41
40/* Maximum ACL we'll accept from client; chosen (somewhat arbitrarily) to 42/* Maximum ACL we'll accept from client; chosen (somewhat arbitrarily) to
41 * fit in a page: */ 43 * fit in a page: */
@@ -45,13 +47,9 @@ struct nfs4_acl *nfs4_acl_new(int);
45int nfs4_acl_get_whotype(char *, u32); 47int nfs4_acl_get_whotype(char *, u32);
46int nfs4_acl_write_who(int who, char *p); 48int nfs4_acl_write_who(int who, char *p);
47 49
48#define NFS4_ACL_TYPE_DEFAULT 0x01 50int nfsd4_get_nfs4_acl(struct svc_rqst *rqstp, struct dentry *dentry,
49#define NFS4_ACL_DIR 0x02 51 struct nfs4_acl **acl);
50#define NFS4_ACL_OWNER 0x04 52__be32 nfsd4_set_nfs4_acl(struct svc_rqst *rqstp, struct svc_fh *fhp,
51 53 struct nfs4_acl *acl);
52struct nfs4_acl *nfs4_acl_posix_to_nfsv4(struct posix_acl *,
53 struct posix_acl *, unsigned int flags);
54int nfs4_acl_nfsv4_to_posix(struct nfs4_acl *, struct posix_acl **,
55 struct posix_acl **, unsigned int flags);
56 54
57#endif /* LINUX_NFS4_ACL_H */ 55#endif /* LINUX_NFS4_ACL_H */
diff --git a/fs/nfsd/nfs2acl.c b/fs/nfsd/nfs2acl.c
index 95d76dc6c5da..11c1fba29312 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)
30static __be32 nfsacld_proc_getacl(struct svc_rqst * rqstp, 30static __be32 nfsacld_proc_getacl(struct svc_rqst * rqstp,
31 struct nfsd3_getaclargs *argp, struct nfsd3_getaclres *resp) 31 struct nfsd3_getaclargs *argp, struct nfsd3_getaclres *resp)
32{ 32{
33 svc_fh *fh;
34 struct posix_acl *acl; 33 struct posix_acl *acl;
34 struct inode *inode;
35 svc_fh *fh;
35 __be32 nfserr = 0; 36 __be32 nfserr = 0;
36 37
37 dprintk("nfsd: GETACL(2acl) %s\n", SVCFH_fmt(&argp->fh)); 38 dprintk("nfsd: GETACL(2acl) %s\n", SVCFH_fmt(&argp->fh));
@@ -41,6 +42,8 @@ static __be32 nfsacld_proc_getacl(struct svc_rqst * rqstp,
41 if (nfserr) 42 if (nfserr)
42 RETURN_STATUS(nfserr); 43 RETURN_STATUS(nfserr);
43 44
45 inode = fh->fh_dentry->d_inode;
46
44 if (argp->mask & ~(NFS_ACL|NFS_ACLCNT|NFS_DFACL|NFS_DFACLCNT)) 47 if (argp->mask & ~(NFS_ACL|NFS_ACLCNT|NFS_DFACL|NFS_DFACLCNT))
45 RETURN_STATUS(nfserr_inval); 48 RETURN_STATUS(nfserr_inval);
46 resp->mask = argp->mask; 49 resp->mask = argp->mask;
@@ -50,21 +53,13 @@ static __be32 nfsacld_proc_getacl(struct svc_rqst * rqstp,
50 goto fail; 53 goto fail;
51 54
52 if (resp->mask & (NFS_ACL|NFS_ACLCNT)) { 55 if (resp->mask & (NFS_ACL|NFS_ACLCNT)) {
53 acl = nfsd_get_posix_acl(fh, ACL_TYPE_ACCESS); 56 acl = get_acl(inode, ACL_TYPE_ACCESS);
54 if (IS_ERR(acl)) { 57 if (IS_ERR(acl)) {
55 int err = PTR_ERR(acl); 58 nfserr = nfserrno(PTR_ERR(acl));
56 59 goto fail;
57 if (err == -ENODATA || err == -EOPNOTSUPP)
58 acl = NULL;
59 else {
60 nfserr = nfserrno(err);
61 goto fail;
62 }
63 } 60 }
64 if (acl == NULL) { 61 if (acl == NULL) {
65 /* Solaris returns the inode's minimum ACL. */ 62 /* Solaris returns the inode's minimum ACL. */
66
67 struct inode *inode = fh->fh_dentry->d_inode;
68 acl = posix_acl_from_mode(inode->i_mode, GFP_KERNEL); 63 acl = posix_acl_from_mode(inode->i_mode, GFP_KERNEL);
69 } 64 }
70 resp->acl_access = acl; 65 resp->acl_access = acl;
@@ -72,17 +67,10 @@ static __be32 nfsacld_proc_getacl(struct svc_rqst * rqstp,
72 if (resp->mask & (NFS_DFACL|NFS_DFACLCNT)) { 67 if (resp->mask & (NFS_DFACL|NFS_DFACLCNT)) {
73 /* Check how Solaris handles requests for the Default ACL 68 /* Check how Solaris handles requests for the Default ACL
74 of a non-directory! */ 69 of a non-directory! */
75 70 acl = get_acl(inode, ACL_TYPE_DEFAULT);
76 acl = nfsd_get_posix_acl(fh, ACL_TYPE_DEFAULT);
77 if (IS_ERR(acl)) { 71 if (IS_ERR(acl)) {
78 int err = PTR_ERR(acl); 72 nfserr = nfserrno(PTR_ERR(acl));
79 73 goto fail;
80 if (err == -ENODATA || err == -EOPNOTSUPP)
81 acl = NULL;
82 else {
83 nfserr = nfserrno(err);
84 goto fail;
85 }
86 } 74 }
87 resp->acl_default = acl; 75 resp->acl_default = acl;
88 } 76 }
@@ -103,31 +91,51 @@ static __be32 nfsacld_proc_setacl(struct svc_rqst * rqstp,
103 struct nfsd3_setaclargs *argp, 91 struct nfsd3_setaclargs *argp,
104 struct nfsd_attrstat *resp) 92 struct nfsd_attrstat *resp)
105{ 93{
94 struct inode *inode;
106 svc_fh *fh; 95 svc_fh *fh;
107 __be32 nfserr = 0; 96 __be32 nfserr = 0;
97 int error;
108 98
109 dprintk("nfsd: SETACL(2acl) %s\n", SVCFH_fmt(&argp->fh)); 99 dprintk("nfsd: SETACL(2acl) %s\n", SVCFH_fmt(&argp->fh));
110 100
111 fh = fh_copy(&resp->fh, &argp->fh); 101 fh = fh_copy(&resp->fh, &argp->fh);
112 nfserr = fh_verify(rqstp, &resp->fh, 0, NFSD_MAY_SATTR); 102 nfserr = fh_verify(rqstp, &resp->fh, 0, NFSD_MAY_SATTR);
103 if (nfserr)
104 goto out;
113 105
114 if (!nfserr) { 106 inode = fh->fh_dentry->d_inode;
115 nfserr = nfserrno( nfsd_set_posix_acl( 107 if (!IS_POSIXACL(inode) || !inode->i_op->set_acl) {
116 fh, ACL_TYPE_ACCESS, argp->acl_access) ); 108 error = -EOPNOTSUPP;
117 } 109 goto out_errno;
118 if (!nfserr) {
119 nfserr = nfserrno( nfsd_set_posix_acl(
120 fh, ACL_TYPE_DEFAULT, argp->acl_default) );
121 }
122 if (!nfserr) {
123 nfserr = fh_getattr(fh, &resp->stat);
124 } 110 }
125 111
112 error = fh_want_write(fh);
113 if (error)
114 goto out_errno;
115
116 error = inode->i_op->set_acl(inode, argp->acl_access, ACL_TYPE_ACCESS);
117 if (error)
118 goto out_drop_write;
119 error = inode->i_op->set_acl(inode, argp->acl_default,
120 ACL_TYPE_DEFAULT);
121 if (error)
122 goto out_drop_write;
123
124 fh_drop_write(fh);
125
126 nfserr = fh_getattr(fh, &resp->stat);
127
128out:
126 /* argp->acl_{access,default} may have been allocated in 129 /* argp->acl_{access,default} may have been allocated in
127 nfssvc_decode_setaclargs. */ 130 nfssvc_decode_setaclargs. */
128 posix_acl_release(argp->acl_access); 131 posix_acl_release(argp->acl_access);
129 posix_acl_release(argp->acl_default); 132 posix_acl_release(argp->acl_default);
130 return nfserr; 133 return nfserr;
134out_drop_write:
135 fh_drop_write(fh);
136out_errno:
137 nfserr = nfserrno(error);
138 goto out;
131} 139}
132 140
133/* 141/*
diff --git a/fs/nfsd/nfs3acl.c b/fs/nfsd/nfs3acl.c
index 9cbc1a841f87..adc5f1b1dc26 100644
--- a/fs/nfsd/nfs3acl.c
+++ b/fs/nfsd/nfs3acl.c
@@ -29,8 +29,9 @@ nfsd3_proc_null(struct svc_rqst *rqstp, void *argp, void *resp)
29static __be32 nfsd3_proc_getacl(struct svc_rqst * rqstp, 29static __be32 nfsd3_proc_getacl(struct svc_rqst * rqstp,
30 struct nfsd3_getaclargs *argp, struct nfsd3_getaclres *resp) 30 struct nfsd3_getaclargs *argp, struct nfsd3_getaclres *resp)
31{ 31{
32 svc_fh *fh;
33 struct posix_acl *acl; 32 struct posix_acl *acl;
33 struct inode *inode;
34 svc_fh *fh;
34 __be32 nfserr = 0; 35 __be32 nfserr = 0;
35 36
36 fh = fh_copy(&resp->fh, &argp->fh); 37 fh = fh_copy(&resp->fh, &argp->fh);
@@ -38,26 +39,20 @@ static __be32 nfsd3_proc_getacl(struct svc_rqst * rqstp,
38 if (nfserr) 39 if (nfserr)
39 RETURN_STATUS(nfserr); 40 RETURN_STATUS(nfserr);
40 41
42 inode = fh->fh_dentry->d_inode;
43
41 if (argp->mask & ~(NFS_ACL|NFS_ACLCNT|NFS_DFACL|NFS_DFACLCNT)) 44 if (argp->mask & ~(NFS_ACL|NFS_ACLCNT|NFS_DFACL|NFS_DFACLCNT))
42 RETURN_STATUS(nfserr_inval); 45 RETURN_STATUS(nfserr_inval);
43 resp->mask = argp->mask; 46 resp->mask = argp->mask;
44 47
45 if (resp->mask & (NFS_ACL|NFS_ACLCNT)) { 48 if (resp->mask & (NFS_ACL|NFS_ACLCNT)) {
46 acl = nfsd_get_posix_acl(fh, ACL_TYPE_ACCESS); 49 acl = get_acl(inode, ACL_TYPE_ACCESS);
47 if (IS_ERR(acl)) { 50 if (IS_ERR(acl)) {
48 int err = PTR_ERR(acl); 51 nfserr = nfserrno(PTR_ERR(acl));
49 52 goto fail;
50 if (err == -ENODATA || err == -EOPNOTSUPP)
51 acl = NULL;
52 else {
53 nfserr = nfserrno(err);
54 goto fail;
55 }
56 } 53 }
57 if (acl == NULL) { 54 if (acl == NULL) {
58 /* Solaris returns the inode's minimum ACL. */ 55 /* Solaris returns the inode's minimum ACL. */
59
60 struct inode *inode = fh->fh_dentry->d_inode;
61 acl = posix_acl_from_mode(inode->i_mode, GFP_KERNEL); 56 acl = posix_acl_from_mode(inode->i_mode, GFP_KERNEL);
62 } 57 }
63 resp->acl_access = acl; 58 resp->acl_access = acl;
@@ -65,17 +60,10 @@ static __be32 nfsd3_proc_getacl(struct svc_rqst * rqstp,
65 if (resp->mask & (NFS_DFACL|NFS_DFACLCNT)) { 60 if (resp->mask & (NFS_DFACL|NFS_DFACLCNT)) {
66 /* Check how Solaris handles requests for the Default ACL 61 /* Check how Solaris handles requests for the Default ACL
67 of a non-directory! */ 62 of a non-directory! */
68 63 acl = get_acl(inode, ACL_TYPE_DEFAULT);
69 acl = nfsd_get_posix_acl(fh, ACL_TYPE_DEFAULT);
70 if (IS_ERR(acl)) { 64 if (IS_ERR(acl)) {
71 int err = PTR_ERR(acl); 65 nfserr = nfserrno(PTR_ERR(acl));
72 66 goto fail;
73 if (err == -ENODATA || err == -EOPNOTSUPP)
74 acl = NULL;
75 else {
76 nfserr = nfserrno(err);
77 goto fail;
78 }
79 } 67 }
80 resp->acl_default = acl; 68 resp->acl_default = acl;
81 } 69 }
@@ -96,21 +84,37 @@ static __be32 nfsd3_proc_setacl(struct svc_rqst * rqstp,
96 struct nfsd3_setaclargs *argp, 84 struct nfsd3_setaclargs *argp,
97 struct nfsd3_attrstat *resp) 85 struct nfsd3_attrstat *resp)
98{ 86{
87 struct inode *inode;
99 svc_fh *fh; 88 svc_fh *fh;
100 __be32 nfserr = 0; 89 __be32 nfserr = 0;
90 int error;
101 91
102 fh = fh_copy(&resp->fh, &argp->fh); 92 fh = fh_copy(&resp->fh, &argp->fh);
103 nfserr = fh_verify(rqstp, &resp->fh, 0, NFSD_MAY_SATTR); 93 nfserr = fh_verify(rqstp, &resp->fh, 0, NFSD_MAY_SATTR);
94 if (nfserr)
95 goto out;
104 96
105 if (!nfserr) { 97 inode = fh->fh_dentry->d_inode;
106 nfserr = nfserrno( nfsd_set_posix_acl( 98 if (!IS_POSIXACL(inode) || !inode->i_op->set_acl) {
107 fh, ACL_TYPE_ACCESS, argp->acl_access) ); 99 error = -EOPNOTSUPP;
108 } 100 goto out_errno;
109 if (!nfserr) {
110 nfserr = nfserrno( nfsd_set_posix_acl(
111 fh, ACL_TYPE_DEFAULT, argp->acl_default) );
112 } 101 }
113 102
103 error = fh_want_write(fh);
104 if (error)
105 goto out_errno;
106
107 error = inode->i_op->set_acl(inode, argp->acl_access, ACL_TYPE_ACCESS);
108 if (error)
109 goto out_drop_write;
110 error = inode->i_op->set_acl(inode, argp->acl_default,
111 ACL_TYPE_DEFAULT);
112
113out_drop_write:
114 fh_drop_write(fh);
115out_errno:
116 nfserr = nfserrno(error);
117out:
114 /* argp->acl_{access,default} may have been allocated in 118 /* argp->acl_{access,default} may have been allocated in
115 nfs3svc_decode_setaclargs. */ 119 nfs3svc_decode_setaclargs. */
116 posix_acl_release(argp->acl_access); 120 posix_acl_release(argp->acl_access);
diff --git a/fs/nfsd/nfs4acl.c b/fs/nfsd/nfs4acl.c
index 8a50b3c18093..649ad7cf2204 100644
--- a/fs/nfsd/nfs4acl.c
+++ b/fs/nfsd/nfs4acl.c
@@ -37,8 +37,13 @@
37#include <linux/slab.h> 37#include <linux/slab.h>
38#include <linux/nfs_fs.h> 38#include <linux/nfs_fs.h>
39#include <linux/export.h> 39#include <linux/export.h>
40#include "nfsfh.h"
40#include "acl.h" 41#include "acl.h"
42#include "vfs.h"
41 43
44#define NFS4_ACL_TYPE_DEFAULT 0x01
45#define NFS4_ACL_DIR 0x02
46#define NFS4_ACL_OWNER 0x04
42 47
43/* mode bit translations: */ 48/* mode bit translations: */
44#define NFS4_READ_MODE (NFS4_ACE_READ_DATA) 49#define NFS4_READ_MODE (NFS4_ACE_READ_DATA)
@@ -130,36 +135,50 @@ static short ace2type(struct nfs4_ace *);
130static void _posix_to_nfsv4_one(struct posix_acl *, struct nfs4_acl *, 135static void _posix_to_nfsv4_one(struct posix_acl *, struct nfs4_acl *,
131 unsigned int); 136 unsigned int);
132 137
133struct nfs4_acl * 138int
134nfs4_acl_posix_to_nfsv4(struct posix_acl *pacl, struct posix_acl *dpacl, 139nfsd4_get_nfs4_acl(struct svc_rqst *rqstp, struct dentry *dentry,
135 unsigned int flags) 140 struct nfs4_acl **acl)
136{ 141{
137 struct nfs4_acl *acl; 142 struct inode *inode = dentry->d_inode;
143 int error = 0;
144 struct posix_acl *pacl = NULL, *dpacl = NULL;
145 unsigned int flags = 0;
138 int size = 0; 146 int size = 0;
139 147
140 if (pacl) { 148 pacl = get_acl(inode, ACL_TYPE_ACCESS);
141 if (posix_acl_valid(pacl) < 0) 149 if (!pacl) {
142 return ERR_PTR(-EINVAL); 150 pacl = posix_acl_from_mode(inode->i_mode, GFP_KERNEL);
143 size += 2*pacl->a_count; 151 if (IS_ERR(pacl))
152 return PTR_ERR(pacl);
153 /* allocate for worst case: one (deny, allow) pair each: */
154 size += 2 * pacl->a_count;
144 } 155 }
145 if (dpacl) { 156
146 if (posix_acl_valid(dpacl) < 0) 157 if (S_ISDIR(inode->i_mode)) {
147 return ERR_PTR(-EINVAL); 158 flags = NFS4_ACL_DIR;
148 size += 2*dpacl->a_count; 159 dpacl = get_acl(inode, ACL_TYPE_DEFAULT);
160 if (dpacl)
161 size += 2 * dpacl->a_count;
162 } else {
163 dpacl = NULL;
149 } 164 }
150 165
151 /* Allocate for worst case: one (deny, allow) pair each: */ 166 *acl = nfs4_acl_new(size);
152 acl = nfs4_acl_new(size); 167 if (*acl == NULL) {
153 if (acl == NULL) 168 error = -ENOMEM;
154 return ERR_PTR(-ENOMEM); 169 goto out;
170 }
155 171
156 if (pacl) 172 if (pacl)
157 _posix_to_nfsv4_one(pacl, acl, flags & ~NFS4_ACL_TYPE_DEFAULT); 173 _posix_to_nfsv4_one(pacl, *acl, flags & ~NFS4_ACL_TYPE_DEFAULT);
158 174
159 if (dpacl) 175 if (dpacl)
160 _posix_to_nfsv4_one(dpacl, acl, flags | NFS4_ACL_TYPE_DEFAULT); 176 _posix_to_nfsv4_one(dpacl, *acl, flags | NFS4_ACL_TYPE_DEFAULT);
161 177
162 return acl; 178 out:
179 posix_acl_release(pacl);
180 posix_acl_release(dpacl);
181 return error;
163} 182}
164 183
165struct posix_acl_summary { 184struct posix_acl_summary {
@@ -719,8 +738,9 @@ static void process_one_v4_ace(struct posix_acl_state *state,
719 } 738 }
720} 739}
721 740
722int nfs4_acl_nfsv4_to_posix(struct nfs4_acl *acl, struct posix_acl **pacl, 741static int nfs4_acl_nfsv4_to_posix(struct nfs4_acl *acl,
723 struct posix_acl **dpacl, unsigned int flags) 742 struct posix_acl **pacl, struct posix_acl **dpacl,
743 unsigned int flags)
724{ 744{
725 struct posix_acl_state effective_acl_state, default_acl_state; 745 struct posix_acl_state effective_acl_state, default_acl_state;
726 struct nfs4_ace *ace; 746 struct nfs4_ace *ace;
@@ -780,6 +800,57 @@ out_estate:
780 return ret; 800 return ret;
781} 801}
782 802
803__be32
804nfsd4_set_nfs4_acl(struct svc_rqst *rqstp, struct svc_fh *fhp,
805 struct nfs4_acl *acl)
806{
807 __be32 error;
808 int host_error;
809 struct dentry *dentry;
810 struct inode *inode;
811 struct posix_acl *pacl = NULL, *dpacl = NULL;
812 unsigned int flags = 0;
813
814 /* Get inode */
815 error = fh_verify(rqstp, fhp, 0, NFSD_MAY_SATTR);
816 if (error)
817 return error;
818
819 dentry = fhp->fh_dentry;
820 inode = dentry->d_inode;
821
822 if (!inode->i_op->set_acl || !IS_POSIXACL(inode))
823 return nfserr_attrnotsupp;
824
825 if (S_ISDIR(inode->i_mode))
826 flags = NFS4_ACL_DIR;
827
828 host_error = nfs4_acl_nfsv4_to_posix(acl, &pacl, &dpacl, flags);
829 if (host_error == -EINVAL)
830 return nfserr_attrnotsupp;
831 if (host_error < 0)
832 goto out_nfserr;
833
834 host_error = inode->i_op->set_acl(inode, pacl, ACL_TYPE_ACCESS);
835 if (host_error < 0)
836 goto out_release;
837
838 if (S_ISDIR(inode->i_mode)) {
839 host_error = inode->i_op->set_acl(inode, dpacl,
840 ACL_TYPE_DEFAULT);
841 }
842
843out_release:
844 posix_acl_release(pacl);
845 posix_acl_release(dpacl);
846out_nfserr:
847 if (host_error == -EOPNOTSUPP)
848 return nfserr_attrnotsupp;
849 else
850 return nfserrno(host_error);
851}
852
853
783static short 854static short
784ace2type(struct nfs4_ace *ace) 855ace2type(struct nfs4_ace *ace)
785{ 856{
@@ -798,9 +869,6 @@ ace2type(struct nfs4_ace *ace)
798 return -1; 869 return -1;
799} 870}
800 871
801EXPORT_SYMBOL(nfs4_acl_posix_to_nfsv4);
802EXPORT_SYMBOL(nfs4_acl_nfsv4_to_posix);
803
804struct nfs4_acl * 872struct nfs4_acl *
805nfs4_acl_new(int n) 873nfs4_acl_new(int n)
806{ 874{
@@ -862,7 +930,3 @@ nfs4_acl_write_who(int who, char *p)
862 BUG(); 930 BUG();
863 return -1; 931 return -1;
864} 932}
865
866EXPORT_SYMBOL(nfs4_acl_new);
867EXPORT_SYMBOL(nfs4_acl_get_whotype);
868EXPORT_SYMBOL(nfs4_acl_write_who);
diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c
index 419572f33b72..825b8a99b99b 100644
--- a/fs/nfsd/nfs4proc.c
+++ b/fs/nfsd/nfs4proc.c
@@ -41,6 +41,7 @@
41#include "vfs.h" 41#include "vfs.h"
42#include "current_stateid.h" 42#include "current_stateid.h"
43#include "netns.h" 43#include "netns.h"
44#include "acl.h"
44 45
45#ifdef CONFIG_NFSD_V4_SECURITY_LABEL 46#ifdef CONFIG_NFSD_V4_SECURITY_LABEL
46#include <linux/security.h> 47#include <linux/security.h>
diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c
index 7eea63cada1d..1426eb66c8c6 100644
--- a/fs/nfsd/vfs.c
+++ b/fs/nfsd/vfs.c
@@ -468,158 +468,7 @@ out:
468 return err; 468 return err;
469} 469}
470 470
471#if defined(CONFIG_NFSD_V2_ACL) || \
472 defined(CONFIG_NFSD_V3_ACL) || \
473 defined(CONFIG_NFSD_V4)
474static ssize_t nfsd_getxattr(struct dentry *dentry, char *key, void **buf)
475{
476 ssize_t buflen;
477 ssize_t ret;
478
479 buflen = vfs_getxattr(dentry, key, NULL, 0);
480 if (buflen <= 0)
481 return buflen;
482
483 *buf = kmalloc(buflen, GFP_KERNEL);
484 if (!*buf)
485 return -ENOMEM;
486
487 ret = vfs_getxattr(dentry, key, *buf, buflen);
488 if (ret < 0)
489 kfree(*buf);
490 return ret;
491}
492#endif
493
494#if defined(CONFIG_NFSD_V4) 471#if defined(CONFIG_NFSD_V4)
495static int
496set_nfsv4_acl_one(struct dentry *dentry, struct posix_acl *pacl, char *key)
497{
498 int len;
499 size_t buflen;
500 char *buf = NULL;
501 int error = 0;
502
503 buflen = posix_acl_xattr_size(pacl->a_count);
504 buf = kmalloc(buflen, GFP_KERNEL);
505 error = -ENOMEM;
506 if (buf == NULL)
507 goto out;
508
509 len = posix_acl_to_xattr(&init_user_ns, pacl, buf, buflen);
510 if (len < 0) {
511 error = len;
512 goto out;
513 }
514
515 error = vfs_setxattr(dentry, key, buf, len, 0);
516out:
517 kfree(buf);
518 return error;
519}
520
521__be32
522nfsd4_set_nfs4_acl(struct svc_rqst *rqstp, struct svc_fh *fhp,
523 struct nfs4_acl *acl)
524{
525 __be32 error;
526 int host_error;
527 struct dentry *dentry;
528 struct inode *inode;
529 struct posix_acl *pacl = NULL, *dpacl = NULL;
530 unsigned int flags = 0;
531
532 /* Get inode */
533 error = fh_verify(rqstp, fhp, 0, NFSD_MAY_SATTR);
534 if (error)
535 return error;
536
537 dentry = fhp->fh_dentry;
538 inode = dentry->d_inode;
539 if (S_ISDIR(inode->i_mode))
540 flags = NFS4_ACL_DIR;
541
542 host_error = nfs4_acl_nfsv4_to_posix(acl, &pacl, &dpacl, flags);
543 if (host_error == -EINVAL) {
544 return nfserr_attrnotsupp;
545 } else if (host_error < 0)
546 goto out_nfserr;
547
548 host_error = set_nfsv4_acl_one(dentry, pacl, POSIX_ACL_XATTR_ACCESS);
549 if (host_error < 0)
550 goto out_release;
551
552 if (S_ISDIR(inode->i_mode))
553 host_error = set_nfsv4_acl_one(dentry, dpacl, POSIX_ACL_XATTR_DEFAULT);
554
555out_release:
556 posix_acl_release(pacl);
557 posix_acl_release(dpacl);
558out_nfserr:
559 if (host_error == -EOPNOTSUPP)
560 return nfserr_attrnotsupp;
561 else
562 return nfserrno(host_error);
563}
564
565static struct posix_acl *
566_get_posix_acl(struct dentry *dentry, char *key)
567{
568 void *buf = NULL;
569 struct posix_acl *pacl = NULL;
570 int buflen;
571
572 buflen = nfsd_getxattr(dentry, key, &buf);
573 if (!buflen)
574 buflen = -ENODATA;
575 if (buflen <= 0)
576 return ERR_PTR(buflen);
577
578 pacl = posix_acl_from_xattr(&init_user_ns, buf, buflen);
579 kfree(buf);
580 return pacl;
581}
582
583int
584nfsd4_get_nfs4_acl(struct svc_rqst *rqstp, struct dentry *dentry, struct nfs4_acl **acl)
585{
586 struct inode *inode = dentry->d_inode;
587 int error = 0;
588 struct posix_acl *pacl = NULL, *dpacl = NULL;
589 unsigned int flags = 0;
590
591 pacl = _get_posix_acl(dentry, POSIX_ACL_XATTR_ACCESS);
592 if (IS_ERR(pacl) && PTR_ERR(pacl) == -ENODATA)
593 pacl = posix_acl_from_mode(inode->i_mode, GFP_KERNEL);
594 if (IS_ERR(pacl)) {
595 error = PTR_ERR(pacl);
596 pacl = NULL;
597 goto out;
598 }
599
600 if (S_ISDIR(inode->i_mode)) {
601 dpacl = _get_posix_acl(dentry, POSIX_ACL_XATTR_DEFAULT);
602 if (IS_ERR(dpacl) && PTR_ERR(dpacl) == -ENODATA)
603 dpacl = NULL;
604 else if (IS_ERR(dpacl)) {
605 error = PTR_ERR(dpacl);
606 dpacl = NULL;
607 goto out;
608 }
609 flags = NFS4_ACL_DIR;
610 }
611
612 *acl = nfs4_acl_posix_to_nfsv4(pacl, dpacl, flags);
613 if (IS_ERR(*acl)) {
614 error = PTR_ERR(*acl);
615 *acl = NULL;
616 }
617 out:
618 posix_acl_release(pacl);
619 posix_acl_release(dpacl);
620 return error;
621}
622
623/* 472/*
624 * NFS junction information is stored in an extended attribute. 473 * NFS junction information is stored in an extended attribute.
625 */ 474 */
@@ -2284,93 +2133,3 @@ out_nomem:
2284 nfsd_racache_shutdown(); 2133 nfsd_racache_shutdown();
2285 return -ENOMEM; 2134 return -ENOMEM;
2286} 2135}
2287
2288#if defined(CONFIG_NFSD_V2_ACL) || defined(CONFIG_NFSD_V3_ACL)
2289struct posix_acl *
2290nfsd_get_posix_acl(struct svc_fh *fhp, int type)
2291{
2292 struct inode *inode = fhp->fh_dentry->d_inode;
2293 char *name;
2294 void *value = NULL;
2295 ssize_t size;
2296 struct posix_acl *acl;
2297
2298 if (!IS_POSIXACL(inode))
2299 return ERR_PTR(-EOPNOTSUPP);
2300
2301 switch (type) {
2302 case ACL_TYPE_ACCESS:
2303 name = POSIX_ACL_XATTR_ACCESS;
2304 break;
2305 case ACL_TYPE_DEFAULT:
2306 name = POSIX_ACL_XATTR_DEFAULT;
2307 break;
2308 default:
2309 return ERR_PTR(-EOPNOTSUPP);
2310 }
2311
2312 size = nfsd_getxattr(fhp->fh_dentry, name, &value);
2313 if (size < 0)
2314 return ERR_PTR(size);
2315
2316 acl = posix_acl_from_xattr(&init_user_ns, value, size);
2317 kfree(value);
2318 return acl;
2319}
2320
2321int
2322nfsd_set_posix_acl(struct svc_fh *fhp, int type, struct posix_acl *acl)
2323{
2324 struct inode *inode = fhp->fh_dentry->d_inode;
2325 char *name;
2326 void *value = NULL;
2327 size_t size;
2328 int error;
2329
2330 if (!IS_POSIXACL(inode) ||
2331 !inode->i_op->setxattr || !inode->i_op->removexattr)
2332 return -EOPNOTSUPP;
2333 switch(type) {
2334 case ACL_TYPE_ACCESS:
2335 name = POSIX_ACL_XATTR_ACCESS;
2336 break;
2337 case ACL_TYPE_DEFAULT:
2338 name = POSIX_ACL_XATTR_DEFAULT;
2339 break;
2340 default:
2341 return -EOPNOTSUPP;
2342 }
2343
2344 if (acl && acl->a_count) {
2345 size = posix_acl_xattr_size(acl->a_count);
2346 value = kmalloc(size, GFP_KERNEL);
2347 if (!value)
2348 return -ENOMEM;
2349 error = posix_acl_to_xattr(&init_user_ns, acl, value, size);
2350 if (error < 0)
2351 goto getout;
2352 size = error;
2353 } else
2354 size = 0;
2355
2356 error = fh_want_write(fhp);
2357 if (error)
2358 goto getout;
2359 if (size)
2360 error = vfs_setxattr(fhp->fh_dentry, name, value, size, 0);
2361 else {
2362 if (!S_ISDIR(inode->i_mode) && type == ACL_TYPE_DEFAULT)
2363 error = 0;
2364 else {
2365 error = vfs_removexattr(fhp->fh_dentry, name);
2366 if (error == -ENODATA)
2367 error = 0;
2368 }
2369 }
2370 fh_drop_write(fhp);
2371
2372getout:
2373 kfree(value);
2374 return error;
2375}
2376#endif /* defined(CONFIG_NFSD_V2_ACL) || defined(CONFIG_NFSD_V3_ACL) */
diff --git a/fs/nfsd/vfs.h b/fs/nfsd/vfs.h
index a4be2e389670..1bc1d440a1a5 100644
--- a/fs/nfsd/vfs.h
+++ b/fs/nfsd/vfs.h
@@ -52,9 +52,6 @@ __be32 nfsd_setattr(struct svc_rqst *, struct svc_fh *,
52 struct iattr *, int, time_t); 52 struct iattr *, int, time_t);
53int nfsd_mountpoint(struct dentry *, struct svc_export *); 53int nfsd_mountpoint(struct dentry *, struct svc_export *);
54#ifdef CONFIG_NFSD_V4 54#ifdef CONFIG_NFSD_V4
55__be32 nfsd4_set_nfs4_acl(struct svc_rqst *, struct svc_fh *,
56 struct nfs4_acl *);
57int nfsd4_get_nfs4_acl(struct svc_rqst *, struct dentry *, struct nfs4_acl **);
58__be32 nfsd4_set_nfs4_label(struct svc_rqst *, struct svc_fh *, 55__be32 nfsd4_set_nfs4_label(struct svc_rqst *, struct svc_fh *,
59 struct xdr_netobj *); 56 struct xdr_netobj *);
60#endif /* CONFIG_NFSD_V4 */ 57#endif /* CONFIG_NFSD_V4 */
@@ -101,11 +98,6 @@ __be32 nfsd_statfs(struct svc_rqst *, struct svc_fh *,
101__be32 nfsd_permission(struct svc_rqst *, struct svc_export *, 98__be32 nfsd_permission(struct svc_rqst *, struct svc_export *,
102 struct dentry *, int); 99 struct dentry *, int);
103 100
104#if defined(CONFIG_NFSD_V2_ACL) || defined(CONFIG_NFSD_V3_ACL)
105struct posix_acl *nfsd_get_posix_acl(struct svc_fh *, int);
106int nfsd_set_posix_acl(struct svc_fh *, int, struct posix_acl *);
107#endif
108
109static inline int fh_want_write(struct svc_fh *fh) 101static inline int fh_want_write(struct svc_fh *fh)
110{ 102{
111 int ret = mnt_want_write(fh->fh_export->ex_path.mnt); 103 int ret = mnt_want_write(fh->fh_export->ex_path.mnt);