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