Print this page
        
*** 118,132 ****
  boolean_t zone_isnative;
  boolean_t zone_iscluster;
  boolean_t zone_islabeled;
  boolean_t shutdown_in_progress;
  static zoneid_t zone_id;
- static zoneid_t zone_did = 0;
  dladm_handle_t dld_handle = NULL;
  
! char pre_statechg_hook[2 * MAXPATHLEN];
! char post_statechg_hook[2 * MAXPATHLEN];
  char query_hook[2 * MAXPATHLEN];
  
  zlog_t logsys;
  
  mutex_t lock = DEFAULTMUTEX;    /* to serialize stuff */
--- 118,131 ----
  boolean_t zone_isnative;
  boolean_t zone_iscluster;
  boolean_t zone_islabeled;
  boolean_t shutdown_in_progress;
  static zoneid_t zone_id;
  dladm_handle_t dld_handle = NULL;
  
! static char pre_statechg_hook[2 * MAXPATHLEN];
! static char post_statechg_hook[2 * MAXPATHLEN];
  char query_hook[2 * MAXPATHLEN];
  
  zlog_t logsys;
  
  mutex_t lock = DEFAULTMUTEX;    /* to serialize stuff */
*** 292,302 ****
  filter_bootargs(zlog_t *zlogp, const char *inargs, char *outargs,
      char *init_file)
  {
          int argc = 0, argc_save;
          int i;
!         int err = Z_OK;
          char *arg, *lasts, **argv = NULL, **argv_save;
          char zonecfg_args[BOOTARGS_MAX];
          char scratchargs[BOOTARGS_MAX], *sargs;
          char scratchopt[3];
          char c;
--- 291,301 ----
  filter_bootargs(zlog_t *zlogp, const char *inargs, char *outargs,
      char *init_file)
  {
          int argc = 0, argc_save;
          int i;
!         int err;
          char *arg, *lasts, **argv = NULL, **argv_save;
          char zonecfg_args[BOOTARGS_MAX];
          char scratchargs[BOOTARGS_MAX], *sargs;
          char scratchopt[3];
          char c;
*** 307,320 ****
           * If the user didn't specify transient boot arguments, check
           * to see if there were any specified in the zone configuration,
           * and use them if applicable.
           */
          if (inargs == NULL || inargs[0] == '\0')  {
                  bzero(zonecfg_args, sizeof (zonecfg_args));
!                 (void) zonecfg_get_bootargs(snap_hndl, zonecfg_args,
                      sizeof (zonecfg_args));
                  inargs = zonecfg_args;
          }
  
          if (strlen(inargs) >= BOOTARGS_MAX) {
                  zerror(zlogp, B_FALSE, "boot argument string too long");
                  return (Z_INVAL);
--- 306,334 ----
           * If the user didn't specify transient boot arguments, check
           * to see if there were any specified in the zone configuration,
           * and use them if applicable.
           */
          if (inargs == NULL || inargs[0] == '\0')  {
+                 zone_dochandle_t handle;
+                 if ((handle = zonecfg_init_handle()) == NULL) {
+                         zerror(zlogp, B_TRUE,
+                             "getting zone configuration handle");
+                         return (Z_BAD_HANDLE);
+                 }
+                 err = zonecfg_get_snapshot_handle(zone_name, handle);
+                 if (err != Z_OK) {
+                         zerror(zlogp, B_FALSE,
+                             "invalid configuration snapshot");
+                         zonecfg_fini_handle(handle);
+                         return (Z_BAD_HANDLE);
+                 }
+ 
                  bzero(zonecfg_args, sizeof (zonecfg_args));
!                 (void) zonecfg_get_bootargs(handle, zonecfg_args,
                      sizeof (zonecfg_args));
                  inargs = zonecfg_args;
+                 zonecfg_fini_handle(handle);
          }
  
          if (strlen(inargs) >= BOOTARGS_MAX) {
                  zerror(zlogp, B_FALSE, "boot argument string too long");
                  return (Z_INVAL);
*** 460,470 ****
  
  /*
   * Run the brand's pre-state change callback, if it exists.
   */
  static int
! brand_prestatechg(zlog_t *zlogp, int state, int cmd, boolean_t debug)
  {
          char cmdbuf[2 * MAXPATHLEN];
          const char *altroot;
  
          if (pre_statechg_hook[0] == '\0')
--- 474,484 ----
  
  /*
   * Run the brand's pre-state change callback, if it exists.
   */
  static int
! brand_prestatechg(zlog_t *zlogp, int state, int cmd)
  {
          char cmdbuf[2 * MAXPATHLEN];
          const char *altroot;
  
          if (pre_statechg_hook[0] == '\0')
*** 473,493 ****
          altroot = zonecfg_get_root();
          if (snprintf(cmdbuf, sizeof (cmdbuf), "%s %d %d %s", pre_statechg_hook,
              state, cmd, altroot) > sizeof (cmdbuf))
                  return (-1);
  
!         if (do_subproc(zlogp, cmdbuf, NULL, debug) != 0)
                  return (-1);
  
          return (0);
  }
  
  /*
   * Run the brand's post-state change callback, if it exists.
   */
  static int
! brand_poststatechg(zlog_t *zlogp, int state, int cmd, boolean_t debug)
  {
          char cmdbuf[2 * MAXPATHLEN];
          const char *altroot;
  
          if (post_statechg_hook[0] == '\0')
--- 487,507 ----
          altroot = zonecfg_get_root();
          if (snprintf(cmdbuf, sizeof (cmdbuf), "%s %d %d %s", pre_statechg_hook,
              state, cmd, altroot) > sizeof (cmdbuf))
                  return (-1);
  
!         if (do_subproc(zlogp, cmdbuf, NULL) != 0)
                  return (-1);
  
          return (0);
  }
  
  /*
   * Run the brand's post-state change callback, if it exists.
   */
  static int
! brand_poststatechg(zlog_t *zlogp, int state, int cmd)
  {
          char cmdbuf[2 * MAXPATHLEN];
          const char *altroot;
  
          if (post_statechg_hook[0] == '\0')
*** 496,506 ****
          altroot = zonecfg_get_root();
          if (snprintf(cmdbuf, sizeof (cmdbuf), "%s %d %d %s", post_statechg_hook,
              state, cmd, altroot) > sizeof (cmdbuf))
                  return (-1);
  
!         if (do_subproc(zlogp, cmdbuf, NULL, debug) != 0)
                  return (-1);
  
          return (0);
  }
  
--- 510,520 ----
          altroot = zonecfg_get_root();
          if (snprintf(cmdbuf, sizeof (cmdbuf), "%s %d %d %s", post_statechg_hook,
              state, cmd, altroot) > sizeof (cmdbuf))
                  return (-1);
  
!         if (do_subproc(zlogp, cmdbuf, NULL) != 0)
                  return (-1);
  
          return (0);
  }
  
*** 533,587 ****
  
  /*
   * Bring a zone up to the pre-boot "ready" stage.  The mount_cmd argument is
   * 'true' if this is being invoked as part of the processing for the "mount"
   * subcommand.
-  *
-  * If a scratch zone mount (ALT_MOUNT) is being performed then do not
-  * call the state change hooks.
   */
  static int
! zone_ready(zlog_t *zlogp, zone_mnt_t mount_cmd, int zstate, boolean_t debug)
  {
          int err;
-         boolean_t snapped = B_FALSE;
  
!         if ((snap_hndl = zonecfg_init_handle()) == NULL) {
!                 zerror(zlogp, B_TRUE, "getting zone configuration handle");
!                 goto bad;
!         }
          if ((err = zonecfg_create_snapshot(zone_name)) != Z_OK) {
                  zerror(zlogp, B_FALSE, "unable to create snapshot: %s",
                      zonecfg_strerror(err));
                  goto bad;
          }
-         snapped = B_TRUE;
  
!         if (zonecfg_get_snapshot_handle(zone_name, snap_hndl) != Z_OK) {
!                 zerror(zlogp, B_FALSE, "invalid configuration snapshot");
                  goto bad;
          }
- 
-         if (zone_did == 0)
-                 zone_did = zone_get_did(zone_name);
- 
-         if (!ALT_MOUNT(mount_cmd) &&
-             brand_prestatechg(zlogp, zstate, Z_READY, debug) != 0)
-                 goto bad;
- 
-         if ((zone_id = vplat_create(zlogp, mount_cmd, zone_did)) == -1)
-                 goto bad;
- 
          if (vplat_bringup(zlogp, mount_cmd, zone_id) != 0) {
                  bringup_failure_recovery = B_TRUE;
!                 (void) vplat_teardown(NULL, (mount_cmd != Z_MNT_BOOT), B_FALSE,
!                     debug);
                  goto bad;
          }
  
          if (!ALT_MOUNT(mount_cmd) &&
!             brand_poststatechg(zlogp, zstate, Z_READY, debug) != 0)
                  goto bad;
  
          return (0);
  
  bad:
--- 547,589 ----
  
  /*
   * Bring a zone up to the pre-boot "ready" stage.  The mount_cmd argument is
   * 'true' if this is being invoked as part of the processing for the "mount"
   * subcommand.
   */
  static int
! zone_ready(zlog_t *zlogp, zone_mnt_t mount_cmd, int zstate)
  {
          int err;
  
!         if (!ALT_MOUNT(mount_cmd) &&
!             brand_prestatechg(zlogp, zstate, Z_READY) != 0)
!                 return (-1);
! 
          if ((err = zonecfg_create_snapshot(zone_name)) != Z_OK) {
                  zerror(zlogp, B_FALSE, "unable to create snapshot: %s",
                      zonecfg_strerror(err));
                  goto bad;
          }
  
!         if ((zone_id = vplat_create(zlogp, mount_cmd)) == -1) {
!                 if ((err = zonecfg_destroy_snapshot(zone_name)) != Z_OK)
!                         zerror(zlogp, B_FALSE, "destroying snapshot: %s",
!                             zonecfg_strerror(err));
                  goto bad;
          }
          if (vplat_bringup(zlogp, mount_cmd, zone_id) != 0) {
                  bringup_failure_recovery = B_TRUE;
!                 (void) vplat_teardown(NULL, (mount_cmd != Z_MNT_BOOT), B_FALSE);
!                 if ((err = zonecfg_destroy_snapshot(zone_name)) != Z_OK)
!                         zerror(zlogp, B_FALSE, "destroying snapshot: %s",
!                             zonecfg_strerror(err));
                  goto bad;
          }
  
          if (!ALT_MOUNT(mount_cmd) &&
!             brand_poststatechg(zlogp, zstate, Z_READY) != 0)
                  goto bad;
  
          return (0);
  
  bad:
*** 588,606 ****
          /*
           * If something goes wrong, we up the zones's state to the target
           * state, READY, and then invoke the hook as if we're halting.
           */
          if (!ALT_MOUNT(mount_cmd))
!                 (void) brand_poststatechg(zlogp, ZONE_STATE_READY, Z_HALT,
!                     debug);
! 
!         if (snapped)
!                 if ((err = zonecfg_destroy_snapshot(zone_name)) != Z_OK)
!                         zerror(zlogp, B_FALSE, "destroying snapshot: %s",
!                             zonecfg_strerror(err));
!         zonecfg_fini_handle(snap_hndl);
!         snap_hndl = NULL;
          return (-1);
  }
  
  int
  init_template(void)
--- 590,600 ----
          /*
           * If something goes wrong, we up the zones's state to the target
           * state, READY, and then invoke the hook as if we're halting.
           */
          if (!ALT_MOUNT(mount_cmd))
!                 (void) brand_poststatechg(zlogp, ZONE_STATE_READY, Z_HALT);
          return (-1);
  }
  
  int
  init_template(void)
*** 777,788 ****
          return (0);
  }
  
  /*
   * env variable name format
!  *      _ZONECFG_{resource name}_{identifying attr. name}_{property name}
!  * Any dashes (-) in the property names are replaced with underscore (_).
   */
  static void
  set_zonecfg_env(char *rsrc, char *attr, char *name, char *val)
  {
          char *p;
--- 771,781 ----
          return (0);
  }
  
  /*
   * env variable name format
!  *      _ZONECFG;{resource name};{identifying attr. name};{property name}
   */
  static void
  set_zonecfg_env(char *rsrc, char *attr, char *name, char *val)
  {
          char *p;
*** 809,836 ****
   * If debug is true, export the brand hook debug env. variable as well.
   *
   * We could export more of the config in the future, as necessary.
   */
  static int
! setup_subproc_env(boolean_t debug)
  {
          int res;
          struct zone_nwiftab ntab;
          struct zone_devtab dtab;
-         struct zone_attrtab atab;
          char net_resources[MAXNAMELEN * 2];
          char dev_resources[MAXNAMELEN * 2];
  
!         /* snap_hndl is null when called through the set_brand_env code path */
!         if (snap_hndl == NULL)
!                 return (Z_OK);
  
!         net_resources[0] = '\0';
!         if ((res = zonecfg_setnwifent(snap_hndl)) != Z_OK)
                  goto done;
  
!         while (zonecfg_getnwifent(snap_hndl, &ntab) == Z_OK) {
                  struct zone_res_attrtab *rap;
                  char *phys;
  
                  phys = ntab.zone_nwif_physical;
  
--- 802,830 ----
   * If debug is true, export the brand hook debug env. variable as well.
   *
   * We could export more of the config in the future, as necessary.
   */
  static int
! setup_subproc_env()
  {
          int res;
+         zone_dochandle_t handle;
          struct zone_nwiftab ntab;
          struct zone_devtab dtab;
          char net_resources[MAXNAMELEN * 2];
          char dev_resources[MAXNAMELEN * 2];
  
!         if ((handle = zonecfg_init_handle()) == NULL)
!                 exit(Z_NOMEM);
  
!         if ((res = zonecfg_get_handle(zone_name, handle)) != Z_OK)
                  goto done;
  
!         if ((res = zonecfg_setnwifent(handle)) != Z_OK)
!                 goto done;
! 
!         while (zonecfg_getnwifent(handle, &ntab) == Z_OK) {
                  struct zone_res_attrtab *rap;
                  char *phys;
  
                  phys = ntab.zone_nwif_physical;
  
*** 853,873 ****
  
                  for (rap = ntab.zone_nwif_attrp; rap != NULL;
                      rap = rap->zone_res_attr_next)
                          set_zonecfg_env(RSRC_NET, phys, rap->zone_res_attr_name,
                              rap->zone_res_attr_value);
-                 nwifent_free_attrs(&ntab);
          }
  
!         (void) setenv("_ZONECFG_net_resources", net_resources, 1);
  
!         (void) zonecfg_endnwifent(snap_hndl);
! 
!         if ((res = zonecfg_setdevent(snap_hndl)) != Z_OK)
                  goto done;
  
!         while (zonecfg_getdevent(snap_hndl, &dtab) == Z_OK) {
                  struct zone_res_attrtab *rap;
                  char *match;
  
                  match = dtab.zone_dev_match;
  
--- 847,864 ----
  
                  for (rap = ntab.zone_nwif_attrp; rap != NULL;
                      rap = rap->zone_res_attr_next)
                          set_zonecfg_env(RSRC_NET, phys, rap->zone_res_attr_name,
                              rap->zone_res_attr_value);
          }
  
!         (void) zonecfg_endnwifent(handle);
  
!         if ((res = zonecfg_setdevent(handle)) != Z_OK)
                  goto done;
  
!         while (zonecfg_getdevent(handle, &dtab) == Z_OK) {
                  struct zone_res_attrtab *rap;
                  char *match;
  
                  match = dtab.zone_dev_match;
  
*** 878,930 ****
                      rap = rap->zone_res_attr_next)
                          set_zonecfg_env(RSRC_DEV, match,
                              rap->zone_res_attr_name, rap->zone_res_attr_value);
          }
  
!         (void) zonecfg_enddevent(snap_hndl);
  
-         if ((res = zonecfg_setattrent(snap_hndl)) != Z_OK)
-                 goto done;
- 
-         while (zonecfg_getattrent(snap_hndl, &atab) == Z_OK) {
-                 set_zonecfg_env("attr", NULL, atab.zone_attr_name,
-                     atab.zone_attr_value);
-         }
- 
-         (void) zonecfg_endattrent(snap_hndl);
- 
-         if (debug)
-                 (void) setenv("_ZONEADMD_brand_debug", "1", 1);
-         else
-                 (void) setenv("_ZONEADMD_brand_debug", "", 1);
- 
          res = Z_OK;
  
  done:
          return (res);
  }
  
- void
- nwifent_free_attrs(struct zone_nwiftab *np)
- {
-         struct zone_res_attrtab *rap;
- 
-         for (rap = np->zone_nwif_attrp; rap != NULL; ) {
-                 struct zone_res_attrtab *tp = rap;
- 
-                 rap = rap->zone_res_attr_next;
-                 free(tp);
-         }
- }
- 
  /*
   * If retstr is not NULL, the output of the subproc is returned in the str,
   * otherwise it is output using zerror().  Any memory allocated for retstr
   * should be freed by the caller.
   */
  int
! do_subproc(zlog_t *zlogp, char *cmdbuf, char **retstr, boolean_t debug)
  {
          char buf[1024];         /* arbitrary large amount */
          char *inbuf;
          FILE *file;
          int status;
--- 869,894 ----
                      rap = rap->zone_res_attr_next)
                          set_zonecfg_env(RSRC_DEV, match,
                              rap->zone_res_attr_name, rap->zone_res_attr_value);
          }
  
!         (void) zonecfg_enddevent(handle);
  
          res = Z_OK;
  
  done:
+         zonecfg_fini_handle(handle);
          return (res);
  }
  
  /*
   * If retstr is not NULL, the output of the subproc is returned in the str,
   * otherwise it is output using zerror().  Any memory allocated for retstr
   * should be freed by the caller.
   */
  int
! do_subproc(zlog_t *zlogp, char *cmdbuf, char **retstr)
  {
          char buf[1024];         /* arbitrary large amount */
          char *inbuf;
          FILE *file;
          int status;
*** 939,949 ****
                  rd_cnt = 0;
          } else {
                  inbuf = buf;
          }
  
!         if (setup_subproc_env(debug) != Z_OK) {
                  zerror(zlogp, B_FALSE, "failed to setup environment");
                  return (-1);
          }
  
          file = popen(cmdbuf, "r");
--- 903,913 ----
                  rd_cnt = 0;
          } else {
                  inbuf = buf;
          }
  
!         if (setup_subproc_env() != Z_OK) {
                  zerror(zlogp, B_FALSE, "failed to setup environment");
                  return (-1);
          }
  
          file = popen(cmdbuf, "r");
*** 952,968 ****
                  return (-1);
          }
  
          while (fgets(inbuf, 1024, file) != NULL) {
                  if (retstr == NULL) {
!                         if (zlogp != &logsys) {
!                                 int last = strlen(inbuf) - 1;
! 
!                                 if (inbuf[last] == '\n')
!                                         inbuf[last] = '\0';
                                  zerror(zlogp, B_FALSE, "%s", inbuf);
-                         }
                  } else {
                          char *p;
  
                          rd_cnt += 1024 - 1;
                          if ((p = realloc(*retstr, rd_cnt + 1024)) == NULL) {
--- 916,927 ----
                  return (-1);
          }
  
          while (fgets(inbuf, 1024, file) != NULL) {
                  if (retstr == NULL) {
!                         if (zlogp != &logsys)
                                  zerror(zlogp, B_FALSE, "%s", inbuf);
                  } else {
                          char *p;
  
                          rd_cnt += 1024 - 1;
                          if ((p = realloc(*retstr, rd_cnt + 1024)) == NULL) {
*** 989,1049 ****
          }
          return (WEXITSTATUS(status));
  }
  
  /*
-  * Get the path for this zone's init(1M) (or equivalent) process. First look
-  * for a zone-specific init-name attr, then get it from the brand.
-  */
- static int
- get_initname(brand_handle_t bh, char *initname, int len)
- {
-         struct zone_attrtab a;
- 
-         bzero(&a, sizeof (a));
-         (void) strlcpy(a.zone_attr_name, "init-name",
-             sizeof (a.zone_attr_name));
- 
-         if (zonecfg_lookup_attr(snap_hndl, &a) == Z_OK) {
-                 (void) strlcpy(initname, a.zone_attr_value, len);
-                 return (0);
-         }
- 
-         return (brand_get_initname(bh, initname, len));
- }
- 
- /*
-  * Get the restart-init flag for this zone's init(1M) (or equivalent) process.
-  * First look for a zone-specific restart-init attr, then get it from the brand.
-  */
- static boolean_t
- restartinit(brand_handle_t bh)
- {
-         struct zone_attrtab a;
- 
-         bzero(&a, sizeof (a));
-         (void) strlcpy(a.zone_attr_name, "restart-init",
-             sizeof (a.zone_attr_name));
- 
-         if (zonecfg_lookup_attr(snap_hndl, &a) == Z_OK) {
-                 if (strcmp(a.zone_attr_value, "false") == 0)
-                         return (B_FALSE);
-                 return (B_TRUE);
-         }
- 
-         return (brand_restartinit(bh));
- }
- 
- /*
   * Get the app-svc-dependent flag for this zone's init process. This is a
   * zone-specific attr which controls the type of contract we create for the
   * zone's init. When true, the contract will include CT_PR_EV_EXIT in the fatal
   * set, so that when any service which is in the same contract exits, the init
   * application will be terminated.
   */
  static boolean_t
! is_app_svc_dep(brand_handle_t bh)
  {
          struct zone_attrtab a;
  
          bzero(&a, sizeof (a));
          (void) strlcpy(a.zone_attr_name, "app-svc-dependent",
--- 948,967 ----
          }
          return (WEXITSTATUS(status));
  }
  
  /*
   * Get the app-svc-dependent flag for this zone's init process. This is a
   * zone-specific attr which controls the type of contract we create for the
   * zone's init. When true, the contract will include CT_PR_EV_EXIT in the fatal
   * set, so that when any service which is in the same contract exits, the init
   * application will be terminated.
+  *
+  * We use the global "snap_hndl", so no parameters get passed here.
   */
  static boolean_t
! is_app_svc_dep(void)
  {
          struct zone_attrtab a;
  
          bzero(&a, sizeof (a));
          (void) strlcpy(a.zone_attr_name, "app-svc-dependent",
*** 1056,1066 ****
  
          return (B_FALSE);
  }
  
  static int
! zone_bootup(zlog_t *zlogp, const char *bootargs, int zstate, boolean_t debug)
  {
          zoneid_t zoneid;
          struct stat st;
          char rpath[MAXPATHLEN], initpath[MAXPATHLEN], init_file[MAXPATHLEN];
          char nbootargs[BOOTARGS_MAX];
--- 974,984 ----
  
          return (B_FALSE);
  }
  
  static int
! zone_bootup(zlog_t *zlogp, const char *bootargs, int zstate)
  {
          zoneid_t zoneid;
          struct stat st;
          char rpath[MAXPATHLEN], initpath[MAXPATHLEN], init_file[MAXPATHLEN];
          char nbootargs[BOOTARGS_MAX];
*** 1072,1082 ****
          char errmsg[DLADM_STRSIZE];
          int err;
          boolean_t restart_init;
          boolean_t app_svc_dep;
  
!         if (brand_prestatechg(zlogp, zstate, Z_BOOT, debug) != 0)
                  return (-1);
  
          if ((zoneid = getzoneidbyname(zone_name)) == -1) {
                  zerror(zlogp, B_TRUE, "unable to get zoneid");
                  goto bad;
--- 990,1000 ----
          char errmsg[DLADM_STRSIZE];
          int err;
          boolean_t restart_init;
          boolean_t app_svc_dep;
  
!         if (brand_prestatechg(zlogp, zstate, Z_BOOT) != 0)
                  return (-1);
  
          if ((zoneid = getzoneidbyname(zone_name)) == -1) {
                  zerror(zlogp, B_TRUE, "unable to get zoneid");
                  goto bad;
*** 1115,1139 ****
                  brand_close(bh);
                  goto bad;
          }
  
          /* Get the path for this zone's init(1M) (or equivalent) process.  */
!         if (get_initname(bh, init_file, MAXPATHLEN) != 0) {
                  zerror(zlogp, B_FALSE,
                      "unable to determine zone's init(1M) location");
                  brand_close(bh);
                  goto bad;
          }
  
!         /* See if we should restart init if it dies. */
!         restart_init = restartinit(bh);
  
          /*
           * See if we need to setup contract dependencies between the zone's
           * primary application and any of its services.
           */
!         app_svc_dep = is_app_svc_dep(bh);
  
          brand_close(bh);
  
          err = filter_bootargs(zlogp, bootargs, nbootargs, init_file);
          if (err != Z_OK)
--- 1033,1057 ----
                  brand_close(bh);
                  goto bad;
          }
  
          /* Get the path for this zone's init(1M) (or equivalent) process.  */
!         if (brand_get_initname(bh, init_file, MAXPATHLEN) != 0) {
                  zerror(zlogp, B_FALSE,
                      "unable to determine zone's init(1M) location");
                  brand_close(bh);
                  goto bad;
          }
  
!         /* See if this zone's brand should restart init if it dies. */
!         restart_init = brand_restartinit(bh);
  
          /*
           * See if we need to setup contract dependencies between the zone's
           * primary application and any of its services.
           */
!         app_svc_dep = is_app_svc_dep();
  
          brand_close(bh);
  
          err = filter_bootargs(zlogp, bootargs, nbootargs, init_file);
          if (err != Z_OK)
*** 1155,1167 ****
          if (lstat(initpath, &st) == -1) {
                  zerror(zlogp, B_TRUE, "could not stat %s", initpath);
                  goto bad;
          }
  
!         if ((st.st_mode & S_IFMT) == S_IFLNK) {
!                 /* symlink, we'll have to wait and resolve when we boot */
!         } else if ((st.st_mode & S_IXUSR) == 0) {
                  zerror(zlogp, B_FALSE, "%s is not executable", initpath);
                  goto bad;
          }
  
          /*
--- 1073,1087 ----
          if (lstat(initpath, &st) == -1) {
                  zerror(zlogp, B_TRUE, "could not stat %s", initpath);
                  goto bad;
          }
  
!         /*
!          * If a symlink, we'll have to wait and resolve when we boot,
!          * otherwise check the executable bits now.
!          */
!         if ((st.st_mode & S_IFMT) != S_IFLNK && (st.st_mode & S_IXUSR) == 0) {
                  zerror(zlogp, B_FALSE, "%s is not executable", initpath);
                  goto bad;
          }
  
          /*
*** 1183,1193 ****
           * If there is a brand 'boot' callback, execute it now to give the
           * brand one last chance to do any additional setup before the zone
           * is booted.
           */
          if ((strlen(cmdbuf) > EXEC_LEN) &&
!             (do_subproc(zlogp, cmdbuf, NULL, debug) != Z_OK)) {
                  zerror(zlogp, B_FALSE, "%s failed", cmdbuf);
                  goto bad;
          }
  
          if (zone_setattr(zoneid, ZONE_ATTR_INITNAME, init_file, 0) == -1) {
--- 1103,1113 ----
           * If there is a brand 'boot' callback, execute it now to give the
           * brand one last chance to do any additional setup before the zone
           * is booted.
           */
          if ((strlen(cmdbuf) > EXEC_LEN) &&
!             (do_subproc(zlogp, cmdbuf, NULL) != Z_OK)) {
                  zerror(zlogp, B_FALSE, "%s failed", cmdbuf);
                  goto bad;
          }
  
          if (zone_setattr(zoneid, ZONE_ATTR_INITNAME, init_file, 0) == -1) {
*** 1221,1231 ****
          if (zone_boot(zoneid) == -1) {
                  zerror(zlogp, B_TRUE, "unable to boot zone");
                  goto bad;
          }
  
!         if (brand_poststatechg(zlogp, zstate, Z_BOOT, debug) != 0)
                  goto bad;
  
          /* Startup a thread to perform zfd logging/tty svc for the zone. */
          create_log_thread(zlogp, zone_id);
  
--- 1141,1151 ----
          if (zone_boot(zoneid) == -1) {
                  zerror(zlogp, B_TRUE, "unable to boot zone");
                  goto bad;
          }
  
!         if (brand_poststatechg(zlogp, zstate, Z_BOOT) != 0)
                  goto bad;
  
          /* Startup a thread to perform zfd logging/tty svc for the zone. */
          create_log_thread(zlogp, zone_id);
  
*** 1237,1269 ****
  bad:
          /*
           * If something goes wrong, we up the zones's state to the target
           * state, RUNNING, and then invoke the hook as if we're halting.
           */
!         (void) brand_poststatechg(zlogp, ZONE_STATE_RUNNING, Z_HALT, debug);
  
          return (-1);
  }
  
  static int
! zone_halt(zlog_t *zlogp, boolean_t unmount_cmd, boolean_t rebooting, int zstate,
!     boolean_t debug)
  {
          int err;
  
-         /*
-          * If performing a scratch zone unmount then do not call the
-          * state change hooks.
-          */
          if (unmount_cmd == B_FALSE &&
!             brand_prestatechg(zlogp, zstate, Z_HALT, debug) != 0)
                  return (-1);
  
          /* Shutting down, stop the memcap thread */
          destroy_mcap_thread();
  
!         if (vplat_teardown(zlogp, unmount_cmd, rebooting, debug) != 0) {
                  if (!bringup_failure_recovery)
                          zerror(zlogp, B_FALSE, "unable to destroy zone");
                  destroy_log_thread();
                  return (-1);
          }
--- 1157,1184 ----
  bad:
          /*
           * If something goes wrong, we up the zones's state to the target
           * state, RUNNING, and then invoke the hook as if we're halting.
           */
!         (void) brand_poststatechg(zlogp, ZONE_STATE_RUNNING, Z_HALT);
  
          return (-1);
  }
  
  static int
! zone_halt(zlog_t *zlogp, boolean_t unmount_cmd, boolean_t rebooting, int zstate)
  {
          int err;
  
          if (unmount_cmd == B_FALSE &&
!             brand_prestatechg(zlogp, zstate, Z_HALT) != 0)
                  return (-1);
  
          /* Shutting down, stop the memcap thread */
          destroy_mcap_thread();
  
!         if (vplat_teardown(zlogp, unmount_cmd, rebooting) != 0) {
                  if (!bringup_failure_recovery)
                          zerror(zlogp, B_FALSE, "unable to destroy zone");
                  destroy_log_thread();
                  return (-1);
          }
*** 1270,1289 ****
  
          /* Shut down is done, stop the log thread */
          destroy_log_thread();
  
          if (unmount_cmd == B_FALSE &&
!             brand_poststatechg(zlogp, zstate, Z_HALT, debug) != 0)
                  return (-1);
  
          if ((err = zonecfg_destroy_snapshot(zone_name)) != Z_OK)
                  zerror(zlogp, B_FALSE, "destroying snapshot: %s",
                      zonecfg_strerror(err));
  
-         zonecfg_fini_handle(snap_hndl);
-         snap_hndl = NULL;
- 
          return (0);
  }
  
  static int
  zone_graceful_shutdown(zlog_t *zlogp)
--- 1185,1201 ----
  
          /* Shut down is done, stop the log thread */
          destroy_log_thread();
  
          if (unmount_cmd == B_FALSE &&
!             brand_poststatechg(zlogp, zstate, Z_HALT) != 0)
                  return (-1);
  
          if ((err = zonecfg_destroy_snapshot(zone_name)) != Z_OK)
                  zerror(zlogp, B_FALSE, "destroying snapshot: %s",
                      zonecfg_strerror(err));
  
          return (0);
  }
  
  static int
  zone_graceful_shutdown(zlog_t *zlogp)
*** 1495,1509 ****
          ucred_t *uc = NULL;
          const priv_set_t *eset;
  
          zone_state_t zstate;
          zone_cmd_t cmd;
-         boolean_t debug;
          int init_status;
          zone_cmd_arg_t *zargp;
  
!         boolean_t kernelcall = B_TRUE;
  
          int rval = -1;
          uint64_t uniqid;
          zoneid_t zoneid = -1;
          zlog_t zlog;
--- 1407,1420 ----
          ucred_t *uc = NULL;
          const priv_set_t *eset;
  
          zone_state_t zstate;
          zone_cmd_t cmd;
          int init_status;
          zone_cmd_arg_t *zargp;
  
!         boolean_t kernelcall;
  
          int rval = -1;
          uint64_t uniqid;
          zoneid_t zoneid = -1;
          zlog_t zlog;
*** 1549,1559 ****
                      "unexpected (expected %d bytes)", alen,
                      sizeof (zone_cmd_arg_t));
                  goto out;
          }
          cmd = zargp->cmd;
-         debug = zargp->debug;
          init_status = zargp->status;
  
          if (door_ucred(&uc) != 0) {
                  zerror(&logsys, B_TRUE, "door_ucred");
                  goto out;
--- 1460,1469 ----
*** 1657,1685 ****
                  break;
  
          case ZONE_STATE_INSTALLED:
                  switch (cmd) {
                  case Z_READY:
!                         rval = zone_ready(zlogp, Z_MNT_BOOT, zstate, debug);
                          if (rval == 0)
                                  eventstream_write(Z_EVT_ZONE_READIED);
                          zcons_statechanged();
                          break;
                  case Z_BOOT:
                  case Z_FORCEBOOT:
                          eventstream_write(Z_EVT_ZONE_BOOTING);
!                         if ((rval = zone_ready(zlogp, Z_MNT_BOOT, zstate,
!                             debug)) == 0) {
                                  rval = zone_bootup(zlogp, zargp->bootbuf,
!                                     zstate, debug);
                          }
                          audit_put_record(zlogp, uc, rval, "boot");
                          zcons_statechanged();
                          if (rval != 0) {
                                  bringup_failure_recovery = B_TRUE;
                                  (void) zone_halt(zlogp, B_FALSE, B_FALSE,
!                                     zstate, debug);
                                  eventstream_write(Z_EVT_ZONE_BOOTFAILED);
                          }
                          break;
                  case Z_SHUTDOWN:
                  case Z_HALT:
--- 1567,1595 ----
                  break;
  
          case ZONE_STATE_INSTALLED:
                  switch (cmd) {
                  case Z_READY:
!                         rval = zone_ready(zlogp, Z_MNT_BOOT, zstate);
                          if (rval == 0)
                                  eventstream_write(Z_EVT_ZONE_READIED);
                          zcons_statechanged();
                          break;
                  case Z_BOOT:
                  case Z_FORCEBOOT:
                          eventstream_write(Z_EVT_ZONE_BOOTING);
!                         if ((rval = zone_ready(zlogp, Z_MNT_BOOT, zstate))
!                             == 0) {
                                  rval = zone_bootup(zlogp, zargp->bootbuf,
!                                     zstate);
                          }
                          audit_put_record(zlogp, uc, rval, "boot");
                          zcons_statechanged();
                          if (rval != 0) {
                                  bringup_failure_recovery = B_TRUE;
                                  (void) zone_halt(zlogp, B_FALSE, B_FALSE,
!                                     zstate);
                                  eventstream_write(Z_EVT_ZONE_BOOTFAILED);
                          }
                          break;
                  case Z_SHUTDOWN:
                  case Z_HALT:
*** 1727,1737 ****
                                      BOOTARGS_MAX);
                          }
  
                          rval = zone_ready(zlogp,
                              strcmp(zargp->bootbuf, "-U") == 0 ?
!                             Z_MNT_UPDATE : Z_MNT_SCRATCH, zstate, debug);
                          if (rval != 0)
                                  break;
  
                          eventstream_write(Z_EVT_ZONE_READIED);
  
--- 1637,1647 ----
                                      BOOTARGS_MAX);
                          }
  
                          rval = zone_ready(zlogp,
                              strcmp(zargp->bootbuf, "-U") == 0 ?
!                             Z_MNT_UPDATE : Z_MNT_SCRATCH, zstate);
                          if (rval != 0)
                                  break;
  
                          eventstream_write(Z_EVT_ZONE_READIED);
  
*** 1789,1828 ****
                           */
                          zerror(zlogp, B_FALSE, "zone is already ready");
                          rval = 0;
                          break;
                  case Z_BOOT:
-                 case Z_FORCEBOOT:
                          (void) strlcpy(boot_args, zargp->bootbuf,
                              sizeof (boot_args));
                          eventstream_write(Z_EVT_ZONE_BOOTING);
!                         rval = zone_bootup(zlogp, zargp->bootbuf, zstate,
!                             debug);
                          audit_put_record(zlogp, uc, rval, "boot");
                          zcons_statechanged();
                          if (rval != 0) {
                                  bringup_failure_recovery = B_TRUE;
                                  (void) zone_halt(zlogp, B_FALSE, B_TRUE,
!                                     zstate, debug);
                                  eventstream_write(Z_EVT_ZONE_BOOTFAILED);
                          }
                          boot_args[0] = '\0';
                          break;
                  case Z_HALT:
                          if (kernelcall) /* Invalid; can't happen */
                                  abort();
!                         if ((rval = zone_halt(zlogp, B_FALSE, B_FALSE, zstate,
!                             debug)) != 0)
                                  break;
                          zcons_statechanged();
                          eventstream_write(Z_EVT_ZONE_HALTED);
                          break;
                  case Z_SHUTDOWN:
                  case Z_REBOOT:
                  case Z_NOTE_UNINSTALLING:
                  case Z_MOUNT:
-                 case Z_FORCEMOUNT:
                  case Z_UNMOUNT:
                          if (kernelcall) /* Invalid; can't happen */
                                  abort();
                          zerror(zlogp, B_FALSE, "%s operation is invalid "
                              "for zones in state '%s'", z_cmd_name(cmd),
--- 1699,1735 ----
                           */
                          zerror(zlogp, B_FALSE, "zone is already ready");
                          rval = 0;
                          break;
                  case Z_BOOT:
                          (void) strlcpy(boot_args, zargp->bootbuf,
                              sizeof (boot_args));
                          eventstream_write(Z_EVT_ZONE_BOOTING);
!                         rval = zone_bootup(zlogp, zargp->bootbuf, zstate);
                          audit_put_record(zlogp, uc, rval, "boot");
                          zcons_statechanged();
                          if (rval != 0) {
                                  bringup_failure_recovery = B_TRUE;
                                  (void) zone_halt(zlogp, B_FALSE, B_TRUE,
!                                     zstate);
                                  eventstream_write(Z_EVT_ZONE_BOOTFAILED);
                          }
                          boot_args[0] = '\0';
                          break;
                  case Z_HALT:
                          if (kernelcall) /* Invalid; can't happen */
                                  abort();
!                         if ((rval = zone_halt(zlogp, B_FALSE, B_FALSE, zstate))
!                             != 0)
                                  break;
                          zcons_statechanged();
                          eventstream_write(Z_EVT_ZONE_HALTED);
                          break;
                  case Z_SHUTDOWN:
                  case Z_REBOOT:
                  case Z_NOTE_UNINSTALLING:
                  case Z_MOUNT:
                  case Z_UNMOUNT:
                          if (kernelcall) /* Invalid; can't happen */
                                  abort();
                          zerror(zlogp, B_FALSE, "%s operation is invalid "
                              "for zones in state '%s'", z_cmd_name(cmd),
*** 1835,1845 ****
          case ZONE_STATE_MOUNTED:
                  switch (cmd) {
                  case Z_UNMOUNT:
                          if (kernelcall) /* Invalid; can't happen */
                                  abort();
!                         rval = zone_halt(zlogp, B_TRUE, B_FALSE, zstate, debug);
                          if (rval == 0) {
                                  eventstream_write(Z_EVT_ZONE_HALTED);
                                  (void) sema_post(&scratch_sem);
                          }
                          break;
--- 1742,1752 ----
          case ZONE_STATE_MOUNTED:
                  switch (cmd) {
                  case Z_UNMOUNT:
                          if (kernelcall) /* Invalid; can't happen */
                                  abort();
!                         rval = zone_halt(zlogp, B_TRUE, B_FALSE, zstate);
                          if (rval == 0) {
                                  eventstream_write(Z_EVT_ZONE_HALTED);
                                  (void) sema_post(&scratch_sem);
                          }
                          break;
*** 1857,1878 ****
          case ZONE_STATE_RUNNING:
          case ZONE_STATE_SHUTTING_DOWN:
          case ZONE_STATE_DOWN:
                  switch (cmd) {
                  case Z_READY:
!                         if ((rval = zone_halt(zlogp, B_FALSE, B_TRUE, zstate,
!                             debug)) != 0)
                                  break;
                          zcons_statechanged();
!                         if ((rval = zone_ready(zlogp, Z_MNT_BOOT, zstate,
!                             debug)) == 0)
                                  eventstream_write(Z_EVT_ZONE_READIED);
                          else
                                  eventstream_write(Z_EVT_ZONE_HALTED);
                          break;
                  case Z_BOOT:
-                 case Z_FORCEBOOT:
                          /*
                           * We could have two clients racing to boot this
                           * zone; the second client loses, but his request
                           * doesn't fail, since the zone is now in the desired
                           * state.
--- 1764,1783 ----
          case ZONE_STATE_RUNNING:
          case ZONE_STATE_SHUTTING_DOWN:
          case ZONE_STATE_DOWN:
                  switch (cmd) {
                  case Z_READY:
!                         if ((rval = zone_halt(zlogp, B_FALSE, B_TRUE, zstate))
!                             != 0)
                                  break;
                          zcons_statechanged();
!                         if ((rval = zone_ready(zlogp, Z_MNT_BOOT, zstate)) == 0)
                                  eventstream_write(Z_EVT_ZONE_READIED);
                          else
                                  eventstream_write(Z_EVT_ZONE_HALTED);
                          break;
                  case Z_BOOT:
                          /*
                           * We could have two clients racing to boot this
                           * zone; the second client loses, but his request
                           * doesn't fail, since the zone is now in the desired
                           * state.
*** 1884,1922 ****
                          if (kernelcall) {
                                  log_init_exit(init_status);
                          } else {
                                  log_init_exit(-1);
                          }
!                         if ((rval = zone_halt(zlogp, B_FALSE, B_FALSE, zstate,
!                             debug)) != 0)
                                  break;
                          eventstream_write(Z_EVT_ZONE_HALTED);
                          zcons_statechanged();
                          break;
                  case Z_REBOOT:
                          (void) strlcpy(boot_args, zargp->bootbuf,
                              sizeof (boot_args));
                          eventstream_write(Z_EVT_ZONE_REBOOTING);
!                         if ((rval = zone_halt(zlogp, B_FALSE, B_TRUE, zstate,
!                             debug)) != 0) {
                                  eventstream_write(Z_EVT_ZONE_BOOTFAILED);
                                  boot_args[0] = '\0';
                                  break;
                          }
                          zcons_statechanged();
!                         if ((rval = zone_ready(zlogp, Z_MNT_BOOT, zstate,
!                             debug)) != 0) {
                                  eventstream_write(Z_EVT_ZONE_BOOTFAILED);
                                  boot_args[0] = '\0';
                                  break;
                          }
!                         rval = zone_bootup(zlogp, zargp->bootbuf, zstate,
!                             debug);
                          audit_put_record(zlogp, uc, rval, "reboot");
                          if (rval != 0) {
                                  (void) zone_halt(zlogp, B_FALSE, B_TRUE,
!                                     zstate, debug);
                                  eventstream_write(Z_EVT_ZONE_BOOTFAILED);
                          }
                          boot_args[0] = '\0';
                          break;
                  case Z_SHUTDOWN:
--- 1789,1826 ----
                          if (kernelcall) {
                                  log_init_exit(init_status);
                          } else {
                                  log_init_exit(-1);
                          }
!                         if ((rval = zone_halt(zlogp, B_FALSE, B_FALSE, zstate))
!                             != 0)
                                  break;
                          eventstream_write(Z_EVT_ZONE_HALTED);
                          zcons_statechanged();
                          break;
                  case Z_REBOOT:
                          (void) strlcpy(boot_args, zargp->bootbuf,
                              sizeof (boot_args));
                          eventstream_write(Z_EVT_ZONE_REBOOTING);
!                         if ((rval = zone_halt(zlogp, B_FALSE, B_TRUE, zstate))
!                             != 0) {
                                  eventstream_write(Z_EVT_ZONE_BOOTFAILED);
                                  boot_args[0] = '\0';
                                  break;
                          }
                          zcons_statechanged();
!                         if ((rval = zone_ready(zlogp, Z_MNT_BOOT, zstate)) !=
!                             0) {
                                  eventstream_write(Z_EVT_ZONE_BOOTFAILED);
                                  boot_args[0] = '\0';
                                  break;
                          }
!                         rval = zone_bootup(zlogp, zargp->bootbuf, zstate);
                          audit_put_record(zlogp, uc, rval, "reboot");
                          if (rval != 0) {
                                  (void) zone_halt(zlogp, B_FALSE, B_TRUE,
!                                     zstate);
                                  eventstream_write(Z_EVT_ZONE_BOOTFAILED);
                          }
                          boot_args[0] = '\0';
                          break;
                  case Z_SHUTDOWN:
*** 1924,1934 ****
                                  wait_shut = B_TRUE;
                          }
                          break;
                  case Z_NOTE_UNINSTALLING:
                  case Z_MOUNT:
-                 case Z_FORCEMOUNT:
                  case Z_UNMOUNT:
                          zerror(zlogp, B_FALSE, "%s operation is invalid "
                              "for zones in state '%s'", z_cmd_name(cmd),
                              zone_state_str(zstate));
                          rval = -1;
--- 1828,1837 ----
*** 2133,2188 ****
          (void) close(doorfd);
          return (ret);
  }
  
  /*
-  * Run the query hook with the 'env' parameter.  It should return a
-  * string of tab-delimited key-value pairs, each of which should be set
-  * in the environment.
-  *
-  * Because the env_vars string values become part of the environment, the
-  * string is static and we don't free it.
-  *
-  * This function is always called before zoneadmd forks and makes itself
-  * exclusive, so it is possible there could more than one instance of zoneadmd
-  * running in parallel at this point. Thus, we have no zonecfg snapshot and
-  * shouldn't take one yet (i.e. snap_hndl is NULL). Thats ok, since we don't
-  * need any zonecfg info to query for a brand-specific env value.
-  */
- static int
- set_brand_env(zlog_t *zlogp)
- {
-         int ret = 0;
-         static char *env_vars = NULL;
-         char buf[2 * MAXPATHLEN];
- 
-         if (query_hook[0] == '\0' || env_vars != NULL)
-                 return (0);
- 
-         if (snprintf(buf, sizeof (buf), "%s env", query_hook) > sizeof (buf))
-                 return (-1);
- 
-         if (do_subproc(zlogp, buf, &env_vars, B_FALSE) != 0)
-                 return (-1);
- 
-         if (env_vars != NULL) {
-                 char *sp;
- 
-                 sp = strtok(env_vars, "\t");
-                 while (sp != NULL) {
-                         if (putenv(sp) != 0) {
-                                 ret = -1;
-                                 break;
-                         }
-                         sp = strtok(NULL, "\t");
-                 }
-         }
- 
-         return (ret);
- }
- 
- /*
   * Setup the brand's pre and post state change callbacks, as well as the
   * query callback, if any of these exist.
   */
  static int
  brand_callback_init(brand_handle_t bh, char *zone_name)
--- 2036,2045 ----
*** 2414,2428 ****
                  priv_freeset(privset);
                  return (1);
          }
          priv_freeset(privset);
  
-         if (set_brand_env(zlogp) != 0) {
-                 zerror(zlogp, B_FALSE, "Unable to setup brand's environment");
-                 return (1);
-         }
- 
          if (mkzonedir(zlogp) != 0)
                  return (1);
  
          /*
           * Pre-fork: setup shared state
--- 2271,2280 ----