Print this page
6470 mac_unregister() needs to mod_hash_remove() BEFORE holding the perimeter.
Reviewed by: Ryan Zezeski <ryan@zinascii.com>
*** 19,28 ****
--- 19,29 ----
* CDDL HEADER END
*/
/*
* Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright 2017 OmniTI Computer Consulting, Inc. All rights reserved.
*/
#include <sys/types.h>
#include <sys/conf.h>
#include <sys/id_space.h>
*** 512,521 ****
--- 513,534 ----
/*
* Clean up notification thread and wait for it to exit.
*/
i_mac_notify_exit(mip);
+ /*
+ * Prior to acquiring the MAC perimeter, remove the MAC instance from
+ * the internal hash table. Such removal means table-walkers that
+ * acquire the perimeter will not do so on behalf of what we are
+ * unregistering, which prevents a deadlock.
+ */
+ rw_enter(&i_mac_impl_lock, RW_WRITER);
+ (void) mod_hash_remove(i_mac_impl_hash,
+ (mod_hash_key_t)mip->mi_name, &val);
+ rw_exit(&i_mac_impl_lock);
+ ASSERT(mip == (mac_impl_t *)val);
+
i_mac_perim_enter(mip);
/*
* There is still resource properties configured over this mac.
*/
*** 531,544 ****
ASSERT(mip->mi_nactiveclients == 0 && !(mip->mi_state_flags &
MIS_EXCLUSIVE));
mac_driver_stat_delete(mip);
- (void) mod_hash_remove(i_mac_impl_hash,
- (mod_hash_key_t)mip->mi_name, &val);
- ASSERT(mip == (mac_impl_t *)val);
-
ASSERT(i_mac_impl_count > 0);
atomic_dec_32(&i_mac_impl_count);
if (mip->mi_pdata != NULL)
kmem_free(mip->mi_pdata, mip->mi_pdata_size);
--- 544,553 ----