xref: /csrg-svn/sys/ufs/mfs/mfs_vnops.c (revision 39019)
1*39019Smckusick /*
2*39019Smckusick  * Copyright (c) 1989 The Regents of the University of California.
3*39019Smckusick  * All rights reserved.
4*39019Smckusick  *
5*39019Smckusick  * Redistribution and use in source and binary forms are permitted
6*39019Smckusick  * provided that the above copyright notice and this paragraph are
7*39019Smckusick  * duplicated in all such forms and that any documentation,
8*39019Smckusick  * advertising materials, and other materials related to such
9*39019Smckusick  * distribution and use acknowledge that the software was developed
10*39019Smckusick  * by the University of California, Berkeley.  The name of the
11*39019Smckusick  * University may not be used to endorse or promote products derived
12*39019Smckusick  * from this software without specific prior written permission.
13*39019Smckusick  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
14*39019Smckusick  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
15*39019Smckusick  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
16*39019Smckusick  *
17*39019Smckusick  *	@(#)mfs_vnops.c	7.1 (Berkeley) 09/05/89
18*39019Smckusick  */
19*39019Smckusick 
20*39019Smckusick #include "param.h"
21*39019Smckusick #include "time.h"
22*39019Smckusick #include "proc.h"
23*39019Smckusick #include "buf.h"
24*39019Smckusick #include "vmmac.h"
25*39019Smckusick #include "errno.h"
26*39019Smckusick #include "map.h"
27*39019Smckusick #include "vnode.h"
28*39019Smckusick #include "../ufs/inode.h"
29*39019Smckusick #include "../ufs/mfsiom.h"
30*39019Smckusick #include "../machine/vmparam.h"
31*39019Smckusick #include "../machine/pte.h"
32*39019Smckusick #include "../machine/mtpr.h"
33*39019Smckusick 
34*39019Smckusick int mfs_running;		/* 1 => daemon has started running */
35*39019Smckusick static int mfsmap_want;		/* 1 => need kernel I/O resources */
36*39019Smckusick struct map mfsmap[MFS_MAPSIZE];
37*39019Smckusick extern char mfsiobuf[];
38*39019Smckusick 
39*39019Smckusick /*
40*39019Smckusick  * mfs vnode operations.
41*39019Smckusick  */
42*39019Smckusick int	mfs_open(),
43*39019Smckusick 	mfs_strategy(),
44*39019Smckusick 	mfs_ioctl(),
45*39019Smckusick 	mfs_close(),
46*39019Smckusick 	ufs_inactive(),
47*39019Smckusick 	mfs_badop(),
48*39019Smckusick 	mfs_nullop();
49*39019Smckusick 
50*39019Smckusick struct vnodeops mfs_vnodeops = {
51*39019Smckusick 	mfs_badop,
52*39019Smckusick 	mfs_badop,
53*39019Smckusick 	mfs_badop,
54*39019Smckusick 	mfs_open,
55*39019Smckusick 	mfs_close,
56*39019Smckusick 	mfs_badop,
57*39019Smckusick 	mfs_badop,
58*39019Smckusick 	mfs_badop,
59*39019Smckusick 	mfs_badop,
60*39019Smckusick 	mfs_badop,
61*39019Smckusick 	mfs_ioctl,
62*39019Smckusick 	mfs_badop,
63*39019Smckusick 	mfs_badop,
64*39019Smckusick 	mfs_badop,
65*39019Smckusick 	mfs_badop,
66*39019Smckusick 	mfs_badop,
67*39019Smckusick 	mfs_badop,
68*39019Smckusick 	mfs_badop,
69*39019Smckusick 	mfs_badop,
70*39019Smckusick 	mfs_badop,
71*39019Smckusick 	mfs_badop,
72*39019Smckusick 	mfs_badop,
73*39019Smckusick 	mfs_badop,
74*39019Smckusick 	mfs_badop,
75*39019Smckusick 	ufs_inactive,
76*39019Smckusick 	mfs_badop,
77*39019Smckusick 	mfs_badop,
78*39019Smckusick 	mfs_badop,
79*39019Smckusick 	mfs_strategy,
80*39019Smckusick };
81*39019Smckusick 
82*39019Smckusick /*
83*39019Smckusick  * Vnode Operations.
84*39019Smckusick  *
85*39019Smckusick  * Open called to allow memory filesystem to initialize and
86*39019Smckusick  * validate before actual IO. Nothing to do here as the
87*39019Smckusick  * filesystem is ready to go in the process address space.
88*39019Smckusick  */
89*39019Smckusick /* ARGSUSED */
90*39019Smckusick mfs_open(vp, mode, cred)
91*39019Smckusick 	register struct vnode *vp;
92*39019Smckusick 	int mode;
93*39019Smckusick 	struct ucred *cred;
94*39019Smckusick {
95*39019Smckusick 
96*39019Smckusick 	if (vp->v_type != VBLK) {
97*39019Smckusick 		panic("mfs_ioctl not VBLK");
98*39019Smckusick 		/* NOTREACHED */
99*39019Smckusick 	}
100*39019Smckusick 	return (0);
101*39019Smckusick }
102*39019Smckusick 
103*39019Smckusick /*
104*39019Smckusick  * Ioctl operation.
105*39019Smckusick  */
106*39019Smckusick /* ARGSUSED */
107*39019Smckusick mfs_ioctl(vp, com, data, fflag, cred)
108*39019Smckusick 	struct vnode *vp;
109*39019Smckusick 	int com;
110*39019Smckusick 	caddr_t data;
111*39019Smckusick 	int fflag;
112*39019Smckusick 	struct ucred *cred;
113*39019Smckusick {
114*39019Smckusick 
115*39019Smckusick 	return (-1);
116*39019Smckusick }
117*39019Smckusick 
118*39019Smckusick /*
119*39019Smckusick  * Pass I/O requests to the memory filesystem process.
120*39019Smckusick  */
121*39019Smckusick mfs_strategy(bp)
122*39019Smckusick 	register struct buf *bp;
123*39019Smckusick {
124*39019Smckusick 	register struct inode *ip = VTOI(bp->b_vp);
125*39019Smckusick 	int error;
126*39019Smckusick 
127*39019Smckusick 	ILOCK(ip);
128*39019Smckusick 	if (!mfs_running) {
129*39019Smckusick 		mfs_doio(bp, (caddr_t)ip->i_diroff);
130*39019Smckusick 	} else {
131*39019Smckusick 		ip->i_spare[0] = (long)bp;
132*39019Smckusick 		wakeup((caddr_t)bp->b_vp);
133*39019Smckusick 	}
134*39019Smckusick 	error = biowait(bp);
135*39019Smckusick 	IUNLOCK(ip);
136*39019Smckusick 	return (error);
137*39019Smckusick }
138*39019Smckusick 
139*39019Smckusick /*
140*39019Smckusick  * Memory file system I/O.
141*39019Smckusick  *
142*39019Smckusick  * Essentially play ubasetup() and disk interrupt service routine by
143*39019Smckusick  * doing the copies to or from the memfs process. If doing physio
144*39019Smckusick  * (i.e. pagein), we must map the I/O through the kernel virtual
145*39019Smckusick  * address space.
146*39019Smckusick  */
147*39019Smckusick mfs_doio(bp, base)
148*39019Smckusick 	register struct buf *bp;
149*39019Smckusick 	caddr_t base;
150*39019Smckusick {
151*39019Smckusick 	register struct pte *pte, *ppte;
152*39019Smckusick 	register caddr_t vaddr;
153*39019Smckusick 	int off, npf, npf2, reg;
154*39019Smckusick 	caddr_t kernaddr, offset;
155*39019Smckusick 
156*39019Smckusick 	/*
157*39019Smckusick 	 * For phys I/O, map the b_addr into kernel virtual space using
158*39019Smckusick 	 * the Mfsiomap pte's.
159*39019Smckusick 	 */
160*39019Smckusick 	if ((bp->b_flags & B_PHYS) == 0) {
161*39019Smckusick 		kernaddr = bp->b_un.b_addr;
162*39019Smckusick 	} else {
163*39019Smckusick 		if (bp->b_flags & (B_PAGET | B_UAREA | B_DIRTY))
164*39019Smckusick 			panic("swap on memfs?");
165*39019Smckusick 		off = (int)bp->b_un.b_addr & PGOFSET;
166*39019Smckusick 		npf = btoc(bp->b_bcount + off);
167*39019Smckusick 		/*
168*39019Smckusick 		 * Get some mapping page table entries
169*39019Smckusick 		 */
170*39019Smckusick 		while ((reg = rmalloc(mfsmap, (long)npf)) == 0) {
171*39019Smckusick 			mfsmap_want++;
172*39019Smckusick 			sleep((caddr_t)&mfsmap_want, PZERO-1);
173*39019Smckusick 		}
174*39019Smckusick 		reg--;
175*39019Smckusick 		pte = vtopte(bp->b_proc, btop(bp->b_un.b_addr));
176*39019Smckusick 		/*
177*39019Smckusick 		 * Do vmaccess() but with the Mfsiomap page table.
178*39019Smckusick 		 */
179*39019Smckusick 		ppte = &Mfsiomap[reg];
180*39019Smckusick 		vaddr = &mfsiobuf[reg * NBPG];
181*39019Smckusick 		kernaddr = vaddr + off;
182*39019Smckusick 		for (npf2 = npf; npf2; npf2--) {
183*39019Smckusick 			mapin(ppte, (u_int)vaddr, pte->pg_pfnum,
184*39019Smckusick 				(int)(PG_V|PG_KW));
185*39019Smckusick #if defined(tahoe)
186*39019Smckusick 			if ((bp->b_flags & B_READ) == 0)
187*39019Smckusick 				mtpr(P1DC, vaddr);
188*39019Smckusick #endif
189*39019Smckusick 			ppte++;
190*39019Smckusick 			pte++;
191*39019Smckusick 			vaddr += NBPG;
192*39019Smckusick 		}
193*39019Smckusick 	}
194*39019Smckusick 	offset = base + (bp->b_blkno << DEV_BSHIFT);
195*39019Smckusick 	if (bp->b_flags & B_READ)
196*39019Smckusick 		bp->b_error = copyin(offset, kernaddr, bp->b_bcount);
197*39019Smckusick 	else
198*39019Smckusick 		bp->b_error = copyout(kernaddr, offset, bp->b_bcount);
199*39019Smckusick 	if (bp->b_error)
200*39019Smckusick 		bp->b_flags |= B_ERROR;
201*39019Smckusick 	/*
202*39019Smckusick 	 * Release pte's used by physical I/O.
203*39019Smckusick 	 */
204*39019Smckusick 	if (bp->b_flags & B_PHYS) {
205*39019Smckusick 		rmfree(mfsmap, (long)npf, (long)++reg);
206*39019Smckusick 		if (mfsmap_want) {
207*39019Smckusick 			mfsmap_want = 0;
208*39019Smckusick 			wakeup((caddr_t)&mfsmap_want);
209*39019Smckusick 		}
210*39019Smckusick 	}
211*39019Smckusick 	biodone(bp);
212*39019Smckusick }
213*39019Smckusick 
214*39019Smckusick /*
215*39019Smckusick  * Memory filesystem close routine
216*39019Smckusick  */
217*39019Smckusick /* ARGSUSED */
218*39019Smckusick mfs_close(vp, flag, cred)
219*39019Smckusick 	register struct vnode *vp;
220*39019Smckusick 	int flag;
221*39019Smckusick 	struct ucred *cred;
222*39019Smckusick {
223*39019Smckusick 	register struct inode *ip = VTOI(vp);
224*39019Smckusick 
225*39019Smckusick 	/*
226*39019Smckusick 	 * On last close of a memory filesystem
227*39019Smckusick 	 * we must invalidate any in core blocks, so that
228*39019Smckusick 	 * we can, free up its vnode.
229*39019Smckusick 	 */
230*39019Smckusick 	bflush(vp->v_mount);
231*39019Smckusick 	if (binval(vp->v_mount))
232*39019Smckusick 		return (0);
233*39019Smckusick 	/*
234*39019Smckusick 	 * We don't want to really close the device if it is still
235*39019Smckusick 	 * in use. Since every use (buffer, inode, swap, cmap)
236*39019Smckusick 	 * holds a reference to the vnode, and because we ensure
237*39019Smckusick 	 * that there cannot be more than one vnode per device,
238*39019Smckusick 	 * we need only check that we are down to the last
239*39019Smckusick 	 * reference before closing.
240*39019Smckusick 	 */
241*39019Smckusick 	if (vp->v_count > 1) {
242*39019Smckusick 		printf("mfs_close: ref count %d > 1\n", vp->v_count);
243*39019Smckusick 		return (0);
244*39019Smckusick 	}
245*39019Smckusick 	/*
246*39019Smckusick 	 * Send a request to the filesystem server to exit.
247*39019Smckusick 	 */
248*39019Smckusick 	ILOCK(ip);
249*39019Smckusick 	ip->i_spare[0] = 0;
250*39019Smckusick 	wakeup((caddr_t)vp);
251*39019Smckusick 	IUNLOCK(ip);
252*39019Smckusick 	return (0);
253*39019Smckusick }
254*39019Smckusick 
255*39019Smckusick /*
256*39019Smckusick  * Block device bad operation
257*39019Smckusick  */
258*39019Smckusick mfs_badop()
259*39019Smckusick {
260*39019Smckusick 
261*39019Smckusick 	printf("mfs_badop called\n");
262*39019Smckusick 	return (ENXIO);
263*39019Smckusick }
264*39019Smckusick 
265*39019Smckusick /*
266*39019Smckusick  * Block device null operation
267*39019Smckusick  */
268*39019Smckusick mfs_nullop()
269*39019Smckusick {
270*39019Smckusick 
271*39019Smckusick 	return (0);
272*39019Smckusick }
273*39019Smckusick 
274*39019Smckusick /*
275*39019Smckusick  * Memory based filesystem initialization.
276*39019Smckusick  */
277*39019Smckusick mfs_init()
278*39019Smckusick {
279*39019Smckusick 
280*39019Smckusick 	rminit(mfsmap, (long)MFS_MAPREG, (long)1, "mfs mapreg", MFS_MAPSIZE);
281*39019Smckusick }
282