2 * Copyright (c) 2000-2004 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_OSREFERENCE_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
10 * License may not be used to create, or enable the creation or
11 * redistribution of, unlawful or unlicensed copies of an Apple operating
12 * system, or to circumvent, violate, or enable the circumvention or
13 * violation of, any terms of an Apple operating system software license
16 * Please obtain a copy of the License at
17 * http://www.opensource.apple.com/apsl/ and read it before using this
20 * The Original Code and all software distributed under the License are
21 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
22 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
23 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
24 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
25 * Please see the License for the specific language governing rights and
26 * limitations under the License.
28 * @APPLE_LICENSE_OSREFERENCE_HEADER_END@
31 * Copyright 1997,1998 Julian Elischer. All rights reserved.
34 * Redistribution and use in source and binary forms, with or without
35 * modification, are permitted provided that the following conditions are
37 * 1. Redistributions of source code must retain the above copyright
38 * notice, this list of conditions and the following disclaimer.
39 * 2. Redistributions in binary form must reproduce the above copyright notice,
40 * this list of conditions and the following disclaimer in the documentation
41 * and/or other materials provided with the distribution.
43 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER ``AS IS'' AND ANY EXPRESS
44 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
45 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
46 * DISCLAIMED. IN NO EVENT SHALL THE HOLDER OR CONTRIBUTORS BE LIABLE FOR
47 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
48 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
49 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
50 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
51 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
52 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
60 * Dieter Siegmund (dieter@apple.com) Wed Jul 14 13:37:59 PDT 1999
61 * - modified devfs_statfs() to use devfs_stats to calculate the
62 * amount of memory used by devfs
66 #include <sys/param.h>
67 #include <sys/systm.h>
68 #include <sys/kernel.h>
69 #include <sys/vnode_internal.h>
71 #include <sys/kauth.h>
72 #include <sys/mount_internal.h>
73 #include <sys/malloc.h>
76 #include "devfsdefs.h"
78 static int devfs_statfs( struct mount
*mp
, struct vfsstatfs
*sbp
, vfs_context_t context
);
79 static int devfs_vfs_getattr(mount_t mp
, struct vfs_attr
*fsap
, vfs_context_t context
);
81 static struct vfstable
* devfs_vfsp
= 0;
82 extern int setup_kmem
;
86 * Called from the generic VFS startups.
87 * This is the second stage of DEVFS initialisation.
88 * The probed devices have already been loaded and the
89 * basic structure of the DEVFS created.
90 * We take the oportunity to mount the hidden DEVFS layer, so that
91 * devices from devfs get sync'd.
94 devfs_init(struct vfsconf
*vfsp
)
96 devfs_vfsp
= (struct vfstable
*)vfsp
; /* remember this for devfs_kernel_mount below */
100 devfs_make_node(makedev(0, 0), DEVFS_CHAR
,
101 UID_ROOT
, GID_WHEEL
, 0622, "console");
102 devfs_make_node(makedev(2, 0), DEVFS_CHAR
,
103 UID_ROOT
, GID_WHEEL
, 0666, "tty");
107 devfs_make_node(makedev(3, 2), DEVFS_CHAR
,
108 UID_ROOT
, GID_WHEEL
, 0666, "null");
109 devfs_make_node(makedev(3, 3), DEVFS_CHAR
,
110 UID_ROOT
, GID_WHEEL
, 0666, "zero");
111 devfs_make_node(makedev(6, 0), DEVFS_CHAR
,
112 UID_ROOT
, GID_WHEEL
, 0600, "klog");
116 __private_extern__
void
117 devfs_setup_kmem(void)
119 devfs_make_node(makedev(3, 0), DEVFS_CHAR
,
120 UID_ROOT
, GID_KMEM
, 0640, "mem");
121 devfs_make_node(makedev(3, 1), DEVFS_CHAR
,
122 UID_ROOT
, GID_KMEM
, 0640, "kmem");
127 * mp - pointer to 'mount' structure
128 * path - addr in user space of mount point (ie /usr or whatever)
129 * data - addr in user space of mount params including the
130 * name of the block special file to treat as a filesystem.
132 * ndp - namei data pointer (NOT USED)
134 * devfs is special in that it doesn't require any device to be mounted..
135 * It makes up its data as it goes along.
136 * it must be mounted during single user.. until it is, only std{in/out/err}
137 * and the root filesystem are available.
141 devfs_mount(struct mount
*mp
, __unused vnode_t devvp
, __unused user_addr_t data
, vfs_context_t context
)
143 struct devfsmount
*devfs_mp_p
; /* devfs specific mount info */
147 * If they just want to update, we don't need to do anything.
149 if (mp
->mnt_flag
& MNT_UPDATE
)
154 /* Advisory locking should be handled at the VFS layer */
155 vfs_setlocklocal(mp
);
158 * Well, it's not an update, it's a real mount request.
160 * HERE we should check to see if we are already mounted here.
163 MALLOC(devfs_mp_p
, struct devfsmount
*, sizeof(struct devfsmount
),
164 M_DEVFSMNT
, M_WAITOK
);
165 if (devfs_mp_p
== NULL
)
167 bzero(devfs_mp_p
,sizeof(*devfs_mp_p
));
168 devfs_mp_p
->mount
= mp
;
171 * Fill out some fields
173 mp
->mnt_data
= (qaddr_t
)devfs_mp_p
;
174 mp
->mnt_vfsstat
.f_fsid
.val
[0] = (int32_t)(void *)devfs_mp_p
;
175 mp
->mnt_vfsstat
.f_fsid
.val
[1] = vfs_typenum(mp
);
176 mp
->mnt_flag
|= MNT_LOCAL
;
179 error
= dev_dup_plane(devfs_mp_p
);
183 mp
->mnt_data
= (qaddr_t
)0;
184 FREE((caddr_t
)devfs_mp_p
, M_DEVFSMNT
);
190 * Copy in the name of the directory the filesystem
191 * is to be mounted on.
192 * And we clear the remainder of the character strings
196 bzero(mp
->mnt_vfsstat
.f_mntfromname
, MAXPATHLEN
);
197 bcopy("devfs",mp
->mnt_vfsstat
.f_mntfromname
, 5);
198 (void)devfs_statfs(mp
, &mp
->mnt_vfsstat
, context
);
205 devfs_start(__unused
struct mount
*mp
, __unused
int flags
, __unused vfs_context_t context
)
211 * Unmount the filesystem described by mp.
214 devfs_unmount( struct mount
*mp
, int mntflags
, __unused vfs_context_t context
)
216 struct devfsmount
*devfs_mp_p
= (struct devfsmount
*)mp
->mnt_data
;
221 if (mntflags
& MNT_FORCE
) {
225 error
= vflush(mp
, NULLVP
, flags
);
230 devfs_free_plane(devfs_mp_p
);
235 FREE((caddr_t
)devfs_mp_p
, M_DEVFSMNT
);
236 mp
->mnt_data
= (qaddr_t
)0;
237 mp
->mnt_flag
&= ~MNT_LOCAL
;
242 /* return the address of the root vnode in *vpp */
244 devfs_root(struct mount
*mp
, struct vnode
**vpp
, vfs_context_t context
)
246 struct devfsmount
*devfs_mp_p
= (struct devfsmount
*)(mp
->mnt_data
);
250 error
= devfs_dntovn(devfs_mp_p
->plane_root
->de_dnp
, vpp
, context
->vc_proc
);
257 devfs_statfs( struct mount
*mp
, struct vfsstatfs
*sbp
, __unused vfs_context_t context
)
259 struct devfsmount
*devfs_mp_p
= (struct devfsmount
*)mp
->mnt_data
;
262 * Fill in the stat block.
264 //sbp->f_type = mp->mnt_vfsstat.f_type;
265 sbp
->f_flags
= 0; /* XXX */
268 sbp
->f_blocks
= (devfs_stats
.mounts
* sizeof(struct devfsmount
)
269 + devfs_stats
.nodes
* sizeof(devnode_t
)
270 + devfs_stats
.entries
* sizeof(devdirent_t
)
271 + devfs_stats
.stringspace
275 sbp
->f_files
= devfs_stats
.nodes
;
277 sbp
->f_fsid
.val
[0] = (int32_t)(void *)devfs_mp_p
;
278 sbp
->f_fsid
.val
[1] = vfs_typenum(mp
);
284 devfs_vfs_getattr(mount_t mp
, struct vfs_attr
*fsap
, vfs_context_t context
)
286 VFSATTR_RETURN(fsap
, f_objcount
, devfs_stats
.nodes
);
287 VFSATTR_RETURN(fsap
, f_maxobjcount
, devfs_stats
.nodes
);
288 VFSATTR_RETURN(fsap
, f_bsize
, 512);
289 VFSATTR_RETURN(fsap
, f_iosize
, 512);
290 if (VFSATTR_IS_ACTIVE(fsap
, f_blocks
) || VFSATTR_IS_ACTIVE(fsap
, f_bused
)) {
291 fsap
->f_blocks
= (devfs_stats
.mounts
* sizeof(struct devfsmount
)
292 + devfs_stats
.nodes
* sizeof(devnode_t
)
293 + devfs_stats
.entries
* sizeof(devdirent_t
)
294 + devfs_stats
.stringspace
296 fsap
->f_bused
= fsap
->f_blocks
;
297 VFSATTR_SET_SUPPORTED(fsap
, f_blocks
);
298 VFSATTR_SET_SUPPORTED(fsap
, f_bused
);
300 VFSATTR_RETURN(fsap
, f_bfree
, 0);
301 VFSATTR_RETURN(fsap
, f_bavail
, 0);
302 VFSATTR_RETURN(fsap
, f_files
, devfs_stats
.nodes
);
303 VFSATTR_RETURN(fsap
, f_ffree
, 0);
304 VFSATTR_RETURN(fsap
, f_fssubtype
, 0);
310 devfs_sync(__unused
struct mount
*mp
, __unused
int waitfor
, __unused vfs_context_t context
)
317 devfs_vget(__unused
struct mount
*mp
, __unused ino64_t ino
, __unused
struct vnode
**vpp
, __unused vfs_context_t context
)
322 /*************************************************************
323 * The concept of exporting a kernel generated devfs is stupid
324 * So don't handle filehandles
328 devfs_fhtovp (__unused
struct mount
*mp
, __unused
int fhlen
, __unused
unsigned char *fhp
, __unused
struct vnode
**vpp
, __unused vfs_context_t context
)
335 devfs_vptofh (__unused
struct vnode
*vp
, __unused
int *fhlenp
, __unused
unsigned char *fhp
, __unused vfs_context_t context
)
341 devfs_sysctl(__unused
int *name
, __unused u_int namelen
, __unused user_addr_t oldp
,
342 __unused
size_t *oldlenp
, __unused user_addr_t newp
,
343 __unused
size_t newlen
, __unused vfs_context_t context
)
348 #include <sys/namei.h>
351 * Function: devfs_kernel_mount
353 * Mount devfs at the given mount point from within the kernel.
356 devfs_kernel_mount(char * mntname
)
362 struct vfs_context context
;
364 if (devfs_vfsp
== NULL
) {
365 printf("devfs_kernel_mount: devfs_vfsp is NULL\n");
368 context
.vc_proc
= current_proc();
369 context
.vc_ucred
= kauth_cred_get();
372 * Get vnode to be covered
374 NDINIT(&nd
, LOOKUP
, FOLLOW
| LOCKLEAF
, UIO_SYSSPACE32
,
375 CAST_USER_ADDR_T(mntname
), &context
);
376 if ((error
= namei(&nd
))) {
377 printf("devfs_kernel_mount: failed to find directory '%s', %d",
384 if ((error
= VNOP_FSYNC(vp
, MNT_WAIT
, &context
))) {
385 printf("devfs_kernel_mount: vnop_fsync failed: %d\n", error
);
389 if ((error
= buf_invalidateblks(vp
, BUF_WRITE_DATA
, 0, 0))) {
390 printf("devfs_kernel_mount: buf_invalidateblks failed: %d\n", error
);
394 if (vnode_isdir(vp
) == 0) {
395 printf("devfs_kernel_mount: '%s' is not a directory\n", mntname
);
399 if ((vnode_mountedhere(vp
))) {
405 * Allocate and initialize the filesystem.
407 MALLOC_ZONE(mp
, struct mount
*, (u_long
)sizeof(struct mount
),
409 bzero((char *)mp
, (u_long
)sizeof(struct mount
));
411 /* Initialize the default IO constraints */
412 mp
->mnt_maxreadcnt
= mp
->mnt_maxwritecnt
= MAXPHYS
;
413 mp
->mnt_segreadcnt
= mp
->mnt_segwritecnt
= 32;
416 TAILQ_INIT(&mp
->mnt_vnodelist
);
417 TAILQ_INIT(&mp
->mnt_workerqueue
);
418 TAILQ_INIT(&mp
->mnt_newvnodes
);
420 (void)vfs_busy(mp
, LK_NOWAIT
);
421 mp
->mnt_op
= devfs_vfsp
->vfc_vfsops
;
422 mp
->mnt_vtable
= devfs_vfsp
;
423 devfs_vfsp
->vfc_refcount
++;
424 devfs_vfsp
->vfc_threadsafe
= TRUE
;
425 devfs_vfsp
->vfc_64bitready
= TRUE
;
427 mp
->mnt_flag
|= devfs_vfsp
->vfc_flags
& MNT_VISFLAGMASK
;
428 strncpy(mp
->mnt_vfsstat
.f_fstypename
, devfs_vfsp
->vfc_name
, MFSTYPENAMELEN
);
429 vp
->v_mountedhere
= mp
;
430 mp
->mnt_vnodecovered
= vp
;
431 mp
->mnt_vfsstat
.f_owner
= kauth_cred_getuid(kauth_cred_get());
432 (void) copystr(mntname
, mp
->mnt_vfsstat
.f_mntonname
, MAXPATHLEN
- 1, 0);
434 error
= devfs_mount(mp
, NULL
, NULL
, &context
);
437 printf("devfs_kernel_mount: mount %s failed: %d", mntname
, error
);
438 mp
->mnt_vtable
->vfc_refcount
--;
442 mount_lock_destroy(mp
);
443 FREE_ZONE(mp
, sizeof (struct mount
), M_MOUNT
);
454 struct vfsops devfs_vfsops
= {