162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0-only */ 262306a36Sopenharmony_ci#ifndef DRBD_STATE_H 362306a36Sopenharmony_ci#define DRBD_STATE_H 462306a36Sopenharmony_ci 562306a36Sopenharmony_cistruct drbd_device; 662306a36Sopenharmony_cistruct drbd_connection; 762306a36Sopenharmony_ci 862306a36Sopenharmony_ci/** 962306a36Sopenharmony_ci * DOC: DRBD State macros 1062306a36Sopenharmony_ci * 1162306a36Sopenharmony_ci * These macros are used to express state changes in easily readable form. 1262306a36Sopenharmony_ci * 1362306a36Sopenharmony_ci * The NS macros expand to a mask and a value, that can be bit ored onto the 1462306a36Sopenharmony_ci * current state as soon as the spinlock (req_lock) was taken. 1562306a36Sopenharmony_ci * 1662306a36Sopenharmony_ci * The _NS macros are used for state functions that get called with the 1762306a36Sopenharmony_ci * spinlock. These macros expand directly to the new state value. 1862306a36Sopenharmony_ci * 1962306a36Sopenharmony_ci * Besides the basic forms NS() and _NS() additional _?NS[23] are defined 2062306a36Sopenharmony_ci * to express state changes that affect more than one aspect of the state. 2162306a36Sopenharmony_ci * 2262306a36Sopenharmony_ci * E.g. NS2(conn, C_CONNECTED, peer, R_SECONDARY) 2362306a36Sopenharmony_ci * Means that the network connection was established and that the peer 2462306a36Sopenharmony_ci * is in secondary role. 2562306a36Sopenharmony_ci */ 2662306a36Sopenharmony_ci#define role_MASK R_MASK 2762306a36Sopenharmony_ci#define peer_MASK R_MASK 2862306a36Sopenharmony_ci#define disk_MASK D_MASK 2962306a36Sopenharmony_ci#define pdsk_MASK D_MASK 3062306a36Sopenharmony_ci#define conn_MASK C_MASK 3162306a36Sopenharmony_ci#define susp_MASK 1 3262306a36Sopenharmony_ci#define user_isp_MASK 1 3362306a36Sopenharmony_ci#define aftr_isp_MASK 1 3462306a36Sopenharmony_ci#define susp_nod_MASK 1 3562306a36Sopenharmony_ci#define susp_fen_MASK 1 3662306a36Sopenharmony_ci 3762306a36Sopenharmony_ci#define NS(T, S) \ 3862306a36Sopenharmony_ci ({ union drbd_state mask; mask.i = 0; mask.T = T##_MASK; mask; }), \ 3962306a36Sopenharmony_ci ({ union drbd_state val; val.i = 0; val.T = (S); val; }) 4062306a36Sopenharmony_ci#define NS2(T1, S1, T2, S2) \ 4162306a36Sopenharmony_ci ({ union drbd_state mask; mask.i = 0; mask.T1 = T1##_MASK; \ 4262306a36Sopenharmony_ci mask.T2 = T2##_MASK; mask; }), \ 4362306a36Sopenharmony_ci ({ union drbd_state val; val.i = 0; val.T1 = (S1); \ 4462306a36Sopenharmony_ci val.T2 = (S2); val; }) 4562306a36Sopenharmony_ci#define NS3(T1, S1, T2, S2, T3, S3) \ 4662306a36Sopenharmony_ci ({ union drbd_state mask; mask.i = 0; mask.T1 = T1##_MASK; \ 4762306a36Sopenharmony_ci mask.T2 = T2##_MASK; mask.T3 = T3##_MASK; mask; }), \ 4862306a36Sopenharmony_ci ({ union drbd_state val; val.i = 0; val.T1 = (S1); \ 4962306a36Sopenharmony_ci val.T2 = (S2); val.T3 = (S3); val; }) 5062306a36Sopenharmony_ci 5162306a36Sopenharmony_ci#define _NS(D, T, S) \ 5262306a36Sopenharmony_ci D, ({ union drbd_state __ns; __ns = drbd_read_state(D); __ns.T = (S); __ns; }) 5362306a36Sopenharmony_ci#define _NS2(D, T1, S1, T2, S2) \ 5462306a36Sopenharmony_ci D, ({ union drbd_state __ns; __ns = drbd_read_state(D); __ns.T1 = (S1); \ 5562306a36Sopenharmony_ci __ns.T2 = (S2); __ns; }) 5662306a36Sopenharmony_ci#define _NS3(D, T1, S1, T2, S2, T3, S3) \ 5762306a36Sopenharmony_ci D, ({ union drbd_state __ns; __ns = drbd_read_state(D); __ns.T1 = (S1); \ 5862306a36Sopenharmony_ci __ns.T2 = (S2); __ns.T3 = (S3); __ns; }) 5962306a36Sopenharmony_ci 6062306a36Sopenharmony_cienum chg_state_flags { 6162306a36Sopenharmony_ci CS_HARD = 1 << 0, 6262306a36Sopenharmony_ci CS_VERBOSE = 1 << 1, 6362306a36Sopenharmony_ci CS_WAIT_COMPLETE = 1 << 2, 6462306a36Sopenharmony_ci CS_SERIALIZE = 1 << 3, 6562306a36Sopenharmony_ci CS_ORDERED = CS_WAIT_COMPLETE + CS_SERIALIZE, 6662306a36Sopenharmony_ci CS_LOCAL_ONLY = 1 << 4, /* Do not consider a device pair wide state change */ 6762306a36Sopenharmony_ci CS_DC_ROLE = 1 << 5, /* DC = display as connection state change */ 6862306a36Sopenharmony_ci CS_DC_PEER = 1 << 6, 6962306a36Sopenharmony_ci CS_DC_CONN = 1 << 7, 7062306a36Sopenharmony_ci CS_DC_DISK = 1 << 8, 7162306a36Sopenharmony_ci CS_DC_PDSK = 1 << 9, 7262306a36Sopenharmony_ci CS_DC_SUSP = 1 << 10, 7362306a36Sopenharmony_ci CS_DC_MASK = CS_DC_ROLE + CS_DC_PEER + CS_DC_CONN + CS_DC_DISK + CS_DC_PDSK, 7462306a36Sopenharmony_ci CS_IGN_OUTD_FAIL = 1 << 11, 7562306a36Sopenharmony_ci 7662306a36Sopenharmony_ci /* Make sure no meta data IO is in flight, by calling 7762306a36Sopenharmony_ci * drbd_md_get_buffer(). Used for graceful detach. */ 7862306a36Sopenharmony_ci CS_INHIBIT_MD_IO = 1 << 12, 7962306a36Sopenharmony_ci}; 8062306a36Sopenharmony_ci 8162306a36Sopenharmony_ci/* drbd_dev_state and drbd_state are different types. This is to stress the 8262306a36Sopenharmony_ci small difference. There is no suspended flag (.susp), and no suspended 8362306a36Sopenharmony_ci while fence handler runs flas (susp_fen). */ 8462306a36Sopenharmony_ciunion drbd_dev_state { 8562306a36Sopenharmony_ci struct { 8662306a36Sopenharmony_ci#if defined(__LITTLE_ENDIAN_BITFIELD) 8762306a36Sopenharmony_ci unsigned role:2 ; /* 3/4 primary/secondary/unknown */ 8862306a36Sopenharmony_ci unsigned peer:2 ; /* 3/4 primary/secondary/unknown */ 8962306a36Sopenharmony_ci unsigned conn:5 ; /* 17/32 cstates */ 9062306a36Sopenharmony_ci unsigned disk:4 ; /* 8/16 from D_DISKLESS to D_UP_TO_DATE */ 9162306a36Sopenharmony_ci unsigned pdsk:4 ; /* 8/16 from D_DISKLESS to D_UP_TO_DATE */ 9262306a36Sopenharmony_ci unsigned _unused:1 ; 9362306a36Sopenharmony_ci unsigned aftr_isp:1 ; /* isp .. imposed sync pause */ 9462306a36Sopenharmony_ci unsigned peer_isp:1 ; 9562306a36Sopenharmony_ci unsigned user_isp:1 ; 9662306a36Sopenharmony_ci unsigned _pad:11; /* 0 unused */ 9762306a36Sopenharmony_ci#elif defined(__BIG_ENDIAN_BITFIELD) 9862306a36Sopenharmony_ci unsigned _pad:11; 9962306a36Sopenharmony_ci unsigned user_isp:1 ; 10062306a36Sopenharmony_ci unsigned peer_isp:1 ; 10162306a36Sopenharmony_ci unsigned aftr_isp:1 ; /* isp .. imposed sync pause */ 10262306a36Sopenharmony_ci unsigned _unused:1 ; 10362306a36Sopenharmony_ci unsigned pdsk:4 ; /* 8/16 from D_DISKLESS to D_UP_TO_DATE */ 10462306a36Sopenharmony_ci unsigned disk:4 ; /* 8/16 from D_DISKLESS to D_UP_TO_DATE */ 10562306a36Sopenharmony_ci unsigned conn:5 ; /* 17/32 cstates */ 10662306a36Sopenharmony_ci unsigned peer:2 ; /* 3/4 primary/secondary/unknown */ 10762306a36Sopenharmony_ci unsigned role:2 ; /* 3/4 primary/secondary/unknown */ 10862306a36Sopenharmony_ci#else 10962306a36Sopenharmony_ci# error "this endianess is not supported" 11062306a36Sopenharmony_ci#endif 11162306a36Sopenharmony_ci }; 11262306a36Sopenharmony_ci unsigned int i; 11362306a36Sopenharmony_ci}; 11462306a36Sopenharmony_ci 11562306a36Sopenharmony_ciextern enum drbd_state_rv drbd_change_state(struct drbd_device *device, 11662306a36Sopenharmony_ci enum chg_state_flags f, 11762306a36Sopenharmony_ci union drbd_state mask, 11862306a36Sopenharmony_ci union drbd_state val); 11962306a36Sopenharmony_ciextern void drbd_force_state(struct drbd_device *, union drbd_state, 12062306a36Sopenharmony_ci union drbd_state); 12162306a36Sopenharmony_ciextern enum drbd_state_rv _drbd_request_state(struct drbd_device *, 12262306a36Sopenharmony_ci union drbd_state, 12362306a36Sopenharmony_ci union drbd_state, 12462306a36Sopenharmony_ci enum chg_state_flags); 12562306a36Sopenharmony_ci 12662306a36Sopenharmony_ciextern enum drbd_state_rv 12762306a36Sopenharmony_ci_drbd_request_state_holding_state_mutex(struct drbd_device *, union drbd_state, 12862306a36Sopenharmony_ci union drbd_state, enum chg_state_flags); 12962306a36Sopenharmony_ci 13062306a36Sopenharmony_ciextern enum drbd_state_rv _drbd_set_state(struct drbd_device *, union drbd_state, 13162306a36Sopenharmony_ci enum chg_state_flags, 13262306a36Sopenharmony_ci struct completion *done); 13362306a36Sopenharmony_ciextern void print_st_err(struct drbd_device *, union drbd_state, 13462306a36Sopenharmony_ci union drbd_state, enum drbd_state_rv); 13562306a36Sopenharmony_ci 13662306a36Sopenharmony_cienum drbd_state_rv 13762306a36Sopenharmony_ci_conn_request_state(struct drbd_connection *connection, union drbd_state mask, union drbd_state val, 13862306a36Sopenharmony_ci enum chg_state_flags flags); 13962306a36Sopenharmony_ci 14062306a36Sopenharmony_cienum drbd_state_rv 14162306a36Sopenharmony_ciconn_request_state(struct drbd_connection *connection, union drbd_state mask, union drbd_state val, 14262306a36Sopenharmony_ci enum chg_state_flags flags); 14362306a36Sopenharmony_ci 14462306a36Sopenharmony_ciextern void drbd_resume_al(struct drbd_device *device); 14562306a36Sopenharmony_ciextern bool conn_all_vols_unconf(struct drbd_connection *connection); 14662306a36Sopenharmony_ci 14762306a36Sopenharmony_ci/** 14862306a36Sopenharmony_ci * drbd_request_state() - Request a state change 14962306a36Sopenharmony_ci * @device: DRBD device. 15062306a36Sopenharmony_ci * @mask: mask of state bits to change. 15162306a36Sopenharmony_ci * @val: value of new state bits. 15262306a36Sopenharmony_ci * 15362306a36Sopenharmony_ci * This is the most graceful way of requesting a state change. It is verbose 15462306a36Sopenharmony_ci * quite verbose in case the state change is not possible, and all those 15562306a36Sopenharmony_ci * state changes are globally serialized. 15662306a36Sopenharmony_ci */ 15762306a36Sopenharmony_cistatic inline int drbd_request_state(struct drbd_device *device, 15862306a36Sopenharmony_ci union drbd_state mask, 15962306a36Sopenharmony_ci union drbd_state val) 16062306a36Sopenharmony_ci{ 16162306a36Sopenharmony_ci return _drbd_request_state(device, mask, val, CS_VERBOSE + CS_ORDERED); 16262306a36Sopenharmony_ci} 16362306a36Sopenharmony_ci 16462306a36Sopenharmony_ci/* for use in adm_detach() (drbd_adm_detach(), drbd_adm_down()) */ 16562306a36Sopenharmony_ciint drbd_request_detach_interruptible(struct drbd_device *device); 16662306a36Sopenharmony_ci 16762306a36Sopenharmony_cienum drbd_role conn_highest_role(struct drbd_connection *connection); 16862306a36Sopenharmony_cienum drbd_role conn_highest_peer(struct drbd_connection *connection); 16962306a36Sopenharmony_cienum drbd_disk_state conn_highest_disk(struct drbd_connection *connection); 17062306a36Sopenharmony_cienum drbd_disk_state conn_lowest_disk(struct drbd_connection *connection); 17162306a36Sopenharmony_cienum drbd_disk_state conn_highest_pdsk(struct drbd_connection *connection); 17262306a36Sopenharmony_cienum drbd_conns conn_lowest_conn(struct drbd_connection *connection); 17362306a36Sopenharmony_ci 17462306a36Sopenharmony_ci#endif 175