aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfs/client.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/nfs/client.c')
-rw-r--r--fs/nfs/client.c95
1 files changed, 61 insertions, 34 deletions
diff --git a/fs/nfs/client.c b/fs/nfs/client.c
index 7547600b6174..9b728f3565a1 100644
--- a/fs/nfs/client.c
+++ b/fs/nfs/client.c
@@ -143,7 +143,6 @@ static struct nfs_client *nfs_alloc_client(const struct nfs_client_initdata *cl_
143 clp->cl_proto = cl_init->proto; 143 clp->cl_proto = cl_init->proto;
144 144
145#ifdef CONFIG_NFS_V4 145#ifdef CONFIG_NFS_V4
146 init_rwsem(&clp->cl_sem);
147 INIT_LIST_HEAD(&clp->cl_delegations); 146 INIT_LIST_HEAD(&clp->cl_delegations);
148 spin_lock_init(&clp->cl_lock); 147 spin_lock_init(&clp->cl_lock);
149 INIT_DELAYED_WORK(&clp->cl_renewd, nfs4_renew_state); 148 INIT_DELAYED_WORK(&clp->cl_renewd, nfs4_renew_state);
@@ -224,31 +223,54 @@ void nfs_put_client(struct nfs_client *clp)
224 } 223 }
225} 224}
226 225
227static int nfs_sockaddr_match_ipaddr4(const struct sockaddr_in *sa1, 226#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
228 const struct sockaddr_in *sa2) 227static const struct in6_addr *nfs_map_ipv4_addr(const struct sockaddr *sa, struct in6_addr *addr_mapped)
229{ 228{
230 return sa1->sin_addr.s_addr == sa2->sin_addr.s_addr; 229 switch (sa->sa_family) {
230 default:
231 return NULL;
232 case AF_INET6:
233 return &((const struct sockaddr_in6 *)sa)->sin6_addr;
234 break;
235 case AF_INET:
236 ipv6_addr_set_v4mapped(((const struct sockaddr_in *)sa)->sin_addr.s_addr,
237 addr_mapped);
238 return addr_mapped;
239 }
231} 240}
232 241
233static int nfs_sockaddr_match_ipaddr6(const struct sockaddr_in6 *sa1, 242static int nfs_sockaddr_match_ipaddr(const struct sockaddr *sa1,
234 const struct sockaddr_in6 *sa2) 243 const struct sockaddr *sa2)
244{
245 const struct in6_addr *addr1;
246 const struct in6_addr *addr2;
247 struct in6_addr addr1_mapped;
248 struct in6_addr addr2_mapped;
249
250 addr1 = nfs_map_ipv4_addr(sa1, &addr1_mapped);
251 if (likely(addr1 != NULL)) {
252 addr2 = nfs_map_ipv4_addr(sa2, &addr2_mapped);
253 if (likely(addr2 != NULL))
254 return ipv6_addr_equal(addr1, addr2);
255 }
256 return 0;
257}
258#else
259static int nfs_sockaddr_match_ipaddr4(const struct sockaddr_in *sa1,
260 const struct sockaddr_in *sa2)
235{ 261{
236 return ipv6_addr_equal(&sa1->sin6_addr, &sa2->sin6_addr); 262 return sa1->sin_addr.s_addr == sa2->sin_addr.s_addr;
237} 263}
238 264
239static int nfs_sockaddr_match_ipaddr(const struct sockaddr *sa1, 265static int nfs_sockaddr_match_ipaddr(const struct sockaddr *sa1,
240 const struct sockaddr *sa2) 266 const struct sockaddr *sa2)
241{ 267{
242 switch (sa1->sa_family) { 268 if (unlikely(sa1->sa_family != AF_INET || sa2->sa_family != AF_INET))
243 case AF_INET: 269 return 0;
244 return nfs_sockaddr_match_ipaddr4((const struct sockaddr_in *)sa1, 270 return nfs_sockaddr_match_ipaddr4((const struct sockaddr_in *)sa1,
245 (const struct sockaddr_in *)sa2); 271 (const struct sockaddr_in *)sa2);
246 case AF_INET6:
247 return nfs_sockaddr_match_ipaddr6((const struct sockaddr_in6 *)sa1,
248 (const struct sockaddr_in6 *)sa2);
249 }
250 BUG();
251} 272}
273#endif
252 274
253/* 275/*
254 * Find a client by IP address and protocol version 276 * Find a client by IP address and protocol version
@@ -270,8 +292,6 @@ struct nfs_client *nfs_find_client(const struct sockaddr *addr, u32 nfsversion)
270 if (clp->rpc_ops->version != nfsversion) 292 if (clp->rpc_ops->version != nfsversion)
271 continue; 293 continue;
272 294
273 if (addr->sa_family != clap->sa_family)
274 continue;
275 /* Match only the IP address, not the port number */ 295 /* Match only the IP address, not the port number */
276 if (!nfs_sockaddr_match_ipaddr(addr, clap)) 296 if (!nfs_sockaddr_match_ipaddr(addr, clap))
277 continue; 297 continue;
@@ -305,8 +325,6 @@ struct nfs_client *nfs_find_client_next(struct nfs_client *clp)
305 if (clp->rpc_ops->version != nfsvers) 325 if (clp->rpc_ops->version != nfsvers)
306 continue; 326 continue;
307 327
308 if (sap->sa_family != clap->sa_family)
309 continue;
310 /* Match only the IP address, not the port number */ 328 /* Match only the IP address, not the port number */
311 if (!nfs_sockaddr_match_ipaddr(sap, clap)) 329 if (!nfs_sockaddr_match_ipaddr(sap, clap))
312 continue; 330 continue;
@@ -470,7 +488,7 @@ static void nfs_init_timeout_values(struct rpc_timeout *to, int proto,
470static int nfs_create_rpc_client(struct nfs_client *clp, 488static int nfs_create_rpc_client(struct nfs_client *clp,
471 const struct rpc_timeout *timeparms, 489 const struct rpc_timeout *timeparms,
472 rpc_authflavor_t flavor, 490 rpc_authflavor_t flavor,
473 int flags) 491 int discrtry, int noresvport)
474{ 492{
475 struct rpc_clnt *clnt = NULL; 493 struct rpc_clnt *clnt = NULL;
476 struct rpc_create_args args = { 494 struct rpc_create_args args = {
@@ -482,9 +500,13 @@ static int nfs_create_rpc_client(struct nfs_client *clp,
482 .program = &nfs_program, 500 .program = &nfs_program,
483 .version = clp->rpc_ops->version, 501 .version = clp->rpc_ops->version,
484 .authflavor = flavor, 502 .authflavor = flavor,
485 .flags = flags,
486 }; 503 };
487 504
505 if (discrtry)
506 args.flags |= RPC_CLNT_CREATE_DISCRTRY;
507 if (noresvport)
508 args.flags |= RPC_CLNT_CREATE_NONPRIVPORT;
509
488 if (!IS_ERR(clp->cl_rpcclient)) 510 if (!IS_ERR(clp->cl_rpcclient))
489 return 0; 511 return 0;
490 512
@@ -522,6 +544,8 @@ static int nfs_start_lockd(struct nfs_server *server)
522 .protocol = server->flags & NFS_MOUNT_TCP ? 544 .protocol = server->flags & NFS_MOUNT_TCP ?
523 IPPROTO_TCP : IPPROTO_UDP, 545 IPPROTO_TCP : IPPROTO_UDP,
524 .nfs_version = clp->rpc_ops->version, 546 .nfs_version = clp->rpc_ops->version,
547 .noresvport = server->flags & NFS_MOUNT_NORESVPORT ?
548 1 : 0,
525 }; 549 };
526 550
527 if (nlm_init.nfs_version > 3) 551 if (nlm_init.nfs_version > 3)
@@ -623,7 +647,8 @@ static int nfs_init_client(struct nfs_client *clp,
623 * Create a client RPC handle for doing FSSTAT with UNIX auth only 647 * Create a client RPC handle for doing FSSTAT with UNIX auth only
624 * - RFC 2623, sec 2.3.2 648 * - RFC 2623, sec 2.3.2
625 */ 649 */
626 error = nfs_create_rpc_client(clp, timeparms, RPC_AUTH_UNIX, 0); 650 error = nfs_create_rpc_client(clp, timeparms, RPC_AUTH_UNIX,
651 0, data->flags & NFS_MOUNT_NORESVPORT);
627 if (error < 0) 652 if (error < 0)
628 goto error; 653 goto error;
629 nfs_mark_client_ready(clp, NFS_CS_READY); 654 nfs_mark_client_ready(clp, NFS_CS_READY);
@@ -965,7 +990,8 @@ error:
965static int nfs4_init_client(struct nfs_client *clp, 990static int nfs4_init_client(struct nfs_client *clp,
966 const struct rpc_timeout *timeparms, 991 const struct rpc_timeout *timeparms,
967 const char *ip_addr, 992 const char *ip_addr,
968 rpc_authflavor_t authflavour) 993 rpc_authflavor_t authflavour,
994 int flags)
969{ 995{
970 int error; 996 int error;
971 997
@@ -979,7 +1005,7 @@ static int nfs4_init_client(struct nfs_client *clp,
979 clp->rpc_ops = &nfs_v4_clientops; 1005 clp->rpc_ops = &nfs_v4_clientops;
980 1006
981 error = nfs_create_rpc_client(clp, timeparms, authflavour, 1007 error = nfs_create_rpc_client(clp, timeparms, authflavour,
982 RPC_CLNT_CREATE_DISCRTRY); 1008 1, flags & NFS_MOUNT_NORESVPORT);
983 if (error < 0) 1009 if (error < 0)
984 goto error; 1010 goto error;
985 memcpy(clp->cl_ipaddr, ip_addr, sizeof(clp->cl_ipaddr)); 1011 memcpy(clp->cl_ipaddr, ip_addr, sizeof(clp->cl_ipaddr));
@@ -1030,7 +1056,8 @@ static int nfs4_set_client(struct nfs_server *server,
1030 error = PTR_ERR(clp); 1056 error = PTR_ERR(clp);
1031 goto error; 1057 goto error;
1032 } 1058 }
1033 error = nfs4_init_client(clp, timeparms, ip_addr, authflavour); 1059 error = nfs4_init_client(clp, timeparms, ip_addr, authflavour,
1060 server->flags);
1034 if (error < 0) 1061 if (error < 0)
1035 goto error_put; 1062 goto error_put;
1036 1063
@@ -1059,6 +1086,10 @@ static int nfs4_init_server(struct nfs_server *server,
1059 nfs_init_timeout_values(&timeparms, data->nfs_server.protocol, 1086 nfs_init_timeout_values(&timeparms, data->nfs_server.protocol,
1060 data->timeo, data->retrans); 1087 data->timeo, data->retrans);
1061 1088
1089 /* Initialise the client representation from the mount data */
1090 server->flags = data->flags;
1091 server->caps |= NFS_CAP_ATOMIC_OPEN;
1092
1062 /* Get a client record */ 1093 /* Get a client record */
1063 error = nfs4_set_client(server, 1094 error = nfs4_set_client(server,
1064 data->nfs_server.hostname, 1095 data->nfs_server.hostname,
@@ -1071,10 +1102,6 @@ static int nfs4_init_server(struct nfs_server *server,
1071 if (error < 0) 1102 if (error < 0)
1072 goto error; 1103 goto error;
1073 1104
1074 /* Initialise the client representation from the mount data */
1075 server->flags = data->flags;
1076 server->caps |= NFS_CAP_ATOMIC_OPEN;
1077
1078 if (data->rsize) 1105 if (data->rsize)
1079 server->rsize = nfs_block_size(data->rsize, NULL); 1106 server->rsize = nfs_block_size(data->rsize, NULL);
1080 if (data->wsize) 1107 if (data->wsize)
@@ -1177,6 +1204,10 @@ struct nfs_server *nfs4_create_referral_server(struct nfs_clone_mount *data,
1177 parent_server = NFS_SB(data->sb); 1204 parent_server = NFS_SB(data->sb);
1178 parent_client = parent_server->nfs_client; 1205 parent_client = parent_server->nfs_client;
1179 1206
1207 /* Initialise the client representation from the parent server */
1208 nfs_server_copy_userdata(server, parent_server);
1209 server->caps |= NFS_CAP_ATOMIC_OPEN;
1210
1180 /* Get a client representation. 1211 /* Get a client representation.
1181 * Note: NFSv4 always uses TCP, */ 1212 * Note: NFSv4 always uses TCP, */
1182 error = nfs4_set_client(server, data->hostname, 1213 error = nfs4_set_client(server, data->hostname,
@@ -1189,10 +1220,6 @@ struct nfs_server *nfs4_create_referral_server(struct nfs_clone_mount *data,
1189 if (error < 0) 1220 if (error < 0)
1190 goto error; 1221 goto error;
1191 1222
1192 /* Initialise the client representation from the parent server */
1193 nfs_server_copy_userdata(server, parent_server);
1194 server->caps |= NFS_CAP_ATOMIC_OPEN;
1195
1196 error = nfs_init_server_rpcclient(server, parent_server->client->cl_timeout, data->authflavor); 1223 error = nfs_init_server_rpcclient(server, parent_server->client->cl_timeout, data->authflavor);
1197 if (error < 0) 1224 if (error < 0)
1198 goto error; 1225 goto error;