From owner-p4-projects@FreeBSD.ORG Wed Jun 24 18:53:05 2009 Return-Path: Delivered-To: p4-projects@freebsd.org Received: by hub.freebsd.org (Postfix, from userid 32767) id 1C4661065670; Wed, 24 Jun 2009 18:53:05 +0000 (UTC) Delivered-To: perforce@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id C09E6106564A for ; Wed, 24 Jun 2009 18:53:04 +0000 (UTC) (envelope-from jhb@freebsd.org) Received: from repoman.freebsd.org (repoman.freebsd.org [IPv6:2001:4f8:fff6::29]) by mx1.freebsd.org (Postfix) with ESMTP id AD19E8FC17 for ; Wed, 24 Jun 2009 18:53:04 +0000 (UTC) (envelope-from jhb@freebsd.org) Received: from repoman.freebsd.org (localhost [127.0.0.1]) by repoman.freebsd.org (8.14.3/8.14.3) with ESMTP id n5OIr4dO044158 for ; Wed, 24 Jun 2009 18:53:04 GMT (envelope-from jhb@freebsd.org) Received: (from perforce@localhost) by repoman.freebsd.org (8.14.3/8.14.3/Submit) id n5OIr4vS044156 for perforce@freebsd.org; Wed, 24 Jun 2009 18:53:04 GMT (envelope-from jhb@freebsd.org) Date: Wed, 24 Jun 2009 18:53:04 GMT Message-Id: <200906241853.n5OIr4vS044156@repoman.freebsd.org> X-Authentication-Warning: repoman.freebsd.org: perforce set sender to jhb@freebsd.org using -f From: John Baldwin To: Perforce Change Reviews Cc: Subject: PERFORCE change 165083 for review X-BeenThere: p4-projects@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: p4 projects tree changes List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 24 Jun 2009 18:53:06 -0000 http://perforce.freebsd.org/chv.cgi?CH=165083 Change 165083 by jhb@jhb_jhbbsd on 2009/06/24 18:53:03 Missing bits of kib's RLIMIT_SWAP commit. Affected files ... .. //depot/projects/smpng/sys/vm/vm_extern.h#34 edit .. //depot/projects/smpng/sys/vm/vm_fault.c#76 edit .. //depot/projects/smpng/sys/vm/vm_kern.c#44 edit .. //depot/projects/smpng/sys/vm/vm_map.c#99 edit .. //depot/projects/smpng/sys/vm/vm_map.h#43 edit .. //depot/projects/smpng/sys/vm/vm_mmap.c#78 edit .. //depot/projects/smpng/sys/vm/vm_object.c#109 edit .. //depot/projects/smpng/sys/vm/vm_object.h#38 edit .. //depot/projects/smpng/sys/vm/vm_pager.c#27 edit .. //depot/projects/smpng/sys/vm/vm_pager.h#15 edit .. //depot/projects/smpng/sys/vm/vnode_pager.c#74 edit Differences ... ==== //depot/projects/smpng/sys/vm/vm_extern.h#34 (text+ko) ==== @@ -63,7 +63,7 @@ int vm_mmap(vm_map_t, vm_offset_t *, vm_size_t, vm_prot_t, vm_prot_t, int, objtype_t, void *, vm_ooffset_t); void vm_set_page_size(void); struct vmspace *vmspace_alloc(vm_offset_t, vm_offset_t); -struct vmspace *vmspace_fork(struct vmspace *); +struct vmspace *vmspace_fork(struct vmspace *, vm_ooffset_t *); int vmspace_exec(struct proc *, vm_offset_t, vm_offset_t); int vmspace_unshare(struct proc *); void vmspace_exit(struct thread *); ==== //depot/projects/smpng/sys/vm/vm_fault.c#76 (text+ko) ==== @@ -1163,7 +1163,11 @@ VM_OBJECT_LOCK(dst_object); dst_entry->object.vm_object = dst_object; dst_entry->offset = 0; - + if (dst_entry->uip != NULL) { + dst_object->uip = dst_entry->uip; + dst_object->charge = dst_entry->end - dst_entry->start; + dst_entry->uip = NULL; + } prot = dst_entry->max_protection; /* ==== //depot/projects/smpng/sys/vm/vm_kern.c#44 (text+ko) ==== @@ -235,7 +235,8 @@ *min = vm_map_min(parent); ret = vm_map_find(parent, NULL, 0, min, size, superpage_align ? - VMFS_ALIGNED_SPACE : VMFS_ANY_SPACE, VM_PROT_ALL, VM_PROT_ALL, 0); + VMFS_ALIGNED_SPACE : VMFS_ANY_SPACE, VM_PROT_ALL, VM_PROT_ALL, + MAP_ACC_NO_CHARGE); if (ret != KERN_SUCCESS) panic("kmem_suballoc: bad status return of %d", ret); *max = *min + size; @@ -422,6 +423,8 @@ vm_offset_t addr; size = round_page(size); + if (!swap_reserve(size)) + return (0); for (;;) { /* @@ -434,12 +437,14 @@ /* no space now; see if we can ever get space */ if (vm_map_max(map) - vm_map_min(map) < size) { vm_map_unlock(map); + swap_release(size); return (0); } map->needs_wakeup = TRUE; vm_map_unlock_and_wait(map, 0); } - vm_map_insert(map, NULL, 0, addr, addr + size, VM_PROT_ALL, VM_PROT_ALL, 0); + vm_map_insert(map, NULL, 0, addr, addr + size, VM_PROT_ALL, + VM_PROT_ALL, MAP_ACC_CHARGED); vm_map_unlock(map); return (addr); } ==== //depot/projects/smpng/sys/vm/vm_map.c#99 (text+ko) ==== @@ -149,6 +149,10 @@ static void vmspace_zdtor(void *mem, int size, void *arg); #endif +#define ENTRY_CHARGED(e) ((e)->uip != NULL || \ + ((e)->object.vm_object != NULL && (e)->object.vm_object->uip != NULL && \ + !((e)->eflags & MAP_ENTRY_NEEDS_COPY))) + /* * PROC_VMSPACE_{UN,}LOCK() can be a noop as long as vmspaces are type * stable. @@ -1076,6 +1080,8 @@ vm_map_entry_t prev_entry; vm_map_entry_t temp_entry; vm_eflags_t protoeflags; + struct uidinfo *uip; + boolean_t charge_prev_obj; VM_MAP_ASSERT_LOCKED(map); @@ -1103,6 +1109,7 @@ return (KERN_NO_SPACE); protoeflags = 0; + charge_prev_obj = FALSE; if (cow & MAP_COPY_ON_WRITE) protoeflags |= MAP_ENTRY_COW|MAP_ENTRY_NEEDS_COPY; @@ -1118,6 +1125,27 @@ if (cow & MAP_DISABLE_COREDUMP) protoeflags |= MAP_ENTRY_NOCOREDUMP; + uip = NULL; + KASSERT((object != kmem_object && object != kernel_object) || + ((object == kmem_object || object == kernel_object) && + !(protoeflags & MAP_ENTRY_NEEDS_COPY)), + ("kmem or kernel object and cow")); + if (cow & (MAP_ACC_NO_CHARGE | MAP_NOFAULT)) + goto charged; + if ((cow & MAP_ACC_CHARGED) || ((prot & VM_PROT_WRITE) && + ((protoeflags & MAP_ENTRY_NEEDS_COPY) || object == NULL))) { + if (!(cow & MAP_ACC_CHARGED) && !swap_reserve(end - start)) + return (KERN_RESOURCE_SHORTAGE); + KASSERT(object == NULL || (cow & MAP_ENTRY_NEEDS_COPY) || + object->uip == NULL, + ("OVERCOMMIT: vm_map_insert o %p", object)); + uip = curthread->td_ucred->cr_ruidinfo; + uihold(uip); + if (object == NULL && !(protoeflags & MAP_ENTRY_NEEDS_COPY)) + charge_prev_obj = TRUE; + } + +charged: if (object != NULL) { /* * OBJ_ONEMAPPING must be cleared unless this mapping @@ -1135,11 +1163,13 @@ (prev_entry->eflags == protoeflags) && (prev_entry->end == start) && (prev_entry->wired_count == 0) && - ((prev_entry->object.vm_object == NULL) || - vm_object_coalesce(prev_entry->object.vm_object, - prev_entry->offset, - (vm_size_t)(prev_entry->end - prev_entry->start), - (vm_size_t)(end - prev_entry->end)))) { + (prev_entry->uip == uip || + (prev_entry->object.vm_object != NULL && + (prev_entry->object.vm_object->uip == uip))) && + vm_object_coalesce(prev_entry->object.vm_object, + prev_entry->offset, + (vm_size_t)(prev_entry->end - prev_entry->start), + (vm_size_t)(end - prev_entry->end), charge_prev_obj)) { /* * We were able to extend the object. Determine if we * can extend the previous map entry to include the @@ -1152,6 +1182,8 @@ prev_entry->end = end; vm_map_entry_resize_free(map, prev_entry); vm_map_simplify_entry(map, prev_entry); + if (uip != NULL) + uifree(uip); return (KERN_SUCCESS); } @@ -1165,6 +1197,12 @@ offset = prev_entry->offset + (prev_entry->end - prev_entry->start); vm_object_reference(object); + if (uip != NULL && object != NULL && object->uip != NULL && + !(prev_entry->eflags & MAP_ENTRY_NEEDS_COPY)) { + /* Object already accounts for this uid. */ + uifree(uip); + uip = NULL; + } } /* @@ -1179,6 +1217,7 @@ new_entry = vm_map_entry_create(map); new_entry->start = start; new_entry->end = end; + new_entry->uip = NULL; new_entry->eflags = protoeflags; new_entry->object.vm_object = object; @@ -1190,6 +1229,10 @@ new_entry->max_protection = max; new_entry->wired_count = 0; + KASSERT(uip == NULL || !ENTRY_CHARGED(new_entry), + ("OVERCOMMIT: vm_map_insert leaks vm_map %p", new_entry)); + new_entry->uip = uip; + /* * Insert the new entry into the list */ @@ -1398,7 +1441,8 @@ (prev->protection == entry->protection) && (prev->max_protection == entry->max_protection) && (prev->inheritance == entry->inheritance) && - (prev->wired_count == entry->wired_count)) { + (prev->wired_count == entry->wired_count) && + (prev->uip == entry->uip)) { vm_map_entry_unlink(map, prev); entry->start = prev->start; entry->offset = prev->offset; @@ -1416,6 +1460,8 @@ */ if (prev->object.vm_object) vm_object_deallocate(prev->object.vm_object); + if (prev->uip != NULL) + uifree(prev->uip); vm_map_entry_dispose(map, prev); } } @@ -1431,7 +1477,8 @@ (next->protection == entry->protection) && (next->max_protection == entry->max_protection) && (next->inheritance == entry->inheritance) && - (next->wired_count == entry->wired_count)) { + (next->wired_count == entry->wired_count) && + (next->uip == entry->uip)) { vm_map_entry_unlink(map, next); entry->end = next->end; vm_map_entry_resize_free(map, entry); @@ -1441,6 +1488,8 @@ */ if (next->object.vm_object) vm_object_deallocate(next->object.vm_object); + if (next->uip != NULL) + uifree(next->uip); vm_map_entry_dispose(map, next); } } @@ -1489,6 +1538,21 @@ atop(entry->end - entry->start)); entry->object.vm_object = object; entry->offset = 0; + if (entry->uip != NULL) { + object->uip = entry->uip; + object->charge = entry->end - entry->start; + entry->uip = NULL; + } + } else if (entry->object.vm_object != NULL && + ((entry->eflags & MAP_ENTRY_NEEDS_COPY) == 0) && + entry->uip != NULL) { + VM_OBJECT_LOCK(entry->object.vm_object); + KASSERT(entry->object.vm_object->uip == NULL, + ("OVERCOMMIT: vm_entry_clip_start: both uip e %p", entry)); + entry->object.vm_object->uip = entry->uip; + entry->object.vm_object->charge = entry->end - entry->start; + VM_OBJECT_UNLOCK(entry->object.vm_object); + entry->uip = NULL; } new_entry = vm_map_entry_create(map); @@ -1497,6 +1561,8 @@ new_entry->end = start; entry->offset += (start - entry->start); entry->start = start; + if (new_entry->uip != NULL) + uihold(entry->uip); vm_map_entry_link(map, entry->prev, new_entry); @@ -1542,6 +1608,21 @@ atop(entry->end - entry->start)); entry->object.vm_object = object; entry->offset = 0; + if (entry->uip != NULL) { + object->uip = entry->uip; + object->charge = entry->end - entry->start; + entry->uip = NULL; + } + } else if (entry->object.vm_object != NULL && + ((entry->eflags & MAP_ENTRY_NEEDS_COPY) == 0) && + entry->uip != NULL) { + VM_OBJECT_LOCK(entry->object.vm_object); + KASSERT(entry->object.vm_object->uip == NULL, + ("OVERCOMMIT: vm_entry_clip_end: both uip e %p", entry)); + entry->object.vm_object->uip = entry->uip; + entry->object.vm_object->charge = entry->end - entry->start; + VM_OBJECT_UNLOCK(entry->object.vm_object); + entry->uip = NULL; } /* @@ -1552,6 +1633,8 @@ new_entry->start = entry->end = end; new_entry->offset += (end - entry->start); + if (new_entry->uip != NULL) + uihold(entry->uip); vm_map_entry_link(map, entry, new_entry); @@ -1724,6 +1807,8 @@ { vm_map_entry_t current; vm_map_entry_t entry; + vm_object_t obj; + struct uidinfo *uip; vm_map_lock(map); @@ -1751,6 +1836,61 @@ current = current->next; } + + /* + * Do an accounting pass for private read-only mappings that + * now will do cow due to allowed write (e.g. debugger sets + * breakpoint on text segment) + */ + for (current = entry; (current != &map->header) && + (current->start < end); current = current->next) { + + vm_map_clip_end(map, current, end); + + if (set_max || + ((new_prot & ~(current->protection)) & VM_PROT_WRITE) == 0 || + ENTRY_CHARGED(current)) { + continue; + } + + uip = curthread->td_ucred->cr_ruidinfo; + obj = current->object.vm_object; + + if (obj == NULL || (current->eflags & MAP_ENTRY_NEEDS_COPY)) { + if (!swap_reserve(current->end - current->start)) { + vm_map_unlock(map); + return (KERN_RESOURCE_SHORTAGE); + } + uihold(uip); + current->uip = uip; + continue; + } + + VM_OBJECT_LOCK(obj); + if (obj->type != OBJT_DEFAULT && obj->type != OBJT_SWAP) { + VM_OBJECT_UNLOCK(obj); + continue; + } + + /* + * Charge for the whole object allocation now, since + * we cannot distinguish between non-charged and + * charged clipped mapping of the same object later. + */ + KASSERT(obj->charge == 0, + ("vm_map_protect: object %p overcharged\n", obj)); + if (!swap_reserve(ptoa(obj->size))) { + VM_OBJECT_UNLOCK(obj); + vm_map_unlock(map); + return (KERN_RESOURCE_SHORTAGE); + } + + uihold(uip); + obj->uip = uip; + obj->charge = ptoa(obj->size); + VM_OBJECT_UNLOCK(obj); + } + /* * Go back and fix up protections. [Note that clipping is not * necessary the second time.] @@ -1759,8 +1899,6 @@ while ((current != &map->header) && (current->start < end)) { vm_prot_t old_prot; - vm_map_clip_end(map, current, end); - old_prot = current->protection; if (set_max) current->protection = @@ -2470,14 +2608,25 @@ vm_map_entry_delete(vm_map_t map, vm_map_entry_t entry) { vm_object_t object; - vm_pindex_t offidxstart, offidxend, count; + vm_pindex_t offidxstart, offidxend, count, size1; + vm_ooffset_t size; vm_map_entry_unlink(map, entry); - map->size -= entry->end - entry->start; + object = entry->object.vm_object; + size = entry->end - entry->start; + map->size -= size; + + if (entry->uip != NULL) { + swap_release_by_uid(size, entry->uip); + uifree(entry->uip); + } if ((entry->eflags & MAP_ENTRY_IS_SUB_MAP) == 0 && - (object = entry->object.vm_object) != NULL) { - count = OFF_TO_IDX(entry->end - entry->start); + (object != NULL)) { + KASSERT(entry->uip == NULL || object->uip == NULL || + (entry->eflags & MAP_ENTRY_NEEDS_COPY), + ("OVERCOMMIT vm_map_entry_delete: both uip %p", entry)); + count = OFF_TO_IDX(size); offidxstart = OFF_TO_IDX(entry->offset); offidxend = offidxstart + count; VM_OBJECT_LOCK(object); @@ -2489,8 +2638,17 @@ if (object->type == OBJT_SWAP) swap_pager_freespace(object, offidxstart, count); if (offidxend >= object->size && - offidxstart < object->size) + offidxstart < object->size) { + size1 = object->size; object->size = offidxstart; + if (object->uip != NULL) { + size1 -= object->size; + KASSERT(object->charge >= ptoa(size1), + ("vm_map_entry_delete: object->charge < 0")); + swap_release_by_uid(ptoa(size1), object->uip); + object->charge -= ptoa(size1); + } + } } VM_OBJECT_UNLOCK(object); } else @@ -2664,9 +2822,13 @@ vm_map_t src_map, vm_map_t dst_map, vm_map_entry_t src_entry, - vm_map_entry_t dst_entry) + vm_map_entry_t dst_entry, + vm_ooffset_t *fork_charge) { vm_object_t src_object; + vm_offset_t size; + struct uidinfo *uip; + int charged; VM_MAP_ASSERT_LOCKED(dst_map); @@ -2689,8 +2851,10 @@ /* * Make a copy of the object. */ + size = src_entry->end - src_entry->start; if ((src_object = src_entry->object.vm_object) != NULL) { VM_OBJECT_LOCK(src_object); + charged = ENTRY_CHARGED(src_entry); if ((src_object->handle == NULL) && (src_object->type == OBJT_DEFAULT || src_object->type == OBJT_SWAP)) { @@ -2702,14 +2866,39 @@ } vm_object_reference_locked(src_object); vm_object_clear_flag(src_object, OBJ_ONEMAPPING); + if (src_entry->uip != NULL && + !(src_entry->eflags & MAP_ENTRY_NEEDS_COPY)) { + KASSERT(src_object->uip == NULL, + ("OVERCOMMIT: vm_map_copy_entry: uip %p", + src_object)); + src_object->uip = src_entry->uip; + src_object->charge = size; + } VM_OBJECT_UNLOCK(src_object); dst_entry->object.vm_object = src_object; + if (charged) { + uip = curthread->td_ucred->cr_ruidinfo; + uihold(uip); + dst_entry->uip = uip; + *fork_charge += size; + if (!(src_entry->eflags & + MAP_ENTRY_NEEDS_COPY)) { + uihold(uip); + src_entry->uip = uip; + *fork_charge += size; + } + } src_entry->eflags |= (MAP_ENTRY_COW|MAP_ENTRY_NEEDS_COPY); dst_entry->eflags |= (MAP_ENTRY_COW|MAP_ENTRY_NEEDS_COPY); dst_entry->offset = src_entry->offset; } else { dst_entry->object.vm_object = NULL; dst_entry->offset = 0; + if (src_entry->uip != NULL) { + dst_entry->uip = curthread->td_ucred->cr_ruidinfo; + uihold(dst_entry->uip); + *fork_charge += size; + } } pmap_copy(dst_map->pmap, src_map->pmap, dst_entry->start, @@ -2766,7 +2955,7 @@ * The source map must not be locked. */ struct vmspace * -vmspace_fork(struct vmspace *vm1) +vmspace_fork(struct vmspace *vm1, vm_ooffset_t *fork_charge) { struct vmspace *vm2; vm_map_t old_map = &vm1->vm_map; @@ -2777,7 +2966,6 @@ int locked; vm_map_lock(old_map); - vm2 = vmspace_alloc(old_map->min_offset, old_map->max_offset); if (vm2 == NULL) goto unlock_and_return; @@ -2809,6 +2997,12 @@ atop(old_entry->end - old_entry->start)); old_entry->object.vm_object = object; old_entry->offset = 0; + if (old_entry->uip != NULL) { + object->uip = old_entry->uip; + object->charge = old_entry->end - + old_entry->start; + old_entry->uip = NULL; + } } /* @@ -2835,6 +3029,12 @@ } VM_OBJECT_LOCK(object); vm_object_clear_flag(object, OBJ_ONEMAPPING); + if (old_entry->uip != NULL) { + KASSERT(object->uip == NULL, ("vmspace_fork both uip")); + object->uip = old_entry->uip; + object->charge = old_entry->end - old_entry->start; + old_entry->uip = NULL; + } VM_OBJECT_UNLOCK(object); /* @@ -2877,7 +3077,7 @@ new_entry); vmspace_map_entry_forked(vm1, vm2, new_entry); vm_map_copy_entry(old_map, new_map, old_entry, - new_entry); + new_entry, fork_charge); break; } old_entry = old_entry->next; @@ -3005,6 +3205,7 @@ size_t grow_amount, max_grow; rlim_t stacklim, vmemlim; int is_procstack, rv; + struct uidinfo *uip; Retry: PROC_LOCK(p); @@ -3170,13 +3371,17 @@ } grow_amount = addr - stack_entry->end; - + uip = stack_entry->uip; + if (uip == NULL && stack_entry->object.vm_object != NULL) + uip = stack_entry->object.vm_object->uip; + if (uip != NULL && !swap_reserve_by_uid(grow_amount, uip)) + rv = KERN_NO_SPACE; /* Grow the underlying object if applicable. */ - if (stack_entry->object.vm_object == NULL || - vm_object_coalesce(stack_entry->object.vm_object, - stack_entry->offset, - (vm_size_t)(stack_entry->end - stack_entry->start), - (vm_size_t)grow_amount)) { + else if (stack_entry->object.vm_object == NULL || + vm_object_coalesce(stack_entry->object.vm_object, + stack_entry->offset, + (vm_size_t)(stack_entry->end - stack_entry->start), + (vm_size_t)grow_amount, uip != NULL)) { map->size += (addr - stack_entry->end); /* Update the current entry. */ stack_entry->end = addr; @@ -3249,12 +3454,18 @@ { struct vmspace *oldvmspace = p->p_vmspace; struct vmspace *newvmspace; + vm_ooffset_t fork_charge; if (oldvmspace->vm_refcnt == 1) return (0); - newvmspace = vmspace_fork(oldvmspace); + fork_charge = 0; + newvmspace = vmspace_fork(oldvmspace, &fork_charge); if (newvmspace == NULL) return (ENOMEM); + if (!swap_reserve_by_uid(fork_charge, p->p_ucred->cr_ruidinfo)) { + vmspace_free(newvmspace); + return (ENOMEM); + } PROC_VMSPACE_LOCK(p); p->p_vmspace = newvmspace; PROC_VMSPACE_UNLOCK(p); @@ -3300,6 +3511,9 @@ vm_map_t map = *var_map; vm_prot_t prot; vm_prot_t fault_type = fault_typea; + vm_object_t eobject; + struct uidinfo *uip; + vm_ooffset_t size; RetryLookup:; @@ -3356,7 +3570,7 @@ *wired = (entry->wired_count != 0); if (*wired) prot = fault_type = entry->protection; - + size = entry->end - entry->start; /* * If the entry was copy-on-write, we either ... */ @@ -3378,11 +3592,40 @@ if (vm_map_lock_upgrade(map)) goto RetryLookup; + if (entry->uip == NULL) { + /* + * The debugger owner is charged for + * the memory. + */ + uip = curthread->td_ucred->cr_ruidinfo; + uihold(uip); + if (!swap_reserve_by_uid(size, uip)) { + uifree(uip); + vm_map_unlock(map); + return (KERN_RESOURCE_SHORTAGE); + } + entry->uip = uip; + } vm_object_shadow( &entry->object.vm_object, &entry->offset, - atop(entry->end - entry->start)); + atop(size)); entry->eflags &= ~MAP_ENTRY_NEEDS_COPY; + eobject = entry->object.vm_object; + if (eobject->uip != NULL) { + /* + * The object was not shadowed. + */ + swap_release_by_uid(size, entry->uip); + uifree(entry->uip); + entry->uip = NULL; + } else if (entry->uip != NULL) { + VM_OBJECT_LOCK(eobject); + eobject->uip = entry->uip; + eobject->charge = size; + VM_OBJECT_UNLOCK(eobject); + entry->uip = NULL; + } vm_map_lock_downgrade(map); } else { @@ -3402,8 +3645,15 @@ if (vm_map_lock_upgrade(map)) goto RetryLookup; entry->object.vm_object = vm_object_allocate(OBJT_DEFAULT, - atop(entry->end - entry->start)); + atop(size)); entry->offset = 0; + if (entry->uip != NULL) { + VM_OBJECT_LOCK(entry->object.vm_object); + entry->object.vm_object->uip = entry->uip; + entry->object.vm_object->charge = size; + VM_OBJECT_UNLOCK(entry->object.vm_object); + entry->uip = NULL; + } vm_map_lock_downgrade(map); } @@ -3583,9 +3833,15 @@ db_indent -= 2; } } else { + if (entry->uip != NULL) + db_printf(", uip %d", entry->uip->ui_uid); db_printf(", object=%p, offset=0x%jx", (void *)entry->object.vm_object, (uintmax_t)entry->offset); + if (entry->object.vm_object && entry->object.vm_object->uip) + db_printf(", obj uip %d charge %jx", + entry->object.vm_object->uip->ui_uid, + (uintmax_t)entry->object.vm_object->charge); if (entry->eflags & MAP_ENTRY_COW) db_printf(", copy (%s)", (entry->eflags & MAP_ENTRY_NEEDS_COPY) ? "needed" : "done"); ==== //depot/projects/smpng/sys/vm/vm_map.h#43 (text+ko) ==== @@ -114,6 +114,7 @@ vm_inherit_t inheritance; /* inheritance */ int wired_count; /* can be paged if = 0 */ vm_pindex_t lastr; /* last read */ + struct uidinfo *uip; /* tmp storage for creator ref */ }; #define MAP_ENTRY_NOSYNC 0x0001 @@ -310,6 +311,8 @@ #define MAP_PREFAULT_MADVISE 0x0200 /* from (user) madvise request */ #define MAP_STACK_GROWS_DOWN 0x1000 #define MAP_STACK_GROWS_UP 0x2000 +#define MAP_ACC_CHARGED 0x4000 +#define MAP_ACC_NO_CHARGE 0x8000 /* * vm_fault option flags ==== //depot/projects/smpng/sys/vm/vm_mmap.c#78 (text+ko) ==== @@ -633,6 +633,8 @@ return (0); case KERN_PROTECTION_FAILURE: return (EACCES); + case KERN_RESOURCE_SHORTAGE: + return (ENOMEM); } return (EINVAL); } @@ -1208,7 +1210,7 @@ objsize = round_page(va.va_size); if (va.va_nlink == 0) flags |= MAP_NOSYNC; - obj = vm_pager_allocate(OBJT_VNODE, vp, objsize, prot, foff); + obj = vm_pager_allocate(OBJT_VNODE, vp, objsize, prot, foff, td->td_ucred); if (obj == NULL) { error = ENOMEM; goto done; @@ -1289,7 +1291,8 @@ dev_relthread(cdev); if (error != ENODEV) return (error); - obj = vm_pager_allocate(OBJT_DEVICE, cdev, objsize, prot, *foff); + obj = vm_pager_allocate(OBJT_DEVICE, cdev, objsize, prot, *foff, + td->td_ucred); if (obj == NULL) return (EINVAL); *objp = obj; ==== //depot/projects/smpng/sys/vm/vm_object.c#109 (text+ko) ==== @@ -77,6 +77,7 @@ #include #include /* for curproc, pageproc */ #include +#include #include #include #include @@ -222,6 +223,8 @@ object->generation = 1; object->ref_count = 1; object->flags = 0; + object->uip = NULL; + object->charge = 0; if ((object->type == OBJT_DEFAULT) || (object->type == OBJT_SWAP)) object->flags = OBJ_ONEMAPPING; object->pg_color = 0; @@ -609,6 +612,20 @@ mtx_unlock(&vm_object_list_mtx); /* + * Release the allocation charge. + */ + if (object->uip != NULL) { + KASSERT(object->type == OBJT_DEFAULT || + object->type == OBJT_SWAP, + ("vm_object_terminate: non-swap obj %p has uip", + object)); + swap_release_by_uid(object->charge, object->uip); + object->charge = 0; + uifree(object->uip); + object->uip = NULL; + } + + /* * Free the space for the object. */ uma_zfree(obj_zone, object); @@ -1347,6 +1364,14 @@ orig_object->backing_object_offset + entry->offset; new_object->backing_object = source; } + if (orig_object->uip != NULL) { + new_object->uip = orig_object->uip; + uihold(orig_object->uip); + new_object->charge = ptoa(size); + KASSERT(orig_object->charge >= ptoa(size), + ("orig_object->charge < 0")); + orig_object->charge -= ptoa(size); + } retry: if ((m = TAILQ_FIRST(&orig_object->memq)) != NULL) { if (m->pindex < offidxstart) { @@ -1757,6 +1782,13 @@ * and no object references within it, all that is * necessary is to dispose of it. */ + if (backing_object->uip != NULL) { + swap_release_by_uid(backing_object->charge, + backing_object->uip); + backing_object->charge = 0; + uifree(backing_object->uip); + backing_object->uip = NULL; + } KASSERT(backing_object->ref_count == 1, ("backing_object %p was somehow re-referenced during collapse!", backing_object)); VM_OBJECT_UNLOCK(backing_object); @@ -1994,13 +2026,15 @@ * prev_offset Offset into prev_object * prev_size Size of reference to prev_object * next_size Size of reference to the second object + * reserved Indicator that extension region has + * swap accounted for * * Conditions: * The object must *not* be locked. */ boolean_t vm_object_coalesce(vm_object_t prev_object, vm_ooffset_t prev_offset, - vm_size_t prev_size, vm_size_t next_size) + vm_size_t prev_size, vm_size_t next_size, boolean_t reserved) { vm_pindex_t next_pindex; @@ -2039,6 +2073,28 @@ } /* + * Account for the charge. + */ + if (prev_object->uip != NULL) { + + /* + * If prev_object was charged, then this mapping, + * althought not charged now, may become writable + * later. Non-NULL uip in the object would prevent + * swap reservation during enabling of the write + * access, so reserve swap now. Failed reservation + * cause allocation of the separate object for the map + * entry, and swap reservation for this entry is + * managed in appropriate time. + */ + if (!reserved && !swap_reserve_by_uid(ptoa(next_size), + prev_object->uip)) { + return (FALSE); + } + prev_object->charge += ptoa(next_size); + } + + /* * Remove any pages that may still be in the object from a previous * deallocation. */ @@ -2049,6 +2105,16 @@ if (prev_object->type == OBJT_SWAP) swap_pager_freespace(prev_object, next_pindex, next_size); +#if 0 + if (prev_object->uip != NULL) { + KASSERT(prev_object->charge >= + ptoa(prev_object->size - next_pindex), + ("object %p overcharged 1 %jx %jx", prev_object, + (uintmax_t)next_pindex, (uintmax_t)next_size)); + prev_object->charge -= ptoa(prev_object->size - + next_pindex); + } +#endif } /* @@ -2198,9 +2264,10 @@ return; db_iprintf( - "Object %p: type=%d, size=0x%jx, res=%d, ref=%d, flags=0x%x\n", + "Object %p: type=%d, size=0x%jx, res=%d, ref=%d, flags=0x%x uip %d charge %jx\n", object, (int)object->type, (uintmax_t)object->size, - object->resident_page_count, object->ref_count, object->flags); + object->resident_page_count, object->ref_count, object->flags, + object->uip ? object->uip->ui_uid : -1, (uintmax_t)object->charge); db_iprintf(" sref=%d, backing_object(%d)=(%p)+0x%jx\n", object->shadow_count, object->backing_object ? object->backing_object->ref_count : 0, ==== //depot/projects/smpng/sys/vm/vm_object.h#38 (text+ko) ==== @@ -133,6 +133,8 @@ int swp_bcount; } swp; } un_pager; + struct uidinfo *uip; + vm_ooffset_t charge; }; /* @@ -198,7 +200,8 @@ vm_object_t vm_object_allocate (objtype_t, vm_pindex_t); void _vm_object_allocate (objtype_t, vm_pindex_t, vm_object_t); -boolean_t vm_object_coalesce(vm_object_t, vm_ooffset_t, vm_size_t, vm_size_t); +boolean_t vm_object_coalesce(vm_object_t, vm_ooffset_t, vm_size_t, vm_size_t, + boolean_t); void vm_object_collapse (vm_object_t); void vm_object_deallocate (vm_object_t); void vm_object_destroy (vm_object_t); ==== //depot/projects/smpng/sys/vm/vm_pager.c#27 (text+ko) ==== @@ -88,7 +88,7 @@ static int dead_pager_getpages(vm_object_t, vm_page_t *, int, int); static vm_object_t dead_pager_alloc(void *, vm_ooffset_t, vm_prot_t, - vm_ooffset_t); + vm_ooffset_t, struct ucred *); static void dead_pager_putpages(vm_object_t, vm_page_t *, int, int, int *); static boolean_t dead_pager_haspage(vm_object_t, vm_pindex_t, int *, int *); static void dead_pager_dealloc(vm_object_t); @@ -105,7 +105,7 @@ static vm_object_t dead_pager_alloc(void *handle, vm_ooffset_t size, vm_prot_t prot, - vm_ooffset_t off) + vm_ooffset_t off, struct ucred *cred) { return NULL; } @@ -227,14 +227,14 @@ */ vm_object_t vm_pager_allocate(objtype_t type, void *handle, vm_ooffset_t size, - vm_prot_t prot, vm_ooffset_t off) + vm_prot_t prot, vm_ooffset_t off, struct ucred *cred) { vm_object_t ret; struct pagerops *ops; ops = pagertab[type]; if (ops) - ret = (*ops->pgo_alloc) (handle, size, prot, off); + ret = (*ops->pgo_alloc) (handle, size, prot, off, cred); else ret = NULL; return (ret); ==== //depot/projects/smpng/sys/vm/vm_pager.h#15 (text+ko) ==== @@ -47,7 +47,8 @@ TAILQ_HEAD(pagerlst, vm_object); typedef void pgo_init_t(void); -typedef vm_object_t pgo_alloc_t(void *, vm_ooffset_t, vm_prot_t, vm_ooffset_t); +typedef vm_object_t pgo_alloc_t(void *, vm_ooffset_t, vm_prot_t, vm_ooffset_t, + struct ucred *); typedef void pgo_dealloc_t(vm_object_t); typedef int pgo_getpages_t(vm_object_t, vm_page_t *, int, int); typedef void pgo_putpages_t(vm_object_t, vm_page_t *, int, int, int *); @@ -100,7 +101,8 @@ extern struct pagerops *pagertab[]; extern struct mtx pbuf_mtx; -vm_object_t vm_pager_allocate(objtype_t, void *, vm_ooffset_t, vm_prot_t, vm_ooffset_t); +vm_object_t vm_pager_allocate(objtype_t, void *, vm_ooffset_t, vm_prot_t, + vm_ooffset_t, struct ucred *); void vm_pager_bufferinit(void); void vm_pager_deallocate(vm_object_t); static __inline int vm_pager_get_pages(vm_object_t, vm_page_t *, int, int); ==== //depot/projects/smpng/sys/vm/vnode_pager.c#74 (text+ko) ==== @@ -83,7 +83,8 @@ static int vnode_pager_getpages(vm_object_t, vm_page_t *, int, int); static void vnode_pager_putpages(vm_object_t, vm_page_t *, int, boolean_t, int *); static boolean_t vnode_pager_haspage(vm_object_t, vm_pindex_t, int *, int *); -static vm_object_t vnode_pager_alloc(void *, vm_ooffset_t, vm_prot_t, vm_ooffset_t); +static vm_object_t vnode_pager_alloc(void *, vm_ooffset_t, vm_prot_t, + vm_ooffset_t, struct ucred *cred); struct pagerops vnodepagerops = { .pgo_alloc = vnode_pager_alloc, @@ -128,7 +129,7 @@ } } - object = vnode_pager_alloc(vp, size, 0, 0); + object = vnode_pager_alloc(vp, size, 0, 0, td->td_ucred); /* * Dereference the reference we just created. This assumes * that the object is associated with the vp. @@ -185,7 +186,7 @@ >>> TRUNCATED FOR MAIL (1000 lines) <<<