1 1.67 riastrad /* $NetBSD: vfs_init.c,v 1.67 2024/12/07 02:27:38 riastradh Exp $ */ 2 1.9 thorpej 3 1.9 thorpej /*- 4 1.39 ad * Copyright (c) 1998, 2000, 2008 The NetBSD Foundation, Inc. 5 1.9 thorpej * All rights reserved. 6 1.9 thorpej * 7 1.9 thorpej * This code is derived from software contributed to The NetBSD Foundation 8 1.9 thorpej * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility, 9 1.9 thorpej * NASA Ames Research Center. 10 1.9 thorpej * 11 1.9 thorpej * Redistribution and use in source and binary forms, with or without 12 1.9 thorpej * modification, are permitted provided that the following conditions 13 1.9 thorpej * are met: 14 1.9 thorpej * 1. Redistributions of source code must retain the above copyright 15 1.9 thorpej * notice, this list of conditions and the following disclaimer. 16 1.9 thorpej * 2. Redistributions in binary form must reproduce the above copyright 17 1.9 thorpej * notice, this list of conditions and the following disclaimer in the 18 1.9 thorpej * documentation and/or other materials provided with the distribution. 19 1.9 thorpej * 20 1.9 thorpej * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 21 1.9 thorpej * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 22 1.9 thorpej * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 23 1.9 thorpej * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 24 1.9 thorpej * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 25 1.9 thorpej * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 26 1.9 thorpej * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 27 1.9 thorpej * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 28 1.9 thorpej * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 29 1.9 thorpej * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 30 1.9 thorpej * POSSIBILITY OF SUCH DAMAGE. 31 1.9 thorpej */ 32 1.2 cgd 33 1.1 mycroft /* 34 1.1 mycroft * Copyright (c) 1989, 1993 35 1.1 mycroft * The Regents of the University of California. All rights reserved. 36 1.1 mycroft * 37 1.1 mycroft * This code is derived from software contributed 38 1.1 mycroft * to Berkeley by John Heidemann of the UCLA Ficus project. 39 1.1 mycroft * 40 1.1 mycroft * Source: * @(#)i405_init.c 2.10 92/04/27 UCLA Ficus project 41 1.1 mycroft * 42 1.1 mycroft * Redistribution and use in source and binary forms, with or without 43 1.1 mycroft * modification, are permitted provided that the following conditions 44 1.1 mycroft * are met: 45 1.1 mycroft * 1. Redistributions of source code must retain the above copyright 46 1.1 mycroft * notice, this list of conditions and the following disclaimer. 47 1.1 mycroft * 2. Redistributions in binary form must reproduce the above copyright 48 1.1 mycroft * notice, this list of conditions and the following disclaimer in the 49 1.1 mycroft * documentation and/or other materials provided with the distribution. 50 1.24 agc * 3. Neither the name of the University nor the names of its contributors 51 1.1 mycroft * may be used to endorse or promote products derived from this software 52 1.1 mycroft * without specific prior written permission. 53 1.1 mycroft * 54 1.1 mycroft * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 55 1.1 mycroft * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 56 1.1 mycroft * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 57 1.1 mycroft * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 58 1.1 mycroft * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 59 1.1 mycroft * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 60 1.1 mycroft * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 61 1.1 mycroft * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 62 1.1 mycroft * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 63 1.1 mycroft * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 64 1.1 mycroft * SUCH DAMAGE. 65 1.1 mycroft * 66 1.10 fvdl * @(#)vfs_init.c 8.5 (Berkeley) 5/11/95 67 1.1 mycroft */ 68 1.20 lukem 69 1.20 lukem #include <sys/cdefs.h> 70 1.67 riastrad __KERNEL_RCSID(0, "$NetBSD: vfs_init.c,v 1.67 2024/12/07 02:27:38 riastradh Exp $"); 71 1.1 mycroft 72 1.1 mycroft #include <sys/param.h> 73 1.60 riastrad #include <sys/types.h> 74 1.60 riastrad 75 1.1 mycroft #include <sys/buf.h> 76 1.60 riastrad #include <sys/dirhash.h> 77 1.1 mycroft #include <sys/errno.h> 78 1.60 riastrad #include <sys/kauth.h> 79 1.43 yamt #include <sys/kmem.h> 80 1.37 ad #include <sys/module.h> 81 1.60 riastrad #include <sys/mount.h> 82 1.60 riastrad #include <sys/namei.h> 83 1.61 riastrad #include <sys/sdt.h> 84 1.60 riastrad #include <sys/stat.h> 85 1.42 pooka #include <sys/sysctl.h> 86 1.60 riastrad #include <sys/systm.h> 87 1.60 riastrad #include <sys/time.h> 88 1.60 riastrad #include <sys/ucred.h> 89 1.60 riastrad #include <sys/vnode.h> 90 1.61 riastrad #include <sys/vnode_impl.h> 91 1.1 mycroft 92 1.56 riastrad #include <miscfs/deadfs/deadfs.h> 93 1.58 riastrad #include <miscfs/fifofs/fifo.h> 94 1.57 riastrad #include <miscfs/specfs/specdev.h> 95 1.56 riastrad 96 1.1 mycroft /* 97 1.1 mycroft * Sigh, such primitive tools are these... 98 1.1 mycroft */ 99 1.1 mycroft #if 0 100 1.1 mycroft #define DODEBUG(A) A 101 1.1 mycroft #else 102 1.65 riastrad #define DODEBUG(A) __nothing 103 1.1 mycroft #endif 104 1.1 mycroft 105 1.61 riastrad SDT_PROVIDER_DEFINE(vfs); 106 1.61 riastrad 107 1.9 thorpej /* 108 1.9 thorpej * These vnodeopv_descs are listed here because they are not 109 1.9 thorpej * associated with any particular file system, and thus cannot 110 1.9 thorpej * be initialized by vfs_attach(). 111 1.9 thorpej */ 112 1.18 jdolecek const struct vnodeopv_desc * const vfs_special_vnodeopv_descs[] = { 113 1.9 thorpej &dead_vnodeop_opv_desc, 114 1.9 thorpej &fifo_vnodeop_opv_desc, 115 1.9 thorpej &spec_vnodeop_opv_desc, 116 1.9 thorpej NULL, 117 1.9 thorpej }; 118 1.9 thorpej 119 1.34 pooka struct vfs_list_head vfs_list = /* vfs list */ 120 1.34 pooka LIST_HEAD_INITIALIZER(vfs_list); 121 1.34 pooka 122 1.45 elad static kauth_listener_t mount_listener; 123 1.45 elad 124 1.1 mycroft /* 125 1.1 mycroft * This code doesn't work if the defn is **vnodop_defns with cc. 126 1.1 mycroft * The problem is because of the compiler sometimes putting in an 127 1.1 mycroft * extra level of indirection for arrays. It's an interesting 128 1.1 mycroft * "feature" of C. 129 1.1 mycroft */ 130 1.25 junyoung typedef int (*PFI)(void *); 131 1.5 christos 132 1.1 mycroft /* 133 1.1 mycroft * A miscellaneous routine. 134 1.1 mycroft * A generic "default" routine that just returns an error. 135 1.1 mycroft */ 136 1.5 christos /*ARGSUSED*/ 137 1.1 mycroft int 138 1.32 yamt vn_default_error(void *v) 139 1.1 mycroft { 140 1.1 mycroft 141 1.67 riastrad return SET_ERROR(EOPNOTSUPP); 142 1.1 mycroft } 143 1.1 mycroft 144 1.42 pooka static struct sysctllog *vfs_sysctllog; 145 1.42 pooka 146 1.42 pooka /* 147 1.42 pooka * Top level filesystem related information gathering. 148 1.42 pooka */ 149 1.42 pooka static void 150 1.42 pooka sysctl_vfs_setup(void) 151 1.42 pooka { 152 1.42 pooka 153 1.42 pooka sysctl_createv(&vfs_sysctllog, 0, NULL, NULL, 154 1.65 riastrad CTLFLAG_PERMANENT, 155 1.65 riastrad CTLTYPE_NODE, "generic", 156 1.65 riastrad SYSCTL_DESCR("Non-specific vfs related information"), 157 1.65 riastrad NULL, 0, NULL, 0, 158 1.65 riastrad CTL_VFS, VFS_GENERIC, CTL_EOL); 159 1.42 pooka sysctl_createv(&vfs_sysctllog, 0, NULL, NULL, 160 1.65 riastrad CTLFLAG_PERMANENT, 161 1.65 riastrad CTLTYPE_STRING, "fstypes", 162 1.65 riastrad SYSCTL_DESCR("List of file systems present"), 163 1.65 riastrad sysctl_vfs_generic_fstypes, 0, NULL, 0, 164 1.65 riastrad CTL_VFS, VFS_GENERIC, CTL_CREATE, CTL_EOL); 165 1.42 pooka sysctl_createv(&vfs_sysctllog, 0, NULL, NULL, 166 1.65 riastrad CTLFLAG_PERMANENT|CTLFLAG_READWRITE, 167 1.65 riastrad CTLTYPE_INT, "magiclinks", 168 1.65 riastrad SYSCTL_DESCR("Whether \"magic\" symlinks are expanded"), 169 1.65 riastrad NULL, 0, &vfs_magiclinks, 0, 170 1.65 riastrad CTL_VFS, VFS_GENERIC, VFS_MAGICLINKS, CTL_EOL); 171 1.52 jdolecek sysctl_createv(&vfs_sysctllog, 0, NULL, NULL, 172 1.65 riastrad CTLFLAG_PERMANENT|CTLFLAG_READWRITE, 173 1.65 riastrad CTLTYPE_INT, "timestamp_precision", 174 1.65 riastrad SYSCTL_DESCR("File timestamp precision"), 175 1.65 riastrad NULL, 0, &vfs_timestamp_precision, 0, 176 1.65 riastrad CTL_VFS, VFS_GENERIC, VFS_TIMESTAMP_PRECISION, 177 1.65 riastrad CTL_EOL); 178 1.42 pooka } 179 1.42 pooka 180 1.1 mycroft /* 181 1.1 mycroft * vfs_init.c 182 1.1 mycroft * 183 1.1 mycroft * Allocate and fill in operations vectors. 184 1.1 mycroft * 185 1.1 mycroft * An undocumented feature of this approach to defining operations is that 186 1.1 mycroft * there can be multiple entries in vfs_opv_descs for the same operations 187 1.1 mycroft * vector. This allows third parties to extend the set of operations 188 1.1 mycroft * supported by another layer in a binary compatibile way. For example, 189 1.1 mycroft * assume that NFS needed to be modified to support Ficus. NFS has an entry 190 1.1 mycroft * (probably nfs_vnopdeop_decls) declaring all the operations NFS supports by 191 1.1 mycroft * default. Ficus could add another entry (ficus_nfs_vnodeop_decl_entensions) 192 1.1 mycroft * listing those new operations Ficus adds to NFS, all without modifying the 193 1.1 mycroft * NFS code. (Of couse, the OTW NFS protocol still needs to be munged, but 194 1.1 mycroft * that is a(whole)nother story.) This is a feature. 195 1.1 mycroft */ 196 1.3 mycroft 197 1.3 mycroft /* 198 1.9 thorpej * Init the vector, if it needs it. 199 1.3 mycroft * Also handle backwards compatibility. 200 1.3 mycroft */ 201 1.17 jdolecek static void 202 1.28 thorpej vfs_opv_init_explicit(const struct vnodeopv_desc *vfs_opv_desc) 203 1.1 mycroft { 204 1.25 junyoung int (**opv_desc_vector)(void *); 205 1.18 jdolecek const struct vnodeopv_entry_desc *opve_descp; 206 1.1 mycroft 207 1.3 mycroft opv_desc_vector = *(vfs_opv_desc->opv_desc_vector_p); 208 1.3 mycroft 209 1.3 mycroft for (opve_descp = vfs_opv_desc->opv_desc_ops; 210 1.3 mycroft opve_descp->opve_op; 211 1.3 mycroft opve_descp++) { 212 1.1 mycroft /* 213 1.3 mycroft * Sanity check: is this operation listed 214 1.3 mycroft * in the list of operations? We check this 215 1.23 mjl * by seeing if its offset is zero. Since 216 1.3 mycroft * the default routine should always be listed 217 1.3 mycroft * first, it should be the only one with a zero 218 1.3 mycroft * offset. Any other operation with a zero 219 1.3 mycroft * offset is probably not listed in 220 1.3 mycroft * vfs_op_descs, and so is probably an error. 221 1.3 mycroft * 222 1.3 mycroft * A panic here means the layer programmer 223 1.3 mycroft * has committed the all-too common bug 224 1.3 mycroft * of adding a new operation to the layer's 225 1.3 mycroft * list of vnode operations but 226 1.3 mycroft * not adding the operation to the system-wide 227 1.3 mycroft * list of supported operations. 228 1.1 mycroft */ 229 1.3 mycroft if (opve_descp->opve_op->vdesc_offset == 0 && 230 1.65 riastrad opve_descp->opve_op->vdesc_offset != VOFFSET(vop_default)) 231 1.65 riastrad { 232 1.8 christos printf("operation %s not listed in %s.\n", 233 1.3 mycroft opve_descp->opve_op->vdesc_name, "vfs_op_descs"); 234 1.65 riastrad panic("vfs_opv_init: bad operation"); 235 1.1 mycroft } 236 1.3 mycroft 237 1.3 mycroft /* 238 1.3 mycroft * Fill in this entry. 239 1.3 mycroft */ 240 1.3 mycroft opv_desc_vector[opve_descp->opve_op->vdesc_offset] = 241 1.3 mycroft opve_descp->opve_impl; 242 1.1 mycroft } 243 1.3 mycroft } 244 1.3 mycroft 245 1.17 jdolecek static void 246 1.28 thorpej vfs_opv_init_default(const struct vnodeopv_desc *vfs_opv_desc) 247 1.3 mycroft { 248 1.3 mycroft int j; 249 1.25 junyoung int (**opv_desc_vector)(void *); 250 1.3 mycroft 251 1.3 mycroft opv_desc_vector = *(vfs_opv_desc->opv_desc_vector_p); 252 1.3 mycroft 253 1.3 mycroft /* 254 1.3 mycroft * Force every operations vector to have a default routine. 255 1.3 mycroft */ 256 1.3 mycroft if (opv_desc_vector[VOFFSET(vop_default)] == NULL) 257 1.65 riastrad panic("vfs_opv_init: operation vector without vop_default"); 258 1.3 mycroft 259 1.65 riastrad for (j = 0; j < VNODE_OPS_COUNT; j++) { 260 1.65 riastrad if (opv_desc_vector[j] == NULL) { 261 1.26 perry opv_desc_vector[j] = 262 1.3 mycroft opv_desc_vector[VOFFSET(vop_default)]; 263 1.65 riastrad } 264 1.65 riastrad } 265 1.3 mycroft } 266 1.3 mycroft 267 1.3 mycroft void 268 1.28 thorpej vfs_opv_init(const struct vnodeopv_desc * const *vopvdpp) 269 1.3 mycroft { 270 1.25 junyoung int (**opv_desc_vector)(void *); 271 1.3 mycroft int i; 272 1.3 mycroft 273 1.3 mycroft /* 274 1.9 thorpej * Allocate the vectors. 275 1.3 mycroft */ 276 1.9 thorpej for (i = 0; vopvdpp[i] != NULL; i++) { 277 1.9 thorpej opv_desc_vector = 278 1.43 yamt kmem_alloc(VNODE_OPS_COUNT * sizeof(PFI), KM_SLEEP); 279 1.17 jdolecek memset(opv_desc_vector, 0, VNODE_OPS_COUNT * sizeof(PFI)); 280 1.9 thorpej *(vopvdpp[i]->opv_desc_vector_p) = opv_desc_vector; 281 1.9 thorpej DODEBUG(printf("vector at %p allocated\n", 282 1.9 thorpej opv_desc_vector_p)); 283 1.9 thorpej } 284 1.9 thorpej 285 1.9 thorpej /* 286 1.9 thorpej * ...and fill them in. 287 1.9 thorpej */ 288 1.9 thorpej for (i = 0; vopvdpp[i] != NULL; i++) 289 1.9 thorpej vfs_opv_init_explicit(vopvdpp[i]); 290 1.3 mycroft 291 1.1 mycroft /* 292 1.1 mycroft * Finally, go back and replace unfilled routines 293 1.3 mycroft * with their default. 294 1.1 mycroft */ 295 1.9 thorpej for (i = 0; vopvdpp[i] != NULL; i++) 296 1.9 thorpej vfs_opv_init_default(vopvdpp[i]); 297 1.9 thorpej } 298 1.9 thorpej 299 1.9 thorpej void 300 1.28 thorpej vfs_opv_free(const struct vnodeopv_desc * const *vopvdpp) 301 1.9 thorpej { 302 1.9 thorpej int i; 303 1.9 thorpej 304 1.9 thorpej /* 305 1.9 thorpej * Free the vectors allocated in vfs_opv_init(). 306 1.9 thorpej */ 307 1.9 thorpej for (i = 0; vopvdpp[i] != NULL; i++) { 308 1.43 yamt kmem_free(*(vopvdpp[i]->opv_desc_vector_p), 309 1.43 yamt VNODE_OPS_COUNT * sizeof(PFI)); 310 1.9 thorpej *(vopvdpp[i]->opv_desc_vector_p) = NULL; 311 1.9 thorpej } 312 1.1 mycroft } 313 1.1 mycroft 314 1.17 jdolecek #ifdef DEBUG 315 1.17 jdolecek static void 316 1.28 thorpej vfs_op_check(void) 317 1.1 mycroft { 318 1.1 mycroft int i; 319 1.1 mycroft 320 1.8 christos DODEBUG(printf("Vnode_interface_init.\n")); 321 1.17 jdolecek 322 1.1 mycroft /* 323 1.17 jdolecek * Check offset of each op. 324 1.1 mycroft */ 325 1.17 jdolecek for (i = 0; vfs_op_descs[i]; i++) { 326 1.17 jdolecek if (vfs_op_descs[i]->vdesc_offset != i) 327 1.17 jdolecek panic("vfs_op_check: vfs_op_desc[] offset mismatch"); 328 1.17 jdolecek } 329 1.17 jdolecek 330 1.17 jdolecek if (i != VNODE_OPS_COUNT) { 331 1.17 jdolecek panic("vfs_op_check: vnode ops count mismatch (%d != %d)", 332 1.65 riastrad i, VNODE_OPS_COUNT); 333 1.1 mycroft } 334 1.17 jdolecek 335 1.17 jdolecek DODEBUG(printf ("vfs_opv_numops=%d\n", VNODE_OPS_COUNT)); 336 1.1 mycroft } 337 1.17 jdolecek #endif /* DEBUG */ 338 1.1 mycroft 339 1.1 mycroft /* 340 1.45 elad * Common routine to check if an unprivileged mount is allowed. 341 1.45 elad * 342 1.45 elad * We export just this part (i.e., without the access control) so that if a 343 1.45 elad * secmodel wants to implement finer grained user mounts it can do so without 344 1.45 elad * copying too much code. More elaborate policies (i.e., specific users allowed 345 1.45 elad * to also create devices and/or introduce set-id binaries, or export 346 1.45 elad * file-systems) will require a different implementation. 347 1.45 elad * 348 1.45 elad * This routine is intended to be called from listener context, and as such 349 1.45 elad * does not take credentials as an argument. 350 1.45 elad */ 351 1.45 elad int 352 1.45 elad usermount_common_policy(struct mount *mp, u_long flags) 353 1.45 elad { 354 1.45 elad 355 1.45 elad /* No exporting if unprivileged. */ 356 1.45 elad if (flags & MNT_EXPORTED) 357 1.67 riastrad return SET_ERROR(EPERM); 358 1.45 elad 359 1.45 elad /* Must have 'nosuid' and 'nodev'. */ 360 1.45 elad if ((flags & MNT_NODEV) == 0 || (flags & MNT_NOSUID) == 0) 361 1.67 riastrad return SET_ERROR(EPERM); 362 1.45 elad 363 1.45 elad /* Retain 'noexec'. */ 364 1.45 elad if ((mp->mnt_flag & MNT_NOEXEC) && (flags & MNT_NOEXEC) == 0) 365 1.67 riastrad return SET_ERROR(EPERM); 366 1.45 elad 367 1.45 elad return 0; 368 1.45 elad } 369 1.45 elad 370 1.45 elad static int 371 1.45 elad mount_listener_cb(kauth_cred_t cred, kauth_action_t action, void *cookie, 372 1.45 elad void *arg0, void *arg1, void *arg2, void *arg3) 373 1.45 elad { 374 1.45 elad int result; 375 1.45 elad enum kauth_system_req req; 376 1.45 elad 377 1.45 elad result = KAUTH_RESULT_DEFER; 378 1.50 joerg req = (enum kauth_system_req)(uintptr_t)(uintptr_t)arg0; 379 1.45 elad 380 1.46 elad if (action != KAUTH_SYSTEM_MOUNT) 381 1.45 elad return result; 382 1.45 elad 383 1.46 elad if (req == KAUTH_REQ_SYSTEM_MOUNT_GET) 384 1.46 elad result = KAUTH_RESULT_ALLOW; 385 1.46 elad else if (req == KAUTH_REQ_SYSTEM_MOUNT_DEVICE) { 386 1.46 elad vnode_t *devvp = arg2; 387 1.51 christos accmode_t accmode = (accmode_t)(unsigned long)arg3; 388 1.46 elad int error; 389 1.46 elad 390 1.51 christos error = VOP_ACCESS(devvp, accmode, cred); 391 1.46 elad if (!error) 392 1.46 elad result = KAUTH_RESULT_ALLOW; 393 1.46 elad } 394 1.45 elad 395 1.45 elad return result; 396 1.45 elad } 397 1.45 elad 398 1.45 elad /* 399 1.1 mycroft * Initialize the vnode structures and initialize each file system type. 400 1.1 mycroft */ 401 1.5 christos void 402 1.28 thorpej vfsinit(void) 403 1.1 mycroft { 404 1.16 thorpej 405 1.16 thorpej /* 406 1.42 pooka * Attach sysctl nodes 407 1.42 pooka */ 408 1.42 pooka sysctl_vfs_setup(); 409 1.42 pooka 410 1.42 pooka /* 411 1.1 mycroft * Initialize the vnode table 412 1.1 mycroft */ 413 1.1 mycroft vntblinit(); 414 1.9 thorpej 415 1.1 mycroft /* 416 1.1 mycroft * Initialize the vnode name cache 417 1.1 mycroft */ 418 1.1 mycroft nchinit(); 419 1.9 thorpej 420 1.17 jdolecek #ifdef DEBUG 421 1.1 mycroft /* 422 1.17 jdolecek * Check the list of vnode operations. 423 1.1 mycroft */ 424 1.17 jdolecek vfs_op_check(); 425 1.17 jdolecek #endif 426 1.9 thorpej 427 1.1 mycroft /* 428 1.9 thorpej * Initialize the special vnode operations. 429 1.9 thorpej */ 430 1.9 thorpej vfs_opv_init(vfs_special_vnodeopv_descs); 431 1.9 thorpej 432 1.9 thorpej /* 433 1.41 reinoud * Initialise generic dirhash. 434 1.41 reinoud */ 435 1.41 reinoud dirhash_init(); 436 1.41 reinoud 437 1.41 reinoud /* 438 1.40 rumble * Initialise VFS hooks. 439 1.40 rumble */ 440 1.40 rumble vfs_hooks_init(); 441 1.40 rumble 442 1.45 elad mount_listener = kauth_listen_scope(KAUTH_SCOPE_SYSTEM, 443 1.45 elad mount_listener_cb, NULL); 444 1.45 elad 445 1.40 rumble /* 446 1.9 thorpej * Establish each file system which was statically 447 1.9 thorpej * included in the kernel. 448 1.1 mycroft */ 449 1.37 ad module_init_class(MODULE_CLASS_VFS); 450 1.53 thorpej 451 1.54 thorpej /* 452 1.54 thorpej * Initialize EVFILT_FS for kqueue. 453 1.54 thorpej */ 454 1.54 thorpej vfs_evfilt_fs_init(); 455 1.1 mycroft } 456 1.34 pooka 457 1.34 pooka /* 458 1.35 ad * Drop a reference to a file system type. 459 1.35 ad */ 460 1.35 ad void 461 1.35 ad vfs_delref(struct vfsops *vfs) 462 1.35 ad { 463 1.35 ad 464 1.35 ad mutex_enter(&vfs_list_lock); 465 1.35 ad vfs->vfs_refcount--; 466 1.35 ad mutex_exit(&vfs_list_lock); 467 1.35 ad } 468 1.35 ad 469 1.35 ad /* 470 1.34 pooka * Establish a file system and initialize it. 471 1.34 pooka */ 472 1.34 pooka int 473 1.34 pooka vfs_attach(struct vfsops *vfs) 474 1.34 pooka { 475 1.34 pooka struct vfsops *v; 476 1.34 pooka int error = 0; 477 1.34 pooka 478 1.35 ad mutex_enter(&vfs_list_lock); 479 1.34 pooka 480 1.34 pooka /* 481 1.34 pooka * Make sure this file system doesn't already exist. 482 1.34 pooka */ 483 1.34 pooka LIST_FOREACH(v, &vfs_list, vfs_list) { 484 1.34 pooka if (strcmp(vfs->vfs_name, v->vfs_name) == 0) { 485 1.67 riastrad error = SET_ERROR(EEXIST); 486 1.34 pooka goto out; 487 1.34 pooka } 488 1.34 pooka } 489 1.34 pooka 490 1.34 pooka /* 491 1.34 pooka * Initialize the vnode operations for this file system. 492 1.34 pooka */ 493 1.34 pooka vfs_opv_init(vfs->vfs_opv_descs); 494 1.34 pooka 495 1.34 pooka /* 496 1.34 pooka * Now initialize the file system itself. 497 1.34 pooka */ 498 1.34 pooka (*vfs->vfs_init)(); 499 1.34 pooka 500 1.34 pooka /* 501 1.34 pooka * ...and link it into the kernel's list. 502 1.34 pooka */ 503 1.34 pooka LIST_INSERT_HEAD(&vfs_list, vfs, vfs_list); 504 1.34 pooka 505 1.34 pooka /* 506 1.34 pooka * Sanity: make sure the reference count is 0. 507 1.34 pooka */ 508 1.34 pooka vfs->vfs_refcount = 0; 509 1.65 riastrad out: 510 1.35 ad mutex_exit(&vfs_list_lock); 511 1.65 riastrad return error; 512 1.34 pooka } 513 1.34 pooka 514 1.34 pooka /* 515 1.34 pooka * Remove a file system from the kernel. 516 1.34 pooka */ 517 1.34 pooka int 518 1.34 pooka vfs_detach(struct vfsops *vfs) 519 1.34 pooka { 520 1.34 pooka struct vfsops *v; 521 1.35 ad int error = 0; 522 1.35 ad 523 1.35 ad mutex_enter(&vfs_list_lock); 524 1.34 pooka 525 1.34 pooka /* 526 1.34 pooka * Make sure no one is using the filesystem. 527 1.34 pooka */ 528 1.35 ad if (vfs->vfs_refcount != 0) { 529 1.67 riastrad error = SET_ERROR(EBUSY); 530 1.35 ad goto out; 531 1.35 ad } 532 1.34 pooka 533 1.34 pooka /* 534 1.34 pooka * ...and remove it from the kernel's list. 535 1.34 pooka */ 536 1.34 pooka LIST_FOREACH(v, &vfs_list, vfs_list) { 537 1.34 pooka if (v == vfs) { 538 1.34 pooka LIST_REMOVE(v, vfs_list); 539 1.34 pooka break; 540 1.34 pooka } 541 1.34 pooka } 542 1.34 pooka 543 1.35 ad if (v == NULL) { 544 1.67 riastrad error = SET_ERROR(ESRCH); 545 1.35 ad goto out; 546 1.35 ad } 547 1.34 pooka 548 1.34 pooka /* 549 1.34 pooka * Now run the file system-specific cleanups. 550 1.34 pooka */ 551 1.34 pooka (*vfs->vfs_done)(); 552 1.34 pooka 553 1.34 pooka /* 554 1.34 pooka * Free the vnode operations vector. 555 1.34 pooka */ 556 1.34 pooka vfs_opv_free(vfs->vfs_opv_descs); 557 1.65 riastrad out: 558 1.66 riastrad mutex_exit(&vfs_list_lock); 559 1.65 riastrad return error; 560 1.34 pooka } 561 1.34 pooka 562 1.34 pooka void 563 1.34 pooka vfs_reinit(void) 564 1.34 pooka { 565 1.34 pooka struct vfsops *vfs; 566 1.34 pooka 567 1.35 ad mutex_enter(&vfs_list_lock); 568 1.34 pooka LIST_FOREACH(vfs, &vfs_list, vfs_list) { 569 1.34 pooka if (vfs->vfs_reinit) { 570 1.35 ad vfs->vfs_refcount++; 571 1.35 ad mutex_exit(&vfs_list_lock); 572 1.34 pooka (*vfs->vfs_reinit)(); 573 1.35 ad mutex_enter(&vfs_list_lock); 574 1.35 ad vfs->vfs_refcount--; 575 1.34 pooka } 576 1.34 pooka } 577 1.35 ad mutex_exit(&vfs_list_lock); 578 1.34 pooka } 579