diff options
author | kib <kib@FreeBSD.org> | 2009-02-08 20:30:51 +0000 |
---|---|---|
committer | kib <kib@FreeBSD.org> | 2009-02-08 20:30:51 +0000 |
commit | 9a341e28ebd8cb82b35c8eeb849a7607597d399e (patch) | |
tree | 329bfc1903e45928be5dc9c04a265341794927c5 /sys | |
parent | 17606abd64d468568c5f7cb68d9e22dd675fcb15 (diff) | |
download | FreeBSD-src-9a341e28ebd8cb82b35c8eeb849a7607597d399e.zip FreeBSD-src-9a341e28ebd8cb82b35c8eeb849a7607597d399e.tar.gz |
In vm_map_sync(), do not call vm_object_sync() while holding map lock.
Reference object, drop the map lock, and then call vm_object_sync().
The object sync might require vnode lock for OBJT_VNODE type objects.
Reviewed by: tegge
Tested by: pho
Diffstat (limited to 'sys')
-rw-r--r-- | sys/vm/vm_map.c | 12 |
1 files changed, 10 insertions, 2 deletions
diff --git a/sys/vm/vm_map.c b/sys/vm/vm_map.c index 13b9050..281f436 100644 --- a/sys/vm/vm_map.c +++ b/sys/vm/vm_map.c @@ -2304,6 +2304,7 @@ vm_map_sync( vm_size_t size; vm_object_t object; vm_ooffset_t offset; + unsigned int last_timestamp; vm_map_lock_read(map); VM_MAP_RANGE_CHECK(map, start, end); @@ -2338,8 +2339,7 @@ vm_map_sync( * Make a second pass, cleaning/uncaching pages from the indicated * objects as we go. */ - for (current = entry; current != &map->header && current->start < end; - current = current->next) { + for (current = entry; current != &map->header && current->start < end;) { offset = current->offset + (start - current->start); size = (end <= current->end ? end : current->end) - start; if (current->eflags & MAP_ENTRY_IS_SUB_MAP) { @@ -2359,8 +2359,16 @@ vm_map_sync( } else { object = current->object.vm_object; } + vm_object_reference(object); + last_timestamp = map->timestamp; + vm_map_unlock_read(map); vm_object_sync(object, offset, size, syncio, invalidate); start += size; + vm_object_deallocate(object); + vm_map_lock_read(map); + if (last_timestamp == map->timestamp || + !vm_map_lookup_entry(map, start, ¤t)) + current = current->next; } vm_map_unlock_read(map); |