diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2014-02-04 15:26:16 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2014-02-04 15:26:16 -0500 |
commit | d7512f79fd6cb8e2d9b78770289df6391a867ca1 (patch) | |
tree | 741a78dbbf31f56dcc110632fa12a357c8128384 /fs | |
parent | 12b13835a0a8bfabea68741e1ab4d4a4cb77d037 (diff) | |
parent | 88a78a912ee059467ae6db7429a6efe4654620a5 (diff) |
Merge tag 'nfs-for-3.14-3' of git://git.linux-nfs.org/projects/trondmy/linux-nfs
Pull NFS client bugfixes from Trond Myklebust:
"Highlights:
- Fix NFSv3 acl regressions
- Fix NFSv4 memory corruption due to slot table abuse in
nfs4_proc_open_confirm
- nfs4_destroy_session must call rpc_destroy_waitqueue"
* tag 'nfs-for-3.14-3' of git://git.linux-nfs.org/projects/trondmy/linux-nfs:
fs: get_acl() must be allowed to return EOPNOTSUPP
NFSv3: Fix return value of nfs3_proc_setacls
NFSv3: Remove unused function nfs3_proc_set_default_acl
NFSv4.1: nfs4_destroy_session must call rpc_destroy_waitqueue
NFSv4: Fix memory corruption in nfs4_proc_open_confirm
nfs: fix setting of ACLs on file creation.
Diffstat (limited to 'fs')
-rw-r--r-- | fs/nfs/nfs3acl.c | 34 | ||||
-rw-r--r-- | fs/nfs/nfs4client.c | 2 | ||||
-rw-r--r-- | fs/nfs/nfs4proc.c | 8 | ||||
-rw-r--r-- | fs/nfs/nfs4session.c | 25 | ||||
-rw-r--r-- | fs/nfs/nfs4session.h | 2 | ||||
-rw-r--r-- | fs/posix_acl.c | 18 |
6 files changed, 50 insertions, 39 deletions
diff --git a/fs/nfs/nfs3acl.c b/fs/nfs/nfs3acl.c index 9a5ca03fa539..871d6eda8dba 100644 --- a/fs/nfs/nfs3acl.c +++ b/fs/nfs/nfs3acl.c | |||
@@ -80,7 +80,7 @@ struct posix_acl *nfs3_get_acl(struct inode *inode, int type) | |||
80 | } | 80 | } |
81 | 81 | ||
82 | if (res.acl_access != NULL) { | 82 | if (res.acl_access != NULL) { |
83 | if (posix_acl_equiv_mode(res.acl_access, NULL) || | 83 | if ((posix_acl_equiv_mode(res.acl_access, NULL) == 0) || |
84 | res.acl_access->a_count == 0) { | 84 | res.acl_access->a_count == 0) { |
85 | posix_acl_release(res.acl_access); | 85 | posix_acl_release(res.acl_access); |
86 | res.acl_access = NULL; | 86 | res.acl_access = NULL; |
@@ -113,7 +113,7 @@ getout: | |||
113 | return ERR_PTR(status); | 113 | return ERR_PTR(status); |
114 | } | 114 | } |
115 | 115 | ||
116 | int nfs3_proc_setacls(struct inode *inode, struct posix_acl *acl, | 116 | static int __nfs3_proc_setacls(struct inode *inode, struct posix_acl *acl, |
117 | struct posix_acl *dfacl) | 117 | struct posix_acl *dfacl) |
118 | { | 118 | { |
119 | struct nfs_server *server = NFS_SERVER(inode); | 119 | struct nfs_server *server = NFS_SERVER(inode); |
@@ -198,6 +198,15 @@ out: | |||
198 | return status; | 198 | return status; |
199 | } | 199 | } |
200 | 200 | ||
201 | int nfs3_proc_setacls(struct inode *inode, struct posix_acl *acl, | ||
202 | struct posix_acl *dfacl) | ||
203 | { | ||
204 | int ret; | ||
205 | ret = __nfs3_proc_setacls(inode, acl, dfacl); | ||
206 | return (ret == -EOPNOTSUPP) ? 0 : ret; | ||
207 | |||
208 | } | ||
209 | |||
201 | int nfs3_set_acl(struct inode *inode, struct posix_acl *acl, int type) | 210 | int nfs3_set_acl(struct inode *inode, struct posix_acl *acl, int type) |
202 | { | 211 | { |
203 | struct posix_acl *alloc = NULL, *dfacl = NULL; | 212 | struct posix_acl *alloc = NULL, *dfacl = NULL; |
@@ -225,7 +234,7 @@ int nfs3_set_acl(struct inode *inode, struct posix_acl *acl, int type) | |||
225 | if (IS_ERR(alloc)) | 234 | if (IS_ERR(alloc)) |
226 | goto fail; | 235 | goto fail; |
227 | } | 236 | } |
228 | status = nfs3_proc_setacls(inode, acl, dfacl); | 237 | status = __nfs3_proc_setacls(inode, acl, dfacl); |
229 | posix_acl_release(alloc); | 238 | posix_acl_release(alloc); |
230 | return status; | 239 | return status; |
231 | 240 | ||
@@ -233,25 +242,6 @@ fail: | |||
233 | return PTR_ERR(alloc); | 242 | return PTR_ERR(alloc); |
234 | } | 243 | } |
235 | 244 | ||
236 | int nfs3_proc_set_default_acl(struct inode *dir, struct inode *inode, | ||
237 | umode_t mode) | ||
238 | { | ||
239 | struct posix_acl *default_acl, *acl; | ||
240 | int error; | ||
241 | |||
242 | error = posix_acl_create(dir, &mode, &default_acl, &acl); | ||
243 | if (error) | ||
244 | return (error == -EOPNOTSUPP) ? 0 : error; | ||
245 | |||
246 | error = nfs3_proc_setacls(inode, acl, default_acl); | ||
247 | |||
248 | if (acl) | ||
249 | posix_acl_release(acl); | ||
250 | if (default_acl) | ||
251 | posix_acl_release(default_acl); | ||
252 | return error; | ||
253 | } | ||
254 | |||
255 | const struct xattr_handler *nfs3_xattr_handlers[] = { | 245 | const struct xattr_handler *nfs3_xattr_handlers[] = { |
256 | &posix_acl_access_xattr_handler, | 246 | &posix_acl_access_xattr_handler, |
257 | &posix_acl_default_xattr_handler, | 247 | &posix_acl_default_xattr_handler, |
diff --git a/fs/nfs/nfs4client.c b/fs/nfs/nfs4client.c index dbb3e1f30c68..860ad26a5590 100644 --- a/fs/nfs/nfs4client.c +++ b/fs/nfs/nfs4client.c | |||
@@ -170,7 +170,7 @@ void nfs41_shutdown_client(struct nfs_client *clp) | |||
170 | void nfs40_shutdown_client(struct nfs_client *clp) | 170 | void nfs40_shutdown_client(struct nfs_client *clp) |
171 | { | 171 | { |
172 | if (clp->cl_slot_tbl) { | 172 | if (clp->cl_slot_tbl) { |
173 | nfs4_release_slot_table(clp->cl_slot_tbl); | 173 | nfs4_shutdown_slot_table(clp->cl_slot_tbl); |
174 | kfree(clp->cl_slot_tbl); | 174 | kfree(clp->cl_slot_tbl); |
175 | } | 175 | } |
176 | } | 176 | } |
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index 42da6af77587..2da6a698b8f7 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c | |||
@@ -1620,15 +1620,15 @@ static void nfs4_open_confirm_prepare(struct rpc_task *task, void *calldata) | |||
1620 | { | 1620 | { |
1621 | struct nfs4_opendata *data = calldata; | 1621 | struct nfs4_opendata *data = calldata; |
1622 | 1622 | ||
1623 | nfs40_setup_sequence(data->o_arg.server, &data->o_arg.seq_args, | 1623 | nfs40_setup_sequence(data->o_arg.server, &data->c_arg.seq_args, |
1624 | &data->o_res.seq_res, task); | 1624 | &data->c_res.seq_res, task); |
1625 | } | 1625 | } |
1626 | 1626 | ||
1627 | static void nfs4_open_confirm_done(struct rpc_task *task, void *calldata) | 1627 | static void nfs4_open_confirm_done(struct rpc_task *task, void *calldata) |
1628 | { | 1628 | { |
1629 | struct nfs4_opendata *data = calldata; | 1629 | struct nfs4_opendata *data = calldata; |
1630 | 1630 | ||
1631 | nfs40_sequence_done(task, &data->o_res.seq_res); | 1631 | nfs40_sequence_done(task, &data->c_res.seq_res); |
1632 | 1632 | ||
1633 | data->rpc_status = task->tk_status; | 1633 | data->rpc_status = task->tk_status; |
1634 | if (data->rpc_status == 0) { | 1634 | if (data->rpc_status == 0) { |
@@ -1686,7 +1686,7 @@ static int _nfs4_proc_open_confirm(struct nfs4_opendata *data) | |||
1686 | }; | 1686 | }; |
1687 | int status; | 1687 | int status; |
1688 | 1688 | ||
1689 | nfs4_init_sequence(&data->o_arg.seq_args, &data->o_res.seq_res, 1); | 1689 | nfs4_init_sequence(&data->c_arg.seq_args, &data->c_res.seq_res, 1); |
1690 | kref_get(&data->kref); | 1690 | kref_get(&data->kref); |
1691 | data->rpc_done = 0; | 1691 | data->rpc_done = 0; |
1692 | data->rpc_status = 0; | 1692 | data->rpc_status = 0; |
diff --git a/fs/nfs/nfs4session.c b/fs/nfs/nfs4session.c index cf883c7ae053..e799dc3c3b1d 100644 --- a/fs/nfs/nfs4session.c +++ b/fs/nfs/nfs4session.c | |||
@@ -231,14 +231,23 @@ out: | |||
231 | return ret; | 231 | return ret; |
232 | } | 232 | } |
233 | 233 | ||
234 | /* | ||
235 | * nfs4_release_slot_table - release all slot table entries | ||
236 | */ | ||
237 | static void nfs4_release_slot_table(struct nfs4_slot_table *tbl) | ||
238 | { | ||
239 | nfs4_shrink_slot_table(tbl, 0); | ||
240 | } | ||
241 | |||
234 | /** | 242 | /** |
235 | * nfs4_release_slot_table - release resources attached to a slot table | 243 | * nfs4_shutdown_slot_table - release resources attached to a slot table |
236 | * @tbl: slot table to shut down | 244 | * @tbl: slot table to shut down |
237 | * | 245 | * |
238 | */ | 246 | */ |
239 | void nfs4_release_slot_table(struct nfs4_slot_table *tbl) | 247 | void nfs4_shutdown_slot_table(struct nfs4_slot_table *tbl) |
240 | { | 248 | { |
241 | nfs4_shrink_slot_table(tbl, 0); | 249 | nfs4_release_slot_table(tbl); |
250 | rpc_destroy_wait_queue(&tbl->slot_tbl_waitq); | ||
242 | } | 251 | } |
243 | 252 | ||
244 | /** | 253 | /** |
@@ -422,7 +431,7 @@ void nfs41_update_target_slotid(struct nfs4_slot_table *tbl, | |||
422 | spin_unlock(&tbl->slot_tbl_lock); | 431 | spin_unlock(&tbl->slot_tbl_lock); |
423 | } | 432 | } |
424 | 433 | ||
425 | static void nfs4_destroy_session_slot_tables(struct nfs4_session *session) | 434 | static void nfs4_release_session_slot_tables(struct nfs4_session *session) |
426 | { | 435 | { |
427 | nfs4_release_slot_table(&session->fc_slot_table); | 436 | nfs4_release_slot_table(&session->fc_slot_table); |
428 | nfs4_release_slot_table(&session->bc_slot_table); | 437 | nfs4_release_slot_table(&session->bc_slot_table); |
@@ -450,7 +459,7 @@ int nfs4_setup_session_slot_tables(struct nfs4_session *ses) | |||
450 | if (status && tbl->slots == NULL) | 459 | if (status && tbl->slots == NULL) |
451 | /* Fore and back channel share a connection so get | 460 | /* Fore and back channel share a connection so get |
452 | * both slot tables or neither */ | 461 | * both slot tables or neither */ |
453 | nfs4_destroy_session_slot_tables(ses); | 462 | nfs4_release_session_slot_tables(ses); |
454 | return status; | 463 | return status; |
455 | } | 464 | } |
456 | 465 | ||
@@ -470,6 +479,12 @@ struct nfs4_session *nfs4_alloc_session(struct nfs_client *clp) | |||
470 | return session; | 479 | return session; |
471 | } | 480 | } |
472 | 481 | ||
482 | static void nfs4_destroy_session_slot_tables(struct nfs4_session *session) | ||
483 | { | ||
484 | nfs4_shutdown_slot_table(&session->fc_slot_table); | ||
485 | nfs4_shutdown_slot_table(&session->bc_slot_table); | ||
486 | } | ||
487 | |||
473 | void nfs4_destroy_session(struct nfs4_session *session) | 488 | void nfs4_destroy_session(struct nfs4_session *session) |
474 | { | 489 | { |
475 | struct rpc_xprt *xprt; | 490 | struct rpc_xprt *xprt; |
diff --git a/fs/nfs/nfs4session.h b/fs/nfs/nfs4session.h index 232306100651..b34ada9bc6a2 100644 --- a/fs/nfs/nfs4session.h +++ b/fs/nfs/nfs4session.h | |||
@@ -74,7 +74,7 @@ enum nfs4_session_state { | |||
74 | 74 | ||
75 | extern int nfs4_setup_slot_table(struct nfs4_slot_table *tbl, | 75 | extern int nfs4_setup_slot_table(struct nfs4_slot_table *tbl, |
76 | unsigned int max_reqs, const char *queue); | 76 | unsigned int max_reqs, const char *queue); |
77 | extern void nfs4_release_slot_table(struct nfs4_slot_table *tbl); | 77 | extern void nfs4_shutdown_slot_table(struct nfs4_slot_table *tbl); |
78 | extern struct nfs4_slot *nfs4_alloc_slot(struct nfs4_slot_table *tbl); | 78 | extern struct nfs4_slot *nfs4_alloc_slot(struct nfs4_slot_table *tbl); |
79 | extern void nfs4_free_slot(struct nfs4_slot_table *tbl, struct nfs4_slot *slot); | 79 | extern void nfs4_free_slot(struct nfs4_slot_table *tbl, struct nfs4_slot *slot); |
80 | extern void nfs4_slot_tbl_drain_complete(struct nfs4_slot_table *tbl); | 80 | extern void nfs4_slot_tbl_drain_complete(struct nfs4_slot_table *tbl); |
diff --git a/fs/posix_acl.c b/fs/posix_acl.c index 38bae5a0ea25..11c54fd51e16 100644 --- a/fs/posix_acl.c +++ b/fs/posix_acl.c | |||
@@ -521,8 +521,11 @@ posix_acl_chmod(struct inode *inode, umode_t mode) | |||
521 | return -EOPNOTSUPP; | 521 | return -EOPNOTSUPP; |
522 | 522 | ||
523 | acl = get_acl(inode, ACL_TYPE_ACCESS); | 523 | acl = get_acl(inode, ACL_TYPE_ACCESS); |
524 | if (IS_ERR_OR_NULL(acl)) | 524 | if (IS_ERR_OR_NULL(acl)) { |
525 | if (acl == ERR_PTR(-EOPNOTSUPP)) | ||
526 | return 0; | ||
525 | return PTR_ERR(acl); | 527 | return PTR_ERR(acl); |
528 | } | ||
526 | 529 | ||
527 | ret = __posix_acl_chmod(&acl, GFP_KERNEL, mode); | 530 | ret = __posix_acl_chmod(&acl, GFP_KERNEL, mode); |
528 | if (ret) | 531 | if (ret) |
@@ -544,14 +547,15 @@ posix_acl_create(struct inode *dir, umode_t *mode, | |||
544 | goto no_acl; | 547 | goto no_acl; |
545 | 548 | ||
546 | p = get_acl(dir, ACL_TYPE_DEFAULT); | 549 | p = get_acl(dir, ACL_TYPE_DEFAULT); |
547 | if (IS_ERR(p)) | 550 | if (IS_ERR(p)) { |
551 | if (p == ERR_PTR(-EOPNOTSUPP)) | ||
552 | goto apply_umask; | ||
548 | return PTR_ERR(p); | 553 | return PTR_ERR(p); |
549 | |||
550 | if (!p) { | ||
551 | *mode &= ~current_umask(); | ||
552 | goto no_acl; | ||
553 | } | 554 | } |
554 | 555 | ||
556 | if (!p) | ||
557 | goto apply_umask; | ||
558 | |||
555 | *acl = posix_acl_clone(p, GFP_NOFS); | 559 | *acl = posix_acl_clone(p, GFP_NOFS); |
556 | if (!*acl) | 560 | if (!*acl) |
557 | return -ENOMEM; | 561 | return -ENOMEM; |
@@ -575,6 +579,8 @@ posix_acl_create(struct inode *dir, umode_t *mode, | |||
575 | } | 579 | } |
576 | return 0; | 580 | return 0; |
577 | 581 | ||
582 | apply_umask: | ||
583 | *mode &= ~current_umask(); | ||
578 | no_acl: | 584 | no_acl: |
579 | *default_acl = NULL; | 585 | *default_acl = NULL; |
580 | *acl = NULL; | 586 | *acl = NULL; |