Lines Matching +full:assert +full:- +full:falling +full:- +full:edge
31 * graph.c - master restarter graph engine
48 * event-propagation characteristics.
57 * - an edge from the GVT_SVC vertex for the instance's service
59 * - an edge to the GVT_INST vertex of the instance's resarter, if its
62 * - edges from other GVT_INST vertices if the instance is a restarter
64 * - for each dependency property group in the instance's "running"
65 * snapshot, an edge to a GVT_GROUP vertex named by the FMRI of the
68 * - for each value of the "entities" property in each dependency property
69 * group, an edge from the corresponding GVT_GROUP vertex to a
72 * - edges from GVT_GROUP vertices for each dependent instance
91 * in-core copies of the data (dependency information for the graph engine) on
119 * SMF repository for the service/instance they refer to. System-wide
127 * stn_global for the system-wide set. They are re-read when instances are
145 #include <assert.h>
175 #define CONSOLE_LOGIN_FMRI "svc:/system/console-login:default"
181 #define IS_ENABLED(v) ((v)->gv_flags & (GV_ENABLED | GV_ENBLD_NOOVR))
188 * 1. 32-bit value assignments are atomic
211 #define is_depgrp_bypassed(v) ((v->gv_type == GVT_GROUP) && \
212 ((v->gv_depgroup == DEPGRP_EXCLUDE_ALL) || \
213 (v->gv_restart < RERR_RESTART)))
215 #define is_inst_bypassed(v) ((v->gv_type == GVT_INST) && \
216 ((v->gv_flags & GV_TODISABLE) || \
217 (v->gv_flags & GV_TOOFFLINE)))
245 static int halting = -1;
264 /* Statistics for dependency cycle-checking */
272 "(see 'svcs -xv' for details).\n";
287 * entry, which is only used when booting_to_single_user (boot -s) is set.
288 * This is because when doing a "boot -s", sulogin is started from specials.c
289 * after milestone/single-user comes online, for backwards compatibility.
291 * to ensure sulogin will be spawned if milestone/single-user cannot be reached.
296 "svc:/system/install-setup:default",
301 /* This array must have an element for each non-NULL element of up_svcs[]. */
326 int lc_id = ((const graph_vertex_t *)lc_arg)->gv_id; in graph_vertex_compare()
332 return (-1); in graph_vertex_compare()
342 assert(graph_edge_pool != NULL); in graph_init()
347 assert(graph_vertex_pool != NULL); in graph_init()
352 assert(dgraph != NULL); in graph_init()
354 if (!st->st_initial) in graph_init()
365 assert(MUTEX_HELD(&dgraph_lock)); in vertex_get_by_name()
368 if (id == -1) in vertex_get_by_name()
377 assert(MUTEX_HELD(&dgraph_lock)); in vertex_get_by_id()
379 if (id == -1) in vertex_get_by_id()
397 assert(MUTEX_HELD(&dgraph_lock)); in graph_add_vertex()
403 v->gv_id = id; in graph_add_vertex()
405 v->gv_name = startd_alloc(strlen(name) + 1); in graph_add_vertex()
406 (void) strcpy(v->gv_name, name); in graph_add_vertex()
408 v->gv_dependencies = startd_list_create(graph_edge_pool, v, 0); in graph_add_vertex()
409 v->gv_dependents = startd_list_create(graph_edge_pool, v, 0); in graph_add_vertex()
412 assert(p == NULL); in graph_add_vertex()
414 uu_list_node_init(v, &v->gv_link, graph_vertex_pool); in graph_add_vertex()
427 assert(MUTEX_HELD(&dgraph_lock)); in graph_remove_vertex()
429 assert(uu_list_numnodes(v->gv_dependencies) == 0); in graph_remove_vertex()
430 assert(uu_list_numnodes(v->gv_dependents) == 0); in graph_remove_vertex()
431 assert(v->gv_refs == 0); in graph_remove_vertex()
433 startd_free(v->gv_name, strlen(v->gv_name) + 1); in graph_remove_vertex()
434 uu_list_destroy(v->gv_dependencies); in graph_remove_vertex()
435 uu_list_destroy(v->gv_dependents); in graph_remove_vertex()
447 assert(MUTEX_HELD(&dgraph_lock)); in graph_add_edge()
452 e->ge_parent = fv; in graph_add_edge()
453 e->ge_vertex = tv; in graph_add_edge()
455 re->ge_parent = tv; in graph_add_edge()
456 re->ge_vertex = fv; in graph_add_edge()
458 uu_list_node_init(e, &e->ge_link, graph_edge_pool); in graph_add_edge()
459 r = uu_list_insert_before(fv->gv_dependencies, NULL, e); in graph_add_edge()
460 assert(r == 0); in graph_add_edge()
462 uu_list_node_init(re, &re->ge_link, graph_edge_pool); in graph_add_edge()
463 r = uu_list_insert_before(tv->gv_dependents, NULL, re); in graph_add_edge()
464 assert(r == 0); in graph_add_edge()
472 for (e = uu_list_first(v->gv_dependencies); in graph_remove_edge()
474 e = uu_list_next(v->gv_dependencies, e)) { in graph_remove_edge()
475 if (e->ge_vertex == dv) { in graph_remove_edge()
476 uu_list_remove(v->gv_dependencies, e); in graph_remove_edge()
482 for (e = uu_list_first(dv->gv_dependents); in graph_remove_edge()
484 e = uu_list_next(dv->gv_dependents, e)) { in graph_remove_edge()
485 if (e->ge_vertex == v) { in graph_remove_edge()
486 uu_list_remove(dv->gv_dependents, e); in graph_remove_edge()
500 assert(MUTEX_HELD(&dgraph_lock)); in remove_inst_vertex()
501 assert(uu_list_numnodes(v->gv_dependents) == 1); in remove_inst_vertex()
502 assert(uu_list_numnodes(v->gv_dependencies) == 0); in remove_inst_vertex()
503 assert(v->gv_refs == 0); in remove_inst_vertex()
504 assert((v->gv_flags & GV_CONFIGURED) == 0); in remove_inst_vertex()
506 e = uu_list_first(v->gv_dependents); in remove_inst_vertex()
507 sv = e->ge_vertex; in remove_inst_vertex()
520 if (uu_list_numnodes(sv->gv_dependencies) == 0 && in remove_inst_vertex()
521 uu_list_numnodes(sv->gv_dependents) == 0 && in remove_inst_vertex()
522 sv->gv_refs == 0) in remove_inst_vertex()
532 for (e = uu_list_first(v->gv_dependents); in graph_walk_dependents()
534 e = uu_list_next(v->gv_dependents, e)) in graph_walk_dependents()
535 func(e->ge_vertex, arg); in graph_walk_dependents()
544 assert(MUTEX_HELD(&dgraph_lock)); in graph_walk_dependencies()
546 for (e = uu_list_first(v->gv_dependencies); in graph_walk_dependencies()
548 e = uu_list_next(v->gv_dependencies, e)) { in graph_walk_dependencies()
550 func(e->ge_vertex, arg); in graph_walk_dependencies()
593 graph_vertex_t *v = e->ge_vertex; in graph_walk_recurse()
597 i = v->gv_id / 8; in graph_walk_recurse()
598 b = 1 << (v->gv_id % 8); in graph_walk_recurse()
603 if (gip->gi_visited[i] & b) in graph_walk_recurse()
606 gip->gi_visited[i] |= b; in graph_walk_recurse()
611 if (v->gv_type == GVT_GROUP && v->gv_depgroup == DEPGRP_EXCLUDE_ALL) in graph_walk_recurse()
615 * Call pre-visit callback. If this doesn't terminate the walk, in graph_walk_recurse()
618 if ((gip->gi_ret = gip->gi_pre(v, gip->gi_arg)) == UU_WALK_NEXT) { in graph_walk_recurse()
622 if (gip->gi_dir == WALK_DEPENDENTS) in graph_walk_recurse()
623 list = v->gv_dependents; in graph_walk_recurse()
625 list = v->gv_dependencies; in graph_walk_recurse()
629 assert(r == 0); in graph_walk_recurse()
635 assert(gip->gi_ret == UU_WALK_NEXT || gip->gi_ret == UU_WALK_DONE); in graph_walk_recurse()
638 * If given a post-callback, call the function for every vertex. in graph_walk_recurse()
640 if (gip->gi_post != NULL) in graph_walk_recurse()
641 (void) gip->gi_post(v, gip->gi_arg); in graph_walk_recurse()
648 return (gip->gi_ret); in graph_walk_recurse()
658 size_t sz = dictionary->dict_new_id / 8 + 1; in graph_walk()
668 * Fake up an edge for the first iteration in graph_walk()
681 * the vertex was found then path should point to a -1-terminated
692 cs->depth++; in child_pre()
694 if (v->gv_id == cs->id) { in child_pre()
695 cs->path = startd_alloc((cs->depth + 1) * sizeof (int)); in child_pre()
696 cs->path[cs->depth] = -1; in child_pre()
708 cs->depth--; in child_post()
710 if (cs->path != NULL) in child_post()
711 cs->path[cs->depth] = v->gv_id; in child_post()
716 * a NULL-terminated array of pointers to the vertices along the path. If
724 cs.id = to->gv_id; in is_path_to()
746 assert(MUTEX_HELD(&dgraph_lock)); in path_to_str()
747 assert(path[0] != -1); in path_to_str()
753 for (i = 0; path[i] != -1; ++i) { in path_to_str()
760 else if (v->gv_type == GVT_INST || v->gv_type == GVT_SVC) in path_to_str()
761 name = v->gv_name; in path_to_str()
785 * between system/console-login and sulogin. run_sulogin() will fail if
786 * system/console-login is online, and the graph engine should call
787 * graph_clogin_start() to bring system/console-login online, which defers the
793 assert(MUTEX_HELD(&dgraph_lock)); in graph_clogin_start()
872 assert(v->gv_state == RESTARTER_STATE_UNINIT); in vertex_send_event()
874 MUTEX_LOCK(&st->st_load_lock); in vertex_send_event()
875 st->st_load_instances++; in vertex_send_event()
876 MUTEX_UNLOCK(&st->st_load_lock); in vertex_send_event()
880 log_framework(LOG_DEBUG, "Enabling %s.\n", v->gv_name); in vertex_send_event()
881 assert(v->gv_state == RESTARTER_STATE_UNINIT || in vertex_send_event()
882 v->gv_state == RESTARTER_STATE_DISABLED || in vertex_send_event()
883 v->gv_state == RESTARTER_STATE_MAINT); in vertex_send_event()
888 log_framework(LOG_DEBUG, "Disabling %s.\n", v->gv_name); in vertex_send_event()
889 assert(v->gv_state != RESTARTER_STATE_DISABLED); in vertex_send_event()
894 log_framework(LOG_DEBUG, "Stopping %s.\n", v->gv_name); in vertex_send_event()
895 assert(v->gv_state == RESTARTER_STATE_DEGRADED || in vertex_send_event()
896 v->gv_state == RESTARTER_STATE_ONLINE); in vertex_send_event()
900 log_framework(LOG_DEBUG, "Starting %s.\n", v->gv_name); in vertex_send_event()
901 assert(v->gv_state == RESTARTER_STATE_OFFLINE); in vertex_send_event()
924 restarter_protocol_send_event(v->gv_name, v->gv_restarter_channel, e, in vertex_send_event()
925 v->gv_reason); in vertex_send_event()
931 assert(MUTEX_HELD(&dgraph_lock)); in graph_unset_restarter()
932 assert(v->gv_flags & GV_CONFIGURED); in graph_unset_restarter()
936 if (v->gv_restarter_id != -1) { in graph_unset_restarter()
939 rv = vertex_get_by_id(v->gv_restarter_id); in graph_unset_restarter()
943 v->gv_restarter_id = -1; in graph_unset_restarter()
944 v->gv_restarter_channel = NULL; in graph_unset_restarter()
954 assert(MUTEX_HELD(&dgraph_lock)); in free_if_unrefed()
956 if (v->gv_refs > 0) in free_if_unrefed()
959 if (v->gv_type == GVT_SVC && in free_if_unrefed()
960 uu_list_numnodes(v->gv_dependents) == 0 && in free_if_unrefed()
961 uu_list_numnodes(v->gv_dependencies) == 0) { in free_if_unrefed()
964 } else if (v->gv_type == GVT_INST && in free_if_unrefed()
965 (v->gv_flags & GV_CONFIGURED) == 0 && in free_if_unrefed()
966 uu_list_numnodes(v->gv_dependents) == 1 && in free_if_unrefed()
967 uu_list_numnodes(v->gv_dependencies) == 0) { in free_if_unrefed()
981 assert(MUTEX_HELD(&dgraph_lock)); in delete_depgroup()
982 assert(v->gv_type == GVT_GROUP); in delete_depgroup()
983 assert(uu_list_numnodes(v->gv_dependents) == 0); in delete_depgroup()
985 while ((e = uu_list_first(v->gv_dependencies)) != NULL) { in delete_depgroup()
986 dv = e->ge_vertex; in delete_depgroup()
990 switch (dv->gv_type) { in delete_depgroup()
997 assert(uu_list_numnodes(dv->gv_dependencies) == 0); in delete_depgroup()
998 if (uu_list_numnodes(dv->gv_dependents) == 0) in delete_depgroup()
1005 __LINE__, dv->gv_type); in delete_depgroup()
1021 dv = e->ge_vertex; in delete_instance_deps_cb()
1025 * - GVT_INST: restarter in delete_instance_deps_cb()
1026 * - GVT_GROUP - GVT_INST: instance dependency in delete_instance_deps_cb()
1027 * - GVT_GROUP - GVT_SVC - GV_INST: service dependency in delete_instance_deps_cb()
1028 * - GVT_GROUP - GVT_FILE: file dependency in delete_instance_deps_cb()
1030 switch (dv->gv_type) { in delete_instance_deps_cb()
1032 assert(dv->gv_id == v->gv_restarter_id); in delete_instance_deps_cb()
1048 dv->gv_type); in delete_instance_deps_cb()
1062 assert(MUTEX_HELD(&dgraph_lock)); in delete_instance_dependencies()
1063 assert(v->gv_type == GVT_INST); in delete_instance_dependencies()
1068 r = uu_list_walk(v->gv_dependencies, in delete_instance_dependencies()
1070 assert(r == 0); in delete_instance_dependencies()
1090 assert(MUTEX_HELD(&dgraph_lock)); in graph_insert_vertex_unconfigured()
1095 if (strncmp(fmri, "svc:", sizeof ("svc:") - 1) != 0) in graph_insert_vertex_unconfigured()
1100 if (strncmp(fmri, "file:", sizeof ("file:") - 1) != 0) in graph_insert_vertex_unconfigured()
1122 (*vp)->gv_type = type; in graph_insert_vertex_unconfigured()
1123 (*vp)->gv_depgroup = dt; in graph_insert_vertex_unconfigured()
1124 (*vp)->gv_restart = rt; in graph_insert_vertex_unconfigured()
1126 (*vp)->gv_flags = 0; in graph_insert_vertex_unconfigured()
1127 (*vp)->gv_state = RESTARTER_STATE_NONE; in graph_insert_vertex_unconfigured()
1131 (*vp)->gv_start_f = special_vertices[i].start_f; in graph_insert_vertex_unconfigured()
1132 (*vp)->gv_post_online_f = in graph_insert_vertex_unconfigured()
1134 (*vp)->gv_post_disable_f = in graph_insert_vertex_unconfigured()
1140 (*vp)->gv_restarter_id = -1; in graph_insert_vertex_unconfigured()
1141 (*vp)->gv_restarter_channel = 0; in graph_insert_vertex_unconfigured()
1152 assert(r == 0); in graph_insert_vertex_unconfigured()
1172 (*vp)->gv_flags |= (should_be_in_subgraph(*vp)? GV_INSUBGRAPH : 0); in graph_insert_vertex_unconfigured()
1185 assert(MUTEX_HELD(&dgraph_lock)); in graph_insert_dependency()
1191 if (!(fv->gv_type == GVT_GROUP && in graph_insert_dependency()
1192 fv->gv_depgroup == DEPGRP_EXCLUDE_ALL)) { in graph_insert_dependency()
1198 dep_cycle_ns += gethrtime() - now; in graph_insert_dependency()
1204 dep_insert_ns += gethrtime() - now; in graph_insert_dependency()
1207 tv->gv_flags |= (should_be_in_subgraph(tv) ? GV_INSUBGRAPH : 0); in graph_insert_dependency()
1215 assert(v->gv_type == GVT_INST); in inst_running()
1217 if (v->gv_state == RESTARTER_STATE_ONLINE || in inst_running()
1218 v->gv_state == RESTARTER_STATE_DEGRADED) in inst_running()
1226 * 1 - dependency satisfied
1227 * 0 - dependency unsatisfied
1228 * -1 - dependency unsatisfiable (without administrator intervention)
1243 graph_edge_t *edge; in require_all_satisfied() local
1247 if (uu_list_numnodes(groupv->gv_dependencies) == 0) in require_all_satisfied()
1252 for (edge = uu_list_first(groupv->gv_dependencies); in require_all_satisfied()
1253 edge != NULL; in require_all_satisfied()
1254 edge = uu_list_next(groupv->gv_dependencies, edge)) { in require_all_satisfied()
1255 i = dependency_satisfied(edge->ge_vertex, satbility); in require_all_satisfied()
1260 "require_all(%s): %s is unsatisfi%s.\n", groupv->gv_name, in require_all_satisfied()
1261 edge->ge_vertex->gv_name, i == 0 ? "ed" : "able"); in require_all_satisfied()
1266 if (i == -1) in require_all_satisfied()
1267 return (-1); in require_all_satisfied()
1282 graph_edge_t *edge; in require_any_satisfied() local
1286 if (uu_list_numnodes(groupv->gv_dependencies) == 0) in require_any_satisfied()
1291 for (edge = uu_list_first(groupv->gv_dependencies); in require_any_satisfied()
1292 edge != NULL; in require_any_satisfied()
1293 edge = uu_list_next(groupv->gv_dependencies, edge)) { in require_any_satisfied()
1294 s = dependency_satisfied(edge->ge_vertex, satbility); in require_any_satisfied()
1301 groupv->gv_name, edge->ge_vertex->gv_name, in require_any_satisfied()
1308 return ((!satbility || satisfiable) ? 0 : -1); in require_any_satisfied()
1323 graph_edge_t *edge; in optional_all_satisfied() local
1332 for (edge = uu_list_first(groupv->gv_dependencies); in optional_all_satisfied()
1333 edge != NULL; in optional_all_satisfied()
1334 edge = uu_list_next(groupv->gv_dependencies, edge)) { in optional_all_satisfied()
1335 v = edge->ge_vertex; in optional_all_satisfied()
1337 switch (v->gv_type) { in optional_all_satisfied()
1340 if ((v->gv_flags & GV_CONFIGURED) == 0) in optional_all_satisfied()
1343 if (v->gv_state == RESTARTER_STATE_MAINT) in optional_all_satisfied()
1347 if (v->gv_state == RESTARTER_STATE_OFFLINE || in optional_all_satisfied()
1348 v->gv_state == RESTARTER_STATE_DISABLED) { in optional_all_satisfied()
1354 if (i == -1) in optional_all_satisfied()
1378 __LINE__, v->gv_type); in optional_all_satisfied()
1387 "optional_all(%s): %s is unsatisfi%s.\n", groupv->gv_name, in optional_all_satisfied()
1388 v->gv_name, i == 0 ? "ed" : "able"); in optional_all_satisfied()
1392 if (i == -1) in optional_all_satisfied()
1393 return (-1); in optional_all_satisfied()
1404 * An exclude_all dependency is unsatisfied if any non-service element is
1412 (u)->gv_name, (v)->gv_name)
1418 graph_edge_t *edge, *e2; in exclude_all_satisfied() local
1421 for (edge = uu_list_first(groupv->gv_dependencies); in exclude_all_satisfied()
1422 edge != NULL; in exclude_all_satisfied()
1423 edge = uu_list_next(groupv->gv_dependencies, edge)) { in exclude_all_satisfied()
1424 v = edge->ge_vertex; in exclude_all_satisfied()
1426 switch (v->gv_type) { in exclude_all_satisfied()
1428 if ((v->gv_flags & GV_CONFIGURED) == 0) in exclude_all_satisfied()
1431 switch (v->gv_state) { in exclude_all_satisfied()
1435 return (v->gv_flags & GV_ENABLED ? -1 : 0); in exclude_all_satisfied()
1449 __FILE__, __LINE__, v->gv_state); in exclude_all_satisfied()
1462 return (-1); in exclude_all_satisfied()
1468 __LINE__, v->gv_type); in exclude_all_satisfied()
1474 if (uu_list_numnodes(v->gv_dependencies) == 0) in exclude_all_satisfied()
1477 for (e2 = uu_list_first(v->gv_dependencies); in exclude_all_satisfied()
1479 e2 = uu_list_next(v->gv_dependencies, e2)) { in exclude_all_satisfied()
1480 v2 = e2->ge_vertex; in exclude_all_satisfied()
1481 assert(v2->gv_type == GVT_INST); in exclude_all_satisfied()
1483 if ((v2->gv_flags & GV_CONFIGURED) == 0) in exclude_all_satisfied()
1486 switch (v2->gv_state) { in exclude_all_satisfied()
1490 return (v2->gv_flags & GV_ENABLED ? -1 : 0); in exclude_all_satisfied()
1504 __FILE__, __LINE__, v2->gv_type); in exclude_all_satisfied()
1517 * vertex. Return 1 if they are, 0 if they aren't, and -1 if they won't be
1523 assert(v->gv_type == GVT_INST); in instance_satisfied()
1524 assert(!inst_running(v)); in instance_satisfied()
1536 switch (v->gv_type) { in dependency_satisfied()
1538 if ((v->gv_flags & GV_CONFIGURED) == 0) { in dependency_satisfied()
1539 if (v->gv_flags & GV_DEATHROW) { in dependency_satisfied()
1546 return (-1); in dependency_satisfied()
1558 switch (v->gv_state) { in dependency_satisfied()
1561 if (v->gv_flags & GV_TODISABLE) in dependency_satisfied()
1562 return (-1); in dependency_satisfied()
1563 if (v->gv_flags & GV_TOOFFLINE) in dependency_satisfied()
1568 if (!satbility || v->gv_flags & GV_TODISABLE) in dependency_satisfied()
1569 return (satbility ? -1 : 0); in dependency_satisfied()
1570 return (instance_satisfied(v, satbility) != -1 ? in dependency_satisfied()
1571 0 : -1); in dependency_satisfied()
1574 if (!satbility || !(v->gv_flags & GV_ENABLED)) in dependency_satisfied()
1575 return (satbility ? -1 : 0); in dependency_satisfied()
1576 return (instance_satisfied(v, satbility) != -1 ? in dependency_satisfied()
1577 0 : -1); in dependency_satisfied()
1580 return (-1); in dependency_satisfied()
1588 __FILE__, __LINE__, v->gv_state); in dependency_satisfied()
1595 if (uu_list_numnodes(v->gv_dependencies) == 0) in dependency_satisfied()
1596 return (-1); in dependency_satisfied()
1601 return (file_ready(v) ? 1 : -1); in dependency_satisfied()
1609 v->gv_type); in dependency_satisfied()
1615 switch (v->gv_depgroup) { in dependency_satisfied()
1631 __LINE__, v->gv_depgroup); in dependency_satisfied()
1640 if (v->gv_state == RESTARTER_STATE_OFFLINE && in graph_start_if_satisfied()
1642 if (v->gv_start_f == NULL) in graph_start_if_satisfied()
1645 v->gv_start_f(v); in graph_start_if_satisfied()
1654 * instance transitions between offline -> online, or from !running ->
1660 * +-----+ optional_all +-----+ require_all +-----+
1661 * | A |--------------->| B |-------------->| C |
1662 * +-----+ +-----+ +-----+
1664 * offline -> maintenance
1684 if (v->gv_type == GVT_INST) in satbility_cb()
1715 switch (v->gv_type) { in propagate_start()
1729 if (v->gv_depgroup == DEPGRP_EXCLUDE_ALL) { in propagate_start()
1734 err = v->gv_restart; in propagate_start()
1752 v->gv_type); in propagate_start()
1765 * again once their dependencies have been re-satisfied.
1775 switch (v->gv_type) { in propagate_stop()
1801 if (v->gv_depgroup == DEPGRP_EXCLUDE_ALL) { in propagate_stop()
1807 if (err == RERR_NONE || err > v->gv_restart) in propagate_stop()
1816 v->gv_type); in propagate_stop()
1831 assert(v->gv_type == GVT_INST); in offline_vertex()
1840 if (scf_handle_decode_fmri(h, v->gv_name, NULL, NULL, scf_inst, NULL, in offline_vertex()
1854 uu_die("Can't decode FMRI %s: %s\n", v->gv_name, in offline_vertex()
1882 v->gv_name); in offline_vertex()
1901 * If admin is non-zero, this is an administrative request for change
1911 assert(MUTEX_HELD(&dgraph_lock)); in graph_enable_by_vertex()
1912 assert((vertex->gv_flags & GV_CONFIGURED)); in graph_enable_by_vertex()
1914 vertex->gv_flags = (vertex->gv_flags & ~GV_ENABLED) | in graph_enable_by_vertex()
1918 if (vertex->gv_state != RESTARTER_STATE_OFFLINE && in graph_enable_by_vertex()
1919 vertex->gv_state != RESTARTER_STATE_DEGRADED && in graph_enable_by_vertex()
1920 vertex->gv_state != RESTARTER_STATE_ONLINE) { in graph_enable_by_vertex()
1926 vertex->gv_flags &= ~GV_TOOFFLINE; in graph_enable_by_vertex()
1927 vertex->gv_flags &= ~GV_TODISABLE; in graph_enable_by_vertex()
1940 if (vertex->gv_state == RESTARTER_STATE_DISABLED) in graph_enable_by_vertex()
1964 vertex->gv_flags |= GV_TOOFFLINE; in graph_enable_by_vertex()
1967 vertex->gv_flags |= GV_TODISABLE; in graph_enable_by_vertex()
1969 log_framework(LOG_DEBUG, "Marking in-subtree vertices before " in graph_enable_by_vertex()
1970 "disabling %s.\n", vertex->gv_name); in graph_enable_by_vertex()
1973 r = uu_list_walk(vertex->gv_dependents, (uu_walk_fn_t *)mark_subtree, in graph_enable_by_vertex()
1975 assert(r == 0); in graph_enable_by_vertex()
1994 if (v->gv_type != GVT_INST || in graph_enable_by_vertex()
1995 (v->gv_flags & GV_CONFIGURED) == 0 || in graph_enable_by_vertex()
1996 (v->gv_flags & GV_ENABLED) == 0 || in graph_enable_by_vertex()
1997 (v->gv_flags & GV_TOOFFLINE) == 0) in graph_enable_by_vertex()
2000 if ((v->gv_state != RESTARTER_STATE_ONLINE) && in graph_enable_by_vertex()
2001 (v->gv_state != RESTARTER_STATE_DEGRADED)) { in graph_enable_by_vertex()
2012 log_framework(LOG_DEBUG, "Offlining in-subtree " in graph_enable_by_vertex()
2014 v->gv_name, vertex->gv_name); in graph_enable_by_vertex()
2031 * point to a -1-terminated array of ids which compose the path from v to
2043 assert(MUTEX_HELD(&dgraph_lock)); in graph_change_restarter()
2048 assert(err == EINVAL); in graph_change_restarter()
2055 if (v->gv_flags & GV_CONFIGURED) { in graph_change_restarter()
2056 if (v->gv_restarter_id == -1) { in graph_change_restarter()
2067 v->gv_restarter_id = -1; in graph_change_restarter()
2068 v->gv_restarter_channel = NULL; in graph_change_restarter()
2073 if (v->gv_flags & GV_CONFIGURED) { in graph_change_restarter()
2075 if (id != -1 && v->gv_restarter_id == id) { in graph_change_restarter()
2086 assert(err == 0 || err == EEXIST); in graph_change_restarter()
2088 if (rv->gv_delegate_initialized == 0) { in graph_change_restarter()
2089 if ((rv->gv_delegate_channel = restarter_protocol_init_delegate( in graph_change_restarter()
2090 rv->gv_name)) == NULL) in graph_change_restarter()
2092 rv->gv_delegate_initialized = 1; in graph_change_restarter()
2094 v->gv_restarter_id = rv->gv_id; in graph_change_restarter()
2095 v->gv_restarter_channel = rv->gv_delegate_channel; in graph_change_restarter()
2099 assert(err == ELOOP); in graph_change_restarter()
2105 if (!(rv->gv_flags & GV_CONFIGURED)) { in graph_change_restarter()
2108 err = libscf_fmri_get_instance(h, rv->gv_name, &inst); in graph_change_restarter()
2134 * The fmri doesn't specify an instance - translate in graph_change_restarter()
2152 * 0 - success
2153 * ENOENT - service indicated by fmri does not exist
2298 * Find or create a vertex for fmri and make info->v depend on it.
2300 * 0 - success
2301 * nonzero - failure
2303 * On failure, sets info->err to
2304 * EINVAL - fmri is invalid
2305 * fmri does not match info->type
2306 * ELOOP - Adding the dependency creates a circular dependency. *info->pathp
2308 * ECONNABORTED - repository connection was broken
2309 * ECONNRESET - succeeded, but repository connection was reset
2322 assert(MUTEX_HELD(&dgraph_lock)); in process_dependency_fmri()
2325 depgroup_v = info->v; in process_dependency_fmri()
2327 if (strncmp(fmri, "file:", sizeof ("file:") - 1) == 0) { in process_dependency_fmri()
2328 if (info->type != GVT_FILE) { in process_dependency_fmri()
2332 info->pg_name, info->inst_fmri); in process_dependency_fmri()
2333 return (info->err = EINVAL); in process_dependency_fmri()
2336 err = graph_insert_vertex_unconfigured(fmri, info->type, 0, in process_dependency_fmri()
2343 assert(v->gv_type == GVT_FILE); in process_dependency_fmri()
2351 if (info->type != GVT_INST) { in process_dependency_fmri()
2355 info->pg_name, info->inst_fmri); in process_dependency_fmri()
2356 return (info->err = EINVAL); in process_dependency_fmri()
2372 "\"%s\".\n", info->pg_name, info->inst_fmri, in process_dependency_fmri()
2374 return (info->err = EINVAL); in process_dependency_fmri()
2381 "service or instance.\n", info->pg_name, in process_dependency_fmri()
2382 info->inst_fmri); in process_dependency_fmri()
2383 return (info->err = EINVAL); in process_dependency_fmri()
2409 assert(v->gv_type == GVT_INST); in process_dependency_fmri()
2411 assert(v->gv_type == GVT_SVC); in process_dependency_fmri()
2420 info->err = graph_insert_dependency(depgroup_v, v, info->pathp); in process_dependency_fmri()
2421 switch (info->err) { in process_dependency_fmri()
2429 bad_error("graph_insert_dependency", info->err); in process_dependency_fmri()
2433 switch (v->gv_type) { in process_dependency_fmri()
2435 if ((v->gv_flags & GV_CONFIGURED) != 0) in process_dependency_fmri()
2438 inst = safe_scf_instance_create(info->h); in process_dependency_fmri()
2443 err = libscf_lookup_instance(v->gv_name, inst); in process_dependency_fmri()
2453 libscf_handle_rebind(info->h); in process_dependency_fmri()
2466 libscf_handle_rebind(info->h); in process_dependency_fmri()
2479 return (info->err = ECONNRESET); in process_dependency_fmri()
2483 (void) add_service(v->gv_name, info->h, &rebound); in process_dependency_fmri()
2485 return (info->err = ECONNRESET); in process_dependency_fmri()
2498 * Make info->v depend on a new GVT_GROUP node for this property group,
2501 * and set info->err to ECONNABORTED, EINVAL, or the error code returned by
2520 assert(MUTEX_HELD(&dgraph_lock)); in process_dependency_pg()
2532 return (info->err = ECONNABORTED); in process_dependency_pg()
2535 return (info->err = 0); in process_dependency_pg()
2551 pg_name, info->v->gv_name, scf_strerror(scf_error())); in process_dependency_pg()
2553 return (info->err = EINVAL); in process_dependency_pg()
2558 pg_name, info->v->gv_name); in process_dependency_pg()
2560 return (info->err = 0); in process_dependency_pg()
2563 fmri_sz = strlen(info->v->gv_name) + 1 + len + 1; in process_dependency_pg()
2566 (void) snprintf(fmri, fmri_sz, "%s>%s", info->v->gv_name, in process_dependency_pg()
2574 pg_name, info->v->gv_name); in process_dependency_pg()
2577 return (info->err = EINVAL); in process_dependency_pg()
2584 "\n", pg_name, info->v->gv_name); in process_dependency_pg()
2587 return (info->err = EINVAL); in process_dependency_pg()
2598 return (info->err = 0); in process_dependency_pg()
2602 return (info->err = ECONNABORTED); in process_dependency_pg()
2607 pg_name, info->v->gv_name, SCF_PROPERTY_ENTITIES); in process_dependency_pg()
2612 return (info->err = EINVAL); in process_dependency_pg()
2618 assert(err == 0); in process_dependency_pg()
2622 err = graph_insert_dependency(info->v, depgrp, info->pathp); in process_dependency_pg()
2624 assert(err == 0); in process_dependency_pg()
2628 linfo.inst_fmri = info->v->gv_name; in process_dependency_pg()
2632 linfo.pathp = info->pathp; in process_dependency_pg()
2642 return (info->err = linfo.err); in process_dependency_pg()
2646 return (info->err = err); in process_dependency_pg()
2649 return (info->err = 0); in process_dependency_pg()
2652 return (info->err = ECONNABORTED); in process_dependency_pg()
2664 * In the last case, *pathp will point to a -1-terminated array of ids which
2674 assert(MUTEX_HELD(&dgraph_lock)); in set_dependencies()
2679 * vertices is an exclusion-group). in set_dependencies()
2681 old_configured = v->gv_flags & GV_CONFIGURED; in set_dependencies()
2682 v->gv_flags |= GV_CONFIGURED; in set_dependencies()
2692 v->gv_flags &= ~GV_CONFIGURED; in set_dependencies()
2719 assert(MUTEX_HELD(&dgraph_lock)); in handle_cycle()
2724 "because it completes a dependency cycle (see svcs -xv for " in handle_cycle()
2737 assert(MUTEX_HELD(&dgraph_lock)); in vertex_ref()
2739 v->gv_refs++; in vertex_ref()
2752 assert(MUTEX_HELD(&dgraph_lock)); in vertex_unref()
2753 assert(v->gv_refs > 0); in vertex_unref()
2755 v->gv_refs--; in vertex_unref()
2772 graph_vertex_t *v = e->ge_vertex; in append_svcs_or_insts()
2776 switch (v->gv_type) { in append_svcs_or_insts()
2782 r = uu_list_walk(v->gv_dependencies, in append_svcs_or_insts()
2784 assert(r == 0); in append_svcs_or_insts()
2793 __LINE__, v->gv_type); in append_svcs_or_insts()
2799 new->ge_vertex = v; in append_svcs_or_insts()
2800 uu_list_node_init(new, &new->ge_link, graph_edge_pool); in append_svcs_or_insts()
2802 assert(r == 0); in append_svcs_or_insts()
2827 for (e = uu_list_first(v->gv_dependents); in should_be_in_subgraph()
2829 e = uu_list_next(v->gv_dependents, e)) { in should_be_in_subgraph()
2830 graph_vertex_t *dv = e->ge_vertex; in should_be_in_subgraph()
2832 if (!(dv->gv_flags & GV_INSUBGRAPH)) in should_be_in_subgraph()
2838 if (v->gv_type == GVT_INST && dv->gv_type == GVT_SVC) { in should_be_in_subgraph()
2843 for (ee = uu_list_first(dv->gv_dependents); in should_be_in_subgraph()
2845 ee = uu_list_next(dv->gv_dependents, ee)) { in should_be_in_subgraph()
2847 graph_vertex_t *ddv = e->ge_vertex; in should_be_in_subgraph()
2849 if (ddv->gv_type == GVT_GROUP && in should_be_in_subgraph()
2850 ddv->gv_depgroup == DEPGRP_EXCLUDE_ALL) in should_be_in_subgraph()
2853 if (ddv->gv_type == GVT_GROUP && in should_be_in_subgraph()
2854 ddv->gv_depgroup == DEPGRP_OPTIONAL_ALL && in should_be_in_subgraph()
2855 !(v->gv_flags & GV_ENBLD_NOOVR)) in should_be_in_subgraph()
2863 if (v->gv_type == GVT_INST && in should_be_in_subgraph()
2864 dv->gv_type == GVT_GROUP && in should_be_in_subgraph()
2865 dv->gv_depgroup == DEPGRP_OPTIONAL_ALL && in should_be_in_subgraph()
2866 !(v->gv_flags & GV_ENBLD_NOOVR)) in should_be_in_subgraph()
2870 if (dv->gv_type == GVT_GROUP && in should_be_in_subgraph()
2871 dv->gv_depgroup == DEPGRP_EXCLUDE_ALL) in should_be_in_subgraph()
2888 boolean_t old = (v->gv_flags & GV_INSUBGRAPH) != 0; in eval_subgraph()
2894 assert(milestone != NULL && milestone != MILESTONE_NONE); in eval_subgraph()
2902 "Removing %s from the subgraph.\n", v->gv_name); in eval_subgraph()
2904 v->gv_flags = (v->gv_flags & ~GV_INSUBGRAPH) | in eval_subgraph()
2907 if (v->gv_type == GVT_INST && (v->gv_flags & GV_CONFIGURED)) { in eval_subgraph()
2911 err = libscf_fmri_get_instance(h, v->gv_name, &inst); in eval_subgraph()
2958 v->gv_name, strerror(err)); in eval_subgraph()
2967 for (e = uu_list_first(v->gv_dependencies); in eval_subgraph()
2969 e = uu_list_next(v->gv_dependencies, e)) { in eval_subgraph()
2970 r = eval_subgraph(e->ge_vertex, h); in eval_subgraph()
2972 assert(r == ECONNABORTED); in eval_subgraph()
2999 assert(MUTEX_HELD(&dgraph_lock)); in refresh_vertex()
3000 assert(v->gv_type == GVT_INST); in refresh_vertex()
3002 log_framework(LOG_DEBUG, "Graph engine: Refreshing %s.\n", v->gv_name); in refresh_vertex()
3007 * make a list of them now for GV_INSUBGRAPH-flag evaluation in refresh_vertex()
3012 err = uu_list_walk(v->gv_dependencies, in refresh_vertex()
3014 assert(err == 0); in refresh_vertex()
3072 vv = e->ge_vertex; in refresh_vertex()
3079 for (e = uu_list_first(v->gv_dependencies); in refresh_vertex()
3081 e = uu_list_next(v->gv_dependencies, e)) { in refresh_vertex()
3082 if (eval_subgraph(e->ge_vertex, h) == in refresh_vertex()
3133 assert(MUTEX_HELD(&dgraph_lock)); in configure_vertex()
3134 assert(v->gv_type == GVT_INST); in configure_vertex()
3135 assert((v->gv_flags & GV_CONFIGURED) == 0); in configure_vertex()
3138 assert(should_be_in_subgraph(v) == in configure_vertex()
3139 ((v->gv_flags & GV_INSUBGRAPH) != 0)); in configure_vertex()
3144 * SCF_PROPERTY_DEATHROW boolean property in the non-persistent in configure_vertex()
3147 if ((v->gv_flags & GV_DEATHROW) || in configure_vertex()
3148 (is_fmri_in_deathrow(v->gv_name) == B_TRUE)) { in configure_vertex()
3149 if ((v->gv_flags & GV_DEATHROW) == 0) { in configure_vertex()
3153 * non-persistent repository for this instance fmri. in configure_vertex()
3155 v->gv_flags |= GV_DEATHROW; in configure_vertex()
3170 v->gv_name, strerror(err)); in configure_vertex()
3181 v->gv_name); in configure_vertex()
3196 * in a property group 'deathrow', -1 or 0 in all other cases. in configure_vertex()
3213 v->gv_flags |= GV_DEATHROW; in configure_vertex()
3218 log_framework(LOG_DEBUG, "Graph adding %s.\n", v->gv_name); in configure_vertex()
3317 * Make sure the enable-override is set properly before we in configure_vertex()
3321 !(v->gv_flags & GV_INSUBGRAPH)) { in configure_vertex()
3327 * the graph, and all of the new non-subgraph services in configure_vertex()
3343 v->gv_name, strerror(err)); in configure_vertex()
3354 assert(v->gv_flags & GV_INSUBGRAPH); in configure_vertex()
3374 err = libscf_get_basic_instance_data(h, inst, v->gv_name, &enabled, in configure_vertex()
3388 v->gv_name); in configure_vertex()
3396 if ((tset = libscf_get_stn_tset(inst)) == -1) { in configure_vertex()
3399 v->gv_name, scf_strerror(scf_error())); in configure_vertex()
3400 v->gv_stn_tset = 0; in configure_vertex()
3402 v->gv_stn_tset = tset; in configure_vertex()
3404 if (strcmp(v->gv_name, SCF_INSTANCE_GLOBAL) == 0) in configure_vertex()
3405 stn_global = v->gv_stn_tset; in configure_vertex()
3407 if (enabled == -1) { in configure_vertex()
3412 v->gv_flags = (v->gv_flags & ~GV_ENBLD_NOOVR) | in configure_vertex()
3415 if (enabled_ovr != -1) in configure_vertex()
3418 v->gv_state = RESTARTER_STATE_UNINIT; in configure_vertex()
3420 snap = libscf_get_or_make_running_snapshot(inst, v->gv_name, B_TRUE); in configure_vertex()
3435 assert(err == EINVAL || err == ELOOP); in configure_vertex()
3439 v->gv_name, restarter_fmri); in configure_vertex()
3442 handle_cycle(v->gv_name, path); in configure_vertex()
3454 assert(err == ECONNABORTED || err == ECANCELED); in configure_vertex()
3501 v->gv_state = RESTARTER_STATE_MAINT; in configure_vertex()
3510 assert(err == ECONNABORTED); in configure_vertex()
3515 v->gv_flags |= GV_CONFIGURED; in configure_vertex()
3529 * Despite its name, killall's role is to get select user processes-- in kill_user_procs()
3530 * basically those representing terminal-based logins-- to die. Victims in kill_user_procs()
3534 * kill -9. in kill_user_procs()
3541 * inverted by -v. 15 is reserved for dladmd. Yes, this is a in kill_user_procs()
3542 * kludge-- a better policy is needed. in kill_user_procs()
3548 (void) fork_with_timeout("/usr/bin/pkill -TERM -v -u 0,1,15", 1, 5); in kill_user_procs()
3549 (void) fork_with_timeout("/usr/bin/pkill -KILL -v -u 0,1,15", 1, 5); in kill_user_procs()
3575 (strncmp(vfs.f_basetype, "nfs", sizeof ("nfs") - 1) != 0)) in do_uadmin()
3576 fork_with_timeout("/usr/bin/pkill -x -u 0 dhcpagent", 0, 5); in do_uadmin()
3584 * Inside non-global zones, we don't bother, and it's better not to in do_uadmin()
3585 * anyway, since sync(2) can have system-wide impact. in do_uadmin()
3606 fork_with_timeout("/usr/sbin/bootadm -ea update_all", 0, 3600); in do_uadmin()
3611 * If somehow we got there on unsupported platform - in do_uadmin()
3624 "Falling back to regular reboot.\n"); in do_uadmin()
3633 fork_with_timeout("/sbin/umountall -l", 0, 5); in do_uadmin()
3648 * On systems using only ZFS, this call to lockfs -fa is a no-op. in do_uadmin()
3652 fork_with_timeout("/usr/sbin/lockfs -fa", 0, 30); in do_uadmin()
3677 " Shutdown took %lu seconds.", now - halting_time); in do_uadmin()
3704 assert(MUTEX_HELD(&dgraph_lock)); in can_come_up()
3707 * If we are booting to single user (boot -s), in can_come_up()
3709 * spawns sulogin after single-user is online (see specials.c). in can_come_up()
3728 if (!(up_svcs_p[i]->gv_flags & GV_CONFIGURED)) in can_come_up()
3731 switch (up_svcs_p[i]->gv_state) { in can_come_up()
3738 st->st_log_login_reached = 1; in can_come_up()
3744 if (instance_satisfied(up_svcs_p[i], B_TRUE) != -1) in can_come_up()
3748 up_svcs_p[i]->gv_name); in can_come_up()
3755 up_svcs_p[i]->gv_name, in can_come_up()
3756 instance_state_str[up_svcs_p[i]->gv_state]); in can_come_up()
3762 __FILE__, __LINE__, up_svcs_p[i]->gv_state); in can_come_up()
3769 * In the seed repository, console-login is unsatisfiable because in can_come_up()
3771 * to return false until manifest-import is online. in can_come_up()
3781 switch (manifest_import_p->gv_state) { in can_come_up()
3789 if (instance_satisfied(manifest_import_p, B_TRUE) == -1) in can_come_up()
3802 * 0 - success
3803 * EALREADY - sulogin is already running
3804 * EBUSY - console-login is running
3811 assert(MUTEX_HELD(&dgraph_lock)); in run_sulogin()
3833 if (v != NULL && v->gv_state == RESTARTER_STATE_OFFLINE) { in run_sulogin()
3834 if (v->gv_start_f == NULL) in run_sulogin()
3838 v->gv_start_f(v); in run_sulogin()
3849 * keeps sulogin from stepping on console-login's toes.
3859 assert(sulogin_thread_running); in sulogin_thread()
3895 assert(go_to_level1); in single_user_thread()
3913 assert(r == EALREADY || r == EBUSY); in single_user_thread()
3927 single_user_thread_count--; in single_user_thread()
3946 assert(r == ECONNABORTED); in single_user_thread()
4055 single_user_thread_count--; in single_user_thread()
4062 * Dependency graph operations API. These are handle-independent thread-safe
4099 assert(MUTEX_HELD(&dgraph_lock)); in dgraph_add_instance()
4105 assert(v->gv_type == GVT_INST); in dgraph_add_instance()
4107 if (v->gv_flags & GV_CONFIGURED) { in dgraph_add_instance()
4117 assert(err == EINVAL); in dgraph_add_instance()
4144 * deleted, or -1 if the instance's general property group is deleted or if
4204 if (v == NULL || !(v->gv_flags & GV_CONFIGURED)) { in dgraph_update_general()
4205 /* Will get the up-to-date properties. */ in dgraph_update_general()
4215 err = libscf_get_basic_instance_data(h, inst, v->gv_name, &enabled, in dgraph_update_general()
4217 if (err != 0 || enabled == -1) { in dgraph_update_general()
4226 return (-1); in dgraph_update_general()
4238 oldflags = v->gv_flags; in dgraph_update_general()
4239 v->gv_flags = (v->gv_flags & ~GV_ENBLD_NOOVR) | in dgraph_update_general()
4242 if (enabled_ovr != -1) in dgraph_update_general()
4246 * If GV_ENBLD_NOOVR has changed, then we need to re-evaluate the in dgraph_update_general()
4249 if (milestone > MILESTONE_NONE && v->gv_flags != oldflags) in dgraph_update_general()
4280 * 0 - success
4281 * ECONNABORTED - repository connection broken
4282 * ECANCELED - inst was deleted
4283 * EINVAL - inst is invalid (e.g., missing general/enabled)
4284 * -1 - libscf_snapshots_refresh() failed
4293 assert(MUTEX_HELD(&dgraph_lock)); in dgraph_refresh_instance()
4294 assert(v->gv_type == GVT_INST); in dgraph_refresh_instance()
4298 v->gv_name, &enabled, NULL, NULL); in dgraph_refresh_instance()
4310 v->gv_name); in dgraph_refresh_instance()
4317 if ((tset = libscf_get_stn_tset(inst)) == -1) { in dgraph_refresh_instance()
4320 v->gv_name, scf_strerror(scf_error())); in dgraph_refresh_instance()
4323 v->gv_stn_tset = tset; in dgraph_refresh_instance()
4324 if (strcmp(v->gv_name, SCF_INSTANCE_GLOBAL) == 0) in dgraph_refresh_instance()
4327 if (enabled == -1) in dgraph_refresh_instance()
4330 r = libscf_snapshots_refresh(inst, v->gv_name); in dgraph_refresh_instance()
4332 if (r != -1) in dgraph_refresh_instance()
4346 * Returns true only if none of this service's dependents are 'up' -- online
4356 assert(MUTEX_HELD(&dgraph_lock)); in insubtree_dependents_down()
4358 for (e = uu_list_first(v->gv_dependents); e != NULL; in insubtree_dependents_down()
4359 e = uu_list_next(v->gv_dependents, e)) { in insubtree_dependents_down()
4360 vv = e->ge_vertex; in insubtree_dependents_down()
4361 if (vv->gv_type == GVT_INST) { in insubtree_dependents_down()
4362 if ((vv->gv_flags & GV_CONFIGURED) == 0) in insubtree_dependents_down()
4365 if ((vv->gv_flags & GV_TOOFFLINE) == 0) in insubtree_dependents_down()
4368 if ((vv->gv_state == RESTARTER_STATE_ONLINE) || in insubtree_dependents_down()
4369 (vv->gv_state == RESTARTER_STATE_DEGRADED)) in insubtree_dependents_down()
4393 * Returns true only if none of this service's dependents are 'up' -- online,
4402 assert(MUTEX_HELD(&dgraph_lock)); in is_nonsubgraph_leaf()
4404 for (e = uu_list_first(v->gv_dependents); in is_nonsubgraph_leaf()
4406 e = uu_list_next(v->gv_dependents, e)) { in is_nonsubgraph_leaf()
4408 vv = e->ge_vertex; in is_nonsubgraph_leaf()
4409 if (vv->gv_type == GVT_INST) { in is_nonsubgraph_leaf()
4410 if ((vv->gv_flags & GV_CONFIGURED) == 0) in is_nonsubgraph_leaf()
4413 if (vv->gv_flags & GV_INSUBGRAPH) in is_nonsubgraph_leaf()
4416 if (up_state(vv->gv_state)) in is_nonsubgraph_leaf()
4429 if (vv->gv_type == GVT_GROUP && in is_nonsubgraph_leaf()
4430 vv->gv_depgroup == DEPGRP_EXCLUDE_ALL) in is_nonsubgraph_leaf()
4466 log_error(LOG_WARNING, emsg, v->gv_name, buf); in disable_service_temporarily()
4472 r = scf_handle_decode_fmri(h, v->gv_name, NULL, NULL, inst, in disable_service_temporarily()
4477 log_error(LOG_WARNING, emsg, v->gv_name, emsg_cbroken); in disable_service_temporarily()
4505 log_error(LOG_WARNING, emsg, v->gv_name, emsg_cbroken); in disable_service_temporarily()
4510 log_error(LOG_WARNING, emsg, v->gv_name, in disable_service_temporarily()
4516 log_error(LOG_WARNING, emsg, v->gv_name, in disable_service_temporarily()
4517 "the repository is read-only"); in disable_service_temporarily()
4535 assert(MUTEX_HELD(&dgraph_lock)); in offline_subtree_leaves()
4538 if (v->gv_type != GVT_INST) { in offline_subtree_leaves()
4547 if ((v->gv_flags & GV_TOOFFLINE) == 0) in offline_subtree_leaves()
4551 if (!up_state(v->gv_state)) { in offline_subtree_leaves()
4558 if (v->gv_flags & GV_TODISABLE) in offline_subtree_leaves()
4581 assert(MUTEX_HELD(&dgraph_lock)); in disable_nonsubgraph_leaves()
4590 if (v->gv_type == GVT_GROUP && v->gv_depgroup == DEPGRP_EXCLUDE_ALL) in disable_nonsubgraph_leaves()
4594 if (v->gv_type != GVT_INST) in disable_nonsubgraph_leaves()
4597 if ((v->gv_flags & GV_CONFIGURED) == 0) in disable_nonsubgraph_leaves()
4608 if (v->gv_flags & GV_INSUBGRAPH) in disable_nonsubgraph_leaves()
4612 if (!up_state(v->gv_state)) in disable_nonsubgraph_leaves()
4616 if ((v->gv_flags & GV_ENABLED) == 0) in disable_nonsubgraph_leaves()
4651 return (-1); in stn_restarter_state()
4656 * Not incremented atomically - indicative only
4671 restarter_instance_state_t new_state = v->gv_state; in dgraph_state_transition_notify()
4678 if ((from = stn_restarter_state(old_state)) == -1 || in dgraph_state_transition_notify()
4679 (to = stn_restarter_state(new_state)) == -1) { in dgraph_state_transition_notify()
4704 } else if (stn_transition & v->gv_stn_tset) { in dgraph_state_transition_notify()
4731 nvlist_add_string(attr, "fmri", v->gv_name) != 0 || in dgraph_state_transition_notify()
4732 nvlist_add_uint32(attr, "reason-version", in dgraph_state_transition_notify()
4733 restarter_str_version()) || nvlist_add_string(attr, "reason-short", in dgraph_state_transition_notify()
4735 nvlist_add_string(attr, "reason-long", in dgraph_state_transition_notify()
4740 "event: %s\n", v->gv_name, strerror(errno)); in dgraph_state_transition_notify()
4745 if (fmev_rspublish_nvl(FMEV_RULESET_SMF, "state-transition", in dgraph_state_transition_notify()
4749 v->gv_name, fmev_strerror(fmev_errno)); in dgraph_state_transition_notify()
4773 restarter_instance_state_t state = states->ps_state; in dgraph_set_instance_state()
4774 restarter_error_t serr = states->ps_err; in dgraph_set_instance_state()
4784 assert(v->gv_type == GVT_INST); in dgraph_set_instance_state()
4800 log_framework(LOG_DEBUG, "Graph noting %s %s -> %s.\n", v->gv_name, in dgraph_set_instance_state()
4801 instance_state_str[v->gv_state], instance_state_str[state]); in dgraph_set_instance_state()
4803 old_state = v->gv_state; in dgraph_set_instance_state()
4804 v->gv_state = state; in dgraph_set_instance_state()
4806 v->gv_reason = states->ps_reason; in dgraph_set_instance_state()
4808 if (err == 0 && v->gv_state != old_state) { in dgraph_set_instance_state()
4809 dgraph_state_transition_notify(v, old_state, states->ps_reason); in dgraph_set_instance_state()
4829 assert(v->gv_type == GVT_INST); in vertex_subgraph_dependencies_shutdown()
4840 if (v->gv_flags & GV_INSUBGRAPH) in vertex_subgraph_dependencies_shutdown()
4844 * Update non_subgraph_svcs. It is the number of non-subgraph in vertex_subgraph_dependencies_shutdown()
4849 now_up = up_state(v->gv_state); in vertex_subgraph_dependencies_shutdown()
4854 --non_subgraph_svcs; in vertex_subgraph_dependencies_shutdown()
4857 if (halting != -1) { in vertex_subgraph_dependencies_shutdown()
4868 if ((v->gv_flags & GV_ENABLED) && is_nonsubgraph_leaf(v)) { in vertex_subgraph_dependencies_shutdown()
4907 assert(MUTEX_HELD(&dgraph_lock)); in graph_transition_sulogin()
4909 if (state != old_state && st->st_load_complete && in graph_transition_sulogin()
4911 halting == -1) { in graph_transition_sulogin()
4925 * necessary for cases when non-direct dependents may be effected but direct
4929 * PROPAGATE_SAT should be used whenever a non-running service moves into
4980 if (v->gv_flags & GV_CONFIGURED) in dgraph_remove_instance()
4991 err = uu_list_walk(v->gv_dependencies, in dgraph_remove_instance()
4993 assert(err == 0); in dgraph_remove_instance()
5001 * event -- deletion isn't a fault, just a normal stop. This gives in dgraph_remove_instance()
5008 v->gv_flags &= ~GV_CONFIGURED; in dgraph_remove_instance()
5009 v->gv_flags &= ~GV_DEATHROW; in dgraph_remove_instance()
5015 * If there are no (non-service) dependents, the vertex can be in dgraph_remove_instance()
5018 if (v != milestone && v->gv_refs == 0 && in dgraph_remove_instance()
5019 uu_list_numnodes(v->gv_dependents) == 1) in dgraph_remove_instance()
5026 v = e->ge_vertex; in dgraph_remove_instance()
5050 assert(MUTEX_HELD(&dgraph_lock)); in target_milestone_as_runlevel()
5057 if (strcmp(milestone->gv_name, multi_user_fmri) == 0) in target_milestone_as_runlevel()
5059 else if (strcmp(milestone->gv_name, single_user_fmri) == 0) in target_milestone_as_runlevel()
5061 else if (strcmp(milestone->gv_name, multi_user_svr_fmri) == 0) in target_milestone_as_runlevel()
5066 __FILE__, __LINE__, milestone->gv_name); in target_milestone_as_runlevel()
5093 assert(MUTEX_HELD(&dgraph_lock)); in signal_init()
5144 assert(MUTEX_HELD(&dgraph_lock)); in graph_runlevel_changed()
5171 * Move to a backwards-compatible runlevel by executing the appropriate
5175 * 0 - success
5176 * ECONNRESET - success, but handle was reset
5177 * ECONNABORTED - repository connection broken
5178 * ECANCELED - pg was deleted
5292 * Make sure stop rc scripts see the new settings via who -r. in dgraph_set_runlevel()
5419 v = e->ge_vertex; in mark_subtree()
5422 if (v->gv_flags & GV_TOOFFLINE) in mark_subtree()
5425 switch (v->gv_type) { in mark_subtree()
5431 v->gv_flags |= GV_TOOFFLINE; in mark_subtree()
5432 log_framework(LOG_DEBUG, "%s added to subtree\n", v->gv_name); in mark_subtree()
5444 r = uu_list_walk(v->gv_dependents, (uu_walk_fn_t *)mark_subtree, arg, in mark_subtree()
5446 assert(r == 0); in mark_subtree()
5457 v = e->ge_vertex; in mark_subgraph()
5460 if (v->gv_flags & GV_INSUBGRAPH) in mark_subgraph()
5466 if (v->gv_type == GVT_GROUP && v->gv_depgroup == DEPGRP_OPTIONAL_ALL) { in mark_subgraph()
5473 if (optional && (v->gv_type == GVT_INST) && in mark_subgraph()
5474 (!(v->gv_flags & GV_ENBLD_NOOVR))) in mark_subgraph()
5477 v->gv_flags |= GV_INSUBGRAPH; in mark_subgraph()
5480 if (v->gv_type == GVT_GROUP && v->gv_depgroup == DEPGRP_EXCLUDE_ALL) in mark_subgraph()
5483 r = uu_list_walk(v->gv_dependencies, (uu_walk_fn_t *)mark_subgraph, in mark_subgraph()
5485 assert(r == 0); in mark_subgraph()
5499 * The services should be brought down in reverse-dependency order, so we
5500 * can't do it all at once here. We initiate by override-disabling the leaves
5501 * of the dependency tree -- those services which are up but have no
5503 * vertex_subgraph_dependencies_shutdown() will override-disable the newly
5512 * In case we're coming up, we also remove any enable-overrides for the
5521 * 0 - success
5522 * ECONNRESET - success, but handle was rebound
5523 * EINVAL - fmri is invalid (error is logged)
5524 * EALREADY - the milestone is already set to fmri
5525 * ENOENT - a configured vertex does not exist for fmri (an error is logged)
5576 strcmp(cfmri, milestone->gv_name) == 0) { in dgraph_set_milestone()
5586 if (nm == NULL || !(nm->gv_flags & GV_CONFIGURED)) { in dgraph_set_milestone()
5614 v->gv_flags &= ~GV_INSUBGRAPH; in dgraph_set_milestone()
5618 milestone->gv_flags |= GV_INSUBGRAPH; in dgraph_set_milestone()
5620 r = uu_list_walk(milestone->gv_dependencies, in dgraph_set_milestone()
5622 assert(r == 0); in dgraph_set_milestone()
5625 /* Un-override services in the subgraph & override-disable the rest. */ in dgraph_set_milestone()
5633 if (v->gv_type != GVT_INST || in dgraph_set_milestone()
5634 (v->gv_flags & GV_CONFIGURED) == 0) in dgraph_set_milestone()
5638 r = scf_handle_decode_fmri(h, v->gv_name, NULL, NULL, inst, in dgraph_set_milestone()
5660 if (isall || (v->gv_flags & GV_INSUBGRAPH)) { in dgraph_set_milestone()
5664 assert(isnone || (v->gv_flags & GV_INSUBGRAPH) == 0); in dgraph_set_milestone()
5672 if (up_state(v->gv_state)) in dgraph_set_milestone()
5676 if ((v->gv_flags & GV_ENABLED) == 0) in dgraph_set_milestone()
5700 v->gv_name, strerror(r)); in dgraph_set_milestone()
5708 if (halting != -1) { in dgraph_set_milestone()
5737 switch (e->gpe_type) { in handle_graph_update_event()
5744 protocol_states_t *states = e->gpe_data; in handle_graph_update_event()
5746 switch (r = dgraph_set_instance_state(h, e->gpe_inst, states)) { in handle_graph_update_event()
5771 e->gpe_type); in handle_graph_update_event()
5797 MUTEX_LOCK(&gu->gu_lock); in graph_event_thread()
5799 while (gu->gu_wakeup == 0) in graph_event_thread()
5800 (void) pthread_cond_wait(&gu->gu_cv, &gu->gu_lock); in graph_event_thread()
5802 gu->gu_wakeup = 0; in graph_event_thread()
5805 MUTEX_LOCK(&e->gpe_lock); in graph_event_thread()
5806 MUTEX_UNLOCK(&gu->gu_lock); in graph_event_thread()
5817 MUTEX_LOCK(&gu->gu_lock); in graph_event_thread()
5820 MUTEX_UNLOCK(&gu->gu_lock); in graph_event_thread()
5836 * If -m milestone= was specified, we want to set options_ovr/milestone in set_initial_milestone()
5849 if (st->st_subgraph != NULL && in set_initial_milestone()
5850 st->st_subgraph[0] != '\0') { in set_initial_milestone()
5851 sz = strlcpy(fmri, st->st_subgraph, in set_initial_milestone()
5853 assert(sz < max_scf_fmri_size); in set_initial_milestone()
5866 if (st->st_subgraph != NULL && st->st_subgraph[0] != '\0') { in set_initial_milestone()
5871 sz = strlcpy(fmri, st->st_subgraph, max_scf_fmri_size); in set_initial_milestone()
5872 assert(sz < max_scf_fmri_size); in set_initial_milestone()
5894 sz = strlcpy(fmri, st->st_subgraph, in set_initial_milestone()
5896 assert(sz < max_scf_fmri_size); in set_initial_milestone()
5921 sz = strlcpy(fmri, st->st_subgraph, in set_initial_milestone()
5923 assert(sz < max_scf_fmri_size); in set_initial_milestone()
6005 assert(r == 0); in set_initial_milestone()
6146 if (st->st_initial) in graph_thread()
6152 assert(err == 0); in graph_thread()
6157 if (!st->st_initial) in graph_thread()
6160 MUTEX_LOCK(&st->st_load_lock); in graph_thread()
6161 st->st_load_complete = 1; in graph_thread()
6162 (void) pthread_cond_broadcast(&st->st_load_cv); in graph_thread()
6163 MUTEX_UNLOCK(&st->st_load_lock); in graph_thread()
6172 halting == -1) { in graph_thread()
6180 (void) pthread_mutex_lock(&gu->gu_freeze_lock); in graph_thread()
6184 (void) pthread_cond_wait(&gu->gu_freeze_cv, in graph_thread()
6185 &gu->gu_freeze_lock); in graph_thread()
6193 * lowest non-zero timestamp and return its index. If there are no
6194 * non-zero elements, return -1.
6200 int i = 0, smallest = -1; in next_action()
6213 return (-1); in next_action()
6225 * per-instance property group, with each action being a single property
6348 assert(r == 0); in process_actions()
6377 while ((a = next_action(action_ts, NACTIONS)) != -1) { in process_actions()
6388 case -1: in process_actions()
6436 * 0 - success
6437 * ECONNRESET - success, but repository handle rebound
6438 * ECONNABORTED - repository connection broken
6476 case -1: in process_pg_event()
6826 * pre-allocated scratch space. in repository_event_thread()
6887 assert(err == 0); in graph_engine_start()