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