Commit | Line | Data |
---|---|---|
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 | * | |
a3e73aa4 | 17 | * @(#)mfs_vnops.c 7.4 (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 |
36 | static int mfsmap_want; /* 1 => need kernel I/O resources */ |
37 | struct map mfsmap[MFS_MAPSIZE]; | |
38 | extern char mfsiobuf[]; | |
39 | ||
40 | /* | |
41 | * mfs vnode operations. | |
42 | */ | |
43 | int mfs_open(), | |
44 | mfs_strategy(), | |
45 | mfs_ioctl(), | |
46 | mfs_close(), | |
a3e73aa4 | 47 | mfs_inactive(), |
a3017777 KM |
48 | mfs_badop(), |
49 | mfs_nullop(); | |
50 | ||
51 | struct 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 */ | |
92 | mfs_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 */ | |
109 | mfs_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 | */ | |
123 | mfs_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 | */ | |
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 | ||
213 | /* | |
214 | * Memory filesystem close routine | |
215 | */ | |
216 | /* ARGSUSED */ | |
217 | mfs_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 */ | |
258 | mfs_inactive(vp) | |
259 | struct vnode *vp; | |
260 | { | |
261 | ||
262 | if (VTOMFS(vp)->mfs_buflist != (struct buf *)(-1)) | |
263 | panic("mfs_inactive: not inactive"); | |
264 | vp->v_type = VNON; | |
265 | return (0); | |
266 | } | |
267 | ||
a3017777 KM |
268 | /* |
269 | * Block device bad operation | |
270 | */ | |
271 | mfs_badop() | |
272 | { | |
273 | ||
a3e73aa4 KM |
274 | panic("mfs_badop called\n"); |
275 | /* NOTREACHED */ | |
a3017777 KM |
276 | } |
277 | ||
278 | /* | |
279 | * Block device null operation | |
280 | */ | |
281 | mfs_nullop() | |
282 | { | |
283 | ||
284 | return (0); | |
285 | } | |
286 | ||
287 | /* | |
288 | * Memory based filesystem initialization. | |
289 | */ | |
290 | mfs_init() | |
291 | { | |
292 | ||
293 | rminit(mfsmap, (long)MFS_MAPREG, (long)1, "mfs mapreg", MFS_MAPSIZE); | |
294 | } |