6440500 no login prompt (hang) when filesystem/local fails
authorlianep
Mon, 10 Jul 2006 18:12:06 -0700
changeset 2339 73c7b85b6be0
parent 2338 011565c76d7c
child 2340 03a76252b501
6440500 no login prompt (hang) when filesystem/local fails
usr/src/cmd/svc/startd/graph.c
usr/src/cmd/svc/startd/startd.h
usr/src/cmd/svc/startd/transition.c
--- 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();
 	}