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


 338 }
 339 
 340 void
 341 dlmgmt_table_unlock(void)
 342 {
 343         (void) pthread_rwlock_unlock(&dlmgmt_avl_lock);
 344         (void) pthread_mutex_lock(&dlmgmt_avl_mutex);
 345         (void) pthread_cond_broadcast(&dlmgmt_avl_cv);
 346         (void) pthread_mutex_unlock(&dlmgmt_avl_mutex);
 347 }
 348 
 349 void
 350 link_destroy(dlmgmt_link_t *linkp)
 351 {
 352         linkattr_destroy(linkp);
 353         free(linkp);
 354 }
 355 
 356 /*
 357  * Set the DLMGMT_ACTIVE flag on the link to note that it is active.
 358  * When a link is active and is owned by an NGZ then it is added to
 359  * that zone's datalink list.
 360  */
 361 int
 362 link_activate(dlmgmt_link_t *linkp)
 363 {
 364         int             err = 0;
 365         zoneid_t        zoneid = ALL_ZONES;
 366 
 367         /*
 368          * If zone_check_datalink() returns 0 it means we found the
 369          * link in one of the NGZ's datalink lists. Otherwise the link
 370          * is under the GZ.
 371          */
 372         if (zone_check_datalink(&zoneid, linkp->ll_linkid) == 0) {
 373                 /*
 374                  * This is a bit subtle. If the following expression
 375                  * is true then the link was found in one of the NGZ's
 376                  * datalink lists but the link structure has it under
 377                  * the GZ. This means that the link is supposed to be
 378                  * loaned out to an NGZ but the dlmgmtd state is out
 379                  * of sync -- possibly due to the process restarting.
 380                  * In this case we need to sync the dlmgmtd state by
 381                  * marking it as on-loan to the NGZ it's currently
 382                  * under.
 383                  */
 384                 if (zoneid != linkp->ll_zoneid) {
 385                         assert(linkp->ll_zoneid == 0);
 386                         assert(linkp->ll_onloan == B_FALSE);

 387 
 388                         /*
 389                          * If dlmgmtd already has a link with this
 390                          * name under the NGZ then we have a problem.
 391                          */
 392                         if (link_by_name(linkp->ll_link, zoneid) != NULL) {
 393                                 err = EEXIST;
 394                                 goto done;
 395                         }
 396 
 397                         /*
 398                          * Remove the current linkp entry from the
 399                          * list because it's under the wrong zoneid.
 400                          * We don't have to update the dlmgmt_id_avl
 401                          * because it compares entries by ll_linkid
 402                          * only.
 403                          */
 404                         if (avl_find(&dlmgmt_name_avl, linkp, NULL) != NULL)
 405                                 avl_remove(&dlmgmt_name_avl, linkp);
 406 
 407                         /*
 408                          * Update the link to reflect the fact that
 409                          * it's on-loan to an NGZ and re-add it to the
 410                          * list.
 411                          */
 412                         linkp->ll_zoneid = zoneid;
 413                         avl_add(&dlmgmt_name_avl, linkp);
 414                         linkp->ll_onloan = B_TRUE;
 415 
 416                         /*
 417                          * When a VNIC is not persistent and loaned to
 418                          * a zone it is considered transient. This is
 419                          * the same logic found in do_create_vnic()
 420                          * and is needed here in the event of a
 421                          * dlmgmtd restart.
 422                          */
 423                         if (linkp->ll_class == DATALINK_CLASS_VNIC &&
 424                             !(linkp->ll_flags & DLMGMT_PERSIST))
 425                                 linkp->ll_trans = B_TRUE;
 426                 }
 427         } else if (linkp->ll_zoneid != GLOBAL_ZONEID) {
 428                 /*
 429                  * In this case the link was not found under any NGZs
 430                  * but according to its ll_zoneid member it is owned
 431                  * by an NGZ. Add the datalink to the appropriate zone
 432                  * datalink list.
 433                  */
 434                 err = zone_add_datalink(linkp->ll_zoneid, linkp->ll_linkid);
 435                 assert(linkp->ll_onloan == B_FALSE);
 436         }
 437 done:
 438         if (err == 0)
 439                 linkp->ll_flags |= DLMGMT_ACTIVE;
 440         return (err);
 441 }
 442 
 443 /*
 444  * Is linkp visible from the caller's zoneid?  It is if the link is in the
 445  * same zone as the caller, or if the caller is in the global zone and the
 446  * link is on loan to a non-global zone.
 447  */
 448 boolean_t
 449 link_is_visible(dlmgmt_link_t *linkp, zoneid_t zoneid)


 473         (void) strlcpy(link.ll_link, name, MAXLINKNAMELEN);
 474         link.ll_zoneid = zoneid;
 475         linkp = avl_find(&dlmgmt_name_avl, &link, NULL);
 476         return (linkp);
 477 }
 478 
 479 int
 480 dlmgmt_create_common(const char *name, datalink_class_t class, uint32_t media,
 481     zoneid_t zoneid, uint32_t flags, dlmgmt_link_t **linkpp)
 482 {
 483         dlmgmt_link_t   *linkp = NULL;
 484         avl_index_t     name_where, id_where;
 485         int             err = 0;
 486 
 487         if (!dladm_valid_linkname(name))
 488                 return (EINVAL);
 489         if (dlmgmt_nextlinkid == DATALINK_INVALID_LINKID)
 490                 return (ENOSPC);
 491         if (flags & ~(DLMGMT_ACTIVE | DLMGMT_PERSIST | DLMGMT_TRANSIENT) ||
 492             ((flags & DLMGMT_PERSIST) && (flags & DLMGMT_TRANSIENT)) ||
 493             flags == 0)
 494                 return (EINVAL);

 495 
 496         if ((linkp = calloc(1, sizeof (dlmgmt_link_t))) == NULL) {
 497                 err = ENOMEM;
 498                 goto done;
 499         }
 500 
 501         (void) strlcpy(linkp->ll_link, name, MAXLINKNAMELEN);
 502         linkp->ll_class = class;
 503         linkp->ll_media = media;
 504         linkp->ll_linkid = dlmgmt_nextlinkid;
 505         linkp->ll_zoneid = zoneid;
 506         linkp->ll_gen = 0;
 507 
 508         /*
 509          * While DLMGMT_TRANSIENT starts off as a flag it is converted
 510          * into a link field since it is really a substate of
 511          * DLMGMT_ACTIVE -- it should not survive as a flag beyond
 512          * this point.
 513          */
 514         linkp->ll_trans = (flags & DLMGMT_TRANSIENT) ? B_TRUE : B_FALSE;
 515         flags &= ~DLMGMT_TRANSIENT;
 516 
 517         if (avl_find(&dlmgmt_name_avl, linkp, &name_where) != NULL ||
 518             avl_find(&dlmgmt_id_avl, linkp, &id_where) != NULL) {
 519                 err = EEXIST;
 520                 goto done;
 521         }
 522 
 523         avl_insert(&dlmgmt_name_avl, linkp, name_where);
 524         avl_insert(&dlmgmt_id_avl, linkp, id_where);
 525 
 526         if ((flags & DLMGMT_ACTIVE) && (err = link_activate(linkp)) != 0) {
 527                 avl_remove(&dlmgmt_name_avl, linkp);
 528                 avl_remove(&dlmgmt_id_avl, linkp);
 529                 goto done;
 530         }
 531 
 532         linkp->ll_flags = flags;
 533         dlmgmt_advance(linkp);
 534         *linkpp = linkp;




 338 }
 339 
 340 void
 341 dlmgmt_table_unlock(void)
 342 {
 343         (void) pthread_rwlock_unlock(&dlmgmt_avl_lock);
 344         (void) pthread_mutex_lock(&dlmgmt_avl_mutex);
 345         (void) pthread_cond_broadcast(&dlmgmt_avl_cv);
 346         (void) pthread_mutex_unlock(&dlmgmt_avl_mutex);
 347 }
 348 
 349 void
 350 link_destroy(dlmgmt_link_t *linkp)
 351 {
 352         linkattr_destroy(linkp);
 353         free(linkp);
 354 }
 355 
 356 /*
 357  * Set the DLMGMT_ACTIVE flag on the link to note that it is active.
 358  * When a link is active and owned by an NGZ then it is added to
 359  * that zone's datalink list.
 360  */
 361 int
 362 link_activate(dlmgmt_link_t *linkp)
 363 {
 364         int             err = 0;
 365         zoneid_t        zoneid = ALL_ZONES;
 366 
 367         /*
 368          * If zone_check_datalink() returns 0 it means we found the
 369          * link in one of the NGZ's datalink lists. Otherwise the link
 370          * is under the GZ.
 371          */
 372         if (zone_check_datalink(&zoneid, linkp->ll_linkid) == 0) {
 373                 /*
 374                  * This is a bit subtle. If the following expression
 375                  * is true then the link was found in one of the NGZ's
 376                  * datalink lists but the link structure has it under
 377                  * the GZ. This means that the link is supposed to be
 378                  * loaned out to an NGZ but the dlmgmtd state is out
 379                  * of sync -- possibly due to the process restarting.
 380                  * In this case we need to sync the dlmgmtd state by
 381                  * marking it as on-loan to the NGZ it's currently
 382                  * under.
 383                  */
 384                 if (zoneid != linkp->ll_zoneid) {
 385                         assert(linkp->ll_zoneid == 0);
 386                         assert(linkp->ll_onloan == B_FALSE);
 387                         assert(linkp->ll_transient == 0);
 388 
 389                         /*
 390                          * If dlmgmtd already has a link with this
 391                          * name under the NGZ then we have a problem.
 392                          */
 393                         if (link_by_name(linkp->ll_link, zoneid) != NULL) {
 394                                 err = EEXIST;
 395                                 goto done;
 396                         }
 397 
 398                         /*
 399                          * Remove the current linkp entry from the
 400                          * list because it's under the wrong zoneid.
 401                          * We don't have to update the dlmgmt_id_avl
 402                          * because it compares entries by ll_linkid
 403                          * only.
 404                          */
 405                         if (avl_find(&dlmgmt_name_avl, linkp, NULL) != NULL)
 406                                 avl_remove(&dlmgmt_name_avl, linkp);
 407 
 408                         /*
 409                          * Update the link to reflect the fact that
 410                          * it's on-loan to an NGZ and re-add it to the
 411                          * list.
 412                          */
 413                         linkp->ll_zoneid = zoneid;
 414                         avl_add(&dlmgmt_name_avl, linkp);
 415                         linkp->ll_onloan = B_TRUE;
 416 
 417                         /*
 418                          * When a VNIC is not persistent and loaned to
 419                          * a zone it is considered transient. This is
 420                          * the same logic found in do_create_vnic()
 421                          * and is needed here in the event of a
 422                          * dlmgmtd restart.
 423                          */
 424                         if (linkp->ll_class == DATALINK_CLASS_VNIC &&
 425                             !(linkp->ll_flags & DLMGMT_PERSIST))
 426                                 linkp->ll_transient = B_TRUE;
 427                 }
 428         } else if (linkp->ll_zoneid != GLOBAL_ZONEID) {
 429                 /*
 430                  * In this case the link was not found under any NGZ
 431                  * but according to its ll_zoneid member it is owned
 432                  * by an NGZ. Add the datalink to the appropriate zone
 433                  * datalink list.
 434                  */
 435                 err = zone_add_datalink(linkp->ll_zoneid, linkp->ll_linkid);
 436                 assert(linkp->ll_onloan == B_FALSE);
 437         }
 438 done:
 439         if (err == 0)
 440                 linkp->ll_flags |= DLMGMT_ACTIVE;
 441         return (err);
 442 }
 443 
 444 /*
 445  * Is linkp visible from the caller's zoneid?  It is if the link is in the
 446  * same zone as the caller, or if the caller is in the global zone and the
 447  * link is on loan to a non-global zone.
 448  */
 449 boolean_t
 450 link_is_visible(dlmgmt_link_t *linkp, zoneid_t zoneid)


 474         (void) strlcpy(link.ll_link, name, MAXLINKNAMELEN);
 475         link.ll_zoneid = zoneid;
 476         linkp = avl_find(&dlmgmt_name_avl, &link, NULL);
 477         return (linkp);
 478 }
 479 
 480 int
 481 dlmgmt_create_common(const char *name, datalink_class_t class, uint32_t media,
 482     zoneid_t zoneid, uint32_t flags, dlmgmt_link_t **linkpp)
 483 {
 484         dlmgmt_link_t   *linkp = NULL;
 485         avl_index_t     name_where, id_where;
 486         int             err = 0;
 487 
 488         if (!dladm_valid_linkname(name))
 489                 return (EINVAL);
 490         if (dlmgmt_nextlinkid == DATALINK_INVALID_LINKID)
 491                 return (ENOSPC);
 492         if (flags & ~(DLMGMT_ACTIVE | DLMGMT_PERSIST | DLMGMT_TRANSIENT) ||
 493             ((flags & DLMGMT_PERSIST) && (flags & DLMGMT_TRANSIENT)) ||
 494             flags == 0) {
 495                 return (EINVAL);
 496         }
 497 
 498         if ((linkp = calloc(1, sizeof (dlmgmt_link_t))) == NULL) {
 499                 err = ENOMEM;
 500                 goto done;
 501         }
 502 
 503         (void) strlcpy(linkp->ll_link, name, MAXLINKNAMELEN);
 504         linkp->ll_class = class;
 505         linkp->ll_media = media;
 506         linkp->ll_linkid = dlmgmt_nextlinkid;
 507         linkp->ll_zoneid = zoneid;
 508         linkp->ll_gen = 0;
 509 
 510         /*
 511          * While DLMGMT_TRANSIENT starts off as a flag it is converted
 512          * into a link field since it is really a substate of
 513          * DLMGMT_ACTIVE -- it should not survive as a flag beyond
 514          * this point.
 515          */
 516         linkp->ll_transient = (flags & DLMGMT_TRANSIENT) ? B_TRUE : B_FALSE;
 517         flags &= ~DLMGMT_TRANSIENT;
 518 
 519         if (avl_find(&dlmgmt_name_avl, linkp, &name_where) != NULL ||
 520             avl_find(&dlmgmt_id_avl, linkp, &id_where) != NULL) {
 521                 err = EEXIST;
 522                 goto done;
 523         }
 524 
 525         avl_insert(&dlmgmt_name_avl, linkp, name_where);
 526         avl_insert(&dlmgmt_id_avl, linkp, id_where);
 527 
 528         if ((flags & DLMGMT_ACTIVE) && (err = link_activate(linkp)) != 0) {
 529                 avl_remove(&dlmgmt_name_avl, linkp);
 530                 avl_remove(&dlmgmt_id_avl, linkp);
 531                 goto done;
 532         }
 533 
 534         linkp->ll_flags = flags;
 535         dlmgmt_advance(linkp);
 536         *linkpp = linkp;