diff options
Diffstat (limited to 'sys/cam/ctl/ctl_ha.h')
-rw-r--r-- | sys/cam/ctl/ctl_ha.h | 270 |
1 files changed, 270 insertions, 0 deletions
diff --git a/sys/cam/ctl/ctl_ha.h b/sys/cam/ctl/ctl_ha.h new file mode 100644 index 0000000000000..6293c7ce1701e --- /dev/null +++ b/sys/cam/ctl/ctl_ha.h @@ -0,0 +1,270 @@ +/*- + * Copyright (c) 2003-2009 Silicon Graphics International Corp. + * Copyright (c) 2011 Spectra Logic Corporation + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + * + * $Id: //depot/users/kenm/FreeBSD-test2/sys/cam/ctl/ctl_ha.h#1 $ + * $FreeBSD$ + */ + +#ifndef _CTL_HA_H_ +#define _CTL_HA_H_ + +/* + * CTL High Availability Modes: + * + * CTL_HA_MODE_SER_ONLY: Commands are serialized to the other side. Write + * mirroring and read re-direction are assumed to + * happen in the back end. + * CTL_HA_MODE_XFER: Commands are serialized and data is transferred + * for write mirroring and read re-direction. + */ + +typedef enum { + CTL_HA_MODE_SER_ONLY, + CTL_HA_MODE_XFER +} ctl_ha_mode; + + +/* + * This is a stubbed out High Availability interface. It assumes two nodes + * staying in sync. + * + * The reason this interface is here, and stubbed out, is that CTL was + * originally written with support for Copan's (now SGI) high availability + * framework. That framework was not released by SGI, and would not have + * been generally applicable to FreeBSD anyway. + * + * The idea here is to show the kind of API that would need to be in place + * in a HA framework to work with CTL's HA hooks. This API is very close + * to the Copan/SGI API, so that the code using it could stay in place + * as-is. + * + * So, in summary, this is a shell without real substance, and much more + * work would be needed to actually make HA work. The implementation + * inside CTL will also need to change to fit the eventual implementation. + * The additional pieces we would need are: + * + * - HA "Supervisor" framework that can startup the components of the + * system, and initiate failover (i.e. active/active to single mode) + * and failback (single to active/active mode) state transitions. + * This framework would be able to recognize when an event happens + * that requires it to initiate state transitions in the components it + * manages. + * + * - HA communication framework. This framework should have the following + * features: + * - Separate channels for separate system components. The CTL + * instance on one node should communicate with the CTL instance + * on another node. + * - Short message passing. These messages would be fixed length, so + * they could be preallocated and easily passed between the nodes. + * i.e. conceptually like an ethernet packet. + * - DMA/large buffer capability. This would require some negotiation + * with the other node to define the destination. It could + * allow for "push" (i.e. initiated by the requesting node) DMA or + * "pull" (i.e. initiated by the target controller) DMA or both. + * - Communication channel status change notification. + * - HA capability in other portions of the storage stack. Having two CTL + * instances communicate is just one part of an overall HA solution. + * State needs to be synchronized at multiple levels of the system in + * order for failover to actually work. For instance, if CTL is using a + * file on a ZFS filesystem as its backing store, the ZFS array state + * should be synchronized with the other node, so that the other node + * can immediately take over if the node that is primary for a particular + * array fails. + */ + +/* + * Communication channel IDs for various system components. This is to + * make sure one CTL instance talks with another, one ZFS instance talks + * with another, etc. + */ +typedef enum { + CTL_HA_CHAN_NONE, + CTL_HA_CHAN_CTL, + CTL_HA_CHAN_ZFS, + CTL_HA_CHAN_MAX +} ctl_ha_channel; + +/* + * HA communication event notification. These are events generated by the + * HA communication subsystem. + * + * CTL_HA_EVT_MSG_RECV: Message received by the other node. + * CTL_HA_EVT_MSG_SENT: Message sent to the other node. + * CTL_HA_EVT_DISCONNECT: Communication channel disconnected. + * CTL_HA_EVT_DMA_SENT: DMA successfully sent to other node (push). + * CTL_HA_EVT_DMA_RECEIVED: DMA successfully received by other node (pull). + */ +typedef enum { + CTL_HA_EVT_NONE, + CTL_HA_EVT_MSG_RECV, + CTL_HA_EVT_MSG_SENT, + CTL_HA_EVT_DISCONNECT, + CTL_HA_EVT_DMA_SENT, + CTL_HA_EVT_DMA_RECEIVED, + CTL_HA_EVT_MAX +} ctl_ha_event; + +typedef enum { + CTL_HA_STATUS_WAIT, + CTL_HA_STATUS_SUCCESS, + CTL_HA_STATUS_ERROR, + CTL_HA_STATUS_INVALID, + CTL_HA_STATUS_DISCONNECT, + CTL_HA_STATUS_BUSY, + CTL_HA_STATUS_MAX +} ctl_ha_status; + +typedef enum { + CTL_HA_DATA_CTL, + CTL_HA_DATA_ZFS, + CTL_HA_DATA_MAX +} ctl_ha_dtid; + +typedef enum { + CTL_HA_DT_CMD_READ, + CTL_HA_DT_CMD_WRITE, +} ctl_ha_dt_cmd; + +struct ctl_ha_dt_req; + +typedef void (*ctl_ha_dt_cb)(struct ctl_ha_dt_req *); + +struct ctl_ha_dt_req { + ctl_ha_dt_cmd command; + void *context; + ctl_ha_dt_cb callback; + ctl_ha_dtid id; + int ret; + uint32_t size; + uint8_t *local; + uint8_t *remote; +}; + +typedef void (*ctl_evt_handler)(ctl_ha_channel channel, ctl_ha_event event, + int param); +void ctl_ha_register_evthandler(ctl_ha_channel channel, + ctl_evt_handler handler); + +static inline ctl_ha_status +ctl_ha_msg_create(ctl_ha_channel channel, ctl_evt_handler handler) +{ + return (CTL_HA_STATUS_SUCCESS); +} + +/* + * Receive a message of the specified size. + */ +static inline ctl_ha_status +ctl_ha_msg_recv(ctl_ha_channel channel, void *buffer, unsigned int size, + int wait) +{ + return (CTL_HA_STATUS_SUCCESS); +} + +/* + * Send a message of the specified size. + */ +static inline ctl_ha_status +ctl_ha_msg_send(ctl_ha_channel channel, void *buffer, unsigned int size, + int wait) +{ + return (CTL_HA_STATUS_SUCCESS); +} + +/* + * Allocate a data transfer request structure. + */ +static inline struct ctl_ha_dt_req * +ctl_dt_req_alloc(void) +{ + return (NULL); +} + +/* + * Free a data transfer request structure. + */ +static inline void +ctl_dt_req_free(struct ctl_ha_dt_req *req) +{ + return; +} + +/* + * Issue a DMA request for a single buffer. + */ +static inline ctl_ha_status +ctl_dt_single(struct ctl_ha_dt_req *req) +{ + return (CTL_HA_STATUS_WAIT); +} + +/* + * SINGLE: One node + * HA: Two nodes (Active/Active implied) + * SLAVE/MASTER: The component can set these flags to indicate which side + * is in control. It has no effect on the HA framework. + */ +typedef enum { + CTL_HA_STATE_UNKNOWN = 0x00, + CTL_HA_STATE_SINGLE = 0x01, + CTL_HA_STATE_HA = 0x02, + CTL_HA_STATE_MASK = 0x0F, + CTL_HA_STATE_SLAVE = 0x10, + CTL_HA_STATE_MASTER = 0x20 +} ctl_ha_state; + +typedef enum { + CTL_HA_COMP_STATUS_OK, + CTL_HA_COMP_STATUS_FAILED, + CTL_HA_COMP_STATUS_ERROR +} ctl_ha_comp_status; + +struct ctl_ha_component; + +typedef ctl_ha_comp_status (*ctl_hacmp_init_t)(struct ctl_ha_component *); +typedef ctl_ha_comp_status (*ctl_hacmp_start_t)(struct ctl_ha_component *, + ctl_ha_state); + +struct ctl_ha_component { + char *name; + ctl_ha_state state; + ctl_ha_comp_status status; + ctl_hacmp_init_t init; + ctl_hacmp_start_t start; + ctl_hacmp_init_t quiesce; +}; + +#define CTL_HA_STATE_IS_SINGLE(state) ((state & CTL_HA_STATE_MASK) == \ + CTL_HA_STATE_SINGLE) +#define CTL_HA_STATE_IS_HA(state) ((state & CTL_HA_STATE_MASK) == \ + CTL_HA_STATE_HA) + +#endif /* _CTL_HA_H_ */ |