From 6d2fb4205c9e899a2e533d0c7e36303a79bfd99b Mon Sep 17 00:00:00 2001 From: Mike Gerdts Date: Wed, 26 Sep 2018 13:18:20 +0000 Subject: OS-7263 need sysevent for zone_free Reviewed by: Jerry Jelinek Reviewed by: Patrick Mooney Approved by: Patrick Mooney --- usr/src/cmd/mdb/common/modules/genunix/zone.c | 5 ++-- usr/src/uts/common/os/zone.c | 33 +++++++++++++++++++-------- usr/src/uts/common/sys/zone.h | 4 +++- 3 files changed, 29 insertions(+), 13 deletions(-) diff --git a/usr/src/cmd/mdb/common/modules/genunix/zone.c b/usr/src/cmd/mdb/common/modules/genunix/zone.c index 77ed2cbc48..cea1883e11 100644 --- a/usr/src/cmd/mdb/common/modules/genunix/zone.c +++ b/usr/src/cmd/mdb/common/modules/genunix/zone.c @@ -20,7 +20,7 @@ */ /* * Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2012, Joyent, Inc. All rights reserved. + * Copyright (c) 2018, Joyent, Inc. All rights reserved. */ #include @@ -52,7 +52,8 @@ char *zone_status_names[] = { "empty", /* ZONE_IS_EMPTY */ "down", /* ZONE_IS_DOWN */ "dying", /* ZONE_IS_DYING */ - "dead" /* ZONE_IS_DEAD */ + "dead", /* ZONE_IS_DEAD */ + "free" /* ZONE_IS_FREE */ }; static int diff --git a/usr/src/uts/common/os/zone.c b/usr/src/uts/common/os/zone.c index a161fb85a2..42eba20668 100644 --- a/usr/src/uts/common/os/zone.c +++ b/usr/src/uts/common/os/zone.c @@ -106,14 +106,16 @@ * removed from the list of active zones. zone_destroy() returns, and * the zone can be recreated. * - * ZONE_IS_FREE (internal state): zone_ref goes to 0, ZSD destructor - * callbacks are executed, and all memory associated with the zone is - * freed. + * ZONE_IS_FREE (internal state): All references have been dropped and + * the zone_t is no longer in the zone_active nor zone_deathrow lists. + * The zone_t is in the process of being freed. This state exists + * only for publishing a sysevent to indicate that the zone by this + * name can be booted again. * - * Threads can wait for the zone to enter a requested state by using - * zone_status_wait() or zone_status_timedwait() with the desired - * state passed in as an argument. Zone state transitions are - * uni-directional; it is not possible to move back to an earlier state. + * Threads can wait for the zone to enter a requested state (other than + * ZONE_IS_FREE) by using zone_status_wait() or zone_status_timedwait() + * with the desired state passed in as an argument. Zone state transitions + * are uni-directional; it is not possible to move back to an earlier state. * * * Zone-Specific Data: @@ -170,7 +172,7 @@ * * Ordering requirements: * pool_lock --> cpu_lock --> zonehash_lock --> zone_status_lock --> - * zone_lock --> zsd_key_lock --> pidlock --> p_lock + * zone_lock --> zsd_key_lock --> pidlock --> p_lock * * When taking zone_mem_lock or zone_nlwps_lock, the lock ordering is: * zonehash_lock --> a_lock --> pidlock --> p_lock --> zone_mem_lock @@ -353,6 +355,7 @@ const char *zone_status_table[] = { ZONE_EVENT_SHUTTING_DOWN, /* down */ ZONE_EVENT_SHUTTING_DOWN, /* dying */ ZONE_EVENT_UNINITIALIZED, /* dead */ + ZONE_EVENT_FREE, /* free */ }; /* @@ -396,6 +399,7 @@ static int zone_remove_datalink(zoneid_t, datalink_id_t); static int zone_list_datalink(zoneid_t, int *, datalink_id_t *); static int zone_set_network(zoneid_t, zone_net_data_t *); static int zone_get_network(zoneid_t, zone_net_data_t *); +static void zone_status_set(zone_t *, zone_status_t); typedef boolean_t zsd_applyfn_t(kmutex_t *, boolean_t, zone_t *, zone_key_t); @@ -2917,6 +2921,15 @@ zone_free(zone_t *zone) } list_destroy(&zone->zone_dl_list); + /* + * This zone_t can no longer inhibit creation of another zone_t + * with the same name or debug ID. Generate a sysevent so that + * userspace tools know it is safe to carry on. + */ + mutex_enter(&zone_status_lock); + zone_status_set(zone, ZONE_IS_FREE); + mutex_exit(&zone_status_lock); + if (zone->zone_rootvp != NULL) VN_RELE(zone->zone_rootvp); if (zone->zone_rootpath) @@ -2964,8 +2977,8 @@ zone_status_set(zone_t *zone, zone_status_t status) nvlist_t *nvl = NULL; ASSERT(MUTEX_HELD(&zone_status_lock)); - ASSERT(status > ZONE_MIN_STATE && status <= ZONE_MAX_STATE && - status >= zone_status_get(zone)); + ASSERT((status > ZONE_MIN_STATE && status <= ZONE_MAX_STATE || + status == ZONE_IS_FREE) && status >= zone_status_get(zone)); /* Current time since Jan 1 1970 but consumers expect NS */ gethrestime(&now); diff --git a/usr/src/uts/common/sys/zone.h b/usr/src/uts/common/sys/zone.h index e871689f5f..678dd4e029 100644 --- a/usr/src/uts/common/sys/zone.h +++ b/usr/src/uts/common/sys/zone.h @@ -137,6 +137,7 @@ extern "C" { #define ZONE_EVENT_READY "ready" #define ZONE_EVENT_RUNNING "running" #define ZONE_EVENT_SHUTTING_DOWN "shutting_down" +#define ZONE_EVENT_FREE "free" #define ZONE_CB_NAME "zonename" #define ZONE_CB_NEWSTATE "newstate" @@ -244,7 +245,8 @@ typedef enum { ZONE_IS_EMPTY, ZONE_IS_DOWN, ZONE_IS_DYING, - ZONE_IS_DEAD + ZONE_IS_DEAD, + ZONE_IS_FREE /* transient state for zone sysevent */ } zone_status_t; #define ZONE_MIN_STATE ZONE_IS_UNINITIALIZED #define ZONE_MAX_STATE ZONE_IS_DEAD -- cgit v1.2.3