Print this page
patch zone


 559  * When new zones are created constructor callbacks for all registered ZSD
 560  * entries will be called. That also uses the above two phases of marking
 561  * what needs to be done, and then running the callbacks without holding
 562  * any locks.
 563  *
 564  * The framework does not provide any locking around zone_getspecific() and
 565  * zone_setspecific() apart from that needed for internal consistency, so
 566  * callers interested in atomic "test-and-set" semantics will need to provide
 567  * their own locking.
 568  */
 569 
 570 /*
 571  * Helper function to find the zsd_entry associated with the key in the
 572  * given list.
 573  */
 574 static struct zsd_entry *
 575 zsd_find(list_t *l, zone_key_t key)
 576 {
 577         struct zsd_entry *zsd;
 578 
 579         for (zsd = list_head(l); zsd != NULL; zsd = list_next(l, zsd)) {
 580                 if (zsd->zsd_key == key) {
 581                         return (zsd);
 582                 }
 583         }
 584         return (NULL);
 585 }
 586 
 587 /*
 588  * Helper function to find the zsd_entry associated with the key in the
 589  * given list. Move it to the front of the list.
 590  */
 591 static struct zsd_entry *
 592 zsd_find_mru(list_t *l, zone_key_t key)
 593 {
 594         struct zsd_entry *zsd;
 595 
 596         for (zsd = list_head(l); zsd != NULL; zsd = list_next(l, zsd)) {
 597                 if (zsd->zsd_key == key) {
 598                         /*
 599                          * Move to head of list to keep list in MRU order.
 600                          */
 601                         if (zsd != list_head(l)) {
 602                                 list_remove(l, zsd);
 603                                 list_insert_head(l, zsd);
 604                         }
 605                         return (zsd);
 606                 }
 607         }
 608         return (NULL);
 609 }
 610 
 611 void
 612 zone_key_create(zone_key_t *keyp, void *(*create)(zoneid_t),
 613     void (*shutdown)(zoneid_t, void *), void (*destroy)(zoneid_t, void *))
 614 {
 615         struct zsd_entry *zsdp;
 616         struct zsd_entry *t;


 621         zsdp->zsd_data = NULL;
 622         zsdp->zsd_create = create;
 623         zsdp->zsd_shutdown = shutdown;
 624         zsdp->zsd_destroy = destroy;
 625 
 626         /*
 627          * Insert in global list of callbacks. Makes future zone creations
 628          * see it.
 629          */
 630         mutex_enter(&zsd_key_lock);
 631         key = zsdp->zsd_key = ++zsd_keyval;
 632         ASSERT(zsd_keyval != 0);
 633         list_insert_tail(&zsd_registered_keys, zsdp);
 634         mutex_exit(&zsd_key_lock);
 635 
 636         /*
 637          * Insert for all existing zones and mark them as needing
 638          * a create callback.
 639          */
 640         mutex_enter(&zonehash_lock);        /* stop the world */
 641         for (zone = list_head(&zone_active); zone != NULL;
 642             zone = list_next(&zone_active, zone)) {
 643                 zone_status_t status;
 644 
 645                 mutex_enter(&zone->zone_lock);
 646 
 647                 /* Skip zones that are on the way down or not yet up */
 648                 status = zone_status_get(zone);
 649                 if (status >= ZONE_IS_DOWN ||
 650                     status == ZONE_IS_UNINITIALIZED) {
 651                         mutex_exit(&zone->zone_lock);
 652                         continue;
 653                 }
 654 
 655                 t = zsd_find_mru(&zone->zone_zsd, key);
 656                 if (t != NULL) {
 657                         /*
 658                          * A zsd_configure already inserted it after
 659                          * we dropped zsd_key_lock above.
 660                          */
 661                         mutex_exit(&zone->zone_lock);
 662                         continue;


 698  * be called under a global lock. Then call the functions without
 699  * holding any locks. Finally free up the zone_zsd entries. (The apply
 700  * functions need to access the zone_zsd entries to find zsd_data etc.)
 701  */
 702 int
 703 zone_key_delete(zone_key_t key)
 704 {
 705         struct zsd_entry *zsdp = NULL;
 706         zone_t *zone;
 707 
 708         mutex_enter(&zsd_key_lock);
 709         zsdp = zsd_find_mru(&zsd_registered_keys, key);
 710         if (zsdp == NULL) {
 711                 mutex_exit(&zsd_key_lock);
 712                 return (-1);
 713         }
 714         list_remove(&zsd_registered_keys, zsdp);
 715         mutex_exit(&zsd_key_lock);
 716 
 717         mutex_enter(&zonehash_lock);
 718         for (zone = list_head(&zone_active); zone != NULL;
 719             zone = list_next(&zone_active, zone)) {
 720                 struct zsd_entry *del;
 721 
 722                 mutex_enter(&zone->zone_lock);
 723                 del = zsd_find_mru(&zone->zone_zsd, key);
 724                 if (del == NULL) {
 725                         /*
 726                          * Somebody else got here first e.g the zone going
 727                          * away.
 728                          */
 729                         mutex_exit(&zone->zone_lock);
 730                         continue;
 731                 }
 732                 ASSERT(del->zsd_shutdown == zsdp->zsd_shutdown);
 733                 ASSERT(del->zsd_destroy == zsdp->zsd_destroy);
 734                 if (del->zsd_shutdown != NULL &&
 735                     (del->zsd_flags & ZSD_SHUTDOWN_ALL) == 0) {
 736                         del->zsd_flags |= ZSD_SHUTDOWN_NEEDED;
 737                         DTRACE_PROBE2(zsd__shutdown__needed,
 738                             zone_t *, zone, zone_key_t, key);
 739                 }
 740                 if (del->zsd_destroy != NULL &&
 741                     (del->zsd_flags & ZSD_DESTROY_ALL) == 0) {
 742                         del->zsd_flags |= ZSD_DESTROY_NEEDED;
 743                         DTRACE_PROBE2(zsd__destroy__needed,
 744                             zone_t *, zone, zone_key_t, key);
 745                 }
 746                 mutex_exit(&zone->zone_lock);
 747         }
 748         mutex_exit(&zonehash_lock);
 749         kmem_free(zsdp, sizeof (*zsdp));
 750 
 751         /* Now call the shutdown and destroy callback for this key */
 752         zsd_apply_all_zones(zsd_apply_shutdown, key);
 753         zsd_apply_all_zones(zsd_apply_destroy, key);
 754 
 755         /* Now we can free up the zsdp structures in each zone */
 756         mutex_enter(&zonehash_lock);
 757         for (zone = list_head(&zone_active); zone != NULL;
 758             zone = list_next(&zone_active, zone)) {
 759                 struct zsd_entry *del;
 760 
 761                 mutex_enter(&zone->zone_lock);
 762                 del = zsd_find(&zone->zone_zsd, key);
 763                 if (del != NULL) {
 764                         list_remove(&zone->zone_zsd, del);
 765                         ASSERT(!(del->zsd_flags & ZSD_ALL_INPROGRESS));
 766                         kmem_free(del, sizeof (*del));
 767                 }
 768                 mutex_exit(&zone->zone_lock);
 769         }
 770         mutex_exit(&zonehash_lock);
 771 
 772         return (0);
 773 }
 774 
 775 /*
 776  * ZSD counterpart of pthread_setspecific().
 777  *
 778  * Since all zsd callbacks, including those with no create function,


 814         mutex_exit(&zone->zone_lock);
 815         return (data);
 816 }
 817 
 818 /*
 819  * Function used to initialize a zone's list of ZSD callbacks and data
 820  * when the zone is being created.  The callbacks are initialized from
 821  * the template list (zsd_registered_keys). The constructor callback is
 822  * executed later (once the zone exists and with locks dropped).
 823  */
 824 static void
 825 zone_zsd_configure(zone_t *zone)
 826 {
 827         struct zsd_entry *zsdp;
 828         struct zsd_entry *t;
 829 
 830         ASSERT(MUTEX_HELD(&zonehash_lock));
 831         ASSERT(list_head(&zone->zone_zsd) == NULL);
 832         mutex_enter(&zone->zone_lock);
 833         mutex_enter(&zsd_key_lock);
 834         for (zsdp = list_head(&zsd_registered_keys); zsdp != NULL;
 835             zsdp = list_next(&zsd_registered_keys, zsdp)) {
 836                 /*
 837                  * Since this zone is ZONE_IS_UNCONFIGURED, zone_key_create
 838                  * should not have added anything to it.
 839                  */
 840                 ASSERT(zsd_find(&zone->zone_zsd, zsdp->zsd_key) == NULL);
 841 
 842                 t = kmem_zalloc(sizeof (*t), KM_SLEEP);
 843                 t->zsd_key = zsdp->zsd_key;
 844                 t->zsd_create = zsdp->zsd_create;
 845                 t->zsd_shutdown = zsdp->zsd_shutdown;
 846                 t->zsd_destroy = zsdp->zsd_destroy;
 847                 if (zsdp->zsd_create != NULL) {
 848                         t->zsd_flags = ZSD_CREATE_NEEDED;
 849                         DTRACE_PROBE2(zsd__create__needed,
 850                             zone_t *, zone, zone_key_t, zsdp->zsd_key);
 851                 }
 852                 list_insert_tail(&zone->zone_zsd, t);
 853         }
 854         mutex_exit(&zsd_key_lock);
 855         mutex_exit(&zone->zone_lock);


 859 
 860 /*
 861  * Helper function to execute shutdown or destructor callbacks.
 862  */
 863 static void
 864 zone_zsd_callbacks(zone_t *zone, enum zsd_callback_type ct)
 865 {
 866         struct zsd_entry *t;
 867 
 868         ASSERT(ct == ZSD_SHUTDOWN || ct == ZSD_DESTROY);
 869         ASSERT(ct != ZSD_SHUTDOWN || zone_status_get(zone) >= ZONE_IS_EMPTY);
 870         ASSERT(ct != ZSD_DESTROY || zone_status_get(zone) >= ZONE_IS_DOWN);
 871 
 872         /*
 873          * Run the callback solely based on what is registered for the zone
 874          * in zone_zsd. The global list can change independently of this
 875          * as keys are registered and unregistered and we don't register new
 876          * callbacks for a zone that is in the process of going away.
 877          */
 878         mutex_enter(&zone->zone_lock);
 879         for (t = list_head(&zone->zone_zsd); t != NULL;
 880             t = list_next(&zone->zone_zsd, t)) {
 881                 zone_key_t key = t->zsd_key;
 882 
 883                 /* Skip if no callbacks registered */
 884 
 885                 if (ct == ZSD_SHUTDOWN) {
 886                         if (t->zsd_shutdown != NULL &&
 887                             (t->zsd_flags & ZSD_SHUTDOWN_ALL) == 0) {
 888                                 t->zsd_flags |= ZSD_SHUTDOWN_NEEDED;
 889                                 DTRACE_PROBE2(zsd__shutdown__needed,
 890                                     zone_t *, zone, zone_key_t, key);
 891                         }
 892                 } else {
 893                         if (t->zsd_destroy != NULL &&
 894                             (t->zsd_flags & ZSD_DESTROY_ALL) == 0) {
 895                                 t->zsd_flags |= ZSD_DESTROY_NEEDED;
 896                                 DTRACE_PROBE2(zsd__destroy__needed,
 897                                     zone_t *, zone, zone_key_t, key);
 898                         }
 899                 }
 900         }


 902 
 903         /* Now call the shutdown and destroy callback for this key */
 904         zsd_apply_all_keys(zsd_apply_shutdown, zone);
 905         zsd_apply_all_keys(zsd_apply_destroy, zone);
 906 
 907 }
 908 
 909 /*
 910  * Called when the zone is going away; free ZSD-related memory, and
 911  * destroy the zone_zsd list.
 912  */
 913 static void
 914 zone_free_zsd(zone_t *zone)
 915 {
 916         struct zsd_entry *t, *next;
 917 
 918         /*
 919          * Free all the zsd_entry's we had on this zone.
 920          */
 921         mutex_enter(&zone->zone_lock);
 922         for (t = list_head(&zone->zone_zsd); t != NULL; t = next) {
 923                 next = list_next(&zone->zone_zsd, t);
 924                 list_remove(&zone->zone_zsd, t);
 925                 ASSERT(!(t->zsd_flags & ZSD_ALL_INPROGRESS));
 926                 kmem_free(t, sizeof (*t));
 927         }
 928         list_destroy(&zone->zone_zsd);
 929         mutex_exit(&zone->zone_lock);
 930 
 931 }
 932 
 933 /*
 934  * Apply a function to all zones for particular key value.
 935  *
 936  * The applyfn has to drop zonehash_lock if it does some work, and
 937  * then reacquire it before it returns.
 938  * When the lock is dropped we don't follow list_next even
 939  * if it is possible to do so without any hazards. This is
 940  * because we want the design to allow for the list of zones
 941  * to change in any arbitrary way during the time the
 942  * lock was dropped.
 943  *


1284                 }
1285                 cv_wait(&t->zsd_cv, &zone->zone_lock);
1286                 if (lockp != NULL) {
1287                         /* First drop zone_lock to preserve order */
1288                         mutex_exit(&zone->zone_lock);
1289                         mutex_enter(lockp);
1290                         mutex_enter(&zone->zone_lock);
1291                 }
1292         }
1293         return (dropped);
1294 }
1295 
1296 /*
1297  * Frees memory associated with the zone dataset list.
1298  */
1299 static void
1300 zone_free_datasets(zone_t *zone)
1301 {
1302         zone_dataset_t *t, *next;
1303 
1304         for (t = list_head(&zone->zone_datasets); t != NULL; t = next) {
1305                 next = list_next(&zone->zone_datasets, t);
1306                 list_remove(&zone->zone_datasets, t);
1307                 kmem_free(t->zd_dataset, strlen(t->zd_dataset) + 1);
1308                 kmem_free(t, sizeof (*t));
1309         }
1310         list_destroy(&zone->zone_datasets);
1311 }
1312 
1313 /*
1314  * zone.cpu-shares resource control support.
1315  */
1316 /*ARGSUSED*/
1317 static rctl_qty_t
1318 zone_cpu_shares_usage(rctl_t *rctl, struct proc *p)
1319 {
1320         ASSERT(MUTEX_HELD(&p->p_lock));
1321         return (p->p_zone->zone_shares);
1322 }
1323 
1324 /*ARGSUSED*/
1325 static int


3022  *
3023  * As with the other zone_find_by_*() functions, the caller is
3024  * responsible for zone_rele()ing the return value of this function.
3025  */
3026 zone_t *
3027 zone_find_by_path(const char *path)
3028 {
3029         zone_t *zone;
3030         zone_t *zret = NULL;
3031         zone_status_t status;
3032 
3033         if (path == NULL) {
3034                 /*
3035                  * Call from rootconf().
3036                  */
3037                 zone_hold(global_zone);
3038                 return (global_zone);
3039         }
3040         ASSERT(*path == '/');
3041         mutex_enter(&zonehash_lock);
3042         for (zone = list_head(&zone_active); zone != NULL;
3043             zone = list_next(&zone_active, zone)) {
3044                 if (ZONE_PATH_VISIBLE(path, zone))
3045                         zret = zone;
3046         }
3047         ASSERT(zret != NULL);
3048         status = zone_status_get(zret);
3049         if (status < ZONE_IS_READY || status > ZONE_IS_DOWN) {
3050                 /*
3051                  * Zone practically doesn't exist.
3052                  */
3053                 zret = global_zone;
3054         }
3055         zone_hold(zret);
3056         mutex_exit(&zonehash_lock);
3057         return (zret);
3058 }
3059 
3060 /*
3061  * Public interface for updating per-zone load averages.  Called once per
3062  * second.
3063  *


3241                 zone->zone_ncpus_online = 0;
3242         }
3243 }
3244 
3245 /*
3246  * Walk the list of active zones and issue the provided callback for
3247  * each of them.
3248  *
3249  * Caller must not be holding any locks that may be acquired under
3250  * zonehash_lock.  See comment at the beginning of the file for a list of
3251  * common locks and their interactions with zones.
3252  */
3253 int
3254 zone_walk(int (*cb)(zone_t *, void *), void *data)
3255 {
3256         zone_t *zone;
3257         int ret = 0;
3258         zone_status_t status;
3259 
3260         mutex_enter(&zonehash_lock);
3261         for (zone = list_head(&zone_active); zone != NULL;
3262             zone = list_next(&zone_active, zone)) {
3263                 /*
3264                  * Skip zones that shouldn't be externally visible.
3265                  */
3266                 status = zone_status_get(zone);
3267                 if (status < ZONE_IS_READY || status > ZONE_IS_DOWN)
3268                         continue;
3269                 /*
3270                  * Bail immediately if any callback invocation returns a
3271                  * non-zero value.
3272                  */
3273                 ret = (*cb)(zone, data);
3274                 if (ret != 0)
3275                         break;
3276         }
3277         mutex_exit(&zonehash_lock);
3278         return (ret);
3279 }
3280 
3281 static int
3282 zone_set_root(zone_t *zone, const char *upath)


4033 /*
4034  * Helper function to make sure that a zone created on 'rootpath'
4035  * wouldn't end up containing other zones' rootpaths.
4036  */
4037 static boolean_t
4038 zone_is_nested(const char *rootpath)
4039 {
4040         zone_t *zone;
4041         size_t rootpathlen = strlen(rootpath);
4042         size_t len;
4043 
4044         ASSERT(MUTEX_HELD(&zonehash_lock));
4045 
4046         /*
4047          * zone_set_root() appended '/' and '\0' at the end of rootpath
4048          */
4049         if ((rootpathlen <= 3) && (rootpath[0] == '/') &&
4050             (rootpath[1] == '/') && (rootpath[2] == '\0'))
4051                 return (B_TRUE);
4052 
4053         for (zone = list_head(&zone_active); zone != NULL;
4054             zone = list_next(&zone_active, zone)) {
4055                 if (zone == global_zone)
4056                         continue;
4057                 len = strlen(zone->zone_rootpath);
4058                 if (strncmp(rootpath, zone->zone_rootpath,
4059                     MIN(rootpathlen, len)) == 0)
4060                         return (B_TRUE);
4061         }
4062         return (B_FALSE);
4063 }
4064 
4065 static int
4066 zone_set_privset(zone_t *zone, const priv_set_t *zone_privs,
4067     size_t zone_privssz)
4068 {
4069         priv_set_t *privs;
4070 
4071         if (zone_privssz < sizeof (priv_set_t))
4072                 return (ENOMEM);
4073 
4074         privs = kmem_alloc(sizeof (priv_set_t), KM_SLEEP);


5715         mutex_enter(&ct->ct_lock);
5716         mutex_enter(&pp->p_lock);
5717         if ((avl_numnodes(&pp->p_ct_held) != 0) || (ctp->conp_nmembers != 1)) {
5718                 mutex_exit(&pp->p_lock);
5719                 mutex_exit(&ct->ct_lock);
5720                 mutex_exit(&zonehash_lock);
5721                 err = EINVAL;
5722                 goto out;
5723         }
5724 
5725         /*
5726          * Moreover, we don't allow processes whose encapsulating
5727          * process contracts have inherited extrazonal contracts.
5728          * While it would be easier to eliminate all process contracts
5729          * with inherited contracts, we need to be able to give a
5730          * restarted init (or other zone-penetrating process) its
5731          * predecessor's contracts.
5732          */
5733         if (ctp->conp_ninherited != 0) {
5734                 contract_t *next;
5735                 for (next = list_head(&ctp->conp_inherited); next;
5736                     next = list_next(&ctp->conp_inherited, next)) {
5737                         if (contract_getzuniqid(next) != zone->zone_uniqid) {
5738                                 mutex_exit(&pp->p_lock);
5739                                 mutex_exit(&ct->ct_lock);
5740                                 mutex_exit(&zonehash_lock);
5741                                 err = EINVAL;
5742                                 goto out;
5743                         }
5744                 }
5745         }
5746 
5747         mutex_exit(&pp->p_lock);
5748         mutex_exit(&ct->ct_lock);
5749 
5750         status = zone_status_get(zone);
5751         if (status < ZONE_IS_READY || status >= ZONE_IS_SHUTTING_DOWN) {
5752                 /*
5753                  * Can't join
5754                  */
5755                 mutex_exit(&zonehash_lock);
5756                 err = EINVAL;


6074                 return (set_errno(EFAULT));
6075 
6076         myzone = curproc->p_zone;
6077         if (myzone != global_zone) {
6078                 bslabel_t *mybslab;
6079 
6080                 if (!is_system_labeled()) {
6081                         /* just return current zone */
6082                         real_nzones = domi_nzones = 1;
6083                         zoneids = kmem_alloc(sizeof (zoneid_t), KM_SLEEP);
6084                         zoneids[0] = myzone->zone_id;
6085                 } else {
6086                         /* return all zones that are dominated */
6087                         mutex_enter(&zonehash_lock);
6088                         real_nzones = zonecount;
6089                         domi_nzones = 0;
6090                         if (real_nzones > 0) {
6091                                 zoneids = kmem_alloc(real_nzones *
6092                                     sizeof (zoneid_t), KM_SLEEP);
6093                                 mybslab = label2bslabel(myzone->zone_slabel);
6094                                 for (zone = list_head(&zone_active);
6095                                     zone != NULL;
6096                                     zone = list_next(&zone_active, zone)) {
6097                                         if (zone->zone_id == GLOBAL_ZONEID)
6098                                                 continue;
6099                                         if (zone != myzone &&
6100                                             (zone->zone_flags & ZF_IS_SCRATCH))
6101                                                 continue;
6102                                         /*
6103                                          * Note that a label always dominates
6104                                          * itself, so myzone is always included
6105                                          * in the list.
6106                                          */
6107                                         if (bldominates(mybslab,
6108                                             label2bslabel(zone->zone_slabel))) {
6109                                                 zoneids[domi_nzones++] =
6110                                                     zone->zone_id;
6111                                         }
6112                                 }
6113                         }
6114                         mutex_exit(&zonehash_lock);
6115                 }
6116         } else {
6117                 mutex_enter(&zonehash_lock);
6118                 real_nzones = zonecount;
6119                 domi_nzones = 0;
6120                 if (real_nzones > 0) {
6121                         zoneids = kmem_alloc(real_nzones * sizeof (zoneid_t),
6122                             KM_SLEEP);
6123                         for (zone = list_head(&zone_active); zone != NULL;
6124                             zone = list_next(&zone_active, zone))
6125                                 zoneids[domi_nzones++] = zone->zone_id;
6126                         ASSERT(domi_nzones == real_nzones);
6127                 }
6128                 mutex_exit(&zonehash_lock);
6129         }
6130 
6131         /*
6132          * If user has allocated space for fewer entries than we found, then
6133          * return only up to his limit.  Either way, tell him exactly how many
6134          * we found.
6135          */
6136         if (domi_nzones < user_nzones)
6137                 user_nzones = domi_nzones;
6138         error = 0;
6139         if (copyout(&domi_nzones, numzones, sizeof (uint_t)) != 0) {
6140                 error = EFAULT;
6141         } else if (zoneidlist != NULL && user_nzones != 0) {
6142                 if (copyout(zoneids, zoneidlist,
6143                     user_nzones * sizeof (zoneid_t)) != 0)
6144                         error = EFAULT;


6569 {
6570         zone_t *current_zonep;
6571 
6572         ASSERT(INGLOBALZONE(curproc));
6573         mutex_enter(&zonehash_lock);
6574         mutex_enter(&zone_status_lock);
6575 
6576         /* Modify the global zone's status first. */
6577         ASSERT(zone_status_get(global_zone) == ZONE_IS_RUNNING);
6578         zone_status_set(global_zone, ZONE_IS_SHUTTING_DOWN);
6579 
6580         /*
6581          * Now change the states of all running zones to ZONE_IS_SHUTTING_DOWN.
6582          * We don't mark all zones with ZONE_IS_SHUTTING_DOWN because doing so
6583          * could cause assertions to fail (e.g., assertions about a zone's
6584          * state during initialization, readying, or booting) or produce races.
6585          * We'll let threads continue to initialize and ready new zones: they'll
6586          * fail to boot the new zones when they see that the global zone is
6587          * shutting down.
6588          */
6589         for (current_zonep = list_head(&zone_active); current_zonep != NULL;
6590             current_zonep = list_next(&zone_active, current_zonep)) {
6591                 if (zone_status_get(current_zonep) == ZONE_IS_RUNNING)
6592                         zone_status_set(current_zonep, ZONE_IS_SHUTTING_DOWN);
6593         }
6594         mutex_exit(&zone_status_lock);
6595         mutex_exit(&zonehash_lock);
6596 }
6597 
6598 /*
6599  * Returns true if the named dataset is visible in the current zone.
6600  * The 'write' parameter is set to 1 if the dataset is also writable.
6601  */
6602 int
6603 zone_dataset_visible(const char *dataset, int *write)
6604 {
6605         static int zfstype = -1;
6606         zone_dataset_t *zd;
6607         size_t len;
6608         zone_t *zone = curproc->p_zone;
6609         const char *name = NULL;
6610         vfs_t *vfsp = NULL;
6611 
6612         if (dataset[0] == '\0')
6613                 return (0);
6614 
6615         /*
6616          * Walk the list once, looking for datasets which match exactly, or
6617          * specify a dataset underneath an exported dataset.  If found, return
6618          * true and note that it is writable.
6619          */
6620         for (zd = list_head(&zone->zone_datasets); zd != NULL;
6621             zd = list_next(&zone->zone_datasets, zd)) {
6622 
6623                 len = strlen(zd->zd_dataset);
6624                 if (strlen(dataset) >= len &&
6625                     bcmp(dataset, zd->zd_dataset, len) == 0 &&
6626                     (dataset[len] == '\0' || dataset[len] == '/' ||
6627                     dataset[len] == '@')) {
6628                         if (write)
6629                                 *write = 1;
6630                         return (1);
6631                 }
6632         }
6633 
6634         /*
6635          * Walk the list a second time, searching for datasets which are parents
6636          * of exported datasets.  These should be visible, but read-only.
6637          *
6638          * Note that we also have to support forms such as 'pool/dataset/', with
6639          * a trailing slash.
6640          */
6641         for (zd = list_head(&zone->zone_datasets); zd != NULL;
6642             zd = list_next(&zone->zone_datasets, zd)) {
6643 
6644                 len = strlen(dataset);
6645                 if (dataset[len - 1] == '/')
6646                         len--;  /* Ignore trailing slash */
6647                 if (len < strlen(zd->zd_dataset) &&
6648                     bcmp(dataset, zd->zd_dataset, len) == 0 &&
6649                     zd->zd_dataset[len] == '/') {
6650                         if (write)
6651                                 *write = 0;
6652                         return (1);
6653                 }
6654         }
6655 
6656         /*
6657          * We reach here if the given dataset is not found in the zone_dataset
6658          * list. Check if this dataset was added as a filesystem (ie. "add fs")
6659          * instead of delegation. For this we search for the dataset in the
6660          * zone_vfslist of this zone. If found, return true and note that it is
6661          * not writable.
6662          */
6663 


6728  *
6729  * The caller is responsible for zone_rele of the returned zone.
6730  */
6731 zone_t *
6732 zone_find_by_any_path(const char *path, boolean_t treat_abs)
6733 {
6734         zone_t *zone;
6735         int path_offset = 0;
6736 
6737         if (path == NULL) {
6738                 zone_hold(global_zone);
6739                 return (global_zone);
6740         }
6741 
6742         if (*path != '/') {
6743                 ASSERT(treat_abs);
6744                 path_offset = 1;
6745         }
6746 
6747         mutex_enter(&zonehash_lock);
6748         for (zone = list_head(&zone_active); zone != NULL;
6749             zone = list_next(&zone_active, zone)) {
6750                 char    *c;
6751                 size_t  pathlen;
6752                 char *rootpath_start;
6753 
6754                 if (zone == global_zone)        /* skip global zone */
6755                         continue;
6756 
6757                 /* scan backwards to find start of last component */
6758                 c = zone->zone_rootpath + zone->zone_rootpathlen - 2;
6759                 do {
6760                         c--;
6761                 } while (*c != '/');
6762 
6763                 pathlen = c - zone->zone_rootpath + 1 - path_offset;
6764                 rootpath_start = (zone->zone_rootpath + path_offset);
6765                 if (strncmp(path, rootpath_start, pathlen) == 0)
6766                         break;
6767         }
6768         if (zone == NULL)
6769                 zone = global_zone;
6770         zone_hold(zone);
6771         mutex_exit(&zonehash_lock);
6772         return (zone);
6773 }
6774 
6775 /*
6776  * Finds a zone_dl_t with the given linkid in the given zone.  Returns the
6777  * zone_dl_t pointer if found, and NULL otherwise.
6778  */
6779 static zone_dl_t *
6780 zone_find_dl(zone_t *zone, datalink_id_t linkid)
6781 {
6782         zone_dl_t *zdl;
6783 
6784         ASSERT(mutex_owned(&zone->zone_lock));
6785         for (zdl = list_head(&zone->zone_dl_list); zdl != NULL;
6786             zdl = list_next(&zone->zone_dl_list, zdl)) {
6787                 if (zdl->zdl_id == linkid)
6788                         break;
6789         }
6790         return (zdl);
6791 }
6792 
6793 static boolean_t
6794 zone_dl_exists(zone_t *zone, datalink_id_t linkid)
6795 {
6796         boolean_t exists;
6797 
6798         mutex_enter(&zone->zone_lock);
6799         exists = (zone_find_dl(zone, linkid) != NULL);
6800         mutex_exit(&zone->zone_lock);
6801         return (exists);
6802 }
6803 
6804 /*
6805  * Add an data link name for the zone.
6806  */
6807 static int
6808 zone_add_datalink(zoneid_t zoneid, datalink_id_t linkid)
6809 {
6810         zone_dl_t *zdl;
6811         zone_t *zone;
6812         zone_t *thiszone;
6813 
6814         if ((thiszone = zone_find_by_id(zoneid)) == NULL)
6815                 return (set_errno(ENXIO));
6816 
6817         /* Verify that the datalink ID doesn't already belong to a zone. */
6818         mutex_enter(&zonehash_lock);
6819         for (zone = list_head(&zone_active); zone != NULL;
6820             zone = list_next(&zone_active, zone)) {
6821                 if (zone_dl_exists(zone, linkid)) {
6822                         mutex_exit(&zonehash_lock);
6823                         zone_rele(thiszone);
6824                         return (set_errno((zone == thiszone) ? EEXIST : EPERM));
6825                 }
6826         }
6827 
6828         zdl = kmem_zalloc(sizeof (*zdl), KM_SLEEP);
6829         zdl->zdl_id = linkid;
6830         zdl->zdl_net = NULL;
6831         mutex_enter(&thiszone->zone_lock);
6832         list_insert_head(&thiszone->zone_dl_list, zdl);
6833         mutex_exit(&thiszone->zone_lock);
6834         mutex_exit(&zonehash_lock);
6835         zone_rele(thiszone);
6836         return (0);
6837 }
6838 
6839 static int
6840 zone_remove_datalink(zoneid_t zoneid, datalink_id_t linkid)


6864  * Using the zoneidp as ALL_ZONES, we can lookup which zone has been assigned
6865  * the linkid.  Otherwise we just check if the specified zoneidp has been
6866  * assigned the supplied linkid.
6867  */
6868 int
6869 zone_check_datalink(zoneid_t *zoneidp, datalink_id_t linkid)
6870 {
6871         zone_t *zone;
6872         int err = ENXIO;
6873 
6874         if (*zoneidp != ALL_ZONES) {
6875                 if ((zone = zone_find_by_id(*zoneidp)) != NULL) {
6876                         if (zone_dl_exists(zone, linkid))
6877                                 err = 0;
6878                         zone_rele(zone);
6879                 }
6880                 return (err);
6881         }
6882 
6883         mutex_enter(&zonehash_lock);
6884         for (zone = list_head(&zone_active); zone != NULL;
6885             zone = list_next(&zone_active, zone)) {
6886                 if (zone_dl_exists(zone, linkid)) {
6887                         *zoneidp = zone->zone_id;
6888                         err = 0;
6889                         break;
6890                 }
6891         }
6892         mutex_exit(&zonehash_lock);
6893         return (err);
6894 }
6895 
6896 /*
6897  * Get the list of datalink IDs assigned to a zone.
6898  *
6899  * On input, *nump is the number of datalink IDs that can fit in the supplied
6900  * idarray.  Upon return, *nump is either set to the number of datalink IDs
6901  * that were placed in the array if the array was large enough, or to the
6902  * number of datalink IDs that the function needs to place in the array if the
6903  * array is too small.
6904  */
6905 static int
6906 zone_list_datalink(zoneid_t zoneid, int *nump, datalink_id_t *idarray)
6907 {
6908         uint_t num, dlcount;
6909         zone_t *zone;
6910         zone_dl_t *zdl;
6911         datalink_id_t *idptr = idarray;
6912 
6913         if (copyin(nump, &dlcount, sizeof (dlcount)) != 0)
6914                 return (set_errno(EFAULT));
6915         if ((zone = zone_find_by_id(zoneid)) == NULL)
6916                 return (set_errno(ENXIO));
6917 
6918         num = 0;
6919         mutex_enter(&zone->zone_lock);
6920         for (zdl = list_head(&zone->zone_dl_list); zdl != NULL;
6921             zdl = list_next(&zone->zone_dl_list, zdl)) {
6922                 /*
6923                  * If the list is bigger than what the caller supplied, just
6924                  * count, don't do copyout.
6925                  */
6926                 if (++num > dlcount)
6927                         continue;
6928                 if (copyout(&zdl->zdl_id, idptr, sizeof (*idptr)) != 0) {
6929                         mutex_exit(&zone->zone_lock);
6930                         zone_rele(zone);
6931                         return (set_errno(EFAULT));
6932                 }
6933                 idptr++;
6934         }
6935         mutex_exit(&zone->zone_lock);
6936         zone_rele(zone);
6937 
6938         /* Increased or decreased, caller should be notified. */
6939         if (num != dlcount) {
6940                 if (copyout(&num, nump, sizeof (num)) != 0)
6941                         return (set_errno(EFAULT));


6975  * Walk the datalinks for a given zone
6976  */
6977 int
6978 zone_datalink_walk(zoneid_t zoneid, int (*cb)(datalink_id_t, void *),
6979     void *data)
6980 {
6981         zone_t          *zone;
6982         zone_dl_t       *zdl;
6983         datalink_id_t   *idarray;
6984         uint_t          idcount = 0;
6985         int             i, ret = 0;
6986 
6987         if ((zone = zone_find_by_id(zoneid)) == NULL)
6988                 return (ENOENT);
6989 
6990         /*
6991          * We first build an array of linkid's so that we can walk these and
6992          * execute the callback with the zone_lock dropped.
6993          */
6994         mutex_enter(&zone->zone_lock);
6995         for (zdl = list_head(&zone->zone_dl_list); zdl != NULL;
6996             zdl = list_next(&zone->zone_dl_list, zdl)) {
6997                 idcount++;
6998         }
6999 
7000         if (idcount == 0) {
7001                 mutex_exit(&zone->zone_lock);
7002                 zone_rele(zone);
7003                 return (0);
7004         }
7005 
7006         idarray = kmem_alloc(sizeof (datalink_id_t) * idcount, KM_NOSLEEP);
7007         if (idarray == NULL) {
7008                 mutex_exit(&zone->zone_lock);
7009                 zone_rele(zone);
7010                 return (ENOMEM);
7011         }
7012 
7013         for (i = 0, zdl = list_head(&zone->zone_dl_list); zdl != NULL;
7014             i++, zdl = list_next(&zone->zone_dl_list, zdl)) {
7015                 idarray[i] = zdl->zdl_id;

7016         }
7017 
7018         mutex_exit(&zone->zone_lock);
7019 
7020         for (i = 0; i < idcount && ret == 0; i++) {
7021                 if ((ret = (*cb)(idarray[i], data)) != 0)
7022                         break;
7023         }
7024 
7025         zone_rele(zone);
7026         kmem_free(idarray, sizeof (datalink_id_t) * idcount);
7027         return (ret);
7028 }
7029 
7030 static char *
7031 zone_net_type2name(int type)
7032 {
7033         switch (type) {
7034         case ZONE_NETWORK_ADDRESS:
7035                 return (ZONE_NET_ADDRNAME);




 559  * When new zones are created constructor callbacks for all registered ZSD
 560  * entries will be called. That also uses the above two phases of marking
 561  * what needs to be done, and then running the callbacks without holding
 562  * any locks.
 563  *
 564  * The framework does not provide any locking around zone_getspecific() and
 565  * zone_setspecific() apart from that needed for internal consistency, so
 566  * callers interested in atomic "test-and-set" semantics will need to provide
 567  * their own locking.
 568  */
 569 
 570 /*
 571  * Helper function to find the zsd_entry associated with the key in the
 572  * given list.
 573  */
 574 static struct zsd_entry *
 575 zsd_find(list_t *l, zone_key_t key)
 576 {
 577         struct zsd_entry *zsd;
 578 
 579         list_for_each(l, zsd) {
 580                 if (zsd->zsd_key == key) {
 581                         return (zsd);
 582                 }
 583         }
 584         return (NULL);
 585 }
 586 
 587 /*
 588  * Helper function to find the zsd_entry associated with the key in the
 589  * given list. Move it to the front of the list.
 590  */
 591 static struct zsd_entry *
 592 zsd_find_mru(list_t *l, zone_key_t key)
 593 {
 594         struct zsd_entry *zsd;
 595 
 596         list_for_each(l, zsd) {
 597                 if (zsd->zsd_key == key) {
 598                         /*
 599                          * Move to head of list to keep list in MRU order.
 600                          */
 601                         if (zsd != list_head(l)) {
 602                                 list_remove(l, zsd);
 603                                 list_insert_head(l, zsd);
 604                         }
 605                         return (zsd);
 606                 }
 607         }
 608         return (NULL);
 609 }
 610 
 611 void
 612 zone_key_create(zone_key_t *keyp, void *(*create)(zoneid_t),
 613     void (*shutdown)(zoneid_t, void *), void (*destroy)(zoneid_t, void *))
 614 {
 615         struct zsd_entry *zsdp;
 616         struct zsd_entry *t;


 621         zsdp->zsd_data = NULL;
 622         zsdp->zsd_create = create;
 623         zsdp->zsd_shutdown = shutdown;
 624         zsdp->zsd_destroy = destroy;
 625 
 626         /*
 627          * Insert in global list of callbacks. Makes future zone creations
 628          * see it.
 629          */
 630         mutex_enter(&zsd_key_lock);
 631         key = zsdp->zsd_key = ++zsd_keyval;
 632         ASSERT(zsd_keyval != 0);
 633         list_insert_tail(&zsd_registered_keys, zsdp);
 634         mutex_exit(&zsd_key_lock);
 635 
 636         /*
 637          * Insert for all existing zones and mark them as needing
 638          * a create callback.
 639          */
 640         mutex_enter(&zonehash_lock);        /* stop the world */
 641         list_for_each(&zone_active, zone) {

 642                 zone_status_t status;
 643 
 644                 mutex_enter(&zone->zone_lock);
 645 
 646                 /* Skip zones that are on the way down or not yet up */
 647                 status = zone_status_get(zone);
 648                 if (status >= ZONE_IS_DOWN ||
 649                     status == ZONE_IS_UNINITIALIZED) {
 650                         mutex_exit(&zone->zone_lock);
 651                         continue;
 652                 }
 653 
 654                 t = zsd_find_mru(&zone->zone_zsd, key);
 655                 if (t != NULL) {
 656                         /*
 657                          * A zsd_configure already inserted it after
 658                          * we dropped zsd_key_lock above.
 659                          */
 660                         mutex_exit(&zone->zone_lock);
 661                         continue;


 697  * be called under a global lock. Then call the functions without
 698  * holding any locks. Finally free up the zone_zsd entries. (The apply
 699  * functions need to access the zone_zsd entries to find zsd_data etc.)
 700  */
 701 int
 702 zone_key_delete(zone_key_t key)
 703 {
 704         struct zsd_entry *zsdp = NULL;
 705         zone_t *zone;
 706 
 707         mutex_enter(&zsd_key_lock);
 708         zsdp = zsd_find_mru(&zsd_registered_keys, key);
 709         if (zsdp == NULL) {
 710                 mutex_exit(&zsd_key_lock);
 711                 return (-1);
 712         }
 713         list_remove(&zsd_registered_keys, zsdp);
 714         mutex_exit(&zsd_key_lock);
 715 
 716         mutex_enter(&zonehash_lock);
 717         list_for_each(&zone_active, zone) {

 718                 struct zsd_entry *del;
 719 
 720                 mutex_enter(&zone->zone_lock);
 721                 del = zsd_find_mru(&zone->zone_zsd, key);
 722                 if (del == NULL) {
 723                         /*
 724                          * Somebody else got here first e.g the zone going
 725                          * away.
 726                          */
 727                         mutex_exit(&zone->zone_lock);
 728                         continue;
 729                 }
 730                 ASSERT(del->zsd_shutdown == zsdp->zsd_shutdown);
 731                 ASSERT(del->zsd_destroy == zsdp->zsd_destroy);
 732                 if (del->zsd_shutdown != NULL &&
 733                     (del->zsd_flags & ZSD_SHUTDOWN_ALL) == 0) {
 734                         del->zsd_flags |= ZSD_SHUTDOWN_NEEDED;
 735                         DTRACE_PROBE2(zsd__shutdown__needed,
 736                             zone_t *, zone, zone_key_t, key);
 737                 }
 738                 if (del->zsd_destroy != NULL &&
 739                     (del->zsd_flags & ZSD_DESTROY_ALL) == 0) {
 740                         del->zsd_flags |= ZSD_DESTROY_NEEDED;
 741                         DTRACE_PROBE2(zsd__destroy__needed,
 742                             zone_t *, zone, zone_key_t, key);
 743                 }
 744                 mutex_exit(&zone->zone_lock);
 745         }
 746         mutex_exit(&zonehash_lock);
 747         kmem_free(zsdp, sizeof (*zsdp));
 748 
 749         /* Now call the shutdown and destroy callback for this key */
 750         zsd_apply_all_zones(zsd_apply_shutdown, key);
 751         zsd_apply_all_zones(zsd_apply_destroy, key);
 752 
 753         /* Now we can free up the zsdp structures in each zone */
 754         mutex_enter(&zonehash_lock);
 755         list_for_each(&zone_active, zone) {

 756                 struct zsd_entry *del;
 757 
 758                 mutex_enter(&zone->zone_lock);
 759                 del = zsd_find(&zone->zone_zsd, key);
 760                 if (del != NULL) {
 761                         list_remove(&zone->zone_zsd, del);
 762                         ASSERT(!(del->zsd_flags & ZSD_ALL_INPROGRESS));
 763                         kmem_free(del, sizeof (*del));
 764                 }
 765                 mutex_exit(&zone->zone_lock);
 766         }
 767         mutex_exit(&zonehash_lock);
 768 
 769         return (0);
 770 }
 771 
 772 /*
 773  * ZSD counterpart of pthread_setspecific().
 774  *
 775  * Since all zsd callbacks, including those with no create function,


 811         mutex_exit(&zone->zone_lock);
 812         return (data);
 813 }
 814 
 815 /*
 816  * Function used to initialize a zone's list of ZSD callbacks and data
 817  * when the zone is being created.  The callbacks are initialized from
 818  * the template list (zsd_registered_keys). The constructor callback is
 819  * executed later (once the zone exists and with locks dropped).
 820  */
 821 static void
 822 zone_zsd_configure(zone_t *zone)
 823 {
 824         struct zsd_entry *zsdp;
 825         struct zsd_entry *t;
 826 
 827         ASSERT(MUTEX_HELD(&zonehash_lock));
 828         ASSERT(list_head(&zone->zone_zsd) == NULL);
 829         mutex_enter(&zone->zone_lock);
 830         mutex_enter(&zsd_key_lock);
 831         list_for_each(&zsd_registered_keys, zsdp) {

 832                 /*
 833                  * Since this zone is ZONE_IS_UNCONFIGURED, zone_key_create
 834                  * should not have added anything to it.
 835                  */
 836                 ASSERT(zsd_find(&zone->zone_zsd, zsdp->zsd_key) == NULL);
 837 
 838                 t = kmem_zalloc(sizeof (*t), KM_SLEEP);
 839                 t->zsd_key = zsdp->zsd_key;
 840                 t->zsd_create = zsdp->zsd_create;
 841                 t->zsd_shutdown = zsdp->zsd_shutdown;
 842                 t->zsd_destroy = zsdp->zsd_destroy;
 843                 if (zsdp->zsd_create != NULL) {
 844                         t->zsd_flags = ZSD_CREATE_NEEDED;
 845                         DTRACE_PROBE2(zsd__create__needed,
 846                             zone_t *, zone, zone_key_t, zsdp->zsd_key);
 847                 }
 848                 list_insert_tail(&zone->zone_zsd, t);
 849         }
 850         mutex_exit(&zsd_key_lock);
 851         mutex_exit(&zone->zone_lock);


 855 
 856 /*
 857  * Helper function to execute shutdown or destructor callbacks.
 858  */
 859 static void
 860 zone_zsd_callbacks(zone_t *zone, enum zsd_callback_type ct)
 861 {
 862         struct zsd_entry *t;
 863 
 864         ASSERT(ct == ZSD_SHUTDOWN || ct == ZSD_DESTROY);
 865         ASSERT(ct != ZSD_SHUTDOWN || zone_status_get(zone) >= ZONE_IS_EMPTY);
 866         ASSERT(ct != ZSD_DESTROY || zone_status_get(zone) >= ZONE_IS_DOWN);
 867 
 868         /*
 869          * Run the callback solely based on what is registered for the zone
 870          * in zone_zsd. The global list can change independently of this
 871          * as keys are registered and unregistered and we don't register new
 872          * callbacks for a zone that is in the process of going away.
 873          */
 874         mutex_enter(&zone->zone_lock);
 875         list_for_each(&zone->zone_zsd, t) {

 876                 zone_key_t key = t->zsd_key;
 877 
 878                 /* Skip if no callbacks registered */
 879 
 880                 if (ct == ZSD_SHUTDOWN) {
 881                         if (t->zsd_shutdown != NULL &&
 882                             (t->zsd_flags & ZSD_SHUTDOWN_ALL) == 0) {
 883                                 t->zsd_flags |= ZSD_SHUTDOWN_NEEDED;
 884                                 DTRACE_PROBE2(zsd__shutdown__needed,
 885                                     zone_t *, zone, zone_key_t, key);
 886                         }
 887                 } else {
 888                         if (t->zsd_destroy != NULL &&
 889                             (t->zsd_flags & ZSD_DESTROY_ALL) == 0) {
 890                                 t->zsd_flags |= ZSD_DESTROY_NEEDED;
 891                                 DTRACE_PROBE2(zsd__destroy__needed,
 892                                     zone_t *, zone, zone_key_t, key);
 893                         }
 894                 }
 895         }


 897 
 898         /* Now call the shutdown and destroy callback for this key */
 899         zsd_apply_all_keys(zsd_apply_shutdown, zone);
 900         zsd_apply_all_keys(zsd_apply_destroy, zone);
 901 
 902 }
 903 
 904 /*
 905  * Called when the zone is going away; free ZSD-related memory, and
 906  * destroy the zone_zsd list.
 907  */
 908 static void
 909 zone_free_zsd(zone_t *zone)
 910 {
 911         struct zsd_entry *t, *next;
 912 
 913         /*
 914          * Free all the zsd_entry's we had on this zone.
 915          */
 916         mutex_enter(&zone->zone_lock);
 917         list_for_each_safe(&zone->zone_zsd, t, next) {

 918                 list_remove(&zone->zone_zsd, t);
 919                 ASSERT(!(t->zsd_flags & ZSD_ALL_INPROGRESS));
 920                 kmem_free(t, sizeof (*t));
 921         }
 922         list_destroy(&zone->zone_zsd);
 923         mutex_exit(&zone->zone_lock);
 924 
 925 }
 926 
 927 /*
 928  * Apply a function to all zones for particular key value.
 929  *
 930  * The applyfn has to drop zonehash_lock if it does some work, and
 931  * then reacquire it before it returns.
 932  * When the lock is dropped we don't follow list_next even
 933  * if it is possible to do so without any hazards. This is
 934  * because we want the design to allow for the list of zones
 935  * to change in any arbitrary way during the time the
 936  * lock was dropped.
 937  *


1278                 }
1279                 cv_wait(&t->zsd_cv, &zone->zone_lock);
1280                 if (lockp != NULL) {
1281                         /* First drop zone_lock to preserve order */
1282                         mutex_exit(&zone->zone_lock);
1283                         mutex_enter(lockp);
1284                         mutex_enter(&zone->zone_lock);
1285                 }
1286         }
1287         return (dropped);
1288 }
1289 
1290 /*
1291  * Frees memory associated with the zone dataset list.
1292  */
1293 static void
1294 zone_free_datasets(zone_t *zone)
1295 {
1296         zone_dataset_t *t, *next;
1297 
1298         list_for_each_safe(&zone->zone_datasets, t, next) {

1299                 list_remove(&zone->zone_datasets, t);
1300                 kmem_free(t->zd_dataset, strlen(t->zd_dataset) + 1);
1301                 kmem_free(t, sizeof (*t));
1302         }
1303         list_destroy(&zone->zone_datasets);
1304 }
1305 
1306 /*
1307  * zone.cpu-shares resource control support.
1308  */
1309 /*ARGSUSED*/
1310 static rctl_qty_t
1311 zone_cpu_shares_usage(rctl_t *rctl, struct proc *p)
1312 {
1313         ASSERT(MUTEX_HELD(&p->p_lock));
1314         return (p->p_zone->zone_shares);
1315 }
1316 
1317 /*ARGSUSED*/
1318 static int


3015  *
3016  * As with the other zone_find_by_*() functions, the caller is
3017  * responsible for zone_rele()ing the return value of this function.
3018  */
3019 zone_t *
3020 zone_find_by_path(const char *path)
3021 {
3022         zone_t *zone;
3023         zone_t *zret = NULL;
3024         zone_status_t status;
3025 
3026         if (path == NULL) {
3027                 /*
3028                  * Call from rootconf().
3029                  */
3030                 zone_hold(global_zone);
3031                 return (global_zone);
3032         }
3033         ASSERT(*path == '/');
3034         mutex_enter(&zonehash_lock);
3035         list_for_each(&zone_active, zone) {

3036                 if (ZONE_PATH_VISIBLE(path, zone))
3037                         zret = zone;
3038         }
3039         ASSERT(zret != NULL);
3040         status = zone_status_get(zret);
3041         if (status < ZONE_IS_READY || status > ZONE_IS_DOWN) {
3042                 /*
3043                  * Zone practically doesn't exist.
3044                  */
3045                 zret = global_zone;
3046         }
3047         zone_hold(zret);
3048         mutex_exit(&zonehash_lock);
3049         return (zret);
3050 }
3051 
3052 /*
3053  * Public interface for updating per-zone load averages.  Called once per
3054  * second.
3055  *


3233                 zone->zone_ncpus_online = 0;
3234         }
3235 }
3236 
3237 /*
3238  * Walk the list of active zones and issue the provided callback for
3239  * each of them.
3240  *
3241  * Caller must not be holding any locks that may be acquired under
3242  * zonehash_lock.  See comment at the beginning of the file for a list of
3243  * common locks and their interactions with zones.
3244  */
3245 int
3246 zone_walk(int (*cb)(zone_t *, void *), void *data)
3247 {
3248         zone_t *zone;
3249         int ret = 0;
3250         zone_status_t status;
3251 
3252         mutex_enter(&zonehash_lock);
3253         list_for_each(&zone_active, zone) {

3254                 /*
3255                  * Skip zones that shouldn't be externally visible.
3256                  */
3257                 status = zone_status_get(zone);
3258                 if (status < ZONE_IS_READY || status > ZONE_IS_DOWN)
3259                         continue;
3260                 /*
3261                  * Bail immediately if any callback invocation returns a
3262                  * non-zero value.
3263                  */
3264                 ret = (*cb)(zone, data);
3265                 if (ret != 0)
3266                         break;
3267         }
3268         mutex_exit(&zonehash_lock);
3269         return (ret);
3270 }
3271 
3272 static int
3273 zone_set_root(zone_t *zone, const char *upath)


4024 /*
4025  * Helper function to make sure that a zone created on 'rootpath'
4026  * wouldn't end up containing other zones' rootpaths.
4027  */
4028 static boolean_t
4029 zone_is_nested(const char *rootpath)
4030 {
4031         zone_t *zone;
4032         size_t rootpathlen = strlen(rootpath);
4033         size_t len;
4034 
4035         ASSERT(MUTEX_HELD(&zonehash_lock));
4036 
4037         /*
4038          * zone_set_root() appended '/' and '\0' at the end of rootpath
4039          */
4040         if ((rootpathlen <= 3) && (rootpath[0] == '/') &&
4041             (rootpath[1] == '/') && (rootpath[2] == '\0'))
4042                 return (B_TRUE);
4043 
4044         list_for_each(&zone_active, zone) {

4045                 if (zone == global_zone)
4046                         continue;
4047                 len = strlen(zone->zone_rootpath);
4048                 if (strncmp(rootpath, zone->zone_rootpath,
4049                     MIN(rootpathlen, len)) == 0)
4050                         return (B_TRUE);
4051         }
4052         return (B_FALSE);
4053 }
4054 
4055 static int
4056 zone_set_privset(zone_t *zone, const priv_set_t *zone_privs,
4057     size_t zone_privssz)
4058 {
4059         priv_set_t *privs;
4060 
4061         if (zone_privssz < sizeof (priv_set_t))
4062                 return (ENOMEM);
4063 
4064         privs = kmem_alloc(sizeof (priv_set_t), KM_SLEEP);


5705         mutex_enter(&ct->ct_lock);
5706         mutex_enter(&pp->p_lock);
5707         if ((avl_numnodes(&pp->p_ct_held) != 0) || (ctp->conp_nmembers != 1)) {
5708                 mutex_exit(&pp->p_lock);
5709                 mutex_exit(&ct->ct_lock);
5710                 mutex_exit(&zonehash_lock);
5711                 err = EINVAL;
5712                 goto out;
5713         }
5714 
5715         /*
5716          * Moreover, we don't allow processes whose encapsulating
5717          * process contracts have inherited extrazonal contracts.
5718          * While it would be easier to eliminate all process contracts
5719          * with inherited contracts, we need to be able to give a
5720          * restarted init (or other zone-penetrating process) its
5721          * predecessor's contracts.
5722          */
5723         if (ctp->conp_ninherited != 0) {
5724                 contract_t *next;
5725                 list_for_each(&ctp->conp_inherited, next) {

5726                         if (contract_getzuniqid(next) != zone->zone_uniqid) {
5727                                 mutex_exit(&pp->p_lock);
5728                                 mutex_exit(&ct->ct_lock);
5729                                 mutex_exit(&zonehash_lock);
5730                                 err = EINVAL;
5731                                 goto out;
5732                         }
5733                 }
5734         }
5735 
5736         mutex_exit(&pp->p_lock);
5737         mutex_exit(&ct->ct_lock);
5738 
5739         status = zone_status_get(zone);
5740         if (status < ZONE_IS_READY || status >= ZONE_IS_SHUTTING_DOWN) {
5741                 /*
5742                  * Can't join
5743                  */
5744                 mutex_exit(&zonehash_lock);
5745                 err = EINVAL;


6063                 return (set_errno(EFAULT));
6064 
6065         myzone = curproc->p_zone;
6066         if (myzone != global_zone) {
6067                 bslabel_t *mybslab;
6068 
6069                 if (!is_system_labeled()) {
6070                         /* just return current zone */
6071                         real_nzones = domi_nzones = 1;
6072                         zoneids = kmem_alloc(sizeof (zoneid_t), KM_SLEEP);
6073                         zoneids[0] = myzone->zone_id;
6074                 } else {
6075                         /* return all zones that are dominated */
6076                         mutex_enter(&zonehash_lock);
6077                         real_nzones = zonecount;
6078                         domi_nzones = 0;
6079                         if (real_nzones > 0) {
6080                                 zoneids = kmem_alloc(real_nzones *
6081                                     sizeof (zoneid_t), KM_SLEEP);
6082                                 mybslab = label2bslabel(myzone->zone_slabel);
6083                                 list_for_each(&zone_active, zone) {


6084                                         if (zone->zone_id == GLOBAL_ZONEID)
6085                                                 continue;
6086                                         if (zone != myzone &&
6087                                             (zone->zone_flags & ZF_IS_SCRATCH))
6088                                                 continue;
6089                                         /*
6090                                          * Note that a label always dominates
6091                                          * itself, so myzone is always included
6092                                          * in the list.
6093                                          */
6094                                         if (bldominates(mybslab,
6095                                             label2bslabel(zone->zone_slabel))) {
6096                                                 zoneids[domi_nzones++] =
6097                                                     zone->zone_id;
6098                                         }
6099                                 }
6100                         }
6101                         mutex_exit(&zonehash_lock);
6102                 }
6103         } else {
6104                 mutex_enter(&zonehash_lock);
6105                 real_nzones = zonecount;
6106                 domi_nzones = 0;
6107                 if (real_nzones > 0) {
6108                         zoneids = kmem_alloc(real_nzones * sizeof (zoneid_t),
6109                             KM_SLEEP);
6110                         list_for_each(&zone_active, zone)

6111                                 zoneids[domi_nzones++] = zone->zone_id;
6112                         ASSERT(domi_nzones == real_nzones);
6113                 }
6114                 mutex_exit(&zonehash_lock);
6115         }
6116 
6117         /*
6118          * If user has allocated space for fewer entries than we found, then
6119          * return only up to his limit.  Either way, tell him exactly how many
6120          * we found.
6121          */
6122         if (domi_nzones < user_nzones)
6123                 user_nzones = domi_nzones;
6124         error = 0;
6125         if (copyout(&domi_nzones, numzones, sizeof (uint_t)) != 0) {
6126                 error = EFAULT;
6127         } else if (zoneidlist != NULL && user_nzones != 0) {
6128                 if (copyout(zoneids, zoneidlist,
6129                     user_nzones * sizeof (zoneid_t)) != 0)
6130                         error = EFAULT;


6555 {
6556         zone_t *current_zonep;
6557 
6558         ASSERT(INGLOBALZONE(curproc));
6559         mutex_enter(&zonehash_lock);
6560         mutex_enter(&zone_status_lock);
6561 
6562         /* Modify the global zone's status first. */
6563         ASSERT(zone_status_get(global_zone) == ZONE_IS_RUNNING);
6564         zone_status_set(global_zone, ZONE_IS_SHUTTING_DOWN);
6565 
6566         /*
6567          * Now change the states of all running zones to ZONE_IS_SHUTTING_DOWN.
6568          * We don't mark all zones with ZONE_IS_SHUTTING_DOWN because doing so
6569          * could cause assertions to fail (e.g., assertions about a zone's
6570          * state during initialization, readying, or booting) or produce races.
6571          * We'll let threads continue to initialize and ready new zones: they'll
6572          * fail to boot the new zones when they see that the global zone is
6573          * shutting down.
6574          */
6575         list_for_each(&zone_active, cpurrent_zonep) {

6576                 if (zone_status_get(current_zonep) == ZONE_IS_RUNNING)
6577                         zone_status_set(current_zonep, ZONE_IS_SHUTTING_DOWN);
6578         }
6579         mutex_exit(&zone_status_lock);
6580         mutex_exit(&zonehash_lock);
6581 }
6582 
6583 /*
6584  * Returns true if the named dataset is visible in the current zone.
6585  * The 'write' parameter is set to 1 if the dataset is also writable.
6586  */
6587 int
6588 zone_dataset_visible(const char *dataset, int *write)
6589 {
6590         static int zfstype = -1;
6591         zone_dataset_t *zd;
6592         size_t len;
6593         zone_t *zone = curproc->p_zone;
6594         const char *name = NULL;
6595         vfs_t *vfsp = NULL;
6596 
6597         if (dataset[0] == '\0')
6598                 return (0);
6599 
6600         /*
6601          * Walk the list once, looking for datasets which match exactly, or
6602          * specify a dataset underneath an exported dataset.  If found, return
6603          * true and note that it is writable.
6604          */
6605         list_for_each(&zone->zone_datasets, zd) {


6606                 len = strlen(zd->zd_dataset);
6607                 if (strlen(dataset) >= len &&
6608                     bcmp(dataset, zd->zd_dataset, len) == 0 &&
6609                     (dataset[len] == '\0' || dataset[len] == '/' ||
6610                     dataset[len] == '@')) {
6611                         if (write)
6612                                 *write = 1;
6613                         return (1);
6614                 }
6615         }
6616 
6617         /*
6618          * Walk the list a second time, searching for datasets which are parents
6619          * of exported datasets.  These should be visible, but read-only.
6620          *
6621          * Note that we also have to support forms such as 'pool/dataset/', with
6622          * a trailing slash.
6623          */
6624         list_for_each(&zone->zone_dataset, zd) {


6625                 len = strlen(dataset);
6626                 if (dataset[len - 1] == '/')
6627                         len--;  /* Ignore trailing slash */
6628                 if (len < strlen(zd->zd_dataset) &&
6629                     bcmp(dataset, zd->zd_dataset, len) == 0 &&
6630                     zd->zd_dataset[len] == '/') {
6631                         if (write)
6632                                 *write = 0;
6633                         return (1);
6634                 }
6635         }
6636 
6637         /*
6638          * We reach here if the given dataset is not found in the zone_dataset
6639          * list. Check if this dataset was added as a filesystem (ie. "add fs")
6640          * instead of delegation. For this we search for the dataset in the
6641          * zone_vfslist of this zone. If found, return true and note that it is
6642          * not writable.
6643          */
6644 


6709  *
6710  * The caller is responsible for zone_rele of the returned zone.
6711  */
6712 zone_t *
6713 zone_find_by_any_path(const char *path, boolean_t treat_abs)
6714 {
6715         zone_t *zone;
6716         int path_offset = 0;
6717 
6718         if (path == NULL) {
6719                 zone_hold(global_zone);
6720                 return (global_zone);
6721         }
6722 
6723         if (*path != '/') {
6724                 ASSERT(treat_abs);
6725                 path_offset = 1;
6726         }
6727 
6728         mutex_enter(&zonehash_lock);
6729         list_for_each(&zone_active, zone) {

6730                 char    *c;
6731                 size_t  pathlen;
6732                 char *rootpath_start;
6733 
6734                 if (zone == global_zone)        /* skip global zone */
6735                         continue;
6736 
6737                 /* scan backwards to find start of last component */
6738                 c = zone->zone_rootpath + zone->zone_rootpathlen - 2;
6739                 do {
6740                         c--;
6741                 } while (*c != '/');
6742 
6743                 pathlen = c - zone->zone_rootpath + 1 - path_offset;
6744                 rootpath_start = (zone->zone_rootpath + path_offset);
6745                 if (strncmp(path, rootpath_start, pathlen) == 0)
6746                         break;
6747         }
6748         if (zone == NULL)
6749                 zone = global_zone;
6750         zone_hold(zone);
6751         mutex_exit(&zonehash_lock);
6752         return (zone);
6753 }
6754 
6755 /*
6756  * Finds a zone_dl_t with the given linkid in the given zone.  Returns the
6757  * zone_dl_t pointer if found, and NULL otherwise.
6758  */
6759 static zone_dl_t *
6760 zone_find_dl(zone_t *zone, datalink_id_t linkid)
6761 {
6762         zone_dl_t *zdl;
6763 
6764         ASSERT(mutex_owned(&zone->zone_lock));
6765         list_for_each(&zone->zone_dl_list, zdl) {

6766                 if (zdl->zdl_id == linkid)
6767                         break;
6768         }
6769         return (zdl);
6770 }
6771 
6772 static boolean_t
6773 zone_dl_exists(zone_t *zone, datalink_id_t linkid)
6774 {
6775         boolean_t exists;
6776 
6777         mutex_enter(&zone->zone_lock);
6778         exists = (zone_find_dl(zone, linkid) != NULL);
6779         mutex_exit(&zone->zone_lock);
6780         return (exists);
6781 }
6782 
6783 /*
6784  * Add an data link name for the zone.
6785  */
6786 static int
6787 zone_add_datalink(zoneid_t zoneid, datalink_id_t linkid)
6788 {
6789         zone_dl_t *zdl;
6790         zone_t *zone;
6791         zone_t *thiszone;
6792 
6793         if ((thiszone = zone_find_by_id(zoneid)) == NULL)
6794                 return (set_errno(ENXIO));
6795 
6796         /* Verify that the datalink ID doesn't already belong to a zone. */
6797         mutex_enter(&zonehash_lock);
6798         list_for_each(&zone_active, zone) {

6799                 if (zone_dl_exists(zone, linkid)) {
6800                         mutex_exit(&zonehash_lock);
6801                         zone_rele(thiszone);
6802                         return (set_errno((zone == thiszone) ? EEXIST : EPERM));
6803                 }
6804         }
6805 
6806         zdl = kmem_zalloc(sizeof (*zdl), KM_SLEEP);
6807         zdl->zdl_id = linkid;
6808         zdl->zdl_net = NULL;
6809         mutex_enter(&thiszone->zone_lock);
6810         list_insert_head(&thiszone->zone_dl_list, zdl);
6811         mutex_exit(&thiszone->zone_lock);
6812         mutex_exit(&zonehash_lock);
6813         zone_rele(thiszone);
6814         return (0);
6815 }
6816 
6817 static int
6818 zone_remove_datalink(zoneid_t zoneid, datalink_id_t linkid)


6842  * Using the zoneidp as ALL_ZONES, we can lookup which zone has been assigned
6843  * the linkid.  Otherwise we just check if the specified zoneidp has been
6844  * assigned the supplied linkid.
6845  */
6846 int
6847 zone_check_datalink(zoneid_t *zoneidp, datalink_id_t linkid)
6848 {
6849         zone_t *zone;
6850         int err = ENXIO;
6851 
6852         if (*zoneidp != ALL_ZONES) {
6853                 if ((zone = zone_find_by_id(*zoneidp)) != NULL) {
6854                         if (zone_dl_exists(zone, linkid))
6855                                 err = 0;
6856                         zone_rele(zone);
6857                 }
6858                 return (err);
6859         }
6860 
6861         mutex_enter(&zonehash_lock);
6862         list_for_each(&zone_active, zone) {

6863                 if (zone_dl_exists(zone, linkid)) {
6864                         *zoneidp = zone->zone_id;
6865                         err = 0;
6866                         break;
6867                 }
6868         }
6869         mutex_exit(&zonehash_lock);
6870         return (err);
6871 }
6872 
6873 /*
6874  * Get the list of datalink IDs assigned to a zone.
6875  *
6876  * On input, *nump is the number of datalink IDs that can fit in the supplied
6877  * idarray.  Upon return, *nump is either set to the number of datalink IDs
6878  * that were placed in the array if the array was large enough, or to the
6879  * number of datalink IDs that the function needs to place in the array if the
6880  * array is too small.
6881  */
6882 static int
6883 zone_list_datalink(zoneid_t zoneid, int *nump, datalink_id_t *idarray)
6884 {
6885         uint_t num, dlcount;
6886         zone_t *zone;
6887         zone_dl_t *zdl;
6888         datalink_id_t *idptr = idarray;
6889 
6890         if (copyin(nump, &dlcount, sizeof (dlcount)) != 0)
6891                 return (set_errno(EFAULT));
6892         if ((zone = zone_find_by_id(zoneid)) == NULL)
6893                 return (set_errno(ENXIO));
6894 
6895         num = 0;
6896         mutex_enter(&zone->zone_lock);
6897         list_for_each(&zone->zone_dl_list, zdl) {

6898                 /*
6899                  * If the list is bigger than what the caller supplied, just
6900                  * count, don't do copyout.
6901                  */
6902                 if (++num > dlcount)
6903                         continue;
6904                 if (copyout(&zdl->zdl_id, idptr, sizeof (*idptr)) != 0) {
6905                         mutex_exit(&zone->zone_lock);
6906                         zone_rele(zone);
6907                         return (set_errno(EFAULT));
6908                 }
6909                 idptr++;
6910         }
6911         mutex_exit(&zone->zone_lock);
6912         zone_rele(zone);
6913 
6914         /* Increased or decreased, caller should be notified. */
6915         if (num != dlcount) {
6916                 if (copyout(&num, nump, sizeof (num)) != 0)
6917                         return (set_errno(EFAULT));


6951  * Walk the datalinks for a given zone
6952  */
6953 int
6954 zone_datalink_walk(zoneid_t zoneid, int (*cb)(datalink_id_t, void *),
6955     void *data)
6956 {
6957         zone_t          *zone;
6958         zone_dl_t       *zdl;
6959         datalink_id_t   *idarray;
6960         uint_t          idcount = 0;
6961         int             i, ret = 0;
6962 
6963         if ((zone = zone_find_by_id(zoneid)) == NULL)
6964                 return (ENOENT);
6965 
6966         /*
6967          * We first build an array of linkid's so that we can walk these and
6968          * execute the callback with the zone_lock dropped.
6969          */
6970         mutex_enter(&zone->zone_lock);
6971         list_for_each(&zone->zone_dl_lists, zdl) {

6972                 idcount++;
6973         }
6974 
6975         if (idcount == 0) {
6976                 mutex_exit(&zone->zone_lock);
6977                 zone_rele(zone);
6978                 return (0);
6979         }
6980 
6981         idarray = kmem_alloc(sizeof (datalink_id_t) * idcount, KM_NOSLEEP);
6982         if (idarray == NULL) {
6983                 mutex_exit(&zone->zone_lock);
6984                 zone_rele(zone);
6985                 return (ENOMEM);
6986         }
6987 
6988         i = 0;
6989         list_for_each(&zone->zone_dl_list, zdl) {
6990                 idarray[i] = zdl->zdl_id;
6991                 i++;
6992         }
6993 
6994         mutex_exit(&zone->zone_lock);
6995 
6996         for (i = 0; i < idcount && ret == 0; i++) {
6997                 if ((ret = (*cb)(idarray[i], data)) != 0)
6998                         break;
6999         }
7000 
7001         zone_rele(zone);
7002         kmem_free(idarray, sizeof (datalink_id_t) * idcount);
7003         return (ret);
7004 }
7005 
7006 static char *
7007 zone_net_type2name(int type)
7008 {
7009         switch (type) {
7010         case ZONE_NETWORK_ADDRESS:
7011                 return (ZONE_NET_ADDRNAME);