4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22 /*
23 * Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved.
24 * Copyright 2018 Joyent, Inc.
25 * Copyright (c) 2015, Syneto S.R.L. All rights reserved.
26 * Copyright 2016 Toomas Soome <tsoome@me.com>
27 * Copyright 2016 RackTop Systems.
28 */
29
30 /*
31 * graph.c - master restarter graph engine
32 *
33 * The graph engine keeps a dependency graph of all service instances on the
34 * system, as recorded in the repository. It decides when services should
35 * be brought up or down based on service states and dependencies and sends
36 * commands to restarters to effect any changes. It also executes
37 * administrator commands sent by svcadm via the repository.
38 *
39 * The graph is stored in uu_list_t *dgraph and its vertices are
40 * graph_vertex_t's, each of which has a name and an integer id unique to
41 * its name (see dict.c). A vertex's type attribute designates the type
42 * of object it represents: GVT_INST for service instances, GVT_SVC for
43 * service objects (since service instances may depend on another service,
44 * rather than service instance), GVT_FILE for files (which services may
5800 gu->gu_wakeup = 0;
5801
5802 while ((e = graph_event_dequeue()) != NULL) {
5803 MUTEX_LOCK(&e->gpe_lock);
5804 MUTEX_UNLOCK(&gu->gu_lock);
5805
5806 while ((err = handle_graph_update_event(h, e)) ==
5807 ECONNABORTED)
5808 libscf_handle_rebind(h);
5809
5810 if (err == 0)
5811 graph_event_release(e);
5812 else
5813 graph_event_requeue(e);
5814
5815 MUTEX_LOCK(&gu->gu_lock);
5816 }
5817
5818 MUTEX_UNLOCK(&gu->gu_lock);
5819 }
5820
5821 /*
5822 * Unreachable for now -- there's currently no graceful cleanup
5823 * called on exit().
5824 */
5825 MUTEX_UNLOCK(&gu->gu_lock);
5826 scf_handle_destroy(h);
5827 return (NULL);
5828 }
5829
5830 static void
5831 set_initial_milestone(scf_handle_t *h)
5832 {
5833 scf_instance_t *inst;
5834 char *fmri, *cfmri;
5835 size_t sz;
5836 int r;
5837
5838 inst = safe_scf_instance_create(h);
5839 fmri = startd_alloc(max_scf_fmri_size);
5840
5841 /*
5842 * If -m milestone= was specified, we want to set options_ovr/milestone
5843 * to it. Otherwise we want to read what the milestone should be set
5844 * to. Either way we need our inst.
5845 */
5846 get_self:
5847 if (scf_handle_decode_fmri(h, SCF_SERVICE_STARTD, NULL, NULL, inst,
6173 * Now that we've set st_load_complete we need to check can_come_up()
6174 * since if we booted to a milestone, then there won't be any more
6175 * state updates.
6176 */
6177 if (!go_single_user_mode && !go_to_level1 &&
6178 halting == -1) {
6179 if (!sulogin_thread_running && !can_come_up()) {
6180 (void) startd_thread_create(sulogin_thread, NULL);
6181 sulogin_thread_running = B_TRUE;
6182 }
6183 }
6184 MUTEX_UNLOCK(&dgraph_lock);
6185
6186 (void) pthread_mutex_lock(&gu->gu_freeze_lock);
6187
6188 /*CONSTCOND*/
6189 while (1) {
6190 (void) pthread_cond_wait(&gu->gu_freeze_cv,
6191 &gu->gu_freeze_lock);
6192 }
6193
6194 /*
6195 * Unreachable for now -- there's currently no graceful cleanup
6196 * called on exit().
6197 */
6198 (void) pthread_mutex_unlock(&gu->gu_freeze_lock);
6199 scf_handle_destroy(h);
6200
6201 return (NULL);
6202 }
6203
6204
6205 /*
6206 * int next_action()
6207 * Given an array of timestamps 'a' with 'num' elements, find the
6208 * lowest non-zero timestamp and return its index. If there are no
6209 * non-zero elements, return -1.
6210 */
6211 static int
6212 next_action(hrtime_t *a, int num)
6213 {
6214 hrtime_t t = 0;
6215 int i = 0, smallest = -1;
6216
6217 for (i = 0; i < num; i++) {
6218 if (t == 0) {
6219 t = a[i];
6220 smallest = i;
6221 } else if (a[i] != 0 && a[i] < t) {
|
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22 /*
23 * Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved.
24 * Copyright 2019 Joyent, Inc.
25 * Copyright (c) 2015, Syneto S.R.L. All rights reserved.
26 * Copyright 2016 Toomas Soome <tsoome@me.com>
27 * Copyright 2016 RackTop Systems.
28 */
29
30 /*
31 * graph.c - master restarter graph engine
32 *
33 * The graph engine keeps a dependency graph of all service instances on the
34 * system, as recorded in the repository. It decides when services should
35 * be brought up or down based on service states and dependencies and sends
36 * commands to restarters to effect any changes. It also executes
37 * administrator commands sent by svcadm via the repository.
38 *
39 * The graph is stored in uu_list_t *dgraph and its vertices are
40 * graph_vertex_t's, each of which has a name and an integer id unique to
41 * its name (see dict.c). A vertex's type attribute designates the type
42 * of object it represents: GVT_INST for service instances, GVT_SVC for
43 * service objects (since service instances may depend on another service,
44 * rather than service instance), GVT_FILE for files (which services may
5800 gu->gu_wakeup = 0;
5801
5802 while ((e = graph_event_dequeue()) != NULL) {
5803 MUTEX_LOCK(&e->gpe_lock);
5804 MUTEX_UNLOCK(&gu->gu_lock);
5805
5806 while ((err = handle_graph_update_event(h, e)) ==
5807 ECONNABORTED)
5808 libscf_handle_rebind(h);
5809
5810 if (err == 0)
5811 graph_event_release(e);
5812 else
5813 graph_event_requeue(e);
5814
5815 MUTEX_LOCK(&gu->gu_lock);
5816 }
5817
5818 MUTEX_UNLOCK(&gu->gu_lock);
5819 }
5820 }
5821
5822 static void
5823 set_initial_milestone(scf_handle_t *h)
5824 {
5825 scf_instance_t *inst;
5826 char *fmri, *cfmri;
5827 size_t sz;
5828 int r;
5829
5830 inst = safe_scf_instance_create(h);
5831 fmri = startd_alloc(max_scf_fmri_size);
5832
5833 /*
5834 * If -m milestone= was specified, we want to set options_ovr/milestone
5835 * to it. Otherwise we want to read what the milestone should be set
5836 * to. Either way we need our inst.
5837 */
5838 get_self:
5839 if (scf_handle_decode_fmri(h, SCF_SERVICE_STARTD, NULL, NULL, inst,
6165 * Now that we've set st_load_complete we need to check can_come_up()
6166 * since if we booted to a milestone, then there won't be any more
6167 * state updates.
6168 */
6169 if (!go_single_user_mode && !go_to_level1 &&
6170 halting == -1) {
6171 if (!sulogin_thread_running && !can_come_up()) {
6172 (void) startd_thread_create(sulogin_thread, NULL);
6173 sulogin_thread_running = B_TRUE;
6174 }
6175 }
6176 MUTEX_UNLOCK(&dgraph_lock);
6177
6178 (void) pthread_mutex_lock(&gu->gu_freeze_lock);
6179
6180 /*CONSTCOND*/
6181 while (1) {
6182 (void) pthread_cond_wait(&gu->gu_freeze_cv,
6183 &gu->gu_freeze_lock);
6184 }
6185 }
6186
6187
6188 /*
6189 * int next_action()
6190 * Given an array of timestamps 'a' with 'num' elements, find the
6191 * lowest non-zero timestamp and return its index. If there are no
6192 * non-zero elements, return -1.
6193 */
6194 static int
6195 next_action(hrtime_t *a, int num)
6196 {
6197 hrtime_t t = 0;
6198 int i = 0, smallest = -1;
6199
6200 for (i = 0; i < num; i++) {
6201 if (t == 0) {
6202 t = a[i];
6203 smallest = i;
6204 } else if (a[i] != 0 && a[i] < t) {
|