Print this page
        
*** 19,30 ****
   * CDDL HEADER END
   */
  
  /*
   * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
-  * Copyright 2016, Joyent Inc.
   * Copyright (c) 2015 by Delphix. All rights reserved.
   */
  
  /*
   * Copyright 2011 Nexenta Systems, Inc.  All rights reserved.
   */
--- 19,30 ----
   * CDDL HEADER END
   */
  
  /*
   * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
   * Copyright (c) 2015 by Delphix. All rights reserved.
+  * Copyright 2016, Joyent Inc.
   */
  
  /*
   * Copyright 2011 Nexenta Systems, Inc.  All rights reserved.
   */
*** 134,146 ****
          MNTOPT_RO "," MNTOPT_LOFS_NOSUB "," MNTOPT_NODEVICES
  
  #define DFSTYPES        "/etc/dfs/fstypes"
  #define MAXTNZLEN       2048
  
- /* Number of times to retry unmounting if it fails */
- #define UMOUNT_RETRIES  30
- 
  /* a reasonable estimate for the number of lwps per process */
  #define LWPS_PER_PROCESS        10
  
  /* for routing socket */
  static int rts_seqno = 0;
--- 134,143 ----
*** 178,188 ****
  /* from libsocket, not in any header file */
  extern int getnetmaskbyaddr(struct in_addr, struct in_addr *);
  
  /* from zoneadmd */
  extern char query_hook[];
- extern char post_statechg_hook[];
  
  /*
   * For each "net" resource configured in zonecfg, we track a zone_addr_list_t
   * node in a linked list that is sorted by linkid.  The list is constructed as
   * the xml configuration file is parsed, and the information
--- 175,184 ----
*** 215,225 ****
  autofs_cleanup(zoneid_t zoneid)
  {
          /*
           * Ask autofs to unmount all trigger nodes in the given zone.
           */
!         return (_autofssys(AUTOFS_UNMOUNTALL, (void *)((uintptr_t)zoneid)));
  }
  
  static void
  free_mnttable(struct mnttab *mnt_array, uint_t nelem)
  {
--- 211,221 ----
  autofs_cleanup(zoneid_t zoneid)
  {
          /*
           * Ask autofs to unmount all trigger nodes in the given zone.
           */
!         return (_autofssys(AUTOFS_UNMOUNTALL, (void *)zoneid));
  }
  
  static void
  free_mnttable(struct mnttab *mnt_array, uint_t nelem)
  {
*** 606,633 ****
                  resolve_lofs(zlogp, zroot, zrootlen);
          (void) strcpy(strrchr(zroot, '/') + 1, "lu");
  }
  
  /*
-  * Perform brand-specific cleanup if we are unable to unmount a FS.
-  */
- static void
- brand_umount_cleanup(zlog_t *zlogp, char *path)
- {
-         char cmdbuf[2 * MAXPATHLEN];
- 
-         if (post_statechg_hook[0] == '\0')
-                 return;
- 
-         if (snprintf(cmdbuf, sizeof (cmdbuf), "%s %d %d %s", post_statechg_hook,
-             ZONE_STATE_DOWN, Z_UNMOUNT, path) > sizeof (cmdbuf))
-                 return;
- 
-         (void) do_subproc(zlogp, cmdbuf, NULL, B_FALSE);
- }
- 
- /*
   * The general strategy for unmounting filesystems is as follows:
   *
   * - Remote filesystems may be dead, and attempting to contact them as
   * part of a regular unmount may hang forever; we want to always try to
   * forcibly unmount such filesystems and only fall back to regular
--- 602,611 ----
*** 656,666 ****
   */
  static int
  unmount_filesystems(zlog_t *zlogp, zoneid_t zoneid, boolean_t unmount_cmd)
  {
          int error = 0;
-         int fail = 0;
          FILE *mnttab;
          struct mnttab *mnts;
          uint_t nmnt;
          char zroot[MAXPATHLEN + 1];
          size_t zrootlen;
--- 634,643 ----
*** 744,788 ****
                           */
                          if (stuck) {
                                  if (umount2(path, MS_FORCE) == 0) {
                                          unmounted = B_TRUE;
                                          stuck = B_FALSE;
-                                         fail = 0;
                                  } else {
                                          /*
!                                          * We may hit a failure here if there
!                                          * is an app in the GZ with an open
!                                          * pipe into the zone (commonly into
!                                          * the zone's /var/run).  This type
!                                          * of app will notice the closed
!                                          * connection and cleanup, but it may
!                                          * take a while and we have no easy
!                                          * way to notice that.  To deal with
!                                          * this case, we will wait and retry
!                                          * a few times before we give up.
                                           */
-                                         fail++;
-                                         if (fail < (UMOUNT_RETRIES - 1)) {
-                                                 zerror(zlogp, B_FALSE,
-                                                     "unable to unmount '%s', "
-                                                     "retrying in 2 seconds",
-                                                     path);
-                                                 (void) sleep(2);
-                                         } else if (fail > UMOUNT_RETRIES) {
                                                  error++;
                                                  zerror(zlogp, B_FALSE,
!                                                     "unmount of '%s' failed",
!                                                     path);
                                                  free_mnttable(mnts, nmnt);
                                                  goto out;
-                                         } else {
-                                                 /* Try the hook 2 times */
-                                                 brand_umount_cleanup(zlogp,
-                                                     path);
                                          }
                                  }
-                         }
                          /*
                           * Try regular unmounts for everything else.
                           */
                          if (!unmounted && umount2(path, 0) != 0)
                                  newcount++;
--- 721,744 ----
                           */
                          if (stuck) {
                                  if (umount2(path, MS_FORCE) == 0) {
                                          unmounted = B_TRUE;
                                          stuck = B_FALSE;
                                  } else {
                                          /*
!                                          * The first failure indicates a
!                                          * mount we won't be able to get
!                                          * rid of automatically, so we
!                                          * bail.
                                           */
                                          error++;
                                          zerror(zlogp, B_FALSE,
!                                             "unable to unmount '%s'", path);
                                          free_mnttable(mnts, nmnt);
                                          goto out;
                                  }
                          }
                          /*
                           * Try regular unmounts for everything else.
                           */
                          if (!unmounted && umount2(path, 0) != 0)
                                  newcount++;
*** 1114,1127 ****
  }
  
  int
  vplat_get_iptype(zlog_t *zlogp, zone_iptype_t *iptypep)
  {
!         if (zonecfg_get_iptype(snap_hndl, iptypep) != Z_OK) {
                  zerror(zlogp, B_FALSE, "invalid ip-type configuration");
                  return (-1);
          }
          return (0);
  }
  
  /*
   * Apply the standard lists of devices/symlinks/mappings and the user-specified
--- 1070,1096 ----
  }
  
  int
  vplat_get_iptype(zlog_t *zlogp, zone_iptype_t *iptypep)
  {
!         zone_dochandle_t handle;
! 
!         if ((handle = zonecfg_init_handle()) == NULL) {
!                 zerror(zlogp, B_TRUE, "getting zone configuration handle");
!                 return (-1);
!         }
!         if (zonecfg_get_snapshot_handle(zone_name, handle) != Z_OK) {
!                 zerror(zlogp, B_FALSE, "invalid configuration");
!                 zonecfg_fini_handle(handle);
!                 return (-1);
!         }
!         if (zonecfg_get_iptype(handle, iptypep) != Z_OK) {
                  zerror(zlogp, B_FALSE, "invalid ip-type configuration");
+                 zonecfg_fini_handle(handle);
                  return (-1);
          }
+         zonecfg_fini_handle(handle);
          return (0);
  }
  
  /*
   * Apply the standard lists of devices/symlinks/mappings and the user-specified
*** 1130,1146 ****
   */
  static int
  mount_one_dev(zlog_t *zlogp, char *devpath, zone_mnt_t mount_cmd)
  {
          char                    brand[MAXNAMELEN];
          brand_handle_t          bh = NULL;
          struct zone_devtab      ztab;
          di_prof_t               prof = NULL;
          int                     err;
          int                     retval = -1;
          zone_iptype_t           iptype;
!         const char              *curr_iptype = NULL;
  
          if (di_prof_init(devpath, &prof)) {
                  zerror(zlogp, B_TRUE, "failed to initialize profile");
                  goto cleanup;
          }
--- 1099,1116 ----
   */
  static int
  mount_one_dev(zlog_t *zlogp, char *devpath, zone_mnt_t mount_cmd)
  {
          char                    brand[MAXNAMELEN];
+         zone_dochandle_t        handle = NULL;
          brand_handle_t          bh = NULL;
          struct zone_devtab      ztab;
          di_prof_t               prof = NULL;
          int                     err;
          int                     retval = -1;
          zone_iptype_t           iptype;
!         const char              *curr_iptype;
  
          if (di_prof_init(devpath, &prof)) {
                  zerror(zlogp, B_TRUE, "failed to initialize profile");
                  goto cleanup;
          }
*** 1171,1182 ****
                  break;
          case ZS_EXCLUSIVE:
                  curr_iptype = "exclusive";
                  break;
          }
-         if (curr_iptype == NULL)
-                 abort();
  
          if (brand_platform_iter_devices(bh, zone_name,
              mount_one_dev_device_cb, prof, curr_iptype) != 0) {
                  zerror(zlogp, B_TRUE, "failed to add standard device");
                  goto cleanup;
--- 1141,1150 ----
*** 1187,1209 ****
                  zerror(zlogp, B_TRUE, "failed to add standard symlink");
                  goto cleanup;
          }
  
          /* Add user-specified devices and directories */
!         if ((err = zonecfg_setdevent(snap_hndl)) != 0) {
                  zerror(zlogp, B_FALSE, "%s: %s", zone_name,
                      zonecfg_strerror(err));
                  goto cleanup;
          }
!         while (zonecfg_getdevent(snap_hndl, &ztab) == Z_OK) {
                  if (di_prof_add_dev(prof, ztab.zone_dev_match)) {
                          zerror(zlogp, B_TRUE, "failed to add "
                              "user-specified device");
                          goto cleanup;
                  }
          }
!         (void) zonecfg_enddevent(snap_hndl);
  
          /* Send profile to kernel */
          if (di_prof_commit(prof)) {
                  zerror(zlogp, B_TRUE, "failed to commit profile");
                  goto cleanup;
--- 1155,1186 ----
                  zerror(zlogp, B_TRUE, "failed to add standard symlink");
                  goto cleanup;
          }
  
          /* Add user-specified devices and directories */
!         if ((handle = zonecfg_init_handle()) == NULL) {
!                 zerror(zlogp, B_FALSE, "can't initialize zone handle");
!                 goto cleanup;
!         }
!         if ((err = zonecfg_get_handle(zone_name, handle)) != 0) {
!                 zerror(zlogp, B_FALSE, "can't get handle for zone "
!                     "%s: %s", zone_name, zonecfg_strerror(err));
!                 goto cleanup;
!         }
!         if ((err = zonecfg_setdevent(handle)) != 0) {
                  zerror(zlogp, B_FALSE, "%s: %s", zone_name,
                      zonecfg_strerror(err));
                  goto cleanup;
          }
!         while (zonecfg_getdevent(handle, &ztab) == Z_OK) {
                  if (di_prof_add_dev(prof, ztab.zone_dev_match)) {
                          zerror(zlogp, B_TRUE, "failed to add "
                              "user-specified device");
                          goto cleanup;
                  }
          }
!         (void) zonecfg_enddevent(handle);
  
          /* Send profile to kernel */
          if (di_prof_commit(prof)) {
                  zerror(zlogp, B_TRUE, "failed to commit profile");
                  goto cleanup;
*** 1212,1221 ****
--- 1189,1200 ----
          retval = 0;
  
  cleanup:
          if (bh != NULL)
                  brand_close(bh);
+         if (handle != NULL)
+                 zonecfg_fini_handle(handle);
          if (prof)
                  di_prof_fini(prof);
          return (retval);
  }
  
*** 1705,1714 ****
--- 1684,1694 ----
          char rootpath[MAXPATHLEN];
          char brand[MAXNAMELEN];
          char luroot[MAXPATHLEN];
          int i, num_fs = 0;
          struct zone_fstab *fs_ptr = NULL;
+         zone_dochandle_t handle = NULL;
          zone_state_t zstate;
          brand_handle_t bh;
          plat_gmount_cb_data_t cb;
  
          if (zone_get_state(zone_name, &zstate) != Z_OK ||
*** 1723,1733 ****
          if (zone_get_rootpath(zone_name, rootpath, sizeof (rootpath)) != Z_OK) {
                  zerror(zlogp, B_TRUE, "unable to determine zone root");
                  goto bad;
          }
  
!         if (zonecfg_setfsent(snap_hndl) != Z_OK) {
                  zerror(zlogp, B_FALSE, "invalid configuration");
                  goto bad;
          }
  
          /*
--- 1703,1718 ----
          if (zone_get_rootpath(zone_name, rootpath, sizeof (rootpath)) != Z_OK) {
                  zerror(zlogp, B_TRUE, "unable to determine zone root");
                  goto bad;
          }
  
!         if ((handle = zonecfg_init_handle()) == NULL) {
!                 zerror(zlogp, B_TRUE, "getting zone configuration handle");
!                 goto bad;
!         }
!         if (zonecfg_get_snapshot_handle(zone_name, handle) != Z_OK ||
!             zonecfg_setfsent(handle) != Z_OK) {
                  zerror(zlogp, B_FALSE, "invalid configuration");
                  goto bad;
          }
  
          /*
*** 1741,1750 ****
--- 1726,1736 ----
          }
  
          /* Get a handle to the brand info for this zone */
          if ((bh = brand_open(brand)) == NULL) {
                  zerror(zlogp, B_FALSE, "unable to determine zone brand");
+                 zonecfg_fini_handle(handle);
                  return (-1);
          }
  
          /*
           * Get the list of global filesystems to mount from the brand
*** 1755,1764 ****
--- 1741,1751 ----
          cb.pgcd_num_fs = &num_fs;
          if (brand_platform_iter_gmounts(bh, zone_name, zonepath,
              plat_gmount_cb, &cb) != 0) {
                  zerror(zlogp, B_FALSE, "unable to mount filesystems");
                  brand_close(bh);
+                 zonecfg_fini_handle(handle);
                  return (-1);
          }
          brand_close(bh);
  
          /*
*** 1765,1778 ****
           * Iterate through the rest of the filesystems. Sort them all,
           * then mount them in sorted order. This is to make sure the
           * higher level directories (e.g., /usr) get mounted before
           * any beneath them (e.g., /usr/local).
           */
!         if (mount_filesystems_fsent(snap_hndl, zlogp, &fs_ptr, &num_fs,
              mount_cmd) != 0)
                  goto bad;
  
          /*
           * Normally when we mount a zone all the zone filesystems
           * get mounted relative to rootpath, which is usually
           * <zonepath>/root.  But when mounting a zone for administration
           * purposes via the zone "mount" state, build_mounted_pre_var()
--- 1752,1768 ----
           * Iterate through the rest of the filesystems. Sort them all,
           * then mount them in sorted order. This is to make sure the
           * higher level directories (e.g., /usr) get mounted before
           * any beneath them (e.g., /usr/local).
           */
!         if (mount_filesystems_fsent(handle, zlogp, &fs_ptr, &num_fs,
              mount_cmd) != 0)
                  goto bad;
  
+         zonecfg_fini_handle(handle);
+         handle = NULL;
+ 
          /*
           * Normally when we mount a zone all the zone filesystems
           * get mounted relative to rootpath, which is usually
           * <zonepath>/root.  But when mounting a zone for administration
           * purposes via the zone "mount" state, build_mounted_pre_var()
*** 1864,1873 ****
--- 1854,1865 ----
           * Everything looks fine.
           */
          return (0);
  
  bad:
+         if (handle != NULL)
+                 zonecfg_fini_handle(handle);
          free_fs_data(fs_ptr, num_fs);
          return (-1);
  }
  
  /* caller makes sure neither parameter is NULL */
*** 2219,2229 ****
--- 2211,2227 ----
          (void) memset(&lifr.lifr_addr, 0, sizeof (lifr.lifr_addr));
  
          if (ioctl(s, SIOCLIFADDIF, (caddr_t)&lifr) < 0) {
                  /*
                   * Here, we know that the interface can't be brought up.
+                  * A similar warning message was already printed out to
+                  * the console by zoneadm(1M) so instead we log the
+                  * message to syslog and continue.
                   */
+                 zerror(&logsys, B_TRUE, "WARNING: skipping network interface "
+                     "'%s' which may not be present/plumbed in the "
+                     "global zone.", lifr.lifr_name);
                  (void) close(s);
                  return (Z_OK);
          }
  
          /* Preserve literal IPv4 address for later potential printing. */
*** 2432,2462 ****
   * whatever we set up, and return an error.
   */
  static int
  configure_shared_network_interfaces(zlog_t *zlogp)
  {
          struct zone_nwiftab nwiftab, loopback_iftab;
          zoneid_t zoneid;
  
          if ((zoneid = getzoneidbyname(zone_name)) == ZONE_ID_UNDEFINED) {
                  zerror(zlogp, B_TRUE, "unable to get zoneid");
                  return (-1);
          }
  
!         if (zonecfg_setnwifent(snap_hndl) == Z_OK) {
                  for (;;) {
!                         if (zonecfg_getnwifent(snap_hndl, &nwiftab) != Z_OK)
                                  break;
-                         nwifent_free_attrs(&nwiftab);
                          if (configure_one_interface(zlogp, zoneid, &nwiftab) !=
                              Z_OK) {
!                                 (void) zonecfg_endnwifent(snap_hndl);
                                  return (-1);
                          }
                  }
!                 (void) zonecfg_endnwifent(snap_hndl);
          }
          if (is_system_labeled()) {
                  /*
                   * Labeled zones share the loopback interface
                   * so it is not plumbed for shared stack instances.
                   */
--- 2430,2471 ----
   * whatever we set up, and return an error.
   */
  static int
  configure_shared_network_interfaces(zlog_t *zlogp)
  {
+         zone_dochandle_t handle;
          struct zone_nwiftab nwiftab, loopback_iftab;
          zoneid_t zoneid;
  
          if ((zoneid = getzoneidbyname(zone_name)) == ZONE_ID_UNDEFINED) {
                  zerror(zlogp, B_TRUE, "unable to get zoneid");
                  return (-1);
          }
  
!         if ((handle = zonecfg_init_handle()) == NULL) {
!                 zerror(zlogp, B_TRUE, "getting zone configuration handle");
!                 return (-1);
!         }
!         if (zonecfg_get_snapshot_handle(zone_name, handle) != Z_OK) {
!                 zerror(zlogp, B_FALSE, "invalid configuration");
!                 zonecfg_fini_handle(handle);
!                 return (-1);
!         }
!         if (zonecfg_setnwifent(handle) == Z_OK) {
                  for (;;) {
!                         if (zonecfg_getnwifent(handle, &nwiftab) != Z_OK)
                                  break;
                          if (configure_one_interface(zlogp, zoneid, &nwiftab) !=
                              Z_OK) {
!                                 (void) zonecfg_endnwifent(handle);
!                                 zonecfg_fini_handle(handle);
                                  return (-1);
                          }
                  }
!                 (void) zonecfg_endnwifent(handle);
          }
+         zonecfg_fini_handle(handle);
          if (is_system_labeled()) {
                  /*
                   * Labeled zones share the loopback interface
                   * so it is not plumbed for shared stack instances.
                   */
*** 2899,2943 ****
                  free(new);
          }
  }
  
  /*
   * Add the kernel access control information for the interface names.
   * If anything goes wrong, we log a general error message, attempt to tear down
   * whatever we set up, and return an error.
   */
  static int
  configure_exclusive_network_interfaces(zlog_t *zlogp, zoneid_t zoneid)
  {
          struct zone_nwiftab nwiftab;
          char rootpath[MAXPATHLEN];
          char path[MAXPATHLEN];
          datalink_id_t linkid;
          di_prof_t prof = NULL;
          boolean_t added = B_FALSE;
          zone_addr_list_t *zalist = NULL, *new;
  
!         if (zonecfg_setnwifent(snap_hndl) != Z_OK)
                  return (0);
  
          for (;;) {
!                 if (zonecfg_getnwifent(snap_hndl, &nwiftab) != Z_OK)
                          break;
  
-                 nwifent_free_attrs(&nwiftab);
                  if (prof == NULL) {
                          if (zone_get_devroot(zone_name, rootpath,
                              sizeof (rootpath)) != Z_OK) {
!                                 (void) zonecfg_endnwifent(snap_hndl);
                                  zerror(zlogp, B_TRUE,
                                      "unable to determine dev root");
                                  return (-1);
                          }
                          (void) snprintf(path, sizeof (path), "%s%s", rootpath,
!                             "/dev");
                          if (di_prof_init(path, &prof) != 0) {
!                                 (void) zonecfg_endnwifent(snap_hndl);
                                  zerror(zlogp, B_TRUE,
                                      "failed to initialize profile");
                                  return (-1);
                          }
                  }
--- 2908,2985 ----
                  free(new);
          }
  }
  
  /*
+  * For IP networking, we need to use the illumos-native device tree.  For most
+  * zones, this is $ZONEROOT/dev.  For LX ones, it's $ZONEROOT/native/dev.
+  * Return the appropriate post-$ZONEROOT path.
+  */
+ static char *
+ get_brand_dev(void)
+ {
+         static char *lxpath = "/native/dev";
+         /* Cheesy hard-coding of strlen("/native") */
+         char *default_path = lxpath + 7;
+ 
+         /* LX zones are the exception... */
+         if (strcmp(brand_name, "lx") == 0)
+                 return (lxpath);
+ 
+         return (default_path);
+ }
+ 
+ /*
   * Add the kernel access control information for the interface names.
   * If anything goes wrong, we log a general error message, attempt to tear down
   * whatever we set up, and return an error.
   */
  static int
  configure_exclusive_network_interfaces(zlog_t *zlogp, zoneid_t zoneid)
  {
+         zone_dochandle_t handle;
          struct zone_nwiftab nwiftab;
          char rootpath[MAXPATHLEN];
          char path[MAXPATHLEN];
          datalink_id_t linkid;
          di_prof_t prof = NULL;
          boolean_t added = B_FALSE;
          zone_addr_list_t *zalist = NULL, *new;
  
!         if ((handle = zonecfg_init_handle()) == NULL) {
!                 zerror(zlogp, B_TRUE, "getting zone configuration handle");
!                 return (-1);
!         }
!         if (zonecfg_get_snapshot_handle(zone_name, handle) != Z_OK) {
!                 zerror(zlogp, B_FALSE, "invalid configuration");
!                 zonecfg_fini_handle(handle);
!                 return (-1);
!         }
! 
!         if (zonecfg_setnwifent(handle) != Z_OK) {
!                 zonecfg_fini_handle(handle);
                  return (0);
+         }
  
          for (;;) {
!                 if (zonecfg_getnwifent(handle, &nwiftab) != Z_OK)
                          break;
  
                  if (prof == NULL) {
                          if (zone_get_devroot(zone_name, rootpath,
                              sizeof (rootpath)) != Z_OK) {
!                                 (void) zonecfg_endnwifent(handle);
!                                 zonecfg_fini_handle(handle);
                                  zerror(zlogp, B_TRUE,
                                      "unable to determine dev root");
                                  return (-1);
                          }
                          (void) snprintf(path, sizeof (path), "%s%s", rootpath,
!                             get_brand_dev());
                          if (di_prof_init(path, &prof) != 0) {
!                                 (void) zonecfg_endnwifent(handle);
!                                 zonecfg_fini_handle(handle);
                                  zerror(zlogp, B_TRUE,
                                      "failed to initialize profile");
                                  return (-1);
                          }
                  }
*** 2957,2994 ****
                      &linkid, NULL, NULL, NULL) == DLADM_STATUS_OK &&
                      add_datalink(zlogp, zone_name, linkid,
                      nwiftab.zone_nwif_physical) == 0) {
                          added = B_TRUE;
                  } else {
!                         /*
!                          * Failed to add network device, but the brand hook
!                          * might be doing this for us, so keep silent.
!                          */
!                         continue;
                  }
                  /* set up the new IP interface, and add them all later */
                  new = malloc(sizeof (*new));
                  if (new == NULL) {
                          zerror(zlogp, B_TRUE, "no memory for %s",
                              nwiftab.zone_nwif_physical);
                          free_ip_interface(zalist);
                  }
                  bzero(new, sizeof (*new));
                  new->za_nwiftab = nwiftab;
                  new->za_linkid = linkid;
                  zalist = add_ip_interface(zalist, new);
          }
          if (zalist != NULL) {
                  if ((errno = add_net(zlogp, zoneid, zalist)) != 0) {
!                         (void) zonecfg_endnwifent(snap_hndl);
                          zerror(zlogp, B_TRUE, "failed to add address");
                          free_ip_interface(zalist);
                          return (-1);
                  }
                  free_ip_interface(zalist);
          }
!         (void) zonecfg_endnwifent(snap_hndl);
  
          if (prof != NULL && added) {
                  if (di_prof_commit(prof) != 0) {
                          zerror(zlogp, B_TRUE, "failed to commit profile");
                          return (-1);
--- 2999,3038 ----
                      &linkid, NULL, NULL, NULL) == DLADM_STATUS_OK &&
                      add_datalink(zlogp, zone_name, linkid,
                      nwiftab.zone_nwif_physical) == 0) {
                          added = B_TRUE;
                  } else {
!                         (void) zonecfg_endnwifent(handle);
!                         zonecfg_fini_handle(handle);
!                         zerror(zlogp, B_TRUE, "failed to add network device");
!                         return (-1);
                  }
                  /* set up the new IP interface, and add them all later */
                  new = malloc(sizeof (*new));
                  if (new == NULL) {
                          zerror(zlogp, B_TRUE, "no memory for %s",
                              nwiftab.zone_nwif_physical);
+                         zonecfg_fini_handle(handle);
                          free_ip_interface(zalist);
                  }
                  bzero(new, sizeof (*new));
                  new->za_nwiftab = nwiftab;
                  new->za_linkid = linkid;
                  zalist = add_ip_interface(zalist, new);
          }
          if (zalist != NULL) {
                  if ((errno = add_net(zlogp, zoneid, zalist)) != 0) {
!                         (void) zonecfg_endnwifent(handle);
!                         zonecfg_fini_handle(handle);
                          zerror(zlogp, B_TRUE, "failed to add address");
                          free_ip_interface(zalist);
                          return (-1);
                  }
                  free_ip_interface(zalist);
          }
!         (void) zonecfg_endnwifent(handle);
!         zonecfg_fini_handle(handle);
  
          if (prof != NULL && added) {
                  if (di_prof_commit(prof) != 0) {
                          zerror(zlogp, B_TRUE, "failed to commit profile");
                          return (-1);
*** 3120,3146 ****
                      "protection", NULL, 0, DLADM_OPT_ACTIVE);
                  if (dlstatus == DLADM_STATUS_NOTFOUND) {
                          /* datalink does not belong to the GZ */
                          continue;
                  }
!                 if (dlstatus != DLADM_STATUS_OK)
                          zerror(zlogp, B_FALSE,
-                             "clear 'protection' link property: %s",
                              dladm_status2str(dlstatus, dlerr));
! 
                  dlstatus = dladm_set_linkprop(dld_handle, *dllink,
                      "allowed-ips", NULL, 0, DLADM_OPT_ACTIVE);
!                 if (dlstatus != DLADM_STATUS_OK)
                          zerror(zlogp, B_FALSE,
-                             "clear 'allowed-ips' link property: %s",
                              dladm_status2str(dlstatus, dlerr));
          }
          free(dllinks);
          return (0);
  }
  
  static int
  tcp_abort_conn(zlog_t *zlogp, zoneid_t zoneid,
      const struct sockaddr_storage *local, const struct sockaddr_storage *remote)
  {
          int fd;
          struct strioctl ioc;
--- 3164,3215 ----
                      "protection", NULL, 0, DLADM_OPT_ACTIVE);
                  if (dlstatus == DLADM_STATUS_NOTFOUND) {
                          /* datalink does not belong to the GZ */
                          continue;
                  }
!                 if (dlstatus != DLADM_STATUS_OK) {
                          zerror(zlogp, B_FALSE,
                              dladm_status2str(dlstatus, dlerr));
!                         free(dllinks);
!                         return (-1);
!                 }
                  dlstatus = dladm_set_linkprop(dld_handle, *dllink,
                      "allowed-ips", NULL, 0, DLADM_OPT_ACTIVE);
!                 if (dlstatus != DLADM_STATUS_OK) {
                          zerror(zlogp, B_FALSE,
                              dladm_status2str(dlstatus, dlerr));
+                         free(dllinks);
+                         return (-1);
                  }
+         }
          free(dllinks);
          return (0);
  }
  
  static int
+ unconfigure_exclusive_network_interfaces(zlog_t *zlogp, zoneid_t zoneid)
+ {
+         int dlnum = 0;
+ 
+         /*
+          * The kernel shutdown callback for the dls module should have removed
+          * all datalinks from this zone.  If any remain, then there's a
+          * problem.
+          */
+         if (zone_list_datalink(zoneid, &dlnum, NULL) != 0) {
+                 zerror(zlogp, B_TRUE, "unable to list network interfaces");
+                 return (-1);
+         }
+         if (dlnum != 0) {
+                 zerror(zlogp, B_FALSE,
+                     "datalinks remain in zone after shutdown");
+                 return (-1);
+         }
+         return (0);
+ }
+ 
+ static int
  tcp_abort_conn(zlog_t *zlogp, zoneid_t zoneid,
      const struct sockaddr_storage *local, const struct sockaddr_storage *remote)
  {
          int fd;
          struct strioctl ioc;
*** 3218,3235 ****
  
  static int
  get_privset(zlog_t *zlogp, priv_set_t *privs, zone_mnt_t mount_cmd)
  {
          int error = -1;
          char *privname = NULL;
  
          if (ALT_MOUNT(mount_cmd)) {
                  zone_iptype_t   iptype;
!                 const char      *curr_iptype = NULL;
  
!                 if (zonecfg_get_iptype(snap_hndl, &iptype) != Z_OK) {
                          zerror(zlogp, B_TRUE, "unable to determine ip-type");
                          return (-1);
                  }
  
                  switch (iptype) {
                  case ZS_SHARED:
--- 3287,3316 ----
  
  static int
  get_privset(zlog_t *zlogp, priv_set_t *privs, zone_mnt_t mount_cmd)
  {
          int error = -1;
+         zone_dochandle_t handle;
          char *privname = NULL;
  
+         if ((handle = zonecfg_init_handle()) == NULL) {
+                 zerror(zlogp, B_TRUE, "getting zone configuration handle");
+                 return (-1);
+         }
+         if (zonecfg_get_snapshot_handle(zone_name, handle) != Z_OK) {
+                 zerror(zlogp, B_FALSE, "invalid configuration");
+                 zonecfg_fini_handle(handle);
+                 return (-1);
+         }
+ 
          if (ALT_MOUNT(mount_cmd)) {
                  zone_iptype_t   iptype;
!                 const char      *curr_iptype;
  
!                 if (zonecfg_get_iptype(handle, &iptype) != Z_OK) {
                          zerror(zlogp, B_TRUE, "unable to determine ip-type");
+                         zonecfg_fini_handle(handle);
                          return (-1);
                  }
  
                  switch (iptype) {
                  case ZS_SHARED:
*** 3238,3256 ****
                  case ZS_EXCLUSIVE:
                          curr_iptype = "exclusive";
                          break;
                  }
  
!                 if (zonecfg_default_privset(privs, curr_iptype) == Z_OK)
                          return (0);
! 
                  zerror(zlogp, B_FALSE,
                      "failed to determine the zone's default privilege set");
                  return (-1);
          }
  
!         switch (zonecfg_get_privset(snap_hndl, privs, &privname)) {
          case Z_OK:
                  error = 0;
                  break;
          case Z_PRIV_PROHIBITED:
                  zerror(zlogp, B_FALSE, "privilege \"%s\" is not permitted "
--- 3319,3339 ----
                  case ZS_EXCLUSIVE:
                          curr_iptype = "exclusive";
                          break;
                  }
  
!                 if (zonecfg_default_privset(privs, curr_iptype) == Z_OK) {
!                         zonecfg_fini_handle(handle);
                          return (0);
!                 }
                  zerror(zlogp, B_FALSE,
                      "failed to determine the zone's default privilege set");
+                 zonecfg_fini_handle(handle);
                  return (-1);
          }
  
!         switch (zonecfg_get_privset(handle, privs, &privname)) {
          case Z_OK:
                  error = 0;
                  break;
          case Z_PRIV_PROHIBITED:
                  zerror(zlogp, B_FALSE, "privilege \"%s\" is not permitted "
*** 3269,3278 ****
--- 3352,3362 ----
                      "privilege set");
                  break;
          }
  
          free(privname);
+         zonecfg_fini_handle(handle);
          return (error);
  }
  
  static char *
  zone_proj_rctl(const char *name)
*** 3294,3312 ****
--- 3378,3407 ----
          char *nvl_packed = NULL;
          size_t nvl_size = 0;
          nvlist_t **nvlv = NULL;
          int rctlcount = 0;
          int error = -1;
+         zone_dochandle_t handle;
          struct zone_rctltab rctltab;
          rctlblk_t *rctlblk = NULL;
          uint64_t maxlwps;
          uint64_t maxprocs;
          int rproc, rlwp;
  
          *bufp = NULL;
          *bufsizep = 0;
  
+         if ((handle = zonecfg_init_handle()) == NULL) {
+                 zerror(zlogp, B_TRUE, "getting zone configuration handle");
+                 return (-1);
+         }
+         if (zonecfg_get_snapshot_handle(zone_name, handle) != Z_OK) {
+                 zerror(zlogp, B_FALSE, "invalid configuration");
+                 zonecfg_fini_handle(handle);
+                 return (-1);
+         }
+ 
          rctltab.zone_rctl_valptr = NULL;
          if (nvlist_alloc(&nvl, NV_UNIQUE_NAME, 0) != 0) {
                  zerror(zlogp, B_TRUE, "%s failed", "nvlist_alloc");
                  goto out;
          }
*** 3335,3354 ****
                              "unable to set max-processes alias");
                          goto out;
                  }
          }
  
!         if (zonecfg_setrctlent(snap_hndl) != Z_OK) {
                  zerror(zlogp, B_FALSE, "%s failed", "zonecfg_setrctlent");
                  goto out;
          }
  
          if ((rctlblk = malloc(rctlblk_size())) == NULL) {
                  zerror(zlogp, B_TRUE, "memory allocation failed");
                  goto out;
          }
!         while (zonecfg_getrctlent(snap_hndl, &rctltab) == Z_OK) {
                  struct zone_rctlvaltab *rctlval;
                  uint_t i, count;
                  const char *name = rctltab.zone_rctl_name;
                  char *proj_nm;
  
--- 3430,3449 ----
                              "unable to set max-processes alias");
                          goto out;
                  }
          }
  
!         if (zonecfg_setrctlent(handle) != Z_OK) {
                  zerror(zlogp, B_FALSE, "%s failed", "zonecfg_setrctlent");
                  goto out;
          }
  
          if ((rctlblk = malloc(rctlblk_size())) == NULL) {
                  zerror(zlogp, B_TRUE, "memory allocation failed");
                  goto out;
          }
!         while (zonecfg_getrctlent(handle, &rctltab) == Z_OK) {
                  struct zone_rctlvaltab *rctlval;
                  uint_t i, count;
                  const char *name = rctltab.zone_rctl_name;
                  char *proj_nm;
  
*** 3447,3457 ****
                          nvlist_free(nvlv[i]);
                  free(nvlv);
                  nvlv = NULL;
                  rctlcount++;
          }
!         (void) zonecfg_endrctlent(snap_hndl);
  
          if (rctlcount == 0) {
                  error = 0;
                  goto out;
          }
--- 3542,3552 ----
                          nvlist_free(nvlv[i]);
                  free(nvlv);
                  nvlv = NULL;
                  rctlcount++;
          }
!         (void) zonecfg_endrctlent(handle);
  
          if (rctlcount == 0) {
                  error = 0;
                  goto out;
          }
*** 3471,3480 ****
--- 3566,3577 ----
          if (error && nvl_packed != NULL)
                  free(nvl_packed);
          nvlist_free(nvl);
          if (nvlv != NULL)
                  free(nvlv);
+         if (handle != NULL)
+                 zonecfg_fini_handle(handle);
          return (error);
  }
  
  static int
  get_implicit_datasets(zlog_t *zlogp, char **retstr)
*** 3486,3504 ****
  
          if (snprintf(cmdbuf, sizeof (cmdbuf), "%s datasets", query_hook)
              > sizeof (cmdbuf))
                  return (-1);
  
!         if (do_subproc(zlogp, cmdbuf, retstr, B_FALSE) != 0)
                  return (-1);
  
          return (0);
  }
  
  static int
  get_datasets(zlog_t *zlogp, char **bufp, size_t *bufsizep)
  {
          struct zone_dstab dstab;
          size_t total, offset, len;
          int error = -1;
          char *str = NULL;
          char *implicit_datasets = NULL;
--- 3583,3602 ----
  
          if (snprintf(cmdbuf, sizeof (cmdbuf), "%s datasets", query_hook)
              > sizeof (cmdbuf))
                  return (-1);
  
!         if (do_subproc(zlogp, cmdbuf, retstr) != 0)
                  return (-1);
  
          return (0);
  }
  
  static int
  get_datasets(zlog_t *zlogp, char **bufp, size_t *bufsizep)
  {
+         zone_dochandle_t handle;
          struct zone_dstab dstab;
          size_t total, offset, len;
          int error = -1;
          char *str = NULL;
          char *implicit_datasets = NULL;
*** 3505,3528 ****
          int implicit_len = 0;
  
          *bufp = NULL;
          *bufsizep = 0;
  
          if (get_implicit_datasets(zlogp, &implicit_datasets) != 0) {
                  zerror(zlogp, B_FALSE, "getting implicit datasets failed");
                  goto out;
          }
  
!         if (zonecfg_setdsent(snap_hndl) != Z_OK) {
                  zerror(zlogp, B_FALSE, "%s failed", "zonecfg_setdsent");
                  goto out;
          }
  
          total = 0;
!         while (zonecfg_getdsent(snap_hndl, &dstab) == Z_OK)
                  total += strlen(dstab.zone_dataset_name) + 1;
!         (void) zonecfg_enddsent(snap_hndl);
  
          if (implicit_datasets != NULL)
                  implicit_len = strlen(implicit_datasets);
          if (implicit_len > 0)
                  total += implicit_len + 1;
--- 3603,3636 ----
          int implicit_len = 0;
  
          *bufp = NULL;
          *bufsizep = 0;
  
+         if ((handle = zonecfg_init_handle()) == NULL) {
+                 zerror(zlogp, B_TRUE, "getting zone configuration handle");
+                 return (-1);
+         }
+         if (zonecfg_get_snapshot_handle(zone_name, handle) != Z_OK) {
+                 zerror(zlogp, B_FALSE, "invalid configuration");
+                 zonecfg_fini_handle(handle);
+                 return (-1);
+         }
+ 
          if (get_implicit_datasets(zlogp, &implicit_datasets) != 0) {
                  zerror(zlogp, B_FALSE, "getting implicit datasets failed");
                  goto out;
          }
  
!         if (zonecfg_setdsent(handle) != Z_OK) {
                  zerror(zlogp, B_FALSE, "%s failed", "zonecfg_setdsent");
                  goto out;
          }
  
          total = 0;
!         while (zonecfg_getdsent(handle, &dstab) == Z_OK)
                  total += strlen(dstab.zone_dataset_name) + 1;
!         (void) zonecfg_enddsent(handle);
  
          if (implicit_datasets != NULL)
                  implicit_len = strlen(implicit_datasets);
          if (implicit_len > 0)
                  total += implicit_len + 1;
*** 3535,3558 ****
          if ((str = malloc(total)) == NULL) {
                  zerror(zlogp, B_TRUE, "memory allocation failed");
                  goto out;
          }
  
!         if (zonecfg_setdsent(snap_hndl) != Z_OK) {
                  zerror(zlogp, B_FALSE, "%s failed", "zonecfg_setdsent");
                  goto out;
          }
          offset = 0;
!         while (zonecfg_getdsent(snap_hndl, &dstab) == Z_OK) {
                  len = strlen(dstab.zone_dataset_name);
                  (void) strlcpy(str + offset, dstab.zone_dataset_name,
                      total - offset);
                  offset += len;
                  if (offset < total - 1)
                          str[offset++] = ',';
          }
!         (void) zonecfg_enddsent(snap_hndl);
  
          if (implicit_len > 0)
                  (void) strlcpy(str + offset, implicit_datasets, total - offset);
  
          error = 0;
--- 3643,3666 ----
          if ((str = malloc(total)) == NULL) {
                  zerror(zlogp, B_TRUE, "memory allocation failed");
                  goto out;
          }
  
!         if (zonecfg_setdsent(handle) != Z_OK) {
                  zerror(zlogp, B_FALSE, "%s failed", "zonecfg_setdsent");
                  goto out;
          }
          offset = 0;
!         while (zonecfg_getdsent(handle, &dstab) == Z_OK) {
                  len = strlen(dstab.zone_dataset_name);
                  (void) strlcpy(str + offset, dstab.zone_dataset_name,
                      total - offset);
                  offset += len;
                  if (offset < total - 1)
                          str[offset++] = ',';
          }
!         (void) zonecfg_enddsent(handle);
  
          if (implicit_len > 0)
                  (void) strlcpy(str + offset, implicit_datasets, total - offset);
  
          error = 0;
*** 3560,3598 ****
          *bufsizep = total;
  
  out:
          if (error != 0 && str != NULL)
                  free(str);
          if (implicit_datasets != NULL)
                  free(implicit_datasets);
  
          return (error);
  }
  
  static int
  validate_datasets(zlog_t *zlogp)
  {
          struct zone_dstab dstab;
          zfs_handle_t *zhp;
          libzfs_handle_t *hdl;
  
!         if (zonecfg_setdsent(snap_hndl) != Z_OK) {
                  zerror(zlogp, B_FALSE, "invalid configuration");
                  return (-1);
          }
  
          if ((hdl = libzfs_init()) == NULL) {
                  zerror(zlogp, B_FALSE, "opening ZFS library");
                  return (-1);
          }
  
!         while (zonecfg_getdsent(snap_hndl, &dstab) == Z_OK) {
  
                  if ((zhp = zfs_open(hdl, dstab.zone_dataset_name,
                      ZFS_TYPE_FILESYSTEM)) == NULL) {
                          zerror(zlogp, B_FALSE, "cannot open ZFS dataset '%s'",
                              dstab.zone_dataset_name);
                          libzfs_fini(hdl);
                          return (-1);
                  }
  
                  /*
--- 3668,3722 ----
          *bufsizep = total;
  
  out:
          if (error != 0 && str != NULL)
                  free(str);
+         if (handle != NULL)
+                 zonecfg_fini_handle(handle);
          if (implicit_datasets != NULL)
                  free(implicit_datasets);
  
          return (error);
  }
  
  static int
  validate_datasets(zlog_t *zlogp)
  {
+         zone_dochandle_t handle;
          struct zone_dstab dstab;
          zfs_handle_t *zhp;
          libzfs_handle_t *hdl;
  
!         if ((handle = zonecfg_init_handle()) == NULL) {
!                 zerror(zlogp, B_TRUE, "getting zone configuration handle");
!                 return (-1);
!         }
!         if (zonecfg_get_snapshot_handle(zone_name, handle) != Z_OK) {
                  zerror(zlogp, B_FALSE, "invalid configuration");
+                 zonecfg_fini_handle(handle);
                  return (-1);
          }
  
+         if (zonecfg_setdsent(handle) != Z_OK) {
+                 zerror(zlogp, B_FALSE, "invalid configuration");
+                 zonecfg_fini_handle(handle);
+                 return (-1);
+         }
+ 
          if ((hdl = libzfs_init()) == NULL) {
                  zerror(zlogp, B_FALSE, "opening ZFS library");
+                 zonecfg_fini_handle(handle);
                  return (-1);
          }
  
!         while (zonecfg_getdsent(handle, &dstab) == Z_OK) {
  
                  if ((zhp = zfs_open(hdl, dstab.zone_dataset_name,
                      ZFS_TYPE_FILESYSTEM)) == NULL) {
                          zerror(zlogp, B_FALSE, "cannot open ZFS dataset '%s'",
                              dstab.zone_dataset_name);
+                         zonecfg_fini_handle(handle);
                          libzfs_fini(hdl);
                          return (-1);
                  }
  
                  /*
*** 3603,3621 ****
                      zfs_prop_set(zhp, zfs_prop_to_name(ZFS_PROP_ZONED),
                      "on") != 0) {
                          zerror(zlogp, B_FALSE, "cannot set 'zoned' "
                              "property for ZFS dataset '%s'\n",
                              dstab.zone_dataset_name);
                          zfs_close(zhp);
                          libzfs_fini(hdl);
                          return (-1);
                  }
  
                  zfs_close(zhp);
          }
!         (void) zonecfg_enddsent(snap_hndl);
  
          libzfs_fini(hdl);
  
          return (0);
  }
  
--- 3727,3747 ----
                      zfs_prop_set(zhp, zfs_prop_to_name(ZFS_PROP_ZONED),
                      "on") != 0) {
                          zerror(zlogp, B_FALSE, "cannot set 'zoned' "
                              "property for ZFS dataset '%s'\n",
                              dstab.zone_dataset_name);
+                         zonecfg_fini_handle(handle);
                          zfs_close(zhp);
                          libzfs_fini(hdl);
                          return (-1);
                  }
  
                  zfs_close(zhp);
          }
!         (void) zonecfg_enddsent(handle);
  
+         zonecfg_fini_handle(handle);
          libzfs_fini(hdl);
  
          return (0);
  }
  
*** 4348,4361 ****
  setup_zone_rm(zlog_t *zlogp, char *zone_name, zoneid_t zoneid)
  {
          int res;
          uint64_t tmp;
          char sched[MAXNAMELEN];
          char pool_err[128];
  
          /* Get the scheduling class set in the zone configuration. */
!         if (zonecfg_get_sched_class(snap_hndl, sched, sizeof (sched)) == Z_OK &&
              strlen(sched) > 0) {
                  if (zone_setattr(zoneid, ZONE_ATTR_SCHED_CLASS, sched,
                      strlen(sched)) == -1)
                          zerror(zlogp, B_TRUE, "WARNING: unable to set the "
                              "default scheduling class");
--- 4474,4499 ----
  setup_zone_rm(zlog_t *zlogp, char *zone_name, zoneid_t zoneid)
  {
          int res;
          uint64_t tmp;
          char sched[MAXNAMELEN];
+         zone_dochandle_t handle = NULL;
          char pool_err[128];
  
+         if ((handle = zonecfg_init_handle()) == NULL) {
+                 zerror(zlogp, B_TRUE, "getting zone configuration handle");
+                 return (Z_BAD_HANDLE);
+         }
+ 
+         if ((res = zonecfg_get_snapshot_handle(zone_name, handle)) != Z_OK) {
+                 zerror(zlogp, B_FALSE, "invalid configuration");
+                 zonecfg_fini_handle(handle);
+                 return (res);
+         }
+ 
          /* Get the scheduling class set in the zone configuration. */
!         if (zonecfg_get_sched_class(handle, sched, sizeof (sched)) == Z_OK &&
              strlen(sched) > 0) {
                  if (zone_setattr(zoneid, ZONE_ATTR_SCHED_CLASS, sched,
                      strlen(sched)) == -1)
                          zerror(zlogp, B_TRUE, "WARNING: unable to set the "
                              "default scheduling class");
*** 4396,4406 ****
                   * in by default so we can print a warning and modify the class
                   * if we wouldn't be using FSS.
                   */
                  char class_name[PC_CLNMSZ];
  
!                 if (zonecfg_get_dflt_sched_class(snap_hndl, class_name,
                      sizeof (class_name)) != Z_OK) {
                          zerror(zlogp, B_FALSE, "WARNING: unable to determine "
                              "the zone's scheduling class");
  
                  } else if (strcmp("FSS", class_name) != 0) {
--- 4534,4544 ----
                   * in by default so we can print a warning and modify the class
                   * if we wouldn't be using FSS.
                   */
                  char class_name[PC_CLNMSZ];
  
!                 if (zonecfg_get_dflt_sched_class(handle, class_name,
                      sizeof (class_name)) != Z_OK) {
                          zerror(zlogp, B_FALSE, "WARNING: unable to determine "
                              "the zone's scheduling class");
  
                  } else if (strcmp("FSS", class_name) != 0) {
*** 4429,4464 ****
           * If we are rebooting we want to attempt to reuse any temporary pool
           * that was previously set up.  zonecfg_bind_tmp_pool() will do the
           * right thing in all cases (reuse or create) based on the current
           * zonecfg.
           */
!         if ((res = zonecfg_bind_tmp_pool(snap_hndl, zoneid, pool_err,
              sizeof (pool_err))) != Z_OK) {
                  if (res == Z_POOL || res == Z_POOL_CREATE || res == Z_POOL_BIND)
                          zerror(zlogp, B_FALSE, "%s: %s\ndedicated-cpu setting "
                              "cannot be instantiated", zonecfg_strerror(res),
                              pool_err);
                  else
                          zerror(zlogp, B_FALSE, "could not bind zone to "
                              "temporary pool: %s", zonecfg_strerror(res));
                  return (Z_POOL_BIND);
          }
  
          /*
           * Check if we need to warn about poold not being enabled.
           */
!         if (zonecfg_warn_poold(snap_hndl)) {
                  zerror(zlogp, B_FALSE, "WARNING: A range of dedicated-cpus has "
                      "been specified\nbut the dynamic pool service is not "
                      "enabled.\nThe system will not dynamically adjust the\n"
                      "processor allocation within the specified range\n"
                      "until svc:/system/pools/dynamic is enabled.\n"
                      "See poold(1M).");
          }
  
          /* The following is a warning, not an error. */
!         if ((res = zonecfg_bind_pool(snap_hndl, zoneid, pool_err,
              sizeof (pool_err))) != Z_OK) {
                  if (res == Z_POOL_BIND)
                          zerror(zlogp, B_FALSE, "WARNING: unable to bind to "
                              "pool '%s'; using default pool.", pool_err);
                  else if (res == Z_POOL)
--- 4567,4603 ----
           * If we are rebooting we want to attempt to reuse any temporary pool
           * that was previously set up.  zonecfg_bind_tmp_pool() will do the
           * right thing in all cases (reuse or create) based on the current
           * zonecfg.
           */
!         if ((res = zonecfg_bind_tmp_pool(handle, zoneid, pool_err,
              sizeof (pool_err))) != Z_OK) {
                  if (res == Z_POOL || res == Z_POOL_CREATE || res == Z_POOL_BIND)
                          zerror(zlogp, B_FALSE, "%s: %s\ndedicated-cpu setting "
                              "cannot be instantiated", zonecfg_strerror(res),
                              pool_err);
                  else
                          zerror(zlogp, B_FALSE, "could not bind zone to "
                              "temporary pool: %s", zonecfg_strerror(res));
+                 zonecfg_fini_handle(handle);
                  return (Z_POOL_BIND);
          }
  
          /*
           * Check if we need to warn about poold not being enabled.
           */
!         if (zonecfg_warn_poold(handle)) {
                  zerror(zlogp, B_FALSE, "WARNING: A range of dedicated-cpus has "
                      "been specified\nbut the dynamic pool service is not "
                      "enabled.\nThe system will not dynamically adjust the\n"
                      "processor allocation within the specified range\n"
                      "until svc:/system/pools/dynamic is enabled.\n"
                      "See poold(1M).");
          }
  
          /* The following is a warning, not an error. */
!         if ((res = zonecfg_bind_pool(handle, zoneid, pool_err,
              sizeof (pool_err))) != Z_OK) {
                  if (res == Z_POOL_BIND)
                          zerror(zlogp, B_FALSE, "WARNING: unable to bind to "
                              "pool '%s'; using default pool.", pool_err);
                  else if (res == Z_POOL)
*** 4468,4480 ****
                          zerror(zlogp, B_FALSE, "WARNING: %s",
                              zonecfg_strerror(res));
          }
  
          /* Update saved pool name in case it has changed */
!         (void) zonecfg_get_poolname(snap_hndl, zone_name, pool_name,
              sizeof (pool_name));
  
          return (Z_OK);
  }
  
  static void
  report_prop_err(zlog_t *zlogp, const char *name, const char *value, int res)
--- 4607,4620 ----
                          zerror(zlogp, B_FALSE, "WARNING: %s",
                              zonecfg_strerror(res));
          }
  
          /* Update saved pool name in case it has changed */
!         (void) zonecfg_get_poolname(handle, zone_name, pool_name,
              sizeof (pool_name));
  
+         zonecfg_fini_handle(handle);
          return (Z_OK);
  }
  
  static void
  report_prop_err(zlog_t *zlogp, const char *name, const char *value, int res)
*** 4571,4602 ****
  
          return (Z_OK);
  }
  
  static int
! setup_zone_attrs(zlog_t *zlogp, zoneid_t zoneid)
  {
          int res = Z_OK;
  
!         if ((res = setup_zone_hostid(snap_hndl, zlogp, zoneid)) != Z_OK)
                  goto out;
  
!         if ((res = setup_zone_fs_allowed(snap_hndl, zlogp, zoneid)) != Z_OK)
                  goto out;
  
  out:
          return (res);
  }
  
- /*
-  * The zone_did is a persistent debug ID.  Each zone should have a unique ID
-  * in the kernel.  This is used for things like DTrace which want to monitor
-  * zones across reboots.  They can't use the zoneid since that changes on
-  * each boot.
-  */
  zoneid_t
! vplat_create(zlog_t *zlogp, zone_mnt_t mount_cmd, zoneid_t zone_did)
  {
          zoneid_t rval = -1;
          priv_set_t *privs;
          char rootpath[MAXPATHLEN];
          char *rctlbuf = NULL;
--- 4711,4747 ----
  
          return (Z_OK);
  }
  
  static int
! setup_zone_attrs(zlog_t *zlogp, char *zone_namep, zoneid_t zoneid)
  {
+         zone_dochandle_t handle;
          int res = Z_OK;
  
!         if ((handle = zonecfg_init_handle()) == NULL) {
!                 zerror(zlogp, B_TRUE, "getting zone configuration handle");
!                 return (Z_BAD_HANDLE);
!         }
!         if ((res = zonecfg_get_snapshot_handle(zone_namep, handle)) != Z_OK) {
!                 zerror(zlogp, B_FALSE, "invalid configuration");
                  goto out;
+         }
  
!         if ((res = setup_zone_hostid(handle, zlogp, zoneid)) != Z_OK)
                  goto out;
  
+         if ((res = setup_zone_fs_allowed(handle, zlogp, zoneid)) != Z_OK)
+                 goto out;
+ 
  out:
+         zonecfg_fini_handle(handle);
          return (res);
  }
  
  zoneid_t
! vplat_create(zlog_t *zlogp, zone_mnt_t mount_cmd)
  {
          zoneid_t rval = -1;
          priv_set_t *privs;
          char rootpath[MAXPATHLEN];
          char *rctlbuf = NULL;
*** 4608,4618 ****
          char *kzone;
          FILE *fp = NULL;
          tsol_zcent_t *zcent = NULL;
          int match = 0;
          int doi = 0;
!         int flags = -1;
          zone_iptype_t iptype;
  
          if (zone_get_rootpath(zone_name, rootpath, sizeof (rootpath)) != Z_OK) {
                  zerror(zlogp, B_TRUE, "unable to determine zone root");
                  return (-1);
--- 4753,4763 ----
          char *kzone;
          FILE *fp = NULL;
          tsol_zcent_t *zcent = NULL;
          int match = 0;
          int doi = 0;
!         int flags;
          zone_iptype_t iptype;
  
          if (zone_get_rootpath(zone_name, rootpath, sizeof (rootpath)) != Z_OK) {
                  zerror(zlogp, B_TRUE, "unable to determine zone root");
                  return (-1);
*** 4630,4641 ****
                  break;
          case ZS_EXCLUSIVE:
                  flags = ZCF_NET_EXCL;
                  break;
          }
-         if (flags == -1)
-                 abort();
  
          if ((privs = priv_allocset()) == NULL) {
                  zerror(zlogp, B_TRUE, "%s failed", "priv_allocset");
                  return (-1);
          }
--- 4775,4784 ----
*** 4735,4745 ****
          }
  
          xerr = 0;
          if ((zoneid = zone_create(kzone, rootpath, privs, rctlbuf,
              rctlbufsz, zfsbuf, zfsbufsz, &xerr, match, doi, zlabel,
!             flags, zone_did)) == -1) {
                  if (xerr == ZE_AREMOUNTS) {
                          if (zonecfg_find_mounts(rootpath, NULL, NULL) < 1) {
                                  zerror(zlogp, B_FALSE,
                                      "An unknown file-system is mounted on "
                                      "a subdirectory of %s", rootpath);
--- 4878,4888 ----
          }
  
          xerr = 0;
          if ((zoneid = zone_create(kzone, rootpath, privs, rctlbuf,
              rctlbufsz, zfsbuf, zfsbufsz, &xerr, match, doi, zlabel,
!             flags)) == -1) {
                  if (xerr == ZE_AREMOUNTS) {
                          if (zonecfg_find_mounts(rootpath, NULL, NULL) < 1) {
                                  zerror(zlogp, B_FALSE,
                                      "An unknown file-system is mounted on "
                                      "a subdirectory of %s", rootpath);
*** 4781,4791 ****
          if (mount_cmd == Z_MNT_BOOT) {
                  brand_handle_t bh;
                  struct brand_attr attr;
                  char modname[MAXPATHLEN];
  
!                 if (setup_zone_attrs(zlogp, zoneid) != Z_OK)
                          goto error;
  
                  if ((bh = brand_open(brand_name)) == NULL) {
                          zerror(zlogp, B_FALSE,
                              "unable to determine brand name");
--- 4924,4934 ----
          if (mount_cmd == Z_MNT_BOOT) {
                  brand_handle_t bh;
                  struct brand_attr attr;
                  char modname[MAXPATHLEN];
  
!                 if (setup_zone_attrs(zlogp, zone_name, zoneid) != Z_OK)
                          goto error;
  
                  if ((bh = brand_open(brand_name)) == NULL) {
                          zerror(zlogp, B_FALSE,
                              "unable to determine brand name");
*** 4839,4850 ****
                  (void) zone_shutdown(zoneid);
                  (void) zone_destroy(zoneid);
          }
          if (rctlbuf != NULL)
                  free(rctlbuf);
-         if (zfsbuf != NULL)
-                 free(zfsbuf);
          priv_freeset(privs);
          if (fp != NULL)
                  zonecfg_close_scratch(fp);
          lofs_discard_mnttab();
          if (zcent != NULL)
--- 4982,4991 ----
*** 4979,4990 ****
                              0) {
                                  lofs_discard_mnttab();
                                  return (-1);
                          }
                          break;
-                 default:
-                         abort();
                  }
          }
  
          write_index_file(zoneid);
  
--- 5120,5129 ----
*** 5056,5067 ****
                  return (0);
          }
  }
  
  int
! vplat_teardown(zlog_t *zlogp, boolean_t unmount_cmd, boolean_t rebooting,
!     boolean_t debug)
  {
          char *kzone;
          zoneid_t zoneid;
          int res;
          char pool_err[128];
--- 5195,5205 ----
                  return (0);
          }
  }
  
  int
! vplat_teardown(zlog_t *zlogp, boolean_t unmount_cmd, boolean_t rebooting)
  {
          char *kzone;
          zoneid_t zoneid;
          int res;
          char pool_err[128];
*** 5095,5110 ****
                  if (unmount_cmd)
                          (void) lu_root_teardown(zlogp);
                  goto error;
          }
  
!         if (remove_datalink_pool(zlogp, zoneid) != 0)
                  zerror(zlogp, B_FALSE, "unable clear datalink pool property");
  
!         if (remove_datalink_protect(zlogp, zoneid) != 0)
                  zerror(zlogp, B_FALSE,
                      "unable clear datalink protect property");
  
          /*
           * The datalinks assigned to the zone will be removed from the NGZ as
           * part of zone_shutdown() so that we need to remove protect/pool etc.
           * before zone_shutdown(). Even if the shutdown itself fails, the zone
--- 5233,5252 ----
                  if (unmount_cmd)
                          (void) lu_root_teardown(zlogp);
                  goto error;
          }
  
!         if (remove_datalink_pool(zlogp, zoneid) != 0) {
                  zerror(zlogp, B_FALSE, "unable clear datalink pool property");
+                 goto error;
+         }
  
!         if (remove_datalink_protect(zlogp, zoneid) != 0) {
                  zerror(zlogp, B_FALSE,
                      "unable clear datalink protect property");
+                 goto error;
+         }
  
          /*
           * The datalinks assigned to the zone will be removed from the NGZ as
           * part of zone_shutdown() so that we need to remove protect/pool etc.
           * before zone_shutdown(). Even if the shutdown itself fails, the zone
*** 5134,5144 ****
                  goto error;
          }
          brand_close(bh);
  
          if ((strlen(cmdbuf) > EXEC_LEN) &&
!             (do_subproc(zlogp, cmdbuf, NULL, debug) != Z_OK)) {
                  zerror(zlogp, B_FALSE, "%s failed", cmdbuf);
                  goto error;
          }
  
          if (!unmount_cmd) {
--- 5276,5286 ----
                  goto error;
          }
          brand_close(bh);
  
          if ((strlen(cmdbuf) > EXEC_LEN) &&
!             (do_subproc(zlogp, cmdbuf, NULL) != Z_OK)) {
                  zerror(zlogp, B_FALSE, "%s failed", cmdbuf);
                  goto error;
          }
  
          if (!unmount_cmd) {
*** 5166,5175 ****
--- 5308,5323 ----
                                      "network interfaces in zone");
                                  goto error;
                          }
                          break;
                  case ZS_EXCLUSIVE:
+                         if (unconfigure_exclusive_network_interfaces(zlogp,
+                             zoneid) != 0) {
+                                 zerror(zlogp, B_FALSE, "unable to unconfigure "
+                                     "network interfaces in zone");
+                                 goto error;
+                         }
                          status = dladm_zone_halt(dld_handle, zoneid);
                          if (status != DLADM_STATUS_OK) {
                                  zerror(zlogp, B_FALSE, "unable to notify "
                                      "dlmgmtd of zone halt: %s",
                                      dladm_status2str(status, errmsg));
*** 5202,5214 ****
          if (!unmount_cmd) {
                  boolean_t destroy_tmp_pool = B_TRUE;
  
                  if (rebooting) {
                          struct zone_psettab pset_tab;
  
!                         if (zonecfg_lookup_pset(snap_hndl, &pset_tab) == Z_OK)
                                  destroy_tmp_pool = B_FALSE;
                  }
  
                  if (destroy_tmp_pool) {
                          if ((res = zonecfg_destroy_tmp_pool(zone_name, pool_err,
                              sizeof (pool_err))) != Z_OK) {
--- 5350,5367 ----
          if (!unmount_cmd) {
                  boolean_t destroy_tmp_pool = B_TRUE;
  
                  if (rebooting) {
                          struct zone_psettab pset_tab;
+                         zone_dochandle_t handle;
  
!                         if ((handle = zonecfg_init_handle()) != NULL &&
!                             zonecfg_get_handle(zone_name, handle) == Z_OK &&
!                             zonecfg_lookup_pset(handle, &pset_tab) == Z_OK)
                                  destroy_tmp_pool = B_FALSE;
+ 
+                         zonecfg_fini_handle(handle);
                  }
  
                  if (destroy_tmp_pool) {
                          if ((res = zonecfg_destroy_tmp_pool(zone_name, pool_err,
                              sizeof (pool_err))) != Z_OK) {