Print this page
OS-5330 zoneadm mounting an lx or joyent branded zone fails
Reviewed by: Jerry Jelinek <jerry.jelinek@joyent.com>
Approved by: Jerry Jelinek <jerry.jelinek@joyent.com>
(NOTE: Manual port, because of divergence from SmartOS.)
Network interfaces need to configure in /native/dev for LX.
Mismerged snap_hndl (should be handle) blocked lipkg zone boot
(NOTE:  There are other instances of snap_hndl we pulled in from
        illumos-joyent that may need to be nuked too.)
OS-1571 Placate gcc -Wparentheses
Reviewed by: Robert Mustacchi <rm@joyent.com>
OS-5292 zoneadmd should infer zone.max-processes
Reviewed by: Patrick Mooney <patrick.mooney@joyent.com>
OS-4915 want FX high priority zone configuration option
OS-4925 ps pri shows misleading value for zone in RT scheduling class
Reviewed by: Patrick Mooney <patrick.mooney@joyent.com>
OS-4254 libbrand token substitution incomplete for mount entries
OS-3776 project rctls should be in sync with zone rctls
OS-3524 in order to support interaction with docker containers, need to be able to connect to stdio for init from GZ
OS-3525 in order to support 'docker logs' need to be able to get stdio from zone to log file
OS-399 zone phys. mem. cap should be a rctl and have associated kstat
        
*** 19,30 ****
   * CDDL HEADER END
   */
  
  /*
   * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
-  * Copyright (c) 2013, Joyent Inc. All rights reserved.
   * 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,145 ****
          MNTOPT_RO "," MNTOPT_LOFS_NOSUB "," MNTOPT_NODEVICES
  
  #define DFSTYPES        "/etc/dfs/fstypes"
  #define MAXTNZLEN       2048
  
- #define ALT_MOUNT(mount_cmd)    ((mount_cmd) != Z_MNT_BOOT)
- 
  /* 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 ----
*** 159,168 ****
--- 157,179 ----
  static m_label_t *zid_label = NULL;
  static priv_set_t *zprivs = NULL;
  
  static const char *DFLT_FS_ALLOWED = "hsfs,smbfs,nfs,nfs3,nfs4,nfsdyn";
  
+ typedef struct zone_proj_rctl_map {
+         char *zpr_zone_rctl;
+         char *zpr_project_rctl;
+ } zone_proj_rctl_map_t;
+ 
+ static zone_proj_rctl_map_t zone_proj_rctl_map[] = {
+         {"zone.max-msg-ids",    "project.max-msg-ids"},
+         {"zone.max-sem-ids",    "project.max-sem-ids"},
+         {"zone.max-shm-ids",    "project.max-shm-ids"},
+         {"zone.max-shm-memory", "project.max-shm-memory"},
+         {NULL,                  NULL}
+ };
+ 
  /* from libsocket, not in any header file */
  extern int getnetmaskbyaddr(struct in_addr, struct in_addr *);
  
  /* from zoneadmd */
  extern char query_hook[];
*** 1148,1163 ****
          /* 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)) {
                  zerror(zlogp, B_FALSE, "can't get handle for zone "
                      "%s: %s", zone_name, zonecfg_strerror(err));
                  goto cleanup;
          }
!         if (err = zonecfg_setdevent(handle)) {
                  zerror(zlogp, B_FALSE, "%s: %s", zone_name,
                      zonecfg_strerror(err));
                  goto cleanup;
          }
          while (zonecfg_getdevent(handle, &ztab) == Z_OK) {
--- 1159,1174 ----
          /* 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) {
*** 1669,1679 ****
  
  static int
  mount_filesystems(zlog_t *zlogp, zone_mnt_t mount_cmd)
  {
          char rootpath[MAXPATHLEN];
-         char zonepath[MAXPATHLEN];
          char brand[MAXNAMELEN];
          char luroot[MAXPATHLEN];
          int i, num_fs = 0;
          struct zone_fstab *fs_ptr = NULL;
          zone_dochandle_t handle = NULL;
--- 1680,1689 ----
*** 1688,1702 ****
                      zone_state_str(ZONE_STATE_READY),
                      zone_state_str(ZONE_STATE_MOUNTED));
                  goto bad;
          }
  
-         if (zone_get_zonepath(zone_name, zonepath, sizeof (zonepath)) != Z_OK) {
-                 zerror(zlogp, B_TRUE, "unable to determine zone path");
-                 goto bad;
-         }
- 
          if (zone_get_rootpath(zone_name, rootpath, sizeof (rootpath)) != Z_OK) {
                  zerror(zlogp, B_TRUE, "unable to determine zone root");
                  goto bad;
          }
  
--- 1698,1707 ----
*** 1793,1819 ****
                  goto bad;
  
          qsort(fs_ptr, num_fs, sizeof (*fs_ptr), fs_compare);
  
          for (i = 0; i < num_fs; i++) {
!                 if (ALT_MOUNT(mount_cmd) &&
!                     strcmp(fs_ptr[i].zone_fs_dir, "/dev") == 0) {
                          size_t slen = strlen(rootpath) - 2;
  
                          /*
!                          * By default we'll try to mount /dev as /a/dev
!                          * but /dev is special and always goes at the top
!                          * so strip the trailing '/a' from the rootpath.
                           */
                          assert(strcmp(&rootpath[slen], "/a") == 0);
                          rootpath[slen] = '\0';
!                         if (mount_one(zlogp, &fs_ptr[i], rootpath, mount_cmd)
!                             != 0)
                                  goto bad;
                          rootpath[slen] = '/';
                          continue;
                  }
                  if (mount_one(zlogp, &fs_ptr[i], rootpath, mount_cmd) != 0)
                          goto bad;
          }
          if (ALT_MOUNT(mount_cmd) &&
              !build_mounted_post_var(zlogp, mount_cmd, rootpath, luroot))
--- 1798,1841 ----
                  goto bad;
  
          qsort(fs_ptr, num_fs, sizeof (*fs_ptr), fs_compare);
  
          for (i = 0; i < num_fs; i++) {
!                 if (ALT_MOUNT(mount_cmd)) {
!                         if (strcmp(fs_ptr[i].zone_fs_dir, "/dev") == 0) {
                                  size_t slen = strlen(rootpath) - 2;
  
                                  /*
!                                  * By default we'll try to mount /dev
!                                  * as /a/dev but /dev is special and
!                                  * always goes at the top so strip the
!                                  * trailing '/a' from the rootpath.
                                   */
                                  assert(strcmp(&rootpath[slen], "/a") == 0);
                                  rootpath[slen] = '\0';
!                                 if (mount_one(zlogp, &fs_ptr[i], rootpath,
!                                     mount_cmd) != 0)
                                          goto bad;
                                  rootpath[slen] = '/';
                                  continue;
+                         } else if (strcmp(brand_name, default_brand) != 0) {
+                                 /*
+                                  * If mounting non-native brand, skip
+                                  * mounting global mounts and
+                                  * filesystem entries since they are
+                                  * only needed for native pkg upgrade
+                                  * tools.
+                                  *
+                                  * The only exception right now is
+                                  * /dev (handled above), which is
+                                  * needed in the luroot in order to
+                                  * zlogin -S into the zone.
+                                  */
+                                 continue;
                          }
+                 }
+ 
                  if (mount_one(zlogp, &fs_ptr[i], rootpath, mount_cmd) != 0)
                          goto bad;
          }
          if (ALT_MOUNT(mount_cmd) &&
              !build_mounted_post_var(zlogp, mount_cmd, rootpath, luroot))
*** 2886,2895 ****
--- 2908,2936 ----
                  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
*** 2931,2941 ****
                                  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(handle);
                                  zonecfg_fini_handle(handle);
                                  zerror(zlogp, B_TRUE,
                                      "failed to initialize profile");
--- 2972,2982 ----
                                  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");
*** 3315,3324 ****
--- 3356,3378 ----
          free(privname);
          zonecfg_fini_handle(handle);
          return (error);
  }
  
+ static char *
+ zone_proj_rctl(const char *name)
+ {
+         int i;
+ 
+         for (i = 0; zone_proj_rctl_map[i].zpr_zone_rctl != NULL; i++) {
+                 if (strcmp(name, zone_proj_rctl_map[i].zpr_zone_rctl) == 0) {
+                         return (zone_proj_rctl_map[i].zpr_project_rctl);
+                 }
+         }
+         return (NULL);
+ }
+ 
  static int
  get_rctls(zlog_t *zlogp, char **bufp, size_t *bufsizep)
  {
          nvlist_t *nvl = NULL;
          char *nvl_packed = NULL;
*** 3329,3338 ****
--- 3383,3393 ----
          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) {
*** 3351,3374 ****
                  goto out;
          }
  
          /*
           * Allow the administrator to control both the maximum number of
!          * process table slots and the maximum number of lwps with just the
!          * max-processes property.  If only the max-processes property is set,
!          * we add a max-lwps property with a limit derived from max-processes.
           */
!         if (zonecfg_get_aliased_rctl(handle, ALIAS_MAXPROCS, &maxprocs)
!             == Z_OK &&
!             zonecfg_get_aliased_rctl(handle, ALIAS_MAXLWPS, &maxlwps)
!             == Z_NO_ENTRY) {
!                 if (zonecfg_set_aliased_rctl(handle, ALIAS_MAXLWPS,
                      maxprocs * LWPS_PER_PROCESS) != Z_OK) {
                          zerror(zlogp, B_FALSE, "unable to set max-lwps alias");
                          goto out;
                  }
          }
  
          if (zonecfg_setrctlent(handle) != Z_OK) {
                  zerror(zlogp, B_FALSE, "%s failed", "zonecfg_setrctlent");
                  goto out;
          }
--- 3406,3438 ----
                  goto out;
          }
  
          /*
           * Allow the administrator to control both the maximum number of
!          * process table slots, and the maximum number of lwps, with a single
!          * max-processes or max-lwps property. If only the max-processes
!          * property is set, we add a max-lwps property with a limit derived
!          * from max-processes. If only the max-lwps property is set, we add a
!          * max-processes property with the same limit as max-lwps.
           */
!         rproc = zonecfg_get_aliased_rctl(snap_hndl, ALIAS_MAXPROCS, &maxprocs);
!         rlwp = zonecfg_get_aliased_rctl(snap_hndl, ALIAS_MAXLWPS, &maxlwps);
!         if (rproc == Z_OK && rlwp == Z_NO_ENTRY) {
!                 if (zonecfg_set_aliased_rctl(snap_hndl, ALIAS_MAXLWPS,
                      maxprocs * LWPS_PER_PROCESS) != Z_OK) {
                          zerror(zlogp, B_FALSE, "unable to set max-lwps alias");
                          goto out;
                  }
+         } else if (rlwp == Z_OK && rproc == Z_NO_ENTRY) {
+                 /* no scaling for max-proc value */
+                 if (zonecfg_set_aliased_rctl(snap_hndl, ALIAS_MAXPROCS,
+                     maxlwps) != Z_OK) {
+                         zerror(zlogp, B_FALSE,
+                             "unable to set max-processes alias");
+                         goto out;
                  }
+         }
  
          if (zonecfg_setrctlent(handle) != Z_OK) {
                  zerror(zlogp, B_FALSE, "%s failed", "zonecfg_setrctlent");
                  goto out;
          }
*** 3379,3388 ****
--- 3443,3453 ----
          }
          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;
  
                  /* zoneadm should have already warned about unknown rctls. */
                  if (!zonecfg_is_rctl(name)) {
                          zonecfg_free_rctl_value_list(rctltab.zone_rctl_valptr);
                          rctltab.zone_rctl_valptr = NULL;
*** 3445,3454 ****
--- 3510,3539 ----
                                  goto out;
                          }
                  }
                  zonecfg_free_rctl_value_list(rctltab.zone_rctl_valptr);
                  rctltab.zone_rctl_valptr = NULL;
+ 
+                 /*
+                  * With no action on our part we will start zsched with the
+                  * project rctl values for our (zoneadmd) current project. For
+                  * brands running a variant of Illumos, that's not a problem
+                  * since they will setup their own projects, but for a
+                  * non-native brand like lx, where there are no projects, we
+                  * want to start things up with the same project rctls as the
+                  * corresponding zone rctls, since nothing within the zone will
+                  * ever change the project rctls.
+                  */
+                 if ((proj_nm = zone_proj_rctl(name)) != NULL) {
+                         if (nvlist_add_nvlist_array(nvl, proj_nm, nvlv, count)
+                             != 0) {
+                                 zerror(zlogp, B_FALSE,
+                                     "nvlist_add_nvlist_arrays failed");
+                                 goto out;
+                         }
+                 }
+ 
                  if (nvlist_add_nvlist_array(nvl, (char *)name, nvlv, count)
                      != 0) {
                          zerror(zlogp, B_FALSE, "%s failed",
                              "nvlist_add_nvlist_array");
                          goto out;
*** 3706,3726 ****
  {
          int             error = -1;
          zfs_handle_t    *zhp;
          libzfs_handle_t *hdl;
          m_label_t       ds_sl;
-         char            zonepath[MAXPATHLEN];
          char            ds_hexsl[MAXNAMELEN];
  
          if (!is_system_labeled())
                  return (0);
  
-         if (zone_get_zonepath(zone_name, zonepath, sizeof (zonepath)) != Z_OK) {
-                 zerror(zlogp, B_TRUE, "unable to determine zone path");
-                 return (-1);
-         }
- 
          if (!is_zonepath_zfs(zonepath))
                  return (0);
  
          if ((hdl = libzfs_init()) == NULL) {
                  zerror(zlogp, B_FALSE, "opening ZFS library");
--- 3791,3805 ----
*** 4387,4405 ****
          }
          return (B_FALSE);
  }
  
  /*
!  * Set memory cap and pool info for the zone's resource management
!  * configuration.
   */
  static int
  setup_zone_rm(zlog_t *zlogp, char *zone_name, zoneid_t zoneid)
  {
          int res;
          uint64_t tmp;
-         struct zone_mcaptab mcap;
          char sched[MAXNAMELEN];
          zone_dochandle_t handle = NULL;
          char pool_err[128];
  
          if ((handle = zonecfg_init_handle()) == NULL) {
--- 4466,4482 ----
          }
          return (B_FALSE);
  }
  
  /*
!  * Set pool info for the zone's resource management configuration.
   */
  static int
  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) {
*** 4411,4452 ****
                  zerror(zlogp, B_FALSE, "invalid configuration");
                  zonecfg_fini_handle(handle);
                  return (res);
          }
  
-         /*
-          * If a memory cap is configured, set the cap in the kernel using
-          * zone_setattr() and make sure the rcapd SMF service is enabled.
-          */
-         if (zonecfg_getmcapent(handle, &mcap) == Z_OK) {
-                 uint64_t num;
-                 char smf_err[128];
- 
-                 num = (uint64_t)strtoull(mcap.zone_physmem_cap, NULL, 10);
-                 if (zone_setattr(zoneid, ZONE_ATTR_PHYS_MCAP, &num, 0) == -1) {
-                         zerror(zlogp, B_TRUE, "could not set zone memory cap");
-                         zonecfg_fini_handle(handle);
-                         return (Z_INVAL);
-                 }
- 
-                 if (zonecfg_enable_rcapd(smf_err, sizeof (smf_err)) != Z_OK) {
-                         zerror(zlogp, B_FALSE, "enabling system/rcap service "
-                             "failed: %s", smf_err);
-                         zonecfg_fini_handle(handle);
-                         return (Z_INVAL);
-                 }
-         }
- 
          /* 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");
  
!         } else if (zonecfg_get_aliased_rctl(handle, ALIAS_SHARES, &tmp)
              == Z_OK) {
                  /*
                   * If the zone has the zone.cpu-shares rctl set then we want to
                   * use the Fair Share Scheduler (FSS) for processes in the
                   * zone.  Check what scheduling class the zone would be running
--- 4488,4533 ----
                  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");
  
!                 if (strcmp(sched, "FX") == 0) {
!                         /*
!                          * When FX is specified then by default all processes
!                          * will start at the lowest priority level (0) and
!                          * stay there. We support an optional attr which
!                          * indicates that all the processes should be "high
!                          * priority". We set this on the zone so that starting
!                          * init will set the priority high.
!                          */
!                         struct zone_attrtab a;
! 
!                         bzero(&a, sizeof (a));
!                         (void) strlcpy(a.zone_attr_name, "fixed-hi-prio",
!                             sizeof (a.zone_attr_name));
! 
!                         if (zonecfg_lookup_attr(snap_hndl, &a) == Z_OK &&
!                             strcmp(a.zone_attr_value, "true") == 0) {
!                                 boolean_t hi = B_TRUE;
! 
!                                 if (zone_setattr(zoneid,
!                                     ZONE_ATTR_SCHED_FIXEDHI, (void *)hi,
!                                     sizeof (hi)) == -1)
!                                         zerror(zlogp, B_TRUE, "WARNING: unable "
!                                             "to set high priority");
!                         }
!                 }
! 
!         } else if (zonecfg_get_aliased_rctl(snap_hndl, ALIAS_SHARES, &tmp)
              == Z_OK) {
                  /*
                   * If the zone has the zone.cpu-shares rctl set then we want to
                   * use the Fair Share Scheduler (FSS) for processes in the
                   * zone.  Check what scheduling class the zone would be running
*** 4989,4999 ****
  }
  
  int
  vplat_bringup(zlog_t *zlogp, zone_mnt_t mount_cmd, zoneid_t zoneid)
  {
!         char zonepath[MAXPATHLEN];
  
          if (mount_cmd == Z_MNT_BOOT && validate_datasets(zlogp) != 0) {
                  lofs_discard_mnttab();
                  return (-1);
          }
--- 5070,5080 ----
  }
  
  int
  vplat_bringup(zlog_t *zlogp, zone_mnt_t mount_cmd, zoneid_t zoneid)
  {
!         char zpath[MAXPATHLEN];
  
          if (mount_cmd == Z_MNT_BOOT && validate_datasets(zlogp) != 0) {
                  lofs_discard_mnttab();
                  return (-1);
          }
*** 5000,5018 ****
  
          /*
           * Before we try to mount filesystems we need to create the
           * attribute backing store for /dev
           */
!         if (zone_get_zonepath(zone_name, zonepath, sizeof (zonepath)) != Z_OK) {
!                 lofs_discard_mnttab();
!                 return (-1);
!         }
!         resolve_lofs(zlogp, zonepath, sizeof (zonepath));
  
          /* Make /dev directory owned by root, grouped sys */
!         if (make_one_dir(zlogp, zonepath, "/dev", DEFAULT_DIR_MODE,
!             0, 3) != 0) {
                  lofs_discard_mnttab();
                  return (-1);
          }
  
          if (mount_filesystems(zlogp, mount_cmd) != 0) {
--- 5081,5095 ----
  
          /*
           * Before we try to mount filesystems we need to create the
           * attribute backing store for /dev
           */
!         (void) strlcpy(zpath, zonepath, sizeof (zpath));
!         resolve_lofs(zlogp, zpath, sizeof (zpath));
  
          /* Make /dev directory owned by root, grouped sys */
!         if (make_one_dir(zlogp, zpath, "/dev", DEFAULT_DIR_MODE, 0, 3) != 0) {
                  lofs_discard_mnttab();
                  return (-1);
          }
  
          if (mount_filesystems(zlogp, mount_cmd) != 0) {
*** 5124,5134 ****
  {
          char *kzone;
          zoneid_t zoneid;
          int res;
          char pool_err[128];
-         char zpath[MAXPATHLEN];
          char cmdbuf[MAXPATHLEN];
          brand_handle_t bh = NULL;
          dladm_status_t status;
          char errmsg[DLADM_STRSIZE];
          ushort_t flags;
--- 5201,5210 ----
*** 5180,5195 ****
          if (zone_shutdown(zoneid) != 0) {
                  zerror(zlogp, B_TRUE, "unable to shutdown zone");
                  goto error;
          }
  
-         /* Get the zonepath of this zone */
-         if (zone_get_zonepath(zone_name, zpath, sizeof (zpath)) != Z_OK) {
-                 zerror(zlogp, B_FALSE, "unable to determine zone path");
-                 goto error;
-         }
- 
          /* Get a handle to the brand info for this zone */
          if ((bh = brand_open(brand_name)) == NULL) {
                  zerror(zlogp, B_FALSE, "unable to determine zone brand");
                  return (-1);
          }
--- 5256,5265 ----
*** 5196,5206 ****
          /*
           * If there is a brand 'halt' callback, execute it now to give the
           * brand a chance to cleanup any custom configuration.
           */
          (void) strcpy(cmdbuf, EXEC_PREFIX);
!         if (brand_get_halt(bh, zone_name, zpath, cmdbuf + EXEC_LEN,
              sizeof (cmdbuf) - EXEC_LEN) < 0) {
                  brand_close(bh);
                  zerror(zlogp, B_FALSE, "unable to determine branded zone's "
                      "halt callback.");
                  goto error;
--- 5266,5276 ----
          /*
           * If there is a brand 'halt' callback, execute it now to give the
           * brand a chance to cleanup any custom configuration.
           */
          (void) strcpy(cmdbuf, EXEC_PREFIX);
!         if (brand_get_halt(bh, zone_name, zonepath, cmdbuf + EXEC_LEN,
              sizeof (cmdbuf) - EXEC_LEN) < 0) {
                  brand_close(bh);
                  zerror(zlogp, B_FALSE, "unable to determine branded zone's "
                      "halt callback.");
                  goto error;