diff options
author | Christoph Hellwig <hch@infradead.org> | 2013-12-20 08:16:55 -0500 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2014-01-26 08:26:41 -0500 |
commit | 4ac7249ea5a0ceef9f8269f63f33cc873c3fac61 (patch) | |
tree | f12c9d14720d981270c45b207748e215f7a3dca3 | |
parent | feda821e76f3bbbba4bd54d30b4d4005a7848aa5 (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.h | 16 | ||||
-rw-r--r-- | fs/nfsd/nfs2acl.c | 72 | ||||
-rw-r--r-- | fs/nfsd/nfs3acl.c | 62 | ||||
-rw-r--r-- | fs/nfsd/nfs4acl.c | 120 | ||||
-rw-r--r-- | fs/nfsd/nfs4proc.c | 1 | ||||
-rw-r--r-- | fs/nfsd/vfs.c | 241 | ||||
-rw-r--r-- | fs/nfsd/vfs.h | 8 |
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> | 38 | struct nfs4_acl; |
39 | struct svc_fh; | ||
40 | struct 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); | |||
45 | int nfs4_acl_get_whotype(char *, u32); | 47 | int nfs4_acl_get_whotype(char *, u32); |
46 | int nfs4_acl_write_who(int who, char *p); | 48 | int nfs4_acl_write_who(int who, char *p); |
47 | 49 | ||
48 | #define NFS4_ACL_TYPE_DEFAULT 0x01 | 50 | int 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); | |
52 | struct nfs4_acl *nfs4_acl_posix_to_nfsv4(struct posix_acl *, | ||
53 | struct posix_acl *, unsigned int flags); | ||
54 | int 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) | |||
30 | static __be32 nfsacld_proc_getacl(struct svc_rqst * rqstp, | 30 | static __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 | |||
128 | out: | ||
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; |
134 | out_drop_write: | ||
135 | fh_drop_write(fh); | ||
136 | out_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) | |||
29 | static __be32 nfsd3_proc_getacl(struct svc_rqst * rqstp, | 29 | static __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 | |||
113 | out_drop_write: | ||
114 | fh_drop_write(fh); | ||
115 | out_errno: | ||
116 | nfserr = nfserrno(error); | ||
117 | out: | ||
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 *); | |||
130 | static void _posix_to_nfsv4_one(struct posix_acl *, struct nfs4_acl *, | 135 | static void _posix_to_nfsv4_one(struct posix_acl *, struct nfs4_acl *, |
131 | unsigned int); | 136 | unsigned int); |
132 | 137 | ||
133 | struct nfs4_acl * | 138 | int |
134 | nfs4_acl_posix_to_nfsv4(struct posix_acl *pacl, struct posix_acl *dpacl, | 139 | nfsd4_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 | ||
165 | struct posix_acl_summary { | 184 | struct posix_acl_summary { |
@@ -719,8 +738,9 @@ static void process_one_v4_ace(struct posix_acl_state *state, | |||
719 | } | 738 | } |
720 | } | 739 | } |
721 | 740 | ||
722 | int nfs4_acl_nfsv4_to_posix(struct nfs4_acl *acl, struct posix_acl **pacl, | 741 | static 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 | ||
804 | nfsd4_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 | |||
843 | out_release: | ||
844 | posix_acl_release(pacl); | ||
845 | posix_acl_release(dpacl); | ||
846 | out_nfserr: | ||
847 | if (host_error == -EOPNOTSUPP) | ||
848 | return nfserr_attrnotsupp; | ||
849 | else | ||
850 | return nfserrno(host_error); | ||
851 | } | ||
852 | |||
853 | |||
783 | static short | 854 | static short |
784 | ace2type(struct nfs4_ace *ace) | 855 | ace2type(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 | ||
801 | EXPORT_SYMBOL(nfs4_acl_posix_to_nfsv4); | ||
802 | EXPORT_SYMBOL(nfs4_acl_nfsv4_to_posix); | ||
803 | |||
804 | struct nfs4_acl * | 872 | struct nfs4_acl * |
805 | nfs4_acl_new(int n) | 873 | nfs4_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 | |||
866 | EXPORT_SYMBOL(nfs4_acl_new); | ||
867 | EXPORT_SYMBOL(nfs4_acl_get_whotype); | ||
868 | EXPORT_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) | ||
474 | static 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) |
495 | static int | ||
496 | set_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); | ||
516 | out: | ||
517 | kfree(buf); | ||
518 | return error; | ||
519 | } | ||
520 | |||
521 | __be32 | ||
522 | nfsd4_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 | |||
555 | out_release: | ||
556 | posix_acl_release(pacl); | ||
557 | posix_acl_release(dpacl); | ||
558 | out_nfserr: | ||
559 | if (host_error == -EOPNOTSUPP) | ||
560 | return nfserr_attrnotsupp; | ||
561 | else | ||
562 | return nfserrno(host_error); | ||
563 | } | ||
564 | |||
565 | static 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 | |||
583 | int | ||
584 | nfsd4_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) | ||
2289 | struct posix_acl * | ||
2290 | nfsd_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 | |||
2321 | int | ||
2322 | nfsd_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 | |||
2372 | getout: | ||
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); |
53 | int nfsd_mountpoint(struct dentry *, struct svc_export *); | 53 | int 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 *); | ||
57 | int 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) | ||
105 | struct posix_acl *nfsd_get_posix_acl(struct svc_fh *, int); | ||
106 | int nfsd_set_posix_acl(struct svc_fh *, int, struct posix_acl *); | ||
107 | #endif | ||
108 | |||
109 | static inline int fh_want_write(struct svc_fh *fh) | 101 | static 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); |