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


   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 
  22 /*
  23  * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.

  24  */
  25 
  26 #include <sys/types.h>
  27 #include <sys/conf.h>
  28 #include <sys/id_space.h>
  29 #include <sys/esunddi.h>
  30 #include <sys/stat.h>
  31 #include <sys/mkdev.h>
  32 #include <sys/stream.h>
  33 #include <sys/strsubr.h>
  34 #include <sys/dlpi.h>
  35 #include <sys/modhash.h>
  36 #include <sys/mac.h>
  37 #include <sys/mac_provider.h>
  38 #include <sys/mac_impl.h>
  39 #include <sys/mac_client_impl.h>
  40 #include <sys/mac_client_priv.h>
  41 #include <sys/mac_soft_ring.h>
  42 #include <sys/mac_stat.h>
  43 #include <sys/dld.h>


 497 /*
 498  * Unregister from the GLDv3 framework
 499  */
 500 int
 501 mac_unregister(mac_handle_t mh)
 502 {
 503         int                     err;
 504         mac_impl_t              *mip = (mac_impl_t *)mh;
 505         mod_hash_val_t          val;
 506         mac_margin_req_t        *mmr, *nextmmr;
 507 
 508         /* Fail the unregister if there are any open references to this mac. */
 509         if ((err = mac_disable_nowait(mh)) != 0)
 510                 return (err);
 511 
 512         /*
 513          * Clean up notification thread and wait for it to exit.
 514          */
 515         i_mac_notify_exit(mip);
 516 












 517         i_mac_perim_enter(mip);
 518 
 519         /*
 520          * There is still resource properties configured over this mac.
 521          */
 522         if (mip->mi_resource_props.mrp_mask != 0)
 523                 mac_fastpath_enable((mac_handle_t)mip);
 524 
 525         if (mip->mi_minor < MAC_MAX_MINOR + 1) {
 526                 ddi_remove_minor_node(mip->mi_dip, mip->mi_name);
 527                 ddi_remove_minor_node(mip->mi_dip,
 528                     (char *)ddi_driver_name(mip->mi_dip));
 529         }
 530 
 531         ASSERT(mip->mi_nactiveclients == 0 && !(mip->mi_state_flags &
 532             MIS_EXCLUSIVE));
 533 
 534         mac_driver_stat_delete(mip);
 535 
 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         ASSERT(i_mac_impl_count > 0);
 541         atomic_dec_32(&i_mac_impl_count);
 542 
 543         if (mip->mi_pdata != NULL)
 544                 kmem_free(mip->mi_pdata, mip->mi_pdata_size);
 545         mip->mi_pdata = NULL;
 546         mip->mi_pdata_size = 0;
 547 
 548         /*
 549          * Free the list of margin request.
 550          */
 551         for (mmr = mip->mi_mmrp; mmr != NULL; mmr = nextmmr) {
 552                 nextmmr = mmr->mmr_nextp;
 553                 kmem_free(mmr, sizeof (mac_margin_req_t));
 554         }
 555         mip->mi_mmrp = NULL;
 556 
 557         mip->mi_linkstate = mip->mi_lowlinkstate = LINK_STATE_UNKNOWN;
 558         kmem_free(mip->mi_info.mi_unicst_addr, mip->mi_type->mt_addr_length);
 559         mip->mi_info.mi_unicst_addr = NULL;




   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 
  22 /*
  23  * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
  24  * Copyright 2017 OmniTI Computer Consulting, Inc. All rights reserved.
  25  */
  26 
  27 #include <sys/types.h>
  28 #include <sys/conf.h>
  29 #include <sys/id_space.h>
  30 #include <sys/esunddi.h>
  31 #include <sys/stat.h>
  32 #include <sys/mkdev.h>
  33 #include <sys/stream.h>
  34 #include <sys/strsubr.h>
  35 #include <sys/dlpi.h>
  36 #include <sys/modhash.h>
  37 #include <sys/mac.h>
  38 #include <sys/mac_provider.h>
  39 #include <sys/mac_impl.h>
  40 #include <sys/mac_client_impl.h>
  41 #include <sys/mac_client_priv.h>
  42 #include <sys/mac_soft_ring.h>
  43 #include <sys/mac_stat.h>
  44 #include <sys/dld.h>


 498 /*
 499  * Unregister from the GLDv3 framework
 500  */
 501 int
 502 mac_unregister(mac_handle_t mh)
 503 {
 504         int                     err;
 505         mac_impl_t              *mip = (mac_impl_t *)mh;
 506         mod_hash_val_t          val;
 507         mac_margin_req_t        *mmr, *nextmmr;
 508 
 509         /* Fail the unregister if there are any open references to this mac. */
 510         if ((err = mac_disable_nowait(mh)) != 0)
 511                 return (err);
 512 
 513         /*
 514          * Clean up notification thread and wait for it to exit.
 515          */
 516         i_mac_notify_exit(mip);
 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 
 530         i_mac_perim_enter(mip);
 531 
 532         /*
 533          * There is still resource properties configured over this mac.
 534          */
 535         if (mip->mi_resource_props.mrp_mask != 0)
 536                 mac_fastpath_enable((mac_handle_t)mip);
 537 
 538         if (mip->mi_minor < MAC_MAX_MINOR + 1) {
 539                 ddi_remove_minor_node(mip->mi_dip, mip->mi_name);
 540                 ddi_remove_minor_node(mip->mi_dip,
 541                     (char *)ddi_driver_name(mip->mi_dip));
 542         }
 543 
 544         ASSERT(mip->mi_nactiveclients == 0 && !(mip->mi_state_flags &
 545             MIS_EXCLUSIVE));
 546 
 547         mac_driver_stat_delete(mip);
 548 




 549         ASSERT(i_mac_impl_count > 0);
 550         atomic_dec_32(&i_mac_impl_count);
 551 
 552         if (mip->mi_pdata != NULL)
 553                 kmem_free(mip->mi_pdata, mip->mi_pdata_size);
 554         mip->mi_pdata = NULL;
 555         mip->mi_pdata_size = 0;
 556 
 557         /*
 558          * Free the list of margin request.
 559          */
 560         for (mmr = mip->mi_mmrp; mmr != NULL; mmr = nextmmr) {
 561                 nextmmr = mmr->mmr_nextp;
 562                 kmem_free(mmr, sizeof (mac_margin_req_t));
 563         }
 564         mip->mi_mmrp = NULL;
 565 
 566         mip->mi_linkstate = mip->mi_lowlinkstate = LINK_STATE_UNKNOWN;
 567         kmem_free(mip->mi_info.mi_unicst_addr, mip->mi_type->mt_addr_length);
 568         mip->mi_info.mi_unicst_addr = NULL;