2 * Copyright (c) 2000-2010 Apple Inc. All rights reserved.
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
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.
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
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.
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
29 * Copyright 1997,1998 Julian Elischer. All rights reserved.
32 * Redistribution and use in source and binary forms, with or without
33 * modification, are permitted provided that the following conditions are
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.
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
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,
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
70 #include <sys/param.h>
71 #include <sys/systm.h>
72 #include <sys/kernel.h>
73 #include <sys/vnode_internal.h>
75 #include <sys/kauth.h>
76 #include <sys/mount_internal.h>
77 #include <sys/malloc.h>
79 #include <libkern/OSAtomic.h>
80 #include <atm/atm_internal.h>
83 #include <security/mac_framework.h>
87 #include "devfsdefs.h"
94 static int devfs_statfs( struct mount
*mp
, struct vfsstatfs
*sbp
, vfs_context_t ctx
);
95 static int devfs_vfs_getattr(mount_t mp
, struct vfs_attr
*fsap
, vfs_context_t ctx
);
98 extern boolean_t dev_kmem_enabled
;
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.
110 devfs_init(__unused
struct vfsconf
*vfsp
)
115 devfs_make_node(makedev(0, 0), DEVFS_CHAR
,
116 UID_ROOT
, GID_WHEEL
, 0622, "console");
117 devfs_make_node(makedev(2, 0), DEVFS_CHAR
,
118 UID_ROOT
, GID_WHEEL
, 0666, "tty");
120 if (dev_kmem_enabled
) {
121 /* (3,0) reserved for /dev/mem physical memory */
122 devfs_make_node(makedev(3, 1), DEVFS_CHAR
,
123 UID_ROOT
, GID_KMEM
, 0640, "kmem");
126 devfs_make_node(makedev(3, 2), DEVFS_CHAR
,
127 UID_ROOT
, GID_WHEEL
, 0666, "null");
128 devfs_make_node(makedev(3, 3), DEVFS_CHAR
,
129 UID_ROOT
, GID_WHEEL
, 0666, "zero");
130 uint32_t logging_config
= atm_get_diagnostic_config();
132 devfs_make_node(makedev(6, 0), DEVFS_CHAR
,
133 UID_ROOT
, GID_WHEEL
, 0600, "klog");
135 if (!(logging_config
& ATM_TRACE_DISABLE
)) {
136 devfs_make_node(makedev(7, 0), DEVFS_CHAR
,
137 UID_ROOT
, GID_WHEEL
, 0600, "oslog");
138 if (cdevsw_setkqueueok(7, (&(cdevsw
[7])), 0) == -1) {
142 devfs_make_node(makedev(8, 0), DEVFS_CHAR
,
143 UID_ROOT
, GID_WHEEL
, 0600, "oslog_stream");
144 if (cdevsw_setkqueueok(8, (&(cdevsw
[8])), 0) == -1) {
158 * mp - pointer to 'mount' structure
159 * path - addr in user space of mount point (ie /usr or whatever)
160 * data - addr in user space of mount params including the
161 * name of the block special file to treat as a filesystem.
163 * ndp - namei data pointer (NOT USED)
165 * devfs is special in that it doesn't require any device to be mounted..
166 * It makes up its data as it goes along.
167 * it must be mounted during single user.. until it is, only std{in/out/err}
168 * and the root filesystem are available.
172 devfs_mount(struct mount
*mp
, __unused vnode_t devvp
, __unused user_addr_t data
, vfs_context_t ctx
)
174 struct devfsmount
*devfs_mp_p
; /* devfs specific mount info */
178 * If they just want to update, we don't need to do anything.
180 if (mp
->mnt_flag
& MNT_UPDATE
) {
184 /* Advisory locking should be handled at the VFS layer */
185 vfs_setlocklocal(mp
);
188 * Well, it's not an update, it's a real mount request.
190 * HERE we should check to see if we are already mounted here.
193 MALLOC(devfs_mp_p
, struct devfsmount
*, sizeof(struct devfsmount
),
194 M_DEVFSMNT
, M_WAITOK
);
195 if (devfs_mp_p
== NULL
) {
198 bzero(devfs_mp_p
, sizeof(*devfs_mp_p
));
199 devfs_mp_p
->mount
= mp
;
202 * Fill out some fields
204 __IGNORE_WCASTALIGN(mp
->mnt_data
= (qaddr_t
)devfs_mp_p
);
205 mp
->mnt_vfsstat
.f_fsid
.val
[0] = (int32_t)VM_KERNEL_ADDRHASH(devfs_mp_p
);
206 mp
->mnt_vfsstat
.f_fsid
.val
[1] = vfs_typenum(mp
);
207 mp
->mnt_flag
|= MNT_LOCAL
;
210 error
= dev_dup_plane(devfs_mp_p
);
214 mp
->mnt_data
= (qaddr_t
)0;
215 FREE(devfs_mp_p
, M_DEVFSMNT
);
222 * Copy in the name of the directory the filesystem
223 * is to be mounted on.
224 * And we clear the remainder of the character strings
228 bzero(mp
->mnt_vfsstat
.f_mntfromname
, MAXPATHLEN
);
229 bcopy("devfs", mp
->mnt_vfsstat
.f_mntfromname
, 5);
230 (void)devfs_statfs(mp
, &mp
->mnt_vfsstat
, ctx
);
237 devfs_start(__unused
struct mount
*mp
, __unused
int flags
, __unused vfs_context_t ctx
)
243 * Unmount the filesystem described by mp.
246 devfs_unmount( struct mount
*mp
, int mntflags
, __unused vfs_context_t ctx
)
248 struct devfsmount
*devfs_mp_p
= (struct devfsmount
*)mp
->mnt_data
;
253 if (mntflags
& MNT_FORCE
) {
257 error
= vflush(mp
, NULLVP
, flags
);
258 if (error
&& !force
) {
263 devfs_free_plane(devfs_mp_p
);
268 FREE(devfs_mp_p
, M_DEVFSMNT
);
269 mp
->mnt_data
= (qaddr_t
)0;
270 mp
->mnt_flag
&= ~MNT_LOCAL
;
275 /* return the address of the root vnode in *vpp */
277 devfs_root(struct mount
*mp
, struct vnode
**vpp
, __unused vfs_context_t ctx
)
279 struct devfsmount
*devfs_mp_p
= (struct devfsmount
*)(mp
->mnt_data
);
283 /* last parameter to devfs_dntovn() is ignored */
284 error
= devfs_dntovn(devfs_mp_p
->plane_root
->de_dnp
, vpp
, NULL
);
291 devfs_statfs( struct mount
*mp
, struct vfsstatfs
*sbp
, __unused vfs_context_t ctx
)
293 struct devfsmount
*devfs_mp_p
= (struct devfsmount
*)mp
->mnt_data
;
296 * Fill in the stat block.
298 //sbp->f_type = mp->mnt_vfsstat.f_type;
299 sbp
->f_flags
= 0; /* XXX */
302 sbp
->f_blocks
= (devfs_stats
.mounts
* sizeof(struct devfsmount
)
303 + devfs_stats
.nodes
* sizeof(devnode_t
)
304 + devfs_stats
.entries
* sizeof(devdirent_t
)
305 + devfs_stats
.stringspace
309 sbp
->f_files
= devfs_stats
.nodes
;
311 sbp
->f_fsid
.val
[0] = (int32_t)VM_KERNEL_ADDRHASH(devfs_mp_p
);
312 sbp
->f_fsid
.val
[1] = vfs_typenum(mp
);
318 devfs_vfs_getattr(__unused mount_t mp
, struct vfs_attr
*fsap
, __unused vfs_context_t ctx
)
320 VFSATTR_RETURN(fsap
, f_objcount
, devfs_stats
.nodes
);
321 VFSATTR_RETURN(fsap
, f_maxobjcount
, devfs_stats
.nodes
);
322 VFSATTR_RETURN(fsap
, f_bsize
, 512);
323 VFSATTR_RETURN(fsap
, f_iosize
, 512);
324 if (VFSATTR_IS_ACTIVE(fsap
, f_blocks
) || VFSATTR_IS_ACTIVE(fsap
, f_bused
)) {
325 fsap
->f_blocks
= (devfs_stats
.mounts
* sizeof(struct devfsmount
)
326 + devfs_stats
.nodes
* sizeof(devnode_t
)
327 + devfs_stats
.entries
* sizeof(devdirent_t
)
328 + devfs_stats
.stringspace
330 fsap
->f_bused
= fsap
->f_blocks
;
331 VFSATTR_SET_SUPPORTED(fsap
, f_blocks
);
332 VFSATTR_SET_SUPPORTED(fsap
, f_bused
);
334 VFSATTR_RETURN(fsap
, f_bfree
, 0);
335 VFSATTR_RETURN(fsap
, f_bavail
, 0);
336 VFSATTR_RETURN(fsap
, f_files
, devfs_stats
.nodes
);
337 VFSATTR_RETURN(fsap
, f_ffree
, 0);
338 VFSATTR_RETURN(fsap
, f_fssubtype
, 0);
340 if (VFSATTR_IS_ACTIVE(fsap
, f_capabilities
)) {
341 fsap
->f_capabilities
.capabilities
[VOL_CAPABILITIES_FORMAT
] =
342 VOL_CAP_FMT_SYMBOLICLINKS
|
343 VOL_CAP_FMT_HARDLINKS
|
344 VOL_CAP_FMT_NO_ROOT_TIMES
|
345 VOL_CAP_FMT_CASE_SENSITIVE
|
346 VOL_CAP_FMT_CASE_PRESERVING
|
347 VOL_CAP_FMT_FAST_STATFS
|
348 VOL_CAP_FMT_2TB_FILESIZE
|
349 VOL_CAP_FMT_HIDDEN_FILES
;
350 fsap
->f_capabilities
.capabilities
[VOL_CAPABILITIES_INTERFACES
] =
351 VOL_CAP_INT_ATTRLIST
;
352 fsap
->f_capabilities
.capabilities
[VOL_CAPABILITIES_RESERVED1
] = 0;
353 fsap
->f_capabilities
.capabilities
[VOL_CAPABILITIES_RESERVED2
] = 0;
355 fsap
->f_capabilities
.valid
[VOL_CAPABILITIES_FORMAT
] =
356 VOL_CAP_FMT_PERSISTENTOBJECTIDS
|
357 VOL_CAP_FMT_SYMBOLICLINKS
|
358 VOL_CAP_FMT_HARDLINKS
|
359 VOL_CAP_FMT_JOURNAL
|
360 VOL_CAP_FMT_JOURNAL_ACTIVE
|
361 VOL_CAP_FMT_NO_ROOT_TIMES
|
362 VOL_CAP_FMT_SPARSE_FILES
|
363 VOL_CAP_FMT_ZERO_RUNS
|
364 VOL_CAP_FMT_CASE_SENSITIVE
|
365 VOL_CAP_FMT_CASE_PRESERVING
|
366 VOL_CAP_FMT_FAST_STATFS
|
367 VOL_CAP_FMT_2TB_FILESIZE
|
368 VOL_CAP_FMT_OPENDENYMODES
|
369 VOL_CAP_FMT_HIDDEN_FILES
|
370 VOL_CAP_FMT_PATH_FROM_ID
|
371 VOL_CAP_FMT_NO_VOLUME_SIZES
;
372 fsap
->f_capabilities
.valid
[VOL_CAPABILITIES_INTERFACES
] =
373 VOL_CAP_INT_SEARCHFS
|
374 VOL_CAP_INT_ATTRLIST
|
375 VOL_CAP_INT_NFSEXPORT
|
376 VOL_CAP_INT_READDIRATTR
|
377 VOL_CAP_INT_EXCHANGEDATA
|
378 VOL_CAP_INT_COPYFILE
|
379 VOL_CAP_INT_ALLOCATE
|
380 VOL_CAP_INT_VOL_RENAME
|
381 VOL_CAP_INT_ADVLOCK
|
383 VOL_CAP_INT_EXTENDED_SECURITY
|
384 VOL_CAP_INT_USERACCESS
|
385 VOL_CAP_INT_MANLOCK
|
386 VOL_CAP_INT_EXTENDED_ATTR
|
387 VOL_CAP_INT_NAMEDSTREAMS
;
388 fsap
->f_capabilities
.valid
[VOL_CAPABILITIES_RESERVED1
] = 0;
389 fsap
->f_capabilities
.valid
[VOL_CAPABILITIES_RESERVED2
] = 0;
391 VFSATTR_SET_SUPPORTED(fsap
, f_capabilities
);
394 if (VFSATTR_IS_ACTIVE(fsap
, f_attributes
)) {
395 fsap
->f_attributes
.validattr
.commonattr
=
396 ATTR_CMN_NAME
| ATTR_CMN_DEVID
| ATTR_CMN_FSID
|
397 ATTR_CMN_OBJTYPE
| ATTR_CMN_OBJTAG
| ATTR_CMN_OBJID
|
399 ATTR_CMN_MODTIME
| ATTR_CMN_CHGTIME
| ATTR_CMN_ACCTIME
|
400 ATTR_CMN_OWNERID
| ATTR_CMN_GRPID
| ATTR_CMN_ACCESSMASK
|
401 ATTR_CMN_FLAGS
| ATTR_CMN_USERACCESS
| ATTR_CMN_FILEID
;
402 fsap
->f_attributes
.validattr
.volattr
=
403 ATTR_VOL_FSTYPE
| ATTR_VOL_SIZE
| ATTR_VOL_SPACEFREE
|
404 ATTR_VOL_SPACEAVAIL
| ATTR_VOL_MINALLOCATION
|
405 ATTR_VOL_OBJCOUNT
| ATTR_VOL_MAXOBJCOUNT
|
406 ATTR_VOL_MOUNTPOINT
| ATTR_VOL_MOUNTFLAGS
|
407 ATTR_VOL_MOUNTEDDEVICE
| ATTR_VOL_CAPABILITIES
|
409 fsap
->f_attributes
.validattr
.dirattr
=
410 ATTR_DIR_LINKCOUNT
| ATTR_DIR_MOUNTSTATUS
;
411 fsap
->f_attributes
.validattr
.fileattr
=
412 ATTR_FILE_LINKCOUNT
| ATTR_FILE_TOTALSIZE
|
413 ATTR_FILE_IOBLOCKSIZE
| ATTR_FILE_DEVTYPE
|
414 ATTR_FILE_DATALENGTH
;
415 fsap
->f_attributes
.validattr
.forkattr
= 0;
417 fsap
->f_attributes
.nativeattr
.commonattr
=
418 ATTR_CMN_NAME
| ATTR_CMN_DEVID
| ATTR_CMN_FSID
|
419 ATTR_CMN_OBJTYPE
| ATTR_CMN_OBJTAG
| ATTR_CMN_OBJID
|
421 ATTR_CMN_MODTIME
| ATTR_CMN_CHGTIME
| ATTR_CMN_ACCTIME
|
422 ATTR_CMN_OWNERID
| ATTR_CMN_GRPID
| ATTR_CMN_ACCESSMASK
|
423 ATTR_CMN_FLAGS
| ATTR_CMN_USERACCESS
| ATTR_CMN_FILEID
;
424 fsap
->f_attributes
.nativeattr
.volattr
=
425 ATTR_VOL_FSTYPE
| ATTR_VOL_SIZE
| ATTR_VOL_SPACEFREE
|
426 ATTR_VOL_SPACEAVAIL
| ATTR_VOL_MINALLOCATION
|
427 ATTR_VOL_OBJCOUNT
| ATTR_VOL_MAXOBJCOUNT
|
428 ATTR_VOL_MOUNTPOINT
| ATTR_VOL_MOUNTFLAGS
|
429 ATTR_VOL_MOUNTEDDEVICE
| ATTR_VOL_CAPABILITIES
|
431 fsap
->f_attributes
.nativeattr
.dirattr
=
432 ATTR_DIR_MOUNTSTATUS
;
433 fsap
->f_attributes
.nativeattr
.fileattr
=
434 ATTR_FILE_LINKCOUNT
| ATTR_FILE_TOTALSIZE
|
435 ATTR_FILE_IOBLOCKSIZE
| ATTR_FILE_DEVTYPE
|
436 ATTR_FILE_DATALENGTH
;
437 fsap
->f_attributes
.nativeattr
.forkattr
= 0;
439 VFSATTR_SET_SUPPORTED(fsap
, f_attributes
);
446 devfs_sync(__unused
struct mount
*mp
, __unused
int waitfor
, __unused vfs_context_t ctx
)
453 devfs_vget(__unused
struct mount
*mp
, __unused ino64_t ino
, __unused
struct vnode
**vpp
, __unused vfs_context_t ctx
)
458 /*************************************************************
459 * The concept of exporting a kernel generated devfs is stupid
460 * So don't handle filehandles
464 devfs_fhtovp(__unused
struct mount
*mp
, __unused
int fhlen
, __unused
unsigned char *fhp
, __unused
struct vnode
**vpp
, __unused vfs_context_t ctx
)
471 devfs_vptofh(__unused
struct vnode
*vp
, __unused
int *fhlenp
, __unused
unsigned char *fhp
, __unused vfs_context_t ctx
)
477 devfs_sysctl(__unused
int *name
, __unused u_int namelen
, __unused user_addr_t oldp
,
478 __unused
size_t *oldlenp
, __unused user_addr_t newp
,
479 __unused
size_t newlen
, __unused vfs_context_t ctx
)
484 #include <sys/namei.h>
487 * Function: devfs_kernel_mount
489 * Mount devfs at the given mount point from within the kernel.
492 devfs_kernel_mount(char * mntname
)
495 vfs_context_t ctx
= vfs_context_kernel();
496 char fsname
[] = "devfs";
498 error
= kernel_mount(fsname
, NULLVP
, NULLVP
, mntname
, NULL
, 0, MNT_DONTBROWSE
, KERNEL_MOUNT_NOAUTH
, ctx
);
500 printf("devfs_kernel_mount: kernel_mount failed: %d\n", error
);
507 const struct vfsops devfs_vfsops
= {
508 .vfs_mount
= devfs_mount
,
509 .vfs_start
= devfs_start
,
510 .vfs_unmount
= devfs_unmount
,
511 .vfs_root
= devfs_root
,
512 .vfs_getattr
= devfs_vfs_getattr
,
513 .vfs_sync
= devfs_sync
,
514 .vfs_vget
= devfs_vget
,
515 .vfs_fhtovp
= devfs_fhtovp
,
516 .vfs_vptofh
= devfs_vptofh
,
517 .vfs_init
= devfs_init
,
518 .vfs_sysctl
= devfs_sysctl
,
519 // There are other VFS ops that we do not support