NFS: make nfs_match_client killable
Actually we don't do anything with return value from nfs_wait_client_init_complete in nfs_match_client, as a consequence if we get a fatal signal and client is not fully initialised, we'll loop to "again" label This has been proven to cause soft lockups on some scenarios (no-carrier but configured network interfaces) Signed-off-by: Roberto Bergantinos Corpas <rbergant@redhat.com> Reviewed-by: Benjamin Coddington <bcodding@redhat.com> Signed-off-by: Anna Schumaker <Anna.Schumaker@Netapp.com>
This commit is contained in:
parent
b422df915c
commit
950a578c61
@ -284,6 +284,7 @@ static struct nfs_client *nfs_match_client(const struct nfs_client_initdata *dat
|
|||||||
struct nfs_client *clp;
|
struct nfs_client *clp;
|
||||||
const struct sockaddr *sap = data->addr;
|
const struct sockaddr *sap = data->addr;
|
||||||
struct nfs_net *nn = net_generic(data->net, nfs_net_id);
|
struct nfs_net *nn = net_generic(data->net, nfs_net_id);
|
||||||
|
int error;
|
||||||
|
|
||||||
again:
|
again:
|
||||||
list_for_each_entry(clp, &nn->nfs_client_list, cl_share_link) {
|
list_for_each_entry(clp, &nn->nfs_client_list, cl_share_link) {
|
||||||
@ -296,8 +297,10 @@ again:
|
|||||||
if (clp->cl_cons_state > NFS_CS_READY) {
|
if (clp->cl_cons_state > NFS_CS_READY) {
|
||||||
refcount_inc(&clp->cl_count);
|
refcount_inc(&clp->cl_count);
|
||||||
spin_unlock(&nn->nfs_client_lock);
|
spin_unlock(&nn->nfs_client_lock);
|
||||||
nfs_wait_client_init_complete(clp);
|
error = nfs_wait_client_init_complete(clp);
|
||||||
nfs_put_client(clp);
|
nfs_put_client(clp);
|
||||||
|
if (error < 0)
|
||||||
|
return ERR_PTR(error);
|
||||||
spin_lock(&nn->nfs_client_lock);
|
spin_lock(&nn->nfs_client_lock);
|
||||||
goto again;
|
goto again;
|
||||||
}
|
}
|
||||||
@ -407,6 +410,8 @@ struct nfs_client *nfs_get_client(const struct nfs_client_initdata *cl_init)
|
|||||||
clp = nfs_match_client(cl_init);
|
clp = nfs_match_client(cl_init);
|
||||||
if (clp) {
|
if (clp) {
|
||||||
spin_unlock(&nn->nfs_client_lock);
|
spin_unlock(&nn->nfs_client_lock);
|
||||||
|
if (IS_ERR(clp))
|
||||||
|
return clp;
|
||||||
if (new)
|
if (new)
|
||||||
new->rpc_ops->free_client(new);
|
new->rpc_ops->free_client(new);
|
||||||
return nfs_found_client(cl_init, clp);
|
return nfs_found_client(cl_init, clp);
|
||||||
|
Loading…
Reference in New Issue
Block a user