diff options
-rw-r--r-- | fs/nfs/client.c | 3 | ||||
-rw-r--r-- | fs/nfs/namespace.c | 2 | ||||
-rw-r--r-- | fs/nfs/nfs4session.c | 12 | ||||
-rw-r--r-- | fs/nfs/pnfs.c | 2 | ||||
-rw-r--r-- | net/sunrpc/clnt.c | 7 | ||||
-rw-r--r-- | net/sunrpc/xprtrdma/frwr_ops.c | 37 | ||||
-rw-r--r-- | net/sunrpc/xprtrdma/xprt_rdma.h | 3 |
7 files changed, 41 insertions, 25 deletions
diff --git a/fs/nfs/client.c b/fs/nfs/client.c index 7555ba889d1f..ebecfb8fba06 100644 --- a/fs/nfs/client.c +++ b/fs/nfs/client.c | |||
@@ -314,7 +314,8 @@ static struct nfs_client *nfs_match_client(const struct nfs_client_initdata *dat | |||
314 | /* Match the full socket address */ | 314 | /* Match the full socket address */ |
315 | if (!rpc_cmp_addr_port(sap, clap)) | 315 | if (!rpc_cmp_addr_port(sap, clap)) |
316 | /* Match all xprt_switch full socket addresses */ | 316 | /* Match all xprt_switch full socket addresses */ |
317 | if (!rpc_clnt_xprt_switch_has_addr(clp->cl_rpcclient, | 317 | if (IS_ERR(clp->cl_rpcclient) || |
318 | !rpc_clnt_xprt_switch_has_addr(clp->cl_rpcclient, | ||
318 | sap)) | 319 | sap)) |
319 | continue; | 320 | continue; |
320 | 321 | ||
diff --git a/fs/nfs/namespace.c b/fs/nfs/namespace.c index c8162c660c44..5551e8ef67fd 100644 --- a/fs/nfs/namespace.c +++ b/fs/nfs/namespace.c | |||
@@ -98,7 +98,7 @@ rename_retry: | |||
98 | return end; | 98 | return end; |
99 | } | 99 | } |
100 | namelen = strlen(base); | 100 | namelen = strlen(base); |
101 | if (flags & NFS_PATH_CANONICAL) { | 101 | if (*end == '/') { |
102 | /* Strip off excess slashes in base string */ | 102 | /* Strip off excess slashes in base string */ |
103 | while (namelen > 0 && base[namelen - 1] == '/') | 103 | while (namelen > 0 && base[namelen - 1] == '/') |
104 | namelen--; | 104 | namelen--; |
diff --git a/fs/nfs/nfs4session.c b/fs/nfs/nfs4session.c index b62973045a3e..a61350f75c74 100644 --- a/fs/nfs/nfs4session.c +++ b/fs/nfs/nfs4session.c | |||
@@ -178,12 +178,14 @@ static int nfs4_slot_get_seqid(struct nfs4_slot_table *tbl, u32 slotid, | |||
178 | __must_hold(&tbl->slot_tbl_lock) | 178 | __must_hold(&tbl->slot_tbl_lock) |
179 | { | 179 | { |
180 | struct nfs4_slot *slot; | 180 | struct nfs4_slot *slot; |
181 | int ret; | ||
181 | 182 | ||
182 | slot = nfs4_lookup_slot(tbl, slotid); | 183 | slot = nfs4_lookup_slot(tbl, slotid); |
183 | if (IS_ERR(slot)) | 184 | ret = PTR_ERR_OR_ZERO(slot); |
184 | return PTR_ERR(slot); | 185 | if (!ret) |
185 | *seq_nr = slot->seq_nr; | 186 | *seq_nr = slot->seq_nr; |
186 | return 0; | 187 | |
188 | return ret; | ||
187 | } | 189 | } |
188 | 190 | ||
189 | /* | 191 | /* |
@@ -196,7 +198,7 @@ static int nfs4_slot_get_seqid(struct nfs4_slot_table *tbl, u32 slotid, | |||
196 | static bool nfs4_slot_seqid_in_use(struct nfs4_slot_table *tbl, | 198 | static bool nfs4_slot_seqid_in_use(struct nfs4_slot_table *tbl, |
197 | u32 slotid, u32 seq_nr) | 199 | u32 slotid, u32 seq_nr) |
198 | { | 200 | { |
199 | u32 cur_seq; | 201 | u32 cur_seq = 0; |
200 | bool ret = false; | 202 | bool ret = false; |
201 | 203 | ||
202 | spin_lock(&tbl->slot_tbl_lock); | 204 | spin_lock(&tbl->slot_tbl_lock); |
diff --git a/fs/nfs/pnfs.c b/fs/nfs/pnfs.c index 56b2d96f9103..259ef85f435a 100644 --- a/fs/nfs/pnfs.c +++ b/fs/nfs/pnfs.c | |||
@@ -146,6 +146,8 @@ set_pnfs_layoutdriver(struct nfs_server *server, const struct nfs_fh *mntfh, | |||
146 | u32 id; | 146 | u32 id; |
147 | int i; | 147 | int i; |
148 | 148 | ||
149 | if (fsinfo->nlayouttypes == 0) | ||
150 | goto out_no_driver; | ||
149 | if (!(server->nfs_client->cl_exchange_flags & | 151 | if (!(server->nfs_client->cl_exchange_flags & |
150 | (EXCHGID4_FLAG_USE_NON_PNFS | EXCHGID4_FLAG_USE_PNFS_MDS))) { | 152 | (EXCHGID4_FLAG_USE_NON_PNFS | EXCHGID4_FLAG_USE_PNFS_MDS))) { |
151 | printk(KERN_ERR "NFS: %s: cl_exchange_flags 0x%x\n", | 153 | printk(KERN_ERR "NFS: %s: cl_exchange_flags 0x%x\n", |
diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c index 34dd7b26ee5f..62a482790937 100644 --- a/net/sunrpc/clnt.c +++ b/net/sunrpc/clnt.c | |||
@@ -2753,14 +2753,18 @@ EXPORT_SYMBOL_GPL(rpc_cap_max_reconnect_timeout); | |||
2753 | 2753 | ||
2754 | void rpc_clnt_xprt_switch_put(struct rpc_clnt *clnt) | 2754 | void rpc_clnt_xprt_switch_put(struct rpc_clnt *clnt) |
2755 | { | 2755 | { |
2756 | rcu_read_lock(); | ||
2756 | xprt_switch_put(rcu_dereference(clnt->cl_xpi.xpi_xpswitch)); | 2757 | xprt_switch_put(rcu_dereference(clnt->cl_xpi.xpi_xpswitch)); |
2758 | rcu_read_unlock(); | ||
2757 | } | 2759 | } |
2758 | EXPORT_SYMBOL_GPL(rpc_clnt_xprt_switch_put); | 2760 | EXPORT_SYMBOL_GPL(rpc_clnt_xprt_switch_put); |
2759 | 2761 | ||
2760 | void rpc_clnt_xprt_switch_add_xprt(struct rpc_clnt *clnt, struct rpc_xprt *xprt) | 2762 | void rpc_clnt_xprt_switch_add_xprt(struct rpc_clnt *clnt, struct rpc_xprt *xprt) |
2761 | { | 2763 | { |
2764 | rcu_read_lock(); | ||
2762 | rpc_xprt_switch_add_xprt(rcu_dereference(clnt->cl_xpi.xpi_xpswitch), | 2765 | rpc_xprt_switch_add_xprt(rcu_dereference(clnt->cl_xpi.xpi_xpswitch), |
2763 | xprt); | 2766 | xprt); |
2767 | rcu_read_unlock(); | ||
2764 | } | 2768 | } |
2765 | EXPORT_SYMBOL_GPL(rpc_clnt_xprt_switch_add_xprt); | 2769 | EXPORT_SYMBOL_GPL(rpc_clnt_xprt_switch_add_xprt); |
2766 | 2770 | ||
@@ -2770,9 +2774,8 @@ bool rpc_clnt_xprt_switch_has_addr(struct rpc_clnt *clnt, | |||
2770 | struct rpc_xprt_switch *xps; | 2774 | struct rpc_xprt_switch *xps; |
2771 | bool ret; | 2775 | bool ret; |
2772 | 2776 | ||
2773 | xps = rcu_dereference(clnt->cl_xpi.xpi_xpswitch); | ||
2774 | |||
2775 | rcu_read_lock(); | 2777 | rcu_read_lock(); |
2778 | xps = rcu_dereference(clnt->cl_xpi.xpi_xpswitch); | ||
2776 | ret = rpc_xprt_switch_has_addr(xps, sap); | 2779 | ret = rpc_xprt_switch_has_addr(xps, sap); |
2777 | rcu_read_unlock(); | 2780 | rcu_read_unlock(); |
2778 | return ret; | 2781 | return ret; |
diff --git a/net/sunrpc/xprtrdma/frwr_ops.c b/net/sunrpc/xprtrdma/frwr_ops.c index 210949562786..26b26beef2d4 100644 --- a/net/sunrpc/xprtrdma/frwr_ops.c +++ b/net/sunrpc/xprtrdma/frwr_ops.c | |||
@@ -44,18 +44,20 @@ | |||
44 | * being done. | 44 | * being done. |
45 | * | 45 | * |
46 | * When the underlying transport disconnects, MRs are left in one of | 46 | * When the underlying transport disconnects, MRs are left in one of |
47 | * three states: | 47 | * four states: |
48 | * | 48 | * |
49 | * INVALID: The MR was not in use before the QP entered ERROR state. | 49 | * INVALID: The MR was not in use before the QP entered ERROR state. |
50 | * (Or, the LOCAL_INV WR has not completed or flushed yet). | ||
51 | * | ||
52 | * STALE: The MR was being registered or unregistered when the QP | ||
53 | * entered ERROR state, and the pending WR was flushed. | ||
54 | * | 50 | * |
55 | * VALID: The MR was registered before the QP entered ERROR state. | 51 | * VALID: The MR was registered before the QP entered ERROR state. |
56 | * | 52 | * |
57 | * When frwr_op_map encounters STALE and VALID MRs, they are recovered | 53 | * FLUSHED_FR: The MR was being registered when the QP entered ERROR |
58 | * with ib_dereg_mr and then are re-initialized. Beause MR recovery | 54 | * state, and the pending WR was flushed. |
55 | * | ||
56 | * FLUSHED_LI: The MR was being invalidated when the QP entered ERROR | ||
57 | * state, and the pending WR was flushed. | ||
58 | * | ||
59 | * When frwr_op_map encounters FLUSHED and VALID MRs, they are recovered | ||
60 | * with ib_dereg_mr and then are re-initialized. Because MR recovery | ||
59 | * allocates fresh resources, it is deferred to a workqueue, and the | 61 | * allocates fresh resources, it is deferred to a workqueue, and the |
60 | * recovered MRs are placed back on the rb_mws list when recovery is | 62 | * recovered MRs are placed back on the rb_mws list when recovery is |
61 | * complete. frwr_op_map allocates another MR for the current RPC while | 63 | * complete. frwr_op_map allocates another MR for the current RPC while |
@@ -177,12 +179,15 @@ __frwr_reset_mr(struct rpcrdma_ia *ia, struct rpcrdma_mw *r) | |||
177 | static void | 179 | static void |
178 | frwr_op_recover_mr(struct rpcrdma_mw *mw) | 180 | frwr_op_recover_mr(struct rpcrdma_mw *mw) |
179 | { | 181 | { |
182 | enum rpcrdma_frmr_state state = mw->frmr.fr_state; | ||
180 | struct rpcrdma_xprt *r_xprt = mw->mw_xprt; | 183 | struct rpcrdma_xprt *r_xprt = mw->mw_xprt; |
181 | struct rpcrdma_ia *ia = &r_xprt->rx_ia; | 184 | struct rpcrdma_ia *ia = &r_xprt->rx_ia; |
182 | int rc; | 185 | int rc; |
183 | 186 | ||
184 | rc = __frwr_reset_mr(ia, mw); | 187 | rc = __frwr_reset_mr(ia, mw); |
185 | ib_dma_unmap_sg(ia->ri_device, mw->mw_sg, mw->mw_nents, mw->mw_dir); | 188 | if (state != FRMR_FLUSHED_LI) |
189 | ib_dma_unmap_sg(ia->ri_device, | ||
190 | mw->mw_sg, mw->mw_nents, mw->mw_dir); | ||
186 | if (rc) | 191 | if (rc) |
187 | goto out_release; | 192 | goto out_release; |
188 | 193 | ||
@@ -262,10 +267,8 @@ frwr_op_maxpages(struct rpcrdma_xprt *r_xprt) | |||
262 | } | 267 | } |
263 | 268 | ||
264 | static void | 269 | static void |
265 | __frwr_sendcompletion_flush(struct ib_wc *wc, struct rpcrdma_frmr *frmr, | 270 | __frwr_sendcompletion_flush(struct ib_wc *wc, const char *wr) |
266 | const char *wr) | ||
267 | { | 271 | { |
268 | frmr->fr_state = FRMR_IS_STALE; | ||
269 | if (wc->status != IB_WC_WR_FLUSH_ERR) | 272 | if (wc->status != IB_WC_WR_FLUSH_ERR) |
270 | pr_err("rpcrdma: %s: %s (%u/0x%x)\n", | 273 | pr_err("rpcrdma: %s: %s (%u/0x%x)\n", |
271 | wr, ib_wc_status_msg(wc->status), | 274 | wr, ib_wc_status_msg(wc->status), |
@@ -288,7 +291,8 @@ frwr_wc_fastreg(struct ib_cq *cq, struct ib_wc *wc) | |||
288 | if (wc->status != IB_WC_SUCCESS) { | 291 | if (wc->status != IB_WC_SUCCESS) { |
289 | cqe = wc->wr_cqe; | 292 | cqe = wc->wr_cqe; |
290 | frmr = container_of(cqe, struct rpcrdma_frmr, fr_cqe); | 293 | frmr = container_of(cqe, struct rpcrdma_frmr, fr_cqe); |
291 | __frwr_sendcompletion_flush(wc, frmr, "fastreg"); | 294 | frmr->fr_state = FRMR_FLUSHED_FR; |
295 | __frwr_sendcompletion_flush(wc, "fastreg"); | ||
292 | } | 296 | } |
293 | } | 297 | } |
294 | 298 | ||
@@ -308,7 +312,8 @@ frwr_wc_localinv(struct ib_cq *cq, struct ib_wc *wc) | |||
308 | if (wc->status != IB_WC_SUCCESS) { | 312 | if (wc->status != IB_WC_SUCCESS) { |
309 | cqe = wc->wr_cqe; | 313 | cqe = wc->wr_cqe; |
310 | frmr = container_of(cqe, struct rpcrdma_frmr, fr_cqe); | 314 | frmr = container_of(cqe, struct rpcrdma_frmr, fr_cqe); |
311 | __frwr_sendcompletion_flush(wc, frmr, "localinv"); | 315 | frmr->fr_state = FRMR_FLUSHED_LI; |
316 | __frwr_sendcompletion_flush(wc, "localinv"); | ||
312 | } | 317 | } |
313 | } | 318 | } |
314 | 319 | ||
@@ -328,8 +333,10 @@ frwr_wc_localinv_wake(struct ib_cq *cq, struct ib_wc *wc) | |||
328 | /* WARNING: Only wr_cqe and status are reliable at this point */ | 333 | /* WARNING: Only wr_cqe and status are reliable at this point */ |
329 | cqe = wc->wr_cqe; | 334 | cqe = wc->wr_cqe; |
330 | frmr = container_of(cqe, struct rpcrdma_frmr, fr_cqe); | 335 | frmr = container_of(cqe, struct rpcrdma_frmr, fr_cqe); |
331 | if (wc->status != IB_WC_SUCCESS) | 336 | if (wc->status != IB_WC_SUCCESS) { |
332 | __frwr_sendcompletion_flush(wc, frmr, "localinv"); | 337 | frmr->fr_state = FRMR_FLUSHED_LI; |
338 | __frwr_sendcompletion_flush(wc, "localinv"); | ||
339 | } | ||
333 | complete(&frmr->fr_linv_done); | 340 | complete(&frmr->fr_linv_done); |
334 | } | 341 | } |
335 | 342 | ||
diff --git a/net/sunrpc/xprtrdma/xprt_rdma.h b/net/sunrpc/xprtrdma/xprt_rdma.h index 0d35b761c883..6e1bba358203 100644 --- a/net/sunrpc/xprtrdma/xprt_rdma.h +++ b/net/sunrpc/xprtrdma/xprt_rdma.h | |||
@@ -216,7 +216,8 @@ struct rpcrdma_rep { | |||
216 | enum rpcrdma_frmr_state { | 216 | enum rpcrdma_frmr_state { |
217 | FRMR_IS_INVALID, /* ready to be used */ | 217 | FRMR_IS_INVALID, /* ready to be used */ |
218 | FRMR_IS_VALID, /* in use */ | 218 | FRMR_IS_VALID, /* in use */ |
219 | FRMR_IS_STALE, /* failed completion */ | 219 | FRMR_FLUSHED_FR, /* flushed FASTREG WR */ |
220 | FRMR_FLUSHED_LI, /* flushed LOCALINV WR */ | ||
220 | }; | 221 | }; |
221 | 222 | ||
222 | struct rpcrdma_frmr { | 223 | struct rpcrdma_frmr { |