NLM: Add helper to handle IPv4 addresses
[safe/jmp/linux-2.6] / fs / lockd / host.c
1 /*
2  * linux/fs/lockd/host.c
3  *
4  * Management for NLM peer hosts. The nlm_host struct is shared
5  * between client and server implementation. The only reason to
6  * do so is to reduce code bloat.
7  *
8  * Copyright (C) 1996, Olaf Kirch <okir@monad.swb.de>
9  */
10
11 #include <linux/types.h>
12 #include <linux/slab.h>
13 #include <linux/in.h>
14 #include <linux/in6.h>
15 #include <linux/sunrpc/clnt.h>
16 #include <linux/sunrpc/svc.h>
17 #include <linux/lockd/lockd.h>
18 #include <linux/lockd/sm_inter.h>
19 #include <linux/mutex.h>
20
21 #include <net/ipv6.h>
22
23 #define NLMDBG_FACILITY         NLMDBG_HOSTCACHE
24 #define NLM_HOST_NRHASH         32
25 #define NLM_HOST_REBIND         (60 * HZ)
26 #define NLM_HOST_EXPIRE         (300 * HZ)
27 #define NLM_HOST_COLLECT        (120 * HZ)
28
29 static struct hlist_head        nlm_hosts[NLM_HOST_NRHASH];
30 static unsigned long            next_gc;
31 static int                      nrhosts;
32 static DEFINE_MUTEX(nlm_host_mutex);
33
34 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
41 struct nlm_lookup_host_info {
42         const int               server;         /* search for server|client */
43         const struct sockaddr   *sap;           /* address to search for */
44         const size_t            salen;          /* it's length */
45         const unsigned short    protocol;       /* transport to search for*/
46         const u32               version;        /* NLM version to search for */
47         const char              *hostname;      /* remote's hostname */
48         const size_t            hostname_len;   /* it's length */
49         const struct sockaddr   *src_sap;       /* our address (optional) */
50         const size_t            src_len;        /* it's length */
51         const int               noresvport;     /* use non-priv port */
52 };
53
54 /*
55  * Hash function must work well on big- and little-endian platforms
56  */
57 static unsigned int __nlm_hash32(const __be32 n)
58 {
59         unsigned int hash = (__force u32)n ^ ((__force u32)n >> 16);
60         return hash ^ (hash >> 8);
61 }
62
63 static unsigned int __nlm_hash_addr4(const struct sockaddr *sap)
64 {
65         const struct sockaddr_in *sin = (struct sockaddr_in *)sap;
66         return __nlm_hash32(sin->sin_addr.s_addr);
67 }
68
69 static unsigned int __nlm_hash_addr6(const struct sockaddr *sap)
70 {
71         const struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sap;
72         const struct in6_addr addr = sin6->sin6_addr;
73         return __nlm_hash32(addr.s6_addr32[0]) ^
74                __nlm_hash32(addr.s6_addr32[1]) ^
75                __nlm_hash32(addr.s6_addr32[2]) ^
76                __nlm_hash32(addr.s6_addr32[3]);
77 }
78
79 static unsigned int nlm_hash_address(const struct sockaddr *sap)
80 {
81         unsigned int hash;
82
83         switch (sap->sa_family) {
84         case AF_INET:
85                 hash = __nlm_hash_addr4(sap);
86                 break;
87         case AF_INET6:
88                 hash = __nlm_hash_addr6(sap);
89                 break;
90         default:
91                 hash = 0;
92         }
93         return hash & (NLM_HOST_NRHASH - 1);
94 }
95
96 static void nlm_clear_port(struct sockaddr *sap)
97 {
98         switch (sap->sa_family) {
99         case AF_INET:
100                 ((struct sockaddr_in *)sap)->sin_port = 0;
101                 break;
102         case AF_INET6:
103                 ((struct sockaddr_in6 *)sap)->sin6_port = 0;
104                 break;
105         }
106 }
107
108 static void nlm_display_ipv4_address(const struct sockaddr *sap, char *buf,
109                                      const size_t len)
110 {
111         const struct sockaddr_in *sin = (struct sockaddr_in *)sap;
112         snprintf(buf, len, "%pI4", &sin->sin_addr.s_addr);
113 }
114
115 static void nlm_display_ipv6_address(const struct sockaddr *sap, char *buf,
116                                      const size_t len)
117 {
118         const struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sap;
119
120         if (ipv6_addr_v4mapped(&sin6->sin6_addr))
121                 snprintf(buf, len, "%pI4", &sin6->sin6_addr.s6_addr32[3]);
122         else if (sin6->sin6_scope_id != 0)
123                 snprintf(buf, len, "%pI6%%%u", &sin6->sin6_addr,
124                                 sin6->sin6_scope_id);
125         else
126                 snprintf(buf, len, "%pI6", &sin6->sin6_addr);
127 }
128
129 static void nlm_display_address(const struct sockaddr *sap,
130                                 char *buf, const size_t len)
131 {
132         switch (sap->sa_family) {
133         case AF_INET:
134                 nlm_display_ipv4_address(sap, buf, len);
135                 break;
136         case AF_INET6:
137                 nlm_display_ipv6_address(sap, buf, len);
138                 break;
139         default:
140                 snprintf(buf, len, "unsupported address family");
141                 break;
142         }
143 }
144
145 /*
146  * Common host lookup routine for server & client
147  */
148 static struct nlm_host *nlm_lookup_host(struct nlm_lookup_host_info *ni)
149 {
150         struct hlist_head *chain;
151         struct hlist_node *pos;
152         struct nlm_host *host;
153         struct nsm_handle *nsm = NULL;
154
155         mutex_lock(&nlm_host_mutex);
156
157         if (time_after_eq(jiffies, next_gc))
158                 nlm_gc_hosts();
159
160         /* We may keep several nlm_host objects for a peer, because each
161          * nlm_host is identified by
162          * (address, protocol, version, server/client)
163          * We could probably simplify this a little by putting all those
164          * different NLM rpc_clients into one single nlm_host object.
165          * This would allow us to have one nlm_host per address.
166          */
167         chain = &nlm_hosts[nlm_hash_address(ni->sap)];
168         hlist_for_each_entry(host, pos, chain, h_hash) {
169                 if (!nlm_cmp_addr(nlm_addr(host), ni->sap))
170                         continue;
171
172                 /* See if we have an NSM handle for this client */
173                 if (!nsm)
174                         nsm = host->h_nsmhandle;
175
176                 if (host->h_proto != ni->protocol)
177                         continue;
178                 if (host->h_version != ni->version)
179                         continue;
180                 if (host->h_server != ni->server)
181                         continue;
182                 if (ni->server &&
183                     !nlm_cmp_addr(nlm_srcaddr(host), ni->src_sap))
184                         continue;
185
186                 /* Move to head of hash chain. */
187                 hlist_del(&host->h_hash);
188                 hlist_add_head(&host->h_hash, chain);
189
190                 nlm_get_host(host);
191                 dprintk("lockd: nlm_lookup_host found host %s (%s)\n",
192                                 host->h_name, host->h_addrbuf);
193                 goto out;
194         }
195
196         /*
197          * The host wasn't in our hash table.  If we don't
198          * have an NSM handle for it yet, create one.
199          */
200         if (nsm)
201                 atomic_inc(&nsm->sm_count);
202         else {
203                 host = NULL;
204                 nsm = nsm_find(ni->sap, ni->salen,
205                                 ni->hostname, ni->hostname_len, 1);
206                 if (!nsm) {
207                         dprintk("lockd: nlm_lookup_host failed; "
208                                 "no nsm handle\n");
209                         goto out;
210                 }
211         }
212
213         host = kzalloc(sizeof(*host), GFP_KERNEL);
214         if (!host) {
215                 nsm_release(nsm);
216                 dprintk("lockd: nlm_lookup_host failed; no memory\n");
217                 goto out;
218         }
219         host->h_name       = nsm->sm_name;
220         host->h_addrbuf    = nsm->sm_addrbuf;
221         memcpy(nlm_addr(host), ni->sap, ni->salen);
222         host->h_addrlen = ni->salen;
223         nlm_clear_port(nlm_addr(host));
224         memcpy(nlm_srcaddr(host), ni->src_sap, ni->src_len);
225         host->h_version    = ni->version;
226         host->h_proto      = ni->protocol;
227         host->h_rpcclnt    = NULL;
228         mutex_init(&host->h_mutex);
229         host->h_nextrebind = jiffies + NLM_HOST_REBIND;
230         host->h_expires    = jiffies + NLM_HOST_EXPIRE;
231         atomic_set(&host->h_count, 1);
232         init_waitqueue_head(&host->h_gracewait);
233         init_rwsem(&host->h_rwsem);
234         host->h_state      = 0;                 /* pseudo NSM state */
235         host->h_nsmstate   = 0;                 /* real NSM state */
236         host->h_nsmhandle  = nsm;
237         host->h_server     = ni->server;
238         host->h_noresvport = ni->noresvport;
239         hlist_add_head(&host->h_hash, chain);
240         INIT_LIST_HEAD(&host->h_lockowners);
241         spin_lock_init(&host->h_lock);
242         INIT_LIST_HEAD(&host->h_granted);
243         INIT_LIST_HEAD(&host->h_reclaim);
244
245         nrhosts++;
246
247         dprintk("lockd: nlm_lookup_host created host %s\n",
248                         host->h_name);
249
250 out:
251         mutex_unlock(&nlm_host_mutex);
252         return host;
253 }
254
255 /*
256  * Destroy a host
257  */
258 static void
259 nlm_destroy_host(struct nlm_host *host)
260 {
261         struct rpc_clnt *clnt;
262
263         BUG_ON(!list_empty(&host->h_lockowners));
264         BUG_ON(atomic_read(&host->h_count));
265
266         /*
267          * Release NSM handle and unmonitor host.
268          */
269         nsm_unmonitor(host);
270
271         clnt = host->h_rpcclnt;
272         if (clnt != NULL)
273                 rpc_shutdown_client(clnt);
274         kfree(host);
275 }
276
277 /**
278  * nlmclnt_lookup_host - Find an NLM host handle matching a remote server
279  * @sap: network address of server
280  * @salen: length of server address
281  * @protocol: transport protocol to use
282  * @version: NLM protocol version
283  * @hostname: '\0'-terminated hostname of server
284  * @noresvport: 1 if non-privileged port should be used
285  *
286  * Returns an nlm_host structure that matches the passed-in
287  * [server address, transport protocol, NLM version, server hostname].
288  * If one doesn't already exist in the host cache, a new handle is
289  * created and returned.
290  */
291 struct nlm_host *nlmclnt_lookup_host(const struct sockaddr *sap,
292                                      const size_t salen,
293                                      const unsigned short protocol,
294                                      const u32 version,
295                                      const char *hostname,
296                                      int noresvport)
297 {
298         const struct sockaddr source = {
299                 .sa_family      = AF_UNSPEC,
300         };
301         struct nlm_lookup_host_info ni = {
302                 .server         = 0,
303                 .sap            = sap,
304                 .salen          = salen,
305                 .protocol       = protocol,
306                 .version        = version,
307                 .hostname       = hostname,
308                 .hostname_len   = strlen(hostname),
309                 .src_sap        = &source,
310                 .src_len        = sizeof(source),
311                 .noresvport     = noresvport,
312         };
313
314         dprintk("lockd: %s(host='%s', vers=%u, proto=%s)\n", __func__,
315                         (hostname ? hostname : "<none>"), version,
316                         (protocol == IPPROTO_UDP ? "udp" : "tcp"));
317
318         return nlm_lookup_host(&ni);
319 }
320
321 /**
322  * nlmsvc_lookup_host - Find an NLM host handle matching a remote client
323  * @rqstp: incoming NLM request
324  * @hostname: name of client host
325  * @hostname_len: length of client hostname
326  *
327  * Returns an nlm_host structure that matches the [client address,
328  * transport protocol, NLM version, client hostname] of the passed-in
329  * NLM request.  If one doesn't already exist in the host cache, a
330  * new handle is created and returned.
331  *
332  * Before possibly creating a new nlm_host, construct a sockaddr
333  * for a specific source address in case the local system has
334  * multiple network addresses.  The family of the address in
335  * rq_daddr is guaranteed to be the same as the family of the
336  * address in rq_addr, so it's safe to use the same family for
337  * the source address.
338  */
339 struct nlm_host *nlmsvc_lookup_host(const struct svc_rqst *rqstp,
340                                     const char *hostname,
341                                     const size_t hostname_len)
342 {
343         struct sockaddr_in sin = {
344                 .sin_family     = AF_INET,
345         };
346         struct sockaddr_in6 sin6 = {
347                 .sin6_family    = AF_INET6,
348         };
349         struct nlm_lookup_host_info ni = {
350                 .server         = 1,
351                 .sap            = svc_addr(rqstp),
352                 .salen          = rqstp->rq_addrlen,
353                 .protocol       = rqstp->rq_prot,
354                 .version        = rqstp->rq_vers,
355                 .hostname       = hostname,
356                 .hostname_len   = hostname_len,
357                 .src_len        = rqstp->rq_addrlen,
358         };
359
360         dprintk("lockd: %s(host='%*s', vers=%u, proto=%s)\n", __func__,
361                         (int)hostname_len, hostname, rqstp->rq_vers,
362                         (rqstp->rq_prot == IPPROTO_UDP ? "udp" : "tcp"));
363
364         switch (ni.sap->sa_family) {
365         case AF_INET:
366                 sin.sin_addr.s_addr = rqstp->rq_daddr.addr.s_addr;
367                 ni.src_sap = (struct sockaddr *)&sin;
368                 break;
369         case AF_INET6:
370                 ipv6_addr_copy(&sin6.sin6_addr, &rqstp->rq_daddr.addr6);
371                 ni.src_sap = (struct sockaddr *)&sin6;
372                 break;
373         default:
374                 return NULL;
375         }
376
377         return nlm_lookup_host(&ni);
378 }
379
380 /*
381  * Create the NLM RPC client for an NLM peer
382  */
383 struct rpc_clnt *
384 nlm_bind_host(struct nlm_host *host)
385 {
386         struct rpc_clnt *clnt;
387
388         dprintk("lockd: nlm_bind_host %s (%s)\n",
389                         host->h_name, host->h_addrbuf);
390
391         /* Lock host handle */
392         mutex_lock(&host->h_mutex);
393
394         /* If we've already created an RPC client, check whether
395          * RPC rebind is required
396          */
397         if ((clnt = host->h_rpcclnt) != NULL) {
398                 if (time_after_eq(jiffies, host->h_nextrebind)) {
399                         rpc_force_rebind(clnt);
400                         host->h_nextrebind = jiffies + NLM_HOST_REBIND;
401                         dprintk("lockd: next rebind in %lu jiffies\n",
402                                         host->h_nextrebind - jiffies);
403                 }
404         } else {
405                 unsigned long increment = nlmsvc_timeout;
406                 struct rpc_timeout timeparms = {
407                         .to_initval     = increment,
408                         .to_increment   = increment,
409                         .to_maxval      = increment * 6UL,
410                         .to_retries     = 5U,
411                 };
412                 struct rpc_create_args args = {
413                         .protocol       = host->h_proto,
414                         .address        = nlm_addr(host),
415                         .addrsize       = host->h_addrlen,
416                         .saddress       = nlm_srcaddr(host),
417                         .timeout        = &timeparms,
418                         .servername     = host->h_name,
419                         .program        = &nlm_program,
420                         .version        = host->h_version,
421                         .authflavor     = RPC_AUTH_UNIX,
422                         .flags          = (RPC_CLNT_CREATE_NOPING |
423                                            RPC_CLNT_CREATE_AUTOBIND),
424                 };
425
426                 /*
427                  * lockd retries server side blocks automatically so we want
428                  * those to be soft RPC calls. Client side calls need to be
429                  * hard RPC tasks.
430                  */
431                 if (!host->h_server)
432                         args.flags |= RPC_CLNT_CREATE_HARDRTRY;
433                 if (host->h_noresvport)
434                         args.flags |= RPC_CLNT_CREATE_NONPRIVPORT;
435
436                 clnt = rpc_create(&args);
437                 if (!IS_ERR(clnt))
438                         host->h_rpcclnt = clnt;
439                 else {
440                         printk("lockd: couldn't create RPC handle for %s\n", host->h_name);
441                         clnt = NULL;
442                 }
443         }
444
445         mutex_unlock(&host->h_mutex);
446         return clnt;
447 }
448
449 /*
450  * Force a portmap lookup of the remote lockd port
451  */
452 void
453 nlm_rebind_host(struct nlm_host *host)
454 {
455         dprintk("lockd: rebind host %s\n", host->h_name);
456         if (host->h_rpcclnt && time_after_eq(jiffies, host->h_nextrebind)) {
457                 rpc_force_rebind(host->h_rpcclnt);
458                 host->h_nextrebind = jiffies + NLM_HOST_REBIND;
459         }
460 }
461
462 /*
463  * Increment NLM host count
464  */
465 struct nlm_host * nlm_get_host(struct nlm_host *host)
466 {
467         if (host) {
468                 dprintk("lockd: get host %s\n", host->h_name);
469                 atomic_inc(&host->h_count);
470                 host->h_expires = jiffies + NLM_HOST_EXPIRE;
471         }
472         return host;
473 }
474
475 /*
476  * Release NLM host after use
477  */
478 void nlm_release_host(struct nlm_host *host)
479 {
480         if (host != NULL) {
481                 dprintk("lockd: release host %s\n", host->h_name);
482                 BUG_ON(atomic_read(&host->h_count) < 0);
483                 if (atomic_dec_and_test(&host->h_count)) {
484                         BUG_ON(!list_empty(&host->h_lockowners));
485                         BUG_ON(!list_empty(&host->h_granted));
486                         BUG_ON(!list_empty(&host->h_reclaim));
487                 }
488         }
489 }
490
491 /*
492  * We were notified that the host indicated by address &sin
493  * has rebooted.
494  * Release all resources held by that peer.
495  */
496 void nlm_host_rebooted(const struct sockaddr_in *sin,
497                                 const char *hostname,
498                                 unsigned int hostname_len,
499                                 u32 new_state)
500 {
501         struct hlist_head *chain;
502         struct hlist_node *pos;
503         struct nsm_handle *nsm;
504         struct nlm_host *host;
505
506         nsm = nsm_find((struct sockaddr *)sin, sizeof(*sin),
507                         hostname, hostname_len, 0);
508         if (nsm == NULL) {
509                 dprintk("lockd: never saw rebooted peer '%.*s' before\n",
510                                 hostname_len, hostname);
511                 return;
512         }
513
514         dprintk("lockd: nlm_host_rebooted(%.*s, %s)\n",
515                         hostname_len, hostname, nsm->sm_addrbuf);
516
517         /* When reclaiming locks on this peer, make sure that
518          * we set up a new notification */
519         nsm->sm_monitored = 0;
520
521         /* Mark all hosts tied to this NSM state as having rebooted.
522          * We run the loop repeatedly, because we drop the host table
523          * lock for this.
524          * To avoid processing a host several times, we match the nsmstate.
525          */
526 again:  mutex_lock(&nlm_host_mutex);
527         for (chain = nlm_hosts; chain < nlm_hosts + NLM_HOST_NRHASH; ++chain) {
528                 hlist_for_each_entry(host, pos, chain, h_hash) {
529                         if (host->h_nsmhandle == nsm
530                          && host->h_nsmstate != new_state) {
531                                 host->h_nsmstate = new_state;
532                                 host->h_state++;
533
534                                 nlm_get_host(host);
535                                 mutex_unlock(&nlm_host_mutex);
536
537                                 if (host->h_server) {
538                                         /* We're server for this guy, just ditch
539                                          * all the locks he held. */
540                                         nlmsvc_free_host_resources(host);
541                                 } else {
542                                         /* He's the server, initiate lock recovery. */
543                                         nlmclnt_recovery(host);
544                                 }
545
546                                 nlm_release_host(host);
547                                 goto again;
548                         }
549                 }
550         }
551
552         mutex_unlock(&nlm_host_mutex);
553 }
554
555 /*
556  * Shut down the hosts module.
557  * Note that this routine is called only at server shutdown time.
558  */
559 void
560 nlm_shutdown_hosts(void)
561 {
562         struct hlist_head *chain;
563         struct hlist_node *pos;
564         struct nlm_host *host;
565
566         dprintk("lockd: shutting down host module\n");
567         mutex_lock(&nlm_host_mutex);
568
569         /* First, make all hosts eligible for gc */
570         dprintk("lockd: nuking all hosts...\n");
571         for (chain = nlm_hosts; chain < nlm_hosts + NLM_HOST_NRHASH; ++chain) {
572                 hlist_for_each_entry(host, pos, chain, h_hash) {
573                         host->h_expires = jiffies - 1;
574                         if (host->h_rpcclnt) {
575                                 rpc_shutdown_client(host->h_rpcclnt);
576                                 host->h_rpcclnt = NULL;
577                         }
578                 }
579         }
580
581         /* Then, perform a garbage collection pass */
582         nlm_gc_hosts();
583         mutex_unlock(&nlm_host_mutex);
584
585         /* complain if any hosts are left */
586         if (nrhosts) {
587                 printk(KERN_WARNING "lockd: couldn't shutdown host module!\n");
588                 dprintk("lockd: %d hosts left:\n", nrhosts);
589                 for (chain = nlm_hosts; chain < nlm_hosts + NLM_HOST_NRHASH; ++chain) {
590                         hlist_for_each_entry(host, pos, chain, h_hash) {
591                                 dprintk("       %s (cnt %d use %d exp %ld)\n",
592                                         host->h_name, atomic_read(&host->h_count),
593                                         host->h_inuse, host->h_expires);
594                         }
595                 }
596         }
597 }
598
599 /*
600  * Garbage collect any unused NLM hosts.
601  * This GC combines reference counting for async operations with
602  * mark & sweep for resources held by remote clients.
603  */
604 static void
605 nlm_gc_hosts(void)
606 {
607         struct hlist_head *chain;
608         struct hlist_node *pos, *next;
609         struct nlm_host *host;
610
611         dprintk("lockd: host garbage collection\n");
612         for (chain = nlm_hosts; chain < nlm_hosts + NLM_HOST_NRHASH; ++chain) {
613                 hlist_for_each_entry(host, pos, chain, h_hash)
614                         host->h_inuse = 0;
615         }
616
617         /* Mark all hosts that hold locks, blocks or shares */
618         nlmsvc_mark_resources();
619
620         for (chain = nlm_hosts; chain < nlm_hosts + NLM_HOST_NRHASH; ++chain) {
621                 hlist_for_each_entry_safe(host, pos, next, chain, h_hash) {
622                         if (atomic_read(&host->h_count) || host->h_inuse
623                          || time_before(jiffies, host->h_expires)) {
624                                 dprintk("nlm_gc_hosts skipping %s (cnt %d use %d exp %ld)\n",
625                                         host->h_name, atomic_read(&host->h_count),
626                                         host->h_inuse, host->h_expires);
627                                 continue;
628                         }
629                         dprintk("lockd: delete host %s\n", host->h_name);
630                         hlist_del_init(&host->h_hash);
631
632                         nlm_destroy_host(host);
633                         nrhosts--;
634                 }
635         }
636
637         next_gc = jiffies + NLM_HOST_COLLECT;
638 }
639
640
641 /*
642  * Manage NSM handles
643  */
644 static LIST_HEAD(nsm_handles);
645 static DEFINE_SPINLOCK(nsm_lock);
646
647 static struct nsm_handle *nsm_find(const struct sockaddr *sap,
648                                    const size_t salen,
649                                    const char *hostname,
650                                    const size_t hostname_len,
651                                    const int create)
652 {
653         struct nsm_handle *nsm = NULL;
654         struct nsm_handle *pos;
655
656         if (!sap)
657                 return NULL;
658
659         if (hostname && memchr(hostname, '/', hostname_len) != NULL) {
660                 if (printk_ratelimit()) {
661                         printk(KERN_WARNING "Invalid hostname \"%.*s\" "
662                                             "in NFS lock request\n",
663                                 (int)hostname_len, hostname);
664                 }
665                 return NULL;
666         }
667
668 retry:
669         spin_lock(&nsm_lock);
670         list_for_each_entry(pos, &nsm_handles, sm_link) {
671
672                 if (hostname && nsm_use_hostnames) {
673                         if (strlen(pos->sm_name) != hostname_len
674                          || memcmp(pos->sm_name, hostname, hostname_len))
675                                 continue;
676                 } else if (!nlm_cmp_addr(nsm_addr(pos), sap))
677                         continue;
678                 atomic_inc(&pos->sm_count);
679                 kfree(nsm);
680                 nsm = pos;
681                 goto found;
682         }
683         if (nsm) {
684                 list_add(&nsm->sm_link, &nsm_handles);
685                 goto found;
686         }
687         spin_unlock(&nsm_lock);
688
689         if (!create)
690                 return NULL;
691
692         nsm = kzalloc(sizeof(*nsm) + hostname_len + 1, GFP_KERNEL);
693         if (nsm == NULL)
694                 return NULL;
695
696         memcpy(nsm_addr(nsm), sap, salen);
697         nsm->sm_addrlen = salen;
698         nsm->sm_name = (char *) (nsm + 1);
699         memcpy(nsm->sm_name, hostname, hostname_len);
700         nsm->sm_name[hostname_len] = '\0';
701         nlm_display_address((struct sockaddr *)&nsm->sm_addr,
702                                 nsm->sm_addrbuf, sizeof(nsm->sm_addrbuf));
703         atomic_set(&nsm->sm_count, 1);
704         goto retry;
705
706 found:
707         spin_unlock(&nsm_lock);
708         return nsm;
709 }
710
711 /*
712  * Release an NSM handle
713  */
714 void
715 nsm_release(struct nsm_handle *nsm)
716 {
717         if (!nsm)
718                 return;
719         if (atomic_dec_and_lock(&nsm->sm_count, &nsm_lock)) {
720                 list_del(&nsm->sm_link);
721                 spin_unlock(&nsm_lock);
722                 kfree(nsm);
723         }
724 }