17c478bd9Sstevel@tonic-gate /* 27c478bd9Sstevel@tonic-gate * CDDL HEADER START 37c478bd9Sstevel@tonic-gate * 47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 521d7f835Sgm149974 * Common Development and Distribution License (the "License"). 621d7f835Sgm149974 * You may not use this file except in compliance with the License. 77c478bd9Sstevel@tonic-gate * 87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 117c478bd9Sstevel@tonic-gate * and limitations under the License. 127c478bd9Sstevel@tonic-gate * 137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 187c478bd9Sstevel@tonic-gate * 197c478bd9Sstevel@tonic-gate * CDDL HEADER END 207c478bd9Sstevel@tonic-gate */ 217c478bd9Sstevel@tonic-gate /* 2292ba7109Seschrock * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 237c478bd9Sstevel@tonic-gate * Use is subject to license terms. 247c478bd9Sstevel@tonic-gate */ 257c478bd9Sstevel@tonic-gate 267c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 277c478bd9Sstevel@tonic-gate 287c478bd9Sstevel@tonic-gate /* 297c478bd9Sstevel@tonic-gate * specials.c - knowledge of special services 307c478bd9Sstevel@tonic-gate * 317c478bd9Sstevel@tonic-gate * svc.startd(1M) has duties that cannot be carried out without knowledge of the 327c478bd9Sstevel@tonic-gate * transition of various services, such as the milestones, to their online 337c478bd9Sstevel@tonic-gate * states. Hooks are called with the restarter instance's ri_lock held, so 347c478bd9Sstevel@tonic-gate * operations on all instances (or on the graph) should be performed 357c478bd9Sstevel@tonic-gate * asynchronously. 367c478bd9Sstevel@tonic-gate */ 377c478bd9Sstevel@tonic-gate 387c478bd9Sstevel@tonic-gate #include <sys/statvfs.h> 397c478bd9Sstevel@tonic-gate #include <sys/types.h> 407c478bd9Sstevel@tonic-gate #include <assert.h> 417c478bd9Sstevel@tonic-gate #include <errno.h> 427c478bd9Sstevel@tonic-gate #include <libintl.h> 437c478bd9Sstevel@tonic-gate #include <limits.h> 447c478bd9Sstevel@tonic-gate #include <locale.h> 457c478bd9Sstevel@tonic-gate #include <pthread.h> 467c478bd9Sstevel@tonic-gate #include <signal.h> 477c478bd9Sstevel@tonic-gate #include <stdio.h> 487c478bd9Sstevel@tonic-gate #include <string.h> 497c478bd9Sstevel@tonic-gate #include <strings.h> 507c478bd9Sstevel@tonic-gate #include <time.h> 517c478bd9Sstevel@tonic-gate #include <zone.h> 527c478bd9Sstevel@tonic-gate 537c478bd9Sstevel@tonic-gate #include "startd.h" 547c478bd9Sstevel@tonic-gate 557c478bd9Sstevel@tonic-gate void 567c478bd9Sstevel@tonic-gate special_null_transition() 577c478bd9Sstevel@tonic-gate { 587c478bd9Sstevel@tonic-gate } 597c478bd9Sstevel@tonic-gate 607c478bd9Sstevel@tonic-gate static void 617c478bd9Sstevel@tonic-gate special_fsroot_post_online() 627c478bd9Sstevel@tonic-gate { 637c478bd9Sstevel@tonic-gate static int once; 647c478bd9Sstevel@tonic-gate char *locale; 657c478bd9Sstevel@tonic-gate 667c478bd9Sstevel@tonic-gate /* 677c478bd9Sstevel@tonic-gate * /usr, with timezone and locale data, is now available. 687c478bd9Sstevel@tonic-gate */ 697c478bd9Sstevel@tonic-gate if (!st->st_log_timezone_known) { 707c478bd9Sstevel@tonic-gate tzset(); 717c478bd9Sstevel@tonic-gate st->st_log_timezone_known = 1; 727c478bd9Sstevel@tonic-gate } 737c478bd9Sstevel@tonic-gate 747c478bd9Sstevel@tonic-gate if (!st->st_log_locale_known) { 757c478bd9Sstevel@tonic-gate locale = st->st_locale; 767c478bd9Sstevel@tonic-gate 777c478bd9Sstevel@tonic-gate (void) setlocale(LC_ALL, ""); 787c478bd9Sstevel@tonic-gate st->st_locale = setlocale(LC_MESSAGES, ""); 797c478bd9Sstevel@tonic-gate if (st->st_locale) { 807c478bd9Sstevel@tonic-gate st->st_locale = safe_strdup(st->st_locale); 817c478bd9Sstevel@tonic-gate xstr_sanitize(st->st_locale); 827c478bd9Sstevel@tonic-gate free(locale); 837c478bd9Sstevel@tonic-gate } else { 847c478bd9Sstevel@tonic-gate st->st_locale = locale; 857c478bd9Sstevel@tonic-gate } 867c478bd9Sstevel@tonic-gate 877c478bd9Sstevel@tonic-gate (void) textdomain(TEXT_DOMAIN); 887c478bd9Sstevel@tonic-gate st->st_log_locale_known = 1; 897c478bd9Sstevel@tonic-gate } 907c478bd9Sstevel@tonic-gate 917c478bd9Sstevel@tonic-gate if (once) 927c478bd9Sstevel@tonic-gate return; 937c478bd9Sstevel@tonic-gate 947c478bd9Sstevel@tonic-gate /* 957c478bd9Sstevel@tonic-gate * ctime(3C) ends with '\n\0'. 967c478bd9Sstevel@tonic-gate */ 977c478bd9Sstevel@tonic-gate once++; 987c478bd9Sstevel@tonic-gate log_framework(LOG_INFO, "system start time was %s", 997c478bd9Sstevel@tonic-gate ctime(&st->st_start_time.tv_sec)); 1007c478bd9Sstevel@tonic-gate } 1017c478bd9Sstevel@tonic-gate 1027c478bd9Sstevel@tonic-gate static void 103*1af98250Seschrock special_fsminimal_post_online(void) 1047c478bd9Sstevel@tonic-gate { 105*1af98250Seschrock ulong_t rfsid, fsid; 1067c478bd9Sstevel@tonic-gate pid_t init_pid; 107*1af98250Seschrock int ret; 1087c478bd9Sstevel@tonic-gate 1097c478bd9Sstevel@tonic-gate log_framework(LOG_DEBUG, "special_fsminimal_post_online hook " 1107c478bd9Sstevel@tonic-gate "executed\n"); 1117c478bd9Sstevel@tonic-gate 1127c478bd9Sstevel@tonic-gate /* 113*1af98250Seschrock * If /var is still read-only, and it is on a separate filesystem, then 114*1af98250Seschrock * attempt to mount it read-write now. 1157c478bd9Sstevel@tonic-gate */ 116*1af98250Seschrock if ((ret = fs_is_read_only("/var", &fsid)) == 1) { 117*1af98250Seschrock (void) fs_is_read_only("/", &rfsid); 1187c478bd9Sstevel@tonic-gate 119*1af98250Seschrock if (rfsid != fsid) { 1207c478bd9Sstevel@tonic-gate log_framework(LOG_WARNING, "/var filesystem " 1217c478bd9Sstevel@tonic-gate "read-only after system/filesystem/minimal\n"); 1227c478bd9Sstevel@tonic-gate if (fs_remount("/var")) 1237c478bd9Sstevel@tonic-gate log_framework(LOG_WARNING, "/var " 1247c478bd9Sstevel@tonic-gate "filesystem remount failed\n"); 1257c478bd9Sstevel@tonic-gate } 1267c478bd9Sstevel@tonic-gate } 1277c478bd9Sstevel@tonic-gate 128*1af98250Seschrock if ((ret = fs_is_read_only("/var", &fsid)) != 1) { 129*1af98250Seschrock if (ret != 0) 130*1af98250Seschrock log_error(LOG_WARNING, gettext("couldn't check status " 131*1af98250Seschrock "of /var filesystem: %s\n"), strerror(errno)); 132*1af98250Seschrock 1337c478bd9Sstevel@tonic-gate /* 1347c478bd9Sstevel@tonic-gate * Clear (dead) entries and record boot time. 1357c478bd9Sstevel@tonic-gate */ 1367c478bd9Sstevel@tonic-gate utmpx_clear_old(); 1377c478bd9Sstevel@tonic-gate utmpx_write_boottime(); 1387c478bd9Sstevel@tonic-gate 1397c478bd9Sstevel@tonic-gate /* 1407c478bd9Sstevel@tonic-gate * Reinitialize the logs to point to LOG_PREFIX_NORMAL. 1417c478bd9Sstevel@tonic-gate */ 1427c478bd9Sstevel@tonic-gate log_init(); 1437c478bd9Sstevel@tonic-gate 1447c478bd9Sstevel@tonic-gate /* 14592ba7109Seschrock * Poke init so it will create /var/run/initpipe. 1467c478bd9Sstevel@tonic-gate */ 1477c478bd9Sstevel@tonic-gate if (zone_getattr(getzoneid(), ZONE_ATTR_INITPID, &init_pid, 1487c478bd9Sstevel@tonic-gate sizeof (init_pid)) != sizeof (init_pid)) { 149*1af98250Seschrock log_error(LOG_WARNING, "Could not get pid of init: " 150*1af98250Seschrock "%s.\n", strerror(errno)); 1517c478bd9Sstevel@tonic-gate } else { 1527c478bd9Sstevel@tonic-gate if (kill(init_pid, SIGHUP) != 0) { 1537c478bd9Sstevel@tonic-gate switch (errno) { 1547c478bd9Sstevel@tonic-gate case EPERM: 1557c478bd9Sstevel@tonic-gate case ESRCH: 1567c478bd9Sstevel@tonic-gate log_error(LOG_WARNING, 1577c478bd9Sstevel@tonic-gate "Could not signal init: %s.\n", 1587c478bd9Sstevel@tonic-gate strerror(errno)); 1597c478bd9Sstevel@tonic-gate break; 1607c478bd9Sstevel@tonic-gate 1617c478bd9Sstevel@tonic-gate case EINVAL: 1627c478bd9Sstevel@tonic-gate default: 1637c478bd9Sstevel@tonic-gate bad_error("kill", errno); 1647c478bd9Sstevel@tonic-gate } 1657c478bd9Sstevel@tonic-gate } 1667c478bd9Sstevel@tonic-gate } 167*1af98250Seschrock } 168*1af98250Seschrock 169*1af98250Seschrock if ((ret = fs_is_read_only("/etc/svc", &fsid)) != 1) { 170*1af98250Seschrock if (ret != 0) 171*1af98250Seschrock log_error(LOG_WARNING, gettext("couldn't check status " 172*1af98250Seschrock "of /etc/svc filesystem: %s\n"), strerror(errno)); 1737c478bd9Sstevel@tonic-gate 1747c478bd9Sstevel@tonic-gate /* 1757c478bd9Sstevel@tonic-gate * Take pending snapshots and create a svc.startd instance. 1767c478bd9Sstevel@tonic-gate */ 177*1af98250Seschrock (void) startd_thread_create(restarter_post_fsminimal_thread, 178*1af98250Seschrock NULL); 179*1af98250Seschrock } 1807c478bd9Sstevel@tonic-gate } 1817c478bd9Sstevel@tonic-gate 1827c478bd9Sstevel@tonic-gate static void 183*1af98250Seschrock special_single_post_online(void) 1847c478bd9Sstevel@tonic-gate { 1857c478bd9Sstevel@tonic-gate int r; 1867c478bd9Sstevel@tonic-gate 1877c478bd9Sstevel@tonic-gate log_framework(LOG_DEBUG, "special_single_post_online hook executed\n"); 1887c478bd9Sstevel@tonic-gate 1897c478bd9Sstevel@tonic-gate /* 1907c478bd9Sstevel@tonic-gate * Un-set the special reconfig reboot property. 1917c478bd9Sstevel@tonic-gate */ 1927c478bd9Sstevel@tonic-gate r = libscf_set_reconfig(0); 1937c478bd9Sstevel@tonic-gate switch (r) { 1947c478bd9Sstevel@tonic-gate case 0: 1957c478bd9Sstevel@tonic-gate case ENOENT: 1967c478bd9Sstevel@tonic-gate break; 1977c478bd9Sstevel@tonic-gate 1987c478bd9Sstevel@tonic-gate case EPERM: 1997c478bd9Sstevel@tonic-gate case EACCES: 2007c478bd9Sstevel@tonic-gate case EROFS: 2017c478bd9Sstevel@tonic-gate log_error(LOG_WARNING, "Could not clear reconfiguration " 2027c478bd9Sstevel@tonic-gate "property: %s.\n", strerror(r)); 2037c478bd9Sstevel@tonic-gate break; 2047c478bd9Sstevel@tonic-gate 2057c478bd9Sstevel@tonic-gate default: 2067c478bd9Sstevel@tonic-gate bad_error("libscf_set_reconfig", r); 2077c478bd9Sstevel@tonic-gate } 2087c478bd9Sstevel@tonic-gate 2097c478bd9Sstevel@tonic-gate if (booting_to_single_user) 2107c478bd9Sstevel@tonic-gate (void) startd_thread_create(single_user_thread, NULL); 2117c478bd9Sstevel@tonic-gate } 2127c478bd9Sstevel@tonic-gate 2137c478bd9Sstevel@tonic-gate static service_hook_assn_t special_svcs[] = { 2147c478bd9Sstevel@tonic-gate { "svc:/system/filesystem/root:default", 2157c478bd9Sstevel@tonic-gate special_null_transition, 2167c478bd9Sstevel@tonic-gate special_fsroot_post_online, 2177c478bd9Sstevel@tonic-gate special_null_transition }, 2187c478bd9Sstevel@tonic-gate { "svc:/system/filesystem/minimal:default", 2197c478bd9Sstevel@tonic-gate special_null_transition, 2207c478bd9Sstevel@tonic-gate special_fsminimal_post_online, 2217c478bd9Sstevel@tonic-gate special_null_transition }, 2227c478bd9Sstevel@tonic-gate { "svc:/milestone/single-user:default", 2237c478bd9Sstevel@tonic-gate special_null_transition, 2247c478bd9Sstevel@tonic-gate special_single_post_online, 2257c478bd9Sstevel@tonic-gate special_null_transition }, 2267c478bd9Sstevel@tonic-gate }; 2277c478bd9Sstevel@tonic-gate 2287c478bd9Sstevel@tonic-gate void 2297c478bd9Sstevel@tonic-gate special_online_hooks_get(const char *fmri, instance_hook_t *pre_onp, 2307c478bd9Sstevel@tonic-gate instance_hook_t *post_onp, instance_hook_t *post_offp) 2317c478bd9Sstevel@tonic-gate { 2327c478bd9Sstevel@tonic-gate int i; 2337c478bd9Sstevel@tonic-gate 2347c478bd9Sstevel@tonic-gate for (i = 0; i < sizeof (special_svcs) / sizeof (service_hook_assn_t); 2357c478bd9Sstevel@tonic-gate i++) 2367c478bd9Sstevel@tonic-gate if (strcmp(fmri, special_svcs[i].sh_fmri) == 0) { 2377c478bd9Sstevel@tonic-gate *pre_onp = special_svcs[i].sh_pre_online_hook; 2387c478bd9Sstevel@tonic-gate *post_onp = special_svcs[i].sh_post_online_hook; 23921d7f835Sgm149974 *post_offp = special_svcs[i].sh_post_offline_hook; 2407c478bd9Sstevel@tonic-gate return; 2417c478bd9Sstevel@tonic-gate } 2427c478bd9Sstevel@tonic-gate 2437c478bd9Sstevel@tonic-gate *pre_onp = *post_onp = *post_offp = special_null_transition; 2447c478bd9Sstevel@tonic-gate } 245