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  
12  struct 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  
28  extern const struct admin_state_code *VDO_ADMIN_STATE_NORMAL_OPERATION;
29  extern const struct admin_state_code *VDO_ADMIN_STATE_OPERATING;
30  extern const struct admin_state_code *VDO_ADMIN_STATE_FORMATTING;
31  extern const struct admin_state_code *VDO_ADMIN_STATE_PRE_LOADING;
32  extern const struct admin_state_code *VDO_ADMIN_STATE_PRE_LOADED;
33  extern const struct admin_state_code *VDO_ADMIN_STATE_LOADING;
34  extern const struct admin_state_code *VDO_ADMIN_STATE_LOADING_FOR_RECOVERY;
35  extern const struct admin_state_code *VDO_ADMIN_STATE_LOADING_FOR_REBUILD;
36  extern const struct admin_state_code *VDO_ADMIN_STATE_WAITING_FOR_RECOVERY;
37  extern const struct admin_state_code *VDO_ADMIN_STATE_NEW;
38  extern const struct admin_state_code *VDO_ADMIN_STATE_INITIALIZED;
39  extern const struct admin_state_code *VDO_ADMIN_STATE_RECOVERING;
40  extern const struct admin_state_code *VDO_ADMIN_STATE_REBUILDING;
41  extern const struct admin_state_code *VDO_ADMIN_STATE_SAVING;
42  extern const struct admin_state_code *VDO_ADMIN_STATE_SAVED;
43  extern const struct admin_state_code *VDO_ADMIN_STATE_SCRUBBING;
44  extern const struct admin_state_code *VDO_ADMIN_STATE_SAVE_FOR_SCRUBBING;
45  extern const struct admin_state_code *VDO_ADMIN_STATE_STOPPING;
46  extern const struct admin_state_code *VDO_ADMIN_STATE_STOPPED;
47  extern const struct admin_state_code *VDO_ADMIN_STATE_SUSPENDING;
48  extern const struct admin_state_code *VDO_ADMIN_STATE_SUSPENDED;
49  extern const struct admin_state_code *VDO_ADMIN_STATE_SUSPENDED_OPERATION;
50  extern const struct admin_state_code *VDO_ADMIN_STATE_RESUMING;
51  
52  struct 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   */
67  typedef void (*vdo_admin_initiator_fn)(struct admin_state *state);
68  
69  static inline const struct admin_state_code * __must_check
vdo_get_admin_state_code(const struct admin_state * state)70  vdo_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   */
vdo_set_admin_state_code(struct admin_state * state,const struct admin_state_code * code)81  static 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  
vdo_is_state_normal(const struct admin_state * state)87  static 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  
vdo_is_state_suspending(const struct admin_state * state)92  static 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  
vdo_is_state_saving(const struct admin_state * state)97  static 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  
vdo_is_state_saved(const struct admin_state * state)102  static 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  
vdo_is_state_draining(const struct admin_state * state)107  static 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  
vdo_is_state_loading(const struct admin_state * state)112  static 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  
vdo_is_state_resuming(const struct admin_state * state)117  static 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  
vdo_is_state_clean_load(const struct admin_state * state)122  static 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  
vdo_is_state_quiescing(const struct admin_state * state)129  static 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  
vdo_is_state_quiescent(const struct admin_state * state)134  static 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  
139  bool __must_check vdo_assert_load_operation(const struct admin_state_code *operation,
140  					    struct vdo_completion *waiter);
141  
142  bool 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  
146  bool vdo_finish_loading(struct admin_state *state);
147  
148  bool vdo_finish_loading_with_result(struct admin_state *state, int result);
149  
150  bool 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  
154  bool vdo_finish_resuming(struct admin_state *state);
155  
156  bool vdo_finish_resuming_with_result(struct admin_state *state, int result);
157  
158  int vdo_resume_if_quiescent(struct admin_state *state);
159  
160  bool 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  
164  bool vdo_finish_draining(struct admin_state *state);
165  
166  bool vdo_finish_draining_with_result(struct admin_state *state, int result);
167  
168  int vdo_start_operation(struct admin_state *state,
169  			const struct admin_state_code *operation);
170  
171  int 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  
176  bool vdo_finish_operation(struct admin_state *state, int result);
177  
178  #endif /* VDO_ADMIN_STATE_H */
179