Clean up: Rationalize the locking in nfs_get_client() for the case where the target server already appears in the nfs_client_list. Code that takes and releases nfs_client_lock remains in nfs_get_client(). The rest of the logic is moved to a separate function. No behavior change is expected. Signed-off-by: Chuck Lever <chuck.lever@xxxxxxxxxx> --- fs/nfs/client.c | 71 ++++++++++++++++++++++++++++++++----------------------- 1 files changed, 41 insertions(+), 30 deletions(-) diff --git a/fs/nfs/client.c b/fs/nfs/client.c index 3ba6c62..09b3f55 100644 --- a/fs/nfs/client.c +++ b/fs/nfs/client.c @@ -504,6 +504,39 @@ static struct nfs_client *nfs_match_client(const struct nfs_client_initdata *dat } /* + * Found an existing client. Make sure it's ready before returning. + */ +static struct nfs_client * +nfs_found_client(const struct nfs_client_initdata *cl_init, + struct nfs_client *clp) +{ + int error; + + error = wait_event_killable(nfs_client_active_wq, + clp->cl_cons_state < NFS_CS_INITING); + if (error < 0) { + dprintk("<-- nfs_get_client error waiting for nfs_client %p " + "for %s (%d)\n", clp, cl_init->hostname ?: "", error); + nfs_put_client(clp); + return ERR_PTR(-ERESTARTSYS); + } + + if (clp->cl_cons_state < NFS_CS_READY) { + error = clp->cl_cons_state; + dprintk("<-- nfs_get_client found nfs_client %p for %s, not " + "ready (%d)\n", clp, cl_init->hostname ?: "", error); + nfs_put_client(clp); + return ERR_PTR(error); + } + + BUG_ON(clp->cl_cons_state != NFS_CS_READY); + + dprintk("<-- nfs_get_client found nfs_client %p for %s\n", + clp, cl_init->hostname ?: ""); + return clp; +} + +/* * Look up a client by IP address and protocol version * - creates a new record if one doesn't yet exist */ @@ -526,8 +559,12 @@ nfs_get_client(const struct nfs_client_initdata *cl_init, spin_lock(&nn->nfs_client_lock); clp = nfs_match_client(cl_init); - if (clp) - goto found_client; + if (clp) { + spin_unlock(&nn->nfs_client_lock); + if (new) + nfs_free_client(new); + return nfs_found_client(cl_init, clp); + } if (new) goto install_client; @@ -536,7 +573,8 @@ nfs_get_client(const struct nfs_client_initdata *cl_init, new = nfs_alloc_client(cl_init); } while (!IS_ERR(new)); - dprintk("--> nfs_get_client() = %ld [failed]\n", PTR_ERR(new)); + dprintk("<-- nfs_get_client() Failed to find %s (%ld)\n", + cl_init->hostname ?: "", PTR_ERR(new)); return new; /* install a new client and return with it unready */ @@ -553,33 +591,6 @@ install_client: } dprintk("--> nfs_get_client() = %p [new]\n", clp); return clp; - - /* found an existing client - * - make sure it's ready before returning - */ -found_client: - spin_unlock(&nn->nfs_client_lock); - - if (new) - nfs_free_client(new); - - error = wait_event_killable(nfs_client_active_wq, - clp->cl_cons_state < NFS_CS_INITING); - if (error < 0) { - nfs_put_client(clp); - return ERR_PTR(-ERESTARTSYS); - } - - if (clp->cl_cons_state < NFS_CS_READY) { - error = clp->cl_cons_state; - nfs_put_client(clp); - return ERR_PTR(error); - } - - BUG_ON(clp->cl_cons_state != NFS_CS_READY); - - dprintk("--> nfs_get_client() = %p [share]\n", clp); - return clp; } /* -- To unsubscribe from this list: send the line "unsubscribe linux-nfs" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html