]>
git.saurik.com Git - apple/xnu.git/blob - bsd/miscfs/devfs/devfs_vfsops.c
2 * Copyright (c) 2000-2002 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved.
8 * This file contains Original Code and/or Modifications of Original Code
9 * as defined in and that are subject to the Apple Public Source License
10 * Version 2.0 (the 'License'). You may not use this file except in
11 * compliance with the License. Please obtain a copy of the License at
12 * http://www.opensource.apple.com/apsl/ and read it before using this
15 * The Original Code and all software distributed under the License are
16 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
17 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
18 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
20 * Please see the License for the specific language governing rights and
21 * limitations under the License.
23 * @APPLE_LICENSE_HEADER_END@
26 * Copyright 1997,1998 Julian Elischer. All rights reserved.
29 * Redistribution and use in source and binary forms, with or without
30 * modification, are permitted provided that the following conditions are
32 * 1. Redistributions of source code must retain the above copyright
33 * notice, this list of conditions and the following disclaimer.
34 * 2. Redistributions in binary form must reproduce the above copyright notice,
35 * this list of conditions and the following disclaimer in the documentation
36 * and/or other materials provided with the distribution.
38 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER ``AS IS'' AND ANY EXPRESS
39 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
40 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
41 * DISCLAIMED. IN NO EVENT SHALL THE HOLDER OR CONTRIBUTORS BE LIABLE FOR
42 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
43 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
44 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
45 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
46 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
47 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
55 * Dieter Siegmund (dieter@apple.com) Wed Jul 14 13:37:59 PDT 1999
56 * - modified devfs_statfs() to use devfs_stats to calculate the
57 * amount of memory used by devfs
61 #include <sys/param.h>
62 #include <sys/systm.h>
63 #include <sys/kernel.h>
64 #include <sys/vnode.h>
66 #include <sys/mount.h>
67 #include <sys/malloc.h>
70 #include "devfsdefs.h"
72 static int devfs_statfs( struct mount
*mp
, struct statfs
*sbp
, struct proc
*p
);
74 static struct vfsconf
* devfs_vfsp
= 0;
75 static int kernel_mount
= 0;
79 * Called from the generic VFS startups.
80 * This is the second stage of DEVFS initialisation.
81 * The probed devices have already been loaded and the
82 * basic structure of the DEVFS created.
83 * We take the oportunity to mount the hidden DEVFS layer, so that
84 * devices from devfs get sync'd.
87 devfs_init(struct vfsconf
*vfsp
)
89 devfs_vfsp
= vfsp
; /* remember this for devfs_kernel_mount below */
93 devfs_make_node(makedev(0, 0), DEVFS_CHAR
,
94 UID_ROOT
, GID_WHEEL
, 0622, "console");
95 devfs_make_node(makedev(2, 0), DEVFS_CHAR
,
96 UID_ROOT
, GID_WHEEL
, 0666, "tty");
97 devfs_make_node(makedev(3, 0), DEVFS_CHAR
,
98 UID_ROOT
, GID_KMEM
, 0640, "mem");
99 devfs_make_node(makedev(3, 1), DEVFS_CHAR
,
100 UID_ROOT
, GID_KMEM
, 0640, "kmem");
101 devfs_make_node(makedev(3, 2), DEVFS_CHAR
,
102 UID_ROOT
, GID_WHEEL
, 0666, "null");
103 devfs_make_node(makedev(3, 3), DEVFS_CHAR
,
104 UID_ROOT
, GID_WHEEL
, 0666, "zero");
105 devfs_make_node(makedev(6, 0), DEVFS_CHAR
,
106 UID_ROOT
, GID_WHEEL
, 0600, "klog");
111 * mp - pointer to 'mount' structure
112 * path - addr in user space of mount point (ie /usr or whatever)
113 * data - addr in user space of mount params including the
114 * name of the block special file to treat as a filesystem.
116 * ndp - namei data pointer (NOT USED)
118 * devfs is special in that it doesn't require any device to be mounted..
119 * It makes up its data as it goes along.
120 * it must be mounted during single user.. until it is, only std{in/out/err}
121 * and the root filesystem are available.
125 devfs_mount(struct mount
*mp
, char *path
, caddr_t data
,
126 struct nameidata
*ndp
, struct proc
*p
)
128 struct devfsmount
*devfs_mp_p
; /* devfs specific mount info */
133 * If they just want to update, we don't need to do anything.
135 if (mp
->mnt_flag
& MNT_UPDATE
)
141 * Well, it's not an update, it's a real mount request.
143 * HERE we should check to see if we are already mounted here.
146 MALLOC(devfs_mp_p
, struct devfsmount
*, sizeof(struct devfsmount
),
147 M_DEVFSMNT
, M_WAITOK
);
148 if (devfs_mp_p
== NULL
)
150 bzero(devfs_mp_p
,sizeof(*devfs_mp_p
));
151 devfs_mp_p
->mount
= mp
;
154 * Fill out some fields
156 mp
->mnt_data
= (qaddr_t
)devfs_mp_p
;
157 mp
->mnt_stat
.f_type
= mp
->mnt_vfc
->vfc_typenum
;
158 mp
->mnt_stat
.f_fsid
.val
[0] = (int32_t)(void *)devfs_mp_p
;
159 mp
->mnt_stat
.f_fsid
.val
[1] = mp
->mnt_stat
.f_type
;
160 mp
->mnt_flag
|= MNT_LOCAL
;
163 error
= dev_dup_plane(devfs_mp_p
);
166 mp
->mnt_data
= (qaddr_t
)0;
167 FREE((caddr_t
)devfs_mp_p
, M_DEVFSMNT
);
172 * Copy in the name of the directory the filesystem
173 * is to be mounted on.
174 * And we clear the remainder of the character strings
179 copyinstr(path
, (caddr_t
)mp
->mnt_stat
.f_mntonname
,
180 sizeof(mp
->mnt_stat
.f_mntonname
)-1, &size
);
181 bzero(mp
->mnt_stat
.f_mntonname
+ size
,
182 sizeof(mp
->mnt_stat
.f_mntonname
) - size
);
184 bzero(mp
->mnt_stat
.f_mntfromname
, MNAMELEN
);
185 bcopy("devfs",mp
->mnt_stat
.f_mntfromname
, 5);
187 (void)devfs_statfs(mp
, &mp
->mnt_stat
, p
);
193 devfs_start(struct mount
*mp
, int flags
, struct proc
*p
)
199 * Unmount the filesystem described by mp.
202 devfs_unmount( struct mount
*mp
, int mntflags
, struct proc
*p
)
204 struct devfsmount
*devfs_mp_p
= (struct devfsmount
*)mp
->mnt_data
;
209 if (mntflags
& MNT_FORCE
) {
213 error
= vflush(mp
, NULLVP
, flags
);
218 devfs_free_plane(devfs_mp_p
);
220 FREE((caddr_t
)devfs_mp_p
, M_DEVFSMNT
);
222 mp
->mnt_data
= (qaddr_t
)0;
223 mp
->mnt_flag
&= ~MNT_LOCAL
;
228 /* return the address of the root vnode in *vpp */
230 devfs_root(struct mount
*mp
, struct vnode
**vpp
)
232 struct devfsmount
*devfs_mp_p
= (struct devfsmount
*)(mp
->mnt_data
);
235 error
= devfs_dntovn(devfs_mp_p
->plane_root
->de_dnp
,vpp
,
241 devfs_quotactl(struct mount
*mp
, int cmds
, uid_t uid
, caddr_t arg
,
248 devfs_statfs( struct mount
*mp
, struct statfs
*sbp
, struct proc
*p
)
250 struct devfsmount
*devfs_mp_p
= (struct devfsmount
*)mp
->mnt_data
;
253 * Fill in the stat block.
255 sbp
->f_type
= mp
->mnt_stat
.f_type
;
256 sbp
->f_flags
= 0; /* XXX */
259 sbp
->f_blocks
= (devfs_stats
.mounts
* sizeof(struct devfsmount
)
260 + devfs_stats
.nodes
* sizeof(devnode_t
)
261 + devfs_stats
.entries
* sizeof(devdirent_t
)
262 + devfs_stats
.stringspace
266 sbp
->f_files
= devfs_stats
.nodes
;
268 sbp
->f_fsid
.val
[0] = (int32_t)(void *)devfs_mp_p
;
269 sbp
->f_fsid
.val
[1] = mp
->mnt_stat
.f_type
;
272 * Copy the mounted on and mounted from names into
273 * the passed in stat block, if it is not the one
274 * in the mount structure.
276 if (sbp
!= &mp
->mnt_stat
) {
277 bcopy((caddr_t
)mp
->mnt_stat
.f_mntonname
,
278 (caddr_t
)&sbp
->f_mntonname
[0], MNAMELEN
);
279 bcopy((caddr_t
)mp
->mnt_stat
.f_mntfromname
,
280 (caddr_t
)&sbp
->f_mntfromname
[0], MNAMELEN
);
286 devfs_sync(struct mount
*mp
, int waitfor
,struct ucred
*cred
,struct proc
*p
)
293 devfs_vget(struct mount
*mp
, void * ino
,struct vnode
**vpp
)
298 /*************************************************************
299 * The concept of exporting a kernel generated devfs is stupid
300 * So don't handle filehandles
304 devfs_fhtovp (struct mount
*mp
, struct fid
*fhp
, struct mbuf
*nam
,
305 struct vnode
**vpp
, int *exflagsp
, struct ucred
**credanonp
)
312 devfs_vptofh (struct vnode
*vp
, struct fid
*fhp
)
318 devfs_sysctl(name
, namelen
, oldp
, oldlenp
, newp
, newlen
, p
)
330 #include <sys/namei.h>
333 * Function: devfs_kernel_mount
335 * Mount devfs at the given mount point from within the kernel.
338 devfs_kernel_mount(char * mntname
)
346 if (devfs_vfsp
== NULL
) {
347 printf("devfs_kernel_mount: devfs_vfsp is NULL\n");
350 procp
= current_proc();
353 * Get vnode to be covered
355 NDINIT(&nd
, LOOKUP
, FOLLOW
| LOCKLEAF
, UIO_SYSSPACE
,
357 if ((error
= namei(&nd
))) {
358 printf("devfs_kernel_mount: failed to find directory '%s', %d",
363 if ((error
= vinvalbuf(vp
, V_SAVE
, procp
->p_ucred
, procp
, 0, 0))) {
364 printf("devfs_kernel_mount: vinval failed: %d\n", error
);
368 if (vp
->v_type
!= VDIR
) {
369 printf("devfs_kernel_mount: '%s' is not a directory\n", mntname
);
373 if (vp
->v_mountedhere
!= NULL
) {
379 * Allocate and initialize the filesystem.
381 MALLOC_ZONE(mp
, struct mount
*, (u_long
)sizeof(struct mount
),
383 bzero((char *)mp
, (u_long
)sizeof(struct mount
));
385 /* Initialize the default IO constraints */
386 mp
->mnt_maxreadcnt
= mp
->mnt_maxwritecnt
= MAXPHYS
;
387 mp
->mnt_segreadcnt
= mp
->mnt_segwritecnt
= 32;
389 lockinit(&mp
->mnt_lock
, PVFS
, "vfslock", 0, 0);
390 (void)vfs_busy(mp
, LK_NOWAIT
, 0, procp
);
391 LIST_INIT(&mp
->mnt_vnodelist
);
392 mp
->mnt_op
= devfs_vfsp
->vfc_vfsops
;
393 mp
->mnt_vfc
= devfs_vfsp
;
394 devfs_vfsp
->vfc_refcount
++;
396 mp
->mnt_flag
|= devfs_vfsp
->vfc_flags
& MNT_VISFLAGMASK
;
397 strncpy(mp
->mnt_stat
.f_fstypename
, devfs_vfsp
->vfc_name
, MFSNAMELEN
);
398 vp
->v_mountedhere
= mp
;
399 mp
->mnt_vnodecovered
= vp
;
400 mp
->mnt_stat
.f_owner
= procp
->p_ucred
->cr_uid
;
401 (void) copystr(mntname
, mp
->mnt_stat
.f_mntonname
, MNAMELEN
- 1, 0);
404 error
= devfs_mount(mp
, mntname
, NULL
, NULL
, procp
);
407 printf("devfs_kernel_mount: mount %s failed: %d", mntname
, error
);
408 mp
->mnt_vfc
->vfc_refcount
--;
410 if (mp
->mnt_kern_flag
& MNTK_IO_XINFO
)
411 FREE(mp
->mnt_xinfo_ptr
, M_TEMP
);
412 vfs_unbusy(mp
, procp
);
414 FREE_ZONE(mp
, sizeof (struct mount
), M_MOUNT
);
418 simple_lock(&mountlist_slock
);
419 CIRCLEQ_INSERT_TAIL(&mountlist
, mp
, mnt_list
);
420 simple_unlock(&mountlist_slock
);
421 VOP_UNLOCK(vp
, 0, procp
);
422 vfs_unbusy(mp
, procp
);
426 struct vfsops devfs_vfsops
= {