diff options
Diffstat (limited to 'fs/lockd/host.c')
-rw-r--r-- | fs/lockd/host.c | 92 |
1 files changed, 62 insertions, 30 deletions
diff --git a/fs/lockd/host.c b/fs/lockd/host.c index eb75ca7c2d6e..f9b22e58f78f 100644 --- a/fs/lockd/host.c +++ b/fs/lockd/host.c | |||
@@ -21,6 +21,8 @@ | |||
21 | 21 | ||
22 | #include <net/ipv6.h> | 22 | #include <net/ipv6.h> |
23 | 23 | ||
24 | #include "netns.h" | ||
25 | |||
24 | #define NLMDBG_FACILITY NLMDBG_HOSTCACHE | 26 | #define NLMDBG_FACILITY NLMDBG_HOSTCACHE |
25 | #define NLM_HOST_NRHASH 32 | 27 | #define NLM_HOST_NRHASH 32 |
26 | #define NLM_HOST_REBIND (60 * HZ) | 28 | #define NLM_HOST_REBIND (60 * HZ) |
@@ -41,11 +43,10 @@ static struct hlist_head nlm_client_hosts[NLM_HOST_NRHASH]; | |||
41 | hlist_for_each_entry_safe((host), (pos), (next), \ | 43 | hlist_for_each_entry_safe((host), (pos), (next), \ |
42 | (chain), h_hash) | 44 | (chain), h_hash) |
43 | 45 | ||
44 | static unsigned long next_gc; | ||
45 | static unsigned long nrhosts; | 46 | static unsigned long nrhosts; |
46 | static DEFINE_MUTEX(nlm_host_mutex); | 47 | static DEFINE_MUTEX(nlm_host_mutex); |
47 | 48 | ||
48 | static void nlm_gc_hosts(void); | 49 | static void nlm_gc_hosts(struct net *net); |
49 | 50 | ||
50 | struct nlm_lookup_host_info { | 51 | struct nlm_lookup_host_info { |
51 | const int server; /* search for server|client */ | 52 | const int server; /* search for server|client */ |
@@ -172,6 +173,7 @@ out: | |||
172 | static void nlm_destroy_host_locked(struct nlm_host *host) | 173 | static void nlm_destroy_host_locked(struct nlm_host *host) |
173 | { | 174 | { |
174 | struct rpc_clnt *clnt; | 175 | struct rpc_clnt *clnt; |
176 | struct lockd_net *ln = net_generic(host->net, lockd_net_id); | ||
175 | 177 | ||
176 | dprintk("lockd: destroy host %s\n", host->h_name); | 178 | dprintk("lockd: destroy host %s\n", host->h_name); |
177 | 179 | ||
@@ -188,6 +190,7 @@ static void nlm_destroy_host_locked(struct nlm_host *host) | |||
188 | rpc_shutdown_client(clnt); | 190 | rpc_shutdown_client(clnt); |
189 | kfree(host); | 191 | kfree(host); |
190 | 192 | ||
193 | ln->nrhosts--; | ||
191 | nrhosts--; | 194 | nrhosts--; |
192 | } | 195 | } |
193 | 196 | ||
@@ -228,6 +231,7 @@ struct nlm_host *nlmclnt_lookup_host(const struct sockaddr *sap, | |||
228 | struct hlist_node *pos; | 231 | struct hlist_node *pos; |
229 | struct nlm_host *host; | 232 | struct nlm_host *host; |
230 | struct nsm_handle *nsm = NULL; | 233 | struct nsm_handle *nsm = NULL; |
234 | struct lockd_net *ln = net_generic(net, lockd_net_id); | ||
231 | 235 | ||
232 | dprintk("lockd: %s(host='%s', vers=%u, proto=%s)\n", __func__, | 236 | dprintk("lockd: %s(host='%s', vers=%u, proto=%s)\n", __func__, |
233 | (hostname ? hostname : "<none>"), version, | 237 | (hostname ? hostname : "<none>"), version, |
@@ -262,6 +266,7 @@ struct nlm_host *nlmclnt_lookup_host(const struct sockaddr *sap, | |||
262 | goto out; | 266 | goto out; |
263 | 267 | ||
264 | hlist_add_head(&host->h_hash, chain); | 268 | hlist_add_head(&host->h_hash, chain); |
269 | ln->nrhosts++; | ||
265 | nrhosts++; | 270 | nrhosts++; |
266 | 271 | ||
267 | dprintk("lockd: %s created host %s (%s)\n", __func__, | 272 | dprintk("lockd: %s created host %s (%s)\n", __func__, |
@@ -326,7 +331,7 @@ struct nlm_host *nlmsvc_lookup_host(const struct svc_rqst *rqstp, | |||
326 | struct nsm_handle *nsm = NULL; | 331 | struct nsm_handle *nsm = NULL; |
327 | struct sockaddr *src_sap = svc_daddr(rqstp); | 332 | struct sockaddr *src_sap = svc_daddr(rqstp); |
328 | size_t src_len = rqstp->rq_daddrlen; | 333 | size_t src_len = rqstp->rq_daddrlen; |
329 | struct net *net = rqstp->rq_xprt->xpt_net; | 334 | struct net *net = SVC_NET(rqstp); |
330 | struct nlm_lookup_host_info ni = { | 335 | struct nlm_lookup_host_info ni = { |
331 | .server = 1, | 336 | .server = 1, |
332 | .sap = svc_addr(rqstp), | 337 | .sap = svc_addr(rqstp), |
@@ -337,6 +342,7 @@ struct nlm_host *nlmsvc_lookup_host(const struct svc_rqst *rqstp, | |||
337 | .hostname_len = hostname_len, | 342 | .hostname_len = hostname_len, |
338 | .net = net, | 343 | .net = net, |
339 | }; | 344 | }; |
345 | struct lockd_net *ln = net_generic(net, lockd_net_id); | ||
340 | 346 | ||
341 | dprintk("lockd: %s(host='%*s', vers=%u, proto=%s)\n", __func__, | 347 | dprintk("lockd: %s(host='%*s', vers=%u, proto=%s)\n", __func__, |
342 | (int)hostname_len, hostname, rqstp->rq_vers, | 348 | (int)hostname_len, hostname, rqstp->rq_vers, |
@@ -344,8 +350,8 @@ struct nlm_host *nlmsvc_lookup_host(const struct svc_rqst *rqstp, | |||
344 | 350 | ||
345 | mutex_lock(&nlm_host_mutex); | 351 | mutex_lock(&nlm_host_mutex); |
346 | 352 | ||
347 | if (time_after_eq(jiffies, next_gc)) | 353 | if (time_after_eq(jiffies, ln->next_gc)) |
348 | nlm_gc_hosts(); | 354 | nlm_gc_hosts(net); |
349 | 355 | ||
350 | chain = &nlm_server_hosts[nlm_hash_address(ni.sap)]; | 356 | chain = &nlm_server_hosts[nlm_hash_address(ni.sap)]; |
351 | hlist_for_each_entry(host, pos, chain, h_hash) { | 357 | hlist_for_each_entry(host, pos, chain, h_hash) { |
@@ -382,6 +388,7 @@ struct nlm_host *nlmsvc_lookup_host(const struct svc_rqst *rqstp, | |||
382 | memcpy(nlm_srcaddr(host), src_sap, src_len); | 388 | memcpy(nlm_srcaddr(host), src_sap, src_len); |
383 | host->h_srcaddrlen = src_len; | 389 | host->h_srcaddrlen = src_len; |
384 | hlist_add_head(&host->h_hash, chain); | 390 | hlist_add_head(&host->h_hash, chain); |
391 | ln->nrhosts++; | ||
385 | nrhosts++; | 392 | nrhosts++; |
386 | 393 | ||
387 | dprintk("lockd: %s created host %s (%s)\n", | 394 | dprintk("lockd: %s created host %s (%s)\n", |
@@ -565,6 +572,35 @@ void nlm_host_rebooted(const struct nlm_reboot *info) | |||
565 | nsm_release(nsm); | 572 | nsm_release(nsm); |
566 | } | 573 | } |
567 | 574 | ||
575 | static void nlm_complain_hosts(struct net *net) | ||
576 | { | ||
577 | struct hlist_head *chain; | ||
578 | struct hlist_node *pos; | ||
579 | struct nlm_host *host; | ||
580 | |||
581 | if (net) { | ||
582 | struct lockd_net *ln = net_generic(net, lockd_net_id); | ||
583 | |||
584 | if (ln->nrhosts == 0) | ||
585 | return; | ||
586 | printk(KERN_WARNING "lockd: couldn't shutdown host module for net %p!\n", net); | ||
587 | dprintk("lockd: %lu hosts left in net %p:\n", ln->nrhosts, net); | ||
588 | } else { | ||
589 | if (nrhosts == 0) | ||
590 | return; | ||
591 | printk(KERN_WARNING "lockd: couldn't shutdown host module!\n"); | ||
592 | dprintk("lockd: %lu hosts left:\n", nrhosts); | ||
593 | } | ||
594 | |||
595 | for_each_host(host, pos, chain, nlm_server_hosts) { | ||
596 | if (net && host->net != net) | ||
597 | continue; | ||
598 | dprintk(" %s (cnt %d use %d exp %ld net %p)\n", | ||
599 | host->h_name, atomic_read(&host->h_count), | ||
600 | host->h_inuse, host->h_expires, host->net); | ||
601 | } | ||
602 | } | ||
603 | |||
568 | void | 604 | void |
569 | nlm_shutdown_hosts_net(struct net *net) | 605 | nlm_shutdown_hosts_net(struct net *net) |
570 | { | 606 | { |
@@ -572,11 +608,10 @@ nlm_shutdown_hosts_net(struct net *net) | |||
572 | struct hlist_node *pos; | 608 | struct hlist_node *pos; |
573 | struct nlm_host *host; | 609 | struct nlm_host *host; |
574 | 610 | ||
575 | dprintk("lockd: shutting down host module\n"); | ||
576 | mutex_lock(&nlm_host_mutex); | 611 | mutex_lock(&nlm_host_mutex); |
577 | 612 | ||
578 | /* First, make all hosts eligible for gc */ | 613 | /* First, make all hosts eligible for gc */ |
579 | dprintk("lockd: nuking all hosts...\n"); | 614 | dprintk("lockd: nuking all hosts in net %p...\n", net); |
580 | for_each_host(host, pos, chain, nlm_server_hosts) { | 615 | for_each_host(host, pos, chain, nlm_server_hosts) { |
581 | if (net && host->net != net) | 616 | if (net && host->net != net) |
582 | continue; | 617 | continue; |
@@ -588,8 +623,10 @@ nlm_shutdown_hosts_net(struct net *net) | |||
588 | } | 623 | } |
589 | 624 | ||
590 | /* Then, perform a garbage collection pass */ | 625 | /* Then, perform a garbage collection pass */ |
591 | nlm_gc_hosts(); | 626 | nlm_gc_hosts(net); |
592 | mutex_unlock(&nlm_host_mutex); | 627 | mutex_unlock(&nlm_host_mutex); |
628 | |||
629 | nlm_complain_hosts(net); | ||
593 | } | 630 | } |
594 | 631 | ||
595 | /* | 632 | /* |
@@ -599,22 +636,8 @@ nlm_shutdown_hosts_net(struct net *net) | |||
599 | void | 636 | void |
600 | nlm_shutdown_hosts(void) | 637 | nlm_shutdown_hosts(void) |
601 | { | 638 | { |
602 | struct hlist_head *chain; | 639 | dprintk("lockd: shutting down host module\n"); |
603 | struct hlist_node *pos; | ||
604 | struct nlm_host *host; | ||
605 | |||
606 | nlm_shutdown_hosts_net(NULL); | 640 | nlm_shutdown_hosts_net(NULL); |
607 | |||
608 | /* complain if any hosts are left */ | ||
609 | if (nrhosts != 0) { | ||
610 | printk(KERN_WARNING "lockd: couldn't shutdown host module!\n"); | ||
611 | dprintk("lockd: %lu hosts left:\n", nrhosts); | ||
612 | for_each_host(host, pos, chain, nlm_server_hosts) { | ||
613 | dprintk(" %s (cnt %d use %d exp %ld net %p)\n", | ||
614 | host->h_name, atomic_read(&host->h_count), | ||
615 | host->h_inuse, host->h_expires, host->net); | ||
616 | } | ||
617 | } | ||
618 | } | 641 | } |
619 | 642 | ||
620 | /* | 643 | /* |
@@ -623,30 +646,39 @@ nlm_shutdown_hosts(void) | |||
623 | * mark & sweep for resources held by remote clients. | 646 | * mark & sweep for resources held by remote clients. |
624 | */ | 647 | */ |
625 | static void | 648 | static void |
626 | nlm_gc_hosts(void) | 649 | nlm_gc_hosts(struct net *net) |
627 | { | 650 | { |
628 | struct hlist_head *chain; | 651 | struct hlist_head *chain; |
629 | struct hlist_node *pos, *next; | 652 | struct hlist_node *pos, *next; |
630 | struct nlm_host *host; | 653 | struct nlm_host *host; |
631 | 654 | ||
632 | dprintk("lockd: host garbage collection\n"); | 655 | dprintk("lockd: host garbage collection for net %p\n", net); |
633 | for_each_host(host, pos, chain, nlm_server_hosts) | 656 | for_each_host(host, pos, chain, nlm_server_hosts) { |
657 | if (net && host->net != net) | ||
658 | continue; | ||
634 | host->h_inuse = 0; | 659 | host->h_inuse = 0; |
660 | } | ||
635 | 661 | ||
636 | /* Mark all hosts that hold locks, blocks or shares */ | 662 | /* Mark all hosts that hold locks, blocks or shares */ |
637 | nlmsvc_mark_resources(); | 663 | nlmsvc_mark_resources(net); |
638 | 664 | ||
639 | for_each_host_safe(host, pos, next, chain, nlm_server_hosts) { | 665 | for_each_host_safe(host, pos, next, chain, nlm_server_hosts) { |
666 | if (net && host->net != net) | ||
667 | continue; | ||
640 | if (atomic_read(&host->h_count) || host->h_inuse | 668 | if (atomic_read(&host->h_count) || host->h_inuse |
641 | || time_before(jiffies, host->h_expires)) { | 669 | || time_before(jiffies, host->h_expires)) { |
642 | dprintk("nlm_gc_hosts skipping %s " | 670 | dprintk("nlm_gc_hosts skipping %s " |
643 | "(cnt %d use %d exp %ld)\n", | 671 | "(cnt %d use %d exp %ld net %p)\n", |
644 | host->h_name, atomic_read(&host->h_count), | 672 | host->h_name, atomic_read(&host->h_count), |
645 | host->h_inuse, host->h_expires); | 673 | host->h_inuse, host->h_expires, host->net); |
646 | continue; | 674 | continue; |
647 | } | 675 | } |
648 | nlm_destroy_host_locked(host); | 676 | nlm_destroy_host_locked(host); |
649 | } | 677 | } |
650 | 678 | ||
651 | next_gc = jiffies + NLM_HOST_COLLECT; | 679 | if (net) { |
680 | struct lockd_net *ln = net_generic(net, lockd_net_id); | ||
681 | |||
682 | ln->next_gc = jiffies + NLM_HOST_COLLECT; | ||
683 | } | ||
652 | } | 684 | } |