]> git.saurik.com Git - apple/xnu.git/blob - bsd/ufs/mfs/mfs_vnops.c
81e4dad8a6f6374e8c8adc67d3a94457388e2ccb
[apple/xnu.git] / bsd / ufs / mfs / mfs_vnops.c
1 /*
2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved.
7 *
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
13 * file.
14 *
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.
22 *
23 * @APPLE_LICENSE_HEADER_END@
24 */
25 /* $NetBSD: mfs_vnops.c,v 1.5 1994/12/14 13:03:52 mycroft Exp $ */
26
27 /*
28 * Copyright (c) 1989, 1993
29 * The Regents of the University of California. All rights reserved.
30 *
31 * Redistribution and use in source and binary forms, with or without
32 * modification, are permitted provided that the following conditions
33 * are met:
34 * 1. Redistributions of source code must retain the above copyright
35 * notice, this list of conditions and the following disclaimer.
36 * 2. Redistributions in binary form must reproduce the above copyright
37 * notice, this list of conditions and the following disclaimer in the
38 * documentation and/or other materials provided with the distribution.
39 * 3. All advertising materials mentioning features or use of this software
40 * must display the following acknowledgement:
41 * This product includes software developed by the University of
42 * California, Berkeley and its contributors.
43 * 4. Neither the name of the University nor the names of its contributors
44 * may be used to endorse or promote products derived from this software
45 * without specific prior written permission.
46 *
47 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
48 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
49 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
50 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
51 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
52 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
53 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
54 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
55 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
56 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
57 * SUCH DAMAGE.
58 *
59 * @(#)mfs_vnops.c 8.5 (Berkeley) 7/28/94
60 */
61
62 #include <sys/param.h>
63 #include <sys/systm.h>
64 #include <sys/time.h>
65 #include <sys/kernel.h>
66 #include <sys/proc.h>
67 #include <sys/buf.h>
68 #include <sys/map.h>
69 #include <sys/vnode.h>
70 #include <sys/malloc.h>
71
72 #include <miscfs/specfs/specdev.h>
73
74 #include <machine/vmparam.h>
75
76 #include <ufs/mfs/mfsnode.h>
77 #include <ufs/mfs/mfsiom.h>
78 #include <ufs/mfs/mfs_extern.h>
79
80 /*
81 * mfs vnode operations.
82 */
83
84 #define VOPFUNC int (*)(void *)
85
86 int (**mfs_vnodeop_p)(void *);
87 struct vnodeopv_entry_desc mfs_vnodeop_entries[] = {
88 { &vop_default_desc, (VOPFUNC)vn_default_error },
89 { &vop_lookup_desc, (VOPFUNC)mfs_lookup }, /* lookup */
90 { &vop_create_desc, (VOPFUNC)mfs_create }, /* create */
91 { &vop_mknod_desc, (VOPFUNC)mfs_mknod }, /* mknod */
92 { &vop_open_desc, (VOPFUNC)mfs_open }, /* open */
93 { &vop_close_desc, (VOPFUNC)mfs_close }, /* close */
94 { &vop_access_desc, (VOPFUNC)mfs_access }, /* access */
95 { &vop_getattr_desc, (VOPFUNC)mfs_getattr }, /* getattr */
96 { &vop_setattr_desc, (VOPFUNC)mfs_setattr }, /* setattr */
97 { &vop_read_desc, (VOPFUNC)mfs_read }, /* read */
98 { &vop_write_desc, (VOPFUNC)mfs_write }, /* write */
99 { &vop_ioctl_desc, (VOPFUNC)mfs_ioctl }, /* ioctl */
100 { &vop_select_desc, (VOPFUNC)mfs_select }, /* select */
101 { &vop_mmap_desc, (VOPFUNC)mfs_mmap }, /* mmap */
102 { &vop_fsync_desc, (VOPFUNC)spec_fsync }, /* fsync */
103 { &vop_seek_desc, (VOPFUNC)mfs_seek }, /* seek */
104 { &vop_remove_desc, (VOPFUNC)mfs_remove }, /* remove */
105 { &vop_link_desc, (VOPFUNC)mfs_link }, /* link */
106 { &vop_rename_desc, (VOPFUNC)mfs_rename }, /* rename */
107 { &vop_mkdir_desc, (VOPFUNC)mfs_mkdir }, /* mkdir */
108 { &vop_rmdir_desc, (VOPFUNC)mfs_rmdir }, /* rmdir */
109 { &vop_symlink_desc, (VOPFUNC)mfs_symlink }, /* symlink */
110 { &vop_readdir_desc, (VOPFUNC)mfs_readdir }, /* readdir */
111 { &vop_readlink_desc, (VOPFUNC)mfs_readlink }, /* readlink */
112 { &vop_abortop_desc, (VOPFUNC)mfs_abortop }, /* abortop */
113 { &vop_inactive_desc, (VOPFUNC)mfs_inactive }, /* inactive */
114 { &vop_reclaim_desc, (VOPFUNC)mfs_reclaim }, /* reclaim */
115 { &vop_lock_desc, (VOPFUNC)mfs_lock }, /* lock */
116 { &vop_unlock_desc, (VOPFUNC)mfs_unlock }, /* unlock */
117 { &vop_bmap_desc, (VOPFUNC)mfs_bmap }, /* bmap */
118 { &vop_strategy_desc, (VOPFUNC)mfs_strategy }, /* strategy */
119 { &vop_print_desc, (VOPFUNC)mfs_print }, /* print */
120 { &vop_islocked_desc, (VOPFUNC)mfs_islocked }, /* islocked */
121 { &vop_pathconf_desc, (VOPFUNC)mfs_pathconf }, /* pathconf */
122 { &vop_advlock_desc, (VOPFUNC)mfs_advlock }, /* advlock */
123 { &vop_blkatoff_desc, (VOPFUNC)mfs_blkatoff }, /* blkatoff */
124 { &vop_valloc_desc, (VOPFUNC)mfs_valloc }, /* valloc */
125 { &vop_vfree_desc, (VOPFUNC)mfs_vfree }, /* vfree */
126 { &vop_truncate_desc, (VOPFUNC)mfs_truncate }, /* truncate */
127 { &vop_update_desc, (VOPFUNC)mfs_update }, /* update */
128 { &vop_bwrite_desc, (VOPFUNC)mfs_bwrite }, /* bwrite */
129 { &vop_pgrd_desc, (VOPFUNC)mfs_pgrg }, /* pager read */
130 { &vop_pgwr_desc, (VOPFUNC)mfs_pgwr }, /* pager write */
131 { (struct vnodeop_desc*)NULL, (int(*)())NULL }
132 };
133 struct vnodeopv_desc mfs_vnodeop_opv_desc =
134 { &mfs_vnodeop_p, mfs_vnodeop_entries };
135
136 /*
137 * Vnode Operations.
138 *
139 * Open called to allow memory filesystem to initialize and
140 * validate before actual IO. Record our process identifier
141 * so we can tell when we are doing I/O to ourself.
142 */
143 /* ARGSUSED */
144 int
145 mfs_open(ap)
146 struct vop_open_args /* {
147 struct vnode *a_vp;
148 int a_mode;
149 struct ucred *a_cred;
150 struct proc *a_p;
151 } */ *ap;
152 {
153
154 if (ap->a_vp->v_type != VBLK) {
155 panic("mfs_ioctl not VBLK");
156 /* NOTREACHED */
157 }
158 return (0);
159 }
160
161 /*
162 * Ioctl operation.
163 */
164 /* ARGSUSED */
165 int
166 mfs_ioctl(ap)
167 struct vop_ioctl_args /* {
168 struct vnode *a_vp;
169 u_long a_command;
170 caddr_t a_data;
171 int a_fflag;
172 struct ucred *a_cred;
173 struct proc *a_p;
174 } */ *ap;
175 {
176
177 return (ENOTTY);
178 }
179
180 /*
181 * Pass I/O requests to the memory filesystem process.
182 */
183 int
184 mfs_strategy(ap)
185 struct vop_strategy_args /* {
186 struct buf *a_bp;
187 } */ *ap;
188 {
189 register struct buf *bp = ap->a_bp;
190 register struct mfsnode *mfsp;
191 struct vnode *vp;
192 struct proc *p = curproc; /* XXX */
193
194 if (!vfinddev(bp->b_dev, VBLK, &vp) || vp->v_usecount == 0)
195 panic("mfs_strategy: bad dev");
196 mfsp = VTOMFS(vp);
197 /* check for mini-root access */
198 if (mfsp->mfs_pid == 0) {
199 caddr_t base;
200
201 base = mfsp->mfs_baseoff + (bp->b_blkno << DEV_BSHIFT);
202 if (bp->b_flags & B_READ)
203 bcopy(base, bp->b_data, bp->b_bcount);
204 else
205 bcopy(bp->b_data, base, bp->b_bcount);
206 biodone(bp);
207 } else if (mfsp->mfs_pid == p->p_pid) {
208 mfs_doio(bp, mfsp->mfs_baseoff);
209 } else {
210 bp->b_actf = mfsp->mfs_buflist;
211 mfsp->mfs_buflist = bp;
212 wakeup((caddr_t)vp);
213 }
214 return (0);
215 }
216
217 /*
218 * Memory file system I/O.
219 *
220 * Trivial on the HP since buffer has already been mapping into KVA space.
221 */
222 void
223 mfs_doio(bp, base)
224 register struct buf *bp;
225 caddr_t base;
226 {
227
228 base += (bp->b_blkno << DEV_BSHIFT);
229 if (bp->b_flags & B_READ)
230 bp->b_error = copyin(base, bp->b_data, bp->b_bcount);
231 else
232 bp->b_error = copyout(bp->b_data, base, bp->b_bcount);
233 if (bp->b_error)
234 bp->b_flags |= B_ERROR;
235 biodone(bp);
236 }
237
238 /*
239 * This is a noop, simply returning what one has been given.
240 */
241 int
242 mfs_bmap(ap)
243 struct vop_bmap_args /* {
244 struct vnode *a_vp;
245 daddr_t a_bn;
246 struct vnode **a_vpp;
247 daddr_t *a_bnp;
248 int *a_runp;
249 } */ *ap;
250 {
251
252 if (ap->a_vpp != NULL)
253 *ap->a_vpp = ap->a_vp;
254 if (ap->a_bnp != NULL)
255 *ap->a_bnp = ap->a_bn;
256 return (0);
257 }
258
259 /*
260 * Memory filesystem close routine
261 */
262 /* ARGSUSED */
263 int
264 mfs_close(ap)
265 struct vop_close_args /* {
266 struct vnode *a_vp;
267 int a_fflag;
268 struct ucred *a_cred;
269 struct proc *a_p;
270 } */ *ap;
271 {
272 register struct vnode *vp = ap->a_vp;
273 register struct mfsnode *mfsp = VTOMFS(vp);
274 register struct buf *bp;
275 int error;
276
277 /*
278 * Finish any pending I/O requests.
279 */
280 while (bp = mfsp->mfs_buflist) {
281 mfsp->mfs_buflist = bp->b_actf;
282 mfs_doio(bp, mfsp->mfs_baseoff);
283 wakeup((caddr_t)bp);
284 }
285 /*
286 * On last close of a memory filesystem
287 * we must invalidate any in core blocks, so that
288 * we can, free up its vnode.
289 */
290 if (error = vinvalbuf(vp, 1, ap->a_cred, ap->a_p, 0, 0))
291 return (error);
292 /*
293 * There should be no way to have any more uses of this
294 * vnode, so if we find any other uses, it is a panic.
295 */
296 if (vp->v_usecount > 1)
297 printf("mfs_close: ref count %d > 1\n", vp->v_usecount);
298 if (vp->v_usecount > 1 || mfsp->mfs_buflist)
299 panic("mfs_close");
300 /*
301 * Send a request to the filesystem server to exit.
302 */
303 mfsp->mfs_buflist = (struct buf *)(-1);
304 wakeup((caddr_t)vp);
305 return (0);
306 }
307
308 /*
309 * Memory filesystem inactive routine
310 */
311 /* ARGSUSED */
312 int
313 mfs_inactive(ap)
314 struct vop_inactive_args /* {
315 struct vnode *a_vp;
316 } */ *ap;
317 {
318 register struct mfsnode *mfsp = VTOMFS(ap->a_vp);
319
320 if (mfsp->mfs_buflist && mfsp->mfs_buflist != (struct buf *)(-1))
321 panic("mfs_inactive: not inactive (mfs_buflist %x)",
322 mfsp->mfs_buflist);
323 return (0);
324 }
325
326 /*
327 * Reclaim a memory filesystem devvp so that it can be reused.
328 */
329 int
330 mfs_reclaim(ap)
331 struct vop_reclaim_args /* {
332 struct vnode *a_vp;
333 } */ *ap;
334 {
335 register struct vnode *vp = ap->a_vp;
336
337 FREE(vp->v_data, M_MFSNODE);
338 vp->v_data = NULL;
339 return (0);
340 }
341
342 /*
343 * Print out the contents of an mfsnode.
344 */
345 int
346 mfs_print(ap)
347 struct vop_print_args /* {
348 struct vnode *a_vp;
349 } */ *ap;
350 {
351 register struct mfsnode *mfsp = VTOMFS(ap->a_vp);
352
353 printf("tag VT_MFS, pid %d, base %d, size %d\n", mfsp->mfs_pid,
354 mfsp->mfs_baseoff, mfsp->mfs_size);
355 return (0);
356 }
357
358 /*
359 * Block device bad operation
360 */
361 int
362 mfs_badop()
363 {
364
365 panic("mfs_badop called\n");
366 /* NOTREACHED */
367 }
368
369 /*
370 * Memory based filesystem initialization.
371 */
372 mfs_init()
373 {
374
375 }