aboutsummaryrefslogtreecommitdiffstats
path: root/fs/lockd/host.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/lockd/host.c')
-rw-r--r--fs/lockd/host.c92
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
44static unsigned long next_gc;
45static unsigned long nrhosts; 46static unsigned long nrhosts;
46static DEFINE_MUTEX(nlm_host_mutex); 47static DEFINE_MUTEX(nlm_host_mutex);
47 48
48static void nlm_gc_hosts(void); 49static void nlm_gc_hosts(struct net *net);
49 50
50struct nlm_lookup_host_info { 51struct 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:
172static void nlm_destroy_host_locked(struct nlm_host *host) 173static 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
575static 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
568void 604void
569nlm_shutdown_hosts_net(struct net *net) 605nlm_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)
599void 636void
600nlm_shutdown_hosts(void) 637nlm_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 */
625static void 648static void
626nlm_gc_hosts(void) 649nlm_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}