FreeBSD/sys/kern/vfs_bio.c
/*
 * Complete I/O to a VMIO backed page.  Validate the pages as appropriate,
 * restore bogus pages.
 */
Complete I/O to a VMIO backed page.  Validate the pages as appropriate,
restore bogus pages.
Complete I / O to a VMIO backed page . Validate the pages as appropriate restore bogus pages .
static void
vfs_vmio_iodone(struct buf *bp)
{
	vm_ooffset_t foff;
	vm_page_t m;
	vm_object_t obj;
	struct vnode *vp;
	int bogus, i, iosize;
	obj = bp->b_bufobj->bo_object;
	KASSERT(obj->paging_in_progress >= bp->b_npages,
	    ("vfs_vmio_iodone: paging in progress(%d) < b_npages(%d)",
	    obj->paging_in_progress, bp->b_npages));
	vp = bp->b_vp;
	KASSERT(vp->v_holdcnt > 0,
	    ("vfs_vmio_iodone: vnode %p has zero hold count", vp));
	KASSERT(vp->v_object != NULL,
	    ("vfs_vmio_iodone: vnode %p has no vm_object", vp));
	foff = bp->b_offset;
	KASSERT(bp->b_offset != NOOFFSET,
	    ("vfs_vmio_iodone: bp %p has no buffer offset", bp));
	bogus = 0;
	iosize = bp->b_bcount - bp->b_resid;
	VM_OBJECT_WLOCK(obj);
	for (i = 0; i < bp->b_npages; i++) {
		int resid;
		resid = ((foff + PAGE_SIZE) & ~(off_t)PAGE_MASK) - foff;
		if (resid > iosize)
			resid = iosize;
		m = bp->b_pages[i];
		if (m == bogus_page) {
			bogus = 1;
			m = vm_page_lookup(obj, OFF_TO_IDX(foff));
			if (m == NULL)
				panic("biodone: page disappeared!");
			bp->b_pages[i] = m;
		} else if ((bp->b_iocmd == BIO_READ) && resid > 0) {
			KASSERT((m->dirty & vm_page_bits(foff & PAGE_MASK,
			    resid)) == 0, ("vfs_vmio_iodone: page %p "
			    "has unexpected dirty bits", m));
			vfs_page_set_valid(bp, foff, m);
		}
		KASSERT(OFF_TO_IDX(foff) == m->pindex,
		    ("vfs_vmio_iodone: foff(%jd)/pindex(%ju) mismatch",
		    (intmax_t)foff, (uintmax_t)m->pindex));
		vm_page_sunbusy(m);
		foff = (foff + PAGE_SIZE) & ~(off_t)PAGE_MASK;
		iosize -= resid;
	}
	vm_object_pip_wakeupn(obj, bp->b_npages);
	VM_OBJECT_WUNLOCK(obj);
	if (bogus && buf_mapped(bp)) {
		BUF_CHECK_MAPPED(bp);
		pmap_qenter(trunc_page((vm_offset_t)bp->b_data),
		    bp->b_pages, bp->b_npages);
	}
}
static void vfs_vmio_iodone ( struct buf * bp ) { vm_ooffset_t foff ; vm_page_t m ; vm_object_t obj ; struct vnode * vp ; int bogus , i , iosize ; obj = bp -> b_bufobj -> bo_object ; KASSERT ( obj -> paging_in_progress >= bp -> b_npages , ( " " , obj -> paging_in_progress , bp -> b_npages ) ) ; vp = bp -> b_vp ; KASSERT ( vp -> v_holdcnt > 0 , ( " " , vp ) ) ; KASSERT ( vp -> v_object != NULL , ( " " , vp ) ) ; foff = bp -> b_offset ; KASSERT ( bp -> b_offset != NOOFFSET , ( " " , bp ) ) ; bogus = 0 ; iosize = bp -> b_bcount - bp -> b_resid ; VM_OBJECT_WLOCK ( obj ) ; for ( i = 0 ; i < bp -> b_npages ; i ++ ) { int resid ; resid = ( ( foff + PAGE_SIZE ) & ~ ( off_t ) PAGE_MASK ) - foff ; if ( resid > iosize ) resid = iosize ; m = bp -> b_pages [ i ] ; if ( m == bogus_page ) { bogus = 1 ; m = vm_page_lookup ( obj , OFF_TO_IDX ( foff ) ) ; if ( m == NULL ) panic ( " " ) ; bp -> b_pages [ i ] = m ; } else if ( ( bp -> b_iocmd == BIO_READ ) && resid > 0 ) { KASSERT ( ( m -> dirty & vm_page_bits ( foff & PAGE_MASK , resid ) ) == 0 , ( " " " " , m ) ) ; vfs_page_set_valid ( bp , foff , m ) ; } KASSERT ( OFF_TO_IDX ( foff ) == m -> pindex , ( " " , ( intmax_t ) foff , ( uintmax_t ) m -> pindex ) ) ; vm_page_sunbusy ( m ) ; foff = ( foff + PAGE_SIZE ) & ~ ( off_t ) PAGE_MASK ; iosize -= resid ; } vm_object_pip_wakeupn ( obj , bp -> b_npages ) ; VM_OBJECT_WUNLOCK ( obj ) ; if ( bogus && buf_mapped ( bp ) ) { BUF_CHECK_MAPPED ( bp ) ; pmap_qenter ( trunc_page ( ( vm_offset_t ) bp -> b_data ) , bp -> b_pages , bp -> b_npages ) ; } }
Complete I/O to a VMIO backed page.
Complete I / O to a VMIO backed page .
/*
		 * cleanup bogus pages, restoring the originals
		 */ /*
			 * In the write case, the valid and clean bits are
			 * already changed correctly ( see bdwrite() ), so we 
			 * only need to do this here in the read case.
			 */