only vrele can delete the v_type field
[unix-history] / usr / src / sys / ufs / mfs / mfs_vnops.c
CommitLineData
a3017777
KM
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 *
15324dae 17 * @(#)mfs_vnops.c 7.5 (Berkeley) %G%
a3017777
KM
18 */
19
20#include "param.h"
21#include "time.h"
ba72b75d 22#include "kernel.h"
a3017777 23#include "proc.h"
ba72b75d 24#include "user.h"
a3017777
KM
25#include "buf.h"
26#include "vmmac.h"
27#include "errno.h"
28#include "map.h"
29#include "vnode.h"
a3e73aa4 30#include "../ufs/mfsnode.h"
a3017777
KM
31#include "../ufs/mfsiom.h"
32#include "../machine/vmparam.h"
33#include "../machine/pte.h"
34#include "../machine/mtpr.h"
35
a3017777
KM
36static int mfsmap_want; /* 1 => need kernel I/O resources */
37struct map mfsmap[MFS_MAPSIZE];
38extern char mfsiobuf[];
39
40/*
41 * mfs vnode operations.
42 */
43int mfs_open(),
44 mfs_strategy(),
45 mfs_ioctl(),
46 mfs_close(),
a3e73aa4 47 mfs_inactive(),
a3017777
KM
48 mfs_badop(),
49 mfs_nullop();
50
51struct vnodeops mfs_vnodeops = {
52 mfs_badop,
53 mfs_badop,
54 mfs_badop,
55 mfs_open,
56 mfs_close,
57 mfs_badop,
58 mfs_badop,
59 mfs_badop,
60 mfs_badop,
61 mfs_badop,
62 mfs_ioctl,
63 mfs_badop,
64 mfs_badop,
65 mfs_badop,
66 mfs_badop,
67 mfs_badop,
68 mfs_badop,
69 mfs_badop,
70 mfs_badop,
71 mfs_badop,
72 mfs_badop,
73 mfs_badop,
74 mfs_badop,
75 mfs_badop,
a3e73aa4
KM
76 mfs_inactive,
77 mfs_nullop,
a3017777
KM
78 mfs_badop,
79 mfs_badop,
80 mfs_badop,
81 mfs_strategy,
82};
83
84/*
85 * Vnode Operations.
86 *
87 * Open called to allow memory filesystem to initialize and
ba72b75d
KM
88 * validate before actual IO. Record our process identifier
89 * so we can tell when we are doing I/O to ourself.
a3017777
KM
90 */
91/* ARGSUSED */
92mfs_open(vp, mode, cred)
93 register struct vnode *vp;
94 int mode;
95 struct ucred *cred;
96{
97
98 if (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 */
109mfs_ioctl(vp, com, data, fflag, cred)
110 struct vnode *vp;
111 int com;
112 caddr_t data;
113 int fflag;
114 struct ucred *cred;
115{
116
117 return (-1);
118}
119
120/*
121 * Pass I/O requests to the memory filesystem process.
122 */
123mfs_strategy(bp)
124 register struct buf *bp;
125{
a3e73aa4 126 register struct mfsnode *mfsp = VTOMFS(bp->b_vp);
a3017777 127
a3e73aa4
KM
128 if (mfsp->mfs_pid == u.u_procp->p_pid) {
129 mfs_doio(bp, mfsp->mfs_baseoff);
a3017777 130 } else {
a3e73aa4
KM
131 bp->av_forw = mfsp->mfs_buflist;
132 mfsp->mfs_buflist = bp;
a3017777
KM
133 wakeup((caddr_t)bp->b_vp);
134 }
ba72b75d 135 return (0);
a3017777
KM
136}
137
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 */
146mfs_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
213/*
214 * Memory filesystem close routine
215 */
216/* ARGSUSED */
217mfs_close(vp, flag, cred)
218 register struct vnode *vp;
219 int flag;
220 struct ucred *cred;
221{
a3e73aa4 222 register struct mfsnode *mfsp = VTOMFS(vp);
a3017777
KM
223
224 /*
225 * On last close of a memory filesystem
226 * we must invalidate any in core blocks, so that
227 * we can, free up its vnode.
228 */
229 bflush(vp->v_mount);
230 if (binval(vp->v_mount))
231 return (0);
232 /*
233 * We don't want to really close the device if it is still
234 * in use. Since every use (buffer, inode, swap, cmap)
235 * holds a reference to the vnode, and because we ensure
236 * that there cannot be more than one vnode per device,
237 * we need only check that we are down to the last
238 * reference before closing.
239 */
240 if (vp->v_count > 1) {
241 printf("mfs_close: ref count %d > 1\n", vp->v_count);
242 return (0);
243 }
244 /*
245 * Send a request to the filesystem server to exit.
246 */
a3e73aa4 247 while (mfsp->mfs_buflist)
ba72b75d 248 sleep(&lbolt);
a3e73aa4 249 mfsp->mfs_buflist = (struct buf *)(-1);
a3017777 250 wakeup((caddr_t)vp);
a3017777
KM
251 return (0);
252}
253
a3e73aa4
KM
254/*
255 * Memory filesystem inactive routine
256 */
257/* ARGSUSED */
258mfs_inactive(vp)
259 struct vnode *vp;
260{
261
262 if (VTOMFS(vp)->mfs_buflist != (struct buf *)(-1))
263 panic("mfs_inactive: not inactive");
a3e73aa4
KM
264 return (0);
265}
266
a3017777
KM
267/*
268 * Block device bad operation
269 */
270mfs_badop()
271{
272
a3e73aa4
KM
273 panic("mfs_badop called\n");
274 /* NOTREACHED */
a3017777
KM
275}
276
277/*
278 * Block device null operation
279 */
280mfs_nullop()
281{
282
283 return (0);
284}
285
286/*
287 * Memory based filesystem initialization.
288 */
289mfs_init()
290{
291
292 rminit(mfsmap, (long)MFS_MAPREG, (long)1, "mfs mapreg", MFS_MAPSIZE);
293}