Print this page
OS-3342+co
OS-249
| Split |
Close |
| Expand all |
| Collapse all |
--- old/usr/src/cmd/dlmgmtd/dlmgmt_util.c
+++ new/usr/src/cmd/dlmgmtd/dlmgmt_util.c
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License (the "License").
6 6 * You may not use this file except in compliance with the License.
7 7 *
8 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 9 * or http://www.opensolaris.org/os/licensing.
10 10 * See the License for the specific language governing permissions
11 11 * and limitations under the License.
12 12 *
13 13 * When distributing Covered Code, include this CDDL HEADER in each
|
↓ open down ↓ |
13 lines elided |
↑ open up ↑ |
14 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 15 * If applicable, add the following below this CDDL HEADER, with the
16 16 * fields enclosed by brackets "[]" replaced with your own identifying
17 17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 18 *
19 19 * CDDL HEADER END
20 20 */
21 21
22 22 /*
23 23 * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
24 + * Copyright (c) 2011, Joyent Inc. All rights reserved.
24 25 */
25 26
26 27 /*
27 28 * Utility functions used by the dlmgmtd daemon.
28 29 */
29 30
30 31 #include <assert.h>
31 32 #include <pthread.h>
32 33 #include <stddef.h>
33 34 #include <stdlib.h>
34 35 #include <stdio.h>
35 36 #include <errno.h>
36 37 #include <strings.h>
37 38 #include <string.h>
|
↓ open down ↓ |
4 lines elided |
↑ open up ↑ |
38 39 #include <syslog.h>
39 40 #include <stdarg.h>
40 41 #include <zone.h>
41 42 #include <errno.h>
42 43 #include <libdlpi.h>
43 44 #include "dlmgmt_impl.h"
44 45
45 46 /*
46 47 * There are three datalink AVL tables. The dlmgmt_name_avl tree contains all
47 48 * datalinks and is keyed by zoneid and link name. The dlmgmt_id_avl also
48 - * contains all datalinks, and it is keyed by link ID. The dlmgmt_loan_avl is
49 - * keyed by link name, and contains the set of global-zone links that are
50 - * currently on loan to non-global zones.
49 + * contains all datalinks, and it is keyed by link ID.
51 50 */
52 51 avl_tree_t dlmgmt_name_avl;
53 52 avl_tree_t dlmgmt_id_avl;
54 -avl_tree_t dlmgmt_loan_avl;
55 53
56 54 avl_tree_t dlmgmt_dlconf_avl;
57 55
58 56 static pthread_rwlock_t dlmgmt_avl_lock = PTHREAD_RWLOCK_INITIALIZER;
59 57 static pthread_mutex_t dlmgmt_avl_mutex = PTHREAD_MUTEX_INITIALIZER;
60 58 static pthread_cond_t dlmgmt_avl_cv = PTHREAD_COND_INITIALIZER;
61 59 static pthread_rwlock_t dlmgmt_dlconf_lock = PTHREAD_RWLOCK_INITIALIZER;
62 60
63 61 typedef struct dlmgmt_prefix {
64 62 struct dlmgmt_prefix *lp_next;
65 63 char lp_prefix[MAXLINKNAMELEN];
66 64 zoneid_t lp_zoneid;
67 65 uint_t lp_nextppa;
68 66 } dlmgmt_prefix_t;
69 67 static dlmgmt_prefix_t dlmgmt_prefixlist;
70 68
71 69 datalink_id_t dlmgmt_nextlinkid;
72 70 static datalink_id_t dlmgmt_nextconfid = 1;
73 71
74 72 static void dlmgmt_advance_linkid(dlmgmt_link_t *);
75 73 static void dlmgmt_advance_ppa(dlmgmt_link_t *);
76 74
77 75 void
78 76 dlmgmt_log(int pri, const char *fmt, ...)
79 77 {
80 78 va_list alist;
81 79
82 80 va_start(alist, fmt);
83 81 if (debug) {
84 82 (void) vfprintf(stderr, fmt, alist);
85 83 (void) fputc('\n', stderr);
86 84 } else {
87 85 vsyslog(pri, fmt, alist);
88 86 }
89 87 va_end(alist);
90 88 }
91 89
92 90 static int
93 91 cmp_link_by_name(const void *v1, const void *v2)
94 92 {
95 93 const dlmgmt_link_t *link1 = v1;
96 94 const dlmgmt_link_t *link2 = v2;
97 95 int cmp;
98 96
99 97 cmp = strcmp(link1->ll_link, link2->ll_link);
100 98 return ((cmp == 0) ? 0 : ((cmp < 0) ? -1 : 1));
101 99 }
102 100
103 101 /*
104 102 * Note that the zoneid associated with a link is effectively part of its
105 103 * name. This is essentially what results in having each zone have disjoint
106 104 * datalink namespaces.
107 105 */
108 106 static int
109 107 cmp_link_by_zname(const void *v1, const void *v2)
110 108 {
111 109 const dlmgmt_link_t *link1 = v1;
112 110 const dlmgmt_link_t *link2 = v2;
113 111
114 112 if (link1->ll_zoneid < link2->ll_zoneid)
115 113 return (-1);
116 114 if (link1->ll_zoneid > link2->ll_zoneid)
117 115 return (1);
118 116 return (cmp_link_by_name(link1, link2));
119 117 }
120 118
121 119 static int
122 120 cmp_link_by_id(const void *v1, const void *v2)
123 121 {
124 122 const dlmgmt_link_t *link1 = v1;
125 123 const dlmgmt_link_t *link2 = v2;
126 124
127 125 if ((uint64_t)(link1->ll_linkid) == (uint64_t)(link2->ll_linkid))
128 126 return (0);
129 127 else if ((uint64_t)(link1->ll_linkid) < (uint64_t)(link2->ll_linkid))
130 128 return (-1);
131 129 else
132 130 return (1);
133 131 }
134 132
135 133 static int
136 134 cmp_dlconf_by_id(const void *v1, const void *v2)
137 135 {
138 136 const dlmgmt_dlconf_t *dlconfp1 = v1;
139 137 const dlmgmt_dlconf_t *dlconfp2 = v2;
140 138
141 139 if (dlconfp1->ld_id == dlconfp2->ld_id)
142 140 return (0);
143 141 else if (dlconfp1->ld_id < dlconfp2->ld_id)
144 142 return (-1);
145 143 else
146 144 return (1);
147 145 }
148 146
149 147 void
150 148 dlmgmt_linktable_init(void)
151 149 {
152 150 /*
153 151 * Initialize the prefix list. First add the "net" prefix for the
154 152 * global zone to the list.
|
↓ open down ↓ |
90 lines elided |
↑ open up ↑ |
155 153 */
156 154 dlmgmt_prefixlist.lp_next = NULL;
157 155 dlmgmt_prefixlist.lp_zoneid = GLOBAL_ZONEID;
158 156 dlmgmt_prefixlist.lp_nextppa = 0;
159 157 (void) strlcpy(dlmgmt_prefixlist.lp_prefix, "net", MAXLINKNAMELEN);
160 158
161 159 avl_create(&dlmgmt_name_avl, cmp_link_by_zname, sizeof (dlmgmt_link_t),
162 160 offsetof(dlmgmt_link_t, ll_name_node));
163 161 avl_create(&dlmgmt_id_avl, cmp_link_by_id, sizeof (dlmgmt_link_t),
164 162 offsetof(dlmgmt_link_t, ll_id_node));
165 - avl_create(&dlmgmt_loan_avl, cmp_link_by_name, sizeof (dlmgmt_link_t),
166 - offsetof(dlmgmt_link_t, ll_loan_node));
167 163 avl_create(&dlmgmt_dlconf_avl, cmp_dlconf_by_id,
168 164 sizeof (dlmgmt_dlconf_t), offsetof(dlmgmt_dlconf_t, ld_node));
169 165 dlmgmt_nextlinkid = 1;
170 166 }
171 167
172 168 void
173 169 dlmgmt_linktable_fini(void)
174 170 {
175 171 dlmgmt_prefix_t *lpp, *next;
176 172
177 173 for (lpp = dlmgmt_prefixlist.lp_next; lpp != NULL; lpp = next) {
178 174 next = lpp->lp_next;
179 175 free(lpp);
180 176 }
181 177
182 178 avl_destroy(&dlmgmt_dlconf_avl);
183 179 avl_destroy(&dlmgmt_name_avl);
184 - avl_destroy(&dlmgmt_loan_avl);
185 180 avl_destroy(&dlmgmt_id_avl);
186 181 }
187 182
188 183 static void
189 184 linkattr_add(dlmgmt_linkattr_t **headp, dlmgmt_linkattr_t *attrp)
190 185 {
191 186 if (*headp == NULL) {
192 187 *headp = attrp;
193 188 } else {
194 189 (*headp)->lp_prev = attrp;
195 190 attrp->lp_next = *headp;
196 191 *headp = attrp;
197 192 }
198 193 }
199 194
200 195 static void
201 196 linkattr_rm(dlmgmt_linkattr_t **headp, dlmgmt_linkattr_t *attrp)
202 197 {
203 198 dlmgmt_linkattr_t *next, *prev;
204 199
205 200 next = attrp->lp_next;
206 201 prev = attrp->lp_prev;
207 202 if (next != NULL)
208 203 next->lp_prev = prev;
209 204 if (prev != NULL)
210 205 prev->lp_next = next;
211 206 else
212 207 *headp = next;
213 208 }
214 209
215 210 dlmgmt_linkattr_t *
216 211 linkattr_find(dlmgmt_linkattr_t *headp, const char *attr)
217 212 {
218 213 dlmgmt_linkattr_t *attrp;
219 214
220 215 for (attrp = headp; attrp != NULL; attrp = attrp->lp_next) {
221 216 if (strcmp(attrp->lp_name, attr) == 0)
222 217 break;
223 218 }
224 219 return (attrp);
225 220 }
226 221
227 222 int
228 223 linkattr_set(dlmgmt_linkattr_t **headp, const char *attr, void *attrval,
229 224 size_t attrsz, dladm_datatype_t type)
230 225 {
231 226 dlmgmt_linkattr_t *attrp;
232 227 void *newval;
233 228 boolean_t new;
234 229
235 230 attrp = linkattr_find(*headp, attr);
236 231 if (attrp != NULL) {
237 232 /*
238 233 * It is already set. If the value changed, update it.
239 234 */
240 235 if (linkattr_equal(headp, attr, attrval, attrsz))
241 236 return (0);
242 237 new = B_FALSE;
243 238 } else {
244 239 /*
245 240 * It is not set yet, allocate the linkattr and prepend to the
246 241 * list.
247 242 */
248 243 if ((attrp = calloc(1, sizeof (dlmgmt_linkattr_t))) == NULL)
249 244 return (ENOMEM);
250 245
251 246 (void) strlcpy(attrp->lp_name, attr, MAXLINKATTRLEN);
252 247 new = B_TRUE;
253 248 }
254 249 if ((newval = calloc(1, attrsz)) == NULL) {
255 250 if (new)
256 251 free(attrp);
257 252 return (ENOMEM);
258 253 }
259 254
260 255 if (!new)
261 256 free(attrp->lp_val);
262 257 attrp->lp_val = newval;
263 258 bcopy(attrval, attrp->lp_val, attrsz);
264 259 attrp->lp_sz = attrsz;
265 260 attrp->lp_type = type;
266 261 attrp->lp_linkprop = dladm_attr_is_linkprop(attr);
267 262 if (new)
268 263 linkattr_add(headp, attrp);
269 264 return (0);
270 265 }
271 266
272 267 void
273 268 linkattr_unset(dlmgmt_linkattr_t **headp, const char *attr)
274 269 {
275 270 dlmgmt_linkattr_t *attrp;
276 271
277 272 if ((attrp = linkattr_find(*headp, attr)) != NULL) {
278 273 linkattr_rm(headp, attrp);
279 274 free(attrp->lp_val);
280 275 free(attrp);
281 276 }
282 277 }
283 278
284 279 int
285 280 linkattr_get(dlmgmt_linkattr_t **headp, const char *attr, void **attrvalp,
286 281 size_t *attrszp, dladm_datatype_t *typep)
287 282 {
288 283 dlmgmt_linkattr_t *attrp;
289 284
290 285 if ((attrp = linkattr_find(*headp, attr)) == NULL)
291 286 return (ENOENT);
292 287
293 288 *attrvalp = attrp->lp_val;
294 289 *attrszp = attrp->lp_sz;
295 290 if (typep != NULL)
296 291 *typep = attrp->lp_type;
297 292 return (0);
298 293 }
299 294
300 295 boolean_t
301 296 linkattr_equal(dlmgmt_linkattr_t **headp, const char *attr, void *attrval,
302 297 size_t attrsz)
303 298 {
304 299 void *saved_attrval;
305 300 size_t saved_attrsz;
306 301
307 302 if (linkattr_get(headp, attr, &saved_attrval, &saved_attrsz, NULL) != 0)
308 303 return (B_FALSE);
309 304
310 305 return ((saved_attrsz == attrsz) &&
311 306 (memcmp(saved_attrval, attrval, attrsz) == 0));
312 307 }
313 308
314 309 void
315 310 linkattr_destroy(dlmgmt_link_t *linkp)
316 311 {
317 312 dlmgmt_linkattr_t *next, *attrp;
318 313
319 314 for (attrp = linkp->ll_head; attrp != NULL; attrp = next) {
320 315 next = attrp->lp_next;
321 316 free(attrp->lp_val);
322 317 free(attrp);
323 318 }
324 319 }
325 320
326 321 static int
327 322 dlmgmt_table_readwritelock(boolean_t write)
328 323 {
329 324 if (write)
330 325 return (pthread_rwlock_trywrlock(&dlmgmt_avl_lock));
331 326 else
332 327 return (pthread_rwlock_tryrdlock(&dlmgmt_avl_lock));
333 328 }
334 329
335 330 void
336 331 dlmgmt_table_lock(boolean_t write)
337 332 {
338 333 (void) pthread_mutex_lock(&dlmgmt_avl_mutex);
339 334 while (dlmgmt_table_readwritelock(write) == EBUSY)
340 335 (void) pthread_cond_wait(&dlmgmt_avl_cv, &dlmgmt_avl_mutex);
341 336
342 337 (void) pthread_mutex_unlock(&dlmgmt_avl_mutex);
343 338 }
344 339
345 340 void
346 341 dlmgmt_table_unlock(void)
347 342 {
348 343 (void) pthread_rwlock_unlock(&dlmgmt_avl_lock);
349 344 (void) pthread_mutex_lock(&dlmgmt_avl_mutex);
350 345 (void) pthread_cond_broadcast(&dlmgmt_avl_cv);
351 346 (void) pthread_mutex_unlock(&dlmgmt_avl_mutex);
352 347 }
353 348
354 349 void
355 350 link_destroy(dlmgmt_link_t *linkp)
356 351 {
357 352 linkattr_destroy(linkp);
358 353 free(linkp);
359 354 }
360 355
361 356 /*
362 357 * Set the DLMGMT_ACTIVE flag on the link to note that it is active. When a
363 358 * link becomes active and it belongs to a non-global zone, it is also added
364 359 * to that zone.
365 360 */
366 361 int
367 362 link_activate(dlmgmt_link_t *linkp)
368 363 {
369 364 int err = 0;
370 365 zoneid_t zoneid = ALL_ZONES;
371 366
372 367 if (zone_check_datalink(&zoneid, linkp->ll_linkid) == 0) {
373 368 /*
374 369 * This link was already added to a non-global zone. This can
375 370 * happen if dlmgmtd is restarted.
376 371 */
377 372 if (zoneid != linkp->ll_zoneid) {
|
↓ open down ↓ |
183 lines elided |
↑ open up ↑ |
378 373 if (link_by_name(linkp->ll_link, zoneid) != NULL) {
379 374 err = EEXIST;
380 375 goto done;
381 376 }
382 377
383 378 if (avl_find(&dlmgmt_name_avl, linkp, NULL) != NULL)
384 379 avl_remove(&dlmgmt_name_avl, linkp);
385 380
386 381 linkp->ll_zoneid = zoneid;
387 382 avl_add(&dlmgmt_name_avl, linkp);
388 - avl_add(&dlmgmt_loan_avl, linkp);
389 383 linkp->ll_onloan = B_TRUE;
390 384 }
391 385 } else if (linkp->ll_zoneid != GLOBAL_ZONEID) {
392 386 err = zone_add_datalink(linkp->ll_zoneid, linkp->ll_linkid);
393 387 }
394 388 done:
395 389 if (err == 0)
396 390 linkp->ll_flags |= DLMGMT_ACTIVE;
397 391 return (err);
398 392 }
399 393
400 394 /*
401 395 * Is linkp visible from the caller's zoneid? It is if the link is in the
402 396 * same zone as the caller, or if the caller is in the global zone and the
403 397 * link is on loan to a non-global zone.
404 398 */
405 399 boolean_t
406 400 link_is_visible(dlmgmt_link_t *linkp, zoneid_t zoneid)
407 401 {
408 402 return (linkp->ll_zoneid == zoneid ||
409 403 (zoneid == GLOBAL_ZONEID && linkp->ll_onloan));
410 404 }
411 405
412 406 dlmgmt_link_t *
413 407 link_by_id(datalink_id_t linkid, zoneid_t zoneid)
414 408 {
415 409 dlmgmt_link_t link, *linkp;
416 410
417 411 link.ll_linkid = linkid;
418 412 if ((linkp = avl_find(&dlmgmt_id_avl, &link, NULL)) == NULL)
419 413 return (NULL);
420 414 if (zoneid != GLOBAL_ZONEID && linkp->ll_zoneid != zoneid)
421 415 return (NULL);
422 416 return (linkp);
|
↓ open down ↓ |
24 lines elided |
↑ open up ↑ |
423 417 }
424 418
425 419 dlmgmt_link_t *
426 420 link_by_name(const char *name, zoneid_t zoneid)
427 421 {
428 422 dlmgmt_link_t link, *linkp;
429 423
430 424 (void) strlcpy(link.ll_link, name, MAXLINKNAMELEN);
431 425 link.ll_zoneid = zoneid;
432 426 linkp = avl_find(&dlmgmt_name_avl, &link, NULL);
433 - if (linkp == NULL && zoneid == GLOBAL_ZONEID) {
434 - /* The link could be on loan to a non-global zone? */
435 - linkp = avl_find(&dlmgmt_loan_avl, &link, NULL);
436 - }
437 427 return (linkp);
438 428 }
439 429
440 430 int
441 431 dlmgmt_create_common(const char *name, datalink_class_t class, uint32_t media,
442 432 zoneid_t zoneid, uint32_t flags, dlmgmt_link_t **linkpp)
443 433 {
444 434 dlmgmt_link_t *linkp = NULL;
445 435 avl_index_t name_where, id_where;
446 436 int err = 0;
447 437
448 438 if (!dladm_valid_linkname(name))
449 439 return (EINVAL);
450 440 if (dlmgmt_nextlinkid == DATALINK_INVALID_LINKID)
451 441 return (ENOSPC);
452 442
453 443 if ((linkp = calloc(1, sizeof (dlmgmt_link_t))) == NULL) {
|
↓ open down ↓ |
7 lines elided |
↑ open up ↑ |
454 444 err = ENOMEM;
455 445 goto done;
456 446 }
457 447
458 448 (void) strlcpy(linkp->ll_link, name, MAXLINKNAMELEN);
459 449 linkp->ll_class = class;
460 450 linkp->ll_media = media;
461 451 linkp->ll_linkid = dlmgmt_nextlinkid;
462 452 linkp->ll_zoneid = zoneid;
463 453 linkp->ll_gen = 0;
454 + linkp->ll_tomb = B_FALSE;
464 455
465 456 if (avl_find(&dlmgmt_name_avl, linkp, &name_where) != NULL ||
466 457 avl_find(&dlmgmt_id_avl, linkp, &id_where) != NULL) {
467 458 err = EEXIST;
468 459 goto done;
469 460 }
470 461
471 462 avl_insert(&dlmgmt_name_avl, linkp, name_where);
472 463 avl_insert(&dlmgmt_id_avl, linkp, id_where);
473 464
474 465 if ((flags & DLMGMT_ACTIVE) && (err = link_activate(linkp)) != 0) {
475 466 avl_remove(&dlmgmt_name_avl, linkp);
476 467 avl_remove(&dlmgmt_id_avl, linkp);
477 468 goto done;
478 469 }
479 470
480 471 linkp->ll_flags = flags;
481 472 dlmgmt_advance(linkp);
482 473 *linkpp = linkp;
483 474
484 475 done:
485 476 if (err != 0)
486 477 free(linkp);
487 478 return (err);
488 479 }
489 480
490 481 int
491 482 dlmgmt_destroy_common(dlmgmt_link_t *linkp, uint32_t flags)
492 483 {
493 484 if ((linkp->ll_flags & flags) == 0) {
494 485 /*
495 486 * The link does not exist in the specified space.
496 487 */
497 488 return (ENOENT);
498 489 }
499 490
500 491 linkp->ll_flags &= ~flags;
501 492 if (flags & DLMGMT_PERSIST) {
502 493 dlmgmt_linkattr_t *next, *attrp;
503 494
|
↓ open down ↓ |
30 lines elided |
↑ open up ↑ |
504 495 for (attrp = linkp->ll_head; attrp != NULL; attrp = next) {
505 496 next = attrp->lp_next;
506 497 free(attrp->lp_val);
507 498 free(attrp);
508 499 }
509 500 linkp->ll_head = NULL;
510 501 }
511 502
512 503 if ((flags & DLMGMT_ACTIVE) && linkp->ll_zoneid != GLOBAL_ZONEID) {
513 504 (void) zone_remove_datalink(linkp->ll_zoneid, linkp->ll_linkid);
514 - if (linkp->ll_onloan)
515 - avl_remove(&dlmgmt_loan_avl, linkp);
516 505 }
517 506
518 507 if (linkp->ll_flags == 0) {
519 508 avl_remove(&dlmgmt_id_avl, linkp);
520 509 avl_remove(&dlmgmt_name_avl, linkp);
521 510 link_destroy(linkp);
522 511 }
523 512
524 513 return (0);
525 514 }
526 515
527 516 int
528 517 dlmgmt_getattr_common(dlmgmt_linkattr_t **headp, const char *attr,
529 518 dlmgmt_getattr_retval_t *retvalp)
530 519 {
531 520 int err;
532 521 void *attrval;
533 522 size_t attrsz;
534 523 dladm_datatype_t attrtype;
535 524
536 525 err = linkattr_get(headp, attr, &attrval, &attrsz, &attrtype);
537 526 if (err != 0)
538 527 return (err);
539 528
540 529 assert(attrsz > 0);
541 530 if (attrsz > MAXLINKATTRVALLEN)
542 531 return (EINVAL);
543 532
544 533 retvalp->lr_type = attrtype;
545 534 retvalp->lr_attrsz = attrsz;
546 535 bcopy(attrval, retvalp->lr_attrval, attrsz);
547 536 return (0);
548 537 }
549 538
550 539 void
551 540 dlmgmt_dlconf_table_lock(boolean_t write)
552 541 {
553 542 if (write)
554 543 (void) pthread_rwlock_wrlock(&dlmgmt_dlconf_lock);
555 544 else
556 545 (void) pthread_rwlock_rdlock(&dlmgmt_dlconf_lock);
557 546 }
558 547
559 548 void
560 549 dlmgmt_dlconf_table_unlock(void)
561 550 {
562 551 (void) pthread_rwlock_unlock(&dlmgmt_dlconf_lock);
563 552 }
564 553
565 554 int
566 555 dlconf_create(const char *name, datalink_id_t linkid, datalink_class_t class,
567 556 uint32_t media, zoneid_t zoneid, dlmgmt_dlconf_t **dlconfpp)
568 557 {
569 558 dlmgmt_dlconf_t *dlconfp = NULL;
570 559 int err = 0;
571 560
572 561 if (dlmgmt_nextconfid == 0) {
573 562 err = ENOSPC;
574 563 goto done;
575 564 }
576 565
577 566 if ((dlconfp = calloc(1, sizeof (dlmgmt_dlconf_t))) == NULL) {
578 567 err = ENOMEM;
579 568 goto done;
580 569 }
581 570
582 571 (void) strlcpy(dlconfp->ld_link, name, MAXLINKNAMELEN);
583 572 dlconfp->ld_linkid = linkid;
584 573 dlconfp->ld_class = class;
585 574 dlconfp->ld_media = media;
586 575 dlconfp->ld_id = dlmgmt_nextconfid;
587 576 dlconfp->ld_zoneid = zoneid;
588 577
589 578 done:
590 579 *dlconfpp = dlconfp;
591 580 return (err);
592 581 }
593 582
594 583 void
595 584 dlconf_destroy(dlmgmt_dlconf_t *dlconfp)
596 585 {
597 586 dlmgmt_linkattr_t *next, *attrp;
598 587
599 588 for (attrp = dlconfp->ld_head; attrp != NULL; attrp = next) {
600 589 next = attrp->lp_next;
601 590 free(attrp->lp_val);
602 591 free(attrp);
603 592 }
604 593 free(dlconfp);
605 594 }
606 595
607 596 int
608 597 dlmgmt_generate_name(const char *prefix, char *name, size_t size,
609 598 zoneid_t zoneid)
610 599 {
611 600 dlmgmt_prefix_t *lpp, *prev = NULL;
612 601 dlmgmt_link_t link, *linkp;
613 602
614 603 /*
615 604 * See whether the requested prefix is already in the list.
616 605 */
617 606 for (lpp = &dlmgmt_prefixlist; lpp != NULL;
618 607 prev = lpp, lpp = lpp->lp_next) {
619 608 if (lpp->lp_zoneid == zoneid &&
620 609 strcmp(prefix, lpp->lp_prefix) == 0)
621 610 break;
622 611 }
623 612
624 613 /*
625 614 * Not found.
626 615 */
627 616 if (lpp == NULL) {
628 617 assert(prev != NULL);
629 618
630 619 /*
631 620 * First add this new prefix into the prefix list.
632 621 */
633 622 if ((lpp = malloc(sizeof (dlmgmt_prefix_t))) == NULL)
634 623 return (ENOMEM);
635 624
636 625 prev->lp_next = lpp;
637 626 lpp->lp_next = NULL;
638 627 lpp->lp_zoneid = zoneid;
639 628 lpp->lp_nextppa = 0;
640 629 (void) strlcpy(lpp->lp_prefix, prefix, MAXLINKNAMELEN);
641 630
642 631 /*
643 632 * Now determine this prefix's nextppa.
644 633 */
645 634 (void) snprintf(link.ll_link, MAXLINKNAMELEN, "%s%d",
646 635 prefix, 0);
647 636 link.ll_zoneid = zoneid;
648 637 if ((linkp = avl_find(&dlmgmt_name_avl, &link, NULL)) != NULL)
649 638 dlmgmt_advance_ppa(linkp);
650 639 }
651 640
652 641 if (lpp->lp_nextppa == (uint_t)-1)
653 642 return (ENOSPC);
654 643
655 644 (void) snprintf(name, size, "%s%d", prefix, lpp->lp_nextppa);
656 645 return (0);
657 646 }
658 647
659 648 /*
660 649 * Advance the next available ppa value if the name prefix of the current
661 650 * link is in the prefix list.
662 651 */
663 652 static void
664 653 dlmgmt_advance_ppa(dlmgmt_link_t *linkp)
665 654 {
666 655 dlmgmt_prefix_t *lpp;
667 656 char prefix[MAXLINKNAMELEN];
668 657 char linkname[MAXLINKNAMELEN];
669 658 uint_t start, ppa;
670 659
671 660 (void) dlpi_parselink(linkp->ll_link, prefix, &ppa);
672 661
673 662 /*
674 663 * See whether the requested prefix is already in the list.
675 664 */
676 665 for (lpp = &dlmgmt_prefixlist; lpp != NULL; lpp = lpp->lp_next) {
677 666 if (lpp->lp_zoneid == linkp->ll_zoneid &&
678 667 strcmp(prefix, lpp->lp_prefix) == 0)
679 668 break;
680 669 }
681 670
682 671 /*
683 672 * If the link name prefix is in the list, advance the
684 673 * next available ppa for the <prefix>N name.
685 674 */
686 675 if (lpp == NULL || lpp->lp_nextppa != ppa)
687 676 return;
688 677
689 678 start = lpp->lp_nextppa++;
690 679 linkp = AVL_NEXT(&dlmgmt_name_avl, linkp);
691 680 while (lpp->lp_nextppa != start) {
692 681 if (lpp->lp_nextppa == (uint_t)-1) {
693 682 /*
694 683 * wrapped around. search from <prefix>1.
695 684 */
696 685 lpp->lp_nextppa = 0;
697 686 (void) snprintf(linkname, MAXLINKNAMELEN,
698 687 "%s%d", lpp->lp_prefix, lpp->lp_nextppa);
699 688 linkp = link_by_name(linkname, lpp->lp_zoneid);
700 689 if (linkp == NULL)
701 690 return;
702 691 } else {
703 692 if (linkp == NULL)
704 693 return;
705 694 (void) dlpi_parselink(linkp->ll_link, prefix, &ppa);
706 695 if ((strcmp(prefix, lpp->lp_prefix) != 0) ||
707 696 (ppa != lpp->lp_nextppa)) {
708 697 return;
709 698 }
710 699 }
711 700 linkp = AVL_NEXT(&dlmgmt_name_avl, linkp);
712 701 lpp->lp_nextppa++;
713 702 }
714 703 lpp->lp_nextppa = (uint_t)-1;
715 704 }
716 705
717 706 /*
718 707 * Advance to the next available linkid value.
719 708 */
720 709 static void
721 710 dlmgmt_advance_linkid(dlmgmt_link_t *linkp)
722 711 {
723 712 datalink_id_t start;
724 713
725 714 if (linkp->ll_linkid != dlmgmt_nextlinkid)
726 715 return;
727 716
728 717 start = dlmgmt_nextlinkid;
729 718 linkp = AVL_NEXT(&dlmgmt_id_avl, linkp);
730 719
731 720 do {
732 721 if (dlmgmt_nextlinkid == DATALINK_MAX_LINKID) {
733 722 /*
734 723 * wrapped around. search from 1.
735 724 */
736 725 dlmgmt_nextlinkid = 1;
737 726 if ((linkp = link_by_id(1, GLOBAL_ZONEID)) == NULL)
738 727 return;
739 728 } else {
740 729 dlmgmt_nextlinkid++;
741 730 if (linkp == NULL)
742 731 return;
743 732 if (linkp->ll_linkid != dlmgmt_nextlinkid)
744 733 return;
745 734 }
746 735
747 736 linkp = AVL_NEXT(&dlmgmt_id_avl, linkp);
748 737 } while (dlmgmt_nextlinkid != start);
749 738
750 739 dlmgmt_nextlinkid = DATALINK_INVALID_LINKID;
751 740 }
752 741
753 742 /*
754 743 * Advance various global values, for example, next linkid value, next ppa for
755 744 * various prefix etc.
756 745 */
757 746 void
758 747 dlmgmt_advance(dlmgmt_link_t *linkp)
759 748 {
760 749 dlmgmt_advance_linkid(linkp);
761 750 dlmgmt_advance_ppa(linkp);
762 751 }
763 752
764 753 /*
765 754 * Advance to the next available dlconf id.
766 755 */
767 756 void
768 757 dlmgmt_advance_dlconfid(dlmgmt_dlconf_t *dlconfp)
769 758 {
770 759 uint_t start;
771 760
772 761 start = dlmgmt_nextconfid++;
773 762 dlconfp = AVL_NEXT(&dlmgmt_dlconf_avl, dlconfp);
774 763 while (dlmgmt_nextconfid != start) {
775 764 if (dlmgmt_nextconfid == 0) {
776 765 dlmgmt_dlconf_t dlconf;
777 766
778 767 /*
779 768 * wrapped around. search from 1.
780 769 */
781 770 dlconf.ld_id = dlmgmt_nextconfid = 1;
782 771 dlconfp = avl_find(&dlmgmt_dlconf_avl, &dlconf, NULL);
783 772 if (dlconfp == NULL)
784 773 return;
785 774 } else {
786 775 if ((dlconfp == NULL) ||
787 776 (dlconfp->ld_id != dlmgmt_nextconfid)) {
788 777 return;
789 778 }
790 779 }
791 780 dlconfp = AVL_NEXT(&dlmgmt_dlconf_avl, dlconfp);
792 781 dlmgmt_nextconfid++;
793 782 }
794 783 dlmgmt_nextconfid = 0;
795 784 }
|
↓ open down ↓ |
270 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX