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);