diff options
| author | Ryan Zezeski <rpz@joyent.com> | 2016-11-17 21:51:06 -0700 |
|---|---|---|
| committer | Ryan Zezeski <rpz@joyent.com> | 2017-01-30 10:22:02 -0700 |
| commit | 33df115038809a05a8856b165fabdb823350567e (patch) | |
| tree | e932d1cee1bcb46808935d978251487470d5aa7b /usr/src/cmd/zoneadmd/vplat.c | |
| parent | aefd5a8c21e439a1955ccb6b19739e9bf7e8cec3 (diff) | |
| download | illumos-joyent-33df115038809a05a8856b165fabdb823350567e.tar.gz | |
OS-5363 dlmgmtd forking with write locks results in deadlock chaos
OS-5919 remove zone lock file
Reviewed by: Robert Mustacchi <rm@joyent.com>
Reviewed by: Jerry Jelinek <jerry.jelinek@joyent.com>
Approved by: Jerry Jelinek <jerry.jelinek@joyent.com>
Diffstat (limited to 'usr/src/cmd/zoneadmd/vplat.c')
| -rw-r--r-- | usr/src/cmd/zoneadmd/vplat.c | 82 |
1 files changed, 82 insertions, 0 deletions
diff --git a/usr/src/cmd/zoneadmd/vplat.c b/usr/src/cmd/zoneadmd/vplat.c index 9a6f0ceb87..d75ec91e6f 100644 --- a/usr/src/cmd/zoneadmd/vplat.c +++ b/usr/src/cmd/zoneadmd/vplat.c @@ -78,6 +78,7 @@ #include <sys/conf.h> #include <sys/systeminfo.h> #include <sys/secflags.h> +#include <sys/vnic.h> #include <libdlpi.h> #include <libdllink.h> @@ -5151,6 +5152,80 @@ unmounted: } } +/* + * Delete all transient VNICs belonging to this zone. A transient VNIC + * is one that is created and destroyed along with the lifetime of the + * zone. Non-transient VNICs, ones that are assigned from the GZ to a + * NGZ, are reassigned to the GZ in zone_shutdown() via the + * zone-specific data (zsd) callbacks. + */ +static int +delete_transient_vnics(zlog_t *zlogp, zoneid_t zoneid) +{ + dladm_status_t status; + int num_links = 0; + datalink_id_t *links, link; + uint32_t link_flags; + datalink_class_t link_class; + char link_name[MAXLINKNAMELEN]; + vnic_ioc_delete_t ioc; + + if (zone_list_datalink(zoneid, &num_links, NULL) != 0) { + zerror(zlogp, B_TRUE, "unable to determine " + "number of network interfaces"); + return (-1); + } + + if (num_links == 0) + return (0); + + links = malloc(num_links * sizeof (datalink_id_t)); + + if (links == NULL) { + zerror(zlogp, B_TRUE, "failed to delete " + "network interfaces because of alloc fail"); + return (-1); + } + + if (zone_list_datalink(zoneid, &num_links, links) != 0) { + zerror(zlogp, B_TRUE, "failed to delete " + "network interfaces because of failure " + "to list them"); + return (-1); + } + + for (int i = 0; i < num_links; i++) { + char dlerr[DLADM_STRSIZE]; + link = links[i]; + + status = dladm_datalink_id2info(dld_handle, link, &link_flags, + &link_class, NULL, link_name, sizeof (link_name)); + + if (status != DLADM_STATUS_OK) { + zerror(zlogp, B_FALSE, "failed to " + "delete network interface (%u)" + "due to failure to get link info: %s", + link, + dladm_status2str(status, dlerr)); + return (-1); + } + + if (link_flags & DLADM_OPT_TRANSIENT) { + assert(link_class & DATALINK_CLASS_VNIC); + + ioc.vd_vnic_id = link; + if (ioctl(dladm_dld_fd(dld_handle), VNIC_IOC_DELETE, + &ioc) < 0) { + zerror(zlogp, B_TRUE, + "delete VNIC ioctl failed %d", link); + return (-1); + } + } + } + + return (0); +} + int vplat_teardown(zlog_t *zlogp, boolean_t unmount_cmd, boolean_t rebooting, boolean_t debug) @@ -5262,11 +5337,18 @@ vplat_teardown(zlog_t *zlogp, boolean_t unmount_cmd, boolean_t rebooting, } break; case ZS_EXCLUSIVE: + if (delete_transient_vnics(zlogp, zoneid) != 0) { + zerror(zlogp, B_FALSE, "unable to delete " + "transient vnics in zone"); + goto error; + } + status = dladm_zone_halt(dld_handle, zoneid); if (status != DLADM_STATUS_OK) { zerror(zlogp, B_FALSE, "unable to notify " "dlmgmtd of zone halt: %s", dladm_status2str(status, errmsg)); + goto error; } break; } |
