panic("uvm_map_clean: weird flags");
panic("uvm_map_clean: wierd flags");
uvm_map_clean(map, start, end, flags)	struct vm_map *map;	vaddr_t start, end;	int flags;{	struct vm_map_entry *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);	KASSERT((flags & (PGO_FREE|PGO_DEACTIVATE)) !=		(PGO_FREE|PGO_DEACTIVATE));	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 EFAULT;	}	/*	 * 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 EINVAL;		}		if (end <= current->end) {			break;		}		if (current->end != current->next->start) {			vm_map_unlock_read(map);			return EFAULT;		}	}	error = 0;	for (current = entry; start < end; current = current->next) {		amap = current->aref.ar_amap;	/* top layer */		uobj = current->object.uvm_obj;	/* bottom layer */		KASSERT(start >= current->start);		/*		 * 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;		amap_lock(amap);		offset = start - current->start;		size = MIN(end, current->end) - start;		for ( ; 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: deactivate_it:				/* 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) {					KASSERT(pg->uobject == NULL);					uvm_unlock_pageq();					simple_unlock(&anon->an_lock);					continue;				}				KASSERT(pg->uanon == anon);				/* ...and deactivate the page. */				pmap_clear_reference(pg);				uvm_pagedeactivate(pg);				uvm_unlock_pageq();				simple_unlock(&anon->an_lock);				continue;			case PGO_FREE:				/*				 * If there are multiple references to				 * the amap, just deactivate the page.				 */				if (amap_refs(amap) > 1)					goto deactivate_it;				/* XXX skip the page if it's wired */				if (pg->wire_count != 0) {					simple_unlock(&anon->an_lock);					continue;				}				amap_unadd(&current->aref, offset);				refs = --anon->an_ref;				simple_unlock(&anon->an_lock);				if (refs == 0)					uvm_anfree(anon);				continue;			default:				panic("uvm_map_clean: weird flags");			}		}		amap_unlock(amap); flush_object:		/*		 * flush pages if we've got a valid backing object.		 */		offset = current->offset + (start - current->start);		size = MIN(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 = EIO;		}		start += size;	}	vm_map_unlock_read(map);	return (error);}