aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2015-01-16 13:59:06 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2015-01-16 13:59:06 -0500
commita2a32cd1d7c3085da129ab6e2060f6afae187176 (patch)
tree05ca46cf9b32d4dd560b7b2836b8d65ce953cca0
parent23aa4b416afdf37869e53c188944dd7c4c47949a (diff)
parent4e379d36c050b0117b5d10048be63a44f5036115 (diff)
Merge tag 'nfs-for-3.19-2' of git://git.linux-nfs.org/projects/trondmy/linux-nfs
Pull NFS client bugfixes from Trond Myklebust: "Highlights include: - Stable fix for a NFSv3/lockd race - Fixes for several NFSv4.1 client id trunking bugs - Remove an incorrect test when checking for delegated opens" * tag 'nfs-for-3.19-2' of git://git.linux-nfs.org/projects/trondmy/linux-nfs: NFSv4: Remove incorrect check in can_open_delegated() NFS: Ignore transport protocol when detecting server trunking NFSv4/v4.1: Verify the client owner id during trunking detection NFSv4: Cache the NFSv4/v4.1 client owner_id in the struct nfs_client NFSv4.1: Fix client id trunking on Linux LOCKD: Fix a race when initialising nlmsvc_timeout
-rw-r--r--fs/lockd/svc.c8
-rw-r--r--fs/nfs/nfs4client.c42
-rw-r--r--fs/nfs/nfs4proc.c21
-rw-r--r--include/linux/nfs_fs_sb.h3
4 files changed, 49 insertions, 25 deletions
diff --git a/fs/lockd/svc.c b/fs/lockd/svc.c
index e94c887da2d7..55505cbe11af 100644
--- a/fs/lockd/svc.c
+++ b/fs/lockd/svc.c
@@ -138,10 +138,6 @@ lockd(void *vrqstp)
138 138
139 dprintk("NFS locking service started (ver " LOCKD_VERSION ").\n"); 139 dprintk("NFS locking service started (ver " LOCKD_VERSION ").\n");
140 140
141 if (!nlm_timeout)
142 nlm_timeout = LOCKD_DFLT_TIMEO;
143 nlmsvc_timeout = nlm_timeout * HZ;
144
145 /* 141 /*
146 * The main request loop. We don't terminate until the last 142 * The main request loop. We don't terminate until the last
147 * NFS mount or NFS daemon has gone away. 143 * NFS mount or NFS daemon has gone away.
@@ -350,6 +346,10 @@ static struct svc_serv *lockd_create_svc(void)
350 printk(KERN_WARNING 346 printk(KERN_WARNING
351 "lockd_up: no pid, %d users??\n", nlmsvc_users); 347 "lockd_up: no pid, %d users??\n", nlmsvc_users);
352 348
349 if (!nlm_timeout)
350 nlm_timeout = LOCKD_DFLT_TIMEO;
351 nlmsvc_timeout = nlm_timeout * HZ;
352
353 serv = svc_create(&nlmsvc_program, LOCKD_BUFSIZE, svc_rpcb_cleanup); 353 serv = svc_create(&nlmsvc_program, LOCKD_BUFSIZE, svc_rpcb_cleanup);
354 if (!serv) { 354 if (!serv) {
355 printk(KERN_WARNING "lockd_up: create service failed\n"); 355 printk(KERN_WARNING "lockd_up: create service failed\n");
diff --git a/fs/nfs/nfs4client.c b/fs/nfs/nfs4client.c
index 03311259b0c4..953daa44a282 100644
--- a/fs/nfs/nfs4client.c
+++ b/fs/nfs/nfs4client.c
@@ -228,6 +228,7 @@ static void nfs4_shutdown_client(struct nfs_client *clp)
228 kfree(clp->cl_serverowner); 228 kfree(clp->cl_serverowner);
229 kfree(clp->cl_serverscope); 229 kfree(clp->cl_serverscope);
230 kfree(clp->cl_implid); 230 kfree(clp->cl_implid);
231 kfree(clp->cl_owner_id);
231} 232}
232 233
233void nfs4_free_client(struct nfs_client *clp) 234void nfs4_free_client(struct nfs_client *clp)
@@ -452,6 +453,14 @@ static void nfs4_swap_callback_idents(struct nfs_client *keep,
452 spin_unlock(&nn->nfs_client_lock); 453 spin_unlock(&nn->nfs_client_lock);
453} 454}
454 455
456static bool nfs4_match_client_owner_id(const struct nfs_client *clp1,
457 const struct nfs_client *clp2)
458{
459 if (clp1->cl_owner_id == NULL || clp2->cl_owner_id == NULL)
460 return true;
461 return strcmp(clp1->cl_owner_id, clp2->cl_owner_id) == 0;
462}
463
455/** 464/**
456 * nfs40_walk_client_list - Find server that recognizes a client ID 465 * nfs40_walk_client_list - Find server that recognizes a client ID
457 * 466 *
@@ -483,9 +492,6 @@ int nfs40_walk_client_list(struct nfs_client *new,
483 if (pos->rpc_ops != new->rpc_ops) 492 if (pos->rpc_ops != new->rpc_ops)
484 continue; 493 continue;
485 494
486 if (pos->cl_proto != new->cl_proto)
487 continue;
488
489 if (pos->cl_minorversion != new->cl_minorversion) 495 if (pos->cl_minorversion != new->cl_minorversion)
490 continue; 496 continue;
491 497
@@ -510,6 +516,9 @@ int nfs40_walk_client_list(struct nfs_client *new,
510 if (pos->cl_clientid != new->cl_clientid) 516 if (pos->cl_clientid != new->cl_clientid)
511 continue; 517 continue;
512 518
519 if (!nfs4_match_client_owner_id(pos, new))
520 continue;
521
513 atomic_inc(&pos->cl_count); 522 atomic_inc(&pos->cl_count);
514 spin_unlock(&nn->nfs_client_lock); 523 spin_unlock(&nn->nfs_client_lock);
515 524
@@ -566,20 +575,14 @@ static bool nfs4_match_clientids(struct nfs_client *a, struct nfs_client *b)
566} 575}
567 576
568/* 577/*
569 * Returns true if the server owners match 578 * Returns true if the server major ids match
570 */ 579 */
571static bool 580static bool
572nfs4_match_serverowners(struct nfs_client *a, struct nfs_client *b) 581nfs4_check_clientid_trunking(struct nfs_client *a, struct nfs_client *b)
573{ 582{
574 struct nfs41_server_owner *o1 = a->cl_serverowner; 583 struct nfs41_server_owner *o1 = a->cl_serverowner;
575 struct nfs41_server_owner *o2 = b->cl_serverowner; 584 struct nfs41_server_owner *o2 = b->cl_serverowner;
576 585
577 if (o1->minor_id != o2->minor_id) {
578 dprintk("NFS: --> %s server owner minor IDs do not match\n",
579 __func__);
580 return false;
581 }
582
583 if (o1->major_id_sz != o2->major_id_sz) 586 if (o1->major_id_sz != o2->major_id_sz)
584 goto out_major_mismatch; 587 goto out_major_mismatch;
585 if (memcmp(o1->major_id, o2->major_id, o1->major_id_sz) != 0) 588 if (memcmp(o1->major_id, o2->major_id, o1->major_id_sz) != 0)
@@ -621,9 +624,6 @@ int nfs41_walk_client_list(struct nfs_client *new,
621 if (pos->rpc_ops != new->rpc_ops) 624 if (pos->rpc_ops != new->rpc_ops)
622 continue; 625 continue;
623 626
624 if (pos->cl_proto != new->cl_proto)
625 continue;
626
627 if (pos->cl_minorversion != new->cl_minorversion) 627 if (pos->cl_minorversion != new->cl_minorversion)
628 continue; 628 continue;
629 629
@@ -654,7 +654,19 @@ int nfs41_walk_client_list(struct nfs_client *new,
654 if (!nfs4_match_clientids(pos, new)) 654 if (!nfs4_match_clientids(pos, new))
655 continue; 655 continue;
656 656
657 if (!nfs4_match_serverowners(pos, new)) 657 /*
658 * Note that session trunking is just a special subcase of
659 * client id trunking. In either case, we want to fall back
660 * to using the existing nfs_client.
661 */
662 if (!nfs4_check_clientid_trunking(pos, new))
663 continue;
664
665 /* Unlike NFSv4.0, we know that NFSv4.1 always uses the
666 * uniform string, however someone might switch the
667 * uniquifier string on us.
668 */
669 if (!nfs4_match_client_owner_id(pos, new))
658 continue; 670 continue;
659 671
660 atomic_inc(&pos->cl_count); 672 atomic_inc(&pos->cl_count);
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index e7f8d5ff2581..c347705b0161 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -1117,8 +1117,6 @@ static int can_open_delegated(struct nfs_delegation *delegation, fmode_t fmode)
1117 return 0; 1117 return 0;
1118 if ((delegation->type & fmode) != fmode) 1118 if ((delegation->type & fmode) != fmode)
1119 return 0; 1119 return 0;
1120 if (test_bit(NFS_DELEGATION_NEED_RECLAIM, &delegation->flags))
1121 return 0;
1122 if (test_bit(NFS_DELEGATION_RETURNING, &delegation->flags)) 1120 if (test_bit(NFS_DELEGATION_RETURNING, &delegation->flags))
1123 return 0; 1121 return 0;
1124 nfs_mark_delegation_referenced(delegation); 1122 nfs_mark_delegation_referenced(delegation);
@@ -4917,11 +4915,14 @@ static void nfs4_init_boot_verifier(const struct nfs_client *clp,
4917} 4915}
4918 4916
4919static unsigned int 4917static unsigned int
4920nfs4_init_nonuniform_client_string(const struct nfs_client *clp, 4918nfs4_init_nonuniform_client_string(struct nfs_client *clp,
4921 char *buf, size_t len) 4919 char *buf, size_t len)
4922{ 4920{
4923 unsigned int result; 4921 unsigned int result;
4924 4922
4923 if (clp->cl_owner_id != NULL)
4924 return strlcpy(buf, clp->cl_owner_id, len);
4925
4925 rcu_read_lock(); 4926 rcu_read_lock();
4926 result = scnprintf(buf, len, "Linux NFSv4.0 %s/%s %s", 4927 result = scnprintf(buf, len, "Linux NFSv4.0 %s/%s %s",
4927 clp->cl_ipaddr, 4928 clp->cl_ipaddr,
@@ -4930,24 +4931,32 @@ nfs4_init_nonuniform_client_string(const struct nfs_client *clp,
4930 rpc_peeraddr2str(clp->cl_rpcclient, 4931 rpc_peeraddr2str(clp->cl_rpcclient,
4931 RPC_DISPLAY_PROTO)); 4932 RPC_DISPLAY_PROTO));
4932 rcu_read_unlock(); 4933 rcu_read_unlock();
4934 clp->cl_owner_id = kstrdup(buf, GFP_KERNEL);
4933 return result; 4935 return result;
4934} 4936}
4935 4937
4936static unsigned int 4938static unsigned int
4937nfs4_init_uniform_client_string(const struct nfs_client *clp, 4939nfs4_init_uniform_client_string(struct nfs_client *clp,
4938 char *buf, size_t len) 4940 char *buf, size_t len)
4939{ 4941{
4940 const char *nodename = clp->cl_rpcclient->cl_nodename; 4942 const char *nodename = clp->cl_rpcclient->cl_nodename;
4943 unsigned int result;
4944
4945 if (clp->cl_owner_id != NULL)
4946 return strlcpy(buf, clp->cl_owner_id, len);
4941 4947
4942 if (nfs4_client_id_uniquifier[0] != '\0') 4948 if (nfs4_client_id_uniquifier[0] != '\0')
4943 return scnprintf(buf, len, "Linux NFSv%u.%u %s/%s", 4949 result = scnprintf(buf, len, "Linux NFSv%u.%u %s/%s",
4944 clp->rpc_ops->version, 4950 clp->rpc_ops->version,
4945 clp->cl_minorversion, 4951 clp->cl_minorversion,
4946 nfs4_client_id_uniquifier, 4952 nfs4_client_id_uniquifier,
4947 nodename); 4953 nodename);
4948 return scnprintf(buf, len, "Linux NFSv%u.%u %s", 4954 else
4955 result = scnprintf(buf, len, "Linux NFSv%u.%u %s",
4949 clp->rpc_ops->version, clp->cl_minorversion, 4956 clp->rpc_ops->version, clp->cl_minorversion,
4950 nodename); 4957 nodename);
4958 clp->cl_owner_id = kstrdup(buf, GFP_KERNEL);
4959 return result;
4951} 4960}
4952 4961
4953/* 4962/*
diff --git a/include/linux/nfs_fs_sb.h b/include/linux/nfs_fs_sb.h
index 1e37fbb78f7a..ddea982355f3 100644
--- a/include/linux/nfs_fs_sb.h
+++ b/include/linux/nfs_fs_sb.h
@@ -74,6 +74,9 @@ struct nfs_client {
74 /* idmapper */ 74 /* idmapper */
75 struct idmap * cl_idmap; 75 struct idmap * cl_idmap;
76 76
77 /* Client owner identifier */
78 const char * cl_owner_id;
79
77 /* Our own IP address, as a null-terminated string. 80 /* Our own IP address, as a null-terminated string.
78 * This is used to generate the mv0 callback address. 81 * This is used to generate the mv0 callback address.
79 */ 82 */