xref: /linux/fs/dlm/requestqueue.c (revision 2896ee37ccc1f9acb244c9b02becb74a43661009)
1e7fd4179SDavid Teigland /******************************************************************************
2e7fd4179SDavid Teigland *******************************************************************************
3e7fd4179SDavid Teigland **
4e7fd4179SDavid Teigland **  Copyright (C) 2005 Red Hat, Inc.  All rights reserved.
5e7fd4179SDavid Teigland **
6e7fd4179SDavid Teigland **  This copyrighted material is made available to anyone wishing to use,
7e7fd4179SDavid Teigland **  modify, copy, or redistribute it subject to the terms and conditions
8e7fd4179SDavid Teigland **  of the GNU General Public License v.2.
9e7fd4179SDavid Teigland **
10e7fd4179SDavid Teigland *******************************************************************************
11e7fd4179SDavid Teigland ******************************************************************************/
12e7fd4179SDavid Teigland 
13e7fd4179SDavid Teigland #include "dlm_internal.h"
14e7fd4179SDavid Teigland #include "member.h"
15e7fd4179SDavid Teigland #include "lock.h"
16e7fd4179SDavid Teigland #include "dir.h"
17e7fd4179SDavid Teigland #include "config.h"
18e7fd4179SDavid Teigland #include "requestqueue.h"
19e7fd4179SDavid Teigland 
20e7fd4179SDavid Teigland struct rq_entry {
21e7fd4179SDavid Teigland 	struct list_head list;
22e7fd4179SDavid Teigland 	int nodeid;
23e7fd4179SDavid Teigland 	char request[1];
24e7fd4179SDavid Teigland };
25e7fd4179SDavid Teigland 
26e7fd4179SDavid Teigland /*
27e7fd4179SDavid Teigland  * Requests received while the lockspace is in recovery get added to the
28e7fd4179SDavid Teigland  * request queue and processed when recovery is complete.  This happens when
29e7fd4179SDavid Teigland  * the lockspace is suspended on some nodes before it is on others, or the
30e7fd4179SDavid Teigland  * lockspace is enabled on some while still suspended on others.
31e7fd4179SDavid Teigland  */
32e7fd4179SDavid Teigland 
33d4400156SDavid Teigland int dlm_add_requestqueue(struct dlm_ls *ls, int nodeid, struct dlm_header *hd)
34e7fd4179SDavid Teigland {
35e7fd4179SDavid Teigland 	struct rq_entry *e;
36e7fd4179SDavid Teigland 	int length = hd->h_length;
37d4400156SDavid Teigland 	int rv = 0;
38e7fd4179SDavid Teigland 
39e7fd4179SDavid Teigland 	e = kmalloc(sizeof(struct rq_entry) + length, GFP_KERNEL);
40e7fd4179SDavid Teigland 	if (!e) {
41e7fd4179SDavid Teigland 		log_print("dlm_add_requestqueue: out of memory\n");
42d4400156SDavid Teigland 		return 0;
43e7fd4179SDavid Teigland 	}
44e7fd4179SDavid Teigland 
45e7fd4179SDavid Teigland 	e->nodeid = nodeid;
46e7fd4179SDavid Teigland 	memcpy(e->request, hd, length);
47e7fd4179SDavid Teigland 
48d4400156SDavid Teigland 	/* We need to check dlm_locking_stopped() after taking the mutex to
49d4400156SDavid Teigland 	   avoid a race where dlm_recoverd enables locking and runs
50d4400156SDavid Teigland 	   process_requestqueue between our earlier dlm_locking_stopped check
51d4400156SDavid Teigland 	   and this addition to the requestqueue. */
52d4400156SDavid Teigland 
5390135925SDavid Teigland 	mutex_lock(&ls->ls_requestqueue_mutex);
54d4400156SDavid Teigland 	if (dlm_locking_stopped(ls))
55e7fd4179SDavid Teigland 		list_add_tail(&e->list, &ls->ls_requestqueue);
56d4400156SDavid Teigland 	else {
57d4400156SDavid Teigland 		log_debug(ls, "dlm_add_requestqueue skip from %d", nodeid);
58d4400156SDavid Teigland 		kfree(e);
59d4400156SDavid Teigland 		rv = -EAGAIN;
60d4400156SDavid Teigland 	}
6190135925SDavid Teigland 	mutex_unlock(&ls->ls_requestqueue_mutex);
62d4400156SDavid Teigland 	return rv;
63e7fd4179SDavid Teigland }
64e7fd4179SDavid Teigland 
65e7fd4179SDavid Teigland int dlm_process_requestqueue(struct dlm_ls *ls)
66e7fd4179SDavid Teigland {
67e7fd4179SDavid Teigland 	struct rq_entry *e;
68e7fd4179SDavid Teigland 	struct dlm_header *hd;
69e7fd4179SDavid Teigland 	int error = 0;
70e7fd4179SDavid Teigland 
7190135925SDavid Teigland 	mutex_lock(&ls->ls_requestqueue_mutex);
72e7fd4179SDavid Teigland 
73e7fd4179SDavid Teigland 	for (;;) {
74e7fd4179SDavid Teigland 		if (list_empty(&ls->ls_requestqueue)) {
7590135925SDavid Teigland 			mutex_unlock(&ls->ls_requestqueue_mutex);
76e7fd4179SDavid Teigland 			error = 0;
77e7fd4179SDavid Teigland 			break;
78e7fd4179SDavid Teigland 		}
79e7fd4179SDavid Teigland 		e = list_entry(ls->ls_requestqueue.next, struct rq_entry, list);
8090135925SDavid Teigland 		mutex_unlock(&ls->ls_requestqueue_mutex);
81e7fd4179SDavid Teigland 
82e7fd4179SDavid Teigland 		hd = (struct dlm_header *) e->request;
8390135925SDavid Teigland 		error = dlm_receive_message(hd, e->nodeid, 1);
84e7fd4179SDavid Teigland 
85e7fd4179SDavid Teigland 		if (error == -EINTR) {
86e7fd4179SDavid Teigland 			/* entry is left on requestqueue */
87e7fd4179SDavid Teigland 			log_debug(ls, "process_requestqueue abort eintr");
88e7fd4179SDavid Teigland 			break;
89e7fd4179SDavid Teigland 		}
90e7fd4179SDavid Teigland 
9190135925SDavid Teigland 		mutex_lock(&ls->ls_requestqueue_mutex);
92e7fd4179SDavid Teigland 		list_del(&e->list);
93e7fd4179SDavid Teigland 		kfree(e);
94e7fd4179SDavid Teigland 
95e7fd4179SDavid Teigland 		if (dlm_locking_stopped(ls)) {
96e7fd4179SDavid Teigland 			log_debug(ls, "process_requestqueue abort running");
9790135925SDavid Teigland 			mutex_unlock(&ls->ls_requestqueue_mutex);
98e7fd4179SDavid Teigland 			error = -EINTR;
99e7fd4179SDavid Teigland 			break;
100e7fd4179SDavid Teigland 		}
101e7fd4179SDavid Teigland 		schedule();
102e7fd4179SDavid Teigland 	}
103e7fd4179SDavid Teigland 
104e7fd4179SDavid Teigland 	return error;
105e7fd4179SDavid Teigland }
106e7fd4179SDavid Teigland 
107e7fd4179SDavid Teigland /*
108e7fd4179SDavid Teigland  * After recovery is done, locking is resumed and dlm_recoverd takes all the
109e7fd4179SDavid Teigland  * saved requests and processes them as they would have been by dlm_recvd.  At
110e7fd4179SDavid Teigland  * the same time, dlm_recvd will start receiving new requests from remote
111e7fd4179SDavid Teigland  * nodes.  We want to delay dlm_recvd processing new requests until
112e7fd4179SDavid Teigland  * dlm_recoverd has finished processing the old saved requests.
113e7fd4179SDavid Teigland  */
114e7fd4179SDavid Teigland 
115e7fd4179SDavid Teigland void dlm_wait_requestqueue(struct dlm_ls *ls)
116e7fd4179SDavid Teigland {
117e7fd4179SDavid Teigland 	for (;;) {
11890135925SDavid Teigland 		mutex_lock(&ls->ls_requestqueue_mutex);
119e7fd4179SDavid Teigland 		if (list_empty(&ls->ls_requestqueue))
120e7fd4179SDavid Teigland 			break;
121e7fd4179SDavid Teigland 		if (dlm_locking_stopped(ls))
122e7fd4179SDavid Teigland 			break;
12390135925SDavid Teigland 		mutex_unlock(&ls->ls_requestqueue_mutex);
124e7fd4179SDavid Teigland 		schedule();
125e7fd4179SDavid Teigland 	}
12690135925SDavid Teigland 	mutex_unlock(&ls->ls_requestqueue_mutex);
127e7fd4179SDavid Teigland }
128e7fd4179SDavid Teigland 
129e7fd4179SDavid Teigland static int purge_request(struct dlm_ls *ls, struct dlm_message *ms, int nodeid)
130e7fd4179SDavid Teigland {
131e7fd4179SDavid Teigland 	uint32_t type = ms->m_type;
132e7fd4179SDavid Teigland 
133*2896ee37SDavid Teigland 	/* the ls is being cleaned up and freed by release_lockspace */
134*2896ee37SDavid Teigland 	if (!ls->ls_count)
135*2896ee37SDavid Teigland 		return 1;
136*2896ee37SDavid Teigland 
137e7fd4179SDavid Teigland 	if (dlm_is_removed(ls, nodeid))
138e7fd4179SDavid Teigland 		return 1;
139e7fd4179SDavid Teigland 
140e7fd4179SDavid Teigland 	/* directory operations are always purged because the directory is
141e7fd4179SDavid Teigland 	   always rebuilt during recovery and the lookups resent */
142e7fd4179SDavid Teigland 
143e7fd4179SDavid Teigland 	if (type == DLM_MSG_REMOVE ||
144e7fd4179SDavid Teigland 	    type == DLM_MSG_LOOKUP ||
145e7fd4179SDavid Teigland 	    type == DLM_MSG_LOOKUP_REPLY)
146e7fd4179SDavid Teigland 		return 1;
147e7fd4179SDavid Teigland 
148e7fd4179SDavid Teigland 	if (!dlm_no_directory(ls))
149e7fd4179SDavid Teigland 		return 0;
150e7fd4179SDavid Teigland 
151e7fd4179SDavid Teigland 	/* with no directory, the master is likely to change as a part of
152e7fd4179SDavid Teigland 	   recovery; requests to/from the defunct master need to be purged */
153e7fd4179SDavid Teigland 
154e7fd4179SDavid Teigland 	switch (type) {
155e7fd4179SDavid Teigland 	case DLM_MSG_REQUEST:
156e7fd4179SDavid Teigland 	case DLM_MSG_CONVERT:
157e7fd4179SDavid Teigland 	case DLM_MSG_UNLOCK:
158e7fd4179SDavid Teigland 	case DLM_MSG_CANCEL:
159e7fd4179SDavid Teigland 		/* we're no longer the master of this resource, the sender
160e7fd4179SDavid Teigland 		   will resend to the new master (see waiter_needs_recovery) */
161e7fd4179SDavid Teigland 
162e7fd4179SDavid Teigland 		if (dlm_hash2nodeid(ls, ms->m_hash) != dlm_our_nodeid())
163e7fd4179SDavid Teigland 			return 1;
164e7fd4179SDavid Teigland 		break;
165e7fd4179SDavid Teigland 
166e7fd4179SDavid Teigland 	case DLM_MSG_REQUEST_REPLY:
167e7fd4179SDavid Teigland 	case DLM_MSG_CONVERT_REPLY:
168e7fd4179SDavid Teigland 	case DLM_MSG_UNLOCK_REPLY:
169e7fd4179SDavid Teigland 	case DLM_MSG_CANCEL_REPLY:
170e7fd4179SDavid Teigland 	case DLM_MSG_GRANT:
171e7fd4179SDavid Teigland 		/* this reply is from the former master of the resource,
172e7fd4179SDavid Teigland 		   we'll resend to the new master if needed */
173e7fd4179SDavid Teigland 
174e7fd4179SDavid Teigland 		if (dlm_hash2nodeid(ls, ms->m_hash) != nodeid)
175e7fd4179SDavid Teigland 			return 1;
176e7fd4179SDavid Teigland 		break;
177e7fd4179SDavid Teigland 	}
178e7fd4179SDavid Teigland 
179e7fd4179SDavid Teigland 	return 0;
180e7fd4179SDavid Teigland }
181e7fd4179SDavid Teigland 
182e7fd4179SDavid Teigland void dlm_purge_requestqueue(struct dlm_ls *ls)
183e7fd4179SDavid Teigland {
184e7fd4179SDavid Teigland 	struct dlm_message *ms;
185e7fd4179SDavid Teigland 	struct rq_entry *e, *safe;
186e7fd4179SDavid Teigland 
18790135925SDavid Teigland 	mutex_lock(&ls->ls_requestqueue_mutex);
188e7fd4179SDavid Teigland 	list_for_each_entry_safe(e, safe, &ls->ls_requestqueue, list) {
189e7fd4179SDavid Teigland 		ms = (struct dlm_message *) e->request;
190e7fd4179SDavid Teigland 
191e7fd4179SDavid Teigland 		if (purge_request(ls, ms, e->nodeid)) {
192e7fd4179SDavid Teigland 			list_del(&e->list);
193e7fd4179SDavid Teigland 			kfree(e);
194e7fd4179SDavid Teigland 		}
195e7fd4179SDavid Teigland 	}
19690135925SDavid Teigland 	mutex_unlock(&ls->ls_requestqueue_mutex);
197e7fd4179SDavid Teigland }
198e7fd4179SDavid Teigland 
199