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; 370f689bed1SRishi 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 } 382f689bed1SRishi Srivatsavai 383f689bed1SRishi Srivatsavai if (avl_find(&dlmgmt_name_avl, linkp, NULL) != NULL) 3842b24ab6bSSebastien Roy avl_remove(&dlmgmt_name_avl, linkp); 385f689bed1SRishi 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; 418*c6d054cbSJoshua M. Clulow if ((linkp = avl_find(&dlmgmt_id_avl, &link, NULL)) == NULL) 419*c6d054cbSJoshua M. Clulow return (NULL); 4202b24ab6bSSebastien Roy if (zoneid != GLOBAL_ZONEID && linkp->ll_zoneid != zoneid) 421*c6d054cbSJoshua M. Clulow return (NULL); 4222b24ab6bSSebastien Roy return (linkp); 4232b24ab6bSSebastien Roy } 4242b24ab6bSSebastien Roy 4252b24ab6bSSebastien Roy dlmgmt_link_t * 4262b24ab6bSSebastien Roy link_by_name(const char *name, zoneid_t zoneid) 4272b24ab6bSSebastien Roy { 4282b24ab6bSSebastien Roy dlmgmt_link_t link, *linkp; 429d62bc4baSyz147064 430d62bc4baSyz147064 (void) strlcpy(link.ll_link, name, MAXLINKNAMELEN); 4312b24ab6bSSebastien Roy link.ll_zoneid = zoneid; 4322b24ab6bSSebastien Roy linkp = avl_find(&dlmgmt_name_avl, &link, NULL); 4332b24ab6bSSebastien Roy if (linkp == NULL && zoneid == GLOBAL_ZONEID) { 4342b24ab6bSSebastien Roy /* The link could be on loan to a non-global zone? */ 4352b24ab6bSSebastien Roy linkp = avl_find(&dlmgmt_loan_avl, &link, NULL); 4362b24ab6bSSebastien Roy } 4372b24ab6bSSebastien Roy return (linkp); 438d62bc4baSyz147064 } 439d62bc4baSyz147064 440d62bc4baSyz147064 int 441d62bc4baSyz147064 dlmgmt_create_common(const char *name, datalink_class_t class, uint32_t media, 4422b24ab6bSSebastien Roy zoneid_t zoneid, uint32_t flags, dlmgmt_link_t **linkpp) 443d62bc4baSyz147064 { 4442b24ab6bSSebastien Roy dlmgmt_link_t *linkp = NULL; 445d62bc4baSyz147064 avl_index_t name_where, id_where; 4462b24ab6bSSebastien Roy int err = 0; 447d62bc4baSyz147064 448d62bc4baSyz147064 if (!dladm_valid_linkname(name)) 449d62bc4baSyz147064 return (EINVAL); 4502b24ab6bSSebastien Roy if (dlmgmt_nextlinkid == DATALINK_INVALID_LINKID) 4512b24ab6bSSebastien Roy return (ENOSPC); 452d62bc4baSyz147064 4532b24ab6bSSebastien Roy if ((linkp = calloc(1, sizeof (dlmgmt_link_t))) == NULL) { 4542b24ab6bSSebastien Roy err = ENOMEM; 4552b24ab6bSSebastien Roy goto done; 4562b24ab6bSSebastien Roy } 457d62bc4baSyz147064 4582b24ab6bSSebastien Roy (void) strlcpy(linkp->ll_link, name, MAXLINKNAMELEN); 4592b24ab6bSSebastien Roy linkp->ll_class = class; 4602b24ab6bSSebastien Roy linkp->ll_media = media; 4612b24ab6bSSebastien Roy linkp->ll_linkid = dlmgmt_nextlinkid; 4622b24ab6bSSebastien Roy linkp->ll_zoneid = zoneid; 4632b24ab6bSSebastien Roy linkp->ll_gen = 0; 464d62bc4baSyz147064 4652b24ab6bSSebastien Roy if (avl_find(&dlmgmt_name_avl, linkp, &name_where) != NULL || 4662b24ab6bSSebastien Roy avl_find(&dlmgmt_id_avl, linkp, &id_where) != NULL) { 4672b24ab6bSSebastien Roy err = EEXIST; 4682b24ab6bSSebastien Roy goto done; 4692b24ab6bSSebastien Roy } 4702b24ab6bSSebastien Roy 471d62bc4baSyz147064 avl_insert(&dlmgmt_name_avl, linkp, name_where); 472d62bc4baSyz147064 avl_insert(&dlmgmt_id_avl, linkp, id_where); 4732b24ab6bSSebastien Roy 4742b24ab6bSSebastien Roy if ((flags & DLMGMT_ACTIVE) && (err = link_activate(linkp)) != 0) { 4752b24ab6bSSebastien Roy avl_remove(&dlmgmt_name_avl, linkp); 4762b24ab6bSSebastien Roy avl_remove(&dlmgmt_id_avl, linkp); 4772b24ab6bSSebastien Roy goto done; 4782b24ab6bSSebastien Roy } 4792b24ab6bSSebastien Roy 4802b24ab6bSSebastien Roy linkp->ll_flags = flags; 481d62bc4baSyz147064 dlmgmt_advance(linkp); 482d62bc4baSyz147064 *linkpp = linkp; 4832b24ab6bSSebastien Roy 4842b24ab6bSSebastien Roy done: 4852b24ab6bSSebastien Roy if (err != 0) 4862b24ab6bSSebastien Roy free(linkp); 4872b24ab6bSSebastien Roy return (err); 488d62bc4baSyz147064 } 489d62bc4baSyz147064 490d62bc4baSyz147064 int 491d62bc4baSyz147064 dlmgmt_destroy_common(dlmgmt_link_t *linkp, uint32_t flags) 492d62bc4baSyz147064 { 493d62bc4baSyz147064 if ((linkp->ll_flags & flags) == 0) { 494d62bc4baSyz147064 /* 495d62bc4baSyz147064 * The link does not exist in the specified space. 496d62bc4baSyz147064 */ 497d62bc4baSyz147064 return (ENOENT); 498d62bc4baSyz147064 } 4992b24ab6bSSebastien Roy 500d62bc4baSyz147064 linkp->ll_flags &= ~flags; 5012b24ab6bSSebastien Roy if (flags & DLMGMT_PERSIST) { 502d62bc4baSyz147064 dlmgmt_linkattr_t *next, *attrp; 503d62bc4baSyz147064 504d62bc4baSyz147064 for (attrp = linkp->ll_head; attrp != NULL; attrp = next) { 505d62bc4baSyz147064 next = attrp->lp_next; 506d62bc4baSyz147064 free(attrp->lp_val); 507d62bc4baSyz147064 free(attrp); 508d62bc4baSyz147064 } 509d62bc4baSyz147064 linkp->ll_head = NULL; 510d62bc4baSyz147064 } 511d62bc4baSyz147064 5122b24ab6bSSebastien Roy if ((flags & DLMGMT_ACTIVE) && linkp->ll_zoneid != GLOBAL_ZONEID) { 5132b24ab6bSSebastien Roy (void) zone_remove_datalink(linkp->ll_zoneid, linkp->ll_linkid); 5142b24ab6bSSebastien Roy if (linkp->ll_onloan) 5152b24ab6bSSebastien Roy avl_remove(&dlmgmt_loan_avl, linkp); 5162b24ab6bSSebastien Roy } 5172b24ab6bSSebastien Roy 518d62bc4baSyz147064 if (linkp->ll_flags == 0) { 519d62bc4baSyz147064 avl_remove(&dlmgmt_id_avl, linkp); 520d62bc4baSyz147064 avl_remove(&dlmgmt_name_avl, linkp); 521d62bc4baSyz147064 link_destroy(linkp); 522d62bc4baSyz147064 } 523d62bc4baSyz147064 524d62bc4baSyz147064 return (0); 525d62bc4baSyz147064 } 526d62bc4baSyz147064 5272b24ab6bSSebastien Roy int 528d62bc4baSyz147064 dlmgmt_getattr_common(dlmgmt_linkattr_t **headp, const char *attr, 529024b0a25Sseb dlmgmt_getattr_retval_t *retvalp) 530d62bc4baSyz147064 { 531d62bc4baSyz147064 int err; 532d62bc4baSyz147064 void *attrval; 533d62bc4baSyz147064 size_t attrsz; 534d62bc4baSyz147064 dladm_datatype_t attrtype; 535d62bc4baSyz147064 536d62bc4baSyz147064 err = linkattr_get(headp, attr, &attrval, &attrsz, &attrtype); 537d62bc4baSyz147064 if (err != 0) 5382b24ab6bSSebastien Roy return (err); 539d62bc4baSyz147064 540d62bc4baSyz147064 assert(attrsz > 0); 5412b24ab6bSSebastien Roy if (attrsz > MAXLINKATTRVALLEN) 5422b24ab6bSSebastien Roy return (EINVAL); 543d62bc4baSyz147064 544d62bc4baSyz147064 retvalp->lr_type = attrtype; 545024b0a25Sseb retvalp->lr_attrsz = attrsz; 546024b0a25Sseb bcopy(attrval, retvalp->lr_attrval, attrsz); 5472b24ab6bSSebastien Roy return (0); 548d62bc4baSyz147064 } 549d62bc4baSyz147064 550d62bc4baSyz147064 void 551d62bc4baSyz147064 dlmgmt_dlconf_table_lock(boolean_t write) 552d62bc4baSyz147064 { 553d62bc4baSyz147064 if (write) 554d62bc4baSyz147064 (void) pthread_rwlock_wrlock(&dlmgmt_dlconf_lock); 555d62bc4baSyz147064 else 556d62bc4baSyz147064 (void) pthread_rwlock_rdlock(&dlmgmt_dlconf_lock); 557d62bc4baSyz147064 } 558d62bc4baSyz147064 559d62bc4baSyz147064 void 5602b24ab6bSSebastien Roy dlmgmt_dlconf_table_unlock(void) 561d62bc4baSyz147064 { 562d62bc4baSyz147064 (void) pthread_rwlock_unlock(&dlmgmt_dlconf_lock); 563d62bc4baSyz147064 } 564d62bc4baSyz147064 565d62bc4baSyz147064 int 566d62bc4baSyz147064 dlconf_create(const char *name, datalink_id_t linkid, datalink_class_t class, 5672b24ab6bSSebastien Roy uint32_t media, zoneid_t zoneid, dlmgmt_dlconf_t **dlconfpp) 568d62bc4baSyz147064 { 569d62bc4baSyz147064 dlmgmt_dlconf_t *dlconfp = NULL; 570d62bc4baSyz147064 int err = 0; 571d62bc4baSyz147064 572d62bc4baSyz147064 if (dlmgmt_nextconfid == 0) { 573d62bc4baSyz147064 err = ENOSPC; 574d62bc4baSyz147064 goto done; 575d62bc4baSyz147064 } 576d62bc4baSyz147064 577d62bc4baSyz147064 if ((dlconfp = calloc(1, sizeof (dlmgmt_dlconf_t))) == NULL) { 578d62bc4baSyz147064 err = ENOMEM; 579d62bc4baSyz147064 goto done; 580d62bc4baSyz147064 } 581d62bc4baSyz147064 582d62bc4baSyz147064 (void) strlcpy(dlconfp->ld_link, name, MAXLINKNAMELEN); 583d62bc4baSyz147064 dlconfp->ld_linkid = linkid; 584d62bc4baSyz147064 dlconfp->ld_class = class; 585d62bc4baSyz147064 dlconfp->ld_media = media; 586d62bc4baSyz147064 dlconfp->ld_id = dlmgmt_nextconfid; 5872b24ab6bSSebastien Roy dlconfp->ld_zoneid = zoneid; 588d62bc4baSyz147064 589d62bc4baSyz147064 done: 590d62bc4baSyz147064 *dlconfpp = dlconfp; 591d62bc4baSyz147064 return (err); 592d62bc4baSyz147064 } 593d62bc4baSyz147064 594d62bc4baSyz147064 void 595d62bc4baSyz147064 dlconf_destroy(dlmgmt_dlconf_t *dlconfp) 596d62bc4baSyz147064 { 597d62bc4baSyz147064 dlmgmt_linkattr_t *next, *attrp; 598d62bc4baSyz147064 599d62bc4baSyz147064 for (attrp = dlconfp->ld_head; attrp != NULL; attrp = next) { 600d62bc4baSyz147064 next = attrp->lp_next; 601d62bc4baSyz147064 free(attrp->lp_val); 602d62bc4baSyz147064 free(attrp); 603d62bc4baSyz147064 } 604d62bc4baSyz147064 free(dlconfp); 605d62bc4baSyz147064 } 606d62bc4baSyz147064 607d62bc4baSyz147064 int 6082b24ab6bSSebastien Roy dlmgmt_generate_name(const char *prefix, char *name, size_t size, 6092b24ab6bSSebastien Roy zoneid_t zoneid) 610d62bc4baSyz147064 { 611d62bc4baSyz147064 dlmgmt_prefix_t *lpp, *prev = NULL; 6122b24ab6bSSebastien Roy dlmgmt_link_t link, *linkp; 613d62bc4baSyz147064 614d62bc4baSyz147064 /* 615d62bc4baSyz147064 * See whether the requested prefix is already in the list. 616d62bc4baSyz147064 */ 6172b24ab6bSSebastien Roy for (lpp = &dlmgmt_prefixlist; lpp != NULL; 6182b24ab6bSSebastien Roy prev = lpp, lpp = lpp->lp_next) { 6192b24ab6bSSebastien Roy if (lpp->lp_zoneid == zoneid && 6202b24ab6bSSebastien Roy strcmp(prefix, lpp->lp_prefix) == 0) 621d62bc4baSyz147064 break; 622d62bc4baSyz147064 } 623d62bc4baSyz147064 624d62bc4baSyz147064 /* 625d62bc4baSyz147064 * Not found. 626d62bc4baSyz147064 */ 627d62bc4baSyz147064 if (lpp == NULL) { 628d62bc4baSyz147064 assert(prev != NULL); 629d62bc4baSyz147064 630d62bc4baSyz147064 /* 631d62bc4baSyz147064 * First add this new prefix into the prefix list. 632d62bc4baSyz147064 */ 633d62bc4baSyz147064 if ((lpp = malloc(sizeof (dlmgmt_prefix_t))) == NULL) 634d62bc4baSyz147064 return (ENOMEM); 635d62bc4baSyz147064 636d62bc4baSyz147064 prev->lp_next = lpp; 637d62bc4baSyz147064 lpp->lp_next = NULL; 6382b24ab6bSSebastien Roy lpp->lp_zoneid = zoneid; 639d62bc4baSyz147064 lpp->lp_nextppa = 0; 640d62bc4baSyz147064 (void) strlcpy(lpp->lp_prefix, prefix, MAXLINKNAMELEN); 641d62bc4baSyz147064 642d62bc4baSyz147064 /* 643d62bc4baSyz147064 * Now determine this prefix's nextppa. 644d62bc4baSyz147064 */ 645d62bc4baSyz147064 (void) snprintf(link.ll_link, MAXLINKNAMELEN, "%s%d", 6462b24ab6bSSebastien Roy prefix, 0); 6472b24ab6bSSebastien Roy link.ll_zoneid = zoneid; 6482b24ab6bSSebastien Roy if ((linkp = avl_find(&dlmgmt_name_avl, &link, NULL)) != NULL) 649d62bc4baSyz147064 dlmgmt_advance_ppa(linkp); 650d62bc4baSyz147064 } 651d62bc4baSyz147064 652d62bc4baSyz147064 if (lpp->lp_nextppa == (uint_t)-1) 653d62bc4baSyz147064 return (ENOSPC); 654d62bc4baSyz147064 655d62bc4baSyz147064 (void) snprintf(name, size, "%s%d", prefix, lpp->lp_nextppa); 656d62bc4baSyz147064 return (0); 657d62bc4baSyz147064 } 658d62bc4baSyz147064 659d62bc4baSyz147064 /* 660d62bc4baSyz147064 * Advance the next available ppa value if the name prefix of the current 661d62bc4baSyz147064 * link is in the prefix list. 662d62bc4baSyz147064 */ 663d62bc4baSyz147064 static void 664d62bc4baSyz147064 dlmgmt_advance_ppa(dlmgmt_link_t *linkp) 665d62bc4baSyz147064 { 666d62bc4baSyz147064 dlmgmt_prefix_t *lpp; 667d62bc4baSyz147064 char prefix[MAXLINKNAMELEN]; 6682b24ab6bSSebastien Roy char linkname[MAXLINKNAMELEN]; 669d62bc4baSyz147064 uint_t start, ppa; 670d62bc4baSyz147064 671d62bc4baSyz147064 (void) dlpi_parselink(linkp->ll_link, prefix, &ppa); 672d62bc4baSyz147064 673d62bc4baSyz147064 /* 674d62bc4baSyz147064 * See whether the requested prefix is already in the list. 675d62bc4baSyz147064 */ 6762b24ab6bSSebastien Roy for (lpp = &dlmgmt_prefixlist; lpp != NULL; lpp = lpp->lp_next) { 6772b24ab6bSSebastien Roy if (lpp->lp_zoneid == linkp->ll_zoneid && 6782b24ab6bSSebastien Roy strcmp(prefix, lpp->lp_prefix) == 0) 679d62bc4baSyz147064 break; 680d62bc4baSyz147064 } 681d62bc4baSyz147064 682d62bc4baSyz147064 /* 683d62bc4baSyz147064 * If the link name prefix is in the list, advance the 684d62bc4baSyz147064 * next available ppa for the <prefix>N name. 685d62bc4baSyz147064 */ 686d62bc4baSyz147064 if (lpp == NULL || lpp->lp_nextppa != ppa) 687d62bc4baSyz147064 return; 688d62bc4baSyz147064 689d62bc4baSyz147064 start = lpp->lp_nextppa++; 690d62bc4baSyz147064 linkp = AVL_NEXT(&dlmgmt_name_avl, linkp); 691d62bc4baSyz147064 while (lpp->lp_nextppa != start) { 692d62bc4baSyz147064 if (lpp->lp_nextppa == (uint_t)-1) { 693d62bc4baSyz147064 /* 694d62bc4baSyz147064 * wrapped around. search from <prefix>1. 695d62bc4baSyz147064 */ 696d62bc4baSyz147064 lpp->lp_nextppa = 0; 6972b24ab6bSSebastien Roy (void) snprintf(linkname, MAXLINKNAMELEN, 698d62bc4baSyz147064 "%s%d", lpp->lp_prefix, lpp->lp_nextppa); 6992b24ab6bSSebastien Roy linkp = link_by_name(linkname, lpp->lp_zoneid); 700d62bc4baSyz147064 if (linkp == NULL) 701d62bc4baSyz147064 return; 702d62bc4baSyz147064 } else { 703d62bc4baSyz147064 if (linkp == NULL) 704d62bc4baSyz147064 return; 705d62bc4baSyz147064 (void) dlpi_parselink(linkp->ll_link, prefix, &ppa); 706d62bc4baSyz147064 if ((strcmp(prefix, lpp->lp_prefix) != 0) || 707d62bc4baSyz147064 (ppa != lpp->lp_nextppa)) { 708d62bc4baSyz147064 return; 709d62bc4baSyz147064 } 710d62bc4baSyz147064 } 711d62bc4baSyz147064 linkp = AVL_NEXT(&dlmgmt_name_avl, linkp); 712d62bc4baSyz147064 lpp->lp_nextppa++; 713d62bc4baSyz147064 } 714d62bc4baSyz147064 lpp->lp_nextppa = (uint_t)-1; 715d62bc4baSyz147064 } 716d62bc4baSyz147064 717d62bc4baSyz147064 /* 718d62bc4baSyz147064 * Advance to the next available linkid value. 719d62bc4baSyz147064 */ 720d62bc4baSyz147064 static void 721d62bc4baSyz147064 dlmgmt_advance_linkid(dlmgmt_link_t *linkp) 722d62bc4baSyz147064 { 723d62bc4baSyz147064 datalink_id_t start; 724d62bc4baSyz147064 725d62bc4baSyz147064 if (linkp->ll_linkid != dlmgmt_nextlinkid) 726d62bc4baSyz147064 return; 727d62bc4baSyz147064 728d62bc4baSyz147064 start = dlmgmt_nextlinkid; 729d62bc4baSyz147064 linkp = AVL_NEXT(&dlmgmt_id_avl, linkp); 730d62bc4baSyz147064 731d62bc4baSyz147064 do { 732d62bc4baSyz147064 if (dlmgmt_nextlinkid == DATALINK_MAX_LINKID) { 733d62bc4baSyz147064 /* 734d62bc4baSyz147064 * wrapped around. search from 1. 735d62bc4baSyz147064 */ 736d62bc4baSyz147064 dlmgmt_nextlinkid = 1; 7372b24ab6bSSebastien Roy if ((linkp = link_by_id(1, GLOBAL_ZONEID)) == NULL) 738d62bc4baSyz147064 return; 739d62bc4baSyz147064 } else { 740d62bc4baSyz147064 dlmgmt_nextlinkid++; 741d62bc4baSyz147064 if (linkp == NULL) 742d62bc4baSyz147064 return; 743d62bc4baSyz147064 if (linkp->ll_linkid != dlmgmt_nextlinkid) 744d62bc4baSyz147064 return; 745d62bc4baSyz147064 } 746d62bc4baSyz147064 747d62bc4baSyz147064 linkp = AVL_NEXT(&dlmgmt_id_avl, linkp); 748d62bc4baSyz147064 } while (dlmgmt_nextlinkid != start); 749d62bc4baSyz147064 750d62bc4baSyz147064 dlmgmt_nextlinkid = DATALINK_INVALID_LINKID; 751d62bc4baSyz147064 } 752d62bc4baSyz147064 753d62bc4baSyz147064 /* 754d62bc4baSyz147064 * Advance various global values, for example, next linkid value, next ppa for 755d62bc4baSyz147064 * various prefix etc. 756d62bc4baSyz147064 */ 757d62bc4baSyz147064 void 758d62bc4baSyz147064 dlmgmt_advance(dlmgmt_link_t *linkp) 759d62bc4baSyz147064 { 760d62bc4baSyz147064 dlmgmt_advance_linkid(linkp); 761d62bc4baSyz147064 dlmgmt_advance_ppa(linkp); 762d62bc4baSyz147064 } 763d62bc4baSyz147064 764d62bc4baSyz147064 /* 765d62bc4baSyz147064 * Advance to the next available dlconf id. 766d62bc4baSyz147064 */ 767d62bc4baSyz147064 void 768d62bc4baSyz147064 dlmgmt_advance_dlconfid(dlmgmt_dlconf_t *dlconfp) 769d62bc4baSyz147064 { 770d62bc4baSyz147064 uint_t start; 771d62bc4baSyz147064 772d62bc4baSyz147064 start = dlmgmt_nextconfid++; 773d62bc4baSyz147064 dlconfp = AVL_NEXT(&dlmgmt_dlconf_avl, dlconfp); 774d62bc4baSyz147064 while (dlmgmt_nextconfid != start) { 775d62bc4baSyz147064 if (dlmgmt_nextconfid == 0) { 776d62bc4baSyz147064 dlmgmt_dlconf_t dlconf; 777d62bc4baSyz147064 778d62bc4baSyz147064 /* 779d62bc4baSyz147064 * wrapped around. search from 1. 780d62bc4baSyz147064 */ 781d62bc4baSyz147064 dlconf.ld_id = dlmgmt_nextconfid = 1; 782a73e6fc1SCathy Zhou dlconfp = avl_find(&dlmgmt_dlconf_avl, &dlconf, NULL); 783d62bc4baSyz147064 if (dlconfp == NULL) 784d62bc4baSyz147064 return; 785d62bc4baSyz147064 } else { 786d62bc4baSyz147064 if ((dlconfp == NULL) || 787d62bc4baSyz147064 (dlconfp->ld_id != dlmgmt_nextconfid)) { 788d62bc4baSyz147064 return; 789d62bc4baSyz147064 } 790d62bc4baSyz147064 } 791a73e6fc1SCathy Zhou dlconfp = AVL_NEXT(&dlmgmt_dlconf_avl, dlconfp); 792d62bc4baSyz147064 dlmgmt_nextconfid++; 793d62bc4baSyz147064 } 794d62bc4baSyz147064 dlmgmt_nextconfid = 0; 795d62bc4baSyz147064 } 796