mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-28 10:41:38 -04:00
NFS client updates for Linux 4.14
Hightlights include:
Stable bugfixes:
- Fix mirror allocation in the writeback code to avoid a use after free
- Fix the O_DSYNC writes to use the correct byte range
- Fix 2 use after free issues in the I/O code
Features:
- Writeback fixes to split up the inode->i_lock in order to reduce contention
- RPC client receive fixes to reduce the amount of time the
xprt->transport_lock is held when receiving data from a socket into am
XDR buffer.
- Ditto fixes to reduce contention between call side users of the rdma
rb_lock, and its use in rpcrdma_reply_handler.
- Re-arrange rdma stats to reduce false cacheline sharing.
- Various rdma cleanups and optimisations.
- Refactor the NFSv4.1 exchange id code and clean up the code.
- Const-ify all instances of struct rpc_xprt_ops
Bugfixes:
- Fix the NFSv2 'sec=' mount option.
- NFSv4.1: don't use machine credentials for CLOSE when using 'sec=sys'
- Fix the NFSv3 GRANT callback when the port changes on the server.
- Fix livelock issues with COMMIT
- NFSv4: Use correct inode in _nfs4_opendata_to_nfs4_state() when doing
and NFSv4.1 open by filehandle.
-----BEGIN PGP SIGNATURE-----
iQIcBAABAgAGBQJZtbvIAAoJEGcL54qWCgDy/boP/jRuVk6B2VyhWnJkOgdQzIN3
Q8PIR0oxkywH2MI7c9/G2k5b/HD9BK2iQrXzIoPxRuPrckKLwzqYclzG8PR4Niyg
D3CCzrvGcEXZrv/nHQ+HDMD0ZuUyXFqhrYeyQwNSJ9p/oP0gaxnYwteennfJVa99
mv6+LdoY+lzVYJI1gmMHVF2zOhN+rTe7xUVnjYnsVCpwMvL+u992oZl3qQJRFG6b
HlXOy7h5JRFyue61P20PSgh9D1JUWWYD/V0EG+7cIvByAg5KxhvVgjqSsTTT7FXe
Omn4fTv1MFzk8er9qYFRjpM2IoIdAejFMqX3/PxQVr2qOFNmHYrq+WsdWNQEr/Wu
WREJu5Ac1Hboe2/scA+DtuVPFePPPyrolhwk533aNWrdDywg01e0XqBEDKR/atJd
u5lvW20UfLQuCFLOpaxDpq2ngQSOg6t96N36tsydG0SAVpiydOPMLqkQi7Nb3aoB
79xGpmtnijP5T6jnOI2/nexM08OMTI0BhMbXJC5v1+lnxIJKcKdnGlTM4UJyxUMq
/3dFI4IQZLfkMEjIvZFoi+nKWx3DYhiUhkKhbBYwtB4P4q8Z2qKTPHFxORz9griZ
Pa+8BPuDuodIWuDD97q1Dnw2NWjQim8Rx/ce4c8FHGzwMJLPkcVqk+guGsub5IdO
7qF7Vvv02gJ48TAqTBDf
=1Ssl
-----END PGP SIGNATURE-----
Merge tag 'nfs-for-4.14-1' of git://git.linux-nfs.org/projects/trondmy/linux-nfs
Pull NFS client updates from Trond Myklebust:
"Hightlights include:
Stable bugfixes:
- Fix mirror allocation in the writeback code to avoid a use after
free
- Fix the O_DSYNC writes to use the correct byte range
- Fix 2 use after free issues in the I/O code
Features:
- Writeback fixes to split up the inode->i_lock in order to reduce
contention
- RPC client receive fixes to reduce the amount of time the
xprt->transport_lock is held when receiving data from a socket into
am XDR buffer.
- Ditto fixes to reduce contention between call side users of the
rdma rb_lock, and its use in rpcrdma_reply_handler.
- Re-arrange rdma stats to reduce false cacheline sharing.
- Various rdma cleanups and optimisations.
- Refactor the NFSv4.1 exchange id code and clean up the code.
- Const-ify all instances of struct rpc_xprt_ops
Bugfixes:
- Fix the NFSv2 'sec=' mount option.
- NFSv4.1: don't use machine credentials for CLOSE when using
'sec=sys'
- Fix the NFSv3 GRANT callback when the port changes on the server.
- Fix livelock issues with COMMIT
- NFSv4: Use correct inode in _nfs4_opendata_to_nfs4_state() when
doing and NFSv4.1 open by filehandle"
* tag 'nfs-for-4.14-1' of git://git.linux-nfs.org/projects/trondmy/linux-nfs: (69 commits)
NFS: Count the bytes of skipped subrequests in nfs_lock_and_join_requests()
NFS: Don't hold the group lock when calling nfs_release_request()
NFS: Remove pnfs_generic_transfer_commit_list()
NFS: nfs_lock_and_join_requests and nfs_scan_commit_list can deadlock
NFS: Fix 2 use after free issues in the I/O code
NFS: Sync the correct byte range during synchronous writes
lockd: Delete an error message for a failed memory allocation in reclaimer()
NFS: remove jiffies field from access cache
NFS: flush data when locking a file to ensure cache coherence for mmap.
SUNRPC: remove some dead code.
NFS: don't expect errors from mempool_alloc().
xprtrdma: Use xprt_pin_rqst in rpcrdma_reply_handler
xprtrdma: Re-arrange struct rx_stats
NFS: Fix NFSv2 security settings
NFSv4.1: don't use machine credentials for CLOSE when using 'sec=sys'
SUNRPC: ECONNREFUSED should cause a rebind.
NFS: Remove unused parameter gfp_flags from nfs_pageio_init()
NFSv4: Fix up mirror allocation
SUNRPC: Add a separate spinlock to protect the RPC request receive list
SUNRPC: Cleanup xs_tcp_read_common()
...
This commit is contained in:
commit
8e7757d83d
36 changed files with 1228 additions and 1133 deletions
|
|
@ -171,10 +171,10 @@ int xprt_setup_bc(struct rpc_xprt *xprt, unsigned int min_reqs)
|
|||
/*
|
||||
* Add the temporary list to the backchannel preallocation list
|
||||
*/
|
||||
spin_lock_bh(&xprt->bc_pa_lock);
|
||||
spin_lock(&xprt->bc_pa_lock);
|
||||
list_splice(&tmp_list, &xprt->bc_pa_list);
|
||||
xprt_inc_alloc_count(xprt, min_reqs);
|
||||
spin_unlock_bh(&xprt->bc_pa_lock);
|
||||
spin_unlock(&xprt->bc_pa_lock);
|
||||
|
||||
dprintk("RPC: setup backchannel transport done\n");
|
||||
return 0;
|
||||
|
|
|
|||
|
|
@ -1903,6 +1903,14 @@ call_connect_status(struct rpc_task *task)
|
|||
task->tk_status = 0;
|
||||
switch (status) {
|
||||
case -ECONNREFUSED:
|
||||
/* A positive refusal suggests a rebind is needed. */
|
||||
if (RPC_IS_SOFTCONN(task))
|
||||
break;
|
||||
if (clnt->cl_autobind) {
|
||||
rpc_force_rebind(clnt);
|
||||
task->tk_action = call_bind;
|
||||
return;
|
||||
}
|
||||
case -ECONNRESET:
|
||||
case -ECONNABORTED:
|
||||
case -ENETUNREACH:
|
||||
|
|
@ -2139,10 +2147,6 @@ call_status(struct rpc_task *task)
|
|||
rpc_delay(task, 3*HZ);
|
||||
case -ETIMEDOUT:
|
||||
task->tk_action = call_timeout;
|
||||
if (!(task->tk_flags & RPC_TASK_NO_RETRANS_TIMEOUT)
|
||||
&& task->tk_client->cl_discrtry)
|
||||
xprt_conditional_disconnect(req->rq_xprt,
|
||||
req->rq_connect_cookie);
|
||||
break;
|
||||
case -ECONNREFUSED:
|
||||
case -ECONNRESET:
|
||||
|
|
|
|||
|
|
@ -1013,7 +1013,7 @@ static int receive_cb_reply(struct svc_sock *svsk, struct svc_rqst *rqstp)
|
|||
|
||||
if (!bc_xprt)
|
||||
return -EAGAIN;
|
||||
spin_lock_bh(&bc_xprt->transport_lock);
|
||||
spin_lock(&bc_xprt->recv_lock);
|
||||
req = xprt_lookup_rqst(bc_xprt, xid);
|
||||
if (!req)
|
||||
goto unlock_notfound;
|
||||
|
|
@ -1031,7 +1031,7 @@ static int receive_cb_reply(struct svc_sock *svsk, struct svc_rqst *rqstp)
|
|||
memcpy(dst->iov_base, src->iov_base, src->iov_len);
|
||||
xprt_complete_rqst(req->rq_task, rqstp->rq_arg.len);
|
||||
rqstp->rq_arg.len = 0;
|
||||
spin_unlock_bh(&bc_xprt->transport_lock);
|
||||
spin_unlock(&bc_xprt->recv_lock);
|
||||
return 0;
|
||||
unlock_notfound:
|
||||
printk(KERN_NOTICE
|
||||
|
|
@ -1040,7 +1040,7 @@ unlock_notfound:
|
|||
__func__, ntohl(calldir),
|
||||
bc_xprt, ntohl(xid));
|
||||
unlock_eagain:
|
||||
spin_unlock_bh(&bc_xprt->transport_lock);
|
||||
spin_unlock(&bc_xprt->recv_lock);
|
||||
return -EAGAIN;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -844,6 +844,50 @@ struct rpc_rqst *xprt_lookup_rqst(struct rpc_xprt *xprt, __be32 xid)
|
|||
}
|
||||
EXPORT_SYMBOL_GPL(xprt_lookup_rqst);
|
||||
|
||||
/**
|
||||
* xprt_pin_rqst - Pin a request on the transport receive list
|
||||
* @req: Request to pin
|
||||
*
|
||||
* Caller must ensure this is atomic with the call to xprt_lookup_rqst()
|
||||
* so should be holding the xprt transport lock.
|
||||
*/
|
||||
void xprt_pin_rqst(struct rpc_rqst *req)
|
||||
{
|
||||
set_bit(RPC_TASK_MSG_RECV, &req->rq_task->tk_runstate);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(xprt_pin_rqst);
|
||||
|
||||
/**
|
||||
* xprt_unpin_rqst - Unpin a request on the transport receive list
|
||||
* @req: Request to pin
|
||||
*
|
||||
* Caller should be holding the xprt transport lock.
|
||||
*/
|
||||
void xprt_unpin_rqst(struct rpc_rqst *req)
|
||||
{
|
||||
struct rpc_task *task = req->rq_task;
|
||||
|
||||
clear_bit(RPC_TASK_MSG_RECV, &task->tk_runstate);
|
||||
if (test_bit(RPC_TASK_MSG_RECV_WAIT, &task->tk_runstate))
|
||||
wake_up_bit(&task->tk_runstate, RPC_TASK_MSG_RECV);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(xprt_unpin_rqst);
|
||||
|
||||
static void xprt_wait_on_pinned_rqst(struct rpc_rqst *req)
|
||||
__must_hold(&req->rq_xprt->recv_lock)
|
||||
{
|
||||
struct rpc_task *task = req->rq_task;
|
||||
|
||||
if (task && test_bit(RPC_TASK_MSG_RECV, &task->tk_runstate)) {
|
||||
spin_unlock(&req->rq_xprt->recv_lock);
|
||||
set_bit(RPC_TASK_MSG_RECV_WAIT, &task->tk_runstate);
|
||||
wait_on_bit(&task->tk_runstate, RPC_TASK_MSG_RECV,
|
||||
TASK_UNINTERRUPTIBLE);
|
||||
clear_bit(RPC_TASK_MSG_RECV_WAIT, &task->tk_runstate);
|
||||
spin_lock(&req->rq_xprt->recv_lock);
|
||||
}
|
||||
}
|
||||
|
||||
static void xprt_update_rtt(struct rpc_task *task)
|
||||
{
|
||||
struct rpc_rqst *req = task->tk_rqstp;
|
||||
|
|
@ -966,13 +1010,13 @@ void xprt_transmit(struct rpc_task *task)
|
|||
/*
|
||||
* Add to the list only if we're expecting a reply
|
||||
*/
|
||||
spin_lock_bh(&xprt->transport_lock);
|
||||
/* Update the softirq receive buffer */
|
||||
memcpy(&req->rq_private_buf, &req->rq_rcv_buf,
|
||||
sizeof(req->rq_private_buf));
|
||||
/* Add request to the receive list */
|
||||
spin_lock(&xprt->recv_lock);
|
||||
list_add_tail(&req->rq_list, &xprt->recv);
|
||||
spin_unlock_bh(&xprt->transport_lock);
|
||||
spin_unlock(&xprt->recv_lock);
|
||||
xprt_reset_majortimeo(req);
|
||||
/* Turn off autodisconnect */
|
||||
del_singleshot_timer_sync(&xprt->timer);
|
||||
|
|
@ -1287,12 +1331,16 @@ void xprt_release(struct rpc_task *task)
|
|||
task->tk_ops->rpc_count_stats(task, task->tk_calldata);
|
||||
else if (task->tk_client)
|
||||
rpc_count_iostats(task, task->tk_client->cl_metrics);
|
||||
spin_lock(&xprt->recv_lock);
|
||||
if (!list_empty(&req->rq_list)) {
|
||||
list_del(&req->rq_list);
|
||||
xprt_wait_on_pinned_rqst(req);
|
||||
}
|
||||
spin_unlock(&xprt->recv_lock);
|
||||
spin_lock_bh(&xprt->transport_lock);
|
||||
xprt->ops->release_xprt(xprt, task);
|
||||
if (xprt->ops->release_request)
|
||||
xprt->ops->release_request(task);
|
||||
if (!list_empty(&req->rq_list))
|
||||
list_del(&req->rq_list);
|
||||
xprt->last_used = jiffies;
|
||||
xprt_schedule_autodisconnect(xprt);
|
||||
spin_unlock_bh(&xprt->transport_lock);
|
||||
|
|
@ -1318,6 +1366,7 @@ static void xprt_init(struct rpc_xprt *xprt, struct net *net)
|
|||
|
||||
spin_lock_init(&xprt->transport_lock);
|
||||
spin_lock_init(&xprt->reserve_lock);
|
||||
spin_lock_init(&xprt->recv_lock);
|
||||
|
||||
INIT_LIST_HEAD(&xprt->free);
|
||||
INIT_LIST_HEAD(&xprt->recv);
|
||||
|
|
|
|||
|
|
@ -49,6 +49,7 @@ static int rpcrdma_bc_setup_rqst(struct rpcrdma_xprt *r_xprt,
|
|||
if (IS_ERR(rb))
|
||||
goto out_fail;
|
||||
req->rl_rdmabuf = rb;
|
||||
xdr_buf_init(&req->rl_hdrbuf, rb->rg_base, rdmab_length(rb));
|
||||
|
||||
size = r_xprt->rx_data.inline_rsize;
|
||||
rb = rpcrdma_alloc_regbuf(size, DMA_TO_DEVICE, GFP_KERNEL);
|
||||
|
|
@ -202,20 +203,24 @@ size_t xprt_rdma_bc_maxpayload(struct rpc_xprt *xprt)
|
|||
*/
|
||||
int rpcrdma_bc_marshal_reply(struct rpc_rqst *rqst)
|
||||
{
|
||||
struct rpc_xprt *xprt = rqst->rq_xprt;
|
||||
struct rpcrdma_xprt *r_xprt = rpcx_to_rdmax(xprt);
|
||||
struct rpcrdma_xprt *r_xprt = rpcx_to_rdmax(rqst->rq_xprt);
|
||||
struct rpcrdma_req *req = rpcr_to_rdmar(rqst);
|
||||
struct rpcrdma_msg *headerp;
|
||||
__be32 *p;
|
||||
|
||||
headerp = rdmab_to_msg(req->rl_rdmabuf);
|
||||
headerp->rm_xid = rqst->rq_xid;
|
||||
headerp->rm_vers = rpcrdma_version;
|
||||
headerp->rm_credit =
|
||||
cpu_to_be32(r_xprt->rx_buf.rb_bc_srv_max_requests);
|
||||
headerp->rm_type = rdma_msg;
|
||||
headerp->rm_body.rm_chunks[0] = xdr_zero;
|
||||
headerp->rm_body.rm_chunks[1] = xdr_zero;
|
||||
headerp->rm_body.rm_chunks[2] = xdr_zero;
|
||||
rpcrdma_set_xdrlen(&req->rl_hdrbuf, 0);
|
||||
xdr_init_encode(&req->rl_stream, &req->rl_hdrbuf,
|
||||
req->rl_rdmabuf->rg_base);
|
||||
|
||||
p = xdr_reserve_space(&req->rl_stream, 28);
|
||||
if (unlikely(!p))
|
||||
return -EIO;
|
||||
*p++ = rqst->rq_xid;
|
||||
*p++ = rpcrdma_version;
|
||||
*p++ = cpu_to_be32(r_xprt->rx_buf.rb_bc_srv_max_requests);
|
||||
*p++ = rdma_msg;
|
||||
*p++ = xdr_zero;
|
||||
*p++ = xdr_zero;
|
||||
*p = xdr_zero;
|
||||
|
||||
if (!rpcrdma_prepare_send_sges(&r_xprt->rx_ia, req, RPCRDMA_HDRLEN_MIN,
|
||||
&rqst->rq_snd_buf, rpcrdma_noch))
|
||||
|
|
@ -271,9 +276,6 @@ void xprt_rdma_bc_free_rqst(struct rpc_rqst *rqst)
|
|||
* @xprt: transport receiving the call
|
||||
* @rep: receive buffer containing the call
|
||||
*
|
||||
* Called in the RPC reply handler, which runs in a tasklet.
|
||||
* Be quick about it.
|
||||
*
|
||||
* Operational assumptions:
|
||||
* o Backchannel credits are ignored, just as the NFS server
|
||||
* forechannel currently does
|
||||
|
|
@ -284,7 +286,6 @@ void rpcrdma_bc_receive_call(struct rpcrdma_xprt *r_xprt,
|
|||
struct rpcrdma_rep *rep)
|
||||
{
|
||||
struct rpc_xprt *xprt = &r_xprt->rx_xprt;
|
||||
struct rpcrdma_msg *headerp;
|
||||
struct svc_serv *bc_serv;
|
||||
struct rpcrdma_req *req;
|
||||
struct rpc_rqst *rqst;
|
||||
|
|
@ -292,24 +293,15 @@ void rpcrdma_bc_receive_call(struct rpcrdma_xprt *r_xprt,
|
|||
size_t size;
|
||||
__be32 *p;
|
||||
|
||||
headerp = rdmab_to_msg(rep->rr_rdmabuf);
|
||||
p = xdr_inline_decode(&rep->rr_stream, 0);
|
||||
size = xdr_stream_remaining(&rep->rr_stream);
|
||||
|
||||
#ifdef RPCRDMA_BACKCHANNEL_DEBUG
|
||||
pr_info("RPC: %s: callback XID %08x, length=%u\n",
|
||||
__func__, be32_to_cpu(headerp->rm_xid), rep->rr_len);
|
||||
pr_info("RPC: %s: %*ph\n", __func__, rep->rr_len, headerp);
|
||||
__func__, be32_to_cpup(p), size);
|
||||
pr_info("RPC: %s: %*ph\n", __func__, size, p);
|
||||
#endif
|
||||
|
||||
/* Sanity check:
|
||||
* Need at least enough bytes for RPC/RDMA header, as code
|
||||
* here references the header fields by array offset. Also,
|
||||
* backward calls are always inline, so ensure there
|
||||
* are some bytes beyond the RPC/RDMA header.
|
||||
*/
|
||||
if (rep->rr_len < RPCRDMA_HDRLEN_MIN + 24)
|
||||
goto out_short;
|
||||
p = (__be32 *)((unsigned char *)headerp + RPCRDMA_HDRLEN_MIN);
|
||||
size = rep->rr_len - RPCRDMA_HDRLEN_MIN;
|
||||
|
||||
/* Grab a free bc rqst */
|
||||
spin_lock(&xprt->bc_pa_lock);
|
||||
if (list_empty(&xprt->bc_pa_list)) {
|
||||
|
|
@ -325,7 +317,7 @@ void rpcrdma_bc_receive_call(struct rpcrdma_xprt *r_xprt,
|
|||
/* Prepare rqst */
|
||||
rqst->rq_reply_bytes_recvd = 0;
|
||||
rqst->rq_bytes_sent = 0;
|
||||
rqst->rq_xid = headerp->rm_xid;
|
||||
rqst->rq_xid = *p;
|
||||
|
||||
rqst->rq_private_buf.len = size;
|
||||
set_bit(RPC_BC_PA_IN_USE, &rqst->rq_bc_pa_state);
|
||||
|
|
@ -337,9 +329,9 @@ void rpcrdma_bc_receive_call(struct rpcrdma_xprt *r_xprt,
|
|||
buf->len = size;
|
||||
|
||||
/* The receive buffer has to be hooked to the rpcrdma_req
|
||||
* so that it can be reposted after the server is done
|
||||
* parsing it but just before sending the backward
|
||||
* direction reply.
|
||||
* so that it is not released while the req is pointing
|
||||
* to its buffer, and so that it can be reposted after
|
||||
* the Upper Layer is done decoding it.
|
||||
*/
|
||||
req = rpcr_to_rdmar(rqst);
|
||||
dprintk("RPC: %s: attaching rep %p to req %p\n",
|
||||
|
|
@ -367,13 +359,4 @@ out_overflow:
|
|||
* when the connection is re-established.
|
||||
*/
|
||||
return;
|
||||
|
||||
out_short:
|
||||
pr_warn("RPC/RDMA short backward direction call\n");
|
||||
|
||||
if (rpcrdma_ep_post_recv(&r_xprt->rx_ia, rep))
|
||||
xprt_disconnect_done(xprt);
|
||||
else
|
||||
pr_warn("RPC: %s: reposting rep %p\n",
|
||||
__func__, rep);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -177,7 +177,7 @@ fmr_op_maxpages(struct rpcrdma_xprt *r_xprt)
|
|||
/* Use the ib_map_phys_fmr() verb to register a memory region
|
||||
* for remote access via RDMA READ or RDMA WRITE.
|
||||
*/
|
||||
static int
|
||||
static struct rpcrdma_mr_seg *
|
||||
fmr_op_map(struct rpcrdma_xprt *r_xprt, struct rpcrdma_mr_seg *seg,
|
||||
int nsegs, bool writing, struct rpcrdma_mw **out)
|
||||
{
|
||||
|
|
@ -188,7 +188,7 @@ fmr_op_map(struct rpcrdma_xprt *r_xprt, struct rpcrdma_mr_seg *seg,
|
|||
|
||||
mw = rpcrdma_get_mw(r_xprt);
|
||||
if (!mw)
|
||||
return -ENOBUFS;
|
||||
return ERR_PTR(-ENOBUFS);
|
||||
|
||||
pageoff = offset_in_page(seg1->mr_offset);
|
||||
seg1->mr_offset -= pageoff; /* start of page */
|
||||
|
|
@ -232,13 +232,13 @@ fmr_op_map(struct rpcrdma_xprt *r_xprt, struct rpcrdma_mr_seg *seg,
|
|||
mw->mw_offset = dma_pages[0] + pageoff;
|
||||
|
||||
*out = mw;
|
||||
return mw->mw_nents;
|
||||
return seg;
|
||||
|
||||
out_dmamap_err:
|
||||
pr_err("rpcrdma: failed to DMA map sg %p sg_nents %d\n",
|
||||
mw->mw_sg, i);
|
||||
rpcrdma_put_mw(r_xprt, mw);
|
||||
return -EIO;
|
||||
return ERR_PTR(-EIO);
|
||||
|
||||
out_maperr:
|
||||
pr_err("rpcrdma: ib_map_phys_fmr %u@0x%llx+%i (%d) status %i\n",
|
||||
|
|
@ -247,7 +247,7 @@ out_maperr:
|
|||
ib_dma_unmap_sg(r_xprt->rx_ia.ri_device,
|
||||
mw->mw_sg, mw->mw_nents, mw->mw_dir);
|
||||
rpcrdma_put_mw(r_xprt, mw);
|
||||
return -EIO;
|
||||
return ERR_PTR(-EIO);
|
||||
}
|
||||
|
||||
/* Invalidate all memory regions that were registered for "req".
|
||||
|
|
|
|||
|
|
@ -344,7 +344,7 @@ frwr_wc_localinv_wake(struct ib_cq *cq, struct ib_wc *wc)
|
|||
/* Post a REG_MR Work Request to register a memory region
|
||||
* for remote access via RDMA READ or RDMA WRITE.
|
||||
*/
|
||||
static int
|
||||
static struct rpcrdma_mr_seg *
|
||||
frwr_op_map(struct rpcrdma_xprt *r_xprt, struct rpcrdma_mr_seg *seg,
|
||||
int nsegs, bool writing, struct rpcrdma_mw **out)
|
||||
{
|
||||
|
|
@ -364,7 +364,7 @@ frwr_op_map(struct rpcrdma_xprt *r_xprt, struct rpcrdma_mr_seg *seg,
|
|||
rpcrdma_defer_mr_recovery(mw);
|
||||
mw = rpcrdma_get_mw(r_xprt);
|
||||
if (!mw)
|
||||
return -ENOBUFS;
|
||||
return ERR_PTR(-ENOBUFS);
|
||||
} while (mw->frmr.fr_state != FRMR_IS_INVALID);
|
||||
frmr = &mw->frmr;
|
||||
frmr->fr_state = FRMR_IS_VALID;
|
||||
|
|
@ -429,25 +429,25 @@ frwr_op_map(struct rpcrdma_xprt *r_xprt, struct rpcrdma_mr_seg *seg,
|
|||
mw->mw_offset = mr->iova;
|
||||
|
||||
*out = mw;
|
||||
return mw->mw_nents;
|
||||
return seg;
|
||||
|
||||
out_dmamap_err:
|
||||
pr_err("rpcrdma: failed to DMA map sg %p sg_nents %d\n",
|
||||
mw->mw_sg, i);
|
||||
frmr->fr_state = FRMR_IS_INVALID;
|
||||
rpcrdma_put_mw(r_xprt, mw);
|
||||
return -EIO;
|
||||
return ERR_PTR(-EIO);
|
||||
|
||||
out_mapmr_err:
|
||||
pr_err("rpcrdma: failed to map mr %p (%d/%d)\n",
|
||||
frmr->fr_mr, n, mw->mw_nents);
|
||||
rpcrdma_defer_mr_recovery(mw);
|
||||
return -EIO;
|
||||
return ERR_PTR(-EIO);
|
||||
|
||||
out_senderr:
|
||||
pr_err("rpcrdma: FRMR registration ib_post_send returned %i\n", rc);
|
||||
rpcrdma_defer_mr_recovery(mw);
|
||||
return -ENOTCONN;
|
||||
return ERR_PTR(-ENOTCONN);
|
||||
}
|
||||
|
||||
/* Invalidate all memory regions that were registered for "req".
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -52,7 +52,7 @@ int svc_rdma_handle_bc_reply(struct rpc_xprt *xprt, __be32 *rdma_resp,
|
|||
if (src->iov_len < 24)
|
||||
goto out_shortreply;
|
||||
|
||||
spin_lock_bh(&xprt->transport_lock);
|
||||
spin_lock(&xprt->recv_lock);
|
||||
req = xprt_lookup_rqst(xprt, xid);
|
||||
if (!req)
|
||||
goto out_notfound;
|
||||
|
|
@ -69,17 +69,20 @@ int svc_rdma_handle_bc_reply(struct rpc_xprt *xprt, __be32 *rdma_resp,
|
|||
else if (credits > r_xprt->rx_buf.rb_bc_max_requests)
|
||||
credits = r_xprt->rx_buf.rb_bc_max_requests;
|
||||
|
||||
spin_lock_bh(&xprt->transport_lock);
|
||||
cwnd = xprt->cwnd;
|
||||
xprt->cwnd = credits << RPC_CWNDSHIFT;
|
||||
if (xprt->cwnd > cwnd)
|
||||
xprt_release_rqst_cong(req->rq_task);
|
||||
spin_unlock_bh(&xprt->transport_lock);
|
||||
|
||||
|
||||
ret = 0;
|
||||
xprt_complete_rqst(req->rq_task, rcvbuf->len);
|
||||
rcvbuf->len = 0;
|
||||
|
||||
out_unlock:
|
||||
spin_unlock_bh(&xprt->transport_lock);
|
||||
spin_unlock(&xprt->recv_lock);
|
||||
out:
|
||||
return ret;
|
||||
|
||||
|
|
@ -266,7 +269,7 @@ xprt_rdma_bc_put(struct rpc_xprt *xprt)
|
|||
module_put(THIS_MODULE);
|
||||
}
|
||||
|
||||
static struct rpc_xprt_ops xprt_rdma_bc_procs = {
|
||||
static const struct rpc_xprt_ops xprt_rdma_bc_procs = {
|
||||
.reserve_xprt = xprt_reserve_xprt_cong,
|
||||
.release_xprt = xprt_release_xprt_cong,
|
||||
.alloc_slot = xprt_alloc_slot,
|
||||
|
|
|
|||
|
|
@ -149,7 +149,7 @@ static struct ctl_table sunrpc_table[] = {
|
|||
|
||||
#endif
|
||||
|
||||
static struct rpc_xprt_ops xprt_rdma_procs; /*forward reference */
|
||||
static const struct rpc_xprt_ops xprt_rdma_procs;
|
||||
|
||||
static void
|
||||
xprt_rdma_format_addresses4(struct rpc_xprt *xprt, struct sockaddr *sap)
|
||||
|
|
@ -559,6 +559,7 @@ rpcrdma_get_rdmabuf(struct rpcrdma_xprt *r_xprt, struct rpcrdma_req *req,
|
|||
|
||||
r_xprt->rx_stats.hardway_register_count += size;
|
||||
req->rl_rdmabuf = rb;
|
||||
xdr_buf_init(&req->rl_hdrbuf, rb->rg_base, rdmab_length(rb));
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -684,7 +685,6 @@ xprt_rdma_free(struct rpc_task *task)
|
|||
|
||||
dprintk("RPC: %s: called on 0x%p\n", __func__, req->rl_reply);
|
||||
|
||||
rpcrdma_remove_req(&r_xprt->rx_buf, req);
|
||||
if (!list_empty(&req->rl_registered))
|
||||
ia->ri_ops->ro_unmap_safe(r_xprt, req, !RPC_IS_ASYNC(task));
|
||||
rpcrdma_unmap_sges(ia, req);
|
||||
|
|
@ -730,7 +730,7 @@ xprt_rdma_send_request(struct rpc_task *task)
|
|||
if (unlikely(!list_empty(&req->rl_registered)))
|
||||
r_xprt->rx_ia.ri_ops->ro_unmap_safe(r_xprt, req, false);
|
||||
|
||||
rc = rpcrdma_marshal_req(rqst);
|
||||
rc = rpcrdma_marshal_req(r_xprt, rqst);
|
||||
if (rc < 0)
|
||||
goto failed_marshal;
|
||||
|
||||
|
|
@ -811,7 +811,7 @@ xprt_rdma_disable_swap(struct rpc_xprt *xprt)
|
|||
* Plumbing for rpc transport switch and kernel module
|
||||
*/
|
||||
|
||||
static struct rpc_xprt_ops xprt_rdma_procs = {
|
||||
static const struct rpc_xprt_ops xprt_rdma_procs = {
|
||||
.reserve_xprt = xprt_reserve_xprt_cong,
|
||||
.release_xprt = xprt_release_xprt_cong, /* sunrpc/xprt.c */
|
||||
.alloc_slot = xprt_alloc_slot,
|
||||
|
|
|
|||
|
|
@ -139,14 +139,11 @@ rpcrdma_wc_send(struct ib_cq *cq, struct ib_wc *wc)
|
|||
static void
|
||||
rpcrdma_update_granted_credits(struct rpcrdma_rep *rep)
|
||||
{
|
||||
struct rpcrdma_msg *rmsgp = rdmab_to_msg(rep->rr_rdmabuf);
|
||||
struct rpcrdma_buffer *buffer = &rep->rr_rxprt->rx_buf;
|
||||
__be32 *p = rep->rr_rdmabuf->rg_base;
|
||||
u32 credits;
|
||||
|
||||
if (rep->rr_len < RPCRDMA_HDRLEN_ERR)
|
||||
return;
|
||||
|
||||
credits = be32_to_cpu(rmsgp->rm_credit);
|
||||
credits = be32_to_cpup(p + 2);
|
||||
if (credits == 0)
|
||||
credits = 1; /* don't deadlock */
|
||||
else if (credits > buffer->rb_max_requests)
|
||||
|
|
@ -173,21 +170,19 @@ rpcrdma_wc_receive(struct ib_cq *cq, struct ib_wc *wc)
|
|||
goto out_fail;
|
||||
|
||||
/* status == SUCCESS means all fields in wc are trustworthy */
|
||||
if (wc->opcode != IB_WC_RECV)
|
||||
return;
|
||||
|
||||
dprintk("RPC: %s: rep %p opcode 'recv', length %u: success\n",
|
||||
__func__, rep, wc->byte_len);
|
||||
|
||||
rep->rr_len = wc->byte_len;
|
||||
rpcrdma_set_xdrlen(&rep->rr_hdrbuf, wc->byte_len);
|
||||
rep->rr_wc_flags = wc->wc_flags;
|
||||
rep->rr_inv_rkey = wc->ex.invalidate_rkey;
|
||||
|
||||
ib_dma_sync_single_for_cpu(rdmab_device(rep->rr_rdmabuf),
|
||||
rdmab_addr(rep->rr_rdmabuf),
|
||||
rep->rr_len, DMA_FROM_DEVICE);
|
||||
wc->byte_len, DMA_FROM_DEVICE);
|
||||
|
||||
rpcrdma_update_granted_credits(rep);
|
||||
if (wc->byte_len >= RPCRDMA_HDRLEN_ERR)
|
||||
rpcrdma_update_granted_credits(rep);
|
||||
|
||||
out_schedule:
|
||||
queue_work(rpcrdma_receive_wq, &rep->rr_work);
|
||||
|
|
@ -198,7 +193,7 @@ out_fail:
|
|||
pr_err("rpcrdma: Recv: %s (%u/0x%x)\n",
|
||||
ib_wc_status_msg(wc->status),
|
||||
wc->status, wc->vendor_err);
|
||||
rep->rr_len = RPCRDMA_BAD_LEN;
|
||||
rpcrdma_set_xdrlen(&rep->rr_hdrbuf, 0);
|
||||
goto out_schedule;
|
||||
}
|
||||
|
||||
|
|
@ -974,6 +969,8 @@ rpcrdma_create_rep(struct rpcrdma_xprt *r_xprt)
|
|||
rc = PTR_ERR(rep->rr_rdmabuf);
|
||||
goto out_free;
|
||||
}
|
||||
xdr_buf_init(&rep->rr_hdrbuf, rep->rr_rdmabuf->rg_base,
|
||||
rdmab_length(rep->rr_rdmabuf));
|
||||
|
||||
rep->rr_cqe.done = rpcrdma_wc_receive;
|
||||
rep->rr_rxprt = r_xprt;
|
||||
|
|
@ -1004,7 +1001,6 @@ rpcrdma_buffer_create(struct rpcrdma_xprt *r_xprt)
|
|||
spin_lock_init(&buf->rb_recovery_lock);
|
||||
INIT_LIST_HEAD(&buf->rb_mws);
|
||||
INIT_LIST_HEAD(&buf->rb_all);
|
||||
INIT_LIST_HEAD(&buf->rb_pending);
|
||||
INIT_LIST_HEAD(&buf->rb_stale_mrs);
|
||||
INIT_DELAYED_WORK(&buf->rb_refresh_worker,
|
||||
rpcrdma_mr_refresh_worker);
|
||||
|
|
|
|||
|
|
@ -218,18 +218,17 @@ enum {
|
|||
|
||||
struct rpcrdma_rep {
|
||||
struct ib_cqe rr_cqe;
|
||||
unsigned int rr_len;
|
||||
int rr_wc_flags;
|
||||
u32 rr_inv_rkey;
|
||||
struct rpcrdma_regbuf *rr_rdmabuf;
|
||||
struct rpcrdma_xprt *rr_rxprt;
|
||||
struct work_struct rr_work;
|
||||
struct xdr_buf rr_hdrbuf;
|
||||
struct xdr_stream rr_stream;
|
||||
struct list_head rr_list;
|
||||
struct ib_recv_wr rr_recv_wr;
|
||||
struct rpcrdma_regbuf *rr_rdmabuf;
|
||||
};
|
||||
|
||||
#define RPCRDMA_BAD_LEN (~0U)
|
||||
|
||||
/*
|
||||
* struct rpcrdma_mw - external memory region metadata
|
||||
*
|
||||
|
|
@ -341,11 +340,12 @@ enum {
|
|||
struct rpcrdma_buffer;
|
||||
struct rpcrdma_req {
|
||||
struct list_head rl_list;
|
||||
__be32 rl_xid;
|
||||
unsigned int rl_mapped_sges;
|
||||
unsigned int rl_connect_cookie;
|
||||
struct rpcrdma_buffer *rl_buffer;
|
||||
struct rpcrdma_rep *rl_reply;
|
||||
struct xdr_stream rl_stream;
|
||||
struct xdr_buf rl_hdrbuf;
|
||||
struct ib_send_wr rl_send_wr;
|
||||
struct ib_sge rl_send_sge[RPCRDMA_MAX_SEND_SGES];
|
||||
struct rpcrdma_regbuf *rl_rdmabuf; /* xprt header */
|
||||
|
|
@ -403,7 +403,6 @@ struct rpcrdma_buffer {
|
|||
int rb_send_count, rb_recv_count;
|
||||
struct list_head rb_send_bufs;
|
||||
struct list_head rb_recv_bufs;
|
||||
struct list_head rb_pending;
|
||||
u32 rb_max_requests;
|
||||
atomic_t rb_credits; /* most recent credit grant */
|
||||
|
||||
|
|
@ -440,24 +439,27 @@ struct rpcrdma_create_data_internal {
|
|||
* Statistics for RPCRDMA
|
||||
*/
|
||||
struct rpcrdma_stats {
|
||||
/* accessed when sending a call */
|
||||
unsigned long read_chunk_count;
|
||||
unsigned long write_chunk_count;
|
||||
unsigned long reply_chunk_count;
|
||||
|
||||
unsigned long long total_rdma_request;
|
||||
unsigned long long total_rdma_reply;
|
||||
|
||||
/* rarely accessed error counters */
|
||||
unsigned long long pullup_copy_count;
|
||||
unsigned long long fixup_copy_count;
|
||||
unsigned long hardway_register_count;
|
||||
unsigned long failed_marshal_count;
|
||||
unsigned long bad_reply_count;
|
||||
unsigned long nomsg_call_count;
|
||||
unsigned long bcall_count;
|
||||
unsigned long mrs_recovered;
|
||||
unsigned long mrs_orphaned;
|
||||
unsigned long mrs_allocated;
|
||||
|
||||
/* accessed when receiving a reply */
|
||||
unsigned long long total_rdma_reply;
|
||||
unsigned long long fixup_copy_count;
|
||||
unsigned long local_inv_needed;
|
||||
unsigned long nomsg_call_count;
|
||||
unsigned long bcall_count;
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
@ -465,7 +467,8 @@ struct rpcrdma_stats {
|
|||
*/
|
||||
struct rpcrdma_xprt;
|
||||
struct rpcrdma_memreg_ops {
|
||||
int (*ro_map)(struct rpcrdma_xprt *,
|
||||
struct rpcrdma_mr_seg *
|
||||
(*ro_map)(struct rpcrdma_xprt *,
|
||||
struct rpcrdma_mr_seg *, int, bool,
|
||||
struct rpcrdma_mw **);
|
||||
void (*ro_unmap_sync)(struct rpcrdma_xprt *,
|
||||
|
|
@ -552,34 +555,6 @@ void rpcrdma_destroy_req(struct rpcrdma_req *);
|
|||
int rpcrdma_buffer_create(struct rpcrdma_xprt *);
|
||||
void rpcrdma_buffer_destroy(struct rpcrdma_buffer *);
|
||||
|
||||
static inline void
|
||||
rpcrdma_insert_req(struct rpcrdma_buffer *buffers, struct rpcrdma_req *req)
|
||||
{
|
||||
spin_lock(&buffers->rb_lock);
|
||||
if (list_empty(&req->rl_list))
|
||||
list_add_tail(&req->rl_list, &buffers->rb_pending);
|
||||
spin_unlock(&buffers->rb_lock);
|
||||
}
|
||||
|
||||
static inline struct rpcrdma_req *
|
||||
rpcrdma_lookup_req_locked(struct rpcrdma_buffer *buffers, __be32 xid)
|
||||
{
|
||||
struct rpcrdma_req *pos;
|
||||
|
||||
list_for_each_entry(pos, &buffers->rb_pending, rl_list)
|
||||
if (pos->rl_xid == xid)
|
||||
return pos;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static inline void
|
||||
rpcrdma_remove_req(struct rpcrdma_buffer *buffers, struct rpcrdma_req *req)
|
||||
{
|
||||
spin_lock(&buffers->rb_lock);
|
||||
list_del(&req->rl_list);
|
||||
spin_unlock(&buffers->rb_lock);
|
||||
}
|
||||
|
||||
struct rpcrdma_mw *rpcrdma_get_mw(struct rpcrdma_xprt *);
|
||||
void rpcrdma_put_mw(struct rpcrdma_xprt *, struct rpcrdma_mw *);
|
||||
struct rpcrdma_req *rpcrdma_buffer_get(struct rpcrdma_buffer *);
|
||||
|
|
@ -638,10 +613,16 @@ enum rpcrdma_chunktype {
|
|||
bool rpcrdma_prepare_send_sges(struct rpcrdma_ia *, struct rpcrdma_req *,
|
||||
u32, struct xdr_buf *, enum rpcrdma_chunktype);
|
||||
void rpcrdma_unmap_sges(struct rpcrdma_ia *, struct rpcrdma_req *);
|
||||
int rpcrdma_marshal_req(struct rpc_rqst *);
|
||||
int rpcrdma_marshal_req(struct rpcrdma_xprt *r_xprt, struct rpc_rqst *rqst);
|
||||
void rpcrdma_set_max_header_sizes(struct rpcrdma_xprt *);
|
||||
void rpcrdma_reply_handler(struct work_struct *work);
|
||||
|
||||
static inline void rpcrdma_set_xdrlen(struct xdr_buf *xdr, size_t len)
|
||||
{
|
||||
xdr->head[0].iov_len = len;
|
||||
xdr->len = len;
|
||||
}
|
||||
|
||||
/* RPC/RDMA module init - xprtrdma/transport.c
|
||||
*/
|
||||
extern unsigned int xprt_rdma_max_inline_read;
|
||||
|
|
|
|||
|
|
@ -969,10 +969,12 @@ static void xs_local_data_read_skb(struct rpc_xprt *xprt,
|
|||
return;
|
||||
|
||||
/* Look up and lock the request corresponding to the given XID */
|
||||
spin_lock_bh(&xprt->transport_lock);
|
||||
spin_lock(&xprt->recv_lock);
|
||||
rovr = xprt_lookup_rqst(xprt, *xp);
|
||||
if (!rovr)
|
||||
goto out_unlock;
|
||||
xprt_pin_rqst(rovr);
|
||||
spin_unlock(&xprt->recv_lock);
|
||||
task = rovr->rq_task;
|
||||
|
||||
copied = rovr->rq_private_buf.buflen;
|
||||
|
|
@ -981,13 +983,16 @@ static void xs_local_data_read_skb(struct rpc_xprt *xprt,
|
|||
|
||||
if (xs_local_copy_to_xdr(&rovr->rq_private_buf, skb)) {
|
||||
dprintk("RPC: sk_buff copy failed\n");
|
||||
goto out_unlock;
|
||||
spin_lock(&xprt->recv_lock);
|
||||
goto out_unpin;
|
||||
}
|
||||
|
||||
spin_lock(&xprt->recv_lock);
|
||||
xprt_complete_rqst(task, copied);
|
||||
|
||||
out_unpin:
|
||||
xprt_unpin_rqst(rovr);
|
||||
out_unlock:
|
||||
spin_unlock_bh(&xprt->transport_lock);
|
||||
spin_unlock(&xprt->recv_lock);
|
||||
}
|
||||
|
||||
static void xs_local_data_receive(struct sock_xprt *transport)
|
||||
|
|
@ -1050,10 +1055,12 @@ static void xs_udp_data_read_skb(struct rpc_xprt *xprt,
|
|||
return;
|
||||
|
||||
/* Look up and lock the request corresponding to the given XID */
|
||||
spin_lock_bh(&xprt->transport_lock);
|
||||
spin_lock(&xprt->recv_lock);
|
||||
rovr = xprt_lookup_rqst(xprt, *xp);
|
||||
if (!rovr)
|
||||
goto out_unlock;
|
||||
xprt_pin_rqst(rovr);
|
||||
spin_unlock(&xprt->recv_lock);
|
||||
task = rovr->rq_task;
|
||||
|
||||
if ((copied = rovr->rq_private_buf.buflen) > repsize)
|
||||
|
|
@ -1062,16 +1069,21 @@ static void xs_udp_data_read_skb(struct rpc_xprt *xprt,
|
|||
/* Suck it into the iovec, verify checksum if not done by hw. */
|
||||
if (csum_partial_copy_to_xdr(&rovr->rq_private_buf, skb)) {
|
||||
__UDPX_INC_STATS(sk, UDP_MIB_INERRORS);
|
||||
goto out_unlock;
|
||||
spin_lock(&xprt->recv_lock);
|
||||
goto out_unpin;
|
||||
}
|
||||
|
||||
__UDPX_INC_STATS(sk, UDP_MIB_INDATAGRAMS);
|
||||
|
||||
spin_lock_bh(&xprt->transport_lock);
|
||||
xprt_adjust_cwnd(xprt, task, copied);
|
||||
xprt_complete_rqst(task, copied);
|
||||
|
||||
out_unlock:
|
||||
spin_unlock_bh(&xprt->transport_lock);
|
||||
spin_lock(&xprt->recv_lock);
|
||||
xprt_complete_rqst(task, copied);
|
||||
out_unpin:
|
||||
xprt_unpin_rqst(rovr);
|
||||
out_unlock:
|
||||
spin_unlock(&xprt->recv_lock);
|
||||
}
|
||||
|
||||
static void xs_udp_data_receive(struct sock_xprt *transport)
|
||||
|
|
@ -1277,25 +1289,12 @@ static inline void xs_tcp_read_common(struct rpc_xprt *xprt,
|
|||
}
|
||||
|
||||
len = desc->count;
|
||||
if (len > transport->tcp_reclen - transport->tcp_offset) {
|
||||
struct xdr_skb_reader my_desc;
|
||||
|
||||
len = transport->tcp_reclen - transport->tcp_offset;
|
||||
memcpy(&my_desc, desc, sizeof(my_desc));
|
||||
my_desc.count = len;
|
||||
r = xdr_partial_copy_from_skb(rcvbuf, transport->tcp_copied,
|
||||
&my_desc, xdr_skb_read_bits);
|
||||
desc->count -= r;
|
||||
desc->offset += r;
|
||||
} else
|
||||
r = xdr_partial_copy_from_skb(rcvbuf, transport->tcp_copied,
|
||||
if (len > transport->tcp_reclen - transport->tcp_offset)
|
||||
desc->count = transport->tcp_reclen - transport->tcp_offset;
|
||||
r = xdr_partial_copy_from_skb(rcvbuf, transport->tcp_copied,
|
||||
desc, xdr_skb_read_bits);
|
||||
|
||||
if (r > 0) {
|
||||
transport->tcp_copied += r;
|
||||
transport->tcp_offset += r;
|
||||
}
|
||||
if (r != len) {
|
||||
if (desc->count) {
|
||||
/* Error when copying to the receive buffer,
|
||||
* usually because we weren't able to allocate
|
||||
* additional buffer pages. All we can do now
|
||||
|
|
@ -1315,6 +1314,10 @@ static inline void xs_tcp_read_common(struct rpc_xprt *xprt,
|
|||
return;
|
||||
}
|
||||
|
||||
transport->tcp_copied += r;
|
||||
transport->tcp_offset += r;
|
||||
desc->count = len - r;
|
||||
|
||||
dprintk("RPC: XID %08x read %zd bytes\n",
|
||||
ntohl(transport->tcp_xid), r);
|
||||
dprintk("RPC: xprt = %p, tcp_copied = %lu, tcp_offset = %u, "
|
||||
|
|
@ -1343,21 +1346,24 @@ static inline int xs_tcp_read_reply(struct rpc_xprt *xprt,
|
|||
dprintk("RPC: read reply XID %08x\n", ntohl(transport->tcp_xid));
|
||||
|
||||
/* Find and lock the request corresponding to this xid */
|
||||
spin_lock_bh(&xprt->transport_lock);
|
||||
spin_lock(&xprt->recv_lock);
|
||||
req = xprt_lookup_rqst(xprt, transport->tcp_xid);
|
||||
if (!req) {
|
||||
dprintk("RPC: XID %08x request not found!\n",
|
||||
ntohl(transport->tcp_xid));
|
||||
spin_unlock_bh(&xprt->transport_lock);
|
||||
spin_unlock(&xprt->recv_lock);
|
||||
return -1;
|
||||
}
|
||||
xprt_pin_rqst(req);
|
||||
spin_unlock(&xprt->recv_lock);
|
||||
|
||||
xs_tcp_read_common(xprt, desc, req);
|
||||
|
||||
spin_lock(&xprt->recv_lock);
|
||||
if (!(transport->tcp_flags & TCP_RCV_COPY_DATA))
|
||||
xprt_complete_rqst(req->rq_task, transport->tcp_copied);
|
||||
|
||||
spin_unlock_bh(&xprt->transport_lock);
|
||||
xprt_unpin_rqst(req);
|
||||
spin_unlock(&xprt->recv_lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -1376,11 +1382,9 @@ static int xs_tcp_read_callback(struct rpc_xprt *xprt,
|
|||
container_of(xprt, struct sock_xprt, xprt);
|
||||
struct rpc_rqst *req;
|
||||
|
||||
/* Look up and lock the request corresponding to the given XID */
|
||||
spin_lock_bh(&xprt->transport_lock);
|
||||
/* Look up the request corresponding to the given XID */
|
||||
req = xprt_lookup_bc_request(xprt, transport->tcp_xid);
|
||||
if (req == NULL) {
|
||||
spin_unlock_bh(&xprt->transport_lock);
|
||||
printk(KERN_WARNING "Callback slot table overflowed\n");
|
||||
xprt_force_disconnect(xprt);
|
||||
return -1;
|
||||
|
|
@ -1391,7 +1395,6 @@ static int xs_tcp_read_callback(struct rpc_xprt *xprt,
|
|||
|
||||
if (!(transport->tcp_flags & TCP_RCV_COPY_DATA))
|
||||
xprt_complete_bc_request(req, transport->tcp_copied);
|
||||
spin_unlock_bh(&xprt->transport_lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -1516,6 +1519,7 @@ static void xs_tcp_data_receive(struct sock_xprt *transport)
|
|||
.arg.data = xprt,
|
||||
};
|
||||
unsigned long total = 0;
|
||||
int loop;
|
||||
int read = 0;
|
||||
|
||||
mutex_lock(&transport->recv_mutex);
|
||||
|
|
@ -1524,20 +1528,20 @@ static void xs_tcp_data_receive(struct sock_xprt *transport)
|
|||
goto out;
|
||||
|
||||
/* We use rd_desc to pass struct xprt to xs_tcp_data_recv */
|
||||
for (;;) {
|
||||
for (loop = 0; loop < 64; loop++) {
|
||||
lock_sock(sk);
|
||||
read = tcp_read_sock(sk, &rd_desc, xs_tcp_data_recv);
|
||||
if (read <= 0) {
|
||||
clear_bit(XPRT_SOCK_DATA_READY, &transport->sock_state);
|
||||
release_sock(sk);
|
||||
if (!test_bit(XPRT_SOCK_DATA_READY, &transport->sock_state))
|
||||
break;
|
||||
} else {
|
||||
release_sock(sk);
|
||||
total += read;
|
||||
break;
|
||||
}
|
||||
release_sock(sk);
|
||||
total += read;
|
||||
rd_desc.count = 65536;
|
||||
}
|
||||
if (test_bit(XPRT_SOCK_DATA_READY, &transport->sock_state))
|
||||
queue_work(xprtiod_workqueue, &transport->recv_worker);
|
||||
out:
|
||||
mutex_unlock(&transport->recv_mutex);
|
||||
trace_xs_tcp_data_ready(xprt, read, total);
|
||||
|
|
@ -2724,7 +2728,7 @@ static void bc_destroy(struct rpc_xprt *xprt)
|
|||
module_put(THIS_MODULE);
|
||||
}
|
||||
|
||||
static struct rpc_xprt_ops xs_local_ops = {
|
||||
static const struct rpc_xprt_ops xs_local_ops = {
|
||||
.reserve_xprt = xprt_reserve_xprt,
|
||||
.release_xprt = xs_tcp_release_xprt,
|
||||
.alloc_slot = xprt_alloc_slot,
|
||||
|
|
@ -2742,7 +2746,7 @@ static struct rpc_xprt_ops xs_local_ops = {
|
|||
.disable_swap = xs_disable_swap,
|
||||
};
|
||||
|
||||
static struct rpc_xprt_ops xs_udp_ops = {
|
||||
static const struct rpc_xprt_ops xs_udp_ops = {
|
||||
.set_buffer_size = xs_udp_set_buffer_size,
|
||||
.reserve_xprt = xprt_reserve_xprt_cong,
|
||||
.release_xprt = xprt_release_xprt_cong,
|
||||
|
|
@ -2764,7 +2768,7 @@ static struct rpc_xprt_ops xs_udp_ops = {
|
|||
.inject_disconnect = xs_inject_disconnect,
|
||||
};
|
||||
|
||||
static struct rpc_xprt_ops xs_tcp_ops = {
|
||||
static const struct rpc_xprt_ops xs_tcp_ops = {
|
||||
.reserve_xprt = xprt_reserve_xprt,
|
||||
.release_xprt = xs_tcp_release_xprt,
|
||||
.alloc_slot = xprt_lock_and_alloc_slot,
|
||||
|
|
@ -2795,7 +2799,7 @@ static struct rpc_xprt_ops xs_tcp_ops = {
|
|||
* The rpc_xprt_ops for the server backchannel
|
||||
*/
|
||||
|
||||
static struct rpc_xprt_ops bc_tcp_ops = {
|
||||
static const struct rpc_xprt_ops bc_tcp_ops = {
|
||||
.reserve_xprt = xprt_reserve_xprt,
|
||||
.release_xprt = xprt_release_xprt,
|
||||
.alloc_slot = xprt_alloc_slot,
|
||||
|
|
|
|||
Loading…
Reference in a new issue