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,1018 **** 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 --- 972,1005 ----
*** 1031,1041 **** 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 * 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 --- 1018,1028 ---- 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 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,1095 **** 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 --- 1034,1070 ----
*** 1130,1139 **** --- 1105,1118 ---- 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,1151 **** /* * 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); } /* --- 1120,1129 ----