diff options
author | Simon Derr <simon.derr@bull.net> | 2013-06-21 09:32:42 -0400 |
---|---|---|
committer | Eric Van Hensbergen <ericvh@gmail.com> | 2013-07-07 23:04:36 -0400 |
commit | 1cff33069a4a1ac9ed080756113ecd17ad408282 (patch) | |
tree | bc7c5e50fb6ad102b16b93da9263fc36506d5d32 /net | |
parent | 2f52d07cb75d96fcbb5b9ab72938590fa9ffb19d (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.c | 6 | ||||
-rw-r--r-- | net/9p/trans_rdma.c | 31 |
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 | ||
480 | dont_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 | } |