aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorSimon Derr <simon.derr@bull.net>2013-06-21 09:32:42 -0400
committerEric Van Hensbergen <ericvh@gmail.com>2013-07-07 23:04:36 -0400
commit1cff33069a4a1ac9ed080756113ecd17ad408282 (patch)
treebc7c5e50fb6ad102b16b93da9263fc36506d5d32 /net
parent2f52d07cb75d96fcbb5b9ab72938590fa9ffb19d (diff)
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: Simon Derr <simon.derr@bull.net> Signed-off-by: Eric Van Hensbergen <ericvh@gmail.com>
Diffstat (limited to 'net')
-rw-r--r--net/9p/client.c6
-rw-r--r--net/9p/trans_rdma.c31
2 files changed, 34 insertions, 3 deletions
diff --git a/net/9p/client.c b/net/9p/client.c
index db5bf2480a33..d18a0b22f62c 100644
--- a/net/9p/client.c
+++ b/net/9p/client.c
@@ -656,8 +656,10 @@ static int p9_client_flush(struct p9_client *c, struct p9_req_t *oldreq)
656 return PTR_ERR(req); 656 return PTR_ERR(req);
657 657
658 658
659 /* if we haven't received a response for oldreq, 659 /*
660 remove it from the list. */ 660 * if we haven't received a response for oldreq,
661 * remove it from the list.
662 */
661 spin_lock(&c->lock); 663 spin_lock(&c->lock);
662 if (oldreq->status == REQ_STATUS_FLSH) 664 if (oldreq->status == REQ_STATUS_FLSH)
663 list_del(&oldreq->req_list); 665 list_del(&oldreq->req_list);
diff --git a/net/9p/trans_rdma.c b/net/9p/trans_rdma.c
index 926e72d00e57..8f68df5d2973 100644
--- a/net/9p/trans_rdma.c
+++ b/net/9p/trans_rdma.c
@@ -74,6 +74,8 @@
74 * @sq_sem: Semaphore for the SQ 74 * @sq_sem: Semaphore for the SQ
75 * @rq_depth: The depth of the Receive Queue. 75 * @rq_depth: The depth of the Receive Queue.
76 * @rq_sem: Semaphore for the RQ 76 * @rq_sem: Semaphore for the RQ
77 * @excess_rc : Amount of posted Receive Contexts without a pending request.
78 * See rdma_request()
77 * @addr: The remote peer's address 79 * @addr: The remote peer's address
78 * @req_lock: Protects the active request list 80 * @req_lock: Protects the active request list
79 * @cm_done: Completion event for connection management tracking 81 * @cm_done: Completion event for connection management tracking
@@ -99,6 +101,7 @@ struct p9_trans_rdma {
99 struct semaphore sq_sem; 101 struct semaphore sq_sem;
100 int rq_depth; 102 int rq_depth;
101 struct semaphore rq_sem; 103 struct semaphore rq_sem;
104 atomic_t excess_rc;
102 struct sockaddr_in addr; 105 struct sockaddr_in addr;
103 spinlock_t req_lock; 106 spinlock_t req_lock;
104 107
@@ -426,6 +429,26 @@ static int rdma_request(struct p9_client *client, struct p9_req_t *req)
426 struct p9_rdma_context *c = NULL; 429 struct p9_rdma_context *c = NULL;
427 struct p9_rdma_context *rpl_context = NULL; 430 struct p9_rdma_context *rpl_context = NULL;
428 431
432 /* When an error occurs between posting the recv and the send,
433 * there will be a receive context posted without a pending request.
434 * Since there is no way to "un-post" it, we remember it and skip
435 * post_recv() for the next request.
436 * So here,
437 * see if we are this `next request' and need to absorb an excess rc.
438 * If yes, then drop and free our own, and do not recv_post().
439 **/
440 if (unlikely(atomic_read(&rdma->excess_rc) > 0)) {
441 if ((atomic_sub_return(1, &rdma->excess_rc) >= 0)) {
442 /* Got one ! */
443 kfree(req->rc);
444 req->rc = NULL;
445 goto dont_need_post_recv;
446 } else {
447 /* We raced and lost. */
448 atomic_inc(&rdma->excess_rc);
449 }
450 }
451
429 /* Allocate an fcall for the reply */ 452 /* Allocate an fcall for the reply */
430 rpl_context = kmalloc(sizeof *rpl_context, GFP_NOFS); 453 rpl_context = kmalloc(sizeof *rpl_context, GFP_NOFS);
431 if (!rpl_context) { 454 if (!rpl_context) {
@@ -451,10 +474,10 @@ static int rdma_request(struct p9_client *client, struct p9_req_t *req)
451 p9_debug(P9_DEBUG_FCALL, "POST RECV failed\n"); 474 p9_debug(P9_DEBUG_FCALL, "POST RECV failed\n");
452 goto recv_error; 475 goto recv_error;
453 } 476 }
454
455 /* remove posted receive buffer from request structure */ 477 /* remove posted receive buffer from request structure */
456 req->rc = NULL; 478 req->rc = NULL;
457 479
480dont_need_post_recv:
458 /* Post the request */ 481 /* Post the request */
459 c = kmalloc(sizeof *c, GFP_NOFS); 482 c = kmalloc(sizeof *c, GFP_NOFS);
460 if (!c) { 483 if (!c) {
@@ -499,6 +522,11 @@ static int rdma_request(struct p9_client *client, struct p9_req_t *req)
499 send_error: 522 send_error:
500 kfree(c); 523 kfree(c);
501 p9_debug(P9_DEBUG_ERROR, "Error %d in rdma_request()\n", err); 524 p9_debug(P9_DEBUG_ERROR, "Error %d in rdma_request()\n", err);
525
526 /* Ach.
527 * We did recv_post(), but not send. We have one recv_post in excess.
528 */
529 atomic_inc(&rdma->excess_rc);
502 return err; 530 return err;
503 531
504 /* Handle errors that happened during or while preparing post_recv(): */ 532 /* 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 init_completion(&rdma->cm_done); 577 init_completion(&rdma->cm_done);
550 sema_init(&rdma->sq_sem, rdma->sq_depth); 578 sema_init(&rdma->sq_sem, rdma->sq_depth);
551 sema_init(&rdma->rq_sem, rdma->rq_depth); 579 sema_init(&rdma->rq_sem, rdma->rq_depth);
580 atomic_set(&rdma->excess_rc, 0);
552 581
553 return rdma; 582 return rdma;
554} 583}