1/* 2 * Copyright (c) 2000-2010 Apple Inc. All rights reserved. 3 * 4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ 5 * 6 * This file contains Original Code and/or Modifications of Original Code 7 * as defined in and that are subject to the Apple Public Source License 8 * Version 2.0 (the 'License'). You may not use this file except in 9 * compliance with the License. The rights granted to you under the License 10 * may not be used to create, or enable the creation or redistribution of, 11 * unlawful or unlicensed copies of an Apple operating system, or to 12 * circumvent, violate, or enable the circumvention or violation of, any 13 * terms of an Apple operating system software license agreement. 14 * 15 * Please obtain a copy of the License at 16 * http://www.opensource.apple.com/apsl/ and read it before using this file. 17 * 18 * The Original Code and all software distributed under the License are 19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 23 * Please see the License for the specific language governing rights and 24 * limitations under the License. 25 * 26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ 27 */ 28/*- 29 * Copyright 1997,1998 Julian Elischer. All rights reserved. 30 * julian@freebsd.org 31 * 32 * Redistribution and use in source and binary forms, with or without 33 * modification, are permitted provided that the following conditions are 34 * met: 35 * 1. Redistributions of source code must retain the above copyright 36 * notice, this list of conditions and the following disclaimer. 37 * 2. Redistributions in binary form must reproduce the above copyright notice, 38 * this list of conditions and the following disclaimer in the documentation 39 * and/or other materials provided with the distribution. 40 * 41 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER ``AS IS'' AND ANY EXPRESS 42 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 43 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 44 * DISCLAIMED. IN NO EVENT SHALL THE HOLDER OR CONTRIBUTORS BE LIABLE FOR 45 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 46 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 47 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 48 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 49 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 50 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 51 * SUCH DAMAGE. 52 * 53 * devfs_vfsops.c 54 * 55 */ 56/* 57 * NOTICE: This file was modified by SPARTA, Inc. in 2005 to introduce 58 * support for mandatory and extensible security protections. This notice 59 * is included in support of clause 2.2 (b) of the Apple Public License, 60 * Version 2.0. 61 */ 62/* 63 * HISTORY 64 * Dieter Siegmund (dieter@apple.com) Wed Jul 14 13:37:59 PDT 1999 65 * - modified devfs_statfs() to use devfs_stats to calculate the 66 * amount of memory used by devfs 67 */ 68 69 70#include <sys/param.h> 71#include <sys/systm.h> 72#include <sys/kernel.h> 73#include <sys/vnode_internal.h> 74#include <sys/proc.h> 75#include <sys/kauth.h> 76#include <sys/mount_internal.h> 77#include <sys/malloc.h> 78 79#include <libkern/OSAtomic.h> 80 81#if CONFIG_MACF 82#include <security/mac_framework.h> 83#endif 84 85#include "devfs.h" 86#include "devfsdefs.h" 87 88#if FDESC 89#include "fdesc.h" 90#endif /* FDESC */ 91 92 93static int devfs_statfs( struct mount *mp, struct vfsstatfs *sbp, vfs_context_t ctx); 94static int devfs_vfs_getattr(mount_t mp, struct vfs_attr *fsap, vfs_context_t ctx); 95 96#if !defined(SECURE_KERNEL) 97extern int setup_kmem; 98__private_extern__ void devfs_setup_kmem(void); 99#endif 100 101/*- 102 * Called from the generic VFS startups. 103 * This is the second stage of DEVFS initialisation. 104 * The probed devices have already been loaded and the 105 * basic structure of the DEVFS created. 106 * We take the oportunity to mount the hidden DEVFS layer, so that 107 * devices from devfs get sync'd. 108 */ 109static int 110devfs_init(__unused struct vfsconf *vfsp) 111{ 112 if (devfs_sinit()) 113 return (ENOTSUP); 114 devfs_make_node(makedev(0, 0), DEVFS_CHAR, 115 UID_ROOT, GID_WHEEL, 0622, "console"); 116 devfs_make_node(makedev(2, 0), DEVFS_CHAR, 117 UID_ROOT, GID_WHEEL, 0666, "tty"); 118#if !defined(SECURE_KERNEL) 119 if (setup_kmem) { 120 devfs_setup_kmem(); 121 } 122#endif 123 devfs_make_node(makedev(3, 2), DEVFS_CHAR, 124 UID_ROOT, GID_WHEEL, 0666, "null"); 125 devfs_make_node(makedev(3, 3), DEVFS_CHAR, 126 UID_ROOT, GID_WHEEL, 0666, "zero"); 127 devfs_make_node(makedev(6, 0), DEVFS_CHAR, 128 UID_ROOT, GID_WHEEL, 0600, "klog"); 129 130#if FDESC 131 devfs_fdesc_init(); 132#endif 133 134 return 0; 135} 136 137#if !defined(SECURE_KERNEL) 138__private_extern__ void 139devfs_setup_kmem(void) 140{ 141 devfs_make_node(makedev(3, 0), DEVFS_CHAR, 142 UID_ROOT, GID_KMEM, 0640, "mem"); 143 devfs_make_node(makedev(3, 1), DEVFS_CHAR, 144 UID_ROOT, GID_KMEM, 0640, "kmem"); 145} 146#endif 147 148 149/*- 150 * mp - pointer to 'mount' structure 151 * path - addr in user space of mount point (ie /usr or whatever) 152 * data - addr in user space of mount params including the 153 * name of the block special file to treat as a filesystem. 154 * (NOT USED) 155 * ndp - namei data pointer (NOT USED) 156 * p - proc pointer 157 * devfs is special in that it doesn't require any device to be mounted.. 158 * It makes up its data as it goes along. 159 * it must be mounted during single user.. until it is, only std{in/out/err} 160 * and the root filesystem are available. 161 */ 162/*proto*/ 163int 164devfs_mount(struct mount *mp, __unused vnode_t devvp, __unused user_addr_t data, vfs_context_t ctx) 165{ 166 struct devfsmount *devfs_mp_p; /* devfs specific mount info */ 167 int error; 168 169 /*- 170 * If they just want to update, we don't need to do anything. 171 */ 172 if (mp->mnt_flag & MNT_UPDATE) 173 { 174 return 0; 175 } 176 177 /* Advisory locking should be handled at the VFS layer */ 178 vfs_setlocklocal(mp); 179 180 /*- 181 * Well, it's not an update, it's a real mount request. 182 * Time to get dirty. 183 * HERE we should check to see if we are already mounted here. 184 */ 185 186 MALLOC(devfs_mp_p, struct devfsmount *, sizeof(struct devfsmount), 187 M_DEVFSMNT, M_WAITOK); 188 if (devfs_mp_p == NULL) 189 return (ENOMEM); 190 bzero(devfs_mp_p,sizeof(*devfs_mp_p)); 191 devfs_mp_p->mount = mp; 192 193 /*- 194 * Fill out some fields 195 */ 196 mp->mnt_data = (qaddr_t)devfs_mp_p; 197 mp->mnt_vfsstat.f_fsid.val[0] = (int32_t)(uintptr_t)devfs_mp_p; 198 mp->mnt_vfsstat.f_fsid.val[1] = vfs_typenum(mp); 199 mp->mnt_flag |= MNT_LOCAL; 200 201 DEVFS_LOCK(); 202 error = dev_dup_plane(devfs_mp_p); 203 DEVFS_UNLOCK(); 204 205 if (error) { 206 mp->mnt_data = (qaddr_t)0; 207 FREE((caddr_t)devfs_mp_p, M_DEVFSMNT); 208 return (error); 209 } else 210 DEVFS_INCR_MOUNTS(); 211 212 /*- 213 * Copy in the name of the directory the filesystem 214 * is to be mounted on. 215 * And we clear the remainder of the character strings 216 * to be tidy. 217 */ 218 219 bzero(mp->mnt_vfsstat.f_mntfromname, MAXPATHLEN); 220 bcopy("devfs",mp->mnt_vfsstat.f_mntfromname, 5); 221 (void)devfs_statfs(mp, &mp->mnt_vfsstat, ctx); 222 223 return 0; 224} 225 226 227static int 228devfs_start(__unused struct mount *mp, __unused int flags, __unused vfs_context_t ctx) 229{ 230 return 0; 231} 232 233/*- 234 * Unmount the filesystem described by mp. 235 */ 236static int 237devfs_unmount( struct mount *mp, int mntflags, __unused vfs_context_t ctx) 238{ 239 struct devfsmount *devfs_mp_p = (struct devfsmount *)mp->mnt_data; 240 int flags = 0; 241 int force = 0; 242 int error; 243 244 if (mntflags & MNT_FORCE) { 245 flags |= FORCECLOSE; 246 force = 1; 247 } 248 error = vflush(mp, NULLVP, flags); 249 if (error && !force) 250 return error; 251 252 DEVFS_LOCK(); 253 devfs_free_plane(devfs_mp_p); 254 DEVFS_UNLOCK(); 255 256 DEVFS_DECR_MOUNTS(); 257 258 FREE((caddr_t)devfs_mp_p, M_DEVFSMNT); 259 mp->mnt_data = (qaddr_t)0; 260 mp->mnt_flag &= ~MNT_LOCAL; 261 262 return 0; 263} 264 265/* return the address of the root vnode in *vpp */ 266static int 267devfs_root(struct mount *mp, struct vnode **vpp, __unused vfs_context_t ctx) 268{ 269 struct devfsmount *devfs_mp_p = (struct devfsmount *)(mp->mnt_data); 270 int error; 271 272 DEVFS_LOCK(); 273 /* last parameter to devfs_dntovn() is ignored */ 274 error = devfs_dntovn(devfs_mp_p->plane_root->de_dnp, vpp, NULL); 275 DEVFS_UNLOCK(); 276 277 return error; 278} 279 280static int 281devfs_statfs( struct mount *mp, struct vfsstatfs *sbp, __unused vfs_context_t ctx) 282{ 283 struct devfsmount *devfs_mp_p = (struct devfsmount *)mp->mnt_data; 284 285 /*- 286 * Fill in the stat block. 287 */ 288 //sbp->f_type = mp->mnt_vfsstat.f_type; 289 sbp->f_flags = 0; /* XXX */ 290 sbp->f_bsize = 512; 291 sbp->f_iosize = 512; 292 sbp->f_blocks = (devfs_stats.mounts * sizeof(struct devfsmount) 293 + devfs_stats.nodes * sizeof(devnode_t) 294 + devfs_stats.entries * sizeof(devdirent_t) 295 + devfs_stats.stringspace 296 ) / sbp->f_bsize; 297 sbp->f_bfree = 0; 298 sbp->f_bavail = 0; 299 sbp->f_files = devfs_stats.nodes; 300 sbp->f_ffree = 0; 301 sbp->f_fsid.val[0] = (int32_t)(uintptr_t)devfs_mp_p; 302 sbp->f_fsid.val[1] = vfs_typenum(mp); 303 304 return 0; 305} 306 307static int 308devfs_vfs_getattr(__unused mount_t mp, struct vfs_attr *fsap, __unused vfs_context_t ctx) 309{ 310 VFSATTR_RETURN(fsap, f_objcount, devfs_stats.nodes); 311 VFSATTR_RETURN(fsap, f_maxobjcount, devfs_stats.nodes); 312 VFSATTR_RETURN(fsap, f_bsize, 512); 313 VFSATTR_RETURN(fsap, f_iosize, 512); 314 if (VFSATTR_IS_ACTIVE(fsap, f_blocks) || VFSATTR_IS_ACTIVE(fsap, f_bused)) { 315 fsap->f_blocks = (devfs_stats.mounts * sizeof(struct devfsmount) 316 + devfs_stats.nodes * sizeof(devnode_t) 317 + devfs_stats.entries * sizeof(devdirent_t) 318 + devfs_stats.stringspace 319 ) / fsap->f_bsize; 320 fsap->f_bused = fsap->f_blocks; 321 VFSATTR_SET_SUPPORTED(fsap, f_blocks); 322 VFSATTR_SET_SUPPORTED(fsap, f_bused); 323 } 324 VFSATTR_RETURN(fsap, f_bfree, 0); 325 VFSATTR_RETURN(fsap, f_bavail, 0); 326 VFSATTR_RETURN(fsap, f_files, devfs_stats.nodes); 327 VFSATTR_RETURN(fsap, f_ffree, 0); 328 VFSATTR_RETURN(fsap, f_fssubtype, 0); 329 330 if (VFSATTR_IS_ACTIVE(fsap, f_capabilities)) { 331 fsap->f_capabilities.capabilities[VOL_CAPABILITIES_FORMAT] = 332 VOL_CAP_FMT_SYMBOLICLINKS | 333 VOL_CAP_FMT_HARDLINKS | 334 VOL_CAP_FMT_NO_ROOT_TIMES | 335 VOL_CAP_FMT_CASE_SENSITIVE | 336 VOL_CAP_FMT_CASE_PRESERVING | 337 VOL_CAP_FMT_FAST_STATFS | 338 VOL_CAP_FMT_2TB_FILESIZE | 339 VOL_CAP_FMT_HIDDEN_FILES; 340 fsap->f_capabilities.capabilities[VOL_CAPABILITIES_INTERFACES] = 341 VOL_CAP_INT_ATTRLIST ; 342 fsap->f_capabilities.capabilities[VOL_CAPABILITIES_RESERVED1] = 0; 343 fsap->f_capabilities.capabilities[VOL_CAPABILITIES_RESERVED2] = 0; 344 345 fsap->f_capabilities.valid[VOL_CAPABILITIES_FORMAT] = 346 VOL_CAP_FMT_PERSISTENTOBJECTIDS | 347 VOL_CAP_FMT_SYMBOLICLINKS | 348 VOL_CAP_FMT_HARDLINKS | 349 VOL_CAP_FMT_JOURNAL | 350 VOL_CAP_FMT_JOURNAL_ACTIVE | 351 VOL_CAP_FMT_NO_ROOT_TIMES | 352 VOL_CAP_FMT_SPARSE_FILES | 353 VOL_CAP_FMT_ZERO_RUNS | 354 VOL_CAP_FMT_CASE_SENSITIVE | 355 VOL_CAP_FMT_CASE_PRESERVING | 356 VOL_CAP_FMT_FAST_STATFS | 357 VOL_CAP_FMT_2TB_FILESIZE | 358 VOL_CAP_FMT_OPENDENYMODES | 359 VOL_CAP_FMT_HIDDEN_FILES | 360 VOL_CAP_FMT_PATH_FROM_ID | 361 VOL_CAP_FMT_NO_VOLUME_SIZES; 362 fsap->f_capabilities.valid[VOL_CAPABILITIES_INTERFACES] = 363 VOL_CAP_INT_SEARCHFS | 364 VOL_CAP_INT_ATTRLIST | 365 VOL_CAP_INT_NFSEXPORT | 366 VOL_CAP_INT_READDIRATTR | 367 VOL_CAP_INT_EXCHANGEDATA | 368 VOL_CAP_INT_COPYFILE | 369 VOL_CAP_INT_ALLOCATE | 370 VOL_CAP_INT_VOL_RENAME | 371 VOL_CAP_INT_ADVLOCK | 372 VOL_CAP_INT_FLOCK | 373 VOL_CAP_INT_EXTENDED_SECURITY | 374 VOL_CAP_INT_USERACCESS | 375 VOL_CAP_INT_MANLOCK | 376 VOL_CAP_INT_EXTENDED_ATTR | 377 VOL_CAP_INT_NAMEDSTREAMS; 378 fsap->f_capabilities.valid[VOL_CAPABILITIES_RESERVED1] = 0; 379 fsap->f_capabilities.valid[VOL_CAPABILITIES_RESERVED2] = 0; 380 381 VFSATTR_SET_SUPPORTED(fsap, f_capabilities); 382 } 383 384 if (VFSATTR_IS_ACTIVE(fsap, f_attributes)) { 385 fsap->f_attributes.validattr.commonattr = 386 ATTR_CMN_NAME | ATTR_CMN_DEVID | ATTR_CMN_FSID | 387 ATTR_CMN_OBJTYPE | ATTR_CMN_OBJTAG | ATTR_CMN_OBJID | 388 ATTR_CMN_PAROBJID | 389 ATTR_CMN_MODTIME | ATTR_CMN_CHGTIME | ATTR_CMN_ACCTIME | 390 ATTR_CMN_OWNERID | ATTR_CMN_GRPID | ATTR_CMN_ACCESSMASK | 391 ATTR_CMN_FLAGS | ATTR_CMN_USERACCESS | ATTR_CMN_FILEID; 392 fsap->f_attributes.validattr.volattr = 393 ATTR_VOL_FSTYPE | ATTR_VOL_SIZE | ATTR_VOL_SPACEFREE | 394 ATTR_VOL_SPACEAVAIL | ATTR_VOL_MINALLOCATION | 395 ATTR_VOL_OBJCOUNT | ATTR_VOL_MAXOBJCOUNT | 396 ATTR_VOL_MOUNTPOINT | ATTR_VOL_MOUNTFLAGS | 397 ATTR_VOL_MOUNTEDDEVICE | ATTR_VOL_CAPABILITIES | 398 ATTR_VOL_ATTRIBUTES; 399 fsap->f_attributes.validattr.dirattr = 400 ATTR_DIR_LINKCOUNT | ATTR_DIR_MOUNTSTATUS; 401 fsap->f_attributes.validattr.fileattr = 402 ATTR_FILE_LINKCOUNT | ATTR_FILE_TOTALSIZE | 403 ATTR_FILE_IOBLOCKSIZE | ATTR_FILE_DEVTYPE | 404 ATTR_FILE_DATALENGTH; 405 fsap->f_attributes.validattr.forkattr = 0; 406 407 fsap->f_attributes.nativeattr.commonattr = 408 ATTR_CMN_NAME | ATTR_CMN_DEVID | ATTR_CMN_FSID | 409 ATTR_CMN_OBJTYPE | ATTR_CMN_OBJTAG | ATTR_CMN_OBJID | 410 ATTR_CMN_PAROBJID | 411 ATTR_CMN_MODTIME | ATTR_CMN_CHGTIME | ATTR_CMN_ACCTIME | 412 ATTR_CMN_OWNERID | ATTR_CMN_GRPID | ATTR_CMN_ACCESSMASK | 413 ATTR_CMN_FLAGS | ATTR_CMN_USERACCESS | ATTR_CMN_FILEID; 414 fsap->f_attributes.nativeattr.volattr = 415 ATTR_VOL_FSTYPE | ATTR_VOL_SIZE | ATTR_VOL_SPACEFREE | 416 ATTR_VOL_SPACEAVAIL | ATTR_VOL_MINALLOCATION | 417 ATTR_VOL_OBJCOUNT | ATTR_VOL_MAXOBJCOUNT | 418 ATTR_VOL_MOUNTPOINT | ATTR_VOL_MOUNTFLAGS | 419 ATTR_VOL_MOUNTEDDEVICE | ATTR_VOL_CAPABILITIES | 420 ATTR_VOL_ATTRIBUTES; 421 fsap->f_attributes.nativeattr.dirattr = 422 ATTR_DIR_MOUNTSTATUS; 423 fsap->f_attributes.nativeattr.fileattr = 424 ATTR_FILE_LINKCOUNT | ATTR_FILE_TOTALSIZE | 425 ATTR_FILE_IOBLOCKSIZE | ATTR_FILE_DEVTYPE | 426 ATTR_FILE_DATALENGTH; 427 fsap->f_attributes.nativeattr.forkattr = 0; 428 429 VFSATTR_SET_SUPPORTED(fsap, f_attributes); 430 } 431 432 return 0; 433} 434 435static int 436devfs_sync(__unused struct mount *mp, __unused int waitfor, __unused vfs_context_t ctx) 437{ 438 return (0); 439} 440 441 442static int 443devfs_vget(__unused struct mount *mp, __unused ino64_t ino, __unused struct vnode **vpp, __unused vfs_context_t ctx) 444{ 445 return ENOTSUP; 446} 447 448/************************************************************* 449 * The concept of exporting a kernel generated devfs is stupid 450 * So don't handle filehandles 451 */ 452 453static int 454devfs_fhtovp (__unused struct mount *mp, __unused int fhlen, __unused unsigned char *fhp, __unused struct vnode **vpp, __unused vfs_context_t ctx) 455{ 456 return (EINVAL); 457} 458 459 460static int 461devfs_vptofh (__unused struct vnode *vp, __unused int *fhlenp, __unused unsigned char *fhp, __unused vfs_context_t ctx) 462{ 463 return (EINVAL); 464} 465 466static int 467devfs_sysctl(__unused int *name, __unused u_int namelen, __unused user_addr_t oldp, 468 __unused size_t *oldlenp, __unused user_addr_t newp, 469 __unused size_t newlen, __unused vfs_context_t ctx) 470{ 471 return (ENOTSUP); 472} 473 474#include <sys/namei.h> 475 476/* 477 * Function: devfs_kernel_mount 478 * Purpose: 479 * Mount devfs at the given mount point from within the kernel. 480 */ 481int 482devfs_kernel_mount(char * mntname) 483{ 484 struct mount *mp; 485 int error; 486 struct nameidata nd; 487 struct vnode * vp; 488 vfs_context_t ctx = vfs_context_kernel(); 489 struct vfstable *vfsp; 490 491 /* Find our vfstable entry */ 492 for (vfsp = vfsconf; vfsp; vfsp = vfsp->vfc_next) 493 if (!strncmp(vfsp->vfc_name, "devfs", sizeof(vfsp->vfc_name))) 494 break; 495 496 if (!vfsp) { 497 panic("Could not find entry in vfsconf for devfs.\n"); 498 } 499 500 /* 501 * Get vnode to be covered 502 */ 503 NDINIT(&nd, LOOKUP, OP_MOUNT, FOLLOW | LOCKLEAF, UIO_SYSSPACE, 504 CAST_USER_ADDR_T(mntname), ctx); 505 if ((error = namei(&nd))) { 506 printf("devfs_kernel_mount: failed to find directory '%s', %d\n", 507 mntname, error); 508 return (error); 509 } 510 nameidone(&nd); 511 vp = nd.ni_vp; 512 513 if ((error = VNOP_FSYNC(vp, MNT_WAIT, ctx))) { 514 printf("devfs_kernel_mount: vnop_fsync failed: %d\n", error); 515 vnode_put(vp); 516 return (error); 517 } 518 if ((error = buf_invalidateblks(vp, BUF_WRITE_DATA, 0, 0))) { 519 printf("devfs_kernel_mount: buf_invalidateblks failed: %d\n", error); 520 vnode_put(vp); 521 return (error); 522 } 523 if (vnode_isdir(vp) == 0) { 524 printf("devfs_kernel_mount: '%s' is not a directory\n", mntname); 525 vnode_put(vp); 526 return (ENOTDIR); 527 } 528 if ((vnode_mountedhere(vp))) { 529 vnode_put(vp); 530 return (EBUSY); 531 } 532 533 /* 534 * Allocate and initialize the filesystem. 535 */ 536 MALLOC_ZONE(mp, struct mount *, sizeof(struct mount), 537 M_MOUNT, M_WAITOK); 538 bzero((char *)mp, sizeof(struct mount)); 539 540 /* Initialize the default IO constraints */ 541 mp->mnt_maxreadcnt = mp->mnt_maxwritecnt = MAXPHYS; 542 mp->mnt_segreadcnt = mp->mnt_segwritecnt = 32; 543 mp->mnt_ioflags = 0; 544 mp->mnt_realrootvp = NULLVP; 545 mp->mnt_authcache_ttl = CACHED_LOOKUP_RIGHT_TTL; 546 547 mount_lock_init(mp); 548 TAILQ_INIT(&mp->mnt_vnodelist); 549 TAILQ_INIT(&mp->mnt_workerqueue); 550 TAILQ_INIT(&mp->mnt_newvnodes); 551 552 (void)vfs_busy(mp, LK_NOWAIT); 553 mp->mnt_op = &devfs_vfsops; 554 mp->mnt_vtable = vfsp; 555 mp->mnt_flag = 0; 556 mp->mnt_flag |= vfsp->vfc_flags & MNT_VISFLAGMASK; 557 strlcpy(mp->mnt_vfsstat.f_fstypename, vfsp->vfc_name, MFSTYPENAMELEN); 558 vp->v_mountedhere = mp; 559 mp->mnt_vnodecovered = vp; 560 mp->mnt_vfsstat.f_owner = kauth_cred_getuid(kauth_cred_get()); 561 (void) copystr(mntname, mp->mnt_vfsstat.f_mntonname, MAXPATHLEN - 1, 0); 562#if CONFIG_MACF 563 mac_mount_label_init(mp); 564 mac_mount_label_associate(ctx, mp); 565#endif 566 567 error = devfs_mount(mp, NULL, USER_ADDR_NULL, ctx); 568 569 if (error) { 570 printf("devfs_kernel_mount: mount %s failed: %d\n", mntname, error); 571 mp->mnt_vtable->vfc_refcount--; 572 573 vfs_unbusy(mp); 574 575 mount_lock_destroy(mp); 576#if CONFIG_MACF 577 mac_mount_label_destroy(mp); 578#endif 579 FREE_ZONE(mp, sizeof (struct mount), M_MOUNT); 580 vnode_put(vp); 581 return (error); 582 } 583 vnode_ref(vp); 584 vnode_put(vp); 585 vfs_unbusy(mp); 586 mount_list_add(mp); 587 return (0); 588} 589 590struct vfsops devfs_vfsops = { 591 devfs_mount, 592 devfs_start, 593 devfs_unmount, 594 devfs_root, 595 NULL, /* quotactl */ 596 devfs_vfs_getattr, 597 devfs_sync, 598 devfs_vget, 599 devfs_fhtovp, 600 devfs_vptofh, 601 devfs_init, 602 devfs_sysctl, 603 NULL, 604 {NULL} 605}; 606