summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDan McDonald <danmcd@joyent.com>2021-10-25 11:37:01 -0400
committerDan McDonald <danmcd@joyent.com>2021-10-25 11:37:01 -0400
commita13af751641959037ad97975673e381167ef2d2b (patch)
tree5fe12039129a807c3b2887cdae4b7bbed3da8354
parent8670ecf7cf83864d6cefc939dbe8d114948999d7 (diff)
parent55fcd84f321375248464013e08f0ff6d6e00fffe (diff)
downloadillumos-joyent-a13af751641959037ad97975673e381167ef2d2b.tar.gz
[illumos-gate merge]
commit 55fcd84f321375248464013e08f0ff6d6e00fffe 14019 Allow more control over zone init exit actions commit ba5494d78f75a2e62b09b817fc6abf7351a952c2 14163 zfs-tests: remove_raidz.ksh is broken Conflicts: usr/src/uts/common/sys/zone.h usr/src/uts/common/os/zone.c usr/src/uts/common/os/exit.c usr/src/cmd/zoneadmd/zoneadmd.c
-rw-r--r--usr/src/cmd/zoneadmd/zoneadmd.c19
-rw-r--r--usr/src/lib/libbrand/common/libbrand.c29
-rw-r--r--usr/src/lib/libbrand/common/libbrand.h2
-rw-r--r--usr/src/lib/libbrand/common/mapfile-vers2
-rw-r--r--usr/src/lib/libbrand/dtd/brand.dtd.137
-rw-r--r--usr/src/test/zfs-tests/tests/functional/removal/remove_raidz.ksh6
-rw-r--r--usr/src/uts/common/os/exit.c29
7 files changed, 99 insertions, 25 deletions
diff --git a/usr/src/cmd/zoneadmd/zoneadmd.c b/usr/src/cmd/zoneadmd/zoneadmd.c
index 0c24c1a0e7..8566e9683e 100644
--- a/usr/src/cmd/zoneadmd/zoneadmd.c
+++ b/usr/src/cmd/zoneadmd/zoneadmd.c
@@ -1292,8 +1292,8 @@ zone_bootup(zlog_t *zlogp, const char *bootargs, int zstate, boolean_t debug)
dladm_status_t status;
char errmsg[DLADM_STRSIZE];
int err;
- boolean_t restart_init;
boolean_t app_svc_dep;
+ boolean_t restart_init, restart_init0, restart_initreboot;
if (brand_prestatechg(zlogp, zstate, Z_BOOT, debug) != 0)
return (-1);
@@ -1345,8 +1345,10 @@ zone_bootup(zlog_t *zlogp, const char *bootargs, int zstate, boolean_t debug)
goto bad;
}
- /* See if we should restart init if it dies. */
- restart_init = restartinit(bh);
+ /* See if this zone's brand should restart init if it dies. */
+ restart_init = brand_restartinit(bh);
+ restart_init0 = brand_restartinit0(bh);
+ restart_initreboot = brand_restartinitreboot(bh);
/*
* See if we need to setup contract dependencies between the zone's
@@ -1427,6 +1429,17 @@ zone_bootup(zlog_t *zlogp, const char *bootargs, int zstate, boolean_t debug)
zerror(zlogp, B_TRUE, "could not set zone init-no-restart");
goto bad;
}
+ if (restart_init0 && zone_setattr(zoneid, ZONE_ATTR_INITRESTART0,
+ NULL, 0) == -1) {
+ zerror(zlogp, B_TRUE,
+ "could not set zone init-restart-on-exit-0");
+ goto bad;
+ }
+ if (restart_initreboot && zone_setattr(zoneid, ZONE_ATTR_INITREBOOT,
+ NULL, 0) == -1) {
+ zerror(zlogp, B_TRUE, "could not set zone reboot-on-init-exit");
+ goto bad;
+ }
if (app_svc_dep && zone_setattr(zoneid, ZONE_ATTR_APP_SVC_CT,
(void *)B_TRUE, sizeof (boolean_t)) == -1) {
diff --git a/usr/src/lib/libbrand/common/libbrand.c b/usr/src/lib/libbrand/common/libbrand.c
index dc406d60a0..682d0fe32d 100644
--- a/usr/src/lib/libbrand/common/libbrand.c
+++ b/usr/src/lib/libbrand/common/libbrand.c
@@ -63,6 +63,8 @@
#define DTD_ELEM_MODNAME ((const xmlChar *) "modname")
#define DTD_ELEM_MOUNT ((const xmlChar *) "mount")
#define DTD_ELEM_RESTARTINIT ((const xmlChar *) "restartinit")
+#define DTD_ELEM_RESTARTINIT0 ((const xmlChar *) "restartinit0")
+#define DTD_ELEM_RESTARTINITREBOOT ((const xmlChar *) "restartinitreboot")
#define DTD_ELEM_POSTATTACH ((const xmlChar *) "postattach")
#define DTD_ELEM_POSTCLONE ((const xmlChar *) "postclone")
#define DTD_ELEM_POSTINSTALL ((const xmlChar *) "postinstall")
@@ -530,21 +532,40 @@ brand_get_initname(brand_handle_t bh, char *buf, size_t len)
buf, len, DTD_ELEM_INITNAME, B_FALSE, B_FALSE));
}
-boolean_t
-brand_restartinit(brand_handle_t bh)
+static boolean_t
+i_brand_restartinit(brand_handle_t bh, const xmlChar *tagname, boolean_t deflt)
{
struct brand_handle *bhp = (struct brand_handle *)bh;
char val[80];
if (brand_get_value(bhp, NULL, NULL, NULL, NULL,
- val, sizeof (val), DTD_ELEM_RESTARTINIT, B_FALSE, B_FALSE) != 0)
- return (B_TRUE);
+ val, sizeof (val), tagname, B_FALSE, B_FALSE) != 0) {
+ return (deflt);
+ }
if (strcmp(val, "false") == 0)
return (B_FALSE);
return (B_TRUE);
}
+boolean_t
+brand_restartinit(brand_handle_t bh)
+{
+ return (i_brand_restartinit(bh, DTD_ELEM_RESTARTINIT, B_TRUE));
+}
+
+boolean_t
+brand_restartinit0(brand_handle_t bh)
+{
+ return (i_brand_restartinit(bh, DTD_ELEM_RESTARTINIT0, B_FALSE));
+}
+
+boolean_t
+brand_restartinitreboot(brand_handle_t bh)
+{
+ return (i_brand_restartinit(bh, DTD_ELEM_RESTARTINITREBOOT, B_FALSE));
+}
+
int
brand_get_login_cmd(brand_handle_t bh, const char *username,
char *buf, size_t len)
diff --git a/usr/src/lib/libbrand/common/libbrand.h b/usr/src/lib/libbrand/common/libbrand.h
index 30accf95ba..2dc064481f 100644
--- a/usr/src/lib/libbrand/common/libbrand.h
+++ b/usr/src/lib/libbrand/common/libbrand.h
@@ -62,6 +62,8 @@ extern int brand_get_halt(brand_handle_t, const char *, const char *,
char *, size_t);
extern int brand_get_initname(brand_handle_t, char *, size_t);
extern boolean_t brand_restartinit(brand_handle_t);
+extern boolean_t brand_restartinit0(brand_handle_t);
+extern boolean_t brand_restartinitreboot(brand_handle_t);
extern int brand_get_install(brand_handle_t, const char *, const char *,
char *, size_t);
extern int brand_get_installopts(brand_handle_t, char *, size_t);
diff --git a/usr/src/lib/libbrand/common/mapfile-vers b/usr/src/lib/libbrand/common/mapfile-vers
index be79ae12b7..27999af434 100644
--- a/usr/src/lib/libbrand/common/mapfile-vers
+++ b/usr/src/lib/libbrand/common/mapfile-vers
@@ -80,6 +80,8 @@ SYMBOL_VERSION SUNWprivate {
brand_platform_iter_link;
brand_platform_iter_mounts;
brand_restartinit;
+ brand_restartinit0;
+ brand_restartinitreboot;
local:
*;
};
diff --git a/usr/src/lib/libbrand/dtd/brand.dtd.1 b/usr/src/lib/libbrand/dtd/brand.dtd.1
index a579bee93c..78c30a8355 100644
--- a/usr/src/lib/libbrand/dtd/brand.dtd.1
+++ b/usr/src/lib/libbrand/dtd/brand.dtd.1
@@ -212,17 +212,36 @@
<!ATTLIST initname>
<!--
- restartinit
+ restartinit, restartinit0 and restartinitreboot
- Boolean indicating that the program specified by the initname attr
- should be restarted, or not, if it exits. By default, the init program
- will be restarted if this attribute is not provided. Specifying false
- for this attr will prevent that.
+ These three boolean elements control what action is taken when the
+ program specified by the 'initname' element exits.
- It has no attributes.
+ The default values are:
+
+ restartinit: true
+ restartinit0: false
+ restartinitreboot: false
+
+ If 'restartinit' is set to false then the init process will never be
+ restarted and the zone will shut down once init exits. In this case, the
+ other restartinit elements are ignored.
+
+ When 'restartinit0' is set, init will only be restarted if it exited with
+ an exit status of 0, otherwise the zone will shut down.
+
+ If 'restartinitreboot' is set to true then whenever init should be
+ restarted, based on the other restartinit elements, the zone will instead
+ be rebooted.
+
+ These have no attributes.
-->
<!ELEMENT restartinit (#PCDATA) >
<!ATTLIST restartinit>
+<!ELEMENT restartinit0 (#PCDATA) >
+<!ATTLIST restartinit0>
+<!ELEMENT restartinitreboot (#PCDATA) >
+<!ATTLIST restartinitreboot>
<!--
login_cmd
@@ -627,7 +646,7 @@
-->
<!ELEMENT privilege (#PCDATA) >
-<!ATTLIST privilege set ( default | prohibited | required ) #REQUIRED
+<!ATTLIST privilege set ( default | prohibited | required ) #REQUIRED
name CDATA #REQUIRED
ip-type ( shared | exclusive ) "all" >
@@ -642,7 +661,9 @@
directory in which the configuration file is stored.
-->
-<!ELEMENT brand (modname?, initname, restartinit?, login_cmd,
+<!ELEMENT brand (modname?, initname, restartinit?,
+ restartinit0?, restartinitreboot?,
+ login_cmd,
forcedlogin_cmd, user_cmd, install,
installopts?, boot?, sysboot?, halt?, shutdown?,
verify_cfg?, verify_adm?, postattach?, postclone?,
diff --git a/usr/src/test/zfs-tests/tests/functional/removal/remove_raidz.ksh b/usr/src/test/zfs-tests/tests/functional/removal/remove_raidz.ksh
index 73540f8b4b..d23311bfe9 100644
--- a/usr/src/test/zfs-tests/tests/functional/removal/remove_raidz.ksh
+++ b/usr/src/test/zfs-tests/tests/functional/removal/remove_raidz.ksh
@@ -25,7 +25,9 @@ TMPDIR=${TMPDIR:-/tmp}
log_must mkfile $MINVDEVSIZE $TMPDIR/dsk1
log_must mkfile $MINVDEVSIZE $TMPDIR/dsk2
log_must mkfile $MINVDEVSIZE $TMPDIR/dsk3
-DISKS="$TMPDIR/dsk1 raidz $TMPDIR/dsk2 $TMPDIR/dsk3"
+DISKS1="$TMPDIR/dsk1"
+DISKS2="$TMPDIR/dsk2 $TMPDIR/dsk3"
+DISKS="$DISKS1 $DISKS2"
function cleanup
{
@@ -33,7 +35,7 @@ function cleanup
log_must rm -f $DISKS
}
-log_must default_setup_noexit "$DISKS"
+log_must default_setup_noexit "$DISKS1 raidz $DISKS2"
log_onexit cleanup
# Attempt to remove the non raidz disk.
diff --git a/usr/src/uts/common/os/exit.c b/usr/src/uts/common/os/exit.c
index 46e588c926..d1d0fe4765 100644
--- a/usr/src/uts/common/os/exit.c
+++ b/usr/src/uts/common/os/exit.c
@@ -166,7 +166,7 @@ restart_init_notify(zone_t *zone)
* 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
* which are usually inherited across exec() but will break init's
- * assumption that it is being exec()'d from a virgin process. Most
+ * assumption that it is being exec()'d from a virgin process. Most
* importantly this includes closing all file descriptors (exec only
* closes those marked close-on-exec) and resetting signals (exec only
* resets handled signals, and we need to clear any signals which
@@ -343,7 +343,7 @@ exit(int why, int what)
/*
* If proc_exit() fails, then some other lwp in the process
* got there first. We just have to call lwp_exit() to allow
- * the other lwp to finish exiting the process. Otherwise we're
+ * the other lwp to finish exiting the process. Otherwise we're
* restarting init, and should return.
*/
if (proc_exit(why, what) != 0) {
@@ -356,7 +356,7 @@ exit(int why, int what)
/*
* Set the SEXITING flag on the process, after making sure /proc does
- * not have it locked. This is done in more places than proc_exit(),
+ * not have it locked. This is done in more places than proc_exit(),
* so it is a separate function.
*/
void
@@ -471,9 +471,9 @@ zone_init_exit(zone_t *z, int why, int what)
}
}
-
/*
- * The restart failed, the zone will shut down.
+ * The restart failed, or the criteria for a restart are not met;
+ * the zone will shut down.
*/
z->zone_init_status = wstat(why, what);
(void) zone_kadmin(A_SHUTDOWN, AD_HALT, NULL, zone_kcred());
@@ -510,7 +510,7 @@ proc_exit(int why, int what)
/*
* Stop and discard the process's lwps except for the current one,
- * unless some other lwp beat us to it. If exitlwps() fails then
+ * unless some other lwp beat us to it. If exitlwps() fails then
* return and the calling lwp will call (or continue in) lwp_exit().
*/
proc_is_exiting(p);
@@ -560,6 +560,19 @@ proc_exit(int why, int what)
lwp_detach_brand_hdlrs(lwp);
}
+ /*
+ * 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 zone's init restarts, we're done here. */
+ if (zone_init_exit(z, why, what))
+ return (0);
+ }
+
lwp_pcb_exit();
/*
@@ -1005,7 +1018,7 @@ proc_exit(int why, int what)
* curthread's proc pointer is changed to point to the 'sched'
* process for the corresponding zone, except in the case when
* the exiting process is in fact a zsched instance, in which
- * case the proc pointer is set to p0. We do so, so that the
+ * case the proc pointer is set to p0. We do so, so that the
* process still points at the right zone when we call the VN_RELE()
* below.
*
@@ -1089,7 +1102,7 @@ proc_exit(int why, int what)
/*
* task_rele() may ultimately cause the zone to go away (or
* may cause the last user process in a zone to go away, which
- * signals zsched to go away). So prior to this call, we must
+ * signals zsched to go away). So prior to this call, we must
* no longer point at zsched.
*/
t->t_procp = &p0;