amap_unadd(&entry->aref, offset);
amap_unadd(&current->aref, offset);
uvm_map_clean(map, start, end, flags)	vm_map_t map;	vaddr_t start, end;	int flags;{	vm_map_entry_t current, entry;	struct uvm_object *uobj;	struct vm_amap *amap;	struct vm_anon *anon;	struct vm_page *pg;	vaddr_t offset;	vsize_t size;	int rv, error, refs;	UVMHIST_FUNC("uvm_map_clean"); UVMHIST_CALLED(maphist);	UVMHIST_LOG(maphist,"(map=0x%x,start=0x%x,end=0x%x,flags=0x%x)",	map, start, end, flags);#ifdef DIAGNOSTIC	if ((flags & (PGO_FREE|PGO_DEACTIVATE)) == (PGO_FREE|PGO_DEACTIVATE))		panic("uvm_map_clean: FREE and DEACTIVATE");#endif	vm_map_lock_read(map);	VM_MAP_RANGE_CHECK(map, start, end);	if (uvm_map_lookup_entry(map, start, &entry) == FALSE) {		vm_map_unlock_read(map);		return(KERN_INVALID_ADDRESS);	}	/*	 * Make a first pass to check for holes.	 */	for (current = entry; current->start < end; current = current->next) {		if (UVM_ET_ISSUBMAP(current)) {			vm_map_unlock_read(map);			return (KERN_INVALID_ARGUMENT);		}		if (end > current->end && (current->next == &map->header ||		    current->end != current->next->start)) {			vm_map_unlock_read(map);			return (KERN_INVALID_ADDRESS);		}	}	error = KERN_SUCCESS;	for (current = entry; current->start < end; current = current->next) {		amap = current->aref.ar_amap;	/* top layer */		uobj = current->object.uvm_obj;	/* bottom layer */#ifdef DIAGNOSTIC		if (start < current->start)			panic("uvm_map_clean: hole");#endif		/*		 * No amap cleaning necessary if:		 *		 *	(1) There's no amap.		 *		 *	(2) We're not deactivating or freeing pages.		 */		if (amap == NULL ||		    (flags & (PGO_DEACTIVATE|PGO_FREE)) == 0)			goto flush_object;		/* XXX for now, just in case... */		if (amap_clean_works == 0)			goto flush_object;		amap_lock(amap);		offset = start - current->start;		size = (end <= current->end ? end : current->end) -		    start;		for (/* nothing */; size != 0; size -= PAGE_SIZE,		     offset += PAGE_SIZE) {			anon = amap_lookup(&current->aref, offset);			if (anon == NULL)				continue;			simple_lock(&anon->an_lock);			pg = anon->u.an_page;			if (pg == NULL) {				simple_unlock(&anon->an_lock);				continue;			}			switch (flags & (PGO_CLEANIT|PGO_FREE|PGO_DEACTIVATE)) {			/*			 * XXX In these first 3 cases, we always just			 * XXX deactivate the page.  We may want to			 * XXX handle the different cases more			 * XXX specifically, in the future.			 */			case PGO_CLEANIT|PGO_FREE:			case PGO_CLEANIT|PGO_DEACTIVATE:			case PGO_DEACTIVATE:				/* skip the page if it's loaned or wired */				if (pg->loan_count != 0 ||				    pg->wire_count != 0) {					simple_unlock(&anon->an_lock);					continue;				}				uvm_lock_pageq();				/*				 * skip the page if it's not actually owned				 * by the anon (may simply be loaned to the				 * anon).				 */				if ((pg->pqflags & PQ_ANON) == 0) {#ifdef DIAGNOSTIC					if (pg->uobject != NULL)						panic("uvm_map_clean: "						    "page anon vs. object "						    "inconsistency");#endif					uvm_unlock_pageq();					simple_unlock(&anon->an_lock);					continue;				}#ifdef DIAGNOSTIC				if (pg->uanon != anon)					panic("uvm_map_clean: anon "					    "inconsistency");#endif				/* zap all mappings for the page. */				pmap_page_protect(PMAP_PGARG(pg),				    VM_PROT_NONE);				/* ...and deactivate the page. */				uvm_pagedeactivate(pg);				uvm_unlock_pageq();				simple_unlock(&anon->an_lock);				continue;			case PGO_FREE:				/* XXX skip the page if it's wired */				if (pg->wire_count != 0) {					simple_unlock(&anon->an_lock);					continue;				}				amap_unadd(&entry->aref, offset);				refs = --anon->an_ref;				simple_unlock(&anon->an_lock);				if (refs == 0)					uvm_anfree(anon);				continue;			default:				panic("uvm_map_clean: wierd flags");			}#ifdef DIAGNOSTIC			panic("uvm_map_clean: unreachable code");#endif		}		amap_unlock(amap); flush_object:		/*		 * flush pages if we've got a valid backing object.		 */		offset = current->offset + (start - current->start);		size = (end <= current->end ? end : current->end) - start;		if (uobj != NULL) {			simple_lock(&uobj->vmobjlock);			rv = uobj->pgops->pgo_flush(uobj, offset,			    offset + size, flags);			simple_unlock(&uobj->vmobjlock);			if (rv == FALSE)				error = KERN_FAILURE;		}		start += size;	}	vm_map_unlock_read(map);	return (error); }