1b985414bSchristos /*-
2b985414bSchristos * Copyright (c) 2017 The NetBSD Foundation, Inc.
3b985414bSchristos * Copyright (c) 2016 The DragonFly Project
4b985414bSchristos * Copyright (c) 2014 The FreeBSD Foundation
5b985414bSchristos * All rights reserved.
6b985414bSchristos *
7b985414bSchristos * This code is derived from software contributed to The NetBSD Foundation
8b985414bSchristos * by Tomohiro Kusumi <kusumi.tomohiro@gmail.com>.
9b985414bSchristos *
10b985414bSchristos * This software was developed by Edward Tomasz Napierala under sponsorship
11b985414bSchristos * from the FreeBSD Foundation.
12b985414bSchristos *
13b985414bSchristos * Redistribution and use in source and binary forms, with or without
14b985414bSchristos * modification, are permitted provided that the following conditions
15b985414bSchristos * are met:
16b985414bSchristos * 1. Redistributions of source code must retain the above copyright
17b985414bSchristos * notice, this list of conditions and the following disclaimer.
18b985414bSchristos * 2. Redistributions in binary form must reproduce the above copyright
19b985414bSchristos * notice, this list of conditions and the following disclaimer in the
20b985414bSchristos * documentation and/or other materials provided with the distribution.
21b985414bSchristos *
22b985414bSchristos * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
23b985414bSchristos * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24b985414bSchristos * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25b985414bSchristos * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
26b985414bSchristos * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27b985414bSchristos * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28b985414bSchristos * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29b985414bSchristos * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30b985414bSchristos * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31b985414bSchristos * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32b985414bSchristos * SUCH DAMAGE.
33b985414bSchristos *
34b985414bSchristos */
35b985414bSchristos #include <sys/cdefs.h>
36*e7bed289Sriastradh __KERNEL_RCSID(0, "$NetBSD: autofs_vfsops.c,v 1.12 2022/03/28 12:33:22 riastradh Exp $");
37b985414bSchristos
38b985414bSchristos
39b985414bSchristos #include "autofs.h"
40b985414bSchristos #include "autofs_mount.h"
41b985414bSchristos
42b985414bSchristos #include <sys/stat.h>
43b985414bSchristos #include <sys/sysctl.h>
44b985414bSchristos #include <miscfs/genfs/genfs.h>
45b985414bSchristos
46b985414bSchristos MODULE(MODULE_CLASS_VFS, autofs, NULL);
47b985414bSchristos
48b985414bSchristos static int autofs_statvfs(struct mount *, struct statvfs *);
49b985414bSchristos
50b985414bSchristos static void
autofs_init(void)51b985414bSchristos autofs_init(void)
52b985414bSchristos {
53b985414bSchristos
54b985414bSchristos KASSERT(!autofs_softc);
55b985414bSchristos
56b985414bSchristos autofs_softc = kmem_zalloc(sizeof(*autofs_softc), KM_SLEEP);
57b985414bSchristos
58b985414bSchristos pool_init(&autofs_request_pool, sizeof(struct autofs_request), 0, 0, 0,
59b985414bSchristos "autofs_request", &pool_allocator_nointr, IPL_NONE);
60b985414bSchristos pool_init(&autofs_node_pool, sizeof(struct autofs_node), 0, 0, 0,
61b985414bSchristos "autofs_node", &pool_allocator_nointr, IPL_NONE);
62b985414bSchristos
63b985414bSchristos TAILQ_INIT(&autofs_softc->sc_requests);
64b985414bSchristos cv_init(&autofs_softc->sc_cv, "autofscv");
65b985414bSchristos mutex_init(&autofs_softc->sc_lock, MUTEX_DEFAULT, IPL_NONE);
66b985414bSchristos autofs_softc->sc_dev_opened = false;
670d40f566Schristos
680d40f566Schristos workqueue_create(&autofs_tmo_wq, "autofstmo",
690d40f566Schristos autofs_timeout_wq, NULL, 0, 0, WQ_MPSAFE);
70b985414bSchristos }
71b985414bSchristos
72b985414bSchristos static void
autofs_done(void)73b985414bSchristos autofs_done(void)
74b985414bSchristos {
75b5c5b669Stkusumi
76b985414bSchristos KASSERT(autofs_softc);
77b985414bSchristos KASSERT(!autofs_softc->sc_dev_opened);
78b985414bSchristos
790d40f566Schristos workqueue_destroy(autofs_tmo_wq);
800d40f566Schristos
81b985414bSchristos struct autofs_softc *sc = autofs_softc;
82b985414bSchristos autofs_softc = NULL;
83b985414bSchristos
84b985414bSchristos cv_destroy(&sc->sc_cv);
85b985414bSchristos mutex_destroy(&sc->sc_lock);
86b985414bSchristos
87b985414bSchristos pool_destroy(&autofs_request_pool);
88b985414bSchristos pool_destroy(&autofs_node_pool);
89b985414bSchristos
90b985414bSchristos kmem_free(sc, sizeof(*sc));
91b985414bSchristos }
92b985414bSchristos
93b985414bSchristos static int
autofs_mount(struct mount * mp,const char * path,void * data,size_t * data_len)94b985414bSchristos autofs_mount(struct mount *mp, const char *path, void *data, size_t *data_len)
95b985414bSchristos {
96b985414bSchristos struct autofs_args *args = data;
9787d09387Schristos struct autofs_mount *amp = VFSTOAUTOFS(mp);
98b985414bSchristos struct statvfs *sbp = &mp->mnt_stat;
99b985414bSchristos int error;
100b985414bSchristos
10187d09387Schristos if (mp->mnt_flag & MNT_UPDATE) {
10287d09387Schristos if (amp == NULL)
10387d09387Schristos return EIO;
10487d09387Schristos autofs_flush(amp);
10587d09387Schristos return 0;
10687d09387Schristos }
10787d09387Schristos
108b985414bSchristos if (!args)
109b985414bSchristos return EINVAL;
110b985414bSchristos
11187d09387Schristos if (mp->mnt_flag & MNT_GETARGS) {
11287d09387Schristos if (amp == NULL)
11387d09387Schristos return EIO;
11487d09387Schristos error = copyoutstr(amp->am_from, args->from,
11587d09387Schristos sizeof(amp->am_from), NULL);
11687d09387Schristos if (error)
11787d09387Schristos return error;
11887d09387Schristos error = copyoutstr(amp->am_options, args->master_options,
11987d09387Schristos sizeof(amp->am_options), NULL);
12087d09387Schristos if (error)
12187d09387Schristos return error;
12287d09387Schristos error = copyoutstr(amp->am_prefix, args->master_prefix,
12387d09387Schristos sizeof(amp->am_prefix), NULL);
12487d09387Schristos return error;
125b985414bSchristos }
126b985414bSchristos
12787d09387Schristos if (amp != NULL)
12887d09387Schristos return EBUSY;
12987d09387Schristos
130b985414bSchristos /*
131b985414bSchristos * Allocate the autofs mount.
132b985414bSchristos */
133b985414bSchristos amp = kmem_zalloc(sizeof(*amp), KM_SLEEP);
134b985414bSchristos mp->mnt_data = amp;
135b985414bSchristos amp->am_mp = mp;
136b985414bSchristos
137b985414bSchristos /*
138b985414bSchristos * Copy-in master_options string.
139b985414bSchristos */
140b985414bSchristos error = copyinstr(args->master_options, amp->am_options,
141b985414bSchristos sizeof(amp->am_options), NULL);
142b985414bSchristos if (error)
143b985414bSchristos goto fail;
144b985414bSchristos
145b985414bSchristos /*
146b985414bSchristos * Copy-in master_prefix string.
147b985414bSchristos */
148b985414bSchristos error = copyinstr(args->master_prefix, amp->am_prefix,
149b985414bSchristos sizeof(amp->am_prefix), NULL);
150b985414bSchristos if (error)
151b985414bSchristos goto fail;
152b985414bSchristos
153b985414bSchristos /*
154b985414bSchristos * Initialize the autofs mount.
155b985414bSchristos */
156b985414bSchristos mutex_init(&->am_lock, MUTEX_DEFAULT, IPL_NONE);
157b985414bSchristos amp->am_last_ino = AUTOFS_ROOTINO;
158b985414bSchristos
159b985414bSchristos mutex_enter(&->am_lock);
160b985414bSchristos error = autofs_node_new(NULL, amp, ".", -1, &->am_root);
161b985414bSchristos mutex_exit(&->am_lock);
16287d09387Schristos if (error)
16387d09387Schristos goto fail1;
164b985414bSchristos KASSERT(amp->am_root->an_ino == AUTOFS_ROOTINO);
165b985414bSchristos
166b985414bSchristos autofs_statvfs(mp, sbp);
167b985414bSchristos vfs_getnewfsid(mp);
168b985414bSchristos
169b985414bSchristos error = set_statvfs_info(path, UIO_USERSPACE, args->from, UIO_USERSPACE,
170b985414bSchristos mp->mnt_op->vfs_name, mp, curlwp);
171b985414bSchristos if (error)
17287d09387Schristos goto fail1;
173b985414bSchristos strlcpy(amp->am_from, sbp->f_mntfromname, sizeof(amp->am_from));
174b985414bSchristos strlcpy(amp->am_on, sbp->f_mntonname, sizeof(amp->am_on));
175b985414bSchristos
176b985414bSchristos return 0;
177b985414bSchristos
17887d09387Schristos fail1:
17987d09387Schristos mutex_destroy(&->am_lock);
180b985414bSchristos fail:
18187d09387Schristos mp->mnt_data = NULL;
182b985414bSchristos kmem_free(amp, sizeof(*amp));
183b985414bSchristos return error;
184b985414bSchristos }
185b985414bSchristos
186b985414bSchristos static int
autofs_unmount(struct mount * mp,int mntflags)187b985414bSchristos autofs_unmount(struct mount *mp, int mntflags)
188b985414bSchristos {
189b985414bSchristos struct autofs_mount *amp = VFSTOAUTOFS(mp);
190b985414bSchristos int error, flags;
191b985414bSchristos
192b985414bSchristos flags = 0;
193b985414bSchristos if (mntflags & MNT_FORCE)
194b985414bSchristos flags |= FORCECLOSE;
195b985414bSchristos error = vflush(mp, NULL, flags);
196b985414bSchristos if (error) {
19702e6d0f6Stkusumi AUTOFS_DEBUG("vflush failed with error %d", error);
198b985414bSchristos return error;
199b985414bSchristos }
200b985414bSchristos
201b985414bSchristos /*
202b985414bSchristos * All vnodes are gone, and new one will not appear - so,
203b985414bSchristos * no new triggerings.
204b985414bSchristos */
205b985414bSchristos for (;;) {
206b985414bSchristos struct autofs_request *ar;
207b985414bSchristos int dummy;
208b985414bSchristos bool found;
209b985414bSchristos
210b985414bSchristos found = false;
211b985414bSchristos mutex_enter(&autofs_softc->sc_lock);
212b985414bSchristos TAILQ_FOREACH(ar, &autofs_softc->sc_requests, ar_next) {
213b985414bSchristos if (ar->ar_mount != amp)
214b985414bSchristos continue;
215b985414bSchristos ar->ar_error = ENXIO;
216b985414bSchristos ar->ar_done = true;
217b985414bSchristos ar->ar_in_progress = false;
218b985414bSchristos found = true;
219b985414bSchristos }
220b985414bSchristos if (found == false) {
221b985414bSchristos mutex_exit(&autofs_softc->sc_lock);
222b985414bSchristos break;
223b985414bSchristos }
224b985414bSchristos
225b985414bSchristos cv_broadcast(&autofs_softc->sc_cv);
226b985414bSchristos mutex_exit(&autofs_softc->sc_lock);
227b985414bSchristos
228b985414bSchristos tsleep(&dummy, 0, "autofs_umount", hz);
229b985414bSchristos }
230b985414bSchristos
231b985414bSchristos mutex_enter(&->am_lock);
232b985414bSchristos while (!RB_EMPTY(&->am_root->an_children)) {
233b985414bSchristos struct autofs_node *anp;
23487a0cef2Stkusumi /*
23587a0cef2Stkusumi * Force delete all nodes when more than one level of
23687a0cef2Stkusumi * directories are created via indirect map. Autofs doesn't
23787a0cef2Stkusumi * support rmdir(2), thus this is the only way to get out.
23887a0cef2Stkusumi */
239b985414bSchristos anp = RB_MIN(autofs_node_tree, &->am_root->an_children);
24087a0cef2Stkusumi while (!RB_EMPTY(&anp->an_children))
24187a0cef2Stkusumi anp = RB_MIN(autofs_node_tree, &anp->an_children);
242b985414bSchristos autofs_node_delete(anp);
243b985414bSchristos }
244b985414bSchristos autofs_node_delete(amp->am_root);
245b985414bSchristos mp->mnt_data = NULL;
246b985414bSchristos mutex_exit(&->am_lock);
247b985414bSchristos
248b985414bSchristos mutex_destroy(&->am_lock);
249b985414bSchristos
250b985414bSchristos kmem_free(amp, sizeof(*amp));
251b985414bSchristos
252b985414bSchristos return 0;
253b985414bSchristos }
254b985414bSchristos
255b985414bSchristos static int
autofs_start(struct mount * mp,int flags)256b985414bSchristos autofs_start(struct mount *mp, int flags)
257b985414bSchristos {
258b985414bSchristos
259b985414bSchristos return 0;
260b985414bSchristos }
261b985414bSchristos
262b985414bSchristos static int
autofs_root(struct mount * mp,int lktype,struct vnode ** vpp)263c2e9cb94Sad autofs_root(struct mount *mp, int lktype, struct vnode **vpp)
264b985414bSchristos {
265b985414bSchristos struct autofs_node *anp = VFSTOAUTOFS(mp)->am_root;
266b985414bSchristos int error;
267b985414bSchristos
268b985414bSchristos error = vcache_get(mp, &anp, sizeof(anp), vpp);
269b985414bSchristos if (error)
270b985414bSchristos return error;
271c2e9cb94Sad error = vn_lock(*vpp, lktype);
272b985414bSchristos if (error) {
273b985414bSchristos vrele(*vpp);
274392c1668Stkusumi *vpp = NULLVP;
275b985414bSchristos return error;
276b985414bSchristos }
277b985414bSchristos
278b985414bSchristos return 0;
279b985414bSchristos }
280b985414bSchristos
281b985414bSchristos static int
autofs_statvfs(struct mount * mp,struct statvfs * sbp)282b985414bSchristos autofs_statvfs(struct mount *mp, struct statvfs *sbp)
283b985414bSchristos {
284b985414bSchristos
285b985414bSchristos sbp->f_bsize = S_BLKSIZE;
286b985414bSchristos sbp->f_frsize = S_BLKSIZE;
287b985414bSchristos sbp->f_iosize = 0;
288b985414bSchristos sbp->f_blocks = 0;
289b985414bSchristos sbp->f_bfree = 0;
290b985414bSchristos sbp->f_bavail = 0;
291b985414bSchristos sbp->f_bresvd = 0;
292b985414bSchristos sbp->f_files = 0;
293b985414bSchristos sbp->f_ffree = 0;
294b985414bSchristos sbp->f_favail = 0;
295b985414bSchristos sbp->f_fresvd = 0;
296b985414bSchristos
297b985414bSchristos copy_statvfs_info(sbp, mp);
298b985414bSchristos
299b985414bSchristos return 0;
300b985414bSchristos }
301b985414bSchristos
302b985414bSchristos static int
autofs_sync(struct mount * mp,int waitfor,kauth_cred_t uc)303b985414bSchristos autofs_sync(struct mount *mp, int waitfor, kauth_cred_t uc)
304b985414bSchristos {
305b985414bSchristos
306b985414bSchristos return 0;
307b985414bSchristos }
308b985414bSchristos
309b985414bSchristos static int
autofs_loadvnode(struct mount * mp,struct vnode * vp,const void * key,size_t key_len,const void ** new_key)310b985414bSchristos autofs_loadvnode(struct mount *mp, struct vnode *vp,
311b985414bSchristos const void *key, size_t key_len, const void **new_key)
312b985414bSchristos {
313b985414bSchristos struct autofs_node *anp;
314b985414bSchristos
315b985414bSchristos KASSERT(key_len == sizeof(anp));
316b985414bSchristos memcpy(&anp, key, key_len);
317b985414bSchristos KASSERT(!anp->an_vnode);
318b985414bSchristos
319b985414bSchristos vp->v_tag = VT_AUTOFS;
320b985414bSchristos vp->v_type = VDIR;
321b985414bSchristos vp->v_op = autofs_vnodeop_p;
322b985414bSchristos vp->v_data = anp;
323b985414bSchristos
324b985414bSchristos if (anp->an_ino == AUTOFS_ROOTINO)
325b985414bSchristos vp->v_vflag |= VV_ROOT;
326b985414bSchristos
327b985414bSchristos anp->an_vnode = vp;
328b985414bSchristos uvm_vnp_setsize(vp, 0);
329b985414bSchristos
330b985414bSchristos *new_key = &vp->v_data;
331b985414bSchristos
332b985414bSchristos return 0;
333b985414bSchristos }
334b985414bSchristos
335b985414bSchristos static const struct vnodeopv_desc * const autofs_vnodeopv_descs[] = {
336b985414bSchristos &autofs_vnodeop_opv_desc,
337b985414bSchristos NULL,
338b985414bSchristos };
339b985414bSchristos
340b985414bSchristos static struct vfsops autofs_vfsops = {
341b985414bSchristos .vfs_name = MOUNT_AUTOFS,
342b985414bSchristos .vfs_min_mount_data = sizeof(struct autofs_args),
343b985414bSchristos .vfs_mount = autofs_mount,
344b985414bSchristos .vfs_start = autofs_start,
345b985414bSchristos .vfs_unmount = autofs_unmount,
346b985414bSchristos .vfs_root = autofs_root,
347b985414bSchristos .vfs_quotactl = (void *)eopnotsupp,
348b985414bSchristos .vfs_statvfs = autofs_statvfs,
349b985414bSchristos .vfs_sync = autofs_sync,
350b985414bSchristos .vfs_vget = (void *)eopnotsupp,
351b985414bSchristos .vfs_loadvnode = (void *)autofs_loadvnode,
352b985414bSchristos .vfs_newvnode = (void *)eopnotsupp,
353b985414bSchristos .vfs_fhtovp = (void *)eopnotsupp,
354b985414bSchristos .vfs_vptofh = (void *)eopnotsupp,
355b985414bSchristos .vfs_init = autofs_init,
356b985414bSchristos .vfs_reinit = (void *)eopnotsupp,
357b985414bSchristos .vfs_done = autofs_done,
358b985414bSchristos .vfs_mountroot = (void *)eopnotsupp,
359b985414bSchristos .vfs_snapshot = (void *)eopnotsupp,
360b985414bSchristos .vfs_extattrctl = (void *)eopnotsupp,
361b985414bSchristos .vfs_suspendctl = (void *)genfs_suspendctl,
362b985414bSchristos .vfs_renamelock_enter = (void *)eopnotsupp,
363b985414bSchristos .vfs_renamelock_exit = (void *)eopnotsupp,
364b985414bSchristos .vfs_fsync = (void *)eopnotsupp,
365b985414bSchristos .vfs_opv_descs = autofs_vnodeopv_descs
366b985414bSchristos };
367b985414bSchristos
368b985414bSchristos #define AUTOFS_SYSCTL_DEBUG 1
369b985414bSchristos #define AUTOFS_SYSCTL_MOUNT_ON_STAT 2
370b985414bSchristos #define AUTOFS_SYSCTL_TIMEOUT 3
371b985414bSchristos #define AUTOFS_SYSCTL_CACHE 4
372b985414bSchristos #define AUTOFS_SYSCTL_RETRY_ATTEMPTS 5
373b985414bSchristos #define AUTOFS_SYSCTL_RETRY_DELAY 6
374b985414bSchristos #define AUTOFS_SYSCTL_INTERRUPTIBLE 7
375b985414bSchristos
3769120d451Spgoyette SYSCTL_SETUP(autofs_sysctl_create, "autofs sysctl")
377b985414bSchristos {
378b985414bSchristos int error;
379b985414bSchristos
380b985414bSchristos /*
381b985414bSchristos * XXX the "33" below could be dynamic, thereby eliminating one
382b985414bSchristos * more instance of the "number to vfs" mapping problem, but
383b985414bSchristos * "33" is the order as taken from sys/mount.h
384b985414bSchristos */
3859120d451Spgoyette error = sysctl_createv(clog, 0, NULL, NULL,
386b985414bSchristos CTLFLAG_PERMANENT,
387b985414bSchristos CTLTYPE_NODE, "autofs",
388b985414bSchristos SYSCTL_DESCR("Automounter filesystem"),
389b985414bSchristos NULL, 0, NULL, 0,
390b985414bSchristos CTL_VFS, 33, CTL_EOL);
391b985414bSchristos if (error)
392b985414bSchristos goto fail;
393b985414bSchristos
3949120d451Spgoyette error = sysctl_createv(clog, 0, NULL, NULL,
395b985414bSchristos CTLFLAG_PERMANENT | CTLFLAG_READWRITE,
396b985414bSchristos CTLTYPE_INT, "autofs_debug",
397b985414bSchristos SYSCTL_DESCR("Enable debug messages"),
398b985414bSchristos NULL, 0, &autofs_debug, 0,
399b985414bSchristos CTL_VFS, 33, AUTOFS_SYSCTL_DEBUG, CTL_EOL);
400b985414bSchristos if (error)
401b985414bSchristos goto fail;
402b985414bSchristos
4039120d451Spgoyette error = sysctl_createv(clog, 0, NULL, NULL,
404b985414bSchristos CTLFLAG_PERMANENT | CTLFLAG_READWRITE,
405b985414bSchristos CTLTYPE_INT, "autofs_mount_on_stat",
406b985414bSchristos SYSCTL_DESCR("Trigger mount on stat(2) on mountpoint"),
407b985414bSchristos NULL, 0, &autofs_mount_on_stat, 0,
408b985414bSchristos CTL_VFS, 33, AUTOFS_SYSCTL_MOUNT_ON_STAT, CTL_EOL);
409b985414bSchristos if (error)
410b985414bSchristos goto fail;
411b985414bSchristos
4129120d451Spgoyette error = sysctl_createv(clog, 0, NULL, NULL,
413b985414bSchristos CTLFLAG_PERMANENT | CTLFLAG_READWRITE,
414b985414bSchristos CTLTYPE_INT, "autofs_timeout",
415b985414bSchristos SYSCTL_DESCR("Number of seconds to wait for automountd(8)"),
416b985414bSchristos NULL, 0, &autofs_timeout, 0,
417b985414bSchristos CTL_VFS, 33, AUTOFS_SYSCTL_TIMEOUT, CTL_EOL);
418b985414bSchristos if (error)
419b985414bSchristos goto fail;
420b985414bSchristos
4219120d451Spgoyette error = sysctl_createv(clog, 0, NULL, NULL,
422b985414bSchristos CTLFLAG_PERMANENT | CTLFLAG_READWRITE,
423b985414bSchristos CTLTYPE_INT, "autofs_cache",
424b985414bSchristos SYSCTL_DESCR("Number of seconds to wait before reinvoking"),
425b985414bSchristos NULL, 0, &autofs_cache, 0,
426b985414bSchristos CTL_VFS, 33, AUTOFS_SYSCTL_CACHE, CTL_EOL);
427b985414bSchristos if (error)
428b985414bSchristos goto fail;
429b985414bSchristos
4309120d451Spgoyette error = sysctl_createv(clog, 0, NULL, NULL,
431b985414bSchristos CTLFLAG_PERMANENT | CTLFLAG_READWRITE,
432b985414bSchristos CTLTYPE_INT, "autofs_retry_attempts",
433b985414bSchristos SYSCTL_DESCR("Number of attempts before failing mount"),
434b985414bSchristos NULL, 0, &autofs_retry_attempts, 0,
435b985414bSchristos CTL_VFS, 33, AUTOFS_SYSCTL_RETRY_ATTEMPTS, CTL_EOL);
436b985414bSchristos if (error)
437b985414bSchristos goto fail;
438b985414bSchristos
4399120d451Spgoyette error = sysctl_createv(clog, 0, NULL, NULL,
440b985414bSchristos CTLFLAG_PERMANENT | CTLFLAG_READWRITE,
441b985414bSchristos CTLTYPE_INT, "autofs_retry_delay",
442b985414bSchristos SYSCTL_DESCR("Number of seconds before retrying"),
443b985414bSchristos NULL, 0, &autofs_retry_delay, 0,
444b985414bSchristos CTL_VFS, 33, AUTOFS_SYSCTL_RETRY_DELAY, CTL_EOL);
445b985414bSchristos if (error)
446b985414bSchristos goto fail;
447b985414bSchristos
4489120d451Spgoyette error = sysctl_createv(clog, 0, NULL, NULL,
449b985414bSchristos CTLFLAG_PERMANENT | CTLFLAG_READWRITE,
450b985414bSchristos CTLTYPE_INT, "autofs_interruptible",
451b985414bSchristos SYSCTL_DESCR("Allow requests to be interrupted by signal"),
452b985414bSchristos NULL, 0, &autofs_interruptible, 0,
453b985414bSchristos CTL_VFS, 33, AUTOFS_SYSCTL_INTERRUPTIBLE, CTL_EOL);
454b985414bSchristos if (error)
455b985414bSchristos goto fail;
456b985414bSchristos
4579120d451Spgoyette return;
458b985414bSchristos fail:
459b985414bSchristos AUTOFS_WARN("sysctl_createv failed with error %d", error);
460b985414bSchristos
4619120d451Spgoyette return;
462b985414bSchristos }
463b985414bSchristos
4640d40f566Schristos extern const struct cdevsw autofs_cdevsw;
4650d40f566Schristos
466b985414bSchristos static int
autofs_modcmd(modcmd_t cmd,void * arg)467b985414bSchristos autofs_modcmd(modcmd_t cmd, void *arg)
468b985414bSchristos {
469b985414bSchristos #ifdef _MODULE
470b985414bSchristos devmajor_t bmajor = NODEVMAJOR, cmajor = NODEVMAJOR;
471b985414bSchristos #endif
472b985414bSchristos int error = 0;
473b985414bSchristos
474b985414bSchristos switch (cmd) {
475b985414bSchristos case MODULE_CMD_INIT:
476b985414bSchristos error = vfs_attach(&autofs_vfsops);
477b985414bSchristos if (error)
478b985414bSchristos break;
479b985414bSchristos #ifdef _MODULE
4800d40f566Schristos error = devsw_attach("autofs", NULL, &bmajor, &autofs_cdevsw,
481b985414bSchristos &cmajor);
482b985414bSchristos if (error) {
483b985414bSchristos vfs_detach(&autofs_vfsops);
484b985414bSchristos break;
485b985414bSchristos }
486b985414bSchristos #endif
487b985414bSchristos break;
488b985414bSchristos case MODULE_CMD_FINI:
4890d40f566Schristos #ifdef _MODULE
490b985414bSchristos KASSERT(autofs_softc);
491b985414bSchristos mutex_enter(&autofs_softc->sc_lock);
492b985414bSchristos if (autofs_softc->sc_dev_opened) {
493b985414bSchristos mutex_exit(&autofs_softc->sc_lock);
494b985414bSchristos error = EBUSY;
495b985414bSchristos break;
496b985414bSchristos }
497b985414bSchristos mutex_exit(&autofs_softc->sc_lock);
498b985414bSchristos
499*e7bed289Sriastradh devsw_detach(NULL, &autofs_cdevsw);
500b985414bSchristos #endif
501b985414bSchristos error = vfs_detach(&autofs_vfsops);
502b985414bSchristos if (error)
503b985414bSchristos break;
504b985414bSchristos break;
505b985414bSchristos default:
506b985414bSchristos error = ENOTTY;
507b985414bSchristos break;
508b985414bSchristos }
509b985414bSchristos
510b985414bSchristos return error;
511b985414bSchristos }
512