]> CyberLeo.Net >> Repos - FreeBSD/stable/8.git/blob - sys/nlm/nlm_prot_impl.c
Copy head to stable/8 as part of 8.0 Release cycle.
[FreeBSD/stable/8.git] / sys / nlm / nlm_prot_impl.c
1 /*-
2  * Copyright (c) 2008 Isilon Inc http://www.isilon.com/
3  * Authors: Doug Rabson <dfr@rabson.org>
4  * Developed with Red Inc: Alfred Perlstein <alfred@freebsd.org>
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25  * SUCH DAMAGE.
26  */
27
28 #include "opt_inet6.h"
29 #include "opt_nfs.h"
30
31 #include <sys/cdefs.h>
32 __FBSDID("$FreeBSD$");
33
34 #include <sys/param.h>
35 #include <sys/fcntl.h>
36 #include <sys/kernel.h>
37 #include <sys/kthread.h>
38 #include <sys/lockf.h>
39 #include <sys/malloc.h>
40 #include <sys/mount.h>
41 #if __FreeBSD_version >= 700000
42 #include <sys/priv.h>
43 #endif
44 #include <sys/proc.h>
45 #include <sys/socket.h>
46 #include <sys/socketvar.h>
47 #include <sys/syscall.h>
48 #include <sys/sysctl.h>
49 #include <sys/sysent.h>
50 #include <sys/syslog.h>
51 #include <sys/sysproto.h>
52 #include <sys/systm.h>
53 #include <sys/taskqueue.h>
54 #include <sys/unistd.h>
55 #include <sys/vnode.h>
56
57 #include <nfs/nfsproto.h>
58 #include <nfsclient/nfs.h>
59 #include <nfsclient/nfsnode.h>
60
61 #include <nlm/nlm_prot.h>
62 #include <nlm/sm_inter.h>
63 #include <nlm/nlm.h>
64 #include <rpc/rpc_com.h>
65 #include <rpc/rpcb_prot.h>
66
67 MALLOC_DEFINE(M_NLM, "NLM", "Network Lock Manager");
68
69 /*
70  * If a host is inactive (and holds no locks) for this amount of
71  * seconds, we consider it idle and stop tracking it.
72  */
73 #define NLM_IDLE_TIMEOUT        30
74
75 /*
76  * We check the host list for idle every few seconds.
77  */
78 #define NLM_IDLE_PERIOD         5
79
80 /*
81  * Support for sysctl vfs.nlm.sysid
82  */
83 SYSCTL_NODE(_vfs, OID_AUTO, nlm, CTLFLAG_RW, NULL, "Network Lock Manager");
84 SYSCTL_NODE(_vfs_nlm, OID_AUTO, sysid, CTLFLAG_RW, NULL, "");
85
86 /*
87  * Syscall hooks
88  */
89 static int nlm_syscall_offset = SYS_nlm_syscall;
90 static struct sysent nlm_syscall_prev_sysent;
91 #if __FreeBSD_version < 700000
92 static struct sysent nlm_syscall_sysent = {
93         (sizeof(struct nlm_syscall_args) / sizeof(register_t)) | SYF_MPSAFE,
94         (sy_call_t *) nlm_syscall
95 };
96 #else
97 MAKE_SYSENT(nlm_syscall);
98 #endif
99 static bool_t nlm_syscall_registered = FALSE;
100
101 /*
102  * Debug level passed in from userland. We also support a sysctl hook
103  * so that it can be changed on a live system.
104  */
105 static int nlm_debug_level;
106 SYSCTL_INT(_debug, OID_AUTO, nlm_debug, CTLFLAG_RW, &nlm_debug_level, 0, "");
107
108 #define NLM_DEBUG(_level, args...)                      \
109         do {                                            \
110                 if (nlm_debug_level >= (_level))        \
111                         log(LOG_DEBUG, args);           \
112         } while(0)
113 #define NLM_ERR(args...)                        \
114         do {                                    \
115                 log(LOG_ERR, args);             \
116         } while(0)
117
118 /*
119  * Grace period handling. The value of nlm_grace_threshold is the
120  * value of time_uptime after which we are serving requests normally.
121  */
122 static time_t nlm_grace_threshold;
123
124 /*
125  * We check for idle hosts if time_uptime is greater than
126  * nlm_next_idle_check,
127  */
128 static time_t nlm_next_idle_check;
129
130 /*
131  * A socket to use for RPC - shared by all IPv4 RPC clients.
132  */
133 static struct socket *nlm_socket;
134
135 #ifdef INET6
136
137 /*
138  * A socket to use for RPC - shared by all IPv6 RPC clients.
139  */
140 static struct socket *nlm_socket6;
141
142 #endif
143
144 /*
145  * An RPC client handle that can be used to communicate with the local
146  * NSM.
147  */
148 static CLIENT *nlm_nsm;
149
150 /*
151  * An AUTH handle for the server's creds.
152  */
153 static AUTH *nlm_auth;
154
155 /*
156  * A zero timeval for sending async RPC messages.
157  */
158 struct timeval nlm_zero_tv = { 0, 0 };
159
160 /*
161  * The local NSM state number
162  */
163 int nlm_nsm_state;
164
165
166 /*
167  * A lock to protect the host list and waiting lock list.
168  */
169 static struct mtx nlm_global_lock;
170
171 /*
172  * Locks:
173  * (l)          locked by nh_lock
174  * (s)          only accessed via server RPC which is single threaded
175  * (g)          locked by nlm_global_lock
176  * (c)          const until freeing
177  * (a)          modified using atomic ops
178  */
179
180 /*
181  * A pending client-side lock request, stored on the nlm_waiting_locks
182  * list.
183  */
184 struct nlm_waiting_lock {
185         TAILQ_ENTRY(nlm_waiting_lock) nw_link; /* (g) */
186         bool_t          nw_waiting;            /* (g) */
187         nlm4_lock       nw_lock;               /* (c) */
188         union nfsfh     nw_fh;                 /* (c) */
189         struct vnode    *nw_vp;                /* (c) */
190 };
191 TAILQ_HEAD(nlm_waiting_lock_list, nlm_waiting_lock);
192
193 struct nlm_waiting_lock_list nlm_waiting_locks; /* (g) */
194
195 /*
196  * A pending server-side asynchronous lock request, stored on the
197  * nh_pending list of the NLM host.
198  */
199 struct nlm_async_lock {
200         TAILQ_ENTRY(nlm_async_lock) af_link; /* (l) host's list of locks */
201         struct task     af_task;        /* (c) async callback details */
202         void            *af_cookie;     /* (l) lock manager cancel token */
203         struct vnode    *af_vp;         /* (l) vnode to lock */
204         struct flock    af_fl;          /* (c) lock details */
205         struct nlm_host *af_host;       /* (c) host which is locking */
206         CLIENT          *af_rpc;        /* (c) rpc client to send message */
207         nlm4_testargs   af_granted;     /* (c) notification details */
208 };
209 TAILQ_HEAD(nlm_async_lock_list, nlm_async_lock);
210
211 /*
212  * NLM host.
213  */
214 enum nlm_host_state {
215         NLM_UNMONITORED,
216         NLM_MONITORED,
217         NLM_MONITOR_FAILED,
218         NLM_RECOVERING
219 };
220
221 struct nlm_rpc {
222         CLIENT          *nr_client;    /* (l) RPC client handle */
223         time_t          nr_create_time; /* (l) when client was created */
224 };
225
226 struct nlm_host {
227         struct mtx      nh_lock;
228         volatile u_int  nh_refs;       /* (a) reference count */
229         TAILQ_ENTRY(nlm_host) nh_link; /* (g) global list of hosts */
230         char            nh_caller_name[MAXNAMELEN]; /* (c) printable name of host */
231         uint32_t        nh_sysid;        /* (c) our allocaed system ID */
232         char            nh_sysid_string[10]; /* (c) string rep. of sysid */
233         struct sockaddr_storage nh_addr; /* (s) remote address of host */
234         struct nlm_rpc  nh_srvrpc;       /* (l) RPC for server replies */
235         struct nlm_rpc  nh_clntrpc;      /* (l) RPC for client requests */
236         rpcvers_t       nh_vers;         /* (s) NLM version of host */
237         int             nh_state;        /* (s) last seen NSM state of host */
238         enum nlm_host_state nh_monstate; /* (l) local NSM monitoring state */
239         time_t          nh_idle_timeout; /* (s) Time at which host is idle */
240         struct sysctl_ctx_list nh_sysctl; /* (c) vfs.nlm.sysid nodes */
241         struct nlm_async_lock_list nh_pending; /* (l) pending async locks */
242         struct nlm_async_lock_list nh_finished; /* (l) finished async locks */
243 };
244 TAILQ_HEAD(nlm_host_list, nlm_host);
245
246 static struct nlm_host_list nlm_hosts; /* (g) */
247 static uint32_t nlm_next_sysid = 1;    /* (g) */
248
249 static void     nlm_host_unmonitor(struct nlm_host *);
250
251 /**********************************************************************/
252
253 /*
254  * Initialise NLM globals.
255  */
256 static void
257 nlm_init(void *dummy)
258 {
259         int error;
260
261         mtx_init(&nlm_global_lock, "nlm_global_lock", NULL, MTX_DEF);
262         TAILQ_INIT(&nlm_waiting_locks);
263         TAILQ_INIT(&nlm_hosts);
264
265         error = syscall_register(&nlm_syscall_offset, &nlm_syscall_sysent,
266             &nlm_syscall_prev_sysent);
267         if (error)
268                 NLM_ERR("Can't register NLM syscall\n");
269         else
270                 nlm_syscall_registered = TRUE;
271 }
272 SYSINIT(nlm_init, SI_SUB_LOCK, SI_ORDER_FIRST, nlm_init, NULL);
273
274 static void
275 nlm_uninit(void *dummy)
276 {
277
278         if (nlm_syscall_registered)
279                 syscall_deregister(&nlm_syscall_offset,
280                     &nlm_syscall_prev_sysent);
281 }
282 SYSUNINIT(nlm_uninit, SI_SUB_LOCK, SI_ORDER_FIRST, nlm_uninit, NULL);
283
284 /*
285  * Copy a struct netobj.
286  */ 
287 void
288 nlm_copy_netobj(struct netobj *dst, struct netobj *src,
289     struct malloc_type *type)
290 {
291
292         dst->n_len = src->n_len;
293         dst->n_bytes = malloc(src->n_len, type, M_WAITOK);
294         memcpy(dst->n_bytes, src->n_bytes, src->n_len);
295 }
296
297 /*
298  * Create an RPC client handle for the given (address,prog,vers)
299  * triple using UDP.
300  */
301 static CLIENT *
302 nlm_get_rpc(struct sockaddr *sa, rpcprog_t prog, rpcvers_t vers)
303 {
304         char *wchan = "nlmrcv";
305         const char* protofmly;
306         struct sockaddr_storage ss;
307         struct socket *so;
308         CLIENT *rpcb;
309         struct timeval timo;
310         RPCB parms;
311         char *uaddr;
312         enum clnt_stat stat = RPC_SUCCESS;
313         int rpcvers = RPCBVERS4;
314         bool_t do_tcp = FALSE;
315         bool_t tryagain = FALSE;
316         struct portmap mapping;
317         u_short port = 0;
318
319         /*
320          * First we need to contact the remote RPCBIND service to find
321          * the right port.
322          */
323         memcpy(&ss, sa, sa->sa_len);
324         switch (ss.ss_family) {
325         case AF_INET:
326                 ((struct sockaddr_in *)&ss)->sin_port = htons(111);
327                 protofmly = "inet";
328                 so = nlm_socket;
329                 break;
330                 
331 #ifdef INET6
332         case AF_INET6:
333                 ((struct sockaddr_in6 *)&ss)->sin6_port = htons(111);
334                 protofmly = "inet6";
335                 so = nlm_socket6;
336                 break;
337 #endif
338
339         default:
340                 /*
341                  * Unsupported address family - fail.
342                  */
343                 return (NULL);
344         }
345
346         rpcb = clnt_dg_create(so, (struct sockaddr *)&ss,
347             RPCBPROG, rpcvers, 0, 0);
348         if (!rpcb)
349                 return (NULL);
350
351 try_tcp:
352         parms.r_prog = prog;
353         parms.r_vers = vers;
354         if (do_tcp)
355                 parms.r_netid = "tcp";
356         else
357                 parms.r_netid = "udp";
358         parms.r_addr = "";
359         parms.r_owner = "";
360
361         /*
362          * Use the default timeout.
363          */
364         timo.tv_sec = 25;
365         timo.tv_usec = 0;
366 again:
367         switch (rpcvers) {
368         case RPCBVERS4:
369         case RPCBVERS:
370                 /*
371                  * Try RPCBIND 4 then 3.
372                  */
373                 uaddr = NULL;
374                 stat = CLNT_CALL(rpcb, (rpcprog_t) RPCBPROC_GETADDR,
375                     (xdrproc_t) xdr_rpcb, &parms,
376                     (xdrproc_t) xdr_wrapstring, &uaddr, timo);
377                 if (stat == RPC_SUCCESS) {
378                         /*
379                          * We have a reply from the remote RPCBIND - turn it
380                          * into an appropriate address and make a new client
381                          * that can talk to the remote NLM.
382                          *
383                          * XXX fixup IPv6 scope ID.
384                          */
385                         struct netbuf *a;
386                         a = __rpc_uaddr2taddr_af(ss.ss_family, uaddr);
387                         if (!a) {
388                                 tryagain = TRUE;
389                         } else {
390                                 tryagain = FALSE;
391                                 memcpy(&ss, a->buf, a->len);
392                                 free(a->buf, M_RPC);
393                                 free(a, M_RPC);
394                                 xdr_free((xdrproc_t) xdr_wrapstring, &uaddr);
395                         }
396                 }
397                 if (tryagain || stat == RPC_PROGVERSMISMATCH) {
398                         if (rpcvers == RPCBVERS4)
399                                 rpcvers = RPCBVERS;
400                         else if (rpcvers == RPCBVERS)
401                                 rpcvers = PMAPVERS;
402                         CLNT_CONTROL(rpcb, CLSET_VERS, &rpcvers);
403                         goto again;
404                 }
405                 break;
406         case PMAPVERS:
407                 /*
408                  * Try portmap.
409                  */
410                 mapping.pm_prog = parms.r_prog;
411                 mapping.pm_vers = parms.r_vers;
412                 mapping.pm_prot = do_tcp ? IPPROTO_TCP : IPPROTO_UDP;
413                 mapping.pm_port = 0;
414
415                 stat = CLNT_CALL(rpcb, (rpcprog_t) PMAPPROC_GETPORT,
416                     (xdrproc_t) xdr_portmap, &mapping,
417                     (xdrproc_t) xdr_u_short, &port, timo);
418
419                 if (stat == RPC_SUCCESS) {
420                         switch (ss.ss_family) {
421                         case AF_INET:
422                                 ((struct sockaddr_in *)&ss)->sin_port =
423                                         htons(port);
424                                 break;
425                 
426 #ifdef INET6
427                         case AF_INET6:
428                                 ((struct sockaddr_in6 *)&ss)->sin6_port =
429                                         htons(port);
430                                 break;
431 #endif
432                         }
433                 }
434                 break;
435         default:
436                 panic("invalid rpcvers %d", rpcvers);
437         }
438         /*
439          * We may have a positive response from the portmapper, but the NLM
440          * service was not found. Make sure we received a valid port.
441          */
442         switch (ss.ss_family) {
443         case AF_INET:
444                 port = ((struct sockaddr_in *)&ss)->sin_port;
445                 break;
446 #ifdef INET6
447         case AF_INET6:
448                 port = ((struct sockaddr_in6 *)&ss)->sin6_port;
449                 break;
450 #endif
451         }
452         if (stat != RPC_SUCCESS || !port) {
453                 /*
454                  * If we were able to talk to rpcbind or portmap, but the udp
455                  * variant wasn't available, ask about tcp.
456                  *
457                  * XXX - We could also check for a TCP portmapper, but
458                  * if the host is running a portmapper at all, we should be able
459                  * to hail it over UDP.
460                  */
461                 if (stat == RPC_SUCCESS && !do_tcp) {
462                         do_tcp = TRUE;
463                         goto try_tcp;
464                 }
465
466                 /* Otherwise, bad news. */
467                 NLM_ERR("NLM: failed to contact remote rpcbind, "
468                     "stat = %d, port = %d\n", (int) stat, port);
469                 CLNT_DESTROY(rpcb);
470                 return (NULL);
471         }
472
473         if (do_tcp) {
474                 /*
475                  * Destroy the UDP client we used to speak to rpcbind and
476                  * recreate as a TCP client.
477                  */
478                 struct netconfig *nconf = NULL;
479
480                 CLNT_DESTROY(rpcb);
481
482                 switch (ss.ss_family) {
483                 case AF_INET:
484                         nconf = getnetconfigent("tcp");
485                         break;
486 #ifdef INET6
487                 case AF_INET6:
488                         nconf = getnetconfigent("tcp6");
489                         break;
490 #endif
491                 }
492
493                 rpcb = clnt_reconnect_create(nconf, (struct sockaddr *)&ss,
494                     prog, vers, 0, 0);
495                 CLNT_CONTROL(rpcb, CLSET_WAITCHAN, wchan);
496                 rpcb->cl_auth = nlm_auth;
497                 
498         } else {
499                 /*
500                  * Re-use the client we used to speak to rpcbind.
501                  */
502                 CLNT_CONTROL(rpcb, CLSET_SVC_ADDR, &ss);
503                 CLNT_CONTROL(rpcb, CLSET_PROG, &prog);
504                 CLNT_CONTROL(rpcb, CLSET_VERS, &vers);
505                 CLNT_CONTROL(rpcb, CLSET_WAITCHAN, wchan);
506                 rpcb->cl_auth = nlm_auth;
507         }
508
509         return (rpcb);
510 }
511
512 /*
513  * This async callback after when an async lock request has been
514  * granted. We notify the host which initiated the request.
515  */
516 static void
517 nlm_lock_callback(void *arg, int pending)
518 {
519         struct nlm_async_lock *af = (struct nlm_async_lock *) arg;
520         struct rpc_callextra ext;
521
522         NLM_DEBUG(2, "NLM: async lock %p for %s (sysid %d) granted\n",
523             af, af->af_host->nh_caller_name, af->af_host->nh_sysid);
524
525         /*
526          * Send the results back to the host.
527          *
528          * Note: there is a possible race here with nlm_host_notify
529          * destroying the RPC client. To avoid problems, the first
530          * thing nlm_host_notify does is to cancel pending async lock
531          * requests.
532          */
533         memset(&ext, 0, sizeof(ext));
534         ext.rc_auth = nlm_auth;
535         if (af->af_host->nh_vers == NLM_VERS4) {
536                 nlm4_granted_msg_4(&af->af_granted,
537                     NULL, af->af_rpc, &ext, nlm_zero_tv);
538         } else {
539                 /*
540                  * Back-convert to legacy protocol
541                  */
542                 nlm_testargs granted;
543                 granted.cookie = af->af_granted.cookie;
544                 granted.exclusive = af->af_granted.exclusive;
545                 granted.alock.caller_name =
546                         af->af_granted.alock.caller_name;
547                 granted.alock.fh = af->af_granted.alock.fh;
548                 granted.alock.oh = af->af_granted.alock.oh;
549                 granted.alock.svid = af->af_granted.alock.svid;
550                 granted.alock.l_offset =
551                         af->af_granted.alock.l_offset;
552                 granted.alock.l_len =
553                         af->af_granted.alock.l_len;
554
555                 nlm_granted_msg_1(&granted,
556                     NULL, af->af_rpc, &ext, nlm_zero_tv);
557         }
558
559         /*
560          * Move this entry to the nh_finished list. Someone else will
561          * free it later - its too hard to do it here safely without
562          * racing with cancel.
563          *
564          * XXX possibly we should have a third "granted sent but not
565          * ack'ed" list so that we can re-send the granted message.
566          */
567         mtx_lock(&af->af_host->nh_lock);
568         TAILQ_REMOVE(&af->af_host->nh_pending, af, af_link);
569         TAILQ_INSERT_TAIL(&af->af_host->nh_finished, af, af_link);
570         mtx_unlock(&af->af_host->nh_lock);
571 }
572
573 /*
574  * Free an async lock request. The request must have been removed from
575  * any list.
576  */
577 static void
578 nlm_free_async_lock(struct nlm_async_lock *af)
579 {
580         /*
581          * Free an async lock.
582          */
583         if (af->af_rpc)
584                 CLNT_RELEASE(af->af_rpc);
585         xdr_free((xdrproc_t) xdr_nlm4_testargs, &af->af_granted);
586         if (af->af_vp)
587                 vrele(af->af_vp);
588         free(af, M_NLM);
589 }
590
591 /*
592  * Cancel our async request - this must be called with
593  * af->nh_host->nh_lock held. This is slightly complicated by a
594  * potential race with our own callback. If we fail to cancel the
595  * lock, it must already have been granted - we make sure our async
596  * task has completed by calling taskqueue_drain in this case.
597  */
598 static int
599 nlm_cancel_async_lock(struct nlm_async_lock *af)
600 {
601         struct nlm_host *host = af->af_host;
602         int error;
603
604         mtx_assert(&host->nh_lock, MA_OWNED);
605
606         mtx_unlock(&host->nh_lock);
607
608         error = VOP_ADVLOCKASYNC(af->af_vp, NULL, F_CANCEL, &af->af_fl,
609             F_REMOTE, NULL, &af->af_cookie);
610
611         if (error) {
612                 /*
613                  * We failed to cancel - make sure our callback has
614                  * completed before we continue.
615                  */
616                 taskqueue_drain(taskqueue_thread, &af->af_task);
617         }
618
619         mtx_lock(&host->nh_lock);
620         
621         if (!error) {
622                 NLM_DEBUG(2, "NLM: async lock %p for %s (sysid %d) "
623                     "cancelled\n", af, host->nh_caller_name, host->nh_sysid);
624
625                 /*
626                  * Remove from the nh_pending list and free now that
627                  * we are safe from the callback.
628                  */
629                 TAILQ_REMOVE(&host->nh_pending, af, af_link);
630                 mtx_unlock(&host->nh_lock);
631                 nlm_free_async_lock(af);
632                 mtx_lock(&host->nh_lock);
633         }
634
635         return (error);
636 }
637
638 static void
639 nlm_free_finished_locks(struct nlm_host *host)
640 {
641         struct nlm_async_lock *af;
642
643         mtx_lock(&host->nh_lock);
644         while ((af = TAILQ_FIRST(&host->nh_finished)) != NULL) {
645                 TAILQ_REMOVE(&host->nh_finished, af, af_link);
646                 mtx_unlock(&host->nh_lock);
647                 nlm_free_async_lock(af);
648                 mtx_lock(&host->nh_lock);
649         }
650         mtx_unlock(&host->nh_lock);
651 }
652
653 /*
654  * Free resources used by a host. This is called after the reference
655  * count has reached zero so it doesn't need to worry about locks.
656  */
657 static void
658 nlm_host_destroy(struct nlm_host *host)
659 {
660
661         mtx_lock(&nlm_global_lock);
662         TAILQ_REMOVE(&nlm_hosts, host, nh_link);
663         mtx_unlock(&nlm_global_lock);
664
665         if (host->nh_srvrpc.nr_client)
666                 CLNT_RELEASE(host->nh_srvrpc.nr_client);
667         if (host->nh_clntrpc.nr_client)
668                 CLNT_RELEASE(host->nh_clntrpc.nr_client);
669         mtx_destroy(&host->nh_lock);
670         sysctl_ctx_free(&host->nh_sysctl);
671         free(host, M_NLM);
672 }
673
674 #ifdef NFSCLIENT
675
676 /*
677  * Thread start callback for client lock recovery
678  */
679 static void
680 nlm_client_recovery_start(void *arg)
681 {
682         struct nlm_host *host = (struct nlm_host *) arg;
683
684         NLM_DEBUG(1, "NLM: client lock recovery for %s started\n",
685             host->nh_caller_name);
686
687         nlm_client_recovery(host);
688
689         NLM_DEBUG(1, "NLM: client lock recovery for %s completed\n",
690             host->nh_caller_name);
691
692         host->nh_monstate = NLM_MONITORED;
693         nlm_host_release(host);
694
695         kthread_exit();
696 }
697
698 #endif
699
700 /*
701  * This is called when we receive a host state change notification. We
702  * unlock any active locks owned by the host. When rpc.lockd is
703  * shutting down, this function is called with newstate set to zero
704  * which allows us to cancel any pending async locks and clear the
705  * locking state.
706  */
707 static void
708 nlm_host_notify(struct nlm_host *host, int newstate)
709 {
710         struct nlm_async_lock *af;
711
712         if (newstate) {
713                 NLM_DEBUG(1, "NLM: host %s (sysid %d) rebooted, new "
714                     "state is %d\n", host->nh_caller_name,
715                     host->nh_sysid, newstate);
716         }
717
718         /*
719          * Cancel any pending async locks for this host.
720          */
721         mtx_lock(&host->nh_lock);
722         while ((af = TAILQ_FIRST(&host->nh_pending)) != NULL) {
723                 /*
724                  * nlm_cancel_async_lock will remove the entry from
725                  * nh_pending and free it.
726                  */
727                 nlm_cancel_async_lock(af);
728         }
729         mtx_unlock(&host->nh_lock);
730         nlm_free_finished_locks(host);
731
732         /*
733          * The host just rebooted - trash its locks.
734          */
735         lf_clearremotesys(host->nh_sysid);
736         host->nh_state = newstate;
737
738 #ifdef NFSCLIENT
739         /*
740          * If we have any remote locks for this host (i.e. it
741          * represents a remote NFS server that our local NFS client
742          * has locks for), start a recovery thread.
743          */
744         if (newstate != 0
745             && host->nh_monstate != NLM_RECOVERING
746             && lf_countlocks(NLM_SYSID_CLIENT | host->nh_sysid) > 0) {
747                 struct thread *td;
748                 host->nh_monstate = NLM_RECOVERING;
749                 refcount_acquire(&host->nh_refs);
750                 kthread_add(nlm_client_recovery_start, host, curproc, &td, 0, 0,
751                     "NFS lock recovery for %s", host->nh_caller_name);
752         }
753 #endif
754 }
755
756 /*
757  * Sysctl handler to count the number of locks for a sysid.
758  */
759 static int
760 nlm_host_lock_count_sysctl(SYSCTL_HANDLER_ARGS)
761 {
762         struct nlm_host *host;
763         int count;
764
765         host = oidp->oid_arg1;
766         count = lf_countlocks(host->nh_sysid);
767         return sysctl_handle_int(oidp, &count, 0, req);
768 }
769
770 /*
771  * Sysctl handler to count the number of client locks for a sysid.
772  */
773 static int
774 nlm_host_client_lock_count_sysctl(SYSCTL_HANDLER_ARGS)
775 {
776         struct nlm_host *host;
777         int count;
778
779         host = oidp->oid_arg1;
780         count = lf_countlocks(NLM_SYSID_CLIENT | host->nh_sysid);
781         return sysctl_handle_int(oidp, &count, 0, req);
782 }
783
784 /*
785  * Create a new NLM host.
786  */
787 static struct nlm_host *
788 nlm_create_host(const char* caller_name)
789 {
790         struct nlm_host *host;
791         struct sysctl_oid *oid;
792
793         mtx_assert(&nlm_global_lock, MA_OWNED);
794
795         NLM_DEBUG(1, "NLM: new host %s (sysid %d)\n",
796             caller_name, nlm_next_sysid);
797         host = malloc(sizeof(struct nlm_host), M_NLM, M_NOWAIT|M_ZERO);
798         if (!host)
799                 return (NULL);
800         mtx_init(&host->nh_lock, "nh_lock", NULL, MTX_DEF);
801         host->nh_refs = 1;
802         strlcpy(host->nh_caller_name, caller_name, MAXNAMELEN);
803         host->nh_sysid = nlm_next_sysid++;
804         snprintf(host->nh_sysid_string, sizeof(host->nh_sysid_string),
805                 "%d", host->nh_sysid);
806         host->nh_vers = 0;
807         host->nh_state = 0;
808         host->nh_monstate = NLM_UNMONITORED;
809         TAILQ_INIT(&host->nh_pending);
810         TAILQ_INIT(&host->nh_finished);
811         TAILQ_INSERT_TAIL(&nlm_hosts, host, nh_link);
812
813         mtx_unlock(&nlm_global_lock);
814
815         sysctl_ctx_init(&host->nh_sysctl);
816         oid = SYSCTL_ADD_NODE(&host->nh_sysctl,
817             SYSCTL_STATIC_CHILDREN(_vfs_nlm_sysid),
818             OID_AUTO, host->nh_sysid_string, CTLFLAG_RD, NULL, "");
819         SYSCTL_ADD_STRING(&host->nh_sysctl, SYSCTL_CHILDREN(oid), OID_AUTO,
820             "hostname", CTLFLAG_RD, host->nh_caller_name, 0, "");
821         SYSCTL_ADD_INT(&host->nh_sysctl, SYSCTL_CHILDREN(oid), OID_AUTO,
822             "version", CTLFLAG_RD, &host->nh_vers, 0, "");
823         SYSCTL_ADD_INT(&host->nh_sysctl, SYSCTL_CHILDREN(oid), OID_AUTO,
824             "monitored", CTLFLAG_RD, &host->nh_monstate, 0, "");
825         SYSCTL_ADD_PROC(&host->nh_sysctl, SYSCTL_CHILDREN(oid), OID_AUTO,
826             "lock_count", CTLTYPE_INT | CTLFLAG_RD, host, 0,
827             nlm_host_lock_count_sysctl, "I", "");
828         SYSCTL_ADD_PROC(&host->nh_sysctl, SYSCTL_CHILDREN(oid), OID_AUTO,
829             "client_lock_count", CTLTYPE_INT | CTLFLAG_RD, host, 0,
830             nlm_host_client_lock_count_sysctl, "I", "");
831
832         mtx_lock(&nlm_global_lock);
833
834         return (host);
835 }
836
837 /*
838  * Acquire the next sysid for remote locks not handled by the NLM.
839  */
840 uint32_t
841 nlm_acquire_next_sysid(void)
842 {
843         uint32_t next_sysid;
844
845         mtx_lock(&nlm_global_lock);
846         next_sysid = nlm_next_sysid++;
847         mtx_unlock(&nlm_global_lock);
848         return (next_sysid);
849 }
850
851 /*
852  * Return non-zero if the address parts of the two sockaddrs are the
853  * same.
854  */
855 static int
856 nlm_compare_addr(const struct sockaddr *a, const struct sockaddr *b)
857 {
858         const struct sockaddr_in *a4, *b4;
859 #ifdef INET6
860         const struct sockaddr_in6 *a6, *b6;
861 #endif
862
863         if (a->sa_family != b->sa_family)
864                 return (FALSE);
865
866         switch (a->sa_family) {
867         case AF_INET:
868                 a4 = (const struct sockaddr_in *) a;
869                 b4 = (const struct sockaddr_in *) b;
870                 return !memcmp(&a4->sin_addr, &b4->sin_addr,
871                     sizeof(a4->sin_addr));
872 #ifdef INET6
873         case AF_INET6:
874                 a6 = (const struct sockaddr_in6 *) a;
875                 b6 = (const struct sockaddr_in6 *) b;
876                 return !memcmp(&a6->sin6_addr, &b6->sin6_addr,
877                     sizeof(a6->sin6_addr));
878 #endif
879         }
880
881         return (0);
882 }
883
884 /*
885  * Check for idle hosts and stop monitoring them. We could also free
886  * the host structure here, possibly after a larger timeout but that
887  * would require some care to avoid races with
888  * e.g. nlm_host_lock_count_sysctl.
889  */
890 static void
891 nlm_check_idle(void)
892 {
893         struct nlm_host *host;
894
895         mtx_assert(&nlm_global_lock, MA_OWNED);
896
897         if (time_uptime <= nlm_next_idle_check)
898                 return;
899
900         nlm_next_idle_check = time_uptime + NLM_IDLE_PERIOD;
901
902         TAILQ_FOREACH(host, &nlm_hosts, nh_link) {
903                 if (host->nh_monstate == NLM_MONITORED
904                     && time_uptime > host->nh_idle_timeout) {
905                         mtx_unlock(&nlm_global_lock);
906                         if (lf_countlocks(host->nh_sysid) > 0
907                             || lf_countlocks(NLM_SYSID_CLIENT
908                                 + host->nh_sysid)) {
909                                 host->nh_idle_timeout =
910                                         time_uptime + NLM_IDLE_TIMEOUT;
911                                 mtx_lock(&nlm_global_lock);
912                                 continue;
913                         }
914                         nlm_host_unmonitor(host);
915                         mtx_lock(&nlm_global_lock);
916                 } 
917         }
918 }
919
920 /*
921  * Search for an existing NLM host that matches the given name
922  * (typically the caller_name element of an nlm4_lock).  If none is
923  * found, create a new host. If 'addr' is non-NULL, record the remote
924  * address of the host so that we can call it back for async
925  * responses. If 'vers' is greater than zero then record the NLM
926  * program version to use to communicate with this client.
927  */
928 struct nlm_host *
929 nlm_find_host_by_name(const char *name, const struct sockaddr *addr,
930     rpcvers_t vers)
931 {
932         struct nlm_host *host;
933
934         mtx_lock(&nlm_global_lock);
935
936         /*
937          * The remote host is determined by caller_name.
938          */
939         TAILQ_FOREACH(host, &nlm_hosts, nh_link) {
940                 if (!strcmp(host->nh_caller_name, name))
941                         break;
942         }
943
944         if (!host) {
945                 host = nlm_create_host(name);
946                 if (!host) {
947                         mtx_unlock(&nlm_global_lock);
948                         return (NULL);
949                 }
950         }
951         refcount_acquire(&host->nh_refs);
952
953         host->nh_idle_timeout = time_uptime + NLM_IDLE_TIMEOUT;
954
955         /*
956          * If we have an address for the host, record it so that we
957          * can send async replies etc.
958          */
959         if (addr) {
960                 
961                 KASSERT(addr->sa_len < sizeof(struct sockaddr_storage),
962                     ("Strange remote transport address length"));
963
964                 /*
965                  * If we have seen an address before and we currently
966                  * have an RPC client handle, make sure the address is
967                  * the same, otherwise discard the client handle.
968                  */
969                 if (host->nh_addr.ss_len && host->nh_srvrpc.nr_client) {
970                         if (!nlm_compare_addr(
971                                     (struct sockaddr *) &host->nh_addr,
972                                     addr)
973                             || host->nh_vers != vers) {
974                                 CLIENT *client;
975                                 mtx_lock(&host->nh_lock);
976                                 client = host->nh_srvrpc.nr_client;
977                                 host->nh_srvrpc.nr_client = NULL;
978                                 mtx_unlock(&host->nh_lock);
979                                 if (client) {
980                                         CLNT_RELEASE(client);
981                                 }
982                         }
983                 }
984                 memcpy(&host->nh_addr, addr, addr->sa_len);
985                 host->nh_vers = vers;
986         }
987
988         nlm_check_idle();
989
990         mtx_unlock(&nlm_global_lock);
991
992         return (host);
993 }
994
995 /*
996  * Search for an existing NLM host that matches the given remote
997  * address. If none is found, create a new host with the requested
998  * address and remember 'vers' as the NLM protocol version to use for
999  * that host.
1000  */
1001 struct nlm_host *
1002 nlm_find_host_by_addr(const struct sockaddr *addr, int vers)
1003 {
1004         /*
1005          * Fake up a name using inet_ntop. This buffer is
1006          * large enough for an IPv6 address.
1007          */
1008         char tmp[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255"];
1009         struct nlm_host *host;
1010
1011         switch (addr->sa_family) {
1012         case AF_INET:
1013                 __rpc_inet_ntop(AF_INET,
1014                     &((const struct sockaddr_in *) addr)->sin_addr,
1015                     tmp, sizeof tmp);
1016                 break;
1017 #ifdef INET6
1018         case AF_INET6:
1019                 __rpc_inet_ntop(AF_INET6,
1020                     &((const struct sockaddr_in6 *) addr)->sin6_addr,
1021                     tmp, sizeof tmp);
1022                 break;
1023 #endif
1024         default:
1025                 strcmp(tmp, "<unknown>");
1026         }
1027
1028
1029         mtx_lock(&nlm_global_lock);
1030
1031         /*
1032          * The remote host is determined by caller_name.
1033          */
1034         TAILQ_FOREACH(host, &nlm_hosts, nh_link) {
1035                 if (nlm_compare_addr(addr,
1036                         (const struct sockaddr *) &host->nh_addr))
1037                         break;
1038         }
1039
1040         if (!host) {
1041                 host = nlm_create_host(tmp);
1042                 if (!host) {
1043                         mtx_unlock(&nlm_global_lock);
1044                         return (NULL);
1045                 }
1046                 memcpy(&host->nh_addr, addr, addr->sa_len);
1047                 host->nh_vers = vers;
1048         }
1049         refcount_acquire(&host->nh_refs);
1050
1051         host->nh_idle_timeout = time_uptime + NLM_IDLE_TIMEOUT;
1052
1053         nlm_check_idle();
1054
1055         mtx_unlock(&nlm_global_lock);
1056
1057         return (host);
1058 }
1059
1060 /*
1061  * Find the NLM host that matches the value of 'sysid'. If none
1062  * exists, return NULL.
1063  */
1064 static struct nlm_host *
1065 nlm_find_host_by_sysid(int sysid)
1066 {
1067         struct nlm_host *host;
1068
1069         TAILQ_FOREACH(host, &nlm_hosts, nh_link) {
1070                 if (host->nh_sysid == sysid) {
1071                         refcount_acquire(&host->nh_refs);
1072                         return (host);
1073                 }
1074         }
1075
1076         return (NULL);
1077 }
1078
1079 void nlm_host_release(struct nlm_host *host)
1080 {
1081         if (refcount_release(&host->nh_refs)) {
1082                 /*
1083                  * Free the host
1084                  */
1085                 nlm_host_destroy(host);
1086         }
1087 }
1088
1089 /*
1090  * Unregister this NLM host with the local NSM due to idleness.
1091  */
1092 static void
1093 nlm_host_unmonitor(struct nlm_host *host)
1094 {
1095         mon_id smmonid;
1096         sm_stat_res smstat;
1097         struct timeval timo;
1098         enum clnt_stat stat;
1099
1100         NLM_DEBUG(1, "NLM: unmonitoring %s (sysid %d)\n",
1101             host->nh_caller_name, host->nh_sysid);
1102
1103         /*
1104          * We put our assigned system ID value in the priv field to
1105          * make it simpler to find the host if we are notified of a
1106          * host restart.
1107          */
1108         smmonid.mon_name = host->nh_caller_name;
1109         smmonid.my_id.my_name = "localhost";
1110         smmonid.my_id.my_prog = NLM_PROG;
1111         smmonid.my_id.my_vers = NLM_SM;
1112         smmonid.my_id.my_proc = NLM_SM_NOTIFY;
1113
1114         timo.tv_sec = 25;
1115         timo.tv_usec = 0;
1116         stat = CLNT_CALL(nlm_nsm, SM_UNMON,
1117             (xdrproc_t) xdr_mon, &smmonid,
1118             (xdrproc_t) xdr_sm_stat, &smstat, timo);
1119
1120         if (stat != RPC_SUCCESS) {
1121                 NLM_ERR("Failed to contact local NSM - rpc error %d\n", stat);
1122                 return;
1123         }
1124         if (smstat.res_stat == stat_fail) {
1125                 NLM_ERR("Local NSM refuses to unmonitor %s\n",
1126                     host->nh_caller_name);
1127                 return;
1128         }
1129
1130         host->nh_monstate = NLM_UNMONITORED;
1131 }
1132
1133 /*
1134  * Register this NLM host with the local NSM so that we can be
1135  * notified if it reboots.
1136  */
1137 void
1138 nlm_host_monitor(struct nlm_host *host, int state)
1139 {
1140         mon smmon;
1141         sm_stat_res smstat;
1142         struct timeval timo;
1143         enum clnt_stat stat;
1144
1145         if (state && !host->nh_state) {
1146                 /*
1147                  * This is the first time we have seen an NSM state
1148                  * value for this host. We record it here to help
1149                  * detect host reboots.
1150                  */
1151                 host->nh_state = state;
1152                 NLM_DEBUG(1, "NLM: host %s (sysid %d) has NSM state %d\n",
1153                     host->nh_caller_name, host->nh_sysid, state);
1154         }
1155
1156         mtx_lock(&host->nh_lock);
1157         if (host->nh_monstate != NLM_UNMONITORED) {
1158                 mtx_unlock(&host->nh_lock);
1159                 return;
1160         }
1161         host->nh_monstate = NLM_MONITORED;
1162         mtx_unlock(&host->nh_lock);
1163
1164         NLM_DEBUG(1, "NLM: monitoring %s (sysid %d)\n",
1165             host->nh_caller_name, host->nh_sysid);
1166
1167         /*
1168          * We put our assigned system ID value in the priv field to
1169          * make it simpler to find the host if we are notified of a
1170          * host restart.
1171          */
1172         smmon.mon_id.mon_name = host->nh_caller_name;
1173         smmon.mon_id.my_id.my_name = "localhost";
1174         smmon.mon_id.my_id.my_prog = NLM_PROG;
1175         smmon.mon_id.my_id.my_vers = NLM_SM;
1176         smmon.mon_id.my_id.my_proc = NLM_SM_NOTIFY;
1177         memcpy(smmon.priv, &host->nh_sysid, sizeof(host->nh_sysid));
1178
1179         timo.tv_sec = 25;
1180         timo.tv_usec = 0;
1181         stat = CLNT_CALL(nlm_nsm, SM_MON,
1182             (xdrproc_t) xdr_mon, &smmon,
1183             (xdrproc_t) xdr_sm_stat, &smstat, timo);
1184
1185         if (stat != RPC_SUCCESS) {
1186                 NLM_ERR("Failed to contact local NSM - rpc error %d\n", stat);
1187                 return;
1188         }
1189         if (smstat.res_stat == stat_fail) {
1190                 NLM_ERR("Local NSM refuses to monitor %s\n",
1191                     host->nh_caller_name);
1192                 mtx_lock(&host->nh_lock);
1193                 host->nh_monstate = NLM_MONITOR_FAILED;
1194                 mtx_unlock(&host->nh_lock);
1195                 return;
1196         }
1197
1198         host->nh_monstate = NLM_MONITORED;
1199 }
1200
1201 /*
1202  * Return an RPC client handle that can be used to talk to the NLM
1203  * running on the given host.
1204  */
1205 CLIENT *
1206 nlm_host_get_rpc(struct nlm_host *host, bool_t isserver)
1207 {
1208         struct nlm_rpc *rpc;
1209         CLIENT *client;
1210
1211         mtx_lock(&host->nh_lock);
1212
1213         if (isserver)
1214                 rpc = &host->nh_srvrpc;
1215         else
1216                 rpc = &host->nh_clntrpc;
1217
1218         /*
1219          * We can't hold onto RPC handles for too long - the async
1220          * call/reply protocol used by some NLM clients makes it hard
1221          * to tell when they change port numbers (e.g. after a
1222          * reboot). Note that if a client reboots while it isn't
1223          * holding any locks, it won't bother to notify us. We
1224          * expire the RPC handles after two minutes.
1225          */
1226         if (rpc->nr_client && time_uptime > rpc->nr_create_time + 2*60) {
1227                 client = rpc->nr_client;
1228                 rpc->nr_client = NULL;
1229                 mtx_unlock(&host->nh_lock);
1230                 CLNT_RELEASE(client);
1231                 mtx_lock(&host->nh_lock);
1232         }
1233
1234         if (!rpc->nr_client) {
1235                 mtx_unlock(&host->nh_lock);
1236                 client = nlm_get_rpc((struct sockaddr *)&host->nh_addr,
1237                     NLM_PROG, host->nh_vers);
1238                 mtx_lock(&host->nh_lock);
1239
1240                 if (client) {
1241                         if (rpc->nr_client) {
1242                                 mtx_unlock(&host->nh_lock);
1243                                 CLNT_DESTROY(client);
1244                                 mtx_lock(&host->nh_lock);
1245                         } else {
1246                                 rpc->nr_client = client;
1247                                 rpc->nr_create_time = time_uptime;
1248                         }
1249                 }
1250         }
1251
1252         client = rpc->nr_client;
1253         if (client)
1254                 CLNT_ACQUIRE(client);
1255         mtx_unlock(&host->nh_lock);
1256
1257         return (client);
1258
1259 }
1260
1261 int nlm_host_get_sysid(struct nlm_host *host)
1262 {
1263
1264         return (host->nh_sysid);
1265 }
1266
1267 int
1268 nlm_host_get_state(struct nlm_host *host)
1269 {
1270
1271         return (host->nh_state);
1272 }
1273
1274 void *
1275 nlm_register_wait_lock(struct nlm4_lock *lock, struct vnode *vp)
1276 {
1277         struct nlm_waiting_lock *nw;
1278
1279         nw = malloc(sizeof(struct nlm_waiting_lock), M_NLM, M_WAITOK);
1280         nw->nw_lock = *lock;
1281         memcpy(&nw->nw_fh.fh_bytes, nw->nw_lock.fh.n_bytes,
1282             nw->nw_lock.fh.n_len);
1283         nw->nw_lock.fh.n_bytes = nw->nw_fh.fh_bytes;
1284         nw->nw_waiting = TRUE;
1285         nw->nw_vp = vp;
1286         mtx_lock(&nlm_global_lock);
1287         TAILQ_INSERT_TAIL(&nlm_waiting_locks, nw, nw_link);
1288         mtx_unlock(&nlm_global_lock);
1289
1290         return nw;
1291 }
1292
1293 void
1294 nlm_deregister_wait_lock(void *handle)
1295 {
1296         struct nlm_waiting_lock *nw = handle;
1297
1298         mtx_lock(&nlm_global_lock);
1299         TAILQ_REMOVE(&nlm_waiting_locks, nw, nw_link);
1300         mtx_unlock(&nlm_global_lock);
1301         
1302         free(nw, M_NLM);
1303 }
1304
1305 int
1306 nlm_wait_lock(void *handle, int timo)
1307 {
1308         struct nlm_waiting_lock *nw = handle;
1309         int error;
1310
1311         /*
1312          * If the granted message arrived before we got here,
1313          * nw->nw_waiting will be FALSE - in that case, don't sleep.
1314          */
1315         mtx_lock(&nlm_global_lock);
1316         error = 0;
1317         if (nw->nw_waiting)
1318                 error = msleep(nw, &nlm_global_lock, PCATCH, "nlmlock", timo);
1319         TAILQ_REMOVE(&nlm_waiting_locks, nw, nw_link);
1320         if (error) {
1321                 /*
1322                  * The granted message may arrive after the
1323                  * interrupt/timeout but before we manage to lock the
1324                  * mutex. Detect this by examining nw_lock.
1325                  */
1326                 if (!nw->nw_waiting)
1327                         error = 0;
1328         } else {
1329                 /*
1330                  * If nlm_cancel_wait is called, then error will be
1331                  * zero but nw_waiting will still be TRUE. We
1332                  * translate this into EINTR.
1333                  */
1334                 if (nw->nw_waiting)
1335                         error = EINTR;
1336         }
1337         mtx_unlock(&nlm_global_lock);
1338
1339         free(nw, M_NLM);
1340
1341         return (error);
1342 }
1343
1344 void
1345 nlm_cancel_wait(struct vnode *vp)
1346 {
1347         struct nlm_waiting_lock *nw;
1348
1349         mtx_lock(&nlm_global_lock);
1350         TAILQ_FOREACH(nw, &nlm_waiting_locks, nw_link) {
1351                 if (nw->nw_vp == vp) {
1352                         wakeup(nw);
1353                 }
1354         }
1355         mtx_unlock(&nlm_global_lock);
1356 }
1357
1358
1359 /**********************************************************************/
1360
1361 /*
1362  * Syscall interface with userland.
1363  */
1364
1365 extern void nlm_prog_0(struct svc_req *rqstp, SVCXPRT *transp);
1366 extern void nlm_prog_1(struct svc_req *rqstp, SVCXPRT *transp);
1367 extern void nlm_prog_3(struct svc_req *rqstp, SVCXPRT *transp);
1368 extern void nlm_prog_4(struct svc_req *rqstp, SVCXPRT *transp);
1369
1370 static int
1371 nlm_register_services(SVCPOOL *pool, int addr_count, char **addrs)
1372 {
1373         static rpcvers_t versions[] = {
1374                 NLM_SM, NLM_VERS, NLM_VERSX, NLM_VERS4
1375         };
1376         static void (*dispatchers[])(struct svc_req *, SVCXPRT *) = {
1377                 nlm_prog_0, nlm_prog_1, nlm_prog_3, nlm_prog_4
1378         };
1379         static const int version_count = sizeof(versions) / sizeof(versions[0]);
1380
1381         SVCXPRT **xprts;
1382         char netid[16];
1383         char uaddr[128];
1384         struct netconfig *nconf;
1385         int i, j, error;
1386
1387         if (!addr_count) {
1388                 NLM_ERR("NLM: no service addresses given - can't start server");
1389                 return (EINVAL);
1390         }
1391
1392         xprts = malloc(addr_count * sizeof(SVCXPRT *), M_NLM, M_WAITOK|M_ZERO);
1393         for (i = 0; i < version_count; i++) {
1394                 for (j = 0; j < addr_count; j++) {
1395                         /*
1396                          * Create transports for the first version and
1397                          * then just register everything else to the
1398                          * same transports.
1399                          */
1400                         if (i == 0) {
1401                                 char *up;
1402
1403                                 error = copyin(&addrs[2*j], &up,
1404                                     sizeof(char*));
1405                                 if (error)
1406                                         goto out;
1407                                 error = copyinstr(up, netid, sizeof(netid),
1408                                     NULL);
1409                                 if (error)
1410                                         goto out;
1411                                 error = copyin(&addrs[2*j+1], &up,
1412                                     sizeof(char*));
1413                                 if (error)
1414                                         goto out;
1415                                 error = copyinstr(up, uaddr, sizeof(uaddr),
1416                                     NULL);
1417                                 if (error)
1418                                         goto out;
1419                                 nconf = getnetconfigent(netid);
1420                                 if (!nconf) {
1421                                         NLM_ERR("Can't lookup netid %s\n",
1422                                             netid);
1423                                         error = EINVAL;
1424                                         goto out;
1425                                 }
1426                                 xprts[j] = svc_tp_create(pool, dispatchers[i],
1427                                     NLM_PROG, versions[i], uaddr, nconf);
1428                                 if (!xprts[j]) {
1429                                         NLM_ERR("NLM: unable to create "
1430                                             "(NLM_PROG, %d).\n", versions[i]);
1431                                         error = EINVAL;
1432                                         goto out;
1433                                 }
1434                                 freenetconfigent(nconf);
1435                         } else {
1436                                 nconf = getnetconfigent(xprts[j]->xp_netid);
1437                                 rpcb_unset(NLM_PROG, versions[i], nconf);
1438                                 if (!svc_reg(xprts[j], NLM_PROG, versions[i],
1439                                         dispatchers[i], nconf)) {
1440                                         NLM_ERR("NLM: can't register "
1441                                             "(NLM_PROG, %d)\n", versions[i]);
1442                                         error = EINVAL;
1443                                         goto out;
1444                                 }
1445                         }
1446                 }
1447         }
1448         error = 0;
1449 out:
1450         for (j = 0; j < addr_count; j++) {
1451                 if (xprts[j])
1452                         SVC_RELEASE(xprts[j]);
1453         }
1454         free(xprts, M_NLM);
1455         return (error);
1456 }
1457
1458 /*
1459  * Main server entry point. Contacts the local NSM to get its current
1460  * state and send SM_UNMON_ALL. Registers the NLM services and then
1461  * services requests. Does not return until the server is interrupted
1462  * by a signal.
1463  */
1464 static int
1465 nlm_server_main(int addr_count, char **addrs)
1466 {
1467         struct thread *td = curthread;
1468         int error;
1469         SVCPOOL *pool = NULL;
1470         struct sockopt opt;
1471         int portlow;
1472 #ifdef INET6
1473         struct sockaddr_in6 sin6;
1474 #endif
1475         struct sockaddr_in sin;
1476         my_id id;
1477         sm_stat smstat;
1478         struct timeval timo;
1479         enum clnt_stat stat;
1480         struct nlm_host *host, *nhost;
1481         struct nlm_waiting_lock *nw;
1482 #ifdef NFSCLIENT
1483         vop_advlock_t *old_nfs_advlock;
1484         vop_reclaim_t *old_nfs_reclaim;
1485 #endif
1486         int v4_used;
1487 #ifdef INET6
1488         int v6_used;
1489 #endif
1490
1491         if (nlm_socket) {
1492                 NLM_ERR("NLM: can't start server - "
1493                     "it appears to be running already\n");
1494                 return (EPERM);
1495         }
1496
1497         memset(&opt, 0, sizeof(opt));
1498
1499         nlm_socket = NULL;
1500         error = socreate(AF_INET, &nlm_socket, SOCK_DGRAM, 0,
1501             td->td_ucred, td);
1502         if (error) {
1503                 NLM_ERR("NLM: can't create IPv4 socket - error %d\n", error);
1504                 return (error);
1505         }
1506         opt.sopt_dir = SOPT_SET;
1507         opt.sopt_level = IPPROTO_IP;
1508         opt.sopt_name = IP_PORTRANGE;
1509         portlow = IP_PORTRANGE_LOW;
1510         opt.sopt_val = &portlow;
1511         opt.sopt_valsize = sizeof(portlow);
1512         sosetopt(nlm_socket, &opt);
1513
1514 #ifdef INET6
1515         nlm_socket6 = NULL;
1516         error = socreate(AF_INET6, &nlm_socket6, SOCK_DGRAM, 0,
1517             td->td_ucred, td);
1518         if (error) {
1519                 NLM_ERR("NLM: can't create IPv6 socket - error %d\n", error);
1520                 goto out;
1521                 return (error);
1522         }
1523         opt.sopt_dir = SOPT_SET;
1524         opt.sopt_level = IPPROTO_IPV6;
1525         opt.sopt_name = IPV6_PORTRANGE;
1526         portlow = IPV6_PORTRANGE_LOW;
1527         opt.sopt_val = &portlow;
1528         opt.sopt_valsize = sizeof(portlow);
1529         sosetopt(nlm_socket6, &opt);
1530 #endif
1531
1532         nlm_auth = authunix_create(curthread->td_ucred);
1533
1534 #ifdef INET6
1535         memset(&sin6, 0, sizeof(sin6));
1536         sin6.sin6_len = sizeof(sin6);
1537         sin6.sin6_family = AF_INET6;
1538         sin6.sin6_addr = in6addr_loopback;
1539         nlm_nsm = nlm_get_rpc((struct sockaddr *) &sin6, SM_PROG, SM_VERS);
1540         if (!nlm_nsm) {
1541 #endif
1542                 memset(&sin, 0, sizeof(sin));
1543                 sin.sin_len = sizeof(sin);
1544                 sin.sin_family = AF_INET;
1545                 sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
1546                 nlm_nsm = nlm_get_rpc((struct sockaddr *) &sin, SM_PROG,
1547                     SM_VERS);
1548 #ifdef INET6
1549         }
1550 #endif
1551
1552         if (!nlm_nsm) {
1553                 NLM_ERR("Can't start NLM - unable to contact NSM\n");
1554                 error = EINVAL;
1555                 goto out;
1556         }
1557
1558         pool = svcpool_create("NLM", NULL);
1559
1560         error = nlm_register_services(pool, addr_count, addrs);
1561         if (error)
1562                 goto out;
1563
1564         memset(&id, 0, sizeof(id));
1565         id.my_name = "NFS NLM";
1566
1567         timo.tv_sec = 25;
1568         timo.tv_usec = 0;
1569         stat = CLNT_CALL(nlm_nsm, SM_UNMON_ALL,
1570             (xdrproc_t) xdr_my_id, &id,
1571             (xdrproc_t) xdr_sm_stat, &smstat, timo);
1572
1573         if (stat != RPC_SUCCESS) {
1574                 struct rpc_err err;
1575
1576                 CLNT_GETERR(nlm_nsm, &err);
1577                 NLM_ERR("NLM: unexpected error contacting NSM, "
1578                     "stat=%d, errno=%d\n", stat, err.re_errno);
1579                 error = EINVAL;
1580                 goto out;
1581         }
1582
1583         NLM_DEBUG(1, "NLM: local NSM state is %d\n", smstat.state);
1584         nlm_nsm_state = smstat.state;
1585
1586 #ifdef NFSCLIENT
1587         old_nfs_advlock = nfs_advlock_p;
1588         nfs_advlock_p = nlm_advlock;
1589         old_nfs_reclaim = nfs_reclaim_p;
1590         nfs_reclaim_p = nlm_reclaim;
1591 #endif
1592
1593         svc_run(pool);
1594         error = 0;
1595
1596 #ifdef NFSCLIENT
1597         nfs_advlock_p = old_nfs_advlock;
1598         nfs_reclaim_p = old_nfs_reclaim;
1599 #endif
1600
1601 out:
1602         if (pool)
1603                 svcpool_destroy(pool);
1604
1605         /*
1606          * We are finished communicating with the NSM.
1607          */
1608         if (nlm_nsm) {
1609                 CLNT_RELEASE(nlm_nsm);
1610                 nlm_nsm = NULL;
1611         }
1612
1613         /*
1614          * Trash all the existing state so that if the server
1615          * restarts, it gets a clean slate. This is complicated by the
1616          * possibility that there may be other threads trying to make
1617          * client locking requests.
1618          *
1619          * First we fake a client reboot notification which will
1620          * cancel any pending async locks and purge remote lock state
1621          * from the local lock manager. We release the reference from
1622          * nlm_hosts to the host (which may remove it from the list
1623          * and free it). After this phase, the only entries in the
1624          * nlm_host list should be from other threads performing
1625          * client lock requests. We arrange to defer closing the
1626          * sockets until the last RPC client handle is released.
1627          */
1628         v4_used = 0;
1629 #ifdef INET6
1630         v6_used = 0;
1631 #endif
1632         mtx_lock(&nlm_global_lock);
1633         TAILQ_FOREACH(nw, &nlm_waiting_locks, nw_link) {
1634                 wakeup(nw);
1635         }
1636         TAILQ_FOREACH_SAFE(host, &nlm_hosts, nh_link, nhost) {
1637                 mtx_unlock(&nlm_global_lock);
1638                 nlm_host_notify(host, 0);
1639                 nlm_host_release(host);
1640                 mtx_lock(&nlm_global_lock);
1641         }
1642         TAILQ_FOREACH_SAFE(host, &nlm_hosts, nh_link, nhost) {
1643                 mtx_lock(&host->nh_lock);
1644                 if (host->nh_srvrpc.nr_client
1645                     || host->nh_clntrpc.nr_client) {
1646                         if (host->nh_addr.ss_family == AF_INET)
1647                                 v4_used++;
1648 #ifdef INET6
1649                         if (host->nh_addr.ss_family == AF_INET6)
1650                                 v6_used++;
1651 #endif
1652                         /*
1653                          * Note that the rpc over udp code copes
1654                          * correctly with the fact that a socket may
1655                          * be used by many rpc handles.
1656                          */
1657                         if (host->nh_srvrpc.nr_client)
1658                                 CLNT_CONTROL(host->nh_srvrpc.nr_client,
1659                                     CLSET_FD_CLOSE, 0);
1660                         if (host->nh_clntrpc.nr_client)
1661                                 CLNT_CONTROL(host->nh_clntrpc.nr_client,
1662                                     CLSET_FD_CLOSE, 0);
1663                 }
1664                 mtx_unlock(&host->nh_lock);
1665         }
1666         mtx_unlock(&nlm_global_lock);
1667
1668         AUTH_DESTROY(nlm_auth);
1669
1670         if (!v4_used)
1671                 soclose(nlm_socket);
1672         nlm_socket = NULL;
1673 #ifdef INET6
1674         if (!v6_used)
1675                 soclose(nlm_socket6);
1676         nlm_socket6 = NULL;
1677 #endif
1678
1679         return (error);
1680 }
1681
1682 int
1683 nlm_syscall(struct thread *td, struct nlm_syscall_args *uap)
1684 {
1685         int error;
1686
1687 #if __FreeBSD_version >= 700000
1688         error = priv_check(td, PRIV_NFS_LOCKD);
1689 #else
1690         error = suser(td);
1691 #endif
1692         if (error)
1693                 return (error);
1694
1695         nlm_debug_level = uap->debug_level;
1696         nlm_grace_threshold = time_uptime + uap->grace_period;
1697         nlm_next_idle_check = time_uptime + NLM_IDLE_PERIOD;
1698
1699         return nlm_server_main(uap->addr_count, uap->addrs);
1700 }
1701
1702 /**********************************************************************/
1703
1704 /*
1705  * NLM implementation details, called from the RPC stubs.
1706  */
1707
1708
1709 void
1710 nlm_sm_notify(struct nlm_sm_status *argp)
1711 {
1712         uint32_t sysid;
1713         struct nlm_host *host;
1714
1715         NLM_DEBUG(3, "nlm_sm_notify(): mon_name = %s\n", argp->mon_name);
1716         memcpy(&sysid, &argp->priv, sizeof(sysid));
1717         host = nlm_find_host_by_sysid(sysid);
1718         if (host) {
1719                 nlm_host_notify(host, argp->state);
1720                 nlm_host_release(host);
1721         }
1722 }
1723
1724 static void
1725 nlm_convert_to_fhandle_t(fhandle_t *fhp, struct netobj *p)
1726 {
1727         memcpy(fhp, p->n_bytes, sizeof(fhandle_t));
1728 }
1729
1730 struct vfs_state {
1731         struct mount    *vs_mp;
1732         struct vnode    *vs_vp;
1733         int             vs_vfslocked;
1734         int             vs_vnlocked;
1735 };
1736
1737 static int
1738 nlm_get_vfs_state(struct nlm_host *host, struct svc_req *rqstp,
1739     fhandle_t *fhp, struct vfs_state *vs)
1740 {
1741         int error, exflags;
1742         struct ucred *cred = NULL, *credanon;
1743         
1744         memset(vs, 0, sizeof(*vs));
1745
1746         vs->vs_mp = vfs_getvfs(&fhp->fh_fsid);
1747         if (!vs->vs_mp) {
1748                 return (ESTALE);
1749         }
1750         vs->vs_vfslocked = VFS_LOCK_GIANT(vs->vs_mp);
1751
1752         error = VFS_CHECKEXP(vs->vs_mp, (struct sockaddr *)&host->nh_addr,
1753             &exflags, &credanon, NULL, NULL);
1754         if (error)
1755                 goto out;
1756
1757         if (exflags & MNT_EXRDONLY || (vs->vs_mp->mnt_flag & MNT_RDONLY)) {
1758                 error = EROFS;
1759                 goto out;
1760         }
1761
1762         error = VFS_FHTOVP(vs->vs_mp, &fhp->fh_fid, &vs->vs_vp);
1763         if (error)
1764                 goto out;
1765         vs->vs_vnlocked = TRUE;
1766
1767         if (!svc_getcred(rqstp, &cred, NULL)) {
1768                 error = EINVAL;
1769                 goto out;
1770         }
1771         if (cred->cr_uid == 0 || (exflags & MNT_EXPORTANON)) {
1772                 crfree(cred);
1773                 cred = credanon;
1774                 credanon = NULL;
1775         }
1776
1777         /*
1778          * Check cred.
1779          */
1780         error = VOP_ACCESS(vs->vs_vp, VWRITE, cred, curthread);
1781         if (error)
1782                 goto out;
1783
1784 #if __FreeBSD_version < 800011
1785         VOP_UNLOCK(vs->vs_vp, 0, curthread);
1786 #else
1787         VOP_UNLOCK(vs->vs_vp, 0);
1788 #endif
1789         vs->vs_vnlocked = FALSE;
1790
1791 out:
1792         if (cred)
1793                 crfree(cred);
1794         if (credanon)
1795                 crfree(credanon);
1796
1797         return (error);
1798 }
1799
1800 static void
1801 nlm_release_vfs_state(struct vfs_state *vs)
1802 {
1803
1804         if (vs->vs_vp) {
1805                 if (vs->vs_vnlocked)
1806                         vput(vs->vs_vp);
1807                 else
1808                         vrele(vs->vs_vp);
1809         }
1810         if (vs->vs_mp)
1811                 vfs_rel(vs->vs_mp);
1812         VFS_UNLOCK_GIANT(vs->vs_vfslocked);
1813 }
1814
1815 static nlm4_stats
1816 nlm_convert_error(int error)
1817 {
1818
1819         if (error == ESTALE)
1820                 return nlm4_stale_fh;
1821         else if (error == EROFS)
1822                 return nlm4_rofs;
1823         else
1824                 return nlm4_failed;
1825 }
1826
1827 int
1828 nlm_do_test(nlm4_testargs *argp, nlm4_testres *result, struct svc_req *rqstp,
1829         CLIENT **rpcp)
1830 {
1831         fhandle_t fh;
1832         struct vfs_state vs;
1833         struct nlm_host *host, *bhost;
1834         int error, sysid;
1835         struct flock fl;
1836         
1837         memset(result, 0, sizeof(*result));
1838         memset(&vs, 0, sizeof(vs));
1839
1840         host = nlm_find_host_by_name(argp->alock.caller_name,
1841             svc_getrpccaller(rqstp), rqstp->rq_vers);
1842         if (!host) {
1843                 result->stat.stat = nlm4_denied_nolocks;
1844                 return (ENOMEM);
1845         }
1846
1847         NLM_DEBUG(3, "nlm_do_test(): caller_name = %s (sysid = %d)\n",
1848             host->nh_caller_name, host->nh_sysid);
1849
1850         nlm_free_finished_locks(host);
1851         sysid = host->nh_sysid;
1852
1853         nlm_convert_to_fhandle_t(&fh, &argp->alock.fh);
1854         nlm_copy_netobj(&result->cookie, &argp->cookie, M_RPC);
1855
1856         if (time_uptime < nlm_grace_threshold) {
1857                 result->stat.stat = nlm4_denied_grace_period;
1858                 goto out;
1859         }
1860
1861         error = nlm_get_vfs_state(host, rqstp, &fh, &vs);
1862         if (error) {
1863                 result->stat.stat = nlm_convert_error(error);
1864                 goto out;
1865         }
1866
1867         fl.l_start = argp->alock.l_offset;
1868         fl.l_len = argp->alock.l_len;
1869         fl.l_pid = argp->alock.svid;
1870         fl.l_sysid = sysid;
1871         fl.l_whence = SEEK_SET;
1872         if (argp->exclusive)
1873                 fl.l_type = F_WRLCK;
1874         else
1875                 fl.l_type = F_RDLCK;
1876         error = VOP_ADVLOCK(vs.vs_vp, NULL, F_GETLK, &fl, F_REMOTE);
1877         if (error) {
1878                 result->stat.stat = nlm4_failed;
1879                 goto out;
1880         }
1881
1882         if (fl.l_type == F_UNLCK) {
1883                 result->stat.stat = nlm4_granted;
1884         } else {
1885                 result->stat.stat = nlm4_denied;
1886                 result->stat.nlm4_testrply_u.holder.exclusive =
1887                         (fl.l_type == F_WRLCK);
1888                 result->stat.nlm4_testrply_u.holder.svid = fl.l_pid;
1889                 bhost = nlm_find_host_by_sysid(fl.l_sysid);
1890                 if (bhost) {
1891                         /*
1892                          * We don't have any useful way of recording
1893                          * the value of oh used in the original lock
1894                          * request. Ideally, the test reply would have
1895                          * a space for the owning host's name allowing
1896                          * our caller's NLM to keep track.
1897                          *
1898                          * As far as I can see, Solaris uses an eight
1899                          * byte structure for oh which contains a four
1900                          * byte pid encoded in local byte order and
1901                          * the first four bytes of the host
1902                          * name. Linux uses a variable length string
1903                          * 'pid@hostname' in ascii but doesn't even
1904                          * return that in test replies.
1905                          *
1906                          * For the moment, return nothing in oh
1907                          * (already zero'ed above).
1908                          */
1909                         nlm_host_release(bhost);
1910                 }
1911                 result->stat.nlm4_testrply_u.holder.l_offset = fl.l_start;
1912                 result->stat.nlm4_testrply_u.holder.l_len = fl.l_len;
1913         }
1914
1915 out:
1916         nlm_release_vfs_state(&vs);
1917         if (rpcp)
1918                 *rpcp = nlm_host_get_rpc(host, TRUE);
1919         nlm_host_release(host);
1920         return (0);
1921 }
1922
1923 int
1924 nlm_do_lock(nlm4_lockargs *argp, nlm4_res *result, struct svc_req *rqstp,
1925     bool_t monitor, CLIENT **rpcp)
1926 {
1927         fhandle_t fh;
1928         struct vfs_state vs;
1929         struct nlm_host *host;
1930         int error, sysid;
1931         struct flock fl;
1932         
1933         memset(result, 0, sizeof(*result));
1934         memset(&vs, 0, sizeof(vs));
1935
1936         host = nlm_find_host_by_name(argp->alock.caller_name,
1937             svc_getrpccaller(rqstp), rqstp->rq_vers);
1938         if (!host) {
1939                 result->stat.stat = nlm4_denied_nolocks;
1940                 return (ENOMEM);
1941         }
1942
1943         NLM_DEBUG(3, "nlm_do_lock(): caller_name = %s (sysid = %d)\n",
1944             host->nh_caller_name, host->nh_sysid);
1945
1946         if (monitor && host->nh_state && argp->state
1947             && host->nh_state != argp->state) {
1948                 /*
1949                  * The host rebooted without telling us. Trash its
1950                  * locks.
1951                  */
1952                 nlm_host_notify(host, argp->state);
1953         }
1954
1955         nlm_free_finished_locks(host);
1956         sysid = host->nh_sysid;
1957
1958         nlm_convert_to_fhandle_t(&fh, &argp->alock.fh);
1959         nlm_copy_netobj(&result->cookie, &argp->cookie, M_RPC);
1960
1961         if (time_uptime < nlm_grace_threshold && !argp->reclaim) {
1962                 result->stat.stat = nlm4_denied_grace_period;
1963                 goto out;
1964         }
1965
1966         error = nlm_get_vfs_state(host, rqstp, &fh, &vs);
1967         if (error) {
1968                 result->stat.stat = nlm_convert_error(error);
1969                 goto out;
1970         }
1971
1972         fl.l_start = argp->alock.l_offset;
1973         fl.l_len = argp->alock.l_len;
1974         fl.l_pid = argp->alock.svid;
1975         fl.l_sysid = sysid;
1976         fl.l_whence = SEEK_SET;
1977         if (argp->exclusive)
1978                 fl.l_type = F_WRLCK;
1979         else
1980                 fl.l_type = F_RDLCK;
1981         if (argp->block) {
1982                 struct nlm_async_lock *af;
1983                 CLIENT *client;
1984
1985                 /*
1986                  * First, make sure we can contact the host's NLM.
1987                  */
1988                 client = nlm_host_get_rpc(host, TRUE);
1989                 if (!client) {
1990                         result->stat.stat = nlm4_failed;
1991                         goto out;
1992                 }
1993
1994                 /*
1995                  * First we need to check and see if there is an
1996                  * existing blocked lock that matches. This could be a
1997                  * badly behaved client or an RPC re-send. If we find
1998                  * one, just return nlm4_blocked.
1999                  */
2000                 mtx_lock(&host->nh_lock);
2001                 TAILQ_FOREACH(af, &host->nh_pending, af_link) {
2002                         if (af->af_fl.l_start == fl.l_start
2003                             && af->af_fl.l_len == fl.l_len
2004                             && af->af_fl.l_pid == fl.l_pid
2005                             && af->af_fl.l_type == fl.l_type) {
2006                                 break;
2007                         }
2008                 }
2009                 mtx_unlock(&host->nh_lock);
2010                 if (af) {
2011                         CLNT_RELEASE(client);
2012                         result->stat.stat = nlm4_blocked;
2013                         goto out;
2014                 }
2015
2016                 af = malloc(sizeof(struct nlm_async_lock), M_NLM,
2017                     M_WAITOK|M_ZERO);
2018                 TASK_INIT(&af->af_task, 0, nlm_lock_callback, af);
2019                 af->af_vp = vs.vs_vp;
2020                 af->af_fl = fl;
2021                 af->af_host = host;
2022                 af->af_rpc = client;
2023                 /*
2024                  * We use M_RPC here so that we can xdr_free the thing
2025                  * later.
2026                  */
2027                 af->af_granted.exclusive = argp->exclusive;
2028                 af->af_granted.alock.caller_name =
2029                         strdup(argp->alock.caller_name, M_RPC);
2030                 nlm_copy_netobj(&af->af_granted.alock.fh,
2031                     &argp->alock.fh, M_RPC);
2032                 nlm_copy_netobj(&af->af_granted.alock.oh,
2033                     &argp->alock.oh, M_RPC);
2034                 af->af_granted.alock.svid = argp->alock.svid;
2035                 af->af_granted.alock.l_offset = argp->alock.l_offset;
2036                 af->af_granted.alock.l_len = argp->alock.l_len;
2037
2038                 /*
2039                  * Put the entry on the pending list before calling
2040                  * VOP_ADVLOCKASYNC. We do this in case the lock
2041                  * request was blocked (returning EINPROGRESS) but
2042                  * then granted before we manage to run again. The
2043                  * client may receive the granted message before we
2044                  * send our blocked reply but thats their problem.
2045                  */
2046                 mtx_lock(&host->nh_lock);
2047                 TAILQ_INSERT_TAIL(&host->nh_pending, af, af_link);
2048                 mtx_unlock(&host->nh_lock);
2049
2050                 error = VOP_ADVLOCKASYNC(vs.vs_vp, NULL, F_SETLK, &fl, F_REMOTE,
2051                     &af->af_task, &af->af_cookie);
2052
2053                 /*
2054                  * If the lock completed synchronously, just free the
2055                  * tracking structure now.
2056                  */
2057                 if (error != EINPROGRESS) {
2058                         CLNT_RELEASE(af->af_rpc);
2059                         mtx_lock(&host->nh_lock);
2060                         TAILQ_REMOVE(&host->nh_pending, af, af_link);
2061                         mtx_unlock(&host->nh_lock);
2062                         xdr_free((xdrproc_t) xdr_nlm4_testargs,
2063                             &af->af_granted);
2064                         free(af, M_NLM);
2065                 } else {
2066                         NLM_DEBUG(2, "NLM: pending async lock %p for %s "
2067                             "(sysid %d)\n", af, host->nh_caller_name, sysid);
2068                         /*
2069                          * Don't vrele the vnode just yet - this must
2070                          * wait until either the async callback
2071                          * happens or the lock is cancelled.
2072                          */
2073                         vs.vs_vp = NULL;
2074                 }
2075         } else {
2076                 error = VOP_ADVLOCK(vs.vs_vp, NULL, F_SETLK, &fl, F_REMOTE);
2077         }
2078
2079         if (error) {
2080                 if (error == EINPROGRESS) {
2081                         result->stat.stat = nlm4_blocked;
2082                 } else if (error == EDEADLK) {
2083                         result->stat.stat = nlm4_deadlck;
2084                 } else if (error == EAGAIN) {
2085                         result->stat.stat = nlm4_denied;
2086                 } else {
2087                         result->stat.stat = nlm4_failed;
2088                 }
2089         } else {
2090                 if (monitor)
2091                         nlm_host_monitor(host, argp->state);
2092                 result->stat.stat = nlm4_granted;
2093         }       
2094
2095 out:
2096         nlm_release_vfs_state(&vs);
2097         if (rpcp)
2098                 *rpcp = nlm_host_get_rpc(host, TRUE);
2099         nlm_host_release(host);
2100         return (0);
2101 }
2102
2103 int
2104 nlm_do_cancel(nlm4_cancargs *argp, nlm4_res *result, struct svc_req *rqstp,
2105     CLIENT **rpcp)
2106 {
2107         fhandle_t fh;
2108         struct vfs_state vs;
2109         struct nlm_host *host;
2110         int error, sysid;
2111         struct flock fl;
2112         struct nlm_async_lock *af;
2113         
2114         memset(result, 0, sizeof(*result));
2115         memset(&vs, 0, sizeof(vs));
2116
2117         host = nlm_find_host_by_name(argp->alock.caller_name,
2118             svc_getrpccaller(rqstp), rqstp->rq_vers);
2119         if (!host) {
2120                 result->stat.stat = nlm4_denied_nolocks;
2121                 return (ENOMEM);
2122         }
2123
2124         NLM_DEBUG(3, "nlm_do_cancel(): caller_name = %s (sysid = %d)\n",
2125             host->nh_caller_name, host->nh_sysid);
2126
2127         nlm_free_finished_locks(host);
2128         sysid = host->nh_sysid;
2129
2130         nlm_convert_to_fhandle_t(&fh, &argp->alock.fh);
2131         nlm_copy_netobj(&result->cookie, &argp->cookie, M_RPC);
2132
2133         if (time_uptime < nlm_grace_threshold) {
2134                 result->stat.stat = nlm4_denied_grace_period;
2135                 goto out;
2136         }
2137
2138         error = nlm_get_vfs_state(host, rqstp, &fh, &vs);
2139         if (error) {
2140                 result->stat.stat = nlm_convert_error(error);
2141                 goto out;
2142         }
2143
2144         fl.l_start = argp->alock.l_offset;
2145         fl.l_len = argp->alock.l_len;
2146         fl.l_pid = argp->alock.svid;
2147         fl.l_sysid = sysid;
2148         fl.l_whence = SEEK_SET;
2149         if (argp->exclusive)
2150                 fl.l_type = F_WRLCK;
2151         else
2152                 fl.l_type = F_RDLCK;
2153
2154         /*
2155          * First we need to try and find the async lock request - if
2156          * there isn't one, we give up and return nlm4_denied.
2157          */
2158         mtx_lock(&host->nh_lock);
2159
2160         TAILQ_FOREACH(af, &host->nh_pending, af_link) {
2161                 if (af->af_fl.l_start == fl.l_start
2162                     && af->af_fl.l_len == fl.l_len
2163                     && af->af_fl.l_pid == fl.l_pid
2164                     && af->af_fl.l_type == fl.l_type) {
2165                         break;
2166                 }
2167         }
2168
2169         if (!af) {
2170                 mtx_unlock(&host->nh_lock);
2171                 result->stat.stat = nlm4_denied;
2172                 goto out;
2173         }
2174
2175         error = nlm_cancel_async_lock(af);
2176
2177         if (error) {
2178                 result->stat.stat = nlm4_denied;
2179         } else {
2180                 result->stat.stat = nlm4_granted;
2181         }
2182
2183         mtx_unlock(&host->nh_lock);
2184
2185 out:
2186         nlm_release_vfs_state(&vs);
2187         if (rpcp)
2188                 *rpcp = nlm_host_get_rpc(host, TRUE);
2189         nlm_host_release(host);
2190         return (0);
2191 }
2192
2193 int
2194 nlm_do_unlock(nlm4_unlockargs *argp, nlm4_res *result, struct svc_req *rqstp,
2195     CLIENT **rpcp)
2196 {
2197         fhandle_t fh;
2198         struct vfs_state vs;
2199         struct nlm_host *host;
2200         int error, sysid;
2201         struct flock fl;
2202         
2203         memset(result, 0, sizeof(*result));
2204         memset(&vs, 0, sizeof(vs));
2205
2206         host = nlm_find_host_by_name(argp->alock.caller_name,
2207             svc_getrpccaller(rqstp), rqstp->rq_vers);
2208         if (!host) {
2209                 result->stat.stat = nlm4_denied_nolocks;
2210                 return (ENOMEM);
2211         }
2212
2213         NLM_DEBUG(3, "nlm_do_unlock(): caller_name = %s (sysid = %d)\n",
2214             host->nh_caller_name, host->nh_sysid);
2215
2216         nlm_free_finished_locks(host);
2217         sysid = host->nh_sysid;
2218
2219         nlm_convert_to_fhandle_t(&fh, &argp->alock.fh);
2220         nlm_copy_netobj(&result->cookie, &argp->cookie, M_RPC);
2221
2222         if (time_uptime < nlm_grace_threshold) {
2223                 result->stat.stat = nlm4_denied_grace_period;
2224                 goto out;
2225         }
2226
2227         error = nlm_get_vfs_state(host, rqstp, &fh, &vs);
2228         if (error) {
2229                 result->stat.stat = nlm_convert_error(error);
2230                 goto out;
2231         }
2232
2233         fl.l_start = argp->alock.l_offset;
2234         fl.l_len = argp->alock.l_len;
2235         fl.l_pid = argp->alock.svid;
2236         fl.l_sysid = sysid;
2237         fl.l_whence = SEEK_SET;
2238         fl.l_type = F_UNLCK;
2239         error = VOP_ADVLOCK(vs.vs_vp, NULL, F_UNLCK, &fl, F_REMOTE);
2240
2241         /*
2242          * Ignore the error - there is no result code for failure,
2243          * only for grace period.
2244          */
2245         result->stat.stat = nlm4_granted;
2246
2247 out:
2248         nlm_release_vfs_state(&vs);
2249         if (rpcp)
2250                 *rpcp = nlm_host_get_rpc(host, TRUE);
2251         nlm_host_release(host);
2252         return (0);
2253 }
2254
2255 int
2256 nlm_do_granted(nlm4_testargs *argp, nlm4_res *result, struct svc_req *rqstp,
2257
2258     CLIENT **rpcp)
2259 {
2260         struct nlm_host *host;
2261         struct nlm_waiting_lock *nw;
2262         
2263         memset(result, 0, sizeof(*result));
2264
2265         host = nlm_find_host_by_addr(svc_getrpccaller(rqstp), rqstp->rq_vers);
2266         if (!host) {
2267                 result->stat.stat = nlm4_denied_nolocks;
2268                 return (ENOMEM);
2269         }
2270
2271         nlm_copy_netobj(&result->cookie, &argp->cookie, M_RPC);
2272         result->stat.stat = nlm4_denied;
2273
2274         mtx_lock(&nlm_global_lock);
2275         TAILQ_FOREACH(nw, &nlm_waiting_locks, nw_link) {
2276                 if (!nw->nw_waiting)
2277                         continue;
2278                 if (argp->alock.svid == nw->nw_lock.svid
2279                     && argp->alock.l_offset == nw->nw_lock.l_offset
2280                     && argp->alock.l_len == nw->nw_lock.l_len
2281                     && argp->alock.fh.n_len == nw->nw_lock.fh.n_len
2282                     && !memcmp(argp->alock.fh.n_bytes, nw->nw_lock.fh.n_bytes,
2283                         nw->nw_lock.fh.n_len)) {
2284                         nw->nw_waiting = FALSE;
2285                         wakeup(nw);
2286                         result->stat.stat = nlm4_granted;
2287                         break;
2288                 }
2289         }
2290         mtx_unlock(&nlm_global_lock);
2291         if (rpcp)
2292                 *rpcp = nlm_host_get_rpc(host, TRUE);
2293         nlm_host_release(host);
2294         return (0);
2295 }
2296
2297 void
2298 nlm_do_free_all(nlm4_notify *argp)
2299 {
2300         struct nlm_host *host, *thost;
2301
2302         TAILQ_FOREACH_SAFE(host, &nlm_hosts, nh_link, thost) {
2303                 if (!strcmp(host->nh_caller_name, argp->name))
2304                         nlm_host_notify(host, argp->state);
2305         }
2306 }
2307
2308 /*
2309  * Kernel module glue
2310  */
2311 static int
2312 nfslockd_modevent(module_t mod, int type, void *data)
2313 {
2314
2315         return (0);
2316 }
2317 static moduledata_t nfslockd_mod = {
2318         "nfslockd",
2319         nfslockd_modevent,
2320         NULL,
2321 };
2322 DECLARE_MODULE(nfslockd, nfslockd_mod, SI_SUB_VFS, SI_ORDER_ANY);
2323
2324 /* So that loader and kldload(2) can find us, wherever we are.. */
2325 MODULE_DEPEND(nfslockd, krpc, 1, 1, 1);
2326 MODULE_DEPEND(nfslockd, nfs, 1, 1, 1);
2327 MODULE_VERSION(nfslockd, 1);