summaryrefslogtreecommitdiffstats
path: root/sys/vm
diff options
context:
space:
mode:
authorkib <kib@FreeBSD.org>2009-07-03 22:17:37 +0000
committerkib <kib@FreeBSD.org>2009-07-03 22:17:37 +0000
commitaf8ce5a98815085a29b45a941b5af56345470b10 (patch)
tree90fec0503ef96a4f2264eedd1ad62f2525a5c443 /sys/vm
parentea30121075999891414cf35314d413324382bb62 (diff)
downloadFreeBSD-src-af8ce5a98815085a29b45a941b5af56345470b10.zip
FreeBSD-src-af8ce5a98815085a29b45a941b5af56345470b10.tar.gz
When forking a vm space that has wired map entries, do not forget to
charge the objects created by vm_fault_copy_entry. The object charge was set, but reserve not incremented. Reported by: Greg Rivers <gcr+freebsd-current tharned org> Reviewed by: alc (previous version) Approved by: re (kensmith)
Diffstat (limited to 'sys/vm')
-rw-r--r--sys/vm/vm_extern.h3
-rw-r--r--sys/vm/vm_fault.c21
-rw-r--r--sys/vm/vm_map.c4
3 files changed, 16 insertions, 12 deletions
diff --git a/sys/vm/vm_extern.h b/sys/vm/vm_extern.h
index 7bacde4..ec21a3a 100644
--- a/sys/vm/vm_extern.h
+++ b/sys/vm/vm_extern.h
@@ -55,7 +55,8 @@ vm_map_t kmem_suballoc(vm_map_t, vm_offset_t *, vm_offset_t *, vm_size_t,
void swapout_procs(int);
int useracc(void *, int, int);
int vm_fault(vm_map_t, vm_offset_t, vm_prot_t, int);
-void vm_fault_copy_entry(vm_map_t, vm_map_t, vm_map_entry_t, vm_map_entry_t);
+void vm_fault_copy_entry(vm_map_t, vm_map_t, vm_map_entry_t, vm_map_entry_t,
+ vm_ooffset_t *);
void vm_fault_unwire(vm_map_t, vm_offset_t, vm_offset_t, boolean_t);
int vm_fault_wire(vm_map_t, vm_offset_t, vm_offset_t, boolean_t, boolean_t);
int vm_forkproc(struct thread *, struct proc *, struct thread *, struct vmspace *, int);
diff --git a/sys/vm/vm_fault.c b/sys/vm/vm_fault.c
index 43743f4..ff8852b 100644
--- a/sys/vm/vm_fault.c
+++ b/sys/vm/vm_fault.c
@@ -1126,11 +1126,9 @@ vm_fault_unwire(vm_map_t map, vm_offset_t start, vm_offset_t end,
* entry corresponding to a main map entry that is wired down).
*/
void
-vm_fault_copy_entry(dst_map, src_map, dst_entry, src_entry)
- vm_map_t dst_map;
- vm_map_t src_map;
- vm_map_entry_t dst_entry;
- vm_map_entry_t src_entry;
+vm_fault_copy_entry(vm_map_t dst_map, vm_map_t src_map,
+ vm_map_entry_t dst_entry, vm_map_entry_t src_entry,
+ vm_ooffset_t *fork_charge)
{
vm_object_t backing_object, dst_object, object;
vm_object_t src_object;
@@ -1161,13 +1159,16 @@ vm_fault_copy_entry(dst_map, src_map, dst_entry, src_entry)
#endif
VM_OBJECT_LOCK(dst_object);
+ KASSERT(dst_entry->object.vm_object == NULL,
+ ("vm_fault_copy_entry: vm_object not NULL"));
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;
- }
+ dst_object->uip = curthread->td_ucred->cr_ruidinfo;
+ uihold(dst_object->uip);
+ dst_object->charge = dst_entry->end - dst_entry->start;
+ KASSERT(dst_entry->uip == NULL,
+ ("vm_fault_copy_entry: leaked swp charge"));
+ *fork_charge += dst_object->charge;
prot = dst_entry->max_protection;
/*
diff --git a/sys/vm/vm_map.c b/sys/vm/vm_map.c
index 82d37e6..7cc2c2d 100644
--- a/sys/vm/vm_map.c
+++ b/sys/vm/vm_map.c
@@ -2909,7 +2909,8 @@ vm_map_copy_entry(
* Cause wired pages to be copied into the new map by
* simulating faults (the new pages are pageable)
*/
- vm_fault_copy_entry(dst_map, src_map, dst_entry, src_entry);
+ vm_fault_copy_entry(dst_map, src_map, dst_entry, src_entry,
+ fork_charge);
}
}
@@ -3073,6 +3074,7 @@ vmspace_fork(struct vmspace *vm1, vm_ooffset_t *fork_charge)
MAP_ENTRY_IN_TRANSITION);
new_entry->wired_count = 0;
new_entry->object.vm_object = NULL;
+ new_entry->uip = NULL;
vm_map_entry_link(new_map, new_map->header.prev,
new_entry);
vmspace_map_entry_forked(vm1, vm2, new_entry);
OpenPOWER on IntegriCloud