NFS client bugfixes for Linux 4.9
Bugfixes: - Trim extra slashes in v4 nfs_paths to fix tools that use this - Fix a -Wmaybe-uninitialized warnings - Fix suspicious RCU usages - Fix Oops when mounting multiple servers at once - Suppress a false-positive pNFS error - Fix a DMAR failure in NFS over RDMA -----BEGIN PGP SIGNATURE----- iQIcBAABCAAGBQJYJOCbAAoJENfLVL+wpUDrbO0QAIkcxdUu2iQeOrk07VP48kDE UEfJTal8vbW/KtKyL9bIeRa1qCvYpSJXnnKcR/Uo5VHE5nMz/5omoJofWf5Zg0UM iEHyZfOsuGFieBbl1NBaLjEd6MCoJYpmWFUj+3drZ8zqSdqDTL+JgrP7k3XEU2Mx glKb7U0AKoclm3h1MKyCyo5TgDVeI5TOhi+i3VVw2IN79VY2CUp4lHWMY4vloghp h+GuJWeVFS1nBpfCF9PpTU6LdHDfg4o/J5+DrP+IjIffD1XGzGEjfFR0BX5HyDcN PgOSF3fc7uVOOUIBEAqHUHY/7XiKlv6TEMRPdM8ALVoCXZ6hPSSFxq8JBJSWoVEp r11ts66VgYxdQgHbs51Y5AaKudLBwU60KosWuddbdZVb4YPM0cn5WQzVezrpoQYu k4rfrpt+LFv23NGfIJa6JaTSFBzM+YXmggEGUI8TI/YUFSN+wEp4uzLB4r19nqAP ff32iunzV9Z5edpPQFDCf3/1HAhzrL5KWo7E8EvijpdQKZl5k5CnUJxbG22lh4ct QIyYg51LjhCayzbRH8Mu+TKUFT29ORlcSp851BotLjT8ZdUetWXcFab93nAkQI7g sMREml4DvcXWy8qFAOzi8mX1ddTBumxBfOD0m3skPg+odxwsl/KiwjLCRwfTrgwS jfSXsXmrwTniPCDWgKg3 =hFod -----END PGP SIGNATURE----- Merge tag 'nfs-for-4.9-3' of git://git.linux-nfs.org/projects/anna/linux-nfs Pull NFS client bugfixes from Anna Schumaker: "Most of these fix regressions in 4.9, and none are going to stable this time around. Bugfixes: - Trim extra slashes in v4 nfs_paths to fix tools that use this - Fix a -Wmaybe-uninitialized warnings - Fix suspicious RCU usages - Fix Oops when mounting multiple servers at once - Suppress a false-positive pNFS error - Fix a DMAR failure in NFS over RDMA" * tag 'nfs-for-4.9-3' of git://git.linux-nfs.org/projects/anna/linux-nfs: xprtrdma: Fix DMAR failure in frwr_op_map() after reconnect fs/nfs: Fix used uninitialized warn in nfs4_slot_seqid_in_use() NFS: Don't print a pNFS error if we aren't using pNFS NFS: Ignore connections that have cl_rpcclient uninitialized SUNRPC: Fix suspicious RCU usage NFSv4.1: work around -Wmaybe-uninitialized warning NFS: Trim extra slash in v4 nfs_path
This commit is contained in:
commit
ef5beed998
|
@ -314,7 +314,8 @@ static struct nfs_client *nfs_match_client(const struct nfs_client_initdata *dat
|
|||
/* Match the full socket address */
|
||||
if (!rpc_cmp_addr_port(sap, clap))
|
||||
/* Match all xprt_switch full socket addresses */
|
||||
if (!rpc_clnt_xprt_switch_has_addr(clp->cl_rpcclient,
|
||||
if (IS_ERR(clp->cl_rpcclient) ||
|
||||
!rpc_clnt_xprt_switch_has_addr(clp->cl_rpcclient,
|
||||
sap))
|
||||
continue;
|
||||
|
||||
|
|
|
@ -98,7 +98,7 @@ rename_retry:
|
|||
return end;
|
||||
}
|
||||
namelen = strlen(base);
|
||||
if (flags & NFS_PATH_CANONICAL) {
|
||||
if (*end == '/') {
|
||||
/* Strip off excess slashes in base string */
|
||||
while (namelen > 0 && base[namelen - 1] == '/')
|
||||
namelen--;
|
||||
|
|
|
@ -178,12 +178,14 @@ static int nfs4_slot_get_seqid(struct nfs4_slot_table *tbl, u32 slotid,
|
|||
__must_hold(&tbl->slot_tbl_lock)
|
||||
{
|
||||
struct nfs4_slot *slot;
|
||||
int ret;
|
||||
|
||||
slot = nfs4_lookup_slot(tbl, slotid);
|
||||
if (IS_ERR(slot))
|
||||
return PTR_ERR(slot);
|
||||
*seq_nr = slot->seq_nr;
|
||||
return 0;
|
||||
ret = PTR_ERR_OR_ZERO(slot);
|
||||
if (!ret)
|
||||
*seq_nr = slot->seq_nr;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -196,7 +198,7 @@ static int nfs4_slot_get_seqid(struct nfs4_slot_table *tbl, u32 slotid,
|
|||
static bool nfs4_slot_seqid_in_use(struct nfs4_slot_table *tbl,
|
||||
u32 slotid, u32 seq_nr)
|
||||
{
|
||||
u32 cur_seq;
|
||||
u32 cur_seq = 0;
|
||||
bool ret = false;
|
||||
|
||||
spin_lock(&tbl->slot_tbl_lock);
|
||||
|
|
|
@ -146,6 +146,8 @@ set_pnfs_layoutdriver(struct nfs_server *server, const struct nfs_fh *mntfh,
|
|||
u32 id;
|
||||
int i;
|
||||
|
||||
if (fsinfo->nlayouttypes == 0)
|
||||
goto out_no_driver;
|
||||
if (!(server->nfs_client->cl_exchange_flags &
|
||||
(EXCHGID4_FLAG_USE_NON_PNFS | EXCHGID4_FLAG_USE_PNFS_MDS))) {
|
||||
printk(KERN_ERR "NFS: %s: cl_exchange_flags 0x%x\n",
|
||||
|
|
|
@ -2753,14 +2753,18 @@ EXPORT_SYMBOL_GPL(rpc_cap_max_reconnect_timeout);
|
|||
|
||||
void rpc_clnt_xprt_switch_put(struct rpc_clnt *clnt)
|
||||
{
|
||||
rcu_read_lock();
|
||||
xprt_switch_put(rcu_dereference(clnt->cl_xpi.xpi_xpswitch));
|
||||
rcu_read_unlock();
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(rpc_clnt_xprt_switch_put);
|
||||
|
||||
void rpc_clnt_xprt_switch_add_xprt(struct rpc_clnt *clnt, struct rpc_xprt *xprt)
|
||||
{
|
||||
rcu_read_lock();
|
||||
rpc_xprt_switch_add_xprt(rcu_dereference(clnt->cl_xpi.xpi_xpswitch),
|
||||
xprt);
|
||||
rcu_read_unlock();
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(rpc_clnt_xprt_switch_add_xprt);
|
||||
|
||||
|
@ -2770,9 +2774,8 @@ bool rpc_clnt_xprt_switch_has_addr(struct rpc_clnt *clnt,
|
|||
struct rpc_xprt_switch *xps;
|
||||
bool ret;
|
||||
|
||||
xps = rcu_dereference(clnt->cl_xpi.xpi_xpswitch);
|
||||
|
||||
rcu_read_lock();
|
||||
xps = rcu_dereference(clnt->cl_xpi.xpi_xpswitch);
|
||||
ret = rpc_xprt_switch_has_addr(xps, sap);
|
||||
rcu_read_unlock();
|
||||
return ret;
|
||||
|
|
|
@ -44,18 +44,20 @@
|
|||
* being done.
|
||||
*
|
||||
* When the underlying transport disconnects, MRs are left in one of
|
||||
* three states:
|
||||
* four states:
|
||||
*
|
||||
* INVALID: The MR was not in use before the QP entered ERROR state.
|
||||
* (Or, the LOCAL_INV WR has not completed or flushed yet).
|
||||
*
|
||||
* STALE: The MR was being registered or unregistered when the QP
|
||||
* entered ERROR state, and the pending WR was flushed.
|
||||
*
|
||||
* VALID: The MR was registered before the QP entered ERROR state.
|
||||
*
|
||||
* When frwr_op_map encounters STALE and VALID MRs, they are recovered
|
||||
* with ib_dereg_mr and then are re-initialized. Beause MR recovery
|
||||
* FLUSHED_FR: The MR was being registered when the QP entered ERROR
|
||||
* state, and the pending WR was flushed.
|
||||
*
|
||||
* FLUSHED_LI: The MR was being invalidated when the QP entered ERROR
|
||||
* state, and the pending WR was flushed.
|
||||
*
|
||||
* When frwr_op_map encounters FLUSHED and VALID MRs, they are recovered
|
||||
* with ib_dereg_mr and then are re-initialized. Because MR recovery
|
||||
* allocates fresh resources, it is deferred to a workqueue, and the
|
||||
* recovered MRs are placed back on the rb_mws list when recovery is
|
||||
* 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)
|
|||
static void
|
||||
frwr_op_recover_mr(struct rpcrdma_mw *mw)
|
||||
{
|
||||
enum rpcrdma_frmr_state state = mw->frmr.fr_state;
|
||||
struct rpcrdma_xprt *r_xprt = mw->mw_xprt;
|
||||
struct rpcrdma_ia *ia = &r_xprt->rx_ia;
|
||||
int rc;
|
||||
|
||||
rc = __frwr_reset_mr(ia, mw);
|
||||
ib_dma_unmap_sg(ia->ri_device, mw->mw_sg, mw->mw_nents, mw->mw_dir);
|
||||
if (state != FRMR_FLUSHED_LI)
|
||||
ib_dma_unmap_sg(ia->ri_device,
|
||||
mw->mw_sg, mw->mw_nents, mw->mw_dir);
|
||||
if (rc)
|
||||
goto out_release;
|
||||
|
||||
|
@ -262,10 +267,8 @@ frwr_op_maxpages(struct rpcrdma_xprt *r_xprt)
|
|||
}
|
||||
|
||||
static void
|
||||
__frwr_sendcompletion_flush(struct ib_wc *wc, struct rpcrdma_frmr *frmr,
|
||||
const char *wr)
|
||||
__frwr_sendcompletion_flush(struct ib_wc *wc, const char *wr)
|
||||
{
|
||||
frmr->fr_state = FRMR_IS_STALE;
|
||||
if (wc->status != IB_WC_WR_FLUSH_ERR)
|
||||
pr_err("rpcrdma: %s: %s (%u/0x%x)\n",
|
||||
wr, ib_wc_status_msg(wc->status),
|
||||
|
@ -288,7 +291,8 @@ frwr_wc_fastreg(struct ib_cq *cq, struct ib_wc *wc)
|
|||
if (wc->status != IB_WC_SUCCESS) {
|
||||
cqe = wc->wr_cqe;
|
||||
frmr = container_of(cqe, struct rpcrdma_frmr, fr_cqe);
|
||||
__frwr_sendcompletion_flush(wc, frmr, "fastreg");
|
||||
frmr->fr_state = FRMR_FLUSHED_FR;
|
||||
__frwr_sendcompletion_flush(wc, "fastreg");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -308,7 +312,8 @@ frwr_wc_localinv(struct ib_cq *cq, struct ib_wc *wc)
|
|||
if (wc->status != IB_WC_SUCCESS) {
|
||||
cqe = wc->wr_cqe;
|
||||
frmr = container_of(cqe, struct rpcrdma_frmr, fr_cqe);
|
||||
__frwr_sendcompletion_flush(wc, frmr, "localinv");
|
||||
frmr->fr_state = FRMR_FLUSHED_LI;
|
||||
__frwr_sendcompletion_flush(wc, "localinv");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -328,8 +333,10 @@ frwr_wc_localinv_wake(struct ib_cq *cq, struct ib_wc *wc)
|
|||
/* WARNING: Only wr_cqe and status are reliable at this point */
|
||||
cqe = wc->wr_cqe;
|
||||
frmr = container_of(cqe, struct rpcrdma_frmr, fr_cqe);
|
||||
if (wc->status != IB_WC_SUCCESS)
|
||||
__frwr_sendcompletion_flush(wc, frmr, "localinv");
|
||||
if (wc->status != IB_WC_SUCCESS) {
|
||||
frmr->fr_state = FRMR_FLUSHED_LI;
|
||||
__frwr_sendcompletion_flush(wc, "localinv");
|
||||
}
|
||||
complete(&frmr->fr_linv_done);
|
||||
}
|
||||
|
||||
|
|
|
@ -216,7 +216,8 @@ struct rpcrdma_rep {
|
|||
enum rpcrdma_frmr_state {
|
||||
FRMR_IS_INVALID, /* ready to be used */
|
||||
FRMR_IS_VALID, /* in use */
|
||||
FRMR_IS_STALE, /* failed completion */
|
||||
FRMR_FLUSHED_FR, /* flushed FASTREG WR */
|
||||
FRMR_FLUSHED_LI, /* flushed LOCALINV WR */
|
||||
};
|
||||
|
||||
struct rpcrdma_frmr {
|
||||
|
|
Loading…
Reference in New Issue