linux/drivers/block/drbd/drbd_state.h
<<
>>
Prefs
   1#ifndef DRBD_STATE_H
   2#define DRBD_STATE_H
   3
   4struct drbd_conf;
   5struct drbd_tconn;
   6
   7/**
   8 * DOC: DRBD State macros
   9 *
  10 * These macros are used to express state changes in easily readable form.
  11 *
  12 * The NS macros expand to a mask and a value, that can be bit ored onto the
  13 * current state as soon as the spinlock (req_lock) was taken.
  14 *
  15 * The _NS macros are used for state functions that get called with the
  16 * spinlock. These macros expand directly to the new state value.
  17 *
  18 * Besides the basic forms NS() and _NS() additional _?NS[23] are defined
  19 * to express state changes that affect more than one aspect of the state.
  20 *
  21 * E.g. NS2(conn, C_CONNECTED, peer, R_SECONDARY)
  22 * Means that the network connection was established and that the peer
  23 * is in secondary role.
  24 */
  25#define role_MASK R_MASK
  26#define peer_MASK R_MASK
  27#define disk_MASK D_MASK
  28#define pdsk_MASK D_MASK
  29#define conn_MASK C_MASK
  30#define susp_MASK 1
  31#define user_isp_MASK 1
  32#define aftr_isp_MASK 1
  33#define susp_nod_MASK 1
  34#define susp_fen_MASK 1
  35
  36#define NS(T, S) \
  37        ({ union drbd_state mask; mask.i = 0; mask.T = T##_MASK; mask; }), \
  38        ({ union drbd_state val; val.i = 0; val.T = (S); val; })
  39#define NS2(T1, S1, T2, S2) \
  40        ({ union drbd_state mask; mask.i = 0; mask.T1 = T1##_MASK; \
  41          mask.T2 = T2##_MASK; mask; }), \
  42        ({ union drbd_state val; val.i = 0; val.T1 = (S1); \
  43          val.T2 = (S2); val; })
  44#define NS3(T1, S1, T2, S2, T3, S3) \
  45        ({ union drbd_state mask; mask.i = 0; mask.T1 = T1##_MASK; \
  46          mask.T2 = T2##_MASK; mask.T3 = T3##_MASK; mask; }), \
  47        ({ union drbd_state val;  val.i = 0; val.T1 = (S1); \
  48          val.T2 = (S2); val.T3 = (S3); val; })
  49
  50#define _NS(D, T, S) \
  51        D, ({ union drbd_state __ns; __ns = drbd_read_state(D); __ns.T = (S); __ns; })
  52#define _NS2(D, T1, S1, T2, S2) \
  53        D, ({ union drbd_state __ns; __ns = drbd_read_state(D); __ns.T1 = (S1); \
  54        __ns.T2 = (S2); __ns; })
  55#define _NS3(D, T1, S1, T2, S2, T3, S3) \
  56        D, ({ union drbd_state __ns; __ns = drbd_read_state(D); __ns.T1 = (S1); \
  57        __ns.T2 = (S2); __ns.T3 = (S3); __ns; })
  58
  59enum chg_state_flags {
  60        CS_HARD          = 1 << 0,
  61        CS_VERBOSE       = 1 << 1,
  62        CS_WAIT_COMPLETE = 1 << 2,
  63        CS_SERIALIZE     = 1 << 3,
  64        CS_ORDERED       = CS_WAIT_COMPLETE + CS_SERIALIZE,
  65        CS_LOCAL_ONLY    = 1 << 4, /* Do not consider a device pair wide state change */
  66        CS_DC_ROLE       = 1 << 5, /* DC = display as connection state change */
  67        CS_DC_PEER       = 1 << 6,
  68        CS_DC_CONN       = 1 << 7,
  69        CS_DC_DISK       = 1 << 8,
  70        CS_DC_PDSK       = 1 << 9,
  71        CS_DC_SUSP       = 1 << 10,
  72        CS_DC_MASK       = CS_DC_ROLE + CS_DC_PEER + CS_DC_CONN + CS_DC_DISK + CS_DC_PDSK,
  73        CS_IGN_OUTD_FAIL = 1 << 11,
  74};
  75
  76/* drbd_dev_state and drbd_state are different types. This is to stress the
  77   small difference. There is no suspended flag (.susp), and no suspended
  78   while fence handler runs flas (susp_fen). */
  79union drbd_dev_state {
  80        struct {
  81#if defined(__LITTLE_ENDIAN_BITFIELD)
  82                unsigned role:2 ;   /* 3/4       primary/secondary/unknown */
  83                unsigned peer:2 ;   /* 3/4       primary/secondary/unknown */
  84                unsigned conn:5 ;   /* 17/32     cstates */
  85                unsigned disk:4 ;   /* 8/16      from D_DISKLESS to D_UP_TO_DATE */
  86                unsigned pdsk:4 ;   /* 8/16      from D_DISKLESS to D_UP_TO_DATE */
  87                unsigned _unused:1 ;
  88                unsigned aftr_isp:1 ; /* isp .. imposed sync pause */
  89                unsigned peer_isp:1 ;
  90                unsigned user_isp:1 ;
  91                unsigned _pad:11;   /* 0         unused */
  92#elif defined(__BIG_ENDIAN_BITFIELD)
  93                unsigned _pad:11;
  94                unsigned user_isp:1 ;
  95                unsigned peer_isp:1 ;
  96                unsigned aftr_isp:1 ; /* isp .. imposed sync pause */
  97                unsigned _unused:1 ;
  98                unsigned pdsk:4 ;   /* 8/16      from D_DISKLESS to D_UP_TO_DATE */
  99                unsigned disk:4 ;   /* 8/16      from D_DISKLESS to D_UP_TO_DATE */
 100                unsigned conn:5 ;   /* 17/32     cstates */
 101                unsigned peer:2 ;   /* 3/4       primary/secondary/unknown */
 102                unsigned role:2 ;   /* 3/4       primary/secondary/unknown */
 103#else
 104# error "this endianess is not supported"
 105#endif
 106        };
 107        unsigned int i;
 108};
 109
 110extern enum drbd_state_rv drbd_change_state(struct drbd_conf *mdev,
 111                                            enum chg_state_flags f,
 112                                            union drbd_state mask,
 113                                            union drbd_state val);
 114extern void drbd_force_state(struct drbd_conf *, union drbd_state,
 115                        union drbd_state);
 116extern enum drbd_state_rv _drbd_request_state(struct drbd_conf *,
 117                                              union drbd_state,
 118                                              union drbd_state,
 119                                              enum chg_state_flags);
 120extern enum drbd_state_rv __drbd_set_state(struct drbd_conf *, union drbd_state,
 121                                           enum chg_state_flags,
 122                                           struct completion *done);
 123extern void print_st_err(struct drbd_conf *, union drbd_state,
 124                        union drbd_state, int);
 125
 126enum drbd_state_rv
 127_conn_request_state(struct drbd_tconn *tconn, union drbd_state mask, union drbd_state val,
 128                    enum chg_state_flags flags);
 129
 130enum drbd_state_rv
 131conn_request_state(struct drbd_tconn *tconn, union drbd_state mask, union drbd_state val,
 132                   enum chg_state_flags flags);
 133
 134extern void drbd_resume_al(struct drbd_conf *mdev);
 135extern bool conn_all_vols_unconf(struct drbd_tconn *tconn);
 136
 137/**
 138 * drbd_request_state() - Reqest a state change
 139 * @mdev:       DRBD device.
 140 * @mask:       mask of state bits to change.
 141 * @val:        value of new state bits.
 142 *
 143 * This is the most graceful way of requesting a state change. It is verbose
 144 * quite verbose in case the state change is not possible, and all those
 145 * state changes are globally serialized.
 146 */
 147static inline int drbd_request_state(struct drbd_conf *mdev,
 148                                     union drbd_state mask,
 149                                     union drbd_state val)
 150{
 151        return _drbd_request_state(mdev, mask, val, CS_VERBOSE + CS_ORDERED);
 152}
 153
 154enum drbd_role conn_highest_role(struct drbd_tconn *tconn);
 155enum drbd_role conn_highest_peer(struct drbd_tconn *tconn);
 156enum drbd_disk_state conn_highest_disk(struct drbd_tconn *tconn);
 157enum drbd_disk_state conn_lowest_disk(struct drbd_tconn *tconn);
 158enum drbd_disk_state conn_highest_pdsk(struct drbd_tconn *tconn);
 159enum drbd_conns conn_lowest_conn(struct drbd_tconn *tconn);
 160
 161#endif
 162