diff options
author | Mike Gerdts <mike.gerdts@joyent.com> | 2018-11-21 06:17:45 +0000 |
---|---|---|
committer | Mike Gerdts <mike.gerdts@joyent.com> | 2018-11-29 16:03:25 +0000 |
commit | c75576d2f6b4d8218702164bc9cc3e642ff88ccc (patch) | |
tree | 22d332b854b08b7a71a8464213dda311ec0f75b7 | |
parent | aa902e5003c88c1040e012da5bac37e8be18323a (diff) | |
download | illumos-joyent-c75576d2f6b4d8218702164bc9cc3e642ff88ccc.tar.gz |
OS-7389 restart_init() needs to be observable
Reviewed by: Patrick Mooney <patrick.mooney@joyent.com>
Reviewed by: Hans Rosenfeld <hans.rosenfeld@joyent.com>
Approved by: Hans Rosenfeld <hans.rosenfeld@joyent.com>
-rw-r--r-- | usr/src/uts/common/os/exit.c | 23 | ||||
-rw-r--r-- | usr/src/uts/common/os/zone.c | 37 | ||||
-rw-r--r-- | usr/src/uts/common/sys/zone.h | 11 |
3 files changed, 71 insertions, 0 deletions
diff --git a/usr/src/uts/common/os/exit.c b/usr/src/uts/common/os/exit.c index 62176e76f0..06e0117cd6 100644 --- a/usr/src/uts/common/os/exit.c +++ b/usr/src/uts/common/os/exit.c @@ -138,6 +138,27 @@ rexit(int rval) } /* + * Bump the init_restarts kstat and let interested parties know about the + * restart. + */ +static void +restart_init_notify(zone_t *zone) +{ + nvlist_t *nvl = NULL; + + zone->zone_proc_init_restarts++; + + if (nvlist_alloc(&nvl, NV_UNIQUE_NAME, KM_SLEEP) == 0 && + nvlist_add_uint32(nvl, ZONE_CB_RESTARTS, + zone->zone_proc_init_restarts) == 0) { + zone_sysevent_publish(zone, ZONE_EVENT_INIT_CLASS, + ZONE_EVENT_INIT_RESTART_SC, nvl); + } + + nvlist_free(nvl); +} + +/* * Called by proc_exit() when a zone's init exits, presumably because * it failed. As long as the given zone is still in the "running" * state, we will re-exec() init, but first we need to reset things @@ -260,6 +281,8 @@ restart_init(int what, int why) ASSERT(p == curproc); (void) freectty(B_TRUE); + restart_init_notify(p->p_zone); + /* * Now exec() the new init(1M) on top of the current process. If we * succeed, the caller will treat this like a successful system call. diff --git a/usr/src/uts/common/os/zone.c b/usr/src/uts/common/os/zone.c index 1f5cdbc1c1..cf869025bd 100644 --- a/usr/src/uts/common/os/zone.c +++ b/usr/src/uts/common/os/zone.c @@ -2399,6 +2399,7 @@ zone_misc_kstat_update(kstat_t *ksp, int rw) zmp->zm_nested_intp.value.ui32 = zone->zone_nested_intp; zmp->zm_init_pid.value.ui32 = zone->zone_proc_initpid; + zmp->zm_init_restarts.value.ui32 = zone->zone_proc_init_restarts; zmp->zm_boot_time.value.ui64 = (uint64_t)zone->zone_boot_time; return (0); @@ -2444,6 +2445,8 @@ zone_misc_kstat_create(zone_t *zone) kstat_named_init(&zmp->zm_nested_intp, "nested_interp", KSTAT_DATA_UINT32); kstat_named_init(&zmp->zm_init_pid, "init_pid", KSTAT_DATA_UINT32); + kstat_named_init(&zmp->zm_init_restarts, "init_restarts", + KSTAT_DATA_UINT32); kstat_named_init(&zmp->zm_boot_time, "boot_time", KSTAT_DATA_UINT64); ksp->ks_update = zone_misc_kstat_update; @@ -3004,6 +3007,8 @@ zone_status_set(zone_t *zone, zone_status_t status) #ifdef DEBUG (void) printf( "Failed to allocate and send zone state change event.\n"); +#else + /* EMPTY */ #endif } nvlist_free(nvl); @@ -3023,6 +3028,38 @@ zone_status_get(zone_t *zone) return (zone->zone_status); } +/* + * Publish a zones-related sysevent for purposes other than zone state changes. + * While it is unfortunate that zone_event_chan is associated with + * "com.sun:zones:status" (rather than "com.sun:zones") state changes should be + * the only ones with class "status" and subclass "change". + */ +void +zone_sysevent_publish(zone_t *zone, const char *class, const char *subclass, + nvlist_t *ev_nvl) +{ + nvlist_t *nvl = NULL; + timestruc_t now; + uint64_t t; + + gethrestime(&now); + t = (now.tv_sec * NANOSEC) + now.tv_nsec; + + if (nvlist_dup(ev_nvl, &nvl, KM_SLEEP) != 0 || + nvlist_add_string(nvl, ZONE_CB_NAME, zone->zone_name) != 0 || + nvlist_add_uint64(nvl, ZONE_CB_ZONEID, zone->zone_id) != 0 || + nvlist_add_uint64(nvl, ZONE_CB_TIMESTAMP, t) != 0 || + sysevent_evc_publish(zone_event_chan, class, subclass, "sun.com", + "kernel", nvl, EVCH_SLEEP) != 0) { +#ifdef DEBUG + (void) printf("Failed to allocate and send zone misc event.\n"); +#else + /* EMPTY */ +#endif + } + nvlist_free(nvl); +} + static int zone_set_bootargs(zone_t *zone, const char *zone_bootargs) { diff --git a/usr/src/uts/common/sys/zone.h b/usr/src/uts/common/sys/zone.h index 845f20a46f..a4ec347ce4 100644 --- a/usr/src/uts/common/sys/zone.h +++ b/usr/src/uts/common/sys/zone.h @@ -43,6 +43,7 @@ #include <sys/secflags.h> #include <netinet/in.h> #include <sys/cpu_uarray.h> +#include <sys/nvpair.h> #ifdef __cplusplus extern "C" { @@ -143,9 +144,13 @@ extern "C" { #define ZONE_CB_NAME "zonename" #define ZONE_CB_NEWSTATE "newstate" #define ZONE_CB_OLDSTATE "oldstate" +#define ZONE_CB_RESTARTS "restarts" #define ZONE_CB_TIMESTAMP "when" #define ZONE_CB_ZONEID "zoneid" +#define ZONE_EVENT_INIT_CLASS "init" +#define ZONE_EVENT_INIT_RESTART_SC "restart" + /* * Exit values that may be returned by scripts or programs invoked by various * zone commands. @@ -486,6 +491,7 @@ typedef struct { kstat_named_t zm_mfseglim; kstat_named_t zm_nested_intp; kstat_named_t zm_init_pid; + kstat_named_t zm_init_restarts; kstat_named_t zm_boot_time; } zone_misc_kstat_t; @@ -581,6 +587,7 @@ typedef struct zone { kcondvar_t zone_cv; /* used to signal state changes */ struct proc *zone_zsched; /* Dummy kernel "zsched" process */ pid_t zone_proc_initpid; /* pid of "init" for this zone */ + uint_t zone_proc_init_restarts; /* times init restarted */ char *zone_initname; /* fs path to 'init' */ int zone_init_status; /* init's exit status */ int zone_boot_err; /* for zone_boot() if boot fails */ @@ -1014,6 +1021,10 @@ extern rctl_hndl_t rc_zone_max_swap; extern rctl_hndl_t rc_zone_phys_mem; extern rctl_hndl_t rc_zone_max_lofi; +/* For publishing sysevents related to a particular zone */ +extern void zone_sysevent_publish(zone_t *, const char *, const char *, + nvlist_t *); + #endif /* _KERNEL */ #ifdef __cplusplus |