aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfs/client.c
diff options
context:
space:
mode:
authorGlenn Elliott <gelliott@cs.unc.edu>2012-03-04 19:47:13 -0500
committerGlenn Elliott <gelliott@cs.unc.edu>2012-03-04 19:47:13 -0500
commitc71c03bda1e86c9d5198c5d83f712e695c4f2a1e (patch)
treeecb166cb3e2b7e2adb3b5e292245fefd23381ac8 /fs/nfs/client.c
parentea53c912f8a86a8567697115b6a0d8152beee5c8 (diff)
parent6a00f206debf8a5c8899055726ad127dbeeed098 (diff)
Merge branch 'mpi-master' into wip-k-fmlpwip-k-fmlp
Conflicts: litmus/sched_cedf.c
Diffstat (limited to 'fs/nfs/client.c')
-rw-r--r--fs/nfs/client.c458
1 files changed, 333 insertions, 125 deletions
diff --git a/fs/nfs/client.c b/fs/nfs/client.c
index e7340729af89..b3dc2b88b65b 100644
--- a/fs/nfs/client.c
+++ b/fs/nfs/client.c
@@ -48,6 +48,7 @@
48#include "iostat.h" 48#include "iostat.h"
49#include "internal.h" 49#include "internal.h"
50#include "fscache.h" 50#include "fscache.h"
51#include "pnfs.h"
51 52
52#define NFSDBG_FACILITY NFSDBG_CLIENT 53#define NFSDBG_FACILITY NFSDBG_CLIENT
53 54
@@ -55,6 +56,35 @@ static DEFINE_SPINLOCK(nfs_client_lock);
55static LIST_HEAD(nfs_client_list); 56static LIST_HEAD(nfs_client_list);
56static LIST_HEAD(nfs_volume_list); 57static LIST_HEAD(nfs_volume_list);
57static DECLARE_WAIT_QUEUE_HEAD(nfs_client_active_wq); 58static DECLARE_WAIT_QUEUE_HEAD(nfs_client_active_wq);
59#ifdef CONFIG_NFS_V4
60static DEFINE_IDR(cb_ident_idr); /* Protected by nfs_client_lock */
61
62/*
63 * Get a unique NFSv4.0 callback identifier which will be used
64 * by the V4.0 callback service to lookup the nfs_client struct
65 */
66static int nfs_get_cb_ident_idr(struct nfs_client *clp, int minorversion)
67{
68 int ret = 0;
69
70 if (clp->rpc_ops->version != 4 || minorversion != 0)
71 return ret;
72retry:
73 if (!idr_pre_get(&cb_ident_idr, GFP_KERNEL))
74 return -ENOMEM;
75 spin_lock(&nfs_client_lock);
76 ret = idr_get_new(&cb_ident_idr, clp, &clp->cl_cb_ident);
77 spin_unlock(&nfs_client_lock);
78 if (ret == -EAGAIN)
79 goto retry;
80 return ret;
81}
82#endif /* CONFIG_NFS_V4 */
83
84/*
85 * Turn off NFSv4 uid/gid mapping when using AUTH_SYS
86 */
87static int nfs4_disable_idmapping = 0;
58 88
59/* 89/*
60 * RPC cruft for NFS 90 * RPC cruft for NFS
@@ -143,7 +173,10 @@ static struct nfs_client *nfs_alloc_client(const struct nfs_client_initdata *cl_
143 clp->cl_proto = cl_init->proto; 173 clp->cl_proto = cl_init->proto;
144 174
145#ifdef CONFIG_NFS_V4 175#ifdef CONFIG_NFS_V4
146 INIT_LIST_HEAD(&clp->cl_delegations); 176 err = nfs_get_cb_ident_idr(clp, cl_init->minorversion);
177 if (err)
178 goto error_cleanup;
179
147 spin_lock_init(&clp->cl_lock); 180 spin_lock_init(&clp->cl_lock);
148 INIT_DELAYED_WORK(&clp->cl_renewd, nfs4_renew_state); 181 INIT_DELAYED_WORK(&clp->cl_renewd, nfs4_renew_state);
149 rpc_init_wait_queue(&clp->cl_rpcwaitq, "NFS client"); 182 rpc_init_wait_queue(&clp->cl_rpcwaitq, "NFS client");
@@ -155,7 +188,9 @@ static struct nfs_client *nfs_alloc_client(const struct nfs_client_initdata *cl_
155 cred = rpc_lookup_machine_cred(); 188 cred = rpc_lookup_machine_cred();
156 if (!IS_ERR(cred)) 189 if (!IS_ERR(cred))
157 clp->cl_machine_cred = cred; 190 clp->cl_machine_cred = cred;
158 191#if defined(CONFIG_NFS_V4_1)
192 INIT_LIST_HEAD(&clp->cl_layouts);
193#endif
159 nfs_fscache_get_client_cookie(clp); 194 nfs_fscache_get_client_cookie(clp);
160 195
161 return clp; 196 return clp;
@@ -167,21 +202,17 @@ error_0:
167} 202}
168 203
169#ifdef CONFIG_NFS_V4 204#ifdef CONFIG_NFS_V4
170/*
171 * Clears/puts all minor version specific parts from an nfs_client struct
172 * reverting it to minorversion 0.
173 */
174static void nfs4_clear_client_minor_version(struct nfs_client *clp)
175{
176#ifdef CONFIG_NFS_V4_1 205#ifdef CONFIG_NFS_V4_1
177 if (nfs4_has_session(clp)) { 206static void nfs4_shutdown_session(struct nfs_client *clp)
207{
208 if (nfs4_has_session(clp))
178 nfs4_destroy_session(clp->cl_session); 209 nfs4_destroy_session(clp->cl_session);
179 clp->cl_session = NULL;
180 }
181
182 clp->cl_mvops = nfs_v4_minor_ops[0];
183#endif /* CONFIG_NFS_V4_1 */
184} 210}
211#else /* CONFIG_NFS_V4_1 */
212static void nfs4_shutdown_session(struct nfs_client *clp)
213{
214}
215#endif /* CONFIG_NFS_V4_1 */
185 216
186/* 217/*
187 * Destroy the NFS4 callback service 218 * Destroy the NFS4 callback service
@@ -196,17 +227,49 @@ static void nfs4_shutdown_client(struct nfs_client *clp)
196{ 227{
197 if (__test_and_clear_bit(NFS_CS_RENEWD, &clp->cl_res_state)) 228 if (__test_and_clear_bit(NFS_CS_RENEWD, &clp->cl_res_state))
198 nfs4_kill_renewd(clp); 229 nfs4_kill_renewd(clp);
199 nfs4_clear_client_minor_version(clp); 230 nfs4_shutdown_session(clp);
200 nfs4_destroy_callback(clp); 231 nfs4_destroy_callback(clp);
201 if (__test_and_clear_bit(NFS_CS_IDMAP, &clp->cl_res_state)) 232 if (__test_and_clear_bit(NFS_CS_IDMAP, &clp->cl_res_state))
202 nfs_idmap_delete(clp); 233 nfs_idmap_delete(clp);
203 234
204 rpc_destroy_wait_queue(&clp->cl_rpcwaitq); 235 rpc_destroy_wait_queue(&clp->cl_rpcwaitq);
205} 236}
237
238/* idr_remove_all is not needed as all id's are removed by nfs_put_client */
239void nfs_cleanup_cb_ident_idr(void)
240{
241 idr_destroy(&cb_ident_idr);
242}
243
244/* nfs_client_lock held */
245static void nfs_cb_idr_remove_locked(struct nfs_client *clp)
246{
247 if (clp->cl_cb_ident)
248 idr_remove(&cb_ident_idr, clp->cl_cb_ident);
249}
250
251static void pnfs_init_server(struct nfs_server *server)
252{
253 rpc_init_wait_queue(&server->roc_rpcwaitq, "pNFS ROC");
254}
255
206#else 256#else
207static void nfs4_shutdown_client(struct nfs_client *clp) 257static void nfs4_shutdown_client(struct nfs_client *clp)
208{ 258{
209} 259}
260
261void nfs_cleanup_cb_ident_idr(void)
262{
263}
264
265static void nfs_cb_idr_remove_locked(struct nfs_client *clp)
266{
267}
268
269static void pnfs_init_server(struct nfs_server *server)
270{
271}
272
210#endif /* CONFIG_NFS_V4 */ 273#endif /* CONFIG_NFS_V4 */
211 274
212/* 275/*
@@ -227,6 +290,8 @@ static void nfs_free_client(struct nfs_client *clp)
227 if (clp->cl_machine_cred != NULL) 290 if (clp->cl_machine_cred != NULL)
228 put_rpccred(clp->cl_machine_cred); 291 put_rpccred(clp->cl_machine_cred);
229 292
293 nfs4_deviceid_purge_client(clp);
294
230 kfree(clp->cl_hostname); 295 kfree(clp->cl_hostname);
231 kfree(clp); 296 kfree(clp);
232 297
@@ -245,6 +310,7 @@ void nfs_put_client(struct nfs_client *clp)
245 310
246 if (atomic_dec_and_lock(&clp->cl_count, &nfs_client_lock)) { 311 if (atomic_dec_and_lock(&clp->cl_count, &nfs_client_lock)) {
247 list_del(&clp->cl_share_link); 312 list_del(&clp->cl_share_link);
313 nfs_cb_idr_remove_locked(clp);
248 spin_unlock(&nfs_client_lock); 314 spin_unlock(&nfs_client_lock);
249 315
250 BUG_ON(!list_empty(&clp->cl_superblocks)); 316 BUG_ON(!list_empty(&clp->cl_superblocks));
@@ -252,6 +318,7 @@ void nfs_put_client(struct nfs_client *clp)
252 nfs_free_client(clp); 318 nfs_free_client(clp);
253 } 319 }
254} 320}
321EXPORT_SYMBOL_GPL(nfs_put_client);
255 322
256#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) 323#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
257/* 324/*
@@ -359,70 +426,28 @@ static int nfs_sockaddr_cmp(const struct sockaddr *sa1,
359 return 0; 426 return 0;
360} 427}
361 428
362/* 429/* Common match routine for v4.0 and v4.1 callback services */
363 * Find a client by IP address and protocol version 430bool
364 * - returns NULL if no such client 431nfs4_cb_match_client(const struct sockaddr *addr, struct nfs_client *clp,
365 */ 432 u32 minorversion)
366struct nfs_client *nfs_find_client(const struct sockaddr *addr, u32 nfsversion)
367{ 433{
368 struct nfs_client *clp; 434 struct sockaddr *clap = (struct sockaddr *)&clp->cl_addr;
369 435
370 spin_lock(&nfs_client_lock); 436 /* Don't match clients that failed to initialise */
371 list_for_each_entry(clp, &nfs_client_list, cl_share_link) { 437 if (!(clp->cl_cons_state == NFS_CS_READY ||
372 struct sockaddr *clap = (struct sockaddr *)&clp->cl_addr; 438 clp->cl_cons_state == NFS_CS_SESSION_INITING))
439 return false;
373 440
374 /* Don't match clients that failed to initialise properly */ 441 /* Match the version and minorversion */
375 if (!(clp->cl_cons_state == NFS_CS_READY || 442 if (clp->rpc_ops->version != 4 ||
376 clp->cl_cons_state == NFS_CS_SESSION_INITING)) 443 clp->cl_minorversion != minorversion)
377 continue; 444 return false;
378 445
379 /* Different NFS versions cannot share the same nfs_client */ 446 /* Match only the IP address, not the port number */
380 if (clp->rpc_ops->version != nfsversion) 447 if (!nfs_sockaddr_match_ipaddr(addr, clap))
381 continue; 448 return false;
382
383 /* Match only the IP address, not the port number */
384 if (!nfs_sockaddr_match_ipaddr(addr, clap))
385 continue;
386 449
387 atomic_inc(&clp->cl_count); 450 return true;
388 spin_unlock(&nfs_client_lock);
389 return clp;
390 }
391 spin_unlock(&nfs_client_lock);
392 return NULL;
393}
394
395/*
396 * Find a client by IP address and protocol version
397 * - returns NULL if no such client
398 */
399struct nfs_client *nfs_find_client_next(struct nfs_client *clp)
400{
401 struct sockaddr *sap = (struct sockaddr *)&clp->cl_addr;
402 u32 nfsvers = clp->rpc_ops->version;
403
404 spin_lock(&nfs_client_lock);
405 list_for_each_entry_continue(clp, &nfs_client_list, cl_share_link) {
406 struct sockaddr *clap = (struct sockaddr *)&clp->cl_addr;
407
408 /* Don't match clients that failed to initialise properly */
409 if (clp->cl_cons_state != NFS_CS_READY)
410 continue;
411
412 /* Different NFS versions cannot share the same nfs_client */
413 if (clp->rpc_ops->version != nfsvers)
414 continue;
415
416 /* Match only the IP address, not the port number */
417 if (!nfs_sockaddr_match_ipaddr(sap, clap))
418 continue;
419
420 atomic_inc(&clp->cl_count);
421 spin_unlock(&nfs_client_lock);
422 return clp;
423 }
424 spin_unlock(&nfs_client_lock);
425 return NULL;
426} 451}
427 452
428/* 453/*
@@ -463,7 +488,12 @@ static struct nfs_client *nfs_match_client(const struct nfs_client_initdata *dat
463 * Look up a client by IP address and protocol version 488 * Look up a client by IP address and protocol version
464 * - creates a new record if one doesn't yet exist 489 * - creates a new record if one doesn't yet exist
465 */ 490 */
466static struct nfs_client *nfs_get_client(const struct nfs_client_initdata *cl_init) 491static struct nfs_client *
492nfs_get_client(const struct nfs_client_initdata *cl_init,
493 const struct rpc_timeout *timeparms,
494 const char *ip_addr,
495 rpc_authflavor_t authflavour,
496 int noresvport)
467{ 497{
468 struct nfs_client *clp, *new = NULL; 498 struct nfs_client *clp, *new = NULL;
469 int error; 499 int error;
@@ -494,6 +524,13 @@ install_client:
494 clp = new; 524 clp = new;
495 list_add(&clp->cl_share_link, &nfs_client_list); 525 list_add(&clp->cl_share_link, &nfs_client_list);
496 spin_unlock(&nfs_client_lock); 526 spin_unlock(&nfs_client_lock);
527
528 error = cl_init->rpc_ops->init_client(clp, timeparms, ip_addr,
529 authflavour, noresvport);
530 if (error < 0) {
531 nfs_put_client(clp);
532 return ERR_PTR(error);
533 }
497 dprintk("--> nfs_get_client() = %p [new]\n", clp); 534 dprintk("--> nfs_get_client() = %p [new]\n", clp);
498 return clp; 535 return clp;
499 536
@@ -601,6 +638,7 @@ static int nfs_create_rpc_client(struct nfs_client *clp,
601{ 638{
602 struct rpc_clnt *clnt = NULL; 639 struct rpc_clnt *clnt = NULL;
603 struct rpc_create_args args = { 640 struct rpc_create_args args = {
641 .net = &init_net,
604 .protocol = clp->cl_proto, 642 .protocol = clp->cl_proto,
605 .address = (struct sockaddr *)&clp->cl_addr, 643 .address = (struct sockaddr *)&clp->cl_addr,
606 .addrsize = clp->cl_addrlen, 644 .addrsize = clp->cl_addrlen,
@@ -635,7 +673,8 @@ static int nfs_create_rpc_client(struct nfs_client *clp,
635 */ 673 */
636static void nfs_destroy_server(struct nfs_server *server) 674static void nfs_destroy_server(struct nfs_server *server)
637{ 675{
638 if (!(server->flags & NFS_MOUNT_NONLM)) 676 if (!(server->flags & NFS_MOUNT_LOCAL_FLOCK) ||
677 !(server->flags & NFS_MOUNT_LOCAL_FCNTL))
639 nlmclnt_done(server->nlm_host); 678 nlmclnt_done(server->nlm_host);
640} 679}
641 680
@@ -657,7 +696,8 @@ static int nfs_start_lockd(struct nfs_server *server)
657 696
658 if (nlm_init.nfs_version > 3) 697 if (nlm_init.nfs_version > 3)
659 return 0; 698 return 0;
660 if (server->flags & NFS_MOUNT_NONLM) 699 if ((server->flags & NFS_MOUNT_LOCAL_FLOCK) &&
700 (server->flags & NFS_MOUNT_LOCAL_FCNTL))
661 return 0; 701 return 0;
662 702
663 switch (clp->cl_proto) { 703 switch (clp->cl_proto) {
@@ -746,9 +786,9 @@ static int nfs_init_server_rpcclient(struct nfs_server *server,
746/* 786/*
747 * Initialise an NFS2 or NFS3 client 787 * Initialise an NFS2 or NFS3 client
748 */ 788 */
749static int nfs_init_client(struct nfs_client *clp, 789int nfs_init_client(struct nfs_client *clp, const struct rpc_timeout *timeparms,
750 const struct rpc_timeout *timeparms, 790 const char *ip_addr, rpc_authflavor_t authflavour,
751 const struct nfs_parsed_mount_data *data) 791 int noresvport)
752{ 792{
753 int error; 793 int error;
754 794
@@ -763,7 +803,7 @@ static int nfs_init_client(struct nfs_client *clp,
763 * - RFC 2623, sec 2.3.2 803 * - RFC 2623, sec 2.3.2
764 */ 804 */
765 error = nfs_create_rpc_client(clp, timeparms, RPC_AUTH_UNIX, 805 error = nfs_create_rpc_client(clp, timeparms, RPC_AUTH_UNIX,
766 0, data->flags & NFS_MOUNT_NORESVPORT); 806 0, noresvport);
767 if (error < 0) 807 if (error < 0)
768 goto error; 808 goto error;
769 nfs_mark_client_ready(clp, NFS_CS_READY); 809 nfs_mark_client_ready(clp, NFS_CS_READY);
@@ -799,19 +839,17 @@ static int nfs_init_server(struct nfs_server *server,
799 cl_init.rpc_ops = &nfs_v3_clientops; 839 cl_init.rpc_ops = &nfs_v3_clientops;
800#endif 840#endif
801 841
842 nfs_init_timeout_values(&timeparms, data->nfs_server.protocol,
843 data->timeo, data->retrans);
844
802 /* Allocate or find a client reference we can use */ 845 /* Allocate or find a client reference we can use */
803 clp = nfs_get_client(&cl_init); 846 clp = nfs_get_client(&cl_init, &timeparms, NULL, RPC_AUTH_UNIX,
847 data->flags & NFS_MOUNT_NORESVPORT);
804 if (IS_ERR(clp)) { 848 if (IS_ERR(clp)) {
805 dprintk("<-- nfs_init_server() = error %ld\n", PTR_ERR(clp)); 849 dprintk("<-- nfs_init_server() = error %ld\n", PTR_ERR(clp));
806 return PTR_ERR(clp); 850 return PTR_ERR(clp);
807 } 851 }
808 852
809 nfs_init_timeout_values(&timeparms, data->nfs_server.protocol,
810 data->timeo, data->retrans);
811 error = nfs_init_client(clp, &timeparms, data);
812 if (error < 0)
813 goto error;
814
815 server->nfs_client = clp; 853 server->nfs_client = clp;
816 854
817 /* Initialise the client representation from the mount data */ 855 /* Initialise the client representation from the mount data */
@@ -898,11 +936,13 @@ static void nfs_server_set_fsinfo(struct nfs_server *server, struct nfs_fsinfo *
898 if (server->wsize > NFS_MAX_FILE_IO_SIZE) 936 if (server->wsize > NFS_MAX_FILE_IO_SIZE)
899 server->wsize = NFS_MAX_FILE_IO_SIZE; 937 server->wsize = NFS_MAX_FILE_IO_SIZE;
900 server->wpages = (server->wsize + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT; 938 server->wpages = (server->wsize + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;
939 set_pnfs_layoutdriver(server, fsinfo->layouttype);
940
901 server->wtmult = nfs_block_bits(fsinfo->wtmult, NULL); 941 server->wtmult = nfs_block_bits(fsinfo->wtmult, NULL);
902 942
903 server->dtsize = nfs_block_size(fsinfo->dtpref, NULL); 943 server->dtsize = nfs_block_size(fsinfo->dtpref, NULL);
904 if (server->dtsize > PAGE_CACHE_SIZE) 944 if (server->dtsize > PAGE_CACHE_SIZE * NFS_MAX_READDIR_PAGES)
905 server->dtsize = PAGE_CACHE_SIZE; 945 server->dtsize = PAGE_CACHE_SIZE * NFS_MAX_READDIR_PAGES;
906 if (server->dtsize > server->rsize) 946 if (server->dtsize > server->rsize)
907 server->dtsize = server->rsize; 947 server->dtsize = server->rsize;
908 948
@@ -913,6 +953,8 @@ static void nfs_server_set_fsinfo(struct nfs_server *server, struct nfs_fsinfo *
913 953
914 server->maxfilesize = fsinfo->maxfilesize; 954 server->maxfilesize = fsinfo->maxfilesize;
915 955
956 server->time_delta = fsinfo->time_delta;
957
916 /* We're airborne Set socket buffersize */ 958 /* We're airborne Set socket buffersize */
917 rpc_setbufsize(server->client, server->wsize + 100, server->rsize + 100); 959 rpc_setbufsize(server->client, server->wsize + 100, server->rsize + 100);
918} 960}
@@ -935,6 +977,7 @@ static int nfs_probe_fsinfo(struct nfs_server *server, struct nfs_fh *mntfh, str
935 } 977 }
936 978
937 fsinfo.fattr = fattr; 979 fsinfo.fattr = fattr;
980 fsinfo.layouttype = 0;
938 error = clp->rpc_ops->fsinfo(server, mntfh, &fsinfo); 981 error = clp->rpc_ops->fsinfo(server, mntfh, &fsinfo);
939 if (error < 0) 982 if (error < 0)
940 goto out_error; 983 goto out_error;
@@ -976,6 +1019,32 @@ static void nfs_server_copy_userdata(struct nfs_server *target, struct nfs_serve
976 target->options = source->options; 1019 target->options = source->options;
977} 1020}
978 1021
1022static void nfs_server_insert_lists(struct nfs_server *server)
1023{
1024 struct nfs_client *clp = server->nfs_client;
1025
1026 spin_lock(&nfs_client_lock);
1027 list_add_tail_rcu(&server->client_link, &clp->cl_superblocks);
1028 list_add_tail(&server->master_link, &nfs_volume_list);
1029 clear_bit(NFS_CS_STOP_RENEW, &clp->cl_res_state);
1030 spin_unlock(&nfs_client_lock);
1031
1032}
1033
1034static void nfs_server_remove_lists(struct nfs_server *server)
1035{
1036 struct nfs_client *clp = server->nfs_client;
1037
1038 spin_lock(&nfs_client_lock);
1039 list_del_rcu(&server->client_link);
1040 if (clp && list_empty(&clp->cl_superblocks))
1041 set_bit(NFS_CS_STOP_RENEW, &clp->cl_res_state);
1042 list_del(&server->master_link);
1043 spin_unlock(&nfs_client_lock);
1044
1045 synchronize_rcu();
1046}
1047
979/* 1048/*
980 * Allocate and initialise a server record 1049 * Allocate and initialise a server record
981 */ 1050 */
@@ -992,6 +1061,7 @@ static struct nfs_server *nfs_alloc_server(void)
992 /* Zero out the NFS state stuff */ 1061 /* Zero out the NFS state stuff */
993 INIT_LIST_HEAD(&server->client_link); 1062 INIT_LIST_HEAD(&server->client_link);
994 INIT_LIST_HEAD(&server->master_link); 1063 INIT_LIST_HEAD(&server->master_link);
1064 INIT_LIST_HEAD(&server->delegations);
995 1065
996 atomic_set(&server->active, 0); 1066 atomic_set(&server->active, 0);
997 1067
@@ -1007,6 +1077,8 @@ static struct nfs_server *nfs_alloc_server(void)
1007 return NULL; 1077 return NULL;
1008 } 1078 }
1009 1079
1080 pnfs_init_server(server);
1081
1010 return server; 1082 return server;
1011} 1083}
1012 1084
@@ -1017,10 +1089,8 @@ void nfs_free_server(struct nfs_server *server)
1017{ 1089{
1018 dprintk("--> nfs_free_server()\n"); 1090 dprintk("--> nfs_free_server()\n");
1019 1091
1020 spin_lock(&nfs_client_lock); 1092 nfs_server_remove_lists(server);
1021 list_del(&server->client_link); 1093 unset_pnfs_layoutdriver(server);
1022 list_del(&server->master_link);
1023 spin_unlock(&nfs_client_lock);
1024 1094
1025 if (server->destroy != NULL) 1095 if (server->destroy != NULL)
1026 server->destroy(server); 1096 server->destroy(server);
@@ -1095,11 +1165,7 @@ struct nfs_server *nfs_create_server(const struct nfs_parsed_mount_data *data,
1095 (unsigned long long) server->fsid.major, 1165 (unsigned long long) server->fsid.major,
1096 (unsigned long long) server->fsid.minor); 1166 (unsigned long long) server->fsid.minor);
1097 1167
1098 spin_lock(&nfs_client_lock); 1168 nfs_server_insert_lists(server);
1099 list_add_tail(&server->client_link, &server->nfs_client->cl_superblocks);
1100 list_add_tail(&server->master_link, &nfs_volume_list);
1101 spin_unlock(&nfs_client_lock);
1102
1103 server->mount_time = jiffies; 1169 server->mount_time = jiffies;
1104 nfs_free_fattr(fattr); 1170 nfs_free_fattr(fattr);
1105 return server; 1171 return server;
@@ -1112,6 +1178,96 @@ error:
1112 1178
1113#ifdef CONFIG_NFS_V4 1179#ifdef CONFIG_NFS_V4
1114/* 1180/*
1181 * NFSv4.0 callback thread helper
1182 *
1183 * Find a client by IP address, protocol version, and minorversion
1184 *
1185 * Called from the pg_authenticate method. The callback identifier
1186 * is not used as it has not been decoded.
1187 *
1188 * Returns NULL if no such client
1189 */
1190struct nfs_client *
1191nfs4_find_client_no_ident(const struct sockaddr *addr)
1192{
1193 struct nfs_client *clp;
1194
1195 spin_lock(&nfs_client_lock);
1196 list_for_each_entry(clp, &nfs_client_list, cl_share_link) {
1197 if (nfs4_cb_match_client(addr, clp, 0) == false)
1198 continue;
1199 atomic_inc(&clp->cl_count);
1200 spin_unlock(&nfs_client_lock);
1201 return clp;
1202 }
1203 spin_unlock(&nfs_client_lock);
1204 return NULL;
1205}
1206
1207/*
1208 * NFSv4.0 callback thread helper
1209 *
1210 * Find a client by callback identifier
1211 */
1212struct nfs_client *
1213nfs4_find_client_ident(int cb_ident)
1214{
1215 struct nfs_client *clp;
1216
1217 spin_lock(&nfs_client_lock);
1218 clp = idr_find(&cb_ident_idr, cb_ident);
1219 if (clp)
1220 atomic_inc(&clp->cl_count);
1221 spin_unlock(&nfs_client_lock);
1222 return clp;
1223}
1224
1225#if defined(CONFIG_NFS_V4_1)
1226/*
1227 * NFSv4.1 callback thread helper
1228 * For CB_COMPOUND calls, find a client by IP address, protocol version,
1229 * minorversion, and sessionID
1230 *
1231 * Returns NULL if no such client
1232 */
1233struct nfs_client *
1234nfs4_find_client_sessionid(const struct sockaddr *addr,
1235 struct nfs4_sessionid *sid)
1236{
1237 struct nfs_client *clp;
1238
1239 spin_lock(&nfs_client_lock);
1240 list_for_each_entry(clp, &nfs_client_list, cl_share_link) {
1241 if (nfs4_cb_match_client(addr, clp, 1) == false)
1242 continue;
1243
1244 if (!nfs4_has_session(clp))
1245 continue;
1246
1247 /* Match sessionid*/
1248 if (memcmp(clp->cl_session->sess_id.data,
1249 sid->data, NFS4_MAX_SESSIONID_LEN) != 0)
1250 continue;
1251
1252 atomic_inc(&clp->cl_count);
1253 spin_unlock(&nfs_client_lock);
1254 return clp;
1255 }
1256 spin_unlock(&nfs_client_lock);
1257 return NULL;
1258}
1259
1260#else /* CONFIG_NFS_V4_1 */
1261
1262struct nfs_client *
1263nfs4_find_client_sessionid(const struct sockaddr *addr,
1264 struct nfs4_sessionid *sid)
1265{
1266 return NULL;
1267}
1268#endif /* CONFIG_NFS_V4_1 */
1269
1270/*
1115 * Initialize the NFS4 callback service 1271 * Initialize the NFS4 callback service
1116 */ 1272 */
1117static int nfs4_init_callback(struct nfs_client *clp) 1273static int nfs4_init_callback(struct nfs_client *clp)
@@ -1173,11 +1329,11 @@ static int nfs4_init_client_minor_version(struct nfs_client *clp)
1173/* 1329/*
1174 * Initialise an NFS4 client record 1330 * Initialise an NFS4 client record
1175 */ 1331 */
1176static int nfs4_init_client(struct nfs_client *clp, 1332int nfs4_init_client(struct nfs_client *clp,
1177 const struct rpc_timeout *timeparms, 1333 const struct rpc_timeout *timeparms,
1178 const char *ip_addr, 1334 const char *ip_addr,
1179 rpc_authflavor_t authflavour, 1335 rpc_authflavor_t authflavour,
1180 int flags) 1336 int noresvport)
1181{ 1337{
1182 int error; 1338 int error;
1183 1339
@@ -1191,7 +1347,7 @@ static int nfs4_init_client(struct nfs_client *clp,
1191 clp->rpc_ops = &nfs_v4_clientops; 1347 clp->rpc_ops = &nfs_v4_clientops;
1192 1348
1193 error = nfs_create_rpc_client(clp, timeparms, authflavour, 1349 error = nfs_create_rpc_client(clp, timeparms, authflavour,
1194 1, flags & NFS_MOUNT_NORESVPORT); 1350 1, noresvport);
1195 if (error < 0) 1351 if (error < 0)
1196 goto error; 1352 goto error;
1197 strlcpy(clp->cl_ipaddr, ip_addr, sizeof(clp->cl_ipaddr)); 1353 strlcpy(clp->cl_ipaddr, ip_addr, sizeof(clp->cl_ipaddr));
@@ -1244,27 +1400,71 @@ static int nfs4_set_client(struct nfs_server *server,
1244 dprintk("--> nfs4_set_client()\n"); 1400 dprintk("--> nfs4_set_client()\n");
1245 1401
1246 /* Allocate or find a client reference we can use */ 1402 /* Allocate or find a client reference we can use */
1247 clp = nfs_get_client(&cl_init); 1403 clp = nfs_get_client(&cl_init, timeparms, ip_addr, authflavour,
1404 server->flags & NFS_MOUNT_NORESVPORT);
1248 if (IS_ERR(clp)) { 1405 if (IS_ERR(clp)) {
1249 error = PTR_ERR(clp); 1406 error = PTR_ERR(clp);
1250 goto error; 1407 goto error;
1251 } 1408 }
1252 error = nfs4_init_client(clp, timeparms, ip_addr, authflavour, 1409
1253 server->flags); 1410 /*
1254 if (error < 0) 1411 * Query for the lease time on clientid setup or renewal
1255 goto error_put; 1412 *
1413 * Note that this will be set on nfs_clients that were created
1414 * only for the DS role and did not set this bit, but now will
1415 * serve a dual role.
1416 */
1417 set_bit(NFS_CS_CHECK_LEASE_TIME, &clp->cl_res_state);
1256 1418
1257 server->nfs_client = clp; 1419 server->nfs_client = clp;
1258 dprintk("<-- nfs4_set_client() = 0 [new %p]\n", clp); 1420 dprintk("<-- nfs4_set_client() = 0 [new %p]\n", clp);
1259 return 0; 1421 return 0;
1260
1261error_put:
1262 nfs_put_client(clp);
1263error: 1422error:
1264 dprintk("<-- nfs4_set_client() = xerror %d\n", error); 1423 dprintk("<-- nfs4_set_client() = xerror %d\n", error);
1265 return error; 1424 return error;
1266} 1425}
1267 1426
1427/*
1428 * Set up a pNFS Data Server client.
1429 *
1430 * Return any existing nfs_client that matches server address,port,version
1431 * and minorversion.
1432 *
1433 * For a new nfs_client, use a soft mount (default), a low retrans and a
1434 * low timeout interval so that if a connection is lost, we retry through
1435 * the MDS.
1436 */
1437struct nfs_client *nfs4_set_ds_client(struct nfs_client* mds_clp,
1438 const struct sockaddr *ds_addr,
1439 int ds_addrlen, int ds_proto)
1440{
1441 struct nfs_client_initdata cl_init = {
1442 .addr = ds_addr,
1443 .addrlen = ds_addrlen,
1444 .rpc_ops = &nfs_v4_clientops,
1445 .proto = ds_proto,
1446 .minorversion = mds_clp->cl_minorversion,
1447 };
1448 struct rpc_timeout ds_timeout = {
1449 .to_initval = 15 * HZ,
1450 .to_maxval = 15 * HZ,
1451 .to_retries = 1,
1452 .to_exponential = 1,
1453 };
1454 struct nfs_client *clp;
1455
1456 /*
1457 * Set an authflavor equual to the MDS value. Use the MDS nfs_client
1458 * cl_ipaddr so as to use the same EXCHANGE_ID co_ownerid as the MDS
1459 * (section 13.1 RFC 5661).
1460 */
1461 clp = nfs_get_client(&cl_init, &ds_timeout, mds_clp->cl_ipaddr,
1462 mds_clp->cl_rpcclient->cl_auth->au_flavor, 0);
1463
1464 dprintk("<-- %s %p\n", __func__, clp);
1465 return clp;
1466}
1467EXPORT_SYMBOL(nfs4_set_ds_client);
1268 1468
1269/* 1469/*
1270 * Session has been established, and the client marked ready. 1470 * Session has been established, and the client marked ready.
@@ -1301,6 +1501,10 @@ static int nfs4_server_common_setup(struct nfs_server *server,
1301 BUG_ON(!server->nfs_client->rpc_ops); 1501 BUG_ON(!server->nfs_client->rpc_ops);
1302 BUG_ON(!server->nfs_client->rpc_ops->file_inode_ops); 1502 BUG_ON(!server->nfs_client->rpc_ops->file_inode_ops);
1303 1503
1504 /* data servers support only a subset of NFSv4.1 */
1505 if (is_ds_only_client(server->nfs_client))
1506 return -EPROTONOSUPPORT;
1507
1304 fattr = nfs_alloc_fattr(); 1508 fattr = nfs_alloc_fattr();
1305 if (fattr == NULL) 1509 if (fattr == NULL)
1306 return -ENOMEM; 1510 return -ENOMEM;
@@ -1329,11 +1533,7 @@ static int nfs4_server_common_setup(struct nfs_server *server,
1329 if (server->namelen == 0 || server->namelen > NFS4_MAXNAMLEN) 1533 if (server->namelen == 0 || server->namelen > NFS4_MAXNAMLEN)
1330 server->namelen = NFS4_MAXNAMLEN; 1534 server->namelen = NFS4_MAXNAMLEN;
1331 1535
1332 spin_lock(&nfs_client_lock); 1536 nfs_server_insert_lists(server);
1333 list_add_tail(&server->client_link, &server->nfs_client->cl_superblocks);
1334 list_add_tail(&server->master_link, &nfs_volume_list);
1335 spin_unlock(&nfs_client_lock);
1336
1337 server->mount_time = jiffies; 1537 server->mount_time = jiffies;
1338out: 1538out:
1339 nfs_free_fattr(fattr); 1539 nfs_free_fattr(fattr);
@@ -1356,8 +1556,9 @@ static int nfs4_init_server(struct nfs_server *server,
1356 1556
1357 /* Initialise the client representation from the mount data */ 1557 /* Initialise the client representation from the mount data */
1358 server->flags = data->flags; 1558 server->flags = data->flags;
1359 server->caps |= NFS_CAP_ATOMIC_OPEN|NFS_CAP_CHANGE_ATTR| 1559 server->caps |= NFS_CAP_ATOMIC_OPEN|NFS_CAP_CHANGE_ATTR|NFS_CAP_POSIX_LOCK;
1360 NFS_CAP_POSIX_LOCK; 1560 if (!(data->flags & NFS_MOUNT_NORDIRPLUS))
1561 server->caps |= NFS_CAP_READDIRPLUS;
1361 server->options = data->options; 1562 server->options = data->options;
1362 1563
1363 /* Get a client record */ 1564 /* Get a client record */
@@ -1373,6 +1574,13 @@ static int nfs4_init_server(struct nfs_server *server,
1373 if (error < 0) 1574 if (error < 0)
1374 goto error; 1575 goto error;
1375 1576
1577 /*
1578 * Don't use NFS uid/gid mapping if we're using AUTH_SYS or lower
1579 * authentication.
1580 */
1581 if (nfs4_disable_idmapping && data->auth_flavors[0] == RPC_AUTH_UNIX)
1582 server->caps |= NFS_CAP_UIDGID_NOMAP;
1583
1376 if (data->rsize) 1584 if (data->rsize)
1377 server->rsize = nfs_block_size(data->rsize, NULL); 1585 server->rsize = nfs_block_size(data->rsize, NULL);
1378 if (data->wsize) 1586 if (data->wsize)
@@ -1537,11 +1745,7 @@ struct nfs_server *nfs_clone_server(struct nfs_server *source,
1537 if (error < 0) 1745 if (error < 0)
1538 goto out_free_server; 1746 goto out_free_server;
1539 1747
1540 spin_lock(&nfs_client_lock); 1748 nfs_server_insert_lists(server);
1541 list_add_tail(&server->client_link, &server->nfs_client->cl_superblocks);
1542 list_add_tail(&server->master_link, &nfs_volume_list);
1543 spin_unlock(&nfs_client_lock);
1544
1545 server->mount_time = jiffies; 1749 server->mount_time = jiffies;
1546 1750
1547 nfs_free_fattr(fattr_fsinfo); 1751 nfs_free_fattr(fattr_fsinfo);
@@ -1794,3 +1998,7 @@ void nfs_fs_proc_exit(void)
1794} 1998}
1795 1999
1796#endif /* CONFIG_PROC_FS */ 2000#endif /* CONFIG_PROC_FS */
2001
2002module_param(nfs4_disable_idmapping, bool, 0644);
2003MODULE_PARM_DESC(nfs4_disable_idmapping,
2004 "Turn off NFSv4 idmapping when using 'sec=sys'");