18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */ 28c2ecf20Sopenharmony_ci#ifndef DRBD_STATE_H 38c2ecf20Sopenharmony_ci#define DRBD_STATE_H 48c2ecf20Sopenharmony_ci 58c2ecf20Sopenharmony_cistruct drbd_device; 68c2ecf20Sopenharmony_cistruct drbd_connection; 78c2ecf20Sopenharmony_ci 88c2ecf20Sopenharmony_ci/** 98c2ecf20Sopenharmony_ci * DOC: DRBD State macros 108c2ecf20Sopenharmony_ci * 118c2ecf20Sopenharmony_ci * These macros are used to express state changes in easily readable form. 128c2ecf20Sopenharmony_ci * 138c2ecf20Sopenharmony_ci * The NS macros expand to a mask and a value, that can be bit ored onto the 148c2ecf20Sopenharmony_ci * current state as soon as the spinlock (req_lock) was taken. 158c2ecf20Sopenharmony_ci * 168c2ecf20Sopenharmony_ci * The _NS macros are used for state functions that get called with the 178c2ecf20Sopenharmony_ci * spinlock. These macros expand directly to the new state value. 188c2ecf20Sopenharmony_ci * 198c2ecf20Sopenharmony_ci * Besides the basic forms NS() and _NS() additional _?NS[23] are defined 208c2ecf20Sopenharmony_ci * to express state changes that affect more than one aspect of the state. 218c2ecf20Sopenharmony_ci * 228c2ecf20Sopenharmony_ci * E.g. NS2(conn, C_CONNECTED, peer, R_SECONDARY) 238c2ecf20Sopenharmony_ci * Means that the network connection was established and that the peer 248c2ecf20Sopenharmony_ci * is in secondary role. 258c2ecf20Sopenharmony_ci */ 268c2ecf20Sopenharmony_ci#define role_MASK R_MASK 278c2ecf20Sopenharmony_ci#define peer_MASK R_MASK 288c2ecf20Sopenharmony_ci#define disk_MASK D_MASK 298c2ecf20Sopenharmony_ci#define pdsk_MASK D_MASK 308c2ecf20Sopenharmony_ci#define conn_MASK C_MASK 318c2ecf20Sopenharmony_ci#define susp_MASK 1 328c2ecf20Sopenharmony_ci#define user_isp_MASK 1 338c2ecf20Sopenharmony_ci#define aftr_isp_MASK 1 348c2ecf20Sopenharmony_ci#define susp_nod_MASK 1 358c2ecf20Sopenharmony_ci#define susp_fen_MASK 1 368c2ecf20Sopenharmony_ci 378c2ecf20Sopenharmony_ci#define NS(T, S) \ 388c2ecf20Sopenharmony_ci ({ union drbd_state mask; mask.i = 0; mask.T = T##_MASK; mask; }), \ 398c2ecf20Sopenharmony_ci ({ union drbd_state val; val.i = 0; val.T = (S); val; }) 408c2ecf20Sopenharmony_ci#define NS2(T1, S1, T2, S2) \ 418c2ecf20Sopenharmony_ci ({ union drbd_state mask; mask.i = 0; mask.T1 = T1##_MASK; \ 428c2ecf20Sopenharmony_ci mask.T2 = T2##_MASK; mask; }), \ 438c2ecf20Sopenharmony_ci ({ union drbd_state val; val.i = 0; val.T1 = (S1); \ 448c2ecf20Sopenharmony_ci val.T2 = (S2); val; }) 458c2ecf20Sopenharmony_ci#define NS3(T1, S1, T2, S2, T3, S3) \ 468c2ecf20Sopenharmony_ci ({ union drbd_state mask; mask.i = 0; mask.T1 = T1##_MASK; \ 478c2ecf20Sopenharmony_ci mask.T2 = T2##_MASK; mask.T3 = T3##_MASK; mask; }), \ 488c2ecf20Sopenharmony_ci ({ union drbd_state val; val.i = 0; val.T1 = (S1); \ 498c2ecf20Sopenharmony_ci val.T2 = (S2); val.T3 = (S3); val; }) 508c2ecf20Sopenharmony_ci 518c2ecf20Sopenharmony_ci#define _NS(D, T, S) \ 528c2ecf20Sopenharmony_ci D, ({ union drbd_state __ns; __ns = drbd_read_state(D); __ns.T = (S); __ns; }) 538c2ecf20Sopenharmony_ci#define _NS2(D, T1, S1, T2, S2) \ 548c2ecf20Sopenharmony_ci D, ({ union drbd_state __ns; __ns = drbd_read_state(D); __ns.T1 = (S1); \ 558c2ecf20Sopenharmony_ci __ns.T2 = (S2); __ns; }) 568c2ecf20Sopenharmony_ci#define _NS3(D, T1, S1, T2, S2, T3, S3) \ 578c2ecf20Sopenharmony_ci D, ({ union drbd_state __ns; __ns = drbd_read_state(D); __ns.T1 = (S1); \ 588c2ecf20Sopenharmony_ci __ns.T2 = (S2); __ns.T3 = (S3); __ns; }) 598c2ecf20Sopenharmony_ci 608c2ecf20Sopenharmony_cienum chg_state_flags { 618c2ecf20Sopenharmony_ci CS_HARD = 1 << 0, 628c2ecf20Sopenharmony_ci CS_VERBOSE = 1 << 1, 638c2ecf20Sopenharmony_ci CS_WAIT_COMPLETE = 1 << 2, 648c2ecf20Sopenharmony_ci CS_SERIALIZE = 1 << 3, 658c2ecf20Sopenharmony_ci CS_ORDERED = CS_WAIT_COMPLETE + CS_SERIALIZE, 668c2ecf20Sopenharmony_ci CS_LOCAL_ONLY = 1 << 4, /* Do not consider a device pair wide state change */ 678c2ecf20Sopenharmony_ci CS_DC_ROLE = 1 << 5, /* DC = display as connection state change */ 688c2ecf20Sopenharmony_ci CS_DC_PEER = 1 << 6, 698c2ecf20Sopenharmony_ci CS_DC_CONN = 1 << 7, 708c2ecf20Sopenharmony_ci CS_DC_DISK = 1 << 8, 718c2ecf20Sopenharmony_ci CS_DC_PDSK = 1 << 9, 728c2ecf20Sopenharmony_ci CS_DC_SUSP = 1 << 10, 738c2ecf20Sopenharmony_ci CS_DC_MASK = CS_DC_ROLE + CS_DC_PEER + CS_DC_CONN + CS_DC_DISK + CS_DC_PDSK, 748c2ecf20Sopenharmony_ci CS_IGN_OUTD_FAIL = 1 << 11, 758c2ecf20Sopenharmony_ci 768c2ecf20Sopenharmony_ci /* Make sure no meta data IO is in flight, by calling 778c2ecf20Sopenharmony_ci * drbd_md_get_buffer(). Used for graceful detach. */ 788c2ecf20Sopenharmony_ci CS_INHIBIT_MD_IO = 1 << 12, 798c2ecf20Sopenharmony_ci}; 808c2ecf20Sopenharmony_ci 818c2ecf20Sopenharmony_ci/* drbd_dev_state and drbd_state are different types. This is to stress the 828c2ecf20Sopenharmony_ci small difference. There is no suspended flag (.susp), and no suspended 838c2ecf20Sopenharmony_ci while fence handler runs flas (susp_fen). */ 848c2ecf20Sopenharmony_ciunion drbd_dev_state { 858c2ecf20Sopenharmony_ci struct { 868c2ecf20Sopenharmony_ci#if defined(__LITTLE_ENDIAN_BITFIELD) 878c2ecf20Sopenharmony_ci unsigned role:2 ; /* 3/4 primary/secondary/unknown */ 888c2ecf20Sopenharmony_ci unsigned peer:2 ; /* 3/4 primary/secondary/unknown */ 898c2ecf20Sopenharmony_ci unsigned conn:5 ; /* 17/32 cstates */ 908c2ecf20Sopenharmony_ci unsigned disk:4 ; /* 8/16 from D_DISKLESS to D_UP_TO_DATE */ 918c2ecf20Sopenharmony_ci unsigned pdsk:4 ; /* 8/16 from D_DISKLESS to D_UP_TO_DATE */ 928c2ecf20Sopenharmony_ci unsigned _unused:1 ; 938c2ecf20Sopenharmony_ci unsigned aftr_isp:1 ; /* isp .. imposed sync pause */ 948c2ecf20Sopenharmony_ci unsigned peer_isp:1 ; 958c2ecf20Sopenharmony_ci unsigned user_isp:1 ; 968c2ecf20Sopenharmony_ci unsigned _pad:11; /* 0 unused */ 978c2ecf20Sopenharmony_ci#elif defined(__BIG_ENDIAN_BITFIELD) 988c2ecf20Sopenharmony_ci unsigned _pad:11; 998c2ecf20Sopenharmony_ci unsigned user_isp:1 ; 1008c2ecf20Sopenharmony_ci unsigned peer_isp:1 ; 1018c2ecf20Sopenharmony_ci unsigned aftr_isp:1 ; /* isp .. imposed sync pause */ 1028c2ecf20Sopenharmony_ci unsigned _unused:1 ; 1038c2ecf20Sopenharmony_ci unsigned pdsk:4 ; /* 8/16 from D_DISKLESS to D_UP_TO_DATE */ 1048c2ecf20Sopenharmony_ci unsigned disk:4 ; /* 8/16 from D_DISKLESS to D_UP_TO_DATE */ 1058c2ecf20Sopenharmony_ci unsigned conn:5 ; /* 17/32 cstates */ 1068c2ecf20Sopenharmony_ci unsigned peer:2 ; /* 3/4 primary/secondary/unknown */ 1078c2ecf20Sopenharmony_ci unsigned role:2 ; /* 3/4 primary/secondary/unknown */ 1088c2ecf20Sopenharmony_ci#else 1098c2ecf20Sopenharmony_ci# error "this endianess is not supported" 1108c2ecf20Sopenharmony_ci#endif 1118c2ecf20Sopenharmony_ci }; 1128c2ecf20Sopenharmony_ci unsigned int i; 1138c2ecf20Sopenharmony_ci}; 1148c2ecf20Sopenharmony_ci 1158c2ecf20Sopenharmony_ciextern enum drbd_state_rv drbd_change_state(struct drbd_device *device, 1168c2ecf20Sopenharmony_ci enum chg_state_flags f, 1178c2ecf20Sopenharmony_ci union drbd_state mask, 1188c2ecf20Sopenharmony_ci union drbd_state val); 1198c2ecf20Sopenharmony_ciextern void drbd_force_state(struct drbd_device *, union drbd_state, 1208c2ecf20Sopenharmony_ci union drbd_state); 1218c2ecf20Sopenharmony_ciextern enum drbd_state_rv _drbd_request_state(struct drbd_device *, 1228c2ecf20Sopenharmony_ci union drbd_state, 1238c2ecf20Sopenharmony_ci union drbd_state, 1248c2ecf20Sopenharmony_ci enum chg_state_flags); 1258c2ecf20Sopenharmony_ci 1268c2ecf20Sopenharmony_ciextern enum drbd_state_rv 1278c2ecf20Sopenharmony_ci_drbd_request_state_holding_state_mutex(struct drbd_device *, union drbd_state, 1288c2ecf20Sopenharmony_ci union drbd_state, enum chg_state_flags); 1298c2ecf20Sopenharmony_ci 1308c2ecf20Sopenharmony_ciextern enum drbd_state_rv _drbd_set_state(struct drbd_device *, union drbd_state, 1318c2ecf20Sopenharmony_ci enum chg_state_flags, 1328c2ecf20Sopenharmony_ci struct completion *done); 1338c2ecf20Sopenharmony_ciextern void print_st_err(struct drbd_device *, union drbd_state, 1348c2ecf20Sopenharmony_ci union drbd_state, enum drbd_state_rv); 1358c2ecf20Sopenharmony_ci 1368c2ecf20Sopenharmony_cienum drbd_state_rv 1378c2ecf20Sopenharmony_ci_conn_request_state(struct drbd_connection *connection, union drbd_state mask, union drbd_state val, 1388c2ecf20Sopenharmony_ci enum chg_state_flags flags); 1398c2ecf20Sopenharmony_ci 1408c2ecf20Sopenharmony_cienum drbd_state_rv 1418c2ecf20Sopenharmony_ciconn_request_state(struct drbd_connection *connection, union drbd_state mask, union drbd_state val, 1428c2ecf20Sopenharmony_ci enum chg_state_flags flags); 1438c2ecf20Sopenharmony_ci 1448c2ecf20Sopenharmony_ciextern void drbd_resume_al(struct drbd_device *device); 1458c2ecf20Sopenharmony_ciextern bool conn_all_vols_unconf(struct drbd_connection *connection); 1468c2ecf20Sopenharmony_ci 1478c2ecf20Sopenharmony_ci/** 1488c2ecf20Sopenharmony_ci * drbd_request_state() - Request a state change 1498c2ecf20Sopenharmony_ci * @device: DRBD device. 1508c2ecf20Sopenharmony_ci * @mask: mask of state bits to change. 1518c2ecf20Sopenharmony_ci * @val: value of new state bits. 1528c2ecf20Sopenharmony_ci * 1538c2ecf20Sopenharmony_ci * This is the most graceful way of requesting a state change. It is verbose 1548c2ecf20Sopenharmony_ci * quite verbose in case the state change is not possible, and all those 1558c2ecf20Sopenharmony_ci * state changes are globally serialized. 1568c2ecf20Sopenharmony_ci */ 1578c2ecf20Sopenharmony_cistatic inline int drbd_request_state(struct drbd_device *device, 1588c2ecf20Sopenharmony_ci union drbd_state mask, 1598c2ecf20Sopenharmony_ci union drbd_state val) 1608c2ecf20Sopenharmony_ci{ 1618c2ecf20Sopenharmony_ci return _drbd_request_state(device, mask, val, CS_VERBOSE + CS_ORDERED); 1628c2ecf20Sopenharmony_ci} 1638c2ecf20Sopenharmony_ci 1648c2ecf20Sopenharmony_ci/* for use in adm_detach() (drbd_adm_detach(), drbd_adm_down()) */ 1658c2ecf20Sopenharmony_ciint drbd_request_detach_interruptible(struct drbd_device *device); 1668c2ecf20Sopenharmony_ci 1678c2ecf20Sopenharmony_cienum drbd_role conn_highest_role(struct drbd_connection *connection); 1688c2ecf20Sopenharmony_cienum drbd_role conn_highest_peer(struct drbd_connection *connection); 1698c2ecf20Sopenharmony_cienum drbd_disk_state conn_highest_disk(struct drbd_connection *connection); 1708c2ecf20Sopenharmony_cienum drbd_disk_state conn_lowest_disk(struct drbd_connection *connection); 1718c2ecf20Sopenharmony_cienum drbd_disk_state conn_highest_pdsk(struct drbd_connection *connection); 1728c2ecf20Sopenharmony_cienum drbd_conns conn_lowest_conn(struct drbd_connection *connection); 1738c2ecf20Sopenharmony_ci 1748c2ecf20Sopenharmony_ci#endif 175