diff options
Diffstat (limited to 'fs/nfs')
-rw-r--r-- | fs/nfs/client.c | 16 | ||||
-rw-r--r-- | fs/nfs/idmap.c | 15 | ||||
-rw-r--r-- | fs/nfs/internal.h | 1 |
3 files changed, 29 insertions, 3 deletions
diff --git a/fs/nfs/client.c b/fs/nfs/client.c index 25dde0745cfa..d35664287e14 100644 --- a/fs/nfs/client.c +++ b/fs/nfs/client.c | |||
@@ -507,6 +507,17 @@ static struct nfs_client *nfs_match_client(const struct nfs_client_initdata *dat | |||
507 | return NULL; | 507 | return NULL; |
508 | } | 508 | } |
509 | 509 | ||
510 | static bool nfs_client_init_is_complete(const struct nfs_client *clp) | ||
511 | { | ||
512 | return clp->cl_cons_state != NFS_CS_INITING; | ||
513 | } | ||
514 | |||
515 | int nfs_wait_client_init_complete(const struct nfs_client *clp) | ||
516 | { | ||
517 | return wait_event_killable(nfs_client_active_wq, | ||
518 | nfs_client_init_is_complete(clp)); | ||
519 | } | ||
520 | |||
510 | /* | 521 | /* |
511 | * Found an existing client. Make sure it's ready before returning. | 522 | * Found an existing client. Make sure it's ready before returning. |
512 | */ | 523 | */ |
@@ -516,8 +527,7 @@ nfs_found_client(const struct nfs_client_initdata *cl_init, | |||
516 | { | 527 | { |
517 | int error; | 528 | int error; |
518 | 529 | ||
519 | error = wait_event_killable(nfs_client_active_wq, | 530 | error = nfs_wait_client_init_complete(clp); |
520 | clp->cl_cons_state < NFS_CS_INITING); | ||
521 | if (error < 0) { | 531 | if (error < 0) { |
522 | nfs_put_client(clp); | 532 | nfs_put_client(clp); |
523 | return ERR_PTR(-ERESTARTSYS); | 533 | return ERR_PTR(-ERESTARTSYS); |
@@ -1333,7 +1343,7 @@ static int nfs4_init_client_minor_version(struct nfs_client *clp) | |||
1333 | * so that the client back channel can find the | 1343 | * so that the client back channel can find the |
1334 | * nfs_client struct | 1344 | * nfs_client struct |
1335 | */ | 1345 | */ |
1336 | clp->cl_cons_state = NFS_CS_SESSION_INITING; | 1346 | nfs_mark_client_ready(clp, NFS_CS_SESSION_INITING); |
1337 | } | 1347 | } |
1338 | #endif /* CONFIG_NFS_V4_1 */ | 1348 | #endif /* CONFIG_NFS_V4_1 */ |
1339 | 1349 | ||
diff --git a/fs/nfs/idmap.c b/fs/nfs/idmap.c index 2eaecf9d8db7..861be75eb165 100644 --- a/fs/nfs/idmap.c +++ b/fs/nfs/idmap.c | |||
@@ -530,9 +530,24 @@ static struct nfs_client *nfs_get_client_for_event(struct net *net, int event) | |||
530 | struct nfs_net *nn = net_generic(net, nfs_net_id); | 530 | struct nfs_net *nn = net_generic(net, nfs_net_id); |
531 | struct dentry *cl_dentry; | 531 | struct dentry *cl_dentry; |
532 | struct nfs_client *clp; | 532 | struct nfs_client *clp; |
533 | int err; | ||
533 | 534 | ||
535 | restart: | ||
534 | spin_lock(&nn->nfs_client_lock); | 536 | spin_lock(&nn->nfs_client_lock); |
535 | list_for_each_entry(clp, &nn->nfs_client_list, cl_share_link) { | 537 | list_for_each_entry(clp, &nn->nfs_client_list, cl_share_link) { |
538 | /* Wait for initialisation to finish */ | ||
539 | if (clp->cl_cons_state == NFS_CS_INITING) { | ||
540 | atomic_inc(&clp->cl_count); | ||
541 | spin_unlock(&nn->nfs_client_lock); | ||
542 | err = nfs_wait_client_init_complete(clp); | ||
543 | nfs_put_client(clp); | ||
544 | if (err) | ||
545 | return NULL; | ||
546 | goto restart; | ||
547 | } | ||
548 | /* Skip nfs_clients that failed to initialise */ | ||
549 | if (clp->cl_cons_state < 0) | ||
550 | continue; | ||
536 | if (clp->rpc_ops != &nfs_v4_clientops) | 551 | if (clp->rpc_ops != &nfs_v4_clientops) |
537 | continue; | 552 | continue; |
538 | cl_dentry = clp->cl_idmap->idmap_pipe->dentry; | 553 | cl_dentry = clp->cl_idmap->idmap_pipe->dentry; |
diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h index 5ea571e8d0e9..1848a7275592 100644 --- a/fs/nfs/internal.h +++ b/fs/nfs/internal.h | |||
@@ -168,6 +168,7 @@ extern struct nfs_server *nfs_clone_server(struct nfs_server *, | |||
168 | struct nfs_fh *, | 168 | struct nfs_fh *, |
169 | struct nfs_fattr *, | 169 | struct nfs_fattr *, |
170 | rpc_authflavor_t); | 170 | rpc_authflavor_t); |
171 | extern int nfs_wait_client_init_complete(const struct nfs_client *clp); | ||
171 | extern void nfs_mark_client_ready(struct nfs_client *clp, int state); | 172 | extern void nfs_mark_client_ready(struct nfs_client *clp, int state); |
172 | extern struct nfs_client *nfs4_set_ds_client(struct nfs_client* mds_clp, | 173 | extern struct nfs_client *nfs4_set_ds_client(struct nfs_client* mds_clp, |
173 | const struct sockaddr *ds_addr, | 174 | const struct sockaddr *ds_addr, |