linux/drivers/md/dm-vdo/admin-state.h
Matthew Sakai 3f493fcea0 dm vdo: add administrative state and action manager
This patch adds the admin_state structures which are used to track the
states of individual vdo components for handling of operations like suspend
and resume. It also adds the action manager which is used to schedule and
manage cross-thread administrative and internal operations.

Co-developed-by: J. corwin Coburn <corwin@hurlbutnet.net>
Signed-off-by: J. corwin Coburn <corwin@hurlbutnet.net>
Signed-off-by: Matthew Sakai <msakai@redhat.com>
Signed-off-by: Mike Snitzer <snitzer@kernel.org>
2024-02-20 13:43:14 -05:00

179 lines
6.3 KiB
C

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