ctl_ha.h revision 229997
1229997Sken/*- 2229997Sken * Copyright (c) 2003-2009 Silicon Graphics International Corp. 3229997Sken * Copyright (c) 2011 Spectra Logic Corporation 4229997Sken * All rights reserved. 5229997Sken * 6229997Sken * Redistribution and use in source and binary forms, with or without 7229997Sken * modification, are permitted provided that the following conditions 8229997Sken * are met: 9229997Sken * 1. Redistributions of source code must retain the above copyright 10229997Sken * notice, this list of conditions, and the following disclaimer, 11229997Sken * without modification. 12229997Sken * 2. Redistributions in binary form must reproduce at minimum a disclaimer 13229997Sken * substantially similar to the "NO WARRANTY" disclaimer below 14229997Sken * ("Disclaimer") and any redistribution must be conditioned upon 15229997Sken * including a substantially similar Disclaimer requirement for further 16229997Sken * binary redistribution. 17229997Sken * 18229997Sken * NO WARRANTY 19229997Sken * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20229997Sken * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21229997Sken * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR 22229997Sken * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 23229997Sken * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24229997Sken * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25229997Sken * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26229997Sken * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 27229997Sken * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 28229997Sken * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29229997Sken * POSSIBILITY OF SUCH DAMAGES. 30229997Sken * 31229997Sken * $Id: //depot/users/kenm/FreeBSD-test2/sys/cam/ctl/ctl_ha.h#1 $ 32229997Sken * $FreeBSD: head/sys/cam/ctl/ctl_ha.h 229997 2012-01-12 00:34:33Z ken $ 33229997Sken */ 34229997Sken 35229997Sken#ifndef _CTL_HA_H_ 36229997Sken#define _CTL_HA_H_ 37229997Sken 38229997Sken/* 39229997Sken * CTL High Availability Modes: 40229997Sken * 41229997Sken * CTL_HA_MODE_SER_ONLY: Commands are serialized to the other side. Write 42229997Sken * mirroring and read re-direction are assumed to 43229997Sken * happen in the back end. 44229997Sken * CTL_HA_MODE_XFER: Commands are serialized and data is transferred 45229997Sken * for write mirroring and read re-direction. 46229997Sken */ 47229997Sken 48229997Skentypedef enum { 49229997Sken CTL_HA_MODE_SER_ONLY, 50229997Sken CTL_HA_MODE_XFER 51229997Sken} ctl_ha_mode; 52229997Sken 53229997Sken 54229997Sken/* 55229997Sken * This is a stubbed out High Availability interface. It assumes two nodes 56229997Sken * staying in sync. 57229997Sken * 58229997Sken * The reason this interface is here, and stubbed out, is that CTL was 59229997Sken * originally written with support for Copan's (now SGI) high availability 60229997Sken * framework. That framework was not released by SGI, and would not have 61229997Sken * been generally applicable to FreeBSD anyway. 62229997Sken * 63229997Sken * The idea here is to show the kind of API that would need to be in place 64229997Sken * in a HA framework to work with CTL's HA hooks. This API is very close 65229997Sken * to the Copan/SGI API, so that the code using it could stay in place 66229997Sken * as-is. 67229997Sken * 68229997Sken * So, in summary, this is a shell without real substance, and much more 69229997Sken * work would be needed to actually make HA work. The implementation 70229997Sken * inside CTL will also need to change to fit the eventual implementation. 71229997Sken * The additional pieces we would need are: 72229997Sken * 73229997Sken * - HA "Supervisor" framework that can startup the components of the 74229997Sken * system, and initiate failover (i.e. active/active to single mode) 75229997Sken * and failback (single to active/active mode) state transitions. 76229997Sken * This framework would be able to recognize when an event happens 77229997Sken * that requires it to initiate state transitions in the components it 78229997Sken * manages. 79229997Sken * 80229997Sken * - HA communication framework. This framework should have the following 81229997Sken * features: 82229997Sken * - Separate channels for separate system components. The CTL 83229997Sken * instance on one node should communicate with the CTL instance 84229997Sken * on another node. 85229997Sken * - Short message passing. These messages would be fixed length, so 86229997Sken * they could be preallocated and easily passed between the nodes. 87229997Sken * i.e. conceptually like an ethernet packet. 88229997Sken * - DMA/large buffer capability. This would require some negotiation 89229997Sken * with the other node to define the destination. It could 90229997Sken * allow for "push" (i.e. initiated by the requesting node) DMA or 91229997Sken * "pull" (i.e. initiated by the target controller) DMA or both. 92229997Sken * - Communication channel status change notification. 93229997Sken * - HA capability in other portions of the storage stack. Having two CTL 94229997Sken * instances communicate is just one part of an overall HA solution. 95229997Sken * State needs to be synchronized at multiple levels of the system in 96229997Sken * order for failover to actually work. For instance, if CTL is using a 97229997Sken * file on a ZFS filesystem as its backing store, the ZFS array state 98229997Sken * should be synchronized with the other node, so that the other node 99229997Sken * can immediately take over if the node that is primary for a particular 100229997Sken * array fails. 101229997Sken */ 102229997Sken 103229997Sken/* 104229997Sken * Communication channel IDs for various system components. This is to 105229997Sken * make sure one CTL instance talks with another, one ZFS instance talks 106229997Sken * with another, etc. 107229997Sken */ 108229997Skentypedef enum { 109229997Sken CTL_HA_CHAN_NONE, 110229997Sken CTL_HA_CHAN_CTL, 111229997Sken CTL_HA_CHAN_ZFS, 112229997Sken CTL_HA_CHAN_MAX 113229997Sken} ctl_ha_channel; 114229997Sken 115229997Sken/* 116229997Sken * HA communication event notification. These are events generated by the 117229997Sken * HA communication subsystem. 118229997Sken * 119229997Sken * CTL_HA_EVT_MSG_RECV: Message received by the other node. 120229997Sken * CTL_HA_EVT_MSG_SENT: Message sent to the other node. 121229997Sken * CTL_HA_EVT_DISCONNECT: Communication channel disconnected. 122229997Sken * CTL_HA_EVT_DMA_SENT: DMA successfully sent to other node (push). 123229997Sken * CTL_HA_EVT_DMA_RECEIVED: DMA successfully received by other node (pull). 124229997Sken */ 125229997Skentypedef enum { 126229997Sken CTL_HA_EVT_NONE, 127229997Sken CTL_HA_EVT_MSG_RECV, 128229997Sken CTL_HA_EVT_MSG_SENT, 129229997Sken CTL_HA_EVT_DISCONNECT, 130229997Sken CTL_HA_EVT_DMA_SENT, 131229997Sken CTL_HA_EVT_DMA_RECEIVED, 132229997Sken CTL_HA_EVT_MAX 133229997Sken} ctl_ha_event; 134229997Sken 135229997Skentypedef enum { 136229997Sken CTL_HA_STATUS_WAIT, 137229997Sken CTL_HA_STATUS_SUCCESS, 138229997Sken CTL_HA_STATUS_ERROR, 139229997Sken CTL_HA_STATUS_INVALID, 140229997Sken CTL_HA_STATUS_DISCONNECT, 141229997Sken CTL_HA_STATUS_BUSY, 142229997Sken CTL_HA_STATUS_MAX 143229997Sken} ctl_ha_status; 144229997Sken 145229997Skentypedef enum { 146229997Sken CTL_HA_DATA_CTL, 147229997Sken CTL_HA_DATA_ZFS, 148229997Sken CTL_HA_DATA_MAX 149229997Sken} ctl_ha_dtid; 150229997Sken 151229997Skentypedef enum { 152229997Sken CTL_HA_DT_CMD_READ, 153229997Sken CTL_HA_DT_CMD_WRITE, 154229997Sken} ctl_ha_dt_cmd; 155229997Sken 156229997Skenstruct ctl_ha_dt_req; 157229997Sken 158229997Skentypedef void (*ctl_ha_dt_cb)(struct ctl_ha_dt_req *); 159229997Sken 160229997Skenstruct ctl_ha_dt_req { 161229997Sken ctl_ha_dt_cmd command; 162229997Sken void *context; 163229997Sken ctl_ha_dt_cb callback; 164229997Sken ctl_ha_dtid id; 165229997Sken int ret; 166229997Sken uint32_t size; 167229997Sken uint8_t *local; 168229997Sken uint8_t *remote; 169229997Sken}; 170229997Sken 171229997Skentypedef void (*ctl_evt_handler)(ctl_ha_channel channel, ctl_ha_event event, 172229997Sken int param); 173229997Skenvoid ctl_ha_register_evthandler(ctl_ha_channel channel, 174229997Sken ctl_evt_handler handler); 175229997Sken 176229997Skenstatic inline ctl_ha_status 177229997Skenctl_ha_msg_create(ctl_ha_channel channel, ctl_evt_handler handler) 178229997Sken{ 179229997Sken return (CTL_HA_STATUS_SUCCESS); 180229997Sken} 181229997Sken 182229997Sken/* 183229997Sken * Receive a message of the specified size. 184229997Sken */ 185229997Skenstatic inline ctl_ha_status 186229997Skenctl_ha_msg_recv(ctl_ha_channel channel, void *buffer, unsigned int size, 187229997Sken int wait) 188229997Sken{ 189229997Sken return (CTL_HA_STATUS_SUCCESS); 190229997Sken} 191229997Sken 192229997Sken/* 193229997Sken * Send a message of the specified size. 194229997Sken */ 195229997Skenstatic inline ctl_ha_status 196229997Skenctl_ha_msg_send(ctl_ha_channel channel, void *buffer, unsigned int size, 197229997Sken int wait) 198229997Sken{ 199229997Sken return (CTL_HA_STATUS_SUCCESS); 200229997Sken} 201229997Sken 202229997Sken/* 203229997Sken * Allocate a data transfer request structure. 204229997Sken */ 205229997Skenstatic inline struct ctl_ha_dt_req * 206229997Skenctl_dt_req_alloc(void) 207229997Sken{ 208229997Sken return (NULL); 209229997Sken} 210229997Sken 211229997Sken/* 212229997Sken * Free a data transfer request structure. 213229997Sken */ 214229997Skenstatic inline void 215229997Skenctl_dt_req_free(struct ctl_ha_dt_req *req) 216229997Sken{ 217229997Sken return; 218229997Sken} 219229997Sken 220229997Sken/* 221229997Sken * Issue a DMA request for a single buffer. 222229997Sken */ 223229997Skenstatic inline ctl_ha_status 224229997Skenctl_dt_single(struct ctl_ha_dt_req *req) 225229997Sken{ 226229997Sken return (CTL_HA_STATUS_WAIT); 227229997Sken} 228229997Sken 229229997Sken/* 230229997Sken * SINGLE: One node 231229997Sken * HA: Two nodes (Active/Active implied) 232229997Sken * SLAVE/MASTER: The component can set these flags to indicate which side 233229997Sken * is in control. It has no effect on the HA framework. 234229997Sken */ 235229997Skentypedef enum { 236229997Sken CTL_HA_STATE_UNKNOWN = 0x00, 237229997Sken CTL_HA_STATE_SINGLE = 0x01, 238229997Sken CTL_HA_STATE_HA = 0x02, 239229997Sken CTL_HA_STATE_MASK = 0x0F, 240229997Sken CTL_HA_STATE_SLAVE = 0x10, 241229997Sken CTL_HA_STATE_MASTER = 0x20 242229997Sken} ctl_ha_state; 243229997Sken 244229997Skentypedef enum { 245229997Sken CTL_HA_COMP_STATUS_OK, 246229997Sken CTL_HA_COMP_STATUS_FAILED, 247229997Sken CTL_HA_COMP_STATUS_ERROR 248229997Sken} ctl_ha_comp_status; 249229997Sken 250229997Skenstruct ctl_ha_component; 251229997Sken 252229997Skentypedef ctl_ha_comp_status (*ctl_hacmp_init_t)(struct ctl_ha_component *); 253229997Skentypedef ctl_ha_comp_status (*ctl_hacmp_start_t)(struct ctl_ha_component *, 254229997Sken ctl_ha_state); 255229997Sken 256229997Skenstruct ctl_ha_component { 257229997Sken char *name; 258229997Sken ctl_ha_state state; 259229997Sken ctl_ha_comp_status status; 260229997Sken ctl_hacmp_init_t init; 261229997Sken ctl_hacmp_start_t start; 262229997Sken ctl_hacmp_init_t quiesce; 263229997Sken}; 264229997Sken 265229997Sken#define CTL_HA_STATE_IS_SINGLE(state) ((state & CTL_HA_STATE_MASK) == \ 266229997Sken CTL_HA_STATE_SINGLE) 267229997Sken#define CTL_HA_STATE_IS_HA(state) ((state & CTL_HA_STATE_MASK) == \ 268229997Sken CTL_HA_STATE_HA) 269229997Sken 270229997Sken#endif /* _CTL_HA_H_ */ 271