194 int32_t stn_global;
195 /*
196 * info_events_all holds a flag to override notification parameters and send
197 * Information events for all state transitions.
198 * same about the need of a mutex here.
199 */
200 int info_events_all;
201
202 /*
203 * Services in these states are not considered 'down' by the
204 * milestone/shutdown code.
205 */
206 #define up_state(state) ((state) == RESTARTER_STATE_ONLINE || \
207 (state) == RESTARTER_STATE_DEGRADED || \
208 (state) == RESTARTER_STATE_OFFLINE)
209
210 #define is_depgrp_bypassed(v) ((v->gv_type == GVT_GROUP) && \
211 ((v->gv_depgroup == DEPGRP_EXCLUDE_ALL) || \
212 (v->gv_restart < RERR_RESTART)))
213
214 static uu_list_pool_t *graph_edge_pool, *graph_vertex_pool;
215 static uu_list_t *dgraph;
216 static pthread_mutex_t dgraph_lock;
217
218 /*
219 * milestone indicates the current subgraph. When NULL, it is the entire
220 * graph. When MILESTONE_NONE, it is the empty graph. Otherwise, it is all
221 * services on which the target vertex depends.
222 */
223 static graph_vertex_t *milestone = NULL;
224 static boolean_t initial_milestone_set = B_FALSE;
225 static pthread_cond_t initial_milestone_cv = PTHREAD_COND_INITIALIZER;
226
227 /* protected by dgraph_lock */
228 static boolean_t sulogin_thread_running = B_FALSE;
229 static boolean_t sulogin_running = B_FALSE;
230 static boolean_t console_login_ready = B_FALSE;
231
232 /* Number of services to come down to complete milestone transition. */
233 static uint_t non_subgraph_svcs;
1281
1282 satisfiable = B_FALSE;
1283
1284 for (edge = uu_list_first(groupv->gv_dependencies);
1285 edge != NULL;
1286 edge = uu_list_next(groupv->gv_dependencies, edge)) {
1287 s = dependency_satisfied(edge->ge_vertex, satbility);
1288
1289 if (s == 1)
1290 return (1);
1291
1292 log_framework2(LOG_DEBUG, DEBUG_DEPENDENCIES,
1293 "require_any(%s): %s is unsatisfi%s.\n",
1294 groupv->gv_name, edge->ge_vertex->gv_name,
1295 s == 0 ? "ed" : "able");
1296
1297 if (satbility && s == 0)
1298 satisfiable = B_TRUE;
1299 }
1300
1301 return (!satbility || satisfiable ? 0 : -1);
1302 }
1303
1304 /*
1305 * An optional_all dependency only considers elements which are configured,
1306 * enabled, and not in maintenance. If any are unsatisfied, then the dependency
1307 * is unsatisfied.
1308 *
1309 * Offline dependencies which are waiting for a dependency to come online are
1310 * unsatisfied. Offline dependences which cannot possibly come online
1311 * (unsatisfiable) are always considered satisfied.
1312 */
1313 static int
1314 optional_all_satisfied(graph_vertex_t *groupv, boolean_t satbility)
1315 {
1316 graph_edge_t *edge;
1317 graph_vertex_t *v;
1318 boolean_t any_qualified;
1319 boolean_t any_unsatisfied;
1320 int i;
1321
1322 any_qualified = B_FALSE;
1323 any_unsatisfied = B_FALSE;
1324
1325 for (edge = uu_list_first(groupv->gv_dependencies);
1326 edge != NULL;
1327 edge = uu_list_next(groupv->gv_dependencies, edge)) {
1328 v = edge->ge_vertex;
1329
1330 switch (v->gv_type) {
1331 case GVT_INST:
1332 /* Skip missing instances */
1333 if ((v->gv_flags & GV_CONFIGURED) == 0)
1334 continue;
1335
1336 if (v->gv_state == RESTARTER_STATE_MAINT)
1337 continue;
1338
1339 any_qualified = B_TRUE;
1340 if (v->gv_state == RESTARTER_STATE_OFFLINE) {
1341 /*
1342 * For offline dependencies, treat unsatisfiable
1343 * as satisfied.
1344 */
1345 i = dependency_satisfied(v, B_TRUE);
1346 if (i == -1)
1347 i = 1;
1348 } else if (v->gv_state == RESTARTER_STATE_DISABLED) {
1349 /*
1350 * If the instance is transitioning out of
1351 * disabled the dependency is temporarily
1352 * unsatisfied (not unsatisfiable).
1353 */
1354 i = v->gv_flags & GV_ENABLED ? 0 : 1;
1355 } else {
1356 i = dependency_satisfied(v, satbility);
1357 }
1358 break;
1359
1360 case GVT_FILE:
1361 any_qualified = B_TRUE;
1362 i = dependency_satisfied(v, satbility);
1363
1364 break;
1365
1366 case GVT_SVC: {
1367 any_qualified = B_TRUE;
1368 i = optional_all_satisfied(v, satbility);
1369
1370 break;
1371 }
1372
1373 case GVT_GROUP:
1374 default:
1529 * Decide whether v can satisfy a dependency. v can either be a child of
1530 * a group vertex, or of an instance vertex.
1531 */
1532 static int
1533 dependency_satisfied(graph_vertex_t *v, boolean_t satbility)
1534 {
1535 switch (v->gv_type) {
1536 case GVT_INST:
1537 if ((v->gv_flags & GV_CONFIGURED) == 0) {
1538 if (v->gv_flags & GV_DEATHROW) {
1539 /*
1540 * A dependency on an instance with GV_DEATHROW
1541 * flag is always considered as satisfied.
1542 */
1543 return (1);
1544 }
1545 return (-1);
1546 }
1547
1548 /*
1549 * Any vertex with the GV_TODISABLE flag set is guaranteed
1550 * to have its dependencies unsatisfiable. Any vertex with
1551 * GV_TOOFFLINE may be satisfied after it transitions.
1552 */
1553 if (v->gv_flags & GV_TODISABLE)
1554 return (-1);
1555 if (v->gv_flags & GV_TOOFFLINE)
1556 return (0);
1557
1558 switch (v->gv_state) {
1559 case RESTARTER_STATE_ONLINE:
1560 case RESTARTER_STATE_DEGRADED:
1561 return (1);
1562
1563 case RESTARTER_STATE_OFFLINE:
1564 if (!satbility)
1565 return (0);
1566 return (instance_satisfied(v, satbility) != -1 ?
1567 0 : -1);
1568
1569 case RESTARTER_STATE_DISABLED:
1570 case RESTARTER_STATE_MAINT:
1571 return (-1);
1572
1573 case RESTARTER_STATE_UNINIT:
1574 return (0);
1575
1576 default:
1577 #ifndef NDEBUG
1578 uu_warn("%s:%d: Unexpected vertex state %d.\n",
1579 __FILE__, __LINE__, v->gv_state);
1580 #endif
1581 abort();
1582 /* NOTREACHED */
1583 }
1584
1585 case GVT_SVC:
1586 if (uu_list_numnodes(v->gv_dependencies) == 0)
1587 return (-1);
1588 return (require_any_satisfied(v, satbility));
1589
1652 * | A |--------------->| B |-------------->| C |
1653 * +-----+ +-----+ +-----+
1654 *
1655 * offline -> maintenance
1656 *
1657 * If C goes into maintenance, it's not enough simply to check B. Because A has
1658 * an optional dependency, what was previously an unsatisfiable situation is now
1659 * satisfied (B will never come online, even though its state hasn't changed).
1660 *
1661 * Note that it's not necessary to continue examining dependents after reaching
1662 * an optional_all dependency. It's not possible for an optional_all dependency
1663 * to change satisfiability without also coming online, in which case we get a
1664 * start event and propagation continues naturally. However, it does no harm to
1665 * continue propagating satisfiability (as it is a relatively rare event), and
1666 * keeps the walker code simple and generic.
1667 */
1668 /*ARGSUSED*/
1669 static int
1670 satbility_cb(graph_vertex_t *v, void *arg)
1671 {
1672 if (v->gv_flags & GV_TOOFFLINE)
1673 return (UU_WALK_NEXT);
1674
1675 if (v->gv_type == GVT_INST)
1676 graph_start_if_satisfied(v);
1677
1678 return (UU_WALK_NEXT);
1679 }
1680
1681 static void
1682 propagate_satbility(graph_vertex_t *v)
1683 {
1684 graph_walk(v, WALK_DEPENDENTS, satbility_cb, NULL, NULL);
1685 }
1686
1687 static void propagate_stop(graph_vertex_t *, void *);
1688
1689 /*
1690 * propagate_start()
1691 *
1692 * This function is used to propagate a start event to the dependents of the
1693 * given vertex. Any dependents that are offline but have their dependencies
1694 * satisfied are started. Any dependents that are online and have restart_on
1695 * set to "restart" or "refresh" are restarted because their dependencies have
1696 * just changed. This only happens with optional_all dependencies.
1697 */
1698 static void
1699 propagate_start(graph_vertex_t *v, void *arg)
1700 {
1701 restarter_error_t err = (restarter_error_t)arg;
1702
1703 if (v->gv_flags & GV_TOOFFLINE)
1704 return;
1705
1706 switch (v->gv_type) {
1707 case GVT_INST:
1708 /* Restarter */
1709 if (inst_running(v)) {
1710 if (err == RERR_RESTART || err == RERR_REFRESH) {
1711 vertex_send_event(v,
1712 RESTARTER_EVENT_TYPE_STOP_RESET);
1713 }
1714 } else {
1715 graph_start_if_satisfied(v);
1716 }
1717 break;
1718
1719 case GVT_GROUP:
1720 if (v->gv_depgroup == DEPGRP_EXCLUDE_ALL) {
1721 graph_walk_dependents(v, propagate_stop,
1722 (void *)RERR_RESTART);
1723 break;
1743 v->gv_type);
1744 #endif
1745 abort();
1746 }
1747 }
1748
1749 /*
1750 * propagate_stop()
1751 *
1752 * This function is used to propagate a stop event to the dependents of the
1753 * given vertex. Any dependents that are online (or in degraded state) with
1754 * the restart_on property set to "restart" or "refresh" will be stopped as
1755 * their dependencies have just changed, propagate_start() will start them
1756 * again once their dependencies have been re-satisfied.
1757 */
1758 static void
1759 propagate_stop(graph_vertex_t *v, void *arg)
1760 {
1761 restarter_error_t err = (restarter_error_t)arg;
1762
1763 if (v->gv_flags & GV_TOOFFLINE)
1764 return;
1765
1766 switch (v->gv_type) {
1767 case GVT_INST:
1768 /* Restarter */
1769 if (err > RERR_NONE && inst_running(v)) {
1770 if (err == RERR_RESTART || err == RERR_REFRESH) {
1771 vertex_send_event(v,
1772 RESTARTER_EVENT_TYPE_STOP_RESET);
1773 } else {
1774 vertex_send_event(v, RESTARTER_EVENT_TYPE_STOP);
1775 }
1776 }
1777 break;
1778
1779 case GVT_SVC:
1780 graph_walk_dependents(v, propagate_stop, arg);
1781 break;
1782
1783 case GVT_FILE:
1784 #ifndef NDEBUG
1785 uu_warn("%s:%d: propagate_stop() encountered GVT_FILE.\n",
1786 __FILE__, __LINE__);
1787 #endif
1788 abort();
1789 /* NOTREACHED */
1790
1791 case GVT_GROUP:
1792 if (v->gv_depgroup == DEPGRP_EXCLUDE_ALL) {
1793 graph_walk_dependents(v, propagate_start, NULL);
1794 break;
1795 }
1796
1797 if (err == RERR_NONE || err > v->gv_restart)
1798 break;
1799
1800 graph_walk_dependents(v, propagate_stop, arg);
1801 break;
1802
1803 default:
1804 #ifndef NDEBUG
1805 uu_warn("%s:%d: Unknown vertex type %d.\n", __FILE__, __LINE__,
1806 v->gv_type);
1807 #endif
1808 abort();
1809 }
1810 }
1811
1812 void
1813 offline_vertex(graph_vertex_t *v)
4341
4342 assert(MUTEX_HELD(&dgraph_lock));
4343
4344 for (e = uu_list_first(v->gv_dependents); e != NULL;
4345 e = uu_list_next(v->gv_dependents, e)) {
4346 vv = e->ge_vertex;
4347 if (vv->gv_type == GVT_INST) {
4348 if ((vv->gv_flags & GV_CONFIGURED) == 0)
4349 continue;
4350
4351 if ((vv->gv_flags & GV_TOOFFLINE) == 0)
4352 continue;
4353
4354 if ((vv->gv_state == RESTARTER_STATE_ONLINE) ||
4355 (vv->gv_state == RESTARTER_STATE_DEGRADED))
4356 return (B_FALSE);
4357 } else {
4358 /*
4359 * Skip all excluded dependents and decide whether
4360 * to offline the service based on the restart_on
4361 * on attribute.
4362 */
4363 if (is_depgrp_bypassed(vv))
4364 continue;
4365
4366 /*
4367 * For dependency groups or service vertices, keep
4368 * traversing to see if instances are running.
4369 */
4370 if (insubtree_dependents_down(vv) == B_FALSE)
4371 return (B_FALSE);
4372 }
4373 }
4374
4375 return (B_TRUE);
4376 }
4377
4378 /*
4379 * Returns true only if none of this service's dependents are 'up' -- online,
4380 * degraded, or offline.
4381 */
5393
5394 /*
5395 * mark_subtree walks the dependents and add the GV_TOOFFLINE flag
5396 * to the instances that are supposed to go offline during an
5397 * administrative disable operation.
5398 */
5399 static int
5400 mark_subtree(graph_edge_t *e, void *arg)
5401 {
5402 graph_vertex_t *v;
5403 int r;
5404
5405 v = e->ge_vertex;
5406
5407 /* If it's already in the subgraph, skip. */
5408 if (v->gv_flags & GV_TOOFFLINE)
5409 return (UU_WALK_NEXT);
5410
5411 switch (v->gv_type) {
5412 case GVT_INST:
5413 /* If the instance is already disabled, skip it. */
5414 if (!(v->gv_flags & GV_ENABLED))
5415 return (UU_WALK_NEXT);
5416
5417 v->gv_flags |= GV_TOOFFLINE;
5418 log_framework(LOG_DEBUG, "%s added to subtree\n", v->gv_name);
5419 break;
5420 case GVT_GROUP:
5421 /*
5422 * Skip all excluded dependents and decide whether to offline
5423 * the service based on the restart_on attribute.
5424 */
5425 if (is_depgrp_bypassed(v))
5426 return (UU_WALK_NEXT);
5427 break;
5428 }
5429
5430 r = uu_list_walk(v->gv_dependents, (uu_walk_fn_t *)mark_subtree, arg,
5431 0);
5432 assert(r == 0);
5433 return (UU_WALK_NEXT);
5434 }
|
194 int32_t stn_global;
195 /*
196 * info_events_all holds a flag to override notification parameters and send
197 * Information events for all state transitions.
198 * same about the need of a mutex here.
199 */
200 int info_events_all;
201
202 /*
203 * Services in these states are not considered 'down' by the
204 * milestone/shutdown code.
205 */
206 #define up_state(state) ((state) == RESTARTER_STATE_ONLINE || \
207 (state) == RESTARTER_STATE_DEGRADED || \
208 (state) == RESTARTER_STATE_OFFLINE)
209
210 #define is_depgrp_bypassed(v) ((v->gv_type == GVT_GROUP) && \
211 ((v->gv_depgroup == DEPGRP_EXCLUDE_ALL) || \
212 (v->gv_restart < RERR_RESTART)))
213
214 #define is_inst_bypassed(v) ((v->gv_type == GVT_INST) && \
215 ((v->gv_flags & GV_TODISABLE) || \
216 (v->gv_flags & GV_TOOFFLINE)))
217
218 static uu_list_pool_t *graph_edge_pool, *graph_vertex_pool;
219 static uu_list_t *dgraph;
220 static pthread_mutex_t dgraph_lock;
221
222 /*
223 * milestone indicates the current subgraph. When NULL, it is the entire
224 * graph. When MILESTONE_NONE, it is the empty graph. Otherwise, it is all
225 * services on which the target vertex depends.
226 */
227 static graph_vertex_t *milestone = NULL;
228 static boolean_t initial_milestone_set = B_FALSE;
229 static pthread_cond_t initial_milestone_cv = PTHREAD_COND_INITIALIZER;
230
231 /* protected by dgraph_lock */
232 static boolean_t sulogin_thread_running = B_FALSE;
233 static boolean_t sulogin_running = B_FALSE;
234 static boolean_t console_login_ready = B_FALSE;
235
236 /* Number of services to come down to complete milestone transition. */
237 static uint_t non_subgraph_svcs;
1285
1286 satisfiable = B_FALSE;
1287
1288 for (edge = uu_list_first(groupv->gv_dependencies);
1289 edge != NULL;
1290 edge = uu_list_next(groupv->gv_dependencies, edge)) {
1291 s = dependency_satisfied(edge->ge_vertex, satbility);
1292
1293 if (s == 1)
1294 return (1);
1295
1296 log_framework2(LOG_DEBUG, DEBUG_DEPENDENCIES,
1297 "require_any(%s): %s is unsatisfi%s.\n",
1298 groupv->gv_name, edge->ge_vertex->gv_name,
1299 s == 0 ? "ed" : "able");
1300
1301 if (satbility && s == 0)
1302 satisfiable = B_TRUE;
1303 }
1304
1305 return ((!satbility || satisfiable) ? 0 : -1);
1306 }
1307
1308 /*
1309 * An optional_all dependency only considers elements which are configured,
1310 * enabled, and not in maintenance. If any are unsatisfied, then the dependency
1311 * is unsatisfied.
1312 *
1313 * Offline dependencies which are waiting for a dependency to come online are
1314 * unsatisfied. Offline dependences which cannot possibly come online
1315 * (unsatisfiable) are always considered satisfied.
1316 */
1317 static int
1318 optional_all_satisfied(graph_vertex_t *groupv, boolean_t satbility)
1319 {
1320 graph_edge_t *edge;
1321 graph_vertex_t *v;
1322 boolean_t any_qualified;
1323 boolean_t any_unsatisfied;
1324 int i;
1325
1326 any_qualified = B_FALSE;
1327 any_unsatisfied = B_FALSE;
1328
1329 for (edge = uu_list_first(groupv->gv_dependencies);
1330 edge != NULL;
1331 edge = uu_list_next(groupv->gv_dependencies, edge)) {
1332 v = edge->ge_vertex;
1333
1334 switch (v->gv_type) {
1335 case GVT_INST:
1336 /* Skip missing instances */
1337 if ((v->gv_flags & GV_CONFIGURED) == 0)
1338 continue;
1339
1340 if (v->gv_state == RESTARTER_STATE_MAINT)
1341 continue;
1342
1343 any_qualified = B_TRUE;
1344 if (v->gv_state == RESTARTER_STATE_OFFLINE ||
1345 v->gv_state == RESTARTER_STATE_DISABLED) {
1346 /*
1347 * For offline/disabled dependencies,
1348 * treat unsatisfiable as satisfied.
1349 */
1350 i = dependency_satisfied(v, B_TRUE);
1351 if (i == -1)
1352 i = 1;
1353 } else {
1354 i = dependency_satisfied(v, satbility);
1355 }
1356 break;
1357
1358 case GVT_FILE:
1359 any_qualified = B_TRUE;
1360 i = dependency_satisfied(v, satbility);
1361
1362 break;
1363
1364 case GVT_SVC: {
1365 any_qualified = B_TRUE;
1366 i = optional_all_satisfied(v, satbility);
1367
1368 break;
1369 }
1370
1371 case GVT_GROUP:
1372 default:
1527 * Decide whether v can satisfy a dependency. v can either be a child of
1528 * a group vertex, or of an instance vertex.
1529 */
1530 static int
1531 dependency_satisfied(graph_vertex_t *v, boolean_t satbility)
1532 {
1533 switch (v->gv_type) {
1534 case GVT_INST:
1535 if ((v->gv_flags & GV_CONFIGURED) == 0) {
1536 if (v->gv_flags & GV_DEATHROW) {
1537 /*
1538 * A dependency on an instance with GV_DEATHROW
1539 * flag is always considered as satisfied.
1540 */
1541 return (1);
1542 }
1543 return (-1);
1544 }
1545
1546 /*
1547 * Vertices may be transitioning so we try to figure out if
1548 * the end state is likely to satisfy the dependency instead
1549 * of assuming the dependency is unsatisfied/unsatisfiable.
1550 *
1551 * Support for optional_all dependencies depends on us getting
1552 * this right because unsatisfiable dependencies are treated
1553 * as being satisfied.
1554 */
1555 switch (v->gv_state) {
1556 case RESTARTER_STATE_ONLINE:
1557 case RESTARTER_STATE_DEGRADED:
1558 if (v->gv_flags & GV_TODISABLE)
1559 return (-1);
1560 if (v->gv_flags & GV_TOOFFLINE)
1561 return (0);
1562 return (1);
1563
1564 case RESTARTER_STATE_OFFLINE:
1565 if (!satbility || v->gv_flags & GV_TODISABLE)
1566 return (satbility ? -1 : 0);
1567 return (instance_satisfied(v, satbility) != -1 ?
1568 0 : -1);
1569
1570 case RESTARTER_STATE_DISABLED:
1571 if (!satbility || !(v->gv_flags & GV_ENABLED))
1572 return (satbility ? -1 : 0);
1573 return (instance_satisfied(v, satbility) != -1 ?
1574 0 : -1);
1575
1576 case RESTARTER_STATE_MAINT:
1577 return (-1);
1578
1579 case RESTARTER_STATE_UNINIT:
1580 return (0);
1581
1582 default:
1583 #ifndef NDEBUG
1584 uu_warn("%s:%d: Unexpected vertex state %d.\n",
1585 __FILE__, __LINE__, v->gv_state);
1586 #endif
1587 abort();
1588 /* NOTREACHED */
1589 }
1590
1591 case GVT_SVC:
1592 if (uu_list_numnodes(v->gv_dependencies) == 0)
1593 return (-1);
1594 return (require_any_satisfied(v, satbility));
1595
1658 * | A |--------------->| B |-------------->| C |
1659 * +-----+ +-----+ +-----+
1660 *
1661 * offline -> maintenance
1662 *
1663 * If C goes into maintenance, it's not enough simply to check B. Because A has
1664 * an optional dependency, what was previously an unsatisfiable situation is now
1665 * satisfied (B will never come online, even though its state hasn't changed).
1666 *
1667 * Note that it's not necessary to continue examining dependents after reaching
1668 * an optional_all dependency. It's not possible for an optional_all dependency
1669 * to change satisfiability without also coming online, in which case we get a
1670 * start event and propagation continues naturally. However, it does no harm to
1671 * continue propagating satisfiability (as it is a relatively rare event), and
1672 * keeps the walker code simple and generic.
1673 */
1674 /*ARGSUSED*/
1675 static int
1676 satbility_cb(graph_vertex_t *v, void *arg)
1677 {
1678 if (is_inst_bypassed(v))
1679 return (UU_WALK_NEXT);
1680
1681 if (v->gv_type == GVT_INST)
1682 graph_start_if_satisfied(v);
1683
1684 return (UU_WALK_NEXT);
1685 }
1686
1687 static void
1688 propagate_satbility(graph_vertex_t *v)
1689 {
1690 graph_walk(v, WALK_DEPENDENTS, satbility_cb, NULL, NULL);
1691 }
1692
1693 static void propagate_stop(graph_vertex_t *, void *);
1694
1695 /*
1696 * propagate_start()
1697 *
1698 * This function is used to propagate a start event to the dependents of the
1699 * given vertex. Any dependents that are offline but have their dependencies
1700 * satisfied are started. Any dependents that are online and have restart_on
1701 * set to "restart" or "refresh" are restarted because their dependencies have
1702 * just changed. This only happens with optional_all dependencies.
1703 */
1704 static void
1705 propagate_start(graph_vertex_t *v, void *arg)
1706 {
1707 restarter_error_t err = (restarter_error_t)arg;
1708
1709 if (is_inst_bypassed(v))
1710 return;
1711
1712 switch (v->gv_type) {
1713 case GVT_INST:
1714 /* Restarter */
1715 if (inst_running(v)) {
1716 if (err == RERR_RESTART || err == RERR_REFRESH) {
1717 vertex_send_event(v,
1718 RESTARTER_EVENT_TYPE_STOP_RESET);
1719 }
1720 } else {
1721 graph_start_if_satisfied(v);
1722 }
1723 break;
1724
1725 case GVT_GROUP:
1726 if (v->gv_depgroup == DEPGRP_EXCLUDE_ALL) {
1727 graph_walk_dependents(v, propagate_stop,
1728 (void *)RERR_RESTART);
1729 break;
1749 v->gv_type);
1750 #endif
1751 abort();
1752 }
1753 }
1754
1755 /*
1756 * propagate_stop()
1757 *
1758 * This function is used to propagate a stop event to the dependents of the
1759 * given vertex. Any dependents that are online (or in degraded state) with
1760 * the restart_on property set to "restart" or "refresh" will be stopped as
1761 * their dependencies have just changed, propagate_start() will start them
1762 * again once their dependencies have been re-satisfied.
1763 */
1764 static void
1765 propagate_stop(graph_vertex_t *v, void *arg)
1766 {
1767 restarter_error_t err = (restarter_error_t)arg;
1768
1769 if (is_inst_bypassed(v))
1770 return;
1771
1772 switch (v->gv_type) {
1773 case GVT_INST:
1774 /* Restarter */
1775 if (err > RERR_NONE && inst_running(v)) {
1776 if (err == RERR_RESTART || err == RERR_REFRESH) {
1777 vertex_send_event(v,
1778 RESTARTER_EVENT_TYPE_STOP_RESET);
1779 } else {
1780 vertex_send_event(v, RESTARTER_EVENT_TYPE_STOP);
1781 }
1782 }
1783 break;
1784
1785 case GVT_SVC:
1786 graph_walk_dependents(v, propagate_stop, arg);
1787 break;
1788
1789 case GVT_FILE:
1790 #ifndef NDEBUG
1791 uu_warn("%s:%d: propagate_stop() encountered GVT_FILE.\n",
1792 __FILE__, __LINE__);
1793 #endif
1794 abort();
1795 /* NOTREACHED */
1796
1797 case GVT_GROUP:
1798 if (v->gv_depgroup == DEPGRP_EXCLUDE_ALL) {
1799 graph_walk_dependents(v, propagate_start,
1800 (void *)RERR_NONE);
1801 break;
1802 }
1803
1804 if (err == RERR_NONE || err > v->gv_restart)
1805 break;
1806
1807 graph_walk_dependents(v, propagate_stop, arg);
1808 break;
1809
1810 default:
1811 #ifndef NDEBUG
1812 uu_warn("%s:%d: Unknown vertex type %d.\n", __FILE__, __LINE__,
1813 v->gv_type);
1814 #endif
1815 abort();
1816 }
1817 }
1818
1819 void
1820 offline_vertex(graph_vertex_t *v)
4348
4349 assert(MUTEX_HELD(&dgraph_lock));
4350
4351 for (e = uu_list_first(v->gv_dependents); e != NULL;
4352 e = uu_list_next(v->gv_dependents, e)) {
4353 vv = e->ge_vertex;
4354 if (vv->gv_type == GVT_INST) {
4355 if ((vv->gv_flags & GV_CONFIGURED) == 0)
4356 continue;
4357
4358 if ((vv->gv_flags & GV_TOOFFLINE) == 0)
4359 continue;
4360
4361 if ((vv->gv_state == RESTARTER_STATE_ONLINE) ||
4362 (vv->gv_state == RESTARTER_STATE_DEGRADED))
4363 return (B_FALSE);
4364 } else {
4365 /*
4366 * Skip all excluded dependents and decide whether
4367 * to offline the service based on the restart_on
4368 * attribute.
4369 */
4370 if (is_depgrp_bypassed(vv))
4371 continue;
4372
4373 /*
4374 * For dependency groups or service vertices, keep
4375 * traversing to see if instances are running.
4376 */
4377 if (insubtree_dependents_down(vv) == B_FALSE)
4378 return (B_FALSE);
4379 }
4380 }
4381
4382 return (B_TRUE);
4383 }
4384
4385 /*
4386 * Returns true only if none of this service's dependents are 'up' -- online,
4387 * degraded, or offline.
4388 */
5400
5401 /*
5402 * mark_subtree walks the dependents and add the GV_TOOFFLINE flag
5403 * to the instances that are supposed to go offline during an
5404 * administrative disable operation.
5405 */
5406 static int
5407 mark_subtree(graph_edge_t *e, void *arg)
5408 {
5409 graph_vertex_t *v;
5410 int r;
5411
5412 v = e->ge_vertex;
5413
5414 /* If it's already in the subgraph, skip. */
5415 if (v->gv_flags & GV_TOOFFLINE)
5416 return (UU_WALK_NEXT);
5417
5418 switch (v->gv_type) {
5419 case GVT_INST:
5420 /* If the instance is already offline, skip it. */
5421 if (!inst_running(v))
5422 return (UU_WALK_NEXT);
5423
5424 v->gv_flags |= GV_TOOFFLINE;
5425 log_framework(LOG_DEBUG, "%s added to subtree\n", v->gv_name);
5426 break;
5427 case GVT_GROUP:
5428 /*
5429 * Skip all excluded dependents and decide whether to offline
5430 * the service based on the restart_on attribute.
5431 */
5432 if (is_depgrp_bypassed(v))
5433 return (UU_WALK_NEXT);
5434 break;
5435 }
5436
5437 r = uu_list_walk(v->gv_dependents, (uu_walk_fn_t *)mark_subtree, arg,
5438 0);
5439 assert(r == 0);
5440 return (UU_WALK_NEXT);
5441 }
|