diff options
author | Roberto Bergantinos Corpas <rbergant@redhat.com> | 2019-04-25 09:36:51 -0400 |
---|---|---|
committer | Anna Schumaker <Anna.Schumaker@Netapp.com> | 2019-05-07 10:38:14 -0400 |
commit | 950a578c6128c2886e295b9c7ecb0b6b22fcc92b (patch) | |
tree | 3fae267fb97c6507a0dc85f66387d57ced5e06de /fs/nfs/client.c | |
parent | b422df915cef80333d7a1732e6ed81f41db12b79 (diff) |
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>
Diffstat (limited to 'fs/nfs/client.c')
-rw-r--r-- | fs/nfs/client.c | 7 |
1 files changed, 6 insertions, 1 deletions
diff --git a/fs/nfs/client.c b/fs/nfs/client.c index e3baa9f1da76..06e8719655f0 100644 --- a/fs/nfs/client.c +++ b/fs/nfs/client.c | |||
@@ -284,6 +284,7 @@ static struct nfs_client *nfs_match_client(const struct nfs_client_initdata *dat | |||
284 | struct nfs_client *clp; | 284 | struct nfs_client *clp; |
285 | const struct sockaddr *sap = data->addr; | 285 | const struct sockaddr *sap = data->addr; |
286 | struct nfs_net *nn = net_generic(data->net, nfs_net_id); | 286 | struct nfs_net *nn = net_generic(data->net, nfs_net_id); |
287 | int error; | ||
287 | 288 | ||
288 | again: | 289 | again: |
289 | list_for_each_entry(clp, &nn->nfs_client_list, cl_share_link) { | 290 | list_for_each_entry(clp, &nn->nfs_client_list, cl_share_link) { |
@@ -296,8 +297,10 @@ again: | |||
296 | if (clp->cl_cons_state > NFS_CS_READY) { | 297 | if (clp->cl_cons_state > NFS_CS_READY) { |
297 | refcount_inc(&clp->cl_count); | 298 | refcount_inc(&clp->cl_count); |
298 | spin_unlock(&nn->nfs_client_lock); | 299 | spin_unlock(&nn->nfs_client_lock); |
299 | nfs_wait_client_init_complete(clp); | 300 | error = nfs_wait_client_init_complete(clp); |
300 | nfs_put_client(clp); | 301 | nfs_put_client(clp); |
302 | if (error < 0) | ||
303 | return ERR_PTR(error); | ||
301 | spin_lock(&nn->nfs_client_lock); | 304 | spin_lock(&nn->nfs_client_lock); |
302 | goto again; | 305 | goto again; |
303 | } | 306 | } |
@@ -407,6 +410,8 @@ struct nfs_client *nfs_get_client(const struct nfs_client_initdata *cl_init) | |||
407 | clp = nfs_match_client(cl_init); | 410 | clp = nfs_match_client(cl_init); |
408 | if (clp) { | 411 | if (clp) { |
409 | spin_unlock(&nn->nfs_client_lock); | 412 | spin_unlock(&nn->nfs_client_lock); |
413 | if (IS_ERR(clp)) | ||
414 | return clp; | ||
410 | if (new) | 415 | if (new) |
411 | new->rpc_ops->free_client(new); | 416 | new->rpc_ops->free_client(new); |
412 | return nfs_found_client(cl_init, clp); | 417 | return nfs_found_client(cl_init, clp); |