diff options
Diffstat (limited to 'fs/lockd/host.c')
-rw-r--r-- | fs/lockd/host.c | 170 |
1 files changed, 17 insertions, 153 deletions
diff --git a/fs/lockd/host.c b/fs/lockd/host.c index abdebf76b820..99d737bd4325 100644 --- a/fs/lockd/host.c +++ b/fs/lockd/host.c | |||
@@ -15,7 +15,6 @@ | |||
15 | #include <linux/sunrpc/clnt.h> | 15 | #include <linux/sunrpc/clnt.h> |
16 | #include <linux/sunrpc/svc.h> | 16 | #include <linux/sunrpc/svc.h> |
17 | #include <linux/lockd/lockd.h> | 17 | #include <linux/lockd/lockd.h> |
18 | #include <linux/lockd/sm_inter.h> | ||
19 | #include <linux/mutex.h> | 18 | #include <linux/mutex.h> |
20 | 19 | ||
21 | #include <net/ipv6.h> | 20 | #include <net/ipv6.h> |
@@ -32,11 +31,6 @@ static int nrhosts; | |||
32 | static DEFINE_MUTEX(nlm_host_mutex); | 31 | static DEFINE_MUTEX(nlm_host_mutex); |
33 | 32 | ||
34 | static void nlm_gc_hosts(void); | 33 | static void nlm_gc_hosts(void); |
35 | static struct nsm_handle *nsm_find(const struct sockaddr *sap, | ||
36 | const size_t salen, | ||
37 | const char *hostname, | ||
38 | const size_t hostname_len, | ||
39 | const int create); | ||
40 | 34 | ||
41 | struct nlm_lookup_host_info { | 35 | struct nlm_lookup_host_info { |
42 | const int server; /* search for server|client */ | 36 | const int server; /* search for server|client */ |
@@ -105,32 +99,6 @@ static void nlm_clear_port(struct sockaddr *sap) | |||
105 | } | 99 | } |
106 | } | 100 | } |
107 | 101 | ||
108 | static void nlm_display_address(const struct sockaddr *sap, | ||
109 | char *buf, const size_t len) | ||
110 | { | ||
111 | const struct sockaddr_in *sin = (struct sockaddr_in *)sap; | ||
112 | const struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sap; | ||
113 | |||
114 | switch (sap->sa_family) { | ||
115 | case AF_UNSPEC: | ||
116 | snprintf(buf, len, "unspecified"); | ||
117 | break; | ||
118 | case AF_INET: | ||
119 | snprintf(buf, len, "%pI4", &sin->sin_addr.s_addr); | ||
120 | break; | ||
121 | case AF_INET6: | ||
122 | if (ipv6_addr_v4mapped(&sin6->sin6_addr)) | ||
123 | snprintf(buf, len, "%pI4", | ||
124 | &sin6->sin6_addr.s6_addr32[3]); | ||
125 | else | ||
126 | snprintf(buf, len, "%pI6", &sin6->sin6_addr); | ||
127 | break; | ||
128 | default: | ||
129 | snprintf(buf, len, "unsupported address family"); | ||
130 | break; | ||
131 | } | ||
132 | } | ||
133 | |||
134 | /* | 102 | /* |
135 | * Common host lookup routine for server & client | 103 | * Common host lookup routine for server & client |
136 | */ | 104 | */ |
@@ -190,8 +158,8 @@ static struct nlm_host *nlm_lookup_host(struct nlm_lookup_host_info *ni) | |||
190 | atomic_inc(&nsm->sm_count); | 158 | atomic_inc(&nsm->sm_count); |
191 | else { | 159 | else { |
192 | host = NULL; | 160 | host = NULL; |
193 | nsm = nsm_find(ni->sap, ni->salen, | 161 | nsm = nsm_get_handle(ni->sap, ni->salen, |
194 | ni->hostname, ni->hostname_len, 1); | 162 | ni->hostname, ni->hostname_len); |
195 | if (!nsm) { | 163 | if (!nsm) { |
196 | dprintk("lockd: nlm_lookup_host failed; " | 164 | dprintk("lockd: nlm_lookup_host failed; " |
197 | "no nsm handle\n"); | 165 | "no nsm handle\n"); |
@@ -206,6 +174,7 @@ static struct nlm_host *nlm_lookup_host(struct nlm_lookup_host_info *ni) | |||
206 | goto out; | 174 | goto out; |
207 | } | 175 | } |
208 | host->h_name = nsm->sm_name; | 176 | host->h_name = nsm->sm_name; |
177 | host->h_addrbuf = nsm->sm_addrbuf; | ||
209 | memcpy(nlm_addr(host), ni->sap, ni->salen); | 178 | memcpy(nlm_addr(host), ni->sap, ni->salen); |
210 | host->h_addrlen = ni->salen; | 179 | host->h_addrlen = ni->salen; |
211 | nlm_clear_port(nlm_addr(host)); | 180 | nlm_clear_port(nlm_addr(host)); |
@@ -232,11 +201,6 @@ static struct nlm_host *nlm_lookup_host(struct nlm_lookup_host_info *ni) | |||
232 | 201 | ||
233 | nrhosts++; | 202 | nrhosts++; |
234 | 203 | ||
235 | nlm_display_address((struct sockaddr *)&host->h_addr, | ||
236 | host->h_addrbuf, sizeof(host->h_addrbuf)); | ||
237 | nlm_display_address((struct sockaddr *)&host->h_srcaddr, | ||
238 | host->h_srcaddrbuf, sizeof(host->h_srcaddrbuf)); | ||
239 | |||
240 | dprintk("lockd: nlm_lookup_host created host %s\n", | 204 | dprintk("lockd: nlm_lookup_host created host %s\n", |
241 | host->h_name); | 205 | host->h_name); |
242 | 206 | ||
@@ -256,10 +220,8 @@ nlm_destroy_host(struct nlm_host *host) | |||
256 | BUG_ON(!list_empty(&host->h_lockowners)); | 220 | BUG_ON(!list_empty(&host->h_lockowners)); |
257 | BUG_ON(atomic_read(&host->h_count)); | 221 | BUG_ON(atomic_read(&host->h_count)); |
258 | 222 | ||
259 | /* | ||
260 | * Release NSM handle and unmonitor host. | ||
261 | */ | ||
262 | nsm_unmonitor(host); | 223 | nsm_unmonitor(host); |
224 | nsm_release(host->h_nsmhandle); | ||
263 | 225 | ||
264 | clnt = host->h_rpcclnt; | 226 | clnt = host->h_rpcclnt; |
265 | if (clnt != NULL) | 227 | if (clnt != NULL) |
@@ -378,8 +340,8 @@ nlm_bind_host(struct nlm_host *host) | |||
378 | { | 340 | { |
379 | struct rpc_clnt *clnt; | 341 | struct rpc_clnt *clnt; |
380 | 342 | ||
381 | dprintk("lockd: nlm_bind_host %s (%s), my addr=%s\n", | 343 | dprintk("lockd: nlm_bind_host %s (%s)\n", |
382 | host->h_name, host->h_addrbuf, host->h_srcaddrbuf); | 344 | host->h_name, host->h_addrbuf); |
383 | 345 | ||
384 | /* Lock host handle */ | 346 | /* Lock host handle */ |
385 | mutex_lock(&host->h_mutex); | 347 | mutex_lock(&host->h_mutex); |
@@ -481,35 +443,23 @@ void nlm_release_host(struct nlm_host *host) | |||
481 | } | 443 | } |
482 | } | 444 | } |
483 | 445 | ||
484 | /* | 446 | /** |
485 | * We were notified that the host indicated by address &sin | 447 | * nlm_host_rebooted - Release all resources held by rebooted host |
486 | * has rebooted. | 448 | * @info: pointer to decoded results of NLM_SM_NOTIFY call |
487 | * Release all resources held by that peer. | 449 | * |
450 | * We were notified that the specified host has rebooted. Release | ||
451 | * all resources held by that peer. | ||
488 | */ | 452 | */ |
489 | void nlm_host_rebooted(const struct sockaddr_in *sin, | 453 | void nlm_host_rebooted(const struct nlm_reboot *info) |
490 | const char *hostname, | ||
491 | unsigned int hostname_len, | ||
492 | u32 new_state) | ||
493 | { | 454 | { |
494 | struct hlist_head *chain; | 455 | struct hlist_head *chain; |
495 | struct hlist_node *pos; | 456 | struct hlist_node *pos; |
496 | struct nsm_handle *nsm; | 457 | struct nsm_handle *nsm; |
497 | struct nlm_host *host; | 458 | struct nlm_host *host; |
498 | 459 | ||
499 | nsm = nsm_find((struct sockaddr *)sin, sizeof(*sin), | 460 | nsm = nsm_reboot_lookup(info); |
500 | hostname, hostname_len, 0); | 461 | if (unlikely(nsm == NULL)) |
501 | if (nsm == NULL) { | ||
502 | dprintk("lockd: never saw rebooted peer '%.*s' before\n", | ||
503 | hostname_len, hostname); | ||
504 | return; | 462 | return; |
505 | } | ||
506 | |||
507 | dprintk("lockd: nlm_host_rebooted(%.*s, %s)\n", | ||
508 | hostname_len, hostname, nsm->sm_addrbuf); | ||
509 | |||
510 | /* When reclaiming locks on this peer, make sure that | ||
511 | * we set up a new notification */ | ||
512 | nsm->sm_monitored = 0; | ||
513 | 463 | ||
514 | /* Mark all hosts tied to this NSM state as having rebooted. | 464 | /* Mark all hosts tied to this NSM state as having rebooted. |
515 | * We run the loop repeatedly, because we drop the host table | 465 | * We run the loop repeatedly, because we drop the host table |
@@ -520,8 +470,8 @@ again: mutex_lock(&nlm_host_mutex); | |||
520 | for (chain = nlm_hosts; chain < nlm_hosts + NLM_HOST_NRHASH; ++chain) { | 470 | for (chain = nlm_hosts; chain < nlm_hosts + NLM_HOST_NRHASH; ++chain) { |
521 | hlist_for_each_entry(host, pos, chain, h_hash) { | 471 | hlist_for_each_entry(host, pos, chain, h_hash) { |
522 | if (host->h_nsmhandle == nsm | 472 | if (host->h_nsmhandle == nsm |
523 | && host->h_nsmstate != new_state) { | 473 | && host->h_nsmstate != info->state) { |
524 | host->h_nsmstate = new_state; | 474 | host->h_nsmstate = info->state; |
525 | host->h_state++; | 475 | host->h_state++; |
526 | 476 | ||
527 | nlm_get_host(host); | 477 | nlm_get_host(host); |
@@ -629,89 +579,3 @@ nlm_gc_hosts(void) | |||
629 | 579 | ||
630 | next_gc = jiffies + NLM_HOST_COLLECT; | 580 | next_gc = jiffies + NLM_HOST_COLLECT; |
631 | } | 581 | } |
632 | |||
633 | |||
634 | /* | ||
635 | * Manage NSM handles | ||
636 | */ | ||
637 | static LIST_HEAD(nsm_handles); | ||
638 | static DEFINE_SPINLOCK(nsm_lock); | ||
639 | |||
640 | static struct nsm_handle *nsm_find(const struct sockaddr *sap, | ||
641 | const size_t salen, | ||
642 | const char *hostname, | ||
643 | const size_t hostname_len, | ||
644 | const int create) | ||
645 | { | ||
646 | struct nsm_handle *nsm = NULL; | ||
647 | struct nsm_handle *pos; | ||
648 | |||
649 | if (!sap) | ||
650 | return NULL; | ||
651 | |||
652 | if (hostname && memchr(hostname, '/', hostname_len) != NULL) { | ||
653 | if (printk_ratelimit()) { | ||
654 | printk(KERN_WARNING "Invalid hostname \"%.*s\" " | ||
655 | "in NFS lock request\n", | ||
656 | (int)hostname_len, hostname); | ||
657 | } | ||
658 | return NULL; | ||
659 | } | ||
660 | |||
661 | retry: | ||
662 | spin_lock(&nsm_lock); | ||
663 | list_for_each_entry(pos, &nsm_handles, sm_link) { | ||
664 | |||
665 | if (hostname && nsm_use_hostnames) { | ||
666 | if (strlen(pos->sm_name) != hostname_len | ||
667 | || memcmp(pos->sm_name, hostname, hostname_len)) | ||
668 | continue; | ||
669 | } else if (!nlm_cmp_addr(nsm_addr(pos), sap)) | ||
670 | continue; | ||
671 | atomic_inc(&pos->sm_count); | ||
672 | kfree(nsm); | ||
673 | nsm = pos; | ||
674 | goto found; | ||
675 | } | ||
676 | if (nsm) { | ||
677 | list_add(&nsm->sm_link, &nsm_handles); | ||
678 | goto found; | ||
679 | } | ||
680 | spin_unlock(&nsm_lock); | ||
681 | |||
682 | if (!create) | ||
683 | return NULL; | ||
684 | |||
685 | nsm = kzalloc(sizeof(*nsm) + hostname_len + 1, GFP_KERNEL); | ||
686 | if (nsm == NULL) | ||
687 | return NULL; | ||
688 | |||
689 | memcpy(nsm_addr(nsm), sap, salen); | ||
690 | nsm->sm_addrlen = salen; | ||
691 | nsm->sm_name = (char *) (nsm + 1); | ||
692 | memcpy(nsm->sm_name, hostname, hostname_len); | ||
693 | nsm->sm_name[hostname_len] = '\0'; | ||
694 | nlm_display_address((struct sockaddr *)&nsm->sm_addr, | ||
695 | nsm->sm_addrbuf, sizeof(nsm->sm_addrbuf)); | ||
696 | atomic_set(&nsm->sm_count, 1); | ||
697 | goto retry; | ||
698 | |||
699 | found: | ||
700 | spin_unlock(&nsm_lock); | ||
701 | return nsm; | ||
702 | } | ||
703 | |||
704 | /* | ||
705 | * Release an NSM handle | ||
706 | */ | ||
707 | void | ||
708 | nsm_release(struct nsm_handle *nsm) | ||
709 | { | ||
710 | if (!nsm) | ||
711 | return; | ||
712 | if (atomic_dec_and_lock(&nsm->sm_count, &nsm_lock)) { | ||
713 | list_del(&nsm->sm_link); | ||
714 | spin_unlock(&nsm_lock); | ||
715 | kfree(nsm); | ||
716 | } | ||
717 | } | ||