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