result = EIO;
result = VM_PAGER_ERROR;
uvm_loanuobj(ufi, output, flags, va)	struct uvm_faultinfo *ufi;	void ***output;	int flags;	vaddr_t va;{	struct vm_amap *amap = ufi->entry->aref.ar_amap;	struct uvm_object *uobj = ufi->entry->object.uvm_obj;	struct vm_page *pg;	struct vm_anon *anon;	int result, npages;	boolean_t locked;	/*	 * first we must make sure the page is resident.	 *	 * XXXCDC: duplicate code with uvm_fault().	 */	if (uobj->pgops->pgo_get) {	/* try locked pgo_get */		npages = 1;		pg = NULL;		result = uobj->pgops->pgo_get(uobj, va - ufi->entry->start,		    &pg, &npages, 0, VM_PROT_READ, MADV_NORMAL, PGO_LOCKED);	} else {		result = EIO;		/* must have pgo_get op */	}	/*	 * check the result of the locked pgo_get.  if there is a problem,	 * then we fail the loan.	 */	if (result != 0 && result != EBUSY) {		uvmfault_unlockall(ufi, amap, uobj, NULL);		return(-1);	}	/*	 * if we need to unlock for I/O, do so now.	 */	if (result == EBUSY) {		uvmfault_unlockall(ufi, amap, NULL, NULL);		npages = 1;		/* locked: uobj */		result = uobj->pgops->pgo_get(uobj, va - ufi->entry->start,		    &pg, &npages, 0, VM_PROT_READ, MADV_NORMAL, PGO_SYNCIO);		/* locked: <nothing> */		/*		 * check for errors		 */		if (result != 0) {			 if (result == EAGAIN) {				tsleep(&lbolt, PVM, "fltagain2", 0);				return(0); /* redo the lookup and try again */			}			return(-1);	/* total failure */		}		/*		 * pgo_get was a success.   attempt to relock everything.		 */		locked = uvmfault_relock(ufi);		if (locked && amap)			amap_lock(amap);		simple_lock(&uobj->vmobjlock);		/*		 * verify that the page has not be released and re-verify		 * that amap slot is still free.   if there is a problem we		 * drop our lock (thus force a lookup refresh/retry).		 */		if ((pg->flags & PG_RELEASED) != 0 ||		    (locked && amap && amap_lookup(&ufi->entry->aref,		    ufi->orig_rvaddr - ufi->entry->start))) {			if (locked)				uvmfault_unlockall(ufi, amap, NULL, NULL);			locked = FALSE;		}		/*		 * didn't get the lock?   release the page and retry.		 */		if (locked == FALSE) {			if (pg->flags & PG_WANTED)				/* still holding object lock */				wakeup(pg);			if (pg->flags & PG_RELEASED) {#ifdef DIAGNOSTIC				if (uobj->pgops->pgo_releasepg == NULL)			panic("uvm_loanuobj: object has no releasepg function");#endif				/* frees page */				if (uobj->pgops->pgo_releasepg(pg, NULL))					simple_unlock(&uobj->vmobjlock);				return (0);			}			uvm_lock_pageq();			uvm_pageactivate(pg); /* make sure it is in queues */			uvm_unlock_pageq();			pg->flags &= ~(PG_BUSY|PG_WANTED);			UVM_PAGE_OWN(pg, NULL);			simple_unlock(&uobj->vmobjlock);			return (0);		}	}	/*	 * at this point we have the page we want ("pg") marked PG_BUSY for us	 * and we have all data structures locked.   do the loanout.   page can	 * not be PG_RELEASED (we caught this above).	 */	if ((flags & UVM_LOAN_TOANON) == 0) { /* loan to wired-kernel page? */		uvm_lock_pageq();		if (pg->loan_count == 0)			pmap_page_protect(pg, VM_PROT_READ);		pg->loan_count++;		uvm_pagewire(pg);		uvm_unlock_pageq();		**output = pg;		*output = (*output) + 1;		if (pg->flags & PG_WANTED)			wakeup(pg);		pg->flags &= ~(PG_WANTED|PG_BUSY);		UVM_PAGE_OWN(pg, NULL);		return(1);		/* got it! */	}	/*	 * must be a loan to an anon.   check to see if there is already	 * an anon associated with this page.  if so, then just return	 * a reference to this object.   the page should already be	 * mapped read-only because it is already on loan.	 */	if (pg->uanon) {		anon = pg->uanon;		simple_lock(&anon->an_lock);		anon->an_ref++;		simple_unlock(&anon->an_lock);		**output = anon;		*output = (*output) + 1;		uvm_lock_pageq();		uvm_pageactivate(pg);	/* reactivate */		uvm_unlock_pageq();		if (pg->flags & PG_WANTED)			wakeup(pg);		pg->flags &= ~(PG_WANTED|PG_BUSY);		UVM_PAGE_OWN(pg, NULL);		return(1);	}	/*	 * need to allocate a new anon	 */	anon = uvm_analloc();	if (anon == NULL) {		/* out of VM! */		if (pg->flags & PG_WANTED)			wakeup(pg);		pg->flags &= ~(PG_WANTED|PG_BUSY);		UVM_PAGE_OWN(pg, NULL);		uvmfault_unlockall(ufi, amap, uobj, NULL);		return(-1);	}	/* anon is locked! */	anon->u.an_page = pg;	pg->uanon = anon;	uvm_lock_pageq();	if (pg->loan_count == 0)		pmap_page_protect(pg, VM_PROT_READ);	pg->loan_count++;	uvm_pageactivate(pg);	uvm_unlock_pageq();	**output = anon;	*output = (*output) + 1;	if (pg->flags & PG_WANTED)		wakeup(pg);	pg->flags &= ~(PG_WANTED|PG_BUSY);	UVM_PAGE_OWN(pg, NULL);	simple_unlock(&anon->an_lock);	return(1);}