double unlock
File: fs/nfs/.tmp_client.o.preproc
Full description: {AutomatonChecker of /usr/share/stanse/checkers/AutomatonChecker/kernel_locking_irq.xml} in function 'nfs_put_client' double unlock [traces: 8]
Importance: 0
Checker: AutomatonChecker of /usr/share/stanse/checkers/AutomatonChecker/kernel_locking_irq.xml
Trace:
line 928: not affected ==> the lock is still unlocked.
line 928: not affected ==> the lock is still unlocked.
line 931: not affected ==> the lock is still unlocked.
line 931: not affected ==> the lock is still unlocked.
line 933: not affected ==> the lock is still unlocked.
line 933: not affected ==> the lock is still unlocked.
line 936: not affected ==> the lock is still unlocked.
line 181: not affected ==> the lock is still unlocked.
line 181: not affected ==> the lock is still unlocked.
line 184: not affected ==> the lock is still unlocked.
line 184: not affected ==> the lock is still unlocked.
line 184: not affected ==> the lock is still unlocked.
line 186: not affected ==> the lock is still unlocked.
line 186: not affected ==> the lock is still unlocked.
line 187: not affected ==> the lock is still unlocked.
line 188: The lock is unlocked and here is an attempt to unlock it twice.[& nfs_client_lock]
This one is:
False positive index (the lower the better): 0
File contents (this file is distributed under the terms specified in the original file):
1|static spinlock_t nfs_client_lock = (spinlock_t ) { { .rlock = { .raw_lock = { 0 }, .magic = 0xdead4ead, .owner_cpu = -1, .owner = ((void *)-1L), .dep_map = { .name = "nfs_client_lock" } } } };
2|static struct list_head nfs_client_list = { &(nfs_client_list), &(nfs_client_list) };
3|static struct list_head nfs_volume_list = { &(nfs_volume_list), &(nfs_volume_list) };
4|static wait_queue_head_t nfs_client_active_wq = { .lock = (spinlock_t ) { { .rlock = { .raw_lock = { 0 }, .magic = 0xdead4ead, .owner_cpu = -1, .owner = ((void *)-1L), .dep_map = { .name = "nfs_client_active_wq.lock" } } } }, .task_list = { &(nfs_client_active_wq).task_list, &(nfs_client_active_wq).task_list } };
5|
6|
7|
8|
9|static struct rpc_version *nfs_version[5] = {
10| [2] = &nfs_version2,
11|
12| [3] = &nfs_version3,
13|
14|
15| [4] = &nfs_version4,
16|
17|};
18|
19|struct rpc_program nfs_program = {
20| .name = "nfs",
21| .number = 100003,
22| .nrvers = (sizeof(nfs_version) / sizeof((nfs_version)[0]) + (sizeof(struct { int:-!!(0); }))),
23| .version = nfs_version,
24| .stats = &nfs_rpcstat,
25| .pipe_dir_name = "/nfs",
26|};
27|
28|struct rpc_stat nfs_rpcstat = {
29| .program = &nfs_program
30|};
31|
32|
33|
34|static struct rpc_stat nfsacl_rpcstat = { &nfsacl_program };
35|static struct rpc_version * nfsacl_version[] = {
36| [3] = &nfsacl_version3,
37|};
38|
39|struct rpc_program nfsacl_program = {
40| .name = "nfsacl",
41| .number = 100227,
42| .nrvers = (sizeof(nfsacl_version) / sizeof((nfsacl_version)[0]) + (sizeof(struct { int:-!!(0); }))),
43| .version = nfsacl_version,
44| .stats = &nfsacl_rpcstat,
45|};
46|
47|
48|struct nfs_client_initdata {
49| const char *hostname;
50| const struct sockaddr *addr;
51| size_t addrlen;
52| const struct nfs_rpc_ops *rpc_ops;
53| int proto;
54| u32 minorversion;
55|};
56|
57|
58|
59|
60|
61|
62|
63|static struct nfs_client *nfs_alloc_client(const struct nfs_client_initdata *cl_init)
64|{
65| struct nfs_client *clp;
66| struct rpc_cred *cred;
67| int err = -12;
68|
69| if ((clp = kzalloc(sizeof(*clp), __st_GFP_KERNEL_st__)) == ((void *)0))
70| goto error_0;
71|
72| clp->rpc_ops = cl_init->rpc_ops;
73|
74| atomic_set(&clp->cl_count, 1);
75| clp->cl_cons_state = 1;
76|
77| __st_memcpy_st__(&clp->cl_addr, cl_init->addr, cl_init->addrlen);
78| clp->cl_addrlen = cl_init->addrlen;
79|
80| if (cl_init->hostname) {
81| err = -12;
82| clp->cl_hostname = kstrdup(cl_init->hostname, __st_GFP_KERNEL_st__);
83| if (!clp->cl_hostname)
84| goto error_cleanup;
85| }
86|
87| INIT_LIST_HEAD(&clp->cl_superblocks);
88| clp->cl_rpcclient = ERR_PTR(-22);
89|
90| clp->cl_proto = cl_init->proto;
91|
92|
93| INIT_LIST_HEAD(&clp->cl_delegations);
94| do { spinlock_check(&clp->cl_lock); do { static struct lock_class_key __key; __raw_spin_lock_init((&(&clp->cl_lock)->rlock), "&(&clp->cl_lock)->rlock", &__key); } while (0); } while (0);
95| do { do { do { static struct lock_class_key __key; __init_work(((&(&clp->cl_renewd)->work)), 0); ((&(&clp->cl_renewd)->work))->data = (atomic_long_t) { (WORK_STRUCT_NO_CPU) }; lockdep_init_map(&((&(&clp->cl_renewd)->work))->lockdep_map, "(&(&clp->cl_renewd)->work)", &__key, 0); INIT_LIST_HEAD(&((&(&clp->cl_renewd)->work))->entry); do { (((&(&clp->cl_renewd)->work)))->func = ((((nfs4_renew_state)))); } while (0); } while (0); } while (0); do { static struct lock_class_key __key; init_timer_key((&(&clp->cl_renewd)->timer), "&(&clp->cl_renewd)->timer", &__key); } while (0); } while (0);
96| rpc_init_wait_queue(&clp->cl_rpcwaitq, "NFS client");
97| clp->cl_boot_time = (current_kernel_time());
98| clp->cl_state = 1 << NFS4CLNT_LEASE_EXPIRED;
99| clp->cl_minorversion = cl_init->minorversion;
100| clp->cl_mvops = nfs_v4_minor_ops[cl_init->minorversion];
101|
102| cred = rpc_lookup_machine_cred();
103| if (!IS_ERR(cred))
104| clp->cl_machine_cred = cred;
105|
106| INIT_LIST_HEAD(&clp->cl_layouts);
107|
108| nfs_fscache_get_client_cookie(clp);
109|
110| return clp;
111|
112|error_cleanup:
113| kfree(clp);
114|error_0:
115| return ERR_PTR(err);
116|}
117|
118|
119|
120|
121|
122|
123|static void nfs4_clear_client_minor_version(struct nfs_client *clp)
124|{
125|
126| if (nfs4_has_session(clp)) {
127| nfs4_destroy_session(clp->cl_session);
128| clp->cl_session = ((void *)0);
129| }
130|
131| clp->cl_mvops = nfs_v4_minor_ops[0];
132|
133|}
134|
135|
136|
137|
138|static void nfs4_destroy_callback(struct nfs_client *clp)
139|{
140| if (__test_and_clear_bit(1, &clp->cl_res_state))
141| nfs_callback_down(clp->cl_mvops->minor_version);
142|}
143|
144|static void nfs4_shutdown_client(struct nfs_client *clp)
145|{
146| if (__test_and_clear_bit(3, &clp->cl_res_state))
147| nfs4_kill_renewd(clp);
148| nfs4_clear_client_minor_version(clp);
149| nfs4_destroy_callback(clp);
150| if (__test_and_clear_bit(2, &clp->cl_res_state))
151| nfs_idmap_delete(clp);
152|
153| rpc_destroy_wait_queue(&clp->cl_rpcwaitq);
154|}
155|static void nfs_free_client(struct nfs_client *clp)
156|{
157| do { if (__builtin_expect(!!(nfs_debug & 0x0200), 0)) printk("--> nfs_free_client(%u)\n", clp->rpc_ops->version); } while(0);
158|
159| nfs4_shutdown_client(clp);
160|
161| nfs_fscache_release_client_cookie(clp);
162|
163|
164| if (!IS_ERR(clp->cl_rpcclient))
165| rpc_shutdown_client(clp->cl_rpcclient);
166|
167| if (clp->cl_machine_cred != ((void *)0))
168| put_rpccred(clp->cl_machine_cred);
169|
170| kfree(clp->cl_hostname);
171| kfree(clp);
172|
173| do { if (__builtin_expect(!!(nfs_debug & 0x0200), 0)) printk("<-- nfs_free_client()\n"); } while(0);
174|}
175|
176|
177|
178|
179|void nfs_put_client(struct nfs_client *clp)
180|{
181| if (!clp)
|not affected ==> the lock is still unlocked. prev next
182| return;
183|
184| do { if (__builtin_expect(!!(nfs_debug & 0x0200), 0)) printk("--> nfs_put_client({%d})\n", atomic_read(&clp->cl_count)); } while(0);
|not affected ==> the lock is still unlocked. prev next
185|
186| if ((_atomic_dec_and_lock(&clp->cl_count, &nfs_client_lock))) {
|not affected ==> the lock is still unlocked. prev next
187| list_del(&clp->cl_share_link);
|not affected ==> the lock is still unlocked. prev next
188| __st_spin_unlock_st__(&nfs_client_lock);
|The lock is unlocked and here is an attempt to unlock it twice.[& nfs_client_lock] prev
189|
190| __st_BUG_ON_st__(!list_empty(&clp->cl_superblocks));
191|
192| nfs_free_client(clp);
193| }
194|}
195|extern typeof(nfs_put_client) nfs_put_client; extern void *__crc_nfs_put_client ; static const unsigned long __kcrctab_nfs_put_client = (unsigned long) &__crc_nfs_put_client; static const char __kstrtab_nfs_put_client[] = "" "nfs_put_client"; static const struct kernel_symbol __ksymtab_nfs_put_client = { (unsigned long)&nfs_put_client, __kstrtab_nfs_put_client };
196|static int nfs_sockaddr_match_ipaddr6(const struct sockaddr *sa1,
197| const struct sockaddr *sa2)
198|{
199| const struct sockaddr_in6 *sin1 = (const struct sockaddr_in6 *)sa1;
200| const struct sockaddr_in6 *sin2 = (const struct sockaddr_in6 *)sa2;
201|
202| if (ipv6_addr_scope(&sin1->sin6_addr) == 0x02 &&
203| sin1->sin6_scope_id != sin2->sin6_scope_id)
204| return 0;
205|
206| return ipv6_addr_equal(&sin1->sin6_addr, &sin2->sin6_addr);
207|}
208|static int nfs_sockaddr_match_ipaddr4(const struct sockaddr *sa1,
209| const struct sockaddr *sa2)
210|{
211| const struct sockaddr_in *sin1 = (const struct sockaddr_in *)sa1;
212| const struct sockaddr_in *sin2 = (const struct sockaddr_in *)sa2;
213|
214| return sin1->sin_addr.s_addr == sin2->sin_addr.s_addr;
215|}
216|
217|static int nfs_sockaddr_cmp_ip6(const struct sockaddr *sa1,
218| const struct sockaddr *sa2)
219|{
220| const struct sockaddr_in6 *sin1 = (const struct sockaddr_in6 *)sa1;
221| const struct sockaddr_in6 *sin2 = (const struct sockaddr_in6 *)sa2;
222|
223| return nfs_sockaddr_match_ipaddr6(sa1, sa2) &&
224| (sin1->sin6_port == sin2->sin6_port);
225|}
226|
227|static int nfs_sockaddr_cmp_ip4(const struct sockaddr *sa1,
228| const struct sockaddr *sa2)
229|{
230| const struct sockaddr_in *sin1 = (const struct sockaddr_in *)sa1;
231| const struct sockaddr_in *sin2 = (const struct sockaddr_in *)sa2;
232|
233| return nfs_sockaddr_match_ipaddr4(sa1, sa2) &&
234| (sin1->sin_port == sin2->sin_port);
235|}
236|
237|
238|
239|
240|
241|static int nfs_sockaddr_match_ipaddr(const struct sockaddr *sa1,
242| const struct sockaddr *sa2)
243|{
244| if (sa1->sa_family != sa2->sa_family)
245| return 0;
246|
247| switch (sa1->sa_family) {
248| case 2:
249| return nfs_sockaddr_match_ipaddr4(sa1, sa2);
250| case 10:
251| return nfs_sockaddr_match_ipaddr6(sa1, sa2);
252| }
253| return 0;
254|}
255|
256|
257|
258|
259|
260|static int nfs_sockaddr_cmp(const struct sockaddr *sa1,
261| const struct sockaddr *sa2)
262|{
263| if (sa1->sa_family != sa2->sa_family)
264| return 0;
265|
266| switch (sa1->sa_family) {
267| case 2:
268| return nfs_sockaddr_cmp_ip4(sa1, sa2);
269| case 10:
270| return nfs_sockaddr_cmp_ip6(sa1, sa2);
271| }
272| return 0;
273|}
274|
275|
276|
277|
278|
279|struct nfs_client *nfs_find_client(const struct sockaddr *addr, u32 nfsversion)
280|{
281| struct nfs_client *clp;
282|
283| __st_spin_lock_st__(&nfs_client_lock);
284| for (clp = ({ const typeof( ((typeof(*clp) *)0)->cl_share_link ) *__mptr = ((&nfs_client_list)->next); (typeof(*clp) *)( (char *)__mptr - 1 );}); __builtin_prefetch(clp->cl_share_link.next), &clp->cl_share_link != (&nfs_client_list); clp = ({ const typeof( ((typeof(*clp) *)0)->cl_share_link ) *__mptr = (clp->cl_share_link.next); (typeof(*clp) *)( (char *)__mptr - 1 );})) {
285| struct sockaddr *clap = (struct sockaddr *)&clp->cl_addr;
286|
287|
288| if (!(clp->cl_cons_state == 0 ||
289| clp->cl_cons_state == 2))
290| continue;
291|
292|
293| if (clp->rpc_ops->version != nfsversion)
294| continue;
295|
296|
297| if (!nfs_sockaddr_match_ipaddr(addr, clap))
298| continue;
299|
300| atomic_inc(&clp->cl_count);
301| __st_spin_unlock_st__(&nfs_client_lock);
302| return clp;
303| }
304| __st_spin_unlock_st__(&nfs_client_lock);
305| return ((void *)0);
306|}
307|
308|
309|
310|
311|
312|struct nfs_client *nfs_find_client_next(struct nfs_client *clp)
313|{
314| struct sockaddr *sap = (struct sockaddr *)&clp->cl_addr;
315| u32 nfsvers = clp->rpc_ops->version;
316|
317| __st_spin_lock_st__(&nfs_client_lock);
318| for (clp = ({ const typeof( ((typeof(*clp) *)0)->cl_share_link ) *__mptr = (clp->cl_share_link.next); (typeof(*clp) *)( (char *)__mptr - 1 );}); __builtin_prefetch(clp->cl_share_link.next), &clp->cl_share_link != (&nfs_client_list); clp = ({ const typeof( ((typeof(*clp) *)0)->cl_share_link ) *__mptr = (clp->cl_share_link.next); (typeof(*clp) *)( (char *)__mptr - 1 );})) {
319| struct sockaddr *clap = (struct sockaddr *)&clp->cl_addr;
320|
321|
322| if (clp->cl_cons_state != 0)
323| continue;
324|
325|
326| if (clp->rpc_ops->version != nfsvers)
327| continue;
328|
329|
330| if (!nfs_sockaddr_match_ipaddr(sap, clap))
331| continue;
332|
333| atomic_inc(&clp->cl_count);
334| __st_spin_unlock_st__(&nfs_client_lock);
335| return clp;
336| }
337| __st_spin_unlock_st__(&nfs_client_lock);
338| return ((void *)0);
339|}
340|
341|
342|
343|
344|
345|static struct nfs_client *nfs_match_client(const struct nfs_client_initdata *data)
346|{
347| struct nfs_client *clp;
348| const struct sockaddr *sap = data->addr;
349|
350| for (clp = ({ const typeof( ((typeof(*clp) *)0)->cl_share_link ) *__mptr = ((&nfs_client_list)->next); (typeof(*clp) *)( (char *)__mptr - 1 );}); __builtin_prefetch(clp->cl_share_link.next), &clp->cl_share_link != (&nfs_client_list); clp = ({ const typeof( ((typeof(*clp) *)0)->cl_share_link ) *__mptr = (clp->cl_share_link.next); (typeof(*clp) *)( (char *)__mptr - 1 );})) {
351| const struct sockaddr *clap = (struct sockaddr *)&clp->cl_addr;
352|
353| if (clp->cl_cons_state < 0)
354| continue;
355|
356|
357| if (clp->rpc_ops != data->rpc_ops)
358| continue;
359|
360| if (clp->cl_proto != data->proto)
361| continue;
362|
363| if (clp->cl_minorversion != data->minorversion)
364| continue;
365|
366| if (!nfs_sockaddr_cmp(sap, clap))
367| continue;
368|
369| atomic_inc(&clp->cl_count);
370| return clp;
371| }
372| return ((void *)0);
373|}
374|
375|
376|
377|
378|
379|static struct nfs_client *nfs_get_client(const struct nfs_client_initdata *cl_init)
380|{
381| struct nfs_client *clp, *new = ((void *)0);
382| int error;
383|
384| do { if (__builtin_expect(!!(nfs_debug & 0x0200), 0)) printk("--> nfs_get_client(%s,v%u)\n", cl_init->hostname ?: "", cl_init->rpc_ops->version); } while(0)
385| ;
386|
387|
388| do {
389| __st_spin_lock_st__(&nfs_client_lock);
390|
391| clp = nfs_match_client(cl_init);
392| if (clp)
393| goto found_client;
394| if (new)
395| goto install_client;
396|
397| __st_spin_unlock_st__(&nfs_client_lock);
398|
399| new = nfs_alloc_client(cl_init);
400| } while (!IS_ERR(new));
401|
402| do { if (__builtin_expect(!!(nfs_debug & 0x0200), 0)) printk("--> nfs_get_client() = %ld [failed]\n", PTR_ERR(new)); } while(0);
403| return new;
404|
405|
406|install_client:
407| clp = new;
408| list_add(&clp->cl_share_link, &nfs_client_list);
409| __st_spin_unlock_st__(&nfs_client_lock);
410| do { if (__builtin_expect(!!(nfs_debug & 0x0200), 0)) printk("--> nfs_get_client() = %p [new]\n", clp); } while(0);
411| return clp;
412|
413|
414|
415|
416|found_client:
417| __st_spin_unlock_st__(&nfs_client_lock);
418|
419| if (new)
420| nfs_free_client(new);
421|
422| error = ({ int __ret = 0; if (!(clp->cl_cons_state < 1)) do { wait_queue_t __wait = { .private = get_current(), .func = autoremove_wake_function, .task_list = { &((__wait).task_list), &((__wait).task_list) }, }; for (;;) { prepare_to_wait(&nfs_client_active_wq, &__wait, (128 | 2)); if (clp->cl_cons_state < 1) break; if (!fatal_signal_pending(get_current())) { schedule(); continue; } __ret = -512; break; } finish_wait(&nfs_client_active_wq, &__wait); } while (0); __ret; })
423| ;
424| if (error < 0) {
425| nfs_put_client(clp);
426| return ERR_PTR(-512);
427| }
428|
429| if (clp->cl_cons_state < 0) {
430| error = clp->cl_cons_state;
431| nfs_put_client(clp);
432| return ERR_PTR(error);
433| }
434|
435| __st_BUG_ON_st__(clp->cl_cons_state != 0);
436|
437| do { if (__builtin_expect(!!(nfs_debug & 0x0200), 0)) printk("--> nfs_get_client() = %p [share]\n", clp); } while(0);
438| return clp;
439|}
440|
441|
442|
443|
444|void nfs_mark_client_ready(struct nfs_client *clp, int state)
445|{
446| clp->cl_cons_state = state;
447| __wake_up(&nfs_client_active_wq, (1 | 2), 0, ((void *)0));
448|}
449|int nfs4_check_client_ready(struct nfs_client *clp)
450|{
451| if (!nfs4_has_session(clp))
452| return 0;
453| if (clp->cl_cons_state < 0)
454| return -93;
455| return 0;
456|}
457|
458|
459|
460|
461|static void nfs_init_timeout_values(struct rpc_timeout *to, int proto,
462| unsigned int timeo, unsigned int retrans)
463|{
464| to->to_initval = timeo * 250 / 10;
465| to->to_retries = retrans;
466|
467| switch (proto) {
468| case XPRT_TRANSPORT_TCP:
469| case XPRT_TRANSPORT_RDMA:
470| if (to->to_retries == 0)
471| to->to_retries = (2);
472| if (to->to_initval == 0)
473| to->to_initval = (600) * 250 / 10;
474| if (to->to_initval > (600*250))
475| to->to_initval = (600*250);
476| to->to_increment = to->to_initval;
477| to->to_maxval = to->to_initval + (to->to_increment * to->to_retries);
478| if (to->to_maxval > (600*250))
479| to->to_maxval = (600*250);
480| if (to->to_maxval < to->to_initval)
481| to->to_maxval = to->to_initval;
482| to->to_exponential = 0;
483| break;
484| case XPRT_TRANSPORT_UDP:
485| if (to->to_retries == 0)
486| to->to_retries = (3);
487| if (!to->to_initval)
488| to->to_initval = (11) * 250 / 10;
489| if (to->to_initval > (60*250))
490| to->to_initval = (60*250);
491| to->to_maxval = (60*250);
492| to->to_exponential = 1;
493| break;
494| default:
495| __st_BUG_st__();
496| }
497|}
498|
499|
500|
501|
502|static int nfs_create_rpc_client(struct nfs_client *clp,
503| const struct rpc_timeout *timeparms,
504| rpc_authflavor_t flavor,
505| int discrtry, int noresvport)
506|{
507| struct rpc_clnt *clnt = ((void *)0);
508| struct rpc_create_args args = {
509| .net = &init_net,
510| .protocol = clp->cl_proto,
511| .address = (struct sockaddr *)&clp->cl_addr,
512| .addrsize = clp->cl_addrlen,
513| .timeout = timeparms,
514| .servername = clp->cl_hostname,
515| .program = &nfs_program,
516| .version = clp->rpc_ops->version,
517| .authflavor = flavor,
518| };
519|
520| if (discrtry)
521| args.flags |= (1UL << 5);
522| if (noresvport)
523| args.flags |= (1UL << 3);
524|
525| if (!IS_ERR(clp->cl_rpcclient))
526| return 0;
527|
528| clnt = rpc_create(&args);
529| if (IS_ERR(clnt)) {
530| do { if (__builtin_expect(!!(nfs_debug & 0x0200), 0)) printk("%s: cannot create RPC client. Error = %ld\n", __func__, PTR_ERR(clnt)); } while(0)
531| ;
532| return PTR_ERR(clnt);
533| }
534|
535| clp->cl_rpcclient = clnt;
536| return 0;
537|}
538|
539|
540|
541|
542|static void nfs_destroy_server(struct nfs_server *server)
543|{
544| if (!(server->flags & 0x100000) ||
545| !(server->flags & 0x200000))
546| nlmclnt_done(server->nlm_host);
547|}
548|
549|
550|
551|
552|static int nfs_start_lockd(struct nfs_server *server)
553|{
554| struct nlm_host *host;
555| struct nfs_client *clp = server->nfs_client;
556| struct nlmclnt_initdata nlm_init = {
557| .hostname = clp->cl_hostname,
558| .address = (struct sockaddr *)&clp->cl_addr,
559| .addrlen = clp->cl_addrlen,
560| .nfs_version = clp->rpc_ops->version,
561| .noresvport = server->flags & 0x40000 ?
562| 1 : 0,
563| };
564|
565| if (nlm_init.nfs_version > 3)
566| return 0;
567| if ((server->flags & 0x100000) &&
568| (server->flags & 0x200000))
569| return 0;
570|
571| switch (clp->cl_proto) {
572| default:
573| nlm_init.protocol = IPPROTO_TCP;
574| break;
575| case XPRT_TRANSPORT_UDP:
576| nlm_init.protocol = IPPROTO_UDP;
577| }
578|
579| host = nlmclnt_init(&nlm_init);
580| if (IS_ERR(host))
581| return PTR_ERR(host);
582|
583| server->nlm_host = host;
584| server->destroy = nfs_destroy_server;
585| return 0;
586|}
587|
588|
589|
590|
591|
592|static void nfs_init_server_aclclient(struct nfs_server *server)
593|{
594| if (server->nfs_client->rpc_ops->version != 3)
595| goto out_noacl;
596| if (server->flags & 0x0800)
597| goto out_noacl;
598|
599| server->client_acl = rpc_bind_new_program(server->client, &nfsacl_program, 3);
600| if (IS_ERR(server->client_acl))
601| goto out_noacl;
602|
603|
604| server->caps |= (1U << 3);
605| return;
606|
607|out_noacl:
608| server->caps &= ~(1U << 3);
609|}
610|static int nfs_init_server_rpcclient(struct nfs_server *server,
611| const struct rpc_timeout *timeo,
612| rpc_authflavor_t pseudoflavour)
613|{
614| struct nfs_client *clp = server->nfs_client;
615|
616| server->client = rpc_clone_client(clp->cl_rpcclient);
617| if (IS_ERR(server->client)) {
618| do { if (__builtin_expect(!!(nfs_debug & 0x0200), 0)) printk("%s: couldn't create rpc_client!\n", __func__); } while(0);
619| return PTR_ERR(server->client);
620| }
621|
622| __st_memcpy_st__(&server->client->cl_timeout_default,
623| timeo,
624| sizeof(server->client->cl_timeout_default));
625| server->client->cl_timeout = &server->client->cl_timeout_default;
626|
627| if (pseudoflavour != clp->cl_rpcclient->cl_auth->au_flavor) {
628| struct rpc_auth *auth;
629|
630| auth = rpcauth_create(pseudoflavour, server->client);
631| if (IS_ERR(auth)) {
632| do { if (__builtin_expect(!!(nfs_debug & 0x0200), 0)) printk("%s: couldn't create credcache!\n", __func__); } while(0);
633| return PTR_ERR(auth);
634| }
635| }
636| server->client->cl_softrtry = 0;
637| if (server->flags & 0x0001)
638| server->client->cl_softrtry = 1;
639|
640| return 0;
641|}
642|
643|
644|
645|
646|static int nfs_init_client(struct nfs_client *clp,
647| const struct rpc_timeout *timeparms,
648| const struct nfs_parsed_mount_data *data)
649|{
650| int error;
651|
652| if (clp->cl_cons_state == 0) {
653|
654| do { if (__builtin_expect(!!(nfs_debug & 0x0200), 0)) printk("<-- nfs_init_client() = 0 [already %p]\n", clp); } while(0);
655| return 0;
656| }
657|
658|
659|
660|
661|
662| error = nfs_create_rpc_client(clp, timeparms, RPC_AUTH_UNIX,
663| 0, data->flags & 0x40000);
664| if (error < 0)
665| goto error;
666| nfs_mark_client_ready(clp, 0);
667| return 0;
668|
669|error:
670| nfs_mark_client_ready(clp, error);
671| do { if (__builtin_expect(!!(nfs_debug & 0x0200), 0)) printk("<-- nfs_init_client() = xerror %d\n", error); } while(0);
672| return error;
673|}
674|
675|
676|
677|
678|static int nfs_init_server(struct nfs_server *server,
679| const struct nfs_parsed_mount_data *data)
680|{
681| struct nfs_client_initdata cl_init = {
682| .hostname = data->nfs_server.hostname,
683| .addr = (const struct sockaddr *)&data->nfs_server.address,
684| .addrlen = data->nfs_server.addrlen,
685| .rpc_ops = &nfs_v2_clientops,
686| .proto = data->nfs_server.protocol,
687| };
688| struct rpc_timeout timeparms;
689| struct nfs_client *clp;
690| int error;
691|
692| do { if (__builtin_expect(!!(nfs_debug & 0x0200), 0)) printk("--> nfs_init_server()\n"); } while(0);
693|
694|
695| if (data->version == 3)
696| cl_init.rpc_ops = &nfs_v3_clientops;
697|
698|
699|
700| clp = nfs_get_client(&cl_init);
701| if (IS_ERR(clp)) {
702| do { if (__builtin_expect(!!(nfs_debug & 0x0200), 0)) printk("<-- nfs_init_server() = error %ld\n", PTR_ERR(clp)); } while(0);
703| return PTR_ERR(clp);
704| }
705|
706| nfs_init_timeout_values(&timeparms, data->nfs_server.protocol,
707| data->timeo, data->retrans);
708| error = nfs_init_client(clp, &timeparms, data);
709| if (error < 0)
710| goto error;
711|
712| server->nfs_client = clp;
713|
714|
715| server->flags = data->flags;
716| server->options = data->options;
717| server->caps |= (1U << 1)|(1U << 2)|(1U << 6)|
718| (1U << 7)|(1U << 8)|(1U << 9)|(1U << 10)|
719| (1U << 11)|(1U << 12)|(1U << 13);
720|
721| if (data->rsize)
722| server->rsize = nfs_block_size(data->rsize, ((void *)0));
723| if (data->wsize)
724| server->wsize = nfs_block_size(data->wsize, ((void *)0));
725|
726| server->acregmin = data->acregmin * 250;
727| server->acregmax = data->acregmax * 250;
728| server->acdirmin = data->acdirmin * 250;
729| server->acdirmax = data->acdirmax * 250;
730|
731|
732| error = nfs_start_lockd(server);
733| if (error < 0)
734| goto error;
735|
736| server->port = data->nfs_server.port;
737|
738| error = nfs_init_server_rpcclient(server, &timeparms, data->auth_flavors[0]);
739| if (error < 0)
740| goto error;
741|
742|
743| if (data->mount_server.addrlen) {
744| __st_memcpy_st__(&server->mountd_address, &data->mount_server.address,
745| data->mount_server.addrlen);
746| server->mountd_addrlen = data->mount_server.addrlen;
747| }
748| server->mountd_version = data->mount_server.version;
749| server->mountd_port = data->mount_server.port;
750| server->mountd_protocol = data->mount_server.protocol;
751|
752| server->namelen = data->namlen;
753|
754| nfs_init_server_aclclient(server);
755| do { if (__builtin_expect(!!(nfs_debug & 0x0200), 0)) printk("<-- nfs_init_server() = 0 [new %p]\n", clp); } while(0);
756| return 0;
757|
758|error:
759| server->nfs_client = ((void *)0);
760| nfs_put_client(clp);
761| do { if (__builtin_expect(!!(nfs_debug & 0x0200), 0)) printk("<-- nfs_init_server() = xerror %d\n", error); } while(0);
762| return error;
763|}
764|
765|
766|
767|
768|static void nfs_server_set_fsinfo(struct nfs_server *server, struct nfs_fsinfo *fsinfo)
769|{
770| unsigned long max_rpc_payload;
771|
772|
773| if (server->rsize == 0)
774| server->rsize = nfs_block_size(fsinfo->rtpref, ((void *)0));
775| if (server->wsize == 0)
776| server->wsize = nfs_block_size(fsinfo->wtpref, ((void *)0));
777|
778| if (fsinfo->rtmax >= 512 && server->rsize > fsinfo->rtmax)
779| server->rsize = nfs_block_size(fsinfo->rtmax, ((void *)0));
780| if (fsinfo->wtmax >= 512 && server->wsize > fsinfo->wtmax)
781| server->wsize = nfs_block_size(fsinfo->wtmax, ((void *)0));
782|
783| max_rpc_payload = nfs_block_size(rpc_max_payload(server->client), ((void *)0));
784| if (server->rsize > max_rpc_payload)
785| server->rsize = max_rpc_payload;
786| if (server->rsize > (1048576U))
787| server->rsize = (1048576U);
788| server->rpages = (server->rsize + ((1UL) << 12) - 1) >> 12;
789|
790| server->backing_dev_info.name = "nfs";
791| server->backing_dev_info.ra_pages = server->rpages * ((16U) - 1);
792|
793| if (server->wsize > max_rpc_payload)
794| server->wsize = max_rpc_payload;
795| if (server->wsize > (1048576U))
796| server->wsize = (1048576U);
797| server->wpages = (server->wsize + ((1UL) << 12) - 1) >> 12;
798| set_pnfs_layoutdriver(server, fsinfo->layouttype);
799|
800| server->wtmult = nfs_block_bits(fsinfo->wtmult, ((void *)0));
801|
802| server->dtsize = nfs_block_size(fsinfo->dtpref, ((void *)0));
803| if (server->dtsize > ((1UL) << 12) * 8)
804| server->dtsize = ((1UL) << 12) * 8;
805| if (server->dtsize > server->rsize)
806| server->dtsize = server->rsize;
807|
808| if (server->flags & 0x0020) {
809| server->acregmin = server->acregmax = 0;
810| server->acdirmin = server->acdirmax = 0;
811| }
812|
813| server->maxfilesize = fsinfo->maxfilesize;
814|
815| server->time_delta = fsinfo->time_delta;
816|
817|
818| rpc_setbufsize(server->client, server->wsize + 100, server->rsize + 100);
819|}
820|
821|
822|
823|
824|static int nfs_probe_fsinfo(struct nfs_server *server, struct nfs_fh *mntfh, struct nfs_fattr *fattr)
825|{
826| struct nfs_fsinfo fsinfo;
827| struct nfs_client *clp = server->nfs_client;
828| int error;
829|
830| do { if (__builtin_expect(!!(nfs_debug & 0x0200), 0)) printk("--> nfs_probe_fsinfo()\n"); } while(0);
831|
832| if (clp->rpc_ops->set_capabilities != ((void *)0)) {
833| error = clp->rpc_ops->set_capabilities(server, mntfh);
834| if (error < 0)
835| goto out_error;
836| }
837|
838| fsinfo.fattr = fattr;
839| fsinfo.layouttype = 0;
840| error = clp->rpc_ops->fsinfo(server, mntfh, &fsinfo);
841| if (error < 0)
842| goto out_error;
843|
844| nfs_server_set_fsinfo(server, &fsinfo);
845|
846|
847| if (server->namelen == 0) {
848| struct nfs_pathconf pathinfo;
849|
850| pathinfo.fattr = fattr;
851| nfs_fattr_init(fattr);
852|
853| if (clp->rpc_ops->pathconf(server, mntfh, &pathinfo) >= 0)
854| server->namelen = pathinfo.max_namelen;
855| }
856|
857| do { if (__builtin_expect(!!(nfs_debug & 0x0200), 0)) printk("<-- nfs_probe_fsinfo() = 0\n"); } while(0);
858| return 0;
859|
860|out_error:
861| do { if (__builtin_expect(!!(nfs_debug & 0x0200), 0)) printk("nfs_probe_fsinfo: error = %d\n", -error); } while(0);
862| return error;
863|}
864|
865|
866|
867|
868|static void nfs_server_copy_userdata(struct nfs_server *target, struct nfs_server *source)
869|{
870| target->flags = source->flags;
871| target->rsize = source->rsize;
872| target->wsize = source->wsize;
873| target->acregmin = source->acregmin;
874| target->acregmax = source->acregmax;
875| target->acdirmin = source->acdirmin;
876| target->acdirmax = source->acdirmax;
877| target->caps = source->caps;
878| target->options = source->options;
879|}
880|
881|
882|
883|
884|static struct nfs_server *nfs_alloc_server(void)
885|{
886| struct nfs_server *server;
887|
888| server = kzalloc(sizeof(struct nfs_server), __st_GFP_KERNEL_st__);
889| if (!server)
890| return ((void *)0);
891|
892| server->client = server->client_acl = ERR_PTR(-22);
893|
894|
895| INIT_LIST_HEAD(&server->client_link);
896| INIT_LIST_HEAD(&server->master_link);
897|
898| atomic_set(&server->active, 0);
899|
900| server->io_stats = nfs_alloc_iostats();
901| if (!server->io_stats) {
902| kfree(server);
903| return ((void *)0);
904| }
905|
906| if (bdi_init(&server->backing_dev_info)) {
907| nfs_free_iostats(server->io_stats);
908| kfree(server);
909| return ((void *)0);
910| }
911|
912| return server;
913|}
914|
915|
916|
917|
918|void nfs_free_server(struct nfs_server *server)
919|{
920| do { if (__builtin_expect(!!(nfs_debug & 0x0200), 0)) printk("--> nfs_free_server()\n"); } while(0);
921|
922| unset_pnfs_layoutdriver(server);
923| __st_spin_lock_st__(&nfs_client_lock);
924| list_del(&server->client_link);
925| list_del(&server->master_link);
926| __st_spin_unlock_st__(&nfs_client_lock);
|The lock is unlocked here. prev next
927|
928| if (server->destroy != ((void *)0))
|not affected ==> the lock is still unlocked. prev next
929| server->destroy(server);
930|
931| if (!IS_ERR(server->client_acl))
|not affected ==> the lock is still unlocked. prev next
932| rpc_shutdown_client(server->client_acl);
933| if (!IS_ERR(server->client))
|not affected ==> the lock is still unlocked. prev next
934| rpc_shutdown_client(server->client);
935|
936| nfs_put_client(server->nfs_client);
|not affected ==> the lock is still unlocked. prev next
937|
938| nfs_free_iostats(server->io_stats);
939| bdi_destroy(&server->backing_dev_info);
940| kfree(server);
941| nfs_release_automount_timer();
942| do { if (__builtin_expect(!!(nfs_debug & 0x0200), 0)) printk("<-- nfs_free_server()\n"); } while(0);
943|}
944|
945|
946|
947|
948|
949|struct nfs_server *nfs_create_server(const struct nfs_parsed_mount_data *data,
950| struct nfs_fh *mntfh)
951|{
952| struct nfs_server *server;
953| struct nfs_fattr *fattr;
954| int error;
955|
956| server = nfs_alloc_server();
957| if (!server)
958| return ERR_PTR(-12);
959|
960| error = -12;
961| fattr = nfs_alloc_fattr();
962| if (fattr == ((void *)0))
963| goto error;
964|
965|
966| error = nfs_init_server(server, data);
967| if (error < 0)
968| goto error;
969|
970| __st_BUG_ON_st__(!server->nfs_client);
971| __st_BUG_ON_st__(!server->nfs_client->rpc_ops);
972| __st_BUG_ON_st__(!server->nfs_client->rpc_ops->file_inode_ops);
973|
974|
975| error = nfs_probe_fsinfo(server, mntfh, fattr);
976| if (error < 0)
977| goto error;
978| if (server->nfs_client->rpc_ops->version == 3) {
979| if (server->namelen == 0 || server->namelen > 255)
980| server->namelen = 255;
981| if (!(data->flags & 0x4000))
982| server->caps |= (1U << 0);
983| } else {
984| if (server->namelen == 0 || server->namelen > 255)
985| server->namelen = 255;
986| }
987|
988| if (!(fattr->valid & ((1U << 0) | (1U << 1) | (1U << 2) | (1U << 3) | (1U << 4) | (1U << 5) | (1U << 6) | (1U << 10) | (1U << 11) | (1U << 12) | (1U << 13) | (1U << 14)))) {
989| error = server->nfs_client->rpc_ops->getattr(server, mntfh, fattr);
990| if (error < 0) {
991| do { if (__builtin_expect(!!(nfs_debug & 0x0200), 0)) printk("nfs_create_server: getattr error = %d\n", -error); } while(0);
992| goto error;
993| }
994| }
995| __st_memcpy_st__(&server->fsid, &fattr->fsid, sizeof(server->fsid));
996|
997| do { if (__builtin_expect(!!(nfs_debug & 0x0200), 0)) printk("Server FSID: %llx:%llx\n", (unsigned long long) server->fsid.major, (unsigned long long) server->fsid.minor); } while(0)
998|
999| ;
1000|
1001| __st_spin_lock_st__(&nfs_client_lock);
1002| list_add_tail(&server->client_link, &server->nfs_client->cl_superblocks);
1003| list_add_tail(&server->master_link, &nfs_volume_list);
1004| __st_spin_unlock_st__(&nfs_client_lock);
1005|
1006| server->mount_time = jiffies;
1007| nfs_free_fattr(fattr);
1008| return server;
1009|
1010|error:
1011| nfs_free_fattr(fattr);
1012| nfs_free_server(server);
1013| return ERR_PTR(error);
1014|}
1015|
1016|
1017|
1018|
1019|
1020|static int nfs4_init_callback(struct nfs_client *clp)
1021|{
1022| int error;
1023|
1024| if (clp->rpc_ops->version == 4) {
1025| if (nfs4_has_session(clp)) {
1026| error = xprt_setup_backchannel(
1027| clp->cl_rpcclient->cl_xprt,
1028| 1);
1029| if (error < 0)
1030| return error;
1031| }
1032|
1033| error = nfs_callback_up(clp->cl_mvops->minor_version,
1034| clp->cl_rpcclient->cl_xprt);
1035| if (error < 0) {
1036| do { if (__builtin_expect(!!(nfs_debug & 0x0200), 0)) printk("%s: failed to start callback. Error = %d\n", __func__, error); } while(0)
1037| ;
1038| return error;
1039| }
1040| __set_bit(1, &clp->cl_res_state);
1041| }
1042| return 0;
1043|}
1044|
1045|
1046|
1047|
1048|static int nfs4_init_client_minor_version(struct nfs_client *clp)
1049|{
1050|
1051| if (clp->cl_mvops->minor_version) {
1052| struct nfs4_session *session = ((void *)0);
1053|
1054|
1055|
1056|
1057|
1058| session = nfs4_alloc_session(clp);
1059| if (!session)
1060| return -12;
1061|
1062| clp->cl_session = session;
1063|
1064|
1065|
1066|
1067|
1068|
1069| clp->cl_cons_state = 2;
1070| }
1071|
1072|
1073| return nfs4_init_callback(clp);
1074|}
1075|
1076|
1077|
1078|
1079|static int nfs4_init_client(struct nfs_client *clp,
1080| const struct rpc_timeout *timeparms,
1081| const char *ip_addr,
1082| rpc_authflavor_t authflavour,
1083| int flags)
1084|{
1085| int error;
1086|
1087| if (clp->cl_cons_state == 0) {
1088|
1089| do { if (__builtin_expect(!!(nfs_debug & 0x0200), 0)) printk("<-- nfs4_init_client() = 0 [already %p]\n", clp); } while(0);
1090| return 0;
1091| }
1092|
1093|
1094| clp->rpc_ops = &nfs_v4_clientops;
1095|
1096| error = nfs_create_rpc_client(clp, timeparms, authflavour,
1097| 1, flags & 0x40000);
1098| if (error < 0)
1099| goto error;
1100| strlcpy(clp->cl_ipaddr, ip_addr, sizeof(clp->cl_ipaddr));
1101|
1102| error = nfs_idmap_new(clp);
1103| if (error < 0) {
1104| do { if (__builtin_expect(!!(nfs_debug & 0x0200), 0)) printk("%s: failed to create idmapper. Error = %d\n", __func__, error); } while(0)
1105| ;
1106| goto error;
1107| }
1108| __set_bit(2, &clp->cl_res_state);
1109|
1110| error = nfs4_init_client_minor_version(clp);
1111| if (error < 0)
1112| goto error;
1113|
1114| if (!nfs4_has_session(clp))
1115| nfs_mark_client_ready(clp, 0);
1116| return 0;
1117|
1118|error:
1119| nfs_mark_client_ready(clp, error);
1120| do { if (__builtin_expect(!!(nfs_debug & 0x0200), 0)) printk("<-- nfs4_init_client() = xerror %d\n", error); } while(0);
1121| return error;
1122|}
1123|
1124|
1125|
1126|
1127|static int nfs4_set_client(struct nfs_server *server,
1128| const char *hostname,
1129| const struct sockaddr *addr,
1130| const size_t addrlen,
1131| const char *ip_addr,
1132| rpc_authflavor_t authflavour,
1133| int proto, const struct rpc_timeout *timeparms,
1134| u32 minorversion)
1135|{
1136| struct nfs_client_initdata cl_init = {
1137| .hostname = hostname,
1138| .addr = addr,
1139| .addrlen = addrlen,
1140| .rpc_ops = &nfs_v4_clientops,
1141| .proto = proto,
1142| .minorversion = minorversion,
1143| };
1144| struct nfs_client *clp;
1145| int error;
1146|
1147| do { if (__builtin_expect(!!(nfs_debug & 0x0200), 0)) printk("--> nfs4_set_client()\n"); } while(0);
1148|
1149|
1150| clp = nfs_get_client(&cl_init);
1151| if (IS_ERR(clp)) {
1152| error = PTR_ERR(clp);
1153| goto error;
1154| }
1155| error = nfs4_init_client(clp, timeparms, ip_addr, authflavour,
1156| server->flags);
1157| if (error < 0)
1158| goto error_put;
1159|
1160| server->nfs_client = clp;
1161| do { if (__builtin_expect(!!(nfs_debug & 0x0200), 0)) printk("<-- nfs4_set_client() = 0 [new %p]\n", clp); } while(0);
1162| return 0;
1163|
1164|error_put:
1165| nfs_put_client(clp);
1166|error:
1167| do { if (__builtin_expect(!!(nfs_debug & 0x0200), 0)) printk("<-- nfs4_set_client() = xerror %d\n", error); } while(0);
1168| return error;
1169|}
1170|
1171|
1172|
1173|
1174|
1175|
1176|
1177|static void nfs4_session_set_rwsize(struct nfs_server *server)
1178|{
1179|
1180| struct nfs4_session *sess;
1181| u32 server_resp_sz;
1182| u32 server_rqst_sz;
1183|
1184| if (!nfs4_has_session(server->nfs_client))
1185| return;
1186| sess = server->nfs_client->cl_session;
1187| server_resp_sz = sess->fc_attrs.max_resp_sz - nfs41_maxread_overhead;
1188| server_rqst_sz = sess->fc_attrs.max_rqst_sz - nfs41_maxwrite_overhead;
1189|
1190| if (server->rsize > server_resp_sz)
1191| server->rsize = server_resp_sz;
1192| if (server->wsize > server_rqst_sz)
1193| server->wsize = server_rqst_sz;
1194|
1195|}
1196|
1197|static int nfs4_server_common_setup(struct nfs_server *server,
1198| struct nfs_fh *mntfh)
1199|{
1200| struct nfs_fattr *fattr;
1201| int error;
1202|
1203| __st_BUG_ON_st__(!server->nfs_client);
1204| __st_BUG_ON_st__(!server->nfs_client->rpc_ops);
1205| __st_BUG_ON_st__(!server->nfs_client->rpc_ops->file_inode_ops);
1206|
1207| fattr = nfs_alloc_fattr();
1208| if (fattr == ((void *)0))
1209| return -12;
1210|
1211|
1212| error = nfs4_init_session(server);
1213| if (error < 0)
1214| goto out;
1215|
1216|
1217| error = nfs4_get_rootfh(server, mntfh);
1218| if (error < 0)
1219| goto out;
1220|
1221| do { if (__builtin_expect(!!(nfs_debug & 0x0200), 0)) printk("Server FSID: %llx:%llx\n", (unsigned long long) server->fsid.major, (unsigned long long) server->fsid.minor); } while(0)
1222|
1223| ;
1224| do { if (__builtin_expect(!!(nfs_debug & 0x0200), 0)) printk("Mount FH: %d\n", mntfh->size); } while(0);
1225|
1226| nfs4_session_set_rwsize(server);
1227|
1228| error = nfs_probe_fsinfo(server, mntfh, fattr);
1229| if (error < 0)
1230| goto out;
1231|
1232| if (server->namelen == 0 || server->namelen > 255)
1233| server->namelen = 255;
1234|
1235| __st_spin_lock_st__(&nfs_client_lock);
1236| list_add_tail(&server->client_link, &server->nfs_client->cl_superblocks);
1237| list_add_tail(&server->master_link, &nfs_volume_list);
1238| __st_spin_unlock_st__(&nfs_client_lock);
1239|
1240| server->mount_time = jiffies;
1241|out:
1242| nfs_free_fattr(fattr);
1243| return error;
1244|}
1245|
1246|
1247|
1248|
1249|static int nfs4_init_server(struct nfs_server *server,
1250| const struct nfs_parsed_mount_data *data)
1251|{
1252| struct rpc_timeout timeparms;
1253| int error;
1254|
1255| do { if (__builtin_expect(!!(nfs_debug & 0x0200), 0)) printk("--> nfs4_init_server()\n"); } while(0);
1256|
1257| nfs_init_timeout_values(&timeparms, data->nfs_server.protocol,
1258| data->timeo, data->retrans);
1259|
1260|
1261| server->flags = data->flags;
1262| server->caps |= (1U << 4)|(1U << 5)|(1U << 14);
1263| if (!(data->flags & 0x4000))
1264| server->caps |= (1U << 0);
1265| server->options = data->options;
1266|
1267|
1268| error = nfs4_set_client(server,
1269| data->nfs_server.hostname,
1270| (const struct sockaddr *)&data->nfs_server.address,
1271| data->nfs_server.addrlen,
1272| data->client_address,
1273| data->auth_flavors[0],
1274| data->nfs_server.protocol,
1275| &timeparms,
1276| data->minorversion);
1277| if (error < 0)
1278| goto error;
1279|
1280| if (data->rsize)
1281| server->rsize = nfs_block_size(data->rsize, ((void *)0));
1282| if (data->wsize)
1283| server->wsize = nfs_block_size(data->wsize, ((void *)0));
1284|
1285| server->acregmin = data->acregmin * 250;
1286| server->acregmax = data->acregmax * 250;
1287| server->acdirmin = data->acdirmin * 250;
1288| server->acdirmax = data->acdirmax * 250;
1289|
1290| server->port = data->nfs_server.port;
1291|
1292| error = nfs_init_server_rpcclient(server, &timeparms, data->auth_flavors[0]);
1293|
1294|error:
1295|
1296| do { if (__builtin_expect(!!(nfs_debug & 0x0200), 0)) printk("<-- nfs4_init_server() = %d\n", error); } while(0);
1297| return error;
1298|}
1299|
1300|
1301|
1302|
1303|
1304|struct nfs_server *nfs4_create_server(const struct nfs_parsed_mount_data *data,
1305| struct nfs_fh *mntfh)
1306|{
1307| struct nfs_server *server;
1308| int error;
1309|
1310| do { if (__builtin_expect(!!(nfs_debug & 0x0200), 0)) printk("--> nfs4_create_server()\n"); } while(0);
1311|
1312| server = nfs_alloc_server();
1313| if (!server)
1314| return ERR_PTR(-12);
1315|
1316|
1317| error = nfs4_init_server(server, data);
1318| if (error < 0)
1319| goto error;
1320|
1321| error = nfs4_server_common_setup(server, mntfh);
1322| if (error < 0)
1323| goto error;
1324|
1325| do { if (__builtin_expect(!!(nfs_debug & 0x0200), 0)) printk("<-- nfs4_create_server() = %p\n", server); } while(0);
1326| return server;
1327|
1328|error:
1329| nfs_free_server(server);
1330| do { if (__builtin_expect(!!(nfs_debug & 0x0200), 0)) printk("<-- nfs4_create_server() = error %d\n", error); } while(0);
1331| return ERR_PTR(error);
1332|}
1333|
1334|
1335|
1336|
1337|struct nfs_server *nfs4_create_referral_server(struct nfs_clone_mount *data,
1338| struct nfs_fh *mntfh)
1339|{
1340| struct nfs_client *parent_client;
1341| struct nfs_server *server, *parent_server;
1342| int error;
1343|
1344| do { if (__builtin_expect(!!(nfs_debug & 0x0200), 0)) printk("--> nfs4_create_referral_server()\n"); } while(0);
1345|
1346| server = nfs_alloc_server();
1347| if (!server)
1348| return ERR_PTR(-12);
1349|
1350| parent_server = NFS_SB(data->sb);
1351| parent_client = parent_server->nfs_client;
1352|
1353|
1354| nfs_server_copy_userdata(server, parent_server);
1355| server->caps |= (1U << 4)|(1U << 5);
1356|
1357|
1358|
1359| error = nfs4_set_client(server, data->hostname,
1360| data->addr,
1361| data->addrlen,
1362| parent_client->cl_ipaddr,
1363| data->authflavor,
1364| parent_server->client->cl_xprt->prot,
1365| parent_server->client->cl_timeout,
1366| parent_client->cl_mvops->minor_version);
1367| if (error < 0)
1368| goto error;
1369|
1370| error = nfs_init_server_rpcclient(server, parent_server->client->cl_timeout, data->authflavor);
1371| if (error < 0)
1372| goto error;
1373|
1374| error = nfs4_server_common_setup(server, mntfh);
1375| if (error < 0)
1376| goto error;
1377|
1378| do { if (__builtin_expect(!!(nfs_debug & 0x0200), 0)) printk("<-- nfs_create_referral_server() = %p\n", server); } while(0);
1379| return server;
1380|
1381|error:
1382| nfs_free_server(server);
|<context>When called from here. next
1383| do { if (__builtin_expect(!!(nfs_debug & 0x0200), 0)) printk("<-- nfs4_create_referral_server() = error %d\n", error); } while(0);
1384| return ERR_PTR(error);
1385|}
1386|
1387|
1388|
1389|
1390|
1391|
1392|struct nfs_server *nfs_clone_server(struct nfs_server *source,
1393| struct nfs_fh *fh,
1394| struct nfs_fattr *fattr)
1395|{
1396| struct nfs_server *server;
1397| struct nfs_fattr *fattr_fsinfo;
1398| int error;
1399|
1400| do { if (__builtin_expect(!!(nfs_debug & 0x0200), 0)) printk("--> nfs_clone_server(,%llx:%llx,)\n", (unsigned long long) fattr->fsid.major, (unsigned long long) fattr->fsid.minor); } while(0)
1401|
1402| ;
1403|
1404| server = nfs_alloc_server();
1405| if (!server)
1406| return ERR_PTR(-12);
1407|
1408| error = -12;
1409| fattr_fsinfo = nfs_alloc_fattr();
1410| if (fattr_fsinfo == ((void *)0))
1411| goto out_free_server;
1412|
1413|
1414| server->nfs_client = source->nfs_client;
1415| atomic_inc(&server->nfs_client->cl_count);
1416| nfs_server_copy_userdata(server, source);
1417|
1418| server->fsid = fattr->fsid;
1419|
1420| error = nfs_init_server_rpcclient(server,
1421| source->client->cl_timeout,
1422| source->client->cl_auth->au_flavor);
1423| if (error < 0)
1424| goto out_free_server;
1425| if (!IS_ERR(source->client_acl))
1426| nfs_init_server_aclclient(server);
1427|
1428|
1429| error = nfs_probe_fsinfo(server, fh, fattr_fsinfo);
1430| if (error < 0)
1431| goto out_free_server;
1432|
1433| if (server->namelen == 0 || server->namelen > 255)
1434| server->namelen = 255;
1435|
1436| do { if (__builtin_expect(!!(nfs_debug & 0x0200), 0)) printk("Cloned FSID: %llx:%llx\n", (unsigned long long) server->fsid.major, (unsigned long long) server->fsid.minor); } while(0)
1437|
1438| ;
1439|
1440| error = nfs_start_lockd(server);
1441| if (error < 0)
1442| goto out_free_server;
1443|
1444| __st_spin_lock_st__(&nfs_client_lock);
1445| list_add_tail(&server->client_link, &server->nfs_client->cl_superblocks);
1446| list_add_tail(&server->master_link, &nfs_volume_list);
1447| __st_spin_unlock_st__(&nfs_client_lock);
1448|
1449| server->mount_time = jiffies;
1450|
1451| nfs_free_fattr(fattr_fsinfo);
1452| do { if (__builtin_expect(!!(nfs_debug & 0x0200), 0)) printk("<-- nfs_clone_server() = %p\n", server); } while(0);
1453| return server;
1454|
1455|out_free_server:
1456| nfs_free_fattr(fattr_fsinfo);
1457| nfs_free_server(server);
1458| do { if (__builtin_expect(!!(nfs_debug & 0x0200), 0)) printk("<-- nfs_clone_server() = error %d\n", error); } while(0);
1459| return ERR_PTR(error);
1460|}
1461|
1462|
1463|static struct proc_dir_entry *proc_fs_nfs;
1464|
1465|static int nfs_server_list_open(struct inode *inode, struct file *file);
1466|static void *nfs_server_list_start(struct seq_file *p, loff_t *pos);
1467|static void *nfs_server_list_next(struct seq_file *p, void *v, loff_t *pos);
1468|static void nfs_server_list_stop(struct seq_file *p, void *v);
1469|static int nfs_server_list_show(struct seq_file *m, void *v);
1470|
1471|static const struct seq_operations nfs_server_list_ops = {
1472| .start = nfs_server_list_start,
1473| .next = nfs_server_list_next,
1474| .stop = nfs_server_list_stop,
1475| .show = nfs_server_list_show,
1476|};
1477|
1478|static const struct file_operations nfs_server_list_fops = {
1479| .open = nfs_server_list_open,
1480| .read = seq_read,
1481| .llseek = seq_lseek,
1482| .release = seq_release,
1483| .owner = (&__this_module),
1484|};
1485|
1486|static int nfs_volume_list_open(struct inode *inode, struct file *file);
1487|static void *nfs_volume_list_start(struct seq_file *p, loff_t *pos);
1488|static void *nfs_volume_list_next(struct seq_file *p, void *v, loff_t *pos);
1489|static void nfs_volume_list_stop(struct seq_file *p, void *v);
1490|static int nfs_volume_list_show(struct seq_file *m, void *v);
1491|
1492|static const struct seq_operations nfs_volume_list_ops = {
1493| .start = nfs_volume_list_start,
1494| .next = nfs_volume_list_next,
1495| .stop = nfs_volume_list_stop,
1496| .show = nfs_volume_list_show,
1497|};
1498|
1499|static const struct file_operations nfs_volume_list_fops = {
1500| .open = nfs_volume_list_open,
1501| .read = seq_read,
1502| .llseek = seq_lseek,
1503| .release = seq_release,
1504| .owner = (&__this_module),
1505|};
1506|
1507|
1508|
1509|
1510|
1511|static int nfs_server_list_open(struct inode *inode, struct file *file)
1512|{
1513| struct seq_file *m;
1514| int ret;
1515|
1516| ret = seq_open(file, &nfs_server_list_ops);
1517| if (ret < 0)
1518| return ret;
1519|
1520| m = file->private_data;
1521| m->private = PDE(inode)->data;
1522|
1523| return 0;
1524|}
1525|
1526|
1527|
1528|
1529|static void *nfs_server_list_start(struct seq_file *m, loff_t *_pos)
1530|{
1531|
1532| __st_spin_lock_st__(&nfs_client_lock);
1533| return seq_list_start_head(&nfs_client_list, *_pos);
1534|}
1535|
1536|
1537|
1538|
1539|static void *nfs_server_list_next(struct seq_file *p, void *v, loff_t *pos)
1540|{
1541| return seq_list_next(v, &nfs_client_list, pos);
1542|}
1543|
1544|
1545|
1546|
1547|static void nfs_server_list_stop(struct seq_file *p, void *v)
1548|{
1549| __st_spin_unlock_st__(&nfs_client_lock);
1550|}
1551|
1552|
1553|
1554|
1555|static int nfs_server_list_show(struct seq_file *m, void *v)
1556|{
1557| struct nfs_client *clp;
1558|
1559|
1560| if (v == &nfs_client_list) {
1561| seq_puts(m, "NV SERVER PORT USE HOSTNAME\n");
1562| return 0;
1563| }
1564|
1565|
1566| clp = ({ const typeof( ((struct nfs_client *)0)->cl_share_link ) *__mptr = (v); (struct nfs_client *)( (char *)__mptr - 1 );});
1567|
1568| seq_printf(m, "v%u %s %s %3d %s\n",
1569| clp->rpc_ops->version,
1570| rpc_peeraddr2str(clp->cl_rpcclient, RPC_DISPLAY_HEX_ADDR),
1571| rpc_peeraddr2str(clp->cl_rpcclient, RPC_DISPLAY_HEX_PORT),
1572| atomic_read(&clp->cl_count),
1573| clp->cl_hostname);
1574|
1575| return 0;
1576|}
1577|
1578|
1579|
1580|
1581|static int nfs_volume_list_open(struct inode *inode, struct file *file)
1582|{
1583| struct seq_file *m;
1584| int ret;
1585|
1586| ret = seq_open(file, &nfs_volume_list_ops);
1587| if (ret < 0)
1588| return ret;
1589|
1590| m = file->private_data;
1591| m->private = PDE(inode)->data;
1592|
1593| return 0;
1594|}
1595|
1596|
1597|
1598|
1599|static void *nfs_volume_list_start(struct seq_file *m, loff_t *_pos)
1600|{
1601|
1602| __st_spin_lock_st__(&nfs_client_lock);
1603| return seq_list_start_head(&nfs_volume_list, *_pos);
1604|}
1605|
1606|
1607|
1608|
1609|static void *nfs_volume_list_next(struct seq_file *p, void *v, loff_t *pos)
1610|{
1611| return seq_list_next(v, &nfs_volume_list, pos);
1612|}
1613|
1614|
1615|
1616|
1617|static void nfs_volume_list_stop(struct seq_file *p, void *v)
1618|{
1619| __st_spin_unlock_st__(&nfs_client_lock);
1620|}
1621|
1622|
1623|
1624|
1625|static int nfs_volume_list_show(struct seq_file *m, void *v)
1626|{
1627| struct nfs_server *server;
1628| struct nfs_client *clp;
1629| char dev[8], fsid[17];
1630|
1631|
1632| if (v == &nfs_volume_list) {
1633| seq_puts(m, "NV SERVER PORT DEV FSID FSC\n");
1634| return 0;
1635| }
1636|
1637| server = ({ const typeof( ((struct nfs_server *)0)->master_link ) *__mptr = (v); (struct nfs_server *)( (char *)__mptr - 1 );});
1638| clp = server->nfs_client;
1639|
1640| snprintf(dev, 8, "%u:%u",
1641| ((unsigned int) ((server->s_dev) >> 20)), ((unsigned int) ((server->s_dev) & ((1U << 20) - 1))));
1642|
1643| snprintf(fsid, 17, "%llx:%llx",
1644| (unsigned long long) server->fsid.major,
1645| (unsigned long long) server->fsid.minor);
1646|
1647| seq_printf(m, "v%u %s %s %-7s %-17s %s\n",
1648| clp->rpc_ops->version,
1649| rpc_peeraddr2str(clp->cl_rpcclient, RPC_DISPLAY_HEX_ADDR),
1650| rpc_peeraddr2str(clp->cl_rpcclient, RPC_DISPLAY_HEX_PORT),
1651| dev,
1652| fsid,
1653| nfs_server_fscache_state(server));
1654|
1655| return 0;
1656|}
1657|
1658|
1659|
1660|
1661|int nfs_fs_proc_init(void)
1662|{
1663| struct proc_dir_entry *p;
1664|
1665| proc_fs_nfs = proc_mkdir("fs/nfsfs", ((void *)0));
1666| if (!proc_fs_nfs)
1667| goto error_0;
1668|
1669|
1670| p = proc_create("servers", 0100000|(00400|00040|00004),
1671| proc_fs_nfs, &nfs_server_list_fops);
1672| if (!p)
1673| goto error_1;
1674|
1675|
1676| p = proc_create("volumes", 0100000|(00400|00040|00004),
1677| proc_fs_nfs, &nfs_volume_list_fops);
1678| if (!p)
1679| goto error_2;
1680| return 0;
1681|
1682|error_2:
1683| remove_proc_entry("servers", proc_fs_nfs);
1684|error_1:
1685| remove_proc_entry("fs/nfsfs", ((void *)0));
1686|error_0:
1687| return -12;
1688|}
1689|
1690|
1691|
1692|
1693|void nfs_fs_proc_exit(void)
1694|{
1695| remove_proc_entry("volumes", proc_fs_nfs);
1696| remove_proc_entry("servers", proc_fs_nfs);
1697| remove_proc_entry("fs/nfsfs", ((void *)0));
1698|}