Skip to content

Commit 465c209

Browse files
committed
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
2 parents a9c55d5 + 5e3863f commit 465c209

File tree

5 files changed

+21
-23
lines changed

5 files changed

+21
-23
lines changed

fs/nfs/pnfs.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1889,7 +1889,7 @@ pnfs_update_layout(struct inode *ino,
18891889
atomic_read(&lo->plh_outstanding) != 0) {
18901890
spin_unlock(&ino->i_lock);
18911891
lseg = ERR_PTR(wait_var_event_killable(&lo->plh_outstanding,
1892-
atomic_read(&lo->plh_outstanding)));
1892+
!atomic_read(&lo->plh_outstanding)));
18931893
if (IS_ERR(lseg) || !list_empty(&lo->plh_segs))
18941894
goto out_put_layout_hdr;
18951895
pnfs_put_layout_hdr(lo);

include/trace/events/sunrpc.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -712,7 +712,8 @@ TRACE_EVENT(xprt_transmit,
712712

713713
TP_fast_assign(
714714
__entry->task_id = rqst->rq_task->tk_pid;
715-
__entry->client_id = rqst->rq_task->tk_client->cl_clid;
715+
__entry->client_id = rqst->rq_task->tk_client ?
716+
rqst->rq_task->tk_client->cl_clid : -1;
716717
__entry->xid = be32_to_cpu(rqst->rq_xid);
717718
__entry->seqno = rqst->rq_seqno;
718719
__entry->status = status;
@@ -742,7 +743,8 @@ TRACE_EVENT(xprt_enq_xmit,
742743

743744
TP_fast_assign(
744745
__entry->task_id = task->tk_pid;
745-
__entry->client_id = task->tk_client->cl_clid;
746+
__entry->client_id = task->tk_client ?
747+
task->tk_client->cl_clid : -1;
746748
__entry->xid = be32_to_cpu(task->tk_rqstp->rq_xid);
747749
__entry->seqno = task->tk_rqstp->rq_seqno;
748750
__entry->stage = stage;

net/sunrpc/clnt.c

Lines changed: 14 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1730,7 +1730,12 @@ call_allocate(struct rpc_task *task)
17301730
req->rq_callsize = RPC_CALLHDRSIZE + (auth->au_cslack << 1) +
17311731
proc->p_arglen;
17321732
req->rq_callsize <<= 2;
1733-
req->rq_rcvsize = RPC_REPHDRSIZE + auth->au_rslack + proc->p_replen;
1733+
/*
1734+
* Note: the reply buffer must at minimum allocate enough space
1735+
* for the 'struct accepted_reply' from RFC5531.
1736+
*/
1737+
req->rq_rcvsize = RPC_REPHDRSIZE + auth->au_rslack + \
1738+
max_t(size_t, proc->p_replen, 2);
17341739
req->rq_rcvsize <<= 2;
17351740

17361741
status = xprt->ops->buf_alloc(task);
@@ -2387,9 +2392,6 @@ call_decode(struct rpc_task *task)
23872392
WARN_ON(memcmp(&req->rq_rcv_buf, &req->rq_private_buf,
23882393
sizeof(req->rq_rcv_buf)) != 0);
23892394

2390-
if (req->rq_rcv_buf.len < 12)
2391-
goto out_retry;
2392-
23932395
xdr_init_decode(&xdr, &req->rq_rcv_buf,
23942396
req->rq_rcv_buf.head[0].iov_base, req);
23952397
switch (rpc_decode_header(task, &xdr)) {
@@ -2400,7 +2402,6 @@ call_decode(struct rpc_task *task)
24002402
task->tk_pid, __func__, task->tk_status);
24012403
return;
24022404
case -EAGAIN:
2403-
out_retry:
24042405
task->tk_status = 0;
24052406
/* Note: rpc_decode_header() may have freed the RPC slot */
24062407
if (task->tk_rqstp == req) {
@@ -2449,7 +2450,7 @@ static noinline int
24492450
rpc_decode_header(struct rpc_task *task, struct xdr_stream *xdr)
24502451
{
24512452
struct rpc_clnt *clnt = task->tk_client;
2452-
int error = -EACCES;
2453+
int error;
24532454
__be32 *p;
24542455

24552456
/* 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)
24582459
* undefined results
24592460
*/
24602461
if (task->tk_rqstp->rq_rcv_buf.len & 3)
2461-
goto out_badlen;
2462+
goto out_unparsable;
24622463

24632464
p = xdr_inline_decode(xdr, 3 * sizeof(*p));
24642465
if (!p)
@@ -2492,10 +2493,12 @@ rpc_decode_header(struct rpc_task *task, struct xdr_stream *xdr)
24922493
error = -EOPNOTSUPP;
24932494
goto out_err;
24942495
case rpc_garbage_args:
2496+
case rpc_system_err:
24952497
trace_rpc__garbage_args(task);
2498+
error = -EIO;
24962499
break;
24972500
default:
2498-
trace_rpc__unparsable(task);
2501+
goto out_unparsable;
24992502
}
25002503

25012504
out_garbage:
@@ -2509,11 +2512,6 @@ rpc_decode_header(struct rpc_task *task, struct xdr_stream *xdr)
25092512
rpc_exit(task, error);
25102513
return error;
25112514

2512-
out_badlen:
2513-
trace_rpc__unparsable(task);
2514-
error = -EIO;
2515-
goto out_err;
2516-
25172515
out_unparsable:
25182516
trace_rpc__unparsable(task);
25192517
error = -EIO;
@@ -2524,6 +2522,7 @@ rpc_decode_header(struct rpc_task *task, struct xdr_stream *xdr)
25242522
goto out_garbage;
25252523

25262524
out_msg_denied:
2525+
error = -EACCES;
25272526
p = xdr_inline_decode(xdr, sizeof(*p));
25282527
if (!p)
25292528
goto out_unparsable;
@@ -2535,9 +2534,7 @@ rpc_decode_header(struct rpc_task *task, struct xdr_stream *xdr)
25352534
error = -EPROTONOSUPPORT;
25362535
goto out_err;
25372536
default:
2538-
trace_rpc__unparsable(task);
2539-
error = -EIO;
2540-
goto out_err;
2537+
goto out_unparsable;
25412538
}
25422539

25432540
p = xdr_inline_decode(xdr, sizeof(*p));
@@ -2572,8 +2569,7 @@ rpc_decode_header(struct rpc_task *task, struct xdr_stream *xdr)
25722569
task->tk_xprt->servername);
25732570
break;
25742571
default:
2575-
trace_rpc__unparsable(task);
2576-
error = -EIO;
2572+
goto out_unparsable;
25772573
}
25782574
goto out_err;
25792575
}

net/sunrpc/xprt.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -664,7 +664,7 @@ void xprt_disconnect_done(struct rpc_xprt *xprt)
664664
spin_lock_bh(&xprt->transport_lock);
665665
xprt_clear_connected(xprt);
666666
xprt_clear_write_space_locked(xprt);
667-
xprt_wake_pending_tasks(xprt, -EAGAIN);
667+
xprt_wake_pending_tasks(xprt, -ENOTCONN);
668668
spin_unlock_bh(&xprt->transport_lock);
669669
}
670670
EXPORT_SYMBOL_GPL(xprt_disconnect_done);

net/sunrpc/xprtsock.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -453,7 +453,7 @@ xs_read_xdr_buf(struct socket *sock, struct msghdr *msg, int flags,
453453
goto out;
454454
if (ret != want)
455455
goto out;
456-
} else
456+
} else if (offset < seek_init)
457457
offset = seek_init;
458458
ret = -EMSGSIZE;
459459
out:

0 commit comments

Comments
 (0)