1e7fd4179SDavid Teigland /****************************************************************************** 2e7fd4179SDavid Teigland ******************************************************************************* 3e7fd4179SDavid Teigland ** 4e7fd4179SDavid Teigland ** Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved. 5e7fd4179SDavid Teigland ** Copyright (C) 2004-2005 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 "dir.h" 17e7fd4179SDavid Teigland #include "config.h" 18e7fd4179SDavid Teigland #include "ast.h" 19e7fd4179SDavid Teigland #include "memory.h" 20e7fd4179SDavid Teigland #include "rcom.h" 21e7fd4179SDavid Teigland #include "lock.h" 22e7fd4179SDavid Teigland #include "lowcomms.h" 23e7fd4179SDavid Teigland #include "member.h" 24e7fd4179SDavid Teigland #include "recover.h" 25e7fd4179SDavid Teigland 26e7fd4179SDavid Teigland 27e7fd4179SDavid Teigland /* 28e7fd4179SDavid Teigland * Recovery waiting routines: these functions wait for a particular reply from 29e7fd4179SDavid Teigland * a remote node, or for the remote node to report a certain status. They need 30e7fd4179SDavid Teigland * to abort if the lockspace is stopped indicating a node has failed (perhaps 31e7fd4179SDavid Teigland * the one being waited for). 32e7fd4179SDavid Teigland */ 33e7fd4179SDavid Teigland 34e7fd4179SDavid Teigland /* 35e7fd4179SDavid Teigland * Wait until given function returns non-zero or lockspace is stopped 36e7fd4179SDavid Teigland * (LS_RECOVERY_STOP set due to failure of a node in ls_nodes). When another 37e7fd4179SDavid Teigland * function thinks it could have completed the waited-on task, they should wake 38e7fd4179SDavid Teigland * up ls_wait_general to get an immediate response rather than waiting for the 39e7fd4179SDavid Teigland * timer to detect the result. A timer wakes us up periodically while waiting 40e7fd4179SDavid Teigland * to see if we should abort due to a node failure. This should only be called 41e7fd4179SDavid Teigland * by the dlm_recoverd thread. 42e7fd4179SDavid Teigland */ 43e7fd4179SDavid Teigland 44e7fd4179SDavid Teigland static void dlm_wait_timer_fn(unsigned long data) 45e7fd4179SDavid Teigland { 46e7fd4179SDavid Teigland struct dlm_ls *ls = (struct dlm_ls *) data; 4768c817a1SDavid Teigland mod_timer(&ls->ls_timer, jiffies + (dlm_config.ci_recover_timer * HZ)); 48e7fd4179SDavid Teigland wake_up(&ls->ls_wait_general); 49e7fd4179SDavid Teigland } 50e7fd4179SDavid Teigland 51e7fd4179SDavid Teigland int dlm_wait_function(struct dlm_ls *ls, int (*testfn) (struct dlm_ls *ls)) 52e7fd4179SDavid Teigland { 53e7fd4179SDavid Teigland int error = 0; 54e7fd4179SDavid Teigland 55e7fd4179SDavid Teigland init_timer(&ls->ls_timer); 56e7fd4179SDavid Teigland ls->ls_timer.function = dlm_wait_timer_fn; 57e7fd4179SDavid Teigland ls->ls_timer.data = (long) ls; 5868c817a1SDavid Teigland ls->ls_timer.expires = jiffies + (dlm_config.ci_recover_timer * HZ); 59e7fd4179SDavid Teigland add_timer(&ls->ls_timer); 60e7fd4179SDavid Teigland 61e7fd4179SDavid Teigland wait_event(ls->ls_wait_general, testfn(ls) || dlm_recovery_stopped(ls)); 62e7fd4179SDavid Teigland del_timer_sync(&ls->ls_timer); 63e7fd4179SDavid Teigland 64e7fd4179SDavid Teigland if (dlm_recovery_stopped(ls)) { 65e7fd4179SDavid Teigland log_debug(ls, "dlm_wait_function aborted"); 66e7fd4179SDavid Teigland error = -EINTR; 67e7fd4179SDavid Teigland } 68e7fd4179SDavid Teigland return error; 69e7fd4179SDavid Teigland } 70e7fd4179SDavid Teigland 71e7fd4179SDavid Teigland /* 72e7fd4179SDavid Teigland * An efficient way for all nodes to wait for all others to have a certain 73e7fd4179SDavid Teigland * status. The node with the lowest nodeid polls all the others for their 74e7fd4179SDavid Teigland * status (wait_status_all) and all the others poll the node with the low id 75e7fd4179SDavid Teigland * for its accumulated result (wait_status_low). When all nodes have set 76e7fd4179SDavid Teigland * status flag X, then status flag X_ALL will be set on the low nodeid. 77e7fd4179SDavid Teigland */ 78e7fd4179SDavid Teigland 79e7fd4179SDavid Teigland uint32_t dlm_recover_status(struct dlm_ls *ls) 80e7fd4179SDavid Teigland { 81e7fd4179SDavid Teigland uint32_t status; 82e7fd4179SDavid Teigland spin_lock(&ls->ls_recover_lock); 83e7fd4179SDavid Teigland status = ls->ls_recover_status; 84e7fd4179SDavid Teigland spin_unlock(&ls->ls_recover_lock); 85e7fd4179SDavid Teigland return status; 86e7fd4179SDavid Teigland } 87e7fd4179SDavid Teigland 88e7fd4179SDavid Teigland void dlm_set_recover_status(struct dlm_ls *ls, uint32_t status) 89e7fd4179SDavid Teigland { 90e7fd4179SDavid Teigland spin_lock(&ls->ls_recover_lock); 91e7fd4179SDavid Teigland ls->ls_recover_status |= status; 92e7fd4179SDavid Teigland spin_unlock(&ls->ls_recover_lock); 93e7fd4179SDavid Teigland } 94e7fd4179SDavid Teigland 95e7fd4179SDavid Teigland static int wait_status_all(struct dlm_ls *ls, uint32_t wait_status) 96e7fd4179SDavid Teigland { 974007685cSAl Viro struct dlm_rcom *rc = ls->ls_recover_buf; 98e7fd4179SDavid Teigland struct dlm_member *memb; 99e7fd4179SDavid Teigland int error = 0, delay; 100e7fd4179SDavid Teigland 101e7fd4179SDavid Teigland list_for_each_entry(memb, &ls->ls_nodes, list) { 102e7fd4179SDavid Teigland delay = 0; 103e7fd4179SDavid Teigland for (;;) { 104e7fd4179SDavid Teigland if (dlm_recovery_stopped(ls)) { 105e7fd4179SDavid Teigland error = -EINTR; 106e7fd4179SDavid Teigland goto out; 107e7fd4179SDavid Teigland } 108e7fd4179SDavid Teigland 109e7fd4179SDavid Teigland error = dlm_rcom_status(ls, memb->nodeid); 110e7fd4179SDavid Teigland if (error) 111e7fd4179SDavid Teigland goto out; 112e7fd4179SDavid Teigland 113e7fd4179SDavid Teigland if (rc->rc_result & wait_status) 114e7fd4179SDavid Teigland break; 115e7fd4179SDavid Teigland if (delay < 1000) 116e7fd4179SDavid Teigland delay += 20; 117e7fd4179SDavid Teigland msleep(delay); 118e7fd4179SDavid Teigland } 119e7fd4179SDavid Teigland } 120e7fd4179SDavid Teigland out: 121e7fd4179SDavid Teigland return error; 122e7fd4179SDavid Teigland } 123e7fd4179SDavid Teigland 124e7fd4179SDavid Teigland static int wait_status_low(struct dlm_ls *ls, uint32_t wait_status) 125e7fd4179SDavid Teigland { 1264007685cSAl Viro struct dlm_rcom *rc = ls->ls_recover_buf; 127e7fd4179SDavid Teigland int error = 0, delay = 0, nodeid = ls->ls_low_nodeid; 128e7fd4179SDavid Teigland 129e7fd4179SDavid Teigland for (;;) { 130e7fd4179SDavid Teigland if (dlm_recovery_stopped(ls)) { 131e7fd4179SDavid Teigland error = -EINTR; 132e7fd4179SDavid Teigland goto out; 133e7fd4179SDavid Teigland } 134e7fd4179SDavid Teigland 135e7fd4179SDavid Teigland error = dlm_rcom_status(ls, nodeid); 136e7fd4179SDavid Teigland if (error) 137e7fd4179SDavid Teigland break; 138e7fd4179SDavid Teigland 139e7fd4179SDavid Teigland if (rc->rc_result & wait_status) 140e7fd4179SDavid Teigland break; 141e7fd4179SDavid Teigland if (delay < 1000) 142e7fd4179SDavid Teigland delay += 20; 143e7fd4179SDavid Teigland msleep(delay); 144e7fd4179SDavid Teigland } 145e7fd4179SDavid Teigland out: 146e7fd4179SDavid Teigland return error; 147e7fd4179SDavid Teigland } 148e7fd4179SDavid Teigland 149e7fd4179SDavid Teigland static int wait_status(struct dlm_ls *ls, uint32_t status) 150e7fd4179SDavid Teigland { 151e7fd4179SDavid Teigland uint32_t status_all = status << 1; 152e7fd4179SDavid Teigland int error; 153e7fd4179SDavid Teigland 154e7fd4179SDavid Teigland if (ls->ls_low_nodeid == dlm_our_nodeid()) { 155e7fd4179SDavid Teigland error = wait_status_all(ls, status); 156e7fd4179SDavid Teigland if (!error) 157e7fd4179SDavid Teigland dlm_set_recover_status(ls, status_all); 158e7fd4179SDavid Teigland } else 159e7fd4179SDavid Teigland error = wait_status_low(ls, status_all); 160e7fd4179SDavid Teigland 161e7fd4179SDavid Teigland return error; 162e7fd4179SDavid Teigland } 163e7fd4179SDavid Teigland 164e7fd4179SDavid Teigland int dlm_recover_members_wait(struct dlm_ls *ls) 165e7fd4179SDavid Teigland { 166e7fd4179SDavid Teigland return wait_status(ls, DLM_RS_NODES); 167e7fd4179SDavid Teigland } 168e7fd4179SDavid Teigland 169e7fd4179SDavid Teigland int dlm_recover_directory_wait(struct dlm_ls *ls) 170e7fd4179SDavid Teigland { 171e7fd4179SDavid Teigland return wait_status(ls, DLM_RS_DIR); 172e7fd4179SDavid Teigland } 173e7fd4179SDavid Teigland 174e7fd4179SDavid Teigland int dlm_recover_locks_wait(struct dlm_ls *ls) 175e7fd4179SDavid Teigland { 176e7fd4179SDavid Teigland return wait_status(ls, DLM_RS_LOCKS); 177e7fd4179SDavid Teigland } 178e7fd4179SDavid Teigland 179e7fd4179SDavid Teigland int dlm_recover_done_wait(struct dlm_ls *ls) 180e7fd4179SDavid Teigland { 181e7fd4179SDavid Teigland return wait_status(ls, DLM_RS_DONE); 182e7fd4179SDavid Teigland } 183e7fd4179SDavid Teigland 184e7fd4179SDavid Teigland /* 185e7fd4179SDavid Teigland * The recover_list contains all the rsb's for which we've requested the new 186e7fd4179SDavid Teigland * master nodeid. As replies are returned from the resource directories the 187e7fd4179SDavid Teigland * rsb's are removed from the list. When the list is empty we're done. 188e7fd4179SDavid Teigland * 189e7fd4179SDavid Teigland * The recover_list is later similarly used for all rsb's for which we've sent 190e7fd4179SDavid Teigland * new lkb's and need to receive new corresponding lkid's. 191e7fd4179SDavid Teigland * 192e7fd4179SDavid Teigland * We use the address of the rsb struct as a simple local identifier for the 193e7fd4179SDavid Teigland * rsb so we can match an rcom reply with the rsb it was sent for. 194e7fd4179SDavid Teigland */ 195e7fd4179SDavid Teigland 196e7fd4179SDavid Teigland static int recover_list_empty(struct dlm_ls *ls) 197e7fd4179SDavid Teigland { 198e7fd4179SDavid Teigland int empty; 199e7fd4179SDavid Teigland 200e7fd4179SDavid Teigland spin_lock(&ls->ls_recover_list_lock); 201e7fd4179SDavid Teigland empty = list_empty(&ls->ls_recover_list); 202e7fd4179SDavid Teigland spin_unlock(&ls->ls_recover_list_lock); 203e7fd4179SDavid Teigland 204e7fd4179SDavid Teigland return empty; 205e7fd4179SDavid Teigland } 206e7fd4179SDavid Teigland 207e7fd4179SDavid Teigland static void recover_list_add(struct dlm_rsb *r) 208e7fd4179SDavid Teigland { 209e7fd4179SDavid Teigland struct dlm_ls *ls = r->res_ls; 210e7fd4179SDavid Teigland 211e7fd4179SDavid Teigland spin_lock(&ls->ls_recover_list_lock); 212e7fd4179SDavid Teigland if (list_empty(&r->res_recover_list)) { 213e7fd4179SDavid Teigland list_add_tail(&r->res_recover_list, &ls->ls_recover_list); 214e7fd4179SDavid Teigland ls->ls_recover_list_count++; 215e7fd4179SDavid Teigland dlm_hold_rsb(r); 216e7fd4179SDavid Teigland } 217e7fd4179SDavid Teigland spin_unlock(&ls->ls_recover_list_lock); 218e7fd4179SDavid Teigland } 219e7fd4179SDavid Teigland 220e7fd4179SDavid Teigland static void recover_list_del(struct dlm_rsb *r) 221e7fd4179SDavid Teigland { 222e7fd4179SDavid Teigland struct dlm_ls *ls = r->res_ls; 223e7fd4179SDavid Teigland 224e7fd4179SDavid Teigland spin_lock(&ls->ls_recover_list_lock); 225e7fd4179SDavid Teigland list_del_init(&r->res_recover_list); 226e7fd4179SDavid Teigland ls->ls_recover_list_count--; 227e7fd4179SDavid Teigland spin_unlock(&ls->ls_recover_list_lock); 228e7fd4179SDavid Teigland 229e7fd4179SDavid Teigland dlm_put_rsb(r); 230e7fd4179SDavid Teigland } 231e7fd4179SDavid Teigland 232e7fd4179SDavid Teigland static struct dlm_rsb *recover_list_find(struct dlm_ls *ls, uint64_t id) 233e7fd4179SDavid Teigland { 234e7fd4179SDavid Teigland struct dlm_rsb *r = NULL; 235e7fd4179SDavid Teigland 236e7fd4179SDavid Teigland spin_lock(&ls->ls_recover_list_lock); 237e7fd4179SDavid Teigland 238e7fd4179SDavid Teigland list_for_each_entry(r, &ls->ls_recover_list, res_recover_list) { 239e7fd4179SDavid Teigland if (id == (unsigned long) r) 240e7fd4179SDavid Teigland goto out; 241e7fd4179SDavid Teigland } 242e7fd4179SDavid Teigland r = NULL; 243e7fd4179SDavid Teigland out: 244e7fd4179SDavid Teigland spin_unlock(&ls->ls_recover_list_lock); 245e7fd4179SDavid Teigland return r; 246e7fd4179SDavid Teigland } 247e7fd4179SDavid Teigland 248e7fd4179SDavid Teigland static void recover_list_clear(struct dlm_ls *ls) 249e7fd4179SDavid Teigland { 250e7fd4179SDavid Teigland struct dlm_rsb *r, *s; 251e7fd4179SDavid Teigland 252e7fd4179SDavid Teigland spin_lock(&ls->ls_recover_list_lock); 253e7fd4179SDavid Teigland list_for_each_entry_safe(r, s, &ls->ls_recover_list, res_recover_list) { 254e7fd4179SDavid Teigland list_del_init(&r->res_recover_list); 25552069809SDavid Teigland r->res_recover_locks_count = 0; 256e7fd4179SDavid Teigland dlm_put_rsb(r); 257e7fd4179SDavid Teigland ls->ls_recover_list_count--; 258e7fd4179SDavid Teigland } 259e7fd4179SDavid Teigland 260e7fd4179SDavid Teigland if (ls->ls_recover_list_count != 0) { 261e7fd4179SDavid Teigland log_error(ls, "warning: recover_list_count %d", 262e7fd4179SDavid Teigland ls->ls_recover_list_count); 263e7fd4179SDavid Teigland ls->ls_recover_list_count = 0; 264e7fd4179SDavid Teigland } 265e7fd4179SDavid Teigland spin_unlock(&ls->ls_recover_list_lock); 266e7fd4179SDavid Teigland } 267e7fd4179SDavid Teigland 268e7fd4179SDavid Teigland 269e7fd4179SDavid Teigland /* Master recovery: find new master node for rsb's that were 270e7fd4179SDavid Teigland mastered on nodes that have been removed. 271e7fd4179SDavid Teigland 272e7fd4179SDavid Teigland dlm_recover_masters 273e7fd4179SDavid Teigland recover_master 274e7fd4179SDavid Teigland dlm_send_rcom_lookup -> receive_rcom_lookup 275e7fd4179SDavid Teigland dlm_dir_lookup 276e7fd4179SDavid Teigland receive_rcom_lookup_reply <- 277e7fd4179SDavid Teigland dlm_recover_master_reply 278e7fd4179SDavid Teigland set_new_master 279e7fd4179SDavid Teigland set_master_lkbs 280e7fd4179SDavid Teigland set_lock_master 281e7fd4179SDavid Teigland */ 282e7fd4179SDavid Teigland 283e7fd4179SDavid Teigland /* 284e7fd4179SDavid Teigland * Set the lock master for all LKBs in a lock queue 285e7fd4179SDavid Teigland * If we are the new master of the rsb, we may have received new 286e7fd4179SDavid Teigland * MSTCPY locks from other nodes already which we need to ignore 287e7fd4179SDavid Teigland * when setting the new nodeid. 288e7fd4179SDavid Teigland */ 289e7fd4179SDavid Teigland 290e7fd4179SDavid Teigland static void set_lock_master(struct list_head *queue, int nodeid) 291e7fd4179SDavid Teigland { 292e7fd4179SDavid Teigland struct dlm_lkb *lkb; 293e7fd4179SDavid Teigland 294e7fd4179SDavid Teigland list_for_each_entry(lkb, queue, lkb_statequeue) 295e7fd4179SDavid Teigland if (!(lkb->lkb_flags & DLM_IFL_MSTCPY)) 296e7fd4179SDavid Teigland lkb->lkb_nodeid = nodeid; 297e7fd4179SDavid Teigland } 298e7fd4179SDavid Teigland 299e7fd4179SDavid Teigland static void set_master_lkbs(struct dlm_rsb *r) 300e7fd4179SDavid Teigland { 301e7fd4179SDavid Teigland set_lock_master(&r->res_grantqueue, r->res_nodeid); 302e7fd4179SDavid Teigland set_lock_master(&r->res_convertqueue, r->res_nodeid); 303e7fd4179SDavid Teigland set_lock_master(&r->res_waitqueue, r->res_nodeid); 304e7fd4179SDavid Teigland } 305e7fd4179SDavid Teigland 306e7fd4179SDavid Teigland /* 30725985edcSLucas De Marchi * Propagate the new master nodeid to locks 308e7fd4179SDavid Teigland * The NEW_MASTER flag tells dlm_recover_locks() which rsb's to consider. 309f7da790dSDavid Teigland * The NEW_MASTER2 flag tells recover_lvb() and set_locks_purged() which 310f7da790dSDavid Teigland * rsb's to consider. 311e7fd4179SDavid Teigland */ 312e7fd4179SDavid Teigland 313e7fd4179SDavid Teigland static void set_new_master(struct dlm_rsb *r, int nodeid) 314e7fd4179SDavid Teigland { 315e7fd4179SDavid Teigland lock_rsb(r); 316e7fd4179SDavid Teigland r->res_nodeid = nodeid; 317e7fd4179SDavid Teigland set_master_lkbs(r); 318e7fd4179SDavid Teigland rsb_set_flag(r, RSB_NEW_MASTER); 319e7fd4179SDavid Teigland rsb_set_flag(r, RSB_NEW_MASTER2); 320e7fd4179SDavid Teigland unlock_rsb(r); 321e7fd4179SDavid Teigland } 322e7fd4179SDavid Teigland 323e7fd4179SDavid Teigland /* 324e7fd4179SDavid Teigland * We do async lookups on rsb's that need new masters. The rsb's 325e7fd4179SDavid Teigland * waiting for a lookup reply are kept on the recover_list. 326e7fd4179SDavid Teigland */ 327e7fd4179SDavid Teigland 328e7fd4179SDavid Teigland static int recover_master(struct dlm_rsb *r) 329e7fd4179SDavid Teigland { 330e7fd4179SDavid Teigland struct dlm_ls *ls = r->res_ls; 331e7fd4179SDavid Teigland int error, dir_nodeid, ret_nodeid, our_nodeid = dlm_our_nodeid(); 332e7fd4179SDavid Teigland 333e7fd4179SDavid Teigland dir_nodeid = dlm_dir_nodeid(r); 334e7fd4179SDavid Teigland 335e7fd4179SDavid Teigland if (dir_nodeid == our_nodeid) { 336e7fd4179SDavid Teigland error = dlm_dir_lookup(ls, our_nodeid, r->res_name, 337e7fd4179SDavid Teigland r->res_length, &ret_nodeid); 338e7fd4179SDavid Teigland if (error) 339e7fd4179SDavid Teigland log_error(ls, "recover dir lookup error %d", error); 340e7fd4179SDavid Teigland 341e7fd4179SDavid Teigland if (ret_nodeid == our_nodeid) 342e7fd4179SDavid Teigland ret_nodeid = 0; 343e7fd4179SDavid Teigland set_new_master(r, ret_nodeid); 344e7fd4179SDavid Teigland } else { 345e7fd4179SDavid Teigland recover_list_add(r); 346e7fd4179SDavid Teigland error = dlm_send_rcom_lookup(r, dir_nodeid); 347e7fd4179SDavid Teigland } 348e7fd4179SDavid Teigland 349e7fd4179SDavid Teigland return error; 350e7fd4179SDavid Teigland } 351e7fd4179SDavid Teigland 352e7fd4179SDavid Teigland /* 353e7fd4179SDavid Teigland * When not using a directory, most resource names will hash to a new static 354e7fd4179SDavid Teigland * master nodeid and the resource will need to be remastered. 355e7fd4179SDavid Teigland */ 356e7fd4179SDavid Teigland 357e7fd4179SDavid Teigland static int recover_master_static(struct dlm_rsb *r) 358e7fd4179SDavid Teigland { 359e7fd4179SDavid Teigland int master = dlm_dir_nodeid(r); 360e7fd4179SDavid Teigland 361e7fd4179SDavid Teigland if (master == dlm_our_nodeid()) 362e7fd4179SDavid Teigland master = 0; 363e7fd4179SDavid Teigland 364e7fd4179SDavid Teigland if (r->res_nodeid != master) { 365e7fd4179SDavid Teigland if (is_master(r)) 366e7fd4179SDavid Teigland dlm_purge_mstcpy_locks(r); 367e7fd4179SDavid Teigland set_new_master(r, master); 368e7fd4179SDavid Teigland return 1; 369e7fd4179SDavid Teigland } 370e7fd4179SDavid Teigland return 0; 371e7fd4179SDavid Teigland } 372e7fd4179SDavid Teigland 373e7fd4179SDavid Teigland /* 374e7fd4179SDavid Teigland * Go through local root resources and for each rsb which has a master which 375e7fd4179SDavid Teigland * has departed, get the new master nodeid from the directory. The dir will 376e7fd4179SDavid Teigland * assign mastery to the first node to look up the new master. That means 377e7fd4179SDavid Teigland * we'll discover in this lookup if we're the new master of any rsb's. 378e7fd4179SDavid Teigland * 379e7fd4179SDavid Teigland * We fire off all the dir lookup requests individually and asynchronously to 380e7fd4179SDavid Teigland * the correct dir node. 381e7fd4179SDavid Teigland */ 382e7fd4179SDavid Teigland 383e7fd4179SDavid Teigland int dlm_recover_masters(struct dlm_ls *ls) 384e7fd4179SDavid Teigland { 385e7fd4179SDavid Teigland struct dlm_rsb *r; 386e7fd4179SDavid Teigland int error = 0, count = 0; 387e7fd4179SDavid Teigland 388e7fd4179SDavid Teigland log_debug(ls, "dlm_recover_masters"); 389e7fd4179SDavid Teigland 390e7fd4179SDavid Teigland down_read(&ls->ls_root_sem); 391e7fd4179SDavid Teigland list_for_each_entry(r, &ls->ls_root_list, res_root_list) { 392e7fd4179SDavid Teigland if (dlm_recovery_stopped(ls)) { 393e7fd4179SDavid Teigland up_read(&ls->ls_root_sem); 394e7fd4179SDavid Teigland error = -EINTR; 395e7fd4179SDavid Teigland goto out; 396e7fd4179SDavid Teigland } 397e7fd4179SDavid Teigland 398e7fd4179SDavid Teigland if (dlm_no_directory(ls)) 399e7fd4179SDavid Teigland count += recover_master_static(r); 400222d3960SDavid Teigland else if (!is_master(r) && 401222d3960SDavid Teigland (dlm_is_removed(ls, r->res_nodeid) || 402222d3960SDavid Teigland rsb_flag(r, RSB_NEW_MASTER))) { 403e7fd4179SDavid Teigland recover_master(r); 404e7fd4179SDavid Teigland count++; 405e7fd4179SDavid Teigland } 406e7fd4179SDavid Teigland 407e7fd4179SDavid Teigland schedule(); 408e7fd4179SDavid Teigland } 409e7fd4179SDavid Teigland up_read(&ls->ls_root_sem); 410e7fd4179SDavid Teigland 411e7fd4179SDavid Teigland log_debug(ls, "dlm_recover_masters %d resources", count); 412e7fd4179SDavid Teigland 413e7fd4179SDavid Teigland error = dlm_wait_function(ls, &recover_list_empty); 414e7fd4179SDavid Teigland out: 415e7fd4179SDavid Teigland if (error) 416e7fd4179SDavid Teigland recover_list_clear(ls); 417e7fd4179SDavid Teigland return error; 418e7fd4179SDavid Teigland } 419e7fd4179SDavid Teigland 420e7fd4179SDavid Teigland int dlm_recover_master_reply(struct dlm_ls *ls, struct dlm_rcom *rc) 421e7fd4179SDavid Teigland { 422e7fd4179SDavid Teigland struct dlm_rsb *r; 423e7fd4179SDavid Teigland int nodeid; 424e7fd4179SDavid Teigland 425e7fd4179SDavid Teigland r = recover_list_find(ls, rc->rc_id); 426e7fd4179SDavid Teigland if (!r) { 42790135925SDavid Teigland log_error(ls, "dlm_recover_master_reply no id %llx", 4289229f013SDavid Teigland (unsigned long long)rc->rc_id); 429e7fd4179SDavid Teigland goto out; 430e7fd4179SDavid Teigland } 431e7fd4179SDavid Teigland 432e7fd4179SDavid Teigland nodeid = rc->rc_result; 433e7fd4179SDavid Teigland if (nodeid == dlm_our_nodeid()) 434e7fd4179SDavid Teigland nodeid = 0; 435e7fd4179SDavid Teigland 436e7fd4179SDavid Teigland set_new_master(r, nodeid); 437e7fd4179SDavid Teigland recover_list_del(r); 438e7fd4179SDavid Teigland 439e7fd4179SDavid Teigland if (recover_list_empty(ls)) 440e7fd4179SDavid Teigland wake_up(&ls->ls_wait_general); 441e7fd4179SDavid Teigland out: 442e7fd4179SDavid Teigland return 0; 443e7fd4179SDavid Teigland } 444e7fd4179SDavid Teigland 445e7fd4179SDavid Teigland 446e7fd4179SDavid Teigland /* Lock recovery: rebuild the process-copy locks we hold on a 447e7fd4179SDavid Teigland remastered rsb on the new rsb master. 448e7fd4179SDavid Teigland 449e7fd4179SDavid Teigland dlm_recover_locks 450e7fd4179SDavid Teigland recover_locks 451e7fd4179SDavid Teigland recover_locks_queue 452e7fd4179SDavid Teigland dlm_send_rcom_lock -> receive_rcom_lock 453e7fd4179SDavid Teigland dlm_recover_master_copy 454e7fd4179SDavid Teigland receive_rcom_lock_reply <- 455e7fd4179SDavid Teigland dlm_recover_process_copy 456e7fd4179SDavid Teigland */ 457e7fd4179SDavid Teigland 458e7fd4179SDavid Teigland 459e7fd4179SDavid Teigland /* 460e7fd4179SDavid Teigland * keep a count of the number of lkb's we send to the new master; when we get 461e7fd4179SDavid Teigland * an equal number of replies then recovery for the rsb is done 462e7fd4179SDavid Teigland */ 463e7fd4179SDavid Teigland 464e7fd4179SDavid Teigland static int recover_locks_queue(struct dlm_rsb *r, struct list_head *head) 465e7fd4179SDavid Teigland { 466e7fd4179SDavid Teigland struct dlm_lkb *lkb; 467e7fd4179SDavid Teigland int error = 0; 468e7fd4179SDavid Teigland 469e7fd4179SDavid Teigland list_for_each_entry(lkb, head, lkb_statequeue) { 470e7fd4179SDavid Teigland error = dlm_send_rcom_lock(r, lkb); 471e7fd4179SDavid Teigland if (error) 472e7fd4179SDavid Teigland break; 473e7fd4179SDavid Teigland r->res_recover_locks_count++; 474e7fd4179SDavid Teigland } 475e7fd4179SDavid Teigland 476e7fd4179SDavid Teigland return error; 477e7fd4179SDavid Teigland } 478e7fd4179SDavid Teigland 479e7fd4179SDavid Teigland static int recover_locks(struct dlm_rsb *r) 480e7fd4179SDavid Teigland { 481e7fd4179SDavid Teigland int error = 0; 482e7fd4179SDavid Teigland 483e7fd4179SDavid Teigland lock_rsb(r); 484e7fd4179SDavid Teigland 485a345da3eSDavid Teigland DLM_ASSERT(!r->res_recover_locks_count, dlm_dump_rsb(r);); 486e7fd4179SDavid Teigland 487e7fd4179SDavid Teigland error = recover_locks_queue(r, &r->res_grantqueue); 488e7fd4179SDavid Teigland if (error) 489e7fd4179SDavid Teigland goto out; 490e7fd4179SDavid Teigland error = recover_locks_queue(r, &r->res_convertqueue); 491e7fd4179SDavid Teigland if (error) 492e7fd4179SDavid Teigland goto out; 493e7fd4179SDavid Teigland error = recover_locks_queue(r, &r->res_waitqueue); 494e7fd4179SDavid Teigland if (error) 495e7fd4179SDavid Teigland goto out; 496e7fd4179SDavid Teigland 497e7fd4179SDavid Teigland if (r->res_recover_locks_count) 498e7fd4179SDavid Teigland recover_list_add(r); 499e7fd4179SDavid Teigland else 500e7fd4179SDavid Teigland rsb_clear_flag(r, RSB_NEW_MASTER); 501e7fd4179SDavid Teigland out: 502e7fd4179SDavid Teigland unlock_rsb(r); 503e7fd4179SDavid Teigland return error; 504e7fd4179SDavid Teigland } 505e7fd4179SDavid Teigland 506e7fd4179SDavid Teigland int dlm_recover_locks(struct dlm_ls *ls) 507e7fd4179SDavid Teigland { 508e7fd4179SDavid Teigland struct dlm_rsb *r; 509e7fd4179SDavid Teigland int error, count = 0; 510e7fd4179SDavid Teigland 511e7fd4179SDavid Teigland log_debug(ls, "dlm_recover_locks"); 512e7fd4179SDavid Teigland 513e7fd4179SDavid Teigland down_read(&ls->ls_root_sem); 514e7fd4179SDavid Teigland list_for_each_entry(r, &ls->ls_root_list, res_root_list) { 515e7fd4179SDavid Teigland if (is_master(r)) { 516e7fd4179SDavid Teigland rsb_clear_flag(r, RSB_NEW_MASTER); 517e7fd4179SDavid Teigland continue; 518e7fd4179SDavid Teigland } 519e7fd4179SDavid Teigland 520e7fd4179SDavid Teigland if (!rsb_flag(r, RSB_NEW_MASTER)) 521e7fd4179SDavid Teigland continue; 522e7fd4179SDavid Teigland 523e7fd4179SDavid Teigland if (dlm_recovery_stopped(ls)) { 524e7fd4179SDavid Teigland error = -EINTR; 525e7fd4179SDavid Teigland up_read(&ls->ls_root_sem); 526e7fd4179SDavid Teigland goto out; 527e7fd4179SDavid Teigland } 528e7fd4179SDavid Teigland 529e7fd4179SDavid Teigland error = recover_locks(r); 530e7fd4179SDavid Teigland if (error) { 531e7fd4179SDavid Teigland up_read(&ls->ls_root_sem); 532e7fd4179SDavid Teigland goto out; 533e7fd4179SDavid Teigland } 534e7fd4179SDavid Teigland 535e7fd4179SDavid Teigland count += r->res_recover_locks_count; 536e7fd4179SDavid Teigland } 537e7fd4179SDavid Teigland up_read(&ls->ls_root_sem); 538e7fd4179SDavid Teigland 539e7fd4179SDavid Teigland log_debug(ls, "dlm_recover_locks %d locks", count); 540e7fd4179SDavid Teigland 541e7fd4179SDavid Teigland error = dlm_wait_function(ls, &recover_list_empty); 542e7fd4179SDavid Teigland out: 543e7fd4179SDavid Teigland if (error) 544e7fd4179SDavid Teigland recover_list_clear(ls); 545e7fd4179SDavid Teigland else 546e7fd4179SDavid Teigland dlm_set_recover_status(ls, DLM_RS_LOCKS); 547e7fd4179SDavid Teigland return error; 548e7fd4179SDavid Teigland } 549e7fd4179SDavid Teigland 550e7fd4179SDavid Teigland void dlm_recovered_lock(struct dlm_rsb *r) 551e7fd4179SDavid Teigland { 552a345da3eSDavid Teigland DLM_ASSERT(rsb_flag(r, RSB_NEW_MASTER), dlm_dump_rsb(r);); 553e7fd4179SDavid Teigland 554e7fd4179SDavid Teigland r->res_recover_locks_count--; 555e7fd4179SDavid Teigland if (!r->res_recover_locks_count) { 556e7fd4179SDavid Teigland rsb_clear_flag(r, RSB_NEW_MASTER); 557e7fd4179SDavid Teigland recover_list_del(r); 558e7fd4179SDavid Teigland } 559e7fd4179SDavid Teigland 560e7fd4179SDavid Teigland if (recover_list_empty(r->res_ls)) 561e7fd4179SDavid Teigland wake_up(&r->res_ls->ls_wait_general); 562e7fd4179SDavid Teigland } 563e7fd4179SDavid Teigland 564e7fd4179SDavid Teigland /* 565e7fd4179SDavid Teigland * The lvb needs to be recovered on all master rsb's. This includes setting 566e7fd4179SDavid Teigland * the VALNOTVALID flag if necessary, and determining the correct lvb contents 567e7fd4179SDavid Teigland * based on the lvb's of the locks held on the rsb. 568e7fd4179SDavid Teigland * 569e7fd4179SDavid Teigland * RSB_VALNOTVALID is set if there are only NL/CR locks on the rsb. If it 570e7fd4179SDavid Teigland * was already set prior to recovery, it's not cleared, regardless of locks. 571e7fd4179SDavid Teigland * 572e7fd4179SDavid Teigland * The LVB contents are only considered for changing when this is a new master 573e7fd4179SDavid Teigland * of the rsb (NEW_MASTER2). Then, the rsb's lvb is taken from any lkb with 574e7fd4179SDavid Teigland * mode > CR. If no lkb's exist with mode above CR, the lvb contents are taken 575e7fd4179SDavid Teigland * from the lkb with the largest lvb sequence number. 576e7fd4179SDavid Teigland */ 577e7fd4179SDavid Teigland 578e7fd4179SDavid Teigland static void recover_lvb(struct dlm_rsb *r) 579e7fd4179SDavid Teigland { 580e7fd4179SDavid Teigland struct dlm_lkb *lkb, *high_lkb = NULL; 581e7fd4179SDavid Teigland uint32_t high_seq = 0; 58290135925SDavid Teigland int lock_lvb_exists = 0; 58390135925SDavid Teigland int big_lock_exists = 0; 584e7fd4179SDavid Teigland int lvblen = r->res_ls->ls_lvblen; 585e7fd4179SDavid Teigland 586e7fd4179SDavid Teigland list_for_each_entry(lkb, &r->res_grantqueue, lkb_statequeue) { 587e7fd4179SDavid Teigland if (!(lkb->lkb_exflags & DLM_LKF_VALBLK)) 588e7fd4179SDavid Teigland continue; 589e7fd4179SDavid Teigland 59090135925SDavid Teigland lock_lvb_exists = 1; 591e7fd4179SDavid Teigland 592e7fd4179SDavid Teigland if (lkb->lkb_grmode > DLM_LOCK_CR) { 59390135925SDavid Teigland big_lock_exists = 1; 594e7fd4179SDavid Teigland goto setflag; 595e7fd4179SDavid Teigland } 596e7fd4179SDavid Teigland 597e7fd4179SDavid Teigland if (((int)lkb->lkb_lvbseq - (int)high_seq) >= 0) { 598e7fd4179SDavid Teigland high_lkb = lkb; 599e7fd4179SDavid Teigland high_seq = lkb->lkb_lvbseq; 600e7fd4179SDavid Teigland } 601e7fd4179SDavid Teigland } 602e7fd4179SDavid Teigland 603e7fd4179SDavid Teigland list_for_each_entry(lkb, &r->res_convertqueue, lkb_statequeue) { 604e7fd4179SDavid Teigland if (!(lkb->lkb_exflags & DLM_LKF_VALBLK)) 605e7fd4179SDavid Teigland continue; 606e7fd4179SDavid Teigland 60790135925SDavid Teigland lock_lvb_exists = 1; 608e7fd4179SDavid Teigland 609e7fd4179SDavid Teigland if (lkb->lkb_grmode > DLM_LOCK_CR) { 61090135925SDavid Teigland big_lock_exists = 1; 611e7fd4179SDavid Teigland goto setflag; 612e7fd4179SDavid Teigland } 613e7fd4179SDavid Teigland 614e7fd4179SDavid Teigland if (((int)lkb->lkb_lvbseq - (int)high_seq) >= 0) { 615e7fd4179SDavid Teigland high_lkb = lkb; 616e7fd4179SDavid Teigland high_seq = lkb->lkb_lvbseq; 617e7fd4179SDavid Teigland } 618e7fd4179SDavid Teigland } 619e7fd4179SDavid Teigland 620e7fd4179SDavid Teigland setflag: 621e7fd4179SDavid Teigland if (!lock_lvb_exists) 622e7fd4179SDavid Teigland goto out; 623e7fd4179SDavid Teigland 624e7fd4179SDavid Teigland if (!big_lock_exists) 625e7fd4179SDavid Teigland rsb_set_flag(r, RSB_VALNOTVALID); 626e7fd4179SDavid Teigland 627e7fd4179SDavid Teigland /* don't mess with the lvb unless we're the new master */ 628e7fd4179SDavid Teigland if (!rsb_flag(r, RSB_NEW_MASTER2)) 629e7fd4179SDavid Teigland goto out; 630e7fd4179SDavid Teigland 631e7fd4179SDavid Teigland if (!r->res_lvbptr) { 63252bda2b5SDavid Teigland r->res_lvbptr = dlm_allocate_lvb(r->res_ls); 633e7fd4179SDavid Teigland if (!r->res_lvbptr) 634e7fd4179SDavid Teigland goto out; 635e7fd4179SDavid Teigland } 636e7fd4179SDavid Teigland 637e7fd4179SDavid Teigland if (big_lock_exists) { 638e7fd4179SDavid Teigland r->res_lvbseq = lkb->lkb_lvbseq; 639e7fd4179SDavid Teigland memcpy(r->res_lvbptr, lkb->lkb_lvbptr, lvblen); 640e7fd4179SDavid Teigland } else if (high_lkb) { 641e7fd4179SDavid Teigland r->res_lvbseq = high_lkb->lkb_lvbseq; 642e7fd4179SDavid Teigland memcpy(r->res_lvbptr, high_lkb->lkb_lvbptr, lvblen); 643e7fd4179SDavid Teigland } else { 644e7fd4179SDavid Teigland r->res_lvbseq = 0; 645e7fd4179SDavid Teigland memset(r->res_lvbptr, 0, lvblen); 646e7fd4179SDavid Teigland } 647e7fd4179SDavid Teigland out: 648e7fd4179SDavid Teigland return; 649e7fd4179SDavid Teigland } 650e7fd4179SDavid Teigland 651e7fd4179SDavid Teigland /* All master rsb's flagged RECOVER_CONVERT need to be looked at. The locks 652e7fd4179SDavid Teigland converting PR->CW or CW->PR need to have their lkb_grmode set. */ 653e7fd4179SDavid Teigland 654e7fd4179SDavid Teigland static void recover_conversion(struct dlm_rsb *r) 655e7fd4179SDavid Teigland { 656e7fd4179SDavid Teigland struct dlm_lkb *lkb; 657e7fd4179SDavid Teigland int grmode = -1; 658e7fd4179SDavid Teigland 659e7fd4179SDavid Teigland list_for_each_entry(lkb, &r->res_grantqueue, lkb_statequeue) { 660e7fd4179SDavid Teigland if (lkb->lkb_grmode == DLM_LOCK_PR || 661e7fd4179SDavid Teigland lkb->lkb_grmode == DLM_LOCK_CW) { 662e7fd4179SDavid Teigland grmode = lkb->lkb_grmode; 663e7fd4179SDavid Teigland break; 664e7fd4179SDavid Teigland } 665e7fd4179SDavid Teigland } 666e7fd4179SDavid Teigland 667e7fd4179SDavid Teigland list_for_each_entry(lkb, &r->res_convertqueue, lkb_statequeue) { 668e7fd4179SDavid Teigland if (lkb->lkb_grmode != DLM_LOCK_IV) 669e7fd4179SDavid Teigland continue; 670e7fd4179SDavid Teigland if (grmode == -1) 671e7fd4179SDavid Teigland lkb->lkb_grmode = lkb->lkb_rqmode; 672e7fd4179SDavid Teigland else 673e7fd4179SDavid Teigland lkb->lkb_grmode = grmode; 674e7fd4179SDavid Teigland } 675e7fd4179SDavid Teigland } 676e7fd4179SDavid Teigland 677f7da790dSDavid Teigland /* We've become the new master for this rsb and waiting/converting locks may 678f7da790dSDavid Teigland need to be granted in dlm_grant_after_purge() due to locks that may have 679f7da790dSDavid Teigland existed from a removed node. */ 680f7da790dSDavid Teigland 681f7da790dSDavid Teigland static void set_locks_purged(struct dlm_rsb *r) 682f7da790dSDavid Teigland { 683f7da790dSDavid Teigland if (!list_empty(&r->res_waitqueue) || !list_empty(&r->res_convertqueue)) 684f7da790dSDavid Teigland rsb_set_flag(r, RSB_LOCKS_PURGED); 685f7da790dSDavid Teigland } 686f7da790dSDavid Teigland 687e7fd4179SDavid Teigland void dlm_recover_rsbs(struct dlm_ls *ls) 688e7fd4179SDavid Teigland { 689e7fd4179SDavid Teigland struct dlm_rsb *r; 690e7fd4179SDavid Teigland int count = 0; 691e7fd4179SDavid Teigland 692e7fd4179SDavid Teigland log_debug(ls, "dlm_recover_rsbs"); 693e7fd4179SDavid Teigland 694e7fd4179SDavid Teigland down_read(&ls->ls_root_sem); 695e7fd4179SDavid Teigland list_for_each_entry(r, &ls->ls_root_list, res_root_list) { 696e7fd4179SDavid Teigland lock_rsb(r); 697e7fd4179SDavid Teigland if (is_master(r)) { 698e7fd4179SDavid Teigland if (rsb_flag(r, RSB_RECOVER_CONVERT)) 699e7fd4179SDavid Teigland recover_conversion(r); 700f7da790dSDavid Teigland if (rsb_flag(r, RSB_NEW_MASTER2)) 701f7da790dSDavid Teigland set_locks_purged(r); 702e7fd4179SDavid Teigland recover_lvb(r); 703e7fd4179SDavid Teigland count++; 704e7fd4179SDavid Teigland } 705e7fd4179SDavid Teigland rsb_clear_flag(r, RSB_RECOVER_CONVERT); 706f7da790dSDavid Teigland rsb_clear_flag(r, RSB_NEW_MASTER2); 707e7fd4179SDavid Teigland unlock_rsb(r); 708e7fd4179SDavid Teigland } 709e7fd4179SDavid Teigland up_read(&ls->ls_root_sem); 710e7fd4179SDavid Teigland 711e7fd4179SDavid Teigland log_debug(ls, "dlm_recover_rsbs %d rsbs", count); 712e7fd4179SDavid Teigland } 713e7fd4179SDavid Teigland 714e7fd4179SDavid Teigland /* Create a single list of all root rsb's to be used during recovery */ 715e7fd4179SDavid Teigland 716e7fd4179SDavid Teigland int dlm_create_root_list(struct dlm_ls *ls) 717e7fd4179SDavid Teigland { 718*9beb3bf5SBob Peterson struct rb_node *n; 719e7fd4179SDavid Teigland struct dlm_rsb *r; 720e7fd4179SDavid Teigland int i, error = 0; 721e7fd4179SDavid Teigland 722e7fd4179SDavid Teigland down_write(&ls->ls_root_sem); 723e7fd4179SDavid Teigland if (!list_empty(&ls->ls_root_list)) { 724e7fd4179SDavid Teigland log_error(ls, "root list not empty"); 725e7fd4179SDavid Teigland error = -EINVAL; 726e7fd4179SDavid Teigland goto out; 727e7fd4179SDavid Teigland } 728e7fd4179SDavid Teigland 729e7fd4179SDavid Teigland for (i = 0; i < ls->ls_rsbtbl_size; i++) { 730c7be761aSDavid Teigland spin_lock(&ls->ls_rsbtbl[i].lock); 731*9beb3bf5SBob Peterson for (n = rb_first(&ls->ls_rsbtbl[i].keep); n; n = rb_next(n)) { 732*9beb3bf5SBob Peterson r = rb_entry(n, struct dlm_rsb, res_hashnode); 733e7fd4179SDavid Teigland list_add(&r->res_root_list, &ls->ls_root_list); 734e7fd4179SDavid Teigland dlm_hold_rsb(r); 735e7fd4179SDavid Teigland } 73685f0379aSDavid Teigland 73785f0379aSDavid Teigland /* If we're using a directory, add tossed rsbs to the root 73885f0379aSDavid Teigland list; they'll have entries created in the new directory, 73985f0379aSDavid Teigland but no other recovery steps should do anything with them. */ 74085f0379aSDavid Teigland 74185f0379aSDavid Teigland if (dlm_no_directory(ls)) { 742c7be761aSDavid Teigland spin_unlock(&ls->ls_rsbtbl[i].lock); 74385f0379aSDavid Teigland continue; 74485f0379aSDavid Teigland } 74585f0379aSDavid Teigland 746*9beb3bf5SBob Peterson for (n = rb_first(&ls->ls_rsbtbl[i].toss); n; n = rb_next(n)) { 747*9beb3bf5SBob Peterson r = rb_entry(n, struct dlm_rsb, res_hashnode); 74885f0379aSDavid Teigland list_add(&r->res_root_list, &ls->ls_root_list); 74985f0379aSDavid Teigland dlm_hold_rsb(r); 75085f0379aSDavid Teigland } 751c7be761aSDavid Teigland spin_unlock(&ls->ls_rsbtbl[i].lock); 752e7fd4179SDavid Teigland } 753e7fd4179SDavid Teigland out: 754e7fd4179SDavid Teigland up_write(&ls->ls_root_sem); 755e7fd4179SDavid Teigland return error; 756e7fd4179SDavid Teigland } 757e7fd4179SDavid Teigland 758e7fd4179SDavid Teigland void dlm_release_root_list(struct dlm_ls *ls) 759e7fd4179SDavid Teigland { 760e7fd4179SDavid Teigland struct dlm_rsb *r, *safe; 761e7fd4179SDavid Teigland 762e7fd4179SDavid Teigland down_write(&ls->ls_root_sem); 763e7fd4179SDavid Teigland list_for_each_entry_safe(r, safe, &ls->ls_root_list, res_root_list) { 764e7fd4179SDavid Teigland list_del_init(&r->res_root_list); 765e7fd4179SDavid Teigland dlm_put_rsb(r); 766e7fd4179SDavid Teigland } 767e7fd4179SDavid Teigland up_write(&ls->ls_root_sem); 768e7fd4179SDavid Teigland } 769e7fd4179SDavid Teigland 77085f0379aSDavid Teigland /* If not using a directory, clear the entire toss list, there's no benefit to 77185f0379aSDavid Teigland caching the master value since it's fixed. If we are using a dir, keep the 77285f0379aSDavid Teigland rsb's we're the master of. Recovery will add them to the root list and from 77385f0379aSDavid Teigland there they'll be entered in the rebuilt directory. */ 77485f0379aSDavid Teigland 775e7fd4179SDavid Teigland void dlm_clear_toss_list(struct dlm_ls *ls) 776e7fd4179SDavid Teigland { 777*9beb3bf5SBob Peterson struct rb_node *n, *next; 778*9beb3bf5SBob Peterson struct dlm_rsb *rsb; 779e7fd4179SDavid Teigland int i; 780e7fd4179SDavid Teigland 781e7fd4179SDavid Teigland for (i = 0; i < ls->ls_rsbtbl_size; i++) { 782c7be761aSDavid Teigland spin_lock(&ls->ls_rsbtbl[i].lock); 783*9beb3bf5SBob Peterson for (n = rb_first(&ls->ls_rsbtbl[i].toss); n; n = next) { 784*9beb3bf5SBob Peterson next = rb_next(n);; 785*9beb3bf5SBob Peterson rsb = rb_entry(n, struct dlm_rsb, res_hashnode); 786*9beb3bf5SBob Peterson if (dlm_no_directory(ls) || !is_master(rsb)) { 787*9beb3bf5SBob Peterson rb_erase(n, &ls->ls_rsbtbl[i].toss); 788*9beb3bf5SBob Peterson dlm_free_rsb(rsb); 789e7fd4179SDavid Teigland } 79085f0379aSDavid Teigland } 791c7be761aSDavid Teigland spin_unlock(&ls->ls_rsbtbl[i].lock); 792e7fd4179SDavid Teigland } 793e7fd4179SDavid Teigland } 794e7fd4179SDavid Teigland 795