NFS client fixes for Linux 5.0
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 -----BEGIN PGP SIGNATURE----- iQIzBAABCAAdFiEEnZ5MQTpR7cLU7KEp18tUv7ClQOsFAlxCH1kACgkQ18tUv7Cl QOs4rBAAymqyhUzNgap1TX/KezFxqii7CVMVabrA5eGN+ZXbSVAZkwy7BMZWwVIp tEvD7lxWtF11x7bQDw7Xz+ruBCjLdD0RQIFnlBpVKqsRy9oSRA4PsgSbuIFaw+gX Bun4Z0xmOCPF7knRv6gQonArEZfHeokIIN8AtSBtWVByaOrnZwgDkNTIub8akpUl FQlzgq7lTydVzNcju2ImBeubU7KgFEu0F2Zub5z/iR+F2Mx/bAju8Q4YeVlPyD8U QJoIBlXAvgK8LK4bZCh40zPeEt0TMWXnW7o0JHgVQ0g6VbT+hp17I7fz91xEazye qbjpIJIjv5daEv0REM8t5ZCZB3tEatVjb4EQWXp0gJYb0l5E3I/O+7MO44n4uMYx s3UTxzM6NjwCtlgmn4tYUj+vEIExQHUUnwOl02e5iEa7bqNNY75ehAhj5Rh7iQBH H4b+OVuqc608q87rNePdK1LRyh0/u1cDI1kDAQoIP2omlb5hJQGk0Nuz9G2BodIj rP0x7nV+ykOXZtr6TR+RvaksL1W39PzVKYA0aL+e2gbcv4YO+Oq1phvNKwRWPM4a g08r/kvifS5h6/Jq8Wmn83f1vAOX7Sf23RtEoj+t9hc4S4JbsV2iYK3PY3eWbSYE Oz0Vt4gvBBJ+0rHJ10BsQ7686OQkyMKpIlvmx6O5mWVlthovbJM= =6Nzz -----END PGP SIGNATURE----- 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()
This commit is contained in:
Коммит
b0efca46b5
|
@ -133,15 +133,9 @@ static ssize_t nfs4_copy_file_range(struct file *file_in, loff_t pos_in,
|
|||
struct file *file_out, loff_t pos_out,
|
||||
size_t count, unsigned int flags)
|
||||
{
|
||||
ssize_t ret;
|
||||
|
||||
if (file_inode(file_in) == file_inode(file_out))
|
||||
return -EINVAL;
|
||||
retry:
|
||||
ret = nfs42_proc_copy(file_in, pos_in, file_out, pos_out, count);
|
||||
if (ret == -EAGAIN)
|
||||
goto retry;
|
||||
return ret;
|
||||
return nfs42_proc_copy(file_in, pos_in, file_out, pos_out, count);
|
||||
}
|
||||
|
||||
static loff_t nfs4_file_llseek(struct file *filep, loff_t offset, int whence)
|
||||
|
|
|
@ -41,6 +41,9 @@ static unsigned long number_cred_unused;
|
|||
|
||||
static struct cred machine_cred = {
|
||||
.usage = ATOMIC_INIT(1),
|
||||
#ifdef CONFIG_DEBUG_CREDENTIALS
|
||||
.magic = CRED_MAGIC,
|
||||
#endif
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
|
@ -1549,8 +1549,10 @@ gss_marshal(struct rpc_task *task, __be32 *p)
|
|||
cred_len = p++;
|
||||
|
||||
spin_lock(&ctx->gc_seq_lock);
|
||||
req->rq_seqno = ctx->gc_seq++;
|
||||
req->rq_seqno = (ctx->gc_seq < MAXSEQ) ? ctx->gc_seq++ : MAXSEQ;
|
||||
spin_unlock(&ctx->gc_seq_lock);
|
||||
if (req->rq_seqno == MAXSEQ)
|
||||
goto out_expired;
|
||||
|
||||
*p++ = htonl((u32) RPC_GSS_VERSION);
|
||||
*p++ = htonl((u32) ctx->gc_proc);
|
||||
|
@ -1572,14 +1574,18 @@ gss_marshal(struct rpc_task *task, __be32 *p)
|
|||
mic.data = (u8 *)(p + 1);
|
||||
maj_stat = gss_get_mic(ctx->gc_gss_ctx, &verf_buf, &mic);
|
||||
if (maj_stat == GSS_S_CONTEXT_EXPIRED) {
|
||||
clear_bit(RPCAUTH_CRED_UPTODATE, &cred->cr_flags);
|
||||
goto out_expired;
|
||||
} else if (maj_stat != 0) {
|
||||
printk("gss_marshal: gss_get_mic FAILED (%d)\n", maj_stat);
|
||||
pr_warn("gss_marshal: gss_get_mic FAILED (%d)\n", maj_stat);
|
||||
task->tk_status = -EIO;
|
||||
goto out_put_ctx;
|
||||
}
|
||||
p = xdr_encode_opaque(p, NULL, mic.len);
|
||||
gss_put_ctx(ctx);
|
||||
return p;
|
||||
out_expired:
|
||||
clear_bit(RPCAUTH_CRED_UPTODATE, &cred->cr_flags);
|
||||
task->tk_status = -EKEYEXPIRED;
|
||||
out_put_ctx:
|
||||
gss_put_ctx(ctx);
|
||||
return NULL;
|
||||
|
|
|
@ -1739,14 +1739,10 @@ rpc_xdr_encode(struct rpc_task *task)
|
|||
xdr_buf_init(&req->rq_rcv_buf,
|
||||
req->rq_rbuffer,
|
||||
req->rq_rcvsize);
|
||||
req->rq_bytes_sent = 0;
|
||||
|
||||
p = rpc_encode_header(task);
|
||||
if (p == NULL) {
|
||||
printk(KERN_INFO "RPC: couldn't encode RPC header, exit EIO\n");
|
||||
rpc_exit(task, -EIO);
|
||||
if (p == NULL)
|
||||
return;
|
||||
}
|
||||
|
||||
encode = task->tk_msg.rpc_proc->p_encode;
|
||||
if (encode == NULL)
|
||||
|
@ -1771,10 +1767,17 @@ call_encode(struct rpc_task *task)
|
|||
/* Did the encode result in an error condition? */
|
||||
if (task->tk_status != 0) {
|
||||
/* Was the error nonfatal? */
|
||||
if (task->tk_status == -EAGAIN || task->tk_status == -ENOMEM)
|
||||
switch (task->tk_status) {
|
||||
case -EAGAIN:
|
||||
case -ENOMEM:
|
||||
rpc_delay(task, HZ >> 4);
|
||||
else
|
||||
break;
|
||||
case -EKEYEXPIRED:
|
||||
task->tk_action = call_refresh;
|
||||
break;
|
||||
default:
|
||||
rpc_exit(task, task->tk_status);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -2336,7 +2339,8 @@ rpc_encode_header(struct rpc_task *task)
|
|||
*p++ = htonl(clnt->cl_vers); /* program version */
|
||||
*p++ = htonl(task->tk_msg.rpc_proc->p_proc); /* procedure */
|
||||
p = rpcauth_marshcred(task, p);
|
||||
req->rq_slen = xdr_adjust_iovec(&req->rq_svec[0], p);
|
||||
if (p)
|
||||
req->rq_slen = xdr_adjust_iovec(&req->rq_svec[0], p);
|
||||
return p;
|
||||
}
|
||||
|
||||
|
|
|
@ -1151,6 +1151,7 @@ xprt_request_enqueue_transmit(struct rpc_task *task)
|
|||
struct rpc_xprt *xprt = req->rq_xprt;
|
||||
|
||||
if (xprt_request_need_enqueue_transmit(task, req)) {
|
||||
req->rq_bytes_sent = 0;
|
||||
spin_lock(&xprt->queue_lock);
|
||||
/*
|
||||
* Requests that carry congestion control credits are added
|
||||
|
@ -1177,7 +1178,7 @@ xprt_request_enqueue_transmit(struct rpc_task *task)
|
|||
INIT_LIST_HEAD(&req->rq_xmit2);
|
||||
goto out;
|
||||
}
|
||||
} else {
|
||||
} else if (!req->rq_seqno) {
|
||||
list_for_each_entry(pos, &xprt->xmit_queue, rq_xmit) {
|
||||
if (pos->rq_task->tk_owner != task->tk_owner)
|
||||
continue;
|
||||
|
|
|
@ -845,17 +845,13 @@ static int rpcrdma_sendctxs_create(struct rpcrdma_xprt *r_xprt)
|
|||
for (i = 0; i <= buf->rb_sc_last; i++) {
|
||||
sc = rpcrdma_sendctx_create(&r_xprt->rx_ia);
|
||||
if (!sc)
|
||||
goto out_destroy;
|
||||
return -ENOMEM;
|
||||
|
||||
sc->sc_xprt = r_xprt;
|
||||
buf->rb_sc_ctxs[i] = sc;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
out_destroy:
|
||||
rpcrdma_sendctxs_destroy(buf);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
/* 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)
|
|||
WQ_MEM_RECLAIM | WQ_HIGHPRI,
|
||||
0,
|
||||
r_xprt->rx_xprt.address_strings[RPC_DISPLAY_ADDR]);
|
||||
if (!buf->rb_completion_wq)
|
||||
if (!buf->rb_completion_wq) {
|
||||
rc = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
return 0;
|
||||
out:
|
||||
|
|
|
@ -48,6 +48,7 @@
|
|||
#include <net/udp.h>
|
||||
#include <net/tcp.h>
|
||||
#include <linux/bvec.h>
|
||||
#include <linux/highmem.h>
|
||||
#include <linux/uio.h>
|
||||
|
||||
#include <trace/events/sunrpc.h>
|
||||
|
@ -376,6 +377,26 @@ xs_read_discard(struct socket *sock, struct msghdr *msg, int flags,
|
|||
return sock_recvmsg(sock, msg, flags);
|
||||
}
|
||||
|
||||
#if ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE
|
||||
static void
|
||||
xs_flush_bvec(const struct bio_vec *bvec, size_t count, size_t seek)
|
||||
{
|
||||
struct bvec_iter bi = {
|
||||
.bi_size = count,
|
||||
};
|
||||
struct bio_vec bv;
|
||||
|
||||
bvec_iter_advance(bvec, &bi, seek & PAGE_MASK);
|
||||
for_each_bvec(bv, bvec, bi, bi)
|
||||
flush_dcache_page(bv.bv_page);
|
||||
}
|
||||
#else
|
||||
static inline void
|
||||
xs_flush_bvec(const struct bio_vec *bvec, size_t count, size_t seek)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
static ssize_t
|
||||
xs_read_xdr_buf(struct socket *sock, struct msghdr *msg, int flags,
|
||||
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,
|
|||
seek + buf->page_base);
|
||||
if (ret <= 0)
|
||||
goto sock_err;
|
||||
xs_flush_bvec(buf->bvec, ret, seek + buf->page_base);
|
||||
offset += ret - buf->page_base;
|
||||
if (offset == count || msg->msg_flags & (MSG_EOR|MSG_TRUNC))
|
||||
goto out;
|
||||
|
|
Загрузка…
Ссылка в новой задаче