|  | /* SPDX-License-Identifier: GPL-2.0-only */ | 
|  | /* | 
|  | * Copyright 2023 Red Hat | 
|  | */ | 
|  |  | 
|  | #ifndef VDO_ADMIN_STATE_H | 
|  | #define VDO_ADMIN_STATE_H | 
|  |  | 
|  | #include "completion.h" | 
|  | #include "types.h" | 
|  |  | 
|  | struct admin_state_code { | 
|  | const char *name; | 
|  | /* Normal operation, data_vios may be active */ | 
|  | bool normal; | 
|  | /* I/O is draining, new requests should not start */ | 
|  | bool draining; | 
|  | /* This is a startup time operation */ | 
|  | bool loading; | 
|  | /* The next state will be quiescent */ | 
|  | bool quiescing; | 
|  | /* The VDO is quiescent, there should be no I/O */ | 
|  | bool quiescent; | 
|  | /* Whether an operation is in progress and so no other operation may be started */ | 
|  | bool operating; | 
|  | }; | 
|  |  | 
|  | extern const struct admin_state_code *VDO_ADMIN_STATE_NORMAL_OPERATION; | 
|  | extern const struct admin_state_code *VDO_ADMIN_STATE_OPERATING; | 
|  | extern const struct admin_state_code *VDO_ADMIN_STATE_FORMATTING; | 
|  | extern const struct admin_state_code *VDO_ADMIN_STATE_PRE_LOADING; | 
|  | extern const struct admin_state_code *VDO_ADMIN_STATE_PRE_LOADED; | 
|  | extern const struct admin_state_code *VDO_ADMIN_STATE_LOADING; | 
|  | extern const struct admin_state_code *VDO_ADMIN_STATE_LOADING_FOR_RECOVERY; | 
|  | extern const struct admin_state_code *VDO_ADMIN_STATE_LOADING_FOR_REBUILD; | 
|  | extern const struct admin_state_code *VDO_ADMIN_STATE_WAITING_FOR_RECOVERY; | 
|  | extern const struct admin_state_code *VDO_ADMIN_STATE_NEW; | 
|  | extern const struct admin_state_code *VDO_ADMIN_STATE_INITIALIZED; | 
|  | extern const struct admin_state_code *VDO_ADMIN_STATE_RECOVERING; | 
|  | extern const struct admin_state_code *VDO_ADMIN_STATE_REBUILDING; | 
|  | extern const struct admin_state_code *VDO_ADMIN_STATE_SAVING; | 
|  | extern const struct admin_state_code *VDO_ADMIN_STATE_SAVED; | 
|  | extern const struct admin_state_code *VDO_ADMIN_STATE_SCRUBBING; | 
|  | extern const struct admin_state_code *VDO_ADMIN_STATE_SAVE_FOR_SCRUBBING; | 
|  | extern const struct admin_state_code *VDO_ADMIN_STATE_STOPPING; | 
|  | extern const struct admin_state_code *VDO_ADMIN_STATE_STOPPED; | 
|  | extern const struct admin_state_code *VDO_ADMIN_STATE_SUSPENDING; | 
|  | extern const struct admin_state_code *VDO_ADMIN_STATE_SUSPENDED; | 
|  | extern const struct admin_state_code *VDO_ADMIN_STATE_SUSPENDED_OPERATION; | 
|  | extern const struct admin_state_code *VDO_ADMIN_STATE_RESUMING; | 
|  |  | 
|  | struct admin_state { | 
|  | const struct admin_state_code *current_state; | 
|  | /* The next administrative state (when the current operation finishes) */ | 
|  | const struct admin_state_code *next_state; | 
|  | /* A completion waiting on a state change */ | 
|  | struct vdo_completion *waiter; | 
|  | /* Whether an operation is being initiated */ | 
|  | bool starting; | 
|  | /* Whether an operation has completed in the initiator */ | 
|  | bool complete; | 
|  | }; | 
|  |  | 
|  | /** | 
|  | * typedef vdo_admin_initiator_fn - A method to be called once an admin operation may be initiated. | 
|  | */ | 
|  | typedef void (*vdo_admin_initiator_fn)(struct admin_state *state); | 
|  |  | 
|  | static inline const struct admin_state_code * __must_check | 
|  | vdo_get_admin_state_code(const struct admin_state *state) | 
|  | { | 
|  | return READ_ONCE(state->current_state); | 
|  | } | 
|  |  | 
|  | /** | 
|  | * vdo_set_admin_state_code() - Set the current admin state code. | 
|  | * | 
|  | * This function should be used primarily for initialization and by adminState internals. Most uses | 
|  | * should go through the operation interfaces. | 
|  | */ | 
|  | static inline void vdo_set_admin_state_code(struct admin_state *state, | 
|  | const struct admin_state_code *code) | 
|  | { | 
|  | WRITE_ONCE(state->current_state, code); | 
|  | } | 
|  |  | 
|  | static inline bool __must_check vdo_is_state_normal(const struct admin_state *state) | 
|  | { | 
|  | return vdo_get_admin_state_code(state)->normal; | 
|  | } | 
|  |  | 
|  | static inline bool __must_check vdo_is_state_suspending(const struct admin_state *state) | 
|  | { | 
|  | return (vdo_get_admin_state_code(state) == VDO_ADMIN_STATE_SUSPENDING); | 
|  | } | 
|  |  | 
|  | static inline bool __must_check vdo_is_state_saving(const struct admin_state *state) | 
|  | { | 
|  | return (vdo_get_admin_state_code(state) == VDO_ADMIN_STATE_SAVING); | 
|  | } | 
|  |  | 
|  | static inline bool __must_check vdo_is_state_saved(const struct admin_state *state) | 
|  | { | 
|  | return (vdo_get_admin_state_code(state) == VDO_ADMIN_STATE_SAVED); | 
|  | } | 
|  |  | 
|  | static inline bool __must_check vdo_is_state_draining(const struct admin_state *state) | 
|  | { | 
|  | return vdo_get_admin_state_code(state)->draining; | 
|  | } | 
|  |  | 
|  | static inline bool __must_check vdo_is_state_loading(const struct admin_state *state) | 
|  | { | 
|  | return vdo_get_admin_state_code(state)->loading; | 
|  | } | 
|  |  | 
|  | static inline bool __must_check vdo_is_state_resuming(const struct admin_state *state) | 
|  | { | 
|  | return (vdo_get_admin_state_code(state) == VDO_ADMIN_STATE_RESUMING); | 
|  | } | 
|  |  | 
|  | static inline bool __must_check vdo_is_state_clean_load(const struct admin_state *state) | 
|  | { | 
|  | const struct admin_state_code *code = vdo_get_admin_state_code(state); | 
|  |  | 
|  | return ((code == VDO_ADMIN_STATE_FORMATTING) || (code == VDO_ADMIN_STATE_LOADING)); | 
|  | } | 
|  |  | 
|  | static inline bool __must_check vdo_is_state_quiescing(const struct admin_state *state) | 
|  | { | 
|  | return vdo_get_admin_state_code(state)->quiescing; | 
|  | } | 
|  |  | 
|  | static inline bool __must_check vdo_is_state_quiescent(const struct admin_state *state) | 
|  | { | 
|  | return vdo_get_admin_state_code(state)->quiescent; | 
|  | } | 
|  |  | 
|  | bool __must_check vdo_assert_load_operation(const struct admin_state_code *operation, | 
|  | struct vdo_completion *waiter); | 
|  |  | 
|  | bool vdo_start_loading(struct admin_state *state, | 
|  | const struct admin_state_code *operation, | 
|  | struct vdo_completion *waiter, vdo_admin_initiator_fn initiator); | 
|  |  | 
|  | bool vdo_finish_loading(struct admin_state *state); | 
|  |  | 
|  | bool vdo_finish_loading_with_result(struct admin_state *state, int result); | 
|  |  | 
|  | bool vdo_start_resuming(struct admin_state *state, | 
|  | const struct admin_state_code *operation, | 
|  | struct vdo_completion *waiter, vdo_admin_initiator_fn initiator); | 
|  |  | 
|  | bool vdo_finish_resuming(struct admin_state *state); | 
|  |  | 
|  | bool vdo_finish_resuming_with_result(struct admin_state *state, int result); | 
|  |  | 
|  | int vdo_resume_if_quiescent(struct admin_state *state); | 
|  |  | 
|  | bool vdo_start_draining(struct admin_state *state, | 
|  | const struct admin_state_code *operation, | 
|  | struct vdo_completion *waiter, vdo_admin_initiator_fn initiator); | 
|  |  | 
|  | bool vdo_finish_draining(struct admin_state *state); | 
|  |  | 
|  | bool vdo_finish_draining_with_result(struct admin_state *state, int result); | 
|  |  | 
|  | int vdo_start_operation(struct admin_state *state, | 
|  | const struct admin_state_code *operation); | 
|  |  | 
|  | int vdo_start_operation_with_waiter(struct admin_state *state, | 
|  | const struct admin_state_code *operation, | 
|  | struct vdo_completion *waiter, | 
|  | vdo_admin_initiator_fn initiator); | 
|  |  | 
|  | bool vdo_finish_operation(struct admin_state *state, int result); | 
|  |  | 
|  | #endif /* VDO_ADMIN_STATE_H */ |