199b44c3bSlianep /*
299b44c3bSlianep * CDDL HEADER START
399b44c3bSlianep *
499b44c3bSlianep * The contents of this file are subject to the terms of the
599b44c3bSlianep * Common Development and Distribution License (the "License").
699b44c3bSlianep * You may not use this file except in compliance with the License.
799b44c3bSlianep *
899b44c3bSlianep * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
999b44c3bSlianep * or http://www.opensolaris.org/os/licensing.
1099b44c3bSlianep * See the License for the specific language governing permissions
1199b44c3bSlianep * and limitations under the License.
1299b44c3bSlianep *
1399b44c3bSlianep * When distributing Covered Code, include this CDDL HEADER in each
1499b44c3bSlianep * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
1599b44c3bSlianep * If applicable, add the following below this CDDL HEADER, with the
1699b44c3bSlianep * fields enclosed by brackets "[]" replaced with your own identifying
1799b44c3bSlianep * information: Portions Copyright [yyyy] [name of copyright owner]
1899b44c3bSlianep *
1999b44c3bSlianep * CDDL HEADER END
2099b44c3bSlianep */
2199b44c3bSlianep /*
22*845e9415SRenaud Manus * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
2399b44c3bSlianep * Use is subject to license terms.
2499b44c3bSlianep */
2599b44c3bSlianep
2699b44c3bSlianep
2799b44c3bSlianep /*
2899b44c3bSlianep * transition.c - Graph State Machine
2999b44c3bSlianep *
3099b44c3bSlianep * The graph state machine is implemented here, with a typical approach
3199b44c3bSlianep * of a function per state. Separating the implementation allows more
3299b44c3bSlianep * clarity into the actions taken on notification of state change, as well
3399b44c3bSlianep * as a place for future expansion including hooks for configurable actions.
3499b44c3bSlianep * All functions are called with dgraph_lock held.
3599b44c3bSlianep *
3699b44c3bSlianep * The start action for this state machine is not explicit. The states
3756e23938Sbustos * (ONLINE and DEGRADED) which need to know when they're entering the state
3899b44c3bSlianep * due to a daemon restart implement this understanding by checking for
3999b44c3bSlianep * transition from uninitialized. In the future, this would likely be better
4099b44c3bSlianep * as an explicit start action instead of relying on an overloaded transition.
4199b44c3bSlianep *
4299b44c3bSlianep * All gt_enter functions use the same set of return codes.
4399b44c3bSlianep * 0 success
4499b44c3bSlianep * ECONNABORTED repository connection aborted
4599b44c3bSlianep */
4699b44c3bSlianep
4799b44c3bSlianep #include "startd.h"
4899b44c3bSlianep
4999b44c3bSlianep static int
gt_running(restarter_instance_state_t state)5099b44c3bSlianep gt_running(restarter_instance_state_t state)
5199b44c3bSlianep {
5299b44c3bSlianep if (state == RESTARTER_STATE_ONLINE ||
5399b44c3bSlianep state == RESTARTER_STATE_DEGRADED)
5499b44c3bSlianep return (1);
5599b44c3bSlianep
5699b44c3bSlianep return (0);
5799b44c3bSlianep }
5899b44c3bSlianep
5999b44c3bSlianep static int
gt_enter_uninit(scf_handle_t * h,graph_vertex_t * v,restarter_instance_state_t old_state,restarter_error_t rerr)6099b44c3bSlianep gt_enter_uninit(scf_handle_t *h, graph_vertex_t *v,
6199b44c3bSlianep restarter_instance_state_t old_state, restarter_error_t rerr)
6299b44c3bSlianep {
6399b44c3bSlianep int err;
6499b44c3bSlianep scf_instance_t *inst;
6599b44c3bSlianep
6699b44c3bSlianep /* Initialize instance by refreshing it. */
6799b44c3bSlianep
6899b44c3bSlianep err = libscf_fmri_get_instance(h, v->gv_name, &inst);
6999b44c3bSlianep switch (err) {
7099b44c3bSlianep case 0:
7199b44c3bSlianep break;
7299b44c3bSlianep
7399b44c3bSlianep case ECONNABORTED:
7499b44c3bSlianep return (ECONNABORTED);
7599b44c3bSlianep
7699b44c3bSlianep case ENOENT:
7799b44c3bSlianep return (0);
7899b44c3bSlianep
7999b44c3bSlianep case EINVAL:
8099b44c3bSlianep case ENOTSUP:
8199b44c3bSlianep default:
8299b44c3bSlianep bad_error("libscf_fmri_get_instance", err);
8399b44c3bSlianep }
8499b44c3bSlianep
8599b44c3bSlianep err = refresh_vertex(v, inst);
8699b44c3bSlianep if (err == 0)
8799b44c3bSlianep graph_enable_by_vertex(v, v->gv_flags & GV_ENABLED, 0);
8899b44c3bSlianep
8999b44c3bSlianep scf_instance_destroy(inst);
9099b44c3bSlianep
9199b44c3bSlianep /* If the service was running, propagate a stop event. */
9299b44c3bSlianep if (gt_running(old_state)) {
9399b44c3bSlianep log_framework(LOG_DEBUG, "Propagating stop of %s.\n",
9499b44c3bSlianep v->gv_name);
9599b44c3bSlianep
96cd3bce3eSlianep graph_transition_propagate(v, PROPAGATE_STOP, rerr);
9799b44c3bSlianep }
9899b44c3bSlianep
9999b44c3bSlianep graph_transition_sulogin(RESTARTER_STATE_UNINIT, old_state);
10099b44c3bSlianep return (0);
10199b44c3bSlianep }
10299b44c3bSlianep
10356e23938Sbustos /* ARGSUSED */
10499b44c3bSlianep static int
gt_enter_maint(scf_handle_t * h,graph_vertex_t * v,restarter_instance_state_t old_state,restarter_error_t rerr)10599b44c3bSlianep gt_enter_maint(scf_handle_t *h, graph_vertex_t *v,
10699b44c3bSlianep restarter_instance_state_t old_state, restarter_error_t rerr)
10799b44c3bSlianep {
108207246e9SRenaud Manus int to_offline = v->gv_flags & GV_TOOFFLINE;
109207246e9SRenaud Manus
110cd3bce3eSlianep /*
111cd3bce3eSlianep * If the service was running, propagate a stop event. If the
112cd3bce3eSlianep * service was not running the maintenance transition may satisfy
113cd3bce3eSlianep * optional dependencies and should be propagated to determine
114cd3bce3eSlianep * whether new dependents are satisfiable.
115aca380d7SRenaud Manus * Instances that transition to maintenance and have the GV_TOOFFLINE
116aca380d7SRenaud Manus * flag are special because they can expose new subtree leaves so
117aca380d7SRenaud Manus * propagate the offline to the instance dependencies.
118cd3bce3eSlianep */
119207246e9SRenaud Manus
120207246e9SRenaud Manus /* instance transitioning to maintenance is considered disabled */
121207246e9SRenaud Manus v->gv_flags &= ~GV_TODISABLE;
122207246e9SRenaud Manus v->gv_flags &= ~GV_TOOFFLINE;
123207246e9SRenaud Manus
12499b44c3bSlianep if (gt_running(old_state)) {
125aca380d7SRenaud Manus /*
126aca380d7SRenaud Manus * Handle state change during instance disabling.
127aca380d7SRenaud Manus * Propagate offline to the new exposed leaves.
128aca380d7SRenaud Manus */
129207246e9SRenaud Manus if (to_offline) {
130aca380d7SRenaud Manus log_framework(LOG_DEBUG, "%s removed from subtree\n",
131aca380d7SRenaud Manus v->gv_name);
132207246e9SRenaud Manus
133aca380d7SRenaud Manus graph_offline_subtree_leaves(v, (void *)h);
134aca380d7SRenaud Manus }
135aca380d7SRenaud Manus
136cd3bce3eSlianep log_framework(LOG_DEBUG, "Propagating maintenance (stop) of "
137cd3bce3eSlianep "%s.\n", v->gv_name);
13899b44c3bSlianep
139cd3bce3eSlianep graph_transition_propagate(v, PROPAGATE_STOP, rerr);
140cd3bce3eSlianep } else {
14199b44c3bSlianep log_framework(LOG_DEBUG, "Propagating maintenance of %s.\n",
14299b44c3bSlianep v->gv_name);
14399b44c3bSlianep
144cd3bce3eSlianep graph_transition_propagate(v, PROPAGATE_SAT, rerr);
14599b44c3bSlianep }
14699b44c3bSlianep
14799b44c3bSlianep graph_transition_sulogin(RESTARTER_STATE_MAINT, old_state);
14899b44c3bSlianep return (0);
14999b44c3bSlianep }
15099b44c3bSlianep
15156e23938Sbustos /* ARGSUSED */
15299b44c3bSlianep static int
gt_enter_offline(scf_handle_t * h,graph_vertex_t * v,restarter_instance_state_t old_state,restarter_error_t rerr)15399b44c3bSlianep gt_enter_offline(scf_handle_t *h, graph_vertex_t *v,
15499b44c3bSlianep restarter_instance_state_t old_state, restarter_error_t rerr)
15599b44c3bSlianep {
156207246e9SRenaud Manus int to_offline = v->gv_flags & GV_TOOFFLINE;
157207246e9SRenaud Manus
158207246e9SRenaud Manus v->gv_flags &= ~GV_TOOFFLINE;
159207246e9SRenaud Manus
16099b44c3bSlianep /*
16199b44c3bSlianep * If the instance should be enabled, see if we can start it.
16299b44c3bSlianep * Otherwise send a disable command.
163aca380d7SRenaud Manus * If a instance has the GV_TOOFFLINE flag set then it must
164aca380d7SRenaud Manus * remains offline until the disable process completes.
16599b44c3bSlianep */
16699b44c3bSlianep if (v->gv_flags & GV_ENABLED) {
167207246e9SRenaud Manus if (to_offline == 0)
16899b44c3bSlianep graph_start_if_satisfied(v);
16999b44c3bSlianep } else {
17099b44c3bSlianep if (gt_running(old_state) && v->gv_post_disable_f)
17199b44c3bSlianep v->gv_post_disable_f();
172aca380d7SRenaud Manus
17399b44c3bSlianep vertex_send_event(v, RESTARTER_EVENT_TYPE_DISABLE);
17499b44c3bSlianep }
17599b44c3bSlianep
17673b709eaSrm88369 /*
17773b709eaSrm88369 * If the service was running, propagate a stop event. If the
17873b709eaSrm88369 * service was not running the offline transition may satisfy
17973b709eaSrm88369 * optional dependencies and should be propagated to determine
18073b709eaSrm88369 * whether new dependents are satisfiable.
181aca380d7SRenaud Manus * Instances that transition to offline and have the GV_TOOFFLINE flag
182aca380d7SRenaud Manus * are special because they can expose new subtree leaves so propagate
183aca380d7SRenaud Manus * the offline to the instance dependencies.
18473b709eaSrm88369 */
18599b44c3bSlianep if (gt_running(old_state)) {
186aca380d7SRenaud Manus /*
187aca380d7SRenaud Manus * Handle state change during instance disabling.
188aca380d7SRenaud Manus * Propagate offline to the new exposed leaves.
189aca380d7SRenaud Manus */
190207246e9SRenaud Manus if (to_offline) {
191aca380d7SRenaud Manus log_framework(LOG_DEBUG, "%s removed from subtree\n",
192aca380d7SRenaud Manus v->gv_name);
193207246e9SRenaud Manus
194aca380d7SRenaud Manus graph_offline_subtree_leaves(v, (void *)h);
195aca380d7SRenaud Manus }
196aca380d7SRenaud Manus
19799b44c3bSlianep log_framework(LOG_DEBUG, "Propagating stop of %s.\n",
19899b44c3bSlianep v->gv_name);
19999b44c3bSlianep
200cd3bce3eSlianep graph_transition_propagate(v, PROPAGATE_STOP, rerr);
201207246e9SRenaud Manus
202207246e9SRenaud Manus /*
203207246e9SRenaud Manus * The offline transition may satisfy require_any/restart
204207246e9SRenaud Manus * dependencies and should be propagated to determine
205207246e9SRenaud Manus * whether new dependents are satisfiable.
206207246e9SRenaud Manus */
207207246e9SRenaud Manus graph_transition_propagate(v, PROPAGATE_SAT, rerr);
20873b709eaSrm88369 } else {
20973b709eaSrm88369 log_framework(LOG_DEBUG, "Propagating offline of %s.\n",
21073b709eaSrm88369 v->gv_name);
21173b709eaSrm88369
21273b709eaSrm88369 graph_transition_propagate(v, PROPAGATE_SAT, rerr);
21399b44c3bSlianep }
21499b44c3bSlianep
21599b44c3bSlianep graph_transition_sulogin(RESTARTER_STATE_OFFLINE, old_state);
21699b44c3bSlianep return (0);
21799b44c3bSlianep }
21899b44c3bSlianep
21956e23938Sbustos /* ARGSUSED */
22099b44c3bSlianep static int
gt_enter_disabled(scf_handle_t * h,graph_vertex_t * v,restarter_instance_state_t old_state,restarter_error_t rerr)22199b44c3bSlianep gt_enter_disabled(scf_handle_t *h, graph_vertex_t *v,
22299b44c3bSlianep restarter_instance_state_t old_state, restarter_error_t rerr)
22399b44c3bSlianep {
224207246e9SRenaud Manus int to_offline = v->gv_flags & GV_TOOFFLINE;
225207246e9SRenaud Manus
226207246e9SRenaud Manus v->gv_flags &= ~GV_TODISABLE;
227207246e9SRenaud Manus v->gv_flags &= ~GV_TOOFFLINE;
228aca380d7SRenaud Manus
22999b44c3bSlianep /*
23099b44c3bSlianep * If the instance should be disabled, no problem. Otherwise,
23199b44c3bSlianep * send an enable command, which should result in the instance
232aca380d7SRenaud Manus * moving to OFFLINE unless the instance is part of a subtree
233aca380d7SRenaud Manus * (non root) and in this case the result is unpredictable.
23499b44c3bSlianep */
23599b44c3bSlianep if (v->gv_flags & GV_ENABLED) {
23699b44c3bSlianep vertex_send_event(v, RESTARTER_EVENT_TYPE_ENABLE);
23799b44c3bSlianep } else if (gt_running(old_state) && v->gv_post_disable_f) {
23899b44c3bSlianep v->gv_post_disable_f();
23999b44c3bSlianep }
24099b44c3bSlianep
24199b44c3bSlianep /*
242cd3bce3eSlianep * If the service was running, propagate this as a stop. If the
243cd3bce3eSlianep * service was not running the disabled transition may satisfy
244cd3bce3eSlianep * optional dependencies and should be propagated to determine
245cd3bce3eSlianep * whether new dependents are satisfiable.
24699b44c3bSlianep */
24799b44c3bSlianep if (gt_running(old_state)) {
248aca380d7SRenaud Manus /*
249aca380d7SRenaud Manus * We need to propagate the offline to new exposed leaves in
250aca380d7SRenaud Manus * case we've just disabled an instance that was part of a
251aca380d7SRenaud Manus * subtree.
252aca380d7SRenaud Manus */
253207246e9SRenaud Manus if (to_offline) {
254aca380d7SRenaud Manus log_framework(LOG_DEBUG, "%s removed from subtree\n",
255aca380d7SRenaud Manus v->gv_name);
256aca380d7SRenaud Manus
257aca380d7SRenaud Manus /*
258aca380d7SRenaud Manus * Handle state change during instance disabling.
259aca380d7SRenaud Manus * Propagate offline to the new exposed leaves.
260aca380d7SRenaud Manus */
261aca380d7SRenaud Manus graph_offline_subtree_leaves(v, (void *)h);
262aca380d7SRenaud Manus }
263aca380d7SRenaud Manus
264aca380d7SRenaud Manus
26599b44c3bSlianep log_framework(LOG_DEBUG, "Propagating stop of %s.\n",
26699b44c3bSlianep v->gv_name);
26799b44c3bSlianep
268cd3bce3eSlianep graph_transition_propagate(v, PROPAGATE_STOP, rerr);
26999b44c3bSlianep
270cd3bce3eSlianep } else {
27199b44c3bSlianep log_framework(LOG_DEBUG, "Propagating disable of %s.\n",
27299b44c3bSlianep v->gv_name);
27399b44c3bSlianep
274cd3bce3eSlianep graph_transition_propagate(v, PROPAGATE_SAT, rerr);
27599b44c3bSlianep }
27699b44c3bSlianep
27799b44c3bSlianep graph_transition_sulogin(RESTARTER_STATE_DISABLED, old_state);
27899b44c3bSlianep return (0);
27999b44c3bSlianep }
28099b44c3bSlianep
28199b44c3bSlianep static int
gt_internal_online_or_degraded(scf_handle_t * h,graph_vertex_t * v,restarter_instance_state_t old_state,restarter_error_t rerr)28299b44c3bSlianep gt_internal_online_or_degraded(scf_handle_t *h, graph_vertex_t *v,
28399b44c3bSlianep restarter_instance_state_t old_state, restarter_error_t rerr)
28499b44c3bSlianep {
28599b44c3bSlianep int r;
28699b44c3bSlianep
28799b44c3bSlianep /*
28899b44c3bSlianep * If the instance has just come up, update the start
28999b44c3bSlianep * snapshot.
29099b44c3bSlianep */
29199b44c3bSlianep if (gt_running(old_state) == 0) {
29299b44c3bSlianep /*
29399b44c3bSlianep * Don't fire if we're just recovering state
29499b44c3bSlianep * after a restart.
29599b44c3bSlianep */
29699b44c3bSlianep if (old_state != RESTARTER_STATE_UNINIT &&
29799b44c3bSlianep v->gv_post_online_f)
29899b44c3bSlianep v->gv_post_online_f();
29999b44c3bSlianep
30099b44c3bSlianep r = libscf_snapshots_poststart(h, v->gv_name, B_TRUE);
30199b44c3bSlianep switch (r) {
30299b44c3bSlianep case 0:
30399b44c3bSlianep case ENOENT:
30499b44c3bSlianep /*
30599b44c3bSlianep * If ENOENT, the instance must have been
30699b44c3bSlianep * deleted. Pretend we were successful since
30799b44c3bSlianep * we should get a delete event later.
30899b44c3bSlianep */
30999b44c3bSlianep break;
31099b44c3bSlianep
31199b44c3bSlianep case ECONNABORTED:
31299b44c3bSlianep return (ECONNABORTED);
31399b44c3bSlianep
31499b44c3bSlianep case EACCES:
31599b44c3bSlianep case ENOTSUP:
31699b44c3bSlianep default:
31799b44c3bSlianep bad_error("libscf_snapshots_poststart", r);
31899b44c3bSlianep }
31999b44c3bSlianep }
320*845e9415SRenaud Manus
321*845e9415SRenaud Manus if (!(v->gv_flags & GV_ENABLED)) {
32299b44c3bSlianep vertex_send_event(v, RESTARTER_EVENT_TYPE_DISABLE);
323*845e9415SRenaud Manus } else if (v->gv_flags & GV_TOOFFLINE) {
324*845e9415SRenaud Manus /*
325*845e9415SRenaud Manus * If the vertex has the GV_TOOFFLINE flag set then that's
326*845e9415SRenaud Manus * because the instance was transitioning from offline to
327*845e9415SRenaud Manus * online and the reverse disable algorithm doesn't offline
328*845e9415SRenaud Manus * those instances because it was already appearing offline.
329*845e9415SRenaud Manus * So do it now.
330*845e9415SRenaud Manus */
331*845e9415SRenaud Manus offline_vertex(v);
332*845e9415SRenaud Manus }
33399b44c3bSlianep
33499b44c3bSlianep if (gt_running(old_state) == 0) {
33599b44c3bSlianep log_framework(LOG_DEBUG, "Propagating start of %s.\n",
33699b44c3bSlianep v->gv_name);
33799b44c3bSlianep
338cd3bce3eSlianep graph_transition_propagate(v, PROPAGATE_START, rerr);
33999b44c3bSlianep } else if (rerr == RERR_REFRESH) {
34099b44c3bSlianep /* For refresh we'll get a message sans state change */
34199b44c3bSlianep
34299b44c3bSlianep log_framework(LOG_DEBUG, "Propagating refresh of %s.\n",
34399b44c3bSlianep v->gv_name);
34499b44c3bSlianep
345cd3bce3eSlianep graph_transition_propagate(v, PROPAGATE_STOP, rerr);
34699b44c3bSlianep }
34799b44c3bSlianep
34899b44c3bSlianep return (0);
34999b44c3bSlianep }
35099b44c3bSlianep
35199b44c3bSlianep static int
gt_enter_online(scf_handle_t * h,graph_vertex_t * v,restarter_instance_state_t old_state,restarter_error_t rerr)35299b44c3bSlianep gt_enter_online(scf_handle_t *h, graph_vertex_t *v,
35399b44c3bSlianep restarter_instance_state_t old_state, restarter_error_t rerr)
35499b44c3bSlianep {
35599b44c3bSlianep int r;
35699b44c3bSlianep
35799b44c3bSlianep r = gt_internal_online_or_degraded(h, v, old_state, rerr);
35899b44c3bSlianep if (r != 0)
35999b44c3bSlianep return (r);
36099b44c3bSlianep
36199b44c3bSlianep graph_transition_sulogin(RESTARTER_STATE_ONLINE, old_state);
36299b44c3bSlianep return (0);
36399b44c3bSlianep }
36499b44c3bSlianep
36599b44c3bSlianep static int
gt_enter_degraded(scf_handle_t * h,graph_vertex_t * v,restarter_instance_state_t old_state,restarter_error_t rerr)36699b44c3bSlianep gt_enter_degraded(scf_handle_t *h, graph_vertex_t *v,
36799b44c3bSlianep restarter_instance_state_t old_state, restarter_error_t rerr)
36899b44c3bSlianep {
36999b44c3bSlianep int r;
37099b44c3bSlianep
37199b44c3bSlianep r = gt_internal_online_or_degraded(h, v, old_state, rerr);
37299b44c3bSlianep if (r != 0)
37399b44c3bSlianep return (r);
37499b44c3bSlianep
37599b44c3bSlianep graph_transition_sulogin(RESTARTER_STATE_DEGRADED, old_state);
37699b44c3bSlianep return (0);
37799b44c3bSlianep }
37899b44c3bSlianep
37999b44c3bSlianep /*
38099b44c3bSlianep * gt_transition() implements the state transition for the graph
38199b44c3bSlianep * state machine. It can return:
38299b44c3bSlianep * 0 success
38399b44c3bSlianep * ECONNABORTED repository connection aborted
384cd3bce3eSlianep *
385cd3bce3eSlianep * v->gv_state should be set to the state we're transitioning to before
386cd3bce3eSlianep * calling this function.
38799b44c3bSlianep */
38899b44c3bSlianep int
gt_transition(scf_handle_t * h,graph_vertex_t * v,restarter_error_t rerr,restarter_instance_state_t old_state)38999b44c3bSlianep gt_transition(scf_handle_t *h, graph_vertex_t *v, restarter_error_t rerr,
390cd3bce3eSlianep restarter_instance_state_t old_state)
39199b44c3bSlianep {
39256e23938Sbustos int err;
39356e23938Sbustos int lost_repository = 0;
39499b44c3bSlianep
39599b44c3bSlianep /*
39699b44c3bSlianep * If there's a common set of work to be done on exit from the
39799b44c3bSlianep * old_state, include it as a separate set of functions here. For
39899b44c3bSlianep * now there's no such work, so there are no gt_exit functions.
39999b44c3bSlianep */
40099b44c3bSlianep
40156e23938Sbustos err = vertex_subgraph_dependencies_shutdown(h, v, old_state);
40256e23938Sbustos switch (err) {
40356e23938Sbustos case 0:
40456e23938Sbustos break;
40556e23938Sbustos
40656e23938Sbustos case ECONNABORTED:
40756e23938Sbustos lost_repository = 1;
40856e23938Sbustos break;
40956e23938Sbustos
41056e23938Sbustos default:
41156e23938Sbustos bad_error("vertex_subgraph_dependencies_shutdown", err);
41256e23938Sbustos }
41356e23938Sbustos
41499b44c3bSlianep /*
41599b44c3bSlianep * Now call the appropriate gt_enter function for the new state.
41699b44c3bSlianep */
417cd3bce3eSlianep switch (v->gv_state) {
41899b44c3bSlianep case RESTARTER_STATE_UNINIT:
41999b44c3bSlianep err = gt_enter_uninit(h, v, old_state, rerr);
42099b44c3bSlianep break;
42199b44c3bSlianep
42299b44c3bSlianep case RESTARTER_STATE_DISABLED:
42399b44c3bSlianep err = gt_enter_disabled(h, v, old_state, rerr);
42499b44c3bSlianep break;
42599b44c3bSlianep
42699b44c3bSlianep case RESTARTER_STATE_OFFLINE:
42799b44c3bSlianep err = gt_enter_offline(h, v, old_state, rerr);
42899b44c3bSlianep break;
42999b44c3bSlianep
43099b44c3bSlianep case RESTARTER_STATE_ONLINE:
43199b44c3bSlianep err = gt_enter_online(h, v, old_state, rerr);
43299b44c3bSlianep break;
43399b44c3bSlianep
43499b44c3bSlianep case RESTARTER_STATE_DEGRADED:
43599b44c3bSlianep err = gt_enter_degraded(h, v, old_state, rerr);
43699b44c3bSlianep break;
43799b44c3bSlianep
43899b44c3bSlianep case RESTARTER_STATE_MAINT:
43999b44c3bSlianep err = gt_enter_maint(h, v, old_state, rerr);
44099b44c3bSlianep break;
44199b44c3bSlianep
44299b44c3bSlianep default:
443cd3bce3eSlianep /* Shouldn't be in an invalid state. */
44499b44c3bSlianep #ifndef NDEBUG
44556e23938Sbustos uu_warn("%s:%d: Invalid state %d.\n", __FILE__, __LINE__,
446cd3bce3eSlianep v->gv_state);
44799b44c3bSlianep #endif
44899b44c3bSlianep abort();
44999b44c3bSlianep }
45099b44c3bSlianep
45156e23938Sbustos switch (err) {
45256e23938Sbustos case 0:
45356e23938Sbustos break;
45456e23938Sbustos
45556e23938Sbustos case ECONNABORTED:
45656e23938Sbustos lost_repository = 1;
45756e23938Sbustos break;
45856e23938Sbustos
45956e23938Sbustos default:
46056e23938Sbustos #ifndef NDEBUG
46156e23938Sbustos uu_warn("%s:%d: "
46256e23938Sbustos "gt_enter_%s() failed with unexpected error %d.\n",
46356e23938Sbustos __FILE__, __LINE__, instance_state_str[v->gv_state], err);
46456e23938Sbustos #endif
46556e23938Sbustos abort();
46656e23938Sbustos }
46756e23938Sbustos
46856e23938Sbustos return (lost_repository ? ECONNABORTED : 0);
46999b44c3bSlianep }
470