Print this page
7246 SMF stops dependents in the wrong order
7267 SMF is fast and loose with optional dependencies

@@ -20,10 +20,11 @@
  */
 
 /*
  * Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved.
  * Copyright (c) 2015, Syneto S.R.L. All rights reserved.
+ * Copyright 2016 RackTop Systems.
  */
 
 /*
  * graph.c - master restarter graph engine
  *

@@ -205,11 +206,10 @@
         (state) == RESTARTER_STATE_DEGRADED || \
         (state) == RESTARTER_STATE_OFFLINE)
 
 #define is_depgrp_bypassed(v) ((v->gv_type == GVT_GROUP) && \
         ((v->gv_depgroup == DEPGRP_EXCLUDE_ALL) || \
-        (v->gv_depgroup == DEPGRP_OPTIONAL_ALL) || \
         (v->gv_restart < RERR_RESTART)))
 
 static uu_list_pool_t *graph_edge_pool, *graph_vertex_pool;
 static uu_list_t *dgraph;
 static pthread_mutex_t dgraph_lock;

@@ -303,11 +303,10 @@
 static char target_milestone_as_runlevel(void);
 static void graph_runlevel_changed(char rl, int online);
 static int dgraph_set_milestone(const char *, scf_handle_t *, boolean_t);
 static boolean_t should_be_in_subgraph(graph_vertex_t *v);
 static int mark_subtree(graph_edge_t *, void *);
-static boolean_t insubtree_dependents_down(graph_vertex_t *);
 
 /*
  * graph_vertex_compare()
  *      This function can compare either int *id or * graph_vertex_t *gv
  *      values, as the vertex id is always the first element of a

@@ -1326,21 +1325,17 @@
             edge = uu_list_next(groupv->gv_dependencies, edge)) {
                 v = edge->ge_vertex;
 
                 switch (v->gv_type) {
                 case GVT_INST:
-                        /* Skip missing or disabled instances */
-                        if ((v->gv_flags & (GV_CONFIGURED | GV_ENABLED)) !=
-                            (GV_CONFIGURED | GV_ENABLED))
+                        /* Skip missing instances */
+                        if ((v->gv_flags & GV_CONFIGURED) == 0)
                                 continue;
 
                         if (v->gv_state == RESTARTER_STATE_MAINT)
                                 continue;
 
-                        if (v->gv_flags & GV_TOOFFLINE)
-                                continue;
-
                         any_qualified = B_TRUE;
                         if (v->gv_state == RESTARTER_STATE_OFFLINE) {
                                 /*
                                  * For offline dependencies, treat unsatisfiable
                                  * as satisfied.

@@ -1352,11 +1347,11 @@
                                 /*
                                  * The service is enabled, but hasn't
                                  * transitioned out of disabled yet.  Treat it
                                  * as unsatisfied (not unsatisfiable).
                                  */
-                                i = 0;
+                                i = v->gv_flags & GV_ENABLED ? 0 : 1;
                         } else {
                                 i = dependency_satisfied(v, satbility);
                         }
                         break;
 

@@ -1381,34 +1376,28 @@
                             e2 != NULL;
                             e2 = uu_list_next(v->gv_dependencies, e2)) {
                                 v2 = e2->ge_vertex;
                                 assert(v2->gv_type == GVT_INST);
 
-                                if ((v2->gv_flags &
-                                    (GV_CONFIGURED | GV_ENABLED)) !=
-                                    (GV_CONFIGURED | GV_ENABLED))
+                                if ((v2->gv_flags & GV_CONFIGURED) == 0)
                                         continue;
 
                                 if (v2->gv_state == RESTARTER_STATE_MAINT)
                                         continue;
 
-                                if (v2->gv_flags & GV_TOOFFLINE)
-                                        continue;
-
                                 svc_any_qualified = B_TRUE;
-
                                 if (v2->gv_state == RESTARTER_STATE_OFFLINE) {
                                         /*
                                          * For offline dependencies, treat
                                          * unsatisfiable as satisfied.
                                          */
                                         i = dependency_satisfied(v2, B_TRUE);
                                         if (i == -1)
                                                 i = 1;
                                 } else if (v2->gv_state ==
                                     RESTARTER_STATE_DISABLED) {
-                                        i = 0;
+                                        i = v2->gv_flags & GV_ENABLED ? 0 : 1;
                                 } else {
                                         i = dependency_satisfied(v2, satbility);
                                 }
 
                                 if (i == 1) {

@@ -4373,11 +4362,11 @@
 /*
  * Returns true only if none of this service's dependents are 'up' -- online
  * or degraded (offline is considered down in this situation). This function
  * is somehow similar to is_nonsubgraph_leaf() but works on subtrees.
  */
-static boolean_t
+boolean_t
 insubtree_dependents_down(graph_vertex_t *v)
 {
         graph_vertex_t *vv;
         graph_edge_t *e;
 

@@ -4389,20 +4378,20 @@
                 if (vv->gv_type == GVT_INST) {
                         if ((vv->gv_flags & GV_CONFIGURED) == 0)
                                 continue;
 
                         if ((vv->gv_flags & GV_TOOFFLINE) == 0)
-                                continue;
+                                return (B_FALSE);
 
                         if ((vv->gv_state == RESTARTER_STATE_ONLINE) ||
                             (vv->gv_state == RESTARTER_STATE_DEGRADED))
                                 return (B_FALSE);
                 } else {
                         /*
-                         * Skip all excluded and optional_all dependencies
-                         * and decide whether to offline the service based
-                         * on restart_on attribute.
+                         * Skip all excluded dependencies and decide whether
+                         * decide whether to offline the service based on the
+                         * restart_on attribute.
                          */
                         if (is_depgrp_bypassed(vv))
                                 continue;
 
                         /*

@@ -4560,10 +4549,19 @@
 void
 offline_subtree_leaves(graph_vertex_t *v, void *arg)
 {
         assert(MUTEX_HELD(&dgraph_lock));
 
+        /* If v has up dependents, try to bring them down first. */
+        if (insubtree_dependents_down(v) == B_FALSE) {
+                graph_walk_dependents(v, offline_subtree_leaves, arg);
+
+                /* If we couldn't bring them down, return. */
+                if (insubtree_dependents_down(v) == B_FALSE)
+                        return;
+        }
+
         /* If v isn't an instance, recurse on its dependencies. */
         if (v->gv_type != GVT_INST) {
                 graph_walk_dependencies(v, offline_subtree_leaves, arg);
                 return;
         }

@@ -5459,12 +5457,12 @@
                 v->gv_flags |= GV_TOOFFLINE;
                 log_framework(LOG_DEBUG, "%s added to subtree\n", v->gv_name);
                 break;
         case GVT_GROUP:
                 /*
-                 * Skip all excluded and optional_all dependencies and decide
-                 * whether to offline the service based on restart_on attribute.
+                 * Skip all excluded dependencies and decide whether to offline
+                 * the service based on the restart_on attribute.
                  */
                 if (is_depgrp_bypassed(v))
                         return (UU_WALK_NEXT);
                 break;
         }