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
;
52 if (mp
->mnt_flag
& MNT_UPDATE
) {
53 autofs_flush(VFSTOAUTOFS(mp
));
57 error
= copyin(data
, &info
, sizeof(info
));
62 * Copy-in ->f_mntfromname string.
64 memset(sbp
->f_mntfromname
, 0, sizeof(sbp
->f_mntfromname
));
65 error
= copyinstr(info
.from
, sbp
->f_mntfromname
,
66 sizeof(sbp
->f_mntfromname
), NULL
);
70 * Copy-in ->f_mntonname string.
72 memset(sbp
->f_mntonname
, 0, sizeof(sbp
->f_mntonname
));
73 error
= copyinstr(mntpt
, sbp
->f_mntonname
,
74 sizeof(sbp
->f_mntonname
), NULL
);
79 * Allocate the autofs mount.
81 amp
= kmalloc(sizeof(*amp
), M_AUTOFS
, M_WAITOK
| M_ZERO
);
82 mp
->mnt_data
= (qaddr_t
)amp
;
84 strlcpy(amp
->am_from
, sbp
->f_mntfromname
, sizeof(amp
->am_from
));
85 strlcpy(amp
->am_on
, sbp
->f_mntonname
, sizeof(amp
->am_on
));
88 * Copy-in master_options string.
90 error
= copyinstr(info
.master_options
, amp
->am_options
,
91 sizeof(amp
->am_options
), NULL
);
95 * Copy-in master_prefix string.
97 error
= copyinstr(info
.master_prefix
, amp
->am_prefix
,
98 sizeof(amp
->am_prefix
), NULL
);
103 * Initialize the autofs mount.
105 lockinit(&
->am_lock
, "autofsmnlk", 0, 0);
106 amp
->am_last_ino
= AUTOFS_ROOTINO
;
109 vfs_add_vnodeops(mp
, &autofs_vnode_vops
, &mp
->mnt_vn_norm_ops
);
111 lockmgr(&
->am_lock
, LK_EXCLUSIVE
);
112 error
= autofs_node_new(NULL
, amp
, ".", -1, &
->am_root
);
113 lockmgr(&
->am_lock
, LK_RELEASE
);
114 KKASSERT(error
== 0);
115 KKASSERT(amp
->am_root
->an_ino
== AUTOFS_ROOTINO
);
117 autofs_statfs(mp
, sbp
, cred
);
122 kfree(amp
, M_AUTOFS
);
127 autofs_unmount(struct mount
*mp
, int mntflags
)
129 struct autofs_mount
*amp
= VFSTOAUTOFS(mp
);
130 struct autofs_node
*anp
;
131 struct autofs_request
*ar
;
132 int error
, flags
, dummy
;
136 if (mntflags
& MNT_FORCE
)
138 error
= vflush(mp
, 0, flags
);
140 AUTOFS_WARN("vflush failed with error %d", error
);
145 * All vnodes are gone, and new one will not appear - so,
146 * no new triggerings.
150 lockmgr(&autofs_softc
->sc_lock
, LK_EXCLUSIVE
);
151 TAILQ_FOREACH(ar
, &autofs_softc
->sc_requests
, ar_next
) {
152 if (ar
->ar_mount
!= amp
)
154 ar
->ar_error
= ENXIO
;
156 ar
->ar_in_progress
= false;
159 if (found
== false) {
160 lockmgr(&autofs_softc
->sc_lock
, LK_RELEASE
);
164 cv_broadcast(&autofs_softc
->sc_cv
);
165 lockmgr(&autofs_softc
->sc_lock
, LK_RELEASE
);
167 tsleep(&dummy
, 0, "autofs_umount", hz
);
170 lockmgr(&
->am_lock
, LK_EXCLUSIVE
);
171 while (!RB_EMPTY(&
->am_root
->an_children
)) {
172 anp
= RB_MIN(autofs_node_tree
, &
->am_root
->an_children
);
173 if (!RB_EMPTY(&anp
->an_children
)) {
174 AUTOFS_DEBUG("%s has children", anp
->an_name
);
175 lockmgr(&
->am_lock
, LK_RELEASE
);
178 autofs_node_delete(anp
);
180 autofs_node_delete(amp
->am_root
);
182 lockmgr(&
->am_lock
, LK_RELEASE
);
184 lockuninit(&
->am_lock
);
186 kfree(amp
, M_AUTOFS
);
192 autofs_root(struct mount
*mp
, struct vnode
**vpp
)
194 struct autofs_mount
*amp
= VFSTOAUTOFS(mp
);
197 if (amp
->am_root
== NULL
) {
198 AUTOFS_FATAL("called without root node %p", mp
);
203 error
= autofs_node_vn(amp
->am_root
, mp
, LK_EXCLUSIVE
, vpp
);
204 (*vpp
)->v_flag
|= VROOT
;
205 KKASSERT((*vpp
)->v_type
== VDIR
);
212 autofs_statfs(struct mount
*mp
, struct statfs
*sbp
, struct ucred
*cred
)
214 sbp
->f_bsize
= S_BLKSIZE
;
226 autofs_statvfs(struct mount
*mp
, struct statvfs
*sbp
, struct ucred
*cred
)
228 sbp
->f_bsize
= S_BLKSIZE
;
239 static struct vfsops autofs_vfsops
= {
240 .vfs_mount
= autofs_mount
,
241 .vfs_unmount
= autofs_unmount
,
242 .vfs_root
= autofs_root
,
243 .vfs_statfs
= autofs_statfs
,
244 .vfs_statvfs
= autofs_statvfs
,
245 .vfs_init
= autofs_init
,
246 .vfs_uninit
= autofs_uninit
,
250 .vfs_checkexp
= NULL
,
254 VFS_SET(autofs_vfsops
, autofs
, VFCF_SYNTHETIC
| VFCF_NETWORK
);
255 MODULE_VERSION(autofs
, 1);