blob: 3ec26e2c4c40b9ad0de53a8daa9c6c9268d1110a [file] [log] [blame]
Philipp Reisnerb8907332011-01-27 14:07:51 +01001#ifndef DRBD_STATE_H
2#define DRBD_STATE_H
3
4struct drbd_conf;
5
6/**
7 * DOC: DRBD State macros
8 *
9 * These macros are used to express state changes in easily readable form.
10 *
11 * The NS macros expand to a mask and a value, that can be bit ored onto the
12 * current state as soon as the spinlock (req_lock) was taken.
13 *
14 * The _NS macros are used for state functions that get called with the
15 * spinlock. These macros expand directly to the new state value.
16 *
17 * Besides the basic forms NS() and _NS() additional _?NS[23] are defined
18 * to express state changes that affect more than one aspect of the state.
19 *
20 * E.g. NS2(conn, C_CONNECTED, peer, R_SECONDARY)
21 * Means that the network connection was established and that the peer
22 * is in secondary role.
23 */
24#define role_MASK R_MASK
25#define peer_MASK R_MASK
26#define disk_MASK D_MASK
27#define pdsk_MASK D_MASK
28#define conn_MASK C_MASK
29#define susp_MASK 1
30#define user_isp_MASK 1
31#define aftr_isp_MASK 1
32#define susp_nod_MASK 1
33#define susp_fen_MASK 1
34
35#define NS(T, S) \
36 ({ union drbd_state mask; mask.i = 0; mask.T = T##_MASK; mask; }), \
37 ({ union drbd_state val; val.i = 0; val.T = (S); val; })
38#define NS2(T1, S1, T2, S2) \
39 ({ union drbd_state mask; mask.i = 0; mask.T1 = T1##_MASK; \
40 mask.T2 = T2##_MASK; mask; }), \
41 ({ union drbd_state val; val.i = 0; val.T1 = (S1); \
42 val.T2 = (S2); val; })
43#define NS3(T1, S1, T2, S2, T3, S3) \
44 ({ union drbd_state mask; mask.i = 0; mask.T1 = T1##_MASK; \
45 mask.T2 = T2##_MASK; mask.T3 = T3##_MASK; mask; }), \
46 ({ union drbd_state val; val.i = 0; val.T1 = (S1); \
47 val.T2 = (S2); val.T3 = (S3); val; })
48
49#define _NS(D, T, S) \
50 D, ({ union drbd_state __ns; __ns.i = D->state.i; __ns.T = (S); __ns; })
51#define _NS2(D, T1, S1, T2, S2) \
52 D, ({ union drbd_state __ns; __ns.i = D->state.i; __ns.T1 = (S1); \
53 __ns.T2 = (S2); __ns; })
54#define _NS3(D, T1, S1, T2, S2, T3, S3) \
55 D, ({ union drbd_state __ns; __ns.i = D->state.i; __ns.T1 = (S1); \
56 __ns.T2 = (S2); __ns.T3 = (S3); __ns; })
57
58enum chg_state_flags {
59 CS_HARD = 1,
60 CS_VERBOSE = 2,
61 CS_WAIT_COMPLETE = 4,
62 CS_SERIALIZE = 8,
63 CS_ORDERED = CS_WAIT_COMPLETE + CS_SERIALIZE,
64};
65
66extern enum drbd_state_rv drbd_change_state(struct drbd_conf *mdev,
67 enum chg_state_flags f,
68 union drbd_state mask,
69 union drbd_state val);
70extern void drbd_force_state(struct drbd_conf *, union drbd_state,
71 union drbd_state);
72extern enum drbd_state_rv _drbd_request_state(struct drbd_conf *,
73 union drbd_state,
74 union drbd_state,
75 enum chg_state_flags);
76extern enum drbd_state_rv __drbd_set_state(struct drbd_conf *, union drbd_state,
77 enum chg_state_flags,
78 struct completion *done);
79extern void print_st_err(struct drbd_conf *, union drbd_state,
80 union drbd_state, int);
81
82extern void drbd_resume_al(struct drbd_conf *mdev);
83
84/**
85 * drbd_request_state() - Reqest a state change
86 * @mdev: DRBD device.
87 * @mask: mask of state bits to change.
88 * @val: value of new state bits.
89 *
90 * This is the most graceful way of requesting a state change. It is verbose
91 * quite verbose in case the state change is not possible, and all those
92 * state changes are globally serialized.
93 */
94static inline int drbd_request_state(struct drbd_conf *mdev,
95 union drbd_state mask,
96 union drbd_state val)
97{
98 return _drbd_request_state(mdev, mask, val, CS_VERBOSE + CS_ORDERED);
99}
100
101#endif