summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Gerdts <mike.gerdts@joyent.com>2018-11-21 06:17:45 +0000
committerMike Gerdts <mike.gerdts@joyent.com>2018-11-29 16:03:25 +0000
commitc75576d2f6b4d8218702164bc9cc3e642ff88ccc (patch)
tree22d332b854b08b7a71a8464213dda311ec0f75b7
parentaa902e5003c88c1040e012da5bac37e8be18323a (diff)
downloadillumos-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.c23
-rw-r--r--usr/src/uts/common/os/zone.c37
-rw-r--r--usr/src/uts/common/sys/zone.h11
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