12522fe45SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only 2e7fd4179SDavid Teigland /****************************************************************************** 3e7fd4179SDavid Teigland ******************************************************************************* 4e7fd4179SDavid Teigland ** 5e7fd4179SDavid Teigland ** Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved. 6dbcfc347SDavid Teigland ** Copyright (C) 2005-2008 Red Hat, Inc. All rights reserved. 7e7fd4179SDavid Teigland ** 8e7fd4179SDavid Teigland ** 9e7fd4179SDavid Teigland ******************************************************************************* 10e7fd4179SDavid Teigland ******************************************************************************/ 11e7fd4179SDavid Teigland 12e7fd4179SDavid Teigland #include "dlm_internal.h" 13e7fd4179SDavid Teigland #include "lockspace.h" 14e7fd4179SDavid Teigland #include "member.h" 15e7fd4179SDavid Teigland #include "lowcomms.h" 16e7fd4179SDavid Teigland #include "midcomms.h" 17e7fd4179SDavid Teigland #include "rcom.h" 18e7fd4179SDavid Teigland #include "recover.h" 19e7fd4179SDavid Teigland #include "dir.h" 20e7fd4179SDavid Teigland #include "config.h" 21e7fd4179SDavid Teigland #include "memory.h" 22e7fd4179SDavid Teigland #include "lock.h" 23e7fd4179SDavid Teigland #include "util.h" 24e7fd4179SDavid Teigland 25e7fd4179SDavid Teigland static int rcom_response(struct dlm_ls *ls) 26e7fd4179SDavid Teigland { 27e7fd4179SDavid Teigland return test_bit(LSFL_RCOM_READY, &ls->ls_flags); 28e7fd4179SDavid Teigland } 29e7fd4179SDavid Teigland 30a070a91cSAlexander Aring static void _create_rcom(struct dlm_ls *ls, int to_nodeid, int type, int len, 31c4f4e135SAlexander Aring struct dlm_rcom **rc_ret, char *mb, int mb_len, 32c4f4e135SAlexander Aring uint64_t seq) 33e7fd4179SDavid Teigland { 34e7fd4179SDavid Teigland struct dlm_rcom *rc; 35e7fd4179SDavid Teigland 36e7fd4179SDavid Teigland rc = (struct dlm_rcom *) mb; 37e7fd4179SDavid Teigland 383428785aSAlexander Aring rc->rc_header.h_version = cpu_to_le32(DLM_HEADER_MAJOR | DLM_HEADER_MINOR); 393428785aSAlexander Aring rc->rc_header.u.h_lockspace = cpu_to_le32(ls->ls_global_id); 403428785aSAlexander Aring rc->rc_header.h_nodeid = cpu_to_le32(dlm_our_nodeid()); 413428785aSAlexander Aring rc->rc_header.h_length = cpu_to_le16(mb_len); 42e7fd4179SDavid Teigland rc->rc_header.h_cmd = DLM_RCOM; 43e7fd4179SDavid Teigland 442f9dbedaSAlexander Aring rc->rc_type = cpu_to_le32(type); 45c4f4e135SAlexander Aring rc->rc_seq = cpu_to_le64(seq); 4638aa8b0cSDavid Teigland 47e7fd4179SDavid Teigland *rc_ret = rc; 48a070a91cSAlexander Aring } 49a070a91cSAlexander Aring 50a070a91cSAlexander Aring static int create_rcom(struct dlm_ls *ls, int to_nodeid, int type, int len, 51c4f4e135SAlexander Aring struct dlm_rcom **rc_ret, struct dlm_mhandle **mh_ret, 52c4f4e135SAlexander Aring uint64_t seq) 53a070a91cSAlexander Aring { 54a070a91cSAlexander Aring int mb_len = sizeof(struct dlm_rcom) + len; 55a070a91cSAlexander Aring struct dlm_mhandle *mh; 56a070a91cSAlexander Aring char *mb; 57a070a91cSAlexander Aring 58a070a91cSAlexander Aring mh = dlm_midcomms_get_mhandle(to_nodeid, mb_len, GFP_NOFS, &mb); 59a070a91cSAlexander Aring if (!mh) { 60a070a91cSAlexander Aring log_print("%s to %d type %d len %d ENOBUFS", 61a070a91cSAlexander Aring __func__, to_nodeid, type, len); 62a070a91cSAlexander Aring return -ENOBUFS; 63a070a91cSAlexander Aring } 64a070a91cSAlexander Aring 65c4f4e135SAlexander Aring _create_rcom(ls, to_nodeid, type, len, rc_ret, mb, mb_len, seq); 66a070a91cSAlexander Aring *mh_ret = mh; 67e7fd4179SDavid Teigland return 0; 68e7fd4179SDavid Teigland } 69e7fd4179SDavid Teigland 70a070a91cSAlexander Aring static int create_rcom_stateless(struct dlm_ls *ls, int to_nodeid, int type, 71a070a91cSAlexander Aring int len, struct dlm_rcom **rc_ret, 72c4f4e135SAlexander Aring struct dlm_msg **msg_ret, uint64_t seq) 73a070a91cSAlexander Aring { 74a070a91cSAlexander Aring int mb_len = sizeof(struct dlm_rcom) + len; 758f2dc78dSAlexander Aring struct dlm_msg *msg; 76a070a91cSAlexander Aring char *mb; 77a070a91cSAlexander Aring 788f2dc78dSAlexander Aring msg = dlm_lowcomms_new_msg(to_nodeid, mb_len, GFP_NOFS, &mb, 798f2dc78dSAlexander Aring NULL, NULL); 808f2dc78dSAlexander Aring if (!msg) { 81a070a91cSAlexander Aring log_print("create_rcom to %d type %d len %d ENOBUFS", 82a070a91cSAlexander Aring to_nodeid, type, len); 83a070a91cSAlexander Aring return -ENOBUFS; 84a070a91cSAlexander Aring } 85a070a91cSAlexander Aring 86c4f4e135SAlexander Aring _create_rcom(ls, to_nodeid, type, len, rc_ret, mb, mb_len, seq); 878f2dc78dSAlexander Aring *msg_ret = msg; 88a070a91cSAlexander Aring return 0; 89a070a91cSAlexander Aring } 90a070a91cSAlexander Aring 9188aa023aSAlexander Aring static void send_rcom(struct dlm_mhandle *mh, struct dlm_rcom *rc) 92a070a91cSAlexander Aring { 93e01c4b7bSAlexander Aring dlm_midcomms_commit_mhandle(mh, NULL, 0); 94a070a91cSAlexander Aring } 95a070a91cSAlexander Aring 9688aa023aSAlexander Aring static void send_rcom_stateless(struct dlm_msg *msg, struct dlm_rcom *rc) 97a070a91cSAlexander Aring { 988f2dc78dSAlexander Aring dlm_lowcomms_commit_msg(msg); 998f2dc78dSAlexander Aring dlm_lowcomms_put_msg(msg); 100e7fd4179SDavid Teigland } 101e7fd4179SDavid Teigland 102757a4271SDavid Teigland static void set_rcom_status(struct dlm_ls *ls, struct rcom_status *rs, 103757a4271SDavid Teigland uint32_t flags) 104757a4271SDavid Teigland { 105757a4271SDavid Teigland rs->rs_flags = cpu_to_le32(flags); 106757a4271SDavid Teigland } 107757a4271SDavid Teigland 108e7fd4179SDavid Teigland /* When replying to a status request, a node also sends back its 109e7fd4179SDavid Teigland configuration values. The requesting node then checks that the remote 110e7fd4179SDavid Teigland node is configured the same way as itself. */ 111e7fd4179SDavid Teigland 112757a4271SDavid Teigland static void set_rcom_config(struct dlm_ls *ls, struct rcom_config *rf, 113757a4271SDavid Teigland uint32_t num_slots) 114e7fd4179SDavid Teigland { 11593ff2971SAl Viro rf->rf_lvblen = cpu_to_le32(ls->ls_lvblen); 11693ff2971SAl Viro rf->rf_lsflags = cpu_to_le32(ls->ls_exflags); 117757a4271SDavid Teigland 118757a4271SDavid Teigland rf->rf_our_slot = cpu_to_le16(ls->ls_slot); 119757a4271SDavid Teigland rf->rf_num_slots = cpu_to_le16(num_slots); 120757a4271SDavid Teigland rf->rf_generation = cpu_to_le32(ls->ls_generation); 121e7fd4179SDavid Teigland } 122e7fd4179SDavid Teigland 123757a4271SDavid Teigland static int check_rcom_config(struct dlm_ls *ls, struct dlm_rcom *rc, int nodeid) 124e7fd4179SDavid Teigland { 1259e971b71SDavid Teigland struct rcom_config *rf = (struct rcom_config *) rc->rc_buf; 1269e971b71SDavid Teigland 1273428785aSAlexander Aring if ((le32_to_cpu(rc->rc_header.h_version) & 0xFFFF0000) != DLM_HEADER_MAJOR) { 1289e971b71SDavid Teigland log_error(ls, "version mismatch: %x nodeid %d: %x", 1299e971b71SDavid Teigland DLM_HEADER_MAJOR | DLM_HEADER_MINOR, nodeid, 1303428785aSAlexander Aring le32_to_cpu(rc->rc_header.h_version)); 1318b0e7b2cSDavid Teigland return -EPROTO; 1329e971b71SDavid Teigland } 1339e971b71SDavid Teigland 13493ff2971SAl Viro if (le32_to_cpu(rf->rf_lvblen) != ls->ls_lvblen || 13593ff2971SAl Viro le32_to_cpu(rf->rf_lsflags) != ls->ls_exflags) { 136e7fd4179SDavid Teigland log_error(ls, "config mismatch: %d,%x nodeid %d: %d,%x", 13793ff2971SAl Viro ls->ls_lvblen, ls->ls_exflags, nodeid, 13893ff2971SAl Viro le32_to_cpu(rf->rf_lvblen), 13993ff2971SAl Viro le32_to_cpu(rf->rf_lsflags)); 1408b0e7b2cSDavid Teigland return -EPROTO; 141e7fd4179SDavid Teigland } 142e7fd4179SDavid Teigland return 0; 143e7fd4179SDavid Teigland } 144e7fd4179SDavid Teigland 1452f9dbedaSAlexander Aring static void allow_sync_reply(struct dlm_ls *ls, __le64 *new_seq) 14698f176fbSDavid Teigland { 14798f176fbSDavid Teigland spin_lock(&ls->ls_rcom_spin); 1482f9dbedaSAlexander Aring *new_seq = cpu_to_le64(++ls->ls_rcom_seq); 14998f176fbSDavid Teigland set_bit(LSFL_RCOM_WAIT, &ls->ls_flags); 15098f176fbSDavid Teigland spin_unlock(&ls->ls_rcom_spin); 15198f176fbSDavid Teigland } 15298f176fbSDavid Teigland 15398f176fbSDavid Teigland static void disallow_sync_reply(struct dlm_ls *ls) 15498f176fbSDavid Teigland { 15598f176fbSDavid Teigland spin_lock(&ls->ls_rcom_spin); 15698f176fbSDavid Teigland clear_bit(LSFL_RCOM_WAIT, &ls->ls_flags); 15798f176fbSDavid Teigland clear_bit(LSFL_RCOM_READY, &ls->ls_flags); 15898f176fbSDavid Teigland spin_unlock(&ls->ls_rcom_spin); 15998f176fbSDavid Teigland } 16098f176fbSDavid Teigland 161757a4271SDavid Teigland /* 162757a4271SDavid Teigland * low nodeid gathers one slot value at a time from each node. 163757a4271SDavid Teigland * it sets need_slots=0, and saves rf_our_slot returned from each 164757a4271SDavid Teigland * rcom_config. 165757a4271SDavid Teigland * 166757a4271SDavid Teigland * other nodes gather all slot values at once from the low nodeid. 167757a4271SDavid Teigland * they set need_slots=1, and ignore the rf_our_slot returned from each 168757a4271SDavid Teigland * rcom_config. they use the rf_num_slots returned from the low 169757a4271SDavid Teigland * node's rcom_config. 170757a4271SDavid Teigland */ 171757a4271SDavid Teigland 172c4f4e135SAlexander Aring int dlm_rcom_status(struct dlm_ls *ls, int nodeid, uint32_t status_flags, 173c4f4e135SAlexander Aring uint64_t seq) 174e7fd4179SDavid Teigland { 175e7fd4179SDavid Teigland struct dlm_rcom *rc; 1768f2dc78dSAlexander Aring struct dlm_msg *msg; 177e7fd4179SDavid Teigland int error = 0; 178e7fd4179SDavid Teigland 179faa0f267SDavid Teigland ls->ls_recover_nodeid = nodeid; 180e7fd4179SDavid Teigland 181e7fd4179SDavid Teigland if (nodeid == dlm_our_nodeid()) { 1824007685cSAl Viro rc = ls->ls_recover_buf; 1832f9dbedaSAlexander Aring rc->rc_result = cpu_to_le32(dlm_recover_status(ls)); 184e7fd4179SDavid Teigland goto out; 185e7fd4179SDavid Teigland } 186e7fd4179SDavid Teigland 18759661212Stsutomu.owa@toshiba.co.jp retry: 188a070a91cSAlexander Aring error = create_rcom_stateless(ls, nodeid, DLM_RCOM_STATUS, 189c4f4e135SAlexander Aring sizeof(struct rcom_status), &rc, &msg, 190c4f4e135SAlexander Aring seq); 191e7fd4179SDavid Teigland if (error) 192e7fd4179SDavid Teigland goto out; 19398f176fbSDavid Teigland 194757a4271SDavid Teigland set_rcom_status(ls, (struct rcom_status *)rc->rc_buf, status_flags); 195757a4271SDavid Teigland 19698f176fbSDavid Teigland allow_sync_reply(ls, &rc->rc_id); 197d10a0b88SAlexander Aring memset(ls->ls_recover_buf, 0, DLM_MAX_SOCKET_BUFSIZE); 198e7fd4179SDavid Teigland 19988aa023aSAlexander Aring send_rcom_stateless(msg, rc); 200e7fd4179SDavid Teigland 201e7fd4179SDavid Teigland error = dlm_wait_function(ls, &rcom_response); 20298f176fbSDavid Teigland disallow_sync_reply(ls); 20359661212Stsutomu.owa@toshiba.co.jp if (error == -ETIMEDOUT) 20459661212Stsutomu.owa@toshiba.co.jp goto retry; 205e7fd4179SDavid Teigland if (error) 206e7fd4179SDavid Teigland goto out; 207e7fd4179SDavid Teigland 2084007685cSAl Viro rc = ls->ls_recover_buf; 209e7fd4179SDavid Teigland 2102f9dbedaSAlexander Aring if (rc->rc_result == cpu_to_le32(-ESRCH)) { 211e7fd4179SDavid Teigland /* we pretend the remote lockspace exists with 0 status */ 212e7fd4179SDavid Teigland log_debug(ls, "remote node %d not ready", nodeid); 213e7fd4179SDavid Teigland rc->rc_result = 0; 214757a4271SDavid Teigland error = 0; 215757a4271SDavid Teigland } else { 216757a4271SDavid Teigland error = check_rcom_config(ls, rc, nodeid); 217757a4271SDavid Teigland } 218757a4271SDavid Teigland 219e7fd4179SDavid Teigland /* the caller looks at rc_result for the remote recovery status */ 220e7fd4179SDavid Teigland out: 221e7fd4179SDavid Teigland return error; 222e7fd4179SDavid Teigland } 223e7fd4179SDavid Teigland 22411519351SAlexander Aring static void receive_rcom_status(struct dlm_ls *ls, 22511519351SAlexander Aring const struct dlm_rcom *rc_in, 226c4f4e135SAlexander Aring uint64_t seq) 227e7fd4179SDavid Teigland { 228e7fd4179SDavid Teigland struct dlm_rcom *rc; 229757a4271SDavid Teigland struct rcom_status *rs; 230757a4271SDavid Teigland uint32_t status; 2313428785aSAlexander Aring int nodeid = le32_to_cpu(rc_in->rc_header.h_nodeid); 232757a4271SDavid Teigland int len = sizeof(struct rcom_config); 2338f2dc78dSAlexander Aring struct dlm_msg *msg; 234757a4271SDavid Teigland int num_slots = 0; 235757a4271SDavid Teigland int error; 236e7fd4179SDavid Teigland 237757a4271SDavid Teigland if (!dlm_slots_version(&rc_in->rc_header)) { 238757a4271SDavid Teigland status = dlm_recover_status(ls); 239757a4271SDavid Teigland goto do_create; 240757a4271SDavid Teigland } 241757a4271SDavid Teigland 242757a4271SDavid Teigland rs = (struct rcom_status *)rc_in->rc_buf; 243757a4271SDavid Teigland 244c07127b4SNeale Ferguson if (!(le32_to_cpu(rs->rs_flags) & DLM_RSF_NEED_SLOTS)) { 245757a4271SDavid Teigland status = dlm_recover_status(ls); 246757a4271SDavid Teigland goto do_create; 247757a4271SDavid Teigland } 248757a4271SDavid Teigland 249757a4271SDavid Teigland spin_lock(&ls->ls_recover_lock); 250757a4271SDavid Teigland status = ls->ls_recover_status; 251757a4271SDavid Teigland num_slots = ls->ls_num_slots; 252757a4271SDavid Teigland spin_unlock(&ls->ls_recover_lock); 253757a4271SDavid Teigland len += num_slots * sizeof(struct rcom_slot); 254757a4271SDavid Teigland 255757a4271SDavid Teigland do_create: 256a070a91cSAlexander Aring error = create_rcom_stateless(ls, nodeid, DLM_RCOM_STATUS_REPLY, 257c4f4e135SAlexander Aring len, &rc, &msg, seq); 258e7fd4179SDavid Teigland if (error) 259e7fd4179SDavid Teigland return; 260757a4271SDavid Teigland 2614a99c3d9SDavid Teigland rc->rc_id = rc_in->rc_id; 26238aa8b0cSDavid Teigland rc->rc_seq_reply = rc_in->rc_seq; 2632f9dbedaSAlexander Aring rc->rc_result = cpu_to_le32(status); 264e7fd4179SDavid Teigland 265757a4271SDavid Teigland set_rcom_config(ls, (struct rcom_config *)rc->rc_buf, num_slots); 266757a4271SDavid Teigland 267757a4271SDavid Teigland if (!num_slots) 268757a4271SDavid Teigland goto do_send; 269757a4271SDavid Teigland 270757a4271SDavid Teigland spin_lock(&ls->ls_recover_lock); 271757a4271SDavid Teigland if (ls->ls_num_slots != num_slots) { 272757a4271SDavid Teigland spin_unlock(&ls->ls_recover_lock); 273757a4271SDavid Teigland log_debug(ls, "receive_rcom_status num_slots %d to %d", 274757a4271SDavid Teigland num_slots, ls->ls_num_slots); 275757a4271SDavid Teigland rc->rc_result = 0; 276757a4271SDavid Teigland set_rcom_config(ls, (struct rcom_config *)rc->rc_buf, 0); 277757a4271SDavid Teigland goto do_send; 278757a4271SDavid Teigland } 279757a4271SDavid Teigland 280757a4271SDavid Teigland dlm_slots_copy_out(ls, rc); 281757a4271SDavid Teigland spin_unlock(&ls->ls_recover_lock); 282757a4271SDavid Teigland 283757a4271SDavid Teigland do_send: 28488aa023aSAlexander Aring send_rcom_stateless(msg, rc); 285e7fd4179SDavid Teigland } 286e7fd4179SDavid Teigland 28711519351SAlexander Aring static void receive_sync_reply(struct dlm_ls *ls, const struct dlm_rcom *rc_in) 288e7fd4179SDavid Teigland { 28998f176fbSDavid Teigland spin_lock(&ls->ls_rcom_spin); 29098f176fbSDavid Teigland if (!test_bit(LSFL_RCOM_WAIT, &ls->ls_flags) || 2912f9dbedaSAlexander Aring le64_to_cpu(rc_in->rc_id) != ls->ls_rcom_seq) { 29298f176fbSDavid Teigland log_debug(ls, "reject reply %d from %d seq %llx expect %llx", 2932f9dbedaSAlexander Aring le32_to_cpu(rc_in->rc_type), 2943428785aSAlexander Aring le32_to_cpu(rc_in->rc_header.h_nodeid), 2952f9dbedaSAlexander Aring (unsigned long long)le64_to_cpu(rc_in->rc_id), 29657adf7eeSRyusuke Konishi (unsigned long long)ls->ls_rcom_seq); 29798f176fbSDavid Teigland goto out; 2984a99c3d9SDavid Teigland } 2993428785aSAlexander Aring memcpy(ls->ls_recover_buf, rc_in, 3003428785aSAlexander Aring le16_to_cpu(rc_in->rc_header.h_length)); 301e7fd4179SDavid Teigland set_bit(LSFL_RCOM_READY, &ls->ls_flags); 30298f176fbSDavid Teigland clear_bit(LSFL_RCOM_WAIT, &ls->ls_flags); 303e7fd4179SDavid Teigland wake_up(&ls->ls_wait_general); 30498f176fbSDavid Teigland out: 30598f176fbSDavid Teigland spin_unlock(&ls->ls_rcom_spin); 306e7fd4179SDavid Teigland } 307e7fd4179SDavid Teigland 308c4f4e135SAlexander Aring int dlm_rcom_names(struct dlm_ls *ls, int nodeid, char *last_name, 309c4f4e135SAlexander Aring int last_len, uint64_t seq) 310e7fd4179SDavid Teigland { 311*a3d85fcfSAlexander Aring struct dlm_mhandle *mh; 312e7fd4179SDavid Teigland struct dlm_rcom *rc; 3134007685cSAl Viro int error = 0; 314e7fd4179SDavid Teigland 315faa0f267SDavid Teigland ls->ls_recover_nodeid = nodeid; 316e7fd4179SDavid Teigland 31759661212Stsutomu.owa@toshiba.co.jp retry: 318*a3d85fcfSAlexander Aring error = create_rcom(ls, nodeid, DLM_RCOM_NAMES, last_len, 319*a3d85fcfSAlexander Aring &rc, &mh, seq); 320e7fd4179SDavid Teigland if (error) 321e7fd4179SDavid Teigland goto out; 322e7fd4179SDavid Teigland memcpy(rc->rc_buf, last_name, last_len); 32398f176fbSDavid Teigland 32498f176fbSDavid Teigland allow_sync_reply(ls, &rc->rc_id); 325d10a0b88SAlexander Aring memset(ls->ls_recover_buf, 0, DLM_MAX_SOCKET_BUFSIZE); 326e7fd4179SDavid Teigland 327*a3d85fcfSAlexander Aring send_rcom(mh, rc); 328e7fd4179SDavid Teigland 329e7fd4179SDavid Teigland error = dlm_wait_function(ls, &rcom_response); 33098f176fbSDavid Teigland disallow_sync_reply(ls); 33159661212Stsutomu.owa@toshiba.co.jp if (error == -ETIMEDOUT) 33259661212Stsutomu.owa@toshiba.co.jp goto retry; 333e7fd4179SDavid Teigland out: 334e7fd4179SDavid Teigland return error; 335e7fd4179SDavid Teigland } 336e7fd4179SDavid Teigland 33711519351SAlexander Aring static void receive_rcom_names(struct dlm_ls *ls, const struct dlm_rcom *rc_in, 338c4f4e135SAlexander Aring uint64_t seq) 339e7fd4179SDavid Teigland { 340*a3d85fcfSAlexander Aring struct dlm_mhandle *mh; 341e7fd4179SDavid Teigland struct dlm_rcom *rc; 34238aa8b0cSDavid Teigland int error, inlen, outlen, nodeid; 343e7fd4179SDavid Teigland 3443428785aSAlexander Aring nodeid = le32_to_cpu(rc_in->rc_header.h_nodeid); 3453428785aSAlexander Aring inlen = le16_to_cpu(rc_in->rc_header.h_length) - 3463428785aSAlexander Aring sizeof(struct dlm_rcom); 347d10a0b88SAlexander Aring outlen = DLM_MAX_APP_BUFSIZE - sizeof(struct dlm_rcom); 348e7fd4179SDavid Teigland 349*a3d85fcfSAlexander Aring error = create_rcom(ls, nodeid, DLM_RCOM_NAMES_REPLY, outlen, 350*a3d85fcfSAlexander Aring &rc, &mh, seq); 351e7fd4179SDavid Teigland if (error) 352e7fd4179SDavid Teigland return; 3534a99c3d9SDavid Teigland rc->rc_id = rc_in->rc_id; 35438aa8b0cSDavid Teigland rc->rc_seq_reply = rc_in->rc_seq; 355e7fd4179SDavid Teigland 356e7fd4179SDavid Teigland dlm_copy_master_names(ls, rc_in->rc_buf, inlen, rc->rc_buf, outlen, 357e7fd4179SDavid Teigland nodeid); 358*a3d85fcfSAlexander Aring send_rcom(mh, rc); 359e7fd4179SDavid Teigland } 360e7fd4179SDavid Teigland 361c4f4e135SAlexander Aring int dlm_send_rcom_lookup(struct dlm_rsb *r, int dir_nodeid, uint64_t seq) 362e7fd4179SDavid Teigland { 363e7fd4179SDavid Teigland struct dlm_rcom *rc; 364e7fd4179SDavid Teigland struct dlm_mhandle *mh; 365e7fd4179SDavid Teigland struct dlm_ls *ls = r->res_ls; 366e7fd4179SDavid Teigland int error; 367e7fd4179SDavid Teigland 368e7fd4179SDavid Teigland error = create_rcom(ls, dir_nodeid, DLM_RCOM_LOOKUP, r->res_length, 369c4f4e135SAlexander Aring &rc, &mh, seq); 370e7fd4179SDavid Teigland if (error) 371e7fd4179SDavid Teigland goto out; 372e7fd4179SDavid Teigland memcpy(rc->rc_buf, r->res_name, r->res_length); 3732f9dbedaSAlexander Aring rc->rc_id = cpu_to_le64(r->res_id); 374e7fd4179SDavid Teigland 37588aa023aSAlexander Aring send_rcom(mh, rc); 376e7fd4179SDavid Teigland out: 377e7fd4179SDavid Teigland return error; 378e7fd4179SDavid Teigland } 379e7fd4179SDavid Teigland 38011519351SAlexander Aring static void receive_rcom_lookup(struct dlm_ls *ls, 38111519351SAlexander Aring const struct dlm_rcom *rc_in, uint64_t seq) 382e7fd4179SDavid Teigland { 383e7fd4179SDavid Teigland struct dlm_rcom *rc; 384e7fd4179SDavid Teigland struct dlm_mhandle *mh; 3853428785aSAlexander Aring int error, ret_nodeid, nodeid = le32_to_cpu(rc_in->rc_header.h_nodeid); 3863428785aSAlexander Aring int len = le16_to_cpu(rc_in->rc_header.h_length) - 3873428785aSAlexander Aring sizeof(struct dlm_rcom); 388e7fd4179SDavid Teigland 3899250e523SDavid Teigland /* Old code would send this special id to trigger a debug dump. */ 3902f9dbedaSAlexander Aring if (rc_in->rc_id == cpu_to_le64(0xFFFFFFFF)) { 391c04fecb4SDavid Teigland log_error(ls, "receive_rcom_lookup dump from %d", nodeid); 392c04fecb4SDavid Teigland dlm_dump_rsb_name(ls, rc_in->rc_buf, len); 393c04fecb4SDavid Teigland return; 394c04fecb4SDavid Teigland } 395c04fecb4SDavid Teigland 396c4f4e135SAlexander Aring error = create_rcom(ls, nodeid, DLM_RCOM_LOOKUP_REPLY, 0, &rc, &mh, 397c4f4e135SAlexander Aring seq); 398f6089981SColin Ian King if (error) 399f6089981SColin Ian King return; 400f6089981SColin Ian King 401c04fecb4SDavid Teigland error = dlm_master_lookup(ls, nodeid, rc_in->rc_buf, len, 402c04fecb4SDavid Teigland DLM_LU_RECOVER_MASTER, &ret_nodeid, NULL); 403e7fd4179SDavid Teigland if (error) 404e7fd4179SDavid Teigland ret_nodeid = error; 4052f9dbedaSAlexander Aring rc->rc_result = cpu_to_le32(ret_nodeid); 406e7fd4179SDavid Teigland rc->rc_id = rc_in->rc_id; 40738aa8b0cSDavid Teigland rc->rc_seq_reply = rc_in->rc_seq; 408e7fd4179SDavid Teigland 40988aa023aSAlexander Aring send_rcom(mh, rc); 410e7fd4179SDavid Teigland } 411e7fd4179SDavid Teigland 41211519351SAlexander Aring static void receive_rcom_lookup_reply(struct dlm_ls *ls, 41311519351SAlexander Aring const struct dlm_rcom *rc_in) 414e7fd4179SDavid Teigland { 415e7fd4179SDavid Teigland dlm_recover_master_reply(ls, rc_in); 416e7fd4179SDavid Teigland } 417e7fd4179SDavid Teigland 418e7fd4179SDavid Teigland static void pack_rcom_lock(struct dlm_rsb *r, struct dlm_lkb *lkb, 419e7fd4179SDavid Teigland struct rcom_lock *rl) 420e7fd4179SDavid Teigland { 421e7fd4179SDavid Teigland memset(rl, 0, sizeof(*rl)); 422e7fd4179SDavid Teigland 423163a1859SAl Viro rl->rl_ownpid = cpu_to_le32(lkb->lkb_ownpid); 424163a1859SAl Viro rl->rl_lkid = cpu_to_le32(lkb->lkb_id); 425163a1859SAl Viro rl->rl_exflags = cpu_to_le32(lkb->lkb_exflags); 4268a39dcd9SAlexander Aring rl->rl_flags = cpu_to_le32(dlm_dflags_val(lkb)); 427163a1859SAl Viro rl->rl_lvbseq = cpu_to_le32(lkb->lkb_lvbseq); 428e7fd4179SDavid Teigland rl->rl_rqmode = lkb->lkb_rqmode; 429e7fd4179SDavid Teigland rl->rl_grmode = lkb->lkb_grmode; 430e7fd4179SDavid Teigland rl->rl_status = lkb->lkb_status; 431163a1859SAl Viro rl->rl_wait_type = cpu_to_le16(lkb->lkb_wait_type); 432e7fd4179SDavid Teigland 433e5dae548SDavid Teigland if (lkb->lkb_bastfn) 4348304d6f2SDavid Teigland rl->rl_asts |= DLM_CB_BAST; 435e5dae548SDavid Teigland if (lkb->lkb_astfn) 4368304d6f2SDavid Teigland rl->rl_asts |= DLM_CB_CAST; 437e7fd4179SDavid Teigland 438163a1859SAl Viro rl->rl_namelen = cpu_to_le16(r->res_length); 439e7fd4179SDavid Teigland memcpy(rl->rl_name, r->res_name, r->res_length); 440e7fd4179SDavid Teigland 441e7fd4179SDavid Teigland /* FIXME: might we have an lvb without DLM_LKF_VALBLK set ? 442e7fd4179SDavid Teigland If so, receive_rcom_lock_args() won't take this copy. */ 443e7fd4179SDavid Teigland 444e7fd4179SDavid Teigland if (lkb->lkb_lvbptr) 445e7fd4179SDavid Teigland memcpy(rl->rl_lvb, lkb->lkb_lvbptr, r->res_ls->ls_lvblen); 446e7fd4179SDavid Teigland } 447e7fd4179SDavid Teigland 448c4f4e135SAlexander Aring int dlm_send_rcom_lock(struct dlm_rsb *r, struct dlm_lkb *lkb, uint64_t seq) 449e7fd4179SDavid Teigland { 450e7fd4179SDavid Teigland struct dlm_ls *ls = r->res_ls; 451e7fd4179SDavid Teigland struct dlm_rcom *rc; 452e7fd4179SDavid Teigland struct dlm_mhandle *mh; 453e7fd4179SDavid Teigland struct rcom_lock *rl; 454e7fd4179SDavid Teigland int error, len = sizeof(struct rcom_lock); 455e7fd4179SDavid Teigland 456e7fd4179SDavid Teigland if (lkb->lkb_lvbptr) 457e7fd4179SDavid Teigland len += ls->ls_lvblen; 458e7fd4179SDavid Teigland 459c4f4e135SAlexander Aring error = create_rcom(ls, r->res_nodeid, DLM_RCOM_LOCK, len, &rc, &mh, 460c4f4e135SAlexander Aring seq); 461e7fd4179SDavid Teigland if (error) 462e7fd4179SDavid Teigland goto out; 463e7fd4179SDavid Teigland 464e7fd4179SDavid Teigland rl = (struct rcom_lock *) rc->rc_buf; 465e7fd4179SDavid Teigland pack_rcom_lock(r, lkb, rl); 466e425ac99SAlexander Aring rc->rc_id = cpu_to_le64((uintptr_t)r); 467e7fd4179SDavid Teigland 46888aa023aSAlexander Aring send_rcom(mh, rc); 469e7fd4179SDavid Teigland out: 470e7fd4179SDavid Teigland return error; 471e7fd4179SDavid Teigland } 472e7fd4179SDavid Teigland 473ae773d0bSAl Viro /* needs at least dlm_rcom + rcom_lock */ 47411519351SAlexander Aring static void receive_rcom_lock(struct dlm_ls *ls, const struct dlm_rcom *rc_in, 475c4f4e135SAlexander Aring uint64_t seq) 476e7fd4179SDavid Teigland { 477b9d2f6adSAlexander Aring __le32 rl_remid, rl_result; 478b9d2f6adSAlexander Aring struct rcom_lock *rl; 479e7fd4179SDavid Teigland struct dlm_rcom *rc; 480e7fd4179SDavid Teigland struct dlm_mhandle *mh; 4813428785aSAlexander Aring int error, nodeid = le32_to_cpu(rc_in->rc_header.h_nodeid); 482e7fd4179SDavid Teigland 483b9d2f6adSAlexander Aring dlm_recover_master_copy(ls, rc_in, &rl_remid, &rl_result); 484e7fd4179SDavid Teigland 485e7fd4179SDavid Teigland error = create_rcom(ls, nodeid, DLM_RCOM_LOCK_REPLY, 486c4f4e135SAlexander Aring sizeof(struct rcom_lock), &rc, &mh, seq); 487e7fd4179SDavid Teigland if (error) 488e7fd4179SDavid Teigland return; 489e7fd4179SDavid Teigland 490e7fd4179SDavid Teigland memcpy(rc->rc_buf, rc_in->rc_buf, sizeof(struct rcom_lock)); 491b9d2f6adSAlexander Aring rl = (struct rcom_lock *)rc->rc_buf; 492b9d2f6adSAlexander Aring /* set rl_remid and rl_result from dlm_recover_master_copy() */ 493b9d2f6adSAlexander Aring rl->rl_remid = rl_remid; 494b9d2f6adSAlexander Aring rl->rl_result = rl_result; 495b9d2f6adSAlexander Aring 496e7fd4179SDavid Teigland rc->rc_id = rc_in->rc_id; 49738aa8b0cSDavid Teigland rc->rc_seq_reply = rc_in->rc_seq; 498e7fd4179SDavid Teigland 49988aa023aSAlexander Aring send_rcom(mh, rc); 500e7fd4179SDavid Teigland } 501e7fd4179SDavid Teigland 502c36258b5SDavid Teigland /* If the lockspace doesn't exist then still send a status message 503c36258b5SDavid Teigland back; it's possible that it just doesn't have its global_id yet. */ 504c36258b5SDavid Teigland 50511519351SAlexander Aring int dlm_send_ls_not_ready(int nodeid, const struct dlm_rcom *rc_in) 506e7fd4179SDavid Teigland { 507e7fd4179SDavid Teigland struct dlm_rcom *rc; 5081babdb45SDavid Teigland struct rcom_config *rf; 509e7fd4179SDavid Teigland struct dlm_mhandle *mh; 510e7fd4179SDavid Teigland char *mb; 5111babdb45SDavid Teigland int mb_len = sizeof(struct dlm_rcom) + sizeof(struct rcom_config); 512e7fd4179SDavid Teigland 513a070a91cSAlexander Aring mh = dlm_midcomms_get_mhandle(nodeid, mb_len, GFP_NOFS, &mb); 514e7fd4179SDavid Teigland if (!mh) 515e7fd4179SDavid Teigland return -ENOBUFS; 516e7fd4179SDavid Teigland 517e7fd4179SDavid Teigland rc = (struct dlm_rcom *) mb; 518e7fd4179SDavid Teigland 5193428785aSAlexander Aring rc->rc_header.h_version = cpu_to_le32(DLM_HEADER_MAJOR | DLM_HEADER_MINOR); 5208e2e4086SAlexander Aring rc->rc_header.u.h_lockspace = rc_in->rc_header.u.h_lockspace; 5213428785aSAlexander Aring rc->rc_header.h_nodeid = cpu_to_le32(dlm_our_nodeid()); 5223428785aSAlexander Aring rc->rc_header.h_length = cpu_to_le16(mb_len); 523e7fd4179SDavid Teigland rc->rc_header.h_cmd = DLM_RCOM; 524e7fd4179SDavid Teigland 5252f9dbedaSAlexander Aring rc->rc_type = cpu_to_le32(DLM_RCOM_STATUS_REPLY); 526f5888750SDavid Teigland rc->rc_id = rc_in->rc_id; 52738aa8b0cSDavid Teigland rc->rc_seq_reply = rc_in->rc_seq; 5282f9dbedaSAlexander Aring rc->rc_result = cpu_to_le32(-ESRCH); 529e7fd4179SDavid Teigland 5301babdb45SDavid Teigland rf = (struct rcom_config *) rc->rc_buf; 53193ff2971SAl Viro rf->rf_lvblen = cpu_to_le32(~0U); 5321babdb45SDavid Teigland 533e01c4b7bSAlexander Aring dlm_midcomms_commit_mhandle(mh, NULL, 0); 534e7fd4179SDavid Teigland 535e7fd4179SDavid Teigland return 0; 536e7fd4179SDavid Teigland } 537e7fd4179SDavid Teigland 538c04fecb4SDavid Teigland /* 539c04fecb4SDavid Teigland * Ignore messages for stage Y before we set 540c04fecb4SDavid Teigland * recover_status bit for stage X: 541c04fecb4SDavid Teigland * 542c04fecb4SDavid Teigland * recover_status = 0 543c04fecb4SDavid Teigland * 544c04fecb4SDavid Teigland * dlm_recover_members() 545c04fecb4SDavid Teigland * - send nothing 546c04fecb4SDavid Teigland * - recv nothing 547c04fecb4SDavid Teigland * - ignore NAMES, NAMES_REPLY 548c04fecb4SDavid Teigland * - ignore LOOKUP, LOOKUP_REPLY 549c04fecb4SDavid Teigland * - ignore LOCK, LOCK_REPLY 550c04fecb4SDavid Teigland * 551c04fecb4SDavid Teigland * recover_status |= NODES 552c04fecb4SDavid Teigland * 553c04fecb4SDavid Teigland * dlm_recover_members_wait() 554c04fecb4SDavid Teigland * 555c04fecb4SDavid Teigland * dlm_recover_directory() 556c04fecb4SDavid Teigland * - send NAMES 557c04fecb4SDavid Teigland * - recv NAMES_REPLY 558c04fecb4SDavid Teigland * - ignore LOOKUP, LOOKUP_REPLY 559c04fecb4SDavid Teigland * - ignore LOCK, LOCK_REPLY 560c04fecb4SDavid Teigland * 561c04fecb4SDavid Teigland * recover_status |= DIR 562c04fecb4SDavid Teigland * 563c04fecb4SDavid Teigland * dlm_recover_directory_wait() 564c04fecb4SDavid Teigland * 565c04fecb4SDavid Teigland * dlm_recover_masters() 566c04fecb4SDavid Teigland * - send LOOKUP 567c04fecb4SDavid Teigland * - recv LOOKUP_REPLY 568c04fecb4SDavid Teigland * 569c04fecb4SDavid Teigland * dlm_recover_locks() 570c04fecb4SDavid Teigland * - send LOCKS 571c04fecb4SDavid Teigland * - recv LOCKS_REPLY 572c04fecb4SDavid Teigland * 573c04fecb4SDavid Teigland * recover_status |= LOCKS 574c04fecb4SDavid Teigland * 575c04fecb4SDavid Teigland * dlm_recover_locks_wait() 576c04fecb4SDavid Teigland * 577c04fecb4SDavid Teigland * recover_status |= DONE 578c04fecb4SDavid Teigland */ 579c04fecb4SDavid Teigland 580c36258b5SDavid Teigland /* Called by dlm_recv; corresponds to dlm_receive_message() but special 581e7fd4179SDavid Teigland recovery-only comms are sent through here. */ 582e7fd4179SDavid Teigland 58311519351SAlexander Aring void dlm_receive_rcom(struct dlm_ls *ls, const struct dlm_rcom *rc, int nodeid) 584e7fd4179SDavid Teigland { 585ae773d0bSAl Viro int lock_size = sizeof(struct dlm_rcom) + sizeof(struct rcom_lock); 586c04fecb4SDavid Teigland int stop, reply = 0, names = 0, lookup = 0, lock = 0; 5874875647aSDavid Teigland uint32_t status; 588d6e24788SDavid Teigland uint64_t seq; 589ae773d0bSAl Viro 590d6e24788SDavid Teigland switch (rc->rc_type) { 5912f9dbedaSAlexander Aring case cpu_to_le32(DLM_RCOM_STATUS_REPLY): 592c04fecb4SDavid Teigland reply = 1; 593c04fecb4SDavid Teigland break; 5942f9dbedaSAlexander Aring case cpu_to_le32(DLM_RCOM_NAMES): 595c04fecb4SDavid Teigland names = 1; 596c04fecb4SDavid Teigland break; 5972f9dbedaSAlexander Aring case cpu_to_le32(DLM_RCOM_NAMES_REPLY): 598c04fecb4SDavid Teigland names = 1; 599c04fecb4SDavid Teigland reply = 1; 600c04fecb4SDavid Teigland break; 6012f9dbedaSAlexander Aring case cpu_to_le32(DLM_RCOM_LOOKUP): 602c04fecb4SDavid Teigland lookup = 1; 603c04fecb4SDavid Teigland break; 6042f9dbedaSAlexander Aring case cpu_to_le32(DLM_RCOM_LOOKUP_REPLY): 605c04fecb4SDavid Teigland lookup = 1; 606c04fecb4SDavid Teigland reply = 1; 607c04fecb4SDavid Teigland break; 6082f9dbedaSAlexander Aring case cpu_to_le32(DLM_RCOM_LOCK): 6094875647aSDavid Teigland lock = 1; 6104875647aSDavid Teigland break; 6112f9dbedaSAlexander Aring case cpu_to_le32(DLM_RCOM_LOCK_REPLY): 6124875647aSDavid Teigland lock = 1; 6134875647aSDavid Teigland reply = 1; 6144875647aSDavid Teigland break; 61590db4f8bSWu Bo } 616d6e24788SDavid Teigland 617d6e24788SDavid Teigland spin_lock(&ls->ls_recover_lock); 6184875647aSDavid Teigland status = ls->ls_recover_status; 6193e973671SAlexander Aring stop = dlm_recovery_stopped(ls); 620d6e24788SDavid Teigland seq = ls->ls_recover_seq; 621d6e24788SDavid Teigland spin_unlock(&ls->ls_recover_lock); 622d6e24788SDavid Teigland 6232f9dbedaSAlexander Aring if (stop && (rc->rc_type != cpu_to_le32(DLM_RCOM_STATUS))) 624c04fecb4SDavid Teigland goto ignore; 625c04fecb4SDavid Teigland 6262f9dbedaSAlexander Aring if (reply && (le64_to_cpu(rc->rc_seq_reply) != seq)) 627c04fecb4SDavid Teigland goto ignore; 628c04fecb4SDavid Teigland 629c04fecb4SDavid Teigland if (!(status & DLM_RS_NODES) && (names || lookup || lock)) 630c04fecb4SDavid Teigland goto ignore; 631c04fecb4SDavid Teigland 632c04fecb4SDavid Teigland if (!(status & DLM_RS_DIR) && (lookup || lock)) 633c04fecb4SDavid Teigland goto ignore; 634e7fd4179SDavid Teigland 635e7fd4179SDavid Teigland switch (rc->rc_type) { 6362f9dbedaSAlexander Aring case cpu_to_le32(DLM_RCOM_STATUS): 637c4f4e135SAlexander Aring receive_rcom_status(ls, rc, seq); 638e7fd4179SDavid Teigland break; 639e7fd4179SDavid Teigland 6402f9dbedaSAlexander Aring case cpu_to_le32(DLM_RCOM_NAMES): 641c4f4e135SAlexander Aring receive_rcom_names(ls, rc, seq); 642e7fd4179SDavid Teigland break; 643e7fd4179SDavid Teigland 6442f9dbedaSAlexander Aring case cpu_to_le32(DLM_RCOM_LOOKUP): 645c4f4e135SAlexander Aring receive_rcom_lookup(ls, rc, seq); 646e7fd4179SDavid Teigland break; 647e7fd4179SDavid Teigland 6482f9dbedaSAlexander Aring case cpu_to_le32(DLM_RCOM_LOCK): 6493428785aSAlexander Aring if (le16_to_cpu(rc->rc_header.h_length) < lock_size) 650ae773d0bSAl Viro goto Eshort; 651c4f4e135SAlexander Aring receive_rcom_lock(ls, rc, seq); 652e7fd4179SDavid Teigland break; 653e7fd4179SDavid Teigland 6542f9dbedaSAlexander Aring case cpu_to_le32(DLM_RCOM_STATUS_REPLY): 655dbcfc347SDavid Teigland receive_sync_reply(ls, rc); 656e7fd4179SDavid Teigland break; 657e7fd4179SDavid Teigland 6582f9dbedaSAlexander Aring case cpu_to_le32(DLM_RCOM_NAMES_REPLY): 659dbcfc347SDavid Teigland receive_sync_reply(ls, rc); 660e7fd4179SDavid Teigland break; 661e7fd4179SDavid Teigland 6622f9dbedaSAlexander Aring case cpu_to_le32(DLM_RCOM_LOOKUP_REPLY): 663e7fd4179SDavid Teigland receive_rcom_lookup_reply(ls, rc); 664e7fd4179SDavid Teigland break; 665e7fd4179SDavid Teigland 6662f9dbedaSAlexander Aring case cpu_to_le32(DLM_RCOM_LOCK_REPLY): 6673428785aSAlexander Aring if (le16_to_cpu(rc->rc_header.h_length) < lock_size) 668ae773d0bSAl Viro goto Eshort; 669c4f4e135SAlexander Aring dlm_recover_process_copy(ls, rc, seq); 670e7fd4179SDavid Teigland break; 671e7fd4179SDavid Teigland 672e7fd4179SDavid Teigland default: 6732f9dbedaSAlexander Aring log_error(ls, "receive_rcom bad type %d", 6742f9dbedaSAlexander Aring le32_to_cpu(rc->rc_type)); 675e7fd4179SDavid Teigland } 676c04fecb4SDavid Teigland return; 677c04fecb4SDavid Teigland 678c04fecb4SDavid Teigland ignore: 679c04fecb4SDavid Teigland log_limit(ls, "dlm_receive_rcom ignore msg %d " 680c04fecb4SDavid Teigland "from %d %llu %llu recover seq %llu sts %x gen %u", 6812f9dbedaSAlexander Aring le32_to_cpu(rc->rc_type), 682c04fecb4SDavid Teigland nodeid, 6832f9dbedaSAlexander Aring (unsigned long long)le64_to_cpu(rc->rc_seq), 6842f9dbedaSAlexander Aring (unsigned long long)le64_to_cpu(rc->rc_seq_reply), 685c04fecb4SDavid Teigland (unsigned long long)seq, 686c04fecb4SDavid Teigland status, ls->ls_generation); 687c36258b5SDavid Teigland return; 688ae773d0bSAl Viro Eshort: 689c04fecb4SDavid Teigland log_error(ls, "recovery message %d from %d is too short", 6902f9dbedaSAlexander Aring le32_to_cpu(rc->rc_type), nodeid); 691e7fd4179SDavid Teigland } 692e7fd4179SDavid Teigland 693