1e7fd4179SDavid Teigland /****************************************************************************** 2e7fd4179SDavid Teigland ******************************************************************************* 3e7fd4179SDavid Teigland ** 4e7fd4179SDavid Teigland ** Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved. 5dbcfc347SDavid Teigland ** Copyright (C) 2005-2008 Red Hat, Inc. All rights reserved. 6e7fd4179SDavid Teigland ** 7e7fd4179SDavid Teigland ** This copyrighted material is made available to anyone wishing to use, 8e7fd4179SDavid Teigland ** modify, copy, or redistribute it subject to the terms and conditions 9e7fd4179SDavid Teigland ** of the GNU General Public License v.2. 10e7fd4179SDavid Teigland ** 11e7fd4179SDavid Teigland ******************************************************************************* 12e7fd4179SDavid Teigland ******************************************************************************/ 13e7fd4179SDavid Teigland 14e7fd4179SDavid Teigland #include "dlm_internal.h" 15e7fd4179SDavid Teigland #include "lockspace.h" 16e7fd4179SDavid Teigland #include "member.h" 17e7fd4179SDavid Teigland #include "lowcomms.h" 18e7fd4179SDavid Teigland #include "midcomms.h" 19e7fd4179SDavid Teigland #include "rcom.h" 20e7fd4179SDavid Teigland #include "recover.h" 21e7fd4179SDavid Teigland #include "dir.h" 22e7fd4179SDavid Teigland #include "config.h" 23e7fd4179SDavid Teigland #include "memory.h" 24e7fd4179SDavid Teigland #include "lock.h" 25e7fd4179SDavid Teigland #include "util.h" 26e7fd4179SDavid Teigland 27e7fd4179SDavid Teigland static int rcom_response(struct dlm_ls *ls) 28e7fd4179SDavid Teigland { 29e7fd4179SDavid Teigland return test_bit(LSFL_RCOM_READY, &ls->ls_flags); 30e7fd4179SDavid Teigland } 31e7fd4179SDavid Teigland 32e7fd4179SDavid Teigland static int create_rcom(struct dlm_ls *ls, int to_nodeid, int type, int len, 33e7fd4179SDavid Teigland struct dlm_rcom **rc_ret, struct dlm_mhandle **mh_ret) 34e7fd4179SDavid Teigland { 35e7fd4179SDavid Teigland struct dlm_rcom *rc; 36e7fd4179SDavid Teigland struct dlm_mhandle *mh; 37e7fd4179SDavid Teigland char *mb; 38e7fd4179SDavid Teigland int mb_len = sizeof(struct dlm_rcom) + len; 39e7fd4179SDavid Teigland 40573c24c4SDavid Teigland mh = dlm_lowcomms_get_buffer(to_nodeid, mb_len, GFP_NOFS, &mb); 41e7fd4179SDavid Teigland if (!mh) { 42e7fd4179SDavid Teigland log_print("create_rcom to %d type %d len %d ENOBUFS", 43e7fd4179SDavid Teigland to_nodeid, type, len); 44e7fd4179SDavid Teigland return -ENOBUFS; 45e7fd4179SDavid Teigland } 46e7fd4179SDavid Teigland memset(mb, 0, mb_len); 47e7fd4179SDavid Teigland 48e7fd4179SDavid Teigland rc = (struct dlm_rcom *) mb; 49e7fd4179SDavid Teigland 50e7fd4179SDavid Teigland rc->rc_header.h_version = (DLM_HEADER_MAJOR | DLM_HEADER_MINOR); 51e7fd4179SDavid Teigland rc->rc_header.h_lockspace = ls->ls_global_id; 52e7fd4179SDavid Teigland rc->rc_header.h_nodeid = dlm_our_nodeid(); 53e7fd4179SDavid Teigland rc->rc_header.h_length = mb_len; 54e7fd4179SDavid Teigland rc->rc_header.h_cmd = DLM_RCOM; 55e7fd4179SDavid Teigland 56e7fd4179SDavid Teigland rc->rc_type = type; 57e7fd4179SDavid Teigland 5838aa8b0cSDavid Teigland spin_lock(&ls->ls_recover_lock); 5938aa8b0cSDavid Teigland rc->rc_seq = ls->ls_recover_seq; 6038aa8b0cSDavid Teigland spin_unlock(&ls->ls_recover_lock); 6138aa8b0cSDavid Teigland 62e7fd4179SDavid Teigland *mh_ret = mh; 63e7fd4179SDavid Teigland *rc_ret = rc; 64e7fd4179SDavid Teigland return 0; 65e7fd4179SDavid Teigland } 66e7fd4179SDavid Teigland 67e7fd4179SDavid Teigland static void send_rcom(struct dlm_ls *ls, struct dlm_mhandle *mh, 68e7fd4179SDavid Teigland struct dlm_rcom *rc) 69e7fd4179SDavid Teigland { 70e7fd4179SDavid Teigland dlm_rcom_out(rc); 71e7fd4179SDavid Teigland dlm_lowcomms_commit_buffer(mh); 72e7fd4179SDavid Teigland } 73e7fd4179SDavid Teigland 74757a4271SDavid Teigland static void set_rcom_status(struct dlm_ls *ls, struct rcom_status *rs, 75757a4271SDavid Teigland uint32_t flags) 76757a4271SDavid Teigland { 77757a4271SDavid Teigland rs->rs_flags = cpu_to_le32(flags); 78757a4271SDavid Teigland } 79757a4271SDavid Teigland 80e7fd4179SDavid Teigland /* When replying to a status request, a node also sends back its 81e7fd4179SDavid Teigland configuration values. The requesting node then checks that the remote 82e7fd4179SDavid Teigland node is configured the same way as itself. */ 83e7fd4179SDavid Teigland 84757a4271SDavid Teigland static void set_rcom_config(struct dlm_ls *ls, struct rcom_config *rf, 85757a4271SDavid Teigland uint32_t num_slots) 86e7fd4179SDavid Teigland { 8793ff2971SAl Viro rf->rf_lvblen = cpu_to_le32(ls->ls_lvblen); 8893ff2971SAl Viro rf->rf_lsflags = cpu_to_le32(ls->ls_exflags); 89757a4271SDavid Teigland 90757a4271SDavid Teigland rf->rf_our_slot = cpu_to_le16(ls->ls_slot); 91757a4271SDavid Teigland rf->rf_num_slots = cpu_to_le16(num_slots); 92757a4271SDavid Teigland rf->rf_generation = cpu_to_le32(ls->ls_generation); 93e7fd4179SDavid Teigland } 94e7fd4179SDavid Teigland 95757a4271SDavid Teigland static int check_rcom_config(struct dlm_ls *ls, struct dlm_rcom *rc, int nodeid) 96e7fd4179SDavid Teigland { 979e971b71SDavid Teigland struct rcom_config *rf = (struct rcom_config *) rc->rc_buf; 989e971b71SDavid Teigland 999e971b71SDavid Teigland if ((rc->rc_header.h_version & 0xFFFF0000) != DLM_HEADER_MAJOR) { 1009e971b71SDavid Teigland log_error(ls, "version mismatch: %x nodeid %d: %x", 1019e971b71SDavid Teigland DLM_HEADER_MAJOR | DLM_HEADER_MINOR, nodeid, 1029e971b71SDavid Teigland rc->rc_header.h_version); 1038b0e7b2cSDavid Teigland return -EPROTO; 1049e971b71SDavid Teigland } 1059e971b71SDavid Teigland 10693ff2971SAl Viro if (le32_to_cpu(rf->rf_lvblen) != ls->ls_lvblen || 10793ff2971SAl Viro le32_to_cpu(rf->rf_lsflags) != ls->ls_exflags) { 108e7fd4179SDavid Teigland log_error(ls, "config mismatch: %d,%x nodeid %d: %d,%x", 10993ff2971SAl Viro ls->ls_lvblen, ls->ls_exflags, nodeid, 11093ff2971SAl Viro le32_to_cpu(rf->rf_lvblen), 11193ff2971SAl Viro le32_to_cpu(rf->rf_lsflags)); 1128b0e7b2cSDavid Teigland return -EPROTO; 113e7fd4179SDavid Teigland } 114e7fd4179SDavid Teigland return 0; 115e7fd4179SDavid Teigland } 116e7fd4179SDavid Teigland 11798f176fbSDavid Teigland static void allow_sync_reply(struct dlm_ls *ls, uint64_t *new_seq) 11898f176fbSDavid Teigland { 11998f176fbSDavid Teigland spin_lock(&ls->ls_rcom_spin); 12098f176fbSDavid Teigland *new_seq = ++ls->ls_rcom_seq; 12198f176fbSDavid Teigland set_bit(LSFL_RCOM_WAIT, &ls->ls_flags); 12298f176fbSDavid Teigland spin_unlock(&ls->ls_rcom_spin); 12398f176fbSDavid Teigland } 12498f176fbSDavid Teigland 12598f176fbSDavid Teigland static void disallow_sync_reply(struct dlm_ls *ls) 12698f176fbSDavid Teigland { 12798f176fbSDavid Teigland spin_lock(&ls->ls_rcom_spin); 12898f176fbSDavid Teigland clear_bit(LSFL_RCOM_WAIT, &ls->ls_flags); 12998f176fbSDavid Teigland clear_bit(LSFL_RCOM_READY, &ls->ls_flags); 13098f176fbSDavid Teigland spin_unlock(&ls->ls_rcom_spin); 13198f176fbSDavid Teigland } 13298f176fbSDavid Teigland 133757a4271SDavid Teigland /* 134757a4271SDavid Teigland * low nodeid gathers one slot value at a time from each node. 135757a4271SDavid Teigland * it sets need_slots=0, and saves rf_our_slot returned from each 136757a4271SDavid Teigland * rcom_config. 137757a4271SDavid Teigland * 138757a4271SDavid Teigland * other nodes gather all slot values at once from the low nodeid. 139757a4271SDavid Teigland * they set need_slots=1, and ignore the rf_our_slot returned from each 140757a4271SDavid Teigland * rcom_config. they use the rf_num_slots returned from the low 141757a4271SDavid Teigland * node's rcom_config. 142757a4271SDavid Teigland */ 143757a4271SDavid Teigland 144757a4271SDavid Teigland int dlm_rcom_status(struct dlm_ls *ls, int nodeid, uint32_t status_flags) 145e7fd4179SDavid Teigland { 146e7fd4179SDavid Teigland struct dlm_rcom *rc; 147e7fd4179SDavid Teigland struct dlm_mhandle *mh; 148e7fd4179SDavid Teigland int error = 0; 149e7fd4179SDavid Teigland 150faa0f267SDavid Teigland ls->ls_recover_nodeid = nodeid; 151e7fd4179SDavid Teigland 152e7fd4179SDavid Teigland if (nodeid == dlm_our_nodeid()) { 1534007685cSAl Viro rc = ls->ls_recover_buf; 154e7fd4179SDavid Teigland rc->rc_result = dlm_recover_status(ls); 155e7fd4179SDavid Teigland goto out; 156e7fd4179SDavid Teigland } 157e7fd4179SDavid Teigland 158757a4271SDavid Teigland error = create_rcom(ls, nodeid, DLM_RCOM_STATUS, 159757a4271SDavid Teigland sizeof(struct rcom_status), &rc, &mh); 160e7fd4179SDavid Teigland if (error) 161e7fd4179SDavid Teigland goto out; 16298f176fbSDavid Teigland 163757a4271SDavid Teigland set_rcom_status(ls, (struct rcom_status *)rc->rc_buf, status_flags); 164757a4271SDavid Teigland 16598f176fbSDavid Teigland allow_sync_reply(ls, &rc->rc_id); 16668c817a1SDavid Teigland memset(ls->ls_recover_buf, 0, dlm_config.ci_buffer_size); 167e7fd4179SDavid Teigland 168e7fd4179SDavid Teigland send_rcom(ls, mh, rc); 169e7fd4179SDavid Teigland 170e7fd4179SDavid Teigland error = dlm_wait_function(ls, &rcom_response); 17198f176fbSDavid Teigland disallow_sync_reply(ls); 172e7fd4179SDavid Teigland if (error) 173e7fd4179SDavid Teigland goto out; 174e7fd4179SDavid Teigland 1754007685cSAl Viro rc = ls->ls_recover_buf; 176e7fd4179SDavid Teigland 177e7fd4179SDavid Teigland if (rc->rc_result == -ESRCH) { 178e7fd4179SDavid Teigland /* we pretend the remote lockspace exists with 0 status */ 179e7fd4179SDavid Teigland log_debug(ls, "remote node %d not ready", nodeid); 180e7fd4179SDavid Teigland rc->rc_result = 0; 181757a4271SDavid Teigland error = 0; 182757a4271SDavid Teigland } else { 183757a4271SDavid Teigland error = check_rcom_config(ls, rc, nodeid); 184757a4271SDavid Teigland } 185757a4271SDavid Teigland 186e7fd4179SDavid Teigland /* the caller looks at rc_result for the remote recovery status */ 187e7fd4179SDavid Teigland out: 188e7fd4179SDavid Teigland return error; 189e7fd4179SDavid Teigland } 190e7fd4179SDavid Teigland 191e7fd4179SDavid Teigland static void receive_rcom_status(struct dlm_ls *ls, struct dlm_rcom *rc_in) 192e7fd4179SDavid Teigland { 193e7fd4179SDavid Teigland struct dlm_rcom *rc; 194e7fd4179SDavid Teigland struct dlm_mhandle *mh; 195757a4271SDavid Teigland struct rcom_status *rs; 196757a4271SDavid Teigland uint32_t status; 197757a4271SDavid Teigland int nodeid = rc_in->rc_header.h_nodeid; 198757a4271SDavid Teigland int len = sizeof(struct rcom_config); 199757a4271SDavid Teigland int num_slots = 0; 200757a4271SDavid Teigland int error; 201e7fd4179SDavid Teigland 202757a4271SDavid Teigland if (!dlm_slots_version(&rc_in->rc_header)) { 203757a4271SDavid Teigland status = dlm_recover_status(ls); 204757a4271SDavid Teigland goto do_create; 205757a4271SDavid Teigland } 206757a4271SDavid Teigland 207757a4271SDavid Teigland rs = (struct rcom_status *)rc_in->rc_buf; 208757a4271SDavid Teigland 209757a4271SDavid Teigland if (!(rs->rs_flags & DLM_RSF_NEED_SLOTS)) { 210757a4271SDavid Teigland status = dlm_recover_status(ls); 211757a4271SDavid Teigland goto do_create; 212757a4271SDavid Teigland } 213757a4271SDavid Teigland 214757a4271SDavid Teigland spin_lock(&ls->ls_recover_lock); 215757a4271SDavid Teigland status = ls->ls_recover_status; 216757a4271SDavid Teigland num_slots = ls->ls_num_slots; 217757a4271SDavid Teigland spin_unlock(&ls->ls_recover_lock); 218757a4271SDavid Teigland len += num_slots * sizeof(struct rcom_slot); 219757a4271SDavid Teigland 220757a4271SDavid Teigland do_create: 221e7fd4179SDavid Teigland error = create_rcom(ls, nodeid, DLM_RCOM_STATUS_REPLY, 222757a4271SDavid Teigland len, &rc, &mh); 223e7fd4179SDavid Teigland if (error) 224e7fd4179SDavid Teigland return; 225757a4271SDavid Teigland 2264a99c3d9SDavid Teigland rc->rc_id = rc_in->rc_id; 22738aa8b0cSDavid Teigland rc->rc_seq_reply = rc_in->rc_seq; 228757a4271SDavid Teigland rc->rc_result = status; 229e7fd4179SDavid Teigland 230757a4271SDavid Teigland set_rcom_config(ls, (struct rcom_config *)rc->rc_buf, num_slots); 231757a4271SDavid Teigland 232757a4271SDavid Teigland if (!num_slots) 233757a4271SDavid Teigland goto do_send; 234757a4271SDavid Teigland 235757a4271SDavid Teigland spin_lock(&ls->ls_recover_lock); 236757a4271SDavid Teigland if (ls->ls_num_slots != num_slots) { 237757a4271SDavid Teigland spin_unlock(&ls->ls_recover_lock); 238757a4271SDavid Teigland log_debug(ls, "receive_rcom_status num_slots %d to %d", 239757a4271SDavid Teigland num_slots, ls->ls_num_slots); 240757a4271SDavid Teigland rc->rc_result = 0; 241757a4271SDavid Teigland set_rcom_config(ls, (struct rcom_config *)rc->rc_buf, 0); 242757a4271SDavid Teigland goto do_send; 243757a4271SDavid Teigland } 244757a4271SDavid Teigland 245757a4271SDavid Teigland dlm_slots_copy_out(ls, rc); 246757a4271SDavid Teigland spin_unlock(&ls->ls_recover_lock); 247757a4271SDavid Teigland 248757a4271SDavid Teigland do_send: 249e7fd4179SDavid Teigland send_rcom(ls, mh, rc); 250e7fd4179SDavid Teigland } 251e7fd4179SDavid Teigland 2524a99c3d9SDavid Teigland static void receive_sync_reply(struct dlm_ls *ls, struct dlm_rcom *rc_in) 253e7fd4179SDavid Teigland { 25498f176fbSDavid Teigland spin_lock(&ls->ls_rcom_spin); 25598f176fbSDavid Teigland if (!test_bit(LSFL_RCOM_WAIT, &ls->ls_flags) || 25698f176fbSDavid Teigland rc_in->rc_id != ls->ls_rcom_seq) { 25798f176fbSDavid Teigland log_debug(ls, "reject reply %d from %d seq %llx expect %llx", 25898f176fbSDavid Teigland rc_in->rc_type, rc_in->rc_header.h_nodeid, 25957adf7eeSRyusuke Konishi (unsigned long long)rc_in->rc_id, 26057adf7eeSRyusuke Konishi (unsigned long long)ls->ls_rcom_seq); 26198f176fbSDavid Teigland goto out; 2624a99c3d9SDavid Teigland } 263e7fd4179SDavid Teigland memcpy(ls->ls_recover_buf, rc_in, rc_in->rc_header.h_length); 264e7fd4179SDavid Teigland set_bit(LSFL_RCOM_READY, &ls->ls_flags); 26598f176fbSDavid Teigland clear_bit(LSFL_RCOM_WAIT, &ls->ls_flags); 266e7fd4179SDavid Teigland wake_up(&ls->ls_wait_general); 26798f176fbSDavid Teigland out: 26898f176fbSDavid Teigland spin_unlock(&ls->ls_rcom_spin); 269e7fd4179SDavid Teigland } 270e7fd4179SDavid Teigland 271e7fd4179SDavid Teigland int dlm_rcom_names(struct dlm_ls *ls, int nodeid, char *last_name, int last_len) 272e7fd4179SDavid Teigland { 273e7fd4179SDavid Teigland struct dlm_rcom *rc; 274e7fd4179SDavid Teigland struct dlm_mhandle *mh; 2754007685cSAl Viro int error = 0; 276e7fd4179SDavid Teigland 277faa0f267SDavid Teigland ls->ls_recover_nodeid = nodeid; 278e7fd4179SDavid Teigland 279e7fd4179SDavid Teigland error = create_rcom(ls, nodeid, DLM_RCOM_NAMES, last_len, &rc, &mh); 280e7fd4179SDavid Teigland if (error) 281e7fd4179SDavid Teigland goto out; 282e7fd4179SDavid Teigland memcpy(rc->rc_buf, last_name, last_len); 28398f176fbSDavid Teigland 28498f176fbSDavid Teigland allow_sync_reply(ls, &rc->rc_id); 28568c817a1SDavid Teigland memset(ls->ls_recover_buf, 0, dlm_config.ci_buffer_size); 286e7fd4179SDavid Teigland 287e7fd4179SDavid Teigland send_rcom(ls, mh, rc); 288e7fd4179SDavid Teigland 289e7fd4179SDavid Teigland error = dlm_wait_function(ls, &rcom_response); 29098f176fbSDavid Teigland disallow_sync_reply(ls); 291e7fd4179SDavid Teigland out: 292e7fd4179SDavid Teigland return error; 293e7fd4179SDavid Teigland } 294e7fd4179SDavid Teigland 295e7fd4179SDavid Teigland static void receive_rcom_names(struct dlm_ls *ls, struct dlm_rcom *rc_in) 296e7fd4179SDavid Teigland { 297e7fd4179SDavid Teigland struct dlm_rcom *rc; 298e7fd4179SDavid Teigland struct dlm_mhandle *mh; 29938aa8b0cSDavid Teigland int error, inlen, outlen, nodeid; 300e7fd4179SDavid Teigland 301e7fd4179SDavid Teigland nodeid = rc_in->rc_header.h_nodeid; 302e7fd4179SDavid Teigland inlen = rc_in->rc_header.h_length - sizeof(struct dlm_rcom); 30368c817a1SDavid Teigland outlen = dlm_config.ci_buffer_size - sizeof(struct dlm_rcom); 304e7fd4179SDavid Teigland 305e7fd4179SDavid Teigland error = create_rcom(ls, nodeid, DLM_RCOM_NAMES_REPLY, outlen, &rc, &mh); 306e7fd4179SDavid Teigland if (error) 307e7fd4179SDavid Teigland return; 3084a99c3d9SDavid Teigland rc->rc_id = rc_in->rc_id; 30938aa8b0cSDavid Teigland rc->rc_seq_reply = rc_in->rc_seq; 310e7fd4179SDavid Teigland 311e7fd4179SDavid Teigland dlm_copy_master_names(ls, rc_in->rc_buf, inlen, rc->rc_buf, outlen, 312e7fd4179SDavid Teigland nodeid); 313e7fd4179SDavid Teigland send_rcom(ls, mh, rc); 314e7fd4179SDavid Teigland } 315e7fd4179SDavid Teigland 316e7fd4179SDavid Teigland int dlm_send_rcom_lookup(struct dlm_rsb *r, int dir_nodeid) 317e7fd4179SDavid Teigland { 318e7fd4179SDavid Teigland struct dlm_rcom *rc; 319e7fd4179SDavid Teigland struct dlm_mhandle *mh; 320e7fd4179SDavid Teigland struct dlm_ls *ls = r->res_ls; 321e7fd4179SDavid Teigland int error; 322e7fd4179SDavid Teigland 323e7fd4179SDavid Teigland error = create_rcom(ls, dir_nodeid, DLM_RCOM_LOOKUP, r->res_length, 324e7fd4179SDavid Teigland &rc, &mh); 325e7fd4179SDavid Teigland if (error) 326e7fd4179SDavid Teigland goto out; 327e7fd4179SDavid Teigland memcpy(rc->rc_buf, r->res_name, r->res_length); 328e7fd4179SDavid Teigland rc->rc_id = (unsigned long) r; 329e7fd4179SDavid Teigland 330e7fd4179SDavid Teigland send_rcom(ls, mh, rc); 331e7fd4179SDavid Teigland out: 332e7fd4179SDavid Teigland return error; 333e7fd4179SDavid Teigland } 334e7fd4179SDavid Teigland 335*c04fecb4SDavid Teigland int dlm_send_rcom_lookup_dump(struct dlm_rsb *r, int to_nodeid) 336*c04fecb4SDavid Teigland { 337*c04fecb4SDavid Teigland struct dlm_rcom *rc; 338*c04fecb4SDavid Teigland struct dlm_mhandle *mh; 339*c04fecb4SDavid Teigland struct dlm_ls *ls = r->res_ls; 340*c04fecb4SDavid Teigland int error; 341*c04fecb4SDavid Teigland 342*c04fecb4SDavid Teigland error = create_rcom(ls, to_nodeid, DLM_RCOM_LOOKUP, r->res_length, 343*c04fecb4SDavid Teigland &rc, &mh); 344*c04fecb4SDavid Teigland if (error) 345*c04fecb4SDavid Teigland goto out; 346*c04fecb4SDavid Teigland memcpy(rc->rc_buf, r->res_name, r->res_length); 347*c04fecb4SDavid Teigland rc->rc_id = 0xFFFFFFFF; 348*c04fecb4SDavid Teigland 349*c04fecb4SDavid Teigland send_rcom(ls, mh, rc); 350*c04fecb4SDavid Teigland out: 351*c04fecb4SDavid Teigland return error; 352*c04fecb4SDavid Teigland } 353*c04fecb4SDavid Teigland 354e7fd4179SDavid Teigland static void receive_rcom_lookup(struct dlm_ls *ls, struct dlm_rcom *rc_in) 355e7fd4179SDavid Teigland { 356e7fd4179SDavid Teigland struct dlm_rcom *rc; 357e7fd4179SDavid Teigland struct dlm_mhandle *mh; 358e7fd4179SDavid Teigland int error, ret_nodeid, nodeid = rc_in->rc_header.h_nodeid; 359e7fd4179SDavid Teigland int len = rc_in->rc_header.h_length - sizeof(struct dlm_rcom); 360e7fd4179SDavid Teigland 361e7fd4179SDavid Teigland error = create_rcom(ls, nodeid, DLM_RCOM_LOOKUP_REPLY, 0, &rc, &mh); 362e7fd4179SDavid Teigland if (error) 363e7fd4179SDavid Teigland return; 364e7fd4179SDavid Teigland 365*c04fecb4SDavid Teigland if (rc_in->rc_id == 0xFFFFFFFF) { 366*c04fecb4SDavid Teigland log_error(ls, "receive_rcom_lookup dump from %d", nodeid); 367*c04fecb4SDavid Teigland dlm_dump_rsb_name(ls, rc_in->rc_buf, len); 368*c04fecb4SDavid Teigland return; 369*c04fecb4SDavid Teigland } 370*c04fecb4SDavid Teigland 371*c04fecb4SDavid Teigland error = dlm_master_lookup(ls, nodeid, rc_in->rc_buf, len, 372*c04fecb4SDavid Teigland DLM_LU_RECOVER_MASTER, &ret_nodeid, NULL); 373e7fd4179SDavid Teigland if (error) 374e7fd4179SDavid Teigland ret_nodeid = error; 375e7fd4179SDavid Teigland rc->rc_result = ret_nodeid; 376e7fd4179SDavid Teigland rc->rc_id = rc_in->rc_id; 37738aa8b0cSDavid Teigland rc->rc_seq_reply = rc_in->rc_seq; 378e7fd4179SDavid Teigland 379e7fd4179SDavid Teigland send_rcom(ls, mh, rc); 380e7fd4179SDavid Teigland } 381e7fd4179SDavid Teigland 382e7fd4179SDavid Teigland static void receive_rcom_lookup_reply(struct dlm_ls *ls, struct dlm_rcom *rc_in) 383e7fd4179SDavid Teigland { 384e7fd4179SDavid Teigland dlm_recover_master_reply(ls, rc_in); 385e7fd4179SDavid Teigland } 386e7fd4179SDavid Teigland 387e7fd4179SDavid Teigland static void pack_rcom_lock(struct dlm_rsb *r, struct dlm_lkb *lkb, 388e7fd4179SDavid Teigland struct rcom_lock *rl) 389e7fd4179SDavid Teigland { 390e7fd4179SDavid Teigland memset(rl, 0, sizeof(*rl)); 391e7fd4179SDavid Teigland 392163a1859SAl Viro rl->rl_ownpid = cpu_to_le32(lkb->lkb_ownpid); 393163a1859SAl Viro rl->rl_lkid = cpu_to_le32(lkb->lkb_id); 394163a1859SAl Viro rl->rl_exflags = cpu_to_le32(lkb->lkb_exflags); 395163a1859SAl Viro rl->rl_flags = cpu_to_le32(lkb->lkb_flags); 396163a1859SAl Viro rl->rl_lvbseq = cpu_to_le32(lkb->lkb_lvbseq); 397e7fd4179SDavid Teigland rl->rl_rqmode = lkb->lkb_rqmode; 398e7fd4179SDavid Teigland rl->rl_grmode = lkb->lkb_grmode; 399e7fd4179SDavid Teigland rl->rl_status = lkb->lkb_status; 400163a1859SAl Viro rl->rl_wait_type = cpu_to_le16(lkb->lkb_wait_type); 401e7fd4179SDavid Teigland 402e5dae548SDavid Teigland if (lkb->lkb_bastfn) 4038304d6f2SDavid Teigland rl->rl_asts |= DLM_CB_BAST; 404e5dae548SDavid Teigland if (lkb->lkb_astfn) 4058304d6f2SDavid Teigland rl->rl_asts |= DLM_CB_CAST; 406e7fd4179SDavid Teigland 407163a1859SAl Viro rl->rl_namelen = cpu_to_le16(r->res_length); 408e7fd4179SDavid Teigland memcpy(rl->rl_name, r->res_name, r->res_length); 409e7fd4179SDavid Teigland 410e7fd4179SDavid Teigland /* FIXME: might we have an lvb without DLM_LKF_VALBLK set ? 411e7fd4179SDavid Teigland If so, receive_rcom_lock_args() won't take this copy. */ 412e7fd4179SDavid Teigland 413e7fd4179SDavid Teigland if (lkb->lkb_lvbptr) 414e7fd4179SDavid Teigland memcpy(rl->rl_lvb, lkb->lkb_lvbptr, r->res_ls->ls_lvblen); 415e7fd4179SDavid Teigland } 416e7fd4179SDavid Teigland 417e7fd4179SDavid Teigland int dlm_send_rcom_lock(struct dlm_rsb *r, struct dlm_lkb *lkb) 418e7fd4179SDavid Teigland { 419e7fd4179SDavid Teigland struct dlm_ls *ls = r->res_ls; 420e7fd4179SDavid Teigland struct dlm_rcom *rc; 421e7fd4179SDavid Teigland struct dlm_mhandle *mh; 422e7fd4179SDavid Teigland struct rcom_lock *rl; 423e7fd4179SDavid Teigland int error, len = sizeof(struct rcom_lock); 424e7fd4179SDavid Teigland 425e7fd4179SDavid Teigland if (lkb->lkb_lvbptr) 426e7fd4179SDavid Teigland len += ls->ls_lvblen; 427e7fd4179SDavid Teigland 428e7fd4179SDavid Teigland error = create_rcom(ls, r->res_nodeid, DLM_RCOM_LOCK, len, &rc, &mh); 429e7fd4179SDavid Teigland if (error) 430e7fd4179SDavid Teigland goto out; 431e7fd4179SDavid Teigland 432e7fd4179SDavid Teigland rl = (struct rcom_lock *) rc->rc_buf; 433e7fd4179SDavid Teigland pack_rcom_lock(r, lkb, rl); 434e7fd4179SDavid Teigland rc->rc_id = (unsigned long) r; 435e7fd4179SDavid Teigland 436e7fd4179SDavid Teigland send_rcom(ls, mh, rc); 437e7fd4179SDavid Teigland out: 438e7fd4179SDavid Teigland return error; 439e7fd4179SDavid Teigland } 440e7fd4179SDavid Teigland 441ae773d0bSAl Viro /* needs at least dlm_rcom + rcom_lock */ 442e7fd4179SDavid Teigland static void receive_rcom_lock(struct dlm_ls *ls, struct dlm_rcom *rc_in) 443e7fd4179SDavid Teigland { 444e7fd4179SDavid Teigland struct dlm_rcom *rc; 445e7fd4179SDavid Teigland struct dlm_mhandle *mh; 446e7fd4179SDavid Teigland int error, nodeid = rc_in->rc_header.h_nodeid; 447e7fd4179SDavid Teigland 448e7fd4179SDavid Teigland dlm_recover_master_copy(ls, rc_in); 449e7fd4179SDavid Teigland 450e7fd4179SDavid Teigland error = create_rcom(ls, nodeid, DLM_RCOM_LOCK_REPLY, 451e7fd4179SDavid Teigland sizeof(struct rcom_lock), &rc, &mh); 452e7fd4179SDavid Teigland if (error) 453e7fd4179SDavid Teigland return; 454e7fd4179SDavid Teigland 455e7fd4179SDavid Teigland /* We send back the same rcom_lock struct we received, but 456e7fd4179SDavid Teigland dlm_recover_master_copy() has filled in rl_remid and rl_result */ 457e7fd4179SDavid Teigland 458e7fd4179SDavid Teigland memcpy(rc->rc_buf, rc_in->rc_buf, sizeof(struct rcom_lock)); 459e7fd4179SDavid Teigland rc->rc_id = rc_in->rc_id; 46038aa8b0cSDavid Teigland rc->rc_seq_reply = rc_in->rc_seq; 461e7fd4179SDavid Teigland 462e7fd4179SDavid Teigland send_rcom(ls, mh, rc); 463e7fd4179SDavid Teigland } 464e7fd4179SDavid Teigland 465c36258b5SDavid Teigland /* If the lockspace doesn't exist then still send a status message 466c36258b5SDavid Teigland back; it's possible that it just doesn't have its global_id yet. */ 467c36258b5SDavid Teigland 468c36258b5SDavid Teigland int dlm_send_ls_not_ready(int nodeid, struct dlm_rcom *rc_in) 469e7fd4179SDavid Teigland { 470e7fd4179SDavid Teigland struct dlm_rcom *rc; 4711babdb45SDavid Teigland struct rcom_config *rf; 472e7fd4179SDavid Teigland struct dlm_mhandle *mh; 473e7fd4179SDavid Teigland char *mb; 4741babdb45SDavid Teigland int mb_len = sizeof(struct dlm_rcom) + sizeof(struct rcom_config); 475e7fd4179SDavid Teigland 47641684f95SDavid Teigland mh = dlm_lowcomms_get_buffer(nodeid, mb_len, GFP_NOFS, &mb); 477e7fd4179SDavid Teigland if (!mh) 478e7fd4179SDavid Teigland return -ENOBUFS; 479e7fd4179SDavid Teigland memset(mb, 0, mb_len); 480e7fd4179SDavid Teigland 481e7fd4179SDavid Teigland rc = (struct dlm_rcom *) mb; 482e7fd4179SDavid Teigland 483e7fd4179SDavid Teigland rc->rc_header.h_version = (DLM_HEADER_MAJOR | DLM_HEADER_MINOR); 484e7fd4179SDavid Teigland rc->rc_header.h_lockspace = rc_in->rc_header.h_lockspace; 485e7fd4179SDavid Teigland rc->rc_header.h_nodeid = dlm_our_nodeid(); 486e7fd4179SDavid Teigland rc->rc_header.h_length = mb_len; 487e7fd4179SDavid Teigland rc->rc_header.h_cmd = DLM_RCOM; 488e7fd4179SDavid Teigland 489e7fd4179SDavid Teigland rc->rc_type = DLM_RCOM_STATUS_REPLY; 490f5888750SDavid Teigland rc->rc_id = rc_in->rc_id; 49138aa8b0cSDavid Teigland rc->rc_seq_reply = rc_in->rc_seq; 492e7fd4179SDavid Teigland rc->rc_result = -ESRCH; 493e7fd4179SDavid Teigland 4941babdb45SDavid Teigland rf = (struct rcom_config *) rc->rc_buf; 49593ff2971SAl Viro rf->rf_lvblen = cpu_to_le32(~0U); 4961babdb45SDavid Teigland 497e7fd4179SDavid Teigland dlm_rcom_out(rc); 498e7fd4179SDavid Teigland dlm_lowcomms_commit_buffer(mh); 499e7fd4179SDavid Teigland 500e7fd4179SDavid Teigland return 0; 501e7fd4179SDavid Teigland } 502e7fd4179SDavid Teigland 503*c04fecb4SDavid Teigland /* 504*c04fecb4SDavid Teigland * Ignore messages for stage Y before we set 505*c04fecb4SDavid Teigland * recover_status bit for stage X: 506*c04fecb4SDavid Teigland * 507*c04fecb4SDavid Teigland * recover_status = 0 508*c04fecb4SDavid Teigland * 509*c04fecb4SDavid Teigland * dlm_recover_members() 510*c04fecb4SDavid Teigland * - send nothing 511*c04fecb4SDavid Teigland * - recv nothing 512*c04fecb4SDavid Teigland * - ignore NAMES, NAMES_REPLY 513*c04fecb4SDavid Teigland * - ignore LOOKUP, LOOKUP_REPLY 514*c04fecb4SDavid Teigland * - ignore LOCK, LOCK_REPLY 515*c04fecb4SDavid Teigland * 516*c04fecb4SDavid Teigland * recover_status |= NODES 517*c04fecb4SDavid Teigland * 518*c04fecb4SDavid Teigland * dlm_recover_members_wait() 519*c04fecb4SDavid Teigland * 520*c04fecb4SDavid Teigland * dlm_recover_directory() 521*c04fecb4SDavid Teigland * - send NAMES 522*c04fecb4SDavid Teigland * - recv NAMES_REPLY 523*c04fecb4SDavid Teigland * - ignore LOOKUP, LOOKUP_REPLY 524*c04fecb4SDavid Teigland * - ignore LOCK, LOCK_REPLY 525*c04fecb4SDavid Teigland * 526*c04fecb4SDavid Teigland * recover_status |= DIR 527*c04fecb4SDavid Teigland * 528*c04fecb4SDavid Teigland * dlm_recover_directory_wait() 529*c04fecb4SDavid Teigland * 530*c04fecb4SDavid Teigland * dlm_recover_masters() 531*c04fecb4SDavid Teigland * - send LOOKUP 532*c04fecb4SDavid Teigland * - recv LOOKUP_REPLY 533*c04fecb4SDavid Teigland * 534*c04fecb4SDavid Teigland * dlm_recover_locks() 535*c04fecb4SDavid Teigland * - send LOCKS 536*c04fecb4SDavid Teigland * - recv LOCKS_REPLY 537*c04fecb4SDavid Teigland * 538*c04fecb4SDavid Teigland * recover_status |= LOCKS 539*c04fecb4SDavid Teigland * 540*c04fecb4SDavid Teigland * dlm_recover_locks_wait() 541*c04fecb4SDavid Teigland * 542*c04fecb4SDavid Teigland * recover_status |= DONE 543*c04fecb4SDavid Teigland */ 544*c04fecb4SDavid Teigland 545c36258b5SDavid Teigland /* Called by dlm_recv; corresponds to dlm_receive_message() but special 546e7fd4179SDavid Teigland recovery-only comms are sent through here. */ 547e7fd4179SDavid Teigland 548c36258b5SDavid Teigland void dlm_receive_rcom(struct dlm_ls *ls, struct dlm_rcom *rc, int nodeid) 549e7fd4179SDavid Teigland { 550ae773d0bSAl Viro int lock_size = sizeof(struct dlm_rcom) + sizeof(struct rcom_lock); 551*c04fecb4SDavid Teigland int stop, reply = 0, names = 0, lookup = 0, lock = 0; 5524875647aSDavid Teigland uint32_t status; 553d6e24788SDavid Teigland uint64_t seq; 554ae773d0bSAl Viro 555d6e24788SDavid Teigland switch (rc->rc_type) { 556*c04fecb4SDavid Teigland case DLM_RCOM_STATUS_REPLY: 557*c04fecb4SDavid Teigland reply = 1; 558*c04fecb4SDavid Teigland break; 559*c04fecb4SDavid Teigland case DLM_RCOM_NAMES: 560*c04fecb4SDavid Teigland names = 1; 561*c04fecb4SDavid Teigland break; 562*c04fecb4SDavid Teigland case DLM_RCOM_NAMES_REPLY: 563*c04fecb4SDavid Teigland names = 1; 564*c04fecb4SDavid Teigland reply = 1; 565*c04fecb4SDavid Teigland break; 566*c04fecb4SDavid Teigland case DLM_RCOM_LOOKUP: 567*c04fecb4SDavid Teigland lookup = 1; 568*c04fecb4SDavid Teigland break; 569*c04fecb4SDavid Teigland case DLM_RCOM_LOOKUP_REPLY: 570*c04fecb4SDavid Teigland lookup = 1; 571*c04fecb4SDavid Teigland reply = 1; 572*c04fecb4SDavid Teigland break; 5734875647aSDavid Teigland case DLM_RCOM_LOCK: 5744875647aSDavid Teigland lock = 1; 5754875647aSDavid Teigland break; 5764875647aSDavid Teigland case DLM_RCOM_LOCK_REPLY: 5774875647aSDavid Teigland lock = 1; 5784875647aSDavid Teigland reply = 1; 5794875647aSDavid Teigland break; 580d6e24788SDavid Teigland }; 581d6e24788SDavid Teigland 582d6e24788SDavid Teigland spin_lock(&ls->ls_recover_lock); 5834875647aSDavid Teigland status = ls->ls_recover_status; 584d6e24788SDavid Teigland stop = test_bit(LSFL_RECOVERY_STOP, &ls->ls_flags); 585d6e24788SDavid Teigland seq = ls->ls_recover_seq; 586d6e24788SDavid Teigland spin_unlock(&ls->ls_recover_lock); 587d6e24788SDavid Teigland 588*c04fecb4SDavid Teigland if (stop && (rc->rc_type != DLM_RCOM_STATUS)) 589*c04fecb4SDavid Teigland goto ignore; 590*c04fecb4SDavid Teigland 591*c04fecb4SDavid Teigland if (reply && (rc->rc_seq_reply != seq)) 592*c04fecb4SDavid Teigland goto ignore; 593*c04fecb4SDavid Teigland 594*c04fecb4SDavid Teigland if (!(status & DLM_RS_NODES) && (names || lookup || lock)) 595*c04fecb4SDavid Teigland goto ignore; 596*c04fecb4SDavid Teigland 597*c04fecb4SDavid Teigland if (!(status & DLM_RS_DIR) && (lookup || lock)) 598*c04fecb4SDavid Teigland goto ignore; 599e7fd4179SDavid Teigland 600e7fd4179SDavid Teigland switch (rc->rc_type) { 601e7fd4179SDavid Teigland case DLM_RCOM_STATUS: 602e7fd4179SDavid Teigland receive_rcom_status(ls, rc); 603e7fd4179SDavid Teigland break; 604e7fd4179SDavid Teigland 605e7fd4179SDavid Teigland case DLM_RCOM_NAMES: 606e7fd4179SDavid Teigland receive_rcom_names(ls, rc); 607e7fd4179SDavid Teigland break; 608e7fd4179SDavid Teigland 609e7fd4179SDavid Teigland case DLM_RCOM_LOOKUP: 610e7fd4179SDavid Teigland receive_rcom_lookup(ls, rc); 611e7fd4179SDavid Teigland break; 612e7fd4179SDavid Teigland 613e7fd4179SDavid Teigland case DLM_RCOM_LOCK: 614ae773d0bSAl Viro if (rc->rc_header.h_length < lock_size) 615ae773d0bSAl Viro goto Eshort; 616e7fd4179SDavid Teigland receive_rcom_lock(ls, rc); 617e7fd4179SDavid Teigland break; 618e7fd4179SDavid Teigland 619e7fd4179SDavid Teigland case DLM_RCOM_STATUS_REPLY: 620dbcfc347SDavid Teigland receive_sync_reply(ls, rc); 621e7fd4179SDavid Teigland break; 622e7fd4179SDavid Teigland 623e7fd4179SDavid Teigland case DLM_RCOM_NAMES_REPLY: 624dbcfc347SDavid Teigland receive_sync_reply(ls, rc); 625e7fd4179SDavid Teigland break; 626e7fd4179SDavid Teigland 627e7fd4179SDavid Teigland case DLM_RCOM_LOOKUP_REPLY: 628e7fd4179SDavid Teigland receive_rcom_lookup_reply(ls, rc); 629e7fd4179SDavid Teigland break; 630e7fd4179SDavid Teigland 631e7fd4179SDavid Teigland case DLM_RCOM_LOCK_REPLY: 632ae773d0bSAl Viro if (rc->rc_header.h_length < lock_size) 633ae773d0bSAl Viro goto Eshort; 634dbcfc347SDavid Teigland dlm_recover_process_copy(ls, rc); 635e7fd4179SDavid Teigland break; 636e7fd4179SDavid Teigland 637e7fd4179SDavid Teigland default: 638dbcfc347SDavid Teigland log_error(ls, "receive_rcom bad type %d", rc->rc_type); 639e7fd4179SDavid Teigland } 640*c04fecb4SDavid Teigland return; 641*c04fecb4SDavid Teigland 642*c04fecb4SDavid Teigland ignore: 643*c04fecb4SDavid Teigland log_limit(ls, "dlm_receive_rcom ignore msg %d " 644*c04fecb4SDavid Teigland "from %d %llu %llu recover seq %llu sts %x gen %u", 645*c04fecb4SDavid Teigland rc->rc_type, 646*c04fecb4SDavid Teigland nodeid, 647*c04fecb4SDavid Teigland (unsigned long long)rc->rc_seq, 648*c04fecb4SDavid Teigland (unsigned long long)rc->rc_seq_reply, 649*c04fecb4SDavid Teigland (unsigned long long)seq, 650*c04fecb4SDavid Teigland status, ls->ls_generation); 651c36258b5SDavid Teigland return; 652ae773d0bSAl Viro Eshort: 653*c04fecb4SDavid Teigland log_error(ls, "recovery message %d from %d is too short", 654ae773d0bSAl Viro rc->rc_type, nodeid); 655e7fd4179SDavid Teigland } 656e7fd4179SDavid Teigland 657