Commit 465c209d authored by Linus Torvalds's avatar Linus Torvalds

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

Pull NFS client bugfixes from Trond Myklebust:
 "Highlights include:

  Bugfixes:
   - Fix an Oops in SUNRPC back channel tracepoints
   - Fix a SUNRPC client regression when handling oversized replies
   - Fix the minimal size for SUNRPC reply buffer allocation
   - rpc_decode_header() must always return a non-zero value on error
   - Fix a typo in pnfs_update_layout()

  Cleanup:
   - Remove redundant check for the reply length in call_decode()"

* tag 'nfs-for-5.1-2' of git://git.linux-nfs.org/projects/trondmy/linux-nfs:
  SUNRPC: Remove redundant check for the reply length in call_decode()
  SUNRPC: Handle the SYSTEM_ERR rpc error
  SUNRPC: rpc_decode_header() must always return a non-zero value on error
  SUNRPC: Use the ENOTCONN error on socket disconnect
  SUNRPC: Fix the minimal size for reply buffer allocation
  SUNRPC: Fix a client regression when handling oversized replies
  pNFS: Fix a typo in pnfs_update_layout
  fix null pointer deref in tracepoints in back channel
parents a9c55d58 5e3863fd
...@@ -1889,7 +1889,7 @@ pnfs_update_layout(struct inode *ino, ...@@ -1889,7 +1889,7 @@ pnfs_update_layout(struct inode *ino,
atomic_read(&lo->plh_outstanding) != 0) { atomic_read(&lo->plh_outstanding) != 0) {
spin_unlock(&ino->i_lock); spin_unlock(&ino->i_lock);
lseg = ERR_PTR(wait_var_event_killable(&lo->plh_outstanding, lseg = ERR_PTR(wait_var_event_killable(&lo->plh_outstanding,
atomic_read(&lo->plh_outstanding))); !atomic_read(&lo->plh_outstanding)));
if (IS_ERR(lseg) || !list_empty(&lo->plh_segs)) if (IS_ERR(lseg) || !list_empty(&lo->plh_segs))
goto out_put_layout_hdr; goto out_put_layout_hdr;
pnfs_put_layout_hdr(lo); pnfs_put_layout_hdr(lo);
......
...@@ -712,7 +712,8 @@ TRACE_EVENT(xprt_transmit, ...@@ -712,7 +712,8 @@ TRACE_EVENT(xprt_transmit,
TP_fast_assign( TP_fast_assign(
__entry->task_id = rqst->rq_task->tk_pid; __entry->task_id = rqst->rq_task->tk_pid;
__entry->client_id = rqst->rq_task->tk_client->cl_clid; __entry->client_id = rqst->rq_task->tk_client ?
rqst->rq_task->tk_client->cl_clid : -1;
__entry->xid = be32_to_cpu(rqst->rq_xid); __entry->xid = be32_to_cpu(rqst->rq_xid);
__entry->seqno = rqst->rq_seqno; __entry->seqno = rqst->rq_seqno;
__entry->status = status; __entry->status = status;
...@@ -742,7 +743,8 @@ TRACE_EVENT(xprt_enq_xmit, ...@@ -742,7 +743,8 @@ TRACE_EVENT(xprt_enq_xmit,
TP_fast_assign( TP_fast_assign(
__entry->task_id = task->tk_pid; __entry->task_id = task->tk_pid;
__entry->client_id = task->tk_client->cl_clid; __entry->client_id = task->tk_client ?
task->tk_client->cl_clid : -1;
__entry->xid = be32_to_cpu(task->tk_rqstp->rq_xid); __entry->xid = be32_to_cpu(task->tk_rqstp->rq_xid);
__entry->seqno = task->tk_rqstp->rq_seqno; __entry->seqno = task->tk_rqstp->rq_seqno;
__entry->stage = stage; __entry->stage = stage;
......
...@@ -1730,7 +1730,12 @@ call_allocate(struct rpc_task *task) ...@@ -1730,7 +1730,12 @@ call_allocate(struct rpc_task *task)
req->rq_callsize = RPC_CALLHDRSIZE + (auth->au_cslack << 1) + req->rq_callsize = RPC_CALLHDRSIZE + (auth->au_cslack << 1) +
proc->p_arglen; proc->p_arglen;
req->rq_callsize <<= 2; req->rq_callsize <<= 2;
req->rq_rcvsize = RPC_REPHDRSIZE + auth->au_rslack + proc->p_replen; /*
* Note: the reply buffer must at minimum allocate enough space
* for the 'struct accepted_reply' from RFC5531.
*/
req->rq_rcvsize = RPC_REPHDRSIZE + auth->au_rslack + \
max_t(size_t, proc->p_replen, 2);
req->rq_rcvsize <<= 2; req->rq_rcvsize <<= 2;
status = xprt->ops->buf_alloc(task); status = xprt->ops->buf_alloc(task);
...@@ -2387,9 +2392,6 @@ call_decode(struct rpc_task *task) ...@@ -2387,9 +2392,6 @@ call_decode(struct rpc_task *task)
WARN_ON(memcmp(&req->rq_rcv_buf, &req->rq_private_buf, WARN_ON(memcmp(&req->rq_rcv_buf, &req->rq_private_buf,
sizeof(req->rq_rcv_buf)) != 0); sizeof(req->rq_rcv_buf)) != 0);
if (req->rq_rcv_buf.len < 12)
goto out_retry;
xdr_init_decode(&xdr, &req->rq_rcv_buf, xdr_init_decode(&xdr, &req->rq_rcv_buf,
req->rq_rcv_buf.head[0].iov_base, req); req->rq_rcv_buf.head[0].iov_base, req);
switch (rpc_decode_header(task, &xdr)) { switch (rpc_decode_header(task, &xdr)) {
...@@ -2400,7 +2402,6 @@ call_decode(struct rpc_task *task) ...@@ -2400,7 +2402,6 @@ call_decode(struct rpc_task *task)
task->tk_pid, __func__, task->tk_status); task->tk_pid, __func__, task->tk_status);
return; return;
case -EAGAIN: case -EAGAIN:
out_retry:
task->tk_status = 0; task->tk_status = 0;
/* Note: rpc_decode_header() may have freed the RPC slot */ /* Note: rpc_decode_header() may have freed the RPC slot */
if (task->tk_rqstp == req) { if (task->tk_rqstp == req) {
...@@ -2449,7 +2450,7 @@ static noinline int ...@@ -2449,7 +2450,7 @@ static noinline int
rpc_decode_header(struct rpc_task *task, struct xdr_stream *xdr) rpc_decode_header(struct rpc_task *task, struct xdr_stream *xdr)
{ {
struct rpc_clnt *clnt = task->tk_client; struct rpc_clnt *clnt = task->tk_client;
int error = -EACCES; int error;
__be32 *p; __be32 *p;
/* RFC-1014 says that the representation of XDR data must be a /* RFC-1014 says that the representation of XDR data must be a
...@@ -2458,7 +2459,7 @@ rpc_decode_header(struct rpc_task *task, struct xdr_stream *xdr) ...@@ -2458,7 +2459,7 @@ rpc_decode_header(struct rpc_task *task, struct xdr_stream *xdr)
* undefined results * undefined results
*/ */
if (task->tk_rqstp->rq_rcv_buf.len & 3) if (task->tk_rqstp->rq_rcv_buf.len & 3)
goto out_badlen; goto out_unparsable;
p = xdr_inline_decode(xdr, 3 * sizeof(*p)); p = xdr_inline_decode(xdr, 3 * sizeof(*p));
if (!p) if (!p)
...@@ -2492,10 +2493,12 @@ rpc_decode_header(struct rpc_task *task, struct xdr_stream *xdr) ...@@ -2492,10 +2493,12 @@ rpc_decode_header(struct rpc_task *task, struct xdr_stream *xdr)
error = -EOPNOTSUPP; error = -EOPNOTSUPP;
goto out_err; goto out_err;
case rpc_garbage_args: case rpc_garbage_args:
case rpc_system_err:
trace_rpc__garbage_args(task); trace_rpc__garbage_args(task);
error = -EIO;
break; break;
default: default:
trace_rpc__unparsable(task); goto out_unparsable;
} }
out_garbage: out_garbage:
...@@ -2509,11 +2512,6 @@ rpc_decode_header(struct rpc_task *task, struct xdr_stream *xdr) ...@@ -2509,11 +2512,6 @@ rpc_decode_header(struct rpc_task *task, struct xdr_stream *xdr)
rpc_exit(task, error); rpc_exit(task, error);
return error; return error;
out_badlen:
trace_rpc__unparsable(task);
error = -EIO;
goto out_err;
out_unparsable: out_unparsable:
trace_rpc__unparsable(task); trace_rpc__unparsable(task);
error = -EIO; error = -EIO;
...@@ -2524,6 +2522,7 @@ rpc_decode_header(struct rpc_task *task, struct xdr_stream *xdr) ...@@ -2524,6 +2522,7 @@ rpc_decode_header(struct rpc_task *task, struct xdr_stream *xdr)
goto out_garbage; goto out_garbage;
out_msg_denied: out_msg_denied:
error = -EACCES;
p = xdr_inline_decode(xdr, sizeof(*p)); p = xdr_inline_decode(xdr, sizeof(*p));
if (!p) if (!p)
goto out_unparsable; goto out_unparsable;
...@@ -2535,9 +2534,7 @@ rpc_decode_header(struct rpc_task *task, struct xdr_stream *xdr) ...@@ -2535,9 +2534,7 @@ rpc_decode_header(struct rpc_task *task, struct xdr_stream *xdr)
error = -EPROTONOSUPPORT; error = -EPROTONOSUPPORT;
goto out_err; goto out_err;
default: default:
trace_rpc__unparsable(task); goto out_unparsable;
error = -EIO;
goto out_err;
} }
p = xdr_inline_decode(xdr, sizeof(*p)); p = xdr_inline_decode(xdr, sizeof(*p));
...@@ -2572,8 +2569,7 @@ rpc_decode_header(struct rpc_task *task, struct xdr_stream *xdr) ...@@ -2572,8 +2569,7 @@ rpc_decode_header(struct rpc_task *task, struct xdr_stream *xdr)
task->tk_xprt->servername); task->tk_xprt->servername);
break; break;
default: default:
trace_rpc__unparsable(task); goto out_unparsable;
error = -EIO;
} }
goto out_err; goto out_err;
} }
......
...@@ -664,7 +664,7 @@ void xprt_disconnect_done(struct rpc_xprt *xprt) ...@@ -664,7 +664,7 @@ void xprt_disconnect_done(struct rpc_xprt *xprt)
spin_lock_bh(&xprt->transport_lock); spin_lock_bh(&xprt->transport_lock);
xprt_clear_connected(xprt); xprt_clear_connected(xprt);
xprt_clear_write_space_locked(xprt); xprt_clear_write_space_locked(xprt);
xprt_wake_pending_tasks(xprt, -EAGAIN); xprt_wake_pending_tasks(xprt, -ENOTCONN);
spin_unlock_bh(&xprt->transport_lock); spin_unlock_bh(&xprt->transport_lock);
} }
EXPORT_SYMBOL_GPL(xprt_disconnect_done); EXPORT_SYMBOL_GPL(xprt_disconnect_done);
......
...@@ -453,7 +453,7 @@ xs_read_xdr_buf(struct socket *sock, struct msghdr *msg, int flags, ...@@ -453,7 +453,7 @@ xs_read_xdr_buf(struct socket *sock, struct msghdr *msg, int flags,
goto out; goto out;
if (ret != want) if (ret != want)
goto out; goto out;
} else } else if (offset < seek_init)
offset = seek_init; offset = seek_init;
ret = -EMSGSIZE; ret = -EMSGSIZE;
out: out:
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment