summaryrefslogtreecommitdiffstats
path: root/sys/vm/vm_map.c
diff options
context:
space:
mode:
authordillon <dillon@FreeBSD.org>2001-02-04 06:19:28 +0000
committerdillon <dillon@FreeBSD.org>2001-02-04 06:19:28 +0000
commitc8a95a285d887ca5e3be08f3c04f4efde25a5bf1 (patch)
tree9e2c267eac87bf24403df67147f7cc32082387c6 /sys/vm/vm_map.c
parentbb46130566593c534d92d1f9327521daa1faa946 (diff)
downloadFreeBSD-src-c8a95a285d887ca5e3be08f3c04f4efde25a5bf1.zip
FreeBSD-src-c8a95a285d887ca5e3be08f3c04f4efde25a5bf1.tar.gz
This commit represents work mainly submitted by Tor and slightly modified
by myself. It solves a serious vm_map corruption problem that can occur with the buffer cache when block sizes > 64K are used. This code has been heavily tested in -stable but only tested somewhat on -current. An MFC will occur in a few days. My additions include the vm_map_simplify_entry() and minor buffer cache boundry case fix. Make the buffer cache use a system map for buffer cache KVM rather then a normal map. Ensure that VM objects are not allocated for system maps. There were cases where a buffer map could wind up with a backing VM object -- normally harmless, but this could also result in the buffer cache blocking in places where it assumes no blocking will occur, possibly resulting in corrupted maps. Fix a minor boundry case in the buffer cache size limit is reached that could result in non-optimal code. Add vm_map_simplify_entry() calls to prevent 'creeping proliferation' of vm_map_entry's in the buffer cache's vm_map. Previously only a simple linear optimization was made. (The buffer vm_map typically has only a handful of vm_map_entry's. This stabilizes it at that level permanently). PR: 20609 Submitted by: (Tor Egge) tegge
Diffstat (limited to 'sys/vm/vm_map.c')
-rw-r--r--sys/vm/vm_map.c30
1 files changed, 23 insertions, 7 deletions
diff --git a/sys/vm/vm_map.c b/sys/vm/vm_map.c
index 8cc61b1..471e0af 100644
--- a/sys/vm/vm_map.c
+++ b/sys/vm/vm_map.c
@@ -508,6 +508,7 @@ vm_map_insert(vm_map_t map, vm_object_t object, vm_ooffset_t offset,
(prev_entry->max_protection == max)) {
map->size += (end - prev_entry->end);
prev_entry->end = end;
+ vm_map_simplify_entry(map, prev_entry);
return (KERN_SUCCESS);
}
@@ -515,7 +516,7 @@ vm_map_insert(vm_map_t map, vm_object_t object, vm_ooffset_t offset,
* If we can extend the object but cannot extend the
* map entry, we have to create a new map entry. We
* must bump the ref count on the extended object to
- * account for it.
+ * account for it. object may be NULL.
*/
object = prev_entry->object.vm_object;
offset = prev_entry->offset +
@@ -562,6 +563,11 @@ vm_map_insert(vm_map_t map, vm_object_t object, vm_ooffset_t offset,
map->first_free = new_entry;
}
+ /*
+ * It may be possible to simplify the entry
+ */
+ vm_map_simplify_entry(map, new_entry);
+
if (cow & (MAP_PREFAULT|MAP_PREFAULT_PARTIAL)) {
pmap_object_init_pt(map->pmap, start,
object, OFF_TO_IDX(offset), end - start,
@@ -681,7 +687,14 @@ vm_map_find(vm_map_t map, vm_object_t object, vm_ooffset_t offset,
/*
* vm_map_simplify_entry:
*
- * Simplify the given map entry by merging with either neighbor.
+ * Simplify the given map entry by merging with either neighbor. This
+ * routine also has the ability to merge with both neighbors.
+ *
+ * The map must be locked.
+ *
+ * This routine guarentees that the passed entry remains valid (though
+ * possibly extended). When merging, this routine may delete one or
+ * both neighbors.
*/
void
vm_map_simplify_entry(map, entry)
@@ -784,7 +797,7 @@ _vm_map_clip_start(map, entry, start)
* put this improvement.
*/
- if (entry->object.vm_object == NULL) {
+ if (entry->object.vm_object == NULL && !map->system_map) {
vm_object_t object;
object = vm_object_allocate(OBJT_DEFAULT,
atop(entry->end - entry->start));
@@ -840,7 +853,7 @@ _vm_map_clip_end(map, entry, end)
* put this improvement.
*/
- if (entry->object.vm_object == NULL) {
+ if (entry->object.vm_object == NULL && !map->system_map) {
vm_object_t object;
object = vm_object_allocate(OBJT_DEFAULT,
atop(entry->end - entry->start));
@@ -1295,7 +1308,8 @@ vm_map_user_pageable(map, start, end, new_pageable)
atop(entry->end - entry->start));
entry->eflags &= ~MAP_ENTRY_NEEDS_COPY;
- } else if (entry->object.vm_object == NULL) {
+ } else if (entry->object.vm_object == NULL &&
+ !map->system_map) {
entry->object.vm_object =
vm_object_allocate(OBJT_DEFAULT,
@@ -1485,7 +1499,8 @@ vm_map_pageable(map, start, end, new_pageable)
&entry->offset,
atop(entry->end - entry->start));
entry->eflags &= ~MAP_ENTRY_NEEDS_COPY;
- } else if (entry->object.vm_object == NULL) {
+ } else if (entry->object.vm_object == NULL &&
+ !map->system_map) {
entry->object.vm_object =
vm_object_allocate(OBJT_DEFAULT,
atop(entry->end - entry->start));
@@ -2614,7 +2629,8 @@ RetryLookup:;
/*
* Create an object if necessary.
*/
- if (entry->object.vm_object == NULL) {
+ if (entry->object.vm_object == NULL &&
+ !map->system_map) {
if (vm_map_lock_upgrade(map))
goto RetryLookup;
OpenPOWER on IntegriCloud