aboutsummaryrefslogtreecommitdiff
path: root/sys/vm/vm_map.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/vm/vm_map.c')
-rw-r--r--sys/vm/vm_map.c154
1 files changed, 115 insertions, 39 deletions
diff --git a/sys/vm/vm_map.c b/sys/vm/vm_map.c
index 17b0e758acc7..67039d4fabee 100644
--- a/sys/vm/vm_map.c
+++ b/sys/vm/vm_map.c
@@ -61,7 +61,7 @@
* any improvements or extensions that they make and grant Carnegie the
* rights to redistribute these changes.
*
- * $Id: vm_map.c,v 1.103 1997/12/29 01:03:34 dyson Exp $
+ * $Id: vm_map.c,v 1.104 1998/01/06 05:25:58 dyson Exp $
*/
/*
@@ -2405,7 +2405,7 @@ RetryLookup:;
vm_map_lock_downgrade(share_map);
}
- if (entry->object.vm_object != NULL)
+ if (entry->object.vm_object->type == OBJT_DEFAULT)
default_pager_convert_to_swapq(entry->object.vm_object);
/*
* Return the object/offset from this entry. If the entry was
@@ -2479,16 +2479,20 @@ vm_uiomove(mapa, srcobject, cp, cnt, uaddra, npages)
vm_offset_t uaddr, start, end;
vm_pindex_t first_pindex, osize, oindex;
off_t ooffset;
+ int skipinit, allremoved;
if (npages)
*npages = 0;
+ allremoved = 0;
+
while (cnt > 0) {
map = mapa;
uaddr = uaddra;
+ skipinit = 0;
if ((vm_map_lookup(&map, uaddr,
- VM_PROT_READ|VM_PROT_WRITE, &first_entry, &first_object,
+ VM_PROT_READ, &first_entry, &first_object,
&first_pindex, &prot, &wired, &su)) != KERN_SUCCESS) {
return EFAULT;
}
@@ -2506,17 +2510,16 @@ vm_uiomove(mapa, srcobject, cp, cnt, uaddra, npages)
osize = atop(tcnt);
+ oindex = OFF_TO_IDX(cp);
if (npages) {
- vm_pindex_t src_index, idx;
- src_index = OFF_TO_IDX(cp);
+ vm_pindex_t idx;
for (idx = 0; idx < osize; idx++) {
vm_page_t m;
- if ((m = vm_page_lookup(srcobject, src_index + idx)) == NULL) {
+ if ((m = vm_page_lookup(srcobject, oindex + idx)) == NULL) {
vm_map_lookup_done(map, first_entry);
return 0;
}
- if ((m->flags & PG_BUSY) || m->busy ||
- m->hold_count || m->wire_count ||
+ if ((m->flags & PG_BUSY) ||
((m->valid & VM_PAGE_BITS_ALL) != VM_PAGE_BITS_ALL)) {
vm_map_lookup_done(map, first_entry);
return 0;
@@ -2524,46 +2527,113 @@ vm_uiomove(mapa, srcobject, cp, cnt, uaddra, npages)
}
}
- oindex = OFF_TO_IDX(first_entry->offset);
-
/*
* If we are changing an existing map entry, just redirect
* the object, and change mappings.
*/
- if ((first_object->ref_count == 1) &&
- (first_object->backing_object == srcobject) &&
+ if (first_object->type == OBJT_VNODE) {
+
+ if (first_object != srcobject) {
+
+ vm_object_deallocate(first_object);
+ srcobject->flags |= OBJ_OPT;
+ vm_object_reference(srcobject);
+
+ first_entry->object.vm_object = srcobject;
+ first_entry->offset = cp;
+
+ } else if (first_entry->offset != cp) {
+
+ first_entry->offset = cp;
+
+ } else {
+
+ skipinit = 1;
+
+ }
+
+ if (skipinit == 0) {
+ /*
+ * Remove old window into the file
+ */
+ if (!allremoved) {
+ pmap_remove (map->pmap, uaddra, uaddra + cnt);
+ allremoved = 1;
+ }
+
+ /*
+ * Force copy on write for mmaped regions
+ */
+ vm_object_pmap_copy_1 (srcobject,
+ oindex, oindex + osize);
+ }
+
+ } else if ((first_object->ref_count == 1) &&
(first_object->size == osize) &&
(first_object->resident_page_count == 0)) {
+ vm_object_t oldobject;
- /*
- * Remove old window into the file
- */
- pmap_remove (map->pmap, start, end);
+ oldobject = first_object->backing_object;
- /*
- * Force copy on write for mmaped regions
- */
- vm_object_pmap_copy_1 (first_object,
- oindex, oindex + osize);
+ if ((first_object->backing_object_offset != cp) ||
+ (oldobject != srcobject)) {
+ /*
+ * Remove old window into the file
+ */
+ if (!allremoved) {
+ pmap_remove (map->pmap, uaddra, uaddra + cnt);
+ allremoved = 1;
+ }
- /*
- * Point the object appropriately
- */
- first_object->backing_object_offset = cp;
+ /*
+ * Force copy on write for mmaped regions
+ */
+ vm_object_pmap_copy_1 (srcobject,
+ oindex, oindex + osize);
+
+ /*
+ * Point the object appropriately
+ */
+ if (oldobject != srcobject) {
+ /*
+ * Set the object optimization hint flag
+ */
+ srcobject->flags |= OBJ_OPT;
+ vm_object_reference(srcobject);
+
+ if (oldobject) {
+ TAILQ_REMOVE(&oldobject->shadow_head,
+ first_object, shadow_list);
+ oldobject->shadow_count--;
+ if (oldobject->shadow_count == 0)
+ oldobject->flags &= ~OBJ_OPT;
+ vm_object_deallocate(oldobject);
+ }
+
+ TAILQ_INSERT_TAIL(&srcobject->shadow_head,
+ first_object, shadow_list);
+ srcobject->shadow_count++;
+
+ first_object->backing_object = srcobject;
+ }
+
+ first_object->backing_object_offset = cp;
+ } else {
+ skipinit = 1;
+ }
/*
* Otherwise, we have to do a logical mmap.
*/
} else {
- object = srcobject;
- object->flags |= OBJ_OPT;
- vm_object_reference(object);
- ooffset = cp;
-
- vm_object_shadow(&object, &ooffset, osize);
+ srcobject->flags |= OBJ_OPT;
+ vm_object_reference(srcobject);
- pmap_remove (map->pmap, start, end);
- vm_object_pmap_copy_1 (first_object,
+ if (!allremoved) {
+ pmap_remove (map->pmap, uaddra, uaddra + cnt);
+ allremoved = 1;
+ }
+ vm_object_pmap_copy_1 (srcobject,
oindex, oindex + osize);
vm_map_lookup_done(map, first_entry);
@@ -2578,8 +2648,8 @@ vm_uiomove(mapa, srcobject, cp, cnt, uaddra, npages)
SAVE_HINT(map, first_entry->prev);
vm_map_entry_delete(map, first_entry);
- rv = vm_map_insert(map, object, 0, start, end,
- VM_PROT_ALL, VM_PROT_ALL, MAP_COPY_ON_WRITE);
+ rv = vm_map_insert(map, srcobject, cp, start, end,
+ VM_PROT_ALL, VM_PROT_ALL, MAP_COPY_ON_WRITE | MAP_COPY_NEEDED);
if (rv != KERN_SUCCESS)
panic("vm_uiomove: could not insert new entry: %d", rv);
@@ -2588,8 +2658,9 @@ vm_uiomove(mapa, srcobject, cp, cnt, uaddra, npages)
/*
* Map the window directly, if it is already in memory
*/
- pmap_object_init_pt(map->pmap, start,
- srcobject, (vm_pindex_t) OFF_TO_IDX(cp), end - start, 1);
+ if (!skipinit)
+ pmap_object_init_pt(map->pmap, start,
+ srcobject, (vm_pindex_t) OFF_TO_IDX(cp), end - start, 0);
vm_map_unlock(map);
@@ -2663,10 +2734,14 @@ vm_freeze_copyopts(object, froma, toa)
continue;
vm_object_reference(robject);
+
+ s = splvm();
while (robject->paging_in_progress) {
robject->flags |= OBJ_PIPWNT;
tsleep(robject, PVM, "objfrz", 0);
}
+ splx(s);
+
if (robject->ref_count == 1) {
vm_object_deallocate(robject);
continue;
@@ -2690,7 +2765,7 @@ vm_freeze_copyopts(object, froma, toa)
continue;
if( m_in->flags & PG_BUSY) {
- s = splhigh();
+ s = splvm();
while (m_in && (m_in->flags & PG_BUSY)) {
m_in->flags |= PG_WANTED;
tsleep(m_in, PVM, "pwtfrz", 0);
@@ -2705,7 +2780,7 @@ vm_freeze_copyopts(object, froma, toa)
retryout:
m_out = vm_page_lookup(robject, dstpindex);
if( m_out && (m_out->flags & PG_BUSY)) {
- s = splhigh();
+ s = splvm();
while (m_out && (m_out->flags & PG_BUSY)) {
m_out->flags |= PG_WANTED;
tsleep(m_out, PVM, "pwtfrz", 0);
@@ -2733,6 +2808,7 @@ retryout:
vm_object_pip_wakeup(robject);
if (((from - bo_pindex) == 0) && ((to - bo_pindex) == robject->size)) {
+
object->shadow_count--;
TAILQ_REMOVE(&object->shadow_head, robject, shadow_list);