diff options
Diffstat (limited to 'usr/src/cmd/init/init.c')
-rw-r--r-- | usr/src/cmd/init/init.c | 64 |
1 files changed, 58 insertions, 6 deletions
diff --git a/usr/src/cmd/init/init.c b/usr/src/cmd/init/init.c index 031a053b65..fa1b9d687c 100644 --- a/usr/src/cmd/init/init.c +++ b/usr/src/cmd/init/init.c @@ -23,6 +23,7 @@ * Copyright (c) 2013 Gary Mills * * Copyright (c) 1988, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright 2015, Joyent, Inc. */ /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ @@ -144,6 +145,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. @@ -548,6 +551,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; @@ -696,9 +701,8 @@ main(int argc, char *argv[]) console(B_FALSE, "\n\n%s Release %s Version %s %d-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 (c) 2010-2012, " + "Joyent Inc. All rights reserved.\r\n"); } /* @@ -3509,6 +3513,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 @@ -3596,6 +3622,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) { @@ -4305,9 +4337,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 @@ -4438,6 +4468,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) { |