Print this page
7281 mdnsd needs to try harder to send goodbye requests


   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 
  22 /*
  23  * Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved.
  24  * Copyright (c) 2015, Syneto S.R.L. All rights reserved.

  25  */
  26 
  27 /*
  28  * graph.c - master restarter graph engine
  29  *
  30  *   The graph engine keeps a dependency graph of all service instances on the
  31  *   system, as recorded in the repository.  It decides when services should
  32  *   be brought up or down based on service states and dependencies and sends
  33  *   commands to restarters to effect any changes.  It also executes
  34  *   administrator commands sent by svcadm via the repository.
  35  *
  36  *   The graph is stored in uu_list_t *dgraph and its vertices are
  37  *   graph_vertex_t's, each of which has a name and an integer id unique to
  38  *   its name (see dict.c).  A vertex's type attribute designates the type
  39  *   of object it represents: GVT_INST for service instances, GVT_SVC for
  40  *   service objects (since service instances may depend on another service,
  41  *   rather than service instance), GVT_FILE for files (which services may
  42  *   depend on), and GVT_GROUP for dependencies on multiple objects.  GVT_GROUP
  43  *   vertices are necessary because dependency lists may have particular
  44  *   grouping types (require any, require all, optional, or exclude) and


 190  *     access to stn_global
 191  */
 192 int32_t stn_global;
 193 /*
 194  * info_events_all holds a flag to override notification parameters and send
 195  * Information events for all state transitions.
 196  * same about the need of a mutex here.
 197  */
 198 int info_events_all;
 199 
 200 /*
 201  * Services in these states are not considered 'down' by the
 202  * milestone/shutdown code.
 203  */
 204 #define up_state(state) ((state) == RESTARTER_STATE_ONLINE || \
 205         (state) == RESTARTER_STATE_DEGRADED || \
 206         (state) == RESTARTER_STATE_OFFLINE)
 207 
 208 #define is_depgrp_bypassed(v) ((v->gv_type == GVT_GROUP) && \
 209         ((v->gv_depgroup == DEPGRP_EXCLUDE_ALL) || \
 210         (v->gv_depgroup == DEPGRP_OPTIONAL_ALL) || \
 211         (v->gv_restart < RERR_RESTART)))
 212 
 213 static uu_list_pool_t *graph_edge_pool, *graph_vertex_pool;
 214 static uu_list_t *dgraph;
 215 static pthread_mutex_t dgraph_lock;
 216 
 217 /*
 218  * milestone indicates the current subgraph.  When NULL, it is the entire
 219  * graph.  When MILESTONE_NONE, it is the empty graph.  Otherwise, it is all
 220  * services on which the target vertex depends.
 221  */
 222 static graph_vertex_t *milestone = NULL;
 223 static boolean_t initial_milestone_set = B_FALSE;
 224 static pthread_cond_t initial_milestone_cv = PTHREAD_COND_INITIALIZER;
 225 
 226 /* protected by dgraph_lock */
 227 static boolean_t sulogin_thread_running = B_FALSE;
 228 static boolean_t sulogin_running = B_FALSE;
 229 static boolean_t console_login_ready = B_FALSE;
 230 


1311  */
1312 static int
1313 optional_all_satisfied(graph_vertex_t *groupv, boolean_t satbility)
1314 {
1315         graph_edge_t *edge;
1316         graph_vertex_t *v;
1317         boolean_t any_qualified;
1318         boolean_t any_unsatisfied;
1319         int i;
1320 
1321         any_qualified = B_FALSE;
1322         any_unsatisfied = B_FALSE;
1323 
1324         for (edge = uu_list_first(groupv->gv_dependencies);
1325             edge != NULL;
1326             edge = uu_list_next(groupv->gv_dependencies, edge)) {
1327                 v = edge->ge_vertex;
1328 
1329                 switch (v->gv_type) {
1330                 case GVT_INST:
1331                         /* Skip missing or disabled instances */
1332                         if ((v->gv_flags & (GV_CONFIGURED | GV_ENABLED)) !=
1333                             (GV_CONFIGURED | GV_ENABLED))
1334                                 continue;
1335 
1336                         if (v->gv_state == RESTARTER_STATE_MAINT)
1337                                 continue;
1338 
1339                         if (v->gv_flags & GV_TOOFFLINE)
1340                                 continue;
1341 
1342                         any_qualified = B_TRUE;
1343                         if (v->gv_state == RESTARTER_STATE_OFFLINE) {
1344                                 /*
1345                                  * For offline dependencies, treat unsatisfiable
1346                                  * as satisfied.
1347                                  */
1348                                 i = dependency_satisfied(v, B_TRUE);
1349                                 if (i == -1)
1350                                         i = 1;
1351                         } else if (v->gv_state == RESTARTER_STATE_DISABLED) {
1352                                 /*
1353                                  * The service is enabled, but hasn't
1354                                  * transitioned out of disabled yet.  Treat it
1355                                  * as unsatisfied (not unsatisfiable).
1356                                  */
1357                                 i = 0;
1358                         } else {
1359                                 i = dependency_satisfied(v, satbility);
1360                         }
1361                         break;
1362 
1363                 case GVT_FILE:
1364                         any_qualified = B_TRUE;
1365                         i = dependency_satisfied(v, satbility);
1366 
1367                         break;
1368 
1369                 case GVT_SVC: {
1370                         boolean_t svc_any_qualified;
1371                         boolean_t svc_satisfied;
1372                         boolean_t svc_satisfiable;
1373                         graph_vertex_t *v2;
1374                         graph_edge_t *e2;
1375 
1376                         svc_any_qualified = B_FALSE;
1377                         svc_satisfied = B_FALSE;
1378                         svc_satisfiable = B_FALSE;
1379 
1380                         for (e2 = uu_list_first(v->gv_dependencies);
1381                             e2 != NULL;
1382                             e2 = uu_list_next(v->gv_dependencies, e2)) {
1383                                 v2 = e2->ge_vertex;
1384                                 assert(v2->gv_type == GVT_INST);
1385 
1386                                 if ((v2->gv_flags &
1387                                     (GV_CONFIGURED | GV_ENABLED)) !=
1388                                     (GV_CONFIGURED | GV_ENABLED))
1389                                         continue;
1390 
1391                                 if (v2->gv_state == RESTARTER_STATE_MAINT)
1392                                         continue;
1393 
1394                                 if (v2->gv_flags & GV_TOOFFLINE)
1395                                         continue;
1396 
1397                                 svc_any_qualified = B_TRUE;
1398 
1399                                 if (v2->gv_state == RESTARTER_STATE_OFFLINE) {
1400                                         /*
1401                                          * For offline dependencies, treat
1402                                          * unsatisfiable as satisfied.
1403                                          */
1404                                         i = dependency_satisfied(v2, B_TRUE);
1405                                         if (i == -1)
1406                                                 i = 1;
1407                                 } else if (v2->gv_state ==
1408                                     RESTARTER_STATE_DISABLED) {
1409                                         i = 0;
1410                                 } else {
1411                                         i = dependency_satisfied(v2, satbility);
1412                                 }
1413 
1414                                 if (i == 1) {
1415                                         svc_satisfied = B_TRUE;
1416                                         break;
1417                                 }
1418                                 if (i == 0)
1419                                         svc_satisfiable = B_TRUE;
1420                         }
1421 
1422                         if (!svc_any_qualified)
1423                                 continue;
1424                         any_qualified = B_TRUE;
1425                         if (svc_satisfied) {
1426                                 i = 1;
1427                         } else if (svc_satisfiable) {
1428                                 i = 0;
1429                         } else {


1591  * Decide whether v can satisfy a dependency.  v can either be a child of
1592  * a group vertex, or of an instance vertex.
1593  */
1594 static int
1595 dependency_satisfied(graph_vertex_t *v, boolean_t satbility)
1596 {
1597         switch (v->gv_type) {
1598         case GVT_INST:
1599                 if ((v->gv_flags & GV_CONFIGURED) == 0) {
1600                         if (v->gv_flags & GV_DEATHROW) {
1601                                 /*
1602                                  * A dependency on an instance with GV_DEATHROW
1603                                  * flag is always considered as satisfied.
1604                                  */
1605                                 return (1);
1606                         }
1607                         return (-1);
1608                 }
1609 
1610                 /*
1611                  * Any vertex with the GV_TOOFFLINE flag set is guaranteed
1612                  * to have its dependencies unsatisfiable.

1613                  */
1614                 if (v->gv_flags & GV_TOOFFLINE)
1615                         return (-1);


1616 
1617                 switch (v->gv_state) {
1618                 case RESTARTER_STATE_ONLINE:
1619                 case RESTARTER_STATE_DEGRADED:
1620                         return (1);
1621 
1622                 case RESTARTER_STATE_OFFLINE:
1623                         if (!satbility)
1624                                 return (0);
1625                         return (instance_satisfied(v, satbility) != -1 ?
1626                             0 : -1);
1627 
1628                 case RESTARTER_STATE_DISABLED:
1629                 case RESTARTER_STATE_MAINT:
1630                         return (-1);
1631 
1632                 case RESTARTER_STATE_UNINIT:
1633                         return (0);
1634 
1635                 default:


1711  *      |  A  |--------------->|  B  |-------------->|  C  |
1712  *      +-----+                +-----+               +-----+
1713  *
1714  *                                              offline -> maintenance
1715  *
1716  * If C goes into maintenance, it's not enough simply to check B.  Because A has
1717  * an optional dependency, what was previously an unsatisfiable situation is now
1718  * satisfied (B will never come online, even though its state hasn't changed).
1719  *
1720  * Note that it's not necessary to continue examining dependents after reaching
1721  * an optional_all dependency.  It's not possible for an optional_all dependency
1722  * to change satisfiability without also coming online, in which case we get a
1723  * start event and propagation continues naturally.  However, it does no harm to
1724  * continue propagating satisfiability (as it is a relatively rare event), and
1725  * keeps the walker code simple and generic.
1726  */
1727 /*ARGSUSED*/
1728 static int
1729 satbility_cb(graph_vertex_t *v, void *arg)
1730 {



1731         if (v->gv_type == GVT_INST)
1732                 graph_start_if_satisfied(v);
1733 
1734         return (UU_WALK_NEXT);
1735 }
1736 
1737 static void
1738 propagate_satbility(graph_vertex_t *v)
1739 {
1740         graph_walk(v, WALK_DEPENDENTS, satbility_cb, NULL, NULL);
1741 }
1742 
1743 static void propagate_stop(graph_vertex_t *, void *);
1744 
1745 /* ARGSUSED */








1746 static void
1747 propagate_start(graph_vertex_t *v, void *arg)
1748 {





1749         switch (v->gv_type) {
1750         case GVT_INST:







1751                 graph_start_if_satisfied(v);

1752                 break;
1753 
1754         case GVT_GROUP:
1755                 if (v->gv_depgroup == DEPGRP_EXCLUDE_ALL) {
1756                         graph_walk_dependents(v, propagate_stop,
1757                             (void *)RERR_RESTART);
1758                         break;
1759                 }

1760                 /* FALLTHROUGH */
1761 
1762         case GVT_SVC:
1763                 graph_walk_dependents(v, propagate_start, NULL);
1764                 break;
1765 
1766         case GVT_FILE:
1767 #ifndef NDEBUG
1768                 uu_warn("%s:%d: propagate_start() encountered GVT_FILE.\n",
1769                     __FILE__, __LINE__);
1770 #endif
1771                 abort();
1772                 /* NOTREACHED */
1773 
1774         default:
1775 #ifndef NDEBUG
1776                 uu_warn("%s:%d: Unknown vertex type %d.\n", __FILE__, __LINE__,
1777                     v->gv_type);
1778 #endif
1779                 abort();
1780         }
1781 }
1782 









1783 static void
1784 propagate_stop(graph_vertex_t *v, void *arg)
1785 {
1786         graph_edge_t *e;
1787         graph_vertex_t *svc;
1788         restarter_error_t err = (restarter_error_t)arg;
1789 



1790         switch (v->gv_type) {
1791         case GVT_INST:
1792                 /* Restarter */
1793                 if (err > RERR_NONE && inst_running(v)) {
1794                         if (err == RERR_RESTART || err == RERR_REFRESH) {
1795                                 vertex_send_event(v,
1796                                     RESTARTER_EVENT_TYPE_STOP_RESET);
1797                         } else {
1798                                 vertex_send_event(v, RESTARTER_EVENT_TYPE_STOP);
1799                         }
1800                 }
1801                 break;
1802 
1803         case GVT_SVC:
1804                 graph_walk_dependents(v, propagate_stop, arg);
1805                 break;
1806 
1807         case GVT_FILE:
1808 #ifndef NDEBUG
1809                 uu_warn("%s:%d: propagate_stop() encountered GVT_FILE.\n",
1810                     __FILE__, __LINE__);
1811 #endif
1812                 abort();
1813                 /* NOTREACHED */
1814 
1815         case GVT_GROUP:
1816                 if (v->gv_depgroup == DEPGRP_EXCLUDE_ALL) {
1817                         graph_walk_dependents(v, propagate_start, NULL);
1818                         break;
1819                 }
1820 
1821                 if (err == RERR_NONE || err > v->gv_restart)
1822                         break;
1823 
1824                 assert(uu_list_numnodes(v->gv_dependents) == 1);
1825                 e = uu_list_first(v->gv_dependents);
1826                 svc = e->ge_vertex;
1827 
1828                 if (inst_running(svc)) {
1829                         if (err == RERR_RESTART || err == RERR_REFRESH) {
1830                                 vertex_send_event(svc,
1831                                     RESTARTER_EVENT_TYPE_STOP_RESET);
1832                         } else {
1833                                 vertex_send_event(svc,
1834                                     RESTARTER_EVENT_TYPE_STOP);
1835                         }
1836                 }
1837                 break;
1838 
1839         default:
1840 #ifndef NDEBUG
1841                 uu_warn("%s:%d: Unknown vertex type %d.\n", __FILE__, __LINE__,
1842                     v->gv_type);
1843 #endif
1844                 abort();
1845         }
1846 }
1847 
1848 void
1849 offline_vertex(graph_vertex_t *v)
1850 {
1851         scf_handle_t *h = libscf_handle_create_bound_loop();
1852         scf_instance_t *scf_inst = safe_scf_instance_create(h);
1853         scf_propertygroup_t *pg = safe_scf_pg_create(h);
1854         restarter_instance_state_t state, next_state;
1855         int r;
1856 


4381         graph_vertex_t *vv;
4382         graph_edge_t *e;
4383 
4384         assert(MUTEX_HELD(&dgraph_lock));
4385 
4386         for (e = uu_list_first(v->gv_dependents); e != NULL;
4387             e = uu_list_next(v->gv_dependents, e)) {
4388                 vv = e->ge_vertex;
4389                 if (vv->gv_type == GVT_INST) {
4390                         if ((vv->gv_flags & GV_CONFIGURED) == 0)
4391                                 continue;
4392 
4393                         if ((vv->gv_flags & GV_TOOFFLINE) == 0)
4394                                 continue;
4395 
4396                         if ((vv->gv_state == RESTARTER_STATE_ONLINE) ||
4397                             (vv->gv_state == RESTARTER_STATE_DEGRADED))
4398                                 return (B_FALSE);
4399                 } else {
4400                         /*
4401                          * Skip all excluded and optional_all dependencies
4402                          * and decide whether to offline the service based
4403                          * on restart_on attribute.
4404                          */
4405                         if (is_depgrp_bypassed(vv))
4406                                 continue;
4407 
4408                         /*
4409                          * For dependency groups or service vertices, keep
4410                          * traversing to see if instances are running.
4411                          */
4412                         if (insubtree_dependents_down(vv) == B_FALSE)
4413                                 return (B_FALSE);
4414                 }
4415         }
4416 
4417         return (B_TRUE);
4418 }
4419 
4420 /*
4421  * Returns true only if none of this service's dependents are 'up' -- online,
4422  * degraded, or offline.
4423  */


4948  * Propagate a start, stop event, or a satisfiability event.
4949  *
4950  * PROPAGATE_START and PROPAGATE_STOP simply propagate the transition event
4951  * to direct dependents.  PROPAGATE_SAT propagates a start then walks the
4952  * full dependent graph to check for newly satisfied nodes.  This is
4953  * necessary for cases when non-direct dependents may be effected but direct
4954  * dependents may not (e.g. for optional_all evaluations, see the
4955  * propagate_satbility() comments).
4956  *
4957  * PROPAGATE_SAT should be used whenever a non-running service moves into
4958  * a state which can satisfy optional dependencies, like disabled or
4959  * maintenance.
4960  */
4961 void
4962 graph_transition_propagate(graph_vertex_t *v, propagate_event_t type,
4963     restarter_error_t rerr)
4964 {
4965         if (type == PROPAGATE_STOP) {
4966                 graph_walk_dependents(v, propagate_stop, (void *)rerr);
4967         } else if (type == PROPAGATE_START || type == PROPAGATE_SAT) {
4968                 graph_walk_dependents(v, propagate_start, NULL);
4969 
4970                 if (type == PROPAGATE_SAT)
4971                         propagate_satbility(v);
4972         } else {
4973 #ifndef NDEBUG
4974                 uu_warn("%s:%d: Unexpected type value %d.\n",  __FILE__,
4975                     __LINE__, type);
4976 #endif
4977                 abort();
4978         }
4979 }
4980 
4981 /*
4982  * If a vertex for fmri exists and it is enabled, send _DISABLE to the
4983  * restarter.  If it is running, send _STOP.  Send _REMOVE_INSTANCE.  Delete
4984  * all property group dependencies, and the dependency on the restarter,
4985  * disposing of vertices as appropriate.  If other vertices depend on this
4986  * one, mark it unconfigured and return.  Otherwise remove the vertex.  Always
4987  * returns 0.
4988  */


5019                 err = uu_list_walk(v->gv_dependencies,
5020                     (uu_walk_fn_t *)append_svcs_or_insts, old_deps, 0);
5021                 assert(err == 0);
5022         }
5023 
5024         delete_instance_dependencies(v, B_TRUE);
5025 
5026         /*
5027          * Deleting an instance can both satisfy and unsatisfy dependencies,
5028          * depending on their type.  First propagate the stop as a RERR_RESTART
5029          * event -- deletion isn't a fault, just a normal stop.  This gives
5030          * dependent services the chance to do a clean shutdown.  Then, mark
5031          * the service as unconfigured and propagate the start event for the
5032          * optional_all dependencies that might have become satisfied.
5033          */
5034         graph_walk_dependents(v, propagate_stop, (void *)RERR_RESTART);
5035 
5036         v->gv_flags &= ~GV_CONFIGURED;
5037         v->gv_flags &= ~GV_DEATHROW;
5038 
5039         graph_walk_dependents(v, propagate_start, NULL);
5040         propagate_satbility(v);
5041 
5042         /*
5043          * If there are no (non-service) dependents, the vertex can be
5044          * completely removed.
5045          */
5046         if (v != milestone && v->gv_refs == 0 &&
5047             uu_list_numnodes(v->gv_dependents) == 1)
5048                 remove_inst_vertex(v);
5049 
5050         if (milestone > MILESTONE_NONE) {
5051                 void *cookie = NULL;
5052 
5053                 while ((e = uu_list_teardown(old_deps, &cookie)) != NULL) {
5054                         v = e->ge_vertex;
5055 
5056                         if (vertex_unref(v) == VERTEX_INUSE)
5057                                 while (eval_subgraph(v, h) == ECONNABORTED)
5058                                         libscf_handle_rebind(h);
5059 


5444         graph_vertex_t *v;
5445         int r;
5446 
5447         v = e->ge_vertex;
5448 
5449         /* If it's already in the subgraph, skip. */
5450         if (v->gv_flags & GV_TOOFFLINE)
5451                 return (UU_WALK_NEXT);
5452 
5453         switch (v->gv_type) {
5454         case GVT_INST:
5455                 /* If the instance is already disabled, skip it. */
5456                 if (!(v->gv_flags & GV_ENABLED))
5457                         return (UU_WALK_NEXT);
5458 
5459                 v->gv_flags |= GV_TOOFFLINE;
5460                 log_framework(LOG_DEBUG, "%s added to subtree\n", v->gv_name);
5461                 break;
5462         case GVT_GROUP:
5463                 /*
5464                  * Skip all excluded and optional_all dependencies and decide
5465                  * whether to offline the service based on restart_on attribute.
5466                  */
5467                 if (is_depgrp_bypassed(v))
5468                         return (UU_WALK_NEXT);
5469                 break;
5470         }
5471 
5472         r = uu_list_walk(v->gv_dependents, (uu_walk_fn_t *)mark_subtree, arg,
5473             0);
5474         assert(r == 0);
5475         return (UU_WALK_NEXT);
5476 }
5477 
5478 static int
5479 mark_subgraph(graph_edge_t *e, void *arg)
5480 {
5481         graph_vertex_t *v;
5482         int r;
5483         int optional = (int)arg;
5484 
5485         v = e->ge_vertex;




   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 
  22 /*
  23  * Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved.
  24  * Copyright (c) 2015, Syneto S.R.L. All rights reserved.
  25  * Copyright 2016 RackTop Systems.
  26  */
  27 
  28 /*
  29  * graph.c - master restarter graph engine
  30  *
  31  *   The graph engine keeps a dependency graph of all service instances on the
  32  *   system, as recorded in the repository.  It decides when services should
  33  *   be brought up or down based on service states and dependencies and sends
  34  *   commands to restarters to effect any changes.  It also executes
  35  *   administrator commands sent by svcadm via the repository.
  36  *
  37  *   The graph is stored in uu_list_t *dgraph and its vertices are
  38  *   graph_vertex_t's, each of which has a name and an integer id unique to
  39  *   its name (see dict.c).  A vertex's type attribute designates the type
  40  *   of object it represents: GVT_INST for service instances, GVT_SVC for
  41  *   service objects (since service instances may depend on another service,
  42  *   rather than service instance), GVT_FILE for files (which services may
  43  *   depend on), and GVT_GROUP for dependencies on multiple objects.  GVT_GROUP
  44  *   vertices are necessary because dependency lists may have particular
  45  *   grouping types (require any, require all, optional, or exclude) and


 191  *     access to stn_global
 192  */
 193 int32_t stn_global;
 194 /*
 195  * info_events_all holds a flag to override notification parameters and send
 196  * Information events for all state transitions.
 197  * same about the need of a mutex here.
 198  */
 199 int info_events_all;
 200 
 201 /*
 202  * Services in these states are not considered 'down' by the
 203  * milestone/shutdown code.
 204  */
 205 #define up_state(state) ((state) == RESTARTER_STATE_ONLINE || \
 206         (state) == RESTARTER_STATE_DEGRADED || \
 207         (state) == RESTARTER_STATE_OFFLINE)
 208 
 209 #define is_depgrp_bypassed(v) ((v->gv_type == GVT_GROUP) && \
 210         ((v->gv_depgroup == DEPGRP_EXCLUDE_ALL) || \

 211         (v->gv_restart < RERR_RESTART)))
 212 
 213 static uu_list_pool_t *graph_edge_pool, *graph_vertex_pool;
 214 static uu_list_t *dgraph;
 215 static pthread_mutex_t dgraph_lock;
 216 
 217 /*
 218  * milestone indicates the current subgraph.  When NULL, it is the entire
 219  * graph.  When MILESTONE_NONE, it is the empty graph.  Otherwise, it is all
 220  * services on which the target vertex depends.
 221  */
 222 static graph_vertex_t *milestone = NULL;
 223 static boolean_t initial_milestone_set = B_FALSE;
 224 static pthread_cond_t initial_milestone_cv = PTHREAD_COND_INITIALIZER;
 225 
 226 /* protected by dgraph_lock */
 227 static boolean_t sulogin_thread_running = B_FALSE;
 228 static boolean_t sulogin_running = B_FALSE;
 229 static boolean_t console_login_ready = B_FALSE;
 230 


1311  */
1312 static int
1313 optional_all_satisfied(graph_vertex_t *groupv, boolean_t satbility)
1314 {
1315         graph_edge_t *edge;
1316         graph_vertex_t *v;
1317         boolean_t any_qualified;
1318         boolean_t any_unsatisfied;
1319         int i;
1320 
1321         any_qualified = B_FALSE;
1322         any_unsatisfied = B_FALSE;
1323 
1324         for (edge = uu_list_first(groupv->gv_dependencies);
1325             edge != NULL;
1326             edge = uu_list_next(groupv->gv_dependencies, edge)) {
1327                 v = edge->ge_vertex;
1328 
1329                 switch (v->gv_type) {
1330                 case GVT_INST:
1331                         /* Skip missing instances */
1332                         if ((v->gv_flags & GV_CONFIGURED) == 0)

1333                                 continue;
1334 
1335                         if (v->gv_state == RESTARTER_STATE_MAINT)
1336                                 continue;
1337 



1338                         any_qualified = B_TRUE;
1339                         if (v->gv_state == RESTARTER_STATE_OFFLINE) {
1340                                 /*
1341                                  * For offline dependencies, treat unsatisfiable
1342                                  * as satisfied.
1343                                  */
1344                                 i = dependency_satisfied(v, B_TRUE);
1345                                 if (i == -1)
1346                                         i = 1;
1347                         } else if (v->gv_state == RESTARTER_STATE_DISABLED) {
1348                                 /*
1349                                  * The service is enabled, but hasn't
1350                                  * transitioned out of disabled yet.  Treat it
1351                                  * as unsatisfied (not unsatisfiable).
1352                                  */
1353                                 i = v->gv_flags & GV_ENABLED ? 0 : 1;
1354                         } else {
1355                                 i = dependency_satisfied(v, satbility);
1356                         }
1357                         break;
1358 
1359                 case GVT_FILE:
1360                         any_qualified = B_TRUE;
1361                         i = dependency_satisfied(v, satbility);
1362 
1363                         break;
1364 
1365                 case GVT_SVC: {
1366                         boolean_t svc_any_qualified;
1367                         boolean_t svc_satisfied;
1368                         boolean_t svc_satisfiable;
1369                         graph_vertex_t *v2;
1370                         graph_edge_t *e2;
1371 
1372                         svc_any_qualified = B_FALSE;
1373                         svc_satisfied = B_FALSE;
1374                         svc_satisfiable = B_FALSE;
1375 
1376                         for (e2 = uu_list_first(v->gv_dependencies);
1377                             e2 != NULL;
1378                             e2 = uu_list_next(v->gv_dependencies, e2)) {
1379                                 v2 = e2->ge_vertex;
1380                                 assert(v2->gv_type == GVT_INST);
1381 
1382                                 if ((v2->gv_flags & GV_CONFIGURED) == 0)


1383                                         continue;
1384 
1385                                 if (v2->gv_state == RESTARTER_STATE_MAINT)
1386                                         continue;
1387 



1388                                 svc_any_qualified = B_TRUE;
1389 
1390                                 if (v2->gv_state == RESTARTER_STATE_OFFLINE) {
1391                                         /*
1392                                          * For offline dependencies, treat
1393                                          * unsatisfiable as satisfied.
1394                                          */
1395                                         i = dependency_satisfied(v2, B_TRUE);
1396                                         if (i == -1)
1397                                                 i = 1;
1398                                 } else if (v2->gv_state ==
1399                                     RESTARTER_STATE_DISABLED) {
1400                                         i = v2->gv_flags & GV_ENABLED ? 0 : 1;
1401                                 } else {
1402                                         i = dependency_satisfied(v2, satbility);
1403                                 }
1404 
1405                                 if (i == 1) {
1406                                         svc_satisfied = B_TRUE;
1407                                         break;
1408                                 }
1409                                 if (i == 0)
1410                                         svc_satisfiable = B_TRUE;
1411                         }
1412 
1413                         if (!svc_any_qualified)
1414                                 continue;
1415                         any_qualified = B_TRUE;
1416                         if (svc_satisfied) {
1417                                 i = 1;
1418                         } else if (svc_satisfiable) {
1419                                 i = 0;
1420                         } else {


1582  * Decide whether v can satisfy a dependency.  v can either be a child of
1583  * a group vertex, or of an instance vertex.
1584  */
1585 static int
1586 dependency_satisfied(graph_vertex_t *v, boolean_t satbility)
1587 {
1588         switch (v->gv_type) {
1589         case GVT_INST:
1590                 if ((v->gv_flags & GV_CONFIGURED) == 0) {
1591                         if (v->gv_flags & GV_DEATHROW) {
1592                                 /*
1593                                  * A dependency on an instance with GV_DEATHROW
1594                                  * flag is always considered as satisfied.
1595                                  */
1596                                 return (1);
1597                         }
1598                         return (-1);
1599                 }
1600 
1601                 /*
1602                  * Any vertex with the GV_TODISABLE flag set is guaranteed
1603                  * to have its dependencies unsatisfiable.  Any vertex with
1604                  * GV_TOOFFLINE may be satisfied after it transitions.
1605                  */
1606                 if (v->gv_flags & GV_TODISABLE)
1607                         return (-1);
1608                 if (v->gv_flags & GV_TOOFFLINE)
1609                         return (0);
1610 
1611                 switch (v->gv_state) {
1612                 case RESTARTER_STATE_ONLINE:
1613                 case RESTARTER_STATE_DEGRADED:
1614                         return (1);
1615 
1616                 case RESTARTER_STATE_OFFLINE:
1617                         if (!satbility)
1618                                 return (0);
1619                         return (instance_satisfied(v, satbility) != -1 ?
1620                             0 : -1);
1621 
1622                 case RESTARTER_STATE_DISABLED:
1623                 case RESTARTER_STATE_MAINT:
1624                         return (-1);
1625 
1626                 case RESTARTER_STATE_UNINIT:
1627                         return (0);
1628 
1629                 default:


1705  *      |  A  |--------------->|  B  |-------------->|  C  |
1706  *      +-----+                +-----+               +-----+
1707  *
1708  *                                              offline -> maintenance
1709  *
1710  * If C goes into maintenance, it's not enough simply to check B.  Because A has
1711  * an optional dependency, what was previously an unsatisfiable situation is now
1712  * satisfied (B will never come online, even though its state hasn't changed).
1713  *
1714  * Note that it's not necessary to continue examining dependents after reaching
1715  * an optional_all dependency.  It's not possible for an optional_all dependency
1716  * to change satisfiability without also coming online, in which case we get a
1717  * start event and propagation continues naturally.  However, it does no harm to
1718  * continue propagating satisfiability (as it is a relatively rare event), and
1719  * keeps the walker code simple and generic.
1720  */
1721 /*ARGSUSED*/
1722 static int
1723 satbility_cb(graph_vertex_t *v, void *arg)
1724 {
1725         if (v->gv_flags & GV_TOOFFLINE)
1726                 return (UU_WALK_NEXT);
1727 
1728         if (v->gv_type == GVT_INST)
1729                 graph_start_if_satisfied(v);
1730 
1731         return (UU_WALK_NEXT);
1732 }
1733 
1734 static void
1735 propagate_satbility(graph_vertex_t *v)
1736 {
1737         graph_walk(v, WALK_DEPENDENTS, satbility_cb, NULL, NULL);
1738 }
1739 
1740 static void propagate_stop(graph_vertex_t *, void *);
1741 
1742 /*
1743  * propagate_start()
1744  *
1745  * This function is used to propagate a start event to the dependents of the
1746  * given vertex.  Any dependents that are offline but have their dependencies
1747  * satisfied are started.  Any dependents that are online and have restart_on
1748  * set to "restart" or "refresh" are restarted because their dependencies have
1749  * just changed.  This only happens with optional_all dependencies.
1750  */
1751 static void
1752 propagate_start(graph_vertex_t *v, void *arg)
1753 {
1754         restarter_error_t err = (restarter_error_t)arg;
1755 
1756         if (v->gv_flags & GV_TOOFFLINE)
1757                 return;
1758 
1759         switch (v->gv_type) {
1760         case GVT_INST:
1761                 /* Restarter */
1762                 if (inst_running(v)) {
1763                         if (err == RERR_RESTART || err == RERR_REFRESH) {
1764                                 vertex_send_event(v,
1765                                     RESTARTER_EVENT_TYPE_STOP_RESET);
1766                         }
1767                 } else {
1768                         graph_start_if_satisfied(v);
1769                 }
1770                 break;
1771 
1772         case GVT_GROUP:
1773                 if (v->gv_depgroup == DEPGRP_EXCLUDE_ALL) {
1774                         graph_walk_dependents(v, propagate_stop,
1775                             (void *)RERR_RESTART);
1776                         break;
1777                 }
1778                 err = v->gv_restart;
1779                 /* FALLTHROUGH */
1780 
1781         case GVT_SVC:
1782                 graph_walk_dependents(v, propagate_start, (void *)err);
1783                 break;
1784 
1785         case GVT_FILE:
1786 #ifndef NDEBUG
1787                 uu_warn("%s:%d: propagate_start() encountered GVT_FILE.\n",
1788                     __FILE__, __LINE__);
1789 #endif
1790                 abort();
1791                 /* NOTREACHED */
1792 
1793         default:
1794 #ifndef NDEBUG
1795                 uu_warn("%s:%d: Unknown vertex type %d.\n", __FILE__, __LINE__,
1796                     v->gv_type);
1797 #endif
1798                 abort();
1799         }
1800 }
1801 
1802 /*
1803  * propagate_stop()
1804  *
1805  * This function is used to propagate a stop event to the dependencies of the
1806  * given vertex.  Any dependencies that are online (or in degraded state) with
1807  * the restart_on property set to "restart" or "refresh" will be restarted as
1808  * their dependencies have just changed.  This only happens for optional_all
1809  * dependencies.
1810  */
1811 static void
1812 propagate_stop(graph_vertex_t *v, void *arg)
1813 {


1814         restarter_error_t err = (restarter_error_t)arg;
1815 
1816         if (v->gv_flags & GV_TOOFFLINE)
1817                 return;
1818 
1819         switch (v->gv_type) {
1820         case GVT_INST:
1821                 /* Restarter */
1822                 if (err > RERR_NONE && inst_running(v)) {
1823                         if (err == RERR_RESTART || err == RERR_REFRESH) {
1824                                 vertex_send_event(v,
1825                                     RESTARTER_EVENT_TYPE_STOP_RESET);
1826                         } else {
1827                                 vertex_send_event(v, RESTARTER_EVENT_TYPE_STOP);
1828                         }
1829                 }
1830                 break;
1831 
1832         case GVT_SVC:
1833                 graph_walk_dependents(v, propagate_stop, arg);
1834                 break;
1835 
1836         case GVT_FILE:
1837 #ifndef NDEBUG
1838                 uu_warn("%s:%d: propagate_stop() encountered GVT_FILE.\n",
1839                     __FILE__, __LINE__);
1840 #endif
1841                 abort();
1842                 /* NOTREACHED */
1843 
1844         case GVT_GROUP:
1845                 if (v->gv_depgroup == DEPGRP_EXCLUDE_ALL) {
1846                         graph_walk_dependents(v, propagate_start, NULL);
1847                         break;
1848                 }
1849 
1850                 if (err == RERR_NONE || err > v->gv_restart)
1851                         break;
1852 
1853                 graph_walk_dependents(v, propagate_stop, arg);












1854                 break;
1855 
1856         default:
1857 #ifndef NDEBUG
1858                 uu_warn("%s:%d: Unknown vertex type %d.\n", __FILE__, __LINE__,
1859                     v->gv_type);
1860 #endif
1861                 abort();
1862         }
1863 }
1864 
1865 void
1866 offline_vertex(graph_vertex_t *v)
1867 {
1868         scf_handle_t *h = libscf_handle_create_bound_loop();
1869         scf_instance_t *scf_inst = safe_scf_instance_create(h);
1870         scf_propertygroup_t *pg = safe_scf_pg_create(h);
1871         restarter_instance_state_t state, next_state;
1872         int r;
1873 


4398         graph_vertex_t *vv;
4399         graph_edge_t *e;
4400 
4401         assert(MUTEX_HELD(&dgraph_lock));
4402 
4403         for (e = uu_list_first(v->gv_dependents); e != NULL;
4404             e = uu_list_next(v->gv_dependents, e)) {
4405                 vv = e->ge_vertex;
4406                 if (vv->gv_type == GVT_INST) {
4407                         if ((vv->gv_flags & GV_CONFIGURED) == 0)
4408                                 continue;
4409 
4410                         if ((vv->gv_flags & GV_TOOFFLINE) == 0)
4411                                 continue;
4412 
4413                         if ((vv->gv_state == RESTARTER_STATE_ONLINE) ||
4414                             (vv->gv_state == RESTARTER_STATE_DEGRADED))
4415                                 return (B_FALSE);
4416                 } else {
4417                         /*
4418                          * Skip all excluded dependents and decide whether
4419                          * to offline the service based on the restart_on
4420                          * on attribute.
4421                          */
4422                         if (is_depgrp_bypassed(vv))
4423                                 continue;
4424 
4425                         /*
4426                          * For dependency groups or service vertices, keep
4427                          * traversing to see if instances are running.
4428                          */
4429                         if (insubtree_dependents_down(vv) == B_FALSE)
4430                                 return (B_FALSE);
4431                 }
4432         }
4433 
4434         return (B_TRUE);
4435 }
4436 
4437 /*
4438  * Returns true only if none of this service's dependents are 'up' -- online,
4439  * degraded, or offline.
4440  */


4965  * Propagate a start, stop event, or a satisfiability event.
4966  *
4967  * PROPAGATE_START and PROPAGATE_STOP simply propagate the transition event
4968  * to direct dependents.  PROPAGATE_SAT propagates a start then walks the
4969  * full dependent graph to check for newly satisfied nodes.  This is
4970  * necessary for cases when non-direct dependents may be effected but direct
4971  * dependents may not (e.g. for optional_all evaluations, see the
4972  * propagate_satbility() comments).
4973  *
4974  * PROPAGATE_SAT should be used whenever a non-running service moves into
4975  * a state which can satisfy optional dependencies, like disabled or
4976  * maintenance.
4977  */
4978 void
4979 graph_transition_propagate(graph_vertex_t *v, propagate_event_t type,
4980     restarter_error_t rerr)
4981 {
4982         if (type == PROPAGATE_STOP) {
4983                 graph_walk_dependents(v, propagate_stop, (void *)rerr);
4984         } else if (type == PROPAGATE_START || type == PROPAGATE_SAT) {
4985                 graph_walk_dependents(v, propagate_start, (void *)RERR_NONE);
4986 
4987                 if (type == PROPAGATE_SAT)
4988                         propagate_satbility(v);
4989         } else {
4990 #ifndef NDEBUG
4991                 uu_warn("%s:%d: Unexpected type value %d.\n",  __FILE__,
4992                     __LINE__, type);
4993 #endif
4994                 abort();
4995         }
4996 }
4997 
4998 /*
4999  * If a vertex for fmri exists and it is enabled, send _DISABLE to the
5000  * restarter.  If it is running, send _STOP.  Send _REMOVE_INSTANCE.  Delete
5001  * all property group dependencies, and the dependency on the restarter,
5002  * disposing of vertices as appropriate.  If other vertices depend on this
5003  * one, mark it unconfigured and return.  Otherwise remove the vertex.  Always
5004  * returns 0.
5005  */


5036                 err = uu_list_walk(v->gv_dependencies,
5037                     (uu_walk_fn_t *)append_svcs_or_insts, old_deps, 0);
5038                 assert(err == 0);
5039         }
5040 
5041         delete_instance_dependencies(v, B_TRUE);
5042 
5043         /*
5044          * Deleting an instance can both satisfy and unsatisfy dependencies,
5045          * depending on their type.  First propagate the stop as a RERR_RESTART
5046          * event -- deletion isn't a fault, just a normal stop.  This gives
5047          * dependent services the chance to do a clean shutdown.  Then, mark
5048          * the service as unconfigured and propagate the start event for the
5049          * optional_all dependencies that might have become satisfied.
5050          */
5051         graph_walk_dependents(v, propagate_stop, (void *)RERR_RESTART);
5052 
5053         v->gv_flags &= ~GV_CONFIGURED;
5054         v->gv_flags &= ~GV_DEATHROW;
5055 
5056         graph_walk_dependents(v, propagate_start, (void *)RERR_NONE);
5057         propagate_satbility(v);
5058 
5059         /*
5060          * If there are no (non-service) dependents, the vertex can be
5061          * completely removed.
5062          */
5063         if (v != milestone && v->gv_refs == 0 &&
5064             uu_list_numnodes(v->gv_dependents) == 1)
5065                 remove_inst_vertex(v);
5066 
5067         if (milestone > MILESTONE_NONE) {
5068                 void *cookie = NULL;
5069 
5070                 while ((e = uu_list_teardown(old_deps, &cookie)) != NULL) {
5071                         v = e->ge_vertex;
5072 
5073                         if (vertex_unref(v) == VERTEX_INUSE)
5074                                 while (eval_subgraph(v, h) == ECONNABORTED)
5075                                         libscf_handle_rebind(h);
5076 


5461         graph_vertex_t *v;
5462         int r;
5463 
5464         v = e->ge_vertex;
5465 
5466         /* If it's already in the subgraph, skip. */
5467         if (v->gv_flags & GV_TOOFFLINE)
5468                 return (UU_WALK_NEXT);
5469 
5470         switch (v->gv_type) {
5471         case GVT_INST:
5472                 /* If the instance is already disabled, skip it. */
5473                 if (!(v->gv_flags & GV_ENABLED))
5474                         return (UU_WALK_NEXT);
5475 
5476                 v->gv_flags |= GV_TOOFFLINE;
5477                 log_framework(LOG_DEBUG, "%s added to subtree\n", v->gv_name);
5478                 break;
5479         case GVT_GROUP:
5480                 /*
5481                  * Skip all excluded dependents and decide whether to offline
5482                  * the service based on the restart_on attribute.
5483                  */
5484                 if (is_depgrp_bypassed(v))
5485                         return (UU_WALK_NEXT);
5486                 break;
5487         }
5488 
5489         r = uu_list_walk(v->gv_dependents, (uu_walk_fn_t *)mark_subtree, arg,
5490             0);
5491         assert(r == 0);
5492         return (UU_WALK_NEXT);
5493 }
5494 
5495 static int
5496 mark_subgraph(graph_edge_t *e, void *arg)
5497 {
5498         graph_vertex_t *v;
5499         int r;
5500         int optional = (int)arg;
5501 
5502         v = e->ge_vertex;