aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChristoph Hellwig <hch@infradead.org>2013-12-20 08:16:53 -0500
committerAl Viro <viro@zeniv.linux.org.uk>2014-01-26 08:26:20 -0500
commit013cdf1088d7235da9477a2375654921d9b9ba9f (patch)
tree56a89d0a58282c517f6c5a8e68e3d341184e40d1
parente01580bf9e4d0e3bbaead44bd46cdbfe61957732 (diff)
nfs: use generic posix ACL infrastructure for v3 Posix ACLs
This causes a small behaviour change in that we don't bother to set ACLs on file creation if the mode bit can express the access permissions fully, and thus behaving identical to local filesystems. Signed-off-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
-rw-r--r--fs/nfs/inode.c4
-rw-r--r--fs/nfs/nfs3acl.c291
-rw-r--r--fs/nfs/nfs3proc.c76
-rw-r--r--fs/nfs/nfs3super.c3
-rw-r--r--include/linux/nfs_fs.h24
-rw-r--r--include/linux/posix_acl.h4
6 files changed, 121 insertions, 281 deletions
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c
index 00ad1c2b217d..ecd11ba7f960 100644
--- a/fs/nfs/inode.c
+++ b/fs/nfs/inode.c
@@ -1641,10 +1641,6 @@ struct inode *nfs_alloc_inode(struct super_block *sb)
1641 return NULL; 1641 return NULL;
1642 nfsi->flags = 0UL; 1642 nfsi->flags = 0UL;
1643 nfsi->cache_validity = 0UL; 1643 nfsi->cache_validity = 0UL;
1644#ifdef CONFIG_NFS_V3_ACL
1645 nfsi->acl_access = ERR_PTR(-EAGAIN);
1646 nfsi->acl_default = ERR_PTR(-EAGAIN);
1647#endif
1648#if IS_ENABLED(CONFIG_NFS_V4) 1644#if IS_ENABLED(CONFIG_NFS_V4)
1649 nfsi->nfs4_acl = NULL; 1645 nfsi->nfs4_acl = NULL;
1650#endif /* CONFIG_NFS_V4 */ 1646#endif /* CONFIG_NFS_V4 */
diff --git a/fs/nfs/nfs3acl.c b/fs/nfs/nfs3acl.c
index e85967587d74..9a5ca03fa539 100644
--- a/fs/nfs/nfs3acl.c
+++ b/fs/nfs/nfs3acl.c
@@ -10,179 +10,7 @@
10 10
11#define NFSDBG_FACILITY NFSDBG_PROC 11#define NFSDBG_FACILITY NFSDBG_PROC
12 12
13ssize_t nfs3_listxattr(struct dentry *dentry, char *buffer, size_t size) 13struct posix_acl *nfs3_get_acl(struct inode *inode, int type)
14{
15 struct inode *inode = dentry->d_inode;
16 struct posix_acl *acl;
17 int pos=0, len=0;
18
19# define output(s) do { \
20 if (pos + sizeof(s) <= size) { \
21 memcpy(buffer + pos, s, sizeof(s)); \
22 pos += sizeof(s); \
23 } \
24 len += sizeof(s); \
25 } while(0)
26
27 acl = nfs3_proc_getacl(inode, ACL_TYPE_ACCESS);
28 if (IS_ERR(acl))
29 return PTR_ERR(acl);
30 if (acl) {
31 output("system.posix_acl_access");
32 posix_acl_release(acl);
33 }
34
35 if (S_ISDIR(inode->i_mode)) {
36 acl = nfs3_proc_getacl(inode, ACL_TYPE_DEFAULT);
37 if (IS_ERR(acl))
38 return PTR_ERR(acl);
39 if (acl) {
40 output("system.posix_acl_default");
41 posix_acl_release(acl);
42 }
43 }
44
45# undef output
46
47 if (!buffer || len <= size)
48 return len;
49 return -ERANGE;
50}
51
52ssize_t nfs3_getxattr(struct dentry *dentry, const char *name,
53 void *buffer, size_t size)
54{
55 struct inode *inode = dentry->d_inode;
56 struct posix_acl *acl;
57 int type, error = 0;
58
59 if (strcmp(name, POSIX_ACL_XATTR_ACCESS) == 0)
60 type = ACL_TYPE_ACCESS;
61 else if (strcmp(name, POSIX_ACL_XATTR_DEFAULT) == 0)
62 type = ACL_TYPE_DEFAULT;
63 else
64 return -EOPNOTSUPP;
65
66 acl = nfs3_proc_getacl(inode, type);
67 if (IS_ERR(acl))
68 return PTR_ERR(acl);
69 else if (acl) {
70 if (type == ACL_TYPE_ACCESS && acl->a_count == 0)
71 error = -ENODATA;
72 else
73 error = posix_acl_to_xattr(&init_user_ns, acl, buffer, size);
74 posix_acl_release(acl);
75 } else
76 error = -ENODATA;
77
78 return error;
79}
80
81int nfs3_setxattr(struct dentry *dentry, const char *name,
82 const void *value, size_t size, int flags)
83{
84 struct inode *inode = dentry->d_inode;
85 struct posix_acl *acl;
86 int type, error;
87
88 if (strcmp(name, POSIX_ACL_XATTR_ACCESS) == 0)
89 type = ACL_TYPE_ACCESS;
90 else if (strcmp(name, POSIX_ACL_XATTR_DEFAULT) == 0)
91 type = ACL_TYPE_DEFAULT;
92 else
93 return -EOPNOTSUPP;
94
95 acl = posix_acl_from_xattr(&init_user_ns, value, size);
96 if (IS_ERR(acl))
97 return PTR_ERR(acl);
98 error = nfs3_proc_setacl(inode, type, acl);
99 posix_acl_release(acl);
100
101 return error;
102}
103
104int nfs3_removexattr(struct dentry *dentry, const char *name)
105{
106 struct inode *inode = dentry->d_inode;
107 int type;
108
109 if (strcmp(name, POSIX_ACL_XATTR_ACCESS) == 0)
110 type = ACL_TYPE_ACCESS;
111 else if (strcmp(name, POSIX_ACL_XATTR_DEFAULT) == 0)
112 type = ACL_TYPE_DEFAULT;
113 else
114 return -EOPNOTSUPP;
115
116 return nfs3_proc_setacl(inode, type, NULL);
117}
118
119static void __nfs3_forget_cached_acls(struct nfs_inode *nfsi)
120{
121 if (!IS_ERR(nfsi->acl_access)) {
122 posix_acl_release(nfsi->acl_access);
123 nfsi->acl_access = ERR_PTR(-EAGAIN);
124 }
125 if (!IS_ERR(nfsi->acl_default)) {
126 posix_acl_release(nfsi->acl_default);
127 nfsi->acl_default = ERR_PTR(-EAGAIN);
128 }
129}
130
131void nfs3_forget_cached_acls(struct inode *inode)
132{
133 dprintk("NFS: nfs3_forget_cached_acls(%s/%ld)\n", inode->i_sb->s_id,
134 inode->i_ino);
135 spin_lock(&inode->i_lock);
136 __nfs3_forget_cached_acls(NFS_I(inode));
137 spin_unlock(&inode->i_lock);
138}
139
140static struct posix_acl *nfs3_get_cached_acl(struct inode *inode, int type)
141{
142 struct nfs_inode *nfsi = NFS_I(inode);
143 struct posix_acl *acl = ERR_PTR(-EINVAL);
144
145 spin_lock(&inode->i_lock);
146 switch(type) {
147 case ACL_TYPE_ACCESS:
148 acl = nfsi->acl_access;
149 break;
150
151 case ACL_TYPE_DEFAULT:
152 acl = nfsi->acl_default;
153 break;
154
155 default:
156 goto out;
157 }
158 if (IS_ERR(acl))
159 acl = ERR_PTR(-EAGAIN);
160 else
161 acl = posix_acl_dup(acl);
162out:
163 spin_unlock(&inode->i_lock);
164 dprintk("NFS: nfs3_get_cached_acl(%s/%ld, %d) = %p\n", inode->i_sb->s_id,
165 inode->i_ino, type, acl);
166 return acl;
167}
168
169static void nfs3_cache_acls(struct inode *inode, struct posix_acl *acl,
170 struct posix_acl *dfacl)
171{
172 struct nfs_inode *nfsi = NFS_I(inode);
173
174 dprintk("nfs3_cache_acls(%s/%ld, %p, %p)\n", inode->i_sb->s_id,
175 inode->i_ino, acl, dfacl);
176 spin_lock(&inode->i_lock);
177 __nfs3_forget_cached_acls(NFS_I(inode));
178 if (!IS_ERR(acl))
179 nfsi->acl_access = posix_acl_dup(acl);
180 if (!IS_ERR(dfacl))
181 nfsi->acl_default = posix_acl_dup(dfacl);
182 spin_unlock(&inode->i_lock);
183}
184
185struct posix_acl *nfs3_proc_getacl(struct inode *inode, int type)
186{ 14{
187 struct nfs_server *server = NFS_SERVER(inode); 15 struct nfs_server *server = NFS_SERVER(inode);
188 struct page *pages[NFSACL_MAXPAGES] = { }; 16 struct page *pages[NFSACL_MAXPAGES] = { };
@@ -198,7 +26,6 @@ struct posix_acl *nfs3_proc_getacl(struct inode *inode, int type)
198 .rpc_argp = &args, 26 .rpc_argp = &args,
199 .rpc_resp = &res, 27 .rpc_resp = &res,
200 }; 28 };
201 struct posix_acl *acl;
202 int status, count; 29 int status, count;
203 30
204 if (!nfs_server_capable(inode, NFS_CAP_ACLS)) 31 if (!nfs_server_capable(inode, NFS_CAP_ACLS))
@@ -207,10 +34,6 @@ struct posix_acl *nfs3_proc_getacl(struct inode *inode, int type)
207 status = nfs_revalidate_inode(server, inode); 34 status = nfs_revalidate_inode(server, inode);
208 if (status < 0) 35 if (status < 0)
209 return ERR_PTR(status); 36 return ERR_PTR(status);
210 acl = nfs3_get_cached_acl(inode, type);
211 if (acl != ERR_PTR(-EAGAIN))
212 return acl;
213 acl = NULL;
214 37
215 /* 38 /*
216 * Only get the access acl when explicitly requested: We don't 39 * Only get the access acl when explicitly requested: We don't
@@ -257,40 +80,41 @@ struct posix_acl *nfs3_proc_getacl(struct inode *inode, int type)
257 } 80 }
258 81
259 if (res.acl_access != NULL) { 82 if (res.acl_access != NULL) {
260 if (posix_acl_equiv_mode(res.acl_access, NULL) == 0) { 83 if (posix_acl_equiv_mode(res.acl_access, NULL) ||
84 res.acl_access->a_count == 0) {
261 posix_acl_release(res.acl_access); 85 posix_acl_release(res.acl_access);
262 res.acl_access = NULL; 86 res.acl_access = NULL;
263 } 87 }
264 } 88 }
265 nfs3_cache_acls(inode,
266 (res.mask & NFS_ACL) ? res.acl_access : ERR_PTR(-EINVAL),
267 (res.mask & NFS_DFACL) ? res.acl_default : ERR_PTR(-EINVAL));
268 89
269 switch(type) { 90 if (res.mask & NFS_ACL)
270 case ACL_TYPE_ACCESS: 91 set_cached_acl(inode, ACL_TYPE_ACCESS, res.acl_access);
271 acl = res.acl_access; 92 else
272 res.acl_access = NULL; 93 forget_cached_acl(inode, ACL_TYPE_ACCESS);
273 break;
274 94
275 case ACL_TYPE_DEFAULT: 95 if (res.mask & NFS_DFACL)
276 acl = res.acl_default; 96 set_cached_acl(inode, ACL_TYPE_DEFAULT, res.acl_default);
277 res.acl_default = NULL; 97 else
98 forget_cached_acl(inode, ACL_TYPE_DEFAULT);
99
100 nfs_free_fattr(res.fattr);
101 if (type == ACL_TYPE_ACCESS) {
102 posix_acl_release(res.acl_default);
103 return res.acl_access;
104 } else {
105 posix_acl_release(res.acl_access);
106 return res.acl_default;
278 } 107 }
279 108
280getout: 109getout:
281 posix_acl_release(res.acl_access); 110 posix_acl_release(res.acl_access);
282 posix_acl_release(res.acl_default); 111 posix_acl_release(res.acl_default);
283 nfs_free_fattr(res.fattr); 112 nfs_free_fattr(res.fattr);
284 113 return ERR_PTR(status);
285 if (status != 0) {
286 posix_acl_release(acl);
287 acl = ERR_PTR(status);
288 }
289 return acl;
290} 114}
291 115
292static int nfs3_proc_setacls(struct inode *inode, struct posix_acl *acl, 116int nfs3_proc_setacls(struct inode *inode, struct posix_acl *acl,
293 struct posix_acl *dfacl) 117 struct posix_acl *dfacl)
294{ 118{
295 struct nfs_server *server = NFS_SERVER(inode); 119 struct nfs_server *server = NFS_SERVER(inode);
296 struct nfs_fattr *fattr; 120 struct nfs_fattr *fattr;
@@ -353,7 +177,8 @@ static int nfs3_proc_setacls(struct inode *inode, struct posix_acl *acl,
353 switch (status) { 177 switch (status) {
354 case 0: 178 case 0:
355 status = nfs_refresh_inode(inode, fattr); 179 status = nfs_refresh_inode(inode, fattr);
356 nfs3_cache_acls(inode, acl, dfacl); 180 set_cached_acl(inode, ACL_TYPE_ACCESS, acl);
181 set_cached_acl(inode, ACL_TYPE_DEFAULT, dfacl);
357 break; 182 break;
358 case -EPFNOSUPPORT: 183 case -EPFNOSUPPORT:
359 case -EPROTONOSUPPORT: 184 case -EPROTONOSUPPORT:
@@ -373,33 +198,27 @@ out:
373 return status; 198 return status;
374} 199}
375 200
376int nfs3_proc_setacl(struct inode *inode, int type, struct posix_acl *acl) 201int nfs3_set_acl(struct inode *inode, struct posix_acl *acl, int type)
377{ 202{
378 struct posix_acl *alloc = NULL, *dfacl = NULL; 203 struct posix_acl *alloc = NULL, *dfacl = NULL;
379 int status; 204 int status;
380 205
381 if (S_ISDIR(inode->i_mode)) { 206 if (S_ISDIR(inode->i_mode)) {
382 switch(type) { 207 switch(type) {
383 case ACL_TYPE_ACCESS: 208 case ACL_TYPE_ACCESS:
384 alloc = dfacl = nfs3_proc_getacl(inode, 209 alloc = dfacl = get_acl(inode, ACL_TYPE_DEFAULT);
385 ACL_TYPE_DEFAULT); 210 if (IS_ERR(alloc))
386 if (IS_ERR(alloc)) 211 goto fail;
387 goto fail; 212 break;
388 break; 213
389 214 case ACL_TYPE_DEFAULT:
390 case ACL_TYPE_DEFAULT: 215 dfacl = acl;
391 dfacl = acl; 216 alloc = acl = get_acl(inode, ACL_TYPE_ACCESS);
392 alloc = acl = nfs3_proc_getacl(inode, 217 if (IS_ERR(alloc))
393 ACL_TYPE_ACCESS); 218 goto fail;
394 if (IS_ERR(alloc)) 219 break;
395 goto fail;
396 break;
397
398 default:
399 return -EINVAL;
400 } 220 }
401 } else if (type != ACL_TYPE_ACCESS) 221 }
402 return -EINVAL;
403 222
404 if (acl == NULL) { 223 if (acl == NULL) {
405 alloc = acl = posix_acl_from_mode(inode->i_mode, GFP_KERNEL); 224 alloc = acl = posix_acl_from_mode(inode->i_mode, GFP_KERNEL);
@@ -417,24 +236,24 @@ fail:
417int nfs3_proc_set_default_acl(struct inode *dir, struct inode *inode, 236int nfs3_proc_set_default_acl(struct inode *dir, struct inode *inode,
418 umode_t mode) 237 umode_t mode)
419{ 238{
420 struct posix_acl *dfacl, *acl; 239 struct posix_acl *default_acl, *acl;
421 int error = 0; 240 int error;
422 241
423 dfacl = nfs3_proc_getacl(dir, ACL_TYPE_DEFAULT); 242 error = posix_acl_create(dir, &mode, &default_acl, &acl);
424 if (IS_ERR(dfacl)) { 243 if (error)
425 error = PTR_ERR(dfacl);
426 return (error == -EOPNOTSUPP) ? 0 : error; 244 return (error == -EOPNOTSUPP) ? 0 : error;
427 } 245
428 if (!dfacl) 246 error = nfs3_proc_setacls(inode, acl, default_acl);
429 return 0; 247
430 acl = posix_acl_dup(dfacl); 248 if (acl)
431 error = __posix_acl_create(&acl, GFP_KERNEL, &mode); 249 posix_acl_release(acl);
432 if (error < 0) 250 if (default_acl)
433 goto out_release_dfacl; 251 posix_acl_release(default_acl);
434 error = nfs3_proc_setacls(inode, acl, S_ISDIR(inode->i_mode) ?
435 dfacl : NULL);
436 posix_acl_release(acl);
437out_release_dfacl:
438 posix_acl_release(dfacl);
439 return error; 252 return error;
440} 253}
254
255const struct xattr_handler *nfs3_xattr_handlers[] = {
256 &posix_acl_access_xattr_handler,
257 &posix_acl_default_xattr_handler,
258 NULL,
259};
diff --git a/fs/nfs/nfs3proc.c b/fs/nfs/nfs3proc.c
index 01b6f6a49d16..d2255d705421 100644
--- a/fs/nfs/nfs3proc.c
+++ b/fs/nfs/nfs3proc.c
@@ -317,8 +317,8 @@ static int
317nfs3_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr, 317nfs3_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr,
318 int flags) 318 int flags)
319{ 319{
320 struct posix_acl *default_acl, *acl;
320 struct nfs3_createdata *data; 321 struct nfs3_createdata *data;
321 umode_t mode = sattr->ia_mode;
322 int status = -ENOMEM; 322 int status = -ENOMEM;
323 323
324 dprintk("NFS call create %pd\n", dentry); 324 dprintk("NFS call create %pd\n", dentry);
@@ -340,7 +340,9 @@ nfs3_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr,
340 data->arg.create.verifier[1] = cpu_to_be32(current->pid); 340 data->arg.create.verifier[1] = cpu_to_be32(current->pid);
341 } 341 }
342 342
343 sattr->ia_mode &= ~current_umask(); 343 status = posix_acl_create(dir, &sattr->ia_mode, &default_acl, &acl);
344 if (status)
345 goto out;
344 346
345 for (;;) { 347 for (;;) {
346 status = nfs3_do_create(dir, dentry, data); 348 status = nfs3_do_create(dir, dentry, data);
@@ -366,7 +368,7 @@ nfs3_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr,
366 } 368 }
367 369
368 if (status != 0) 370 if (status != 0)
369 goto out; 371 goto out_release_acls;
370 372
371 /* When we created the file with exclusive semantics, make 373 /* When we created the file with exclusive semantics, make
372 * sure we set the attributes afterwards. */ 374 * sure we set the attributes afterwards. */
@@ -385,9 +387,14 @@ nfs3_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr,
385 nfs_post_op_update_inode(dentry->d_inode, data->res.fattr); 387 nfs_post_op_update_inode(dentry->d_inode, data->res.fattr);
386 dprintk("NFS reply setattr (post-create): %d\n", status); 388 dprintk("NFS reply setattr (post-create): %d\n", status);
387 if (status != 0) 389 if (status != 0)
388 goto out; 390 goto out_release_acls;
389 } 391 }
390 status = nfs3_proc_set_default_acl(dir, dentry->d_inode, mode); 392
393 status = nfs3_proc_setacls(dentry->d_inode, acl, default_acl);
394
395out_release_acls:
396 posix_acl_release(acl);
397 posix_acl_release(default_acl);
391out: 398out:
392 nfs3_free_createdata(data); 399 nfs3_free_createdata(data);
393 dprintk("NFS reply create: %d\n", status); 400 dprintk("NFS reply create: %d\n", status);
@@ -572,18 +579,20 @@ out:
572static int 579static int
573nfs3_proc_mkdir(struct inode *dir, struct dentry *dentry, struct iattr *sattr) 580nfs3_proc_mkdir(struct inode *dir, struct dentry *dentry, struct iattr *sattr)
574{ 581{
582 struct posix_acl *default_acl, *acl;
575 struct nfs3_createdata *data; 583 struct nfs3_createdata *data;
576 umode_t mode = sattr->ia_mode;
577 int status = -ENOMEM; 584 int status = -ENOMEM;
578 585
579 dprintk("NFS call mkdir %pd\n", dentry); 586 dprintk("NFS call mkdir %pd\n", dentry);
580 587
581 sattr->ia_mode &= ~current_umask();
582
583 data = nfs3_alloc_createdata(); 588 data = nfs3_alloc_createdata();
584 if (data == NULL) 589 if (data == NULL)
585 goto out; 590 goto out;
586 591
592 status = posix_acl_create(dir, &sattr->ia_mode, &default_acl, &acl);
593 if (status)
594 goto out;
595
587 data->msg.rpc_proc = &nfs3_procedures[NFS3PROC_MKDIR]; 596 data->msg.rpc_proc = &nfs3_procedures[NFS3PROC_MKDIR];
588 data->arg.mkdir.fh = NFS_FH(dir); 597 data->arg.mkdir.fh = NFS_FH(dir);
589 data->arg.mkdir.name = dentry->d_name.name; 598 data->arg.mkdir.name = dentry->d_name.name;
@@ -592,9 +601,13 @@ nfs3_proc_mkdir(struct inode *dir, struct dentry *dentry, struct iattr *sattr)
592 601
593 status = nfs3_do_create(dir, dentry, data); 602 status = nfs3_do_create(dir, dentry, data);
594 if (status != 0) 603 if (status != 0)
595 goto out; 604 goto out_release_acls;
596 605
597 status = nfs3_proc_set_default_acl(dir, dentry->d_inode, mode); 606 status = nfs3_proc_setacls(dentry->d_inode, acl, default_acl);
607
608out_release_acls:
609 posix_acl_release(acl);
610 posix_acl_release(default_acl);
598out: 611out:
599 nfs3_free_createdata(data); 612 nfs3_free_createdata(data);
600 dprintk("NFS reply mkdir: %d\n", status); 613 dprintk("NFS reply mkdir: %d\n", status);
@@ -691,19 +704,21 @@ static int
691nfs3_proc_mknod(struct inode *dir, struct dentry *dentry, struct iattr *sattr, 704nfs3_proc_mknod(struct inode *dir, struct dentry *dentry, struct iattr *sattr,
692 dev_t rdev) 705 dev_t rdev)
693{ 706{
707 struct posix_acl *default_acl, *acl;
694 struct nfs3_createdata *data; 708 struct nfs3_createdata *data;
695 umode_t mode = sattr->ia_mode;
696 int status = -ENOMEM; 709 int status = -ENOMEM;
697 710
698 dprintk("NFS call mknod %pd %u:%u\n", dentry, 711 dprintk("NFS call mknod %pd %u:%u\n", dentry,
699 MAJOR(rdev), MINOR(rdev)); 712 MAJOR(rdev), MINOR(rdev));
700 713
701 sattr->ia_mode &= ~current_umask();
702
703 data = nfs3_alloc_createdata(); 714 data = nfs3_alloc_createdata();
704 if (data == NULL) 715 if (data == NULL)
705 goto out; 716 goto out;
706 717
718 status = posix_acl_create(dir, &sattr->ia_mode, &default_acl, &acl);
719 if (status)
720 goto out;
721
707 data->msg.rpc_proc = &nfs3_procedures[NFS3PROC_MKNOD]; 722 data->msg.rpc_proc = &nfs3_procedures[NFS3PROC_MKNOD];
708 data->arg.mknod.fh = NFS_FH(dir); 723 data->arg.mknod.fh = NFS_FH(dir);
709 data->arg.mknod.name = dentry->d_name.name; 724 data->arg.mknod.name = dentry->d_name.name;
@@ -731,8 +746,13 @@ nfs3_proc_mknod(struct inode *dir, struct dentry *dentry, struct iattr *sattr,
731 746
732 status = nfs3_do_create(dir, dentry, data); 747 status = nfs3_do_create(dir, dentry, data);
733 if (status != 0) 748 if (status != 0)
734 goto out; 749 goto out_release_acls;
735 status = nfs3_proc_set_default_acl(dir, dentry->d_inode, mode); 750
751 status = nfs3_proc_setacls(dentry->d_inode, acl, default_acl);
752
753out_release_acls:
754 posix_acl_release(acl);
755 posix_acl_release(default_acl);
736out: 756out:
737 nfs3_free_createdata(data); 757 nfs3_free_createdata(data);
738 dprintk("NFS reply mknod: %d\n", status); 758 dprintk("NFS reply mknod: %d\n", status);
@@ -904,20 +924,28 @@ static const struct inode_operations nfs3_dir_inode_operations = {
904 .permission = nfs_permission, 924 .permission = nfs_permission,
905 .getattr = nfs_getattr, 925 .getattr = nfs_getattr,
906 .setattr = nfs_setattr, 926 .setattr = nfs_setattr,
907 .listxattr = nfs3_listxattr, 927 .listxattr = generic_listxattr,
908 .getxattr = nfs3_getxattr, 928 .getxattr = generic_getxattr,
909 .setxattr = nfs3_setxattr, 929 .setxattr = generic_setxattr,
910 .removexattr = nfs3_removexattr, 930 .removexattr = generic_removexattr,
931#ifdef CONFIG_NFS_V3_ACL
932 .get_acl = nfs3_get_acl,
933 .set_acl = nfs3_set_acl,
934#endif
911}; 935};
912 936
913static const struct inode_operations nfs3_file_inode_operations = { 937static const struct inode_operations nfs3_file_inode_operations = {
914 .permission = nfs_permission, 938 .permission = nfs_permission,
915 .getattr = nfs_getattr, 939 .getattr = nfs_getattr,
916 .setattr = nfs_setattr, 940 .setattr = nfs_setattr,
917 .listxattr = nfs3_listxattr, 941 .listxattr = generic_listxattr,
918 .getxattr = nfs3_getxattr, 942 .getxattr = generic_getxattr,
919 .setxattr = nfs3_setxattr, 943 .setxattr = generic_setxattr,
920 .removexattr = nfs3_removexattr, 944 .removexattr = generic_removexattr,
945#ifdef CONFIG_NFS_V3_ACL
946 .get_acl = nfs3_get_acl,
947 .set_acl = nfs3_set_acl,
948#endif
921}; 949};
922 950
923const struct nfs_rpc_ops nfs_v3_clientops = { 951const struct nfs_rpc_ops nfs_v3_clientops = {
@@ -965,7 +993,7 @@ const struct nfs_rpc_ops nfs_v3_clientops = {
965 .commit_rpc_prepare = nfs3_proc_commit_rpc_prepare, 993 .commit_rpc_prepare = nfs3_proc_commit_rpc_prepare,
966 .commit_done = nfs3_commit_done, 994 .commit_done = nfs3_commit_done,
967 .lock = nfs3_proc_lock, 995 .lock = nfs3_proc_lock,
968 .clear_acl_cache = nfs3_forget_cached_acls, 996 .clear_acl_cache = forget_all_cached_acls,
969 .close_context = nfs_close_context, 997 .close_context = nfs_close_context,
970 .have_delegation = nfs3_have_delegation, 998 .have_delegation = nfs3_have_delegation,
971 .return_delegation = nfs3_return_delegation, 999 .return_delegation = nfs3_return_delegation,
diff --git a/fs/nfs/nfs3super.c b/fs/nfs/nfs3super.c
index cc471c725230..d6a98949af19 100644
--- a/fs/nfs/nfs3super.c
+++ b/fs/nfs/nfs3super.c
@@ -12,6 +12,9 @@ static struct nfs_subversion nfs_v3 = {
12 .rpc_vers = &nfs_version3, 12 .rpc_vers = &nfs_version3,
13 .rpc_ops = &nfs_v3_clientops, 13 .rpc_ops = &nfs_v3_clientops,
14 .sops = &nfs_sops, 14 .sops = &nfs_sops,
15#ifdef CONFIG_NFS_V3_ACL
16 .xattr = nfs3_xattr_handlers,
17#endif
15}; 18};
16 19
17static int __init init_nfs_v3(void) 20static int __init init_nfs_v3(void)
diff --git a/include/linux/nfs_fs.h b/include/linux/nfs_fs.h
index 48997374eaf0..2b00625952a7 100644
--- a/include/linux/nfs_fs.h
+++ b/include/linux/nfs_fs.h
@@ -154,10 +154,6 @@ struct nfs_inode {
154 struct rb_root access_cache; 154 struct rb_root access_cache;
155 struct list_head access_cache_entry_lru; 155 struct list_head access_cache_entry_lru;
156 struct list_head access_cache_inode_lru; 156 struct list_head access_cache_inode_lru;
157#ifdef CONFIG_NFS_V3_ACL
158 struct posix_acl *acl_access;
159 struct posix_acl *acl_default;
160#endif
161 157
162 /* 158 /*
163 * This is the cookie verifier used for NFSv3 readdir 159 * This is the cookie verifier used for NFSv3 readdir
@@ -564,23 +560,17 @@ extern int nfs_readpage_async(struct nfs_open_context *, struct inode *,
564 * linux/fs/nfs3proc.c 560 * linux/fs/nfs3proc.c
565 */ 561 */
566#ifdef CONFIG_NFS_V3_ACL 562#ifdef CONFIG_NFS_V3_ACL
567extern struct posix_acl *nfs3_proc_getacl(struct inode *inode, int type); 563extern struct posix_acl *nfs3_get_acl(struct inode *inode, int type);
568extern int nfs3_proc_setacl(struct inode *inode, int type, 564extern int nfs3_set_acl(struct inode *inode, struct posix_acl *acl, int type);
569 struct posix_acl *acl); 565extern int nfs3_proc_setacls(struct inode *inode, struct posix_acl *acl,
570extern int nfs3_proc_set_default_acl(struct inode *dir, struct inode *inode, 566 struct posix_acl *dfacl);
571 umode_t mode); 567extern const struct xattr_handler *nfs3_xattr_handlers[];
572extern void nfs3_forget_cached_acls(struct inode *inode);
573#else 568#else
574static inline int nfs3_proc_set_default_acl(struct inode *dir, 569static inline int nfs3_proc_setacls(struct inode *inode, struct posix_acl *acl,
575 struct inode *inode, 570 struct posix_acl *dfacl)
576 umode_t mode)
577{ 571{
578 return 0; 572 return 0;
579} 573}
580
581static inline void nfs3_forget_cached_acls(struct inode *inode)
582{
583}
584#endif /* CONFIG_NFS_V3_ACL */ 574#endif /* CONFIG_NFS_V3_ACL */
585 575
586/* 576/*
diff --git a/include/linux/posix_acl.h b/include/linux/posix_acl.h
index f7e6f6cb214a..3d14be8e14db 100644
--- a/include/linux/posix_acl.h
+++ b/include/linux/posix_acl.h
@@ -191,6 +191,10 @@ static inline int posix_acl_create(struct inode *inode, umode_t *mode,
191 *default_acl = *acl = NULL; 191 *default_acl = *acl = NULL;
192 return 0; 192 return 0;
193} 193}
194
195static inline void forget_all_cached_acls(struct inode *inode)
196{
197}
194#endif /* CONFIG_FS_POSIX_ACL */ 198#endif /* CONFIG_FS_POSIX_ACL */
195 199
196struct posix_acl *get_acl(struct inode *inode, int type); 200struct posix_acl *get_acl(struct inode *inode, int type);