2 * Copyright (c) 2016 The DragonFly Project
3 * Copyright (c) 2014 The FreeBSD Foundation
6 * This software was developed by Edward Tomasz Napierala under sponsorship
7 * from the FreeBSD Foundation.
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
22 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 #include <sys/kernel.h>
33 #include <sys/module.h>
37 #include "autofs_mount.h"
39 static int autofs_statfs(struct mount *mp, struct statfs *sbp,
42 extern struct autofs_softc *autofs_softc;
45 autofs_mount(struct mount *mp, char *mntpt, caddr_t data, struct ucred *cred)
47 struct autofs_mount_info info;
48 struct autofs_mount *amp;
49 struct statfs *sbp = &mp->mnt_stat;
53 if (mp->mnt_flag & MNT_UPDATE) {
54 autofs_flush(VFSTOAUTOFS(mp));
58 error = copyin(data, &info, sizeof(info));
62 memset(sbp->f_mntfromname, 0, sizeof(sbp->f_mntfromname));
63 error = copyinstr(info.from, sbp->f_mntfromname,
64 sizeof(sbp->f_mntfromname), NULL);
68 memset(sbp->f_mntonname, 0, sizeof(sbp->f_mntonname));
69 error = copyinstr(mntpt, sbp->f_mntonname,
70 sizeof(sbp->f_mntonname), NULL);
74 amp = kmalloc(sizeof(*amp), M_AUTOFS, M_WAITOK | M_ZERO);
75 mp->mnt_data = (qaddr_t)amp;
77 strlcpy(amp->am_from, sbp->f_mntfromname, sizeof(amp->am_from));
78 strlcpy(amp->am_on, sbp->f_mntonname, sizeof(amp->am_on));
80 memset(buf, 0, sizeof(buf));
81 error = copyinstr(info.master_options, buf, sizeof(buf), NULL);
84 strlcpy(amp->am_options, buf, sizeof(amp->am_options));
86 memset(buf, 0, sizeof(buf));
87 error = copyinstr(info.master_prefix, buf, sizeof(buf), NULL);
90 strlcpy(amp->am_prefix, buf, sizeof(amp->am_prefix));
92 lockinit(&->am_lock, "autofsmnlk", 0, 0);
93 amp->am_last_ino = AUTOFS_ROOTINO;
96 vfs_add_vnodeops(mp, &autofs_vnode_vops, &mp->mnt_vn_norm_ops);
98 lockmgr(&->am_lock, LK_EXCLUSIVE);
99 error = autofs_node_new(NULL, amp, ".", -1, &->am_root);
100 lockmgr(&->am_lock, LK_RELEASE);
101 KKASSERT(error == 0);
102 KKASSERT(amp->am_root->an_ino == AUTOFS_ROOTINO);
104 autofs_statfs(mp, sbp, cred);
109 kfree(amp, M_AUTOFS);
114 autofs_unmount(struct mount *mp, int mntflags)
116 struct autofs_mount *amp = VFSTOAUTOFS(mp);
117 struct autofs_node *anp;
118 struct autofs_request *ar;
119 int error, flags, dummy;
123 if (mntflags & MNT_FORCE)
125 error = vflush(mp, 0, flags);
127 AUTOFS_WARN("vflush failed with error %d", error);
132 * All vnodes are gone, and new one will not appear - so,
133 * no new triggerings.
137 lockmgr(&autofs_softc->sc_lock, LK_EXCLUSIVE);
138 TAILQ_FOREACH(ar, &autofs_softc->sc_requests, ar_next) {
139 if (ar->ar_mount != amp)
141 ar->ar_error = ENXIO;
143 ar->ar_in_progress = false;
146 if (found == false) {
147 lockmgr(&autofs_softc->sc_lock, LK_RELEASE);
151 cv_broadcast(&autofs_softc->sc_cv);
152 lockmgr(&autofs_softc->sc_lock, LK_RELEASE);
154 tsleep(&dummy, 0, "autofs_umount", hz);
157 lockmgr(&->am_lock, LK_EXCLUSIVE);
158 while (!RB_EMPTY(&->am_root->an_children)) {
159 anp = RB_MIN(autofs_node_tree, &->am_root->an_children);
160 autofs_node_delete(anp);
162 autofs_node_delete(amp->am_root);
164 lockmgr(&->am_lock, LK_RELEASE);
166 lockuninit(&->am_lock);
168 kfree(amp, M_AUTOFS);
174 autofs_root(struct mount *mp, struct vnode **vpp)
176 struct autofs_mount *amp = VFSTOAUTOFS(mp);
179 if (amp->am_root == NULL) {
180 AUTOFS_FATAL("called without root node %p", mp);
185 error = autofs_node_vn(amp->am_root, mp, LK_EXCLUSIVE, vpp);
186 (*vpp)->v_flag |= VROOT;
187 KKASSERT((*vpp)->v_type == VDIR);
194 autofs_statfs(struct mount *mp, struct statfs *sbp, struct ucred *cred)
196 sbp->f_bsize = S_BLKSIZE;
208 autofs_statvfs(struct mount *mp, struct statvfs *sbp, struct ucred *cred)
210 sbp->f_bsize = S_BLKSIZE;
221 static struct vfsops autofs_vfsops = {
222 .vfs_mount = autofs_mount,
223 .vfs_unmount = autofs_unmount,
224 .vfs_root = autofs_root,
225 .vfs_statfs = autofs_statfs,
226 .vfs_statvfs = autofs_statvfs,
227 .vfs_init = autofs_init,
228 .vfs_uninit = autofs_uninit,
232 .vfs_checkexp = NULL,
236 VFS_SET(autofs_vfsops, autofs, VFCF_SYNTHETIC | VFCF_NETWORK);
237 MODULE_VERSION(autofs, 1);