13914ddf8SEdward Tomasz Napierala /*-
2*4d846d26SWarner Losh * SPDX-License-Identifier: BSD-2-Clause
318dffafaSEdward Tomasz Napierala *
43914ddf8SEdward Tomasz Napierala * Copyright (c) 2014 The FreeBSD Foundation
53914ddf8SEdward Tomasz Napierala *
63914ddf8SEdward Tomasz Napierala * This software was developed by Edward Tomasz Napierala under sponsorship
73914ddf8SEdward Tomasz Napierala * from the FreeBSD Foundation.
83914ddf8SEdward Tomasz Napierala *
93914ddf8SEdward Tomasz Napierala * Redistribution and use in source and binary forms, with or without
103914ddf8SEdward Tomasz Napierala * modification, are permitted provided that the following conditions
113914ddf8SEdward Tomasz Napierala * are met:
123914ddf8SEdward Tomasz Napierala * 1. Redistributions of source code must retain the above copyright
133914ddf8SEdward Tomasz Napierala * notice, this list of conditions and the following disclaimer.
143914ddf8SEdward Tomasz Napierala * 2. Redistributions in binary form must reproduce the above copyright
153914ddf8SEdward Tomasz Napierala * notice, this list of conditions and the following disclaimer in the
163914ddf8SEdward Tomasz Napierala * documentation and/or other materials provided with the distribution.
173914ddf8SEdward Tomasz Napierala *
183914ddf8SEdward Tomasz Napierala * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
193914ddf8SEdward Tomasz Napierala * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
203914ddf8SEdward Tomasz Napierala * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
213914ddf8SEdward Tomasz Napierala * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
223914ddf8SEdward Tomasz Napierala * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
233914ddf8SEdward Tomasz Napierala * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
243914ddf8SEdward Tomasz Napierala * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
253914ddf8SEdward Tomasz Napierala * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
263914ddf8SEdward Tomasz Napierala * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
273914ddf8SEdward Tomasz Napierala * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
283914ddf8SEdward Tomasz Napierala * SUCH DAMAGE.
293914ddf8SEdward Tomasz Napierala *
303914ddf8SEdward Tomasz Napierala */
313914ddf8SEdward Tomasz Napierala
32925fd945SEdward Tomasz Napierala
333914ddf8SEdward Tomasz Napierala #include <sys/param.h>
343914ddf8SEdward Tomasz Napierala #include <sys/systm.h>
353914ddf8SEdward Tomasz Napierala #include <sys/conf.h>
363914ddf8SEdward Tomasz Napierala #include <sys/condvar.h>
373914ddf8SEdward Tomasz Napierala #include <sys/ioccom.h>
383914ddf8SEdward Tomasz Napierala #include <sys/kernel.h>
393914ddf8SEdward Tomasz Napierala #include <sys/module.h>
403914ddf8SEdward Tomasz Napierala #include <sys/mount.h>
417571d313SEdward Tomasz Napierala #include <sys/stat.h>
423914ddf8SEdward Tomasz Napierala #include <sys/sx.h>
43759489f9SEdward Tomasz Napierala #include <sys/taskqueue.h>
4442ed64e3SEdward Tomasz Napierala #include <sys/tree.h>
453914ddf8SEdward Tomasz Napierala #include <sys/vnode.h>
463914ddf8SEdward Tomasz Napierala
47f5440d1aSEdward Tomasz Napierala #include <fs/autofs/autofs.h>
483914ddf8SEdward Tomasz Napierala
493914ddf8SEdward Tomasz Napierala static const char *autofs_opts[] = {
503914ddf8SEdward Tomasz Napierala "from", "master_options", "master_prefix", NULL
513914ddf8SEdward Tomasz Napierala };
523914ddf8SEdward Tomasz Napierala
53f81018caSEdward Tomasz Napierala extern struct autofs_softc *autofs_softc;
543914ddf8SEdward Tomasz Napierala
553914ddf8SEdward Tomasz Napierala static int
autofs_mount(struct mount * mp)563914ddf8SEdward Tomasz Napierala autofs_mount(struct mount *mp)
573914ddf8SEdward Tomasz Napierala {
583914ddf8SEdward Tomasz Napierala struct autofs_mount *amp;
593914ddf8SEdward Tomasz Napierala char *from, *fspath, *options, *prefix;
603914ddf8SEdward Tomasz Napierala int error;
613914ddf8SEdward Tomasz Napierala
623914ddf8SEdward Tomasz Napierala if (vfs_filteropt(mp->mnt_optnew, autofs_opts))
633914ddf8SEdward Tomasz Napierala return (EINVAL);
643914ddf8SEdward Tomasz Napierala
65e3d5f1feSEdward Tomasz Napierala if (mp->mnt_flag & MNT_UPDATE) {
66e3d5f1feSEdward Tomasz Napierala autofs_flush(VFSTOAUTOFS(mp));
673914ddf8SEdward Tomasz Napierala return (0);
68e3d5f1feSEdward Tomasz Napierala }
693914ddf8SEdward Tomasz Napierala
703914ddf8SEdward Tomasz Napierala if (vfs_getopt(mp->mnt_optnew, "from", (void **)&from, NULL))
713914ddf8SEdward Tomasz Napierala return (EINVAL);
723914ddf8SEdward Tomasz Napierala
733914ddf8SEdward Tomasz Napierala if (vfs_getopt(mp->mnt_optnew, "fspath", (void **)&fspath, NULL))
743914ddf8SEdward Tomasz Napierala return (EINVAL);
753914ddf8SEdward Tomasz Napierala
763914ddf8SEdward Tomasz Napierala if (vfs_getopt(mp->mnt_optnew, "master_options", (void **)&options, NULL))
773914ddf8SEdward Tomasz Napierala return (EINVAL);
783914ddf8SEdward Tomasz Napierala
793914ddf8SEdward Tomasz Napierala if (vfs_getopt(mp->mnt_optnew, "master_prefix", (void **)&prefix, NULL))
803914ddf8SEdward Tomasz Napierala return (EINVAL);
813914ddf8SEdward Tomasz Napierala
823914ddf8SEdward Tomasz Napierala amp = malloc(sizeof(*amp), M_AUTOFS, M_WAITOK | M_ZERO);
833914ddf8SEdward Tomasz Napierala mp->mnt_data = amp;
843914ddf8SEdward Tomasz Napierala amp->am_mp = mp;
853914ddf8SEdward Tomasz Napierala strlcpy(amp->am_from, from, sizeof(amp->am_from));
863914ddf8SEdward Tomasz Napierala strlcpy(amp->am_mountpoint, fspath, sizeof(amp->am_mountpoint));
873914ddf8SEdward Tomasz Napierala strlcpy(amp->am_options, options, sizeof(amp->am_options));
883914ddf8SEdward Tomasz Napierala strlcpy(amp->am_prefix, prefix, sizeof(amp->am_prefix));
893914ddf8SEdward Tomasz Napierala sx_init(&->am_lock, "autofslk");
903914ddf8SEdward Tomasz Napierala amp->am_last_fileno = 1;
913914ddf8SEdward Tomasz Napierala
923914ddf8SEdward Tomasz Napierala vfs_getnewfsid(mp);
933914ddf8SEdward Tomasz Napierala
94d19c297eSEdward Tomasz Napierala MNT_ILOCK(mp);
95d19c297eSEdward Tomasz Napierala mp->mnt_kern_flag |= MNTK_LOOKUP_SHARED;
96d19c297eSEdward Tomasz Napierala MNT_IUNLOCK(mp);
97d19c297eSEdward Tomasz Napierala
982eaebf35SEdward Tomasz Napierala AUTOFS_XLOCK(amp);
993914ddf8SEdward Tomasz Napierala error = autofs_node_new(NULL, amp, ".", -1, &->am_root);
1003914ddf8SEdward Tomasz Napierala if (error != 0) {
1012eaebf35SEdward Tomasz Napierala AUTOFS_XUNLOCK(amp);
1023914ddf8SEdward Tomasz Napierala free(amp, M_AUTOFS);
1033914ddf8SEdward Tomasz Napierala return (error);
1043914ddf8SEdward Tomasz Napierala }
1052eaebf35SEdward Tomasz Napierala AUTOFS_XUNLOCK(amp);
1063914ddf8SEdward Tomasz Napierala
1073914ddf8SEdward Tomasz Napierala vfs_mountedfrom(mp, from);
1083914ddf8SEdward Tomasz Napierala
1093914ddf8SEdward Tomasz Napierala return (0);
1103914ddf8SEdward Tomasz Napierala }
1113914ddf8SEdward Tomasz Napierala
1123914ddf8SEdward Tomasz Napierala static int
autofs_unmount(struct mount * mp,int mntflags)1133914ddf8SEdward Tomasz Napierala autofs_unmount(struct mount *mp, int mntflags)
1143914ddf8SEdward Tomasz Napierala {
1153914ddf8SEdward Tomasz Napierala struct autofs_mount *amp;
1163914ddf8SEdward Tomasz Napierala struct autofs_node *anp;
1173914ddf8SEdward Tomasz Napierala struct autofs_request *ar;
1183914ddf8SEdward Tomasz Napierala int error, flags;
1193914ddf8SEdward Tomasz Napierala bool found;
1203914ddf8SEdward Tomasz Napierala
1213914ddf8SEdward Tomasz Napierala amp = VFSTOAUTOFS(mp);
1223914ddf8SEdward Tomasz Napierala
1233914ddf8SEdward Tomasz Napierala flags = 0;
1243914ddf8SEdward Tomasz Napierala if (mntflags & MNT_FORCE)
1253914ddf8SEdward Tomasz Napierala flags |= FORCECLOSE;
1263914ddf8SEdward Tomasz Napierala error = vflush(mp, 0, flags, curthread);
1273914ddf8SEdward Tomasz Napierala if (error != 0) {
128d499502dSEdward Tomasz Napierala AUTOFS_DEBUG("vflush failed with error %d", error);
1293914ddf8SEdward Tomasz Napierala return (error);
1303914ddf8SEdward Tomasz Napierala }
1313914ddf8SEdward Tomasz Napierala
1323914ddf8SEdward Tomasz Napierala /*
1333914ddf8SEdward Tomasz Napierala * All vnodes are gone, and new one will not appear - so,
1343914ddf8SEdward Tomasz Napierala * no new triggerings. We can iterate over outstanding
1353914ddf8SEdward Tomasz Napierala * autofs_requests and terminate them.
1363914ddf8SEdward Tomasz Napierala */
1373914ddf8SEdward Tomasz Napierala for (;;) {
1383914ddf8SEdward Tomasz Napierala found = false;
139f81018caSEdward Tomasz Napierala sx_xlock(&autofs_softc->sc_lock);
140f81018caSEdward Tomasz Napierala TAILQ_FOREACH(ar, &autofs_softc->sc_requests, ar_next) {
1413914ddf8SEdward Tomasz Napierala if (ar->ar_mount != amp)
1423914ddf8SEdward Tomasz Napierala continue;
1433914ddf8SEdward Tomasz Napierala ar->ar_error = ENXIO;
1443914ddf8SEdward Tomasz Napierala ar->ar_done = true;
1453914ddf8SEdward Tomasz Napierala ar->ar_in_progress = false;
1463914ddf8SEdward Tomasz Napierala found = true;
1473914ddf8SEdward Tomasz Napierala }
148f81018caSEdward Tomasz Napierala sx_xunlock(&autofs_softc->sc_lock);
1493914ddf8SEdward Tomasz Napierala if (found == false)
1503914ddf8SEdward Tomasz Napierala break;
1513914ddf8SEdward Tomasz Napierala
152f81018caSEdward Tomasz Napierala cv_broadcast(&autofs_softc->sc_cv);
1533914ddf8SEdward Tomasz Napierala pause("autofs_umount", 1);
1543914ddf8SEdward Tomasz Napierala }
1553914ddf8SEdward Tomasz Napierala
1562eaebf35SEdward Tomasz Napierala AUTOFS_XLOCK(amp);
1573914ddf8SEdward Tomasz Napierala
1583914ddf8SEdward Tomasz Napierala /*
1593914ddf8SEdward Tomasz Napierala * Not terribly efficient, but at least not recursive.
1603914ddf8SEdward Tomasz Napierala */
16142ed64e3SEdward Tomasz Napierala while (!RB_EMPTY(&->am_root->an_children)) {
16242ed64e3SEdward Tomasz Napierala anp = RB_MIN(autofs_node_tree, &->am_root->an_children);
16342ed64e3SEdward Tomasz Napierala while (!RB_EMPTY(&anp->an_children))
16442ed64e3SEdward Tomasz Napierala anp = RB_MIN(autofs_node_tree, &anp->an_children);
1653914ddf8SEdward Tomasz Napierala autofs_node_delete(anp);
1663914ddf8SEdward Tomasz Napierala }
1673914ddf8SEdward Tomasz Napierala autofs_node_delete(amp->am_root);
1683914ddf8SEdward Tomasz Napierala
1693914ddf8SEdward Tomasz Napierala mp->mnt_data = NULL;
1702eaebf35SEdward Tomasz Napierala AUTOFS_XUNLOCK(amp);
1713914ddf8SEdward Tomasz Napierala
1723914ddf8SEdward Tomasz Napierala sx_destroy(&->am_lock);
1733914ddf8SEdward Tomasz Napierala
1743914ddf8SEdward Tomasz Napierala free(amp, M_AUTOFS);
1753914ddf8SEdward Tomasz Napierala
1763914ddf8SEdward Tomasz Napierala return (0);
1773914ddf8SEdward Tomasz Napierala }
1783914ddf8SEdward Tomasz Napierala
1793914ddf8SEdward Tomasz Napierala static int
autofs_root(struct mount * mp,int flags,struct vnode ** vpp)1803914ddf8SEdward Tomasz Napierala autofs_root(struct mount *mp, int flags, struct vnode **vpp)
1813914ddf8SEdward Tomasz Napierala {
1823914ddf8SEdward Tomasz Napierala struct autofs_mount *amp;
1833914ddf8SEdward Tomasz Napierala int error;
1843914ddf8SEdward Tomasz Napierala
1853914ddf8SEdward Tomasz Napierala amp = VFSTOAUTOFS(mp);
1863914ddf8SEdward Tomasz Napierala
187d19c297eSEdward Tomasz Napierala error = autofs_node_vn(amp->am_root, mp, flags, vpp);
1883914ddf8SEdward Tomasz Napierala
1893914ddf8SEdward Tomasz Napierala return (error);
1903914ddf8SEdward Tomasz Napierala }
1913914ddf8SEdward Tomasz Napierala
1923914ddf8SEdward Tomasz Napierala static int
autofs_statfs(struct mount * mp,struct statfs * sbp)1933914ddf8SEdward Tomasz Napierala autofs_statfs(struct mount *mp, struct statfs *sbp)
1943914ddf8SEdward Tomasz Napierala {
1953914ddf8SEdward Tomasz Napierala
1967571d313SEdward Tomasz Napierala sbp->f_bsize = S_BLKSIZE;
1973914ddf8SEdward Tomasz Napierala sbp->f_iosize = 0;
1983914ddf8SEdward Tomasz Napierala sbp->f_blocks = 0;
1993914ddf8SEdward Tomasz Napierala sbp->f_bfree = 0;
2003914ddf8SEdward Tomasz Napierala sbp->f_bavail = 0;
2013914ddf8SEdward Tomasz Napierala sbp->f_files = 0;
2023914ddf8SEdward Tomasz Napierala sbp->f_ffree = 0;
2033914ddf8SEdward Tomasz Napierala
2043914ddf8SEdward Tomasz Napierala return (0);
2053914ddf8SEdward Tomasz Napierala }
2063914ddf8SEdward Tomasz Napierala
2073914ddf8SEdward Tomasz Napierala static struct vfsops autofs_vfsops = {
2083914ddf8SEdward Tomasz Napierala .vfs_fhtovp = NULL, /* XXX */
2093914ddf8SEdward Tomasz Napierala .vfs_mount = autofs_mount,
2103914ddf8SEdward Tomasz Napierala .vfs_unmount = autofs_unmount,
2113914ddf8SEdward Tomasz Napierala .vfs_root = autofs_root,
2123914ddf8SEdward Tomasz Napierala .vfs_statfs = autofs_statfs,
2133914ddf8SEdward Tomasz Napierala .vfs_init = autofs_init,
2143914ddf8SEdward Tomasz Napierala .vfs_uninit = autofs_uninit,
2153914ddf8SEdward Tomasz Napierala };
2163914ddf8SEdward Tomasz Napierala
2173914ddf8SEdward Tomasz Napierala VFS_SET(autofs_vfsops, autofs, VFCF_SYNTHETIC | VFCF_NETWORK);
2183914ddf8SEdward Tomasz Napierala MODULE_VERSION(autofs, 1);
219