svn commit: r216554 - stable/7/sys/vm
Max Laier
mlaier at FreeBSD.org
Sun Dec 19 06:09:03 UTC 2010
Author: mlaier
Date: Sun Dec 19 06:09:02 2010
New Revision: 216554
URL: http://svn.freebsd.org/changeset/base/216554
Log:
MFC r216335:
Fix a long standing (from the original 4.4BSD lite sources) race between
vmspace_fork and vm_map_wire that would lead to "vm_fault_copy_wired: page
missing" panics. While faulting in pages for a map entry that is being
wired down, mark the containing map as busy. In vmspace_fork wait until
the map is unbusy, before we try to copy the entries.
Sponsored by: Isilon Systems, Inc.
Approved by: re (kib)
Modified:
stable/7/sys/vm/vm_map.c
stable/7/sys/vm/vm_map.h
Directory Properties:
stable/7/sys/ (props changed)
stable/7/sys/cddl/contrib/opensolaris/ (props changed)
stable/7/sys/contrib/dev/acpica/ (props changed)
stable/7/sys/contrib/pf/ (props changed)
Modified: stable/7/sys/vm/vm_map.c
==============================================================================
--- stable/7/sys/vm/vm_map.c Sun Dec 19 06:07:35 2010 (r216553)
+++ stable/7/sys/vm/vm_map.c Sun Dec 19 06:09:02 2010 (r216554)
@@ -561,6 +561,56 @@ vm_map_wakeup(vm_map_t map)
wakeup(&map->root);
}
+void
+vm_map_busy(vm_map_t map)
+{
+
+#ifdef INVARIANTS
+ if (map->system_map) {
+ mtx_assert(&map->system_mtx, MA_OWNED);
+ } else
+ sx_assert(&map->lock, SX_XLOCKED);
+#endif
+ map->busy++;
+}
+
+void
+vm_map_unbusy(vm_map_t map)
+{
+
+#ifdef INVARIANTS
+ if (map->system_map) {
+ mtx_assert(&map->system_mtx, MA_OWNED);
+ } else
+ sx_assert(&map->lock, SX_XLOCKED);
+#endif
+ KASSERT(map->busy, ("vm_map_unbusy: not busy"));
+ if (--map->busy == 0 && (map->flags & MAP_BUSY_WAKEUP)) {
+ vm_map_modflags(map, 0, MAP_BUSY_WAKEUP);
+ wakeup(&map->busy);
+ }
+}
+
+void
+vm_map_wait_busy(vm_map_t map)
+{
+
+#ifdef INVARIANTS
+ if (map->system_map) {
+ mtx_assert(&map->system_mtx, MA_OWNED);
+ } else
+ sx_assert(&map->lock, SX_XLOCKED);
+#endif
+ while (map->busy) {
+ vm_map_modflags(map, MAP_BUSY_WAKEUP, 0);
+ if (map->system_map)
+ msleep(&map->busy, &map->system_mtx, 0, "mbusy", 0);
+ else
+ sx_sleep(&map->busy, &map->lock, 0, "mbusy", 0);
+ }
+ map->timestamp++;
+}
+
long
vmspace_resident_count(struct vmspace *vmspace)
{
@@ -609,6 +659,7 @@ _vm_map_init(vm_map_t map, vm_offset_t m
map->flags = 0;
map->root = NULL;
map->timestamp = 0;
+ map->busy = 0;
}
void
@@ -2070,12 +2121,14 @@ vm_map_wire(vm_map_t map, vm_offset_t st
entry->object.vm_object->type == OBJT_SG);
/*
* Release the map lock, relying on the in-transition
- * mark.
+ * mark. Mark the map busy for fork.
*/
+ vm_map_busy(map);
vm_map_unlock(map);
rv = vm_fault_wire(map, saved_start, saved_end,
user_wire, fictitious);
vm_map_lock(map);
+ vm_map_unbusy(map);
if (last_timestamp + 1 != map->timestamp) {
/*
* Look again for the entry because the map was
@@ -2605,6 +2658,8 @@ vmspace_fork(struct vmspace *vm1)
vm_object_t object;
vm_map_lock(old_map);
+ if (old_map->busy)
+ vm_map_wait_busy(old_map);
vm2 = vmspace_alloc(old_map->min_offset, old_map->max_offset);
if (vm2 == NULL)
Modified: stable/7/sys/vm/vm_map.h
==============================================================================
--- stable/7/sys/vm/vm_map.h Sun Dec 19 06:07:35 2010 (r216553)
+++ stable/7/sys/vm/vm_map.h Sun Dec 19 06:09:02 2010 (r216554)
@@ -194,12 +194,14 @@ struct vm_map {
pmap_t pmap; /* (c) Physical map */
#define min_offset header.start /* (c) */
#define max_offset header.end /* (c) */
+ int busy;
};
/*
* vm_flags_t values
*/
#define MAP_WIREFUTURE 0x01 /* wire all future pages */
+#define MAP_BUSY_WAKEUP 0x02
#ifdef _KERNEL
static __inline vm_offset_t
@@ -276,6 +278,9 @@ int _vm_map_lock_upgrade(vm_map_t map, c
void _vm_map_lock_downgrade(vm_map_t map, const char *file, int line);
int vm_map_unlock_and_wait(vm_map_t map, boolean_t user_wait);
void vm_map_wakeup(vm_map_t map);
+void vm_map_busy(vm_map_t map);
+void vm_map_unbusy(vm_map_t map);
+void vm_map_wait_busy(vm_map_t map);
#define vm_map_lock(map) _vm_map_lock(map, LOCK_FILE, LOCK_LINE)
#define vm_map_unlock(map) _vm_map_unlock(map, LOCK_FILE, LOCK_LINE)
More information about the svn-src-stable
mailing list