Deleted Added
full compact
vnode_pager.c (4797) vnode_pager.c (5455)
1/*
2 * Copyright (c) 1990 University of Utah.
3 * Copyright (c) 1991 The Regents of the University of California.
4 * All rights reserved.
5 * Copyright (c) 1993,1994 John S. Dyson
6 *
7 * This code is derived from software contributed to Berkeley by
8 * the Systems Programming Group of the University of Utah Computer

--- 23 unchanged lines hidden (view full) ---

32 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
33 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
34 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
35 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
36 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
37 * SUCH DAMAGE.
38 *
39 * from: @(#)vnode_pager.c 7.5 (Berkeley) 4/20/91
1/*
2 * Copyright (c) 1990 University of Utah.
3 * Copyright (c) 1991 The Regents of the University of California.
4 * All rights reserved.
5 * Copyright (c) 1993,1994 John S. Dyson
6 *
7 * This code is derived from software contributed to Berkeley by
8 * the Systems Programming Group of the University of Utah Computer

--- 23 unchanged lines hidden (view full) ---

32 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
33 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
34 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
35 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
36 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
37 * SUCH DAMAGE.
38 *
39 * from: @(#)vnode_pager.c 7.5 (Berkeley) 4/20/91
40 * $Id: vnode_pager.c,v 1.17 1994/11/17 01:22:45 gibbs Exp $
40 * $Id: vnode_pager.c,v 1.18 1994/11/24 14:43:22 davidg Exp $
41 */
42
43/*
44 * Page to/from files (vnodes).
45 *
46 * TODO:
47 * pageouts
48 * fix credential use (uses current process credentials now)

--- 14 unchanged lines hidden (view full) ---

63 * 1) Totally bypass buffer cache for reads
64 * (Currently will still sometimes use buffer cache for reads)
65 * 2) Bypass buffer cache for writes
66 * (Code does not support it, but mods are simple)
67 */
68
69#include <sys/param.h>
70#include <sys/systm.h>
41 */
42
43/*
44 * Page to/from files (vnodes).
45 *
46 * TODO:
47 * pageouts
48 * fix credential use (uses current process credentials now)

--- 14 unchanged lines hidden (view full) ---

63 * 1) Totally bypass buffer cache for reads
64 * (Currently will still sometimes use buffer cache for reads)
65 * 2) Bypass buffer cache for writes
66 * (Code does not support it, but mods are simple)
67 */
68
69#include <sys/param.h>
70#include <sys/systm.h>
71#include <sys/kernel.h>
71#include <sys/proc.h>
72#include <sys/malloc.h>
73#include <sys/vnode.h>
74#include <sys/uio.h>
75#include <sys/mount.h>
76
77#include <vm/vm.h>
78#include <vm/vm_page.h>
79#include <vm/vnode_pager.h>
80
81#include <sys/buf.h>
82#include <miscfs/specfs/specdev.h>
83
72#include <sys/proc.h>
73#include <sys/malloc.h>
74#include <sys/vnode.h>
75#include <sys/uio.h>
76#include <sys/mount.h>
77
78#include <vm/vm.h>
79#include <vm/vm_page.h>
80#include <vm/vnode_pager.h>
81
82#include <sys/buf.h>
83#include <miscfs/specfs/specdev.h>
84
84int vnode_pager_putmulti();
85int vnode_pager_putmulti();
85
86
86void vnode_pager_init();
87void vnode_pager_init();
87vm_pager_t vnode_pager_alloc(caddr_t, vm_offset_t, vm_prot_t, vm_offset_t);
88vm_pager_t vnode_pager_alloc(caddr_t, vm_offset_t, vm_prot_t, vm_offset_t);
88void vnode_pager_dealloc();
89int vnode_pager_getpage();
90int vnode_pager_getmulti();
91int vnode_pager_putpage();
89void vnode_pager_dealloc();
90int vnode_pager_getpage();
91int vnode_pager_getmulti();
92int vnode_pager_putpage();
92boolean_t vnode_pager_haspage();
93
94struct pagerops vnodepagerops = {
95 vnode_pager_init,
96 vnode_pager_alloc,
97 vnode_pager_dealloc,
98 vnode_pager_getpage,
99 vnode_pager_getmulti,

--- 27 unchanged lines hidden (view full) ---

127vnode_pager_alloc(handle, size, prot, offset)
128 caddr_t handle;
129 vm_size_t size;
130 vm_prot_t prot;
131 vm_offset_t offset;
132{
133 register vm_pager_t pager;
134 register vn_pager_t vnp;
93boolean_t vnode_pager_haspage();
94
95struct pagerops vnodepagerops = {
96 vnode_pager_init,
97 vnode_pager_alloc,
98 vnode_pager_dealloc,
99 vnode_pager_getpage,
100 vnode_pager_getmulti,

--- 27 unchanged lines hidden (view full) ---

128vnode_pager_alloc(handle, size, prot, offset)
129 caddr_t handle;
130 vm_size_t size;
131 vm_prot_t prot;
132 vm_offset_t offset;
133{
134 register vm_pager_t pager;
135 register vn_pager_t vnp;
135 vm_object_t object;
136 vm_object_t object, tobject;
136 struct vattr vattr;
137 struct vnode *vp;
138 struct proc *p = curproc; /* XXX */
137 struct vattr vattr;
138 struct vnode *vp;
139 struct proc *p = curproc; /* XXX */
140 int rtval;
139
140 /*
141 * Pageout to vnode, no can do yet.
142 */
143 if (handle == NULL)
144 return (NULL);
145
146 /*
147 * Vnodes keep a pointer to any associated pager so no need to lookup
148 * with vm_pager_lookup.
149 */
150 vp = (struct vnode *) handle;
141
142 /*
143 * Pageout to vnode, no can do yet.
144 */
145 if (handle == NULL)
146 return (NULL);
147
148 /*
149 * Vnodes keep a pointer to any associated pager so no need to lookup
150 * with vm_pager_lookup.
151 */
152 vp = (struct vnode *) handle;
151 object = (vm_object_t) vp->v_vmdata;
153 while ((object = (vm_object_t) vp->v_vmdata) && (object->flags & OBJ_DEAD))
154 tsleep((caddr_t) object, PVM, "vadead", 0);
155
152 pager = NULL;
156 pager = NULL;
153 if( object != NULL)
157 if (object != NULL)
154 pager = object->pager;
155 if (pager == NULL) {
156
157 /*
158 * Allocate pager structures
159 */
160 pager = (vm_pager_t) malloc(sizeof *pager, M_VMPAGER, M_WAITOK);
161 if (pager == NULL)
162 return (NULL);
163 vnp = (vn_pager_t) malloc(sizeof *vnp, M_VMPGDATA, M_WAITOK);
164 if (vnp == NULL) {
165 free((caddr_t) pager, M_VMPAGER);
166 return (NULL);
167 }
158 pager = object->pager;
159 if (pager == NULL) {
160
161 /*
162 * Allocate pager structures
163 */
164 pager = (vm_pager_t) malloc(sizeof *pager, M_VMPAGER, M_WAITOK);
165 if (pager == NULL)
166 return (NULL);
167 vnp = (vn_pager_t) malloc(sizeof *vnp, M_VMPGDATA, M_WAITOK);
168 if (vnp == NULL) {
169 free((caddr_t) pager, M_VMPAGER);
170 return (NULL);
171 }
168
169 /*
170 * And an object of the appropriate size
171 */
172 /*
173 * And an object of the appropriate size
174 */
172 if (VOP_GETATTR(vp, &vattr, p->p_ucred, p) == 0) {
175 if ((rtval = VOP_GETATTR(vp, &vattr, p->p_ucred, p)) == 0) {
173 object = vm_object_allocate(round_page(vattr.va_size));
174 vm_object_enter(object, pager);
175 vm_object_setpager(object, pager, 0, TRUE);
176 } else {
176 object = vm_object_allocate(round_page(vattr.va_size));
177 vm_object_enter(object, pager);
178 vm_object_setpager(object, pager, 0, TRUE);
179 } else {
180 printf("Error in getattr: %d\n", rtval);
177 free((caddr_t) vnp, M_VMPGDATA);
178 free((caddr_t) pager, M_VMPAGER);
179 return (NULL);
180 }
181
182 /*
183 * Hold a reference to the vnode and initialize pager data.
184 */

--- 20 unchanged lines hidden (view full) ---

205}
206
207void
208vnode_pager_dealloc(pager)
209 vm_pager_t pager;
210{
211 register vn_pager_t vnp = (vn_pager_t) pager->pg_data;
212 register struct vnode *vp;
181 free((caddr_t) vnp, M_VMPGDATA);
182 free((caddr_t) pager, M_VMPAGER);
183 return (NULL);
184 }
185
186 /*
187 * Hold a reference to the vnode and initialize pager data.
188 */

--- 20 unchanged lines hidden (view full) ---

209}
210
211void
212vnode_pager_dealloc(pager)
213 vm_pager_t pager;
214{
215 register vn_pager_t vnp = (vn_pager_t) pager->pg_data;
216 register struct vnode *vp;
217 vm_object_t object;
213
214 vp = vnp->vnp_vp;
215 if (vp) {
218
219 vp = vnp->vnp_vp;
220 if (vp) {
221 int s = splbio();
222
223 object = (vm_object_t) vp->v_vmdata;
224 if (object) {
225 while (object->paging_in_progress) {
226 tsleep(object, PVM, "vnpdea", 0);
227 }
228 }
229 splx(s);
230
216 vp->v_vmdata = NULL;
231 vp->v_vmdata = NULL;
217 vp->v_flag &= ~(VTEXT|VVMIO);
232 vp->v_flag &= ~(VTEXT | VVMIO);
218 vrele(vp);
219 }
220 TAILQ_REMOVE(&vnode_pager_list, pager, pg_list);
221 free((caddr_t) vnp, M_VMPGDATA);
222 free((caddr_t) pager, M_VMPAGER);
223}
224
225int
226vnode_pager_getmulti(pager, m, count, reqpage, sync)
227 vm_pager_t pager;
228 vm_page_t *m;
233 vrele(vp);
234 }
235 TAILQ_REMOVE(&vnode_pager_list, pager, pg_list);
236 free((caddr_t) vnp, M_VMPGDATA);
237 free((caddr_t) pager, M_VMPAGER);
238}
239
240int
241vnode_pager_getmulti(pager, m, count, reqpage, sync)
242 vm_pager_t pager;
243 vm_page_t *m;
229 int count;
230 int reqpage;
244 int count;
245 int reqpage;
231 boolean_t sync;
232{
233
234 return vnode_pager_input((vn_pager_t) pager->pg_data, m, count, reqpage);
235}
236
237int
238vnode_pager_getpage(pager, m, sync)

--- 13 unchanged lines hidden (view full) ---

252
253boolean_t
254vnode_pager_putpage(pager, m, sync)
255 vm_pager_t pager;
256 vm_page_t m;
257 boolean_t sync;
258{
259 vm_page_t marray[1];
246 boolean_t sync;
247{
248
249 return vnode_pager_input((vn_pager_t) pager->pg_data, m, count, reqpage);
250}
251
252int
253vnode_pager_getpage(pager, m, sync)

--- 13 unchanged lines hidden (view full) ---

267
268boolean_t
269vnode_pager_putpage(pager, m, sync)
270 vm_pager_t pager;
271 vm_page_t m;
272 boolean_t sync;
273{
274 vm_page_t marray[1];
260 int rtvals[1];
275 int rtvals[1];
261
262 if (pager == NULL)
263 return FALSE;
264 marray[0] = m;
265 vnode_pager_output((vn_pager_t) pager->pg_data, marray, 1, rtvals);
266 return rtvals[0];
267}
268
269int
270vnode_pager_putmulti(pager, m, c, sync, rtvals)
271 vm_pager_t pager;
272 vm_page_t *m;
276
277 if (pager == NULL)
278 return FALSE;
279 marray[0] = m;
280 vnode_pager_output((vn_pager_t) pager->pg_data, marray, 1, rtvals);
281 return rtvals[0];
282}
283
284int
285vnode_pager_putmulti(pager, m, c, sync, rtvals)
286 vm_pager_t pager;
287 vm_page_t *m;
273 int c;
288 int c;
274 boolean_t sync;
289 boolean_t sync;
275 int *rtvals;
290 int *rtvals;
276{
277 return vnode_pager_output((vn_pager_t) pager->pg_data, m, c, rtvals);
278}
279
280
281boolean_t
282vnode_pager_haspage(pager, offset)
283 vm_pager_t pager;
284 vm_offset_t offset;
285{
286 register vn_pager_t vnp = (vn_pager_t) pager->pg_data;
287 register struct vnode *vp = vnp->vnp_vp;
288 daddr_t bn;
291{
292 return vnode_pager_output((vn_pager_t) pager->pg_data, m, c, rtvals);
293}
294
295
296boolean_t
297vnode_pager_haspage(pager, offset)
298 vm_pager_t pager;
299 vm_offset_t offset;
300{
301 register vn_pager_t vnp = (vn_pager_t) pager->pg_data;
302 register struct vnode *vp = vnp->vnp_vp;
303 daddr_t bn;
289 int err;
304 int err;
290 daddr_t block;
291
292 /*
305 daddr_t block;
306
307 /*
293 * If filesystem no longer mounted or offset beyond end of
294 * file we do not have the page.
308 * If filesystem no longer mounted or offset beyond end of file we do
309 * not have the page.
295 */
296 if ((vp->v_mount == NULL) || (offset >= vnp->vnp_size))
297 return FALSE;
298
299 block = offset / vp->v_mount->mnt_stat.f_iosize;
300 if (incore(vp, block))
301 return TRUE;
302 /*
303 * Read the index to find the disk block to read from. If there is no
304 * block, report that we don't have this data.
305 *
306 * Assumes that the vnode has whole page or nothing.
307 */
308 err = VOP_BMAP(vp, block, (struct vnode **) 0, &bn, 0);
310 */
311 if ((vp->v_mount == NULL) || (offset >= vnp->vnp_size))
312 return FALSE;
313
314 block = offset / vp->v_mount->mnt_stat.f_iosize;
315 if (incore(vp, block))
316 return TRUE;
317 /*
318 * Read the index to find the disk block to read from. If there is no
319 * block, report that we don't have this data.
320 *
321 * Assumes that the vnode has whole page or nothing.
322 */
323 err = VOP_BMAP(vp, block, (struct vnode **) 0, &bn, 0);
309/*
310 printf("vnode_pager_haspage: (%d)0x%x: err: %d, bn: %d\n",
311 offset, offset, err, bn);
312*/
313 if (err) {
324 if (err)
314 return (TRUE);
325 return (TRUE);
315 }
316 return ((long) bn < 0 ? FALSE : TRUE);
317}
318
319/*
320 * Lets the VM system know about a change in size for a file.
321 * If this vnode is mapped into some address space (i.e. we have a pager
322 * for it) we adjust our own internal size and flush any cached pages in
323 * the associated object that are affected by the size change.
324 *
325 * Note: this routine may be invoked as a result of a pager put
326 * operation (possibly at object termination time), so we must be careful.
327 */
328void
329vnode_pager_setsize(vp, nsize)
330 struct vnode *vp;
326 return ((long) bn < 0 ? FALSE : TRUE);
327}
328
329/*
330 * Lets the VM system know about a change in size for a file.
331 * If this vnode is mapped into some address space (i.e. we have a pager
332 * for it) we adjust our own internal size and flush any cached pages in
333 * the associated object that are affected by the size change.
334 *
335 * Note: this routine may be invoked as a result of a pager put
336 * operation (possibly at object termination time), so we must be careful.
337 */
338void
339vnode_pager_setsize(vp, nsize)
340 struct vnode *vp;
331 u_long nsize;
341 u_long nsize;
332{
333 register vn_pager_t vnp;
334 register vm_object_t object;
335 vm_pager_t pager;
336
337 /*
338 * Not a mapped vnode
339 */
340 if (vp == NULL || vp->v_type != VREG || vp->v_vmdata == NULL)
341 return;
342
343 /*
344 * Hasn't changed size
345 */
346 object = (vm_object_t) vp->v_vmdata;
342{
343 register vn_pager_t vnp;
344 register vm_object_t object;
345 vm_pager_t pager;
346
347 /*
348 * Not a mapped vnode
349 */
350 if (vp == NULL || vp->v_type != VREG || vp->v_vmdata == NULL)
351 return;
352
353 /*
354 * Hasn't changed size
355 */
356 object = (vm_object_t) vp->v_vmdata;
347 if( object == NULL)
357 if (object == NULL)
348 return;
358 return;
349 if( (pager = object->pager) == NULL)
359 if ((pager = object->pager) == NULL)
350 return;
351 vnp = (vn_pager_t) pager->pg_data;
352 if (nsize == vnp->vnp_size)
353 return;
354
355 /*
356 * No object. This can happen during object termination since
357 * vm_object_page_clean is called after the object has been removed
358 * from the hash table, and clean may cause vnode write operations
359 * which can wind up back here.
360 */
361 object = vm_object_lookup(pager);
362 if (object == NULL)
363 return;
364
365 /*
366 * File has shrunk. Toss any cached pages beyond the new EOF.
367 */
368 if (nsize < vnp->vnp_size) {
360 return;
361 vnp = (vn_pager_t) pager->pg_data;
362 if (nsize == vnp->vnp_size)
363 return;
364
365 /*
366 * No object. This can happen during object termination since
367 * vm_object_page_clean is called after the object has been removed
368 * from the hash table, and clean may cause vnode write operations
369 * which can wind up back here.
370 */
371 object = vm_object_lookup(pager);
372 if (object == NULL)
373 return;
374
375 /*
376 * File has shrunk. Toss any cached pages beyond the new EOF.
377 */
378 if (nsize < vnp->vnp_size) {
369 vm_object_lock(object);
370 vm_object_page_remove(object,
371 round_page((vm_offset_t) nsize), vnp->vnp_size);
372 vm_object_unlock(object);
373
379 if (round_page((vm_offset_t) nsize) < vnp->vnp_size) {
380 vm_object_lock(object);
381 vm_object_page_remove(object,
382 round_page((vm_offset_t) nsize), vnp->vnp_size);
383 vm_object_unlock(object);
384 }
374 /*
375 * this gets rid of garbage at the end of a page that is now
376 * only partially backed by the vnode...
377 */
378 if (nsize & PAGE_MASK) {
379 vm_offset_t kva;
380 vm_page_t m;
381
382 m = vm_page_lookup(object, trunc_page((vm_offset_t) nsize));
383 if (m) {
384 kva = vm_pager_map_page(m);
385 bzero((caddr_t) kva + (nsize & PAGE_MASK),
385 /*
386 * this gets rid of garbage at the end of a page that is now
387 * only partially backed by the vnode...
388 */
389 if (nsize & PAGE_MASK) {
390 vm_offset_t kva;
391 vm_page_t m;
392
393 m = vm_page_lookup(object, trunc_page((vm_offset_t) nsize));
394 if (m) {
395 kva = vm_pager_map_page(m);
396 bzero((caddr_t) kva + (nsize & PAGE_MASK),
386 round_page(nsize) - nsize);
397 round_page(nsize) - nsize);
387 vm_pager_unmap_page(kva);
388 }
389 }
398 vm_pager_unmap_page(kva);
399 }
400 }
390 } else {
391
392 /*
393 * this allows the filesystem and VM cache to stay in sync if
394 * the VM page hasn't been modified... After the page is
395 * removed -- it will be faulted back in from the filesystem
396 * cache.
397 */
398 if (vnp->vnp_size & PAGE_MASK) {
399 vm_page_t m;
400
401 m = vm_page_lookup(object, trunc_page(vnp->vnp_size));
402 if (m && (m->flags & PG_CLEAN)) {
403 vm_object_lock(object);
404 vm_object_page_remove(object,
405 vnp->vnp_size, vnp->vnp_size);
406 vm_object_unlock(object);
407 }
408 }
409 }
410 vnp->vnp_size = (vm_offset_t) nsize;
411 object->size = round_page(nsize);
412
413 vm_object_deallocate(object);
414}
415
416void

--- 31 unchanged lines hidden (view full) ---

448 register vm_object_t object;
449 boolean_t uncached, locked;
450 vm_pager_t pager;
451
452 /*
453 * Not a mapped vnode
454 */
455 object = (vm_object_t) vp->v_vmdata;
401 }
402 vnp->vnp_size = (vm_offset_t) nsize;
403 object->size = round_page(nsize);
404
405 vm_object_deallocate(object);
406}
407
408void

--- 31 unchanged lines hidden (view full) ---

440 register vm_object_t object;
441 boolean_t uncached, locked;
442 vm_pager_t pager;
443
444 /*
445 * Not a mapped vnode
446 */
447 object = (vm_object_t) vp->v_vmdata;
456 if( object == NULL)
457 return(TRUE);
448 if (object == NULL)
449 return (TRUE);
450
458 pager = object->pager;
459 if (pager == NULL)
460 return (TRUE);
461
462 /*
463 * Unlock the vnode if it is currently locked. We do this since
464 * uncaching the object may result in its destruction which may
465 * initiate paging activity which may necessitate locking the vnode.

--- 30 unchanged lines hidden (view full) ---

496 * calculate the linear (byte) disk address of specified virtual
497 * file address
498 */
499vm_offset_t
500vnode_pager_addr(vp, address)
501 struct vnode *vp;
502 vm_offset_t address;
503{
451 pager = object->pager;
452 if (pager == NULL)
453 return (TRUE);
454
455 /*
456 * Unlock the vnode if it is currently locked. We do this since
457 * uncaching the object may result in its destruction which may
458 * initiate paging activity which may necessitate locking the vnode.

--- 30 unchanged lines hidden (view full) ---

489 * calculate the linear (byte) disk address of specified virtual
490 * file address
491 */
492vm_offset_t
493vnode_pager_addr(vp, address)
494 struct vnode *vp;
495 vm_offset_t address;
496{
504 int rtaddress;
505 int bsize;
497 int rtaddress;
498 int bsize;
506 vm_offset_t block;
507 struct vnode *rtvp;
499 vm_offset_t block;
500 struct vnode *rtvp;
508 int err;
509 int vblock, voffset;
501 int err;
502 int vblock, voffset;
510
503
504 if ((int) address < 0)
505 return -1;
506
511 bsize = vp->v_mount->mnt_stat.f_iosize;
512 vblock = address / bsize;
513 voffset = address % bsize;
514
515 err = VOP_BMAP(vp, vblock, &rtvp, &block, 0);
516
517 if (err)
518 rtaddress = -1;

--- 7 unchanged lines hidden (view full) ---

526 * interrupt routine for I/O completion
527 */
528void
529vnode_pager_iodone(bp)
530 struct buf *bp;
531{
532 bp->b_flags |= B_DONE;
533 wakeup((caddr_t) bp);
507 bsize = vp->v_mount->mnt_stat.f_iosize;
508 vblock = address / bsize;
509 voffset = address % bsize;
510
511 err = VOP_BMAP(vp, vblock, &rtvp, &block, 0);
512
513 if (err)
514 rtaddress = -1;

--- 7 unchanged lines hidden (view full) ---

522 * interrupt routine for I/O completion
523 */
524void
525vnode_pager_iodone(bp)
526 struct buf *bp;
527{
528 bp->b_flags |= B_DONE;
529 wakeup((caddr_t) bp);
534 if( bp->b_flags & B_ASYNC) {
530 if (bp->b_flags & B_ASYNC) {
535 vm_offset_t paddr;
536 vm_page_t m;
537 vm_object_t obj = 0;
538 int i;
539 int npages;
540
541 paddr = (vm_offset_t) bp->b_data;
531 vm_offset_t paddr;
532 vm_page_t m;
533 vm_object_t obj = 0;
534 int i;
535 int npages;
536
537 paddr = (vm_offset_t) bp->b_data;
542 if( bp->b_bufsize != bp->b_bcount)
543 bzero( bp->b_data + bp->b_bcount,
544 bp->b_bufsize - bp->b_bcount);
538 if (bp->b_bufsize != bp->b_bcount)
539 bzero(bp->b_data + bp->b_bcount,
540 bp->b_bufsize - bp->b_bcount);
545
546 npages = (bp->b_bufsize + PAGE_SIZE - 1) / PAGE_SIZE;
541
542 npages = (bp->b_bufsize + PAGE_SIZE - 1) / PAGE_SIZE;
547/*
548 printf("bcount: %d, bufsize: %d, npages: %d\n",
549 bp->b_bcount, bp->b_bufsize, npages);
550*/
551 for( i = 0; i < npages; i++) {
543 for (i = 0; i < npages; i++) {
552 m = PHYS_TO_VM_PAGE(pmap_kextract(paddr + i * PAGE_SIZE));
553 obj = m->object;
544 m = PHYS_TO_VM_PAGE(pmap_kextract(paddr + i * PAGE_SIZE));
545 obj = m->object;
554 if( m) {
555 m->flags |= PG_CLEAN;
556 m->flags &= ~(PG_LAUNDRY|PG_FAKE);
546 if (m) {
547 m->dirty = 0;
548 m->valid = VM_PAGE_BITS_ALL;
549 if (m->flags & PG_WANTED)
550 m->flags |= PG_REFERENCED;
557 PAGE_WAKEUP(m);
558 } else {
559 panic("vnode_pager_iodone: page is gone!!!");
560 }
561 }
551 PAGE_WAKEUP(m);
552 } else {
553 panic("vnode_pager_iodone: page is gone!!!");
554 }
555 }
562 pmap_qremove( paddr, npages);
563 if( obj) {
556 pmap_qremove(paddr, npages);
557 if (obj) {
564 --obj->paging_in_progress;
558 --obj->paging_in_progress;
565 if( obj->paging_in_progress == 0)
559 if (obj->paging_in_progress == 0)
566 wakeup((caddr_t) obj);
567 } else {
568 panic("vnode_pager_iodone: object is gone???");
569 }
560 wakeup((caddr_t) obj);
561 } else {
562 panic("vnode_pager_iodone: object is gone???");
563 }
570 HOLDRELE(bp->b_vp);
571 relpbuf(bp);
572 }
573}
574
575/*
576 * small block file system vnode pager input
577 */
578int
579vnode_pager_input_smlfs(vnp, m)
580 vn_pager_t vnp;
581 vm_page_t m;
582{
564 relpbuf(bp);
565 }
566}
567
568/*
569 * small block file system vnode pager input
570 */
571int
572vnode_pager_input_smlfs(vnp, m)
573 vn_pager_t vnp;
574 vm_page_t m;
575{
583 int i;
584 int s;
585 vm_offset_t paging_offset;
576 int i;
577 int s;
586 struct vnode *dp, *vp;
587 struct buf *bp;
578 struct vnode *dp, *vp;
579 struct buf *bp;
588 vm_offset_t foff;
589 vm_offset_t kva;
580 vm_offset_t kva;
590 int fileaddr;
591 int block;
581 int fileaddr;
582 int block;
592 vm_offset_t bsize;
583 vm_offset_t bsize;
593 int error = 0;
584 int error = 0;
594
585
595 paging_offset = m->object->paging_offset;
596 vp = vnp->vnp_vp;
597 bsize = vp->v_mount->mnt_stat.f_iosize;
586 vp = vnp->vnp_vp;
587 bsize = vp->v_mount->mnt_stat.f_iosize;
598 foff = m->offset + paging_offset;
599
588
600 VOP_BMAP(vp, foff, &dp, 0, 0);
589 VOP_BMAP(vp, 0, &dp, 0, 0);
601
602 kva = vm_pager_map_page(m);
603
604 for (i = 0; i < PAGE_SIZE / bsize; i++) {
605
590
591 kva = vm_pager_map_page(m);
592
593 for (i = 0; i < PAGE_SIZE / bsize; i++) {
594
606 /*
607 * calculate logical block and offset
608 */
609 block = foff / bsize + i;
610 s = splbio();
611 while ((bp = incore(vp, block)) != 0) {
612 int amount;
595 if ((vm_page_bits(m->offset + i * bsize, bsize) & m->valid))
596 continue;
613
597
614 /*
615 * wait until the buffer is avail or gone
616 */
617 if (bp->b_flags & B_BUSY) {
618 bp->b_flags |= B_WANTED;
619 tsleep((caddr_t) bp, PVM, "vnwblk", 0);
620 continue;
621 }
622 amount = bsize;
623 if ((foff + bsize) > vnp->vnp_size)
624 amount = vnp->vnp_size - foff;
625
626 /*
627 * make sure that this page is in the buffer
628 */
629 if ((amount > 0) && amount <= bp->b_bcount) {
630 bp->b_flags |= B_BUSY;
631 splx(s);
632
633 /*
634 * copy the data from the buffer
635 */
636 bcopy(bp->b_un.b_addr, (caddr_t) kva + i * bsize, amount);
637 if (amount < bsize) {
638 bzero((caddr_t) kva + amount, bsize - amount);
639 }
640 bp->b_flags &= ~B_BUSY;
641 wakeup((caddr_t) bp);
642 goto nextblock;
643 }
644 break;
645 }
646 splx(s);
647 fileaddr = vnode_pager_addr(vp, foff + i * bsize);
598 fileaddr = vnode_pager_addr(vp, m->offset + i * bsize);
648 if (fileaddr != -1) {
649 bp = getpbuf();
599 if (fileaddr != -1) {
600 bp = getpbuf();
650 VHOLD(vp);
651
652 /* build a minimal buffer header */
653 bp->b_flags = B_BUSY | B_READ | B_CALL;
654 bp->b_iodone = vnode_pager_iodone;
655 bp->b_proc = curproc;
656 bp->b_rcred = bp->b_wcred = bp->b_proc->p_ucred;
657 if (bp->b_rcred != NOCRED)
658 crhold(bp->b_rcred);
659 if (bp->b_wcred != NOCRED)
660 crhold(bp->b_wcred);
661 bp->b_un.b_addr = (caddr_t) kva + i * bsize;
662 bp->b_blkno = fileaddr / DEV_BSIZE;
601
602 /* build a minimal buffer header */
603 bp->b_flags = B_BUSY | B_READ | B_CALL;
604 bp->b_iodone = vnode_pager_iodone;
605 bp->b_proc = curproc;
606 bp->b_rcred = bp->b_wcred = bp->b_proc->p_ucred;
607 if (bp->b_rcred != NOCRED)
608 crhold(bp->b_rcred);
609 if (bp->b_wcred != NOCRED)
610 crhold(bp->b_wcred);
611 bp->b_un.b_addr = (caddr_t) kva + i * bsize;
612 bp->b_blkno = fileaddr / DEV_BSIZE;
663 bgetvp(dp, bp);
613 pbgetvp(dp, bp);
664 bp->b_bcount = bsize;
665 bp->b_bufsize = bsize;
666
667 /* do the input */
668 VOP_STRATEGY(bp);
669
670 /* we definitely need to be at splbio here */
671

--- 7 unchanged lines hidden (view full) ---

679
680 /*
681 * free the buffer header back to the swap buffer pool
682 */
683 relpbuf(bp);
684 HOLDRELE(vp);
685 if (error)
686 break;
614 bp->b_bcount = bsize;
615 bp->b_bufsize = bsize;
616
617 /* do the input */
618 VOP_STRATEGY(bp);
619
620 /* we definitely need to be at splbio here */
621

--- 7 unchanged lines hidden (view full) ---

629
630 /*
631 * free the buffer header back to the swap buffer pool
632 */
633 relpbuf(bp);
634 HOLDRELE(vp);
635 if (error)
636 break;
637
638 vm_page_set_clean(m, i * bsize, bsize);
639 vm_page_set_valid(m, i * bsize, bsize);
687 } else {
640 } else {
641 vm_page_set_clean(m, i * bsize, bsize);
688 bzero((caddr_t) kva + i * bsize, bsize);
689 }
690nextblock:
691 }
692 vm_pager_unmap_page(kva);
642 bzero((caddr_t) kva + i * bsize, bsize);
643 }
644nextblock:
645 }
646 vm_pager_unmap_page(kva);
647 pmap_clear_modify(VM_PAGE_TO_PHYS(m));
693 if (error) {
694 return VM_PAGER_ERROR;
695 }
648 if (error) {
649 return VM_PAGER_ERROR;
650 }
696 pmap_clear_modify(VM_PAGE_TO_PHYS(m));
697 m->flags |= PG_CLEAN;
698 m->flags &= ~PG_LAUNDRY;
699 return VM_PAGER_OK;
700
701}
702
703
704/*
705 * old style vnode pager output routine
706 */
707int
708vnode_pager_input_old(vnp, m)
709 vn_pager_t vnp;
710 vm_page_t m;
711{
712 struct uio auio;
713 struct iovec aiov;
651 return VM_PAGER_OK;
652
653}
654
655
656/*
657 * old style vnode pager output routine
658 */
659int
660vnode_pager_input_old(vnp, m)
661 vn_pager_t vnp;
662 vm_page_t m;
663{
664 struct uio auio;
665 struct iovec aiov;
714 int error;
715 int size;
716 vm_offset_t foff;
666 int error;
667 int size;
717 vm_offset_t kva;
718
719 error = 0;
668 vm_offset_t kva;
669
670 error = 0;
720 foff = m->offset + m->object->paging_offset;
721
722 /*
723 * Return failure if beyond current EOF
724 */
671
672 /*
673 * Return failure if beyond current EOF
674 */
725 if (foff >= vnp->vnp_size) {
675 if (m->offset >= vnp->vnp_size) {
726 return VM_PAGER_BAD;
727 } else {
728 size = PAGE_SIZE;
676 return VM_PAGER_BAD;
677 } else {
678 size = PAGE_SIZE;
729 if (foff + size > vnp->vnp_size)
730 size = vnp->vnp_size - foff;
731/*
732 * Allocate a kernel virtual address and initialize so that
733 * we can use VOP_READ/WRITE routines.
734 */
679 if (m->offset + size > vnp->vnp_size)
680 size = vnp->vnp_size - m->offset;
681 /*
682 * Allocate a kernel virtual address and initialize so that
683 * we can use VOP_READ/WRITE routines.
684 */
735 kva = vm_pager_map_page(m);
736 aiov.iov_base = (caddr_t) kva;
737 aiov.iov_len = size;
738 auio.uio_iov = &aiov;
739 auio.uio_iovcnt = 1;
685 kva = vm_pager_map_page(m);
686 aiov.iov_base = (caddr_t) kva;
687 aiov.iov_len = size;
688 auio.uio_iov = &aiov;
689 auio.uio_iovcnt = 1;
740 auio.uio_offset = foff;
690 auio.uio_offset = m->offset;
741 auio.uio_segflg = UIO_SYSSPACE;
742 auio.uio_rw = UIO_READ;
743 auio.uio_resid = size;
744 auio.uio_procp = (struct proc *) 0;
745
746 error = VOP_READ(vnp->vnp_vp, &auio, 0, curproc->p_ucred);
747 if (!error) {
748 register int count = size - auio.uio_resid;
749
750 if (count == 0)
751 error = EINVAL;
752 else if (count != PAGE_SIZE)
753 bzero((caddr_t) kva + count, PAGE_SIZE - count);
754 }
755 vm_pager_unmap_page(kva);
756 }
757 pmap_clear_modify(VM_PAGE_TO_PHYS(m));
691 auio.uio_segflg = UIO_SYSSPACE;
692 auio.uio_rw = UIO_READ;
693 auio.uio_resid = size;
694 auio.uio_procp = (struct proc *) 0;
695
696 error = VOP_READ(vnp->vnp_vp, &auio, 0, curproc->p_ucred);
697 if (!error) {
698 register int count = size - auio.uio_resid;
699
700 if (count == 0)
701 error = EINVAL;
702 else if (count != PAGE_SIZE)
703 bzero((caddr_t) kva + count, PAGE_SIZE - count);
704 }
705 vm_pager_unmap_page(kva);
706 }
707 pmap_clear_modify(VM_PAGE_TO_PHYS(m));
758 m->flags |= PG_CLEAN;
759 m->flags &= ~PG_LAUNDRY;
708 m->dirty = 0;
760 return error ? VM_PAGER_ERROR : VM_PAGER_OK;
761}
762
763/*
764 * generic vnode pager input routine
765 */
766int
767vnode_pager_input(vnp, m, count, reqpage)
768 register vn_pager_t vnp;
769 vm_page_t *m;
709 return error ? VM_PAGER_ERROR : VM_PAGER_OK;
710}
711
712/*
713 * generic vnode pager input routine
714 */
715int
716vnode_pager_input(vnp, m, count, reqpage)
717 register vn_pager_t vnp;
718 vm_page_t *m;
770 int count, reqpage;
719 int count, reqpage;
771{
720{
772 int i;
721 int i;
773 vm_offset_t kva, foff;
722 vm_offset_t kva, foff;
774 int size, sizea;
723 int size, sizea;
775 vm_object_t object;
724 vm_object_t object;
776 vm_offset_t paging_offset;
777 struct vnode *dp, *vp;
725 struct vnode *dp, *vp;
778 int bsize;
726 int bsize;
779
727
780 int first, last;
781 int reqaddr, firstaddr;
782 int block, offset;
728 int first, last;
729 int reqaddr, firstaddr;
730 int block, offset;
783
784 struct buf *bp, *bpa;
731
732 struct buf *bp, *bpa;
785 int counta;
786 int s;
787 int failflag;
733 int counta;
734 int s;
735 int failflag;
788
736
789 int error = 0;
737 int error = 0;
790
791 object = m[reqpage]->object; /* all vm_page_t items are in same
792 * object */
738
739 object = m[reqpage]->object; /* all vm_page_t items are in same
740 * object */
793 paging_offset = object->paging_offset;
794
795 vp = vnp->vnp_vp;
741
742 vp = vnp->vnp_vp;
796
797 /*
798 * Make sure underlying filesystem is still mounted.
799 */
800 if (vp->v_mount == NULL)
801 return VM_PAGER_FAIL;
802
803 bsize = vp->v_mount->mnt_stat.f_iosize;
804
805 /* get the UNDERLYING device for the file with VOP_BMAP() */
806
807 /*
808 * originally, we did not check for an error return value -- assuming
809 * an fs always has a bmap entry point -- that assumption is wrong!!!
810 */
743 bsize = vp->v_mount->mnt_stat.f_iosize;
744
745 /* get the UNDERLYING device for the file with VOP_BMAP() */
746
747 /*
748 * originally, we did not check for an error return value -- assuming
749 * an fs always has a bmap entry point -- that assumption is wrong!!!
750 */
811 foff = m[reqpage]->offset + paging_offset;
751 foff = m[reqpage]->offset;
812
813 /*
814 * if we can't bmap, use old VOP code
815 */
752
753 /*
754 * if we can't bmap, use old VOP code
755 */
816 if (VOP_BMAP(vp, foff, &dp, 0, 0)) {
756 if (VOP_BMAP(vp, 0, &dp, 0, 0)) {
817 for (i = 0; i < count; i++) {
818 if (i != reqpage) {
819 vnode_pager_freepage(m[i]);
820 }
821 }
822 cnt.v_vnodein++;
823 cnt.v_vnodepgsin++;
824 return vnode_pager_input_old(vnp, m[reqpage]);
825
826 /*
827 * if the blocksize is smaller than a page size, then use
828 * special small filesystem code. NFS sometimes has a small
829 * blocksize, but it can handle large reads itself.
830 */
831 } else if ((PAGE_SIZE / bsize) > 1 &&
757 for (i = 0; i < count; i++) {
758 if (i != reqpage) {
759 vnode_pager_freepage(m[i]);
760 }
761 }
762 cnt.v_vnodein++;
763 cnt.v_vnodepgsin++;
764 return vnode_pager_input_old(vnp, m[reqpage]);
765
766 /*
767 * if the blocksize is smaller than a page size, then use
768 * special small filesystem code. NFS sometimes has a small
769 * blocksize, but it can handle large reads itself.
770 */
771 } else if ((PAGE_SIZE / bsize) > 1 &&
832 (vp->v_mount->mnt_stat.f_type != MOUNT_NFS)) {
772 (vp->v_mount->mnt_stat.f_type != MOUNT_NFS)) {
833
834 for (i = 0; i < count; i++) {
835 if (i != reqpage) {
836 vnode_pager_freepage(m[i]);
837 }
838 }
839 cnt.v_vnodein++;
840 cnt.v_vnodepgsin++;
841 return vnode_pager_input_smlfs(vnp, m[reqpage]);
842 }
773
774 for (i = 0; i < count; i++) {
775 if (i != reqpage) {
776 vnode_pager_freepage(m[i]);
777 }
778 }
779 cnt.v_vnodein++;
780 cnt.v_vnodepgsin++;
781 return vnode_pager_input_smlfs(vnp, m[reqpage]);
782 }
843/*
844 * here on direct device I/O
845 */
846
847
848#ifdef NOTYET
849 if( (vp->v_flag & VVMIO) == 0) {
850#endif
851 /*
783 /*
852 * This pathetic hack gets data from the buffer cache, if it's there.
853 * I believe that this is not really necessary, and the ends can be
854 * gotten by defaulting to the normal vfs read behavior, but this
855 * might be more efficient, because the will NOT invoke read-aheads
856 * and one of the purposes of this code is to bypass the buffer cache
857 * and keep from flushing it by reading in a program.
784 * if ANY DEV_BSIZE blocks are valid on a large filesystem block
785 * then, the entire page is valid --
858 */
786 */
859
860 /*
861 * calculate logical block and offset
862 */
863 block = foff / bsize;
864 offset = foff % bsize;
865 s = splbio();
866
867 /*
868 * if we have a buffer in core, then try to use it
869 */
870 while ((bp = incore(vp, block)) != 0) {
871 int amount;
872
873 /*
874 * wait until the buffer is avail or gone
875 */
876 if (bp->b_flags & B_BUSY) {
877 bp->b_flags |= B_WANTED;
878 tsleep((caddr_t) bp, PVM, "vnwblk", 0);
879 continue;
880 }
881 amount = PAGE_SIZE;
882 if ((foff + amount) > vnp->vnp_size)
883 amount = vnp->vnp_size - foff;
884
885 /*
886 * make sure that this page is in the buffer
887 */
888 if ((amount > 0) && (offset + amount) <= bp->b_bcount) {
889 bp->b_flags |= B_BUSY;
890 splx(s);
891 kva = kmem_alloc_wait( pager_map, PAGE_SIZE);
892
893 /*
894 * map the requested page
895 */
896 pmap_qenter(kva, &m[reqpage], 1);
897
898 /*
899 * copy the data from the buffer
900 */
901 bcopy(bp->b_un.b_addr + offset, (caddr_t) kva, amount);
902 if (amount < PAGE_SIZE) {
903 bzero((caddr_t) kva + amount, PAGE_SIZE - amount);
904 }
905
906 /*
907 * unmap the page and free the kva
908 */
909 pmap_qremove( kva, 1);
910 kmem_free_wakeup(pager_map, kva, PAGE_SIZE);
911
912 /*
913 * release the buffer back to the block subsystem
914 */
915 bp->b_flags &= ~B_BUSY;
916 wakeup((caddr_t) bp);
917
918 /*
919 * we did not have to do any work to get the requested
920 * page, the read behind/ahead does not justify a read
921 */
922 for (i = 0; i < count; i++) {
923 if (i != reqpage) {
924 vnode_pager_freepage(m[i]);
925 }
926 }
927 count = 1;
928 reqpage = 0;
929 m[0] = m[reqpage];
930
931 /*
932 * sorry for the goto
933 */
934 goto finishup;
935 }
936
937 /*
938 * buffer is nowhere to be found, read from the disk
939 */
940 break;
787 if (m[reqpage]->valid) {
788 m[reqpage]->valid = VM_PAGE_BITS_ALL;
789 for (i = 0; i < count; i++) {
790 if (i != reqpage)
791 vnode_pager_freepage(m[i]);
941 }
792 }
942 splx(s);
943#ifdef NOTYET
793 return VM_PAGER_OK;
944 }
794 }
945#endif
795 /*
796 * here on direct device I/O
797 */
946
947 reqaddr = vnode_pager_addr(vp, foff);
798
799 reqaddr = vnode_pager_addr(vp, foff);
800 if (reqaddr == -1 && foff < vnp->vnp_size) {
801 printf("reqaddr: %d, foff: %d, vnp_size: %d\n",
802 reqaddr, foff, vnp->vnp_size);
803 Debugger("");
804 }
948 s = splbio();
949
950 /*
951 * Make sure that our I/O request is contiguous. Scan backward and
952 * stop for the first discontiguous entry or stop for a page being in
953 * buffer cache.
954 */
955 failflag = 0;
956 first = reqpage;
957 for (i = reqpage - 1; i >= 0; --i) {
958 if (failflag ||
805 s = splbio();
806
807 /*
808 * Make sure that our I/O request is contiguous. Scan backward and
809 * stop for the first discontiguous entry or stop for a page being in
810 * buffer cache.
811 */
812 failflag = 0;
813 first = reqpage;
814 for (i = reqpage - 1; i >= 0; --i) {
815 if (failflag ||
959#ifdef NOTYET
960 ((vp->v_flag & VVMIO) == 0 && incore(vp, (foff + (i - reqpage) * PAGE_SIZE) / bsize)) ||
961#else
962 (incore(vp, (foff + (i - reqpage) * PAGE_SIZE) / bsize)) ||
963#endif
964 (vnode_pager_addr(vp, m[i]->offset + paging_offset))
816 (vnode_pager_addr(vp, m[i]->offset))
965 != reqaddr + (i - reqpage) * PAGE_SIZE) {
966 vnode_pager_freepage(m[i]);
967 failflag = 1;
968 } else {
969 first = i;
970 }
971 }
972
973 /*
974 * Scan forward and stop for the first non-contiguous entry or stop
975 * for a page being in buffer cache.
976 */
977 failflag = 0;
978 last = reqpage + 1;
979 for (i = reqpage + 1; i < count; i++) {
980 if (failflag ||
817 != reqaddr + (i - reqpage) * PAGE_SIZE) {
818 vnode_pager_freepage(m[i]);
819 failflag = 1;
820 } else {
821 first = i;
822 }
823 }
824
825 /*
826 * Scan forward and stop for the first non-contiguous entry or stop
827 * for a page being in buffer cache.
828 */
829 failflag = 0;
830 last = reqpage + 1;
831 for (i = reqpage + 1; i < count; i++) {
832 if (failflag ||
981#ifdef NOTYET
982 ((vp->v_flag & VVMIO) == 0 && incore(vp, (foff + (i - reqpage) * PAGE_SIZE) / bsize)) ||
983#else
984 (incore(vp, (foff + (i - reqpage) * PAGE_SIZE) / bsize)) ||
985#endif
986 (vnode_pager_addr(vp, m[i]->offset + paging_offset))
833 (vnode_pager_addr(vp, m[i]->offset))
987 != reqaddr + (i - reqpage) * PAGE_SIZE) {
988 vnode_pager_freepage(m[i]);
989 failflag = 1;
990 } else {
991 last = i + 1;
992 }
993 }
994 splx(s);

--- 5 unchanged lines hidden (view full) ---

1000 count = last;
1001 if (first != 0) {
1002 for (i = first; i < count; i++) {
1003 m[i - first] = m[i];
1004 }
1005 count -= first;
1006 reqpage -= first;
1007 }
834 != reqaddr + (i - reqpage) * PAGE_SIZE) {
835 vnode_pager_freepage(m[i]);
836 failflag = 1;
837 } else {
838 last = i + 1;
839 }
840 }
841 splx(s);

--- 5 unchanged lines hidden (view full) ---

847 count = last;
848 if (first != 0) {
849 for (i = first; i < count; i++) {
850 m[i - first] = m[i];
851 }
852 count -= first;
853 reqpage -= first;
854 }
1008
1009 /*
1010 * calculate the file virtual address for the transfer
1011 */
855 /*
856 * calculate the file virtual address for the transfer
857 */
1012 foff = m[0]->offset + paging_offset;
858 foff = m[0]->offset;
1013
1014 /*
1015 * and get the disk physical address (in bytes)
1016 */
1017 firstaddr = vnode_pager_addr(vp, foff);
1018
1019 /*
1020 * calculate the size of the transfer

--- 4 unchanged lines hidden (view full) ---

1025
1026 /*
1027 * round up physical size for real devices
1028 */
1029 if (dp->v_type == VBLK || dp->v_type == VCHR)
1030 size = (size + DEV_BSIZE - 1) & ~(DEV_BSIZE - 1);
1031
1032 counta = 0;
859
860 /*
861 * and get the disk physical address (in bytes)
862 */
863 firstaddr = vnode_pager_addr(vp, foff);
864
865 /*
866 * calculate the size of the transfer

--- 4 unchanged lines hidden (view full) ---

871
872 /*
873 * round up physical size for real devices
874 */
875 if (dp->v_type == VBLK || dp->v_type == VCHR)
876 size = (size + DEV_BSIZE - 1) & ~(DEV_BSIZE - 1);
877
878 counta = 0;
1033 if( count*PAGE_SIZE > bsize)
879 if (count * PAGE_SIZE > bsize)
1034 counta = (count - reqpage) - 1;
1035 bpa = 0;
1036 sizea = 0;
880 counta = (count - reqpage) - 1;
881 bpa = 0;
882 sizea = 0;
1037 if( counta) {
883 if (counta) {
1038 bpa = getpbuf();
1039 count -= counta;
884 bpa = getpbuf();
885 count -= counta;
1040 sizea = size - count*PAGE_SIZE;
886 sizea = size - count * PAGE_SIZE;
1041 size = count * PAGE_SIZE;
1042 }
887 size = count * PAGE_SIZE;
888 }
1043
1044 bp = getpbuf();
889 bp = getpbuf();
1045 kva = (vm_offset_t)bp->b_data;
890 kva = (vm_offset_t) bp->b_data;
1046
1047 /*
1048 * and map the pages to be read into the kva
1049 */
1050 pmap_qenter(kva, m, count);
891
892 /*
893 * and map the pages to be read into the kva
894 */
895 pmap_qenter(kva, m, count);
1051 VHOLD(vp);
1052
1053 /* build a minimal buffer header */
1054 bp->b_flags = B_BUSY | B_READ | B_CALL;
1055 bp->b_iodone = vnode_pager_iodone;
1056 /* B_PHYS is not set, but it is nice to fill this in */
1057 bp->b_proc = curproc;
1058 bp->b_rcred = bp->b_wcred = bp->b_proc->p_ucred;
1059 if (bp->b_rcred != NOCRED)
1060 crhold(bp->b_rcred);
1061 if (bp->b_wcred != NOCRED)
1062 crhold(bp->b_wcred);
1063 bp->b_blkno = firstaddr / DEV_BSIZE;
896
897 /* build a minimal buffer header */
898 bp->b_flags = B_BUSY | B_READ | B_CALL;
899 bp->b_iodone = vnode_pager_iodone;
900 /* B_PHYS is not set, but it is nice to fill this in */
901 bp->b_proc = curproc;
902 bp->b_rcred = bp->b_wcred = bp->b_proc->p_ucred;
903 if (bp->b_rcred != NOCRED)
904 crhold(bp->b_rcred);
905 if (bp->b_wcred != NOCRED)
906 crhold(bp->b_wcred);
907 bp->b_blkno = firstaddr / DEV_BSIZE;
1064 bgetvp(dp, bp);
908 pbgetvp(dp, bp);
1065 bp->b_bcount = size;
1066 bp->b_bufsize = size;
1067
1068 cnt.v_vnodein++;
1069 cnt.v_vnodepgsin += count;
1070
1071 /* do the input */
1072 VOP_STRATEGY(bp);
1073
909 bp->b_bcount = size;
910 bp->b_bufsize = size;
911
912 cnt.v_vnodein++;
913 cnt.v_vnodepgsin += count;
914
915 /* do the input */
916 VOP_STRATEGY(bp);
917
1074 if( counta) {
1075 for(i=0;i<counta;i++) {
1076 vm_page_deactivate(m[count+i]);
918 if (counta) {
919 for (i = 0; i < counta; i++) {
920 vm_page_deactivate(m[count + i]);
1077 }
921 }
1078 pmap_qenter((vm_offset_t)bpa->b_data, &m[count], counta);
922 pmap_qenter((vm_offset_t) bpa->b_data, &m[count], counta);
1079 ++m[count]->object->paging_in_progress;
923 ++m[count]->object->paging_in_progress;
1080 VHOLD(vp);
1081 bpa->b_flags = B_BUSY | B_READ | B_CALL | B_ASYNC;
1082 bpa->b_iodone = vnode_pager_iodone;
1083 /* B_PHYS is not set, but it is nice to fill this in */
1084 bpa->b_proc = curproc;
1085 bpa->b_rcred = bpa->b_wcred = bpa->b_proc->p_ucred;
1086 if (bpa->b_rcred != NOCRED)
1087 crhold(bpa->b_rcred);
1088 if (bpa->b_wcred != NOCRED)
1089 crhold(bpa->b_wcred);
1090 bpa->b_blkno = (firstaddr + count * PAGE_SIZE) / DEV_BSIZE;
924 bpa->b_flags = B_BUSY | B_READ | B_CALL | B_ASYNC;
925 bpa->b_iodone = vnode_pager_iodone;
926 /* B_PHYS is not set, but it is nice to fill this in */
927 bpa->b_proc = curproc;
928 bpa->b_rcred = bpa->b_wcred = bpa->b_proc->p_ucred;
929 if (bpa->b_rcred != NOCRED)
930 crhold(bpa->b_rcred);
931 if (bpa->b_wcred != NOCRED)
932 crhold(bpa->b_wcred);
933 bpa->b_blkno = (firstaddr + count * PAGE_SIZE) / DEV_BSIZE;
1091 bgetvp(dp, bpa);
934 pbgetvp(dp, bpa);
1092 bpa->b_bcount = sizea;
935 bpa->b_bcount = sizea;
1093 bpa->b_bufsize = counta*PAGE_SIZE;
936 bpa->b_bufsize = counta * PAGE_SIZE;
1094
1095 cnt.v_vnodepgsin += counta;
1096 VOP_STRATEGY(bpa);
1097 }
937
938 cnt.v_vnodepgsin += counta;
939 VOP_STRATEGY(bpa);
940 }
1098
1099 s = splbio();
1100 /* we definitely need to be at splbio here */
1101
1102 while ((bp->b_flags & B_DONE) == 0) {
1103 tsleep((caddr_t) bp, PVM, "vnread", 0);
1104 }
1105 splx(s);
1106 if ((bp->b_flags & B_ERROR) != 0)
1107 error = EIO;
1108
1109 if (!error) {
1110 if (size != count * PAGE_SIZE)
1111 bzero((caddr_t) kva + size, PAGE_SIZE * count - size);
1112 }
941 s = splbio();
942 /* we definitely need to be at splbio here */
943
944 while ((bp->b_flags & B_DONE) == 0) {
945 tsleep((caddr_t) bp, PVM, "vnread", 0);
946 }
947 splx(s);
948 if ((bp->b_flags & B_ERROR) != 0)
949 error = EIO;
950
951 if (!error) {
952 if (size != count * PAGE_SIZE)
953 bzero((caddr_t) kva + size, PAGE_SIZE * count - size);
954 }
1113 pmap_qremove( kva, count);
955 pmap_qremove(kva, count);
1114
1115 /*
1116 * free the buffer header back to the swap buffer pool
1117 */
1118 relpbuf(bp);
1119 HOLDRELE(vp);
1120
1121finishup:
1122 for (i = 0; i < count; i++) {
1123 pmap_clear_modify(VM_PAGE_TO_PHYS(m[i]));
956
957 /*
958 * free the buffer header back to the swap buffer pool
959 */
960 relpbuf(bp);
961 HOLDRELE(vp);
962
963finishup:
964 for (i = 0; i < count; i++) {
965 pmap_clear_modify(VM_PAGE_TO_PHYS(m[i]));
1124 m[i]->flags |= PG_CLEAN;
1125 m[i]->flags &= ~PG_LAUNDRY;
966 m[i]->dirty = 0;
967 m[i]->valid = VM_PAGE_BITS_ALL;
1126 if (i != reqpage) {
1127
1128 /*
1129 * whether or not to leave the page activated is up in
1130 * the air, but we should put the page on a page queue
1131 * somewhere. (it already is in the object). Result:
1132 * It appears that emperical results show that
1133 * deactivating pages is best.
1134 */
1135
1136 /*
1137 * just in case someone was asking for this page we
1138 * now tell them that it is ok to use
1139 */
1140 if (!error) {
968 if (i != reqpage) {
969
970 /*
971 * whether or not to leave the page activated is up in
972 * the air, but we should put the page on a page queue
973 * somewhere. (it already is in the object). Result:
974 * It appears that emperical results show that
975 * deactivating pages is best.
976 */
977
978 /*
979 * just in case someone was asking for this page we
980 * now tell them that it is ok to use
981 */
982 if (!error) {
1141 vm_page_deactivate(m[i]);
983 if (i != reqpage - 1)
984 vm_page_deactivate(m[i]);
985 else
986 vm_page_activate(m[i]);
1142 PAGE_WAKEUP(m[i]);
987 PAGE_WAKEUP(m[i]);
1143 m[i]->flags &= ~PG_FAKE;
1144 } else {
1145 vnode_pager_freepage(m[i]);
1146 }
1147 }
1148 }
1149 if (error) {
1150 printf("vnode_pager_input: I/O read error\n");
1151 }
1152 return (error ? VM_PAGER_ERROR : VM_PAGER_OK);
1153}
1154
1155/*
1156 * old-style vnode pager output routine
1157 */
1158int
1159vnode_pager_output_old(vnp, m)
1160 register vn_pager_t vnp;
1161 vm_page_t m;
1162{
988 } else {
989 vnode_pager_freepage(m[i]);
990 }
991 }
992 }
993 if (error) {
994 printf("vnode_pager_input: I/O read error\n");
995 }
996 return (error ? VM_PAGER_ERROR : VM_PAGER_OK);
997}
998
999/*
1000 * old-style vnode pager output routine
1001 */
1002int
1003vnode_pager_output_old(vnp, m)
1004 register vn_pager_t vnp;
1005 vm_page_t m;
1006{
1163 vm_offset_t foff;
1164 vm_offset_t kva;
1007 vm_offset_t kva, kva2;
1165 vm_offset_t size;
1166 struct iovec aiov;
1167 struct uio auio;
1168 struct vnode *vp;
1008 vm_offset_t size;
1009 struct iovec aiov;
1010 struct uio auio;
1011 struct vnode *vp;
1169 int error;
1012 int error;
1170
1171 vp = vnp->vnp_vp;
1013
1014 vp = vnp->vnp_vp;
1172 foff = m->offset + m->object->paging_offset;
1173
1174 /*
1015
1016 /*
1175 * Return failure if beyond current EOF
1017 * Dont return failure if beyond current EOF placate the VM system.
1176 */
1018 */
1177 if (foff >= vnp->vnp_size) {
1178 return VM_PAGER_BAD;
1019 if (m->offset >= vnp->vnp_size) {
1020 return VM_PAGER_OK;
1179 } else {
1180 size = PAGE_SIZE;
1021 } else {
1022 size = PAGE_SIZE;
1181 if (foff + size > vnp->vnp_size)
1182 size = vnp->vnp_size - foff;
1183/*
1184 * Allocate a kernel virtual address and initialize so that
1185 * we can use VOP_WRITE routines.
1186 */
1023 if (m->offset + size > vnp->vnp_size)
1024 size = vnp->vnp_size - m->offset;
1025
1026 kva2 = kmem_alloc(pager_map, PAGE_SIZE);
1027 /*
1028 * Allocate a kernel virtual address and initialize so that
1029 * we can use VOP_WRITE routines.
1030 */
1187 kva = vm_pager_map_page(m);
1031 kva = vm_pager_map_page(m);
1188 aiov.iov_base = (caddr_t) kva;
1032 bcopy((caddr_t) kva, (caddr_t) kva2, size);
1033 vm_pager_unmap_page(kva);
1034 pmap_clear_modify(VM_PAGE_TO_PHYS(m));
1035 PAGE_WAKEUP(m);
1036
1037 aiov.iov_base = (caddr_t) kva2;
1189 aiov.iov_len = size;
1190 auio.uio_iov = &aiov;
1191 auio.uio_iovcnt = 1;
1038 aiov.iov_len = size;
1039 auio.uio_iov = &aiov;
1040 auio.uio_iovcnt = 1;
1192 auio.uio_offset = foff;
1041 auio.uio_offset = m->offset;
1193 auio.uio_segflg = UIO_SYSSPACE;
1194 auio.uio_rw = UIO_WRITE;
1195 auio.uio_resid = size;
1196 auio.uio_procp = (struct proc *) 0;
1197
1198 error = VOP_WRITE(vp, &auio, 0, curproc->p_ucred);
1199
1042 auio.uio_segflg = UIO_SYSSPACE;
1043 auio.uio_rw = UIO_WRITE;
1044 auio.uio_resid = size;
1045 auio.uio_procp = (struct proc *) 0;
1046
1047 error = VOP_WRITE(vp, &auio, 0, curproc->p_ucred);
1048
1049 kmem_free_wakeup(pager_map, kva2, PAGE_SIZE);
1200 if (!error) {
1201 if ((size - auio.uio_resid) == 0) {
1202 error = EINVAL;
1203 }
1204 }
1050 if (!error) {
1051 if ((size - auio.uio_resid) == 0) {
1052 error = EINVAL;
1053 }
1054 }
1205 vm_pager_unmap_page(kva);
1206 return error ? VM_PAGER_ERROR: VM_PAGER_OK;
1055 return error ? VM_PAGER_ERROR : VM_PAGER_OK;
1207 }
1208}
1209
1210/*
1211 * vnode pager output on a small-block file system
1212 */
1213int
1214vnode_pager_output_smlfs(vnp, m)
1215 vn_pager_t vnp;
1216 vm_page_t m;
1217{
1056 }
1057}
1058
1059/*
1060 * vnode pager output on a small-block file system
1061 */
1062int
1063vnode_pager_output_smlfs(vnp, m)
1064 vn_pager_t vnp;
1065 vm_page_t m;
1066{
1218 int i;
1219 int s;
1220 vm_offset_t paging_offset;
1067 int i;
1068 int s;
1221 struct vnode *dp, *vp;
1222 struct buf *bp;
1069 struct vnode *dp, *vp;
1070 struct buf *bp;
1223 vm_offset_t foff;
1224 vm_offset_t kva;
1071 vm_offset_t kva;
1225 int fileaddr;
1072 int fileaddr;
1226 vm_offset_t bsize;
1073 vm_offset_t bsize;
1227 int error = 0;
1074 int error = 0;
1228
1075
1229 paging_offset = m->object->paging_offset;
1230 vp = vnp->vnp_vp;
1231 bsize = vp->v_mount->mnt_stat.f_iosize;
1076 vp = vnp->vnp_vp;
1077 bsize = vp->v_mount->mnt_stat.f_iosize;
1232 foff = m->offset + paging_offset;
1233
1078
1234 VOP_BMAP(vp, foff, &dp, 0, 0);
1079 VOP_BMAP(vp, 0, &dp, 0, 0);
1235 kva = vm_pager_map_page(m);
1236 for (i = 0; !error && i < (PAGE_SIZE / bsize); i++) {
1237
1080 kva = vm_pager_map_page(m);
1081 for (i = 0; !error && i < (PAGE_SIZE / bsize); i++) {
1082
1083 if ((vm_page_bits(m->offset + i * bsize, bsize) & m->valid & m->dirty) == 0)
1084 continue;
1238 /*
1239 * calculate logical block and offset
1240 */
1085 /*
1086 * calculate logical block and offset
1087 */
1241 fileaddr = vnode_pager_addr(vp, foff + i * bsize);
1088 fileaddr = vnode_pager_addr(vp, m->offset + i * bsize);
1242 if (fileaddr != -1) {
1089 if (fileaddr != -1) {
1243 s = splbio();
1244 bp = incore(vp, (foff / bsize) + i);
1245 if (bp) {
1246 bp = getblk(vp, (foff / bsize) + i, bp->b_bufsize, 0, 0);
1247 bp->b_flags |= B_INVAL;
1248 brelse(bp);
1249 }
1250 splx(s);
1251
1252 bp = getpbuf();
1090
1091 bp = getpbuf();
1253 VHOLD(vp);
1254
1255 /* build a minimal buffer header */
1256 bp->b_flags = B_BUSY | B_CALL | B_WRITE;
1257 bp->b_iodone = vnode_pager_iodone;
1258 bp->b_proc = curproc;
1259 bp->b_rcred = bp->b_wcred = bp->b_proc->p_ucred;
1260 if (bp->b_rcred != NOCRED)
1261 crhold(bp->b_rcred);
1262 if (bp->b_wcred != NOCRED)
1263 crhold(bp->b_wcred);
1264 bp->b_un.b_addr = (caddr_t) kva + i * bsize;
1265 bp->b_blkno = fileaddr / DEV_BSIZE;
1092
1093 /* build a minimal buffer header */
1094 bp->b_flags = B_BUSY | B_CALL | B_WRITE;
1095 bp->b_iodone = vnode_pager_iodone;
1096 bp->b_proc = curproc;
1097 bp->b_rcred = bp->b_wcred = bp->b_proc->p_ucred;
1098 if (bp->b_rcred != NOCRED)
1099 crhold(bp->b_rcred);
1100 if (bp->b_wcred != NOCRED)
1101 crhold(bp->b_wcred);
1102 bp->b_un.b_addr = (caddr_t) kva + i * bsize;
1103 bp->b_blkno = fileaddr / DEV_BSIZE;
1266 bgetvp(dp, bp);
1104 pbgetvp(dp, bp);
1267 ++dp->v_numoutput;
1268 /* for NFS */
1269 bp->b_dirtyoff = 0;
1270 bp->b_dirtyend = bsize;
1271 bp->b_bcount = bsize;
1272 bp->b_bufsize = bsize;
1273
1274 /* do the input */

--- 4 unchanged lines hidden (view full) ---

1279 s = splbio();
1280 while ((bp->b_flags & B_DONE) == 0) {
1281 tsleep((caddr_t) bp, PVM, "vnswrt", 0);
1282 }
1283 splx(s);
1284 if ((bp->b_flags & B_ERROR) != 0)
1285 error = EIO;
1286
1105 ++dp->v_numoutput;
1106 /* for NFS */
1107 bp->b_dirtyoff = 0;
1108 bp->b_dirtyend = bsize;
1109 bp->b_bcount = bsize;
1110 bp->b_bufsize = bsize;
1111
1112 /* do the input */

--- 4 unchanged lines hidden (view full) ---

1117 s = splbio();
1118 while ((bp->b_flags & B_DONE) == 0) {
1119 tsleep((caddr_t) bp, PVM, "vnswrt", 0);
1120 }
1121 splx(s);
1122 if ((bp->b_flags & B_ERROR) != 0)
1123 error = EIO;
1124
1125 vm_page_set_clean(m, i * bsize, bsize);
1287 /*
1288 * free the buffer header back to the swap buffer pool
1289 */
1290 relpbuf(bp);
1291 HOLDRELE(vp);
1292 }
1293 }
1294 vm_pager_unmap_page(kva);

--- 5 unchanged lines hidden (view full) ---

1300
1301/*
1302 * generic vnode pager output routine
1303 */
1304int
1305vnode_pager_output(vnp, m, count, rtvals)
1306 vn_pager_t vnp;
1307 vm_page_t *m;
1126 /*
1127 * free the buffer header back to the swap buffer pool
1128 */
1129 relpbuf(bp);
1130 HOLDRELE(vp);
1131 }
1132 }
1133 vm_pager_unmap_page(kva);

--- 5 unchanged lines hidden (view full) ---

1139
1140/*
1141 * generic vnode pager output routine
1142 */
1143int
1144vnode_pager_output(vnp, m, count, rtvals)
1145 vn_pager_t vnp;
1146 vm_page_t *m;
1308 int count;
1309 int *rtvals;
1147 int count;
1148 int *rtvals;
1310{
1149{
1311 int i, j;
1150 int i, j;
1312 vm_offset_t kva, foff;
1151 vm_offset_t kva, foff;
1313 int size;
1152 int size;
1314 vm_object_t object;
1153 vm_object_t object;
1315 vm_offset_t paging_offset;
1316 struct vnode *dp, *vp;
1317 struct buf *bp;
1318 vm_offset_t reqaddr;
1154 struct vnode *dp, *vp;
1155 struct buf *bp;
1156 vm_offset_t reqaddr;
1319 int bsize;
1320 int s;
1157 int bsize;
1158 int s;
1159 daddr_t block;
1160 struct timeval tv;
1321
1161
1322 int error = 0;
1162 int error = 0;
1323
1324retryoutput:
1325 object = m[0]->object; /* all vm_page_t items are in same object */
1163
1164retryoutput:
1165 object = m[0]->object; /* all vm_page_t items are in same object */
1326 paging_offset = object->paging_offset;
1327
1328 vp = vnp->vnp_vp;
1329
1330 /*
1331 * Make sure underlying filesystem is still mounted.
1332 */
1333 if (vp->v_mount == NULL)
1334 return VM_PAGER_FAIL;
1335
1336 bsize = vp->v_mount->mnt_stat.f_iosize;
1337
1338 for (i = 0; i < count; i++)
1339 rtvals[i] = VM_PAGER_AGAIN;
1340
1166
1167 vp = vnp->vnp_vp;
1168
1169 /*
1170 * Make sure underlying filesystem is still mounted.
1171 */
1172 if (vp->v_mount == NULL)
1173 return VM_PAGER_FAIL;
1174
1175 bsize = vp->v_mount->mnt_stat.f_iosize;
1176
1177 for (i = 0; i < count; i++)
1178 rtvals[i] = VM_PAGER_AGAIN;
1179
1180 if ((int) m[0]->offset < 0) {
1181 printf("vnode_pager_output: attempt to write meta-data!!! -- 0x%x\n", m[0]->offset);
1182 m[0]->dirty = 0;
1183 rtvals[0] = VM_PAGER_OK;
1184 return VM_PAGER_OK;
1185 }
1341 /*
1342 * if the filesystem does not have a bmap, then use the old code
1343 */
1186 /*
1187 * if the filesystem does not have a bmap, then use the old code
1188 */
1344 if (VOP_BMAP(vp, m[0]->offset + paging_offset, &dp, 0, 0)) {
1189 if (VOP_BMAP(vp, (m[0]->offset / bsize), &dp, &block, 0) ||
1190 (block == -1)) {
1345
1346 rtvals[0] = vnode_pager_output_old(vnp, m[0]);
1347
1191
1192 rtvals[0] = vnode_pager_output_old(vnp, m[0]);
1193
1348 pmap_clear_modify(VM_PAGE_TO_PHYS(m[0]));
1349 m[0]->flags |= PG_CLEAN;
1350 m[0]->flags &= ~PG_LAUNDRY;
1194 m[0]->dirty = 0;
1351 cnt.v_vnodeout++;
1352 cnt.v_vnodepgsout++;
1353 return rtvals[0];
1354 }
1195 cnt.v_vnodeout++;
1196 cnt.v_vnodepgsout++;
1197 return rtvals[0];
1198 }
1199 tv = time;
1200 VOP_UPDATE(vp, &tv, &tv, 0);
1355
1356 /*
1357 * if the filesystem has a small blocksize, then use the small block
1358 * filesystem output code
1359 */
1360 if ((bsize < PAGE_SIZE) &&
1361 (vp->v_mount->mnt_stat.f_type != MOUNT_NFS)) {
1362
1363 for (i = 0; i < count; i++) {
1364 rtvals[i] = vnode_pager_output_smlfs(vnp, m[i]);
1365 if (rtvals[i] == VM_PAGER_OK) {
1366 pmap_clear_modify(VM_PAGE_TO_PHYS(m[i]));
1201
1202 /*
1203 * if the filesystem has a small blocksize, then use the small block
1204 * filesystem output code
1205 */
1206 if ((bsize < PAGE_SIZE) &&
1207 (vp->v_mount->mnt_stat.f_type != MOUNT_NFS)) {
1208
1209 for (i = 0; i < count; i++) {
1210 rtvals[i] = vnode_pager_output_smlfs(vnp, m[i]);
1211 if (rtvals[i] == VM_PAGER_OK) {
1212 pmap_clear_modify(VM_PAGE_TO_PHYS(m[i]));
1367 m[i]->flags |= PG_CLEAN;
1368 m[i]->flags &= ~PG_LAUNDRY;
1369 }
1370 }
1371 cnt.v_vnodeout++;
1372 cnt.v_vnodepgsout += count;
1373 return rtvals[0];
1374 }
1213 }
1214 }
1215 cnt.v_vnodeout++;
1216 cnt.v_vnodepgsout += count;
1217 return rtvals[0];
1218 }
1375
1376 for (i = 0; i < count; i++) {
1219 for (i = 0; i < count; i++) {
1377 foff = m[i]->offset + paging_offset;
1220 foff = m[i]->offset;
1378 if (foff >= vnp->vnp_size) {
1379 for (j = i; j < count; j++)
1380 rtvals[j] = VM_PAGER_BAD;
1381 count = i;
1382 break;
1383 }
1384 }
1385 if (count == 0) {
1386 return rtvals[0];
1387 }
1221 if (foff >= vnp->vnp_size) {
1222 for (j = i; j < count; j++)
1223 rtvals[j] = VM_PAGER_BAD;
1224 count = i;
1225 break;
1226 }
1227 }
1228 if (count == 0) {
1229 return rtvals[0];
1230 }
1388 foff = m[0]->offset + paging_offset;
1231 foff = m[0]->offset;
1389 reqaddr = vnode_pager_addr(vp, foff);
1390
1391 /*
1392 * Scan forward and stop for the first non-contiguous entry or stop
1393 * for a page being in buffer cache.
1394 */
1395 for (i = 1; i < count; i++) {
1232 reqaddr = vnode_pager_addr(vp, foff);
1233
1234 /*
1235 * Scan forward and stop for the first non-contiguous entry or stop
1236 * for a page being in buffer cache.
1237 */
1238 for (i = 1; i < count; i++) {
1396 if (vnode_pager_addr(vp, m[i]->offset + paging_offset)
1239 if (vnode_pager_addr(vp, m[i]->offset)
1397 != reqaddr + i * PAGE_SIZE) {
1398 count = i;
1399 break;
1400 }
1401 }
1402
1403 /*
1404 * calculate the size of the transfer

--- 4 unchanged lines hidden (view full) ---

1409
1410 /*
1411 * round up physical size for real devices
1412 */
1413 if (dp->v_type == VBLK || dp->v_type == VCHR)
1414 size = (size + DEV_BSIZE - 1) & ~(DEV_BSIZE - 1);
1415
1416 bp = getpbuf();
1240 != reqaddr + i * PAGE_SIZE) {
1241 count = i;
1242 break;
1243 }
1244 }
1245
1246 /*
1247 * calculate the size of the transfer

--- 4 unchanged lines hidden (view full) ---

1252
1253 /*
1254 * round up physical size for real devices
1255 */
1256 if (dp->v_type == VBLK || dp->v_type == VCHR)
1257 size = (size + DEV_BSIZE - 1) & ~(DEV_BSIZE - 1);
1258
1259 bp = getpbuf();
1417 kva = (vm_offset_t)bp->b_data;
1260 kva = (vm_offset_t) bp->b_data;
1418 /*
1419 * and map the pages to be read into the kva
1420 */
1421 pmap_qenter(kva, m, count);
1261 /*
1262 * and map the pages to be read into the kva
1263 */
1264 pmap_qenter(kva, m, count);
1422#if 0
1423 printf("vnode: writing foff: %d, devoff: %d, size: %d\n",
1424 foff, reqaddr, size);
1425#endif
1426
1265
1427 /*
1428 * next invalidate the incore vfs_bio data
1429 */
1430#ifdef NOTYET
1431 if( (vp->v_flag & VVMIO) == 0) {
1432#endif
1433 for (i = 0; i < count; i++) {
1434 int filblock = (foff + i * PAGE_SIZE) / bsize;
1435 struct buf *fbp;
1436
1437 s = splbio();
1438 fbp = incore(vp, filblock);
1439 if (fbp) {
1440 fbp = getblk(vp, filblock, fbp->b_bufsize, 0, 0);
1441 if (fbp->b_flags & B_DELWRI) {
1442 if (fbp->b_bufsize <= PAGE_SIZE)
1443 fbp->b_flags &= ~B_DELWRI;
1444 else {
1445 bwrite(fbp);
1446 fbp = getblk(vp, filblock,
1447 fbp->b_bufsize, 0, 0);
1448 }
1449 }
1450 fbp->b_flags |= B_INVAL;
1451 brelse(fbp);
1452 }
1453 splx(s);
1454 }
1455#ifdef NOTYET
1456 }
1457#endif
1458
1459
1460 VHOLD(vp);
1461 /* build a minimal buffer header */
1462 bp->b_flags = B_BUSY | B_WRITE | B_CALL;
1463 bp->b_iodone = vnode_pager_iodone;
1464 /* B_PHYS is not set, but it is nice to fill this in */
1465 bp->b_proc = curproc;
1466 bp->b_rcred = bp->b_wcred = bp->b_proc->p_ucred;
1467
1468 if (bp->b_rcred != NOCRED)
1469 crhold(bp->b_rcred);
1470 if (bp->b_wcred != NOCRED)
1471 crhold(bp->b_wcred);
1472 bp->b_blkno = reqaddr / DEV_BSIZE;
1266 /* build a minimal buffer header */
1267 bp->b_flags = B_BUSY | B_WRITE | B_CALL;
1268 bp->b_iodone = vnode_pager_iodone;
1269 /* B_PHYS is not set, but it is nice to fill this in */
1270 bp->b_proc = curproc;
1271 bp->b_rcred = bp->b_wcred = bp->b_proc->p_ucred;
1272
1273 if (bp->b_rcred != NOCRED)
1274 crhold(bp->b_rcred);
1275 if (bp->b_wcred != NOCRED)
1276 crhold(bp->b_wcred);
1277 bp->b_blkno = reqaddr / DEV_BSIZE;
1473 bgetvp(dp, bp);
1278 pbgetvp(dp, bp);
1474 ++dp->v_numoutput;
1475
1476 /* for NFS */
1477 bp->b_dirtyoff = 0;
1478 bp->b_dirtyend = size;
1479
1480 bp->b_bcount = size;
1481 bp->b_bufsize = size;

--- 11 unchanged lines hidden (view full) ---

1493 while ((bp->b_flags & B_DONE) == 0) {
1494 tsleep((caddr_t) bp, PVM, "vnwrite", 0);
1495 }
1496 splx(s);
1497
1498 if ((bp->b_flags & B_ERROR) != 0)
1499 error = EIO;
1500
1279 ++dp->v_numoutput;
1280
1281 /* for NFS */
1282 bp->b_dirtyoff = 0;
1283 bp->b_dirtyend = size;
1284
1285 bp->b_bcount = size;
1286 bp->b_bufsize = size;

--- 11 unchanged lines hidden (view full) ---

1298 while ((bp->b_flags & B_DONE) == 0) {
1299 tsleep((caddr_t) bp, PVM, "vnwrite", 0);
1300 }
1301 splx(s);
1302
1303 if ((bp->b_flags & B_ERROR) != 0)
1304 error = EIO;
1305
1501 pmap_qremove( kva, count);
1306 pmap_qremove(kva, count);
1502
1503 /*
1504 * free the buffer header back to the swap buffer pool
1505 */
1506 relpbuf(bp);
1507 HOLDRELE(vp);
1508
1509 if (!error) {
1510 for (i = 0; i < count; i++) {
1511 pmap_clear_modify(VM_PAGE_TO_PHYS(m[i]));
1307
1308 /*
1309 * free the buffer header back to the swap buffer pool
1310 */
1311 relpbuf(bp);
1312 HOLDRELE(vp);
1313
1314 if (!error) {
1315 for (i = 0; i < count; i++) {
1316 pmap_clear_modify(VM_PAGE_TO_PHYS(m[i]));
1512 m[i]->flags |= PG_CLEAN;
1513 m[i]->flags &= ~PG_LAUNDRY;
1317 m[i]->dirty = 0;
1514 rtvals[i] = VM_PAGER_OK;
1515 }
1516 } else if (count != 1) {
1517 error = 0;
1518 count = 1;
1519 goto retryoutput;
1520 }
1521 if (error) {
1522 printf("vnode_pager_output: I/O write error\n");
1523 }
1318 rtvals[i] = VM_PAGER_OK;
1319 }
1320 } else if (count != 1) {
1321 error = 0;
1322 count = 1;
1323 goto retryoutput;
1324 }
1325 if (error) {
1326 printf("vnode_pager_output: I/O write error\n");
1327 }
1524 return (error ? VM_PAGER_ERROR: VM_PAGER_OK);
1328 return (error ? VM_PAGER_ERROR : VM_PAGER_OK);
1525}
1329}