summaryrefslogtreecommitdiffstats
path: root/sys/vm
diff options
context:
space:
mode:
authortegge <tegge@FreeBSD.org>2003-03-26 18:44:53 +0000
committertegge <tegge@FreeBSD.org>2003-03-26 18:44:53 +0000
commit5a1c87126631f2f5e816ea796b31f8b9870e915c (patch)
tree5e08ed0207899556204c99bda190857f22280975 /sys/vm
parent72a1a2619caba266ac8c65f94a7a2a271537ccfe (diff)
downloadFreeBSD-src-5a1c87126631f2f5e816ea796b31f8b9870e915c.zip
FreeBSD-src-5a1c87126631f2f5e816ea796b31f8b9870e915c.tar.gz
Obtain Giant before calling kmem_alloc without M_NOWAIT and before calling
kmem_free if Giant isn't already held.
Diffstat (limited to 'sys/vm')
-rw-r--r--sys/vm/uma_core.c23
1 files changed, 21 insertions, 2 deletions
diff --git a/sys/vm/uma_core.c b/sys/vm/uma_core.c
index 2e8e704..09f3d67 100644
--- a/sys/vm/uma_core.c
+++ b/sys/vm/uma_core.c
@@ -2017,7 +2017,13 @@ uma_large_malloc(int size, int wait)
if (slab == NULL)
return (NULL);
- mem = page_alloc(NULL, size, &flags, wait);
+ /* XXX: kmem_malloc panics if Giant isn't held and sleep allowed */
+ if ((wait & M_NOWAIT) == 0 && !mtx_owned(&Giant)) {
+ mtx_lock(&Giant);
+ mem = page_alloc(NULL, size, &flags, wait);
+ mtx_unlock(&Giant);
+ } else
+ mem = page_alloc(NULL, size, &flags, wait);
if (mem) {
vsetslab((vm_offset_t)mem, slab);
slab->us_data = mem;
@@ -2035,7 +2041,20 @@ void
uma_large_free(uma_slab_t slab)
{
vsetobj((vm_offset_t)slab->us_data, kmem_object);
- page_free(slab->us_data, slab->us_size, slab->us_flags);
+ /*
+ * XXX: Giant is still needed by kmem_free, since we have
+ * kmem_free -> vm_map_remove -> vm_map_delete ->
+ * vm_object_page_remove -> vm_object_pip_add -> GIANT_REQUIRED
+ * We also get a lock order reversal if we don't have Giant:
+ * vm_map_remove (locks system map) -> vm_map_delete ->
+ * vm_map_entry_unwire -> vm_fault_unwire -> mtx_lock(&Giant)
+ */
+ if (!mtx_owned(&Giant)) {
+ mtx_lock(&Giant);
+ page_free(slab->us_data, slab->us_size, slab->us_flags);
+ mtx_unlock(&Giant);
+ } else
+ page_free(slab->us_data, slab->us_size, slab->us_flags);
uma_zfree_internal(slabzone, slab, NULL, 0);
}
OpenPOWER on IntegriCloud