aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2019-01-19 16:27:38 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2019-01-19 16:27:38 -0500
commitb0efca46b57071e4c281034f04d2b56edf79843d (patch)
tree93d04cfe9cb1bba4ecc694aca73887a32d9e9e47
parent4d5f6e0201bc568c0758ed3f77a06648ec9fd482 (diff)
parentdeaa5c96c2f7e8b934088a1e70a0fe8797bd1149 (diff)
Merge tag 'nfs-for-5.0-2' of git://git.linux-nfs.org/projects/anna/linux-nfs
Pull NFS client fixes from Anna Schumaker: "These are mostly fixes for SUNRPC bugs, with a single v4.2 copy_file_range() fix mixed in. Stable bugfixes: - Fix TCP receive code on archs with flush_dcache_page() Other bugfixes: - Fix error code in rpcrdma_buffer_create() - Fix a double free in rpcrdma_send_ctxs_create() - Fix kernel BUG at kernel/cred.c:825 - Fix unnecessary retry in nfs42_proc_copy_file_range() - Ensure rq_bytes_sent is reset before request transmission - Ensure we respect the RPCSEC_GSS sequence number limit - Address Kerberos performance/behavior regression" * tag 'nfs-for-5.0-2' of git://git.linux-nfs.org/projects/anna/linux-nfs: SUNRPC: Address Kerberos performance/behavior regression SUNRPC: Ensure we respect the RPCSEC_GSS sequence number limit SUNRPC: Ensure rq_bytes_sent is reset before request transmission NFSv4.2 fix unnecessary retry in nfs4_copy_file_range sunrpc: kernel BUG at kernel/cred.c:825! SUNRPC: Fix TCP receive code on archs with flush_dcache_page() xprtrdma: Double free in rpcrdma_sendctxs_create() xprtrdma: Fix error code in rpcrdma_buffer_create()
-rw-r--r--fs/nfs/nfs4file.c8
-rw-r--r--net/sunrpc/auth.c3
-rw-r--r--net/sunrpc/auth_gss/auth_gss.c12
-rw-r--r--net/sunrpc/clnt.c20
-rw-r--r--net/sunrpc/xprt.c3
-rw-r--r--net/sunrpc/xprtrdma/verbs.c10
-rw-r--r--net/sunrpc/xprtsock.c22
7 files changed, 53 insertions, 25 deletions
diff --git a/fs/nfs/nfs4file.c b/fs/nfs/nfs4file.c
index 46d691ba04bc..45b2322e092d 100644
--- a/fs/nfs/nfs4file.c
+++ b/fs/nfs/nfs4file.c
@@ -133,15 +133,9 @@ static ssize_t nfs4_copy_file_range(struct file *file_in, loff_t pos_in,
133 struct file *file_out, loff_t pos_out, 133 struct file *file_out, loff_t pos_out,
134 size_t count, unsigned int flags) 134 size_t count, unsigned int flags)
135{ 135{
136 ssize_t ret;
137
138 if (file_inode(file_in) == file_inode(file_out)) 136 if (file_inode(file_in) == file_inode(file_out))
139 return -EINVAL; 137 return -EINVAL;
140retry: 138 return nfs42_proc_copy(file_in, pos_in, file_out, pos_out, count);
141 ret = nfs42_proc_copy(file_in, pos_in, file_out, pos_out, count);
142 if (ret == -EAGAIN)
143 goto retry;
144 return ret;
145} 139}
146 140
147static loff_t nfs4_file_llseek(struct file *filep, loff_t offset, int whence) 141static loff_t nfs4_file_llseek(struct file *filep, loff_t offset, int whence)
diff --git a/net/sunrpc/auth.c b/net/sunrpc/auth.c
index 1ff9768f5456..f3023bbc0b7f 100644
--- a/net/sunrpc/auth.c
+++ b/net/sunrpc/auth.c
@@ -41,6 +41,9 @@ static unsigned long number_cred_unused;
41 41
42static struct cred machine_cred = { 42static struct cred machine_cred = {
43 .usage = ATOMIC_INIT(1), 43 .usage = ATOMIC_INIT(1),
44#ifdef CONFIG_DEBUG_CREDENTIALS
45 .magic = CRED_MAGIC,
46#endif
44}; 47};
45 48
46/* 49/*
diff --git a/net/sunrpc/auth_gss/auth_gss.c b/net/sunrpc/auth_gss/auth_gss.c
index dc86713b32b6..1531b0219344 100644
--- a/net/sunrpc/auth_gss/auth_gss.c
+++ b/net/sunrpc/auth_gss/auth_gss.c
@@ -1549,8 +1549,10 @@ gss_marshal(struct rpc_task *task, __be32 *p)
1549 cred_len = p++; 1549 cred_len = p++;
1550 1550
1551 spin_lock(&ctx->gc_seq_lock); 1551 spin_lock(&ctx->gc_seq_lock);
1552 req->rq_seqno = ctx->gc_seq++; 1552 req->rq_seqno = (ctx->gc_seq < MAXSEQ) ? ctx->gc_seq++ : MAXSEQ;
1553 spin_unlock(&ctx->gc_seq_lock); 1553 spin_unlock(&ctx->gc_seq_lock);
1554 if (req->rq_seqno == MAXSEQ)
1555 goto out_expired;
1554 1556
1555 *p++ = htonl((u32) RPC_GSS_VERSION); 1557 *p++ = htonl((u32) RPC_GSS_VERSION);
1556 *p++ = htonl((u32) ctx->gc_proc); 1558 *p++ = htonl((u32) ctx->gc_proc);
@@ -1572,14 +1574,18 @@ gss_marshal(struct rpc_task *task, __be32 *p)
1572 mic.data = (u8 *)(p + 1); 1574 mic.data = (u8 *)(p + 1);
1573 maj_stat = gss_get_mic(ctx->gc_gss_ctx, &verf_buf, &mic); 1575 maj_stat = gss_get_mic(ctx->gc_gss_ctx, &verf_buf, &mic);
1574 if (maj_stat == GSS_S_CONTEXT_EXPIRED) { 1576 if (maj_stat == GSS_S_CONTEXT_EXPIRED) {
1575 clear_bit(RPCAUTH_CRED_UPTODATE, &cred->cr_flags); 1577 goto out_expired;
1576 } else if (maj_stat != 0) { 1578 } else if (maj_stat != 0) {
1577 printk("gss_marshal: gss_get_mic FAILED (%d)\n", maj_stat); 1579 pr_warn("gss_marshal: gss_get_mic FAILED (%d)\n", maj_stat);
1580 task->tk_status = -EIO;
1578 goto out_put_ctx; 1581 goto out_put_ctx;
1579 } 1582 }
1580 p = xdr_encode_opaque(p, NULL, mic.len); 1583 p = xdr_encode_opaque(p, NULL, mic.len);
1581 gss_put_ctx(ctx); 1584 gss_put_ctx(ctx);
1582 return p; 1585 return p;
1586out_expired:
1587 clear_bit(RPCAUTH_CRED_UPTODATE, &cred->cr_flags);
1588 task->tk_status = -EKEYEXPIRED;
1583out_put_ctx: 1589out_put_ctx:
1584 gss_put_ctx(ctx); 1590 gss_put_ctx(ctx);
1585 return NULL; 1591 return NULL;
diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c
index 71d9599b5816..d7ec6132c046 100644
--- a/net/sunrpc/clnt.c
+++ b/net/sunrpc/clnt.c
@@ -1739,14 +1739,10 @@ rpc_xdr_encode(struct rpc_task *task)
1739 xdr_buf_init(&req->rq_rcv_buf, 1739 xdr_buf_init(&req->rq_rcv_buf,
1740 req->rq_rbuffer, 1740 req->rq_rbuffer,
1741 req->rq_rcvsize); 1741 req->rq_rcvsize);
1742 req->rq_bytes_sent = 0;
1743 1742
1744 p = rpc_encode_header(task); 1743 p = rpc_encode_header(task);
1745 if (p == NULL) { 1744 if (p == NULL)
1746 printk(KERN_INFO "RPC: couldn't encode RPC header, exit EIO\n");
1747 rpc_exit(task, -EIO);
1748 return; 1745 return;
1749 }
1750 1746
1751 encode = task->tk_msg.rpc_proc->p_encode; 1747 encode = task->tk_msg.rpc_proc->p_encode;
1752 if (encode == NULL) 1748 if (encode == NULL)
@@ -1771,10 +1767,17 @@ call_encode(struct rpc_task *task)
1771 /* Did the encode result in an error condition? */ 1767 /* Did the encode result in an error condition? */
1772 if (task->tk_status != 0) { 1768 if (task->tk_status != 0) {
1773 /* Was the error nonfatal? */ 1769 /* Was the error nonfatal? */
1774 if (task->tk_status == -EAGAIN || task->tk_status == -ENOMEM) 1770 switch (task->tk_status) {
1771 case -EAGAIN:
1772 case -ENOMEM:
1775 rpc_delay(task, HZ >> 4); 1773 rpc_delay(task, HZ >> 4);
1776 else 1774 break;
1775 case -EKEYEXPIRED:
1776 task->tk_action = call_refresh;
1777 break;
1778 default:
1777 rpc_exit(task, task->tk_status); 1779 rpc_exit(task, task->tk_status);
1780 }
1778 return; 1781 return;
1779 } 1782 }
1780 1783
@@ -2336,7 +2339,8 @@ rpc_encode_header(struct rpc_task *task)
2336 *p++ = htonl(clnt->cl_vers); /* program version */ 2339 *p++ = htonl(clnt->cl_vers); /* program version */
2337 *p++ = htonl(task->tk_msg.rpc_proc->p_proc); /* procedure */ 2340 *p++ = htonl(task->tk_msg.rpc_proc->p_proc); /* procedure */
2338 p = rpcauth_marshcred(task, p); 2341 p = rpcauth_marshcred(task, p);
2339 req->rq_slen = xdr_adjust_iovec(&req->rq_svec[0], p); 2342 if (p)
2343 req->rq_slen = xdr_adjust_iovec(&req->rq_svec[0], p);
2340 return p; 2344 return p;
2341} 2345}
2342 2346
diff --git a/net/sunrpc/xprt.c b/net/sunrpc/xprt.c
index 73547d17d3c6..f1ec2110efeb 100644
--- a/net/sunrpc/xprt.c
+++ b/net/sunrpc/xprt.c
@@ -1151,6 +1151,7 @@ xprt_request_enqueue_transmit(struct rpc_task *task)
1151 struct rpc_xprt *xprt = req->rq_xprt; 1151 struct rpc_xprt *xprt = req->rq_xprt;
1152 1152
1153 if (xprt_request_need_enqueue_transmit(task, req)) { 1153 if (xprt_request_need_enqueue_transmit(task, req)) {
1154 req->rq_bytes_sent = 0;
1154 spin_lock(&xprt->queue_lock); 1155 spin_lock(&xprt->queue_lock);
1155 /* 1156 /*
1156 * Requests that carry congestion control credits are added 1157 * Requests that carry congestion control credits are added
@@ -1177,7 +1178,7 @@ xprt_request_enqueue_transmit(struct rpc_task *task)
1177 INIT_LIST_HEAD(&req->rq_xmit2); 1178 INIT_LIST_HEAD(&req->rq_xmit2);
1178 goto out; 1179 goto out;
1179 } 1180 }
1180 } else { 1181 } else if (!req->rq_seqno) {
1181 list_for_each_entry(pos, &xprt->xmit_queue, rq_xmit) { 1182 list_for_each_entry(pos, &xprt->xmit_queue, rq_xmit) {
1182 if (pos->rq_task->tk_owner != task->tk_owner) 1183 if (pos->rq_task->tk_owner != task->tk_owner)
1183 continue; 1184 continue;
diff --git a/net/sunrpc/xprtrdma/verbs.c b/net/sunrpc/xprtrdma/verbs.c
index 7749a2bf6887..4994e75945b8 100644
--- a/net/sunrpc/xprtrdma/verbs.c
+++ b/net/sunrpc/xprtrdma/verbs.c
@@ -845,17 +845,13 @@ static int rpcrdma_sendctxs_create(struct rpcrdma_xprt *r_xprt)
845 for (i = 0; i <= buf->rb_sc_last; i++) { 845 for (i = 0; i <= buf->rb_sc_last; i++) {
846 sc = rpcrdma_sendctx_create(&r_xprt->rx_ia); 846 sc = rpcrdma_sendctx_create(&r_xprt->rx_ia);
847 if (!sc) 847 if (!sc)
848 goto out_destroy; 848 return -ENOMEM;
849 849
850 sc->sc_xprt = r_xprt; 850 sc->sc_xprt = r_xprt;
851 buf->rb_sc_ctxs[i] = sc; 851 buf->rb_sc_ctxs[i] = sc;
852 } 852 }
853 853
854 return 0; 854 return 0;
855
856out_destroy:
857 rpcrdma_sendctxs_destroy(buf);
858 return -ENOMEM;
859} 855}
860 856
861/* The sendctx queue is not guaranteed to have a size that is a 857/* The sendctx queue is not guaranteed to have a size that is a
@@ -1113,8 +1109,10 @@ rpcrdma_buffer_create(struct rpcrdma_xprt *r_xprt)
1113 WQ_MEM_RECLAIM | WQ_HIGHPRI, 1109 WQ_MEM_RECLAIM | WQ_HIGHPRI,
1114 0, 1110 0,
1115 r_xprt->rx_xprt.address_strings[RPC_DISPLAY_ADDR]); 1111 r_xprt->rx_xprt.address_strings[RPC_DISPLAY_ADDR]);
1116 if (!buf->rb_completion_wq) 1112 if (!buf->rb_completion_wq) {
1113 rc = -ENOMEM;
1117 goto out; 1114 goto out;
1115 }
1118 1116
1119 return 0; 1117 return 0;
1120out: 1118out:
diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c
index 13559e6a460b..7754aa3e434f 100644
--- a/net/sunrpc/xprtsock.c
+++ b/net/sunrpc/xprtsock.c
@@ -48,6 +48,7 @@
48#include <net/udp.h> 48#include <net/udp.h>
49#include <net/tcp.h> 49#include <net/tcp.h>
50#include <linux/bvec.h> 50#include <linux/bvec.h>
51#include <linux/highmem.h>
51#include <linux/uio.h> 52#include <linux/uio.h>
52 53
53#include <trace/events/sunrpc.h> 54#include <trace/events/sunrpc.h>
@@ -376,6 +377,26 @@ xs_read_discard(struct socket *sock, struct msghdr *msg, int flags,
376 return sock_recvmsg(sock, msg, flags); 377 return sock_recvmsg(sock, msg, flags);
377} 378}
378 379
380#if ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE
381static void
382xs_flush_bvec(const struct bio_vec *bvec, size_t count, size_t seek)
383{
384 struct bvec_iter bi = {
385 .bi_size = count,
386 };
387 struct bio_vec bv;
388
389 bvec_iter_advance(bvec, &bi, seek & PAGE_MASK);
390 for_each_bvec(bv, bvec, bi, bi)
391 flush_dcache_page(bv.bv_page);
392}
393#else
394static inline void
395xs_flush_bvec(const struct bio_vec *bvec, size_t count, size_t seek)
396{
397}
398#endif
399
379static ssize_t 400static ssize_t
380xs_read_xdr_buf(struct socket *sock, struct msghdr *msg, int flags, 401xs_read_xdr_buf(struct socket *sock, struct msghdr *msg, int flags,
381 struct xdr_buf *buf, size_t count, size_t seek, size_t *read) 402 struct xdr_buf *buf, size_t count, size_t seek, size_t *read)
@@ -409,6 +430,7 @@ xs_read_xdr_buf(struct socket *sock, struct msghdr *msg, int flags,
409 seek + buf->page_base); 430 seek + buf->page_base);
410 if (ret <= 0) 431 if (ret <= 0)
411 goto sock_err; 432 goto sock_err;
433 xs_flush_bvec(buf->bvec, ret, seek + buf->page_base);
412 offset += ret - buf->page_base; 434 offset += ret - buf->page_base;
413 if (offset == count || msg->msg_flags & (MSG_EOR|MSG_TRUNC)) 435 if (offset == count || msg->msg_flags & (MSG_EOR|MSG_TRUNC))
414 goto out; 436 goto out;