diff options
author | Chuck Lever <chuck.lever@oracle.com> | 2015-03-30 14:34:48 -0400 |
---|---|---|
committer | Anna Schumaker <Anna.Schumaker@Netapp.com> | 2015-03-31 09:52:52 -0400 |
commit | 6814baead86b5d44096ddfbb6f944163578e68c3 (patch) | |
tree | 56dbce03517cd92027741bcdf6ca24fb929700c0 | |
parent | 9c1b4d775f2d7dd5bb806e3de2f3e1244a7cbd16 (diff) |
xprtrdma: Add a "deregister_external" op for each memreg mode
There is very little common processing among the different external
memory deregistration functions.
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
Tested-by: Devesh Sharma <Devesh.Sharma@Emulex.Com>
Tested-by: Meghana Cheripady <Meghana.Cheripady@Emulex.Com>
Tested-by: Veeresh U. Kokatnur <veereshuk@chelsio.com>
Signed-off-by: Anna Schumaker <Anna.Schumaker@Netapp.com>
-rw-r--r-- | net/sunrpc/xprtrdma/fmr_ops.c | 27 | ||||
-rw-r--r-- | net/sunrpc/xprtrdma/frwr_ops.c | 36 | ||||
-rw-r--r-- | net/sunrpc/xprtrdma/physical_ops.c | 10 | ||||
-rw-r--r-- | net/sunrpc/xprtrdma/rpc_rdma.c | 11 | ||||
-rw-r--r-- | net/sunrpc/xprtrdma/transport.c | 4 | ||||
-rw-r--r-- | net/sunrpc/xprtrdma/verbs.c | 81 | ||||
-rw-r--r-- | net/sunrpc/xprtrdma/xprt_rdma.h | 5 |
7 files changed, 84 insertions, 90 deletions
diff --git a/net/sunrpc/xprtrdma/fmr_ops.c b/net/sunrpc/xprtrdma/fmr_ops.c index 45fb646a6d36..888aa107cf0b 100644 --- a/net/sunrpc/xprtrdma/fmr_ops.c +++ b/net/sunrpc/xprtrdma/fmr_ops.c | |||
@@ -79,8 +79,35 @@ out_maperr: | |||
79 | return rc; | 79 | return rc; |
80 | } | 80 | } |
81 | 81 | ||
82 | /* Use the ib_unmap_fmr() verb to prevent further remote | ||
83 | * access via RDMA READ or RDMA WRITE. | ||
84 | */ | ||
85 | static int | ||
86 | fmr_op_unmap(struct rpcrdma_xprt *r_xprt, struct rpcrdma_mr_seg *seg) | ||
87 | { | ||
88 | struct rpcrdma_ia *ia = &r_xprt->rx_ia; | ||
89 | struct rpcrdma_mr_seg *seg1 = seg; | ||
90 | int rc, nsegs = seg->mr_nsegs; | ||
91 | LIST_HEAD(l); | ||
92 | |||
93 | list_add(&seg1->rl_mw->r.fmr->list, &l); | ||
94 | rc = ib_unmap_fmr(&l); | ||
95 | read_lock(&ia->ri_qplock); | ||
96 | while (seg1->mr_nsegs--) | ||
97 | rpcrdma_unmap_one(ia, seg++); | ||
98 | read_unlock(&ia->ri_qplock); | ||
99 | if (rc) | ||
100 | goto out_err; | ||
101 | return nsegs; | ||
102 | |||
103 | out_err: | ||
104 | dprintk("RPC: %s: ib_unmap_fmr status %i\n", __func__, rc); | ||
105 | return nsegs; | ||
106 | } | ||
107 | |||
82 | const struct rpcrdma_memreg_ops rpcrdma_fmr_memreg_ops = { | 108 | const struct rpcrdma_memreg_ops rpcrdma_fmr_memreg_ops = { |
83 | .ro_map = fmr_op_map, | 109 | .ro_map = fmr_op_map, |
110 | .ro_unmap = fmr_op_unmap, | ||
84 | .ro_maxpages = fmr_op_maxpages, | 111 | .ro_maxpages = fmr_op_maxpages, |
85 | .ro_displayname = "fmr", | 112 | .ro_displayname = "fmr", |
86 | }; | 113 | }; |
diff --git a/net/sunrpc/xprtrdma/frwr_ops.c b/net/sunrpc/xprtrdma/frwr_ops.c index 23e4d99a2097..35b725bf0afb 100644 --- a/net/sunrpc/xprtrdma/frwr_ops.c +++ b/net/sunrpc/xprtrdma/frwr_ops.c | |||
@@ -110,8 +110,44 @@ out_senderr: | |||
110 | return rc; | 110 | return rc; |
111 | } | 111 | } |
112 | 112 | ||
113 | /* Post a LOCAL_INV Work Request to prevent further remote access | ||
114 | * via RDMA READ or RDMA WRITE. | ||
115 | */ | ||
116 | static int | ||
117 | frwr_op_unmap(struct rpcrdma_xprt *r_xprt, struct rpcrdma_mr_seg *seg) | ||
118 | { | ||
119 | struct rpcrdma_mr_seg *seg1 = seg; | ||
120 | struct rpcrdma_ia *ia = &r_xprt->rx_ia; | ||
121 | struct ib_send_wr invalidate_wr, *bad_wr; | ||
122 | int rc, nsegs = seg->mr_nsegs; | ||
123 | |||
124 | seg1->rl_mw->r.frmr.fr_state = FRMR_IS_INVALID; | ||
125 | |||
126 | memset(&invalidate_wr, 0, sizeof(invalidate_wr)); | ||
127 | invalidate_wr.wr_id = (unsigned long)(void *)seg1->rl_mw; | ||
128 | invalidate_wr.opcode = IB_WR_LOCAL_INV; | ||
129 | invalidate_wr.ex.invalidate_rkey = seg1->rl_mw->r.frmr.fr_mr->rkey; | ||
130 | DECR_CQCOUNT(&r_xprt->rx_ep); | ||
131 | |||
132 | read_lock(&ia->ri_qplock); | ||
133 | while (seg1->mr_nsegs--) | ||
134 | rpcrdma_unmap_one(ia, seg++); | ||
135 | rc = ib_post_send(ia->ri_id->qp, &invalidate_wr, &bad_wr); | ||
136 | read_unlock(&ia->ri_qplock); | ||
137 | if (rc) | ||
138 | goto out_err; | ||
139 | return nsegs; | ||
140 | |||
141 | out_err: | ||
142 | /* Force rpcrdma_buffer_get() to retry */ | ||
143 | seg1->rl_mw->r.frmr.fr_state = FRMR_IS_STALE; | ||
144 | dprintk("RPC: %s: ib_post_send status %i\n", __func__, rc); | ||
145 | return nsegs; | ||
146 | } | ||
147 | |||
113 | const struct rpcrdma_memreg_ops rpcrdma_frwr_memreg_ops = { | 148 | const struct rpcrdma_memreg_ops rpcrdma_frwr_memreg_ops = { |
114 | .ro_map = frwr_op_map, | 149 | .ro_map = frwr_op_map, |
150 | .ro_unmap = frwr_op_unmap, | ||
115 | .ro_maxpages = frwr_op_maxpages, | 151 | .ro_maxpages = frwr_op_maxpages, |
116 | .ro_displayname = "frwr", | 152 | .ro_displayname = "frwr", |
117 | }; | 153 | }; |
diff --git a/net/sunrpc/xprtrdma/physical_ops.c b/net/sunrpc/xprtrdma/physical_ops.c index 5a284ee0e058..5b5a63adfdf3 100644 --- a/net/sunrpc/xprtrdma/physical_ops.c +++ b/net/sunrpc/xprtrdma/physical_ops.c | |||
@@ -44,8 +44,18 @@ physical_op_map(struct rpcrdma_xprt *r_xprt, struct rpcrdma_mr_seg *seg, | |||
44 | return 1; | 44 | return 1; |
45 | } | 45 | } |
46 | 46 | ||
47 | /* Unmap a memory region, but leave it registered. | ||
48 | */ | ||
49 | static int | ||
50 | physical_op_unmap(struct rpcrdma_xprt *r_xprt, struct rpcrdma_mr_seg *seg) | ||
51 | { | ||
52 | rpcrdma_unmap_one(&r_xprt->rx_ia, seg); | ||
53 | return 1; | ||
54 | } | ||
55 | |||
47 | const struct rpcrdma_memreg_ops rpcrdma_physical_memreg_ops = { | 56 | const struct rpcrdma_memreg_ops rpcrdma_physical_memreg_ops = { |
48 | .ro_map = physical_op_map, | 57 | .ro_map = physical_op_map, |
58 | .ro_unmap = physical_op_unmap, | ||
49 | .ro_maxpages = physical_op_maxpages, | 59 | .ro_maxpages = physical_op_maxpages, |
50 | .ro_displayname = "physical", | 60 | .ro_displayname = "physical", |
51 | }; | 61 | }; |
diff --git a/net/sunrpc/xprtrdma/rpc_rdma.c b/net/sunrpc/xprtrdma/rpc_rdma.c index 6ab1d03d7f3e..2c53ea9e1b83 100644 --- a/net/sunrpc/xprtrdma/rpc_rdma.c +++ b/net/sunrpc/xprtrdma/rpc_rdma.c | |||
@@ -284,11 +284,12 @@ rpcrdma_create_chunks(struct rpc_rqst *rqst, struct xdr_buf *target, | |||
284 | return (unsigned char *)iptr - (unsigned char *)headerp; | 284 | return (unsigned char *)iptr - (unsigned char *)headerp; |
285 | 285 | ||
286 | out: | 286 | out: |
287 | if (r_xprt->rx_ia.ri_memreg_strategy != RPCRDMA_FRMR) { | 287 | if (r_xprt->rx_ia.ri_memreg_strategy == RPCRDMA_FRMR) |
288 | for (pos = 0; nchunks--;) | 288 | return n; |
289 | pos += rpcrdma_deregister_external( | 289 | |
290 | &req->rl_segments[pos], r_xprt); | 290 | for (pos = 0; nchunks--;) |
291 | } | 291 | pos += r_xprt->rx_ia.ri_ops->ro_unmap(r_xprt, |
292 | &req->rl_segments[pos]); | ||
292 | return n; | 293 | return n; |
293 | } | 294 | } |
294 | 295 | ||
diff --git a/net/sunrpc/xprtrdma/transport.c b/net/sunrpc/xprtrdma/transport.c index da71a24641e3..54f23b1be986 100644 --- a/net/sunrpc/xprtrdma/transport.c +++ b/net/sunrpc/xprtrdma/transport.c | |||
@@ -584,8 +584,8 @@ xprt_rdma_free(void *buffer) | |||
584 | 584 | ||
585 | for (i = 0; req->rl_nchunks;) { | 585 | for (i = 0; req->rl_nchunks;) { |
586 | --req->rl_nchunks; | 586 | --req->rl_nchunks; |
587 | i += rpcrdma_deregister_external( | 587 | i += r_xprt->rx_ia.ri_ops->ro_unmap(r_xprt, |
588 | &req->rl_segments[i], r_xprt); | 588 | &req->rl_segments[i]); |
589 | } | 589 | } |
590 | 590 | ||
591 | rpcrdma_buffer_put(req); | 591 | rpcrdma_buffer_put(req); |
diff --git a/net/sunrpc/xprtrdma/verbs.c b/net/sunrpc/xprtrdma/verbs.c index 4318c04e095c..b167c99fbfb6 100644 --- a/net/sunrpc/xprtrdma/verbs.c +++ b/net/sunrpc/xprtrdma/verbs.c | |||
@@ -1510,7 +1510,7 @@ rpcrdma_buffer_put_sendbuf(struct rpcrdma_req *req, struct rpcrdma_buffer *buf) | |||
1510 | } | 1510 | } |
1511 | } | 1511 | } |
1512 | 1512 | ||
1513 | /* rpcrdma_unmap_one() was already done by rpcrdma_deregister_frmr_external(). | 1513 | /* rpcrdma_unmap_one() was already done during deregistration. |
1514 | * Redo only the ib_post_send(). | 1514 | * Redo only the ib_post_send(). |
1515 | */ | 1515 | */ |
1516 | static void | 1516 | static void |
@@ -1890,85 +1890,6 @@ rpcrdma_unmap_one(struct rpcrdma_ia *ia, struct rpcrdma_mr_seg *seg) | |||
1890 | seg->mr_dma, seg->mr_dmalen, seg->mr_dir); | 1890 | seg->mr_dma, seg->mr_dmalen, seg->mr_dir); |
1891 | } | 1891 | } |
1892 | 1892 | ||
1893 | static int | ||
1894 | rpcrdma_deregister_frmr_external(struct rpcrdma_mr_seg *seg, | ||
1895 | struct rpcrdma_ia *ia, struct rpcrdma_xprt *r_xprt) | ||
1896 | { | ||
1897 | struct rpcrdma_mr_seg *seg1 = seg; | ||
1898 | struct ib_send_wr invalidate_wr, *bad_wr; | ||
1899 | int rc; | ||
1900 | |||
1901 | seg1->rl_mw->r.frmr.fr_state = FRMR_IS_INVALID; | ||
1902 | |||
1903 | memset(&invalidate_wr, 0, sizeof invalidate_wr); | ||
1904 | invalidate_wr.wr_id = (unsigned long)(void *)seg1->rl_mw; | ||
1905 | invalidate_wr.opcode = IB_WR_LOCAL_INV; | ||
1906 | invalidate_wr.ex.invalidate_rkey = seg1->rl_mw->r.frmr.fr_mr->rkey; | ||
1907 | DECR_CQCOUNT(&r_xprt->rx_ep); | ||
1908 | |||
1909 | read_lock(&ia->ri_qplock); | ||
1910 | while (seg1->mr_nsegs--) | ||
1911 | rpcrdma_unmap_one(ia, seg++); | ||
1912 | rc = ib_post_send(ia->ri_id->qp, &invalidate_wr, &bad_wr); | ||
1913 | read_unlock(&ia->ri_qplock); | ||
1914 | if (rc) { | ||
1915 | /* Force rpcrdma_buffer_get() to retry */ | ||
1916 | seg1->rl_mw->r.frmr.fr_state = FRMR_IS_STALE; | ||
1917 | dprintk("RPC: %s: failed ib_post_send for invalidate," | ||
1918 | " status %i\n", __func__, rc); | ||
1919 | } | ||
1920 | return rc; | ||
1921 | } | ||
1922 | |||
1923 | static int | ||
1924 | rpcrdma_deregister_fmr_external(struct rpcrdma_mr_seg *seg, | ||
1925 | struct rpcrdma_ia *ia) | ||
1926 | { | ||
1927 | struct rpcrdma_mr_seg *seg1 = seg; | ||
1928 | LIST_HEAD(l); | ||
1929 | int rc; | ||
1930 | |||
1931 | list_add(&seg1->rl_mw->r.fmr->list, &l); | ||
1932 | rc = ib_unmap_fmr(&l); | ||
1933 | read_lock(&ia->ri_qplock); | ||
1934 | while (seg1->mr_nsegs--) | ||
1935 | rpcrdma_unmap_one(ia, seg++); | ||
1936 | read_unlock(&ia->ri_qplock); | ||
1937 | if (rc) | ||
1938 | dprintk("RPC: %s: failed ib_unmap_fmr," | ||
1939 | " status %i\n", __func__, rc); | ||
1940 | return rc; | ||
1941 | } | ||
1942 | |||
1943 | int | ||
1944 | rpcrdma_deregister_external(struct rpcrdma_mr_seg *seg, | ||
1945 | struct rpcrdma_xprt *r_xprt) | ||
1946 | { | ||
1947 | struct rpcrdma_ia *ia = &r_xprt->rx_ia; | ||
1948 | int nsegs = seg->mr_nsegs, rc; | ||
1949 | |||
1950 | switch (ia->ri_memreg_strategy) { | ||
1951 | |||
1952 | case RPCRDMA_ALLPHYSICAL: | ||
1953 | read_lock(&ia->ri_qplock); | ||
1954 | rpcrdma_unmap_one(ia, seg); | ||
1955 | read_unlock(&ia->ri_qplock); | ||
1956 | break; | ||
1957 | |||
1958 | case RPCRDMA_FRMR: | ||
1959 | rc = rpcrdma_deregister_frmr_external(seg, ia, r_xprt); | ||
1960 | break; | ||
1961 | |||
1962 | case RPCRDMA_MTHCAFMR: | ||
1963 | rc = rpcrdma_deregister_fmr_external(seg, ia); | ||
1964 | break; | ||
1965 | |||
1966 | default: | ||
1967 | break; | ||
1968 | } | ||
1969 | return nsegs; | ||
1970 | } | ||
1971 | |||
1972 | /* | 1893 | /* |
1973 | * Prepost any receive buffer, then post send. | 1894 | * Prepost any receive buffer, then post send. |
1974 | * | 1895 | * |
diff --git a/net/sunrpc/xprtrdma/xprt_rdma.h b/net/sunrpc/xprtrdma/xprt_rdma.h index 7bf077bf751d..9a727f960df9 100644 --- a/net/sunrpc/xprtrdma/xprt_rdma.h +++ b/net/sunrpc/xprtrdma/xprt_rdma.h | |||
@@ -338,6 +338,8 @@ struct rpcrdma_xprt; | |||
338 | struct rpcrdma_memreg_ops { | 338 | struct rpcrdma_memreg_ops { |
339 | int (*ro_map)(struct rpcrdma_xprt *, | 339 | int (*ro_map)(struct rpcrdma_xprt *, |
340 | struct rpcrdma_mr_seg *, int, bool); | 340 | struct rpcrdma_mr_seg *, int, bool); |
341 | int (*ro_unmap)(struct rpcrdma_xprt *, | ||
342 | struct rpcrdma_mr_seg *); | ||
341 | size_t (*ro_maxpages)(struct rpcrdma_xprt *); | 343 | size_t (*ro_maxpages)(struct rpcrdma_xprt *); |
342 | const char *ro_displayname; | 344 | const char *ro_displayname; |
343 | }; | 345 | }; |
@@ -405,9 +407,6 @@ void rpcrdma_buffer_put(struct rpcrdma_req *); | |||
405 | void rpcrdma_recv_buffer_get(struct rpcrdma_req *); | 407 | void rpcrdma_recv_buffer_get(struct rpcrdma_req *); |
406 | void rpcrdma_recv_buffer_put(struct rpcrdma_rep *); | 408 | void rpcrdma_recv_buffer_put(struct rpcrdma_rep *); |
407 | 409 | ||
408 | int rpcrdma_deregister_external(struct rpcrdma_mr_seg *, | ||
409 | struct rpcrdma_xprt *); | ||
410 | |||
411 | struct rpcrdma_regbuf *rpcrdma_alloc_regbuf(struct rpcrdma_ia *, | 410 | struct rpcrdma_regbuf *rpcrdma_alloc_regbuf(struct rpcrdma_ia *, |
412 | size_t, gfp_t); | 411 | size_t, gfp_t); |
413 | void rpcrdma_free_regbuf(struct rpcrdma_ia *, | 412 | void rpcrdma_free_regbuf(struct rpcrdma_ia *, |