1 /*
2 * Copyright (c) 1989, 1993
3 * The Regents of the University of California. All rights reserved.
4 *
5 * %sccs.include.redist.c%
6 *
7 * @(#)mfs_vnops.c 8.11 (Berkeley) 05/22/95
8 */
9
10 #include <sys/param.h>
11 #include <sys/systm.h>
12 #include <sys/time.h>
13 #include <sys/kernel.h>
14 #include <sys/proc.h>
15 #include <sys/buf.h>
16 #include <sys/map.h>
17 #include <sys/vnode.h>
18 #include <sys/malloc.h>
19
20 #include <miscfs/specfs/specdev.h>
21
22 #include <machine/vmparam.h>
23
24 #include <ufs/mfs/mfsnode.h>
25 #include <ufs/mfs/mfsiom.h>
26 #include <ufs/mfs/mfs_extern.h>
27
28 /*
29 * mfs vnode operations.
30 */
31 int (**mfs_vnodeop_p)();
32 struct vnodeopv_entry_desc mfs_vnodeop_entries[] = {
33 { &vop_default_desc, vn_default_error },
34 { &vop_lookup_desc, mfs_lookup }, /* lookup */
35 { &vop_create_desc, mfs_create }, /* create */
36 { &vop_mknod_desc, mfs_mknod }, /* mknod */
37 { &vop_open_desc, mfs_open }, /* open */
38 { &vop_close_desc, mfs_close }, /* close */
39 { &vop_access_desc, mfs_access }, /* access */
40 { &vop_getattr_desc, mfs_getattr }, /* getattr */
41 { &vop_setattr_desc, mfs_setattr }, /* setattr */
42 { &vop_read_desc, mfs_read }, /* read */
43 { &vop_write_desc, mfs_write }, /* write */
44 { &vop_ioctl_desc, mfs_ioctl }, /* ioctl */
45 { &vop_select_desc, mfs_select }, /* select */
46 { &vop_revoke_desc, mfs_revoke }, /* revoke */
47 { &vop_mmap_desc, mfs_mmap }, /* mmap */
48 { &vop_fsync_desc, spec_fsync }, /* fsync */
49 { &vop_seek_desc, mfs_seek }, /* seek */
50 { &vop_remove_desc, mfs_remove }, /* remove */
51 { &vop_link_desc, mfs_link }, /* link */
52 { &vop_rename_desc, mfs_rename }, /* rename */
53 { &vop_mkdir_desc, mfs_mkdir }, /* mkdir */
54 { &vop_rmdir_desc, mfs_rmdir }, /* rmdir */
55 { &vop_symlink_desc, mfs_symlink }, /* symlink */
56 { &vop_readdir_desc, mfs_readdir }, /* readdir */
57 { &vop_readlink_desc, mfs_readlink }, /* readlink */
58 { &vop_abortop_desc, mfs_abortop }, /* abortop */
59 { &vop_inactive_desc, mfs_inactive }, /* inactive */
60 { &vop_reclaim_desc, mfs_reclaim }, /* reclaim */
61 { &vop_lock_desc, mfs_lock }, /* lock */
62 { &vop_unlock_desc, mfs_unlock }, /* unlock */
63 { &vop_bmap_desc, mfs_bmap }, /* bmap */
64 { &vop_strategy_desc, mfs_strategy }, /* strategy */
65 { &vop_print_desc, mfs_print }, /* print */
66 { &vop_islocked_desc, mfs_islocked }, /* islocked */
67 { &vop_pathconf_desc, mfs_pathconf }, /* pathconf */
68 { &vop_advlock_desc, mfs_advlock }, /* advlock */
69 { &vop_blkatoff_desc, mfs_blkatoff }, /* blkatoff */
70 { &vop_valloc_desc, mfs_valloc }, /* valloc */
71 { &vop_vfree_desc, mfs_vfree }, /* vfree */
72 { &vop_truncate_desc, mfs_truncate }, /* truncate */
73 { &vop_update_desc, mfs_update }, /* update */
74 { &vop_bwrite_desc, mfs_bwrite }, /* bwrite */
75 { (struct vnodeop_desc*)NULL, (int(*)())NULL }
76 };
77 struct vnodeopv_desc mfs_vnodeop_opv_desc =
78 { &mfs_vnodeop_p, mfs_vnodeop_entries };
79
80 /*
81 * Vnode Operations.
82 *
83 * Open called to allow memory filesystem to initialize and
84 * validate before actual IO. Record our process identifier
85 * so we can tell when we are doing I/O to ourself.
86 */
87 /* ARGSUSED */
88 int
mfs_open(ap)89 mfs_open(ap)
90 struct vop_open_args /* {
91 struct vnode *a_vp;
92 int a_mode;
93 struct ucred *a_cred;
94 struct proc *a_p;
95 } */ *ap;
96 {
97
98 if (ap->a_vp->v_type != VBLK) {
99 panic("mfs_ioctl not VBLK");
100 /* NOTREACHED */
101 }
102 return (0);
103 }
104
105 /*
106 * Ioctl operation.
107 */
108 /* ARGSUSED */
109 int
mfs_ioctl(ap)110 mfs_ioctl(ap)
111 struct vop_ioctl_args /* {
112 struct vnode *a_vp;
113 int a_command;
114 caddr_t a_data;
115 int a_fflag;
116 struct ucred *a_cred;
117 struct proc *a_p;
118 } */ *ap;
119 {
120
121 return (ENOTTY);
122 }
123
124 /*
125 * Pass I/O requests to the memory filesystem process.
126 */
127 int
mfs_strategy(ap)128 mfs_strategy(ap)
129 struct vop_strategy_args /* {
130 struct buf *a_bp;
131 } */ *ap;
132 {
133 register struct buf *bp = ap->a_bp;
134 register struct mfsnode *mfsp;
135 struct vnode *vp;
136 struct proc *p = curproc; /* XXX */
137
138 if (!vfinddev(bp->b_dev, VBLK, &vp) || vp->v_usecount == 0)
139 panic("mfs_strategy: bad dev");
140 mfsp = VTOMFS(vp);
141 /* check for mini-root access */
142 if (mfsp->mfs_pid == 0) {
143 caddr_t base;
144
145 base = mfsp->mfs_baseoff + (bp->b_blkno << DEV_BSHIFT);
146 if (bp->b_flags & B_READ)
147 bcopy(base, bp->b_data, bp->b_bcount);
148 else
149 bcopy(bp->b_data, base, bp->b_bcount);
150 biodone(bp);
151 } else if (mfsp->mfs_pid == p->p_pid) {
152 mfs_doio(bp, mfsp->mfs_baseoff);
153 } else {
154 bp->b_actf = mfsp->mfs_buflist;
155 mfsp->mfs_buflist = bp;
156 wakeup((caddr_t)vp);
157 }
158 return (0);
159 }
160
161 /*
162 * Memory file system I/O.
163 *
164 * Trivial on the HP since buffer has already been mapping into KVA space.
165 */
166 void
mfs_doio(bp,base)167 mfs_doio(bp, base)
168 register struct buf *bp;
169 caddr_t base;
170 {
171
172 base += (bp->b_blkno << DEV_BSHIFT);
173 if (bp->b_flags & B_READ)
174 bp->b_error = copyin(base, bp->b_data, bp->b_bcount);
175 else
176 bp->b_error = copyout(bp->b_data, base, bp->b_bcount);
177 if (bp->b_error)
178 bp->b_flags |= B_ERROR;
179 biodone(bp);
180 }
181
182 /*
183 * This is a noop, simply returning what one has been given.
184 */
185 int
mfs_bmap(ap)186 mfs_bmap(ap)
187 struct vop_bmap_args /* {
188 struct vnode *a_vp;
189 ufs_daddr_t a_bn;
190 struct vnode **a_vpp;
191 ufs_daddr_t *a_bnp;
192 int *a_runp;
193 } */ *ap;
194 {
195
196 if (ap->a_vpp != NULL)
197 *ap->a_vpp = ap->a_vp;
198 if (ap->a_bnp != NULL)
199 *ap->a_bnp = ap->a_bn;
200 if (ap->a_runp != NULL)
201 *ap->a_runp = 0;
202 return (0);
203 }
204
205 /*
206 * Memory filesystem close routine
207 */
208 /* ARGSUSED */
209 int
mfs_close(ap)210 mfs_close(ap)
211 struct vop_close_args /* {
212 struct vnode *a_vp;
213 int a_fflag;
214 struct ucred *a_cred;
215 struct proc *a_p;
216 } */ *ap;
217 {
218 register struct vnode *vp = ap->a_vp;
219 register struct mfsnode *mfsp = VTOMFS(vp);
220 register struct buf *bp;
221 int error;
222
223 /*
224 * Finish any pending I/O requests.
225 */
226 while (bp = mfsp->mfs_buflist) {
227 mfsp->mfs_buflist = bp->b_actf;
228 mfs_doio(bp, mfsp->mfs_baseoff);
229 wakeup((caddr_t)bp);
230 }
231 /*
232 * On last close of a memory filesystem
233 * we must invalidate any in core blocks, so that
234 * we can, free up its vnode.
235 */
236 if (error = vinvalbuf(vp, 1, ap->a_cred, ap->a_p, 0, 0))
237 return (error);
238 /*
239 * There should be no way to have any more uses of this
240 * vnode, so if we find any other uses, it is a panic.
241 */
242 if (vp->v_usecount > 1)
243 printf("mfs_close: ref count %d > 1\n", vp->v_usecount);
244 if (vp->v_usecount > 1 || mfsp->mfs_buflist)
245 panic("mfs_close");
246 /*
247 * Send a request to the filesystem server to exit.
248 */
249 mfsp->mfs_buflist = (struct buf *)(-1);
250 wakeup((caddr_t)vp);
251 return (0);
252 }
253
254 /*
255 * Memory filesystem inactive routine
256 */
257 /* ARGSUSED */
258 int
mfs_inactive(ap)259 mfs_inactive(ap)
260 struct vop_inactive_args /* {
261 struct vnode *a_vp;
262 struct proc *a_p;
263 } */ *ap;
264 {
265 struct vnode *vp = ap->a_vp;
266 struct mfsnode *mfsp = VTOMFS(vp);
267
268 if (mfsp->mfs_buflist && mfsp->mfs_buflist != (struct buf *)(-1))
269 panic("mfs_inactive: not inactive (mfs_buflist %x)",
270 mfsp->mfs_buflist);
271 VOP_UNLOCK(vp, 0, ap->a_p);
272 return (0);
273 }
274
275 /*
276 * Reclaim a memory filesystem devvp so that it can be reused.
277 */
278 int
mfs_reclaim(ap)279 mfs_reclaim(ap)
280 struct vop_reclaim_args /* {
281 struct vnode *a_vp;
282 } */ *ap;
283 {
284 register struct vnode *vp = ap->a_vp;
285
286 FREE(vp->v_data, M_MFSNODE);
287 vp->v_data = NULL;
288 return (0);
289 }
290
291 /*
292 * Print out the contents of an mfsnode.
293 */
294 int
mfs_print(ap)295 mfs_print(ap)
296 struct vop_print_args /* {
297 struct vnode *a_vp;
298 } */ *ap;
299 {
300 register struct mfsnode *mfsp = VTOMFS(ap->a_vp);
301
302 printf("tag VT_MFS, pid %d, base %d, size %d\n", mfsp->mfs_pid,
303 mfsp->mfs_baseoff, mfsp->mfs_size);
304 return (0);
305 }
306
307 /*
308 * Block device bad operation
309 */
310 int
mfs_badop()311 mfs_badop()
312 {
313
314 panic("mfs_badop called\n");
315 /* NOTREACHED */
316 }
317
318 /*
319 * Memory based filesystem initialization.
320 */
321 mfs_init(vfsp)
322 struct vfsconf *vfsp;
323 {
324
325 return;
326 }
327