Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 093a1468 authored by Trond Myklebust's avatar Trond Myklebust Committed by J. Bruce Fields
Browse files

SUNRPC: Fix locking around callback channel reply receive



Both xprt_lookup_rqst() and xprt_complete_rqst() require that you
take the transport lock in order to avoid races with xprt_transmit().

Signed-off-by: default avatarTrond Myklebust <trond.myklebust@primarydata.com>
Cc: stable@vger.kernel.org
Reviewed-by: default avatarJeff Layton <jlayton@primarydata.com>
Signed-off-by: default avatarJ. Bruce Fields <bfields@redhat.com>
parent 6d0ba043
Loading
Loading
Loading
Loading
+16 −11
Original line number Original line Diff line number Diff line
@@ -1019,17 +1019,12 @@ static int receive_cb_reply(struct svc_sock *svsk, struct svc_rqst *rqstp)
	xid = *p++;
	xid = *p++;
	calldir = *p;
	calldir = *p;


	if (bc_xprt)
	if (!bc_xprt)
		req = xprt_lookup_rqst(bc_xprt, xid);

	if (!req) {
		printk(KERN_NOTICE
			"%s: Got unrecognized reply: "
			"calldir 0x%x xpt_bc_xprt %p xid %08x\n",
			__func__, ntohl(calldir),
			bc_xprt, ntohl(xid));
		return -EAGAIN;
		return -EAGAIN;
	}
	spin_lock_bh(&bc_xprt->transport_lock);
	req = xprt_lookup_rqst(bc_xprt, xid);
	if (!req)
		goto unlock_notfound;


	memcpy(&req->rq_private_buf, &req->rq_rcv_buf, sizeof(struct xdr_buf));
	memcpy(&req->rq_private_buf, &req->rq_rcv_buf, sizeof(struct xdr_buf));
	/*
	/*
@@ -1040,11 +1035,21 @@ static int receive_cb_reply(struct svc_sock *svsk, struct svc_rqst *rqstp)
	dst = &req->rq_private_buf.head[0];
	dst = &req->rq_private_buf.head[0];
	src = &rqstp->rq_arg.head[0];
	src = &rqstp->rq_arg.head[0];
	if (dst->iov_len < src->iov_len)
	if (dst->iov_len < src->iov_len)
		return -EAGAIN; /* whatever; just giving up. */
		goto unlock_eagain; /* whatever; just giving up. */
	memcpy(dst->iov_base, src->iov_base, src->iov_len);
	memcpy(dst->iov_base, src->iov_base, src->iov_len);
	xprt_complete_rqst(req->rq_task, rqstp->rq_arg.len);
	xprt_complete_rqst(req->rq_task, rqstp->rq_arg.len);
	rqstp->rq_arg.len = 0;
	rqstp->rq_arg.len = 0;
	spin_unlock_bh(&bc_xprt->transport_lock);
	return 0;
	return 0;
unlock_notfound:
	printk(KERN_NOTICE
		"%s: Got unrecognized reply: "
		"calldir 0x%x xpt_bc_xprt %p xid %08x\n",
		__func__, ntohl(calldir),
		bc_xprt, ntohl(xid));
unlock_eagain:
	spin_unlock_bh(&bc_xprt->transport_lock);
	return -EAGAIN;
}
}


static int copy_pages_to_kvecs(struct kvec *vec, struct page **pages, int len)
static int copy_pages_to_kvecs(struct kvec *vec, struct page **pages, int len)