1 1.110 riastrad /* $NetBSD: vfs_mount.c,v 1.110 2024/12/07 02:27:38 riastradh Exp $ */ 2 1.1 rmind 3 1.1 rmind /*- 4 1.75 ad * Copyright (c) 1997-2020 The NetBSD Foundation, Inc. 5 1.1 rmind * All rights reserved. 6 1.1 rmind * 7 1.1 rmind * This code is derived from software contributed to The NetBSD Foundation 8 1.1 rmind * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility, 9 1.1 rmind * NASA Ames Research Center, by Charles M. Hannum, and by Andrew Doran. 10 1.1 rmind * 11 1.1 rmind * Redistribution and use in source and binary forms, with or without 12 1.1 rmind * modification, are permitted provided that the following conditions 13 1.1 rmind * are met: 14 1.1 rmind * 1. Redistributions of source code must retain the above copyright 15 1.1 rmind * notice, this list of conditions and the following disclaimer. 16 1.1 rmind * 2. Redistributions in binary form must reproduce the above copyright 17 1.1 rmind * notice, this list of conditions and the following disclaimer in the 18 1.1 rmind * documentation and/or other materials provided with the distribution. 19 1.1 rmind * 20 1.1 rmind * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 21 1.1 rmind * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 22 1.1 rmind * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 23 1.1 rmind * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 24 1.1 rmind * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 25 1.1 rmind * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 26 1.1 rmind * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 27 1.1 rmind * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 28 1.1 rmind * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 29 1.1 rmind * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 30 1.1 rmind * POSSIBILITY OF SUCH DAMAGE. 31 1.1 rmind */ 32 1.1 rmind 33 1.1 rmind /* 34 1.1 rmind * Copyright (c) 1989, 1993 35 1.1 rmind * The Regents of the University of California. All rights reserved. 36 1.1 rmind * (c) UNIX System Laboratories, Inc. 37 1.1 rmind * All or some portions of this file are derived from material licensed 38 1.1 rmind * to the University of California by American Telephone and Telegraph 39 1.1 rmind * Co. or Unix System Laboratories, Inc. and are reproduced herein with 40 1.1 rmind * the permission of UNIX System Laboratories, Inc. 41 1.1 rmind * 42 1.1 rmind * Redistribution and use in source and binary forms, with or without 43 1.1 rmind * modification, are permitted provided that the following conditions 44 1.1 rmind * are met: 45 1.1 rmind * 1. Redistributions of source code must retain the above copyright 46 1.1 rmind * notice, this list of conditions and the following disclaimer. 47 1.1 rmind * 2. Redistributions in binary form must reproduce the above copyright 48 1.1 rmind * notice, this list of conditions and the following disclaimer in the 49 1.1 rmind * documentation and/or other materials provided with the distribution. 50 1.1 rmind * 3. Neither the name of the University nor the names of its contributors 51 1.1 rmind * may be used to endorse or promote products derived from this software 52 1.1 rmind * without specific prior written permission. 53 1.1 rmind * 54 1.1 rmind * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 55 1.1 rmind * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 56 1.1 rmind * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 57 1.1 rmind * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 58 1.1 rmind * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 59 1.1 rmind * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 60 1.1 rmind * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 61 1.1 rmind * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 62 1.1 rmind * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 63 1.1 rmind * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 64 1.1 rmind * SUCH DAMAGE. 65 1.1 rmind * 66 1.1 rmind * @(#)vfs_subr.c 8.13 (Berkeley) 4/18/94 67 1.1 rmind */ 68 1.1 rmind 69 1.1 rmind #include <sys/cdefs.h> 70 1.110 riastrad __KERNEL_RCSID(0, "$NetBSD: vfs_mount.c,v 1.110 2024/12/07 02:27:38 riastradh Exp $"); 71 1.103 hannken 72 1.103 hannken #include "veriexec.h" 73 1.1 rmind 74 1.1 rmind #include <sys/param.h> 75 1.1 rmind #include <sys/kernel.h> 76 1.1 rmind 77 1.1 rmind #include <sys/atomic.h> 78 1.1 rmind #include <sys/buf.h> 79 1.1 rmind #include <sys/conf.h> 80 1.108 riastrad #include <sys/device.h> 81 1.108 riastrad #include <sys/extattr.h> 82 1.1 rmind #include <sys/fcntl.h> 83 1.1 rmind #include <sys/filedesc.h> 84 1.108 riastrad #include <sys/fstrans.h> 85 1.1 rmind #include <sys/kauth.h> 86 1.1 rmind #include <sys/kmem.h> 87 1.1 rmind #include <sys/module.h> 88 1.1 rmind #include <sys/mount.h> 89 1.1 rmind #include <sys/namei.h> 90 1.110 riastrad #include <sys/sdt.h> 91 1.1 rmind #include <sys/syscallargs.h> 92 1.1 rmind #include <sys/sysctl.h> 93 1.1 rmind #include <sys/systm.h> 94 1.108 riastrad #include <sys/verified_exec.h> 95 1.5 dsl #include <sys/vfs_syscalls.h> 96 1.41 hannken #include <sys/vnode_impl.h> 97 1.1 rmind 98 1.101 hannken #include <miscfs/deadfs/deadfs.h> 99 1.1 rmind #include <miscfs/genfs/genfs.h> 100 1.1 rmind #include <miscfs/specfs/specdev.h> 101 1.1 rmind 102 1.86 hannken #include <uvm/uvm_swap.h> 103 1.86 hannken 104 1.52 hannken enum mountlist_type { 105 1.52 hannken ME_MOUNT, 106 1.52 hannken ME_MARKER 107 1.52 hannken }; 108 1.52 hannken struct mountlist_entry { 109 1.52 hannken TAILQ_ENTRY(mountlist_entry) me_list; /* Mount list. */ 110 1.52 hannken struct mount *me_mount; /* Actual mount if ME_MOUNT, 111 1.52 hannken current mount else. */ 112 1.52 hannken enum mountlist_type me_type; /* Mount or marker. */ 113 1.52 hannken }; 114 1.52 hannken struct mount_iterator { 115 1.52 hannken struct mountlist_entry mi_entry; 116 1.52 hannken }; 117 1.52 hannken 118 1.45 hannken static struct vnode *vfs_vnode_iterator_next1(struct vnode_iterator *, 119 1.45 hannken bool (*)(void *, struct vnode *), void *, bool); 120 1.45 hannken 121 1.33 pooka /* Root filesystem. */ 122 1.1 rmind vnode_t * rootvnode; 123 1.1 rmind 124 1.1 rmind /* Mounted filesystem list. */ 125 1.54 hannken static TAILQ_HEAD(mountlist, mountlist_entry) mountlist; 126 1.73 ad static kmutex_t mountlist_lock __cacheline_aligned; 127 1.54 hannken int vnode_offset_next_by_lru /* XXX: ugly hack for pstat.c */ 128 1.54 hannken = offsetof(vnode_impl_t, vi_lrulist.tqe_next); 129 1.1 rmind 130 1.73 ad kmutex_t vfs_list_lock __cacheline_aligned; 131 1.1 rmind 132 1.1 rmind static specificdata_domain_t mount_specificdata_domain; 133 1.1 rmind static kmutex_t mntid_lock; 134 1.1 rmind 135 1.73 ad static kmutex_t mountgen_lock __cacheline_aligned; 136 1.1 rmind static uint64_t mountgen; 137 1.1 rmind 138 1.1 rmind void 139 1.1 rmind vfs_mount_sysinit(void) 140 1.1 rmind { 141 1.1 rmind 142 1.24 christos TAILQ_INIT(&mountlist); 143 1.1 rmind mutex_init(&mountlist_lock, MUTEX_DEFAULT, IPL_NONE); 144 1.1 rmind mutex_init(&vfs_list_lock, MUTEX_DEFAULT, IPL_NONE); 145 1.1 rmind 146 1.1 rmind mount_specificdata_domain = specificdata_domain_create(); 147 1.1 rmind mutex_init(&mntid_lock, MUTEX_DEFAULT, IPL_NONE); 148 1.1 rmind mutex_init(&mountgen_lock, MUTEX_DEFAULT, IPL_NONE); 149 1.1 rmind mountgen = 0; 150 1.1 rmind } 151 1.1 rmind 152 1.1 rmind struct mount * 153 1.1 rmind vfs_mountalloc(struct vfsops *vfsops, vnode_t *vp) 154 1.1 rmind { 155 1.1 rmind struct mount *mp; 156 1.60 hannken int error __diagused; 157 1.1 rmind 158 1.1 rmind mp = kmem_zalloc(sizeof(*mp), KM_SLEEP); 159 1.1 rmind mp->mnt_op = vfsops; 160 1.1 rmind mp->mnt_refcnt = 1; 161 1.1 rmind TAILQ_INIT(&mp->mnt_vnodelist); 162 1.73 ad mp->mnt_renamelock = mutex_obj_alloc(MUTEX_DEFAULT, IPL_NONE); 163 1.73 ad mp->mnt_vnodelock = mutex_obj_alloc(MUTEX_DEFAULT, IPL_NONE); 164 1.73 ad mp->mnt_updating = mutex_obj_alloc(MUTEX_DEFAULT, IPL_NONE); 165 1.1 rmind mp->mnt_vnodecovered = vp; 166 1.1 rmind mount_initspecific(mp); 167 1.69 hannken 168 1.69 hannken error = fstrans_mount(mp); 169 1.69 hannken KASSERT(error == 0); 170 1.1 rmind 171 1.1 rmind mutex_enter(&mountgen_lock); 172 1.1 rmind mp->mnt_gen = mountgen++; 173 1.1 rmind mutex_exit(&mountgen_lock); 174 1.1 rmind 175 1.1 rmind return mp; 176 1.1 rmind } 177 1.1 rmind 178 1.1 rmind /* 179 1.1 rmind * vfs_rootmountalloc: lookup a filesystem type, and if found allocate and 180 1.1 rmind * initialize a mount structure for it. 181 1.1 rmind * 182 1.1 rmind * Devname is usually updated by mount(8) after booting. 183 1.1 rmind */ 184 1.1 rmind int 185 1.1 rmind vfs_rootmountalloc(const char *fstypename, const char *devname, 186 1.1 rmind struct mount **mpp) 187 1.1 rmind { 188 1.1 rmind struct vfsops *vfsp = NULL; 189 1.1 rmind struct mount *mp; 190 1.57 hannken int error __diagused; 191 1.1 rmind 192 1.1 rmind mutex_enter(&vfs_list_lock); 193 1.1 rmind LIST_FOREACH(vfsp, &vfs_list, vfs_list) 194 1.108 riastrad if (!strncmp(vfsp->vfs_name, fstypename, 195 1.1 rmind sizeof(mp->mnt_stat.f_fstypename))) 196 1.1 rmind break; 197 1.1 rmind if (vfsp == NULL) { 198 1.1 rmind mutex_exit(&vfs_list_lock); 199 1.110 riastrad return SET_ERROR(ENODEV); 200 1.1 rmind } 201 1.1 rmind vfsp->vfs_refcount++; 202 1.1 rmind mutex_exit(&vfs_list_lock); 203 1.1 rmind 204 1.1 rmind if ((mp = vfs_mountalloc(vfsp, NULL)) == NULL) 205 1.110 riastrad return SET_ERROR(ENOMEM); 206 1.57 hannken error = vfs_busy(mp); 207 1.57 hannken KASSERT(error == 0); 208 1.1 rmind mp->mnt_flag = MNT_RDONLY; 209 1.1 rmind (void)strlcpy(mp->mnt_stat.f_fstypename, vfsp->vfs_name, 210 1.1 rmind sizeof(mp->mnt_stat.f_fstypename)); 211 1.1 rmind mp->mnt_stat.f_mntonname[0] = '/'; 212 1.1 rmind mp->mnt_stat.f_mntonname[1] = '\0'; 213 1.1 rmind mp->mnt_stat.f_mntfromname[sizeof(mp->mnt_stat.f_mntfromname) - 1] = 214 1.1 rmind '\0'; 215 1.1 rmind (void)copystr(devname, mp->mnt_stat.f_mntfromname, 216 1.1 rmind sizeof(mp->mnt_stat.f_mntfromname) - 1, 0); 217 1.1 rmind *mpp = mp; 218 1.1 rmind return 0; 219 1.1 rmind } 220 1.1 rmind 221 1.1 rmind /* 222 1.1 rmind * vfs_getnewfsid: get a new unique fsid. 223 1.1 rmind */ 224 1.1 rmind void 225 1.1 rmind vfs_getnewfsid(struct mount *mp) 226 1.1 rmind { 227 1.1 rmind static u_short xxxfs_mntid; 228 1.96 hannken struct mountlist_entry *me; 229 1.1 rmind fsid_t tfsid; 230 1.1 rmind int mtype; 231 1.1 rmind 232 1.1 rmind mutex_enter(&mntid_lock); 233 1.1 rmind if (xxxfs_mntid == 0) 234 1.1 rmind ++xxxfs_mntid; 235 1.96 hannken mtype = makefstype(mp->mnt_op->vfs_name); 236 1.1 rmind tfsid.__fsid_val[0] = makedev(mtype & 0xff, xxxfs_mntid); 237 1.1 rmind tfsid.__fsid_val[1] = mtype; 238 1.96 hannken /* Always increment to not return the same fsid to parallel mounts. */ 239 1.96 hannken xxxfs_mntid++; 240 1.96 hannken 241 1.96 hannken /* 242 1.96 hannken * Directly walk mountlist to prevent deadlock through 243 1.96 hannken * mountlist_iterator_next() -> vfs_busy(). 244 1.96 hannken */ 245 1.96 hannken mutex_enter(&mountlist_lock); 246 1.96 hannken for (me = TAILQ_FIRST(&mountlist); me != TAILQ_END(&mountlist); ) { 247 1.96 hannken if (me->me_type == ME_MOUNT && 248 1.96 hannken me->me_mount->mnt_stat.f_fsidx.__fsid_val[0] == 249 1.96 hannken tfsid.__fsid_val[0] && 250 1.96 hannken me->me_mount->mnt_stat.f_fsidx.__fsid_val[1] == 251 1.96 hannken tfsid.__fsid_val[1]) { 252 1.96 hannken tfsid.__fsid_val[0]++; 253 1.96 hannken xxxfs_mntid++; 254 1.96 hannken me = TAILQ_FIRST(&mountlist); 255 1.96 hannken } else { 256 1.96 hannken me = TAILQ_NEXT(me, me_list); 257 1.96 hannken } 258 1.1 rmind } 259 1.96 hannken mutex_exit(&mountlist_lock); 260 1.96 hannken 261 1.1 rmind mp->mnt_stat.f_fsidx.__fsid_val[0] = tfsid.__fsid_val[0]; 262 1.96 hannken mp->mnt_stat.f_fsidx.__fsid_val[1] = tfsid.__fsid_val[1]; 263 1.1 rmind mp->mnt_stat.f_fsid = mp->mnt_stat.f_fsidx.__fsid_val[0]; 264 1.1 rmind mutex_exit(&mntid_lock); 265 1.1 rmind } 266 1.1 rmind 267 1.1 rmind /* 268 1.1 rmind * Lookup a mount point by filesystem identifier. 269 1.1 rmind * 270 1.1 rmind * XXX Needs to add a reference to the mount point. 271 1.1 rmind */ 272 1.1 rmind struct mount * 273 1.1 rmind vfs_getvfs(fsid_t *fsid) 274 1.1 rmind { 275 1.53 hannken mount_iterator_t *iter; 276 1.1 rmind struct mount *mp; 277 1.1 rmind 278 1.53 hannken mountlist_iterator_init(&iter); 279 1.53 hannken while ((mp = mountlist_iterator_next(iter)) != NULL) { 280 1.1 rmind if (mp->mnt_stat.f_fsidx.__fsid_val[0] == fsid->__fsid_val[0] && 281 1.1 rmind mp->mnt_stat.f_fsidx.__fsid_val[1] == fsid->__fsid_val[1]) { 282 1.53 hannken mountlist_iterator_destroy(iter); 283 1.53 hannken return mp; 284 1.1 rmind } 285 1.1 rmind } 286 1.53 hannken mountlist_iterator_destroy(iter); 287 1.1 rmind return NULL; 288 1.1 rmind } 289 1.1 rmind 290 1.1 rmind /* 291 1.55 hannken * Take a reference to a mount structure. 292 1.55 hannken */ 293 1.55 hannken void 294 1.55 hannken vfs_ref(struct mount *mp) 295 1.55 hannken { 296 1.55 hannken 297 1.55 hannken KASSERT(mp->mnt_refcnt > 0 || mutex_owned(&mountlist_lock)); 298 1.55 hannken 299 1.55 hannken atomic_inc_uint(&mp->mnt_refcnt); 300 1.55 hannken } 301 1.55 hannken 302 1.55 hannken /* 303 1.1 rmind * Drop a reference to a mount structure, freeing if the last reference. 304 1.1 rmind */ 305 1.1 rmind void 306 1.55 hannken vfs_rele(struct mount *mp) 307 1.1 rmind { 308 1.1 rmind 309 1.93 riastrad membar_release(); 310 1.1 rmind if (__predict_true((int)atomic_dec_uint_nv(&mp->mnt_refcnt) > 0)) { 311 1.1 rmind return; 312 1.1 rmind } 313 1.93 riastrad membar_acquire(); 314 1.1 rmind 315 1.1 rmind /* 316 1.1 rmind * Nothing else has visibility of the mount: we can now 317 1.1 rmind * free the data structures. 318 1.1 rmind */ 319 1.1 rmind KASSERT(mp->mnt_refcnt == 0); 320 1.1 rmind specificdata_fini(mount_specificdata_domain, &mp->mnt_specdataref); 321 1.73 ad mutex_obj_free(mp->mnt_updating); 322 1.73 ad mutex_obj_free(mp->mnt_renamelock); 323 1.73 ad mutex_obj_free(mp->mnt_vnodelock); 324 1.1 rmind if (mp->mnt_op != NULL) { 325 1.1 rmind vfs_delref(mp->mnt_op); 326 1.1 rmind } 327 1.70 hannken fstrans_unmount(mp); 328 1.70 hannken /* 329 1.70 hannken * Final free of mp gets done from fstrans_mount_dtor(). 330 1.70 hannken * 331 1.70 hannken * Prevents this memory to be reused as a mount before 332 1.70 hannken * fstrans releases all references to it. 333 1.70 hannken */ 334 1.1 rmind } 335 1.1 rmind 336 1.1 rmind /* 337 1.1 rmind * Mark a mount point as busy, and gain a new reference to it. Used to 338 1.1 rmind * prevent the file system from being unmounted during critical sections. 339 1.1 rmind * 340 1.18 mlelstv * vfs_busy can be called multiple times and by multiple threads 341 1.18 mlelstv * and must be accompanied by the same number of vfs_unbusy calls. 342 1.18 mlelstv * 343 1.1 rmind * => The caller must hold a pre-existing reference to the mount. 344 1.1 rmind * => Will fail if the file system is being unmounted, or is unmounted. 345 1.1 rmind */ 346 1.58 hannken static inline int 347 1.58 hannken _vfs_busy(struct mount *mp, bool wait) 348 1.1 rmind { 349 1.1 rmind 350 1.1 rmind KASSERT(mp->mnt_refcnt > 0); 351 1.1 rmind 352 1.58 hannken if (wait) { 353 1.66 hannken fstrans_start(mp); 354 1.61 hannken } else { 355 1.66 hannken if (fstrans_start_nowait(mp)) 356 1.110 riastrad return SET_ERROR(EBUSY); 357 1.58 hannken } 358 1.1 rmind if (__predict_false((mp->mnt_iflag & IMNT_GONE) != 0)) { 359 1.61 hannken fstrans_done(mp); 360 1.110 riastrad return SET_ERROR(ENOENT); 361 1.1 rmind } 362 1.55 hannken vfs_ref(mp); 363 1.1 rmind return 0; 364 1.1 rmind } 365 1.1 rmind 366 1.58 hannken int 367 1.58 hannken vfs_busy(struct mount *mp) 368 1.58 hannken { 369 1.58 hannken 370 1.58 hannken return _vfs_busy(mp, true); 371 1.58 hannken } 372 1.58 hannken 373 1.58 hannken int 374 1.58 hannken vfs_trybusy(struct mount *mp) 375 1.58 hannken { 376 1.58 hannken 377 1.58 hannken return _vfs_busy(mp, false); 378 1.58 hannken } 379 1.58 hannken 380 1.1 rmind /* 381 1.1 rmind * Unbusy a busy filesystem. 382 1.1 rmind * 383 1.18 mlelstv * Every successful vfs_busy() call must be undone by a vfs_unbusy() call. 384 1.1 rmind */ 385 1.1 rmind void 386 1.56 hannken vfs_unbusy(struct mount *mp) 387 1.1 rmind { 388 1.1 rmind 389 1.1 rmind KASSERT(mp->mnt_refcnt > 0); 390 1.1 rmind 391 1.61 hannken fstrans_done(mp); 392 1.56 hannken vfs_rele(mp); 393 1.1 rmind } 394 1.1 rmind 395 1.99 hannken /* 396 1.99 hannken * Change a file systems lower mount. 397 1.99 hannken * Both the current and the new lower mount may be NULL. The caller 398 1.99 hannken * guarantees exclusive access to the mount and holds a pre-existing 399 1.99 hannken * reference to the new lower mount. 400 1.99 hannken */ 401 1.99 hannken int 402 1.99 hannken vfs_set_lowermount(struct mount *mp, struct mount *lowermp) 403 1.99 hannken { 404 1.99 hannken struct mount *oldlowermp; 405 1.99 hannken int error; 406 1.99 hannken 407 1.100 hannken #ifdef DEBUG 408 1.100 hannken /* 409 1.100 hannken * Limit the depth of file system stack so kernel sanitizers 410 1.100 hannken * may stress mount/unmount without exhausting the kernel stack. 411 1.100 hannken */ 412 1.100 hannken int depth; 413 1.100 hannken struct mount *mp2; 414 1.100 hannken 415 1.100 hannken for (depth = 0, mp2 = lowermp; mp2; depth++, mp2 = mp2->mnt_lower) { 416 1.100 hannken if (depth == 23) 417 1.110 riastrad return SET_ERROR(EINVAL); 418 1.100 hannken } 419 1.100 hannken #endif 420 1.100 hannken 421 1.99 hannken if (lowermp) { 422 1.101 hannken if (lowermp == dead_rootmount) 423 1.110 riastrad return SET_ERROR(ENOENT); 424 1.99 hannken error = vfs_busy(lowermp); 425 1.99 hannken if (error) 426 1.99 hannken return error; 427 1.99 hannken vfs_ref(lowermp); 428 1.99 hannken } 429 1.99 hannken 430 1.99 hannken oldlowermp = mp->mnt_lower; 431 1.99 hannken mp->mnt_lower = lowermp; 432 1.99 hannken 433 1.99 hannken if (lowermp) 434 1.99 hannken vfs_unbusy(lowermp); 435 1.99 hannken 436 1.99 hannken if (oldlowermp) 437 1.99 hannken vfs_rele(oldlowermp); 438 1.99 hannken 439 1.99 hannken return 0; 440 1.99 hannken } 441 1.99 hannken 442 1.27 hannken struct vnode_iterator { 443 1.44 hannken vnode_impl_t vi_vnode; 444 1.40 msaitoh }; 445 1.27 hannken 446 1.27 hannken void 447 1.44 hannken vfs_vnode_iterator_init(struct mount *mp, struct vnode_iterator **vnip) 448 1.27 hannken { 449 1.44 hannken vnode_t *vp; 450 1.44 hannken vnode_impl_t *vip; 451 1.27 hannken 452 1.38 hannken vp = vnalloc_marker(mp); 453 1.44 hannken vip = VNODE_TO_VIMPL(vp); 454 1.27 hannken 455 1.73 ad mutex_enter(mp->mnt_vnodelock); 456 1.44 hannken TAILQ_INSERT_HEAD(&mp->mnt_vnodelist, vip, vi_mntvnodes); 457 1.27 hannken vp->v_usecount = 1; 458 1.73 ad mutex_exit(mp->mnt_vnodelock); 459 1.27 hannken 460 1.44 hannken *vnip = (struct vnode_iterator *)vip; 461 1.27 hannken } 462 1.27 hannken 463 1.27 hannken void 464 1.44 hannken vfs_vnode_iterator_destroy(struct vnode_iterator *vni) 465 1.27 hannken { 466 1.44 hannken vnode_impl_t *mvip = &vni->vi_vnode; 467 1.44 hannken vnode_t *mvp = VIMPL_TO_VNODE(mvip); 468 1.73 ad kmutex_t *lock; 469 1.27 hannken 470 1.38 hannken KASSERT(vnis_marker(mvp)); 471 1.78 ad if (vrefcnt(mvp) != 0) { 472 1.73 ad lock = mvp->v_mount->mnt_vnodelock; 473 1.73 ad mutex_enter(lock); 474 1.44 hannken TAILQ_REMOVE(&mvp->v_mount->mnt_vnodelist, mvip, vi_mntvnodes); 475 1.32 hannken mvp->v_usecount = 0; 476 1.73 ad mutex_exit(lock); 477 1.32 hannken } 478 1.38 hannken vnfree_marker(mvp); 479 1.27 hannken } 480 1.27 hannken 481 1.45 hannken static struct vnode * 482 1.45 hannken vfs_vnode_iterator_next1(struct vnode_iterator *vni, 483 1.45 hannken bool (*f)(void *, struct vnode *), void *cl, bool do_wait) 484 1.27 hannken { 485 1.44 hannken vnode_impl_t *mvip = &vni->vi_vnode; 486 1.44 hannken struct mount *mp = VIMPL_TO_VNODE(mvip)->v_mount; 487 1.44 hannken vnode_t *vp; 488 1.44 hannken vnode_impl_t *vip; 489 1.73 ad kmutex_t *lock; 490 1.27 hannken int error; 491 1.27 hannken 492 1.44 hannken KASSERT(vnis_marker(VIMPL_TO_VNODE(mvip))); 493 1.27 hannken 494 1.73 ad lock = mp->mnt_vnodelock; 495 1.27 hannken do { 496 1.73 ad mutex_enter(lock); 497 1.44 hannken vip = TAILQ_NEXT(mvip, vi_mntvnodes); 498 1.44 hannken TAILQ_REMOVE(&mp->mnt_vnodelist, mvip, vi_mntvnodes); 499 1.44 hannken VIMPL_TO_VNODE(mvip)->v_usecount = 0; 500 1.29 christos again: 501 1.72 maxv if (vip == NULL) { 502 1.73 ad mutex_exit(lock); 503 1.109 riastrad return NULL; 504 1.27 hannken } 505 1.72 maxv vp = VIMPL_TO_VNODE(vip); 506 1.72 maxv KASSERT(vp != NULL); 507 1.27 hannken mutex_enter(vp->v_interlock); 508 1.38 hannken if (vnis_marker(vp) || 509 1.45 hannken vdead_check(vp, (do_wait ? 0 : VDEAD_NOWAIT)) || 510 1.37 hannken (f && !(*f)(cl, vp))) { 511 1.27 hannken mutex_exit(vp->v_interlock); 512 1.44 hannken vip = TAILQ_NEXT(vip, vi_mntvnodes); 513 1.29 christos goto again; 514 1.27 hannken } 515 1.27 hannken 516 1.108 riastrad TAILQ_INSERT_AFTER(&mp->mnt_vnodelist, vip, mvip, 517 1.108 riastrad vi_mntvnodes); 518 1.44 hannken VIMPL_TO_VNODE(mvip)->v_usecount = 1; 519 1.73 ad mutex_exit(lock); 520 1.43 hannken error = vcache_vget(vp); 521 1.27 hannken KASSERT(error == 0 || error == ENOENT); 522 1.27 hannken } while (error != 0); 523 1.27 hannken 524 1.29 christos return vp; 525 1.27 hannken } 526 1.27 hannken 527 1.45 hannken struct vnode * 528 1.45 hannken vfs_vnode_iterator_next(struct vnode_iterator *vni, 529 1.45 hannken bool (*f)(void *, struct vnode *), void *cl) 530 1.45 hannken { 531 1.45 hannken 532 1.45 hannken return vfs_vnode_iterator_next1(vni, f, cl, false); 533 1.45 hannken } 534 1.45 hannken 535 1.1 rmind /* 536 1.1 rmind * Move a vnode from one mount queue to another. 537 1.1 rmind */ 538 1.1 rmind void 539 1.1 rmind vfs_insmntque(vnode_t *vp, struct mount *mp) 540 1.1 rmind { 541 1.44 hannken vnode_impl_t *vip = VNODE_TO_VIMPL(vp); 542 1.1 rmind struct mount *omp; 543 1.73 ad kmutex_t *lock; 544 1.1 rmind 545 1.4 rmind KASSERT(mp == NULL || (mp->mnt_iflag & IMNT_UNMOUNT) == 0 || 546 1.4 rmind vp->v_tag == VT_VFS); 547 1.1 rmind 548 1.1 rmind /* 549 1.1 rmind * Delete from old mount point vnode list, if on one. 550 1.1 rmind */ 551 1.73 ad if ((omp = vp->v_mount) != NULL) { 552 1.73 ad lock = omp->mnt_vnodelock; 553 1.73 ad mutex_enter(lock); 554 1.44 hannken TAILQ_REMOVE(&vp->v_mount->mnt_vnodelist, vip, vi_mntvnodes); 555 1.73 ad mutex_exit(lock); 556 1.73 ad } 557 1.73 ad 558 1.1 rmind /* 559 1.1 rmind * Insert into list of vnodes for the new mount point, if 560 1.1 rmind * available. The caller must take a reference on the mount 561 1.1 rmind * structure and donate to the vnode. 562 1.1 rmind */ 563 1.73 ad if ((vp->v_mount = mp) != NULL) { 564 1.73 ad lock = mp->mnt_vnodelock; 565 1.73 ad mutex_enter(lock); 566 1.44 hannken TAILQ_INSERT_TAIL(&mp->mnt_vnodelist, vip, vi_mntvnodes); 567 1.73 ad mutex_exit(lock); 568 1.73 ad } 569 1.1 rmind 570 1.1 rmind if (omp != NULL) { 571 1.1 rmind /* Release reference to old mount. */ 572 1.55 hannken vfs_rele(omp); 573 1.1 rmind } 574 1.1 rmind } 575 1.1 rmind 576 1.1 rmind /* 577 1.1 rmind * Remove any vnodes in the vnode table belonging to mount point mp. 578 1.1 rmind * 579 1.1 rmind * If FORCECLOSE is not specified, there should not be any active ones, 580 1.1 rmind * return error if any are found (nb: this is a user error, not a 581 1.1 rmind * system error). If FORCECLOSE is specified, detach any active vnodes 582 1.1 rmind * that are found. 583 1.1 rmind * 584 1.1 rmind * If WRITECLOSE is set, only flush out regular file vnodes open for 585 1.1 rmind * writing. 586 1.1 rmind * 587 1.1 rmind * SKIPSYSTEM causes any vnodes marked VV_SYSTEM to be skipped. 588 1.1 rmind */ 589 1.1 rmind #ifdef DEBUG 590 1.1 rmind int busyprt = 0; /* print out busy vnodes */ 591 1.1 rmind struct ctldebug debug1 = { "busyprt", &busyprt }; 592 1.1 rmind #endif 593 1.1 rmind 594 1.46 hannken static vnode_t * 595 1.46 hannken vflushnext(struct vnode_iterator *marker, int *when) 596 1.46 hannken { 597 1.77 maxv if (getticks() > *when) { 598 1.46 hannken yield(); 599 1.77 maxv *when = getticks() + hz / 10; 600 1.46 hannken } 601 1.97 riastrad preempt_point(); 602 1.46 hannken return vfs_vnode_iterator_next1(marker, NULL, NULL, true); 603 1.46 hannken } 604 1.29 christos 605 1.46 hannken /* 606 1.46 hannken * Flush one vnode. Referenced on entry, unreferenced on return. 607 1.46 hannken */ 608 1.46 hannken static int 609 1.46 hannken vflush_one(vnode_t *vp, vnode_t *skipvp, int flags) 610 1.29 christos { 611 1.46 hannken int error; 612 1.46 hannken struct vattr vattr; 613 1.46 hannken 614 1.46 hannken if (vp == skipvp || 615 1.46 hannken ((flags & SKIPSYSTEM) && (vp->v_vflag & VV_SYSTEM))) { 616 1.46 hannken vrele(vp); 617 1.46 hannken return 0; 618 1.46 hannken } 619 1.29 christos /* 620 1.46 hannken * If WRITECLOSE is set, only flush out regular file 621 1.46 hannken * vnodes open for writing or open and unlinked. 622 1.29 christos */ 623 1.46 hannken if ((flags & WRITECLOSE)) { 624 1.46 hannken if (vp->v_type != VREG) { 625 1.46 hannken vrele(vp); 626 1.46 hannken return 0; 627 1.46 hannken } 628 1.46 hannken error = vn_lock(vp, LK_EXCLUSIVE); 629 1.46 hannken if (error) { 630 1.46 hannken KASSERT(error == ENOENT); 631 1.46 hannken vrele(vp); 632 1.46 hannken return 0; 633 1.46 hannken } 634 1.46 hannken error = VOP_FSYNC(vp, curlwp->l_cred, FSYNC_WAIT, 0, 0); 635 1.46 hannken if (error == 0) 636 1.46 hannken error = VOP_GETATTR(vp, &vattr, curlwp->l_cred); 637 1.46 hannken VOP_UNLOCK(vp); 638 1.46 hannken if (error) { 639 1.46 hannken vrele(vp); 640 1.46 hannken return error; 641 1.46 hannken } 642 1.46 hannken if (vp->v_writecount == 0 && vattr.va_nlink > 0) { 643 1.46 hannken vrele(vp); 644 1.46 hannken return 0; 645 1.46 hannken } 646 1.46 hannken } 647 1.29 christos /* 648 1.46 hannken * First try to recycle the vnode. 649 1.29 christos */ 650 1.46 hannken if (vrecycle(vp)) 651 1.46 hannken return 0; 652 1.29 christos /* 653 1.46 hannken * If FORCECLOSE is set, forcibly close the vnode. 654 1.67 hannken * For block or character devices, revert to an 655 1.67 hannken * anonymous device. For all other files, just 656 1.67 hannken * kill them. 657 1.29 christos */ 658 1.46 hannken if (flags & FORCECLOSE) { 659 1.78 ad if (vrefcnt(vp) > 1 && 660 1.67 hannken (vp->v_type == VBLK || vp->v_type == VCHR)) 661 1.67 hannken vcache_make_anon(vp); 662 1.67 hannken else 663 1.67 hannken vgone(vp); 664 1.46 hannken return 0; 665 1.29 christos } 666 1.46 hannken vrele(vp); 667 1.110 riastrad return SET_ERROR(EBUSY); 668 1.29 christos } 669 1.29 christos 670 1.1 rmind int 671 1.1 rmind vflush(struct mount *mp, vnode_t *skipvp, int flags) 672 1.1 rmind { 673 1.27 hannken vnode_t *vp; 674 1.27 hannken struct vnode_iterator *marker; 675 1.47 hannken int busy, error, when, retries = 2; 676 1.46 hannken 677 1.47 hannken do { 678 1.47 hannken busy = error = when = 0; 679 1.1 rmind 680 1.47 hannken /* 681 1.47 hannken * First, flush out any vnode references from the 682 1.47 hannken * deferred vrele list. 683 1.47 hannken */ 684 1.62 hannken vrele_flush(mp); 685 1.1 rmind 686 1.47 hannken vfs_vnode_iterator_init(mp, &marker); 687 1.29 christos 688 1.47 hannken while ((vp = vflushnext(marker, &when)) != NULL) { 689 1.47 hannken error = vflush_one(vp, skipvp, flags); 690 1.47 hannken if (error == EBUSY) { 691 1.47 hannken error = 0; 692 1.47 hannken busy++; 693 1.1 rmind #ifdef DEBUG 694 1.47 hannken if (busyprt && retries == 0) 695 1.47 hannken vprint("vflush: busy vnode", vp); 696 1.1 rmind #endif 697 1.47 hannken } else if (error != 0) { 698 1.47 hannken break; 699 1.47 hannken } 700 1.46 hannken } 701 1.46 hannken 702 1.47 hannken vfs_vnode_iterator_destroy(marker); 703 1.47 hannken } while (error == 0 && busy > 0 && retries-- > 0); 704 1.46 hannken 705 1.46 hannken if (error) 706 1.46 hannken return error; 707 1.1 rmind if (busy) 708 1.110 riastrad return SET_ERROR(EBUSY); 709 1.45 hannken return 0; 710 1.1 rmind } 711 1.1 rmind 712 1.1 rmind /* 713 1.1 rmind * Mount a file system. 714 1.1 rmind */ 715 1.1 rmind 716 1.1 rmind /* 717 1.1 rmind * Scan all active processes to see if any of them have a current or root 718 1.1 rmind * directory onto which the new filesystem has just been mounted. If so, 719 1.1 rmind * replace them with the new mount point. 720 1.1 rmind */ 721 1.1 rmind static void 722 1.1 rmind mount_checkdirs(vnode_t *olddp) 723 1.1 rmind { 724 1.1 rmind vnode_t *newdp, *rele1, *rele2; 725 1.1 rmind struct cwdinfo *cwdi; 726 1.1 rmind struct proc *p; 727 1.1 rmind bool retry; 728 1.1 rmind 729 1.78 ad if (vrefcnt(olddp) == 1) { 730 1.1 rmind return; 731 1.1 rmind } 732 1.74 ad if (VFS_ROOT(olddp->v_mountedhere, LK_EXCLUSIVE, &newdp)) 733 1.1 rmind panic("mount: lost mount"); 734 1.1 rmind 735 1.1 rmind do { 736 1.1 rmind retry = false; 737 1.83 ad mutex_enter(&proc_lock); 738 1.1 rmind PROCLIST_FOREACH(p, &allproc) { 739 1.1 rmind if ((cwdi = p->p_cwdi) == NULL) 740 1.1 rmind continue; 741 1.1 rmind /* 742 1.1 rmind * Cannot change to the old directory any more, 743 1.1 rmind * so even if we see a stale value it is not a 744 1.1 rmind * problem. 745 1.1 rmind */ 746 1.1 rmind if (cwdi->cwdi_cdir != olddp && 747 1.1 rmind cwdi->cwdi_rdir != olddp) 748 1.1 rmind continue; 749 1.1 rmind retry = true; 750 1.1 rmind rele1 = NULL; 751 1.1 rmind rele2 = NULL; 752 1.1 rmind atomic_inc_uint(&cwdi->cwdi_refcnt); 753 1.83 ad mutex_exit(&proc_lock); 754 1.81 ad rw_enter(&cwdi->cwdi_lock, RW_WRITER); 755 1.81 ad if (cwdi->cwdi_cdir == olddp) { 756 1.81 ad rele1 = cwdi->cwdi_cdir; 757 1.81 ad vref(newdp); 758 1.81 ad cwdi->cwdi_cdir = newdp; 759 1.81 ad } 760 1.81 ad if (cwdi->cwdi_rdir == olddp) { 761 1.81 ad rele2 = cwdi->cwdi_rdir; 762 1.81 ad vref(newdp); 763 1.81 ad cwdi->cwdi_rdir = newdp; 764 1.1 rmind } 765 1.81 ad rw_exit(&cwdi->cwdi_lock); 766 1.1 rmind cwdfree(cwdi); 767 1.1 rmind if (rele1 != NULL) 768 1.1 rmind vrele(rele1); 769 1.1 rmind if (rele2 != NULL) 770 1.1 rmind vrele(rele2); 771 1.83 ad mutex_enter(&proc_lock); 772 1.1 rmind break; 773 1.1 rmind } 774 1.83 ad mutex_exit(&proc_lock); 775 1.1 rmind } while (retry); 776 1.1 rmind 777 1.1 rmind if (rootvnode == olddp) { 778 1.1 rmind vrele(rootvnode); 779 1.1 rmind vref(newdp); 780 1.1 rmind rootvnode = newdp; 781 1.1 rmind } 782 1.1 rmind vput(newdp); 783 1.1 rmind } 784 1.1 rmind 785 1.31 manu /* 786 1.31 manu * Start extended attributes 787 1.31 manu */ 788 1.31 manu static int 789 1.31 manu start_extattr(struct mount *mp) 790 1.31 manu { 791 1.31 manu int error; 792 1.31 manu 793 1.31 manu error = VFS_EXTATTRCTL(mp, EXTATTR_CMD_START, NULL, 0, NULL); 794 1.108 riastrad if (error) 795 1.31 manu printf("%s: failed to start extattr: error = %d\n", 796 1.31 manu mp->mnt_stat.f_mntonname, error); 797 1.31 manu 798 1.31 manu return error; 799 1.31 manu } 800 1.31 manu 801 1.1 rmind int 802 1.1 rmind mount_domount(struct lwp *l, vnode_t **vpp, struct vfsops *vfsops, 803 1.1 rmind const char *path, int flags, void *data, size_t *data_len) 804 1.1 rmind { 805 1.1 rmind vnode_t *vp = *vpp; 806 1.1 rmind struct mount *mp; 807 1.1 rmind struct pathbuf *pb; 808 1.1 rmind struct nameidata nd; 809 1.85 hannken int error, error2; 810 1.1 rmind 811 1.1 rmind error = kauth_authorize_system(l->l_cred, KAUTH_SYSTEM_MOUNT, 812 1.1 rmind KAUTH_REQ_SYSTEM_MOUNT_NEW, vp, KAUTH_ARG(flags), data); 813 1.1 rmind if (error) { 814 1.1 rmind vfs_delref(vfsops); 815 1.1 rmind return error; 816 1.1 rmind } 817 1.1 rmind 818 1.1 rmind /* Cannot make a non-dir a mount-point (from here anyway). */ 819 1.1 rmind if (vp->v_type != VDIR) { 820 1.1 rmind vfs_delref(vfsops); 821 1.110 riastrad return SET_ERROR(ENOTDIR); 822 1.1 rmind } 823 1.1 rmind 824 1.1 rmind if (flags & MNT_EXPORTED) { 825 1.1 rmind vfs_delref(vfsops); 826 1.110 riastrad return SET_ERROR(EINVAL); 827 1.1 rmind } 828 1.1 rmind 829 1.1 rmind if ((mp = vfs_mountalloc(vfsops, vp)) == NULL) { 830 1.1 rmind vfs_delref(vfsops); 831 1.110 riastrad return SET_ERROR(ENOMEM); 832 1.1 rmind } 833 1.1 rmind 834 1.1 rmind mp->mnt_stat.f_owner = kauth_cred_geteuid(l->l_cred); 835 1.1 rmind 836 1.1 rmind /* 837 1.1 rmind * The underlying file system may refuse the mount for 838 1.1 rmind * various reasons. Allow the user to force it to happen. 839 1.1 rmind * 840 1.1 rmind * Set the mount level flags. 841 1.1 rmind */ 842 1.12 christos mp->mnt_flag = flags & (MNT_BASIC_FLAGS | MNT_FORCE | MNT_IGNORE); 843 1.1 rmind 844 1.1 rmind error = VFS_MOUNT(mp, path, data, data_len); 845 1.1 rmind mp->mnt_flag &= ~MNT_OP_FLAGS; 846 1.1 rmind 847 1.94 hannken if (error != 0) { 848 1.94 hannken vfs_rele(mp); 849 1.94 hannken return error; 850 1.94 hannken } 851 1.94 hannken 852 1.94 hannken /* Suspend new file system before taking mnt_updating. */ 853 1.94 hannken do { 854 1.94 hannken error2 = vfs_suspend(mp, 0); 855 1.94 hannken } while (error2 == EINTR || error2 == ERESTART); 856 1.94 hannken KASSERT(error2 == 0 || error2 == EOPNOTSUPP); 857 1.94 hannken mutex_enter(mp->mnt_updating); 858 1.1 rmind 859 1.1 rmind /* 860 1.1 rmind * Validate and prepare the mount point. 861 1.1 rmind */ 862 1.1 rmind error = pathbuf_copyin(path, &pb); 863 1.1 rmind if (error != 0) { 864 1.1 rmind goto err_mounted; 865 1.1 rmind } 866 1.1 rmind NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | TRYEMULROOT, pb); 867 1.1 rmind error = namei(&nd); 868 1.1 rmind pathbuf_destroy(pb); 869 1.1 rmind if (error != 0) { 870 1.1 rmind goto err_mounted; 871 1.1 rmind } 872 1.1 rmind if (nd.ni_vp != vp) { 873 1.1 rmind vput(nd.ni_vp); 874 1.110 riastrad error = SET_ERROR(EINVAL); 875 1.1 rmind goto err_mounted; 876 1.1 rmind } 877 1.1 rmind if (vp->v_mountedhere != NULL) { 878 1.1 rmind vput(nd.ni_vp); 879 1.110 riastrad error = SET_ERROR(EBUSY); 880 1.1 rmind goto err_mounted; 881 1.1 rmind } 882 1.1 rmind error = vinvalbuf(vp, V_SAVE, l->l_cred, l, 0, 0); 883 1.1 rmind if (error != 0) { 884 1.1 rmind vput(nd.ni_vp); 885 1.1 rmind goto err_mounted; 886 1.1 rmind } 887 1.1 rmind 888 1.1 rmind /* 889 1.1 rmind * Put the new filesystem on the mount list after root. 890 1.1 rmind */ 891 1.1 rmind cache_purge(vp); 892 1.1 rmind mp->mnt_iflag &= ~IMNT_WANTRDWR; 893 1.1 rmind 894 1.52 hannken mountlist_append(mp); 895 1.1 rmind if ((mp->mnt_flag & (MNT_RDONLY | MNT_ASYNC)) == 0) 896 1.35 hannken vfs_syncer_add_to_worklist(mp); 897 1.35 hannken vp->v_mountedhere = mp; 898 1.1 rmind vput(nd.ni_vp); 899 1.1 rmind 900 1.1 rmind mount_checkdirs(vp); 901 1.73 ad mutex_exit(mp->mnt_updating); 902 1.94 hannken if (error2 == 0) 903 1.94 hannken vfs_resume(mp); 904 1.1 rmind 905 1.1 rmind /* Hold an additional reference to the mount across VFS_START(). */ 906 1.56 hannken vfs_ref(mp); 907 1.1 rmind (void) VFS_STATVFS(mp, &mp->mnt_stat); 908 1.1 rmind error = VFS_START(mp, 0); 909 1.71 christos if (error) { 910 1.1 rmind vrele(vp); 911 1.31 manu } else if (flags & MNT_EXTATTR) { 912 1.71 christos if (start_extattr(mp) != 0) 913 1.71 christos mp->mnt_flag &= ~MNT_EXTATTR; 914 1.31 manu } 915 1.1 rmind /* Drop reference held for VFS_START(). */ 916 1.55 hannken vfs_rele(mp); 917 1.1 rmind *vpp = NULL; 918 1.1 rmind return error; 919 1.1 rmind 920 1.1 rmind err_mounted: 921 1.1 rmind if (VFS_UNMOUNT(mp, MNT_FORCE) != 0) 922 1.1 rmind panic("Unmounting fresh file system failed"); 923 1.94 hannken mutex_exit(mp->mnt_updating); 924 1.85 hannken if (error2 == 0) 925 1.85 hannken vfs_resume(mp); 926 1.99 hannken vfs_set_lowermount(mp, NULL); 927 1.55 hannken vfs_rele(mp); 928 1.1 rmind 929 1.1 rmind return error; 930 1.1 rmind } 931 1.1 rmind 932 1.1 rmind /* 933 1.1 rmind * Do the actual file system unmount. File system is assumed to have 934 1.1 rmind * been locked by the caller. 935 1.1 rmind * 936 1.1 rmind * => Caller hold reference to the mount, explicitly for dounmount(). 937 1.1 rmind */ 938 1.1 rmind int 939 1.1 rmind dounmount(struct mount *mp, int flags, struct lwp *l) 940 1.1 rmind { 941 1.105 riastrad struct vnode *coveredvp, *vp; 942 1.105 riastrad struct vnode_impl *vip; 943 1.31 manu int error, async, used_syncer, used_extattr; 944 1.68 hannken const bool was_suspended = fstrans_is_owner(mp); 945 1.1 rmind 946 1.1 rmind #if NVERIEXEC > 0 947 1.1 rmind error = veriexec_unmountchk(mp); 948 1.1 rmind if (error) 949 1.1 rmind return (error); 950 1.1 rmind #endif /* NVERIEXEC > 0 */ 951 1.1 rmind 952 1.68 hannken if (!was_suspended) { 953 1.68 hannken error = vfs_suspend(mp, 0); 954 1.68 hannken if (error) { 955 1.68 hannken return error; 956 1.49 hannken } 957 1.49 hannken } 958 1.62 hannken 959 1.64 hannken KASSERT((mp->mnt_iflag & IMNT_GONE) == 0); 960 1.1 rmind 961 1.35 hannken used_syncer = (mp->mnt_iflag & IMNT_ONWORKLIST) != 0; 962 1.31 manu used_extattr = mp->mnt_flag & MNT_EXTATTR; 963 1.1 rmind 964 1.1 rmind mp->mnt_iflag |= IMNT_UNMOUNT; 965 1.73 ad mutex_enter(mp->mnt_updating); 966 1.107 bad /* 967 1.107 bad * Temporarily clear the MNT_ASYNC flags so that bwrite() doesn't 968 1.107 bad * convert the sync writes to delayed writes. 969 1.107 bad */ 970 1.1 rmind async = mp->mnt_flag & MNT_ASYNC; 971 1.1 rmind mp->mnt_flag &= ~MNT_ASYNC; 972 1.1 rmind cache_purgevfs(mp); /* remove cache entries for this file sys */ 973 1.35 hannken if (used_syncer) 974 1.35 hannken vfs_syncer_remove_from_worklist(mp); 975 1.1 rmind error = 0; 976 1.36 manu if (((mp->mnt_flag & MNT_RDONLY) == 0) && ((flags & MNT_FORCE) == 0)) { 977 1.1 rmind error = VFS_SYNC(mp, MNT_WAIT, l->l_cred); 978 1.1 rmind } 979 1.1 rmind if (error == 0 || (flags & MNT_FORCE)) { 980 1.1 rmind error = VFS_UNMOUNT(mp, flags); 981 1.1 rmind } 982 1.1 rmind if (error) { 983 1.18 mlelstv mp->mnt_iflag &= ~IMNT_UNMOUNT; 984 1.106 bad mp->mnt_flag |= async; 985 1.1 rmind if ((mp->mnt_flag & (MNT_RDONLY | MNT_ASYNC)) == 0) 986 1.35 hannken vfs_syncer_add_to_worklist(mp); 987 1.73 ad mutex_exit(mp->mnt_updating); 988 1.68 hannken if (!was_suspended) 989 1.68 hannken vfs_resume(mp); 990 1.31 manu if (used_extattr) { 991 1.31 manu if (start_extattr(mp) != 0) 992 1.31 manu mp->mnt_flag &= ~MNT_EXTATTR; 993 1.31 manu else 994 1.31 manu mp->mnt_flag |= MNT_EXTATTR; 995 1.31 manu } 996 1.1 rmind return (error); 997 1.1 rmind } 998 1.73 ad mutex_exit(mp->mnt_updating); 999 1.19 mlelstv 1000 1.19 mlelstv /* 1001 1.19 mlelstv * mark filesystem as gone to prevent further umounts 1002 1.19 mlelstv * after mnt_umounting lock is gone, this also prevents 1003 1.19 mlelstv * vfs_busy() from succeeding. 1004 1.19 mlelstv */ 1005 1.19 mlelstv mp->mnt_iflag |= IMNT_GONE; 1006 1.95 hannken if ((coveredvp = mp->mnt_vnodecovered) != NULLVP) { 1007 1.95 hannken coveredvp->v_mountedhere = NULL; 1008 1.95 hannken } 1009 1.68 hannken if (!was_suspended) 1010 1.68 hannken vfs_resume(mp); 1011 1.19 mlelstv 1012 1.52 hannken mountlist_remove(mp); 1013 1.105 riastrad 1014 1.105 riastrad if ((vip = TAILQ_FIRST(&mp->mnt_vnodelist)) != NULL) { 1015 1.105 riastrad vp = VIMPL_TO_VNODE(vip); 1016 1.104 hannken vprint("dangling", vp); 1017 1.1 rmind panic("unmount: dangling vnode"); 1018 1.104 hannken } 1019 1.1 rmind vfs_hooks_unmount(mp); 1020 1.19 mlelstv 1021 1.99 hannken vfs_set_lowermount(mp, NULL); 1022 1.55 hannken vfs_rele(mp); /* reference from mount() */ 1023 1.1 rmind if (coveredvp != NULLVP) { 1024 1.1 rmind vrele(coveredvp); 1025 1.1 rmind } 1026 1.1 rmind return (0); 1027 1.1 rmind } 1028 1.1 rmind 1029 1.1 rmind /* 1030 1.1 rmind * Unmount all file systems. 1031 1.1 rmind * We traverse the list in reverse order under the assumption that doing so 1032 1.1 rmind * will avoid needing to worry about dependencies. 1033 1.1 rmind */ 1034 1.1 rmind bool 1035 1.1 rmind vfs_unmountall(struct lwp *l) 1036 1.1 rmind { 1037 1.1 rmind 1038 1.16 pooka printf("unmounting file systems...\n"); 1039 1.1 rmind return vfs_unmountall1(l, true, true); 1040 1.1 rmind } 1041 1.1 rmind 1042 1.1 rmind static void 1043 1.1 rmind vfs_unmount_print(struct mount *mp, const char *pfx) 1044 1.1 rmind { 1045 1.1 rmind 1046 1.1 rmind aprint_verbose("%sunmounted %s on %s type %s\n", pfx, 1047 1.1 rmind mp->mnt_stat.f_mntfromname, mp->mnt_stat.f_mntonname, 1048 1.1 rmind mp->mnt_stat.f_fstypename); 1049 1.1 rmind } 1050 1.1 rmind 1051 1.53 hannken /* 1052 1.53 hannken * Return the mount with the highest generation less than "gen". 1053 1.53 hannken */ 1054 1.53 hannken static struct mount * 1055 1.53 hannken vfs_unmount_next(uint64_t gen) 1056 1.1 rmind { 1057 1.53 hannken mount_iterator_t *iter; 1058 1.1 rmind struct mount *mp, *nmp; 1059 1.1 rmind 1060 1.1 rmind nmp = NULL; 1061 1.1 rmind 1062 1.53 hannken mountlist_iterator_init(&iter); 1063 1.53 hannken while ((mp = mountlist_iterator_next(iter)) != NULL) { 1064 1.108 riastrad if ((nmp == NULL || mp->mnt_gen > nmp->mnt_gen) && 1065 1.53 hannken mp->mnt_gen < gen) { 1066 1.53 hannken if (nmp != NULL) 1067 1.55 hannken vfs_rele(nmp); 1068 1.1 rmind nmp = mp; 1069 1.55 hannken vfs_ref(nmp); 1070 1.1 rmind } 1071 1.1 rmind } 1072 1.53 hannken mountlist_iterator_destroy(iter); 1073 1.53 hannken 1074 1.53 hannken return nmp; 1075 1.53 hannken } 1076 1.53 hannken 1077 1.53 hannken bool 1078 1.53 hannken vfs_unmount_forceone(struct lwp *l) 1079 1.53 hannken { 1080 1.53 hannken struct mount *mp; 1081 1.53 hannken int error; 1082 1.53 hannken 1083 1.53 hannken mp = vfs_unmount_next(mountgen); 1084 1.53 hannken if (mp == NULL) { 1085 1.1 rmind return false; 1086 1.1 rmind } 1087 1.1 rmind 1088 1.1 rmind #ifdef DEBUG 1089 1.16 pooka printf("forcefully unmounting %s (%s)...\n", 1090 1.53 hannken mp->mnt_stat.f_mntonname, mp->mnt_stat.f_mntfromname); 1091 1.1 rmind #endif 1092 1.53 hannken if ((error = dounmount(mp, MNT_FORCE, l)) == 0) { 1093 1.53 hannken vfs_unmount_print(mp, "forcefully "); 1094 1.1 rmind return true; 1095 1.1 rmind } else { 1096 1.55 hannken vfs_rele(mp); 1097 1.1 rmind } 1098 1.1 rmind 1099 1.1 rmind #ifdef DEBUG 1100 1.1 rmind printf("forceful unmount of %s failed with error %d\n", 1101 1.53 hannken mp->mnt_stat.f_mntonname, error); 1102 1.1 rmind #endif 1103 1.1 rmind 1104 1.1 rmind return false; 1105 1.1 rmind } 1106 1.1 rmind 1107 1.1 rmind bool 1108 1.1 rmind vfs_unmountall1(struct lwp *l, bool force, bool verbose) 1109 1.1 rmind { 1110 1.53 hannken struct mount *mp; 1111 1.86 hannken mount_iterator_t *iter; 1112 1.1 rmind bool any_error = false, progress = false; 1113 1.53 hannken uint64_t gen; 1114 1.1 rmind int error; 1115 1.1 rmind 1116 1.53 hannken gen = mountgen; 1117 1.53 hannken for (;;) { 1118 1.53 hannken mp = vfs_unmount_next(gen); 1119 1.53 hannken if (mp == NULL) 1120 1.53 hannken break; 1121 1.53 hannken gen = mp->mnt_gen; 1122 1.53 hannken 1123 1.1 rmind #ifdef DEBUG 1124 1.16 pooka printf("unmounting %p %s (%s)...\n", 1125 1.1 rmind (void *)mp, mp->mnt_stat.f_mntonname, 1126 1.1 rmind mp->mnt_stat.f_mntfromname); 1127 1.1 rmind #endif 1128 1.1 rmind if ((error = dounmount(mp, force ? MNT_FORCE : 0, l)) == 0) { 1129 1.1 rmind vfs_unmount_print(mp, ""); 1130 1.1 rmind progress = true; 1131 1.1 rmind } else { 1132 1.55 hannken vfs_rele(mp); 1133 1.1 rmind if (verbose) { 1134 1.1 rmind printf("unmount of %s failed with error %d\n", 1135 1.1 rmind mp->mnt_stat.f_mntonname, error); 1136 1.1 rmind } 1137 1.1 rmind any_error = true; 1138 1.1 rmind } 1139 1.1 rmind } 1140 1.1 rmind if (verbose) { 1141 1.16 pooka printf("unmounting done\n"); 1142 1.1 rmind } 1143 1.1 rmind if (any_error && verbose) { 1144 1.1 rmind printf("WARNING: some file systems would not unmount\n"); 1145 1.1 rmind } 1146 1.86 hannken /* If the mountlist is empty it is time to remove swap. */ 1147 1.86 hannken mountlist_iterator_init(&iter); 1148 1.86 hannken if (mountlist_iterator_next(iter) == NULL) { 1149 1.86 hannken uvm_swap_shutdown(l); 1150 1.86 hannken } 1151 1.86 hannken mountlist_iterator_destroy(iter); 1152 1.86 hannken 1153 1.1 rmind return progress; 1154 1.1 rmind } 1155 1.1 rmind 1156 1.1 rmind void 1157 1.1 rmind vfs_sync_all(struct lwp *l) 1158 1.1 rmind { 1159 1.1 rmind printf("syncing disks... "); 1160 1.1 rmind 1161 1.1 rmind /* remove user processes from run queue */ 1162 1.1 rmind suspendsched(); 1163 1.1 rmind (void)spl0(); 1164 1.1 rmind 1165 1.1 rmind /* avoid coming back this way again if we panic. */ 1166 1.1 rmind doing_shutdown = 1; 1167 1.1 rmind 1168 1.5 dsl do_sys_sync(l); 1169 1.1 rmind 1170 1.1 rmind /* Wait for sync to finish. */ 1171 1.80 ad if (vfs_syncwait() != 0) { 1172 1.1 rmind #if defined(DDB) && defined(DEBUG_HALT_BUSY) 1173 1.1 rmind Debugger(); 1174 1.1 rmind #endif 1175 1.1 rmind printf("giving up\n"); 1176 1.1 rmind return; 1177 1.1 rmind } else 1178 1.1 rmind printf("done\n"); 1179 1.1 rmind } 1180 1.1 rmind 1181 1.3 rmind /* 1182 1.3 rmind * Sync and unmount file systems before shutting down. 1183 1.3 rmind */ 1184 1.3 rmind void 1185 1.3 rmind vfs_shutdown(void) 1186 1.1 rmind { 1187 1.3 rmind lwp_t *l = curlwp; 1188 1.1 rmind 1189 1.1 rmind vfs_sync_all(l); 1190 1.1 rmind 1191 1.1 rmind /* 1192 1.89 andvar * If we have panicked - do not make the situation potentially 1193 1.1 rmind * worse by unmounting the file systems. 1194 1.1 rmind */ 1195 1.3 rmind if (panicstr != NULL) { 1196 1.1 rmind return; 1197 1.3 rmind } 1198 1.1 rmind 1199 1.1 rmind /* Unmount file systems. */ 1200 1.1 rmind vfs_unmountall(l); 1201 1.1 rmind } 1202 1.1 rmind 1203 1.1 rmind /* 1204 1.1 rmind * Print a list of supported file system types (used by vfs_mountroot) 1205 1.1 rmind */ 1206 1.1 rmind static void 1207 1.1 rmind vfs_print_fstypes(void) 1208 1.1 rmind { 1209 1.1 rmind struct vfsops *v; 1210 1.1 rmind int cnt = 0; 1211 1.1 rmind 1212 1.1 rmind mutex_enter(&vfs_list_lock); 1213 1.1 rmind LIST_FOREACH(v, &vfs_list, vfs_list) 1214 1.1 rmind ++cnt; 1215 1.1 rmind mutex_exit(&vfs_list_lock); 1216 1.1 rmind 1217 1.1 rmind if (cnt == 0) { 1218 1.1 rmind printf("WARNING: No file system modules have been loaded.\n"); 1219 1.1 rmind return; 1220 1.1 rmind } 1221 1.1 rmind 1222 1.1 rmind printf("Supported file systems:"); 1223 1.1 rmind mutex_enter(&vfs_list_lock); 1224 1.1 rmind LIST_FOREACH(v, &vfs_list, vfs_list) { 1225 1.1 rmind printf(" %s", v->vfs_name); 1226 1.1 rmind } 1227 1.1 rmind mutex_exit(&vfs_list_lock); 1228 1.1 rmind printf("\n"); 1229 1.1 rmind } 1230 1.1 rmind 1231 1.1 rmind /* 1232 1.1 rmind * Mount the root file system. If the operator didn't specify a 1233 1.1 rmind * file system to use, try all possible file systems until one 1234 1.1 rmind * succeeds. 1235 1.1 rmind */ 1236 1.1 rmind int 1237 1.1 rmind vfs_mountroot(void) 1238 1.1 rmind { 1239 1.1 rmind struct vfsops *v; 1240 1.1 rmind int error = ENODEV; 1241 1.1 rmind 1242 1.1 rmind if (root_device == NULL) 1243 1.1 rmind panic("vfs_mountroot: root device unknown"); 1244 1.1 rmind 1245 1.1 rmind switch (device_class(root_device)) { 1246 1.1 rmind case DV_IFNET: 1247 1.1 rmind if (rootdev != NODEV) 1248 1.1 rmind panic("vfs_mountroot: rootdev set for DV_IFNET " 1249 1.1 rmind "(0x%llx -> %llu,%llu)", 1250 1.1 rmind (unsigned long long)rootdev, 1251 1.1 rmind (unsigned long long)major(rootdev), 1252 1.1 rmind (unsigned long long)minor(rootdev)); 1253 1.1 rmind break; 1254 1.1 rmind 1255 1.1 rmind case DV_DISK: 1256 1.1 rmind if (rootdev == NODEV) 1257 1.1 rmind panic("vfs_mountroot: rootdev not set for DV_DISK"); 1258 1.1 rmind if (bdevvp(rootdev, &rootvp)) 1259 1.1 rmind panic("vfs_mountroot: can't get vnode for rootdev"); 1260 1.90 hannken vn_lock(rootvp, LK_EXCLUSIVE | LK_RETRY); 1261 1.1 rmind error = VOP_OPEN(rootvp, FREAD, FSCRED); 1262 1.90 hannken VOP_UNLOCK(rootvp); 1263 1.1 rmind if (error) { 1264 1.1 rmind printf("vfs_mountroot: can't open root device\n"); 1265 1.1 rmind return (error); 1266 1.1 rmind } 1267 1.1 rmind break; 1268 1.1 rmind 1269 1.1 rmind case DV_VIRTUAL: 1270 1.1 rmind break; 1271 1.1 rmind 1272 1.1 rmind default: 1273 1.1 rmind printf("%s: inappropriate for root file system\n", 1274 1.1 rmind device_xname(root_device)); 1275 1.110 riastrad return SET_ERROR(ENODEV); 1276 1.1 rmind } 1277 1.1 rmind 1278 1.1 rmind /* 1279 1.1 rmind * If user specified a root fs type, use it. Make sure the 1280 1.1 rmind * specified type exists and has a mount_root() 1281 1.1 rmind */ 1282 1.1 rmind if (strcmp(rootfstype, ROOT_FSTYPE_ANY) != 0) { 1283 1.1 rmind v = vfs_getopsbyname(rootfstype); 1284 1.110 riastrad error = SET_ERROR(EFTYPE); 1285 1.1 rmind if (v != NULL) { 1286 1.1 rmind if (v->vfs_mountroot != NULL) { 1287 1.1 rmind error = (v->vfs_mountroot)(); 1288 1.1 rmind } 1289 1.1 rmind v->vfs_refcount--; 1290 1.1 rmind } 1291 1.1 rmind goto done; 1292 1.1 rmind } 1293 1.1 rmind 1294 1.1 rmind /* 1295 1.1 rmind * Try each file system currently configured into the kernel. 1296 1.1 rmind */ 1297 1.1 rmind mutex_enter(&vfs_list_lock); 1298 1.1 rmind LIST_FOREACH(v, &vfs_list, vfs_list) { 1299 1.1 rmind if (v->vfs_mountroot == NULL) 1300 1.1 rmind continue; 1301 1.1 rmind #ifdef DEBUG 1302 1.1 rmind aprint_normal("mountroot: trying %s...\n", v->vfs_name); 1303 1.1 rmind #endif 1304 1.1 rmind v->vfs_refcount++; 1305 1.1 rmind mutex_exit(&vfs_list_lock); 1306 1.1 rmind error = (*v->vfs_mountroot)(); 1307 1.1 rmind mutex_enter(&vfs_list_lock); 1308 1.1 rmind v->vfs_refcount--; 1309 1.1 rmind if (!error) { 1310 1.1 rmind aprint_normal("root file system type: %s\n", 1311 1.1 rmind v->vfs_name); 1312 1.1 rmind break; 1313 1.1 rmind } 1314 1.1 rmind } 1315 1.1 rmind mutex_exit(&vfs_list_lock); 1316 1.1 rmind 1317 1.1 rmind if (v == NULL) { 1318 1.1 rmind vfs_print_fstypes(); 1319 1.1 rmind printf("no file system for %s", device_xname(root_device)); 1320 1.1 rmind if (device_class(root_device) == DV_DISK) 1321 1.1 rmind printf(" (dev 0x%llx)", (unsigned long long)rootdev); 1322 1.1 rmind printf("\n"); 1323 1.110 riastrad error = SET_ERROR(EFTYPE); 1324 1.1 rmind } 1325 1.1 rmind 1326 1.1 rmind done: 1327 1.1 rmind if (error && device_class(root_device) == DV_DISK) { 1328 1.91 riastrad vn_lock(rootvp, LK_EXCLUSIVE | LK_RETRY); 1329 1.1 rmind VOP_CLOSE(rootvp, FREAD, FSCRED); 1330 1.91 riastrad VOP_UNLOCK(rootvp); 1331 1.1 rmind vrele(rootvp); 1332 1.1 rmind } 1333 1.1 rmind if (error == 0) { 1334 1.53 hannken mount_iterator_t *iter; 1335 1.24 christos struct mount *mp; 1336 1.1 rmind 1337 1.53 hannken mountlist_iterator_init(&iter); 1338 1.53 hannken mp = mountlist_iterator_next(iter); 1339 1.53 hannken KASSERT(mp != NULL); 1340 1.53 hannken mountlist_iterator_destroy(iter); 1341 1.53 hannken 1342 1.24 christos mp->mnt_flag |= MNT_ROOTFS; 1343 1.24 christos mp->mnt_op->vfs_refcount++; 1344 1.1 rmind 1345 1.1 rmind /* 1346 1.1 rmind * Get the vnode for '/'. Set cwdi0.cwdi_cdir to 1347 1.76 ad * reference it, and donate it the reference grabbed 1348 1.76 ad * with VFS_ROOT(). 1349 1.1 rmind */ 1350 1.76 ad error = VFS_ROOT(mp, LK_NONE, &rootvnode); 1351 1.1 rmind if (error) 1352 1.1 rmind panic("cannot find root vnode, error=%d", error); 1353 1.1 rmind cwdi0.cwdi_cdir = rootvnode; 1354 1.1 rmind cwdi0.cwdi_rdir = NULL; 1355 1.1 rmind 1356 1.1 rmind /* 1357 1.1 rmind * Now that root is mounted, we can fixup initproc's CWD 1358 1.1 rmind * info. All other processes are kthreads, which merely 1359 1.1 rmind * share proc0's CWD info. 1360 1.1 rmind */ 1361 1.1 rmind initproc->p_cwdi->cwdi_cdir = rootvnode; 1362 1.1 rmind vref(initproc->p_cwdi->cwdi_cdir); 1363 1.1 rmind initproc->p_cwdi->cwdi_rdir = NULL; 1364 1.1 rmind /* 1365 1.1 rmind * Enable loading of modules from the filesystem 1366 1.1 rmind */ 1367 1.1 rmind module_load_vfs_init(); 1368 1.1 rmind 1369 1.1 rmind } 1370 1.1 rmind return (error); 1371 1.1 rmind } 1372 1.1 rmind 1373 1.1 rmind /* 1374 1.1 rmind * mount_specific_key_create -- 1375 1.1 rmind * Create a key for subsystem mount-specific data. 1376 1.1 rmind */ 1377 1.1 rmind int 1378 1.1 rmind mount_specific_key_create(specificdata_key_t *keyp, specificdata_dtor_t dtor) 1379 1.1 rmind { 1380 1.1 rmind 1381 1.1 rmind return specificdata_key_create(mount_specificdata_domain, keyp, dtor); 1382 1.1 rmind } 1383 1.1 rmind 1384 1.1 rmind /* 1385 1.1 rmind * mount_specific_key_delete -- 1386 1.1 rmind * Delete a key for subsystem mount-specific data. 1387 1.1 rmind */ 1388 1.1 rmind void 1389 1.1 rmind mount_specific_key_delete(specificdata_key_t key) 1390 1.1 rmind { 1391 1.1 rmind 1392 1.1 rmind specificdata_key_delete(mount_specificdata_domain, key); 1393 1.1 rmind } 1394 1.1 rmind 1395 1.1 rmind /* 1396 1.1 rmind * mount_initspecific -- 1397 1.1 rmind * Initialize a mount's specificdata container. 1398 1.1 rmind */ 1399 1.1 rmind void 1400 1.1 rmind mount_initspecific(struct mount *mp) 1401 1.1 rmind { 1402 1.22 martin int error __diagused; 1403 1.1 rmind 1404 1.1 rmind error = specificdata_init(mount_specificdata_domain, 1405 1.108 riastrad &mp->mnt_specdataref); 1406 1.1 rmind KASSERT(error == 0); 1407 1.1 rmind } 1408 1.1 rmind 1409 1.1 rmind /* 1410 1.1 rmind * mount_finispecific -- 1411 1.1 rmind * Finalize a mount's specificdata container. 1412 1.1 rmind */ 1413 1.1 rmind void 1414 1.1 rmind mount_finispecific(struct mount *mp) 1415 1.1 rmind { 1416 1.1 rmind 1417 1.1 rmind specificdata_fini(mount_specificdata_domain, &mp->mnt_specdataref); 1418 1.1 rmind } 1419 1.1 rmind 1420 1.1 rmind /* 1421 1.1 rmind * mount_getspecific -- 1422 1.1 rmind * Return mount-specific data corresponding to the specified key. 1423 1.1 rmind */ 1424 1.1 rmind void * 1425 1.1 rmind mount_getspecific(struct mount *mp, specificdata_key_t key) 1426 1.1 rmind { 1427 1.1 rmind 1428 1.1 rmind return specificdata_getspecific(mount_specificdata_domain, 1429 1.108 riastrad &mp->mnt_specdataref, key); 1430 1.1 rmind } 1431 1.1 rmind 1432 1.1 rmind /* 1433 1.1 rmind * mount_setspecific -- 1434 1.1 rmind * Set mount-specific data corresponding to the specified key. 1435 1.1 rmind */ 1436 1.1 rmind void 1437 1.1 rmind mount_setspecific(struct mount *mp, specificdata_key_t key, void *data) 1438 1.1 rmind { 1439 1.1 rmind 1440 1.1 rmind specificdata_setspecific(mount_specificdata_domain, 1441 1.108 riastrad &mp->mnt_specdataref, key, data); 1442 1.1 rmind } 1443 1.1 rmind 1444 1.1 rmind /* 1445 1.1 rmind * Check to see if a filesystem is mounted on a block device. 1446 1.1 rmind */ 1447 1.1 rmind int 1448 1.1 rmind vfs_mountedon(vnode_t *vp) 1449 1.1 rmind { 1450 1.1 rmind vnode_t *vq; 1451 1.1 rmind int error = 0; 1452 1.1 rmind 1453 1.1 rmind if (vp->v_type != VBLK) 1454 1.110 riastrad return SET_ERROR(ENOTBLK); 1455 1.21 hannken if (spec_node_getmountedfs(vp) != NULL) 1456 1.110 riastrad return SET_ERROR(EBUSY); 1457 1.92 riastrad if (spec_node_lookup_by_dev(vp->v_type, vp->v_rdev, VDEAD_NOWAIT, &vq) 1458 1.92 riastrad == 0) { 1459 1.21 hannken if (spec_node_getmountedfs(vq) != NULL) 1460 1.110 riastrad error = SET_ERROR(EBUSY); 1461 1.17 hannken vrele(vq); 1462 1.1 rmind } 1463 1.17 hannken 1464 1.17 hannken return error; 1465 1.1 rmind } 1466 1.1 rmind 1467 1.1 rmind /* 1468 1.1 rmind * Check if a device pointed to by vp is mounted. 1469 1.1 rmind * 1470 1.1 rmind * Returns: 1471 1.1 rmind * EINVAL if it's not a disk 1472 1.1 rmind * EBUSY if it's a disk and mounted 1473 1.1 rmind * 0 if it's a disk and not mounted 1474 1.1 rmind */ 1475 1.1 rmind int 1476 1.1 rmind rawdev_mounted(vnode_t *vp, vnode_t **bvpp) 1477 1.1 rmind { 1478 1.1 rmind vnode_t *bvp; 1479 1.1 rmind dev_t dev; 1480 1.1 rmind int d_type; 1481 1.1 rmind 1482 1.1 rmind bvp = NULL; 1483 1.1 rmind d_type = D_OTHER; 1484 1.1 rmind 1485 1.1 rmind if (iskmemvp(vp)) 1486 1.110 riastrad return SET_ERROR(EINVAL); 1487 1.1 rmind 1488 1.1 rmind switch (vp->v_type) { 1489 1.1 rmind case VCHR: { 1490 1.1 rmind const struct cdevsw *cdev; 1491 1.1 rmind 1492 1.7 christos dev = vp->v_rdev; 1493 1.1 rmind cdev = cdevsw_lookup(dev); 1494 1.1 rmind if (cdev != NULL) { 1495 1.1 rmind dev_t blkdev; 1496 1.1 rmind 1497 1.1 rmind blkdev = devsw_chr2blk(dev); 1498 1.1 rmind if (blkdev != NODEV) { 1499 1.1 rmind if (vfinddev(blkdev, VBLK, &bvp) != 0) { 1500 1.1 rmind d_type = (cdev->d_flag & D_TYPEMASK); 1501 1.1 rmind /* XXX: what if bvp disappears? */ 1502 1.1 rmind vrele(bvp); 1503 1.1 rmind } 1504 1.1 rmind } 1505 1.1 rmind } 1506 1.1 rmind 1507 1.1 rmind break; 1508 1.108 riastrad } 1509 1.1 rmind 1510 1.1 rmind case VBLK: { 1511 1.1 rmind const struct bdevsw *bdev; 1512 1.1 rmind 1513 1.7 christos dev = vp->v_rdev; 1514 1.1 rmind bdev = bdevsw_lookup(dev); 1515 1.1 rmind if (bdev != NULL) 1516 1.1 rmind d_type = (bdev->d_flag & D_TYPEMASK); 1517 1.1 rmind 1518 1.1 rmind bvp = vp; 1519 1.1 rmind 1520 1.1 rmind break; 1521 1.108 riastrad } 1522 1.1 rmind 1523 1.1 rmind default: 1524 1.1 rmind break; 1525 1.1 rmind } 1526 1.1 rmind 1527 1.1 rmind if (d_type != D_DISK) 1528 1.110 riastrad return SET_ERROR(EINVAL); 1529 1.1 rmind 1530 1.1 rmind if (bvpp != NULL) 1531 1.1 rmind *bvpp = bvp; 1532 1.1 rmind 1533 1.1 rmind /* 1534 1.1 rmind * XXX: This is bogus. We should be failing the request 1535 1.1 rmind * XXX: not only if this specific slice is mounted, but 1536 1.1 rmind * XXX: if it's on a disk with any other mounted slice. 1537 1.1 rmind */ 1538 1.1 rmind if (vfs_mountedon(bvp)) 1539 1.110 riastrad return SET_ERROR(EBUSY); 1540 1.1 rmind 1541 1.1 rmind return 0; 1542 1.1 rmind } 1543 1.1 rmind 1544 1.1 rmind /* 1545 1.1 rmind * Make a 'unique' number from a mount type name. 1546 1.1 rmind */ 1547 1.1 rmind long 1548 1.1 rmind makefstype(const char *type) 1549 1.1 rmind { 1550 1.1 rmind long rv; 1551 1.1 rmind 1552 1.1 rmind for (rv = 0; *type; type++) { 1553 1.1 rmind rv <<= 2; 1554 1.1 rmind rv ^= *type; 1555 1.1 rmind } 1556 1.1 rmind return rv; 1557 1.1 rmind } 1558 1.24 christos 1559 1.52 hannken static struct mountlist_entry * 1560 1.52 hannken mountlist_alloc(enum mountlist_type type, struct mount *mp) 1561 1.52 hannken { 1562 1.52 hannken struct mountlist_entry *me; 1563 1.52 hannken 1564 1.52 hannken me = kmem_zalloc(sizeof(*me), KM_SLEEP); 1565 1.52 hannken me->me_mount = mp; 1566 1.52 hannken me->me_type = type; 1567 1.52 hannken 1568 1.52 hannken return me; 1569 1.52 hannken } 1570 1.52 hannken 1571 1.52 hannken static void 1572 1.52 hannken mountlist_free(struct mountlist_entry *me) 1573 1.52 hannken { 1574 1.52 hannken 1575 1.52 hannken kmem_free(me, sizeof(*me)); 1576 1.52 hannken } 1577 1.52 hannken 1578 1.52 hannken void 1579 1.52 hannken mountlist_iterator_init(mount_iterator_t **mip) 1580 1.52 hannken { 1581 1.52 hannken struct mountlist_entry *me; 1582 1.52 hannken 1583 1.52 hannken me = mountlist_alloc(ME_MARKER, NULL); 1584 1.52 hannken mutex_enter(&mountlist_lock); 1585 1.54 hannken TAILQ_INSERT_HEAD(&mountlist, me, me_list); 1586 1.52 hannken mutex_exit(&mountlist_lock); 1587 1.52 hannken *mip = (mount_iterator_t *)me; 1588 1.52 hannken } 1589 1.52 hannken 1590 1.52 hannken void 1591 1.52 hannken mountlist_iterator_destroy(mount_iterator_t *mi) 1592 1.52 hannken { 1593 1.52 hannken struct mountlist_entry *marker = &mi->mi_entry; 1594 1.52 hannken 1595 1.52 hannken if (marker->me_mount != NULL) 1596 1.56 hannken vfs_unbusy(marker->me_mount); 1597 1.52 hannken 1598 1.52 hannken mutex_enter(&mountlist_lock); 1599 1.54 hannken TAILQ_REMOVE(&mountlist, marker, me_list); 1600 1.52 hannken mutex_exit(&mountlist_lock); 1601 1.52 hannken 1602 1.52 hannken mountlist_free(marker); 1603 1.52 hannken 1604 1.52 hannken } 1605 1.52 hannken 1606 1.52 hannken /* 1607 1.52 hannken * Return the next mount or NULL for this iterator. 1608 1.52 hannken * Mark it busy on success. 1609 1.52 hannken */ 1610 1.58 hannken static inline struct mount * 1611 1.58 hannken _mountlist_iterator_next(mount_iterator_t *mi, bool wait) 1612 1.52 hannken { 1613 1.52 hannken struct mountlist_entry *me, *marker = &mi->mi_entry; 1614 1.52 hannken struct mount *mp; 1615 1.58 hannken int error; 1616 1.52 hannken 1617 1.52 hannken if (marker->me_mount != NULL) { 1618 1.56 hannken vfs_unbusy(marker->me_mount); 1619 1.52 hannken marker->me_mount = NULL; 1620 1.52 hannken } 1621 1.52 hannken 1622 1.52 hannken mutex_enter(&mountlist_lock); 1623 1.52 hannken for (;;) { 1624 1.52 hannken KASSERT(marker->me_type == ME_MARKER); 1625 1.52 hannken 1626 1.52 hannken me = TAILQ_NEXT(marker, me_list); 1627 1.52 hannken if (me == NULL) { 1628 1.52 hannken /* End of list: keep marker and return. */ 1629 1.52 hannken mutex_exit(&mountlist_lock); 1630 1.52 hannken return NULL; 1631 1.52 hannken } 1632 1.54 hannken TAILQ_REMOVE(&mountlist, marker, me_list); 1633 1.54 hannken TAILQ_INSERT_AFTER(&mountlist, me, marker, me_list); 1634 1.52 hannken 1635 1.52 hannken /* Skip other markers. */ 1636 1.52 hannken if (me->me_type != ME_MOUNT) 1637 1.52 hannken continue; 1638 1.52 hannken 1639 1.52 hannken /* Take an initial reference for vfs_busy() below. */ 1640 1.52 hannken mp = me->me_mount; 1641 1.52 hannken KASSERT(mp != NULL); 1642 1.55 hannken vfs_ref(mp); 1643 1.52 hannken mutex_exit(&mountlist_lock); 1644 1.52 hannken 1645 1.52 hannken /* Try to mark this mount busy and return on success. */ 1646 1.58 hannken if (wait) 1647 1.58 hannken error = vfs_busy(mp); 1648 1.58 hannken else 1649 1.58 hannken error = vfs_trybusy(mp); 1650 1.58 hannken if (error == 0) { 1651 1.55 hannken vfs_rele(mp); 1652 1.52 hannken marker->me_mount = mp; 1653 1.52 hannken return mp; 1654 1.52 hannken } 1655 1.55 hannken vfs_rele(mp); 1656 1.52 hannken mutex_enter(&mountlist_lock); 1657 1.52 hannken } 1658 1.52 hannken } 1659 1.52 hannken 1660 1.58 hannken struct mount * 1661 1.58 hannken mountlist_iterator_next(mount_iterator_t *mi) 1662 1.58 hannken { 1663 1.58 hannken 1664 1.58 hannken return _mountlist_iterator_next(mi, true); 1665 1.58 hannken } 1666 1.58 hannken 1667 1.58 hannken struct mount * 1668 1.58 hannken mountlist_iterator_trynext(mount_iterator_t *mi) 1669 1.58 hannken { 1670 1.58 hannken 1671 1.58 hannken return _mountlist_iterator_next(mi, false); 1672 1.58 hannken } 1673 1.58 hannken 1674 1.52 hannken /* 1675 1.52 hannken * Attach new mount to the end of the mount list. 1676 1.52 hannken */ 1677 1.24 christos void 1678 1.24 christos mountlist_append(struct mount *mp) 1679 1.24 christos { 1680 1.52 hannken struct mountlist_entry *me; 1681 1.52 hannken 1682 1.52 hannken me = mountlist_alloc(ME_MOUNT, mp); 1683 1.24 christos mutex_enter(&mountlist_lock); 1684 1.54 hannken TAILQ_INSERT_TAIL(&mountlist, me, me_list); 1685 1.24 christos mutex_exit(&mountlist_lock); 1686 1.24 christos } 1687 1.52 hannken 1688 1.52 hannken /* 1689 1.52 hannken * Remove mount from mount list. 1690 1.108 riastrad */ 1691 1.108 riastrad void 1692 1.52 hannken mountlist_remove(struct mount *mp) 1693 1.52 hannken { 1694 1.52 hannken struct mountlist_entry *me; 1695 1.52 hannken 1696 1.52 hannken mutex_enter(&mountlist_lock); 1697 1.54 hannken TAILQ_FOREACH(me, &mountlist, me_list) 1698 1.52 hannken if (me->me_type == ME_MOUNT && me->me_mount == mp) 1699 1.52 hannken break; 1700 1.52 hannken KASSERT(me != NULL); 1701 1.54 hannken TAILQ_REMOVE(&mountlist, me, me_list); 1702 1.52 hannken mutex_exit(&mountlist_lock); 1703 1.52 hannken mountlist_free(me); 1704 1.52 hannken } 1705 1.52 hannken 1706 1.52 hannken /* 1707 1.52 hannken * Unlocked variant to traverse the mountlist. 1708 1.52 hannken * To be used from DDB only. 1709 1.52 hannken */ 1710 1.52 hannken struct mount * 1711 1.52 hannken _mountlist_next(struct mount *mp) 1712 1.52 hannken { 1713 1.52 hannken struct mountlist_entry *me; 1714 1.52 hannken 1715 1.52 hannken if (mp == NULL) { 1716 1.54 hannken me = TAILQ_FIRST(&mountlist); 1717 1.52 hannken } else { 1718 1.54 hannken TAILQ_FOREACH(me, &mountlist, me_list) 1719 1.52 hannken if (me->me_type == ME_MOUNT && me->me_mount == mp) 1720 1.52 hannken break; 1721 1.52 hannken if (me != NULL) 1722 1.52 hannken me = TAILQ_NEXT(me, me_list); 1723 1.52 hannken } 1724 1.52 hannken 1725 1.52 hannken while (me != NULL && me->me_type != ME_MOUNT) 1726 1.52 hannken me = TAILQ_NEXT(me, me_list); 1727 1.52 hannken 1728 1.52 hannken return (me ? me->me_mount : NULL); 1729 1.52 hannken } 1730