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