xref: /linux/fs/dlm/recover.c (revision 9beb3bf5a92bb8fc6503f844bf0772df29f14a02)
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