summaryrefslogtreecommitdiff
path: root/usr
diff options
context:
space:
mode:
Diffstat (limited to 'usr')
-rw-r--r--usr/src/uts/common/os/exit.c166
-rw-r--r--usr/src/uts/common/os/zone.c10
-rw-r--r--usr/src/uts/common/sys/zone.h3
-rw-r--r--usr/src/uts/common/vm/vm_page.c20
4 files changed, 148 insertions, 51 deletions
diff --git a/usr/src/uts/common/os/exit.c b/usr/src/uts/common/os/exit.c
index 3edddcf61f..62176e76f0 100644
--- a/usr/src/uts/common/os/exit.c
+++ b/usr/src/uts/common/os/exit.c
@@ -21,7 +21,7 @@
/*
* Copyright (c) 1988, 2010, Oracle and/or its affiliates. All rights reserved.
- * Copyright 2017 Joyent, Inc.
+ * Copyright 2018 Joyent, Inc.
*/
/* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
@@ -320,6 +320,119 @@ proc_is_exiting(proc_t *p)
}
/*
+ * Return true if zone's init is restarted, false if exit processing should
+ * proceeed.
+ */
+static boolean_t
+zone_init_exit(zone_t *z, int why, int what)
+{
+ /*
+ * Typically we don't let the zone's init exit unless zone_start_init()
+ * failed its exec, or we are shutting down the zone or the machine,
+ * although the various flags handled within this function will control
+ * the behavior.
+ *
+ * Since we are single threaded, we don't need to lock the following
+ * accesses to zone_proc_initpid.
+ */
+ if (z->zone_boot_err != 0 ||
+ zone_status_get(z) >= ZONE_IS_SHUTTING_DOWN ||
+ zone_status_get(global_zone) >= ZONE_IS_SHUTTING_DOWN) {
+ /*
+ * Clear the zone's init pid and proceed with exit processing.
+ */
+ z->zone_proc_initpid = -1;
+ return (B_FALSE);
+ }
+
+ /*
+ * There are a variety of configuration flags on the zone to control
+ * init exit behavior.
+ *
+ * If the init process should be restarted, the "zone_restart_init"
+ * member will be set.
+ */
+ if (!z->zone_restart_init) {
+ /*
+ * The zone has been setup to halt when init exits.
+ */
+ z->zone_init_status = wstat(why, what);
+ (void) zone_kadmin(A_SHUTDOWN, AD_HALT, NULL, zone_kcred());
+ z->zone_proc_initpid = -1;
+ return (B_FALSE);
+ }
+
+ /*
+ * At this point we know we're configured to restart init, but there
+ * are various modifiers to that behavior.
+ */
+
+ if (z->zone_reboot_on_init_exit) {
+ /*
+ * Some init programs in branded zones do not tolerate a
+ * restart in the traditional manner; setting
+ * "zone_reboot_on_init_exit" will cause the entire zone to be
+ * rebooted instead.
+ */
+
+ if (z->zone_restart_init_0) {
+ /*
+ * Some init programs in branded zones only want to
+ * restart if they exit 0, otherwise the zone should
+ * shutdown. Setting the "zone_restart_init_0" member
+ * controls this behavior.
+ */
+ if (why == CLD_EXITED && what == 0) {
+ /* Trigger a zone reboot */
+ (void) zone_kadmin(A_REBOOT, 0, NULL,
+ zone_kcred());
+ } else {
+ /* Shutdown instead of reboot */
+ (void) zone_kadmin(A_SHUTDOWN, AD_HALT, NULL,
+ zone_kcred());
+ }
+ } else {
+ /* Trigger a zone reboot */
+ (void) zone_kadmin(A_REBOOT, 0, NULL, zone_kcred());
+ }
+
+ z->zone_init_status = wstat(why, what);
+ z->zone_proc_initpid = -1;
+ return (B_FALSE);
+ }
+
+ if (z->zone_restart_init_0) {
+ /*
+ * Some init programs in branded zones only want to restart if
+ * they exit 0, otherwise the zone should shutdown. Setting the
+ * "zone_restart_init_0" member controls this behavior.
+ *
+ * In this case we only restart init if it exited successfully.
+ */
+ if (why == CLD_EXITED && what == 0 &&
+ restart_init(what, why) == 0) {
+ return (B_TRUE);
+ }
+ } else {
+ /*
+ * No restart modifiers on the zone, attempt to restart init.
+ */
+ if (restart_init(what, why) == 0) {
+ return (B_TRUE);
+ }
+ }
+
+
+ /*
+ * The restart failed, the zone will shut down.
+ */
+ z->zone_init_status = wstat(why, what);
+ (void) zone_kadmin(A_SHUTDOWN, AD_HALT, NULL, zone_kcred());
+ z->zone_proc_initpid = -1;
+ return (B_FALSE);
+}
+
+/*
* Return value:
* 1 - exitlwps() failed, call (or continue) lwp_exit()
* 0 - restarting init. Return through system call path
@@ -366,55 +479,10 @@ proc_exit(int why, int what)
}
mutex_exit(&p->p_lock);
- /*
- * Don't let init exit unless zone_start_init() failed its exec, or
- * we are shutting down the zone or the machine.
- *
- * Since we are single threaded, we don't need to lock the
- * following accesses to zone_proc_initpid.
- */
if (p->p_pid == z->zone_proc_initpid) {
- if (z->zone_boot_err == 0 &&
- zone_status_get(z) < ZONE_IS_SHUTTING_DOWN &&
- zone_status_get(global_zone) < ZONE_IS_SHUTTING_DOWN) {
-
- /*
- * If the init process should be restarted, the
- * "zone_restart_init" member will be set. Some init
- * programs in branded zones do not tolerate a restart
- * in the traditional manner; setting the
- * "zone_reboot_on_init_exit" member will cause the
- * entire zone to be rebooted instead. If neither of
- * these flags is set the zone will shut down.
- */
- if (z->zone_reboot_on_init_exit == B_TRUE &&
- z->zone_restart_init == B_TRUE) {
- /*
- * Trigger a zone reboot and continue
- * with exit processing.
- */
- z->zone_init_status = wstat(why, what);
- (void) zone_kadmin(A_REBOOT, 0, NULL,
- zone_kcred());
-
- } else {
- if (z->zone_restart_init == B_TRUE) {
- if (restart_init(what, why) == 0)
- return (0);
- }
-
- z->zone_init_status = wstat(why, what);
- (void) zone_kadmin(A_SHUTDOWN, AD_HALT, NULL,
- zone_kcred());
- }
- }
-
- /*
- * Since we didn't or couldn't restart init, we clear
- * the zone's init state and proceed with exit
- * processing.
- */
- z->zone_proc_initpid = -1;
+ /* If zone's init restarts, we're done here. */
+ if (zone_init_exit(z, why, what))
+ return (0);
}
/*
diff --git a/usr/src/uts/common/os/zone.c b/usr/src/uts/common/os/zone.c
index 06a8549c5b..90e5e27d5c 100644
--- a/usr/src/uts/common/os/zone.c
+++ b/usr/src/uts/common/os/zone.c
@@ -2787,6 +2787,7 @@ zone_init(void)
mutex_exit(&p0.p_lock);
zone0.zone_restart_init = B_TRUE;
zone0.zone_reboot_on_init_exit = B_FALSE;
+ zone0.zone_restart_init_0 = B_FALSE;
zone0.zone_init_status = -1;
zone0.zone_brand = &native_brand;
rctl_prealloc_destroy(gp);
@@ -5063,6 +5064,7 @@ zone_create(const char *zone_name, const char *zone_root,
zone->zone_ncpus_online = 0;
zone->zone_restart_init = B_TRUE;
zone->zone_reboot_on_init_exit = B_FALSE;
+ zone->zone_restart_init_0 = B_FALSE;
zone->zone_init_status = -1;
zone->zone_brand = &native_brand;
zone->zone_initname = NULL;
@@ -6360,6 +6362,14 @@ zone_setattr(zoneid_t zoneid, int attr, void *buf, size_t bufsize)
zone->zone_restart_init = B_FALSE;
err = 0;
break;
+ case ZONE_ATTR_INITRESTART0:
+ zone->zone_restart_init_0 = B_TRUE;
+ err = 0;
+ break;
+ case ZONE_ATTR_INITREBOOT:
+ zone->zone_reboot_on_init_exit = B_TRUE;
+ err = 0;
+ break;
case ZONE_ATTR_BOOTARGS:
err = zone_set_bootargs(zone, (const char *)buf);
break;
diff --git a/usr/src/uts/common/sys/zone.h b/usr/src/uts/common/sys/zone.h
index 87253134fd..e871689f5f 100644
--- a/usr/src/uts/common/sys/zone.h
+++ b/usr/src/uts/common/sys/zone.h
@@ -120,6 +120,8 @@ extern "C" {
#define ZONE_ATTR_APP_SVC_CT 19
#define ZONE_ATTR_SCHED_FIXEDHI 20
#define ZONE_ATTR_SECFLAGS 21
+#define ZONE_ATTR_INITRESTART0 22
+#define ZONE_ATTR_INITREBOOT 23
/* Start of the brand-specific attribute namespace */
#define ZONE_ATTR_BRAND_ATTRS 32768
@@ -609,6 +611,7 @@ typedef struct zone {
boolean_t zone_restart_init; /* Restart init if it dies? */
boolean_t zone_reboot_on_init_exit; /* Reboot if init dies? */
+ boolean_t zone_restart_init_0; /* Restart only if it exits 0 */
boolean_t zone_setup_app_contract; /* setup contract? */
struct brand *zone_brand; /* zone's brand */
void *zone_brand_data; /* store brand specific data */
diff --git a/usr/src/uts/common/vm/vm_page.c b/usr/src/uts/common/vm/vm_page.c
index f8c5d8f6d9..abccf82057 100644
--- a/usr/src/uts/common/vm/vm_page.c
+++ b/usr/src/uts/common/vm/vm_page.c
@@ -22,7 +22,7 @@
* Copyright (c) 1986, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2015, Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
* Copyright (c) 2015, 2016 by Delphix. All rights reserved.
- * Copyright 2017 Joyent, Inc.
+ * Copyright 2018 Joyent, Inc.
*/
/* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */
@@ -441,10 +441,26 @@ init_pages_pp_maximum()
}
}
+/*
+ * In the past, we limited the maximum pages that could be gotten to essentially
+ * 1/2 of the total pages on the system. However, this is too conservative for
+ * some cases. For example, if we want to host a large virtual machine which
+ * needs to use a significant portion of the system's memory. In practice,
+ * allowing more than 1/2 of the total pages is fine, but becomes problematic
+ * as we approach or exceed 75% of the pages on the system. Thus, we limit the
+ * maximum to 23/32 of the total pages, which is ~72%.
+ */
void
set_max_page_get(pgcnt_t target_total_pages)
{
- max_page_get = target_total_pages / 2;
+ max_page_get = (target_total_pages >> 5) * 23;
+ ASSERT3U(max_page_get, >, 0);
+}
+
+pgcnt_t
+get_max_page_get()
+{
+ return (max_page_get);
}
static pgcnt_t pending_delete;