Changeset View
Changeset View
Standalone View
Standalone View
head/sys/vm/vm_map.c
Show First 20 Lines • Show All 3,716 Lines • ▼ Show 20 Lines | if ((entry->protection & protection) != protection) | ||||
return (FALSE); | return (FALSE); | ||||
/* go to next entry */ | /* go to next entry */ | ||||
start = entry->end; | start = entry->end; | ||||
entry = vm_map_entry_succ(entry); | entry = vm_map_entry_succ(entry); | ||||
} | } | ||||
return (TRUE); | return (TRUE); | ||||
} | } | ||||
/* | /* | ||||
* | |||||
* vm_map_copy_anon_object: | |||||
* | |||||
* Copies an anonymous object from an existing map entry to a | |||||
* new one. Carries forward the swap charge. May change the | |||||
* src object on return. | |||||
*/ | |||||
static void | |||||
vm_map_copy_anon_object(vm_map_entry_t src_entry, vm_map_entry_t dst_entry, | |||||
vm_offset_t size, vm_ooffset_t *fork_charge) | |||||
{ | |||||
vm_object_t src_object; | |||||
struct ucred *cred; | |||||
int charged; | |||||
src_object = src_entry->object.vm_object; | |||||
VM_OBJECT_WLOCK(src_object); | |||||
charged = ENTRY_CHARGED(src_entry); | |||||
vm_object_collapse(src_object); | |||||
if ((src_object->flags & OBJ_ONEMAPPING) != 0) { | |||||
vm_object_split(src_entry); | |||||
src_object = src_entry->object.vm_object; | |||||
} | |||||
vm_object_reference_locked(src_object); | |||||
vm_object_clear_flag(src_object, OBJ_ONEMAPPING); | |||||
if (src_entry->cred != NULL && | |||||
!(src_entry->eflags & MAP_ENTRY_NEEDS_COPY)) { | |||||
KASSERT(src_object->cred == NULL, | |||||
("OVERCOMMIT: vm_map_copy_anon_entry: cred %p", | |||||
src_object)); | |||||
src_object->cred = src_entry->cred; | |||||
src_object->charge = size; | |||||
} | |||||
VM_OBJECT_WUNLOCK(src_object); | |||||
dst_entry->object.vm_object = src_object; | |||||
if (charged) { | |||||
cred = curthread->td_ucred; | |||||
crhold(cred); | |||||
dst_entry->cred = cred; | |||||
*fork_charge += size; | |||||
if (!(src_entry->eflags & MAP_ENTRY_NEEDS_COPY)) { | |||||
crhold(cred); | |||||
src_entry->cred = cred; | |||||
*fork_charge += size; | |||||
} | |||||
} | |||||
} | |||||
/* | |||||
* vm_map_copy_entry: | * vm_map_copy_entry: | ||||
* | * | ||||
* Copies the contents of the source entry to the destination | * Copies the contents of the source entry to the destination | ||||
* entry. The entries *must* be aligned properly. | * entry. The entries *must* be aligned properly. | ||||
*/ | */ | ||||
static void | static void | ||||
vm_map_copy_entry( | vm_map_copy_entry( | ||||
vm_map_t src_map, | vm_map_t src_map, | ||||
vm_map_t dst_map, | vm_map_t dst_map, | ||||
vm_map_entry_t src_entry, | vm_map_entry_t src_entry, | ||||
vm_map_entry_t dst_entry, | vm_map_entry_t dst_entry, | ||||
vm_ooffset_t *fork_charge) | vm_ooffset_t *fork_charge) | ||||
{ | { | ||||
vm_object_t src_object; | vm_object_t src_object; | ||||
vm_map_entry_t fake_entry; | vm_map_entry_t fake_entry; | ||||
vm_offset_t size; | vm_offset_t size; | ||||
struct ucred *cred; | |||||
int charged; | |||||
VM_MAP_ASSERT_LOCKED(dst_map); | VM_MAP_ASSERT_LOCKED(dst_map); | ||||
if ((dst_entry->eflags|src_entry->eflags) & MAP_ENTRY_IS_SUB_MAP) | if ((dst_entry->eflags|src_entry->eflags) & MAP_ENTRY_IS_SUB_MAP) | ||||
return; | return; | ||||
if (src_entry->wired_count == 0 || | if (src_entry->wired_count == 0 || | ||||
(src_entry->protection & VM_PROT_WRITE) == 0) { | (src_entry->protection & VM_PROT_WRITE) == 0) { | ||||
Show All 9 Lines | if ((src_entry->eflags & MAP_ENTRY_NEEDS_COPY) == 0 && | ||||
src_entry->protection & ~VM_PROT_WRITE); | src_entry->protection & ~VM_PROT_WRITE); | ||||
} | } | ||||
/* | /* | ||||
* Make a copy of the object. | * Make a copy of the object. | ||||
*/ | */ | ||||
size = src_entry->end - src_entry->start; | size = src_entry->end - src_entry->start; | ||||
if ((src_object = src_entry->object.vm_object) != NULL) { | if ((src_object = src_entry->object.vm_object) != NULL) { | ||||
VM_OBJECT_WLOCK(src_object); | |||||
charged = ENTRY_CHARGED(src_entry); | |||||
if ((src_object->flags & OBJ_ANON) != 0) { | if ((src_object->flags & OBJ_ANON) != 0) { | ||||
vm_object_collapse(src_object); | vm_map_copy_anon_object(src_entry, dst_entry, | ||||
if ((src_object->flags & OBJ_ONEMAPPING) != 0) { | size, fork_charge); | ||||
vm_object_split(src_entry); | /* May have split/collapsed, reload obj. */ | ||||
src_object = | src_object = src_entry->object.vm_object; | ||||
src_entry->object.vm_object; | } else { | ||||
} | vm_object_reference(src_object); | ||||
} | |||||
vm_object_reference_locked(src_object); | |||||
vm_object_clear_flag(src_object, OBJ_ONEMAPPING); | |||||
if (src_entry->cred != NULL && | |||||
!(src_entry->eflags & MAP_ENTRY_NEEDS_COPY)) { | |||||
KASSERT(src_object->cred == NULL, | |||||
("OVERCOMMIT: vm_map_copy_entry: cred %p", | |||||
src_object)); | |||||
src_object->cred = src_entry->cred; | |||||
src_object->charge = size; | |||||
} | |||||
VM_OBJECT_WUNLOCK(src_object); | |||||
dst_entry->object.vm_object = src_object; | dst_entry->object.vm_object = src_object; | ||||
if (charged) { | |||||
cred = curthread->td_ucred; | |||||
crhold(cred); | |||||
dst_entry->cred = cred; | |||||
*fork_charge += size; | |||||
if (!(src_entry->eflags & | |||||
MAP_ENTRY_NEEDS_COPY)) { | |||||
crhold(cred); | |||||
src_entry->cred = cred; | |||||
*fork_charge += size; | |||||
} | |||||
} | } | ||||
src_entry->eflags |= MAP_ENTRY_COW | | src_entry->eflags |= MAP_ENTRY_COW | | ||||
MAP_ENTRY_NEEDS_COPY; | MAP_ENTRY_NEEDS_COPY; | ||||
dst_entry->eflags |= MAP_ENTRY_COW | | dst_entry->eflags |= MAP_ENTRY_COW | | ||||
MAP_ENTRY_NEEDS_COPY; | MAP_ENTRY_NEEDS_COPY; | ||||
dst_entry->offset = src_entry->offset; | dst_entry->offset = src_entry->offset; | ||||
if (src_entry->eflags & MAP_ENTRY_WRITECNT) { | if (src_entry->eflags & MAP_ENTRY_WRITECNT) { | ||||
/* | /* | ||||
▲ Show 20 Lines • Show All 1,183 Lines • Show Last 20 Lines |