1/* SPDX-License-Identifier: GPL-2.0-only */
2/*
3 * Copyright 2023 Red Hat
4 */
5
6#ifndef VDO_ADMIN_STATE_H
7#define VDO_ADMIN_STATE_H
8
9#include "completion.h"
10#include "types.h"
11
12struct admin_state_code {
13	const char *name;
14	/* Normal operation, data_vios may be active */
15	bool normal;
16	/* I/O is draining, new requests should not start */
17	bool draining;
18	/* This is a startup time operation */
19	bool loading;
20	/* The next state will be quiescent */
21	bool quiescing;
22	/* The VDO is quiescent, there should be no I/O */
23	bool quiescent;
24	/* Whether an operation is in progress and so no other operation may be started */
25	bool operating;
26};
27
28extern const struct admin_state_code *VDO_ADMIN_STATE_NORMAL_OPERATION;
29extern const struct admin_state_code *VDO_ADMIN_STATE_OPERATING;
30extern const struct admin_state_code *VDO_ADMIN_STATE_FORMATTING;
31extern const struct admin_state_code *VDO_ADMIN_STATE_PRE_LOADING;
32extern const struct admin_state_code *VDO_ADMIN_STATE_PRE_LOADED;
33extern const struct admin_state_code *VDO_ADMIN_STATE_LOADING;
34extern const struct admin_state_code *VDO_ADMIN_STATE_LOADING_FOR_RECOVERY;
35extern const struct admin_state_code *VDO_ADMIN_STATE_LOADING_FOR_REBUILD;
36extern const struct admin_state_code *VDO_ADMIN_STATE_WAITING_FOR_RECOVERY;
37extern const struct admin_state_code *VDO_ADMIN_STATE_NEW;
38extern const struct admin_state_code *VDO_ADMIN_STATE_INITIALIZED;
39extern const struct admin_state_code *VDO_ADMIN_STATE_RECOVERING;
40extern const struct admin_state_code *VDO_ADMIN_STATE_REBUILDING;
41extern const struct admin_state_code *VDO_ADMIN_STATE_SAVING;
42extern const struct admin_state_code *VDO_ADMIN_STATE_SAVED;
43extern const struct admin_state_code *VDO_ADMIN_STATE_SCRUBBING;
44extern const struct admin_state_code *VDO_ADMIN_STATE_SAVE_FOR_SCRUBBING;
45extern const struct admin_state_code *VDO_ADMIN_STATE_STOPPING;
46extern const struct admin_state_code *VDO_ADMIN_STATE_STOPPED;
47extern const struct admin_state_code *VDO_ADMIN_STATE_SUSPENDING;
48extern const struct admin_state_code *VDO_ADMIN_STATE_SUSPENDED;
49extern const struct admin_state_code *VDO_ADMIN_STATE_SUSPENDED_OPERATION;
50extern const struct admin_state_code *VDO_ADMIN_STATE_RESUMING;
51
52struct admin_state {
53	const struct admin_state_code *current_state;
54	/* The next administrative state (when the current operation finishes) */
55	const struct admin_state_code *next_state;
56	/* A completion waiting on a state change */
57	struct vdo_completion *waiter;
58	/* Whether an operation is being initiated */
59	bool starting;
60	/* Whether an operation has completed in the initiator */
61	bool complete;
62};
63
64/**
65 * typedef vdo_admin_initiator_fn - A method to be called once an admin operation may be initiated.
66 */
67typedef void (*vdo_admin_initiator_fn)(struct admin_state *state);
68
69static inline const struct admin_state_code * __must_check
70vdo_get_admin_state_code(const struct admin_state *state)
71{
72	return READ_ONCE(state->current_state);
73}
74
75/**
76 * vdo_set_admin_state_code() - Set the current admin state code.
77 *
78 * This function should be used primarily for initialization and by adminState internals. Most uses
79 * should go through the operation interfaces.
80 */
81static inline void vdo_set_admin_state_code(struct admin_state *state,
82					    const struct admin_state_code *code)
83{
84	WRITE_ONCE(state->current_state, code);
85}
86
87static inline bool __must_check vdo_is_state_normal(const struct admin_state *state)
88{
89	return vdo_get_admin_state_code(state)->normal;
90}
91
92static inline bool __must_check vdo_is_state_suspending(const struct admin_state *state)
93{
94	return (vdo_get_admin_state_code(state) == VDO_ADMIN_STATE_SUSPENDING);
95}
96
97static inline bool __must_check vdo_is_state_saving(const struct admin_state *state)
98{
99	return (vdo_get_admin_state_code(state) == VDO_ADMIN_STATE_SAVING);
100}
101
102static inline bool __must_check vdo_is_state_saved(const struct admin_state *state)
103{
104	return (vdo_get_admin_state_code(state) == VDO_ADMIN_STATE_SAVED);
105}
106
107static inline bool __must_check vdo_is_state_draining(const struct admin_state *state)
108{
109	return vdo_get_admin_state_code(state)->draining;
110}
111
112static inline bool __must_check vdo_is_state_loading(const struct admin_state *state)
113{
114	return vdo_get_admin_state_code(state)->loading;
115}
116
117static inline bool __must_check vdo_is_state_resuming(const struct admin_state *state)
118{
119	return (vdo_get_admin_state_code(state) == VDO_ADMIN_STATE_RESUMING);
120}
121
122static inline bool __must_check vdo_is_state_clean_load(const struct admin_state *state)
123{
124	const struct admin_state_code *code = vdo_get_admin_state_code(state);
125
126	return ((code == VDO_ADMIN_STATE_FORMATTING) || (code == VDO_ADMIN_STATE_LOADING));
127}
128
129static inline bool __must_check vdo_is_state_quiescing(const struct admin_state *state)
130{
131	return vdo_get_admin_state_code(state)->quiescing;
132}
133
134static inline bool __must_check vdo_is_state_quiescent(const struct admin_state *state)
135{
136	return vdo_get_admin_state_code(state)->quiescent;
137}
138
139bool __must_check vdo_assert_load_operation(const struct admin_state_code *operation,
140					    struct vdo_completion *waiter);
141
142bool vdo_start_loading(struct admin_state *state,
143		       const struct admin_state_code *operation,
144		       struct vdo_completion *waiter, vdo_admin_initiator_fn initiator);
145
146bool vdo_finish_loading(struct admin_state *state);
147
148bool vdo_finish_loading_with_result(struct admin_state *state, int result);
149
150bool vdo_start_resuming(struct admin_state *state,
151			const struct admin_state_code *operation,
152			struct vdo_completion *waiter, vdo_admin_initiator_fn initiator);
153
154bool vdo_finish_resuming(struct admin_state *state);
155
156bool vdo_finish_resuming_with_result(struct admin_state *state, int result);
157
158int vdo_resume_if_quiescent(struct admin_state *state);
159
160bool vdo_start_draining(struct admin_state *state,
161			const struct admin_state_code *operation,
162			struct vdo_completion *waiter, vdo_admin_initiator_fn initiator);
163
164bool vdo_finish_draining(struct admin_state *state);
165
166bool vdo_finish_draining_with_result(struct admin_state *state, int result);
167
168int vdo_start_operation(struct admin_state *state,
169			const struct admin_state_code *operation);
170
171int vdo_start_operation_with_waiter(struct admin_state *state,
172				    const struct admin_state_code *operation,
173				    struct vdo_completion *waiter,
174				    vdo_admin_initiator_fn initiator);
175
176bool vdo_finish_operation(struct admin_state *state, int result);
177
178#endif /* VDO_ADMIN_STATE_H */
179