Commit 673fdfe3f0630b03f3854d0361b1232f2e5ef7fb

Authored by Linus Torvalds

Merge tag 'nfs-for-3.13-2' of git://git.linux-nfs.org/projects/trondmy/linux-nfs

Pull NFS client bugfixes:
 - Stable fix for data corruption when retransmitting O_DIRECT writes
 - Stable fix for a deep recursion/stack overflow bug in rpc_release_client
 - Stable fix for infinite looping when mounting a NFSv4.x volume
 - Fix a typo in the nfs mount option parser
 - Allow pNFS layouts to be compiled into the kernel when NFSv4.1 is

* tag 'nfs-for-3.13-2' of git://git.linux-nfs.org/projects/trondmy/linux-nfs:
  nfs: fix pnfs Kconfig defaults
  NFS: correctly report misuse of "migration" mount option.
  nfs: don't retry detect_trunking with RPC_AUTH_UNIX more than once
  SUNRPC: Avoid deep recursion in rpc_release_client
  SUNRPC: Fix a data corruption issue when retransmitting RPC calls

Showing 5 changed files Side-by-side Diff

... ... @@ -116,17 +116,17 @@
116 116 config PNFS_FILE_LAYOUT
117 117 tristate
118 118 depends on NFS_V4_1
119   - default m
  119 + default NFS_V4
120 120  
121 121 config PNFS_BLOCK
122 122 tristate
123 123 depends on NFS_V4_1 && BLK_DEV_DM
124   - default m
  124 + default NFS_V4
125 125  
126 126 config PNFS_OBJLAYOUT
127 127 tristate
128 128 depends on NFS_V4_1 && SCSI_OSD_ULD
129   - default m
  129 + default NFS_V4
130 130  
131 131 config NFS_V4_1_IMPLEMENTATION_ID_DOMAIN
132 132 string "NFSv4.1 Implementation ID Domain"
... ... @@ -2093,10 +2093,15 @@
2093 2093 nfs4_root_machine_cred(clp);
2094 2094 goto again;
2095 2095 }
2096   - if (i > 2)
  2096 + if (clnt->cl_auth->au_flavor == RPC_AUTH_UNIX)
2097 2097 break;
2098 2098 case -NFS4ERR_CLID_INUSE:
2099 2099 case -NFS4ERR_WRONGSEC:
  2100 + /* No point in retrying if we already used RPC_AUTH_UNIX */
  2101 + if (clnt->cl_auth->au_flavor == RPC_AUTH_UNIX) {
  2102 + status = -EPERM;
  2103 + break;
  2104 + }
2100 2105 clnt = rpc_clone_client_set_auth(clnt, RPC_AUTH_UNIX);
2101 2106 if (IS_ERR(clnt)) {
2102 2107 status = PTR_ERR(clnt);
... ... @@ -1614,7 +1614,7 @@
1614 1614 goto out_minorversion_mismatch;
1615 1615  
1616 1616 if (mnt->options & NFS_OPTION_MIGRATION &&
1617   - mnt->version != 4 && mnt->minorversion != 0)
  1617 + (mnt->version != 4 || mnt->minorversion != 0))
1618 1618 goto out_migration_misuse;
1619 1619  
1620 1620 /*
... ... @@ -750,14 +750,16 @@
750 750 /*
751 751 * Free an RPC client
752 752 */
753   -static void
  753 +static struct rpc_clnt *
754 754 rpc_free_client(struct rpc_clnt *clnt)
755 755 {
  756 + struct rpc_clnt *parent = NULL;
  757 +
756 758 dprintk_rcu("RPC: destroying %s client for %s\n",
757 759 clnt->cl_program->name,
758 760 rcu_dereference(clnt->cl_xprt)->servername);
759 761 if (clnt->cl_parent != clnt)
760   - rpc_release_client(clnt->cl_parent);
  762 + parent = clnt->cl_parent;
761 763 rpc_clnt_remove_pipedir(clnt);
762 764 rpc_unregister_client(clnt);
763 765 rpc_free_iostats(clnt->cl_metrics);
764 766  
765 767  
... ... @@ -766,18 +768,17 @@
766 768 rpciod_down();
767 769 rpc_free_clid(clnt);
768 770 kfree(clnt);
  771 + return parent;
769 772 }
770 773  
771 774 /*
772 775 * Free an RPC client
773 776 */
774   -static void
  777 +static struct rpc_clnt *
775 778 rpc_free_auth(struct rpc_clnt *clnt)
776 779 {
777   - if (clnt->cl_auth == NULL) {
778   - rpc_free_client(clnt);
779   - return;
780   - }
  780 + if (clnt->cl_auth == NULL)
  781 + return rpc_free_client(clnt);
781 782  
782 783 /*
783 784 * Note: RPCSEC_GSS may need to send NULL RPC calls in order to
... ... @@ -788,7 +789,8 @@
788 789 rpcauth_release(clnt->cl_auth);
789 790 clnt->cl_auth = NULL;
790 791 if (atomic_dec_and_test(&clnt->cl_count))
791   - rpc_free_client(clnt);
  792 + return rpc_free_client(clnt);
  793 + return NULL;
792 794 }
793 795  
794 796 /*
... ... @@ -799,10 +801,13 @@
799 801 {
800 802 dprintk("RPC: rpc_release_client(%p)\n", clnt);
801 803  
802   - if (list_empty(&clnt->cl_tasks))
803   - wake_up(&destroy_wait);
804   - if (atomic_dec_and_test(&clnt->cl_count))
805   - rpc_free_auth(clnt);
  804 + do {
  805 + if (list_empty(&clnt->cl_tasks))
  806 + wake_up(&destroy_wait);
  807 + if (!atomic_dec_and_test(&clnt->cl_count))
  808 + break;
  809 + clnt = rpc_free_auth(clnt);
  810 + } while (clnt != NULL);
806 811 }
807 812 EXPORT_SYMBOL_GPL(rpc_release_client);
808 813  
net/sunrpc/xprtsock.c
... ... @@ -393,8 +393,10 @@
393 393 return kernel_sendmsg(sock, &msg, NULL, 0, 0);
394 394 }
395 395  
396   -static int xs_send_pagedata(struct socket *sock, struct xdr_buf *xdr, unsigned int base, int more)
  396 +static int xs_send_pagedata(struct socket *sock, struct xdr_buf *xdr, unsigned int base, int more, bool zerocopy)
397 397 {
  398 + ssize_t (*do_sendpage)(struct socket *sock, struct page *page,
  399 + int offset, size_t size, int flags);
398 400 struct page **ppage;
399 401 unsigned int remainder;
400 402 int err, sent = 0;
... ... @@ -403,6 +405,9 @@
403 405 base += xdr->page_base;
404 406 ppage = xdr->pages + (base >> PAGE_SHIFT);
405 407 base &= ~PAGE_MASK;
  408 + do_sendpage = sock->ops->sendpage;
  409 + if (!zerocopy)
  410 + do_sendpage = sock_no_sendpage;
406 411 for(;;) {
407 412 unsigned int len = min_t(unsigned int, PAGE_SIZE - base, remainder);
408 413 int flags = XS_SENDMSG_FLAGS;
... ... @@ -410,7 +415,7 @@
410 415 remainder -= len;
411 416 if (remainder != 0 || more)
412 417 flags |= MSG_MORE;
413   - err = sock->ops->sendpage(sock, *ppage, base, len, flags);
  418 + err = do_sendpage(sock, *ppage, base, len, flags);
414 419 if (remainder == 0 || err != len)
415 420 break;
416 421 sent += err;
417 422  
... ... @@ -431,9 +436,10 @@
431 436 * @addrlen: UDP only -- length of destination address
432 437 * @xdr: buffer containing this request
433 438 * @base: starting position in the buffer
  439 + * @zerocopy: true if it is safe to use sendpage()
434 440 *
435 441 */
436   -static int xs_sendpages(struct socket *sock, struct sockaddr *addr, int addrlen, struct xdr_buf *xdr, unsigned int base)
  442 +static int xs_sendpages(struct socket *sock, struct sockaddr *addr, int addrlen, struct xdr_buf *xdr, unsigned int base, bool zerocopy)
437 443 {
438 444 unsigned int remainder = xdr->len - base;
439 445 int err, sent = 0;
... ... @@ -461,7 +467,7 @@
461 467 if (base < xdr->page_len) {
462 468 unsigned int len = xdr->page_len - base;
463 469 remainder -= len;
464   - err = xs_send_pagedata(sock, xdr, base, remainder != 0);
  470 + err = xs_send_pagedata(sock, xdr, base, remainder != 0, zerocopy);
465 471 if (remainder == 0 || err != len)
466 472 goto out;
467 473 sent += err;
... ... @@ -564,7 +570,7 @@
564 570 req->rq_svec->iov_base, req->rq_svec->iov_len);
565 571  
566 572 status = xs_sendpages(transport->sock, NULL, 0,
567   - xdr, req->rq_bytes_sent);
  573 + xdr, req->rq_bytes_sent, true);
568 574 dprintk("RPC: %s(%u) = %d\n",
569 575 __func__, xdr->len - req->rq_bytes_sent, status);
570 576 if (likely(status >= 0)) {
... ... @@ -620,7 +626,7 @@
620 626 status = xs_sendpages(transport->sock,
621 627 xs_addr(xprt),
622 628 xprt->addrlen, xdr,
623   - req->rq_bytes_sent);
  629 + req->rq_bytes_sent, true);
624 630  
625 631 dprintk("RPC: xs_udp_send_request(%u) = %d\n",
626 632 xdr->len - req->rq_bytes_sent, status);
... ... @@ -693,6 +699,7 @@
693 699 struct rpc_xprt *xprt = req->rq_xprt;
694 700 struct sock_xprt *transport = container_of(xprt, struct sock_xprt, xprt);
695 701 struct xdr_buf *xdr = &req->rq_snd_buf;
  702 + bool zerocopy = true;
696 703 int status;
697 704  
698 705 xs_encode_stream_record_marker(&req->rq_snd_buf);
699 706  
... ... @@ -700,13 +707,20 @@
700 707 xs_pktdump("packet data:",
701 708 req->rq_svec->iov_base,
702 709 req->rq_svec->iov_len);
  710 + /* Don't use zero copy if this is a resend. If the RPC call
  711 + * completes while the socket holds a reference to the pages,
  712 + * then we may end up resending corrupted data.
  713 + */
  714 + if (task->tk_flags & RPC_TASK_SENT)
  715 + zerocopy = false;
703 716  
704 717 /* Continue transmitting the packet/record. We must be careful
705 718 * to cope with writespace callbacks arriving _after_ we have
706 719 * called sendmsg(). */
707 720 while (1) {
708 721 status = xs_sendpages(transport->sock,
709   - NULL, 0, xdr, req->rq_bytes_sent);
  722 + NULL, 0, xdr, req->rq_bytes_sent,
  723 + zerocopy);
710 724  
711 725 dprintk("RPC: xs_tcp_send_request(%u) = %d\n",
712 726 xdr->len - req->rq_bytes_sent, status);