diff options
Diffstat (limited to 'fs/nfs/client.c')
-rw-r--r-- | fs/nfs/client.c | 27 |
1 files changed, 18 insertions, 9 deletions
diff --git a/fs/nfs/client.c b/fs/nfs/client.c index 34c3996bd0f5..5fea638743e4 100644 --- a/fs/nfs/client.c +++ b/fs/nfs/client.c | |||
@@ -232,11 +232,15 @@ void nfs_put_client(struct nfs_client *clp) | |||
232 | * Find a client by address | 232 | * Find a client by address |
233 | * - caller must hold nfs_client_lock | 233 | * - caller must hold nfs_client_lock |
234 | */ | 234 | */ |
235 | static struct nfs_client *__nfs_find_client(const struct sockaddr_in *addr, int nfsversion) | 235 | static struct nfs_client *__nfs_find_client(const struct sockaddr_in *addr, int nfsversion, int match_port) |
236 | { | 236 | { |
237 | struct nfs_client *clp; | 237 | struct nfs_client *clp; |
238 | 238 | ||
239 | list_for_each_entry(clp, &nfs_client_list, cl_share_link) { | 239 | list_for_each_entry(clp, &nfs_client_list, cl_share_link) { |
240 | /* Don't match clients that failed to initialise properly */ | ||
241 | if (clp->cl_cons_state < 0) | ||
242 | continue; | ||
243 | |||
240 | /* Different NFS versions cannot share the same nfs_client */ | 244 | /* Different NFS versions cannot share the same nfs_client */ |
241 | if (clp->cl_nfsversion != nfsversion) | 245 | if (clp->cl_nfsversion != nfsversion) |
242 | continue; | 246 | continue; |
@@ -245,7 +249,7 @@ static struct nfs_client *__nfs_find_client(const struct sockaddr_in *addr, int | |||
245 | sizeof(clp->cl_addr.sin_addr)) != 0) | 249 | sizeof(clp->cl_addr.sin_addr)) != 0) |
246 | continue; | 250 | continue; |
247 | 251 | ||
248 | if (clp->cl_addr.sin_port == addr->sin_port) | 252 | if (!match_port || clp->cl_addr.sin_port == addr->sin_port) |
249 | goto found; | 253 | goto found; |
250 | } | 254 | } |
251 | 255 | ||
@@ -265,11 +269,12 @@ struct nfs_client *nfs_find_client(const struct sockaddr_in *addr, int nfsversio | |||
265 | struct nfs_client *clp; | 269 | struct nfs_client *clp; |
266 | 270 | ||
267 | spin_lock(&nfs_client_lock); | 271 | spin_lock(&nfs_client_lock); |
268 | clp = __nfs_find_client(addr, nfsversion); | 272 | clp = __nfs_find_client(addr, nfsversion, 0); |
269 | spin_unlock(&nfs_client_lock); | 273 | spin_unlock(&nfs_client_lock); |
270 | 274 | if (clp != NULL && clp->cl_cons_state != NFS_CS_READY) { | |
271 | BUG_ON(clp && clp->cl_cons_state == 0); | 275 | nfs_put_client(clp); |
272 | 276 | clp = NULL; | |
277 | } | ||
273 | return clp; | 278 | return clp; |
274 | } | 279 | } |
275 | 280 | ||
@@ -292,7 +297,7 @@ static struct nfs_client *nfs_get_client(const char *hostname, | |||
292 | do { | 297 | do { |
293 | spin_lock(&nfs_client_lock); | 298 | spin_lock(&nfs_client_lock); |
294 | 299 | ||
295 | clp = __nfs_find_client(addr, nfsversion); | 300 | clp = __nfs_find_client(addr, nfsversion, 1); |
296 | if (clp) | 301 | if (clp) |
297 | goto found_client; | 302 | goto found_client; |
298 | if (new) | 303 | if (new) |
@@ -849,6 +854,7 @@ error: | |||
849 | */ | 854 | */ |
850 | static int nfs4_init_client(struct nfs_client *clp, | 855 | static int nfs4_init_client(struct nfs_client *clp, |
851 | int proto, int timeo, int retrans, | 856 | int proto, int timeo, int retrans, |
857 | const char *ip_addr, | ||
852 | rpc_authflavor_t authflavour) | 858 | rpc_authflavor_t authflavour) |
853 | { | 859 | { |
854 | int error; | 860 | int error; |
@@ -865,6 +871,7 @@ static int nfs4_init_client(struct nfs_client *clp, | |||
865 | error = nfs_create_rpc_client(clp, proto, timeo, retrans, authflavour); | 871 | error = nfs_create_rpc_client(clp, proto, timeo, retrans, authflavour); |
866 | if (error < 0) | 872 | if (error < 0) |
867 | goto error; | 873 | goto error; |
874 | memcpy(clp->cl_ipaddr, ip_addr, sizeof(clp->cl_ipaddr)); | ||
868 | 875 | ||
869 | error = nfs_idmap_new(clp); | 876 | error = nfs_idmap_new(clp); |
870 | if (error < 0) { | 877 | if (error < 0) { |
@@ -888,6 +895,7 @@ error: | |||
888 | */ | 895 | */ |
889 | static int nfs4_set_client(struct nfs_server *server, | 896 | static int nfs4_set_client(struct nfs_server *server, |
890 | const char *hostname, const struct sockaddr_in *addr, | 897 | const char *hostname, const struct sockaddr_in *addr, |
898 | const char *ip_addr, | ||
891 | rpc_authflavor_t authflavour, | 899 | rpc_authflavor_t authflavour, |
892 | int proto, int timeo, int retrans) | 900 | int proto, int timeo, int retrans) |
893 | { | 901 | { |
@@ -902,7 +910,7 @@ static int nfs4_set_client(struct nfs_server *server, | |||
902 | error = PTR_ERR(clp); | 910 | error = PTR_ERR(clp); |
903 | goto error; | 911 | goto error; |
904 | } | 912 | } |
905 | error = nfs4_init_client(clp, proto, timeo, retrans, authflavour); | 913 | error = nfs4_init_client(clp, proto, timeo, retrans, ip_addr, authflavour); |
906 | if (error < 0) | 914 | if (error < 0) |
907 | goto error_put; | 915 | goto error_put; |
908 | 916 | ||
@@ -971,7 +979,7 @@ struct nfs_server *nfs4_create_server(const struct nfs4_mount_data *data, | |||
971 | return ERR_PTR(-ENOMEM); | 979 | return ERR_PTR(-ENOMEM); |
972 | 980 | ||
973 | /* Get a client record */ | 981 | /* Get a client record */ |
974 | error = nfs4_set_client(server, hostname, addr, authflavour, | 982 | error = nfs4_set_client(server, hostname, addr, ip_addr, authflavour, |
975 | data->proto, data->timeo, data->retrans); | 983 | data->proto, data->timeo, data->retrans); |
976 | if (error < 0) | 984 | if (error < 0) |
977 | goto error; | 985 | goto error; |
@@ -1041,6 +1049,7 @@ struct nfs_server *nfs4_create_referral_server(struct nfs_clone_mount *data, | |||
1041 | /* Get a client representation. | 1049 | /* Get a client representation. |
1042 | * Note: NFSv4 always uses TCP, */ | 1050 | * Note: NFSv4 always uses TCP, */ |
1043 | error = nfs4_set_client(server, data->hostname, data->addr, | 1051 | error = nfs4_set_client(server, data->hostname, data->addr, |
1052 | parent_client->cl_ipaddr, | ||
1044 | data->authflavor, | 1053 | data->authflavor, |
1045 | parent_server->client->cl_xprt->prot, | 1054 | parent_server->client->cl_xprt->prot, |
1046 | parent_client->retrans_timeo, | 1055 | parent_client->retrans_timeo, |