xref: /original-bsd/sys/ufs/mfs/mfs_vnops.c (revision 9fa17c5f)
1 /*
2  * Copyright (c) 1989 The Regents of the University of California.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms are permitted
6  * provided that the above copyright notice and this paragraph are
7  * duplicated in all such forms and that any documentation,
8  * advertising materials, and other materials related to such
9  * distribution and use acknowledge that the software was developed
10  * by the University of California, Berkeley.  The name of the
11  * University may not be used to endorse or promote products derived
12  * from this software without specific prior written permission.
13  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
14  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
15  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
16  *
17  *	@(#)mfs_vnops.c	7.16 (Berkeley) 06/22/90
18  */
19 
20 #include "param.h"
21 #include "time.h"
22 #include "kernel.h"
23 #include "proc.h"
24 #include "user.h"
25 #include "buf.h"
26 #include "vmmac.h"
27 #include "errno.h"
28 #include "map.h"
29 #include "vnode.h"
30 #include "../ufs/mfsnode.h"
31 #include "../ufs/mfsiom.h"
32 #include "machine/vmparam.h"
33 #include "machine/pte.h"
34 #include "machine/mtpr.h"
35 
36 #if !defined(hp300)
37 static int mfsmap_want;		/* 1 => need kernel I/O resources */
38 struct map mfsmap[MFS_MAPSIZE];
39 extern char mfsiobuf[];
40 #endif
41 
42 /*
43  * mfs vnode operations.
44  */
45 int	mfs_open(),
46 	mfs_strategy(),
47 	mfs_bmap(),
48 	mfs_ioctl(),
49 	mfs_close(),
50 	mfs_inactive(),
51 	mfs_print(),
52 	mfs_badop(),
53 	mfs_nullop();
54 
55 struct vnodeops mfs_vnodeops = {
56 	mfs_badop,		/* lookup */
57 	mfs_badop,		/* create */
58 	mfs_badop,		/* mknod */
59 	mfs_open,		/* open */
60 	mfs_close,		/* close */
61 	mfs_badop,		/* access */
62 	mfs_badop,		/* getattr */
63 	mfs_badop,		/* setattr */
64 	mfs_badop,		/* read */
65 	mfs_badop,		/* write */
66 	mfs_ioctl,		/* ioctl */
67 	mfs_badop,		/* select */
68 	mfs_badop,		/* mmap */
69 	mfs_badop,		/* fsync */
70 	mfs_badop,		/* seek */
71 	mfs_badop,		/* remove */
72 	mfs_badop,		/* link */
73 	mfs_badop,		/* rename */
74 	mfs_badop,		/* mkdir */
75 	mfs_badop,		/* rmdir */
76 	mfs_badop,		/* symlink */
77 	mfs_badop,		/* readdir */
78 	mfs_badop,		/* readlink */
79 	mfs_badop,		/* abortop */
80 	mfs_inactive,		/* inactive */
81 	mfs_nullop,		/* reclaim */
82 	mfs_nullop,		/* lock */
83 	mfs_nullop,		/* unlock */
84 	mfs_bmap,		/* bmap */
85 	mfs_strategy,		/* strategy */
86 	mfs_print,		/* print */
87 	mfs_nullop,		/* islocked */
88 };
89 
90 /*
91  * Vnode Operations.
92  *
93  * Open called to allow memory filesystem to initialize and
94  * validate before actual IO. Record our process identifier
95  * so we can tell when we are doing I/O to ourself.
96  */
97 /* ARGSUSED */
98 mfs_open(vp, mode, cred)
99 	register struct vnode *vp;
100 	int mode;
101 	struct ucred *cred;
102 {
103 
104 	if (vp->v_type != VBLK) {
105 		panic("mfs_ioctl not VBLK");
106 		/* NOTREACHED */
107 	}
108 	return (0);
109 }
110 
111 /*
112  * Ioctl operation.
113  */
114 /* ARGSUSED */
115 mfs_ioctl(vp, com, data, fflag, cred)
116 	struct vnode *vp;
117 	int com;
118 	caddr_t data;
119 	int fflag;
120 	struct ucred *cred;
121 {
122 
123 	return (-1);
124 }
125 
126 /*
127  * Pass I/O requests to the memory filesystem process.
128  */
129 mfs_strategy(bp)
130 	register struct buf *bp;
131 {
132 	register struct mfsnode *mfsp;
133 	struct vnode *vp;
134 
135 	if (vfinddev(bp->b_dev, VBLK, &vp) || vp->v_usecount == 0)
136 		panic("mfs_strategy: bad dev");
137 	mfsp = VTOMFS(vp);
138 	if (mfsp->mfs_pid == u.u_procp->p_pid) {
139 		mfs_doio(bp, mfsp->mfs_baseoff);
140 	} else {
141 		bp->av_forw = mfsp->mfs_buflist;
142 		mfsp->mfs_buflist = bp;
143 		wakeup((caddr_t)vp);
144 	}
145 	return (0);
146 }
147 
148 #if defined(vax) || defined(tahoe)
149 /*
150  * Memory file system I/O.
151  *
152  * Essentially play ubasetup() and disk interrupt service routine by
153  * doing the copies to or from the memfs process. If doing physio
154  * (i.e. pagein), we must map the I/O through the kernel virtual
155  * address space.
156  */
157 mfs_doio(bp, base)
158 	register struct buf *bp;
159 	caddr_t base;
160 {
161 	register struct pte *pte, *ppte;
162 	register caddr_t vaddr;
163 	int off, npf, npf2, reg;
164 	caddr_t kernaddr, offset;
165 
166 	/*
167 	 * For phys I/O, map the b_addr into kernel virtual space using
168 	 * the Mfsiomap pte's.
169 	 */
170 	if ((bp->b_flags & B_PHYS) == 0) {
171 		kernaddr = bp->b_un.b_addr;
172 	} else {
173 		if (bp->b_flags & (B_PAGET | B_UAREA | B_DIRTY))
174 			panic("swap on memfs?");
175 		off = (int)bp->b_un.b_addr & PGOFSET;
176 		npf = btoc(bp->b_bcount + off);
177 		/*
178 		 * Get some mapping page table entries
179 		 */
180 		while ((reg = rmalloc(mfsmap, (long)npf)) == 0) {
181 			mfsmap_want++;
182 			sleep((caddr_t)&mfsmap_want, PZERO-1);
183 		}
184 		reg--;
185 		pte = vtopte(bp->b_proc, btop(bp->b_un.b_addr));
186 		/*
187 		 * Do vmaccess() but with the Mfsiomap page table.
188 		 */
189 		ppte = &Mfsiomap[reg];
190 		vaddr = &mfsiobuf[reg * NBPG];
191 		kernaddr = vaddr + off;
192 		for (npf2 = npf; npf2; npf2--) {
193 			mapin(ppte, (u_int)vaddr, pte->pg_pfnum,
194 				(int)(PG_V|PG_KW));
195 #if defined(tahoe)
196 			if ((bp->b_flags & B_READ) == 0)
197 				mtpr(P1DC, vaddr);
198 #endif
199 			ppte++;
200 			pte++;
201 			vaddr += NBPG;
202 		}
203 	}
204 	offset = base + (bp->b_blkno << DEV_BSHIFT);
205 	if (bp->b_flags & B_READ)
206 		bp->b_error = copyin(offset, kernaddr, bp->b_bcount);
207 	else
208 		bp->b_error = copyout(kernaddr, offset, bp->b_bcount);
209 	if (bp->b_error)
210 		bp->b_flags |= B_ERROR;
211 	/*
212 	 * Release pte's used by physical I/O.
213 	 */
214 	if (bp->b_flags & B_PHYS) {
215 		rmfree(mfsmap, (long)npf, (long)++reg);
216 		if (mfsmap_want) {
217 			mfsmap_want = 0;
218 			wakeup((caddr_t)&mfsmap_want);
219 		}
220 	}
221 	biodone(bp);
222 }
223 #endif	/* vax || tahoe */
224 
225 #if defined(hp300)
226 /*
227  * Memory file system I/O.
228  *
229  * Trivial on the HP since buffer has already been mapping into KVA space.
230  */
231 mfs_doio(bp, base)
232 	register struct buf *bp;
233 	caddr_t base;
234 {
235 	base += (bp->b_blkno << DEV_BSHIFT);
236 	if (bp->b_flags & B_READ)
237 		bp->b_error = copyin(base, bp->b_un.b_addr, bp->b_bcount);
238 	else
239 		bp->b_error = copyout(bp->b_un.b_addr, base, bp->b_bcount);
240 	if (bp->b_error)
241 		bp->b_flags |= B_ERROR;
242 	biodone(bp);
243 }
244 #endif
245 
246 /*
247  * This is a noop, simply returning what one has been given.
248  */
249 mfs_bmap(vp, bn, vpp, bnp)
250 	struct vnode *vp;
251 	daddr_t bn;
252 	struct vnode **vpp;
253 	daddr_t *bnp;
254 {
255 
256 	if (vpp != NULL)
257 		*vpp = vp;
258 	if (bnp != NULL)
259 		*bnp = bn;
260 	return (0);
261 }
262 
263 /*
264  * Memory filesystem close routine
265  */
266 /* ARGSUSED */
267 mfs_close(vp, flag, cred)
268 	register struct vnode *vp;
269 	int flag;
270 	struct ucred *cred;
271 {
272 	register struct mfsnode *mfsp = VTOMFS(vp);
273 	register struct buf *bp;
274 
275 	/*
276 	 * Finish any pending I/O requests.
277 	 */
278 	while (bp = mfsp->mfs_buflist) {
279 		mfsp->mfs_buflist = bp->av_forw;
280 		mfs_doio(bp, mfsp->mfs_baseoff);
281 		wakeup((caddr_t)bp);
282 	}
283 	/*
284 	 * On last close of a memory filesystem
285 	 * we must invalidate any in core blocks, so that
286 	 * we can, free up its vnode.
287 	 */
288 	vflushbuf(vp, 0);
289 	if (vinvalbuf(vp, 1))
290 		return (0);
291 	/*
292 	 * There should be no way to have any more uses of this
293 	 * vnode, so if we find any other uses, it is a panic.
294 	 */
295 	if (vp->v_usecount > 1)
296 		printf("mfs_close: ref count %d > 1\n", vp->v_usecount);
297 	if (vp->v_usecount > 1 || mfsp->mfs_buflist)
298 		panic("mfs_close");
299 	/*
300 	 * Send a request to the filesystem server to exit.
301 	 */
302 	mfsp->mfs_buflist = (struct buf *)(-1);
303 	wakeup((caddr_t)vp);
304 	return (0);
305 }
306 
307 /*
308  * Memory filesystem inactive routine
309  */
310 /* ARGSUSED */
311 mfs_inactive(vp)
312 	struct vnode *vp;
313 {
314 
315 	if (VTOMFS(vp)->mfs_buflist != (struct buf *)(-1))
316 		panic("mfs_inactive: not inactive");
317 	return (0);
318 }
319 
320 /*
321  * Print out the contents of an mfsnode.
322  */
323 mfs_print(vp)
324 	struct vnode *vp;
325 {
326 	register struct mfsnode *mfsp = VTOMFS(vp);
327 
328 	printf("tag VT_MFS, pid %d, base %d, size %d\n", mfsp->mfs_pid,
329 		mfsp->mfs_baseoff, mfsp->mfs_size);
330 }
331 
332 /*
333  * Block device bad operation
334  */
335 mfs_badop()
336 {
337 
338 	panic("mfs_badop called\n");
339 	/* NOTREACHED */
340 }
341 
342 /*
343  * Block device null operation
344  */
345 mfs_nullop()
346 {
347 
348 	return (0);
349 }
350 
351 /*
352  * Memory based filesystem initialization.
353  */
354 mfs_init()
355 {
356 
357 #if !defined(hp300)
358 	rminit(mfsmap, (long)MFS_MAPREG, (long)1, "mfs mapreg", MFS_MAPSIZE);
359 #endif
360 }
361