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 | * | |
f317c143 | 17 | * @(#)mfs_vnops.c 7.7 (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 | 31 | #include "../ufs/mfsiom.h" |
f317c143 KM |
32 | #include "machine/vmparam.h" |
33 | #include "machine/pte.h" | |
34 | #include "machine/mtpr.h" | |
a3017777 | 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); |
5350b6c1 | 223 | register struct buf *bp; |
a3017777 | 224 | |
5350b6c1 KM |
225 | /* |
226 | * Finish any pending I/O requests. | |
227 | */ | |
228 | while (bp = mfsp->mfs_buflist) { | |
229 | mfsp->mfs_buflist = bp->av_forw; | |
230 | mfs_doio(bp, mfsp->mfs_baseoff); | |
231 | wakeup((caddr_t)bp); | |
232 | } | |
a3017777 KM |
233 | /* |
234 | * On last close of a memory filesystem | |
235 | * we must invalidate any in core blocks, so that | |
236 | * we can, free up its vnode. | |
237 | */ | |
238 | bflush(vp->v_mount); | |
239 | if (binval(vp->v_mount)) | |
240 | return (0); | |
241 | /* | |
5350b6c1 KM |
242 | * There should be no way to have any more uses of this |
243 | * vnode, so if we find any other uses, it is a panic. | |
a3017777 | 244 | */ |
5350b6c1 | 245 | if (vp->v_count > 1) |
a3017777 | 246 | printf("mfs_close: ref count %d > 1\n", vp->v_count); |
5350b6c1 KM |
247 | if (vp->v_count > 1 || mfsp->mfs_buflist) |
248 | panic("mfs_close"); | |
a3017777 KM |
249 | /* |
250 | * Send a request to the filesystem server to exit. | |
251 | */ | |
a3e73aa4 | 252 | mfsp->mfs_buflist = (struct buf *)(-1); |
a3017777 | 253 | wakeup((caddr_t)vp); |
a3017777 KM |
254 | return (0); |
255 | } | |
256 | ||
a3e73aa4 KM |
257 | /* |
258 | * Memory filesystem inactive routine | |
259 | */ | |
260 | /* ARGSUSED */ | |
261 | mfs_inactive(vp) | |
262 | struct vnode *vp; | |
263 | { | |
264 | ||
265 | if (VTOMFS(vp)->mfs_buflist != (struct buf *)(-1)) | |
266 | panic("mfs_inactive: not inactive"); | |
a3e73aa4 KM |
267 | return (0); |
268 | } | |
269 | ||
a3017777 KM |
270 | /* |
271 | * Block device bad operation | |
272 | */ | |
273 | mfs_badop() | |
274 | { | |
275 | ||
a3e73aa4 KM |
276 | panic("mfs_badop called\n"); |
277 | /* NOTREACHED */ | |
a3017777 KM |
278 | } |
279 | ||
280 | /* | |
281 | * Block device null operation | |
282 | */ | |
283 | mfs_nullop() | |
284 | { | |
285 | ||
286 | return (0); | |
287 | } | |
288 | ||
289 | /* | |
290 | * Memory based filesystem initialization. | |
291 | */ | |
292 | mfs_init() | |
293 | { | |
294 | ||
295 | rminit(mfsmap, (long)MFS_MAPREG, (long)1, "mfs mapreg", MFS_MAPSIZE); | |
296 | } |