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


   4  * The contents of this file are subject to the terms of the
   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  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  23  * Use is subject to license terms.


  24  */
  25 
  26 
  27 /*
  28  * transition.c - Graph State Machine
  29  *
  30  * The graph state machine is implemented here, with a typical approach
  31  * of a function per state.  Separating the implementation allows more
  32  * clarity into the actions taken on notification of state change, as well
  33  * as a place for future expansion including hooks for configurable actions.
  34  * All functions are called with dgraph_lock held.
  35  *
  36  * The start action for this state machine is not explicit.  The states
  37  * (ONLINE and DEGRADED) which need to know when they're entering the state
  38  * due to a daemon restart implement this understanding by checking for
  39  * transition from uninitialized.  In the future, this would likely be better
  40  * as an explicit start action instead of relying on an overloaded transition.
  41  *
  42  * All gt_enter functions use the same set of return codes.
  43  *    0              success


 120         /* instance transitioning to maintenance is considered disabled */
 121         v->gv_flags &= ~GV_TODISABLE;
 122         v->gv_flags &= ~GV_TOOFFLINE;
 123 
 124         if (gt_running(old_state)) {
 125                 /*
 126                  * Handle state change during instance disabling.
 127                  * Propagate offline to the new exposed leaves.
 128                  */
 129                 if (to_offline) {
 130                         log_framework(LOG_DEBUG, "%s removed from subtree\n",
 131                             v->gv_name);
 132 
 133                         graph_offline_subtree_leaves(v, (void *)h);
 134                 }
 135 
 136                 log_framework(LOG_DEBUG, "Propagating maintenance (stop) of "
 137                     "%s.\n", v->gv_name);
 138 
 139                 graph_transition_propagate(v, PROPAGATE_STOP, rerr);







 140         } else {
 141                 log_framework(LOG_DEBUG, "Propagating maintenance of %s.\n",
 142                     v->gv_name);
 143 
 144                 graph_transition_propagate(v, PROPAGATE_SAT, rerr);
 145         }
 146 
 147         graph_transition_sulogin(RESTARTER_STATE_MAINT, old_state);
 148         return (0);
 149 }
 150 
 151 /* ARGSUSED */
 152 static int
 153 gt_enter_offline(scf_handle_t *h, graph_vertex_t *v,
 154     restarter_instance_state_t old_state, restarter_error_t rerr)
 155 {
 156         int to_offline = v->gv_flags & GV_TOOFFLINE;
 157 
 158         v->gv_flags &= ~GV_TOOFFLINE;
 159 


 250                  * case we've just disabled an instance that was part of a
 251                  * subtree.
 252                  */
 253                 if (to_offline) {
 254                         log_framework(LOG_DEBUG, "%s removed from subtree\n",
 255                             v->gv_name);
 256 
 257                         /*
 258                          * Handle state change during instance disabling.
 259                          * Propagate offline to the new exposed leaves.
 260                          */
 261                         graph_offline_subtree_leaves(v, (void *)h);
 262                 }
 263 
 264 
 265                 log_framework(LOG_DEBUG, "Propagating stop of %s.\n",
 266                     v->gv_name);
 267 
 268                 graph_transition_propagate(v, PROPAGATE_STOP, rerr);
 269 






 270         } else {
 271                 log_framework(LOG_DEBUG, "Propagating disable of %s.\n",
 272                     v->gv_name);
 273 
 274                 graph_transition_propagate(v, PROPAGATE_SAT, rerr);
 275         }
 276 
 277         graph_transition_sulogin(RESTARTER_STATE_DISABLED, old_state);
 278         return (0);
 279 }
 280 
 281 static int
 282 gt_internal_online_or_degraded(scf_handle_t *h, graph_vertex_t *v,
 283     restarter_instance_state_t old_state, restarter_error_t rerr)
 284 {
 285         int r;
 286 
 287         /*
 288          * If the instance has just come up, update the start
 289          * snapshot.


 309                         break;
 310 
 311                 case ECONNABORTED:
 312                         return (ECONNABORTED);
 313 
 314                 case EACCES:
 315                 case ENOTSUP:
 316                 default:
 317                         bad_error("libscf_snapshots_poststart", r);
 318                 }
 319         }
 320 
 321         if (!(v->gv_flags & GV_ENABLED)) {
 322                 vertex_send_event(v, RESTARTER_EVENT_TYPE_DISABLE);
 323         } else if (v->gv_flags & GV_TOOFFLINE) {
 324                 /*
 325                  * If the vertex has the GV_TOOFFLINE flag set then that's
 326                  * because the instance was transitioning from offline to
 327                  * online and the reverse disable algorithm doesn't offline
 328                  * those instances because it was already appearing offline.
 329                  * So do it now.
 330                  */

 331                 offline_vertex(v);
 332         }
 333 
 334         if (gt_running(old_state) == 0) {
 335                 log_framework(LOG_DEBUG, "Propagating start of %s.\n",
 336                     v->gv_name);
 337 
 338                 graph_transition_propagate(v, PROPAGATE_START, rerr);
 339         } else if (rerr == RERR_REFRESH) {
 340                 /* For refresh we'll get a message sans state change */
 341 
 342                 log_framework(LOG_DEBUG, "Propagating refresh of %s.\n",
 343                     v->gv_name);
 344 
 345                 graph_transition_propagate(v, PROPAGATE_STOP, rerr);
 346         }
 347 
 348         return (0);
 349 }
 350 




   4  * The contents of this file are subject to the terms of the
   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  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  23  * Use is subject to license terms.
  24  *
  25  * Copyright 2016 RackTop Systems.
  26  */
  27 
  28 
  29 /*
  30  * transition.c - Graph State Machine
  31  *
  32  * The graph state machine is implemented here, with a typical approach
  33  * of a function per state.  Separating the implementation allows more
  34  * clarity into the actions taken on notification of state change, as well
  35  * as a place for future expansion including hooks for configurable actions.
  36  * All functions are called with dgraph_lock held.
  37  *
  38  * The start action for this state machine is not explicit.  The states
  39  * (ONLINE and DEGRADED) which need to know when they're entering the state
  40  * due to a daemon restart implement this understanding by checking for
  41  * transition from uninitialized.  In the future, this would likely be better
  42  * as an explicit start action instead of relying on an overloaded transition.
  43  *
  44  * All gt_enter functions use the same set of return codes.
  45  *    0              success


 122         /* instance transitioning to maintenance is considered disabled */
 123         v->gv_flags &= ~GV_TODISABLE;
 124         v->gv_flags &= ~GV_TOOFFLINE;
 125 
 126         if (gt_running(old_state)) {
 127                 /*
 128                  * Handle state change during instance disabling.
 129                  * Propagate offline to the new exposed leaves.
 130                  */
 131                 if (to_offline) {
 132                         log_framework(LOG_DEBUG, "%s removed from subtree\n",
 133                             v->gv_name);
 134 
 135                         graph_offline_subtree_leaves(v, (void *)h);
 136                 }
 137 
 138                 log_framework(LOG_DEBUG, "Propagating maintenance (stop) of "
 139                     "%s.\n", v->gv_name);
 140 
 141                 graph_transition_propagate(v, PROPAGATE_STOP, rerr);
 142 
 143                 /*
 144                  * The maintenance transition may satisfy optional_all/restart
 145                  * dependencies and should be propagated to determine
 146                  * whether new dependents are satisfiable.
 147                  */
 148                 graph_transition_propagate(v, PROPAGATE_SAT, rerr);
 149         } else {
 150                 log_framework(LOG_DEBUG, "Propagating maintenance of %s.\n",
 151                     v->gv_name);
 152 
 153                 graph_transition_propagate(v, PROPAGATE_SAT, rerr);
 154         }
 155 
 156         graph_transition_sulogin(RESTARTER_STATE_MAINT, old_state);
 157         return (0);
 158 }
 159 
 160 /* ARGSUSED */
 161 static int
 162 gt_enter_offline(scf_handle_t *h, graph_vertex_t *v,
 163     restarter_instance_state_t old_state, restarter_error_t rerr)
 164 {
 165         int to_offline = v->gv_flags & GV_TOOFFLINE;
 166 
 167         v->gv_flags &= ~GV_TOOFFLINE;
 168 


 259                  * case we've just disabled an instance that was part of a
 260                  * subtree.
 261                  */
 262                 if (to_offline) {
 263                         log_framework(LOG_DEBUG, "%s removed from subtree\n",
 264                             v->gv_name);
 265 
 266                         /*
 267                          * Handle state change during instance disabling.
 268                          * Propagate offline to the new exposed leaves.
 269                          */
 270                         graph_offline_subtree_leaves(v, (void *)h);
 271                 }
 272 
 273 
 274                 log_framework(LOG_DEBUG, "Propagating stop of %s.\n",
 275                     v->gv_name);
 276 
 277                 graph_transition_propagate(v, PROPAGATE_STOP, rerr);
 278 
 279                 /*
 280                  * The disable transition may satisfy optional_all/restart
 281                  * dependencies and should be propagated to determine
 282                  * whether new dependents are satisfiable.
 283                  */
 284                 graph_transition_propagate(v, PROPAGATE_SAT, rerr);
 285         } else {
 286                 log_framework(LOG_DEBUG, "Propagating disable of %s.\n",
 287                     v->gv_name);
 288 
 289                 graph_transition_propagate(v, PROPAGATE_SAT, rerr);
 290         }
 291 
 292         graph_transition_sulogin(RESTARTER_STATE_DISABLED, old_state);
 293         return (0);
 294 }
 295 
 296 static int
 297 gt_internal_online_or_degraded(scf_handle_t *h, graph_vertex_t *v,
 298     restarter_instance_state_t old_state, restarter_error_t rerr)
 299 {
 300         int r;
 301 
 302         /*
 303          * If the instance has just come up, update the start
 304          * snapshot.


 324                         break;
 325 
 326                 case ECONNABORTED:
 327                         return (ECONNABORTED);
 328 
 329                 case EACCES:
 330                 case ENOTSUP:
 331                 default:
 332                         bad_error("libscf_snapshots_poststart", r);
 333                 }
 334         }
 335 
 336         if (!(v->gv_flags & GV_ENABLED)) {
 337                 vertex_send_event(v, RESTARTER_EVENT_TYPE_DISABLE);
 338         } else if (v->gv_flags & GV_TOOFFLINE) {
 339                 /*
 340                  * If the vertex has the GV_TOOFFLINE flag set then that's
 341                  * because the instance was transitioning from offline to
 342                  * online and the reverse disable algorithm doesn't offline
 343                  * those instances because it was already appearing offline.
 344                  * Try to do it now.
 345                  */
 346                 if (insubtree_dependents_down(v))
 347                         offline_vertex(v);
 348         }
 349 
 350         if (gt_running(old_state) == 0) {
 351                 log_framework(LOG_DEBUG, "Propagating start of %s.\n",
 352                     v->gv_name);
 353 
 354                 graph_transition_propagate(v, PROPAGATE_START, rerr);
 355         } else if (rerr == RERR_REFRESH) {
 356                 /* For refresh we'll get a message sans state change */
 357 
 358                 log_framework(LOG_DEBUG, "Propagating refresh of %s.\n",
 359                     v->gv_name);
 360 
 361                 graph_transition_propagate(v, PROPAGATE_STOP, rerr);
 362         }
 363 
 364         return (0);
 365 }
 366