Print this page
NEX-15390 illumos#8149 introduced deadlock between device detach and kstat read
Reviewed by: Robert Mustacchi <rm@joyent.com>
Reviewed by: Bryan Cantrill <bryan@joyent.com>
Reviewed by: Rick McNeal <rick.mcneal@nexenta.com>

@@ -972,47 +972,34 @@
 static int
 dls_devnet_hold_common(datalink_id_t linkid, dls_devnet_t **ddpp,
     boolean_t tmp_hold)
 {
         dls_devnet_t            *ddp;
-        dev_t                   phydev = 0;
-        dls_dev_handle_t        ddh = NULL;
         int                     err;
 
-        /*
-         * Hold this link to prevent it being detached in case of a
-         * physical link.
-         */
-        if (dls_mgmt_get_phydev(linkid, &phydev) == 0)
-                (void) softmac_hold_device(phydev, &ddh);
-
         rw_enter(&i_dls_devnet_lock, RW_READER);
         if ((err = mod_hash_find(i_dls_devnet_id_hash,
             (mod_hash_key_t)(uintptr_t)linkid, (mod_hash_val_t *)&ddp)) != 0) {
                 ASSERT(err == MH_ERR_NOTFOUND);
                 rw_exit(&i_dls_devnet_lock);
-                softmac_rele_device(ddh);
                 return (ENOENT);
         }
 
         mutex_enter(&ddp->dd_mutex);
         ASSERT(ddp->dd_ref > 0);
         if (ddp->dd_flags & DD_CONDEMNED) {
                 mutex_exit(&ddp->dd_mutex);
                 rw_exit(&i_dls_devnet_lock);
-                softmac_rele_device(ddh);
                 return (ENOENT);
         }
         if (tmp_hold)
                 ddp->dd_tref++;
         else
                 ddp->dd_ref++;
         mutex_exit(&ddp->dd_mutex);
         rw_exit(&i_dls_devnet_lock);
 
-        softmac_rele_device(ddh);
-
         *ddpp = ddp;
         return (0);
 }
 
 int

@@ -1031,11 +1018,11 @@
         return (dls_devnet_hold_common(linkid, ddpp, B_TRUE));
 }
 
 /*
  * This funtion is called when a DLS client tries to open a device node.
- * This dev_t could a result of a /dev/net node access (returned by
+ * This dev_t could be a result of a /dev/net node access (returned by
  * devnet_create_rvp->dls_devnet_open()) or a direct /dev node access.
  * In both cases, this function bumps up the reference count of the
  * dls_devnet_t structure. The reference is held as long as the device node
  * is open. In the case of /dev/net while it is true that the initial reference
  * is held when the devnet_create_rvp->dls_devnet_open call happens, this

@@ -1047,49 +1034,37 @@
 int
 dls_devnet_hold_by_dev(dev_t dev, dls_dl_handle_t *ddhp)
 {
         char                    name[MAXNAMELEN];
         char                    *drv;
-        dls_dev_handle_t        ddh = NULL;
         dls_devnet_t            *ddp;
         int                     err;
 
         if ((drv = ddi_major_to_name(getmajor(dev))) == NULL)
                 return (EINVAL);
 
         (void) snprintf(name, sizeof (name), "%s%d", drv,
             DLS_MINOR2INST(getminor(dev)));
 
-        /*
-         * Hold this link to prevent it being detached in case of a
-         * GLDv3 physical link.
-         */
-        if (DLS_MINOR2INST(getminor(dev)) <= DLS_MAX_PPA)
-                (void) softmac_hold_device(dev, &ddh);
-
         rw_enter(&i_dls_devnet_lock, RW_READER);
         if ((err = mod_hash_find(i_dls_devnet_hash,
             (mod_hash_key_t)name, (mod_hash_val_t *)&ddp)) != 0) {
                 ASSERT(err == MH_ERR_NOTFOUND);
                 rw_exit(&i_dls_devnet_lock);
-                softmac_rele_device(ddh);
                 return (ENOENT);
         }
         mutex_enter(&ddp->dd_mutex);
         ASSERT(ddp->dd_ref > 0);
         if (ddp->dd_flags & DD_CONDEMNED) {
                 mutex_exit(&ddp->dd_mutex);
                 rw_exit(&i_dls_devnet_lock);
-                softmac_rele_device(ddh);
                 return (ENOENT);
         }
         ddp->dd_ref++;
         mutex_exit(&ddp->dd_mutex);
         rw_exit(&i_dls_devnet_lock);
 
-        softmac_rele_device(ddh);
-
         *ddhp = ddp;
         return (0);
 }
 
 void

@@ -1130,10 +1105,14 @@
                 return (ENOENT);
 
         if (err != ENOENT)
                 return (err);
 
+        /*
+         * If we reach this point it means dlmgmtd is up but has no
+         * mapping for the link name.
+         */
         if (ddi_parse(link, drv, &ppa) != DDI_SUCCESS)
                 return (ENOENT);
 
         if (IS_IPTUN_LINK(drv)) {
                 if ((err = i_dls_devnet_create_iptun(link, drv, &linkid)) != 0)

@@ -1141,11 +1120,10 @@
                 /*
                  * At this point, an IP tunnel MAC has registered, which
                  * resulted in a link being created.
                  */
                 err = dls_devnet_hold(linkid, ddpp);
-                ASSERT(err == 0);
                 if (err != 0) {
                         VERIFY(i_dls_devnet_destroy_iptun(linkid) == 0);
                         return (err);
                 }
                 /*