diff options
author | kib <kib@FreeBSD.org> | 2007-08-18 16:40:33 +0000 |
---|---|---|
committer | kib <kib@FreeBSD.org> | 2007-08-18 16:40:33 +0000 |
commit | ba6ef6eccaefee0eb05036b28d4e1074aa92ea5c (patch) | |
tree | 8d3069975564b76f59783f6cab8fa5fed278be76 /sys | |
parent | c58bdad9f2ec03ff531566782125fee5182ff68f (diff) | |
download | FreeBSD-src-ba6ef6eccaefee0eb05036b28d4e1074aa92ea5c.zip FreeBSD-src-ba6ef6eccaefee0eb05036b28d4e1074aa92ea5c.tar.gz |
Fix the phys_pager in the way similar to the rev. 1.83 of the
sys/vm/device_pager.c:
Protect the creation of the phys pager with non-NULL handle with the
phys_pager_mtx. Lookup of phys pager in the pagers list by handle is now
synchronized with its removal from the list, and phys_pager_mtx is put
before vm object lock in lock order. Dispose the phys_pager_alloc_lock
and tsleep calls, together with acquiring Giant, since phys_pager_mtx
now covers the same block.
Reviewed by: alc
Approved by: re (kensmith)
Diffstat (limited to 'sys')
-rw-r--r-- | sys/vm/phys_pager.c | 47 |
1 files changed, 25 insertions, 22 deletions
diff --git a/sys/vm/phys_pager.c b/sys/vm/phys_pager.c index 626e888..c699b8f 100644 --- a/sys/vm/phys_pager.c +++ b/sys/vm/phys_pager.c @@ -42,8 +42,6 @@ __FBSDID("$FreeBSD$"); #include <vm/vm_page.h> #include <vm/vm_pager.h> -/* prevent concurrent creation races */ -static int phys_pager_alloc_lock; /* list of device pager objects */ static struct pagerlst phys_pager_object_list; /* protect access to phys_pager_object_list */ @@ -64,7 +62,7 @@ static vm_object_t phys_pager_alloc(void *handle, vm_ooffset_t size, vm_prot_t prot, vm_ooffset_t foff) { - vm_object_t object; + vm_object_t object, object1; vm_pindex_t pindex; /* @@ -76,38 +74,41 @@ phys_pager_alloc(void *handle, vm_ooffset_t size, vm_prot_t prot, pindex = OFF_TO_IDX(foff + PAGE_MASK + size); if (handle != NULL) { - mtx_lock(&Giant); - /* - * Lock to prevent object creation race condition. - */ - while (phys_pager_alloc_lock) { - phys_pager_alloc_lock = -1; - tsleep(&phys_pager_alloc_lock, PVM, "swpalc", 0); - } - phys_pager_alloc_lock = 1; - + mtx_lock(&phys_pager_mtx); /* * Look up pager, creating as necessary. */ + object1 = NULL; object = vm_pager_object_lookup(&phys_pager_object_list, handle); if (object == NULL) { /* * Allocate object and associate it with the pager. */ - object = vm_object_allocate(OBJT_PHYS, pindex); - object->handle = handle; - mtx_lock(&phys_pager_mtx); - TAILQ_INSERT_TAIL(&phys_pager_object_list, object, - pager_object_list); mtx_unlock(&phys_pager_mtx); + object1 = vm_object_allocate(OBJT_PHYS, pindex); + mtx_lock(&phys_pager_mtx); + object = vm_pager_object_lookup(&phys_pager_object_list, + handle); + if (object != NULL) { + /* + * We raced with other thread while + * allocating object. + */ + if (pindex > object->size) + object->size = pindex; + } else { + object = object1; + object1 = NULL; + object->handle = handle; + TAILQ_INSERT_TAIL(&phys_pager_object_list, object, + pager_object_list); + } } else { if (pindex > object->size) object->size = pindex; } - if (phys_pager_alloc_lock == -1) - wakeup(&phys_pager_alloc_lock); - phys_pager_alloc_lock = 0; - mtx_unlock(&Giant); + mtx_unlock(&phys_pager_mtx); + vm_object_deallocate(object1); } else { object = vm_object_allocate(OBJT_PHYS, pindex); } @@ -123,9 +124,11 @@ phys_pager_dealloc(vm_object_t object) { if (object->handle != NULL) { + VM_OBJECT_UNLOCK(object); mtx_lock(&phys_pager_mtx); TAILQ_REMOVE(&phys_pager_object_list, object, pager_object_list); mtx_unlock(&phys_pager_mtx); + VM_OBJECT_LOCK(object); } } |