1*e7fd4179SDavid Teigland /****************************************************************************** 2*e7fd4179SDavid Teigland ******************************************************************************* 3*e7fd4179SDavid Teigland ** 4*e7fd4179SDavid Teigland ** Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved. 5*e7fd4179SDavid Teigland ** Copyright (C) 2005 Red Hat, Inc. All rights reserved. 6*e7fd4179SDavid Teigland ** 7*e7fd4179SDavid Teigland ** This copyrighted material is made available to anyone wishing to use, 8*e7fd4179SDavid Teigland ** modify, copy, or redistribute it subject to the terms and conditions 9*e7fd4179SDavid Teigland ** of the GNU General Public License v.2. 10*e7fd4179SDavid Teigland ** 11*e7fd4179SDavid Teigland ******************************************************************************* 12*e7fd4179SDavid Teigland ******************************************************************************/ 13*e7fd4179SDavid Teigland 14*e7fd4179SDavid Teigland #include "dlm_internal.h" 15*e7fd4179SDavid Teigland #include "lockspace.h" 16*e7fd4179SDavid Teigland #include "member.h" 17*e7fd4179SDavid Teigland #include "lowcomms.h" 18*e7fd4179SDavid Teigland #include "midcomms.h" 19*e7fd4179SDavid Teigland #include "rcom.h" 20*e7fd4179SDavid Teigland #include "recover.h" 21*e7fd4179SDavid Teigland #include "dir.h" 22*e7fd4179SDavid Teigland #include "config.h" 23*e7fd4179SDavid Teigland #include "memory.h" 24*e7fd4179SDavid Teigland #include "lock.h" 25*e7fd4179SDavid Teigland #include "util.h" 26*e7fd4179SDavid Teigland 27*e7fd4179SDavid Teigland 28*e7fd4179SDavid Teigland static int rcom_response(struct dlm_ls *ls) 29*e7fd4179SDavid Teigland { 30*e7fd4179SDavid Teigland return test_bit(LSFL_RCOM_READY, &ls->ls_flags); 31*e7fd4179SDavid Teigland } 32*e7fd4179SDavid Teigland 33*e7fd4179SDavid Teigland static int create_rcom(struct dlm_ls *ls, int to_nodeid, int type, int len, 34*e7fd4179SDavid Teigland struct dlm_rcom **rc_ret, struct dlm_mhandle **mh_ret) 35*e7fd4179SDavid Teigland { 36*e7fd4179SDavid Teigland struct dlm_rcom *rc; 37*e7fd4179SDavid Teigland struct dlm_mhandle *mh; 38*e7fd4179SDavid Teigland char *mb; 39*e7fd4179SDavid Teigland int mb_len = sizeof(struct dlm_rcom) + len; 40*e7fd4179SDavid Teigland 41*e7fd4179SDavid Teigland mh = dlm_lowcomms_get_buffer(to_nodeid, mb_len, GFP_KERNEL, &mb); 42*e7fd4179SDavid Teigland if (!mh) { 43*e7fd4179SDavid Teigland log_print("create_rcom to %d type %d len %d ENOBUFS", 44*e7fd4179SDavid Teigland to_nodeid, type, len); 45*e7fd4179SDavid Teigland return -ENOBUFS; 46*e7fd4179SDavid Teigland } 47*e7fd4179SDavid Teigland memset(mb, 0, mb_len); 48*e7fd4179SDavid Teigland 49*e7fd4179SDavid Teigland rc = (struct dlm_rcom *) mb; 50*e7fd4179SDavid Teigland 51*e7fd4179SDavid Teigland rc->rc_header.h_version = (DLM_HEADER_MAJOR | DLM_HEADER_MINOR); 52*e7fd4179SDavid Teigland rc->rc_header.h_lockspace = ls->ls_global_id; 53*e7fd4179SDavid Teigland rc->rc_header.h_nodeid = dlm_our_nodeid(); 54*e7fd4179SDavid Teigland rc->rc_header.h_length = mb_len; 55*e7fd4179SDavid Teigland rc->rc_header.h_cmd = DLM_RCOM; 56*e7fd4179SDavid Teigland 57*e7fd4179SDavid Teigland rc->rc_type = type; 58*e7fd4179SDavid Teigland 59*e7fd4179SDavid Teigland *mh_ret = mh; 60*e7fd4179SDavid Teigland *rc_ret = rc; 61*e7fd4179SDavid Teigland return 0; 62*e7fd4179SDavid Teigland } 63*e7fd4179SDavid Teigland 64*e7fd4179SDavid Teigland static void send_rcom(struct dlm_ls *ls, struct dlm_mhandle *mh, 65*e7fd4179SDavid Teigland struct dlm_rcom *rc) 66*e7fd4179SDavid Teigland { 67*e7fd4179SDavid Teigland dlm_rcom_out(rc); 68*e7fd4179SDavid Teigland dlm_lowcomms_commit_buffer(mh); 69*e7fd4179SDavid Teigland } 70*e7fd4179SDavid Teigland 71*e7fd4179SDavid Teigland /* When replying to a status request, a node also sends back its 72*e7fd4179SDavid Teigland configuration values. The requesting node then checks that the remote 73*e7fd4179SDavid Teigland node is configured the same way as itself. */ 74*e7fd4179SDavid Teigland 75*e7fd4179SDavid Teigland static void make_config(struct dlm_ls *ls, struct rcom_config *rf) 76*e7fd4179SDavid Teigland { 77*e7fd4179SDavid Teigland rf->rf_lvblen = ls->ls_lvblen; 78*e7fd4179SDavid Teigland rf->rf_lsflags = ls->ls_exflags; 79*e7fd4179SDavid Teigland } 80*e7fd4179SDavid Teigland 81*e7fd4179SDavid Teigland static int check_config(struct dlm_ls *ls, struct rcom_config *rf, int nodeid) 82*e7fd4179SDavid Teigland { 83*e7fd4179SDavid Teigland if (rf->rf_lvblen != ls->ls_lvblen || 84*e7fd4179SDavid Teigland rf->rf_lsflags != ls->ls_exflags) { 85*e7fd4179SDavid Teigland log_error(ls, "config mismatch: %d,%x nodeid %d: %d,%x", 86*e7fd4179SDavid Teigland ls->ls_lvblen, ls->ls_exflags, 87*e7fd4179SDavid Teigland nodeid, rf->rf_lvblen, rf->rf_lsflags); 88*e7fd4179SDavid Teigland return -EINVAL; 89*e7fd4179SDavid Teigland } 90*e7fd4179SDavid Teigland return 0; 91*e7fd4179SDavid Teigland } 92*e7fd4179SDavid Teigland 93*e7fd4179SDavid Teigland int dlm_rcom_status(struct dlm_ls *ls, int nodeid) 94*e7fd4179SDavid Teigland { 95*e7fd4179SDavid Teigland struct dlm_rcom *rc; 96*e7fd4179SDavid Teigland struct dlm_mhandle *mh; 97*e7fd4179SDavid Teigland int error = 0; 98*e7fd4179SDavid Teigland 99*e7fd4179SDavid Teigland memset(ls->ls_recover_buf, 0, dlm_config.buffer_size); 100*e7fd4179SDavid Teigland 101*e7fd4179SDavid Teigland if (nodeid == dlm_our_nodeid()) { 102*e7fd4179SDavid Teigland rc = (struct dlm_rcom *) ls->ls_recover_buf; 103*e7fd4179SDavid Teigland rc->rc_result = dlm_recover_status(ls); 104*e7fd4179SDavid Teigland goto out; 105*e7fd4179SDavid Teigland } 106*e7fd4179SDavid Teigland 107*e7fd4179SDavid Teigland error = create_rcom(ls, nodeid, DLM_RCOM_STATUS, 0, &rc, &mh); 108*e7fd4179SDavid Teigland if (error) 109*e7fd4179SDavid Teigland goto out; 110*e7fd4179SDavid Teigland 111*e7fd4179SDavid Teigland send_rcom(ls, mh, rc); 112*e7fd4179SDavid Teigland 113*e7fd4179SDavid Teigland error = dlm_wait_function(ls, &rcom_response); 114*e7fd4179SDavid Teigland clear_bit(LSFL_RCOM_READY, &ls->ls_flags); 115*e7fd4179SDavid Teigland if (error) 116*e7fd4179SDavid Teigland goto out; 117*e7fd4179SDavid Teigland 118*e7fd4179SDavid Teigland rc = (struct dlm_rcom *) ls->ls_recover_buf; 119*e7fd4179SDavid Teigland 120*e7fd4179SDavid Teigland if (rc->rc_result == -ESRCH) { 121*e7fd4179SDavid Teigland /* we pretend the remote lockspace exists with 0 status */ 122*e7fd4179SDavid Teigland log_debug(ls, "remote node %d not ready", nodeid); 123*e7fd4179SDavid Teigland rc->rc_result = 0; 124*e7fd4179SDavid Teigland } else 125*e7fd4179SDavid Teigland error = check_config(ls, (struct rcom_config *) rc->rc_buf, 126*e7fd4179SDavid Teigland nodeid); 127*e7fd4179SDavid Teigland /* the caller looks at rc_result for the remote recovery status */ 128*e7fd4179SDavid Teigland out: 129*e7fd4179SDavid Teigland return error; 130*e7fd4179SDavid Teigland } 131*e7fd4179SDavid Teigland 132*e7fd4179SDavid Teigland static void receive_rcom_status(struct dlm_ls *ls, struct dlm_rcom *rc_in) 133*e7fd4179SDavid Teigland { 134*e7fd4179SDavid Teigland struct dlm_rcom *rc; 135*e7fd4179SDavid Teigland struct dlm_mhandle *mh; 136*e7fd4179SDavid Teigland int error, nodeid = rc_in->rc_header.h_nodeid; 137*e7fd4179SDavid Teigland 138*e7fd4179SDavid Teigland error = create_rcom(ls, nodeid, DLM_RCOM_STATUS_REPLY, 139*e7fd4179SDavid Teigland sizeof(struct rcom_config), &rc, &mh); 140*e7fd4179SDavid Teigland if (error) 141*e7fd4179SDavid Teigland return; 142*e7fd4179SDavid Teigland rc->rc_result = dlm_recover_status(ls); 143*e7fd4179SDavid Teigland make_config(ls, (struct rcom_config *) rc->rc_buf); 144*e7fd4179SDavid Teigland 145*e7fd4179SDavid Teigland send_rcom(ls, mh, rc); 146*e7fd4179SDavid Teigland } 147*e7fd4179SDavid Teigland 148*e7fd4179SDavid Teigland static void receive_rcom_status_reply(struct dlm_ls *ls, struct dlm_rcom *rc_in) 149*e7fd4179SDavid Teigland { 150*e7fd4179SDavid Teigland memcpy(ls->ls_recover_buf, rc_in, rc_in->rc_header.h_length); 151*e7fd4179SDavid Teigland set_bit(LSFL_RCOM_READY, &ls->ls_flags); 152*e7fd4179SDavid Teigland wake_up(&ls->ls_wait_general); 153*e7fd4179SDavid Teigland } 154*e7fd4179SDavid Teigland 155*e7fd4179SDavid Teigland int dlm_rcom_names(struct dlm_ls *ls, int nodeid, char *last_name, int last_len) 156*e7fd4179SDavid Teigland { 157*e7fd4179SDavid Teigland struct dlm_rcom *rc; 158*e7fd4179SDavid Teigland struct dlm_mhandle *mh; 159*e7fd4179SDavid Teigland int error = 0, len = sizeof(struct dlm_rcom); 160*e7fd4179SDavid Teigland 161*e7fd4179SDavid Teigland memset(ls->ls_recover_buf, 0, dlm_config.buffer_size); 162*e7fd4179SDavid Teigland 163*e7fd4179SDavid Teigland if (nodeid == dlm_our_nodeid()) { 164*e7fd4179SDavid Teigland dlm_copy_master_names(ls, last_name, last_len, 165*e7fd4179SDavid Teigland ls->ls_recover_buf + len, 166*e7fd4179SDavid Teigland dlm_config.buffer_size - len, nodeid); 167*e7fd4179SDavid Teigland goto out; 168*e7fd4179SDavid Teigland } 169*e7fd4179SDavid Teigland 170*e7fd4179SDavid Teigland error = create_rcom(ls, nodeid, DLM_RCOM_NAMES, last_len, &rc, &mh); 171*e7fd4179SDavid Teigland if (error) 172*e7fd4179SDavid Teigland goto out; 173*e7fd4179SDavid Teigland memcpy(rc->rc_buf, last_name, last_len); 174*e7fd4179SDavid Teigland 175*e7fd4179SDavid Teigland send_rcom(ls, mh, rc); 176*e7fd4179SDavid Teigland 177*e7fd4179SDavid Teigland error = dlm_wait_function(ls, &rcom_response); 178*e7fd4179SDavid Teigland clear_bit(LSFL_RCOM_READY, &ls->ls_flags); 179*e7fd4179SDavid Teigland out: 180*e7fd4179SDavid Teigland return error; 181*e7fd4179SDavid Teigland } 182*e7fd4179SDavid Teigland 183*e7fd4179SDavid Teigland static void receive_rcom_names(struct dlm_ls *ls, struct dlm_rcom *rc_in) 184*e7fd4179SDavid Teigland { 185*e7fd4179SDavid Teigland struct dlm_rcom *rc; 186*e7fd4179SDavid Teigland struct dlm_mhandle *mh; 187*e7fd4179SDavid Teigland int error, inlen, outlen; 188*e7fd4179SDavid Teigland int nodeid = rc_in->rc_header.h_nodeid; 189*e7fd4179SDavid Teigland uint32_t status = dlm_recover_status(ls); 190*e7fd4179SDavid Teigland 191*e7fd4179SDavid Teigland /* 192*e7fd4179SDavid Teigland * We can't run dlm_dir_rebuild_send (which uses ls_nodes) while 193*e7fd4179SDavid Teigland * dlm_recoverd is running ls_nodes_reconfig (which changes ls_nodes). 194*e7fd4179SDavid Teigland * It could only happen in rare cases where we get a late NAMES 195*e7fd4179SDavid Teigland * message from a previous instance of recovery. 196*e7fd4179SDavid Teigland */ 197*e7fd4179SDavid Teigland 198*e7fd4179SDavid Teigland if (!(status & DLM_RS_NODES)) { 199*e7fd4179SDavid Teigland log_debug(ls, "ignoring RCOM_NAMES from %u", nodeid); 200*e7fd4179SDavid Teigland return; 201*e7fd4179SDavid Teigland } 202*e7fd4179SDavid Teigland 203*e7fd4179SDavid Teigland nodeid = rc_in->rc_header.h_nodeid; 204*e7fd4179SDavid Teigland inlen = rc_in->rc_header.h_length - sizeof(struct dlm_rcom); 205*e7fd4179SDavid Teigland outlen = dlm_config.buffer_size - sizeof(struct dlm_rcom); 206*e7fd4179SDavid Teigland 207*e7fd4179SDavid Teigland error = create_rcom(ls, nodeid, DLM_RCOM_NAMES_REPLY, outlen, &rc, &mh); 208*e7fd4179SDavid Teigland if (error) 209*e7fd4179SDavid Teigland return; 210*e7fd4179SDavid Teigland 211*e7fd4179SDavid Teigland dlm_copy_master_names(ls, rc_in->rc_buf, inlen, rc->rc_buf, outlen, 212*e7fd4179SDavid Teigland nodeid); 213*e7fd4179SDavid Teigland send_rcom(ls, mh, rc); 214*e7fd4179SDavid Teigland } 215*e7fd4179SDavid Teigland 216*e7fd4179SDavid Teigland static void receive_rcom_names_reply(struct dlm_ls *ls, struct dlm_rcom *rc_in) 217*e7fd4179SDavid Teigland { 218*e7fd4179SDavid Teigland memcpy(ls->ls_recover_buf, rc_in, rc_in->rc_header.h_length); 219*e7fd4179SDavid Teigland set_bit(LSFL_RCOM_READY, &ls->ls_flags); 220*e7fd4179SDavid Teigland wake_up(&ls->ls_wait_general); 221*e7fd4179SDavid Teigland } 222*e7fd4179SDavid Teigland 223*e7fd4179SDavid Teigland int dlm_send_rcom_lookup(struct dlm_rsb *r, int dir_nodeid) 224*e7fd4179SDavid Teigland { 225*e7fd4179SDavid Teigland struct dlm_rcom *rc; 226*e7fd4179SDavid Teigland struct dlm_mhandle *mh; 227*e7fd4179SDavid Teigland struct dlm_ls *ls = r->res_ls; 228*e7fd4179SDavid Teigland int error; 229*e7fd4179SDavid Teigland 230*e7fd4179SDavid Teigland error = create_rcom(ls, dir_nodeid, DLM_RCOM_LOOKUP, r->res_length, 231*e7fd4179SDavid Teigland &rc, &mh); 232*e7fd4179SDavid Teigland if (error) 233*e7fd4179SDavid Teigland goto out; 234*e7fd4179SDavid Teigland memcpy(rc->rc_buf, r->res_name, r->res_length); 235*e7fd4179SDavid Teigland rc->rc_id = (unsigned long) r; 236*e7fd4179SDavid Teigland 237*e7fd4179SDavid Teigland send_rcom(ls, mh, rc); 238*e7fd4179SDavid Teigland out: 239*e7fd4179SDavid Teigland return error; 240*e7fd4179SDavid Teigland } 241*e7fd4179SDavid Teigland 242*e7fd4179SDavid Teigland static void receive_rcom_lookup(struct dlm_ls *ls, struct dlm_rcom *rc_in) 243*e7fd4179SDavid Teigland { 244*e7fd4179SDavid Teigland struct dlm_rcom *rc; 245*e7fd4179SDavid Teigland struct dlm_mhandle *mh; 246*e7fd4179SDavid Teigland int error, ret_nodeid, nodeid = rc_in->rc_header.h_nodeid; 247*e7fd4179SDavid Teigland int len = rc_in->rc_header.h_length - sizeof(struct dlm_rcom); 248*e7fd4179SDavid Teigland 249*e7fd4179SDavid Teigland error = create_rcom(ls, nodeid, DLM_RCOM_LOOKUP_REPLY, 0, &rc, &mh); 250*e7fd4179SDavid Teigland if (error) 251*e7fd4179SDavid Teigland return; 252*e7fd4179SDavid Teigland 253*e7fd4179SDavid Teigland error = dlm_dir_lookup(ls, nodeid, rc_in->rc_buf, len, &ret_nodeid); 254*e7fd4179SDavid Teigland if (error) 255*e7fd4179SDavid Teigland ret_nodeid = error; 256*e7fd4179SDavid Teigland rc->rc_result = ret_nodeid; 257*e7fd4179SDavid Teigland rc->rc_id = rc_in->rc_id; 258*e7fd4179SDavid Teigland 259*e7fd4179SDavid Teigland send_rcom(ls, mh, rc); 260*e7fd4179SDavid Teigland } 261*e7fd4179SDavid Teigland 262*e7fd4179SDavid Teigland static void receive_rcom_lookup_reply(struct dlm_ls *ls, struct dlm_rcom *rc_in) 263*e7fd4179SDavid Teigland { 264*e7fd4179SDavid Teigland dlm_recover_master_reply(ls, rc_in); 265*e7fd4179SDavid Teigland } 266*e7fd4179SDavid Teigland 267*e7fd4179SDavid Teigland static void pack_rcom_lock(struct dlm_rsb *r, struct dlm_lkb *lkb, 268*e7fd4179SDavid Teigland struct rcom_lock *rl) 269*e7fd4179SDavid Teigland { 270*e7fd4179SDavid Teigland memset(rl, 0, sizeof(*rl)); 271*e7fd4179SDavid Teigland 272*e7fd4179SDavid Teigland rl->rl_ownpid = lkb->lkb_ownpid; 273*e7fd4179SDavid Teigland rl->rl_lkid = lkb->lkb_id; 274*e7fd4179SDavid Teigland rl->rl_exflags = lkb->lkb_exflags; 275*e7fd4179SDavid Teigland rl->rl_flags = lkb->lkb_flags; 276*e7fd4179SDavid Teigland rl->rl_lvbseq = lkb->lkb_lvbseq; 277*e7fd4179SDavid Teigland rl->rl_rqmode = lkb->lkb_rqmode; 278*e7fd4179SDavid Teigland rl->rl_grmode = lkb->lkb_grmode; 279*e7fd4179SDavid Teigland rl->rl_status = lkb->lkb_status; 280*e7fd4179SDavid Teigland rl->rl_wait_type = lkb->lkb_wait_type; 281*e7fd4179SDavid Teigland 282*e7fd4179SDavid Teigland if (lkb->lkb_bastaddr) 283*e7fd4179SDavid Teigland rl->rl_asts |= AST_BAST; 284*e7fd4179SDavid Teigland if (lkb->lkb_astaddr) 285*e7fd4179SDavid Teigland rl->rl_asts |= AST_COMP; 286*e7fd4179SDavid Teigland 287*e7fd4179SDavid Teigland if (lkb->lkb_range) 288*e7fd4179SDavid Teigland memcpy(rl->rl_range, lkb->lkb_range, 4*sizeof(uint64_t)); 289*e7fd4179SDavid Teigland 290*e7fd4179SDavid Teigland rl->rl_namelen = r->res_length; 291*e7fd4179SDavid Teigland memcpy(rl->rl_name, r->res_name, r->res_length); 292*e7fd4179SDavid Teigland 293*e7fd4179SDavid Teigland /* FIXME: might we have an lvb without DLM_LKF_VALBLK set ? 294*e7fd4179SDavid Teigland If so, receive_rcom_lock_args() won't take this copy. */ 295*e7fd4179SDavid Teigland 296*e7fd4179SDavid Teigland if (lkb->lkb_lvbptr) 297*e7fd4179SDavid Teigland memcpy(rl->rl_lvb, lkb->lkb_lvbptr, r->res_ls->ls_lvblen); 298*e7fd4179SDavid Teigland } 299*e7fd4179SDavid Teigland 300*e7fd4179SDavid Teigland int dlm_send_rcom_lock(struct dlm_rsb *r, struct dlm_lkb *lkb) 301*e7fd4179SDavid Teigland { 302*e7fd4179SDavid Teigland struct dlm_ls *ls = r->res_ls; 303*e7fd4179SDavid Teigland struct dlm_rcom *rc; 304*e7fd4179SDavid Teigland struct dlm_mhandle *mh; 305*e7fd4179SDavid Teigland struct rcom_lock *rl; 306*e7fd4179SDavid Teigland int error, len = sizeof(struct rcom_lock); 307*e7fd4179SDavid Teigland 308*e7fd4179SDavid Teigland if (lkb->lkb_lvbptr) 309*e7fd4179SDavid Teigland len += ls->ls_lvblen; 310*e7fd4179SDavid Teigland 311*e7fd4179SDavid Teigland error = create_rcom(ls, r->res_nodeid, DLM_RCOM_LOCK, len, &rc, &mh); 312*e7fd4179SDavid Teigland if (error) 313*e7fd4179SDavid Teigland goto out; 314*e7fd4179SDavid Teigland 315*e7fd4179SDavid Teigland rl = (struct rcom_lock *) rc->rc_buf; 316*e7fd4179SDavid Teigland pack_rcom_lock(r, lkb, rl); 317*e7fd4179SDavid Teigland rc->rc_id = (unsigned long) r; 318*e7fd4179SDavid Teigland 319*e7fd4179SDavid Teigland send_rcom(ls, mh, rc); 320*e7fd4179SDavid Teigland out: 321*e7fd4179SDavid Teigland return error; 322*e7fd4179SDavid Teigland } 323*e7fd4179SDavid Teigland 324*e7fd4179SDavid Teigland static void receive_rcom_lock(struct dlm_ls *ls, struct dlm_rcom *rc_in) 325*e7fd4179SDavid Teigland { 326*e7fd4179SDavid Teigland struct dlm_rcom *rc; 327*e7fd4179SDavid Teigland struct dlm_mhandle *mh; 328*e7fd4179SDavid Teigland int error, nodeid = rc_in->rc_header.h_nodeid; 329*e7fd4179SDavid Teigland 330*e7fd4179SDavid Teigland dlm_recover_master_copy(ls, rc_in); 331*e7fd4179SDavid Teigland 332*e7fd4179SDavid Teigland error = create_rcom(ls, nodeid, DLM_RCOM_LOCK_REPLY, 333*e7fd4179SDavid Teigland sizeof(struct rcom_lock), &rc, &mh); 334*e7fd4179SDavid Teigland if (error) 335*e7fd4179SDavid Teigland return; 336*e7fd4179SDavid Teigland 337*e7fd4179SDavid Teigland /* We send back the same rcom_lock struct we received, but 338*e7fd4179SDavid Teigland dlm_recover_master_copy() has filled in rl_remid and rl_result */ 339*e7fd4179SDavid Teigland 340*e7fd4179SDavid Teigland memcpy(rc->rc_buf, rc_in->rc_buf, sizeof(struct rcom_lock)); 341*e7fd4179SDavid Teigland rc->rc_id = rc_in->rc_id; 342*e7fd4179SDavid Teigland 343*e7fd4179SDavid Teigland send_rcom(ls, mh, rc); 344*e7fd4179SDavid Teigland } 345*e7fd4179SDavid Teigland 346*e7fd4179SDavid Teigland static void receive_rcom_lock_reply(struct dlm_ls *ls, struct dlm_rcom *rc_in) 347*e7fd4179SDavid Teigland { 348*e7fd4179SDavid Teigland uint32_t status = dlm_recover_status(ls); 349*e7fd4179SDavid Teigland 350*e7fd4179SDavid Teigland if (!(status & DLM_RS_DIR)) { 351*e7fd4179SDavid Teigland log_debug(ls, "ignoring RCOM_LOCK_REPLY from %u", 352*e7fd4179SDavid Teigland rc_in->rc_header.h_nodeid); 353*e7fd4179SDavid Teigland return; 354*e7fd4179SDavid Teigland } 355*e7fd4179SDavid Teigland 356*e7fd4179SDavid Teigland dlm_recover_process_copy(ls, rc_in); 357*e7fd4179SDavid Teigland } 358*e7fd4179SDavid Teigland 359*e7fd4179SDavid Teigland static int send_ls_not_ready(int nodeid, struct dlm_rcom *rc_in) 360*e7fd4179SDavid Teigland { 361*e7fd4179SDavid Teigland struct dlm_rcom *rc; 362*e7fd4179SDavid Teigland struct dlm_mhandle *mh; 363*e7fd4179SDavid Teigland char *mb; 364*e7fd4179SDavid Teigland int mb_len = sizeof(struct dlm_rcom); 365*e7fd4179SDavid Teigland 366*e7fd4179SDavid Teigland mh = dlm_lowcomms_get_buffer(nodeid, mb_len, GFP_KERNEL, &mb); 367*e7fd4179SDavid Teigland if (!mh) 368*e7fd4179SDavid Teigland return -ENOBUFS; 369*e7fd4179SDavid Teigland memset(mb, 0, mb_len); 370*e7fd4179SDavid Teigland 371*e7fd4179SDavid Teigland rc = (struct dlm_rcom *) mb; 372*e7fd4179SDavid Teigland 373*e7fd4179SDavid Teigland rc->rc_header.h_version = (DLM_HEADER_MAJOR | DLM_HEADER_MINOR); 374*e7fd4179SDavid Teigland rc->rc_header.h_lockspace = rc_in->rc_header.h_lockspace; 375*e7fd4179SDavid Teigland rc->rc_header.h_nodeid = dlm_our_nodeid(); 376*e7fd4179SDavid Teigland rc->rc_header.h_length = mb_len; 377*e7fd4179SDavid Teigland rc->rc_header.h_cmd = DLM_RCOM; 378*e7fd4179SDavid Teigland 379*e7fd4179SDavid Teigland rc->rc_type = DLM_RCOM_STATUS_REPLY; 380*e7fd4179SDavid Teigland rc->rc_result = -ESRCH; 381*e7fd4179SDavid Teigland 382*e7fd4179SDavid Teigland dlm_rcom_out(rc); 383*e7fd4179SDavid Teigland dlm_lowcomms_commit_buffer(mh); 384*e7fd4179SDavid Teigland 385*e7fd4179SDavid Teigland return 0; 386*e7fd4179SDavid Teigland } 387*e7fd4179SDavid Teigland 388*e7fd4179SDavid Teigland /* Called by dlm_recvd; corresponds to dlm_receive_message() but special 389*e7fd4179SDavid Teigland recovery-only comms are sent through here. */ 390*e7fd4179SDavid Teigland 391*e7fd4179SDavid Teigland void dlm_receive_rcom(struct dlm_header *hd, int nodeid) 392*e7fd4179SDavid Teigland { 393*e7fd4179SDavid Teigland struct dlm_rcom *rc = (struct dlm_rcom *) hd; 394*e7fd4179SDavid Teigland struct dlm_ls *ls; 395*e7fd4179SDavid Teigland 396*e7fd4179SDavid Teigland dlm_rcom_in(rc); 397*e7fd4179SDavid Teigland 398*e7fd4179SDavid Teigland /* If the lockspace doesn't exist then still send a status message 399*e7fd4179SDavid Teigland back; it's possible that it just doesn't have its global_id yet. */ 400*e7fd4179SDavid Teigland 401*e7fd4179SDavid Teigland ls = dlm_find_lockspace_global(hd->h_lockspace); 402*e7fd4179SDavid Teigland if (!ls) { 403*e7fd4179SDavid Teigland log_print("lockspace %x from %d not found", 404*e7fd4179SDavid Teigland hd->h_lockspace, nodeid); 405*e7fd4179SDavid Teigland send_ls_not_ready(nodeid, rc); 406*e7fd4179SDavid Teigland return; 407*e7fd4179SDavid Teigland } 408*e7fd4179SDavid Teigland 409*e7fd4179SDavid Teigland if (dlm_recovery_stopped(ls) && (rc->rc_type != DLM_RCOM_STATUS)) { 410*e7fd4179SDavid Teigland log_error(ls, "ignoring recovery message %x from %d", 411*e7fd4179SDavid Teigland rc->rc_type, nodeid); 412*e7fd4179SDavid Teigland goto out; 413*e7fd4179SDavid Teigland } 414*e7fd4179SDavid Teigland 415*e7fd4179SDavid Teigland if (nodeid != rc->rc_header.h_nodeid) { 416*e7fd4179SDavid Teigland log_error(ls, "bad rcom nodeid %d from %d", 417*e7fd4179SDavid Teigland rc->rc_header.h_nodeid, nodeid); 418*e7fd4179SDavid Teigland goto out; 419*e7fd4179SDavid Teigland } 420*e7fd4179SDavid Teigland 421*e7fd4179SDavid Teigland switch (rc->rc_type) { 422*e7fd4179SDavid Teigland case DLM_RCOM_STATUS: 423*e7fd4179SDavid Teigland receive_rcom_status(ls, rc); 424*e7fd4179SDavid Teigland break; 425*e7fd4179SDavid Teigland 426*e7fd4179SDavid Teigland case DLM_RCOM_NAMES: 427*e7fd4179SDavid Teigland receive_rcom_names(ls, rc); 428*e7fd4179SDavid Teigland break; 429*e7fd4179SDavid Teigland 430*e7fd4179SDavid Teigland case DLM_RCOM_LOOKUP: 431*e7fd4179SDavid Teigland receive_rcom_lookup(ls, rc); 432*e7fd4179SDavid Teigland break; 433*e7fd4179SDavid Teigland 434*e7fd4179SDavid Teigland case DLM_RCOM_LOCK: 435*e7fd4179SDavid Teigland receive_rcom_lock(ls, rc); 436*e7fd4179SDavid Teigland break; 437*e7fd4179SDavid Teigland 438*e7fd4179SDavid Teigland case DLM_RCOM_STATUS_REPLY: 439*e7fd4179SDavid Teigland receive_rcom_status_reply(ls, rc); 440*e7fd4179SDavid Teigland break; 441*e7fd4179SDavid Teigland 442*e7fd4179SDavid Teigland case DLM_RCOM_NAMES_REPLY: 443*e7fd4179SDavid Teigland receive_rcom_names_reply(ls, rc); 444*e7fd4179SDavid Teigland break; 445*e7fd4179SDavid Teigland 446*e7fd4179SDavid Teigland case DLM_RCOM_LOOKUP_REPLY: 447*e7fd4179SDavid Teigland receive_rcom_lookup_reply(ls, rc); 448*e7fd4179SDavid Teigland break; 449*e7fd4179SDavid Teigland 450*e7fd4179SDavid Teigland case DLM_RCOM_LOCK_REPLY: 451*e7fd4179SDavid Teigland receive_rcom_lock_reply(ls, rc); 452*e7fd4179SDavid Teigland break; 453*e7fd4179SDavid Teigland 454*e7fd4179SDavid Teigland default: 455*e7fd4179SDavid Teigland DLM_ASSERT(0, printk("rc_type=%x\n", rc->rc_type);); 456*e7fd4179SDavid Teigland } 457*e7fd4179SDavid Teigland out: 458*e7fd4179SDavid Teigland dlm_put_lockspace(ls); 459*e7fd4179SDavid Teigland } 460*e7fd4179SDavid Teigland 461