vnode_pager.c revision 4797
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
9 * Science Department.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 *    notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 *    notice, this list of conditions and the following disclaimer in the
18 *    documentation and/or other materials provided with the distribution.
19 * 3. All advertising materials mentioning features or use of this software
20 *    must display the following acknowledgement:
21 *	This product includes software developed by the University of
22 *	California, Berkeley and its contributors.
23 * 4. Neither the name of the University nor the names of its contributors
24 *    may be used to endorse or promote products derived from this software
25 *    without specific prior written permission.
26 *
27 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
28 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
29 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
30 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
31 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
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 $
41 */
42
43/*
44 * Page to/from files (vnodes).
45 *
46 * TODO:
47 *	pageouts
48 *	fix credential use (uses current process credentials now)
49 */
50
51/*
52 * MODIFICATIONS:
53 * John S. Dyson  08 Dec 93
54 *
55 * This file in conjunction with some vm_fault mods, eliminate the performance
56 * advantage for using the buffer cache and minimize memory copies.
57 *
58 * 1) Supports multiple - block reads
59 * 2) Bypasses buffer cache for reads
60 *
61 * TODO:
62 *
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/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
84int     vnode_pager_putmulti();
85
86void    vnode_pager_init();
87vm_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();
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,
100	vnode_pager_putpage,
101	vnode_pager_putmulti,
102	vnode_pager_haspage
103};
104
105
106
107static int vnode_pager_input(vn_pager_t vnp, vm_page_t * m, int count, int reqpage);
108static int vnode_pager_output(vn_pager_t vnp, vm_page_t * m, int count, int *rtvals);
109
110extern vm_map_t pager_map;
111
112struct pagerlst vnode_pager_list;	/* list of managed vnodes */
113
114#define MAXBP (PAGE_SIZE/DEV_BSIZE);
115
116void
117vnode_pager_init()
118{
119	TAILQ_INIT(&vnode_pager_list);
120}
121
122/*
123 * Allocate (or lookup) pager for a vnode.
124 * Handle is a vnode pointer.
125 */
126vm_pager_t
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;
135	vm_object_t object;
136	struct vattr vattr;
137	struct vnode *vp;
138	struct proc *p = curproc;	/* XXX */
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;
151	object = (vm_object_t) vp->v_vmdata;
152	pager = NULL;
153	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		}
168
169		/*
170		 * And an object of the appropriate size
171		 */
172		if (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 {
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		 */
185		VREF(vp);
186		vnp->vnp_flags = 0;
187		vnp->vnp_vp = vp;
188		vnp->vnp_size = vattr.va_size;
189
190		TAILQ_INSERT_TAIL(&vnode_pager_list, pager, pg_list);
191		pager->pg_handle = handle;
192		pager->pg_type = PG_VNODE;
193		pager->pg_ops = &vnodepagerops;
194		pager->pg_data = (caddr_t) vnp;
195		vp->v_vmdata = (caddr_t) object;
196	} else {
197
198		/*
199		 * vm_object_lookup() will remove the object from the cache if
200		 * found and also gain a reference to the object.
201		 */
202		(void) vm_object_lookup(pager);
203	}
204	return (pager);
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;
213
214	vp = vnp->vnp_vp;
215	if (vp) {
216		vp->v_vmdata = NULL;
217		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;
229	int     count;
230	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)
239	vm_pager_t pager;
240	vm_page_t m;
241	boolean_t sync;
242{
243
244	vm_page_t marray[1];
245
246	if (pager == NULL)
247		return FALSE;
248	marray[0] = m;
249
250	return vnode_pager_input((vn_pager_t) pager->pg_data, marray, 1, 0);
251}
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];
260	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;
273	int     c;
274	boolean_t sync;
275	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;
289	int     err;
290	daddr_t block;
291
292	/*
293	 * If filesystem no longer mounted or offset beyond end of
294	 * file we do 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);
309/*
310	printf("vnode_pager_haspage: (%d)0x%x: err: %d, bn: %d\n",
311		offset, offset, err, bn);
312*/
313	if (err) {
314		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;
331	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;
347	if( object == NULL)
348		return;
349	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) {
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
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),
386				      round_page(nsize) - nsize);
387				vm_pager_unmap_page(kva);
388			}
389		}
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
417vnode_pager_umount(mp)
418	register struct mount *mp;
419{
420	register vm_pager_t pager, npager;
421	struct vnode *vp;
422
423	pager = vnode_pager_list.tqh_first;
424	while (pager) {
425
426		/*
427		 * Save the next pointer now since uncaching may terminate the
428		 * object and render pager invalid
429		 */
430		vp = ((vn_pager_t) pager->pg_data)->vnp_vp;
431		npager = pager->pg_list.tqe_next;
432		if (mp == (struct mount *) 0 || vp->v_mount == mp)
433			(void) vnode_pager_uncache(vp);
434		pager = npager;
435	}
436}
437
438/*
439 * Remove vnode associated object from the object cache.
440 *
441 * Note: this routine may be invoked as a result of a pager put
442 * operation (possibly at object termination time), so we must be careful.
443 */
444boolean_t
445vnode_pager_uncache(vp)
446	register struct vnode *vp;
447{
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;
456	if( object == NULL)
457		return(TRUE);
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.
466	 */
467	locked = VOP_ISLOCKED(vp);
468	if (locked)
469		VOP_UNLOCK(vp);
470
471	/*
472	 * Must use vm_object_lookup() as it actually removes the object from
473	 * the cache list.
474	 */
475	object = vm_object_lookup(pager);
476	if (object) {
477		uncached = (object->ref_count <= 1);
478		pager_cache(object, FALSE);
479	} else
480		uncached = TRUE;
481	if (locked)
482		VOP_LOCK(vp);
483	return (uncached);
484}
485
486
487void
488vnode_pager_freepage(m)
489	vm_page_t m;
490{
491	PAGE_WAKEUP(m);
492	vm_page_free(m);
493}
494
495/*
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{
504	int     rtaddress;
505	int     bsize;
506	vm_offset_t block;
507	struct vnode *rtvp;
508	int     err;
509	int     vblock, voffset;
510
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;
519	else
520		rtaddress = block * DEV_BSIZE + voffset;
521
522	return rtaddress;
523}
524
525/*
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);
534	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;
542		if( bp->b_bufsize != bp->b_bcount)
543			bzero( bp->b_data + bp->b_bcount,
544				bp->b_bufsize - bp->b_bcount);
545
546		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++) {
552			m = PHYS_TO_VM_PAGE(pmap_kextract(paddr + i * PAGE_SIZE));
553			obj = m->object;
554			if( m) {
555				m->flags |= PG_CLEAN;
556				m->flags &= ~(PG_LAUNDRY|PG_FAKE);
557				PAGE_WAKEUP(m);
558			} else {
559				panic("vnode_pager_iodone: page is gone!!!");
560			}
561		}
562		pmap_qremove( paddr, npages);
563		if( obj) {
564			--obj->paging_in_progress;
565			if( obj->paging_in_progress == 0)
566				wakeup((caddr_t) obj);
567		} else {
568			panic("vnode_pager_iodone: object is gone???");
569		}
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{
583	int     i;
584	int     s;
585	vm_offset_t paging_offset;
586	struct vnode *dp, *vp;
587	struct buf *bp;
588	vm_offset_t foff;
589	vm_offset_t kva;
590	int     fileaddr;
591	int     block;
592	vm_offset_t bsize;
593	int     error = 0;
594
595	paging_offset = m->object->paging_offset;
596	vp = vnp->vnp_vp;
597	bsize = vp->v_mount->mnt_stat.f_iosize;
598	foff = m->offset + paging_offset;
599
600	VOP_BMAP(vp, foff, &dp, 0, 0);
601
602	kva = vm_pager_map_page(m);
603
604	for (i = 0; i < PAGE_SIZE / bsize; i++) {
605
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;
613
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);
648		if (fileaddr != -1) {
649			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;
663			bgetvp(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
672			s = splbio();
673			while ((bp->b_flags & B_DONE) == 0) {
674				tsleep((caddr_t) bp, PVM, "vnsrd", 0);
675			}
676			splx(s);
677			if ((bp->b_flags & B_ERROR) != 0)
678				error = EIO;
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;
687		} else {
688			bzero((caddr_t) kva + i * bsize, bsize);
689		}
690nextblock:
691	}
692	vm_pager_unmap_page(kva);
693	if (error) {
694		return VM_PAGER_ERROR;
695	}
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;
714	int     error;
715	int     size;
716	vm_offset_t foff;
717	vm_offset_t kva;
718
719	error = 0;
720	foff = m->offset + m->object->paging_offset;
721
722	/*
723	 * Return failure if beyond current EOF
724	 */
725	if (foff >= vnp->vnp_size) {
726		return VM_PAGER_BAD;
727	} else {
728		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 */
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;
740		auio.uio_offset = foff;
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));
758	m->flags |= PG_CLEAN;
759	m->flags &= ~PG_LAUNDRY;
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;
770	int     count, reqpage;
771{
772	int     i;
773	vm_offset_t kva, foff;
774	int     size, sizea;
775	vm_object_t object;
776	vm_offset_t paging_offset;
777	struct vnode *dp, *vp;
778	int     bsize;
779
780	int     first, last;
781	int     reqaddr, firstaddr;
782	int     block, offset;
783
784	struct buf *bp, *bpa;
785	int	counta;
786	int     s;
787	int     failflag;
788
789	int     error = 0;
790
791	object = m[reqpage]->object;	/* all vm_page_t items are in same
792					 * object */
793	paging_offset = object->paging_offset;
794
795	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	 */
811	foff = m[reqpage]->offset + paging_offset;
812
813	/*
814	 * if we can't bmap, use old VOP code
815	 */
816	if (VOP_BMAP(vp, foff, &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 &&
832		   (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	}
843/*
844 * here on direct device I/O
845 */
846
847
848#ifdef NOTYET
849	if( (vp->v_flag & VVMIO) == 0) {
850#endif
851	/*
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.
858	 */
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;
941		}
942		splx(s);
943#ifdef NOTYET
944	}
945#endif
946
947	reqaddr = vnode_pager_addr(vp, foff);
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 ||
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))
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 ||
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))
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);
995
996	/*
997	 * the first and last page have been calculated now, move input pages
998	 * to be zero based...
999	 */
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	}
1008
1009	/*
1010	 * calculate the file virtual address for the transfer
1011	 */
1012	foff = m[0]->offset + paging_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
1021	 */
1022	size = count * PAGE_SIZE;
1023	if ((foff + size) > vnp->vnp_size)
1024		size = vnp->vnp_size - foff;
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;
1033	if( count*PAGE_SIZE > bsize)
1034		counta = (count - reqpage) - 1;
1035	bpa = 0;
1036	sizea = 0;
1037	if( counta) {
1038		bpa = getpbuf();
1039		count -= counta;
1040		sizea = size - count*PAGE_SIZE;
1041		size = count * PAGE_SIZE;
1042	}
1043
1044	bp = getpbuf();
1045	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);
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;
1064	bgetvp(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
1074	if( counta) {
1075		for(i=0;i<counta;i++) {
1076			vm_page_deactivate(m[count+i]);
1077		}
1078		pmap_qenter((vm_offset_t)bpa->b_data, &m[count], counta);
1079		++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;
1091		bgetvp(dp, bpa);
1092		bpa->b_bcount = sizea;
1093		bpa->b_bufsize = counta*PAGE_SIZE;
1094
1095		cnt.v_vnodepgsin += counta;
1096		VOP_STRATEGY(bpa);
1097	}
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	}
1113	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]));
1124		m[i]->flags |= PG_CLEAN;
1125		m[i]->flags &= ~PG_LAUNDRY;
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) {
1141				vm_page_deactivate(m[i]);
1142				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{
1163	vm_offset_t foff;
1164	vm_offset_t kva;
1165	vm_offset_t size;
1166	struct iovec aiov;
1167	struct uio auio;
1168	struct vnode *vp;
1169	int     error;
1170
1171	vp = vnp->vnp_vp;
1172	foff = m->offset + m->object->paging_offset;
1173
1174	/*
1175	 * Return failure if beyond current EOF
1176	 */
1177	if (foff >= vnp->vnp_size) {
1178		return VM_PAGER_BAD;
1179	} else {
1180		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 */
1187		kva = vm_pager_map_page(m);
1188		aiov.iov_base = (caddr_t) kva;
1189		aiov.iov_len = size;
1190		auio.uio_iov = &aiov;
1191		auio.uio_iovcnt = 1;
1192		auio.uio_offset = foff;
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
1200		if (!error) {
1201			if ((size - auio.uio_resid) == 0) {
1202				error = EINVAL;
1203			}
1204		}
1205		vm_pager_unmap_page(kva);
1206		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{
1218	int     i;
1219	int     s;
1220	vm_offset_t paging_offset;
1221	struct vnode *dp, *vp;
1222	struct buf *bp;
1223	vm_offset_t foff;
1224	vm_offset_t kva;
1225	int     fileaddr;
1226	vm_offset_t bsize;
1227	int     error = 0;
1228
1229	paging_offset = m->object->paging_offset;
1230	vp = vnp->vnp_vp;
1231	bsize = vp->v_mount->mnt_stat.f_iosize;
1232	foff = m->offset + paging_offset;
1233
1234	VOP_BMAP(vp, foff, &dp, 0, 0);
1235	kva = vm_pager_map_page(m);
1236	for (i = 0; !error && i < (PAGE_SIZE / bsize); i++) {
1237
1238		/*
1239		 * calculate logical block and offset
1240		 */
1241		fileaddr = vnode_pager_addr(vp, foff + i * bsize);
1242		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();
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;
1266			bgetvp(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 */
1275			VOP_STRATEGY(bp);
1276
1277			/* we definitely need to be at splbio here */
1278
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
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);
1295	if (error)
1296		return VM_PAGER_ERROR;
1297	else
1298		return VM_PAGER_OK;
1299}
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;
1308	int     count;
1309	int    *rtvals;
1310{
1311	int     i, j;
1312	vm_offset_t kva, foff;
1313	int     size;
1314	vm_object_t object;
1315	vm_offset_t paging_offset;
1316	struct vnode *dp, *vp;
1317	struct buf *bp;
1318	vm_offset_t reqaddr;
1319	int     bsize;
1320	int     s;
1321
1322	int     error = 0;
1323
1324retryoutput:
1325	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
1341	/*
1342	 * if the filesystem does not have a bmap, then use the old code
1343	 */
1344	if (VOP_BMAP(vp, m[0]->offset + paging_offset, &dp, 0, 0)) {
1345
1346		rtvals[0] = vnode_pager_output_old(vnp, m[0]);
1347
1348		pmap_clear_modify(VM_PAGE_TO_PHYS(m[0]));
1349		m[0]->flags |= PG_CLEAN;
1350		m[0]->flags &= ~PG_LAUNDRY;
1351		cnt.v_vnodeout++;
1352		cnt.v_vnodepgsout++;
1353		return rtvals[0];
1354	}
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]));
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	}
1375
1376	for (i = 0; i < count; i++) {
1377		foff = m[i]->offset + paging_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	}
1388	foff = m[0]->offset + paging_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++) {
1396		if (vnode_pager_addr(vp, m[i]->offset + paging_offset)
1397		    != reqaddr + i * PAGE_SIZE) {
1398			count = i;
1399			break;
1400		}
1401	}
1402
1403	/*
1404	 * calculate the size of the transfer
1405	 */
1406	size = count * PAGE_SIZE;
1407	if ((foff + size) > vnp->vnp_size)
1408		size = vnp->vnp_size - foff;
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();
1417	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);
1422#if 0
1423	printf("vnode: writing foff: %d, devoff: %d, size: %d\n",
1424		foff, reqaddr, size);
1425#endif
1426
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;
1473	bgetvp(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;
1482
1483	cnt.v_vnodeout++;
1484	cnt.v_vnodepgsout += count;
1485
1486	/* do the output */
1487	VOP_STRATEGY(bp);
1488
1489	s = splbio();
1490
1491	/* we definitely need to be at splbio here */
1492
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
1501	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]));
1512			m[i]->flags |= PG_CLEAN;
1513			m[i]->flags &= ~PG_LAUNDRY;
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	}
1524	return (error ? VM_PAGER_ERROR: VM_PAGER_OK);
1525}
1526