diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2017-04-01 13:43:37 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2017-04-01 13:43:37 -0400 |
commit | 09c8b3d1d6433860e9c51f5fc72f22a9b56ebb52 (patch) | |
tree | 0c33c895c216ba2f367da356cde71f5c6b93c323 | |
parent | fe8e12b5032536d37751c47e1c0446f17e974e5c (diff) | |
parent | 23abec20aa7034c5d49b62c0a668f7291c819fab (diff) |
Merge tag 'nfsd-4.11-1' of git://linux-nfs.org/~bfields/linux
Pull nfsd fixes from Bruce Fields:
"The restriction of NFSv4 to TCP went overboard and also broke the
backchannel; fix.
Also some minor refinements to the nfsd version-setting interface that
we'd like to get fixed before release"
* tag 'nfsd-4.11-1' of git://linux-nfs.org/~bfields/linux:
svcrdma: set XPT_CONG_CTRL flag for bc xprt
NFSD: fix nfsd_reset_versions for NFSv4.
NFSD: fix nfsd_minorversion(.., NFSD_AVAIL)
NFSD: further refinement of content of /proc/fs/nfsd/versions
nfsd: map the ENOKEY to nfserr_perm for avoiding warning
SUNRPC/backchanel: set XPT_CONG_CTRL flag for bc xprt
-rw-r--r-- | fs/nfsd/nfsctl.c | 43 | ||||
-rw-r--r-- | fs/nfsd/nfsproc.c | 1 | ||||
-rw-r--r-- | fs/nfsd/nfssvc.c | 28 | ||||
-rw-r--r-- | net/sunrpc/svcsock.c | 1 | ||||
-rw-r--r-- | net/sunrpc/xprtrdma/svc_rdma_transport.c | 1 |
5 files changed, 49 insertions, 25 deletions
diff --git a/fs/nfsd/nfsctl.c b/fs/nfsd/nfsctl.c index 73e75ac90525..8bf8f667a8cf 100644 --- a/fs/nfsd/nfsctl.c +++ b/fs/nfsd/nfsctl.c | |||
@@ -538,13 +538,21 @@ out_free: | |||
538 | 538 | ||
539 | static ssize_t | 539 | static ssize_t |
540 | nfsd_print_version_support(char *buf, int remaining, const char *sep, | 540 | nfsd_print_version_support(char *buf, int remaining, const char *sep, |
541 | unsigned vers, unsigned minor) | 541 | unsigned vers, int minor) |
542 | { | 542 | { |
543 | const char *format = (minor == 0) ? "%s%c%u" : "%s%c%u.%u"; | 543 | const char *format = minor < 0 ? "%s%c%u" : "%s%c%u.%u"; |
544 | bool supported = !!nfsd_vers(vers, NFSD_TEST); | 544 | bool supported = !!nfsd_vers(vers, NFSD_TEST); |
545 | 545 | ||
546 | if (vers == 4 && !nfsd_minorversion(minor, NFSD_TEST)) | 546 | if (vers == 4 && minor >= 0 && |
547 | !nfsd_minorversion(minor, NFSD_TEST)) | ||
547 | supported = false; | 548 | supported = false; |
549 | if (minor == 0 && supported) | ||
550 | /* | ||
551 | * special case for backward compatability. | ||
552 | * +4.0 is never reported, it is implied by | ||
553 | * +4, unless -4.0 is present. | ||
554 | */ | ||
555 | return 0; | ||
548 | return snprintf(buf, remaining, format, sep, | 556 | return snprintf(buf, remaining, format, sep, |
549 | supported ? '+' : '-', vers, minor); | 557 | supported ? '+' : '-', vers, minor); |
550 | } | 558 | } |
@@ -554,7 +562,6 @@ static ssize_t __write_versions(struct file *file, char *buf, size_t size) | |||
554 | char *mesg = buf; | 562 | char *mesg = buf; |
555 | char *vers, *minorp, sign; | 563 | char *vers, *minorp, sign; |
556 | int len, num, remaining; | 564 | int len, num, remaining; |
557 | unsigned minor; | ||
558 | ssize_t tlen = 0; | 565 | ssize_t tlen = 0; |
559 | char *sep; | 566 | char *sep; |
560 | struct nfsd_net *nn = net_generic(netns(file), nfsd_net_id); | 567 | struct nfsd_net *nn = net_generic(netns(file), nfsd_net_id); |
@@ -575,6 +582,7 @@ static ssize_t __write_versions(struct file *file, char *buf, size_t size) | |||
575 | if (len <= 0) return -EINVAL; | 582 | if (len <= 0) return -EINVAL; |
576 | do { | 583 | do { |
577 | enum vers_op cmd; | 584 | enum vers_op cmd; |
585 | unsigned minor; | ||
578 | sign = *vers; | 586 | sign = *vers; |
579 | if (sign == '+' || sign == '-') | 587 | if (sign == '+' || sign == '-') |
580 | num = simple_strtol((vers+1), &minorp, 0); | 588 | num = simple_strtol((vers+1), &minorp, 0); |
@@ -585,8 +593,8 @@ static ssize_t __write_versions(struct file *file, char *buf, size_t size) | |||
585 | return -EINVAL; | 593 | return -EINVAL; |
586 | if (kstrtouint(minorp+1, 0, &minor) < 0) | 594 | if (kstrtouint(minorp+1, 0, &minor) < 0) |
587 | return -EINVAL; | 595 | return -EINVAL; |
588 | } else | 596 | } |
589 | minor = 0; | 597 | |
590 | cmd = sign == '-' ? NFSD_CLEAR : NFSD_SET; | 598 | cmd = sign == '-' ? NFSD_CLEAR : NFSD_SET; |
591 | switch(num) { | 599 | switch(num) { |
592 | case 2: | 600 | case 2: |
@@ -594,8 +602,20 @@ static ssize_t __write_versions(struct file *file, char *buf, size_t size) | |||
594 | nfsd_vers(num, cmd); | 602 | nfsd_vers(num, cmd); |
595 | break; | 603 | break; |
596 | case 4: | 604 | case 4: |
597 | if (nfsd_minorversion(minor, cmd) >= 0) | 605 | if (*minorp == '.') { |
598 | break; | 606 | if (nfsd_minorversion(minor, cmd) < 0) |
607 | return -EINVAL; | ||
608 | } else if ((cmd == NFSD_SET) != nfsd_vers(num, NFSD_TEST)) { | ||
609 | /* | ||
610 | * Either we have +4 and no minors are enabled, | ||
611 | * or we have -4 and at least one minor is enabled. | ||
612 | * In either case, propagate 'cmd' to all minors. | ||
613 | */ | ||
614 | minor = 0; | ||
615 | while (nfsd_minorversion(minor, cmd) >= 0) | ||
616 | minor++; | ||
617 | } | ||
618 | break; | ||
599 | default: | 619 | default: |
600 | return -EINVAL; | 620 | return -EINVAL; |
601 | } | 621 | } |
@@ -612,9 +632,11 @@ static ssize_t __write_versions(struct file *file, char *buf, size_t size) | |||
612 | sep = ""; | 632 | sep = ""; |
613 | remaining = SIMPLE_TRANSACTION_LIMIT; | 633 | remaining = SIMPLE_TRANSACTION_LIMIT; |
614 | for (num=2 ; num <= 4 ; num++) { | 634 | for (num=2 ; num <= 4 ; num++) { |
635 | int minor; | ||
615 | if (!nfsd_vers(num, NFSD_AVAIL)) | 636 | if (!nfsd_vers(num, NFSD_AVAIL)) |
616 | continue; | 637 | continue; |
617 | minor = 0; | 638 | |
639 | minor = -1; | ||
618 | do { | 640 | do { |
619 | len = nfsd_print_version_support(buf, remaining, | 641 | len = nfsd_print_version_support(buf, remaining, |
620 | sep, num, minor); | 642 | sep, num, minor); |
@@ -624,7 +646,8 @@ static ssize_t __write_versions(struct file *file, char *buf, size_t size) | |||
624 | buf += len; | 646 | buf += len; |
625 | tlen += len; | 647 | tlen += len; |
626 | minor++; | 648 | minor++; |
627 | sep = " "; | 649 | if (len) |
650 | sep = " "; | ||
628 | } while (num == 4 && minor <= NFSD_SUPPORTED_MINOR_VERSION); | 651 | } while (num == 4 && minor <= NFSD_SUPPORTED_MINOR_VERSION); |
629 | } | 652 | } |
630 | out: | 653 | out: |
diff --git a/fs/nfsd/nfsproc.c b/fs/nfsd/nfsproc.c index fa82b7707e85..03a7e9da4da0 100644 --- a/fs/nfsd/nfsproc.c +++ b/fs/nfsd/nfsproc.c | |||
@@ -786,6 +786,7 @@ nfserrno (int errno) | |||
786 | { nfserr_serverfault, -ESERVERFAULT }, | 786 | { nfserr_serverfault, -ESERVERFAULT }, |
787 | { nfserr_serverfault, -ENFILE }, | 787 | { nfserr_serverfault, -ENFILE }, |
788 | { nfserr_io, -EUCLEAN }, | 788 | { nfserr_io, -EUCLEAN }, |
789 | { nfserr_perm, -ENOKEY }, | ||
789 | }; | 790 | }; |
790 | int i; | 791 | int i; |
791 | 792 | ||
diff --git a/fs/nfsd/nfssvc.c b/fs/nfsd/nfssvc.c index 786a4a2cb2d7..31e1f9593457 100644 --- a/fs/nfsd/nfssvc.c +++ b/fs/nfsd/nfssvc.c | |||
@@ -167,7 +167,8 @@ nfsd_adjust_nfsd_versions4(void) | |||
167 | 167 | ||
168 | int nfsd_minorversion(u32 minorversion, enum vers_op change) | 168 | int nfsd_minorversion(u32 minorversion, enum vers_op change) |
169 | { | 169 | { |
170 | if (minorversion > NFSD_SUPPORTED_MINOR_VERSION) | 170 | if (minorversion > NFSD_SUPPORTED_MINOR_VERSION && |
171 | change != NFSD_AVAIL) | ||
171 | return -1; | 172 | return -1; |
172 | switch(change) { | 173 | switch(change) { |
173 | case NFSD_SET: | 174 | case NFSD_SET: |
@@ -415,23 +416,20 @@ static void nfsd_last_thread(struct svc_serv *serv, struct net *net) | |||
415 | 416 | ||
416 | void nfsd_reset_versions(void) | 417 | void nfsd_reset_versions(void) |
417 | { | 418 | { |
418 | int found_one = 0; | ||
419 | int i; | 419 | int i; |
420 | 420 | ||
421 | for (i = NFSD_MINVERS; i < NFSD_NRVERS; i++) { | 421 | for (i = 0; i < NFSD_NRVERS; i++) |
422 | if (nfsd_program.pg_vers[i]) | 422 | if (nfsd_vers(i, NFSD_TEST)) |
423 | found_one = 1; | 423 | return; |
424 | } | ||
425 | 424 | ||
426 | if (!found_one) { | 425 | for (i = 0; i < NFSD_NRVERS; i++) |
427 | for (i = NFSD_MINVERS; i < NFSD_NRVERS; i++) | 426 | if (i != 4) |
428 | nfsd_program.pg_vers[i] = nfsd_version[i]; | 427 | nfsd_vers(i, NFSD_SET); |
429 | #if defined(CONFIG_NFSD_V2_ACL) || defined(CONFIG_NFSD_V3_ACL) | 428 | else { |
430 | for (i = NFSD_ACL_MINVERS; i < NFSD_ACL_NRVERS; i++) | 429 | int minor = 0; |
431 | nfsd_acl_program.pg_vers[i] = | 430 | while (nfsd_minorversion(minor, NFSD_SET) >= 0) |
432 | nfsd_acl_version[i]; | 431 | minor++; |
433 | #endif | 432 | } |
434 | } | ||
435 | } | 433 | } |
436 | 434 | ||
437 | /* | 435 | /* |
diff --git a/net/sunrpc/svcsock.c b/net/sunrpc/svcsock.c index 8931e33b6541..2b720fa35c4f 100644 --- a/net/sunrpc/svcsock.c +++ b/net/sunrpc/svcsock.c | |||
@@ -1635,6 +1635,7 @@ static struct svc_xprt *svc_bc_create_socket(struct svc_serv *serv, | |||
1635 | 1635 | ||
1636 | xprt = &svsk->sk_xprt; | 1636 | xprt = &svsk->sk_xprt; |
1637 | svc_xprt_init(net, &svc_tcp_bc_class, xprt, serv); | 1637 | svc_xprt_init(net, &svc_tcp_bc_class, xprt, serv); |
1638 | set_bit(XPT_CONG_CTRL, &svsk->sk_xprt.xpt_flags); | ||
1638 | 1639 | ||
1639 | serv->sv_bc_xprt = xprt; | 1640 | serv->sv_bc_xprt = xprt; |
1640 | 1641 | ||
diff --git a/net/sunrpc/xprtrdma/svc_rdma_transport.c b/net/sunrpc/xprtrdma/svc_rdma_transport.c index c13a5c35ce14..fc8f14c7bfec 100644 --- a/net/sunrpc/xprtrdma/svc_rdma_transport.c +++ b/net/sunrpc/xprtrdma/svc_rdma_transport.c | |||
@@ -127,6 +127,7 @@ static struct svc_xprt *svc_rdma_bc_create(struct svc_serv *serv, | |||
127 | xprt = &cma_xprt->sc_xprt; | 127 | xprt = &cma_xprt->sc_xprt; |
128 | 128 | ||
129 | svc_xprt_init(net, &svc_rdma_bc_class, xprt, serv); | 129 | svc_xprt_init(net, &svc_rdma_bc_class, xprt, serv); |
130 | set_bit(XPT_CONG_CTRL, &xprt->xpt_flags); | ||
130 | serv->sv_bc_xprt = xprt; | 131 | serv->sv_bc_xprt = xprt; |
131 | 132 | ||
132 | dprintk("svcrdma: %s(%p)\n", __func__, xprt); | 133 | dprintk("svcrdma: %s(%p)\n", __func__, xprt); |