| /* 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 */ |