aboutsummaryrefslogtreecommitdiff
path: root/sys/vm/vm_map.c
diff options
context:
space:
mode:
authorJohn Dyson <dyson@FreeBSD.org>1998-01-12 01:46:33 +0000
committerJohn Dyson <dyson@FreeBSD.org>1998-01-12 01:46:33 +0000
commit925a3a419a0a6ae7c36b5ab5e6a63e6e0afa4ca4 (patch)
treec03f4ae3331fe8a79b20e357b7542800c30221c7 /sys/vm/vm_map.c
parentde48a0f797028b4e7574b354487dd12eb844d8ab (diff)
downloadsrc-925a3a419a0a6ae7c36b5ab5e6a63e6e0afa4ca4.tar.gz
src-925a3a419a0a6ae7c36b5ab5e6a63e6e0afa4ca4.zip
Fix some vnode management problems, and better mgmt of vnode free list.
Fix the UIO optimization code. Fix an assumption in vm_map_insert regarding allocation of swap pagers. Fix an spl problem in the collapse handling in vm_object_deallocate. When pages are freed from vnode objects, and the criteria for putting the associated vnode onto the free list is reached, either put the vnode onto the list, or put it onto an interrupt safe version of the list, for further transfer onto the actual free list. Some minor syntax changes changing pre-decs, pre-incs to post versions. Remove a bogus timeout (that I added for debugging) from vn_lock. PHK will likely still have problems with the vnode list management, and so do I, but it is better than it was.
Notes
Notes: svn path=/head/; revision=32454
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);