summaryrefslogtreecommitdiff
path: root/usr/src/cmd/init/init.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src/cmd/init/init.c')
-rw-r--r--usr/src/cmd/init/init.c63
1 files changed, 57 insertions, 6 deletions
diff --git a/usr/src/cmd/init/init.c b/usr/src/cmd/init/init.c
index 1afc73b976..e195573349 100644
--- a/usr/src/cmd/init/init.c
+++ b/usr/src/cmd/init/init.c
@@ -25,6 +25,7 @@
* Copyright (c) 2013 Gary Mills
*
* Copyright (c) 1988, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright 2020 Joyent, Inc.
*/
/* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
@@ -148,6 +149,8 @@
#define UT_USER_SZ 32 /* Size of a utmpx ut_user field */
#define UT_LINE_SZ 32 /* Size of a utmpx ut_line field */
+#define CHECK_SVC SCF_INSTANCE_FS_MINIMAL
+
/*
* SLEEPTIME The number of seconds "init" sleeps between wakeups if
* nothing else requires this "init" wakeup.
@@ -552,6 +555,8 @@ static time_t init_boot_time; /* Substitute for kernel boot time. */
#define NSTARTD_FAILURE_TIMES 3 /* trigger after 3 failures */
#define STARTD_FAILURE_RATE_NS 5000000000LL /* 1 failure/5 seconds */
+#define STARTD_THROTTLE_RETRY 60 /* space failure retry after 60 secs */
+#define ROOT_MIN_FREE 524288 /* 512KB min. space needed in root */
static hrtime_t startd_failure_time[NSTARTD_FAILURE_TIMES];
static uint_t startd_failure_index;
@@ -697,9 +702,7 @@ main(int argc, char *argv[])
console(B_FALSE,
"\n\n%s Release %s Version %s %s-bit\r\n",
un.sysname, un.release, un.version, bits);
- console(B_FALSE,
- "Copyright (c) 1983, 2010, Oracle and/or its affiliates."
- " All rights reserved.\r\n");
+ console(B_FALSE, "Copyright 2010-2020 Joyent, Inc.\r\n");
#else
bootbanner_print(init_bootbanner_print, 0);
#endif
@@ -3471,6 +3474,28 @@ bail:
}
/*
+ * Attempt to confirm that svc.startd is ready to accept a user-initiated
+ * run-level change. startd is not ready until it has started its
+ * _scf_notify_wait thread to watch for events from svc.configd. This is
+ * inherently racy. To workaround this, we check the status of a file that
+ * startd will create once it has started the _scf_notify_wait thread.
+ * If we don't see this file after one minute, then charge ahead.
+ */
+static void
+verify_startd_ready()
+{
+ struct stat64 buf;
+ int i;
+
+ for (i = 0; i < 60; i++) {
+ if (stat64("/etc/svc/volatile/startd.ready", &buf) == 0)
+ return;
+ sleep(1);
+ }
+ console(B_TRUE, "verify startd timeout\n");
+}
+
+/*
* Function to handle requests from users to main init running as process 1.
*/
static void
@@ -3558,6 +3583,12 @@ userinit(int argc, char **argv)
(void) audit_put_record(ADT_SUCCESS, ADT_SUCCESS, argv[1]);
/*
+ * Before we tell init to start a run-level change, we need to be
+ * sure svc.startd is ready to accept that.
+ */
+ verify_startd_ready();
+
+ /*
* Signal init; init will take care of telling svc.startd.
*/
if (kill(init_pid, init_signal) == FAILURE) {
@@ -4267,9 +4298,7 @@ contract_event(struct pollfd *poll)
if (ret == 0) {
if (cookie == STARTD_COOKIE &&
do_restart_startd) {
- if (smf_debug)
- console(B_TRUE, "Restarting "
- "svc.startd.\n");
+ console(B_TRUE, "Restarting svc.startd.\n");
/*
* Account for the failure. If the failure rate
@@ -4400,6 +4429,28 @@ startd_run(const char *cline, int tmpl, ctid_t old_ctid)
if (pid == 0) {
/* child */
+ struct statvfs64 sbuf;
+
+ /*
+ * svc.configd needs some space (a few hundred KB) in / for its
+ * database. One common cause for startd failure is when
+ * configd dies because / is full. We don't want to go into the
+ * fast restart loop (startd_failure_rate_critical) and enter
+ * maintenance so we check for this case and slow down the
+ * failure rate so as to keep retrying in the hope space will
+ * free up.
+ */
+ if (statvfs64("/", &sbuf) != -1 &&
+ (sbuf.f_bsize * sbuf.f_bfree) < ROOT_MIN_FREE) {
+ syslog(LOG_ERR, "Insufficent space (%ld) in / to "
+ "start svc.startd.\n",
+ (long)(sbuf.f_bsize * sbuf.f_bfree));
+ console(B_TRUE, "Insufficent space (%ld) in / to "
+ "start svc.startd.\n",
+ (long)(sbuf.f_bsize * sbuf.f_bfree));
+ sleep(STARTD_THROTTLE_RETRY);
+ exit(1);
+ }
/* See the comment in efork() */
for (i = SIGHUP; i <= SIGRTMAX; ++i) {