Print this page
Merge cleanup from previous six commits
OS-200 need a better mechanism for storing persistent zone_did
OS-2564 zone boot failed: could not start zoneadmd
OS-1763 mount of /etc/svc/volatile failed: Device busy
OS-511 make zonecfg device resource extensible, like the net resource
OS-224 add more zonecfg net properties
*** 143,152 ****
--- 143,155 ----
#define TEXT_DOMAIN "SYS_TEST" /* Use this only if it wasn't */
#endif
#define DEFAULT_LOCALE "C"
+ #define RSRC_NET "net"
+ #define RSRC_DEV "device"
+
static const char *
z_cmd_name(zone_cmd_t zcmd)
{
/* This list needs to match the enum in sys/zone.h */
static const char *zcmdstr[] = {
*** 679,688 ****
--- 682,693 ----
} else if (child == 0) { /* child */
char opt_buf[MAX_MNTOPT_STR];
int optlen = 0;
int mflag = MS_DATA;
+ int i;
+ int ret;
(void) ct_tmpl_clear(tmpl_fd);
/*
* Even though there are no procs running in the zone, we
* do this for paranoia's sake.
*** 706,719 ****
(void) strlcpy(opt_buf, opt, sizeof (opt_buf));
opt = opt_buf;
optlen = MAX_MNTOPT_STR;
mflag = MS_OPTIONSTR;
}
! if (mount(spec, dir, mflag, fstype, NULL, 0, opt, optlen) != 0)
! _exit(errno);
! _exit(0);
}
/* parent */
if (contract_latest(&ct) == -1)
ct = -1;
(void) ct_tmpl_clear(tmpl_fd);
--- 711,741 ----
(void) strlcpy(opt_buf, opt, sizeof (opt_buf));
opt = opt_buf;
optlen = MAX_MNTOPT_STR;
mflag = MS_OPTIONSTR;
}
!
! /*
! * There is an obscure race condition which can cause mount
! * to return EBUSY. This happens for example on the mount
! * of the zone's /etc/svc/volatile file system if there is
! * a GZ process running svcs -Z, which will touch the
! * mountpoint, just as we're trying to do the mount. To cope
! * with this, we retry up to 3 times to let this transient
! * process get out of the way.
! */
! for (i = 0; i < 3; i++) {
! ret = 0;
! if (mount(spec, dir, mflag, fstype, NULL, 0, opt,
! optlen) != 0)
! ret = errno;
! if (ret != EBUSY)
! break;
! (void) sleep(1);
}
+ _exit(ret);
+ }
/* parent */
if (contract_latest(&ct) == -1)
ct = -1;
(void) ct_tmpl_clear(tmpl_fd);
*** 732,741 ****
--- 754,872 ----
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;
+ /* Enough for maximal name, rsrc + attr, & slop for ZONECFG & _'s */
+ char nm[2 * MAXNAMELEN + 32];
+
+ if (attr == NULL)
+ (void) snprintf(nm, sizeof (nm), "_ZONECFG_%s_%s", rsrc,
+ name);
+ else
+ (void) snprintf(nm, sizeof (nm), "_ZONECFG_%s_%s_%s", rsrc,
+ attr, name);
+
+ p = nm;
+ while ((p = strchr(p, '-')) != NULL)
+ *p++ = '_';
+
+ (void) setenv(nm, val, 1);
+ }
+
+ /*
+ * Export zonecfg network and device properties into environment for the boot
+ * and state change hooks.
+ * 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;
+
+ (void) strlcat(net_resources, phys, sizeof (net_resources));
+ (void) strlcat(net_resources, " ", sizeof (net_resources));
+
+ set_zonecfg_env(RSRC_NET, phys, "physical", phys);
+
+ set_zonecfg_env(RSRC_NET, phys, "address",
+ ntab.zone_nwif_address);
+ set_zonecfg_env(RSRC_NET, phys, "allowed-address",
+ ntab.zone_nwif_allowed_address);
+ set_zonecfg_env(RSRC_NET, phys, "defrouter",
+ ntab.zone_nwif_defrouter);
+ set_zonecfg_env(RSRC_NET, phys, "global-nic",
+ ntab.zone_nwif_gnic);
+ set_zonecfg_env(RSRC_NET, phys, "mac-addr", ntab.zone_nwif_mac);
+ set_zonecfg_env(RSRC_NET, phys, "vlan-id",
+ ntab.zone_nwif_vlan_id);
+
+ 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;
+
+ (void) strlcat(dev_resources, match, sizeof (dev_resources));
+ (void) strlcat(dev_resources, " ", sizeof (dev_resources));
+
+ for (rap = dtab.zone_dev_attrp; rap != NULL;
+ 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
*** 756,765 ****
--- 887,901 ----
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");
if (file == NULL) {
zerror(zlogp, B_TRUE, "could not launch: %s", cmdbuf);
return (-1);
}
*** 1461,1470 ****
--- 1597,1607 ----
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))
*** 1471,1480 ****
--- 1608,1618 ----
== 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);
*** 1593,1602 ****
--- 1731,1741 ----
(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);
*** 1607,1616 ****
--- 1746,1756 ----
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:
*** 1654,1663 ****
--- 1794,1804 ----
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;
*** 1679,1688 ****
--- 1820,1830 ----
}
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);
*** 1690,1701 ****
!= 0) {
eventstream_write(Z_EVT_ZONE_BOOTFAILED);
boot_args[0] = '\0';
break;
}
! 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);
--- 1832,1844 ----
!= 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);