]>
git.saurik.com Git - apple/xnu.git/blob - bsd/ufs/mfs/mfs_vfsops.c
2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * The contents of this file constitute Original Code as defined in and
7 * are subject to the Apple Public Source License Version 1.1 (the
8 * "License"). You may not use this file except in compliance with the
9 * License. Please obtain a copy of the License at
10 * http://www.apple.com/publicsource and read it before using this file.
12 * This Original Code and all software distributed under the License are
13 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
17 * License for the specific language governing rights and limitations
20 * @APPLE_LICENSE_HEADER_END@
22 /* Copyright (c) 1995 NeXT Computer, Inc. All Rights Reserved */
24 * Copyright (c) 1989, 1990, 1993, 1994
25 * The Regents of the University of California. All rights reserved.
27 * Redistribution and use in source and binary forms, with or without
28 * modification, are permitted provided that the following conditions
30 * 1. Redistributions of source code must retain the above copyright
31 * notice, this list of conditions and the following disclaimer.
32 * 2. Redistributions in binary form must reproduce the above copyright
33 * notice, this list of conditions and the following disclaimer in the
34 * documentation and/or other materials provided with the distribution.
35 * 3. All advertising materials mentioning features or use of this software
36 * must display the following acknowledgement:
37 * This product includes software developed by the University of
38 * California, Berkeley and its contributors.
39 * 4. Neither the name of the University nor the names of its contributors
40 * may be used to endorse or promote products derived from this software
41 * without specific prior written permission.
43 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
44 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
45 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
46 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
47 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
48 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
49 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
50 * HOWEVER 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
55 * @(#)mfs_vfsops.c 8.4 (Berkeley) 4/16/94
58 #include <sys/param.h>
59 #include <sys/systm.h>
61 #include <sys/kernel.h>
64 #include <sys/mount.h>
65 #include <sys/signalvar.h>
66 #include <sys/vnode.h>
67 #include <sys/malloc.h>
69 #include <ufs/ufs/quota.h>
70 #include <ufs/ufs/inode.h>
71 #include <ufs/ufs/ufsmount.h>
72 #include <ufs/ufs/ufs_extern.h>
74 #include <ufs/ffs/fs.h>
75 #include <ufs/ffs/ffs_extern.h>
77 #include <ufs/mfs/mfsnode.h>
78 #include <ufs/mfs/mfs_extern.h>
80 caddr_t mfs_rootbase
; /* address of mini-root in kernel virtual memory */
81 u_long mfs_rootsize
; /* size of mini-root in bytes */
83 static int mfs_minor
; /* used for building internal dev_t */
85 extern int (**mfs_vnodeop_p
)(void *);
90 struct vfsops mfs_vfsops
= {
106 * Called by main() when mfs is going to be mounted as root.
108 * Name is updated by mount(8) after booting.
110 #define ROOTNAME "mfs_root"
114 extern struct vnode
*rootvp
;
115 register struct fs
*fs
;
116 register struct mount
*mp
;
117 struct proc
*p
= kernel_proc
; /* XXX - WMG*/
118 struct ufsmount
*ump
;
119 struct mfsnode
*mfsp
;
124 * Get vnodes for swapdev and rootdev.
127 if (bdevvp(swapdev
, &swapdev_vp
) || bdevvp(rootdev
, &rootvp
))
128 panic("mfs_mountroot: can't setup bdevvp's");
130 if ( bdevvp(rootdev
, &rootvp
))
131 panic("mfs_mountroot: can't setup bdevvp's");
134 MALLOC_ZONE(mp
, struct mount
*,
135 sizeof(struct mount
), M_MOUNT
, M_WAITOK
);
136 bzero((char *)mp
, (u_long
)sizeof(struct mount
));
137 mp
->mnt_op
= &mfs_vfsops
;
138 mp
->mnt_flag
= MNT_RDONLY
;
139 MALLOC(mfsp
, struct mfsnode
*, sizeof(struct mfsnode
), M_MFSNODE
, M_WAITOK
);
140 rootvp
->v_data
= mfsp
;
141 rootvp
->v_op
= mfs_vnodeop_p
;
142 rootvp
->v_tag
= VT_MFS
;
143 mfsp
->mfs_baseoff
= mfs_rootbase
;
144 mfsp
->mfs_size
= mfs_rootsize
;
145 mfsp
->mfs_vnode
= rootvp
;
146 mfsp
->mfs_pid
= p
->p_pid
;
147 mfsp
->mfs_buflist
= (struct buf
*)0;
148 if (error
= ffs_mountfs(rootvp
, mp
, p
)) {
149 _FREE_ZONE(mp
, sizeof (struct mount
), M_MOUNT
);
150 _FREE(mfsp
, M_MFSNODE
);
153 if (error
= vfs_lock(mp
)) {
154 (void)ffs_unmount(mp
, 0, p
);
155 _FREE_ZONE(mp
, sizeof (struct mount
), M_MOUNT
);
156 _FREE(mfsp
, M_MFSNODE
);
159 CIRCLEQ_INSERT_TAIL(&mountlist
, mp
, mnt_list
);
160 mp
->mnt_vnodecovered
= NULLVP
;
163 bzero(fs
->fs_fsmnt
, sizeof(fs
->fs_fsmnt
));
164 fs
->fs_fsmnt
[0] = '/';
165 bcopy(fs
->fs_fsmnt
, mp
->mnt_stat
.f_mntonname
, MNAMELEN
);
166 (void) copystr(ROOTNAME
, mp
->mnt_stat
.f_mntfromname
, MNAMELEN
- 1,
168 bzero(mp
->mnt_stat
.f_mntfromname
+ size
, MNAMELEN
- size
);
169 (void)ffs_statfs(mp
, &mp
->mnt_stat
, p
);
176 * This is called early in boot to set the base address and size
179 mfs_initminiroot(base
)
182 struct fs
*fs
= (struct fs
*)(base
+ SBOFF
);
183 extern int (*mountroot
)();
185 /* check for valid super block */
186 if (fs
->fs_magic
!= FS_MAGIC
|| fs
->fs_bsize
> MAXBSIZE
||
187 fs
->fs_bsize
< sizeof(struct fs
))
189 mountroot
= mfs_mountroot
;
191 mfs_rootsize
= fs
->fs_fsize
* fs
->fs_size
;
192 rootdev
= makedev(255, mfs_minor
++);
193 return (mfs_rootsize
);
203 mfs_mount(mp
, path
, data
, ndp
, p
)
204 register struct mount
*mp
;
207 struct nameidata
*ndp
;
211 struct mfs_args args
;
212 struct ufsmount
*ump
;
213 register struct fs
*fs
;
214 register struct mfsnode
*mfsp
;
218 if (error
= copyin(data
, (caddr_t
)&args
, sizeof (struct mfs_args
)))
222 * If updating, check whether changing from read-only to
223 * read/write; if there is no device name, that's all we do.
225 if (mp
->mnt_flag
& MNT_UPDATE
) {
228 if (fs
->fs_ronly
== 0 && (mp
->mnt_flag
& MNT_RDONLY
)) {
230 if (mp
->mnt_flag
& MNT_FORCE
)
234 error
= ffs_flushfiles(mp
, flags
, p
);
239 if (fs
->fs_ronly
&& (mp
->mnt_kern_flag
& MNTK_WANTRDWR
))
243 return (vfs_export(mp
, &ump
->um_export
, &args
.export
));
247 MALLOC(mfsp
, struct mfsnode
*, sizeof(struct mfsnode
), M_MFSNODE
, M_WAITOK
);
248 error
= getnewvnode(VT_MFS
, (struct mount
*)0, mfs_vnodeop_p
, &devvp
);
250 FREE(mfsp
, M_MFSNODE
);
253 devvp
->v_type
= VBLK
;
254 if (checkalias(devvp
, makedev(255, mfs_minor
++), (struct mount
*)0))
255 panic("mfs_mount: dup dev");
256 devvp
->v_data
= mfsp
;
257 mfsp
->mfs_baseoff
= args
.base
;
258 mfsp
->mfs_size
= args
.size
;
259 mfsp
->mfs_vnode
= devvp
;
260 mfsp
->mfs_pid
= p
->p_pid
;
261 mfsp
->mfs_buflist
= (struct buf
*)0;
262 if (error
= ffs_mountfs(devvp
, mp
, p
)) {
263 mfsp
->mfs_buflist
= (struct buf
*)-1;
269 (void) copyinstr(path
, fs
->fs_fsmnt
, sizeof(fs
->fs_fsmnt
) - 1, &size
);
270 bzero(fs
->fs_fsmnt
+ size
, sizeof(fs
->fs_fsmnt
) - size
);
271 bcopy(fs
->fs_fsmnt
, mp
->mnt_stat
.f_mntonname
, MNAMELEN
);
272 (void) copyinstr(args
.fspec
, mp
->mnt_stat
.f_mntfromname
, MNAMELEN
- 1,
274 bzero(mp
->mnt_stat
.f_mntfromname
+ size
, MNAMELEN
- size
);
278 int mfs_pri
= PWAIT
| PCATCH
; /* XXX prob. temp */
281 * Used to grab the process and keep it in the kernel to service
282 * memory filesystem I/O requests.
284 * Loop servicing I/O requests.
285 * Copy the requested data into or out of the memory filesystem
290 mfs_start(mp
, flags
, p
)
295 register struct vnode
*vp
= VFSTOUFS(mp
)->um_devvp
;
296 register struct mfsnode
*mfsp
= VTOMFS(vp
);
297 register struct buf
*bp
;
298 register caddr_t base
;
301 base
= mfsp
->mfs_baseoff
;
302 while (mfsp
->mfs_buflist
!= (struct buf
*)(-1)) {
303 while (bp
= mfsp
->mfs_buflist
) {
304 mfsp
->mfs_buflist
= bp
->b_actf
;
309 * If a non-ignored signal is received, try to unmount.
310 * If that fails, clear the signal (it has been "processed"),
311 * otherwise we will loop here, as tsleep will always return
314 if (error
= tsleep((caddr_t
)vp
, mfs_pri
, "mfsidl", 0))
315 if (dounmount(mp
, 0, p
) != 0)
316 CLRSIG(p
, CURSIG(p
));
322 * Get file system statistics.
324 mfs_statfs(mp
, sbp
, p
)
331 error
= ffs_statfs(mp
, sbp
, p
);
337 strncpy(&sbp
->f_fstypename
[0], mp
->mnt_op
->vfs_name
, MFSNAMELEN
);
338 sbp
->f_fstypename
[MFSNAMELEN
] = '\0';