--- a/usr/src/cmd/svc/startd/graph.c Mon Jul 10 17:57:49 2006 -0700
+++ b/usr/src/cmd/svc/startd/graph.c Mon Jul 10 18:12:06 2006 -0700
@@ -1590,7 +1590,7 @@
* instance transitions between offline -> online, or from !running ->
* maintenance, as well as when an instance is removed from the graph.
*
- * We have to walk the all dependents, since optional_all dependencies several
+ * We have to walk all the dependents, since optional_all dependencies several
* levels up could become (un)satisfied, instead of unsatisfiable. For example,
*
* +-----+ optional_all +-----+ require_all +-----+
@@ -4006,7 +4006,7 @@
old_state = v->gv_state;
v->gv_state = state;
- err = gt_transition(h, v, serr, old_state, state);
+ err = gt_transition(h, v, serr, old_state);
MUTEX_UNLOCK(&dgraph_lock);
return (err);
@@ -4068,31 +4068,34 @@
}
/*
- * Propagate a start, stop or maintenance event. Use the
- * RESTARTER_EVENT_TYPE_START, RESTARTER_EVENT_TYPE_STOP, and
- * RESTARTER_EVENT_TYPE_ADMIN_MAINT_ON respectively to represent those
- * events.
+ * Propagate a start, stop event, or a satisfiability event.
*
- * For maintenance, we need to propagate_satbility() as well to
- * take care of walking further down the graph than just the direct
- * dependents.
+ * PROPAGATE_START and PROPAGATE_STOP simply propagate the transition event
+ * to direct dependents. PROPAGATE_SAT propagates a start then walks the
+ * full dependent graph to check for newly satisfied nodes. This is
+ * necessary for cases when non-direct dependents may be effected but direct
+ * dependents may not (e.g. for optional_all evaluations, see the
+ * propagate_satbility() comments).
+ *
+ * PROPAGATE_SAT should be used whenever a non-running service moves into
+ * a state which can satisfy optional dependencies, like disabled or
+ * maintenance.
*/
void
-graph_transition_propagate(graph_vertex_t *v, restarter_event_type_t propagate,
+graph_transition_propagate(graph_vertex_t *v, propagate_event_t type,
restarter_error_t rerr)
{
- if (propagate == RESTARTER_EVENT_TYPE_STOP) {
+ if (type == PROPAGATE_STOP) {
graph_walk_dependents(v, propagate_stop, (void *)rerr);
- } else if (propagate == RESTARTER_EVENT_TYPE_START ||
- propagate == RESTARTER_EVENT_TYPE_ADMIN_MAINT_ON) {
+ } else if (type == PROPAGATE_START || type == PROPAGATE_SAT) {
graph_walk_dependents(v, propagate_start, NULL);
- if (propagate == RESTARTER_EVENT_TYPE_ADMIN_MAINT_ON)
+ if (type == PROPAGATE_SAT)
propagate_satbility(v);
} else {
#ifndef NDEBUG
- uu_warn("%s:%d: Unexpected propagate value %d.\n", __FILE__,
- __LINE__, propagate);
+ uu_warn("%s:%d: Unexpected type value %d.\n", __FILE__,
+ __LINE__, type);
#endif
abort();
}
--- a/usr/src/cmd/svc/startd/startd.h Mon Jul 10 17:57:49 2006 -0700
+++ b/usr/src/cmd/svc/startd/startd.h Mon Jul 10 18:12:06 2006 -0700
@@ -274,6 +274,12 @@
METHOD_RESTART_OTHER
} method_restart_t;
+typedef enum {
+ PROPAGATE_START,
+ PROPAGATE_STOP,
+ PROPAGATE_SAT
+} propagate_event_t;
+
/*
* Graph representation.
*/
@@ -587,7 +593,7 @@
graph_vertex_t *v, int was_running);
void graph_transition_sulogin(restarter_instance_state_t,
restarter_instance_state_t);
-void graph_transition_propagate(graph_vertex_t *, restarter_event_type_t,
+void graph_transition_propagate(graph_vertex_t *, propagate_event_t,
restarter_error_t);
/* libscf.c - common */
@@ -717,7 +723,7 @@
/* transition.c */
int gt_transition(scf_handle_t *, graph_vertex_t *, restarter_error_t,
- restarter_instance_state_t, restarter_instance_state_t);
+ restarter_instance_state_t);
/* utmpx.c */
void utmpx_init(void);
--- a/usr/src/cmd/svc/startd/transition.c Mon Jul 10 17:57:49 2006 -0700
+++ b/usr/src/cmd/svc/startd/transition.c Mon Jul 10 18:12:06 2006 -0700
@@ -96,7 +96,7 @@
log_framework(LOG_DEBUG, "Propagating stop of %s.\n",
v->gv_name);
- graph_transition_propagate(v, RESTARTER_EVENT_TYPE_STOP, rerr);
+ graph_transition_propagate(v, PROPAGATE_STOP, rerr);
}
graph_transition_sulogin(RESTARTER_STATE_UNINIT, old_state);
@@ -109,16 +109,22 @@
{
vertex_subgraph_dependencies_shutdown(h, v, gt_running(old_state));
+ /*
+ * If the service was running, propagate a stop event. If the
+ * service was not running the maintenance transition may satisfy
+ * optional dependencies and should be propagated to determine
+ * whether new dependents are satisfiable.
+ */
if (gt_running(old_state)) {
- log_framework(LOG_DEBUG, "Propagating stop of %s.\n",
- v->gv_name);
+ log_framework(LOG_DEBUG, "Propagating maintenance (stop) of "
+ "%s.\n", v->gv_name);
- graph_transition_propagate(v, RESTARTER_EVENT_TYPE_STOP, rerr);
- } else if (v->gv_state == RESTARTER_STATE_MAINT) {
+ graph_transition_propagate(v, PROPAGATE_STOP, rerr);
+ } else {
log_framework(LOG_DEBUG, "Propagating maintenance of %s.\n",
v->gv_name);
- graph_transition_propagate(v, RESTARTER_EVENT_TYPE_START, rerr);
+ graph_transition_propagate(v, PROPAGATE_SAT, rerr);
}
graph_transition_sulogin(RESTARTER_STATE_MAINT, old_state);
@@ -147,7 +153,7 @@
log_framework(LOG_DEBUG, "Propagating stop of %s.\n",
v->gv_name);
- graph_transition_propagate(v, RESTARTER_EVENT_TYPE_STOP, rerr);
+ graph_transition_propagate(v, PROPAGATE_STOP, rerr);
}
graph_transition_sulogin(RESTARTER_STATE_OFFLINE, old_state);
@@ -172,21 +178,22 @@
}
/*
- * If the service was running, propagate this as a stop.
- * Otherwise, we treat other transitions as a start propagate,
- * since they can satisfy optional_all dependencies.
+ * If the service was running, propagate this as a stop. If the
+ * service was not running the disabled transition may satisfy
+ * optional dependencies and should be propagated to determine
+ * whether new dependents are satisfiable.
*/
if (gt_running(old_state)) {
log_framework(LOG_DEBUG, "Propagating stop of %s.\n",
v->gv_name);
- graph_transition_propagate(v, RESTARTER_EVENT_TYPE_STOP, rerr);
+ graph_transition_propagate(v, PROPAGATE_STOP, rerr);
- } else if (v->gv_state == RESTARTER_STATE_DISABLED) {
+ } else {
log_framework(LOG_DEBUG, "Propagating disable of %s.\n",
v->gv_name);
- graph_transition_propagate(v, RESTARTER_EVENT_TYPE_START, rerr);
+ graph_transition_propagate(v, PROPAGATE_SAT, rerr);
}
graph_transition_sulogin(RESTARTER_STATE_DISABLED, old_state);
@@ -239,15 +246,14 @@
log_framework(LOG_DEBUG, "Propagating start of %s.\n",
v->gv_name);
- graph_transition_propagate(v,
- RESTARTER_EVENT_TYPE_ADMIN_MAINT_ON, rerr);
+ graph_transition_propagate(v, PROPAGATE_START, rerr);
} else if (rerr == RERR_REFRESH) {
/* For refresh we'll get a message sans state change */
log_framework(LOG_DEBUG, "Propagating refresh of %s.\n",
v->gv_name);
- graph_transition_propagate(v, RESTARTER_EVENT_TYPE_STOP, rerr);
+ graph_transition_propagate(v, PROPAGATE_STOP, rerr);
}
return (0);
@@ -286,10 +292,13 @@
* state machine. It can return:
* 0 success
* ECONNABORTED repository connection aborted
+ *
+ * v->gv_state should be set to the state we're transitioning to before
+ * calling this function.
*/
int
gt_transition(scf_handle_t *h, graph_vertex_t *v, restarter_error_t rerr,
- restarter_instance_state_t old_state, restarter_instance_state_t new_state)
+ restarter_instance_state_t old_state)
{
int err = 0;
@@ -302,7 +311,7 @@
/*
* Now call the appropriate gt_enter function for the new state.
*/
- switch (new_state) {
+ switch (v->gv_state) {
case RESTARTER_STATE_UNINIT:
err = gt_enter_uninit(h, v, old_state, rerr);
break;
@@ -328,10 +337,10 @@
break;
default:
- /* Shouldn't have been passed an invalid state. */
+ /* Shouldn't be in an invalid state. */
#ifndef NDEBUG
uu_warn("%s:%d: Uncaught case %d.\n", __FILE__, __LINE__,
- new_state);
+ v->gv_state);
#endif
abort();
}