diff options
35 files changed, 515 insertions, 420 deletions
diff --git a/fs/nfs/Makefile b/fs/nfs/Makefile index cce2c057bd2d..e0bb048e9576 100644 --- a/fs/nfs/Makefile +++ b/fs/nfs/Makefile | |||
@@ -6,8 +6,7 @@ obj-$(CONFIG_NFS_FS) += nfs.o | |||
6 | 6 | ||
7 | nfs-y := client.o dir.o file.o getroot.o inode.o super.o \ | 7 | nfs-y := client.o dir.o file.o getroot.o inode.o super.o \ |
8 | direct.o pagelist.o read.o symlink.o unlink.o \ | 8 | direct.o pagelist.o read.o symlink.o unlink.o \ |
9 | write.o namespace.o mount_clnt.o \ | 9 | write.o namespace.o mount_clnt.o |
10 | dns_resolve.o cache_lib.o | ||
11 | nfs-$(CONFIG_ROOT_NFS) += nfsroot.o | 10 | nfs-$(CONFIG_ROOT_NFS) += nfsroot.o |
12 | nfs-$(CONFIG_SYSCTL) += sysctl.o | 11 | nfs-$(CONFIG_SYSCTL) += sysctl.o |
13 | nfs-$(CONFIG_NFS_FSCACHE) += fscache.o fscache-index.o | 12 | nfs-$(CONFIG_NFS_FSCACHE) += fscache.o fscache-index.o |
@@ -22,7 +21,8 @@ nfsv3-$(CONFIG_NFS_V3_ACL) += nfs3acl.o | |||
22 | obj-$(CONFIG_NFS_V4) += nfsv4.o | 21 | obj-$(CONFIG_NFS_V4) += nfsv4.o |
23 | nfsv4-y := nfs4proc.o nfs4xdr.o nfs4state.o nfs4renewd.o nfs4super.o nfs4file.o \ | 22 | nfsv4-y := nfs4proc.o nfs4xdr.o nfs4state.o nfs4renewd.o nfs4super.o nfs4file.o \ |
24 | delegation.o idmap.o callback.o callback_xdr.o callback_proc.o \ | 23 | delegation.o idmap.o callback.o callback_xdr.o callback_proc.o \ |
25 | nfs4namespace.o nfs4getroot.o nfs4client.o | 24 | nfs4namespace.o nfs4getroot.o nfs4client.o dns_resolve.o |
25 | nfsv4-$(CONFIG_NFS_USE_LEGACY_DNS) += cache_lib.o | ||
26 | nfsv4-$(CONFIG_SYSCTL) += nfs4sysctl.o | 26 | nfsv4-$(CONFIG_SYSCTL) += nfs4sysctl.o |
27 | nfsv4-$(CONFIG_NFS_V4_1) += nfs4session.o pnfs.o pnfs_dev.o | 27 | nfsv4-$(CONFIG_NFS_V4_1) += nfs4session.o pnfs.o pnfs_dev.o |
28 | 28 | ||
diff --git a/fs/nfs/blocklayout/blocklayout.c b/fs/nfs/blocklayout/blocklayout.c index 434b93ec0970..e242bbf72972 100644 --- a/fs/nfs/blocklayout/blocklayout.c +++ b/fs/nfs/blocklayout/blocklayout.c | |||
@@ -1089,9 +1089,10 @@ nfs4_blk_get_deviceinfo(struct nfs_server *server, const struct nfs_fh *fh, | |||
1089 | dev->pgbase = 0; | 1089 | dev->pgbase = 0; |
1090 | dev->pglen = PAGE_SIZE * max_pages; | 1090 | dev->pglen = PAGE_SIZE * max_pages; |
1091 | dev->mincount = 0; | 1091 | dev->mincount = 0; |
1092 | dev->maxcount = max_resp_sz - nfs41_maxgetdevinfo_overhead; | ||
1092 | 1093 | ||
1093 | dprintk("%s: dev_id: %s\n", __func__, dev->dev_id.data); | 1094 | dprintk("%s: dev_id: %s\n", __func__, dev->dev_id.data); |
1094 | rc = nfs4_proc_getdeviceinfo(server, dev); | 1095 | rc = nfs4_proc_getdeviceinfo(server, dev, NULL); |
1095 | dprintk("%s getdevice info returns %d\n", __func__, rc); | 1096 | dprintk("%s getdevice info returns %d\n", __func__, rc); |
1096 | if (rc) { | 1097 | if (rc) { |
1097 | rv = ERR_PTR(rc); | 1098 | rv = ERR_PTR(rc); |
diff --git a/fs/nfs/callback_proc.c b/fs/nfs/callback_proc.c index 3d2af31e004c..e6ebc4c38c81 100644 --- a/fs/nfs/callback_proc.c +++ b/fs/nfs/callback_proc.c | |||
@@ -415,7 +415,7 @@ __be32 nfs4_callback_sequence(struct cb_sequenceargs *args, | |||
415 | 415 | ||
416 | spin_lock(&tbl->slot_tbl_lock); | 416 | spin_lock(&tbl->slot_tbl_lock); |
417 | /* state manager is resetting the session */ | 417 | /* state manager is resetting the session */ |
418 | if (test_bit(NFS4_SESSION_DRAINING, &clp->cl_session->session_state)) { | 418 | if (test_bit(NFS4_SLOT_TBL_DRAINING, &tbl->slot_tbl_state)) { |
419 | spin_unlock(&tbl->slot_tbl_lock); | 419 | spin_unlock(&tbl->slot_tbl_lock); |
420 | status = htonl(NFS4ERR_DELAY); | 420 | status = htonl(NFS4ERR_DELAY); |
421 | /* Return NFS4ERR_BADSESSION if we're draining the session | 421 | /* Return NFS4ERR_BADSESSION if we're draining the session |
diff --git a/fs/nfs/callback_xdr.c b/fs/nfs/callback_xdr.c index d450c21bc382..f4ccfe6521ec 100644 --- a/fs/nfs/callback_xdr.c +++ b/fs/nfs/callback_xdr.c | |||
@@ -763,7 +763,7 @@ static void nfs4_callback_free_slot(struct nfs4_session *session) | |||
763 | * A single slot, so highest used slotid is either 0 or -1 | 763 | * A single slot, so highest used slotid is either 0 or -1 |
764 | */ | 764 | */ |
765 | tbl->highest_used_slotid = NFS4_NO_SLOT; | 765 | tbl->highest_used_slotid = NFS4_NO_SLOT; |
766 | nfs4_session_drain_complete(session, tbl); | 766 | nfs4_slot_tbl_drain_complete(tbl); |
767 | spin_unlock(&tbl->slot_tbl_lock); | 767 | spin_unlock(&tbl->slot_tbl_lock); |
768 | } | 768 | } |
769 | 769 | ||
diff --git a/fs/nfs/client.c b/fs/nfs/client.c index c426528deff4..340b1eff0267 100644 --- a/fs/nfs/client.c +++ b/fs/nfs/client.c | |||
@@ -753,8 +753,6 @@ static int nfs_init_server(struct nfs_server *server, | |||
753 | data->timeo, data->retrans); | 753 | data->timeo, data->retrans); |
754 | if (data->flags & NFS_MOUNT_NORESVPORT) | 754 | if (data->flags & NFS_MOUNT_NORESVPORT) |
755 | set_bit(NFS_CS_NORESVPORT, &cl_init.init_flags); | 755 | set_bit(NFS_CS_NORESVPORT, &cl_init.init_flags); |
756 | if (server->options & NFS_OPTION_MIGRATION) | ||
757 | set_bit(NFS_CS_MIGRATION, &cl_init.init_flags); | ||
758 | 756 | ||
759 | /* Allocate or find a client reference we can use */ | 757 | /* Allocate or find a client reference we can use */ |
760 | clp = nfs_get_client(&cl_init, &timeparms, NULL, RPC_AUTH_UNIX); | 758 | clp = nfs_get_client(&cl_init, &timeparms, NULL, RPC_AUTH_UNIX); |
diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c index 743d3b524fc5..c3f21888654f 100644 --- a/fs/nfs/dir.c +++ b/fs/nfs/dir.c | |||
@@ -1385,18 +1385,6 @@ static int nfs_finish_open(struct nfs_open_context *ctx, | |||
1385 | { | 1385 | { |
1386 | int err; | 1386 | int err; |
1387 | 1387 | ||
1388 | if (ctx->dentry != dentry) { | ||
1389 | dput(ctx->dentry); | ||
1390 | ctx->dentry = dget(dentry); | ||
1391 | } | ||
1392 | |||
1393 | /* If the open_intent is for execute, we have an extra check to make */ | ||
1394 | if (ctx->mode & FMODE_EXEC) { | ||
1395 | err = nfs_may_open(dentry->d_inode, ctx->cred, open_flags); | ||
1396 | if (err < 0) | ||
1397 | goto out; | ||
1398 | } | ||
1399 | |||
1400 | err = finish_open(file, dentry, do_open, opened); | 1388 | err = finish_open(file, dentry, do_open, opened); |
1401 | if (err) | 1389 | if (err) |
1402 | goto out; | 1390 | goto out; |
@@ -1455,13 +1443,13 @@ int nfs_atomic_open(struct inode *dir, struct dentry *dentry, | |||
1455 | 1443 | ||
1456 | nfs_block_sillyrename(dentry->d_parent); | 1444 | nfs_block_sillyrename(dentry->d_parent); |
1457 | inode = NFS_PROTO(dir)->open_context(dir, ctx, open_flags, &attr); | 1445 | inode = NFS_PROTO(dir)->open_context(dir, ctx, open_flags, &attr); |
1458 | d_drop(dentry); | 1446 | nfs_unblock_sillyrename(dentry->d_parent); |
1459 | if (IS_ERR(inode)) { | 1447 | if (IS_ERR(inode)) { |
1460 | nfs_unblock_sillyrename(dentry->d_parent); | ||
1461 | put_nfs_open_context(ctx); | 1448 | put_nfs_open_context(ctx); |
1462 | err = PTR_ERR(inode); | 1449 | err = PTR_ERR(inode); |
1463 | switch (err) { | 1450 | switch (err) { |
1464 | case -ENOENT: | 1451 | case -ENOENT: |
1452 | d_drop(dentry); | ||
1465 | d_add(dentry, NULL); | 1453 | d_add(dentry, NULL); |
1466 | break; | 1454 | break; |
1467 | case -EISDIR: | 1455 | case -EISDIR: |
@@ -1477,16 +1465,8 @@ int nfs_atomic_open(struct inode *dir, struct dentry *dentry, | |||
1477 | } | 1465 | } |
1478 | goto out; | 1466 | goto out; |
1479 | } | 1467 | } |
1480 | res = d_add_unique(dentry, inode); | ||
1481 | if (res != NULL) | ||
1482 | dentry = res; | ||
1483 | |||
1484 | nfs_unblock_sillyrename(dentry->d_parent); | ||
1485 | nfs_set_verifier(dentry, nfs_save_change_attribute(dir)); | ||
1486 | |||
1487 | err = nfs_finish_open(ctx, dentry, file, open_flags, opened); | ||
1488 | 1468 | ||
1489 | dput(res); | 1469 | err = nfs_finish_open(ctx, ctx->dentry, file, open_flags, opened); |
1490 | out: | 1470 | out: |
1491 | return err; | 1471 | return err; |
1492 | 1472 | ||
diff --git a/fs/nfs/dns_resolve.c b/fs/nfs/dns_resolve.c index 945527092295..fc0f95ec7358 100644 --- a/fs/nfs/dns_resolve.c +++ b/fs/nfs/dns_resolve.c | |||
@@ -29,7 +29,6 @@ ssize_t nfs_dns_resolve_name(struct net *net, char *name, size_t namelen, | |||
29 | kfree(ip_addr); | 29 | kfree(ip_addr); |
30 | return ret; | 30 | return ret; |
31 | } | 31 | } |
32 | EXPORT_SYMBOL_GPL(nfs_dns_resolve_name); | ||
33 | 32 | ||
34 | #else | 33 | #else |
35 | 34 | ||
@@ -351,7 +350,6 @@ ssize_t nfs_dns_resolve_name(struct net *net, char *name, | |||
351 | ret = -ESRCH; | 350 | ret = -ESRCH; |
352 | return ret; | 351 | return ret; |
353 | } | 352 | } |
354 | EXPORT_SYMBOL_GPL(nfs_dns_resolve_name); | ||
355 | 353 | ||
356 | static struct cache_detail nfs_dns_resolve_template = { | 354 | static struct cache_detail nfs_dns_resolve_template = { |
357 | .owner = THIS_MODULE, | 355 | .owner = THIS_MODULE, |
@@ -396,6 +394,21 @@ void nfs_dns_resolver_cache_destroy(struct net *net) | |||
396 | cache_destroy_net(nn->nfs_dns_resolve, net); | 394 | cache_destroy_net(nn->nfs_dns_resolve, net); |
397 | } | 395 | } |
398 | 396 | ||
397 | static int nfs4_dns_net_init(struct net *net) | ||
398 | { | ||
399 | return nfs_dns_resolver_cache_init(net); | ||
400 | } | ||
401 | |||
402 | static void nfs4_dns_net_exit(struct net *net) | ||
403 | { | ||
404 | nfs_dns_resolver_cache_destroy(net); | ||
405 | } | ||
406 | |||
407 | static struct pernet_operations nfs4_dns_resolver_ops = { | ||
408 | .init = nfs4_dns_net_init, | ||
409 | .exit = nfs4_dns_net_exit, | ||
410 | }; | ||
411 | |||
399 | static int rpc_pipefs_event(struct notifier_block *nb, unsigned long event, | 412 | static int rpc_pipefs_event(struct notifier_block *nb, unsigned long event, |
400 | void *ptr) | 413 | void *ptr) |
401 | { | 414 | { |
@@ -432,11 +445,24 @@ static struct notifier_block nfs_dns_resolver_block = { | |||
432 | 445 | ||
433 | int nfs_dns_resolver_init(void) | 446 | int nfs_dns_resolver_init(void) |
434 | { | 447 | { |
435 | return rpc_pipefs_notifier_register(&nfs_dns_resolver_block); | 448 | int err; |
449 | |||
450 | err = register_pernet_subsys(&nfs4_dns_resolver_ops); | ||
451 | if (err < 0) | ||
452 | goto out; | ||
453 | err = rpc_pipefs_notifier_register(&nfs_dns_resolver_block); | ||
454 | if (err < 0) | ||
455 | goto out1; | ||
456 | return 0; | ||
457 | out1: | ||
458 | unregister_pernet_subsys(&nfs4_dns_resolver_ops); | ||
459 | out: | ||
460 | return err; | ||
436 | } | 461 | } |
437 | 462 | ||
438 | void nfs_dns_resolver_destroy(void) | 463 | void nfs_dns_resolver_destroy(void) |
439 | { | 464 | { |
440 | rpc_pipefs_notifier_unregister(&nfs_dns_resolver_block); | 465 | rpc_pipefs_notifier_unregister(&nfs_dns_resolver_block); |
466 | unregister_pernet_subsys(&nfs4_dns_resolver_ops); | ||
441 | } | 467 | } |
442 | #endif | 468 | #endif |
diff --git a/fs/nfs/idmap.c b/fs/nfs/idmap.c index c516da5873fd..c2c4163d5683 100644 --- a/fs/nfs/idmap.c +++ b/fs/nfs/idmap.c | |||
@@ -262,29 +262,42 @@ static ssize_t nfs_idmap_get_desc(const char *name, size_t namelen, | |||
262 | return desclen; | 262 | return desclen; |
263 | } | 263 | } |
264 | 264 | ||
265 | static ssize_t nfs_idmap_request_key(struct key_type *key_type, | 265 | static struct key *nfs_idmap_request_key(const char *name, size_t namelen, |
266 | const char *name, size_t namelen, | 266 | const char *type, struct idmap *idmap) |
267 | const char *type, void *data, | ||
268 | size_t data_size, struct idmap *idmap) | ||
269 | { | 267 | { |
270 | const struct cred *saved_cred; | ||
271 | struct key *rkey; | ||
272 | char *desc; | 268 | char *desc; |
273 | struct user_key_payload *payload; | 269 | struct key *rkey; |
274 | ssize_t ret; | 270 | ssize_t ret; |
275 | 271 | ||
276 | ret = nfs_idmap_get_desc(name, namelen, type, strlen(type), &desc); | 272 | ret = nfs_idmap_get_desc(name, namelen, type, strlen(type), &desc); |
277 | if (ret <= 0) | 273 | if (ret <= 0) |
278 | goto out; | 274 | return ERR_PTR(ret); |
275 | |||
276 | rkey = request_key(&key_type_id_resolver, desc, ""); | ||
277 | if (IS_ERR(rkey)) { | ||
278 | mutex_lock(&idmap->idmap_mutex); | ||
279 | rkey = request_key_with_auxdata(&key_type_id_resolver_legacy, | ||
280 | desc, "", 0, idmap); | ||
281 | mutex_unlock(&idmap->idmap_mutex); | ||
282 | } | ||
283 | |||
284 | kfree(desc); | ||
285 | return rkey; | ||
286 | } | ||
287 | |||
288 | static ssize_t nfs_idmap_get_key(const char *name, size_t namelen, | ||
289 | const char *type, void *data, | ||
290 | size_t data_size, struct idmap *idmap) | ||
291 | { | ||
292 | const struct cred *saved_cred; | ||
293 | struct key *rkey; | ||
294 | struct user_key_payload *payload; | ||
295 | ssize_t ret; | ||
279 | 296 | ||
280 | saved_cred = override_creds(id_resolver_cache); | 297 | saved_cred = override_creds(id_resolver_cache); |
281 | if (idmap) | 298 | rkey = nfs_idmap_request_key(name, namelen, type, idmap); |
282 | rkey = request_key_with_auxdata(key_type, desc, "", 0, idmap); | ||
283 | else | ||
284 | rkey = request_key(&key_type_id_resolver, desc, ""); | ||
285 | revert_creds(saved_cred); | 299 | revert_creds(saved_cred); |
286 | 300 | ||
287 | kfree(desc); | ||
288 | if (IS_ERR(rkey)) { | 301 | if (IS_ERR(rkey)) { |
289 | ret = PTR_ERR(rkey); | 302 | ret = PTR_ERR(rkey); |
290 | goto out; | 303 | goto out; |
@@ -316,23 +329,6 @@ out: | |||
316 | return ret; | 329 | return ret; |
317 | } | 330 | } |
318 | 331 | ||
319 | static ssize_t nfs_idmap_get_key(const char *name, size_t namelen, | ||
320 | const char *type, void *data, | ||
321 | size_t data_size, struct idmap *idmap) | ||
322 | { | ||
323 | ssize_t ret = nfs_idmap_request_key(&key_type_id_resolver, | ||
324 | name, namelen, type, data, | ||
325 | data_size, NULL); | ||
326 | if (ret < 0) { | ||
327 | mutex_lock(&idmap->idmap_mutex); | ||
328 | ret = nfs_idmap_request_key(&key_type_id_resolver_legacy, | ||
329 | name, namelen, type, data, | ||
330 | data_size, idmap); | ||
331 | mutex_unlock(&idmap->idmap_mutex); | ||
332 | } | ||
333 | return ret; | ||
334 | } | ||
335 | |||
336 | /* ID -> Name */ | 332 | /* ID -> Name */ |
337 | static ssize_t nfs_idmap_lookup_name(__u32 id, const char *type, char *buf, | 333 | static ssize_t nfs_idmap_lookup_name(__u32 id, const char *type, char *buf, |
338 | size_t buflen, struct idmap *idmap) | 334 | size_t buflen, struct idmap *idmap) |
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c index f908af672197..8ea62be3fefe 100644 --- a/fs/nfs/inode.c +++ b/fs/nfs/inode.c | |||
@@ -48,7 +48,6 @@ | |||
48 | #include "iostat.h" | 48 | #include "iostat.h" |
49 | #include "internal.h" | 49 | #include "internal.h" |
50 | #include "fscache.h" | 50 | #include "fscache.h" |
51 | #include "dns_resolve.h" | ||
52 | #include "pnfs.h" | 51 | #include "pnfs.h" |
53 | #include "nfs.h" | 52 | #include "nfs.h" |
54 | #include "netns.h" | 53 | #include "netns.h" |
@@ -785,16 +784,23 @@ EXPORT_SYMBOL_GPL(put_nfs_open_context); | |||
785 | * Ensure that mmap has a recent RPC credential for use when writing out | 784 | * Ensure that mmap has a recent RPC credential for use when writing out |
786 | * shared pages | 785 | * shared pages |
787 | */ | 786 | */ |
788 | void nfs_file_set_open_context(struct file *filp, struct nfs_open_context *ctx) | 787 | void nfs_inode_attach_open_context(struct nfs_open_context *ctx) |
789 | { | 788 | { |
790 | struct inode *inode = file_inode(filp); | 789 | struct inode *inode = ctx->dentry->d_inode; |
791 | struct nfs_inode *nfsi = NFS_I(inode); | 790 | struct nfs_inode *nfsi = NFS_I(inode); |
792 | 791 | ||
793 | filp->private_data = get_nfs_open_context(ctx); | ||
794 | spin_lock(&inode->i_lock); | 792 | spin_lock(&inode->i_lock); |
795 | list_add(&ctx->list, &nfsi->open_files); | 793 | list_add(&ctx->list, &nfsi->open_files); |
796 | spin_unlock(&inode->i_lock); | 794 | spin_unlock(&inode->i_lock); |
797 | } | 795 | } |
796 | EXPORT_SYMBOL_GPL(nfs_inode_attach_open_context); | ||
797 | |||
798 | void nfs_file_set_open_context(struct file *filp, struct nfs_open_context *ctx) | ||
799 | { | ||
800 | filp->private_data = get_nfs_open_context(ctx); | ||
801 | if (list_empty(&ctx->list)) | ||
802 | nfs_inode_attach_open_context(ctx); | ||
803 | } | ||
798 | EXPORT_SYMBOL_GPL(nfs_file_set_open_context); | 804 | EXPORT_SYMBOL_GPL(nfs_file_set_open_context); |
799 | 805 | ||
800 | /* | 806 | /* |
@@ -820,10 +826,11 @@ struct nfs_open_context *nfs_find_open_context(struct inode *inode, struct rpc_c | |||
820 | 826 | ||
821 | static void nfs_file_clear_open_context(struct file *filp) | 827 | static void nfs_file_clear_open_context(struct file *filp) |
822 | { | 828 | { |
823 | struct inode *inode = file_inode(filp); | ||
824 | struct nfs_open_context *ctx = nfs_file_open_context(filp); | 829 | struct nfs_open_context *ctx = nfs_file_open_context(filp); |
825 | 830 | ||
826 | if (ctx) { | 831 | if (ctx) { |
832 | struct inode *inode = ctx->dentry->d_inode; | ||
833 | |||
827 | filp->private_data = NULL; | 834 | filp->private_data = NULL; |
828 | spin_lock(&inode->i_lock); | 835 | spin_lock(&inode->i_lock); |
829 | list_move_tail(&ctx->list, &NFS_I(inode)->open_files); | 836 | list_move_tail(&ctx->list, &NFS_I(inode)->open_files); |
@@ -1723,12 +1730,11 @@ EXPORT_SYMBOL_GPL(nfs_net_id); | |||
1723 | static int nfs_net_init(struct net *net) | 1730 | static int nfs_net_init(struct net *net) |
1724 | { | 1731 | { |
1725 | nfs_clients_init(net); | 1732 | nfs_clients_init(net); |
1726 | return nfs_dns_resolver_cache_init(net); | 1733 | return 0; |
1727 | } | 1734 | } |
1728 | 1735 | ||
1729 | static void nfs_net_exit(struct net *net) | 1736 | static void nfs_net_exit(struct net *net) |
1730 | { | 1737 | { |
1731 | nfs_dns_resolver_cache_destroy(net); | ||
1732 | nfs_cleanup_cb_ident_idr(net); | 1738 | nfs_cleanup_cb_ident_idr(net); |
1733 | } | 1739 | } |
1734 | 1740 | ||
@@ -1746,10 +1752,6 @@ static int __init init_nfs_fs(void) | |||
1746 | { | 1752 | { |
1747 | int err; | 1753 | int err; |
1748 | 1754 | ||
1749 | err = nfs_dns_resolver_init(); | ||
1750 | if (err < 0) | ||
1751 | goto out10;; | ||
1752 | |||
1753 | err = register_pernet_subsys(&nfs_net_ops); | 1755 | err = register_pernet_subsys(&nfs_net_ops); |
1754 | if (err < 0) | 1756 | if (err < 0) |
1755 | goto out9; | 1757 | goto out9; |
@@ -1815,8 +1817,6 @@ out7: | |||
1815 | out8: | 1817 | out8: |
1816 | unregister_pernet_subsys(&nfs_net_ops); | 1818 | unregister_pernet_subsys(&nfs_net_ops); |
1817 | out9: | 1819 | out9: |
1818 | nfs_dns_resolver_destroy(); | ||
1819 | out10: | ||
1820 | return err; | 1820 | return err; |
1821 | } | 1821 | } |
1822 | 1822 | ||
@@ -1829,7 +1829,6 @@ static void __exit exit_nfs_fs(void) | |||
1829 | nfs_destroy_nfspagecache(); | 1829 | nfs_destroy_nfspagecache(); |
1830 | nfs_fscache_unregister(); | 1830 | nfs_fscache_unregister(); |
1831 | unregister_pernet_subsys(&nfs_net_ops); | 1831 | unregister_pernet_subsys(&nfs_net_ops); |
1832 | nfs_dns_resolver_destroy(); | ||
1833 | #ifdef CONFIG_PROC_FS | 1832 | #ifdef CONFIG_PROC_FS |
1834 | rpc_proc_unregister(&init_net, "nfs"); | 1833 | rpc_proc_unregister(&init_net, "nfs"); |
1835 | #endif | 1834 | #endif |
diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h index 97ec2ef6a220..3c8373f90ab3 100644 --- a/fs/nfs/internal.h +++ b/fs/nfs/internal.h | |||
@@ -255,6 +255,7 @@ extern int nfs4_decode_dirent(struct xdr_stream *, | |||
255 | #ifdef CONFIG_NFS_V4_1 | 255 | #ifdef CONFIG_NFS_V4_1 |
256 | extern const u32 nfs41_maxread_overhead; | 256 | extern const u32 nfs41_maxread_overhead; |
257 | extern const u32 nfs41_maxwrite_overhead; | 257 | extern const u32 nfs41_maxwrite_overhead; |
258 | extern const u32 nfs41_maxgetdevinfo_overhead; | ||
258 | #endif | 259 | #endif |
259 | 260 | ||
260 | /* nfs4proc.c */ | 261 | /* nfs4proc.c */ |
diff --git a/fs/nfs/mount_clnt.c b/fs/nfs/mount_clnt.c index 91a6faf811ac..99a45283b9ee 100644 --- a/fs/nfs/mount_clnt.c +++ b/fs/nfs/mount_clnt.c | |||
@@ -139,7 +139,10 @@ struct mnt_fhstatus { | |||
139 | * nfs_mount - Obtain an NFS file handle for the given host and path | 139 | * nfs_mount - Obtain an NFS file handle for the given host and path |
140 | * @info: pointer to mount request arguments | 140 | * @info: pointer to mount request arguments |
141 | * | 141 | * |
142 | * Uses default timeout parameters specified by underlying transport. | 142 | * Uses default timeout parameters specified by underlying transport. On |
143 | * successful return, the auth_flavs list and auth_flav_len will be populated | ||
144 | * with the list from the server or a faked-up list if the server didn't | ||
145 | * provide one. | ||
143 | */ | 146 | */ |
144 | int nfs_mount(struct nfs_mount_request *info) | 147 | int nfs_mount(struct nfs_mount_request *info) |
145 | { | 148 | { |
@@ -195,6 +198,15 @@ int nfs_mount(struct nfs_mount_request *info) | |||
195 | dprintk("NFS: MNT request succeeded\n"); | 198 | dprintk("NFS: MNT request succeeded\n"); |
196 | status = 0; | 199 | status = 0; |
197 | 200 | ||
201 | /* | ||
202 | * If the server didn't provide a flavor list, allow the | ||
203 | * client to try any flavor. | ||
204 | */ | ||
205 | if (info->version != NFS_MNT3_VERSION || *info->auth_flav_len == 0) { | ||
206 | dprintk("NFS: Faking up auth_flavs list\n"); | ||
207 | info->auth_flavs[0] = RPC_AUTH_NULL; | ||
208 | *info->auth_flav_len = 1; | ||
209 | } | ||
198 | out: | 210 | out: |
199 | return status; | 211 | return status; |
200 | 212 | ||
diff --git a/fs/nfs/nfs4_fs.h b/fs/nfs/nfs4_fs.h index 283fd284bdb8..ee81e354bce7 100644 --- a/fs/nfs/nfs4_fs.h +++ b/fs/nfs/nfs4_fs.h | |||
@@ -194,7 +194,7 @@ struct nfs4_state_recovery_ops { | |||
194 | int (*recover_lock)(struct nfs4_state *, struct file_lock *); | 194 | int (*recover_lock)(struct nfs4_state *, struct file_lock *); |
195 | int (*establish_clid)(struct nfs_client *, struct rpc_cred *); | 195 | int (*establish_clid)(struct nfs_client *, struct rpc_cred *); |
196 | struct rpc_cred * (*get_clid_cred)(struct nfs_client *); | 196 | struct rpc_cred * (*get_clid_cred)(struct nfs_client *); |
197 | int (*reclaim_complete)(struct nfs_client *); | 197 | int (*reclaim_complete)(struct nfs_client *, struct rpc_cred *); |
198 | int (*detect_trunking)(struct nfs_client *, struct nfs_client **, | 198 | int (*detect_trunking)(struct nfs_client *, struct nfs_client **, |
199 | struct rpc_cred *); | 199 | struct rpc_cred *); |
200 | }; | 200 | }; |
diff --git a/fs/nfs/nfs4client.c b/fs/nfs/nfs4client.c index 18191919cc0b..90dce91dd5b5 100644 --- a/fs/nfs/nfs4client.c +++ b/fs/nfs/nfs4client.c | |||
@@ -208,7 +208,7 @@ struct nfs_client *nfs4_init_client(struct nfs_client *clp, | |||
208 | __set_bit(NFS_CS_DISCRTRY, &clp->cl_flags); | 208 | __set_bit(NFS_CS_DISCRTRY, &clp->cl_flags); |
209 | error = nfs_create_rpc_client(clp, timeparms, RPC_AUTH_GSS_KRB5I); | 209 | error = nfs_create_rpc_client(clp, timeparms, RPC_AUTH_GSS_KRB5I); |
210 | if (error == -EINVAL) | 210 | if (error == -EINVAL) |
211 | error = nfs_create_rpc_client(clp, timeparms, RPC_AUTH_NULL); | 211 | error = nfs_create_rpc_client(clp, timeparms, RPC_AUTH_UNIX); |
212 | if (error < 0) | 212 | if (error < 0) |
213 | goto error; | 213 | goto error; |
214 | 214 | ||
@@ -631,6 +631,8 @@ static int nfs4_set_client(struct nfs_server *server, | |||
631 | 631 | ||
632 | if (server->flags & NFS_MOUNT_NORESVPORT) | 632 | if (server->flags & NFS_MOUNT_NORESVPORT) |
633 | set_bit(NFS_CS_NORESVPORT, &cl_init.init_flags); | 633 | set_bit(NFS_CS_NORESVPORT, &cl_init.init_flags); |
634 | if (server->options & NFS_OPTION_MIGRATION) | ||
635 | set_bit(NFS_CS_MIGRATION, &cl_init.init_flags); | ||
634 | 636 | ||
635 | /* Allocate or find a client reference we can use */ | 637 | /* Allocate or find a client reference we can use */ |
636 | clp = nfs_get_client(&cl_init, timeparms, ip_addr, authflavour); | 638 | clp = nfs_get_client(&cl_init, timeparms, ip_addr, authflavour); |
@@ -735,7 +737,7 @@ static int nfs4_server_common_setup(struct nfs_server *server, | |||
735 | return -ENOMEM; | 737 | return -ENOMEM; |
736 | 738 | ||
737 | /* We must ensure the session is initialised first */ | 739 | /* We must ensure the session is initialised first */ |
738 | error = nfs4_init_session(server); | 740 | error = nfs4_init_session(server->nfs_client); |
739 | if (error < 0) | 741 | if (error < 0) |
740 | goto out; | 742 | goto out; |
741 | 743 | ||
diff --git a/fs/nfs/nfs4file.c b/fs/nfs/nfs4file.c index 13e6bb3e3fe5..e5b804dd944c 100644 --- a/fs/nfs/nfs4file.c +++ b/fs/nfs/nfs4file.c | |||
@@ -69,7 +69,6 @@ nfs4_file_open(struct inode *inode, struct file *filp) | |||
69 | goto out_drop; | 69 | goto out_drop; |
70 | } | 70 | } |
71 | } | 71 | } |
72 | iput(inode); | ||
73 | if (inode != dentry->d_inode) | 72 | if (inode != dentry->d_inode) |
74 | goto out_drop; | 73 | goto out_drop; |
75 | 74 | ||
diff --git a/fs/nfs/nfs4filelayout.c b/fs/nfs/nfs4filelayout.c index 22d10623f5ee..17ed87ef9de8 100644 --- a/fs/nfs/nfs4filelayout.c +++ b/fs/nfs/nfs4filelayout.c | |||
@@ -643,7 +643,8 @@ filelayout_check_layout(struct pnfs_layout_hdr *lo, | |||
643 | d = nfs4_find_get_deviceid(NFS_SERVER(lo->plh_inode)->pnfs_curr_ld, | 643 | d = nfs4_find_get_deviceid(NFS_SERVER(lo->plh_inode)->pnfs_curr_ld, |
644 | NFS_SERVER(lo->plh_inode)->nfs_client, id); | 644 | NFS_SERVER(lo->plh_inode)->nfs_client, id); |
645 | if (d == NULL) { | 645 | if (d == NULL) { |
646 | dsaddr = filelayout_get_device_info(lo->plh_inode, id, gfp_flags); | 646 | dsaddr = filelayout_get_device_info(lo->plh_inode, id, |
647 | lo->plh_lc_cred, gfp_flags); | ||
647 | if (dsaddr == NULL) | 648 | if (dsaddr == NULL) |
648 | goto out; | 649 | goto out; |
649 | } else | 650 | } else |
diff --git a/fs/nfs/nfs4filelayout.h b/fs/nfs/nfs4filelayout.h index 235ff952d3c8..cebd20e7e923 100644 --- a/fs/nfs/nfs4filelayout.h +++ b/fs/nfs/nfs4filelayout.h | |||
@@ -150,6 +150,7 @@ struct nfs4_pnfs_ds *nfs4_fl_prepare_ds(struct pnfs_layout_segment *lseg, | |||
150 | extern void nfs4_fl_put_deviceid(struct nfs4_file_layout_dsaddr *dsaddr); | 150 | extern void nfs4_fl_put_deviceid(struct nfs4_file_layout_dsaddr *dsaddr); |
151 | extern void nfs4_fl_free_deviceid(struct nfs4_file_layout_dsaddr *dsaddr); | 151 | extern void nfs4_fl_free_deviceid(struct nfs4_file_layout_dsaddr *dsaddr); |
152 | struct nfs4_file_layout_dsaddr * | 152 | struct nfs4_file_layout_dsaddr * |
153 | filelayout_get_device_info(struct inode *inode, struct nfs4_deviceid *dev_id, gfp_t gfp_flags); | 153 | filelayout_get_device_info(struct inode *inode, struct nfs4_deviceid *dev_id, |
154 | struct rpc_cred *cred, gfp_t gfp_flags); | ||
154 | 155 | ||
155 | #endif /* FS_NFS_NFS4FILELAYOUT_H */ | 156 | #endif /* FS_NFS_NFS4FILELAYOUT_H */ |
diff --git a/fs/nfs/nfs4filelayoutdev.c b/fs/nfs/nfs4filelayoutdev.c index 661a0f611215..95604f64cab8 100644 --- a/fs/nfs/nfs4filelayoutdev.c +++ b/fs/nfs/nfs4filelayoutdev.c | |||
@@ -668,7 +668,10 @@ decode_and_add_device(struct inode *inode, struct pnfs_device *dev, gfp_t gfp_fl | |||
668 | * of available devices, and return it. | 668 | * of available devices, and return it. |
669 | */ | 669 | */ |
670 | struct nfs4_file_layout_dsaddr * | 670 | struct nfs4_file_layout_dsaddr * |
671 | filelayout_get_device_info(struct inode *inode, struct nfs4_deviceid *dev_id, gfp_t gfp_flags) | 671 | filelayout_get_device_info(struct inode *inode, |
672 | struct nfs4_deviceid *dev_id, | ||
673 | struct rpc_cred *cred, | ||
674 | gfp_t gfp_flags) | ||
672 | { | 675 | { |
673 | struct pnfs_device *pdev = NULL; | 676 | struct pnfs_device *pdev = NULL; |
674 | u32 max_resp_sz; | 677 | u32 max_resp_sz; |
@@ -708,8 +711,9 @@ filelayout_get_device_info(struct inode *inode, struct nfs4_deviceid *dev_id, gf | |||
708 | pdev->pgbase = 0; | 711 | pdev->pgbase = 0; |
709 | pdev->pglen = max_resp_sz; | 712 | pdev->pglen = max_resp_sz; |
710 | pdev->mincount = 0; | 713 | pdev->mincount = 0; |
714 | pdev->maxcount = max_resp_sz - nfs41_maxgetdevinfo_overhead; | ||
711 | 715 | ||
712 | rc = nfs4_proc_getdeviceinfo(server, pdev); | 716 | rc = nfs4_proc_getdeviceinfo(server, pdev, cred); |
713 | dprintk("%s getdevice info returns %d\n", __func__, rc); | 717 | dprintk("%s getdevice info returns %d\n", __func__, rc); |
714 | if (rc) | 718 | if (rc) |
715 | goto out_free; | 719 | goto out_free; |
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index c0d3123b6eba..d95616f140ad 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c | |||
@@ -84,8 +84,10 @@ static int nfs4_do_setattr(struct inode *inode, struct rpc_cred *cred, | |||
84 | struct nfs4_state *state, struct nfs4_label *ilabel, | 84 | struct nfs4_state *state, struct nfs4_label *ilabel, |
85 | struct nfs4_label *olabel); | 85 | struct nfs4_label *olabel); |
86 | #ifdef CONFIG_NFS_V4_1 | 86 | #ifdef CONFIG_NFS_V4_1 |
87 | static int nfs41_test_stateid(struct nfs_server *, nfs4_stateid *); | 87 | static int nfs41_test_stateid(struct nfs_server *, nfs4_stateid *, |
88 | static int nfs41_free_stateid(struct nfs_server *, nfs4_stateid *); | 88 | struct rpc_cred *); |
89 | static int nfs41_free_stateid(struct nfs_server *, nfs4_stateid *, | ||
90 | struct rpc_cred *); | ||
89 | #endif | 91 | #endif |
90 | 92 | ||
91 | #ifdef CONFIG_NFS_V4_SECURITY_LABEL | 93 | #ifdef CONFIG_NFS_V4_SECURITY_LABEL |
@@ -626,7 +628,7 @@ int nfs41_setup_sequence(struct nfs4_session *session, | |||
626 | task->tk_timeout = 0; | 628 | task->tk_timeout = 0; |
627 | 629 | ||
628 | spin_lock(&tbl->slot_tbl_lock); | 630 | spin_lock(&tbl->slot_tbl_lock); |
629 | if (test_bit(NFS4_SESSION_DRAINING, &session->session_state) && | 631 | if (test_bit(NFS4_SLOT_TBL_DRAINING, &tbl->slot_tbl_state) && |
630 | !args->sa_privileged) { | 632 | !args->sa_privileged) { |
631 | /* The state manager will wait until the slot table is empty */ | 633 | /* The state manager will wait until the slot table is empty */ |
632 | dprintk("%s session is draining\n", __func__); | 634 | dprintk("%s session is draining\n", __func__); |
@@ -1147,7 +1149,7 @@ static struct nfs4_state *nfs4_try_open_cached(struct nfs4_opendata *opendata) | |||
1147 | struct nfs4_state *state = opendata->state; | 1149 | struct nfs4_state *state = opendata->state; |
1148 | struct nfs_inode *nfsi = NFS_I(state->inode); | 1150 | struct nfs_inode *nfsi = NFS_I(state->inode); |
1149 | struct nfs_delegation *delegation; | 1151 | struct nfs_delegation *delegation; |
1150 | int open_mode = opendata->o_arg.open_flags & (O_EXCL|O_TRUNC); | 1152 | int open_mode = opendata->o_arg.open_flags; |
1151 | fmode_t fmode = opendata->o_arg.fmode; | 1153 | fmode_t fmode = opendata->o_arg.fmode; |
1152 | nfs4_stateid stateid; | 1154 | nfs4_stateid stateid; |
1153 | int ret = -EAGAIN; | 1155 | int ret = -EAGAIN; |
@@ -1926,18 +1928,30 @@ static void nfs41_clear_delegation_stateid(struct nfs4_state *state) | |||
1926 | { | 1928 | { |
1927 | struct nfs_server *server = NFS_SERVER(state->inode); | 1929 | struct nfs_server *server = NFS_SERVER(state->inode); |
1928 | nfs4_stateid *stateid = &state->stateid; | 1930 | nfs4_stateid *stateid = &state->stateid; |
1929 | int status; | 1931 | struct nfs_delegation *delegation; |
1932 | struct rpc_cred *cred = NULL; | ||
1933 | int status = -NFS4ERR_BAD_STATEID; | ||
1930 | 1934 | ||
1931 | /* If a state reset has been done, test_stateid is unneeded */ | 1935 | /* If a state reset has been done, test_stateid is unneeded */ |
1932 | if (test_bit(NFS_DELEGATED_STATE, &state->flags) == 0) | 1936 | if (test_bit(NFS_DELEGATED_STATE, &state->flags) == 0) |
1933 | return; | 1937 | return; |
1934 | 1938 | ||
1935 | status = nfs41_test_stateid(server, stateid); | 1939 | /* Get the delegation credential for use by test/free_stateid */ |
1940 | rcu_read_lock(); | ||
1941 | delegation = rcu_dereference(NFS_I(state->inode)->delegation); | ||
1942 | if (delegation != NULL && | ||
1943 | nfs4_stateid_match(&delegation->stateid, stateid)) { | ||
1944 | cred = get_rpccred(delegation->cred); | ||
1945 | rcu_read_unlock(); | ||
1946 | status = nfs41_test_stateid(server, stateid, cred); | ||
1947 | } else | ||
1948 | rcu_read_unlock(); | ||
1949 | |||
1936 | if (status != NFS_OK) { | 1950 | if (status != NFS_OK) { |
1937 | /* Free the stateid unless the server explicitly | 1951 | /* Free the stateid unless the server explicitly |
1938 | * informs us the stateid is unrecognized. */ | 1952 | * informs us the stateid is unrecognized. */ |
1939 | if (status != -NFS4ERR_BAD_STATEID) | 1953 | if (status != -NFS4ERR_BAD_STATEID) |
1940 | nfs41_free_stateid(server, stateid); | 1954 | nfs41_free_stateid(server, stateid, cred); |
1941 | nfs_remove_bad_delegation(state->inode); | 1955 | nfs_remove_bad_delegation(state->inode); |
1942 | 1956 | ||
1943 | write_seqlock(&state->seqlock); | 1957 | write_seqlock(&state->seqlock); |
@@ -1945,6 +1959,9 @@ static void nfs41_clear_delegation_stateid(struct nfs4_state *state) | |||
1945 | write_sequnlock(&state->seqlock); | 1959 | write_sequnlock(&state->seqlock); |
1946 | clear_bit(NFS_DELEGATED_STATE, &state->flags); | 1960 | clear_bit(NFS_DELEGATED_STATE, &state->flags); |
1947 | } | 1961 | } |
1962 | |||
1963 | if (cred != NULL) | ||
1964 | put_rpccred(cred); | ||
1948 | } | 1965 | } |
1949 | 1966 | ||
1950 | /** | 1967 | /** |
@@ -1959,6 +1976,7 @@ static int nfs41_check_open_stateid(struct nfs4_state *state) | |||
1959 | { | 1976 | { |
1960 | struct nfs_server *server = NFS_SERVER(state->inode); | 1977 | struct nfs_server *server = NFS_SERVER(state->inode); |
1961 | nfs4_stateid *stateid = &state->open_stateid; | 1978 | nfs4_stateid *stateid = &state->open_stateid; |
1979 | struct rpc_cred *cred = state->owner->so_cred; | ||
1962 | int status; | 1980 | int status; |
1963 | 1981 | ||
1964 | /* If a state reset has been done, test_stateid is unneeded */ | 1982 | /* If a state reset has been done, test_stateid is unneeded */ |
@@ -1967,12 +1985,12 @@ static int nfs41_check_open_stateid(struct nfs4_state *state) | |||
1967 | (test_bit(NFS_O_RDWR_STATE, &state->flags) == 0)) | 1985 | (test_bit(NFS_O_RDWR_STATE, &state->flags) == 0)) |
1968 | return -NFS4ERR_BAD_STATEID; | 1986 | return -NFS4ERR_BAD_STATEID; |
1969 | 1987 | ||
1970 | status = nfs41_test_stateid(server, stateid); | 1988 | status = nfs41_test_stateid(server, stateid, cred); |
1971 | if (status != NFS_OK) { | 1989 | if (status != NFS_OK) { |
1972 | /* Free the stateid unless the server explicitly | 1990 | /* Free the stateid unless the server explicitly |
1973 | * informs us the stateid is unrecognized. */ | 1991 | * informs us the stateid is unrecognized. */ |
1974 | if (status != -NFS4ERR_BAD_STATEID) | 1992 | if (status != -NFS4ERR_BAD_STATEID) |
1975 | nfs41_free_stateid(server, stateid); | 1993 | nfs41_free_stateid(server, stateid, cred); |
1976 | 1994 | ||
1977 | clear_bit(NFS_O_RDONLY_STATE, &state->flags); | 1995 | clear_bit(NFS_O_RDONLY_STATE, &state->flags); |
1978 | clear_bit(NFS_O_WRONLY_STATE, &state->flags); | 1996 | clear_bit(NFS_O_WRONLY_STATE, &state->flags); |
@@ -2013,10 +2031,11 @@ static inline void nfs4_exclusive_attrset(struct nfs4_opendata *opendata, struct | |||
2013 | static int _nfs4_open_and_get_state(struct nfs4_opendata *opendata, | 2031 | static int _nfs4_open_and_get_state(struct nfs4_opendata *opendata, |
2014 | fmode_t fmode, | 2032 | fmode_t fmode, |
2015 | int flags, | 2033 | int flags, |
2016 | struct nfs4_state **res) | 2034 | struct nfs_open_context *ctx) |
2017 | { | 2035 | { |
2018 | struct nfs4_state_owner *sp = opendata->owner; | 2036 | struct nfs4_state_owner *sp = opendata->owner; |
2019 | struct nfs_server *server = sp->so_server; | 2037 | struct nfs_server *server = sp->so_server; |
2038 | struct dentry *dentry; | ||
2020 | struct nfs4_state *state; | 2039 | struct nfs4_state *state; |
2021 | unsigned int seq; | 2040 | unsigned int seq; |
2022 | int ret; | 2041 | int ret; |
@@ -2034,13 +2053,31 @@ static int _nfs4_open_and_get_state(struct nfs4_opendata *opendata, | |||
2034 | if (server->caps & NFS_CAP_POSIX_LOCK) | 2053 | if (server->caps & NFS_CAP_POSIX_LOCK) |
2035 | set_bit(NFS_STATE_POSIX_LOCKS, &state->flags); | 2054 | set_bit(NFS_STATE_POSIX_LOCKS, &state->flags); |
2036 | 2055 | ||
2056 | dentry = opendata->dentry; | ||
2057 | if (dentry->d_inode == NULL) { | ||
2058 | /* FIXME: Is this d_drop() ever needed? */ | ||
2059 | d_drop(dentry); | ||
2060 | dentry = d_add_unique(dentry, igrab(state->inode)); | ||
2061 | if (dentry == NULL) { | ||
2062 | dentry = opendata->dentry; | ||
2063 | } else if (dentry != ctx->dentry) { | ||
2064 | dput(ctx->dentry); | ||
2065 | ctx->dentry = dget(dentry); | ||
2066 | } | ||
2067 | nfs_set_verifier(dentry, | ||
2068 | nfs_save_change_attribute(opendata->dir->d_inode)); | ||
2069 | } | ||
2070 | |||
2037 | ret = nfs4_opendata_access(sp->so_cred, opendata, state, fmode, flags); | 2071 | ret = nfs4_opendata_access(sp->so_cred, opendata, state, fmode, flags); |
2038 | if (ret != 0) | 2072 | if (ret != 0) |
2039 | goto out; | 2073 | goto out; |
2040 | 2074 | ||
2041 | if (read_seqcount_retry(&sp->so_reclaim_seqcount, seq)) | 2075 | ctx->state = state; |
2042 | nfs4_schedule_stateid_recovery(server, state); | 2076 | if (dentry->d_inode == state->inode) { |
2043 | *res = state; | 2077 | nfs_inode_attach_open_context(ctx); |
2078 | if (read_seqcount_retry(&sp->so_reclaim_seqcount, seq)) | ||
2079 | nfs4_schedule_stateid_recovery(server, state); | ||
2080 | } | ||
2044 | out: | 2081 | out: |
2045 | return ret; | 2082 | return ret; |
2046 | } | 2083 | } |
@@ -2049,19 +2086,19 @@ out: | |||
2049 | * Returns a referenced nfs4_state | 2086 | * Returns a referenced nfs4_state |
2050 | */ | 2087 | */ |
2051 | static int _nfs4_do_open(struct inode *dir, | 2088 | static int _nfs4_do_open(struct inode *dir, |
2052 | struct dentry *dentry, | 2089 | struct nfs_open_context *ctx, |
2053 | fmode_t fmode, | ||
2054 | int flags, | 2090 | int flags, |
2055 | struct iattr *sattr, | 2091 | struct iattr *sattr, |
2056 | struct nfs4_label *label, | 2092 | struct nfs4_label *label) |
2057 | struct rpc_cred *cred, | ||
2058 | struct nfs4_state **res, | ||
2059 | struct nfs4_threshold **ctx_th) | ||
2060 | { | 2093 | { |
2061 | struct nfs4_state_owner *sp; | 2094 | struct nfs4_state_owner *sp; |
2062 | struct nfs4_state *state = NULL; | 2095 | struct nfs4_state *state = NULL; |
2063 | struct nfs_server *server = NFS_SERVER(dir); | 2096 | struct nfs_server *server = NFS_SERVER(dir); |
2064 | struct nfs4_opendata *opendata; | 2097 | struct nfs4_opendata *opendata; |
2098 | struct dentry *dentry = ctx->dentry; | ||
2099 | struct rpc_cred *cred = ctx->cred; | ||
2100 | struct nfs4_threshold **ctx_th = &ctx->mdsthreshold; | ||
2101 | fmode_t fmode = ctx->mode & (FMODE_READ|FMODE_WRITE|FMODE_EXEC); | ||
2065 | enum open_claim_type4 claim = NFS4_OPEN_CLAIM_NULL; | 2102 | enum open_claim_type4 claim = NFS4_OPEN_CLAIM_NULL; |
2066 | struct nfs4_label *olabel = NULL; | 2103 | struct nfs4_label *olabel = NULL; |
2067 | int status; | 2104 | int status; |
@@ -2103,9 +2140,10 @@ static int _nfs4_do_open(struct inode *dir, | |||
2103 | if (dentry->d_inode != NULL) | 2140 | if (dentry->d_inode != NULL) |
2104 | opendata->state = nfs4_get_open_state(dentry->d_inode, sp); | 2141 | opendata->state = nfs4_get_open_state(dentry->d_inode, sp); |
2105 | 2142 | ||
2106 | status = _nfs4_open_and_get_state(opendata, fmode, flags, &state); | 2143 | status = _nfs4_open_and_get_state(opendata, fmode, flags, ctx); |
2107 | if (status != 0) | 2144 | if (status != 0) |
2108 | goto err_free_label; | 2145 | goto err_free_label; |
2146 | state = ctx->state; | ||
2109 | 2147 | ||
2110 | if ((opendata->o_arg.open_flags & O_EXCL) && | 2148 | if ((opendata->o_arg.open_flags & O_EXCL) && |
2111 | (opendata->o_arg.createmode != NFS4_CREATE_GUARDED)) { | 2149 | (opendata->o_arg.createmode != NFS4_CREATE_GUARDED)) { |
@@ -2132,7 +2170,6 @@ static int _nfs4_do_open(struct inode *dir, | |||
2132 | 2170 | ||
2133 | nfs4_opendata_put(opendata); | 2171 | nfs4_opendata_put(opendata); |
2134 | nfs4_put_state_owner(sp); | 2172 | nfs4_put_state_owner(sp); |
2135 | *res = state; | ||
2136 | return 0; | 2173 | return 0; |
2137 | err_free_label: | 2174 | err_free_label: |
2138 | nfs4_label_free(olabel); | 2175 | nfs4_label_free(olabel); |
@@ -2142,29 +2179,24 @@ err_opendata_put: | |||
2142 | err_put_state_owner: | 2179 | err_put_state_owner: |
2143 | nfs4_put_state_owner(sp); | 2180 | nfs4_put_state_owner(sp); |
2144 | out_err: | 2181 | out_err: |
2145 | *res = NULL; | ||
2146 | return status; | 2182 | return status; |
2147 | } | 2183 | } |
2148 | 2184 | ||
2149 | 2185 | ||
2150 | static struct nfs4_state *nfs4_do_open(struct inode *dir, | 2186 | static struct nfs4_state *nfs4_do_open(struct inode *dir, |
2151 | struct dentry *dentry, | 2187 | struct nfs_open_context *ctx, |
2152 | fmode_t fmode, | ||
2153 | int flags, | 2188 | int flags, |
2154 | struct iattr *sattr, | 2189 | struct iattr *sattr, |
2155 | struct nfs4_label *label, | 2190 | struct nfs4_label *label) |
2156 | struct rpc_cred *cred, | ||
2157 | struct nfs4_threshold **ctx_th) | ||
2158 | { | 2191 | { |
2159 | struct nfs_server *server = NFS_SERVER(dir); | 2192 | struct nfs_server *server = NFS_SERVER(dir); |
2160 | struct nfs4_exception exception = { }; | 2193 | struct nfs4_exception exception = { }; |
2161 | struct nfs4_state *res; | 2194 | struct nfs4_state *res; |
2162 | int status; | 2195 | int status; |
2163 | 2196 | ||
2164 | fmode &= FMODE_READ|FMODE_WRITE|FMODE_EXEC; | ||
2165 | do { | 2197 | do { |
2166 | status = _nfs4_do_open(dir, dentry, fmode, flags, sattr, label, cred, | 2198 | status = _nfs4_do_open(dir, ctx, flags, sattr, label); |
2167 | &res, ctx_th); | 2199 | res = ctx->state; |
2168 | if (status == 0) | 2200 | if (status == 0) |
2169 | break; | 2201 | break; |
2170 | /* NOTE: BAD_SEQID means the server and client disagree about the | 2202 | /* NOTE: BAD_SEQID means the server and client disagree about the |
@@ -2527,15 +2559,13 @@ nfs4_atomic_open(struct inode *dir, struct nfs_open_context *ctx, int open_flags | |||
2527 | label = nfs4_label_init_security(dir, ctx->dentry, attr, &l); | 2559 | label = nfs4_label_init_security(dir, ctx->dentry, attr, &l); |
2528 | 2560 | ||
2529 | /* Protect against concurrent sillydeletes */ | 2561 | /* Protect against concurrent sillydeletes */ |
2530 | state = nfs4_do_open(dir, ctx->dentry, ctx->mode, open_flags, attr, label, | 2562 | state = nfs4_do_open(dir, ctx, open_flags, attr, label); |
2531 | ctx->cred, &ctx->mdsthreshold); | ||
2532 | 2563 | ||
2533 | nfs4_label_release_security(label); | 2564 | nfs4_label_release_security(label); |
2534 | 2565 | ||
2535 | if (IS_ERR(state)) | 2566 | if (IS_ERR(state)) |
2536 | return ERR_CAST(state); | 2567 | return ERR_CAST(state); |
2537 | ctx->state = state; | 2568 | return state->inode; |
2538 | return igrab(state->inode); | ||
2539 | } | 2569 | } |
2540 | 2570 | ||
2541 | static void nfs4_close_context(struct nfs_open_context *ctx, int is_sync) | 2571 | static void nfs4_close_context(struct nfs_open_context *ctx, int is_sync) |
@@ -3186,17 +3216,11 @@ nfs4_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr, | |||
3186 | ilabel = nfs4_label_init_security(dir, dentry, sattr, &l); | 3216 | ilabel = nfs4_label_init_security(dir, dentry, sattr, &l); |
3187 | 3217 | ||
3188 | sattr->ia_mode &= ~current_umask(); | 3218 | sattr->ia_mode &= ~current_umask(); |
3189 | state = nfs4_do_open(dir, dentry, ctx->mode, | 3219 | state = nfs4_do_open(dir, ctx, flags, sattr, ilabel); |
3190 | flags, sattr, ilabel, ctx->cred, | ||
3191 | &ctx->mdsthreshold); | ||
3192 | d_drop(dentry); | ||
3193 | if (IS_ERR(state)) { | 3220 | if (IS_ERR(state)) { |
3194 | status = PTR_ERR(state); | 3221 | status = PTR_ERR(state); |
3195 | goto out; | 3222 | goto out; |
3196 | } | 3223 | } |
3197 | d_add(dentry, igrab(state->inode)); | ||
3198 | nfs_set_verifier(dentry, nfs_save_change_attribute(dir)); | ||
3199 | ctx->state = state; | ||
3200 | out: | 3224 | out: |
3201 | nfs4_label_release_security(ilabel); | 3225 | nfs4_label_release_security(ilabel); |
3202 | put_nfs_open_context(ctx); | 3226 | put_nfs_open_context(ctx); |
@@ -4690,7 +4714,7 @@ int nfs4_proc_setclientid(struct nfs_client *clp, u32 program, | |||
4690 | /* cb_client4 */ | 4714 | /* cb_client4 */ |
4691 | rcu_read_lock(); | 4715 | rcu_read_lock(); |
4692 | setclientid.sc_netid_len = scnprintf(setclientid.sc_netid, | 4716 | setclientid.sc_netid_len = scnprintf(setclientid.sc_netid, |
4693 | sizeof(setclientid.sc_netid), | 4717 | sizeof(setclientid.sc_netid), "%s", |
4694 | rpc_peeraddr2str(clp->cl_rpcclient, | 4718 | rpc_peeraddr2str(clp->cl_rpcclient, |
4695 | RPC_DISPLAY_NETID)); | 4719 | RPC_DISPLAY_NETID)); |
4696 | rcu_read_unlock(); | 4720 | rcu_read_unlock(); |
@@ -5401,13 +5425,18 @@ static int nfs41_check_expired_locks(struct nfs4_state *state) | |||
5401 | 5425 | ||
5402 | list_for_each_entry(lsp, &state->lock_states, ls_locks) { | 5426 | list_for_each_entry(lsp, &state->lock_states, ls_locks) { |
5403 | if (test_bit(NFS_LOCK_INITIALIZED, &lsp->ls_flags)) { | 5427 | if (test_bit(NFS_LOCK_INITIALIZED, &lsp->ls_flags)) { |
5404 | status = nfs41_test_stateid(server, &lsp->ls_stateid); | 5428 | struct rpc_cred *cred = lsp->ls_state->owner->so_cred; |
5429 | |||
5430 | status = nfs41_test_stateid(server, | ||
5431 | &lsp->ls_stateid, | ||
5432 | cred); | ||
5405 | if (status != NFS_OK) { | 5433 | if (status != NFS_OK) { |
5406 | /* Free the stateid unless the server | 5434 | /* Free the stateid unless the server |
5407 | * informs us the stateid is unrecognized. */ | 5435 | * informs us the stateid is unrecognized. */ |
5408 | if (status != -NFS4ERR_BAD_STATEID) | 5436 | if (status != -NFS4ERR_BAD_STATEID) |
5409 | nfs41_free_stateid(server, | 5437 | nfs41_free_stateid(server, |
5410 | &lsp->ls_stateid); | 5438 | &lsp->ls_stateid, |
5439 | cred); | ||
5411 | clear_bit(NFS_LOCK_INITIALIZED, &lsp->ls_flags); | 5440 | clear_bit(NFS_LOCK_INITIALIZED, &lsp->ls_flags); |
5412 | ret = status; | 5441 | ret = status; |
5413 | } | 5442 | } |
@@ -5897,7 +5926,8 @@ int nfs4_proc_exchange_id(struct nfs_client *clp, struct rpc_cred *cred) | |||
5897 | struct nfs41_exchange_id_args args = { | 5926 | struct nfs41_exchange_id_args args = { |
5898 | .verifier = &verifier, | 5927 | .verifier = &verifier, |
5899 | .client = clp, | 5928 | .client = clp, |
5900 | .flags = EXCHGID4_FLAG_SUPP_MOVED_REFER, | 5929 | .flags = EXCHGID4_FLAG_SUPP_MOVED_REFER | |
5930 | EXCHGID4_FLAG_BIND_PRINC_STATEID, | ||
5901 | }; | 5931 | }; |
5902 | struct nfs41_exchange_id_res res = { | 5932 | struct nfs41_exchange_id_res res = { |
5903 | 0 | 5933 | 0 |
@@ -6154,17 +6184,14 @@ int nfs4_proc_get_lease_time(struct nfs_client *clp, struct nfs_fsinfo *fsinfo) | |||
6154 | */ | 6184 | */ |
6155 | static void nfs4_init_channel_attrs(struct nfs41_create_session_args *args) | 6185 | static void nfs4_init_channel_attrs(struct nfs41_create_session_args *args) |
6156 | { | 6186 | { |
6157 | struct nfs4_session *session = args->client->cl_session; | 6187 | unsigned int max_rqst_sz, max_resp_sz; |
6158 | unsigned int mxrqst_sz = session->fc_target_max_rqst_sz, | 6188 | |
6159 | mxresp_sz = session->fc_target_max_resp_sz; | 6189 | max_rqst_sz = NFS_MAX_FILE_IO_SIZE + nfs41_maxwrite_overhead; |
6190 | max_resp_sz = NFS_MAX_FILE_IO_SIZE + nfs41_maxread_overhead; | ||
6160 | 6191 | ||
6161 | if (mxrqst_sz == 0) | ||
6162 | mxrqst_sz = NFS_MAX_FILE_IO_SIZE; | ||
6163 | if (mxresp_sz == 0) | ||
6164 | mxresp_sz = NFS_MAX_FILE_IO_SIZE; | ||
6165 | /* Fore channel attributes */ | 6192 | /* Fore channel attributes */ |
6166 | args->fc_attrs.max_rqst_sz = mxrqst_sz; | 6193 | args->fc_attrs.max_rqst_sz = max_rqst_sz; |
6167 | args->fc_attrs.max_resp_sz = mxresp_sz; | 6194 | args->fc_attrs.max_resp_sz = max_resp_sz; |
6168 | args->fc_attrs.max_ops = NFS4_MAX_OPS; | 6195 | args->fc_attrs.max_ops = NFS4_MAX_OPS; |
6169 | args->fc_attrs.max_reqs = max_session_slots; | 6196 | args->fc_attrs.max_reqs = max_session_slots; |
6170 | 6197 | ||
@@ -6551,12 +6578,14 @@ static const struct rpc_call_ops nfs4_reclaim_complete_call_ops = { | |||
6551 | /* | 6578 | /* |
6552 | * Issue a global reclaim complete. | 6579 | * Issue a global reclaim complete. |
6553 | */ | 6580 | */ |
6554 | static int nfs41_proc_reclaim_complete(struct nfs_client *clp) | 6581 | static int nfs41_proc_reclaim_complete(struct nfs_client *clp, |
6582 | struct rpc_cred *cred) | ||
6555 | { | 6583 | { |
6556 | struct nfs4_reclaim_complete_data *calldata; | 6584 | struct nfs4_reclaim_complete_data *calldata; |
6557 | struct rpc_task *task; | 6585 | struct rpc_task *task; |
6558 | struct rpc_message msg = { | 6586 | struct rpc_message msg = { |
6559 | .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_RECLAIM_COMPLETE], | 6587 | .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_RECLAIM_COMPLETE], |
6588 | .rpc_cred = cred, | ||
6560 | }; | 6589 | }; |
6561 | struct rpc_task_setup task_setup_data = { | 6590 | struct rpc_task_setup task_setup_data = { |
6562 | .rpc_client = clp->cl_rpcclient, | 6591 | .rpc_client = clp->cl_rpcclient, |
@@ -6740,6 +6769,7 @@ nfs4_proc_layoutget(struct nfs4_layoutget *lgp, gfp_t gfp_flags) | |||
6740 | .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_LAYOUTGET], | 6769 | .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_LAYOUTGET], |
6741 | .rpc_argp = &lgp->args, | 6770 | .rpc_argp = &lgp->args, |
6742 | .rpc_resp = &lgp->res, | 6771 | .rpc_resp = &lgp->res, |
6772 | .rpc_cred = lgp->cred, | ||
6743 | }; | 6773 | }; |
6744 | struct rpc_task_setup task_setup_data = { | 6774 | struct rpc_task_setup task_setup_data = { |
6745 | .rpc_client = server->client, | 6775 | .rpc_client = server->client, |
@@ -6843,6 +6873,7 @@ int nfs4_proc_layoutreturn(struct nfs4_layoutreturn *lrp) | |||
6843 | .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_LAYOUTRETURN], | 6873 | .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_LAYOUTRETURN], |
6844 | .rpc_argp = &lrp->args, | 6874 | .rpc_argp = &lrp->args, |
6845 | .rpc_resp = &lrp->res, | 6875 | .rpc_resp = &lrp->res, |
6876 | .rpc_cred = lrp->cred, | ||
6846 | }; | 6877 | }; |
6847 | struct rpc_task_setup task_setup_data = { | 6878 | struct rpc_task_setup task_setup_data = { |
6848 | .rpc_client = lrp->clp->cl_rpcclient, | 6879 | .rpc_client = lrp->clp->cl_rpcclient, |
@@ -6912,7 +6943,9 @@ int nfs4_proc_getdevicelist(struct nfs_server *server, | |||
6912 | EXPORT_SYMBOL_GPL(nfs4_proc_getdevicelist); | 6943 | EXPORT_SYMBOL_GPL(nfs4_proc_getdevicelist); |
6913 | 6944 | ||
6914 | static int | 6945 | static int |
6915 | _nfs4_proc_getdeviceinfo(struct nfs_server *server, struct pnfs_device *pdev) | 6946 | _nfs4_proc_getdeviceinfo(struct nfs_server *server, |
6947 | struct pnfs_device *pdev, | ||
6948 | struct rpc_cred *cred) | ||
6916 | { | 6949 | { |
6917 | struct nfs4_getdeviceinfo_args args = { | 6950 | struct nfs4_getdeviceinfo_args args = { |
6918 | .pdev = pdev, | 6951 | .pdev = pdev, |
@@ -6924,6 +6957,7 @@ _nfs4_proc_getdeviceinfo(struct nfs_server *server, struct pnfs_device *pdev) | |||
6924 | .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_GETDEVICEINFO], | 6957 | .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_GETDEVICEINFO], |
6925 | .rpc_argp = &args, | 6958 | .rpc_argp = &args, |
6926 | .rpc_resp = &res, | 6959 | .rpc_resp = &res, |
6960 | .rpc_cred = cred, | ||
6927 | }; | 6961 | }; |
6928 | int status; | 6962 | int status; |
6929 | 6963 | ||
@@ -6934,14 +6968,16 @@ _nfs4_proc_getdeviceinfo(struct nfs_server *server, struct pnfs_device *pdev) | |||
6934 | return status; | 6968 | return status; |
6935 | } | 6969 | } |
6936 | 6970 | ||
6937 | int nfs4_proc_getdeviceinfo(struct nfs_server *server, struct pnfs_device *pdev) | 6971 | int nfs4_proc_getdeviceinfo(struct nfs_server *server, |
6972 | struct pnfs_device *pdev, | ||
6973 | struct rpc_cred *cred) | ||
6938 | { | 6974 | { |
6939 | struct nfs4_exception exception = { }; | 6975 | struct nfs4_exception exception = { }; |
6940 | int err; | 6976 | int err; |
6941 | 6977 | ||
6942 | do { | 6978 | do { |
6943 | err = nfs4_handle_exception(server, | 6979 | err = nfs4_handle_exception(server, |
6944 | _nfs4_proc_getdeviceinfo(server, pdev), | 6980 | _nfs4_proc_getdeviceinfo(server, pdev, cred), |
6945 | &exception); | 6981 | &exception); |
6946 | } while (exception.retry); | 6982 | } while (exception.retry); |
6947 | return err; | 6983 | return err; |
@@ -7125,7 +7161,9 @@ out: | |||
7125 | return err; | 7161 | return err; |
7126 | } | 7162 | } |
7127 | 7163 | ||
7128 | static int _nfs41_test_stateid(struct nfs_server *server, nfs4_stateid *stateid) | 7164 | static int _nfs41_test_stateid(struct nfs_server *server, |
7165 | nfs4_stateid *stateid, | ||
7166 | struct rpc_cred *cred) | ||
7129 | { | 7167 | { |
7130 | int status; | 7168 | int status; |
7131 | struct nfs41_test_stateid_args args = { | 7169 | struct nfs41_test_stateid_args args = { |
@@ -7136,6 +7174,7 @@ static int _nfs41_test_stateid(struct nfs_server *server, nfs4_stateid *stateid) | |||
7136 | .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_TEST_STATEID], | 7174 | .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_TEST_STATEID], |
7137 | .rpc_argp = &args, | 7175 | .rpc_argp = &args, |
7138 | .rpc_resp = &res, | 7176 | .rpc_resp = &res, |
7177 | .rpc_cred = cred, | ||
7139 | }; | 7178 | }; |
7140 | 7179 | ||
7141 | dprintk("NFS call test_stateid %p\n", stateid); | 7180 | dprintk("NFS call test_stateid %p\n", stateid); |
@@ -7156,17 +7195,20 @@ static int _nfs41_test_stateid(struct nfs_server *server, nfs4_stateid *stateid) | |||
7156 | * | 7195 | * |
7157 | * @server: server / transport on which to perform the operation | 7196 | * @server: server / transport on which to perform the operation |
7158 | * @stateid: state ID to test | 7197 | * @stateid: state ID to test |
7198 | * @cred: credential | ||
7159 | * | 7199 | * |
7160 | * Returns NFS_OK if the server recognizes that "stateid" is valid. | 7200 | * Returns NFS_OK if the server recognizes that "stateid" is valid. |
7161 | * Otherwise a negative NFS4ERR value is returned if the operation | 7201 | * Otherwise a negative NFS4ERR value is returned if the operation |
7162 | * failed or the state ID is not currently valid. | 7202 | * failed or the state ID is not currently valid. |
7163 | */ | 7203 | */ |
7164 | static int nfs41_test_stateid(struct nfs_server *server, nfs4_stateid *stateid) | 7204 | static int nfs41_test_stateid(struct nfs_server *server, |
7205 | nfs4_stateid *stateid, | ||
7206 | struct rpc_cred *cred) | ||
7165 | { | 7207 | { |
7166 | struct nfs4_exception exception = { }; | 7208 | struct nfs4_exception exception = { }; |
7167 | int err; | 7209 | int err; |
7168 | do { | 7210 | do { |
7169 | err = _nfs41_test_stateid(server, stateid); | 7211 | err = _nfs41_test_stateid(server, stateid, cred); |
7170 | if (err != -NFS4ERR_DELAY) | 7212 | if (err != -NFS4ERR_DELAY) |
7171 | break; | 7213 | break; |
7172 | nfs4_handle_exception(server, err, &exception); | 7214 | nfs4_handle_exception(server, err, &exception); |
@@ -7215,10 +7257,12 @@ const struct rpc_call_ops nfs41_free_stateid_ops = { | |||
7215 | 7257 | ||
7216 | static struct rpc_task *_nfs41_free_stateid(struct nfs_server *server, | 7258 | static struct rpc_task *_nfs41_free_stateid(struct nfs_server *server, |
7217 | nfs4_stateid *stateid, | 7259 | nfs4_stateid *stateid, |
7260 | struct rpc_cred *cred, | ||
7218 | bool privileged) | 7261 | bool privileged) |
7219 | { | 7262 | { |
7220 | struct rpc_message msg = { | 7263 | struct rpc_message msg = { |
7221 | .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_FREE_STATEID], | 7264 | .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_FREE_STATEID], |
7265 | .rpc_cred = cred, | ||
7222 | }; | 7266 | }; |
7223 | struct rpc_task_setup task_setup = { | 7267 | struct rpc_task_setup task_setup = { |
7224 | .rpc_client = server->client, | 7268 | .rpc_client = server->client, |
@@ -7251,16 +7295,19 @@ static struct rpc_task *_nfs41_free_stateid(struct nfs_server *server, | |||
7251 | * | 7295 | * |
7252 | * @server: server / transport on which to perform the operation | 7296 | * @server: server / transport on which to perform the operation |
7253 | * @stateid: state ID to release | 7297 | * @stateid: state ID to release |
7298 | * @cred: credential | ||
7254 | * | 7299 | * |
7255 | * Returns NFS_OK if the server freed "stateid". Otherwise a | 7300 | * Returns NFS_OK if the server freed "stateid". Otherwise a |
7256 | * negative NFS4ERR value is returned. | 7301 | * negative NFS4ERR value is returned. |
7257 | */ | 7302 | */ |
7258 | static int nfs41_free_stateid(struct nfs_server *server, nfs4_stateid *stateid) | 7303 | static int nfs41_free_stateid(struct nfs_server *server, |
7304 | nfs4_stateid *stateid, | ||
7305 | struct rpc_cred *cred) | ||
7259 | { | 7306 | { |
7260 | struct rpc_task *task; | 7307 | struct rpc_task *task; |
7261 | int ret; | 7308 | int ret; |
7262 | 7309 | ||
7263 | task = _nfs41_free_stateid(server, stateid, true); | 7310 | task = _nfs41_free_stateid(server, stateid, cred, true); |
7264 | if (IS_ERR(task)) | 7311 | if (IS_ERR(task)) |
7265 | return PTR_ERR(task); | 7312 | return PTR_ERR(task); |
7266 | ret = rpc_wait_for_completion_task(task); | 7313 | ret = rpc_wait_for_completion_task(task); |
@@ -7273,8 +7320,9 @@ static int nfs41_free_stateid(struct nfs_server *server, nfs4_stateid *stateid) | |||
7273 | static int nfs41_free_lock_state(struct nfs_server *server, struct nfs4_lock_state *lsp) | 7320 | static int nfs41_free_lock_state(struct nfs_server *server, struct nfs4_lock_state *lsp) |
7274 | { | 7321 | { |
7275 | struct rpc_task *task; | 7322 | struct rpc_task *task; |
7323 | struct rpc_cred *cred = lsp->ls_state->owner->so_cred; | ||
7276 | 7324 | ||
7277 | task = _nfs41_free_stateid(server, &lsp->ls_stateid, false); | 7325 | task = _nfs41_free_stateid(server, &lsp->ls_stateid, cred, false); |
7278 | nfs4_free_lock_state(server, lsp); | 7326 | nfs4_free_lock_state(server, lsp); |
7279 | if (IS_ERR(task)) | 7327 | if (IS_ERR(task)) |
7280 | return PTR_ERR(task); | 7328 | return PTR_ERR(task); |
diff --git a/fs/nfs/nfs4session.c b/fs/nfs/nfs4session.c index ebda5f4a031b..36e21cb29d65 100644 --- a/fs/nfs/nfs4session.c +++ b/fs/nfs/nfs4session.c | |||
@@ -73,7 +73,7 @@ void nfs4_free_slot(struct nfs4_slot_table *tbl, struct nfs4_slot *slot) | |||
73 | tbl->highest_used_slotid = new_max; | 73 | tbl->highest_used_slotid = new_max; |
74 | else { | 74 | else { |
75 | tbl->highest_used_slotid = NFS4_NO_SLOT; | 75 | tbl->highest_used_slotid = NFS4_NO_SLOT; |
76 | nfs4_session_drain_complete(tbl->session, tbl); | 76 | nfs4_slot_tbl_drain_complete(tbl); |
77 | } | 77 | } |
78 | } | 78 | } |
79 | dprintk("%s: slotid %u highest_used_slotid %d\n", __func__, | 79 | dprintk("%s: slotid %u highest_used_slotid %d\n", __func__, |
@@ -226,7 +226,7 @@ static bool nfs41_assign_slot(struct rpc_task *task, void *pslot) | |||
226 | struct nfs4_slot *slot = pslot; | 226 | struct nfs4_slot *slot = pslot; |
227 | struct nfs4_slot_table *tbl = slot->table; | 227 | struct nfs4_slot_table *tbl = slot->table; |
228 | 228 | ||
229 | if (nfs4_session_draining(tbl->session) && !args->sa_privileged) | 229 | if (nfs4_slot_tbl_draining(tbl) && !args->sa_privileged) |
230 | return false; | 230 | return false; |
231 | slot->generation = tbl->generation; | 231 | slot->generation = tbl->generation; |
232 | args->sa_slot = slot; | 232 | args->sa_slot = slot; |
@@ -478,48 +478,12 @@ static int nfs41_check_session_ready(struct nfs_client *clp) | |||
478 | return 0; | 478 | return 0; |
479 | } | 479 | } |
480 | 480 | ||
481 | int nfs4_init_session(struct nfs_server *server) | 481 | int nfs4_init_session(struct nfs_client *clp) |
482 | { | 482 | { |
483 | struct nfs_client *clp = server->nfs_client; | ||
484 | struct nfs4_session *session; | ||
485 | unsigned int target_max_rqst_sz = NFS_MAX_FILE_IO_SIZE; | ||
486 | unsigned int target_max_resp_sz = NFS_MAX_FILE_IO_SIZE; | ||
487 | |||
488 | if (!nfs4_has_session(clp)) | 483 | if (!nfs4_has_session(clp)) |
489 | return 0; | 484 | return 0; |
490 | 485 | ||
491 | if (server->rsize != 0) | 486 | clear_bit(NFS4_SESSION_INITING, &clp->cl_session->session_state); |
492 | target_max_resp_sz = server->rsize; | ||
493 | target_max_resp_sz += nfs41_maxread_overhead; | ||
494 | |||
495 | if (server->wsize != 0) | ||
496 | target_max_rqst_sz = server->wsize; | ||
497 | target_max_rqst_sz += nfs41_maxwrite_overhead; | ||
498 | |||
499 | session = clp->cl_session; | ||
500 | spin_lock(&clp->cl_lock); | ||
501 | if (test_and_clear_bit(NFS4_SESSION_INITING, &session->session_state)) { | ||
502 | /* Initialise targets and channel attributes */ | ||
503 | session->fc_target_max_rqst_sz = target_max_rqst_sz; | ||
504 | session->fc_attrs.max_rqst_sz = target_max_rqst_sz; | ||
505 | session->fc_target_max_resp_sz = target_max_resp_sz; | ||
506 | session->fc_attrs.max_resp_sz = target_max_resp_sz; | ||
507 | } else { | ||
508 | /* Just adjust the targets */ | ||
509 | if (target_max_rqst_sz > session->fc_target_max_rqst_sz) { | ||
510 | session->fc_target_max_rqst_sz = target_max_rqst_sz; | ||
511 | set_bit(NFS4CLNT_SESSION_RESET, &clp->cl_state); | ||
512 | } | ||
513 | if (target_max_resp_sz > session->fc_target_max_resp_sz) { | ||
514 | session->fc_target_max_resp_sz = target_max_resp_sz; | ||
515 | set_bit(NFS4CLNT_SESSION_RESET, &clp->cl_state); | ||
516 | } | ||
517 | } | ||
518 | spin_unlock(&clp->cl_lock); | ||
519 | |||
520 | if (test_bit(NFS4CLNT_SESSION_RESET, &clp->cl_state)) | ||
521 | nfs4_schedule_lease_recovery(clp); | ||
522 | |||
523 | return nfs41_check_session_ready(clp); | 487 | return nfs41_check_session_ready(clp); |
524 | } | 488 | } |
525 | 489 | ||
diff --git a/fs/nfs/nfs4session.h b/fs/nfs/nfs4session.h index 6f3cb39386d4..3a153d82b90c 100644 --- a/fs/nfs/nfs4session.h +++ b/fs/nfs/nfs4session.h | |||
@@ -25,6 +25,10 @@ struct nfs4_slot { | |||
25 | }; | 25 | }; |
26 | 26 | ||
27 | /* Sessions */ | 27 | /* Sessions */ |
28 | enum nfs4_slot_tbl_state { | ||
29 | NFS4_SLOT_TBL_DRAINING, | ||
30 | }; | ||
31 | |||
28 | #define SLOT_TABLE_SZ DIV_ROUND_UP(NFS4_MAX_SLOT_TABLE, 8*sizeof(long)) | 32 | #define SLOT_TABLE_SZ DIV_ROUND_UP(NFS4_MAX_SLOT_TABLE, 8*sizeof(long)) |
29 | struct nfs4_slot_table { | 33 | struct nfs4_slot_table { |
30 | struct nfs4_session *session; /* Parent session */ | 34 | struct nfs4_session *session; /* Parent session */ |
@@ -43,6 +47,7 @@ struct nfs4_slot_table { | |||
43 | unsigned long generation; /* Generation counter for | 47 | unsigned long generation; /* Generation counter for |
44 | target_highest_slotid */ | 48 | target_highest_slotid */ |
45 | struct completion complete; | 49 | struct completion complete; |
50 | unsigned long slot_tbl_state; | ||
46 | }; | 51 | }; |
47 | 52 | ||
48 | /* | 53 | /* |
@@ -61,14 +66,10 @@ struct nfs4_session { | |||
61 | struct nfs4_channel_attrs bc_attrs; | 66 | struct nfs4_channel_attrs bc_attrs; |
62 | struct nfs4_slot_table bc_slot_table; | 67 | struct nfs4_slot_table bc_slot_table; |
63 | struct nfs_client *clp; | 68 | struct nfs_client *clp; |
64 | /* Create session arguments */ | ||
65 | unsigned int fc_target_max_rqst_sz; | ||
66 | unsigned int fc_target_max_resp_sz; | ||
67 | }; | 69 | }; |
68 | 70 | ||
69 | enum nfs4_session_state { | 71 | enum nfs4_session_state { |
70 | NFS4_SESSION_INITING, | 72 | NFS4_SESSION_INITING, |
71 | NFS4_SESSION_DRAINING, | ||
72 | }; | 73 | }; |
73 | 74 | ||
74 | #if defined(CONFIG_NFS_V4_1) | 75 | #if defined(CONFIG_NFS_V4_1) |
@@ -85,15 +86,14 @@ extern int nfs4_setup_session_slot_tables(struct nfs4_session *ses); | |||
85 | 86 | ||
86 | extern struct nfs4_session *nfs4_alloc_session(struct nfs_client *clp); | 87 | extern struct nfs4_session *nfs4_alloc_session(struct nfs_client *clp); |
87 | extern void nfs4_destroy_session(struct nfs4_session *session); | 88 | extern void nfs4_destroy_session(struct nfs4_session *session); |
88 | extern int nfs4_init_session(struct nfs_server *server); | 89 | extern int nfs4_init_session(struct nfs_client *clp); |
89 | extern int nfs4_init_ds_session(struct nfs_client *, unsigned long); | 90 | extern int nfs4_init_ds_session(struct nfs_client *, unsigned long); |
90 | 91 | ||
91 | extern void nfs4_session_drain_complete(struct nfs4_session *session, | 92 | extern void nfs4_slot_tbl_drain_complete(struct nfs4_slot_table *tbl); |
92 | struct nfs4_slot_table *tbl); | ||
93 | 93 | ||
94 | static inline bool nfs4_session_draining(struct nfs4_session *session) | 94 | static inline bool nfs4_slot_tbl_draining(struct nfs4_slot_table *tbl) |
95 | { | 95 | { |
96 | return !!test_bit(NFS4_SESSION_DRAINING, &session->session_state); | 96 | return !!test_bit(NFS4_SLOT_TBL_DRAINING, &tbl->slot_tbl_state); |
97 | } | 97 | } |
98 | 98 | ||
99 | bool nfs41_wake_and_assign_slot(struct nfs4_slot_table *tbl, | 99 | bool nfs41_wake_and_assign_slot(struct nfs4_slot_table *tbl, |
@@ -119,7 +119,7 @@ static inline int nfs4_has_persistent_session(const struct nfs_client *clp) | |||
119 | 119 | ||
120 | #else /* defined(CONFIG_NFS_V4_1) */ | 120 | #else /* defined(CONFIG_NFS_V4_1) */ |
121 | 121 | ||
122 | static inline int nfs4_init_session(struct nfs_server *server) | 122 | static inline int nfs4_init_session(struct nfs_client *clp) |
123 | { | 123 | { |
124 | return 0; | 124 | return 0; |
125 | } | 125 | } |
diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c index 300d17d85c0e..b0e42d7a19a1 100644 --- a/fs/nfs/nfs4state.c +++ b/fs/nfs/nfs4state.c | |||
@@ -228,38 +228,37 @@ static int nfs41_setup_state_renewal(struct nfs_client *clp) | |||
228 | return status; | 228 | return status; |
229 | } | 229 | } |
230 | 230 | ||
231 | /* | 231 | static void nfs4_end_drain_slot_table(struct nfs4_slot_table *tbl) |
232 | * Back channel returns NFS4ERR_DELAY for new requests when | ||
233 | * NFS4_SESSION_DRAINING is set so there is no work to be done when draining | ||
234 | * is ended. | ||
235 | */ | ||
236 | static void nfs4_end_drain_session(struct nfs_client *clp) | ||
237 | { | 232 | { |
238 | struct nfs4_session *ses = clp->cl_session; | 233 | if (test_and_clear_bit(NFS4_SLOT_TBL_DRAINING, &tbl->slot_tbl_state)) { |
239 | struct nfs4_slot_table *tbl; | ||
240 | |||
241 | if (ses == NULL) | ||
242 | return; | ||
243 | tbl = &ses->fc_slot_table; | ||
244 | if (test_and_clear_bit(NFS4_SESSION_DRAINING, &ses->session_state)) { | ||
245 | spin_lock(&tbl->slot_tbl_lock); | 234 | spin_lock(&tbl->slot_tbl_lock); |
246 | nfs41_wake_slot_table(tbl); | 235 | nfs41_wake_slot_table(tbl); |
247 | spin_unlock(&tbl->slot_tbl_lock); | 236 | spin_unlock(&tbl->slot_tbl_lock); |
248 | } | 237 | } |
249 | } | 238 | } |
250 | 239 | ||
240 | static void nfs4_end_drain_session(struct nfs_client *clp) | ||
241 | { | ||
242 | struct nfs4_session *ses = clp->cl_session; | ||
243 | |||
244 | if (ses != NULL) { | ||
245 | nfs4_end_drain_slot_table(&ses->bc_slot_table); | ||
246 | nfs4_end_drain_slot_table(&ses->fc_slot_table); | ||
247 | } | ||
248 | } | ||
249 | |||
251 | /* | 250 | /* |
252 | * Signal state manager thread if session fore channel is drained | 251 | * Signal state manager thread if session fore channel is drained |
253 | */ | 252 | */ |
254 | void nfs4_session_drain_complete(struct nfs4_session *session, | 253 | void nfs4_slot_tbl_drain_complete(struct nfs4_slot_table *tbl) |
255 | struct nfs4_slot_table *tbl) | ||
256 | { | 254 | { |
257 | if (nfs4_session_draining(session)) | 255 | if (nfs4_slot_tbl_draining(tbl)) |
258 | complete(&tbl->complete); | 256 | complete(&tbl->complete); |
259 | } | 257 | } |
260 | 258 | ||
261 | static int nfs4_wait_on_slot_tbl(struct nfs4_slot_table *tbl) | 259 | static int nfs4_drain_slot_tbl(struct nfs4_slot_table *tbl) |
262 | { | 260 | { |
261 | set_bit(NFS4_SLOT_TBL_DRAINING, &tbl->slot_tbl_state); | ||
263 | spin_lock(&tbl->slot_tbl_lock); | 262 | spin_lock(&tbl->slot_tbl_lock); |
264 | if (tbl->highest_used_slotid != NFS4_NO_SLOT) { | 263 | if (tbl->highest_used_slotid != NFS4_NO_SLOT) { |
265 | INIT_COMPLETION(tbl->complete); | 264 | INIT_COMPLETION(tbl->complete); |
@@ -275,13 +274,12 @@ static int nfs4_begin_drain_session(struct nfs_client *clp) | |||
275 | struct nfs4_session *ses = clp->cl_session; | 274 | struct nfs4_session *ses = clp->cl_session; |
276 | int ret = 0; | 275 | int ret = 0; |
277 | 276 | ||
278 | set_bit(NFS4_SESSION_DRAINING, &ses->session_state); | ||
279 | /* back channel */ | 277 | /* back channel */ |
280 | ret = nfs4_wait_on_slot_tbl(&ses->bc_slot_table); | 278 | ret = nfs4_drain_slot_tbl(&ses->bc_slot_table); |
281 | if (ret) | 279 | if (ret) |
282 | return ret; | 280 | return ret; |
283 | /* fore channel */ | 281 | /* fore channel */ |
284 | return nfs4_wait_on_slot_tbl(&ses->fc_slot_table); | 282 | return nfs4_drain_slot_tbl(&ses->fc_slot_table); |
285 | } | 283 | } |
286 | 284 | ||
287 | static void nfs41_finish_session_reset(struct nfs_client *clp) | 285 | static void nfs41_finish_session_reset(struct nfs_client *clp) |
@@ -1564,11 +1562,12 @@ static void nfs4_state_start_reclaim_reboot(struct nfs_client *clp) | |||
1564 | } | 1562 | } |
1565 | 1563 | ||
1566 | static void nfs4_reclaim_complete(struct nfs_client *clp, | 1564 | static void nfs4_reclaim_complete(struct nfs_client *clp, |
1567 | const struct nfs4_state_recovery_ops *ops) | 1565 | const struct nfs4_state_recovery_ops *ops, |
1566 | struct rpc_cred *cred) | ||
1568 | { | 1567 | { |
1569 | /* Notify the server we're done reclaiming our state */ | 1568 | /* Notify the server we're done reclaiming our state */ |
1570 | if (ops->reclaim_complete) | 1569 | if (ops->reclaim_complete) |
1571 | (void)ops->reclaim_complete(clp); | 1570 | (void)ops->reclaim_complete(clp, cred); |
1572 | } | 1571 | } |
1573 | 1572 | ||
1574 | static void nfs4_clear_reclaim_server(struct nfs_server *server) | 1573 | static void nfs4_clear_reclaim_server(struct nfs_server *server) |
@@ -1613,9 +1612,15 @@ static int nfs4_state_clear_reclaim_reboot(struct nfs_client *clp) | |||
1613 | 1612 | ||
1614 | static void nfs4_state_end_reclaim_reboot(struct nfs_client *clp) | 1613 | static void nfs4_state_end_reclaim_reboot(struct nfs_client *clp) |
1615 | { | 1614 | { |
1615 | const struct nfs4_state_recovery_ops *ops; | ||
1616 | struct rpc_cred *cred; | ||
1617 | |||
1616 | if (!nfs4_state_clear_reclaim_reboot(clp)) | 1618 | if (!nfs4_state_clear_reclaim_reboot(clp)) |
1617 | return; | 1619 | return; |
1618 | nfs4_reclaim_complete(clp, clp->cl_mvops->reboot_recovery_ops); | 1620 | ops = clp->cl_mvops->reboot_recovery_ops; |
1621 | cred = ops->get_clid_cred(clp); | ||
1622 | nfs4_reclaim_complete(clp, ops, cred); | ||
1623 | put_rpccred(cred); | ||
1619 | } | 1624 | } |
1620 | 1625 | ||
1621 | static void nfs_delegation_clear_all(struct nfs_client *clp) | 1626 | static void nfs_delegation_clear_all(struct nfs_client *clp) |
diff --git a/fs/nfs/nfs4super.c b/fs/nfs/nfs4super.c index a5e1a3026d48..5dbe2d269210 100644 --- a/fs/nfs/nfs4super.c +++ b/fs/nfs/nfs4super.c | |||
@@ -9,6 +9,7 @@ | |||
9 | #include "delegation.h" | 9 | #include "delegation.h" |
10 | #include "internal.h" | 10 | #include "internal.h" |
11 | #include "nfs4_fs.h" | 11 | #include "nfs4_fs.h" |
12 | #include "dns_resolve.h" | ||
12 | #include "pnfs.h" | 13 | #include "pnfs.h" |
13 | #include "nfs.h" | 14 | #include "nfs.h" |
14 | 15 | ||
@@ -331,18 +332,24 @@ static int __init init_nfs_v4(void) | |||
331 | { | 332 | { |
332 | int err; | 333 | int err; |
333 | 334 | ||
334 | err = nfs_idmap_init(); | 335 | err = nfs_dns_resolver_init(); |
335 | if (err) | 336 | if (err) |
336 | goto out; | 337 | goto out; |
337 | 338 | ||
338 | err = nfs4_register_sysctl(); | 339 | err = nfs_idmap_init(); |
339 | if (err) | 340 | if (err) |
340 | goto out1; | 341 | goto out1; |
341 | 342 | ||
343 | err = nfs4_register_sysctl(); | ||
344 | if (err) | ||
345 | goto out2; | ||
346 | |||
342 | register_nfs_version(&nfs_v4); | 347 | register_nfs_version(&nfs_v4); |
343 | return 0; | 348 | return 0; |
344 | out1: | 349 | out2: |
345 | nfs_idmap_quit(); | 350 | nfs_idmap_quit(); |
351 | out1: | ||
352 | nfs_dns_resolver_destroy(); | ||
346 | out: | 353 | out: |
347 | return err; | 354 | return err; |
348 | } | 355 | } |
@@ -352,6 +359,7 @@ static void __exit exit_nfs_v4(void) | |||
352 | unregister_nfs_version(&nfs_v4); | 359 | unregister_nfs_version(&nfs_v4); |
353 | nfs4_unregister_sysctl(); | 360 | nfs4_unregister_sysctl(); |
354 | nfs_idmap_quit(); | 361 | nfs_idmap_quit(); |
362 | nfs_dns_resolver_destroy(); | ||
355 | } | 363 | } |
356 | 364 | ||
357 | MODULE_LICENSE("GPL"); | 365 | MODULE_LICENSE("GPL"); |
diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c index 2a3f77e14db6..0abfb8466e79 100644 --- a/fs/nfs/nfs4xdr.c +++ b/fs/nfs/nfs4xdr.c | |||
@@ -867,6 +867,12 @@ const u32 nfs41_maxread_overhead = ((RPC_MAX_HEADER_WITH_AUTH + | |||
867 | decode_sequence_maxsz + | 867 | decode_sequence_maxsz + |
868 | decode_putfh_maxsz) * | 868 | decode_putfh_maxsz) * |
869 | XDR_UNIT); | 869 | XDR_UNIT); |
870 | |||
871 | const u32 nfs41_maxgetdevinfo_overhead = ((RPC_MAX_REPHEADER_WITH_AUTH + | ||
872 | compound_decode_hdr_maxsz + | ||
873 | decode_sequence_maxsz) * | ||
874 | XDR_UNIT); | ||
875 | EXPORT_SYMBOL_GPL(nfs41_maxgetdevinfo_overhead); | ||
870 | #endif /* CONFIG_NFS_V4_1 */ | 876 | #endif /* CONFIG_NFS_V4_1 */ |
871 | 877 | ||
872 | static const umode_t nfs_type2fmt[] = { | 878 | static const umode_t nfs_type2fmt[] = { |
@@ -1924,7 +1930,7 @@ encode_getdeviceinfo(struct xdr_stream *xdr, | |||
1924 | p = xdr_encode_opaque_fixed(p, args->pdev->dev_id.data, | 1930 | p = xdr_encode_opaque_fixed(p, args->pdev->dev_id.data, |
1925 | NFS4_DEVICEID4_SIZE); | 1931 | NFS4_DEVICEID4_SIZE); |
1926 | *p++ = cpu_to_be32(args->pdev->layout_type); | 1932 | *p++ = cpu_to_be32(args->pdev->layout_type); |
1927 | *p++ = cpu_to_be32(args->pdev->pglen); /* gdia_maxcount */ | 1933 | *p++ = cpu_to_be32(args->pdev->maxcount); /* gdia_maxcount */ |
1928 | *p++ = cpu_to_be32(0); /* bitmap length 0 */ | 1934 | *p++ = cpu_to_be32(0); /* bitmap length 0 */ |
1929 | } | 1935 | } |
1930 | 1936 | ||
diff --git a/fs/nfs/objlayout/objlayout.c b/fs/nfs/objlayout/objlayout.c index a9ebd817278b..e4f9cbfec67b 100644 --- a/fs/nfs/objlayout/objlayout.c +++ b/fs/nfs/objlayout/objlayout.c | |||
@@ -613,8 +613,10 @@ int objlayout_get_deviceinfo(struct pnfs_layout_hdr *pnfslay, | |||
613 | pd.pgbase = 0; | 613 | pd.pgbase = 0; |
614 | pd.pglen = PAGE_SIZE; | 614 | pd.pglen = PAGE_SIZE; |
615 | pd.mincount = 0; | 615 | pd.mincount = 0; |
616 | pd.maxcount = PAGE_SIZE; | ||
616 | 617 | ||
617 | err = nfs4_proc_getdeviceinfo(NFS_SERVER(pnfslay->plh_inode), &pd); | 618 | err = nfs4_proc_getdeviceinfo(NFS_SERVER(pnfslay->plh_inode), &pd, |
619 | pnfslay->plh_lc_cred); | ||
618 | dprintk("%s nfs_getdeviceinfo returned %d\n", __func__, err); | 620 | dprintk("%s nfs_getdeviceinfo returned %d\n", __func__, err); |
619 | if (err) | 621 | if (err) |
620 | goto err_out; | 622 | goto err_out; |
diff --git a/fs/nfs/pnfs.c b/fs/nfs/pnfs.c index c5bd758e5637..3a3a79d6bf15 100644 --- a/fs/nfs/pnfs.c +++ b/fs/nfs/pnfs.c | |||
@@ -360,7 +360,7 @@ pnfs_put_lseg(struct pnfs_layout_segment *lseg) | |||
360 | } | 360 | } |
361 | EXPORT_SYMBOL_GPL(pnfs_put_lseg); | 361 | EXPORT_SYMBOL_GPL(pnfs_put_lseg); |
362 | 362 | ||
363 | static inline u64 | 363 | static u64 |
364 | end_offset(u64 start, u64 len) | 364 | end_offset(u64 start, u64 len) |
365 | { | 365 | { |
366 | u64 end; | 366 | u64 end; |
@@ -376,9 +376,9 @@ end_offset(u64 start, u64 len) | |||
376 | * start2 end2 | 376 | * start2 end2 |
377 | * [----------------) | 377 | * [----------------) |
378 | */ | 378 | */ |
379 | static inline int | 379 | static bool |
380 | lo_seg_contained(struct pnfs_layout_range *l1, | 380 | pnfs_lseg_range_contained(const struct pnfs_layout_range *l1, |
381 | struct pnfs_layout_range *l2) | 381 | const struct pnfs_layout_range *l2) |
382 | { | 382 | { |
383 | u64 start1 = l1->offset; | 383 | u64 start1 = l1->offset; |
384 | u64 end1 = end_offset(start1, l1->length); | 384 | u64 end1 = end_offset(start1, l1->length); |
@@ -395,9 +395,9 @@ lo_seg_contained(struct pnfs_layout_range *l1, | |||
395 | * start2 end2 | 395 | * start2 end2 |
396 | * [----------------) | 396 | * [----------------) |
397 | */ | 397 | */ |
398 | static inline int | 398 | static bool |
399 | lo_seg_intersecting(struct pnfs_layout_range *l1, | 399 | pnfs_lseg_range_intersecting(const struct pnfs_layout_range *l1, |
400 | struct pnfs_layout_range *l2) | 400 | const struct pnfs_layout_range *l2) |
401 | { | 401 | { |
402 | u64 start1 = l1->offset; | 402 | u64 start1 = l1->offset; |
403 | u64 end1 = end_offset(start1, l1->length); | 403 | u64 end1 = end_offset(start1, l1->length); |
@@ -409,12 +409,12 @@ lo_seg_intersecting(struct pnfs_layout_range *l1, | |||
409 | } | 409 | } |
410 | 410 | ||
411 | static bool | 411 | static bool |
412 | should_free_lseg(struct pnfs_layout_range *lseg_range, | 412 | should_free_lseg(const struct pnfs_layout_range *lseg_range, |
413 | struct pnfs_layout_range *recall_range) | 413 | const struct pnfs_layout_range *recall_range) |
414 | { | 414 | { |
415 | return (recall_range->iomode == IOMODE_ANY || | 415 | return (recall_range->iomode == IOMODE_ANY || |
416 | lseg_range->iomode == recall_range->iomode) && | 416 | lseg_range->iomode == recall_range->iomode) && |
417 | lo_seg_intersecting(lseg_range, recall_range); | 417 | pnfs_lseg_range_intersecting(lseg_range, recall_range); |
418 | } | 418 | } |
419 | 419 | ||
420 | static bool pnfs_lseg_dec_and_remove_zero(struct pnfs_layout_segment *lseg, | 420 | static bool pnfs_lseg_dec_and_remove_zero(struct pnfs_layout_segment *lseg, |
@@ -766,6 +766,7 @@ send_layoutget(struct pnfs_layout_hdr *lo, | |||
766 | lgp->args.inode = ino; | 766 | lgp->args.inode = ino; |
767 | lgp->args.ctx = get_nfs_open_context(ctx); | 767 | lgp->args.ctx = get_nfs_open_context(ctx); |
768 | lgp->gfp_flags = gfp_flags; | 768 | lgp->gfp_flags = gfp_flags; |
769 | lgp->cred = lo->plh_lc_cred; | ||
769 | 770 | ||
770 | /* Synchronously retrieve layout information from server and | 771 | /* Synchronously retrieve layout information from server and |
771 | * store in lseg. | 772 | * store in lseg. |
@@ -860,6 +861,7 @@ _pnfs_return_layout(struct inode *ino) | |||
860 | lrp->args.inode = ino; | 861 | lrp->args.inode = ino; |
861 | lrp->args.layout = lo; | 862 | lrp->args.layout = lo; |
862 | lrp->clp = NFS_SERVER(ino)->nfs_client; | 863 | lrp->clp = NFS_SERVER(ino)->nfs_client; |
864 | lrp->cred = lo->plh_lc_cred; | ||
863 | 865 | ||
864 | status = nfs4_proc_layoutreturn(lrp); | 866 | status = nfs4_proc_layoutreturn(lrp); |
865 | out: | 867 | out: |
@@ -984,8 +986,8 @@ out: | |||
984 | * are seen first. | 986 | * are seen first. |
985 | */ | 987 | */ |
986 | static s64 | 988 | static s64 |
987 | cmp_layout(struct pnfs_layout_range *l1, | 989 | pnfs_lseg_range_cmp(const struct pnfs_layout_range *l1, |
988 | struct pnfs_layout_range *l2) | 990 | const struct pnfs_layout_range *l2) |
989 | { | 991 | { |
990 | s64 d; | 992 | s64 d; |
991 | 993 | ||
@@ -1012,7 +1014,7 @@ pnfs_layout_insert_lseg(struct pnfs_layout_hdr *lo, | |||
1012 | dprintk("%s:Begin\n", __func__); | 1014 | dprintk("%s:Begin\n", __func__); |
1013 | 1015 | ||
1014 | list_for_each_entry(lp, &lo->plh_segs, pls_list) { | 1016 | list_for_each_entry(lp, &lo->plh_segs, pls_list) { |
1015 | if (cmp_layout(&lseg->pls_range, &lp->pls_range) > 0) | 1017 | if (pnfs_lseg_range_cmp(&lseg->pls_range, &lp->pls_range) > 0) |
1016 | continue; | 1018 | continue; |
1017 | list_add_tail(&lseg->pls_list, &lp->pls_list); | 1019 | list_add_tail(&lseg->pls_list, &lp->pls_list); |
1018 | dprintk("%s: inserted lseg %p " | 1020 | dprintk("%s: inserted lseg %p " |
@@ -1050,7 +1052,7 @@ alloc_init_layout_hdr(struct inode *ino, | |||
1050 | INIT_LIST_HEAD(&lo->plh_segs); | 1052 | INIT_LIST_HEAD(&lo->plh_segs); |
1051 | INIT_LIST_HEAD(&lo->plh_bulk_destroy); | 1053 | INIT_LIST_HEAD(&lo->plh_bulk_destroy); |
1052 | lo->plh_inode = ino; | 1054 | lo->plh_inode = ino; |
1053 | lo->plh_lc_cred = get_rpccred(ctx->state->owner->so_cred); | 1055 | lo->plh_lc_cred = get_rpccred(ctx->cred); |
1054 | return lo; | 1056 | return lo; |
1055 | } | 1057 | } |
1056 | 1058 | ||
@@ -1091,21 +1093,21 @@ out_existing: | |||
1091 | * READ READ true | 1093 | * READ READ true |
1092 | * READ RW true | 1094 | * READ RW true |
1093 | */ | 1095 | */ |
1094 | static int | 1096 | static bool |
1095 | is_matching_lseg(struct pnfs_layout_range *ls_range, | 1097 | pnfs_lseg_range_match(const struct pnfs_layout_range *ls_range, |
1096 | struct pnfs_layout_range *range) | 1098 | const struct pnfs_layout_range *range) |
1097 | { | 1099 | { |
1098 | struct pnfs_layout_range range1; | 1100 | struct pnfs_layout_range range1; |
1099 | 1101 | ||
1100 | if ((range->iomode == IOMODE_RW && | 1102 | if ((range->iomode == IOMODE_RW && |
1101 | ls_range->iomode != IOMODE_RW) || | 1103 | ls_range->iomode != IOMODE_RW) || |
1102 | !lo_seg_intersecting(ls_range, range)) | 1104 | !pnfs_lseg_range_intersecting(ls_range, range)) |
1103 | return 0; | 1105 | return 0; |
1104 | 1106 | ||
1105 | /* range1 covers only the first byte in the range */ | 1107 | /* range1 covers only the first byte in the range */ |
1106 | range1 = *range; | 1108 | range1 = *range; |
1107 | range1.length = 1; | 1109 | range1.length = 1; |
1108 | return lo_seg_contained(ls_range, &range1); | 1110 | return pnfs_lseg_range_contained(ls_range, &range1); |
1109 | } | 1111 | } |
1110 | 1112 | ||
1111 | /* | 1113 | /* |
@@ -1121,7 +1123,7 @@ pnfs_find_lseg(struct pnfs_layout_hdr *lo, | |||
1121 | 1123 | ||
1122 | list_for_each_entry(lseg, &lo->plh_segs, pls_list) { | 1124 | list_for_each_entry(lseg, &lo->plh_segs, pls_list) { |
1123 | if (test_bit(NFS_LSEG_VALID, &lseg->pls_flags) && | 1125 | if (test_bit(NFS_LSEG_VALID, &lseg->pls_flags) && |
1124 | is_matching_lseg(&lseg->pls_range, range)) { | 1126 | pnfs_lseg_range_match(&lseg->pls_range, range)) { |
1125 | ret = pnfs_get_lseg(lseg); | 1127 | ret = pnfs_get_lseg(lseg); |
1126 | break; | 1128 | break; |
1127 | } | 1129 | } |
diff --git a/fs/nfs/pnfs.h b/fs/nfs/pnfs.h index f5f8a470a647..a4f41810a7f4 100644 --- a/fs/nfs/pnfs.h +++ b/fs/nfs/pnfs.h | |||
@@ -149,9 +149,10 @@ struct pnfs_device { | |||
149 | struct nfs4_deviceid dev_id; | 149 | struct nfs4_deviceid dev_id; |
150 | unsigned int layout_type; | 150 | unsigned int layout_type; |
151 | unsigned int mincount; | 151 | unsigned int mincount; |
152 | unsigned int maxcount; /* gdia_maxcount */ | ||
152 | struct page **pages; | 153 | struct page **pages; |
153 | unsigned int pgbase; | 154 | unsigned int pgbase; |
154 | unsigned int pglen; | 155 | unsigned int pglen; /* reply buffer length */ |
155 | }; | 156 | }; |
156 | 157 | ||
157 | #define NFS4_PNFS_GETDEVLIST_MAXNUM 16 | 158 | #define NFS4_PNFS_GETDEVLIST_MAXNUM 16 |
@@ -170,7 +171,8 @@ extern int nfs4_proc_getdevicelist(struct nfs_server *server, | |||
170 | const struct nfs_fh *fh, | 171 | const struct nfs_fh *fh, |
171 | struct pnfs_devicelist *devlist); | 172 | struct pnfs_devicelist *devlist); |
172 | extern int nfs4_proc_getdeviceinfo(struct nfs_server *server, | 173 | extern int nfs4_proc_getdeviceinfo(struct nfs_server *server, |
173 | struct pnfs_device *dev); | 174 | struct pnfs_device *dev, |
175 | struct rpc_cred *cred); | ||
174 | extern struct pnfs_layout_segment* nfs4_proc_layoutget(struct nfs4_layoutget *lgp, gfp_t gfp_flags); | 176 | extern struct pnfs_layout_segment* nfs4_proc_layoutget(struct nfs4_layoutget *lgp, gfp_t gfp_flags); |
175 | extern int nfs4_proc_layoutreturn(struct nfs4_layoutreturn *lrp); | 177 | extern int nfs4_proc_layoutreturn(struct nfs4_layoutreturn *lrp); |
176 | 178 | ||
diff --git a/fs/nfs/super.c b/fs/nfs/super.c index 76e1ee5d03ed..71fdc0dfa0d2 100644 --- a/fs/nfs/super.c +++ b/fs/nfs/super.c | |||
@@ -1614,29 +1614,13 @@ out_security_failure: | |||
1614 | } | 1614 | } |
1615 | 1615 | ||
1616 | /* | 1616 | /* |
1617 | * Select a security flavor for this mount. The selected flavor | 1617 | * Ensure that the specified authtype in args->auth_flavors[0] is supported by |
1618 | * is planted in args->auth_flavors[0]. | 1618 | * the server. Returns 0 if it's ok, and -EACCES if not. |
1619 | * | ||
1620 | * Returns 0 on success, -EACCES on failure. | ||
1621 | */ | 1619 | */ |
1622 | static int nfs_select_flavor(struct nfs_parsed_mount_data *args, | 1620 | static int nfs_verify_authflavor(struct nfs_parsed_mount_data *args, |
1623 | struct nfs_mount_request *request) | 1621 | rpc_authflavor_t *server_authlist, unsigned int count) |
1624 | { | 1622 | { |
1625 | unsigned int i, count = *(request->auth_flav_len); | 1623 | unsigned int i; |
1626 | rpc_authflavor_t flavor; | ||
1627 | |||
1628 | /* | ||
1629 | * The NFSv2 MNT operation does not return a flavor list. | ||
1630 | */ | ||
1631 | if (args->mount_server.version != NFS_MNT3_VERSION) | ||
1632 | goto out_default; | ||
1633 | |||
1634 | /* | ||
1635 | * Certain releases of Linux's mountd return an empty | ||
1636 | * flavor list in some cases. | ||
1637 | */ | ||
1638 | if (count == 0) | ||
1639 | goto out_default; | ||
1640 | 1624 | ||
1641 | /* | 1625 | /* |
1642 | * If the sec= mount option is used, the specified flavor or AUTH_NULL | 1626 | * If the sec= mount option is used, the specified flavor or AUTH_NULL |
@@ -1646,60 +1630,19 @@ static int nfs_select_flavor(struct nfs_parsed_mount_data *args, | |||
1646 | * means that the server will ignore the rpc creds, so any flavor | 1630 | * means that the server will ignore the rpc creds, so any flavor |
1647 | * can be used. | 1631 | * can be used. |
1648 | */ | 1632 | */ |
1649 | if (args->auth_flavors[0] != RPC_AUTH_MAXFLAVOR) { | ||
1650 | for (i = 0; i < count; i++) { | ||
1651 | if (args->auth_flavors[0] == request->auth_flavs[i] || | ||
1652 | request->auth_flavs[i] == RPC_AUTH_NULL) | ||
1653 | goto out; | ||
1654 | } | ||
1655 | dfprintk(MOUNT, "NFS: auth flavor %d not supported by server\n", | ||
1656 | args->auth_flavors[0]); | ||
1657 | goto out_err; | ||
1658 | } | ||
1659 | |||
1660 | /* | ||
1661 | * RFC 2623, section 2.7 suggests we SHOULD prefer the | ||
1662 | * flavor listed first. However, some servers list | ||
1663 | * AUTH_NULL first. Avoid ever choosing AUTH_NULL. | ||
1664 | */ | ||
1665 | for (i = 0; i < count; i++) { | ||
1666 | struct rpcsec_gss_info info; | ||
1667 | |||
1668 | flavor = request->auth_flavs[i]; | ||
1669 | switch (flavor) { | ||
1670 | case RPC_AUTH_UNIX: | ||
1671 | goto out_set; | ||
1672 | case RPC_AUTH_NULL: | ||
1673 | continue; | ||
1674 | default: | ||
1675 | if (rpcauth_get_gssinfo(flavor, &info) == 0) | ||
1676 | goto out_set; | ||
1677 | } | ||
1678 | } | ||
1679 | |||
1680 | /* | ||
1681 | * As a last chance, see if the server list contains AUTH_NULL - | ||
1682 | * if it does, use the default flavor. | ||
1683 | */ | ||
1684 | for (i = 0; i < count; i++) { | 1633 | for (i = 0; i < count; i++) { |
1685 | if (request->auth_flavs[i] == RPC_AUTH_NULL) | 1634 | if (args->auth_flavors[0] == server_authlist[i] || |
1686 | goto out_default; | 1635 | server_authlist[i] == RPC_AUTH_NULL) |
1636 | goto out; | ||
1687 | } | 1637 | } |
1688 | 1638 | ||
1689 | dfprintk(MOUNT, "NFS: no auth flavors in common with server\n"); | 1639 | dfprintk(MOUNT, "NFS: auth flavor %u not supported by server\n", |
1690 | goto out_err; | 1640 | args->auth_flavors[0]); |
1641 | return -EACCES; | ||
1691 | 1642 | ||
1692 | out_default: | ||
1693 | /* use default if flavor not already set */ | ||
1694 | flavor = (args->auth_flavors[0] == RPC_AUTH_MAXFLAVOR) ? | ||
1695 | RPC_AUTH_UNIX : args->auth_flavors[0]; | ||
1696 | out_set: | ||
1697 | args->auth_flavors[0] = flavor; | ||
1698 | out: | 1643 | out: |
1699 | dfprintk(MOUNT, "NFS: using auth flavor %d\n", args->auth_flavors[0]); | 1644 | dfprintk(MOUNT, "NFS: using auth flavor %u\n", args->auth_flavors[0]); |
1700 | return 0; | 1645 | return 0; |
1701 | out_err: | ||
1702 | return -EACCES; | ||
1703 | } | 1646 | } |
1704 | 1647 | ||
1705 | /* | 1648 | /* |
@@ -1707,10 +1650,10 @@ out_err: | |||
1707 | * corresponding to the provided path. | 1650 | * corresponding to the provided path. |
1708 | */ | 1651 | */ |
1709 | static int nfs_request_mount(struct nfs_parsed_mount_data *args, | 1652 | static int nfs_request_mount(struct nfs_parsed_mount_data *args, |
1710 | struct nfs_fh *root_fh) | 1653 | struct nfs_fh *root_fh, |
1654 | rpc_authflavor_t *server_authlist, | ||
1655 | unsigned int *server_authlist_len) | ||
1711 | { | 1656 | { |
1712 | rpc_authflavor_t server_authlist[NFS_MAX_SECFLAVORS]; | ||
1713 | unsigned int server_authlist_len = ARRAY_SIZE(server_authlist); | ||
1714 | struct nfs_mount_request request = { | 1657 | struct nfs_mount_request request = { |
1715 | .sap = (struct sockaddr *) | 1658 | .sap = (struct sockaddr *) |
1716 | &args->mount_server.address, | 1659 | &args->mount_server.address, |
@@ -1718,7 +1661,7 @@ static int nfs_request_mount(struct nfs_parsed_mount_data *args, | |||
1718 | .protocol = args->mount_server.protocol, | 1661 | .protocol = args->mount_server.protocol, |
1719 | .fh = root_fh, | 1662 | .fh = root_fh, |
1720 | .noresvport = args->flags & NFS_MOUNT_NORESVPORT, | 1663 | .noresvport = args->flags & NFS_MOUNT_NORESVPORT, |
1721 | .auth_flav_len = &server_authlist_len, | 1664 | .auth_flav_len = server_authlist_len, |
1722 | .auth_flavs = server_authlist, | 1665 | .auth_flavs = server_authlist, |
1723 | .net = args->net, | 1666 | .net = args->net, |
1724 | }; | 1667 | }; |
@@ -1762,24 +1705,92 @@ static int nfs_request_mount(struct nfs_parsed_mount_data *args, | |||
1762 | return status; | 1705 | return status; |
1763 | } | 1706 | } |
1764 | 1707 | ||
1765 | return nfs_select_flavor(args, &request); | 1708 | return 0; |
1766 | } | 1709 | } |
1767 | 1710 | ||
1768 | struct dentry *nfs_try_mount(int flags, const char *dev_name, | 1711 | static struct nfs_server *nfs_try_mount_request(struct nfs_mount_info *mount_info, |
1769 | struct nfs_mount_info *mount_info, | 1712 | struct nfs_subversion *nfs_mod) |
1770 | struct nfs_subversion *nfs_mod) | ||
1771 | { | 1713 | { |
1772 | int status; | 1714 | int status; |
1773 | struct nfs_server *server; | 1715 | unsigned int i; |
1716 | bool tried_auth_unix = false; | ||
1717 | bool auth_null_in_list = false; | ||
1718 | struct nfs_server *server = ERR_PTR(-EACCES); | ||
1719 | struct nfs_parsed_mount_data *args = mount_info->parsed; | ||
1720 | rpc_authflavor_t authlist[NFS_MAX_SECFLAVORS]; | ||
1721 | unsigned int authlist_len = ARRAY_SIZE(authlist); | ||
1722 | |||
1723 | status = nfs_request_mount(args, mount_info->mntfh, authlist, | ||
1724 | &authlist_len); | ||
1725 | if (status) | ||
1726 | return ERR_PTR(status); | ||
1774 | 1727 | ||
1775 | if (mount_info->parsed->need_mount) { | 1728 | /* |
1776 | status = nfs_request_mount(mount_info->parsed, mount_info->mntfh); | 1729 | * Was a sec= authflavor specified in the options? First, verify |
1730 | * whether the server supports it, and then just try to use it if so. | ||
1731 | */ | ||
1732 | if (args->auth_flavors[0] != RPC_AUTH_MAXFLAVOR) { | ||
1733 | status = nfs_verify_authflavor(args, authlist, authlist_len); | ||
1734 | dfprintk(MOUNT, "NFS: using auth flavor %u\n", args->auth_flavors[0]); | ||
1777 | if (status) | 1735 | if (status) |
1778 | return ERR_PTR(status); | 1736 | return ERR_PTR(status); |
1737 | return nfs_mod->rpc_ops->create_server(mount_info, nfs_mod); | ||
1779 | } | 1738 | } |
1780 | 1739 | ||
1781 | /* Get a volume representation */ | 1740 | /* |
1782 | server = nfs_mod->rpc_ops->create_server(mount_info, nfs_mod); | 1741 | * No sec= option was provided. RFC 2623, section 2.7 suggests we |
1742 | * SHOULD prefer the flavor listed first. However, some servers list | ||
1743 | * AUTH_NULL first. Avoid ever choosing AUTH_NULL. | ||
1744 | */ | ||
1745 | for (i = 0; i < authlist_len; ++i) { | ||
1746 | rpc_authflavor_t flavor; | ||
1747 | struct rpcsec_gss_info info; | ||
1748 | |||
1749 | flavor = authlist[i]; | ||
1750 | switch (flavor) { | ||
1751 | case RPC_AUTH_UNIX: | ||
1752 | tried_auth_unix = true; | ||
1753 | break; | ||
1754 | case RPC_AUTH_NULL: | ||
1755 | auth_null_in_list = true; | ||
1756 | continue; | ||
1757 | default: | ||
1758 | if (rpcauth_get_gssinfo(flavor, &info) != 0) | ||
1759 | continue; | ||
1760 | /* Fallthrough */ | ||
1761 | } | ||
1762 | dfprintk(MOUNT, "NFS: attempting to use auth flavor %u\n", flavor); | ||
1763 | args->auth_flavors[0] = flavor; | ||
1764 | server = nfs_mod->rpc_ops->create_server(mount_info, nfs_mod); | ||
1765 | if (!IS_ERR(server)) | ||
1766 | return server; | ||
1767 | } | ||
1768 | |||
1769 | /* | ||
1770 | * Nothing we tried so far worked. At this point, give up if we've | ||
1771 | * already tried AUTH_UNIX or if the server's list doesn't contain | ||
1772 | * AUTH_NULL | ||
1773 | */ | ||
1774 | if (tried_auth_unix || !auth_null_in_list) | ||
1775 | return server; | ||
1776 | |||
1777 | /* Last chance! Try AUTH_UNIX */ | ||
1778 | dfprintk(MOUNT, "NFS: attempting to use auth flavor %u\n", RPC_AUTH_UNIX); | ||
1779 | args->auth_flavors[0] = RPC_AUTH_UNIX; | ||
1780 | return nfs_mod->rpc_ops->create_server(mount_info, nfs_mod); | ||
1781 | } | ||
1782 | |||
1783 | struct dentry *nfs_try_mount(int flags, const char *dev_name, | ||
1784 | struct nfs_mount_info *mount_info, | ||
1785 | struct nfs_subversion *nfs_mod) | ||
1786 | { | ||
1787 | struct nfs_server *server; | ||
1788 | |||
1789 | if (mount_info->parsed->need_mount) | ||
1790 | server = nfs_try_mount_request(mount_info, nfs_mod); | ||
1791 | else | ||
1792 | server = nfs_mod->rpc_ops->create_server(mount_info, nfs_mod); | ||
1793 | |||
1783 | if (IS_ERR(server)) | 1794 | if (IS_ERR(server)) |
1784 | return ERR_CAST(server); | 1795 | return ERR_CAST(server); |
1785 | 1796 | ||
@@ -1948,6 +1959,7 @@ static int nfs23_validate_mount_data(void *options, | |||
1948 | args->namlen = data->namlen; | 1959 | args->namlen = data->namlen; |
1949 | args->bsize = data->bsize; | 1960 | args->bsize = data->bsize; |
1950 | 1961 | ||
1962 | args->auth_flavors[0] = RPC_AUTH_UNIX; | ||
1951 | if (data->flags & NFS_MOUNT_SECFLAVOUR) | 1963 | if (data->flags & NFS_MOUNT_SECFLAVOUR) |
1952 | args->auth_flavors[0] = data->pseudoflavor; | 1964 | args->auth_flavors[0] = data->pseudoflavor; |
1953 | if (!args->nfs_server.hostname) | 1965 | if (!args->nfs_server.hostname) |
@@ -2657,6 +2669,7 @@ static int nfs4_validate_mount_data(void *options, | |||
2657 | goto out_no_address; | 2669 | goto out_no_address; |
2658 | args->nfs_server.port = ntohs(((struct sockaddr_in *)sap)->sin_port); | 2670 | args->nfs_server.port = ntohs(((struct sockaddr_in *)sap)->sin_port); |
2659 | 2671 | ||
2672 | args->auth_flavors[0] = RPC_AUTH_UNIX; | ||
2660 | if (data->auth_flavourlen) { | 2673 | if (data->auth_flavourlen) { |
2661 | if (data->auth_flavourlen > 1) | 2674 | if (data->auth_flavourlen > 1) |
2662 | goto out_inval_auth; | 2675 | goto out_inval_auth; |
diff --git a/include/linux/nfs_fs.h b/include/linux/nfs_fs.h index d4b003d9e78d..0b176297aaf6 100644 --- a/include/linux/nfs_fs.h +++ b/include/linux/nfs_fs.h | |||
@@ -359,6 +359,7 @@ extern struct nfs_open_context *get_nfs_open_context(struct nfs_open_context *ct | |||
359 | extern void put_nfs_open_context(struct nfs_open_context *ctx); | 359 | extern void put_nfs_open_context(struct nfs_open_context *ctx); |
360 | extern struct nfs_open_context *nfs_find_open_context(struct inode *inode, struct rpc_cred *cred, fmode_t mode); | 360 | extern struct nfs_open_context *nfs_find_open_context(struct inode *inode, struct rpc_cred *cred, fmode_t mode); |
361 | extern struct nfs_open_context *alloc_nfs_open_context(struct dentry *dentry, fmode_t f_mode); | 361 | extern struct nfs_open_context *alloc_nfs_open_context(struct dentry *dentry, fmode_t f_mode); |
362 | extern void nfs_inode_attach_open_context(struct nfs_open_context *ctx); | ||
362 | extern void nfs_file_set_open_context(struct file *filp, struct nfs_open_context *ctx); | 363 | extern void nfs_file_set_open_context(struct file *filp, struct nfs_open_context *ctx); |
363 | extern struct nfs_lock_context *nfs_get_lock_context(struct nfs_open_context *ctx); | 364 | extern struct nfs_lock_context *nfs_get_lock_context(struct nfs_open_context *ctx); |
364 | extern void nfs_put_lock_context(struct nfs_lock_context *l_ctx); | 365 | extern void nfs_put_lock_context(struct nfs_lock_context *l_ctx); |
diff --git a/include/linux/nfs_xdr.h b/include/linux/nfs_xdr.h index ed31ba7a6f9e..8651574a305b 100644 --- a/include/linux/nfs_xdr.h +++ b/include/linux/nfs_xdr.h | |||
@@ -248,6 +248,7 @@ struct nfs4_layoutget_res { | |||
248 | struct nfs4_layoutget { | 248 | struct nfs4_layoutget { |
249 | struct nfs4_layoutget_args args; | 249 | struct nfs4_layoutget_args args; |
250 | struct nfs4_layoutget_res res; | 250 | struct nfs4_layoutget_res res; |
251 | struct rpc_cred *cred; | ||
251 | gfp_t gfp_flags; | 252 | gfp_t gfp_flags; |
252 | }; | 253 | }; |
253 | 254 | ||
diff --git a/include/linux/sunrpc/sched.h b/include/linux/sunrpc/sched.h index 84ca436b76c2..6d870353674a 100644 --- a/include/linux/sunrpc/sched.h +++ b/include/linux/sunrpc/sched.h | |||
@@ -88,15 +88,6 @@ struct rpc_task { | |||
88 | tk_rebind_retry : 2; | 88 | tk_rebind_retry : 2; |
89 | }; | 89 | }; |
90 | 90 | ||
91 | /* support walking a list of tasks on a wait queue */ | ||
92 | #define task_for_each(task, pos, head) \ | ||
93 | list_for_each(pos, head) \ | ||
94 | if ((task=list_entry(pos, struct rpc_task, u.tk_wait.list)),1) | ||
95 | |||
96 | #define task_for_first(task, head) \ | ||
97 | if (!list_empty(head) && \ | ||
98 | ((task=list_entry((head)->next, struct rpc_task, u.tk_wait.list)),1)) | ||
99 | |||
100 | typedef void (*rpc_action)(struct rpc_task *); | 91 | typedef void (*rpc_action)(struct rpc_task *); |
101 | 92 | ||
102 | struct rpc_call_ops { | 93 | struct rpc_call_ops { |
@@ -238,7 +229,6 @@ struct rpc_task *rpc_wake_up_first(struct rpc_wait_queue *, | |||
238 | bool (*)(struct rpc_task *, void *), | 229 | bool (*)(struct rpc_task *, void *), |
239 | void *); | 230 | void *); |
240 | void rpc_wake_up_status(struct rpc_wait_queue *, int); | 231 | void rpc_wake_up_status(struct rpc_wait_queue *, int); |
241 | int rpc_queue_empty(struct rpc_wait_queue *); | ||
242 | void rpc_delay(struct rpc_task *, unsigned long); | 232 | void rpc_delay(struct rpc_task *, unsigned long); |
243 | void * rpc_malloc(struct rpc_task *, size_t); | 233 | void * rpc_malloc(struct rpc_task *, size_t); |
244 | void rpc_free(void *); | 234 | void rpc_free(void *); |
@@ -259,16 +249,6 @@ static inline int rpc_wait_for_completion_task(struct rpc_task *task) | |||
259 | return __rpc_wait_for_completion_task(task, NULL); | 249 | return __rpc_wait_for_completion_task(task, NULL); |
260 | } | 250 | } |
261 | 251 | ||
262 | static inline void rpc_task_set_priority(struct rpc_task *task, unsigned char prio) | ||
263 | { | ||
264 | task->tk_priority = prio - RPC_PRIORITY_LOW; | ||
265 | } | ||
266 | |||
267 | static inline int rpc_task_has_priority(struct rpc_task *task, unsigned char prio) | ||
268 | { | ||
269 | return (task->tk_priority + RPC_PRIORITY_LOW == prio); | ||
270 | } | ||
271 | |||
272 | #if defined(RPC_DEBUG) || defined (RPC_TRACEPOINTS) | 252 | #if defined(RPC_DEBUG) || defined (RPC_TRACEPOINTS) |
273 | static inline const char * rpc_qname(const struct rpc_wait_queue *q) | 253 | static inline const char * rpc_qname(const struct rpc_wait_queue *q) |
274 | { | 254 | { |
diff --git a/net/sunrpc/auth_gss/auth_gss.c b/net/sunrpc/auth_gss/auth_gss.c index 7da6b457f66a..fc2f78d6a9b4 100644 --- a/net/sunrpc/auth_gss/auth_gss.c +++ b/net/sunrpc/auth_gss/auth_gss.c | |||
@@ -52,6 +52,8 @@ | |||
52 | #include <linux/sunrpc/gss_api.h> | 52 | #include <linux/sunrpc/gss_api.h> |
53 | #include <asm/uaccess.h> | 53 | #include <asm/uaccess.h> |
54 | 54 | ||
55 | #include "../netns.h" | ||
56 | |||
55 | static const struct rpc_authops authgss_ops; | 57 | static const struct rpc_authops authgss_ops; |
56 | 58 | ||
57 | static const struct rpc_credops gss_credops; | 59 | static const struct rpc_credops gss_credops; |
@@ -85,8 +87,6 @@ struct gss_auth { | |||
85 | }; | 87 | }; |
86 | 88 | ||
87 | /* pipe_version >= 0 if and only if someone has a pipe open. */ | 89 | /* pipe_version >= 0 if and only if someone has a pipe open. */ |
88 | static int pipe_version = -1; | ||
89 | static atomic_t pipe_users = ATOMIC_INIT(0); | ||
90 | static DEFINE_SPINLOCK(pipe_version_lock); | 90 | static DEFINE_SPINLOCK(pipe_version_lock); |
91 | static struct rpc_wait_queue pipe_version_rpc_waitqueue; | 91 | static struct rpc_wait_queue pipe_version_rpc_waitqueue; |
92 | static DECLARE_WAIT_QUEUE_HEAD(pipe_version_waitqueue); | 92 | static DECLARE_WAIT_QUEUE_HEAD(pipe_version_waitqueue); |
@@ -266,24 +266,27 @@ struct gss_upcall_msg { | |||
266 | char databuf[UPCALL_BUF_LEN]; | 266 | char databuf[UPCALL_BUF_LEN]; |
267 | }; | 267 | }; |
268 | 268 | ||
269 | static int get_pipe_version(void) | 269 | static int get_pipe_version(struct net *net) |
270 | { | 270 | { |
271 | struct sunrpc_net *sn = net_generic(net, sunrpc_net_id); | ||
271 | int ret; | 272 | int ret; |
272 | 273 | ||
273 | spin_lock(&pipe_version_lock); | 274 | spin_lock(&pipe_version_lock); |
274 | if (pipe_version >= 0) { | 275 | if (sn->pipe_version >= 0) { |
275 | atomic_inc(&pipe_users); | 276 | atomic_inc(&sn->pipe_users); |
276 | ret = pipe_version; | 277 | ret = sn->pipe_version; |
277 | } else | 278 | } else |
278 | ret = -EAGAIN; | 279 | ret = -EAGAIN; |
279 | spin_unlock(&pipe_version_lock); | 280 | spin_unlock(&pipe_version_lock); |
280 | return ret; | 281 | return ret; |
281 | } | 282 | } |
282 | 283 | ||
283 | static void put_pipe_version(void) | 284 | static void put_pipe_version(struct net *net) |
284 | { | 285 | { |
285 | if (atomic_dec_and_lock(&pipe_users, &pipe_version_lock)) { | 286 | struct sunrpc_net *sn = net_generic(net, sunrpc_net_id); |
286 | pipe_version = -1; | 287 | |
288 | if (atomic_dec_and_lock(&sn->pipe_users, &pipe_version_lock)) { | ||
289 | sn->pipe_version = -1; | ||
287 | spin_unlock(&pipe_version_lock); | 290 | spin_unlock(&pipe_version_lock); |
288 | } | 291 | } |
289 | } | 292 | } |
@@ -291,9 +294,10 @@ static void put_pipe_version(void) | |||
291 | static void | 294 | static void |
292 | gss_release_msg(struct gss_upcall_msg *gss_msg) | 295 | gss_release_msg(struct gss_upcall_msg *gss_msg) |
293 | { | 296 | { |
297 | struct net *net = rpc_net_ns(gss_msg->auth->client); | ||
294 | if (!atomic_dec_and_test(&gss_msg->count)) | 298 | if (!atomic_dec_and_test(&gss_msg->count)) |
295 | return; | 299 | return; |
296 | put_pipe_version(); | 300 | put_pipe_version(net); |
297 | BUG_ON(!list_empty(&gss_msg->list)); | 301 | BUG_ON(!list_empty(&gss_msg->list)); |
298 | if (gss_msg->ctx != NULL) | 302 | if (gss_msg->ctx != NULL) |
299 | gss_put_ctx(gss_msg->ctx); | 303 | gss_put_ctx(gss_msg->ctx); |
@@ -439,7 +443,10 @@ static void gss_encode_msg(struct gss_upcall_msg *gss_msg, | |||
439 | struct rpc_clnt *clnt, | 443 | struct rpc_clnt *clnt, |
440 | const char *service_name) | 444 | const char *service_name) |
441 | { | 445 | { |
442 | if (pipe_version == 0) | 446 | struct net *net = rpc_net_ns(clnt); |
447 | struct sunrpc_net *sn = net_generic(net, sunrpc_net_id); | ||
448 | |||
449 | if (sn->pipe_version == 0) | ||
443 | gss_encode_v0_msg(gss_msg); | 450 | gss_encode_v0_msg(gss_msg); |
444 | else /* pipe_version == 1 */ | 451 | else /* pipe_version == 1 */ |
445 | gss_encode_v1_msg(gss_msg, clnt, service_name); | 452 | gss_encode_v1_msg(gss_msg, clnt, service_name); |
@@ -455,7 +462,7 @@ gss_alloc_msg(struct gss_auth *gss_auth, struct rpc_clnt *clnt, | |||
455 | gss_msg = kzalloc(sizeof(*gss_msg), GFP_NOFS); | 462 | gss_msg = kzalloc(sizeof(*gss_msg), GFP_NOFS); |
456 | if (gss_msg == NULL) | 463 | if (gss_msg == NULL) |
457 | return ERR_PTR(-ENOMEM); | 464 | return ERR_PTR(-ENOMEM); |
458 | vers = get_pipe_version(); | 465 | vers = get_pipe_version(rpc_net_ns(clnt)); |
459 | if (vers < 0) { | 466 | if (vers < 0) { |
460 | kfree(gss_msg); | 467 | kfree(gss_msg); |
461 | return ERR_PTR(vers); | 468 | return ERR_PTR(vers); |
@@ -559,24 +566,34 @@ out: | |||
559 | static inline int | 566 | static inline int |
560 | gss_create_upcall(struct gss_auth *gss_auth, struct gss_cred *gss_cred) | 567 | gss_create_upcall(struct gss_auth *gss_auth, struct gss_cred *gss_cred) |
561 | { | 568 | { |
569 | struct net *net = rpc_net_ns(gss_auth->client); | ||
570 | struct sunrpc_net *sn = net_generic(net, sunrpc_net_id); | ||
562 | struct rpc_pipe *pipe; | 571 | struct rpc_pipe *pipe; |
563 | struct rpc_cred *cred = &gss_cred->gc_base; | 572 | struct rpc_cred *cred = &gss_cred->gc_base; |
564 | struct gss_upcall_msg *gss_msg; | 573 | struct gss_upcall_msg *gss_msg; |
574 | unsigned long timeout; | ||
565 | DEFINE_WAIT(wait); | 575 | DEFINE_WAIT(wait); |
566 | int err = 0; | 576 | int err; |
567 | 577 | ||
568 | dprintk("RPC: %s for uid %u\n", | 578 | dprintk("RPC: %s for uid %u\n", |
569 | __func__, from_kuid(&init_user_ns, cred->cr_uid)); | 579 | __func__, from_kuid(&init_user_ns, cred->cr_uid)); |
570 | retry: | 580 | retry: |
581 | err = 0; | ||
582 | /* Default timeout is 15s unless we know that gssd is not running */ | ||
583 | timeout = 15 * HZ; | ||
584 | if (!sn->gssd_running) | ||
585 | timeout = HZ >> 2; | ||
571 | gss_msg = gss_setup_upcall(gss_auth->client, gss_auth, cred); | 586 | gss_msg = gss_setup_upcall(gss_auth->client, gss_auth, cred); |
572 | if (PTR_ERR(gss_msg) == -EAGAIN) { | 587 | if (PTR_ERR(gss_msg) == -EAGAIN) { |
573 | err = wait_event_interruptible_timeout(pipe_version_waitqueue, | 588 | err = wait_event_interruptible_timeout(pipe_version_waitqueue, |
574 | pipe_version >= 0, 15*HZ); | 589 | sn->pipe_version >= 0, timeout); |
575 | if (pipe_version < 0) { | 590 | if (sn->pipe_version < 0) { |
591 | if (err == 0) | ||
592 | sn->gssd_running = 0; | ||
576 | warn_gssd(); | 593 | warn_gssd(); |
577 | err = -EACCES; | 594 | err = -EACCES; |
578 | } | 595 | } |
579 | if (err) | 596 | if (err < 0) |
580 | goto out; | 597 | goto out; |
581 | goto retry; | 598 | goto retry; |
582 | } | 599 | } |
@@ -707,20 +724,22 @@ out: | |||
707 | 724 | ||
708 | static int gss_pipe_open(struct inode *inode, int new_version) | 725 | static int gss_pipe_open(struct inode *inode, int new_version) |
709 | { | 726 | { |
727 | struct net *net = inode->i_sb->s_fs_info; | ||
728 | struct sunrpc_net *sn = net_generic(net, sunrpc_net_id); | ||
710 | int ret = 0; | 729 | int ret = 0; |
711 | 730 | ||
712 | spin_lock(&pipe_version_lock); | 731 | spin_lock(&pipe_version_lock); |
713 | if (pipe_version < 0) { | 732 | if (sn->pipe_version < 0) { |
714 | /* First open of any gss pipe determines the version: */ | 733 | /* First open of any gss pipe determines the version: */ |
715 | pipe_version = new_version; | 734 | sn->pipe_version = new_version; |
716 | rpc_wake_up(&pipe_version_rpc_waitqueue); | 735 | rpc_wake_up(&pipe_version_rpc_waitqueue); |
717 | wake_up(&pipe_version_waitqueue); | 736 | wake_up(&pipe_version_waitqueue); |
718 | } else if (pipe_version != new_version) { | 737 | } else if (sn->pipe_version != new_version) { |
719 | /* Trying to open a pipe of a different version */ | 738 | /* Trying to open a pipe of a different version */ |
720 | ret = -EBUSY; | 739 | ret = -EBUSY; |
721 | goto out; | 740 | goto out; |
722 | } | 741 | } |
723 | atomic_inc(&pipe_users); | 742 | atomic_inc(&sn->pipe_users); |
724 | out: | 743 | out: |
725 | spin_unlock(&pipe_version_lock); | 744 | spin_unlock(&pipe_version_lock); |
726 | return ret; | 745 | return ret; |
@@ -740,6 +759,7 @@ static int gss_pipe_open_v1(struct inode *inode) | |||
740 | static void | 759 | static void |
741 | gss_pipe_release(struct inode *inode) | 760 | gss_pipe_release(struct inode *inode) |
742 | { | 761 | { |
762 | struct net *net = inode->i_sb->s_fs_info; | ||
743 | struct rpc_pipe *pipe = RPC_I(inode)->pipe; | 763 | struct rpc_pipe *pipe = RPC_I(inode)->pipe; |
744 | struct gss_upcall_msg *gss_msg; | 764 | struct gss_upcall_msg *gss_msg; |
745 | 765 | ||
@@ -758,7 +778,7 @@ restart: | |||
758 | } | 778 | } |
759 | spin_unlock(&pipe->lock); | 779 | spin_unlock(&pipe->lock); |
760 | 780 | ||
761 | put_pipe_version(); | 781 | put_pipe_version(net); |
762 | } | 782 | } |
763 | 783 | ||
764 | static void | 784 | static void |
diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c index 5a750b9c3640..f0339ae9bf37 100644 --- a/net/sunrpc/clnt.c +++ b/net/sunrpc/clnt.c | |||
@@ -157,20 +157,15 @@ static struct dentry *rpc_setup_pipedir_sb(struct super_block *sb, | |||
157 | } | 157 | } |
158 | 158 | ||
159 | static int | 159 | static int |
160 | rpc_setup_pipedir(struct rpc_clnt *clnt, const char *dir_name) | 160 | rpc_setup_pipedir(struct rpc_clnt *clnt, const char *dir_name, |
161 | struct super_block *pipefs_sb) | ||
161 | { | 162 | { |
162 | struct net *net = rpc_net_ns(clnt); | ||
163 | struct super_block *pipefs_sb; | ||
164 | struct dentry *dentry; | 163 | struct dentry *dentry; |
165 | 164 | ||
166 | clnt->cl_dentry = NULL; | 165 | clnt->cl_dentry = NULL; |
167 | if (dir_name == NULL) | 166 | if (dir_name == NULL) |
168 | return 0; | 167 | return 0; |
169 | pipefs_sb = rpc_get_sb_net(net); | ||
170 | if (!pipefs_sb) | ||
171 | return 0; | ||
172 | dentry = rpc_setup_pipedir_sb(pipefs_sb, clnt, dir_name); | 168 | dentry = rpc_setup_pipedir_sb(pipefs_sb, clnt, dir_name); |
173 | rpc_put_sb_net(net); | ||
174 | if (IS_ERR(dentry)) | 169 | if (IS_ERR(dentry)) |
175 | return PTR_ERR(dentry); | 170 | return PTR_ERR(dentry); |
176 | clnt->cl_dentry = dentry; | 171 | clnt->cl_dentry = dentry; |
@@ -182,6 +177,8 @@ static inline int rpc_clnt_skip_event(struct rpc_clnt *clnt, unsigned long event | |||
182 | if (((event == RPC_PIPEFS_MOUNT) && clnt->cl_dentry) || | 177 | if (((event == RPC_PIPEFS_MOUNT) && clnt->cl_dentry) || |
183 | ((event == RPC_PIPEFS_UMOUNT) && !clnt->cl_dentry)) | 178 | ((event == RPC_PIPEFS_UMOUNT) && !clnt->cl_dentry)) |
184 | return 1; | 179 | return 1; |
180 | if ((event == RPC_PIPEFS_MOUNT) && atomic_read(&clnt->cl_count) == 0) | ||
181 | return 1; | ||
185 | return 0; | 182 | return 0; |
186 | } | 183 | } |
187 | 184 | ||
@@ -241,8 +238,6 @@ static struct rpc_clnt *rpc_get_client_for_event(struct net *net, int event) | |||
241 | continue; | 238 | continue; |
242 | if (rpc_clnt_skip_event(clnt, event)) | 239 | if (rpc_clnt_skip_event(clnt, event)) |
243 | continue; | 240 | continue; |
244 | if (atomic_inc_not_zero(&clnt->cl_count) == 0) | ||
245 | continue; | ||
246 | spin_unlock(&sn->rpc_client_lock); | 241 | spin_unlock(&sn->rpc_client_lock); |
247 | return clnt; | 242 | return clnt; |
248 | } | 243 | } |
@@ -259,7 +254,6 @@ static int rpc_pipefs_event(struct notifier_block *nb, unsigned long event, | |||
259 | 254 | ||
260 | while ((clnt = rpc_get_client_for_event(sb->s_fs_info, event))) { | 255 | while ((clnt = rpc_get_client_for_event(sb->s_fs_info, event))) { |
261 | error = __rpc_pipefs_event(clnt, event, sb); | 256 | error = __rpc_pipefs_event(clnt, event, sb); |
262 | rpc_release_client(clnt); | ||
263 | if (error) | 257 | if (error) |
264 | break; | 258 | break; |
265 | } | 259 | } |
@@ -289,12 +283,46 @@ static void rpc_clnt_set_nodename(struct rpc_clnt *clnt, const char *nodename) | |||
289 | memcpy(clnt->cl_nodename, nodename, clnt->cl_nodelen); | 283 | memcpy(clnt->cl_nodename, nodename, clnt->cl_nodelen); |
290 | } | 284 | } |
291 | 285 | ||
286 | static int rpc_client_register(const struct rpc_create_args *args, | ||
287 | struct rpc_clnt *clnt) | ||
288 | { | ||
289 | const struct rpc_program *program = args->program; | ||
290 | struct rpc_auth *auth; | ||
291 | struct net *net = rpc_net_ns(clnt); | ||
292 | struct super_block *pipefs_sb; | ||
293 | int err = 0; | ||
294 | |||
295 | pipefs_sb = rpc_get_sb_net(net); | ||
296 | if (pipefs_sb) { | ||
297 | err = rpc_setup_pipedir(clnt, program->pipe_dir_name, pipefs_sb); | ||
298 | if (err) | ||
299 | goto out; | ||
300 | } | ||
301 | |||
302 | auth = rpcauth_create(args->authflavor, clnt); | ||
303 | if (IS_ERR(auth)) { | ||
304 | dprintk("RPC: Couldn't create auth handle (flavor %u)\n", | ||
305 | args->authflavor); | ||
306 | err = PTR_ERR(auth); | ||
307 | goto err_auth; | ||
308 | } | ||
309 | |||
310 | rpc_register_client(clnt); | ||
311 | out: | ||
312 | if (pipefs_sb) | ||
313 | rpc_put_sb_net(net); | ||
314 | return err; | ||
315 | |||
316 | err_auth: | ||
317 | __rpc_clnt_remove_pipedir(clnt); | ||
318 | goto out; | ||
319 | } | ||
320 | |||
292 | static struct rpc_clnt * rpc_new_client(const struct rpc_create_args *args, struct rpc_xprt *xprt) | 321 | static struct rpc_clnt * rpc_new_client(const struct rpc_create_args *args, struct rpc_xprt *xprt) |
293 | { | 322 | { |
294 | const struct rpc_program *program = args->program; | 323 | const struct rpc_program *program = args->program; |
295 | const struct rpc_version *version; | 324 | const struct rpc_version *version; |
296 | struct rpc_clnt *clnt = NULL; | 325 | struct rpc_clnt *clnt = NULL; |
297 | struct rpc_auth *auth; | ||
298 | int err; | 326 | int err; |
299 | 327 | ||
300 | /* sanity check the name before trying to print it */ | 328 | /* sanity check the name before trying to print it */ |
@@ -354,25 +382,14 @@ static struct rpc_clnt * rpc_new_client(const struct rpc_create_args *args, stru | |||
354 | 382 | ||
355 | atomic_set(&clnt->cl_count, 1); | 383 | atomic_set(&clnt->cl_count, 1); |
356 | 384 | ||
357 | err = rpc_setup_pipedir(clnt, program->pipe_dir_name); | ||
358 | if (err < 0) | ||
359 | goto out_no_path; | ||
360 | |||
361 | auth = rpcauth_create(args->authflavor, clnt); | ||
362 | if (IS_ERR(auth)) { | ||
363 | dprintk("RPC: Couldn't create auth handle (flavor %u)\n", | ||
364 | args->authflavor); | ||
365 | err = PTR_ERR(auth); | ||
366 | goto out_no_auth; | ||
367 | } | ||
368 | |||
369 | /* save the nodename */ | 385 | /* save the nodename */ |
370 | rpc_clnt_set_nodename(clnt, utsname()->nodename); | 386 | rpc_clnt_set_nodename(clnt, utsname()->nodename); |
371 | rpc_register_client(clnt); | 387 | |
388 | err = rpc_client_register(args, clnt); | ||
389 | if (err) | ||
390 | goto out_no_path; | ||
372 | return clnt; | 391 | return clnt; |
373 | 392 | ||
374 | out_no_auth: | ||
375 | rpc_clnt_remove_pipedir(clnt); | ||
376 | out_no_path: | 393 | out_no_path: |
377 | kfree(clnt->cl_principal); | 394 | kfree(clnt->cl_principal); |
378 | out_no_principal: | 395 | out_no_principal: |
@@ -637,8 +654,8 @@ rpc_free_client(struct rpc_clnt *clnt) | |||
637 | rcu_dereference(clnt->cl_xprt)->servername); | 654 | rcu_dereference(clnt->cl_xprt)->servername); |
638 | if (clnt->cl_parent != clnt) | 655 | if (clnt->cl_parent != clnt) |
639 | rpc_release_client(clnt->cl_parent); | 656 | rpc_release_client(clnt->cl_parent); |
640 | rpc_unregister_client(clnt); | ||
641 | rpc_clnt_remove_pipedir(clnt); | 657 | rpc_clnt_remove_pipedir(clnt); |
658 | rpc_unregister_client(clnt); | ||
642 | rpc_free_iostats(clnt->cl_metrics); | 659 | rpc_free_iostats(clnt->cl_metrics); |
643 | kfree(clnt->cl_principal); | 660 | kfree(clnt->cl_principal); |
644 | clnt->cl_metrics = NULL; | 661 | clnt->cl_metrics = NULL; |
diff --git a/net/sunrpc/netns.h b/net/sunrpc/netns.h index 7111a4c9113b..74d948f5d5a1 100644 --- a/net/sunrpc/netns.h +++ b/net/sunrpc/netns.h | |||
@@ -28,7 +28,11 @@ struct sunrpc_net { | |||
28 | wait_queue_head_t gssp_wq; | 28 | wait_queue_head_t gssp_wq; |
29 | struct rpc_clnt *gssp_clnt; | 29 | struct rpc_clnt *gssp_clnt; |
30 | int use_gss_proxy; | 30 | int use_gss_proxy; |
31 | int pipe_version; | ||
32 | atomic_t pipe_users; | ||
31 | struct proc_dir_entry *use_gssp_proc; | 33 | struct proc_dir_entry *use_gssp_proc; |
34 | |||
35 | unsigned int gssd_running; | ||
32 | }; | 36 | }; |
33 | 37 | ||
34 | extern int sunrpc_net_id; | 38 | extern int sunrpc_net_id; |
diff --git a/net/sunrpc/rpc_pipe.c b/net/sunrpc/rpc_pipe.c index a9129f8d7070..4679df5a6d50 100644 --- a/net/sunrpc/rpc_pipe.c +++ b/net/sunrpc/rpc_pipe.c | |||
@@ -216,11 +216,14 @@ rpc_destroy_inode(struct inode *inode) | |||
216 | static int | 216 | static int |
217 | rpc_pipe_open(struct inode *inode, struct file *filp) | 217 | rpc_pipe_open(struct inode *inode, struct file *filp) |
218 | { | 218 | { |
219 | struct net *net = inode->i_sb->s_fs_info; | ||
220 | struct sunrpc_net *sn = net_generic(net, sunrpc_net_id); | ||
219 | struct rpc_pipe *pipe; | 221 | struct rpc_pipe *pipe; |
220 | int first_open; | 222 | int first_open; |
221 | int res = -ENXIO; | 223 | int res = -ENXIO; |
222 | 224 | ||
223 | mutex_lock(&inode->i_mutex); | 225 | mutex_lock(&inode->i_mutex); |
226 | sn->gssd_running = 1; | ||
224 | pipe = RPC_I(inode)->pipe; | 227 | pipe = RPC_I(inode)->pipe; |
225 | if (pipe == NULL) | 228 | if (pipe == NULL) |
226 | goto out; | 229 | goto out; |
@@ -664,7 +667,8 @@ static struct dentry *__rpc_lookup_create_exclusive(struct dentry *parent, | |||
664 | return ERR_PTR(-ENOMEM); | 667 | return ERR_PTR(-ENOMEM); |
665 | } | 668 | } |
666 | if (dentry->d_inode == NULL) { | 669 | if (dentry->d_inode == NULL) { |
667 | d_set_d_op(dentry, &rpc_dentry_operations); | 670 | if (!dentry->d_op) |
671 | d_set_d_op(dentry, &rpc_dentry_operations); | ||
668 | return dentry; | 672 | return dentry; |
669 | } | 673 | } |
670 | dput(dentry); | 674 | dput(dentry); |
@@ -1069,6 +1073,8 @@ void rpc_pipefs_init_net(struct net *net) | |||
1069 | struct sunrpc_net *sn = net_generic(net, sunrpc_net_id); | 1073 | struct sunrpc_net *sn = net_generic(net, sunrpc_net_id); |
1070 | 1074 | ||
1071 | mutex_init(&sn->pipefs_sb_lock); | 1075 | mutex_init(&sn->pipefs_sb_lock); |
1076 | sn->gssd_running = 1; | ||
1077 | sn->pipe_version = -1; | ||
1072 | } | 1078 | } |
1073 | 1079 | ||
1074 | /* | 1080 | /* |
@@ -1121,6 +1127,7 @@ rpc_fill_super(struct super_block *sb, void *data, int silent) | |||
1121 | return -ENOMEM; | 1127 | return -ENOMEM; |
1122 | dprintk("RPC: sending pipefs MOUNT notification for net %p%s\n", | 1128 | dprintk("RPC: sending pipefs MOUNT notification for net %p%s\n", |
1123 | net, NET_NAME(net)); | 1129 | net, NET_NAME(net)); |
1130 | mutex_lock(&sn->pipefs_sb_lock); | ||
1124 | sn->pipefs_sb = sb; | 1131 | sn->pipefs_sb = sb; |
1125 | err = blocking_notifier_call_chain(&rpc_pipefs_notifier_list, | 1132 | err = blocking_notifier_call_chain(&rpc_pipefs_notifier_list, |
1126 | RPC_PIPEFS_MOUNT, | 1133 | RPC_PIPEFS_MOUNT, |
@@ -1128,6 +1135,7 @@ rpc_fill_super(struct super_block *sb, void *data, int silent) | |||
1128 | if (err) | 1135 | if (err) |
1129 | goto err_depopulate; | 1136 | goto err_depopulate; |
1130 | sb->s_fs_info = get_net(net); | 1137 | sb->s_fs_info = get_net(net); |
1138 | mutex_unlock(&sn->pipefs_sb_lock); | ||
1131 | return 0; | 1139 | return 0; |
1132 | 1140 | ||
1133 | err_depopulate: | 1141 | err_depopulate: |
@@ -1136,6 +1144,7 @@ err_depopulate: | |||
1136 | sb); | 1144 | sb); |
1137 | sn->pipefs_sb = NULL; | 1145 | sn->pipefs_sb = NULL; |
1138 | __rpc_depopulate(root, files, RPCAUTH_lockd, RPCAUTH_RootEOF); | 1146 | __rpc_depopulate(root, files, RPCAUTH_lockd, RPCAUTH_RootEOF); |
1147 | mutex_unlock(&sn->pipefs_sb_lock); | ||
1139 | return err; | 1148 | return err; |
1140 | } | 1149 | } |
1141 | 1150 | ||
@@ -1157,12 +1166,12 @@ static void rpc_kill_sb(struct super_block *sb) | |||
1157 | goto out; | 1166 | goto out; |
1158 | } | 1167 | } |
1159 | sn->pipefs_sb = NULL; | 1168 | sn->pipefs_sb = NULL; |
1160 | mutex_unlock(&sn->pipefs_sb_lock); | ||
1161 | dprintk("RPC: sending pipefs UMOUNT notification for net %p%s\n", | 1169 | dprintk("RPC: sending pipefs UMOUNT notification for net %p%s\n", |
1162 | net, NET_NAME(net)); | 1170 | net, NET_NAME(net)); |
1163 | blocking_notifier_call_chain(&rpc_pipefs_notifier_list, | 1171 | blocking_notifier_call_chain(&rpc_pipefs_notifier_list, |
1164 | RPC_PIPEFS_UMOUNT, | 1172 | RPC_PIPEFS_UMOUNT, |
1165 | sb); | 1173 | sb); |
1174 | mutex_unlock(&sn->pipefs_sb_lock); | ||
1166 | put_net(net); | 1175 | put_net(net); |
1167 | out: | 1176 | out: |
1168 | kill_litter_super(sb); | 1177 | kill_litter_super(sb); |
diff --git a/net/sunrpc/sched.c b/net/sunrpc/sched.c index f8529fc8e542..b7b32c34c18d 100644 --- a/net/sunrpc/sched.c +++ b/net/sunrpc/sched.c | |||
@@ -324,11 +324,17 @@ EXPORT_SYMBOL_GPL(__rpc_wait_for_completion_task); | |||
324 | * Note: If the task is ASYNC, and is being made runnable after sitting on an | 324 | * Note: If the task is ASYNC, and is being made runnable after sitting on an |
325 | * rpc_wait_queue, this must be called with the queue spinlock held to protect | 325 | * rpc_wait_queue, this must be called with the queue spinlock held to protect |
326 | * the wait queue operation. | 326 | * the wait queue operation. |
327 | * Note the ordering of rpc_test_and_set_running() and rpc_clear_queued(), | ||
328 | * which is needed to ensure that __rpc_execute() doesn't loop (due to the | ||
329 | * lockless RPC_IS_QUEUED() test) before we've had a chance to test | ||
330 | * the RPC_TASK_RUNNING flag. | ||
327 | */ | 331 | */ |
328 | static void rpc_make_runnable(struct rpc_task *task) | 332 | static void rpc_make_runnable(struct rpc_task *task) |
329 | { | 333 | { |
334 | bool need_wakeup = !rpc_test_and_set_running(task); | ||
335 | |||
330 | rpc_clear_queued(task); | 336 | rpc_clear_queued(task); |
331 | if (rpc_test_and_set_running(task)) | 337 | if (!need_wakeup) |
332 | return; | 338 | return; |
333 | if (RPC_IS_ASYNC(task)) { | 339 | if (RPC_IS_ASYNC(task)) { |
334 | INIT_WORK(&task->u.tk_work, rpc_async_schedule); | 340 | INIT_WORK(&task->u.tk_work, rpc_async_schedule); |
@@ -440,20 +446,6 @@ static void rpc_wake_up_task_queue_locked(struct rpc_wait_queue *queue, struct r | |||
440 | } | 446 | } |
441 | 447 | ||
442 | /* | 448 | /* |
443 | * Tests whether rpc queue is empty | ||
444 | */ | ||
445 | int rpc_queue_empty(struct rpc_wait_queue *queue) | ||
446 | { | ||
447 | int res; | ||
448 | |||
449 | spin_lock_bh(&queue->lock); | ||
450 | res = queue->qlen; | ||
451 | spin_unlock_bh(&queue->lock); | ||
452 | return res == 0; | ||
453 | } | ||
454 | EXPORT_SYMBOL_GPL(rpc_queue_empty); | ||
455 | |||
456 | /* | ||
457 | * Wake up a task on a specific queue | 449 | * Wake up a task on a specific queue |
458 | */ | 450 | */ |
459 | void rpc_wake_up_queued_task(struct rpc_wait_queue *queue, struct rpc_task *task) | 451 | void rpc_wake_up_queued_task(struct rpc_wait_queue *queue, struct rpc_task *task) |
@@ -798,7 +790,6 @@ static void __rpc_execute(struct rpc_task *task) | |||
798 | task->tk_flags |= RPC_TASK_KILLED; | 790 | task->tk_flags |= RPC_TASK_KILLED; |
799 | rpc_exit(task, -ERESTARTSYS); | 791 | rpc_exit(task, -ERESTARTSYS); |
800 | } | 792 | } |
801 | rpc_set_running(task); | ||
802 | dprintk("RPC: %5u sync task resuming\n", task->tk_pid); | 793 | dprintk("RPC: %5u sync task resuming\n", task->tk_pid); |
803 | } | 794 | } |
804 | 795 | ||
@@ -819,9 +810,11 @@ static void __rpc_execute(struct rpc_task *task) | |||
819 | */ | 810 | */ |
820 | void rpc_execute(struct rpc_task *task) | 811 | void rpc_execute(struct rpc_task *task) |
821 | { | 812 | { |
813 | bool is_async = RPC_IS_ASYNC(task); | ||
814 | |||
822 | rpc_set_active(task); | 815 | rpc_set_active(task); |
823 | rpc_make_runnable(task); | 816 | rpc_make_runnable(task); |
824 | if (!RPC_IS_ASYNC(task)) | 817 | if (!is_async) |
825 | __rpc_execute(task); | 818 | __rpc_execute(task); |
826 | } | 819 | } |
827 | 820 | ||