1d62bc4baSyz147064 /* 2d62bc4baSyz147064 * CDDL HEADER START 3d62bc4baSyz147064 * 4d62bc4baSyz147064 * The contents of this file are subject to the terms of the 5d62bc4baSyz147064 * Common Development and Distribution License (the "License"). 6d62bc4baSyz147064 * You may not use this file except in compliance with the License. 7d62bc4baSyz147064 * 8d62bc4baSyz147064 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9d62bc4baSyz147064 * or http://www.opensolaris.org/os/licensing. 10d62bc4baSyz147064 * See the License for the specific language governing permissions 11d62bc4baSyz147064 * and limitations under the License. 12d62bc4baSyz147064 * 13d62bc4baSyz147064 * When distributing Covered Code, include this CDDL HEADER in each 14d62bc4baSyz147064 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15d62bc4baSyz147064 * If applicable, add the following below this CDDL HEADER, with the 16d62bc4baSyz147064 * fields enclosed by brackets "[]" replaced with your own identifying 17d62bc4baSyz147064 * information: Portions Copyright [yyyy] [name of copyright owner] 18d62bc4baSyz147064 * 19d62bc4baSyz147064 * CDDL HEADER END 20d62bc4baSyz147064 */ 21d62bc4baSyz147064 22d62bc4baSyz147064 /* 2332715170SCathy Zhou * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. 24d62bc4baSyz147064 */ 25d62bc4baSyz147064 26d62bc4baSyz147064 /* 27d62bc4baSyz147064 * Utility functions used by the dlmgmtd daemon. 28d62bc4baSyz147064 */ 29d62bc4baSyz147064 30d62bc4baSyz147064 #include <assert.h> 31d62bc4baSyz147064 #include <pthread.h> 32d62bc4baSyz147064 #include <stddef.h> 33d62bc4baSyz147064 #include <stdlib.h> 34d62bc4baSyz147064 #include <stdio.h> 352b24ab6bSSebastien Roy #include <errno.h> 36d62bc4baSyz147064 #include <strings.h> 372b24ab6bSSebastien Roy #include <string.h> 38d62bc4baSyz147064 #include <syslog.h> 39d62bc4baSyz147064 #include <stdarg.h> 402b24ab6bSSebastien Roy #include <zone.h> 4182a2fc47SJames Carlson #include <errno.h> 42d62bc4baSyz147064 #include <libdlpi.h> 43d62bc4baSyz147064 #include "dlmgmt_impl.h" 44d62bc4baSyz147064 45d62bc4baSyz147064 /* 462b24ab6bSSebastien Roy * There are three datalink AVL tables. The dlmgmt_name_avl tree contains all 472b24ab6bSSebastien Roy * datalinks and is keyed by zoneid and link name. The dlmgmt_id_avl also 482b24ab6bSSebastien Roy * contains all datalinks, and it is keyed by link ID. The dlmgmt_loan_avl is 492b24ab6bSSebastien Roy * keyed by link name, and contains the set of global-zone links that are 502b24ab6bSSebastien Roy * currently on loan to non-global zones. 51d62bc4baSyz147064 */ 52d62bc4baSyz147064 avl_tree_t dlmgmt_name_avl; 53d62bc4baSyz147064 avl_tree_t dlmgmt_id_avl; 542b24ab6bSSebastien Roy avl_tree_t dlmgmt_loan_avl; 55d62bc4baSyz147064 56d62bc4baSyz147064 avl_tree_t dlmgmt_dlconf_avl; 57d62bc4baSyz147064 58d62bc4baSyz147064 static pthread_rwlock_t dlmgmt_avl_lock = PTHREAD_RWLOCK_INITIALIZER; 59d62bc4baSyz147064 static pthread_mutex_t dlmgmt_avl_mutex = PTHREAD_MUTEX_INITIALIZER; 60d62bc4baSyz147064 static pthread_cond_t dlmgmt_avl_cv = PTHREAD_COND_INITIALIZER; 61d62bc4baSyz147064 static pthread_rwlock_t dlmgmt_dlconf_lock = PTHREAD_RWLOCK_INITIALIZER; 62d62bc4baSyz147064 63d62bc4baSyz147064 typedef struct dlmgmt_prefix { 64d62bc4baSyz147064 struct dlmgmt_prefix *lp_next; 65d62bc4baSyz147064 char lp_prefix[MAXLINKNAMELEN]; 662b24ab6bSSebastien Roy zoneid_t lp_zoneid; 67d62bc4baSyz147064 uint_t lp_nextppa; 68d62bc4baSyz147064 } dlmgmt_prefix_t; 692b24ab6bSSebastien Roy static dlmgmt_prefix_t dlmgmt_prefixlist; 70d62bc4baSyz147064 712b24ab6bSSebastien Roy datalink_id_t dlmgmt_nextlinkid; 72d62bc4baSyz147064 static datalink_id_t dlmgmt_nextconfid = 1; 73d62bc4baSyz147064 74d62bc4baSyz147064 static void dlmgmt_advance_linkid(dlmgmt_link_t *); 75d62bc4baSyz147064 static void dlmgmt_advance_ppa(dlmgmt_link_t *); 76d62bc4baSyz147064 77d62bc4baSyz147064 void 78d62bc4baSyz147064 dlmgmt_log(int pri, const char *fmt, ...) 79d62bc4baSyz147064 { 80d62bc4baSyz147064 va_list alist; 81d62bc4baSyz147064 82d62bc4baSyz147064 va_start(alist, fmt); 83d62bc4baSyz147064 if (debug) { 84d62bc4baSyz147064 (void) vfprintf(stderr, fmt, alist); 85d62bc4baSyz147064 (void) fputc('\n', stderr); 86d62bc4baSyz147064 } else { 87d62bc4baSyz147064 vsyslog(pri, fmt, alist); 88d62bc4baSyz147064 } 89d62bc4baSyz147064 va_end(alist); 90d62bc4baSyz147064 } 91d62bc4baSyz147064 92d62bc4baSyz147064 static int 93d62bc4baSyz147064 cmp_link_by_name(const void *v1, const void *v2) 94d62bc4baSyz147064 { 95d62bc4baSyz147064 const dlmgmt_link_t *link1 = v1; 96d62bc4baSyz147064 const dlmgmt_link_t *link2 = v2; 97d62bc4baSyz147064 int cmp; 98d62bc4baSyz147064 99d62bc4baSyz147064 cmp = strcmp(link1->ll_link, link2->ll_link); 100d62bc4baSyz147064 return ((cmp == 0) ? 0 : ((cmp < 0) ? -1 : 1)); 101d62bc4baSyz147064 } 102d62bc4baSyz147064 1032b24ab6bSSebastien Roy /* 1042b24ab6bSSebastien Roy * Note that the zoneid associated with a link is effectively part of its 1052b24ab6bSSebastien Roy * name. This is essentially what results in having each zone have disjoint 1062b24ab6bSSebastien Roy * datalink namespaces. 1072b24ab6bSSebastien Roy */ 1082b24ab6bSSebastien Roy static int 1092b24ab6bSSebastien Roy cmp_link_by_zname(const void *v1, const void *v2) 1102b24ab6bSSebastien Roy { 1112b24ab6bSSebastien Roy const dlmgmt_link_t *link1 = v1; 1122b24ab6bSSebastien Roy const dlmgmt_link_t *link2 = v2; 1132b24ab6bSSebastien Roy 1142b24ab6bSSebastien Roy if (link1->ll_zoneid < link2->ll_zoneid) 1152b24ab6bSSebastien Roy return (-1); 1162b24ab6bSSebastien Roy if (link1->ll_zoneid > link2->ll_zoneid) 1172b24ab6bSSebastien Roy return (1); 1182b24ab6bSSebastien Roy return (cmp_link_by_name(link1, link2)); 1192b24ab6bSSebastien Roy } 1202b24ab6bSSebastien Roy 121d62bc4baSyz147064 static int 122d62bc4baSyz147064 cmp_link_by_id(const void *v1, const void *v2) 123d62bc4baSyz147064 { 124d62bc4baSyz147064 const dlmgmt_link_t *link1 = v1; 125d62bc4baSyz147064 const dlmgmt_link_t *link2 = v2; 126d62bc4baSyz147064 127d62bc4baSyz147064 if ((uint64_t)(link1->ll_linkid) == (uint64_t)(link2->ll_linkid)) 128d62bc4baSyz147064 return (0); 129d62bc4baSyz147064 else if ((uint64_t)(link1->ll_linkid) < (uint64_t)(link2->ll_linkid)) 130d62bc4baSyz147064 return (-1); 131d62bc4baSyz147064 else 132d62bc4baSyz147064 return (1); 133d62bc4baSyz147064 } 134d62bc4baSyz147064 135d62bc4baSyz147064 static int 136d62bc4baSyz147064 cmp_dlconf_by_id(const void *v1, const void *v2) 137d62bc4baSyz147064 { 138d62bc4baSyz147064 const dlmgmt_dlconf_t *dlconfp1 = v1; 139d62bc4baSyz147064 const dlmgmt_dlconf_t *dlconfp2 = v2; 140d62bc4baSyz147064 141d62bc4baSyz147064 if (dlconfp1->ld_id == dlconfp2->ld_id) 142d62bc4baSyz147064 return (0); 143d62bc4baSyz147064 else if (dlconfp1->ld_id < dlconfp2->ld_id) 144d62bc4baSyz147064 return (-1); 145d62bc4baSyz147064 else 146d62bc4baSyz147064 return (1); 147d62bc4baSyz147064 } 148d62bc4baSyz147064 1492b24ab6bSSebastien Roy void 1502b24ab6bSSebastien Roy dlmgmt_linktable_init(void) 151d62bc4baSyz147064 { 152d62bc4baSyz147064 /* 1532b24ab6bSSebastien Roy * Initialize the prefix list. First add the "net" prefix for the 1542b24ab6bSSebastien Roy * global zone to the list. 155d62bc4baSyz147064 */ 1562b24ab6bSSebastien Roy dlmgmt_prefixlist.lp_next = NULL; 1572b24ab6bSSebastien Roy dlmgmt_prefixlist.lp_zoneid = GLOBAL_ZONEID; 1582b24ab6bSSebastien Roy dlmgmt_prefixlist.lp_nextppa = 0; 1592b24ab6bSSebastien Roy (void) strlcpy(dlmgmt_prefixlist.lp_prefix, "net", MAXLINKNAMELEN); 160d62bc4baSyz147064 1612b24ab6bSSebastien Roy avl_create(&dlmgmt_name_avl, cmp_link_by_zname, sizeof (dlmgmt_link_t), 1622b24ab6bSSebastien Roy offsetof(dlmgmt_link_t, ll_name_node)); 163d62bc4baSyz147064 avl_create(&dlmgmt_id_avl, cmp_link_by_id, sizeof (dlmgmt_link_t), 1642b24ab6bSSebastien Roy offsetof(dlmgmt_link_t, ll_id_node)); 1652b24ab6bSSebastien Roy avl_create(&dlmgmt_loan_avl, cmp_link_by_name, sizeof (dlmgmt_link_t), 1662b24ab6bSSebastien Roy offsetof(dlmgmt_link_t, ll_loan_node)); 167d62bc4baSyz147064 avl_create(&dlmgmt_dlconf_avl, cmp_dlconf_by_id, 168d62bc4baSyz147064 sizeof (dlmgmt_dlconf_t), offsetof(dlmgmt_dlconf_t, ld_node)); 169d62bc4baSyz147064 dlmgmt_nextlinkid = 1; 170d62bc4baSyz147064 } 171d62bc4baSyz147064 172d62bc4baSyz147064 void 1732b24ab6bSSebastien Roy dlmgmt_linktable_fini(void) 174d62bc4baSyz147064 { 175d62bc4baSyz147064 dlmgmt_prefix_t *lpp, *next; 176d62bc4baSyz147064 1772b24ab6bSSebastien Roy for (lpp = dlmgmt_prefixlist.lp_next; lpp != NULL; lpp = next) { 178d62bc4baSyz147064 next = lpp->lp_next; 179d62bc4baSyz147064 free(lpp); 180d62bc4baSyz147064 } 181d62bc4baSyz147064 182d62bc4baSyz147064 avl_destroy(&dlmgmt_dlconf_avl); 183d62bc4baSyz147064 avl_destroy(&dlmgmt_name_avl); 1842b24ab6bSSebastien Roy avl_destroy(&dlmgmt_loan_avl); 185d62bc4baSyz147064 avl_destroy(&dlmgmt_id_avl); 186d62bc4baSyz147064 } 187d62bc4baSyz147064 1882b24ab6bSSebastien Roy static void 189d62bc4baSyz147064 linkattr_add(dlmgmt_linkattr_t **headp, dlmgmt_linkattr_t *attrp) 190d62bc4baSyz147064 { 191d62bc4baSyz147064 if (*headp == NULL) { 192d62bc4baSyz147064 *headp = attrp; 193d62bc4baSyz147064 } else { 194d62bc4baSyz147064 (*headp)->lp_prev = attrp; 195d62bc4baSyz147064 attrp->lp_next = *headp; 196d62bc4baSyz147064 *headp = attrp; 197d62bc4baSyz147064 } 198d62bc4baSyz147064 } 199d62bc4baSyz147064 2002b24ab6bSSebastien Roy static void 201d62bc4baSyz147064 linkattr_rm(dlmgmt_linkattr_t **headp, dlmgmt_linkattr_t *attrp) 202d62bc4baSyz147064 { 203d62bc4baSyz147064 dlmgmt_linkattr_t *next, *prev; 204d62bc4baSyz147064 205d62bc4baSyz147064 next = attrp->lp_next; 206d62bc4baSyz147064 prev = attrp->lp_prev; 207d62bc4baSyz147064 if (next != NULL) 208d62bc4baSyz147064 next->lp_prev = prev; 209d62bc4baSyz147064 if (prev != NULL) 210d62bc4baSyz147064 prev->lp_next = next; 211d62bc4baSyz147064 else 212d62bc4baSyz147064 *headp = next; 2132b24ab6bSSebastien Roy } 214d62bc4baSyz147064 2152b24ab6bSSebastien Roy dlmgmt_linkattr_t * 2162b24ab6bSSebastien Roy linkattr_find(dlmgmt_linkattr_t *headp, const char *attr) 2172b24ab6bSSebastien Roy { 2182b24ab6bSSebastien Roy dlmgmt_linkattr_t *attrp; 2192b24ab6bSSebastien Roy 2202b24ab6bSSebastien Roy for (attrp = headp; attrp != NULL; attrp = attrp->lp_next) { 2212b24ab6bSSebastien Roy if (strcmp(attrp->lp_name, attr) == 0) 2222b24ab6bSSebastien Roy break; 2232b24ab6bSSebastien Roy } 2242b24ab6bSSebastien Roy return (attrp); 225d62bc4baSyz147064 } 226d62bc4baSyz147064 227d62bc4baSyz147064 int 228d62bc4baSyz147064 linkattr_set(dlmgmt_linkattr_t **headp, const char *attr, void *attrval, 229d62bc4baSyz147064 size_t attrsz, dladm_datatype_t type) 230d62bc4baSyz147064 { 231d62bc4baSyz147064 dlmgmt_linkattr_t *attrp; 2322b24ab6bSSebastien Roy void *newval; 2332b24ab6bSSebastien Roy boolean_t new; 234d62bc4baSyz147064 2352b24ab6bSSebastien Roy attrp = linkattr_find(*headp, attr); 236d62bc4baSyz147064 if (attrp != NULL) { 237d62bc4baSyz147064 /* 238d62bc4baSyz147064 * It is already set. If the value changed, update it. 239d62bc4baSyz147064 */ 240d62bc4baSyz147064 if (linkattr_equal(headp, attr, attrval, attrsz)) 241d62bc4baSyz147064 return (0); 2422b24ab6bSSebastien Roy new = B_FALSE; 243d62bc4baSyz147064 } else { 244d62bc4baSyz147064 /* 245d62bc4baSyz147064 * It is not set yet, allocate the linkattr and prepend to the 246d62bc4baSyz147064 * list. 247d62bc4baSyz147064 */ 248d62bc4baSyz147064 if ((attrp = calloc(1, sizeof (dlmgmt_linkattr_t))) == NULL) 249d62bc4baSyz147064 return (ENOMEM); 250d62bc4baSyz147064 251d62bc4baSyz147064 (void) strlcpy(attrp->lp_name, attr, MAXLINKATTRLEN); 2522b24ab6bSSebastien Roy new = B_TRUE; 253d62bc4baSyz147064 } 2542b24ab6bSSebastien Roy if ((newval = calloc(1, attrsz)) == NULL) { 2552b24ab6bSSebastien Roy if (new) 256d62bc4baSyz147064 free(attrp); 257d62bc4baSyz147064 return (ENOMEM); 258d62bc4baSyz147064 } 259d62bc4baSyz147064 2602b24ab6bSSebastien Roy if (!new) 2612b24ab6bSSebastien Roy free(attrp->lp_val); 2622b24ab6bSSebastien Roy attrp->lp_val = newval; 263d62bc4baSyz147064 bcopy(attrval, attrp->lp_val, attrsz); 264d62bc4baSyz147064 attrp->lp_sz = attrsz; 265d62bc4baSyz147064 attrp->lp_type = type; 26662ee1d25SArtem Kachitchkine attrp->lp_linkprop = dladm_attr_is_linkprop(attr); 2672b24ab6bSSebastien Roy if (new) 2682b24ab6bSSebastien Roy linkattr_add(headp, attrp); 269d62bc4baSyz147064 return (0); 270d62bc4baSyz147064 } 271d62bc4baSyz147064 2722b24ab6bSSebastien Roy void 273d62bc4baSyz147064 linkattr_unset(dlmgmt_linkattr_t **headp, const char *attr) 274d62bc4baSyz147064 { 2752b24ab6bSSebastien Roy dlmgmt_linkattr_t *attrp; 276d62bc4baSyz147064 27732715170SCathy Zhou if ((attrp = linkattr_find(*headp, attr)) != NULL) { 2782b24ab6bSSebastien Roy linkattr_rm(headp, attrp); 27932715170SCathy Zhou free(attrp->lp_val); 28032715170SCathy Zhou free(attrp); 28132715170SCathy Zhou } 282d62bc4baSyz147064 } 283d62bc4baSyz147064 284d62bc4baSyz147064 int 285d62bc4baSyz147064 linkattr_get(dlmgmt_linkattr_t **headp, const char *attr, void **attrvalp, 286d62bc4baSyz147064 size_t *attrszp, dladm_datatype_t *typep) 287d62bc4baSyz147064 { 2882b24ab6bSSebastien Roy dlmgmt_linkattr_t *attrp; 289d62bc4baSyz147064 2902b24ab6bSSebastien Roy if ((attrp = linkattr_find(*headp, attr)) == NULL) 291d62bc4baSyz147064 return (ENOENT); 292d62bc4baSyz147064 293d62bc4baSyz147064 *attrvalp = attrp->lp_val; 294d62bc4baSyz147064 *attrszp = attrp->lp_sz; 295d62bc4baSyz147064 if (typep != NULL) 296d62bc4baSyz147064 *typep = attrp->lp_type; 297d62bc4baSyz147064 return (0); 298d62bc4baSyz147064 } 299d62bc4baSyz147064 300d62bc4baSyz147064 boolean_t 301d62bc4baSyz147064 linkattr_equal(dlmgmt_linkattr_t **headp, const char *attr, void *attrval, 302d62bc4baSyz147064 size_t attrsz) 303d62bc4baSyz147064 { 304d62bc4baSyz147064 void *saved_attrval; 305d62bc4baSyz147064 size_t saved_attrsz; 306d62bc4baSyz147064 307d62bc4baSyz147064 if (linkattr_get(headp, attr, &saved_attrval, &saved_attrsz, NULL) != 0) 308d62bc4baSyz147064 return (B_FALSE); 309d62bc4baSyz147064 310d62bc4baSyz147064 return ((saved_attrsz == attrsz) && 311d62bc4baSyz147064 (memcmp(saved_attrval, attrval, attrsz) == 0)); 312d62bc4baSyz147064 } 313d62bc4baSyz147064 31432715170SCathy Zhou void 31532715170SCathy Zhou linkattr_destroy(dlmgmt_link_t *linkp) 31632715170SCathy Zhou { 31732715170SCathy Zhou dlmgmt_linkattr_t *next, *attrp; 31832715170SCathy Zhou 31932715170SCathy Zhou for (attrp = linkp->ll_head; attrp != NULL; attrp = next) { 32032715170SCathy Zhou next = attrp->lp_next; 32132715170SCathy Zhou free(attrp->lp_val); 32232715170SCathy Zhou free(attrp); 32332715170SCathy Zhou } 32432715170SCathy Zhou } 32532715170SCathy Zhou 326d62bc4baSyz147064 static int 327d62bc4baSyz147064 dlmgmt_table_readwritelock(boolean_t write) 328d62bc4baSyz147064 { 329d62bc4baSyz147064 if (write) 330d62bc4baSyz147064 return (pthread_rwlock_trywrlock(&dlmgmt_avl_lock)); 331d62bc4baSyz147064 else 332d62bc4baSyz147064 return (pthread_rwlock_tryrdlock(&dlmgmt_avl_lock)); 333d62bc4baSyz147064 } 334d62bc4baSyz147064 335d62bc4baSyz147064 void 336d62bc4baSyz147064 dlmgmt_table_lock(boolean_t write) 337d62bc4baSyz147064 { 338d62bc4baSyz147064 (void) pthread_mutex_lock(&dlmgmt_avl_mutex); 339d62bc4baSyz147064 while (dlmgmt_table_readwritelock(write) == EBUSY) 340d62bc4baSyz147064 (void) pthread_cond_wait(&dlmgmt_avl_cv, &dlmgmt_avl_mutex); 341d62bc4baSyz147064 342d62bc4baSyz147064 (void) pthread_mutex_unlock(&dlmgmt_avl_mutex); 343d62bc4baSyz147064 } 344d62bc4baSyz147064 345d62bc4baSyz147064 void 3462b24ab6bSSebastien Roy dlmgmt_table_unlock(void) 347d62bc4baSyz147064 { 348d62bc4baSyz147064 (void) pthread_rwlock_unlock(&dlmgmt_avl_lock); 349d62bc4baSyz147064 (void) pthread_mutex_lock(&dlmgmt_avl_mutex); 350d62bc4baSyz147064 (void) pthread_cond_broadcast(&dlmgmt_avl_cv); 351d62bc4baSyz147064 (void) pthread_mutex_unlock(&dlmgmt_avl_mutex); 352d62bc4baSyz147064 } 353d62bc4baSyz147064 354d62bc4baSyz147064 void 355d62bc4baSyz147064 link_destroy(dlmgmt_link_t *linkp) 356d62bc4baSyz147064 { 35732715170SCathy Zhou linkattr_destroy(linkp); 358d62bc4baSyz147064 free(linkp); 359d62bc4baSyz147064 } 360d62bc4baSyz147064 3612b24ab6bSSebastien Roy /* 3622b24ab6bSSebastien Roy * Set the DLMGMT_ACTIVE flag on the link to note that it is active. When a 3632b24ab6bSSebastien Roy * link becomes active and it belongs to a non-global zone, it is also added 3642b24ab6bSSebastien Roy * to that zone. 3652b24ab6bSSebastien Roy */ 3662b24ab6bSSebastien Roy int 3672b24ab6bSSebastien Roy link_activate(dlmgmt_link_t *linkp) 368d62bc4baSyz147064 { 3692b24ab6bSSebastien Roy int err = 0; 370*f689bed1SRishi Srivatsavai zoneid_t zoneid = ALL_ZONES; 371d62bc4baSyz147064 3722b24ab6bSSebastien Roy if (zone_check_datalink(&zoneid, linkp->ll_linkid) == 0) { 3732b24ab6bSSebastien Roy /* 3742b24ab6bSSebastien Roy * This link was already added to a non-global zone. This can 3752b24ab6bSSebastien Roy * happen if dlmgmtd is restarted. 3762b24ab6bSSebastien Roy */ 3772b24ab6bSSebastien Roy if (zoneid != linkp->ll_zoneid) { 3782b24ab6bSSebastien Roy if (link_by_name(linkp->ll_link, zoneid) != NULL) { 3792b24ab6bSSebastien Roy err = EEXIST; 3802b24ab6bSSebastien Roy goto done; 3812b24ab6bSSebastien Roy } 382*f689bed1SRishi Srivatsavai 383*f689bed1SRishi Srivatsavai if (avl_find(&dlmgmt_name_avl, linkp, NULL) != NULL) 3842b24ab6bSSebastien Roy avl_remove(&dlmgmt_name_avl, linkp); 385*f689bed1SRishi Srivatsavai 3862b24ab6bSSebastien Roy linkp->ll_zoneid = zoneid; 3872b24ab6bSSebastien Roy avl_add(&dlmgmt_name_avl, linkp); 3882b24ab6bSSebastien Roy avl_add(&dlmgmt_loan_avl, linkp); 3892b24ab6bSSebastien Roy linkp->ll_onloan = B_TRUE; 3902b24ab6bSSebastien Roy } 3912b24ab6bSSebastien Roy } else if (linkp->ll_zoneid != GLOBAL_ZONEID) { 3922b24ab6bSSebastien Roy err = zone_add_datalink(linkp->ll_zoneid, linkp->ll_linkid); 3932b24ab6bSSebastien Roy } 3942b24ab6bSSebastien Roy done: 3952b24ab6bSSebastien Roy if (err == 0) 3962b24ab6bSSebastien Roy linkp->ll_flags |= DLMGMT_ACTIVE; 3972b24ab6bSSebastien Roy return (err); 3982b24ab6bSSebastien Roy } 3992b24ab6bSSebastien Roy 4002b24ab6bSSebastien Roy /* 4012b24ab6bSSebastien Roy * Is linkp visible from the caller's zoneid? It is if the link is in the 4022b24ab6bSSebastien Roy * same zone as the caller, or if the caller is in the global zone and the 4032b24ab6bSSebastien Roy * link is on loan to a non-global zone. 4042b24ab6bSSebastien Roy */ 4052b24ab6bSSebastien Roy boolean_t 4062b24ab6bSSebastien Roy link_is_visible(dlmgmt_link_t *linkp, zoneid_t zoneid) 4072b24ab6bSSebastien Roy { 4082b24ab6bSSebastien Roy return (linkp->ll_zoneid == zoneid || 4092b24ab6bSSebastien Roy (zoneid == GLOBAL_ZONEID && linkp->ll_onloan)); 410d62bc4baSyz147064 } 411d62bc4baSyz147064 412d62bc4baSyz147064 dlmgmt_link_t * 4132b24ab6bSSebastien Roy link_by_id(datalink_id_t linkid, zoneid_t zoneid) 414d62bc4baSyz147064 { 4152b24ab6bSSebastien Roy dlmgmt_link_t link, *linkp; 4162b24ab6bSSebastien Roy 4172b24ab6bSSebastien Roy link.ll_linkid = linkid; 4182b24ab6bSSebastien Roy linkp = avl_find(&dlmgmt_id_avl, &link, NULL); 4192b24ab6bSSebastien Roy if (zoneid != GLOBAL_ZONEID && linkp->ll_zoneid != zoneid) 4202b24ab6bSSebastien Roy linkp = NULL; 4212b24ab6bSSebastien Roy return (linkp); 4222b24ab6bSSebastien Roy } 4232b24ab6bSSebastien Roy 4242b24ab6bSSebastien Roy dlmgmt_link_t * 4252b24ab6bSSebastien Roy link_by_name(const char *name, zoneid_t zoneid) 4262b24ab6bSSebastien Roy { 4272b24ab6bSSebastien Roy dlmgmt_link_t link, *linkp; 428d62bc4baSyz147064 429d62bc4baSyz147064 (void) strlcpy(link.ll_link, name, MAXLINKNAMELEN); 4302b24ab6bSSebastien Roy link.ll_zoneid = zoneid; 4312b24ab6bSSebastien Roy linkp = avl_find(&dlmgmt_name_avl, &link, NULL); 4322b24ab6bSSebastien Roy if (linkp == NULL && zoneid == GLOBAL_ZONEID) { 4332b24ab6bSSebastien Roy /* The link could be on loan to a non-global zone? */ 4342b24ab6bSSebastien Roy linkp = avl_find(&dlmgmt_loan_avl, &link, NULL); 4352b24ab6bSSebastien Roy } 4362b24ab6bSSebastien Roy return (linkp); 437d62bc4baSyz147064 } 438d62bc4baSyz147064 439d62bc4baSyz147064 int 440d62bc4baSyz147064 dlmgmt_create_common(const char *name, datalink_class_t class, uint32_t media, 4412b24ab6bSSebastien Roy zoneid_t zoneid, uint32_t flags, dlmgmt_link_t **linkpp) 442d62bc4baSyz147064 { 4432b24ab6bSSebastien Roy dlmgmt_link_t *linkp = NULL; 444d62bc4baSyz147064 avl_index_t name_where, id_where; 4452b24ab6bSSebastien Roy int err = 0; 446d62bc4baSyz147064 447d62bc4baSyz147064 if (!dladm_valid_linkname(name)) 448d62bc4baSyz147064 return (EINVAL); 4492b24ab6bSSebastien Roy if (dlmgmt_nextlinkid == DATALINK_INVALID_LINKID) 4502b24ab6bSSebastien Roy return (ENOSPC); 451d62bc4baSyz147064 4522b24ab6bSSebastien Roy if ((linkp = calloc(1, sizeof (dlmgmt_link_t))) == NULL) { 4532b24ab6bSSebastien Roy err = ENOMEM; 4542b24ab6bSSebastien Roy goto done; 4552b24ab6bSSebastien Roy } 456d62bc4baSyz147064 4572b24ab6bSSebastien Roy (void) strlcpy(linkp->ll_link, name, MAXLINKNAMELEN); 4582b24ab6bSSebastien Roy linkp->ll_class = class; 4592b24ab6bSSebastien Roy linkp->ll_media = media; 4602b24ab6bSSebastien Roy linkp->ll_linkid = dlmgmt_nextlinkid; 4612b24ab6bSSebastien Roy linkp->ll_zoneid = zoneid; 4622b24ab6bSSebastien Roy linkp->ll_gen = 0; 463d62bc4baSyz147064 4642b24ab6bSSebastien Roy if (avl_find(&dlmgmt_name_avl, linkp, &name_where) != NULL || 4652b24ab6bSSebastien Roy avl_find(&dlmgmt_id_avl, linkp, &id_where) != NULL) { 4662b24ab6bSSebastien Roy err = EEXIST; 4672b24ab6bSSebastien Roy goto done; 4682b24ab6bSSebastien Roy } 4692b24ab6bSSebastien Roy 470d62bc4baSyz147064 avl_insert(&dlmgmt_name_avl, linkp, name_where); 471d62bc4baSyz147064 avl_insert(&dlmgmt_id_avl, linkp, id_where); 4722b24ab6bSSebastien Roy 4732b24ab6bSSebastien Roy if ((flags & DLMGMT_ACTIVE) && (err = link_activate(linkp)) != 0) { 4742b24ab6bSSebastien Roy avl_remove(&dlmgmt_name_avl, linkp); 4752b24ab6bSSebastien Roy avl_remove(&dlmgmt_id_avl, linkp); 4762b24ab6bSSebastien Roy goto done; 4772b24ab6bSSebastien Roy } 4782b24ab6bSSebastien Roy 4792b24ab6bSSebastien Roy linkp->ll_flags = flags; 480d62bc4baSyz147064 dlmgmt_advance(linkp); 481d62bc4baSyz147064 *linkpp = linkp; 4822b24ab6bSSebastien Roy 4832b24ab6bSSebastien Roy done: 4842b24ab6bSSebastien Roy if (err != 0) 4852b24ab6bSSebastien Roy free(linkp); 4862b24ab6bSSebastien Roy return (err); 487d62bc4baSyz147064 } 488d62bc4baSyz147064 489d62bc4baSyz147064 int 490d62bc4baSyz147064 dlmgmt_destroy_common(dlmgmt_link_t *linkp, uint32_t flags) 491d62bc4baSyz147064 { 492d62bc4baSyz147064 if ((linkp->ll_flags & flags) == 0) { 493d62bc4baSyz147064 /* 494d62bc4baSyz147064 * The link does not exist in the specified space. 495d62bc4baSyz147064 */ 496d62bc4baSyz147064 return (ENOENT); 497d62bc4baSyz147064 } 4982b24ab6bSSebastien Roy 499d62bc4baSyz147064 linkp->ll_flags &= ~flags; 5002b24ab6bSSebastien Roy if (flags & DLMGMT_PERSIST) { 501d62bc4baSyz147064 dlmgmt_linkattr_t *next, *attrp; 502d62bc4baSyz147064 503d62bc4baSyz147064 for (attrp = linkp->ll_head; attrp != NULL; attrp = next) { 504d62bc4baSyz147064 next = attrp->lp_next; 505d62bc4baSyz147064 free(attrp->lp_val); 506d62bc4baSyz147064 free(attrp); 507d62bc4baSyz147064 } 508d62bc4baSyz147064 linkp->ll_head = NULL; 509d62bc4baSyz147064 } 510d62bc4baSyz147064 5112b24ab6bSSebastien Roy if ((flags & DLMGMT_ACTIVE) && linkp->ll_zoneid != GLOBAL_ZONEID) { 5122b24ab6bSSebastien Roy (void) zone_remove_datalink(linkp->ll_zoneid, linkp->ll_linkid); 5132b24ab6bSSebastien Roy if (linkp->ll_onloan) 5142b24ab6bSSebastien Roy avl_remove(&dlmgmt_loan_avl, linkp); 5152b24ab6bSSebastien Roy } 5162b24ab6bSSebastien Roy 517d62bc4baSyz147064 if (linkp->ll_flags == 0) { 518d62bc4baSyz147064 avl_remove(&dlmgmt_id_avl, linkp); 519d62bc4baSyz147064 avl_remove(&dlmgmt_name_avl, linkp); 520d62bc4baSyz147064 link_destroy(linkp); 521d62bc4baSyz147064 } 522d62bc4baSyz147064 523d62bc4baSyz147064 return (0); 524d62bc4baSyz147064 } 525d62bc4baSyz147064 5262b24ab6bSSebastien Roy int 527d62bc4baSyz147064 dlmgmt_getattr_common(dlmgmt_linkattr_t **headp, const char *attr, 528024b0a25Sseb dlmgmt_getattr_retval_t *retvalp) 529d62bc4baSyz147064 { 530d62bc4baSyz147064 int err; 531d62bc4baSyz147064 void *attrval; 532d62bc4baSyz147064 size_t attrsz; 533d62bc4baSyz147064 dladm_datatype_t attrtype; 534d62bc4baSyz147064 535d62bc4baSyz147064 err = linkattr_get(headp, attr, &attrval, &attrsz, &attrtype); 536d62bc4baSyz147064 if (err != 0) 5372b24ab6bSSebastien Roy return (err); 538d62bc4baSyz147064 539d62bc4baSyz147064 assert(attrsz > 0); 5402b24ab6bSSebastien Roy if (attrsz > MAXLINKATTRVALLEN) 5412b24ab6bSSebastien Roy return (EINVAL); 542d62bc4baSyz147064 543d62bc4baSyz147064 retvalp->lr_type = attrtype; 544024b0a25Sseb retvalp->lr_attrsz = attrsz; 545024b0a25Sseb bcopy(attrval, retvalp->lr_attrval, attrsz); 5462b24ab6bSSebastien Roy return (0); 547d62bc4baSyz147064 } 548d62bc4baSyz147064 549d62bc4baSyz147064 void 550d62bc4baSyz147064 dlmgmt_dlconf_table_lock(boolean_t write) 551d62bc4baSyz147064 { 552d62bc4baSyz147064 if (write) 553d62bc4baSyz147064 (void) pthread_rwlock_wrlock(&dlmgmt_dlconf_lock); 554d62bc4baSyz147064 else 555d62bc4baSyz147064 (void) pthread_rwlock_rdlock(&dlmgmt_dlconf_lock); 556d62bc4baSyz147064 } 557d62bc4baSyz147064 558d62bc4baSyz147064 void 5592b24ab6bSSebastien Roy dlmgmt_dlconf_table_unlock(void) 560d62bc4baSyz147064 { 561d62bc4baSyz147064 (void) pthread_rwlock_unlock(&dlmgmt_dlconf_lock); 562d62bc4baSyz147064 } 563d62bc4baSyz147064 564d62bc4baSyz147064 int 565d62bc4baSyz147064 dlconf_create(const char *name, datalink_id_t linkid, datalink_class_t class, 5662b24ab6bSSebastien Roy uint32_t media, zoneid_t zoneid, dlmgmt_dlconf_t **dlconfpp) 567d62bc4baSyz147064 { 568d62bc4baSyz147064 dlmgmt_dlconf_t *dlconfp = NULL; 569d62bc4baSyz147064 int err = 0; 570d62bc4baSyz147064 571d62bc4baSyz147064 if (dlmgmt_nextconfid == 0) { 572d62bc4baSyz147064 err = ENOSPC; 573d62bc4baSyz147064 goto done; 574d62bc4baSyz147064 } 575d62bc4baSyz147064 576d62bc4baSyz147064 if ((dlconfp = calloc(1, sizeof (dlmgmt_dlconf_t))) == NULL) { 577d62bc4baSyz147064 err = ENOMEM; 578d62bc4baSyz147064 goto done; 579d62bc4baSyz147064 } 580d62bc4baSyz147064 581d62bc4baSyz147064 (void) strlcpy(dlconfp->ld_link, name, MAXLINKNAMELEN); 582d62bc4baSyz147064 dlconfp->ld_linkid = linkid; 583d62bc4baSyz147064 dlconfp->ld_class = class; 584d62bc4baSyz147064 dlconfp->ld_media = media; 585d62bc4baSyz147064 dlconfp->ld_id = dlmgmt_nextconfid; 5862b24ab6bSSebastien Roy dlconfp->ld_zoneid = zoneid; 587d62bc4baSyz147064 588d62bc4baSyz147064 done: 589d62bc4baSyz147064 *dlconfpp = dlconfp; 590d62bc4baSyz147064 return (err); 591d62bc4baSyz147064 } 592d62bc4baSyz147064 593d62bc4baSyz147064 void 594d62bc4baSyz147064 dlconf_destroy(dlmgmt_dlconf_t *dlconfp) 595d62bc4baSyz147064 { 596d62bc4baSyz147064 dlmgmt_linkattr_t *next, *attrp; 597d62bc4baSyz147064 598d62bc4baSyz147064 for (attrp = dlconfp->ld_head; attrp != NULL; attrp = next) { 599d62bc4baSyz147064 next = attrp->lp_next; 600d62bc4baSyz147064 free(attrp->lp_val); 601d62bc4baSyz147064 free(attrp); 602d62bc4baSyz147064 } 603d62bc4baSyz147064 free(dlconfp); 604d62bc4baSyz147064 } 605d62bc4baSyz147064 606d62bc4baSyz147064 int 6072b24ab6bSSebastien Roy dlmgmt_generate_name(const char *prefix, char *name, size_t size, 6082b24ab6bSSebastien Roy zoneid_t zoneid) 609d62bc4baSyz147064 { 610d62bc4baSyz147064 dlmgmt_prefix_t *lpp, *prev = NULL; 6112b24ab6bSSebastien Roy dlmgmt_link_t link, *linkp; 612d62bc4baSyz147064 613d62bc4baSyz147064 /* 614d62bc4baSyz147064 * See whether the requested prefix is already in the list. 615d62bc4baSyz147064 */ 6162b24ab6bSSebastien Roy for (lpp = &dlmgmt_prefixlist; lpp != NULL; 6172b24ab6bSSebastien Roy prev = lpp, lpp = lpp->lp_next) { 6182b24ab6bSSebastien Roy if (lpp->lp_zoneid == zoneid && 6192b24ab6bSSebastien Roy strcmp(prefix, lpp->lp_prefix) == 0) 620d62bc4baSyz147064 break; 621d62bc4baSyz147064 } 622d62bc4baSyz147064 623d62bc4baSyz147064 /* 624d62bc4baSyz147064 * Not found. 625d62bc4baSyz147064 */ 626d62bc4baSyz147064 if (lpp == NULL) { 627d62bc4baSyz147064 assert(prev != NULL); 628d62bc4baSyz147064 629d62bc4baSyz147064 /* 630d62bc4baSyz147064 * First add this new prefix into the prefix list. 631d62bc4baSyz147064 */ 632d62bc4baSyz147064 if ((lpp = malloc(sizeof (dlmgmt_prefix_t))) == NULL) 633d62bc4baSyz147064 return (ENOMEM); 634d62bc4baSyz147064 635d62bc4baSyz147064 prev->lp_next = lpp; 636d62bc4baSyz147064 lpp->lp_next = NULL; 6372b24ab6bSSebastien Roy lpp->lp_zoneid = zoneid; 638d62bc4baSyz147064 lpp->lp_nextppa = 0; 639d62bc4baSyz147064 (void) strlcpy(lpp->lp_prefix, prefix, MAXLINKNAMELEN); 640d62bc4baSyz147064 641d62bc4baSyz147064 /* 642d62bc4baSyz147064 * Now determine this prefix's nextppa. 643d62bc4baSyz147064 */ 644d62bc4baSyz147064 (void) snprintf(link.ll_link, MAXLINKNAMELEN, "%s%d", 6452b24ab6bSSebastien Roy prefix, 0); 6462b24ab6bSSebastien Roy link.ll_zoneid = zoneid; 6472b24ab6bSSebastien Roy if ((linkp = avl_find(&dlmgmt_name_avl, &link, NULL)) != NULL) 648d62bc4baSyz147064 dlmgmt_advance_ppa(linkp); 649d62bc4baSyz147064 } 650d62bc4baSyz147064 651d62bc4baSyz147064 if (lpp->lp_nextppa == (uint_t)-1) 652d62bc4baSyz147064 return (ENOSPC); 653d62bc4baSyz147064 654d62bc4baSyz147064 (void) snprintf(name, size, "%s%d", prefix, lpp->lp_nextppa); 655d62bc4baSyz147064 return (0); 656d62bc4baSyz147064 } 657d62bc4baSyz147064 658d62bc4baSyz147064 /* 659d62bc4baSyz147064 * Advance the next available ppa value if the name prefix of the current 660d62bc4baSyz147064 * link is in the prefix list. 661d62bc4baSyz147064 */ 662d62bc4baSyz147064 static void 663d62bc4baSyz147064 dlmgmt_advance_ppa(dlmgmt_link_t *linkp) 664d62bc4baSyz147064 { 665d62bc4baSyz147064 dlmgmt_prefix_t *lpp; 666d62bc4baSyz147064 char prefix[MAXLINKNAMELEN]; 6672b24ab6bSSebastien Roy char linkname[MAXLINKNAMELEN]; 668d62bc4baSyz147064 uint_t start, ppa; 669d62bc4baSyz147064 670d62bc4baSyz147064 (void) dlpi_parselink(linkp->ll_link, prefix, &ppa); 671d62bc4baSyz147064 672d62bc4baSyz147064 /* 673d62bc4baSyz147064 * See whether the requested prefix is already in the list. 674d62bc4baSyz147064 */ 6752b24ab6bSSebastien Roy for (lpp = &dlmgmt_prefixlist; lpp != NULL; lpp = lpp->lp_next) { 6762b24ab6bSSebastien Roy if (lpp->lp_zoneid == linkp->ll_zoneid && 6772b24ab6bSSebastien Roy strcmp(prefix, lpp->lp_prefix) == 0) 678d62bc4baSyz147064 break; 679d62bc4baSyz147064 } 680d62bc4baSyz147064 681d62bc4baSyz147064 /* 682d62bc4baSyz147064 * If the link name prefix is in the list, advance the 683d62bc4baSyz147064 * next available ppa for the <prefix>N name. 684d62bc4baSyz147064 */ 685d62bc4baSyz147064 if (lpp == NULL || lpp->lp_nextppa != ppa) 686d62bc4baSyz147064 return; 687d62bc4baSyz147064 688d62bc4baSyz147064 start = lpp->lp_nextppa++; 689d62bc4baSyz147064 linkp = AVL_NEXT(&dlmgmt_name_avl, linkp); 690d62bc4baSyz147064 while (lpp->lp_nextppa != start) { 691d62bc4baSyz147064 if (lpp->lp_nextppa == (uint_t)-1) { 692d62bc4baSyz147064 /* 693d62bc4baSyz147064 * wrapped around. search from <prefix>1. 694d62bc4baSyz147064 */ 695d62bc4baSyz147064 lpp->lp_nextppa = 0; 6962b24ab6bSSebastien Roy (void) snprintf(linkname, MAXLINKNAMELEN, 697d62bc4baSyz147064 "%s%d", lpp->lp_prefix, lpp->lp_nextppa); 6982b24ab6bSSebastien Roy linkp = link_by_name(linkname, lpp->lp_zoneid); 699d62bc4baSyz147064 if (linkp == NULL) 700d62bc4baSyz147064 return; 701d62bc4baSyz147064 } else { 702d62bc4baSyz147064 if (linkp == NULL) 703d62bc4baSyz147064 return; 704d62bc4baSyz147064 (void) dlpi_parselink(linkp->ll_link, prefix, &ppa); 705d62bc4baSyz147064 if ((strcmp(prefix, lpp->lp_prefix) != 0) || 706d62bc4baSyz147064 (ppa != lpp->lp_nextppa)) { 707d62bc4baSyz147064 return; 708d62bc4baSyz147064 } 709d62bc4baSyz147064 } 710d62bc4baSyz147064 linkp = AVL_NEXT(&dlmgmt_name_avl, linkp); 711d62bc4baSyz147064 lpp->lp_nextppa++; 712d62bc4baSyz147064 } 713d62bc4baSyz147064 lpp->lp_nextppa = (uint_t)-1; 714d62bc4baSyz147064 } 715d62bc4baSyz147064 716d62bc4baSyz147064 /* 717d62bc4baSyz147064 * Advance to the next available linkid value. 718d62bc4baSyz147064 */ 719d62bc4baSyz147064 static void 720d62bc4baSyz147064 dlmgmt_advance_linkid(dlmgmt_link_t *linkp) 721d62bc4baSyz147064 { 722d62bc4baSyz147064 datalink_id_t start; 723d62bc4baSyz147064 724d62bc4baSyz147064 if (linkp->ll_linkid != dlmgmt_nextlinkid) 725d62bc4baSyz147064 return; 726d62bc4baSyz147064 727d62bc4baSyz147064 start = dlmgmt_nextlinkid; 728d62bc4baSyz147064 linkp = AVL_NEXT(&dlmgmt_id_avl, linkp); 729d62bc4baSyz147064 730d62bc4baSyz147064 do { 731d62bc4baSyz147064 if (dlmgmt_nextlinkid == DATALINK_MAX_LINKID) { 732d62bc4baSyz147064 /* 733d62bc4baSyz147064 * wrapped around. search from 1. 734d62bc4baSyz147064 */ 735d62bc4baSyz147064 dlmgmt_nextlinkid = 1; 7362b24ab6bSSebastien Roy if ((linkp = link_by_id(1, GLOBAL_ZONEID)) == NULL) 737d62bc4baSyz147064 return; 738d62bc4baSyz147064 } else { 739d62bc4baSyz147064 dlmgmt_nextlinkid++; 740d62bc4baSyz147064 if (linkp == NULL) 741d62bc4baSyz147064 return; 742d62bc4baSyz147064 if (linkp->ll_linkid != dlmgmt_nextlinkid) 743d62bc4baSyz147064 return; 744d62bc4baSyz147064 } 745d62bc4baSyz147064 746d62bc4baSyz147064 linkp = AVL_NEXT(&dlmgmt_id_avl, linkp); 747d62bc4baSyz147064 } while (dlmgmt_nextlinkid != start); 748d62bc4baSyz147064 749d62bc4baSyz147064 dlmgmt_nextlinkid = DATALINK_INVALID_LINKID; 750d62bc4baSyz147064 } 751d62bc4baSyz147064 752d62bc4baSyz147064 /* 753d62bc4baSyz147064 * Advance various global values, for example, next linkid value, next ppa for 754d62bc4baSyz147064 * various prefix etc. 755d62bc4baSyz147064 */ 756d62bc4baSyz147064 void 757d62bc4baSyz147064 dlmgmt_advance(dlmgmt_link_t *linkp) 758d62bc4baSyz147064 { 759d62bc4baSyz147064 dlmgmt_advance_linkid(linkp); 760d62bc4baSyz147064 dlmgmt_advance_ppa(linkp); 761d62bc4baSyz147064 } 762d62bc4baSyz147064 763d62bc4baSyz147064 /* 764d62bc4baSyz147064 * Advance to the next available dlconf id. 765d62bc4baSyz147064 */ 766d62bc4baSyz147064 void 767d62bc4baSyz147064 dlmgmt_advance_dlconfid(dlmgmt_dlconf_t *dlconfp) 768d62bc4baSyz147064 { 769d62bc4baSyz147064 uint_t start; 770d62bc4baSyz147064 771d62bc4baSyz147064 start = dlmgmt_nextconfid++; 772d62bc4baSyz147064 dlconfp = AVL_NEXT(&dlmgmt_dlconf_avl, dlconfp); 773d62bc4baSyz147064 while (dlmgmt_nextconfid != start) { 774d62bc4baSyz147064 if (dlmgmt_nextconfid == 0) { 775d62bc4baSyz147064 dlmgmt_dlconf_t dlconf; 776d62bc4baSyz147064 777d62bc4baSyz147064 /* 778d62bc4baSyz147064 * wrapped around. search from 1. 779d62bc4baSyz147064 */ 780d62bc4baSyz147064 dlconf.ld_id = dlmgmt_nextconfid = 1; 781a73e6fc1SCathy Zhou dlconfp = avl_find(&dlmgmt_dlconf_avl, &dlconf, NULL); 782d62bc4baSyz147064 if (dlconfp == NULL) 783d62bc4baSyz147064 return; 784d62bc4baSyz147064 } else { 785d62bc4baSyz147064 if ((dlconfp == NULL) || 786d62bc4baSyz147064 (dlconfp->ld_id != dlmgmt_nextconfid)) { 787d62bc4baSyz147064 return; 788d62bc4baSyz147064 } 789d62bc4baSyz147064 } 790a73e6fc1SCathy Zhou dlconfp = AVL_NEXT(&dlmgmt_dlconf_avl, dlconfp); 791d62bc4baSyz147064 dlmgmt_nextconfid++; 792d62bc4baSyz147064 } 793d62bc4baSyz147064 dlmgmt_nextconfid = 0; 794d62bc4baSyz147064 } 795