FreeBSD/sys/kern/kern_sendfile.c
/*
 * Iterate through pages vector and request paging for non-valid pages.
 */
Iterate through pages vector and request paging for non-valid pages.
Iterate through pages vector and request paging for non - valid pages .
static int
sendfile_swapin(vm_object_t obj, struct sf_io *sfio, off_t off, off_t len,
    int npages, int rhpages, int flags)
{
	vm_page_t *pa = sfio->pa;
	int nios;
	nios = 0;
	flags = (flags & SF_NODISKIO) ? VM_ALLOC_NOWAIT : 0;
	VM_OBJECT_WLOCK(obj);
	for (int i = 0; i < npages; i++) {
		pa[i] = vm_page_grab(obj, OFF_TO_IDX(vmoff(i, off)),
		    VM_ALLOC_WIRED | VM_ALLOC_NORMAL | flags);
		if (pa[i] == NULL) {
			npages = i;
			rhpages = 0;
			break;
		}
	}
	for (int i = 0; i < npages;) {
		int j, a, count, rv;
		if (vm_page_is_valid(pa[i], vmoff(i, off) & PAGE_MASK,
		    xfsize(i, npages, off, len))) {
			vm_page_xunbusy(pa[i]);
			SFSTAT_INC(sf_pages_valid);
			i++;
			continue;
		}
		for (j = i + 1; j < npages; j++)
			if (vm_page_is_valid(pa[j], vmoff(j, off) & PAGE_MASK,
			    xfsize(j, npages, off, len))) {
				SFSTAT_INC(sf_pages_valid);
				break;
			}
		while (!vm_pager_has_page(obj, OFF_TO_IDX(vmoff(i, off)),
		    NULL, &a) && i < j) {
			pmap_zero_page(pa[i]);
			pa[i]->valid = VM_PAGE_BITS_ALL;
			pa[i]->dirty = 0;
			vm_page_xunbusy(pa[i]);
			i++;
		}
		if (i == j)
			continue;
		if (j < npages)
			a = min(a, j - i - 1);
		count = min(a + 1, npages - i);
		refcount_acquire(&sfio->nios);
		rv = vm_pager_get_pages_async(obj, pa + i, count, NULL,
		    i + count == npages ? &rhpages : NULL,
		    &sendfile_iodone, sfio);
		KASSERT(rv == VM_PAGER_OK, ("%s: pager fail obj %p page %p",
		    __func__, obj, pa[i]));
		SFSTAT_INC(sf_iocnt);
		SFSTAT_ADD(sf_pages_read, count);
		if (i + count == npages)
			SFSTAT_ADD(sf_rhpages_read, rhpages);
#ifdef INVARIANTS
		for (j = i; j < i + count && j < npages; j++)
			KASSERT(pa[j] == vm_page_lookup(obj,
			    OFF_TO_IDX(vmoff(j, off))),
			    ("pa[j] %p lookup %p\n", pa[j],
			    vm_page_lookup(obj, OFF_TO_IDX(vmoff(j, off)))));
#endif
		i += count;
		nios++;
	}
	VM_OBJECT_WUNLOCK(obj);
	if (nios == 0 && npages != 0)
		SFSTAT_INC(sf_noiocnt);
	return (nios);
}
static int sendfile_swapin ( vm_object_t obj , struct sf_io * sfio , off_t off , off_t len , int npages , int rhpages , int flags ) { vm_page_t * pa = sfio -> pa ; int nios ; nios = 0 ; flags = ( flags & SF_NODISKIO ) ? VM_ALLOC_NOWAIT : 0 ; VM_OBJECT_WLOCK ( obj ) ; for ( int i = 0 ; i < npages ; i ++ ) { pa [ i ] = vm_page_grab ( obj , OFF_TO_IDX ( vmoff ( i , off ) ) , VM_ALLOC_WIRED | VM_ALLOC_NORMAL | flags ) ; if ( pa [ i ] == NULL ) { npages = i ; rhpages = 0 ; break ; } } for ( int i = 0 ; i < npages ; ) { int j , a , count , rv ; if ( vm_page_is_valid ( pa [ i ] , vmoff ( i , off ) & PAGE_MASK , xfsize ( i , npages , off , len ) ) ) { vm_page_xunbusy ( pa [ i ] ) ; SFSTAT_INC ( sf_pages_valid ) ; i ++ ; continue ; } for ( j = i + 1 ; j < npages ; j ++ ) if ( vm_page_is_valid ( pa [ j ] , vmoff ( j , off ) & PAGE_MASK , xfsize ( j , npages , off , len ) ) ) { SFSTAT_INC ( sf_pages_valid ) ; break ; } while ( ! vm_pager_has_page ( obj , OFF_TO_IDX ( vmoff ( i , off ) ) , NULL , & a ) && i < j ) { pmap_zero_page ( pa [ i ] ) ; pa [ i ] -> valid = VM_PAGE_BITS_ALL ; pa [ i ] -> dirty = 0 ; vm_page_xunbusy ( pa [ i ] ) ; i ++ ; } if ( i == j ) continue ; if ( j < npages ) a = min ( a , j - i - 1 ) ; count = min ( a + 1 , npages - i ) ; refcount_acquire ( & sfio -> nios ) ; rv = vm_pager_get_pages_async ( obj , pa + i , count , NULL , i + count == npages ? & rhpages : NULL , & sendfile_iodone , sfio ) ; KASSERT ( rv == VM_PAGER_OK , ( " " , __func__ , obj , pa [ i ] ) ) ; SFSTAT_INC ( sf_iocnt ) ; SFSTAT_ADD ( sf_pages_read , count ) ; if ( i + count == npages ) SFSTAT_ADD ( sf_rhpages_read , rhpages ) ; #ifdef INVARIANTS for ( j = i ; j < i + count && j < npages ; j ++ ) KASSERT ( pa [ j ] == vm_page_lookup ( obj , OFF_TO_IDX ( vmoff ( j , off ) ) ) , ( " \n " , pa [ j ] , vm_page_lookup ( obj , OFF_TO_IDX ( vmoff ( j , off ) ) ) ) ) ; #endif i += count ; nios ++ ; } VM_OBJECT_WUNLOCK ( obj ) ; if ( nios == 0 && npages != 0 ) SFSTAT_INC ( sf_noiocnt ) ; return ( nios ) ; }
Iterate through pages vector and request paging for non-valid pages.
Iterate through pages vector and request paging for non - valid pages .
/*
	 * First grab all the pages and wire them.  Note that we grab
	 * only required pages.  Readahead pages are dealt with later.
	 */ /* Skip valid pages. */ /*
		 * Now 'i' points to first invalid page, iterate further
		 * to make 'j' point at first valid after a bunch of
		 * invalid ones.
		 */ /*
		 * Now we got region of invalid pages between 'i' and 'j'.
		 * Check that they belong to pager.  They may not be there,
		 * which is a regular situation for shmem pager.  For vnode
		 * pager this happens only in case of sparse file.
		 *
		 * Important feature of vm_pager_has_page() is the hint
		 * stored in 'a', about how many pages we can pagein after
		 * this page in a single I/O.
		 */ /*
		 * We want to pagein as many pages as possible, limited only
		 * by the 'a' hint and actual request.
		 *
		 * We should not pagein into already valid page, thus if
		 * 'j' didn't reach last page, trim by that page.
		 *
		 * When the pagein fulfils the request, also specify readahead.
		 */