diff options
| author | <gerald.jelinek@sun.com> | 2009-03-01 11:25:17 -0700 |
|---|---|---|
| committer | <gerald.jelinek@sun.com> | 2009-03-01 11:25:17 -0700 |
| commit | 2766118b5daac564c456d4a091c4c6f27850a5e0 (patch) | |
| tree | 4d3fbbaa8bf3be2a3978bf16faccf85452f1b027 /usr/src/cmd/zoneadm/zoneadm.c | |
| parent | 419dcee755f59d2dd3409402a75a01822737c1dd (diff) | |
| download | illumos-joyent-2766118b5daac564c456d4a091c4c6f27850a5e0.tar.gz | |
6757506 race can cause zoneadm to emit 'zoneadm: failed to get zone name: Invalid argument' messages
Diffstat (limited to 'usr/src/cmd/zoneadm/zoneadm.c')
| -rw-r--r-- | usr/src/cmd/zoneadm/zoneadm.c | 91 |
1 files changed, 55 insertions, 36 deletions
diff --git a/usr/src/cmd/zoneadm/zoneadm.c b/usr/src/cmd/zoneadm/zoneadm.c index 0b8ad00ea2..8e3b1a4d0d 100644 --- a/usr/src/cmd/zoneadm/zoneadm.c +++ b/usr/src/cmd/zoneadm/zoneadm.c @@ -422,6 +422,10 @@ zone_print(zone_entry_t *zent, boolean_t verbose, boolean_t parsable) static boolean_t firsttime = B_TRUE; char *ip_type_str; + /* Skip a zone that shutdown while we were collecting data. */ + if (zent->zname[0] == '\0') + return; + if (zent->ziptype == ZS_EXCLUSIVE) ip_type_str = "excl"; else @@ -471,6 +475,7 @@ lookup_zone_info(const char *zone_name, zoneid_t zid, zone_entry_t *zent) char root[MAXPATHLEN], *cp; int err; uuid_t uuid; + zone_dochandle_t handle; (void) strlcpy(zent->zname, zone_name, sizeof (zent->zname)); (void) strlcpy(zent->zroot, "???", sizeof (zent->zroot)); @@ -543,47 +548,49 @@ lookup_zone_info(const char *zone_name, zoneid_t zid, zone_entry_t *zent) */ if (zid == GLOBAL_ZONEID) { zent->ziptype = ZS_SHARED; - } else { + return (Z_OK); + } - if (zent->zstate_num == ZONE_STATE_RUNNING) { - ushort_t flags; + /* + * There is a race condition where the zone could boot while + * we're walking the index file. In this case the zone state + * could be seen as running from the call above, but the zoneid + * would be undefined. + * + * There is also a race condition where the zone could shutdown after + * we got its running state above. This is also not an error and + * we fall back to getting the ziptype from the zone configuration. + */ + if (zent->zstate_num == ZONE_STATE_RUNNING && + zid != ZONE_ID_UNDEFINED) { + ushort_t flags; - if (zone_getattr(zid, ZONE_ATTR_FLAGS, &flags, - sizeof (flags)) < 0) { - zperror2(zent->zname, - gettext("could not get zone flags")); - return (Z_ERR); - } + if (zone_getattr(zid, ZONE_ATTR_FLAGS, &flags, + sizeof (flags)) >= 0) { if (flags & ZF_NET_EXCL) zent->ziptype = ZS_EXCLUSIVE; else zent->ziptype = ZS_SHARED; - } else { - zone_dochandle_t handle; + return (Z_OK); + } + } - if ((handle = zonecfg_init_handle()) == NULL) { - zperror2(zent->zname, - gettext("could not init handle")); - return (Z_ERR); - } - if ((err = zonecfg_get_handle(zent->zname, handle)) - != Z_OK) { - zperror2(zent->zname, - gettext("could not get handle")); - zonecfg_fini_handle(handle); - return (Z_ERR); - } + if ((handle = zonecfg_init_handle()) == NULL) { + zperror2(zent->zname, gettext("could not init handle")); + return (Z_ERR); + } + if ((err = zonecfg_get_handle(zent->zname, handle)) != Z_OK) { + zperror2(zent->zname, gettext("could not get handle")); + zonecfg_fini_handle(handle); + return (Z_ERR); + } - if ((err = zonecfg_get_iptype(handle, &zent->ziptype)) - != Z_OK) { - zperror2(zent->zname, - gettext("could not get ip-type")); - zonecfg_fini_handle(handle); - return (Z_ERR); - } - zonecfg_fini_handle(handle); - } + if ((err = zonecfg_get_iptype(handle, &zent->ziptype)) != Z_OK) { + zperror2(zent->zname, gettext("could not get ip-type")); + zonecfg_fini_handle(handle); + return (Z_ERR); } + zonecfg_fini_handle(handle); return (Z_OK); } @@ -594,6 +601,10 @@ lookup_zone_info(const char *zone_name, zoneid_t zid, zone_entry_t *zent) * to fetch the list of running zones (stored in the global zents). This * function may be called multiple times, so if zents is already set, we * return immediately to save work. + * + * Note that the data about running zones can change while this function + * is running, so its possible that the list of zones will have empty slots + * at the end. */ static int @@ -646,8 +657,12 @@ again: char altname[ZONENAME_MAX]; if (getzonenamebyid(zids[i], name, sizeof (name)) < 0) { - zperror(gettext("failed to get zone name"), B_FALSE); - retv = Z_ERR; + /* + * There is a race condition where the zone may have + * shutdown since we retrieved the number of running + * zones above. This is not an error, there will be + * an empty slot at the end of the list. + */ continue; } if (zonecfg_is_scratch(name)) { @@ -669,8 +684,12 @@ again: continue; } if (lookup_zone_info(name, zids[i], zentp) != Z_OK) { - zerror(gettext("failed to get zone data")); - retv = Z_ERR; + /* + * There is a race condition where the zone may have + * shutdown since we retrieved the number of running + * zones above. This is not an error, there will be + * an empty slot at the end of the list. + */ continue; } zentp++; |
