FreeBSD/sys/kern/vfs_bio.c
/*
 * Byte granular extension of VMIO buffers.
 */
Byte granular extension of VMIO buffers.
Byte granular extension of VMIO buffers .
static void
vfs_vmio_extend(struct buf *bp, int desiredpages, int size)
{
	vm_object_t obj;
	vm_offset_t toff;
	vm_offset_t tinc;
	vm_page_t m;
	obj = bp->b_bufobj->bo_object;
	VM_OBJECT_WLOCK(obj);
	while (bp->b_npages < desiredpages) {
		m = vm_page_grab(obj, OFF_TO_IDX(bp->b_offset) + bp->b_npages,
		    VM_ALLOC_NOBUSY | VM_ALLOC_SYSTEM |
		    VM_ALLOC_WIRED | VM_ALLOC_IGN_SBUSY |
		    VM_ALLOC_COUNT(desiredpages - bp->b_npages));
		if (m->valid == 0)
			bp->b_flags &= ~B_CACHE;
		bp->b_pages[bp->b_npages] = m;
		++bp->b_npages;
	}
	toff = bp->b_bcount;
	tinc = PAGE_SIZE - ((bp->b_offset + toff) & PAGE_MASK);
	while ((bp->b_flags & B_CACHE) && toff < size) {
		vm_pindex_t pi;
		if (tinc > (size - toff))
			tinc = size - toff;
		pi = ((bp->b_offset & PAGE_MASK) + toff) >> PAGE_SHIFT;
		m = bp->b_pages[pi];
		vfs_buf_test_cache(bp, bp->b_offset, toff, tinc, m);
		toff += tinc;
		tinc = PAGE_SIZE;
	}
	VM_OBJECT_WUNLOCK(obj);
	if (buf_mapped(bp))
		bpmap_qenter(bp);
	else
		BUF_CHECK_UNMAPPED(bp);
}
static void vfs_vmio_extend ( struct buf * bp , int desiredpages , int size ) { vm_object_t obj ; vm_offset_t toff ; vm_offset_t tinc ; vm_page_t m ; obj = bp -> b_bufobj -> bo_object ; VM_OBJECT_WLOCK ( obj ) ; while ( bp -> b_npages < desiredpages ) { m = vm_page_grab ( obj , OFF_TO_IDX ( bp -> b_offset ) + bp -> b_npages , VM_ALLOC_NOBUSY | VM_ALLOC_SYSTEM | VM_ALLOC_WIRED | VM_ALLOC_IGN_SBUSY | VM_ALLOC_COUNT ( desiredpages - bp -> b_npages ) ) ; if ( m -> valid == 0 ) bp -> b_flags &= ~ B_CACHE ; bp -> b_pages [ bp -> b_npages ] = m ; ++ bp -> b_npages ; } toff = bp -> b_bcount ; tinc = PAGE_SIZE - ( ( bp -> b_offset + toff ) & PAGE_MASK ) ; while ( ( bp -> b_flags & B_CACHE ) && toff < size ) { vm_pindex_t pi ; if ( tinc > ( size - toff ) ) tinc = size - toff ; pi = ( ( bp -> b_offset & PAGE_MASK ) + toff ) >> PAGE_SHIFT ; m = bp -> b_pages [ pi ] ; vfs_buf_test_cache ( bp , bp -> b_offset , toff , tinc , m ) ; toff += tinc ; tinc = PAGE_SIZE ; } VM_OBJECT_WUNLOCK ( obj ) ; if ( buf_mapped ( bp ) ) bpmap_qenter ( bp ) ; else BUF_CHECK_UNMAPPED ( bp ) ; }
Byte granular extension of VMIO buffers.
Byte granular extension of VMIO buffers .
/*
	 * We are growing the buffer, possibly in a 
	 * byte-granular fashion.
	 */ /*
	 * Step 1, bring in the VM pages from the object, allocating
	 * them if necessary.  We must clear B_CACHE if these pages
	 * are not valid for the range covered by the buffer.
	 */ /*
		 * We must allocate system pages since blocking
		 * here could interfere with paging I/O, no
		 * matter which process we are.
		 *
		 * Only exclusive busy can be tested here.
		 * Blocking on shared busy might lead to
		 * deadlocks once allocbuf() is called after
		 * pages are vfs_busy_pages().
		 */ /*
	 * Step 2.  We've loaded the pages into the buffer,
	 * we have to figure out if we can still have B_CACHE
	 * set.  Note that B_CACHE is set according to the
	 * byte-granular range ( bcount and size ), not the
	 * aligned range ( newbsize ).
	 *
	 * The VM test is against m->valid, which is DEV_BSIZE
	 * aligned.  Needless to say, the validity of the data
	 * needs to also be DEV_BSIZE aligned.  Note that this
	 * fails with NFS if the server or some other client
	 * extends the file's EOF.  If our buffer is resized, 
	 * B_CACHE may remain set! XXX
	 */ /*
	 * Step 3, fixup the KVA pmap.
	 */