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 ----