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;
}