summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSimon Derr <simon.derr@bull.net>2013-06-21 15:32:41 +0200
committerEric Van Hensbergen <ericvh@gmail.com>2013-07-07 22:02:29 -0500
commit2f52d07cb75d96fcbb5b9ab72938590fa9ffb19d (patch)
treeec7258ce3685ab86bbea93f8b5dd666fcc6da98b
parentb530e252e291c27fdcb1b73c72ad17f75c8bdba6 (diff)
downloadlinux-2f52d07cb75d96fcbb5b9ab72938590fa9ffb19d.tar.gz
linux-2f52d07cb75d96fcbb5b9ab72938590fa9ffb19d.tar.bz2
linux-2f52d07cb75d96fcbb5b9ab72938590fa9ffb19d.zip
9P/RDMA: Improve error handling in rdma_request
Most importantly: - do not free the recv context (rpl_context) after a successful post_recv() - but do free the send context (c) after a failed send. Signed-off-by: Simon Derr <simon.derr@bull.net> Signed-off-by: Eric Van Hensbergen <ericvh@gmail.com>
-rw-r--r--net/9p/trans_rdma.c44
1 files changed, 28 insertions, 16 deletions
diff --git a/net/9p/trans_rdma.c b/net/9p/trans_rdma.c
index 1bd4c7150114..926e72d00e57 100644
--- a/net/9p/trans_rdma.c
+++ b/net/9p/trans_rdma.c
@@ -430,7 +430,7 @@ static int rdma_request(struct p9_client *client, struct p9_req_t *req)
rpl_context = kmalloc(sizeof *rpl_context, GFP_NOFS);
if (!rpl_context) {
err = -ENOMEM;
- goto err_close;
+ goto recv_error;
}
rpl_context->rc = req->rc;
@@ -441,13 +441,15 @@ static int rdma_request(struct p9_client *client, struct p9_req_t *req)
* outstanding request, so we must keep a count to avoid
* overflowing the RQ.
*/
- if (down_interruptible(&rdma->rq_sem))
- goto error; /* FIXME : -EINTR instead */
+ if (down_interruptible(&rdma->rq_sem)) {
+ err = -EINTR;
+ goto recv_error;
+ }
err = post_recv(client, rpl_context);
if (err) {
p9_debug(P9_DEBUG_FCALL, "POST RECV failed\n");
- goto err_free;
+ goto recv_error;
}
/* remove posted receive buffer from request structure */
@@ -457,15 +459,17 @@ static int rdma_request(struct p9_client *client, struct p9_req_t *req)
c = kmalloc(sizeof *c, GFP_NOFS);
if (!c) {
err = -ENOMEM;
- goto err_free;
+ goto send_error;
}
c->req = req;
c->busa = ib_dma_map_single(rdma->cm_id->device,
c->req->tc->sdata, c->req->tc->size,
DMA_TO_DEVICE);
- if (ib_dma_mapping_error(rdma->cm_id->device, c->busa))
- goto error;
+ if (ib_dma_mapping_error(rdma->cm_id->device, c->busa)) {
+ err = -EIO;
+ goto send_error;
+ }
sge.addr = c->busa;
sge.length = c->req->tc->size;
@@ -479,19 +483,27 @@ static int rdma_request(struct p9_client *client, struct p9_req_t *req)
wr.sg_list = &sge;
wr.num_sge = 1;
- if (down_interruptible(&rdma->sq_sem))
- goto error;
+ if (down_interruptible(&rdma->sq_sem)) {
+ err = -EINTR;
+ goto send_error;
+ }
- return ib_post_send(rdma->qp, &wr, &bad_wr);
+ err = ib_post_send(rdma->qp, &wr, &bad_wr);
+ if (err)
+ goto send_error;
- error:
+ /* Success */
+ return 0;
+
+ /* Handle errors that happened during or while preparing the send: */
+ send_error:
kfree(c);
+ p9_debug(P9_DEBUG_ERROR, "Error %d in rdma_request()\n", err);
+ return err;
+
+ /* Handle errors that happened during or while preparing post_recv(): */
+ recv_error:
kfree(rpl_context);
- p9_debug(P9_DEBUG_ERROR, "EIO\n");
- return -EIO;
- err_free:
- kfree(rpl_context);
- err_close:
spin_lock_irqsave(&rdma->req_lock, flags);
if (rdma->state < P9_RDMA_CLOSING) {
rdma->state = P9_RDMA_CLOSING;