]> asedeno.scripts.mit.edu Git - linux.git/blobdiff - net/sunrpc/xprtrdma/verbs.c
xprtrdma: Fix MR list handling
[linux.git] / net / sunrpc / xprtrdma / verbs.c
index 3a1a31c3d7919de56624c824f8573302395ddd64..82361e7bbb51ca4512e07ec606be0ffef6179c2c 100644 (file)
@@ -79,7 +79,6 @@ static void rpcrdma_reqs_reset(struct rpcrdma_xprt *r_xprt);
 static void rpcrdma_reps_destroy(struct rpcrdma_buffer *buf);
 static void rpcrdma_mrs_create(struct rpcrdma_xprt *r_xprt);
 static void rpcrdma_mrs_destroy(struct rpcrdma_buffer *buf);
-static void rpcrdma_mr_free(struct rpcrdma_mr *mr);
 static struct rpcrdma_regbuf *
 rpcrdma_regbuf_alloc(size_t size, enum dma_data_direction direction,
                     gfp_t flags);
@@ -966,7 +965,7 @@ rpcrdma_mrs_create(struct rpcrdma_xprt *r_xprt)
                mr->mr_xprt = r_xprt;
 
                spin_lock(&buf->rb_lock);
-               list_add(&mr->mr_list, &buf->rb_mrs);
+               rpcrdma_mr_push(mr, &buf->rb_mrs);
                list_add(&mr->mr_all, &buf->rb_all_mrs);
                spin_unlock(&buf->rb_lock);
        }
@@ -1183,10 +1182,19 @@ int rpcrdma_buffer_create(struct rpcrdma_xprt *r_xprt)
  */
 void rpcrdma_req_destroy(struct rpcrdma_req *req)
 {
+       struct rpcrdma_mr *mr;
+
        list_del(&req->rl_all);
 
-       while (!list_empty(&req->rl_free_mrs))
-               rpcrdma_mr_free(rpcrdma_mr_pop(&req->rl_free_mrs));
+       while ((mr = rpcrdma_mr_pop(&req->rl_free_mrs))) {
+               struct rpcrdma_buffer *buf = &mr->mr_xprt->rx_buf;
+
+               spin_lock(&buf->rb_lock);
+               list_del(&mr->mr_all);
+               spin_unlock(&buf->rb_lock);
+
+               frwr_release_mr(mr);
+       }
 
        rpcrdma_regbuf_free(req->rl_recvbuf);
        rpcrdma_regbuf_free(req->rl_sendbuf);
@@ -1194,24 +1202,28 @@ void rpcrdma_req_destroy(struct rpcrdma_req *req)
        kfree(req);
 }
 
-static void
-rpcrdma_mrs_destroy(struct rpcrdma_buffer *buf)
+/**
+ * rpcrdma_mrs_destroy - Release all of a transport's MRs
+ * @buf: controlling buffer instance
+ *
+ * Relies on caller holding the transport send lock to protect
+ * removing mr->mr_list from req->rl_free_mrs safely.
+ */
+static void rpcrdma_mrs_destroy(struct rpcrdma_buffer *buf)
 {
        struct rpcrdma_xprt *r_xprt = container_of(buf, struct rpcrdma_xprt,
                                                   rx_buf);
        struct rpcrdma_mr *mr;
-       unsigned int count;
 
-       count = 0;
        spin_lock(&buf->rb_lock);
        while ((mr = list_first_entry_or_null(&buf->rb_all_mrs,
                                              struct rpcrdma_mr,
                                              mr_all)) != NULL) {
+               list_del(&mr->mr_list);
                list_del(&mr->mr_all);
                spin_unlock(&buf->rb_lock);
 
                frwr_release_mr(mr);
-               count++;
                spin_lock(&buf->rb_lock);
        }
        spin_unlock(&buf->rb_lock);
@@ -1284,17 +1296,6 @@ void rpcrdma_mr_put(struct rpcrdma_mr *mr)
        rpcrdma_mr_push(mr, &mr->mr_req->rl_free_mrs);
 }
 
-static void rpcrdma_mr_free(struct rpcrdma_mr *mr)
-{
-       struct rpcrdma_xprt *r_xprt = mr->mr_xprt;
-       struct rpcrdma_buffer *buf = &r_xprt->rx_buf;
-
-       mr->mr_req = NULL;
-       spin_lock(&buf->rb_lock);
-       rpcrdma_mr_push(mr, &buf->rb_mrs);
-       spin_unlock(&buf->rb_lock);
-}
-
 /**
  * rpcrdma_buffer_get - Get a request buffer
  * @buffers: Buffer pool from which to obtain a buffer