xref: /freebsd/sys/fs/autofs/autofs.c (revision 3914ddf8a7b16925f50cc2e29e916aa2d56063fb)
1*3914ddf8SEdward Tomasz Napierala /*-
2*3914ddf8SEdward Tomasz Napierala  * Copyright (c) 2014 The FreeBSD Foundation
3*3914ddf8SEdward Tomasz Napierala  * All rights reserved.
4*3914ddf8SEdward Tomasz Napierala  *
5*3914ddf8SEdward Tomasz Napierala  * This software was developed by Edward Tomasz Napierala under sponsorship
6*3914ddf8SEdward Tomasz Napierala  * from the FreeBSD Foundation.
7*3914ddf8SEdward Tomasz Napierala  *
8*3914ddf8SEdward Tomasz Napierala  * Redistribution and use in source and binary forms, with or without
9*3914ddf8SEdward Tomasz Napierala  * modification, are permitted provided that the following conditions
10*3914ddf8SEdward Tomasz Napierala  * are met:
11*3914ddf8SEdward Tomasz Napierala  * 1. Redistributions of source code must retain the above copyright
12*3914ddf8SEdward Tomasz Napierala  *    notice, this list of conditions and the following disclaimer.
13*3914ddf8SEdward Tomasz Napierala  * 2. Redistributions in binary form must reproduce the above copyright
14*3914ddf8SEdward Tomasz Napierala  *    notice, this list of conditions and the following disclaimer in the
15*3914ddf8SEdward Tomasz Napierala  *    documentation and/or other materials provided with the distribution.
16*3914ddf8SEdward Tomasz Napierala  *
17*3914ddf8SEdward Tomasz Napierala  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18*3914ddf8SEdward Tomasz Napierala  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19*3914ddf8SEdward Tomasz Napierala  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20*3914ddf8SEdward Tomasz Napierala  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21*3914ddf8SEdward Tomasz Napierala  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22*3914ddf8SEdward Tomasz Napierala  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23*3914ddf8SEdward Tomasz Napierala  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24*3914ddf8SEdward Tomasz Napierala  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25*3914ddf8SEdward Tomasz Napierala  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26*3914ddf8SEdward Tomasz Napierala  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27*3914ddf8SEdward Tomasz Napierala  * SUCH DAMAGE.
28*3914ddf8SEdward Tomasz Napierala  *
29*3914ddf8SEdward Tomasz Napierala  * $FreeBSD$
30*3914ddf8SEdward Tomasz Napierala  */
31*3914ddf8SEdward Tomasz Napierala /*-
32*3914ddf8SEdward Tomasz Napierala  * Copyright (c) 1989, 1991, 1993, 1995
33*3914ddf8SEdward Tomasz Napierala  *	The Regents of the University of California.  All rights reserved.
34*3914ddf8SEdward Tomasz Napierala  *
35*3914ddf8SEdward Tomasz Napierala  * This code is derived from software contributed to Berkeley by
36*3914ddf8SEdward Tomasz Napierala  * Rick Macklem at The University of Guelph.
37*3914ddf8SEdward Tomasz Napierala  *
38*3914ddf8SEdward Tomasz Napierala  * Redistribution and use in source and binary forms, with or without
39*3914ddf8SEdward Tomasz Napierala  * modification, are permitted provided that the following conditions
40*3914ddf8SEdward Tomasz Napierala  * are met:
41*3914ddf8SEdward Tomasz Napierala  * 1. Redistributions of source code must retain the above copyright
42*3914ddf8SEdward Tomasz Napierala  *    notice, this list of conditions and the following disclaimer.
43*3914ddf8SEdward Tomasz Napierala  * 2. Redistributions in binary form must reproduce the above copyright
44*3914ddf8SEdward Tomasz Napierala  *    notice, this list of conditions and the following disclaimer in the
45*3914ddf8SEdward Tomasz Napierala  *    documentation and/or other materials provided with the distribution.
46*3914ddf8SEdward Tomasz Napierala  * 4. Neither the name of the University nor the names of its contributors
47*3914ddf8SEdward Tomasz Napierala  *    may be used to endorse or promote products derived from this software
48*3914ddf8SEdward Tomasz Napierala  *    without specific prior written permission.
49*3914ddf8SEdward Tomasz Napierala  *
50*3914ddf8SEdward Tomasz Napierala  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
51*3914ddf8SEdward Tomasz Napierala  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
52*3914ddf8SEdward Tomasz Napierala  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
53*3914ddf8SEdward Tomasz Napierala  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
54*3914ddf8SEdward Tomasz Napierala  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
55*3914ddf8SEdward Tomasz Napierala  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
56*3914ddf8SEdward Tomasz Napierala  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
57*3914ddf8SEdward Tomasz Napierala  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
58*3914ddf8SEdward Tomasz Napierala  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
59*3914ddf8SEdward Tomasz Napierala  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
60*3914ddf8SEdward Tomasz Napierala  * SUCH DAMAGE.
61*3914ddf8SEdward Tomasz Napierala  *
62*3914ddf8SEdward Tomasz Napierala  */
63*3914ddf8SEdward Tomasz Napierala 
64*3914ddf8SEdward Tomasz Napierala #include <sys/param.h>
65*3914ddf8SEdward Tomasz Napierala #include <sys/systm.h>
66*3914ddf8SEdward Tomasz Napierala #include <sys/buf.h>
67*3914ddf8SEdward Tomasz Napierala #include <sys/conf.h>
68*3914ddf8SEdward Tomasz Napierala #include <sys/dirent.h>
69*3914ddf8SEdward Tomasz Napierala #include <sys/ioccom.h>
70*3914ddf8SEdward Tomasz Napierala #include <sys/kernel.h>
71*3914ddf8SEdward Tomasz Napierala #include <sys/module.h>
72*3914ddf8SEdward Tomasz Napierala #include <sys/mount.h>
73*3914ddf8SEdward Tomasz Napierala #include <sys/refcount.h>
74*3914ddf8SEdward Tomasz Napierala #include <sys/sx.h>
75*3914ddf8SEdward Tomasz Napierala #include <sys/sysctl.h>
76*3914ddf8SEdward Tomasz Napierala #include <sys/syscallsubr.h>
77*3914ddf8SEdward Tomasz Napierala #include <sys/vnode.h>
78*3914ddf8SEdward Tomasz Napierala #include <machine/atomic.h>
79*3914ddf8SEdward Tomasz Napierala #include <vm/uma.h>
80*3914ddf8SEdward Tomasz Napierala 
81*3914ddf8SEdward Tomasz Napierala #include "autofs.h"
82*3914ddf8SEdward Tomasz Napierala #include "autofs_ioctl.h"
83*3914ddf8SEdward Tomasz Napierala 
84*3914ddf8SEdward Tomasz Napierala MALLOC_DEFINE(M_AUTOFS, "autofs", "Automounter filesystem");
85*3914ddf8SEdward Tomasz Napierala 
86*3914ddf8SEdward Tomasz Napierala uma_zone_t autofs_request_zone;
87*3914ddf8SEdward Tomasz Napierala uma_zone_t autofs_node_zone;
88*3914ddf8SEdward Tomasz Napierala 
89*3914ddf8SEdward Tomasz Napierala static int	autofs_open(struct cdev *dev, int flags, int fmt,
90*3914ddf8SEdward Tomasz Napierala 		    struct thread *td);
91*3914ddf8SEdward Tomasz Napierala static int	autofs_close(struct cdev *dev, int flag, int fmt,
92*3914ddf8SEdward Tomasz Napierala 		    struct thread *td);
93*3914ddf8SEdward Tomasz Napierala static int	autofs_ioctl(struct cdev *dev, u_long cmd, caddr_t arg,
94*3914ddf8SEdward Tomasz Napierala 		    int mode, struct thread *td);
95*3914ddf8SEdward Tomasz Napierala 
96*3914ddf8SEdward Tomasz Napierala static struct cdevsw autofs_cdevsw = {
97*3914ddf8SEdward Tomasz Napierala      .d_version = D_VERSION,
98*3914ddf8SEdward Tomasz Napierala      .d_open   = autofs_open,
99*3914ddf8SEdward Tomasz Napierala      .d_close   = autofs_close,
100*3914ddf8SEdward Tomasz Napierala      .d_ioctl   = autofs_ioctl,
101*3914ddf8SEdward Tomasz Napierala      .d_name    = "autofs",
102*3914ddf8SEdward Tomasz Napierala };
103*3914ddf8SEdward Tomasz Napierala 
104*3914ddf8SEdward Tomasz Napierala /*
105*3914ddf8SEdward Tomasz Napierala  * List of signals that can interrupt an autofs trigger.  Might be a good
106*3914ddf8SEdward Tomasz Napierala  * idea to keep it synchronised with list in sys/fs/nfs/nfs_commonkrpc.c.
107*3914ddf8SEdward Tomasz Napierala  */
108*3914ddf8SEdward Tomasz Napierala int autofs_sig_set[] = {
109*3914ddf8SEdward Tomasz Napierala 	SIGINT,
110*3914ddf8SEdward Tomasz Napierala 	SIGTERM,
111*3914ddf8SEdward Tomasz Napierala 	SIGHUP,
112*3914ddf8SEdward Tomasz Napierala 	SIGKILL,
113*3914ddf8SEdward Tomasz Napierala 	SIGQUIT
114*3914ddf8SEdward Tomasz Napierala };
115*3914ddf8SEdward Tomasz Napierala 
116*3914ddf8SEdward Tomasz Napierala struct autofs_softc	*sc;
117*3914ddf8SEdward Tomasz Napierala 
118*3914ddf8SEdward Tomasz Napierala SYSCTL_NODE(_vfs, OID_AUTO, autofs, CTLFLAG_RD, 0, "Automounter filesystem");
119*3914ddf8SEdward Tomasz Napierala int autofs_debug = 1;
120*3914ddf8SEdward Tomasz Napierala TUNABLE_INT("vfs.autofs.debug", &autofs_debug);
121*3914ddf8SEdward Tomasz Napierala SYSCTL_INT(_vfs_autofs, OID_AUTO, debug, CTLFLAG_RWTUN,
122*3914ddf8SEdward Tomasz Napierala     &autofs_debug, 1, "Enable debug messages");
123*3914ddf8SEdward Tomasz Napierala int autofs_mount_on_stat = 0;
124*3914ddf8SEdward Tomasz Napierala TUNABLE_INT("vfs.autofs.mount_on_stat", &autofs_mount_on_stat);
125*3914ddf8SEdward Tomasz Napierala SYSCTL_INT(_vfs_autofs, OID_AUTO, mount_on_stat, CTLFLAG_RWTUN,
126*3914ddf8SEdward Tomasz Napierala     &autofs_mount_on_stat, 0, "Trigger mount on stat(2) on mountpoint");
127*3914ddf8SEdward Tomasz Napierala int autofs_timeout = 30;
128*3914ddf8SEdward Tomasz Napierala TUNABLE_INT("vfs.autofs.timeout", &autofs_timeout);
129*3914ddf8SEdward Tomasz Napierala SYSCTL_INT(_vfs_autofs, OID_AUTO, timeout, CTLFLAG_RWTUN,
130*3914ddf8SEdward Tomasz Napierala     &autofs_timeout, 30, "Number of seconds to wait for automountd(8)");
131*3914ddf8SEdward Tomasz Napierala int autofs_cache = 600;
132*3914ddf8SEdward Tomasz Napierala TUNABLE_INT("vfs.autofs.cache", &autofs_cache);
133*3914ddf8SEdward Tomasz Napierala SYSCTL_INT(_vfs_autofs, OID_AUTO, cache, CTLFLAG_RWTUN,
134*3914ddf8SEdward Tomasz Napierala     &autofs_cache, 600, "Number of seconds to wait before reinvoking "
135*3914ddf8SEdward Tomasz Napierala     "automountd(8) for any given file or directory");
136*3914ddf8SEdward Tomasz Napierala int autofs_retry_attempts = 3;
137*3914ddf8SEdward Tomasz Napierala TUNABLE_INT("vfs.autofs.retry_attempts", &autofs_retry_attempts);
138*3914ddf8SEdward Tomasz Napierala SYSCTL_INT(_vfs_autofs, OID_AUTO, retry_attempts, CTLFLAG_RWTUN,
139*3914ddf8SEdward Tomasz Napierala     &autofs_retry_attempts, 3, "Number of attempts before failing mount");
140*3914ddf8SEdward Tomasz Napierala int autofs_retry_delay = 1;
141*3914ddf8SEdward Tomasz Napierala TUNABLE_INT("vfs.autofs.retry_delay", &autofs_retry_delay);
142*3914ddf8SEdward Tomasz Napierala SYSCTL_INT(_vfs_autofs, OID_AUTO, retry_delay, CTLFLAG_RWTUN,
143*3914ddf8SEdward Tomasz Napierala     &autofs_retry_delay, 1, "Number of seconds before retrying");
144*3914ddf8SEdward Tomasz Napierala int autofs_interruptible = 1;
145*3914ddf8SEdward Tomasz Napierala TUNABLE_INT("vfs.autofs.interruptible", &autofs_interruptible);
146*3914ddf8SEdward Tomasz Napierala SYSCTL_INT(_vfs_autofs, OID_AUTO, interruptible, CTLFLAG_RWTUN,
147*3914ddf8SEdward Tomasz Napierala     &autofs_interruptible, 1, "Allow requests to be interrupted by signal");
148*3914ddf8SEdward Tomasz Napierala 
149*3914ddf8SEdward Tomasz Napierala int
150*3914ddf8SEdward Tomasz Napierala autofs_init(struct vfsconf *vfsp)
151*3914ddf8SEdward Tomasz Napierala {
152*3914ddf8SEdward Tomasz Napierala 	int error;
153*3914ddf8SEdward Tomasz Napierala 
154*3914ddf8SEdward Tomasz Napierala 	sc = malloc(sizeof(*sc), M_AUTOFS, M_WAITOK | M_ZERO);
155*3914ddf8SEdward Tomasz Napierala 
156*3914ddf8SEdward Tomasz Napierala 	autofs_request_zone = uma_zcreate("autofs_request",
157*3914ddf8SEdward Tomasz Napierala 	    sizeof(struct autofs_request), NULL, NULL, NULL, NULL,
158*3914ddf8SEdward Tomasz Napierala 	    UMA_ALIGN_PTR, 0);
159*3914ddf8SEdward Tomasz Napierala 	autofs_node_zone = uma_zcreate("autofs_node",
160*3914ddf8SEdward Tomasz Napierala 	    sizeof(struct autofs_node), NULL, NULL, NULL, NULL,
161*3914ddf8SEdward Tomasz Napierala 	    UMA_ALIGN_PTR, 0);
162*3914ddf8SEdward Tomasz Napierala 
163*3914ddf8SEdward Tomasz Napierala 	TAILQ_INIT(&sc->sc_requests);
164*3914ddf8SEdward Tomasz Napierala 	cv_init(&sc->sc_cv, "autofscv");
165*3914ddf8SEdward Tomasz Napierala 	sx_init(&sc->sc_lock, "autofslk");
166*3914ddf8SEdward Tomasz Napierala 
167*3914ddf8SEdward Tomasz Napierala 	error = make_dev_p(MAKEDEV_CHECKNAME, &sc->sc_cdev, &autofs_cdevsw,
168*3914ddf8SEdward Tomasz Napierala 	    NULL, UID_ROOT, GID_WHEEL, 0600, "autofs");
169*3914ddf8SEdward Tomasz Napierala 	if (error != 0) {
170*3914ddf8SEdward Tomasz Napierala 		AUTOFS_WARN("failed to create device node, error %d", error);
171*3914ddf8SEdward Tomasz Napierala 		free(sc, M_AUTOFS);
172*3914ddf8SEdward Tomasz Napierala 		return (error);
173*3914ddf8SEdward Tomasz Napierala 	}
174*3914ddf8SEdward Tomasz Napierala 	sc->sc_cdev->si_drv1 = sc;
175*3914ddf8SEdward Tomasz Napierala 
176*3914ddf8SEdward Tomasz Napierala 	return (0);
177*3914ddf8SEdward Tomasz Napierala }
178*3914ddf8SEdward Tomasz Napierala 
179*3914ddf8SEdward Tomasz Napierala int
180*3914ddf8SEdward Tomasz Napierala autofs_uninit(struct vfsconf *vfsp)
181*3914ddf8SEdward Tomasz Napierala {
182*3914ddf8SEdward Tomasz Napierala 
183*3914ddf8SEdward Tomasz Napierala 	sx_xlock(&sc->sc_lock);
184*3914ddf8SEdward Tomasz Napierala 	if (sc->sc_dev_opened) {
185*3914ddf8SEdward Tomasz Napierala 		sx_xunlock(&sc->sc_lock);
186*3914ddf8SEdward Tomasz Napierala 		return (EBUSY);
187*3914ddf8SEdward Tomasz Napierala 	}
188*3914ddf8SEdward Tomasz Napierala 	if (sc->sc_cdev != NULL)
189*3914ddf8SEdward Tomasz Napierala 		destroy_dev(sc->sc_cdev);
190*3914ddf8SEdward Tomasz Napierala 
191*3914ddf8SEdward Tomasz Napierala 	uma_zdestroy(autofs_request_zone);
192*3914ddf8SEdward Tomasz Napierala 	uma_zdestroy(autofs_node_zone);
193*3914ddf8SEdward Tomasz Napierala 
194*3914ddf8SEdward Tomasz Napierala 	sx_xunlock(&sc->sc_lock);
195*3914ddf8SEdward Tomasz Napierala 	/*
196*3914ddf8SEdward Tomasz Napierala 	 * XXX: Race with open?
197*3914ddf8SEdward Tomasz Napierala 	 */
198*3914ddf8SEdward Tomasz Napierala 	free(sc, M_AUTOFS);
199*3914ddf8SEdward Tomasz Napierala 
200*3914ddf8SEdward Tomasz Napierala 	return (0);
201*3914ddf8SEdward Tomasz Napierala }
202*3914ddf8SEdward Tomasz Napierala 
203*3914ddf8SEdward Tomasz Napierala bool
204*3914ddf8SEdward Tomasz Napierala autofs_ignore_thread(const struct thread *td)
205*3914ddf8SEdward Tomasz Napierala {
206*3914ddf8SEdward Tomasz Napierala 	struct proc *p;
207*3914ddf8SEdward Tomasz Napierala 
208*3914ddf8SEdward Tomasz Napierala 	p = td->td_proc;
209*3914ddf8SEdward Tomasz Napierala 
210*3914ddf8SEdward Tomasz Napierala 	if (sc->sc_dev_opened == false)
211*3914ddf8SEdward Tomasz Napierala 		return (false);
212*3914ddf8SEdward Tomasz Napierala 
213*3914ddf8SEdward Tomasz Napierala 	PROC_LOCK(p);
214*3914ddf8SEdward Tomasz Napierala 	if (p->p_session->s_sid == sc->sc_dev_sid) {
215*3914ddf8SEdward Tomasz Napierala 		PROC_UNLOCK(p);
216*3914ddf8SEdward Tomasz Napierala 		return (true);
217*3914ddf8SEdward Tomasz Napierala 	}
218*3914ddf8SEdward Tomasz Napierala 	PROC_UNLOCK(p);
219*3914ddf8SEdward Tomasz Napierala 
220*3914ddf8SEdward Tomasz Napierala 	return (false);
221*3914ddf8SEdward Tomasz Napierala }
222*3914ddf8SEdward Tomasz Napierala 
223*3914ddf8SEdward Tomasz Napierala static char *
224*3914ddf8SEdward Tomasz Napierala autofs_path(struct autofs_node *anp)
225*3914ddf8SEdward Tomasz Napierala {
226*3914ddf8SEdward Tomasz Napierala 	struct autofs_mount *amp;
227*3914ddf8SEdward Tomasz Napierala 	char *path, *tmp;
228*3914ddf8SEdward Tomasz Napierala 
229*3914ddf8SEdward Tomasz Napierala 	amp = anp->an_mount;
230*3914ddf8SEdward Tomasz Napierala 
231*3914ddf8SEdward Tomasz Napierala 	path = strdup("", M_AUTOFS);
232*3914ddf8SEdward Tomasz Napierala 	for (; anp->an_parent != NULL; anp = anp->an_parent) {
233*3914ddf8SEdward Tomasz Napierala 		tmp = malloc(strlen(anp->an_name) + strlen(path) + 2,
234*3914ddf8SEdward Tomasz Napierala 		    M_AUTOFS, M_WAITOK);
235*3914ddf8SEdward Tomasz Napierala 		strcpy(tmp, anp->an_name);
236*3914ddf8SEdward Tomasz Napierala 		strcat(tmp, "/");
237*3914ddf8SEdward Tomasz Napierala 		strcat(tmp, path);
238*3914ddf8SEdward Tomasz Napierala 		free(path, M_AUTOFS);
239*3914ddf8SEdward Tomasz Napierala 		path = tmp;
240*3914ddf8SEdward Tomasz Napierala 	}
241*3914ddf8SEdward Tomasz Napierala 
242*3914ddf8SEdward Tomasz Napierala 	tmp = malloc(strlen(amp->am_mountpoint) + strlen(path) + 2,
243*3914ddf8SEdward Tomasz Napierala 	    M_AUTOFS, M_WAITOK);
244*3914ddf8SEdward Tomasz Napierala 	strcpy(tmp, amp->am_mountpoint);
245*3914ddf8SEdward Tomasz Napierala 	strcat(tmp, "/");
246*3914ddf8SEdward Tomasz Napierala 	strcat(tmp, path);
247*3914ddf8SEdward Tomasz Napierala 	free(path, M_AUTOFS);
248*3914ddf8SEdward Tomasz Napierala 	path = tmp;
249*3914ddf8SEdward Tomasz Napierala 
250*3914ddf8SEdward Tomasz Napierala 	return (path);
251*3914ddf8SEdward Tomasz Napierala }
252*3914ddf8SEdward Tomasz Napierala 
253*3914ddf8SEdward Tomasz Napierala static void
254*3914ddf8SEdward Tomasz Napierala autofs_callout(void *context)
255*3914ddf8SEdward Tomasz Napierala {
256*3914ddf8SEdward Tomasz Napierala 	struct autofs_request *ar;
257*3914ddf8SEdward Tomasz Napierala 	struct autofs_softc *sc;
258*3914ddf8SEdward Tomasz Napierala 
259*3914ddf8SEdward Tomasz Napierala 	ar = context;
260*3914ddf8SEdward Tomasz Napierala 	sc = ar->ar_mount->am_softc;
261*3914ddf8SEdward Tomasz Napierala 
262*3914ddf8SEdward Tomasz Napierala 	sx_xlock(&sc->sc_lock);
263*3914ddf8SEdward Tomasz Napierala 	AUTOFS_WARN("request %d for %s timed out after %d seconds",
264*3914ddf8SEdward Tomasz Napierala 	    ar->ar_id, ar->ar_path, autofs_timeout);
265*3914ddf8SEdward Tomasz Napierala 	/*
266*3914ddf8SEdward Tomasz Napierala 	 * XXX: EIO perhaps?
267*3914ddf8SEdward Tomasz Napierala 	 */
268*3914ddf8SEdward Tomasz Napierala 	ar->ar_error = ETIMEDOUT;
269*3914ddf8SEdward Tomasz Napierala 	ar->ar_done = true;
270*3914ddf8SEdward Tomasz Napierala 	ar->ar_in_progress = false;
271*3914ddf8SEdward Tomasz Napierala 	cv_broadcast(&sc->sc_cv);
272*3914ddf8SEdward Tomasz Napierala 	sx_xunlock(&sc->sc_lock);
273*3914ddf8SEdward Tomasz Napierala }
274*3914ddf8SEdward Tomasz Napierala 
275*3914ddf8SEdward Tomasz Napierala bool
276*3914ddf8SEdward Tomasz Napierala autofs_cached(struct autofs_node *anp, const char *component, int componentlen)
277*3914ddf8SEdward Tomasz Napierala {
278*3914ddf8SEdward Tomasz Napierala 	int error;
279*3914ddf8SEdward Tomasz Napierala 	struct autofs_mount *amp;
280*3914ddf8SEdward Tomasz Napierala 
281*3914ddf8SEdward Tomasz Napierala 	amp = anp->an_mount;
282*3914ddf8SEdward Tomasz Napierala 
283*3914ddf8SEdward Tomasz Napierala 	AUTOFS_ASSERT_UNLOCKED(amp);
284*3914ddf8SEdward Tomasz Napierala 
285*3914ddf8SEdward Tomasz Napierala 	/*
286*3914ddf8SEdward Tomasz Napierala 	 * For top-level nodes we need to request automountd(8)
287*3914ddf8SEdward Tomasz Napierala 	 * assistance even if the node is marked as cached,
288*3914ddf8SEdward Tomasz Napierala 	 * but the requested subdirectory does not exist.  This
289*3914ddf8SEdward Tomasz Napierala 	 * is necessary for wildcard indirect map keys to work.
290*3914ddf8SEdward Tomasz Napierala 	 */
291*3914ddf8SEdward Tomasz Napierala 	if (anp->an_parent == NULL && componentlen != 0) {
292*3914ddf8SEdward Tomasz Napierala 		AUTOFS_LOCK(amp);
293*3914ddf8SEdward Tomasz Napierala 		error = autofs_node_find(anp, component, componentlen, NULL);
294*3914ddf8SEdward Tomasz Napierala 		AUTOFS_UNLOCK(amp);
295*3914ddf8SEdward Tomasz Napierala 		if (error != 0)
296*3914ddf8SEdward Tomasz Napierala 			return (false);
297*3914ddf8SEdward Tomasz Napierala 	}
298*3914ddf8SEdward Tomasz Napierala 
299*3914ddf8SEdward Tomasz Napierala 	return (anp->an_cached);
300*3914ddf8SEdward Tomasz Napierala }
301*3914ddf8SEdward Tomasz Napierala 
302*3914ddf8SEdward Tomasz Napierala static void
303*3914ddf8SEdward Tomasz Napierala autofs_cache_callout(void *context)
304*3914ddf8SEdward Tomasz Napierala {
305*3914ddf8SEdward Tomasz Napierala 	struct autofs_node *anp;
306*3914ddf8SEdward Tomasz Napierala 
307*3914ddf8SEdward Tomasz Napierala 	anp = context;
308*3914ddf8SEdward Tomasz Napierala 	anp->an_cached = false;
309*3914ddf8SEdward Tomasz Napierala }
310*3914ddf8SEdward Tomasz Napierala 
311*3914ddf8SEdward Tomasz Napierala /*
312*3914ddf8SEdward Tomasz Napierala  * The set/restore sigmask functions are used to (temporarily) overwrite
313*3914ddf8SEdward Tomasz Napierala  * the thread td_sigmask during triggering.
314*3914ddf8SEdward Tomasz Napierala  */
315*3914ddf8SEdward Tomasz Napierala static void
316*3914ddf8SEdward Tomasz Napierala autofs_set_sigmask(sigset_t *oldset)
317*3914ddf8SEdward Tomasz Napierala {
318*3914ddf8SEdward Tomasz Napierala 	sigset_t newset;
319*3914ddf8SEdward Tomasz Napierala 	int i;
320*3914ddf8SEdward Tomasz Napierala 
321*3914ddf8SEdward Tomasz Napierala 	SIGFILLSET(newset);
322*3914ddf8SEdward Tomasz Napierala 	/* Remove the autofs set of signals from newset */
323*3914ddf8SEdward Tomasz Napierala 	PROC_LOCK(curproc);
324*3914ddf8SEdward Tomasz Napierala 	mtx_lock(&curproc->p_sigacts->ps_mtx);
325*3914ddf8SEdward Tomasz Napierala 	for (i = 0 ; i < sizeof(autofs_sig_set)/sizeof(int) ; i++) {
326*3914ddf8SEdward Tomasz Napierala 		/*
327*3914ddf8SEdward Tomasz Napierala 		 * But make sure we leave the ones already masked
328*3914ddf8SEdward Tomasz Napierala 		 * by the process, i.e. remove the signal from the
329*3914ddf8SEdward Tomasz Napierala 		 * temporary signalmask only if it wasn't already
330*3914ddf8SEdward Tomasz Napierala 		 * in p_sigmask.
331*3914ddf8SEdward Tomasz Napierala 		 */
332*3914ddf8SEdward Tomasz Napierala 		if (!SIGISMEMBER(curthread->td_sigmask, autofs_sig_set[i]) &&
333*3914ddf8SEdward Tomasz Napierala 		    !SIGISMEMBER(curproc->p_sigacts->ps_sigignore,
334*3914ddf8SEdward Tomasz Napierala 		    autofs_sig_set[i])) {
335*3914ddf8SEdward Tomasz Napierala 			SIGDELSET(newset, autofs_sig_set[i]);
336*3914ddf8SEdward Tomasz Napierala 		}
337*3914ddf8SEdward Tomasz Napierala 	}
338*3914ddf8SEdward Tomasz Napierala 	mtx_unlock(&curproc->p_sigacts->ps_mtx);
339*3914ddf8SEdward Tomasz Napierala 	kern_sigprocmask(curthread, SIG_SETMASK, &newset, oldset,
340*3914ddf8SEdward Tomasz Napierala 	    SIGPROCMASK_PROC_LOCKED);
341*3914ddf8SEdward Tomasz Napierala 	PROC_UNLOCK(curproc);
342*3914ddf8SEdward Tomasz Napierala }
343*3914ddf8SEdward Tomasz Napierala 
344*3914ddf8SEdward Tomasz Napierala static void
345*3914ddf8SEdward Tomasz Napierala autofs_restore_sigmask(sigset_t *set)
346*3914ddf8SEdward Tomasz Napierala {
347*3914ddf8SEdward Tomasz Napierala 
348*3914ddf8SEdward Tomasz Napierala 	kern_sigprocmask(curthread, SIG_SETMASK, set, NULL, 0);
349*3914ddf8SEdward Tomasz Napierala }
350*3914ddf8SEdward Tomasz Napierala 
351*3914ddf8SEdward Tomasz Napierala static int
352*3914ddf8SEdward Tomasz Napierala autofs_trigger_one(struct autofs_node *anp,
353*3914ddf8SEdward Tomasz Napierala     const char *component, int componentlen)
354*3914ddf8SEdward Tomasz Napierala {
355*3914ddf8SEdward Tomasz Napierala 	sigset_t oldset;
356*3914ddf8SEdward Tomasz Napierala 	struct autofs_mount *amp;
357*3914ddf8SEdward Tomasz Napierala 	struct autofs_softc *sc;
358*3914ddf8SEdward Tomasz Napierala 	struct autofs_node *firstanp;
359*3914ddf8SEdward Tomasz Napierala 	struct autofs_request *ar;
360*3914ddf8SEdward Tomasz Napierala 	char *key, *path;
361*3914ddf8SEdward Tomasz Napierala 	int error = 0, request_error, last;
362*3914ddf8SEdward Tomasz Napierala 
363*3914ddf8SEdward Tomasz Napierala 	amp = VFSTOAUTOFS(anp->an_vnode->v_mount);
364*3914ddf8SEdward Tomasz Napierala 	sc = amp->am_softc;
365*3914ddf8SEdward Tomasz Napierala 
366*3914ddf8SEdward Tomasz Napierala 	sx_assert(&sc->sc_lock, SA_XLOCKED);
367*3914ddf8SEdward Tomasz Napierala 
368*3914ddf8SEdward Tomasz Napierala 	if (anp->an_parent == NULL) {
369*3914ddf8SEdward Tomasz Napierala 		key = strndup(component, componentlen, M_AUTOFS);
370*3914ddf8SEdward Tomasz Napierala 	} else {
371*3914ddf8SEdward Tomasz Napierala 		for (firstanp = anp; firstanp->an_parent->an_parent != NULL;
372*3914ddf8SEdward Tomasz Napierala 		    firstanp = firstanp->an_parent)
373*3914ddf8SEdward Tomasz Napierala 			continue;
374*3914ddf8SEdward Tomasz Napierala 		key = strdup(firstanp->an_name, M_AUTOFS);
375*3914ddf8SEdward Tomasz Napierala 	}
376*3914ddf8SEdward Tomasz Napierala 
377*3914ddf8SEdward Tomasz Napierala 	path = autofs_path(anp);
378*3914ddf8SEdward Tomasz Napierala 
379*3914ddf8SEdward Tomasz Napierala 	TAILQ_FOREACH(ar, &sc->sc_requests, ar_next) {
380*3914ddf8SEdward Tomasz Napierala 		if (strcmp(ar->ar_path, path) != 0)
381*3914ddf8SEdward Tomasz Napierala 			continue;
382*3914ddf8SEdward Tomasz Napierala 		if (strcmp(ar->ar_key, key) != 0)
383*3914ddf8SEdward Tomasz Napierala 			continue;
384*3914ddf8SEdward Tomasz Napierala 
385*3914ddf8SEdward Tomasz Napierala 		KASSERT(strcmp(ar->ar_from, amp->am_from) == 0,
386*3914ddf8SEdward Tomasz Napierala 		    ("from changed; %s != %s", ar->ar_from, amp->am_from));
387*3914ddf8SEdward Tomasz Napierala 		KASSERT(strcmp(ar->ar_prefix, amp->am_prefix) == 0,
388*3914ddf8SEdward Tomasz Napierala 		    ("prefix changed; %s != %s",
389*3914ddf8SEdward Tomasz Napierala 		     ar->ar_prefix, amp->am_prefix));
390*3914ddf8SEdward Tomasz Napierala 		KASSERT(strcmp(ar->ar_options, amp->am_options) == 0,
391*3914ddf8SEdward Tomasz Napierala 		    ("options changed; %s != %s",
392*3914ddf8SEdward Tomasz Napierala 		     ar->ar_options, amp->am_options));
393*3914ddf8SEdward Tomasz Napierala 
394*3914ddf8SEdward Tomasz Napierala 		break;
395*3914ddf8SEdward Tomasz Napierala 	}
396*3914ddf8SEdward Tomasz Napierala 
397*3914ddf8SEdward Tomasz Napierala 	if (ar != NULL) {
398*3914ddf8SEdward Tomasz Napierala 		refcount_acquire(&ar->ar_refcount);
399*3914ddf8SEdward Tomasz Napierala 	} else {
400*3914ddf8SEdward Tomasz Napierala 		ar = uma_zalloc(autofs_request_zone, M_WAITOK | M_ZERO);
401*3914ddf8SEdward Tomasz Napierala 		ar->ar_mount = amp;
402*3914ddf8SEdward Tomasz Napierala 
403*3914ddf8SEdward Tomasz Napierala 		ar->ar_id = atomic_fetchadd_int(&sc->sc_last_request_id, 1);
404*3914ddf8SEdward Tomasz Napierala 		strlcpy(ar->ar_from, amp->am_from, sizeof(ar->ar_from));
405*3914ddf8SEdward Tomasz Napierala 		strlcpy(ar->ar_path, path, sizeof(ar->ar_path));
406*3914ddf8SEdward Tomasz Napierala 		strlcpy(ar->ar_prefix, amp->am_prefix, sizeof(ar->ar_prefix));
407*3914ddf8SEdward Tomasz Napierala 		strlcpy(ar->ar_key, key, sizeof(ar->ar_key));
408*3914ddf8SEdward Tomasz Napierala 		strlcpy(ar->ar_options,
409*3914ddf8SEdward Tomasz Napierala 		    amp->am_options, sizeof(ar->ar_options));
410*3914ddf8SEdward Tomasz Napierala 
411*3914ddf8SEdward Tomasz Napierala 		callout_init(&ar->ar_callout, 1);
412*3914ddf8SEdward Tomasz Napierala 		callout_reset(&ar->ar_callout,
413*3914ddf8SEdward Tomasz Napierala 		    autofs_timeout * hz, autofs_callout, ar);
414*3914ddf8SEdward Tomasz Napierala 		refcount_init(&ar->ar_refcount, 1);
415*3914ddf8SEdward Tomasz Napierala 		TAILQ_INSERT_TAIL(&sc->sc_requests, ar, ar_next);
416*3914ddf8SEdward Tomasz Napierala 	}
417*3914ddf8SEdward Tomasz Napierala 
418*3914ddf8SEdward Tomasz Napierala 	cv_broadcast(&sc->sc_cv);
419*3914ddf8SEdward Tomasz Napierala 	while (ar->ar_done == false) {
420*3914ddf8SEdward Tomasz Napierala 		if (autofs_interruptible != 0) {
421*3914ddf8SEdward Tomasz Napierala 			autofs_set_sigmask(&oldset);
422*3914ddf8SEdward Tomasz Napierala 			error = cv_wait_sig(&sc->sc_cv, &sc->sc_lock);
423*3914ddf8SEdward Tomasz Napierala 			autofs_restore_sigmask(&oldset);
424*3914ddf8SEdward Tomasz Napierala 			if (error != 0) {
425*3914ddf8SEdward Tomasz Napierala 				/*
426*3914ddf8SEdward Tomasz Napierala 				 * XXX: For some reson this returns -1
427*3914ddf8SEdward Tomasz Napierala 				 *	instead of EINTR, wtf?!
428*3914ddf8SEdward Tomasz Napierala 				 */
429*3914ddf8SEdward Tomasz Napierala 				error = EINTR;
430*3914ddf8SEdward Tomasz Napierala 				AUTOFS_WARN("cv_wait_sig for %s failed "
431*3914ddf8SEdward Tomasz Napierala 				    "with error %d", ar->ar_path, error);
432*3914ddf8SEdward Tomasz Napierala 				break;
433*3914ddf8SEdward Tomasz Napierala 			}
434*3914ddf8SEdward Tomasz Napierala 		} else {
435*3914ddf8SEdward Tomasz Napierala 			cv_wait(&sc->sc_cv, &sc->sc_lock);
436*3914ddf8SEdward Tomasz Napierala 		}
437*3914ddf8SEdward Tomasz Napierala 	}
438*3914ddf8SEdward Tomasz Napierala 
439*3914ddf8SEdward Tomasz Napierala 	request_error = ar->ar_error;
440*3914ddf8SEdward Tomasz Napierala 	if (request_error != 0) {
441*3914ddf8SEdward Tomasz Napierala 		AUTOFS_WARN("request for %s completed with error %d",
442*3914ddf8SEdward Tomasz Napierala 		    ar->ar_path, request_error);
443*3914ddf8SEdward Tomasz Napierala 	}
444*3914ddf8SEdward Tomasz Napierala 
445*3914ddf8SEdward Tomasz Napierala 	last = refcount_release(&ar->ar_refcount);
446*3914ddf8SEdward Tomasz Napierala 	if (last) {
447*3914ddf8SEdward Tomasz Napierala 		TAILQ_REMOVE(&sc->sc_requests, ar, ar_next);
448*3914ddf8SEdward Tomasz Napierala 		/*
449*3914ddf8SEdward Tomasz Napierala 		 * XXX: Is it safe?
450*3914ddf8SEdward Tomasz Napierala 		 */
451*3914ddf8SEdward Tomasz Napierala 		sx_xunlock(&sc->sc_lock);
452*3914ddf8SEdward Tomasz Napierala 		callout_drain(&ar->ar_callout);
453*3914ddf8SEdward Tomasz Napierala 		sx_xlock(&sc->sc_lock);
454*3914ddf8SEdward Tomasz Napierala 		uma_zfree(autofs_request_zone, ar);
455*3914ddf8SEdward Tomasz Napierala 	}
456*3914ddf8SEdward Tomasz Napierala 
457*3914ddf8SEdward Tomasz Napierala 	/*
458*3914ddf8SEdward Tomasz Napierala 	 * Note that we do not do negative caching on purpose.  This
459*3914ddf8SEdward Tomasz Napierala 	 * way the user can retry access at any time, e.g. after fixing
460*3914ddf8SEdward Tomasz Napierala 	 * the failure reason, without waiting for cache timer to expire.
461*3914ddf8SEdward Tomasz Napierala 	 */
462*3914ddf8SEdward Tomasz Napierala 	if (error == 0 && request_error == 0 && autofs_cache > 0) {
463*3914ddf8SEdward Tomasz Napierala 		anp->an_cached = true;
464*3914ddf8SEdward Tomasz Napierala 		callout_reset(&anp->an_callout, autofs_cache * hz,
465*3914ddf8SEdward Tomasz Napierala 		    autofs_cache_callout, anp);
466*3914ddf8SEdward Tomasz Napierala 	}
467*3914ddf8SEdward Tomasz Napierala 
468*3914ddf8SEdward Tomasz Napierala 	free(key, M_AUTOFS);
469*3914ddf8SEdward Tomasz Napierala 	free(path, M_AUTOFS);
470*3914ddf8SEdward Tomasz Napierala 
471*3914ddf8SEdward Tomasz Napierala 	if (error != 0)
472*3914ddf8SEdward Tomasz Napierala 		return (error);
473*3914ddf8SEdward Tomasz Napierala 	return (request_error);
474*3914ddf8SEdward Tomasz Napierala }
475*3914ddf8SEdward Tomasz Napierala 
476*3914ddf8SEdward Tomasz Napierala /*
477*3914ddf8SEdward Tomasz Napierala  * Send request to automountd(8) and wait for completion.
478*3914ddf8SEdward Tomasz Napierala  */
479*3914ddf8SEdward Tomasz Napierala int
480*3914ddf8SEdward Tomasz Napierala autofs_trigger(struct autofs_node *anp,
481*3914ddf8SEdward Tomasz Napierala     const char *component, int componentlen)
482*3914ddf8SEdward Tomasz Napierala {
483*3914ddf8SEdward Tomasz Napierala 	int error;
484*3914ddf8SEdward Tomasz Napierala 
485*3914ddf8SEdward Tomasz Napierala 	for (;;) {
486*3914ddf8SEdward Tomasz Napierala 		error = autofs_trigger_one(anp, component, componentlen);
487*3914ddf8SEdward Tomasz Napierala 		if (error == 0) {
488*3914ddf8SEdward Tomasz Napierala 			anp->an_retries = 0;
489*3914ddf8SEdward Tomasz Napierala 			return (0);
490*3914ddf8SEdward Tomasz Napierala 		}
491*3914ddf8SEdward Tomasz Napierala 		if (error == EINTR) {
492*3914ddf8SEdward Tomasz Napierala 			AUTOFS_DEBUG("trigger interrupted by signal, "
493*3914ddf8SEdward Tomasz Napierala 			    "not retrying");
494*3914ddf8SEdward Tomasz Napierala 			anp->an_retries = 0;
495*3914ddf8SEdward Tomasz Napierala 			return (error);
496*3914ddf8SEdward Tomasz Napierala 		}
497*3914ddf8SEdward Tomasz Napierala 		anp->an_retries++;
498*3914ddf8SEdward Tomasz Napierala 		if (anp->an_retries >= autofs_retry_attempts) {
499*3914ddf8SEdward Tomasz Napierala 			AUTOFS_DEBUG("trigger failed %d times; returning "
500*3914ddf8SEdward Tomasz Napierala 			    "error %d", anp->an_retries, error);
501*3914ddf8SEdward Tomasz Napierala 			anp->an_retries = 0;
502*3914ddf8SEdward Tomasz Napierala 			return (error);
503*3914ddf8SEdward Tomasz Napierala 
504*3914ddf8SEdward Tomasz Napierala 		}
505*3914ddf8SEdward Tomasz Napierala 		AUTOFS_DEBUG("trigger failed with error %d; will retry in "
506*3914ddf8SEdward Tomasz Napierala 		    "%d seconds, %d attempts left", error, autofs_retry_delay,
507*3914ddf8SEdward Tomasz Napierala 		    autofs_retry_attempts - anp->an_retries);
508*3914ddf8SEdward Tomasz Napierala 		sx_xunlock(&sc->sc_lock);
509*3914ddf8SEdward Tomasz Napierala 		pause("autofs_retry", autofs_retry_delay * hz);
510*3914ddf8SEdward Tomasz Napierala 		sx_xlock(&sc->sc_lock);
511*3914ddf8SEdward Tomasz Napierala 	}
512*3914ddf8SEdward Tomasz Napierala }
513*3914ddf8SEdward Tomasz Napierala 
514*3914ddf8SEdward Tomasz Napierala static int
515*3914ddf8SEdward Tomasz Napierala autofs_ioctl_request(struct autofs_softc *sc, struct autofs_daemon_request *adr)
516*3914ddf8SEdward Tomasz Napierala {
517*3914ddf8SEdward Tomasz Napierala 	struct autofs_request *ar;
518*3914ddf8SEdward Tomasz Napierala 	int error;
519*3914ddf8SEdward Tomasz Napierala 
520*3914ddf8SEdward Tomasz Napierala 	sx_xlock(&sc->sc_lock);
521*3914ddf8SEdward Tomasz Napierala 	for (;;) {
522*3914ddf8SEdward Tomasz Napierala 		TAILQ_FOREACH(ar, &sc->sc_requests, ar_next) {
523*3914ddf8SEdward Tomasz Napierala 			if (ar->ar_done)
524*3914ddf8SEdward Tomasz Napierala 				continue;
525*3914ddf8SEdward Tomasz Napierala 			if (ar->ar_in_progress)
526*3914ddf8SEdward Tomasz Napierala 				continue;
527*3914ddf8SEdward Tomasz Napierala 
528*3914ddf8SEdward Tomasz Napierala 			break;
529*3914ddf8SEdward Tomasz Napierala 		}
530*3914ddf8SEdward Tomasz Napierala 
531*3914ddf8SEdward Tomasz Napierala 		if (ar != NULL)
532*3914ddf8SEdward Tomasz Napierala 			break;
533*3914ddf8SEdward Tomasz Napierala 
534*3914ddf8SEdward Tomasz Napierala 		error = cv_wait_sig(&sc->sc_cv, &sc->sc_lock);
535*3914ddf8SEdward Tomasz Napierala 		if (error != 0) {
536*3914ddf8SEdward Tomasz Napierala 			/*
537*3914ddf8SEdward Tomasz Napierala 			 * XXX: For some reson this returns -1 instead
538*3914ddf8SEdward Tomasz Napierala 			 * 	of EINTR, wtf?!
539*3914ddf8SEdward Tomasz Napierala 			 */
540*3914ddf8SEdward Tomasz Napierala 			error = EINTR;
541*3914ddf8SEdward Tomasz Napierala 			sx_xunlock(&sc->sc_lock);
542*3914ddf8SEdward Tomasz Napierala 			AUTOFS_DEBUG("failed with error %d", error);
543*3914ddf8SEdward Tomasz Napierala 			return (error);
544*3914ddf8SEdward Tomasz Napierala 		}
545*3914ddf8SEdward Tomasz Napierala 	}
546*3914ddf8SEdward Tomasz Napierala 
547*3914ddf8SEdward Tomasz Napierala 	ar->ar_in_progress = true;
548*3914ddf8SEdward Tomasz Napierala 	sx_xunlock(&sc->sc_lock);
549*3914ddf8SEdward Tomasz Napierala 
550*3914ddf8SEdward Tomasz Napierala 	adr->adr_id = ar->ar_id;
551*3914ddf8SEdward Tomasz Napierala 	strlcpy(adr->adr_from, ar->ar_from, sizeof(adr->adr_from));
552*3914ddf8SEdward Tomasz Napierala 	strlcpy(adr->adr_path, ar->ar_path, sizeof(adr->adr_path));
553*3914ddf8SEdward Tomasz Napierala 	strlcpy(adr->adr_prefix, ar->ar_prefix, sizeof(adr->adr_prefix));
554*3914ddf8SEdward Tomasz Napierala 	strlcpy(adr->adr_key, ar->ar_key, sizeof(adr->adr_key));
555*3914ddf8SEdward Tomasz Napierala 	strlcpy(adr->adr_options, ar->ar_options, sizeof(adr->adr_options));
556*3914ddf8SEdward Tomasz Napierala 
557*3914ddf8SEdward Tomasz Napierala 	PROC_LOCK(curproc);
558*3914ddf8SEdward Tomasz Napierala 	sc->sc_dev_sid = curproc->p_session->s_sid;
559*3914ddf8SEdward Tomasz Napierala 	PROC_UNLOCK(curproc);
560*3914ddf8SEdward Tomasz Napierala 
561*3914ddf8SEdward Tomasz Napierala 	return (0);
562*3914ddf8SEdward Tomasz Napierala }
563*3914ddf8SEdward Tomasz Napierala 
564*3914ddf8SEdward Tomasz Napierala static int
565*3914ddf8SEdward Tomasz Napierala autofs_ioctl_done(struct autofs_softc *sc, struct autofs_daemon_done *add)
566*3914ddf8SEdward Tomasz Napierala {
567*3914ddf8SEdward Tomasz Napierala 	struct autofs_request *ar;
568*3914ddf8SEdward Tomasz Napierala 
569*3914ddf8SEdward Tomasz Napierala 	sx_xlock(&sc->sc_lock);
570*3914ddf8SEdward Tomasz Napierala 	TAILQ_FOREACH(ar, &sc->sc_requests, ar_next) {
571*3914ddf8SEdward Tomasz Napierala 		if (ar->ar_id == add->add_id)
572*3914ddf8SEdward Tomasz Napierala 			break;
573*3914ddf8SEdward Tomasz Napierala 	}
574*3914ddf8SEdward Tomasz Napierala 
575*3914ddf8SEdward Tomasz Napierala 	if (ar == NULL) {
576*3914ddf8SEdward Tomasz Napierala 		sx_xunlock(&sc->sc_lock);
577*3914ddf8SEdward Tomasz Napierala 		AUTOFS_DEBUG("id %d not found", add->add_id);
578*3914ddf8SEdward Tomasz Napierala 		return (ESRCH);
579*3914ddf8SEdward Tomasz Napierala 	}
580*3914ddf8SEdward Tomasz Napierala 
581*3914ddf8SEdward Tomasz Napierala 	ar->ar_error = add->add_error;
582*3914ddf8SEdward Tomasz Napierala 	ar->ar_done = true;
583*3914ddf8SEdward Tomasz Napierala 	ar->ar_in_progress = false;
584*3914ddf8SEdward Tomasz Napierala 	cv_broadcast(&sc->sc_cv);
585*3914ddf8SEdward Tomasz Napierala 
586*3914ddf8SEdward Tomasz Napierala 	sx_xunlock(&sc->sc_lock);
587*3914ddf8SEdward Tomasz Napierala 
588*3914ddf8SEdward Tomasz Napierala 	return (0);
589*3914ddf8SEdward Tomasz Napierala }
590*3914ddf8SEdward Tomasz Napierala 
591*3914ddf8SEdward Tomasz Napierala static int
592*3914ddf8SEdward Tomasz Napierala autofs_open(struct cdev *dev, int flags, int fmt, struct thread *td)
593*3914ddf8SEdward Tomasz Napierala {
594*3914ddf8SEdward Tomasz Napierala 
595*3914ddf8SEdward Tomasz Napierala 	sx_xlock(&sc->sc_lock);
596*3914ddf8SEdward Tomasz Napierala 	if (sc->sc_dev_opened) {
597*3914ddf8SEdward Tomasz Napierala 		sx_xunlock(&sc->sc_lock);
598*3914ddf8SEdward Tomasz Napierala 		return (EBUSY);
599*3914ddf8SEdward Tomasz Napierala 	}
600*3914ddf8SEdward Tomasz Napierala 
601*3914ddf8SEdward Tomasz Napierala 	sc->sc_dev_opened = true;
602*3914ddf8SEdward Tomasz Napierala 	sx_xunlock(&sc->sc_lock);
603*3914ddf8SEdward Tomasz Napierala 
604*3914ddf8SEdward Tomasz Napierala 	return (0);
605*3914ddf8SEdward Tomasz Napierala }
606*3914ddf8SEdward Tomasz Napierala 
607*3914ddf8SEdward Tomasz Napierala static int
608*3914ddf8SEdward Tomasz Napierala autofs_close(struct cdev *dev, int flag, int fmt, struct thread *td)
609*3914ddf8SEdward Tomasz Napierala {
610*3914ddf8SEdward Tomasz Napierala 
611*3914ddf8SEdward Tomasz Napierala 	sx_xlock(&sc->sc_lock);
612*3914ddf8SEdward Tomasz Napierala 	KASSERT(sc->sc_dev_opened, ("not opened?"));
613*3914ddf8SEdward Tomasz Napierala 	sc->sc_dev_opened = false;
614*3914ddf8SEdward Tomasz Napierala 	sx_xunlock(&sc->sc_lock);
615*3914ddf8SEdward Tomasz Napierala 
616*3914ddf8SEdward Tomasz Napierala 	return (0);
617*3914ddf8SEdward Tomasz Napierala }
618*3914ddf8SEdward Tomasz Napierala 
619*3914ddf8SEdward Tomasz Napierala static int
620*3914ddf8SEdward Tomasz Napierala autofs_ioctl(struct cdev *dev, u_long cmd, caddr_t arg, int mode,
621*3914ddf8SEdward Tomasz Napierala     struct thread *td)
622*3914ddf8SEdward Tomasz Napierala {
623*3914ddf8SEdward Tomasz Napierala 
624*3914ddf8SEdward Tomasz Napierala 	KASSERT(sc->sc_dev_opened, ("not opened?"));
625*3914ddf8SEdward Tomasz Napierala 
626*3914ddf8SEdward Tomasz Napierala 	switch (cmd) {
627*3914ddf8SEdward Tomasz Napierala 	case AUTOFSREQUEST:
628*3914ddf8SEdward Tomasz Napierala 		return (autofs_ioctl_request(sc,
629*3914ddf8SEdward Tomasz Napierala 		    (struct autofs_daemon_request *)arg));
630*3914ddf8SEdward Tomasz Napierala 	case AUTOFSDONE:
631*3914ddf8SEdward Tomasz Napierala 		return (autofs_ioctl_done(sc,
632*3914ddf8SEdward Tomasz Napierala 		    (struct autofs_daemon_done *)arg));
633*3914ddf8SEdward Tomasz Napierala 	default:
634*3914ddf8SEdward Tomasz Napierala 		AUTOFS_DEBUG("invalid cmd %lx", cmd);
635*3914ddf8SEdward Tomasz Napierala 		return (EINVAL);
636*3914ddf8SEdward Tomasz Napierala 	}
637*3914ddf8SEdward Tomasz Napierala }
638