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>

Split Close
Expand all
Collapse all
          --- old/usr/src/uts/common/io/dls/dls_mgmt.c
          +++ new/usr/src/uts/common/io/dls/dls_mgmt.c
↓ open down ↓ 966 lines elided ↑ open up ↑
 967  967          kmem_cache_free(i_dls_devnet_cachep, ddp);
 968  968  
 969  969          return (0);
 970  970  }
 971  971  
 972  972  static int
 973  973  dls_devnet_hold_common(datalink_id_t linkid, dls_devnet_t **ddpp,
 974  974      boolean_t tmp_hold)
 975  975  {
 976  976          dls_devnet_t            *ddp;
 977      -        dev_t                   phydev = 0;
 978      -        dls_dev_handle_t        ddh = NULL;
 979  977          int                     err;
 980  978  
 981      -        /*
 982      -         * Hold this link to prevent it being detached in case of a
 983      -         * physical link.
 984      -         */
 985      -        if (dls_mgmt_get_phydev(linkid, &phydev) == 0)
 986      -                (void) softmac_hold_device(phydev, &ddh);
 987      -
 988  979          rw_enter(&i_dls_devnet_lock, RW_READER);
 989  980          if ((err = mod_hash_find(i_dls_devnet_id_hash,
 990  981              (mod_hash_key_t)(uintptr_t)linkid, (mod_hash_val_t *)&ddp)) != 0) {
 991  982                  ASSERT(err == MH_ERR_NOTFOUND);
 992  983                  rw_exit(&i_dls_devnet_lock);
 993      -                softmac_rele_device(ddh);
 994  984                  return (ENOENT);
 995  985          }
 996  986  
 997  987          mutex_enter(&ddp->dd_mutex);
 998  988          ASSERT(ddp->dd_ref > 0);
 999  989          if (ddp->dd_flags & DD_CONDEMNED) {
1000  990                  mutex_exit(&ddp->dd_mutex);
1001  991                  rw_exit(&i_dls_devnet_lock);
1002      -                softmac_rele_device(ddh);
1003  992                  return (ENOENT);
1004  993          }
1005  994          if (tmp_hold)
1006  995                  ddp->dd_tref++;
1007  996          else
1008  997                  ddp->dd_ref++;
1009  998          mutex_exit(&ddp->dd_mutex);
1010  999          rw_exit(&i_dls_devnet_lock);
1011 1000  
1012      -        softmac_rele_device(ddh);
1013      -
1014 1001          *ddpp = ddp;
1015 1002          return (0);
1016 1003  }
1017 1004  
1018 1005  int
1019 1006  dls_devnet_hold(datalink_id_t linkid, dls_devnet_t **ddpp)
1020 1007  {
1021 1008          return (dls_devnet_hold_common(linkid, ddpp, B_FALSE));
1022 1009  }
1023 1010  
↓ open down ↓ 2 lines elided ↑ open up ↑
1026 1013   * delete the dls_devnet_t will wait until the temporary reference is released.
1027 1014   */
1028 1015  int
1029 1016  dls_devnet_hold_tmp(datalink_id_t linkid, dls_devnet_t **ddpp)
1030 1017  {
1031 1018          return (dls_devnet_hold_common(linkid, ddpp, B_TRUE));
1032 1019  }
1033 1020  
1034 1021  /*
1035 1022   * This funtion is called when a DLS client tries to open a device node.
1036      - * This dev_t could a result of a /dev/net node access (returned by
     1023 + * This dev_t could be a result of a /dev/net node access (returned by
1037 1024   * devnet_create_rvp->dls_devnet_open()) or a direct /dev node access.
1038 1025   * In both cases, this function bumps up the reference count of the
1039 1026   * dls_devnet_t structure. The reference is held as long as the device node
1040 1027   * is open. In the case of /dev/net while it is true that the initial reference
1041 1028   * is held when the devnet_create_rvp->dls_devnet_open call happens, this
1042 1029   * initial reference is released immediately in devnet_inactive_callback ->
1043 1030   * dls_devnet_close(). (Note that devnet_inactive_callback() is called right
1044 1031   * after dld_open completes, not when the /dev/net node is being closed).
1045 1032   * To undo this function, call dls_devnet_rele()
1046 1033   */
1047 1034  int
1048 1035  dls_devnet_hold_by_dev(dev_t dev, dls_dl_handle_t *ddhp)
1049 1036  {
1050 1037          char                    name[MAXNAMELEN];
1051 1038          char                    *drv;
1052      -        dls_dev_handle_t        ddh = NULL;
1053 1039          dls_devnet_t            *ddp;
1054 1040          int                     err;
1055 1041  
1056 1042          if ((drv = ddi_major_to_name(getmajor(dev))) == NULL)
1057 1043                  return (EINVAL);
1058 1044  
1059 1045          (void) snprintf(name, sizeof (name), "%s%d", drv,
1060 1046              DLS_MINOR2INST(getminor(dev)));
1061 1047  
1062      -        /*
1063      -         * Hold this link to prevent it being detached in case of a
1064      -         * GLDv3 physical link.
1065      -         */
1066      -        if (DLS_MINOR2INST(getminor(dev)) <= DLS_MAX_PPA)
1067      -                (void) softmac_hold_device(dev, &ddh);
1068      -
1069 1048          rw_enter(&i_dls_devnet_lock, RW_READER);
1070 1049          if ((err = mod_hash_find(i_dls_devnet_hash,
1071 1050              (mod_hash_key_t)name, (mod_hash_val_t *)&ddp)) != 0) {
1072 1051                  ASSERT(err == MH_ERR_NOTFOUND);
1073 1052                  rw_exit(&i_dls_devnet_lock);
1074      -                softmac_rele_device(ddh);
1075 1053                  return (ENOENT);
1076 1054          }
1077 1055          mutex_enter(&ddp->dd_mutex);
1078 1056          ASSERT(ddp->dd_ref > 0);
1079 1057          if (ddp->dd_flags & DD_CONDEMNED) {
1080 1058                  mutex_exit(&ddp->dd_mutex);
1081 1059                  rw_exit(&i_dls_devnet_lock);
1082      -                softmac_rele_device(ddh);
1083 1060                  return (ENOENT);
1084 1061          }
1085 1062          ddp->dd_ref++;
1086 1063          mutex_exit(&ddp->dd_mutex);
1087 1064          rw_exit(&i_dls_devnet_lock);
1088 1065  
1089      -        softmac_rele_device(ddh);
1090      -
1091 1066          *ddhp = ddp;
1092 1067          return (0);
1093 1068  }
1094 1069  
1095 1070  void
1096 1071  dls_devnet_rele(dls_devnet_t *ddp)
1097 1072  {
1098 1073          mutex_enter(&ddp->dd_mutex);
1099 1074          ASSERT(ddp->dd_ref > 1);
1100 1075          ddp->dd_ref--;
↓ open down ↓ 24 lines elided ↑ open up ↑
1125 1100           * If we failed to get the link's linkid because the dlmgmtd daemon
1126 1101           * has not been started, return ENOENT so that the application can
1127 1102           * fallback to open the /dev node.
1128 1103           */
1129 1104          if (err == EBADF)
1130 1105                  return (ENOENT);
1131 1106  
1132 1107          if (err != ENOENT)
1133 1108                  return (err);
1134 1109  
     1110 +        /*
     1111 +         * If we reach this point it means dlmgmtd is up but has no
     1112 +         * mapping for the link name.
     1113 +         */
1135 1114          if (ddi_parse(link, drv, &ppa) != DDI_SUCCESS)
1136 1115                  return (ENOENT);
1137 1116  
1138 1117          if (IS_IPTUN_LINK(drv)) {
1139 1118                  if ((err = i_dls_devnet_create_iptun(link, drv, &linkid)) != 0)
1140 1119                          return (err);
1141 1120                  /*
1142 1121                   * At this point, an IP tunnel MAC has registered, which
1143 1122                   * resulted in a link being created.
1144 1123                   */
1145 1124                  err = dls_devnet_hold(linkid, ddpp);
1146      -                ASSERT(err == 0);
1147 1125                  if (err != 0) {
1148 1126                          VERIFY(i_dls_devnet_destroy_iptun(linkid) == 0);
1149 1127                          return (err);
1150 1128                  }
1151 1129                  /*
1152 1130                   * dls_devnet_rele() will know to destroy the implicit IP
1153 1131                   * tunnel on last reference release if DD_IMPLICIT_IPTUN is
1154 1132                   * set.
1155 1133                   */
1156 1134                  (*ddpp)->dd_flags |= DD_IMPLICIT_IPTUN;
↓ open down ↓ 595 lines elided ↑ open up ↑
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX