Commit 1cff3306 authored by Simon Derr's avatar Simon Derr Committed by Eric Van Hensbergen

9P/RDMA: count posted buffers without a pending request

In rdma_request():

If an error occurs between posting the recv and the send,
there will be a reply context posted without a pending
request.
Since there is no way to "un-post" it, we remember it and
skip post_recv() for the next request.
Signed-off-by: default avatarSimon Derr <simon.derr@bull.net>
Signed-off-by: default avatarEric Van Hensbergen <ericvh@gmail.com>
parent 2f52d07c
...@@ -656,8 +656,10 @@ static int p9_client_flush(struct p9_client *c, struct p9_req_t *oldreq) ...@@ -656,8 +656,10 @@ static int p9_client_flush(struct p9_client *c, struct p9_req_t *oldreq)
return PTR_ERR(req); return PTR_ERR(req);
/* if we haven't received a response for oldreq, /*
remove it from the list. */ * if we haven't received a response for oldreq,
* remove it from the list.
*/
spin_lock(&c->lock); spin_lock(&c->lock);
if (oldreq->status == REQ_STATUS_FLSH) if (oldreq->status == REQ_STATUS_FLSH)
list_del(&oldreq->req_list); list_del(&oldreq->req_list);
......
...@@ -74,6 +74,8 @@ ...@@ -74,6 +74,8 @@
* @sq_sem: Semaphore for the SQ * @sq_sem: Semaphore for the SQ
* @rq_depth: The depth of the Receive Queue. * @rq_depth: The depth of the Receive Queue.
* @rq_sem: Semaphore for the RQ * @rq_sem: Semaphore for the RQ
* @excess_rc : Amount of posted Receive Contexts without a pending request.
* See rdma_request()
* @addr: The remote peer's address * @addr: The remote peer's address
* @req_lock: Protects the active request list * @req_lock: Protects the active request list
* @cm_done: Completion event for connection management tracking * @cm_done: Completion event for connection management tracking
...@@ -99,6 +101,7 @@ struct p9_trans_rdma { ...@@ -99,6 +101,7 @@ struct p9_trans_rdma {
struct semaphore sq_sem; struct semaphore sq_sem;
int rq_depth; int rq_depth;
struct semaphore rq_sem; struct semaphore rq_sem;
atomic_t excess_rc;
struct sockaddr_in addr; struct sockaddr_in addr;
spinlock_t req_lock; spinlock_t req_lock;
...@@ -426,6 +429,26 @@ static int rdma_request(struct p9_client *client, struct p9_req_t *req) ...@@ -426,6 +429,26 @@ static int rdma_request(struct p9_client *client, struct p9_req_t *req)
struct p9_rdma_context *c = NULL; struct p9_rdma_context *c = NULL;
struct p9_rdma_context *rpl_context = NULL; struct p9_rdma_context *rpl_context = NULL;
/* When an error occurs between posting the recv and the send,
* there will be a receive context posted without a pending request.
* Since there is no way to "un-post" it, we remember it and skip
* post_recv() for the next request.
* So here,
* see if we are this `next request' and need to absorb an excess rc.
* If yes, then drop and free our own, and do not recv_post().
**/
if (unlikely(atomic_read(&rdma->excess_rc) > 0)) {
if ((atomic_sub_return(1, &rdma->excess_rc) >= 0)) {
/* Got one ! */
kfree(req->rc);
req->rc = NULL;
goto dont_need_post_recv;
} else {
/* We raced and lost. */
atomic_inc(&rdma->excess_rc);
}
}
/* Allocate an fcall for the reply */ /* Allocate an fcall for the reply */
rpl_context = kmalloc(sizeof *rpl_context, GFP_NOFS); rpl_context = kmalloc(sizeof *rpl_context, GFP_NOFS);
if (!rpl_context) { if (!rpl_context) {
...@@ -451,10 +474,10 @@ static int rdma_request(struct p9_client *client, struct p9_req_t *req) ...@@ -451,10 +474,10 @@ static int rdma_request(struct p9_client *client, struct p9_req_t *req)
p9_debug(P9_DEBUG_FCALL, "POST RECV failed\n"); p9_debug(P9_DEBUG_FCALL, "POST RECV failed\n");
goto recv_error; goto recv_error;
} }
/* remove posted receive buffer from request structure */ /* remove posted receive buffer from request structure */
req->rc = NULL; req->rc = NULL;
dont_need_post_recv:
/* Post the request */ /* Post the request */
c = kmalloc(sizeof *c, GFP_NOFS); c = kmalloc(sizeof *c, GFP_NOFS);
if (!c) { if (!c) {
...@@ -499,6 +522,11 @@ static int rdma_request(struct p9_client *client, struct p9_req_t *req) ...@@ -499,6 +522,11 @@ static int rdma_request(struct p9_client *client, struct p9_req_t *req)
send_error: send_error:
kfree(c); kfree(c);
p9_debug(P9_DEBUG_ERROR, "Error %d in rdma_request()\n", err); p9_debug(P9_DEBUG_ERROR, "Error %d in rdma_request()\n", err);
/* Ach.
* We did recv_post(), but not send. We have one recv_post in excess.
*/
atomic_inc(&rdma->excess_rc);
return err; return err;
/* Handle errors that happened during or while preparing post_recv(): */ /* Handle errors that happened during or while preparing post_recv(): */
...@@ -549,6 +577,7 @@ static struct p9_trans_rdma *alloc_rdma(struct p9_rdma_opts *opts) ...@@ -549,6 +577,7 @@ static struct p9_trans_rdma *alloc_rdma(struct p9_rdma_opts *opts)
init_completion(&rdma->cm_done); init_completion(&rdma->cm_done);
sema_init(&rdma->sq_sem, rdma->sq_depth); sema_init(&rdma->sq_sem, rdma->sq_depth);
sema_init(&rdma->rq_sem, rdma->rq_depth); sema_init(&rdma->rq_sem, rdma->rq_depth);
atomic_set(&rdma->excess_rc, 0);
return rdma; return rdma;
} }
......
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