Print this page
usr/src/cmd/dlmgmtd/dlmgmt_door.c


 911                  * ddp->dd_linkid is not set. Following this, the link
 912                  * must still be in the DD_INITIALIZING state because
 913                  * that flag is removed IFF dd_linkid is set. This is
 914                  * why we can ASSERT the DD_INITIALIZING flag below if
 915                  * the call to i_dls_devnet_setzid() fails.
 916                  */
 917                 if (linkid == DATALINK_INVALID_LINKID ||
 918                     class != DATALINK_CLASS_PHYS) {
 919                         err = EINVAL;
 920                         goto done;
 921                 }
 922 
 923                 ASSERT(ddp->dd_flags & DD_INITIALIZING);
 924 
 925         } else {
 926                 ddp = kmem_cache_alloc(i_dls_devnet_cachep, KM_SLEEP);
 927                 ddp->dd_flags = DD_INITIALIZING;
 928                 ddp->dd_tref = 0;
 929                 ddp->dd_ref++;
 930                 ddp->dd_owner_zid = zoneid;








 931                 (void) strlcpy(ddp->dd_mac, macname, sizeof (ddp->dd_mac));
 932                 VERIFY(mod_hash_insert(i_dls_devnet_hash,
 933                     (mod_hash_key_t)ddp->dd_mac, (mod_hash_val_t)ddp) == 0);
 934         }
 935 
 936         if (linkid != DATALINK_INVALID_LINKID) {
 937                 ddp->dd_linkid = linkid;
 938                 (void) strlcpy(ddp->dd_linkname, linkname,
 939                     sizeof (ddp->dd_linkname));
 940                 VERIFY(mod_hash_insert(i_dls_devnet_id_hash,
 941                     (mod_hash_key_t)(uintptr_t)linkid,
 942                     (mod_hash_val_t)ddp) == 0);
 943                 devnet_need_rebuild = B_TRUE;
 944                 stat_create = B_TRUE;
 945                 mutex_enter(&ddp->dd_mutex);
 946                 if (!ddp->dd_prop_loaded && (ddp->dd_prop_taskid == 0)) {
 947                         ddp->dd_prop_taskid = taskq_dispatch(system_taskq,
 948                             dls_devnet_prop_task, ddp, TQ_SLEEP);
 949                 }
 950                 mutex_exit(&ddp->dd_mutex);
 951         }
 952         err = 0;
 953 done:
 954         /*
 955          * It is safe to drop the i_dls_devnet_lock at this point. In the case
 956          * of physical devices, the softmac framework will fail the device
 957          * detach based on the smac_state or smac_hold_cnt. Other cases like
 958          * vnic and aggr use their own scheme to serialize creates and deletes
 959          * and ensure that *ddp is valid.
 960          */
 961         rw_exit(&i_dls_devnet_lock);





















 962         if (err == 0) {
 963                 if (zoneid != GLOBAL_ZONEID &&
 964                     (err = i_dls_devnet_setzid(ddp, zoneid, B_FALSE,
 965                     B_FALSE)) != 0) {
 966                         /*
 967                          * At this point the link is marked as
 968                          * DD_INITIALIZING -- there can be no
 969                          * outstanding temp refs and therefore no need
 970                          * to wait for them.
 971                          */
 972                         ASSERT(ddp->dd_flags & DD_INITIALIZING);
 973                         (void) dls_devnet_unset(mh, &linkid, B_FALSE);
 974                         return (err);
 975                 }
 976 
 977                 /*
 978                  * The kstat subsystem holds its own locks (rather perimeter)
 979                  * before calling the ks_update (dls_devnet_stat_update) entry
 980                  * point which in turn grabs the i_dls_devnet_lock. So the
 981                  * lock hierarchy is kstat locks -> i_dls_devnet_lock.
 982                  */
 983                 if (stat_create)
 984                         dls_devnet_stat_create(ddp, zoneid, zoneid);
 985                 if (ddpp != NULL)
 986                         *ddpp = ddp;
 987 
 988                 mutex_enter(&ddp->dd_mutex);
 989                 if (linkid != DATALINK_INVALID_LINKID && !ddp->dd_prop_loaded &&
 990                     ddp->dd_prop_taskid == TASKQID_INVALID) {
 991                         ddp->dd_prop_taskid = taskq_dispatch(system_taskq,
 992                             dls_devnet_prop_task, ddp, TQ_SLEEP);
 993                 }
 994                 mutex_exit(&ddp->dd_mutex);
 995 
 996         }
 997         return (err);
 998 }
 999 
1000 /*
1001  * Disassociate the linkid from the link identified by macname. If
1002  * wait is B_TRUE, wait until all temporary refs are released and the
1003  * prop task is finished.
1004  *
1005  * If waiting then you SHOULD NOT call this from inside the MAC perim
1006  * as deadlock will ensue. Otherwise, this function is safe to call
1007  * from inside or outside the MAC perim.
1008  */
1009 static int
1010 dls_devnet_unset(mac_handle_t mh, datalink_id_t *id, boolean_t wait)


1031          * property loading as part of the post attach hasn't yet completed.
1032          */
1033         VERIFY(ddp->dd_ref != 0);
1034         if ((ddp->dd_ref != 1) || (!wait &&
1035             (ddp->dd_tref != 0 || ddp->dd_prop_taskid != 0))) {
1036                 int zstatus = 0;
1037 
1038                 /*
1039                  * There are a couple of alternatives that might be going on
1040                  * here; a) the zone is shutting down and it has a transient
1041                  * link assigned, in which case we want to clean it up instead
1042                  * of moving it back to the global zone, or b) its possible
1043                  * that we're trying to clean up an orphaned vnic that was
1044                  * delegated to a zone and which wasn't cleaned up properly
1045                  * when the zone went away.  Check for either of these cases
1046                  * before we simply return EBUSY.
1047                  *
1048                  * zstatus indicates which situation we are dealing with:
1049                  *       0 - means return EBUSY
1050                  *       1 - means case (a), cleanup transient link
1051                  *      -1 - means case (b), orphained VNIC
1052                  */
1053                 if (ddp->dd_ref > 1 && ddp->dd_zid != GLOBAL_ZONEID) {
1054                         zone_t  *zp;
1055 
1056                         if ((zp = zone_find_by_id(ddp->dd_zid)) == NULL) {
1057                                 zstatus = -1;
1058                         } else {
1059                                 if (ddp->dd_transient) {
1060                                         zone_status_t s = zone_status_get(zp);
1061 
1062                                         if (s >= ZONE_IS_SHUTTING_DOWN)
1063                                                 zstatus = 1;
1064                                 }
1065                                 zone_rele(zp);
1066                         }
1067                 }
1068 
1069                 if (zstatus == 0) {
1070                         mutex_exit(&ddp->dd_mutex);
1071                         rw_exit(&i_dls_devnet_lock);
1072                         return (EBUSY);
1073                 }
1074 
1075                 /*
1076                  * We want to delete the link, reset ref to 1;
1077                  */
1078                 if (zstatus == -1)
1079                         /* Log a warning, but continue in this case */
1080                         cmn_err(CE_WARN, "clear orphaned datalink: %s\n",
1081                             ddp->dd_linkname);

1082                 ddp->dd_ref = 1;
1083         }
1084 
1085         ddp->dd_flags |= DD_CONDEMNED;
1086         ddp->dd_ref--;
1087         *id = ddp->dd_linkid;
1088 
1089         /*
1090          * Remove this dls_devnet_t from the hash table.
1091          */
1092         VERIFY(mod_hash_remove(i_dls_devnet_hash,
1093             (mod_hash_key_t)ddp->dd_mac, &val) == 0);
1094 
1095         if (ddp->dd_linkid != DATALINK_INVALID_LINKID) {
1096                 VERIFY(mod_hash_remove(i_dls_devnet_id_hash,
1097                     (mod_hash_key_t)(uintptr_t)ddp->dd_linkid, &val) == 0);
1098 
1099                 devnet_need_rebuild = B_TRUE;
1100         }
1101         rw_exit(&i_dls_devnet_lock);
1102 
1103         /*
1104          * It is important to call i_dls_devnet_setzid() WITHOUT the
1105          * i_dls_devnet_lock held. The setzid call grabs the MAC
1106          * perim; thus causing DLS -> MAC lock ordering if performed
1107          * with the i_dls_devnet_lock held. This forces consumers to
1108          * grab the MAC perim before calling dls_devnet_unset() (the
1109          * locking rules state MAC -> DLS order). By performing the
1110          * setzid outside of the i_dls_devnet_lock consumers can
1111          * safely call dls_devnet_unset() outside the MAC perim.
1112          */
1113         if (ddp->dd_zid != GLOBAL_ZONEID) {













1114                 dls_devnet_stat_destroy(ddp, ddp->dd_zid);

1115                 (void) i_dls_devnet_setzid(ddp, GLOBAL_ZONEID, B_FALSE,
1116                     B_FALSE);
1117         }
1118 
1119         if (wait) {
1120                 /*
1121                  * Wait until all temporary references are released.
1122                  * The holders of the tref need the MAC perim to
1123                  * perform their work and release the tref. To avoid
1124                  * deadlock, assert that the perim is never held here.
1125                  */
1126                 ASSERT0(MAC_PERIM_HELD(mh));
1127                 while ((ddp->dd_tref != 0) || (ddp->dd_prop_taskid != 0))
1128                         cv_wait(&ddp->dd_cv, &ddp->dd_mutex);
1129         } else {
1130                 VERIFY(ddp->dd_tref == 0);
1131                 VERIFY(ddp->dd_prop_taskid == (taskqid_t)NULL);
1132         }
1133 
1134         if (ddp->dd_linkid != DATALINK_INVALID_LINKID) {
1135                 dls_devnet_stat_destroy(ddp, ddp->dd_owner_zid);
1136         }
1137 
1138         ddp->dd_prop_loaded = B_FALSE;
1139         ddp->dd_linkid = DATALINK_INVALID_LINKID;
1140         ddp->dd_flags = 0;
1141         mutex_exit(&ddp->dd_mutex);
1142         kmem_cache_free(i_dls_devnet_cachep, ddp);
1143 
1144         return (0);
1145 }
1146 
1147 /*
1148  * This is a private hold routine used when we already have the dls_link_t, thus
1149  * we know that it cannot go away.
1150  */
1151 int
1152 dls_devnet_hold_tmp_by_link(dls_link_t *dlp, dls_dl_handle_t *ddhp)
1153 {
1154         int err;
1155         dls_devnet_t *ddp = NULL;
1156 
1157         rw_enter(&i_dls_devnet_lock, RW_WRITER);
1158         if ((err = mod_hash_find(i_dls_devnet_hash,
1159             (mod_hash_key_t)dlp->dl_name, (mod_hash_val_t *)&ddp)) != 0) {
1160                 ASSERT(err == MH_ERR_NOTFOUND);
1161                 rw_exit(&i_dls_devnet_lock);
1162                 return (ENOENT);
1163         }
1164 
1165         mutex_enter(&ddp->dd_mutex);
1166         ASSERT(ddp->dd_ref > 0);
1167         if (ddp->dd_flags & DD_CONDEMNED) {
1168                 mutex_exit(&ddp->dd_mutex);
1169                 rw_exit(&i_dls_devnet_lock);
1170                 return (ENOENT);
1171         }
1172         ddp->dd_tref++;
1173         mutex_exit(&ddp->dd_mutex);
1174         rw_exit(&i_dls_devnet_lock);
1175 
1176         *ddhp = ddp;
1177         return (0);
1178 }
1179 
1180 static int
1181 dls_devnet_hold_common(datalink_id_t linkid, dls_devnet_t **ddpp,
1182     boolean_t tmp_hold)
1183 {
1184         dls_devnet_t            *ddp;
1185         int                     err;
1186 
1187         rw_enter(&i_dls_devnet_lock, RW_READER);


1918          *    i_dls_devnet_hash.
1919          *
1920          * Even if #3 wasn't true the dls_devnet_set() may fail for
1921          * different reasons in the future; the point is that it _can_
1922          * fail as part of its contract. We can't rely on it working
1923          * so we must assume that these two pieces of state (devnet
1924          * and link hashes), which should always be in sync, can get
1925          * out of sync and thus even if we get ENOENT from the devnet
1926          * hash we should still try to delete from the link hash just
1927          * in case.
1928          *
1929          * We could prevent the ENOTEMPTY from dls_link_rele_by_name()
1930          * by calling mac_disable() before calling
1931          * dls_devnet_destroy() but that's not currently possible due
1932          * to a long-standing bug. OpenSolaris 6791335: The semantics
1933          * of mac_disable() were modified by Crossbow such that
1934          * dls_devnet_destroy() needs to be called before
1935          * mac_disable() can succeed. This is because of the implicit
1936          * reference that dls has on the mac_impl_t.
1937          */
1938         if (err != 0 && err != ENOENT) {
1939                 return (err);
1940         }
1941 
1942         mac_perim_enter_by_mh(mh, &mph);
1943         err = dls_link_rele_by_name(mac_name(mh));
1944         if (err != 0) {
1945                 dls_devnet_t    *ddp;
1946 
1947                 /*
1948                  * XXX It is a general GLDv3 bug that dls_devnet_set() has to
1949                  * be called to re-set the link when destroy fails.  The
1950                  * zoneid below will be incorrect if this function is ever
1951                  * called from kernel context or from a zone other than that
1952                  * which initially created the link.
1953                  */
1954                 (void) dls_devnet_set(mh, *idp, crgetzoneid(CRED()), &ddp);
1955 
1956                 /*
1957                  * You might think dd_linkid should always be set
1958                  * here, but in the case where dls_devnet_unset()
1959                  * returns ENOENT it will be DATALINK_INVALID_LINKID.
1960                  * Stay consistent with the rest of DLS and only




 911                  * ddp->dd_linkid is not set. Following this, the link
 912                  * must still be in the DD_INITIALIZING state because
 913                  * that flag is removed IFF dd_linkid is set. This is
 914                  * why we can ASSERT the DD_INITIALIZING flag below if
 915                  * the call to i_dls_devnet_setzid() fails.
 916                  */
 917                 if (linkid == DATALINK_INVALID_LINKID ||
 918                     class != DATALINK_CLASS_PHYS) {
 919                         err = EINVAL;
 920                         goto done;
 921                 }
 922 
 923                 ASSERT(ddp->dd_flags & DD_INITIALIZING);
 924 
 925         } else {
 926                 ddp = kmem_cache_alloc(i_dls_devnet_cachep, KM_SLEEP);
 927                 ddp->dd_flags = DD_INITIALIZING;
 928                 ddp->dd_tref = 0;
 929                 ddp->dd_ref++;
 930                 ddp->dd_owner_zid = zoneid;
 931                 /*
 932                  * If we are creating a new devnet which will be owned by a NGZ
 933                  * then mark it as transient. This link has never been in the
 934                  * GZ, the GZ will not have a hold on its reference, and we do
 935                  * not want to return it to the GZ when the zone halts.
 936                  */
 937                 if (zoneid != GLOBAL_ZONEID)
 938                         ddp->dd_transient = B_TRUE;
 939                 (void) strlcpy(ddp->dd_mac, macname, sizeof (ddp->dd_mac));
 940                 VERIFY(mod_hash_insert(i_dls_devnet_hash,
 941                     (mod_hash_key_t)ddp->dd_mac, (mod_hash_val_t)ddp) == 0);
 942         }
 943 
 944         if (linkid != DATALINK_INVALID_LINKID) {
 945                 ddp->dd_linkid = linkid;
 946                 (void) strlcpy(ddp->dd_linkname, linkname,
 947                     sizeof (ddp->dd_linkname));
 948                 VERIFY(mod_hash_insert(i_dls_devnet_id_hash,
 949                     (mod_hash_key_t)(uintptr_t)linkid,
 950                     (mod_hash_val_t)ddp) == 0);
 951                 devnet_need_rebuild = B_TRUE;
 952                 stat_create = B_TRUE;




 953         }


 954         err = 0;
 955 done:
 956         /*
 957          * It is safe to drop the i_dls_devnet_lock at this point. In the case
 958          * of physical devices, the softmac framework will fail the device
 959          * detach based on the smac_state or smac_hold_cnt. Other cases like
 960          * vnic and aggr use their own scheme to serialize creates and deletes
 961          * and ensure that *ddp is valid.
 962          */
 963         rw_exit(&i_dls_devnet_lock);
 964 
 965         if (err == 0 && zoneid != GLOBAL_ZONEID) {
 966                 /*
 967                  * If this link is being created directly within a non-global
 968                  * zone, then flag it as transient so that it will be cleaned
 969                  * up when the zone is shut down.
 970                  */
 971                 err = i_dls_devnet_setzid(ddp, zoneid, B_FALSE, B_TRUE);
 972                 if (err != 0) {
 973                         /*
 974                          * At this point the link is marked as
 975                          * DD_INITIALIZING -- there can be no
 976                          * outstanding temp refs and therefore no need
 977                          * to wait for them.
 978                          */
 979                         ASSERT(ddp->dd_flags & DD_INITIALIZING);
 980                         (void) dls_devnet_unset(mh, &linkid, B_FALSE);
 981                         return (err);
 982                 }
 983         }
 984 
 985         if (err == 0) {
 986                 if (zoneid != GLOBAL_ZONEID &&
 987                     (err = i_dls_devnet_setzid(ddp, zoneid, B_FALSE,
 988                     B_FALSE)) != 0) {
 989                         /*
 990                          * At this point the link is marked as
 991                          * DD_INITIALIZING -- there can be no
 992                          * outstanding temp refs and therefore no need
 993                          * to wait for them.
 994                          */
 995                         ASSERT(ddp->dd_flags & DD_INITIALIZING);
 996                         (void) dls_devnet_unset(mh, &linkid, B_FALSE);
 997                         return (err);
 998                 }
 999 
1000                 /*
1001                  * The kstat subsystem holds its own locks (rather perimeter)
1002                  * before calling the ks_update (dls_devnet_stat_update) entry
1003                  * point which in turn grabs the i_dls_devnet_lock. So the
1004                  * lock hierarchy is kstat locks -> i_dls_devnet_lock.
1005                  */
1006                 if (stat_create)
1007                         dls_devnet_stat_create(ddp, zoneid, zoneid);
1008                 if (ddpp != NULL)
1009                         *ddpp = ddp;
1010 
1011                 mutex_enter(&ddp->dd_mutex);
1012                 if (linkid != DATALINK_INVALID_LINKID &&
1013                     !ddp->dd_prop_loaded && ddp->dd_prop_taskid == 0) {
1014                         ddp->dd_prop_taskid = taskq_dispatch(system_taskq,
1015                             dls_devnet_prop_task, ddp, TQ_SLEEP);
1016                 }
1017                 mutex_exit(&ddp->dd_mutex);
1018 
1019         }
1020         return (err);
1021 }
1022 
1023 /*
1024  * Disassociate the linkid from the link identified by macname. If
1025  * wait is B_TRUE, wait until all temporary refs are released and the
1026  * prop task is finished.
1027  *
1028  * If waiting then you SHOULD NOT call this from inside the MAC perim
1029  * as deadlock will ensue. Otherwise, this function is safe to call
1030  * from inside or outside the MAC perim.
1031  */
1032 static int
1033 dls_devnet_unset(mac_handle_t mh, datalink_id_t *id, boolean_t wait)


1054          * property loading as part of the post attach hasn't yet completed.
1055          */
1056         VERIFY(ddp->dd_ref != 0);
1057         if ((ddp->dd_ref != 1) || (!wait &&
1058             (ddp->dd_tref != 0 || ddp->dd_prop_taskid != 0))) {
1059                 int zstatus = 0;
1060 
1061                 /*
1062                  * There are a couple of alternatives that might be going on
1063                  * here; a) the zone is shutting down and it has a transient
1064                  * link assigned, in which case we want to clean it up instead
1065                  * of moving it back to the global zone, or b) its possible
1066                  * that we're trying to clean up an orphaned vnic that was
1067                  * delegated to a zone and which wasn't cleaned up properly
1068                  * when the zone went away.  Check for either of these cases
1069                  * before we simply return EBUSY.
1070                  *
1071                  * zstatus indicates which situation we are dealing with:
1072                  *       0 - means return EBUSY
1073                  *       1 - means case (a), cleanup transient link
1074                  *      -1 - means case (b), orphaned VNIC
1075                  */
1076                 if (ddp->dd_ref > 1 && ddp->dd_zid != GLOBAL_ZONEID) {
1077                         zone_t  *zp;
1078 
1079                         if ((zp = zone_find_by_id(ddp->dd_zid)) == NULL) {
1080                                 zstatus = -1;
1081                         } else {
1082                                 if (ddp->dd_transient) {
1083                                         zone_status_t s = zone_status_get(zp);
1084 
1085                                         if (s >= ZONE_IS_SHUTTING_DOWN)
1086                                                 zstatus = 1;
1087                                 }
1088                                 zone_rele(zp);
1089                         }
1090                 }
1091 
1092                 if (zstatus == 0) {
1093                         mutex_exit(&ddp->dd_mutex);
1094                         rw_exit(&i_dls_devnet_lock);
1095                         return (EBUSY);
1096                 }
1097 
1098                 /*
1099                  * We want to delete the link, reset ref to 1;
1100                  */
1101                 if (zstatus == -1) {
1102                         /* Log a warning, but continue in this case */
1103                         cmn_err(CE_WARN, "clear orphaned datalink: %s\n",
1104                             ddp->dd_linkname);
1105                 }
1106                 ddp->dd_ref = 1;
1107         }
1108 
1109         ddp->dd_flags |= DD_CONDEMNED;
1110         ddp->dd_ref--;
1111         *id = ddp->dd_linkid;
1112 
1113         /*
1114          * Remove this dls_devnet_t from the hash table.
1115          */
1116         VERIFY(mod_hash_remove(i_dls_devnet_hash,
1117             (mod_hash_key_t)ddp->dd_mac, &val) == 0);
1118 
1119         if (ddp->dd_linkid != DATALINK_INVALID_LINKID) {
1120                 VERIFY(mod_hash_remove(i_dls_devnet_id_hash,
1121                     (mod_hash_key_t)(uintptr_t)ddp->dd_linkid, &val) == 0);
1122 
1123                 devnet_need_rebuild = B_TRUE;
1124         }
1125         rw_exit(&i_dls_devnet_lock);
1126 
1127         /*
1128          * It is important to call i_dls_devnet_setzid() WITHOUT the
1129          * i_dls_devnet_lock held. The setzid call grabs the MAC
1130          * perim; thus causing DLS -> MAC lock ordering if performed
1131          * with the i_dls_devnet_lock held. This forces consumers to
1132          * grab the MAC perim before calling dls_devnet_unset() (the
1133          * locking rules state MAC -> DLS order). By performing the
1134          * setzid outside of the i_dls_devnet_lock consumers can
1135          * safely call dls_devnet_unset() outside the MAC perim.
1136          */
1137         if (ddp->dd_zid != GLOBAL_ZONEID) {
1138                 /*
1139                  * We need to release the dd_mutex before we try and destroy the
1140                  * stat. When we destroy it, we'll need to grab the lock for the
1141                  * kstat but if there's a concurrent reader of the kstat, we'll
1142                  * be blocked on it. This will lead to deadlock because these
1143                  * kstats employ a ks_update function (dls_devnet_stat_update)
1144                  * which needs the dd_mutex that we currently hold.
1145                  *
1146                  * Because we've already flagged the dls_devnet_t as
1147                  * DD_CONDEMNED and we still have a write lock on
1148                  * i_dls_devnet_lock, we should be able to release the dd_mutex.
1149                  */
1150                 mutex_exit(&ddp->dd_mutex);
1151                 dls_devnet_stat_destroy(ddp, ddp->dd_zid);
1152                 mutex_enter(&ddp->dd_mutex);
1153                 (void) i_dls_devnet_setzid(ddp, GLOBAL_ZONEID, B_FALSE,
1154                     B_FALSE);
1155         }
1156 
1157         if (wait) {
1158                 /*
1159                  * Wait until all temporary references are released.
1160                  * The holders of the tref need the MAC perim to
1161                  * perform their work and release the tref. To avoid
1162                  * deadlock, assert that the perim is never held here.
1163                  */
1164                 ASSERT0(MAC_PERIM_HELD(mh));
1165                 while ((ddp->dd_tref != 0) || (ddp->dd_prop_taskid != 0))
1166                         cv_wait(&ddp->dd_cv, &ddp->dd_mutex);
1167         } else {
1168                 VERIFY(ddp->dd_tref == 0);
1169                 VERIFY(ddp->dd_prop_taskid == 0);
1170         }
1171 
1172         if (ddp->dd_linkid != DATALINK_INVALID_LINKID) {
1173                 dls_devnet_stat_destroy(ddp, ddp->dd_owner_zid);
1174         }
1175 
1176         ddp->dd_prop_loaded = B_FALSE;
1177         ddp->dd_linkid = DATALINK_INVALID_LINKID;
1178         ddp->dd_flags = 0;
1179         mutex_exit(&ddp->dd_mutex);
1180         kmem_cache_free(i_dls_devnet_cachep, ddp);
1181 
1182         return (0);
1183 }
1184 
1185 /*
1186  * This is a private hold routine used when we already have the dls_link_t, thus
1187  * we know that it cannot go away.
1188  */
1189 int
1190 dls_devnet_hold_tmp_by_link(dls_link_t *dlp, dls_dl_handle_t *ddhp)
1191 {
1192         int err;
1193         dls_devnet_t *ddp = NULL;
1194 
1195         rw_enter(&i_dls_devnet_lock, RW_WRITER);
1196         if ((err = mod_hash_find(i_dls_devnet_hash,
1197             (mod_hash_key_t)dlp->dl_name, (mod_hash_val_t *)&ddp)) != 0) {
1198                 ASSERT(err == MH_ERR_NOTFOUND);
1199                 rw_exit(&i_dls_devnet_lock);
1200                 return (ENOENT);
1201         }
1202 
1203         mutex_enter(&ddp->dd_mutex);
1204         VERIFY(ddp->dd_ref > 0);
1205         if (DD_NOT_VISIBLE(ddp->dd_flags)) {
1206                 mutex_exit(&ddp->dd_mutex);
1207                 rw_exit(&i_dls_devnet_lock);
1208                 return (ENOENT);
1209         }
1210         ddp->dd_tref++;
1211         mutex_exit(&ddp->dd_mutex);
1212         rw_exit(&i_dls_devnet_lock);
1213 
1214         *ddhp = ddp;
1215         return (0);
1216 }
1217 
1218 static int
1219 dls_devnet_hold_common(datalink_id_t linkid, dls_devnet_t **ddpp,
1220     boolean_t tmp_hold)
1221 {
1222         dls_devnet_t            *ddp;
1223         int                     err;
1224 
1225         rw_enter(&i_dls_devnet_lock, RW_READER);


1956          *    i_dls_devnet_hash.
1957          *
1958          * Even if #3 wasn't true the dls_devnet_set() may fail for
1959          * different reasons in the future; the point is that it _can_
1960          * fail as part of its contract. We can't rely on it working
1961          * so we must assume that these two pieces of state (devnet
1962          * and link hashes), which should always be in sync, can get
1963          * out of sync and thus even if we get ENOENT from the devnet
1964          * hash we should still try to delete from the link hash just
1965          * in case.
1966          *
1967          * We could prevent the ENOTEMPTY from dls_link_rele_by_name()
1968          * by calling mac_disable() before calling
1969          * dls_devnet_destroy() but that's not currently possible due
1970          * to a long-standing bug. OpenSolaris 6791335: The semantics
1971          * of mac_disable() were modified by Crossbow such that
1972          * dls_devnet_destroy() needs to be called before
1973          * mac_disable() can succeed. This is because of the implicit
1974          * reference that dls has on the mac_impl_t.
1975          */
1976         if (err != 0 && err != ENOENT)
1977                 return (err);

1978 
1979         mac_perim_enter_by_mh(mh, &mph);
1980         err = dls_link_rele_by_name(mac_name(mh));
1981         if (err != 0) {
1982                 dls_devnet_t    *ddp;
1983 
1984                 /*
1985                  * XXX It is a general GLDv3 bug that dls_devnet_set() has to
1986                  * be called to re-set the link when destroy fails.  The
1987                  * zoneid below will be incorrect if this function is ever
1988                  * called from kernel context or from a zone other than that
1989                  * which initially created the link.
1990                  */
1991                 (void) dls_devnet_set(mh, *idp, crgetzoneid(CRED()), &ddp);
1992 
1993                 /*
1994                  * You might think dd_linkid should always be set
1995                  * here, but in the case where dls_devnet_unset()
1996                  * returns ENOENT it will be DATALINK_INVALID_LINKID.
1997                  * Stay consistent with the rest of DLS and only