Print this page
6470 mac_unregister() needs to mod_hash_remove() BEFORE holding the perimeter.
Reviewed by: Ryan Zezeski <ryan@zinascii.com>

Split Close
Expand all
Collapse all
          --- old/usr/src/uts/common/io/mac/mac_provider.c
          +++ new/usr/src/uts/common/io/mac/mac_provider.c
↓ open down ↓ 13 lines elided ↑ open up ↑
  14   14   * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15   15   * If applicable, add the following below this CDDL HEADER, with the
  16   16   * fields enclosed by brackets "[]" replaced with your own identifying
  17   17   * information: Portions Copyright [yyyy] [name of copyright owner]
  18   18   *
  19   19   * CDDL HEADER END
  20   20   */
  21   21  
  22   22  /*
  23   23   * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
       24 + * Copyright 2017 OmniTI Computer Consulting, Inc. All rights reserved.
  24   25   */
  25   26  
  26   27  #include <sys/types.h>
  27   28  #include <sys/conf.h>
  28   29  #include <sys/id_space.h>
  29   30  #include <sys/esunddi.h>
  30   31  #include <sys/stat.h>
  31   32  #include <sys/mkdev.h>
  32   33  #include <sys/stream.h>
  33   34  #include <sys/strsubr.h>
↓ open down ↓ 473 lines elided ↑ open up ↑
 507  508  
 508  509          /* Fail the unregister if there are any open references to this mac. */
 509  510          if ((err = mac_disable_nowait(mh)) != 0)
 510  511                  return (err);
 511  512  
 512  513          /*
 513  514           * Clean up notification thread and wait for it to exit.
 514  515           */
 515  516          i_mac_notify_exit(mip);
 516  517  
      518 +        /*
      519 +         * Prior to acquiring the MAC perimeter, remove the MAC instance from
      520 +         * the internal hash table. Such removal means table-walkers that
      521 +         * acquire the perimeter will not do so on behalf of what we are
      522 +         * unregistering, which prevents a deadlock.
      523 +         */
      524 +        rw_enter(&i_mac_impl_lock, RW_WRITER);
      525 +        (void) mod_hash_remove(i_mac_impl_hash,
      526 +            (mod_hash_key_t)mip->mi_name, &val);
      527 +        rw_exit(&i_mac_impl_lock);
      528 +        ASSERT(mip == (mac_impl_t *)val);
      529 +
 517  530          i_mac_perim_enter(mip);
 518  531  
 519  532          /*
 520  533           * There is still resource properties configured over this mac.
 521  534           */
 522  535          if (mip->mi_resource_props.mrp_mask != 0)
 523  536                  mac_fastpath_enable((mac_handle_t)mip);
 524  537  
 525  538          if (mip->mi_minor < MAC_MAX_MINOR + 1) {
 526  539                  ddi_remove_minor_node(mip->mi_dip, mip->mi_name);
 527  540                  ddi_remove_minor_node(mip->mi_dip,
 528  541                      (char *)ddi_driver_name(mip->mi_dip));
 529  542          }
 530  543  
 531  544          ASSERT(mip->mi_nactiveclients == 0 && !(mip->mi_state_flags &
 532  545              MIS_EXCLUSIVE));
 533  546  
 534  547          mac_driver_stat_delete(mip);
 535  548  
 536      -        (void) mod_hash_remove(i_mac_impl_hash,
 537      -            (mod_hash_key_t)mip->mi_name, &val);
 538      -        ASSERT(mip == (mac_impl_t *)val);
 539      -
 540  549          ASSERT(i_mac_impl_count > 0);
 541  550          atomic_dec_32(&i_mac_impl_count);
 542  551  
 543  552          if (mip->mi_pdata != NULL)
 544  553                  kmem_free(mip->mi_pdata, mip->mi_pdata_size);
 545  554          mip->mi_pdata = NULL;
 546  555          mip->mi_pdata_size = 0;
 547  556  
 548  557          /*
 549  558           * Free the list of margin request.
↓ open down ↓ 960 lines elided ↑ open up ↑
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX