blob: 2661674364af8e6187ca86b14c0d3e39a1f8db00 [file] [log] [blame]
Thomas Gleixner2522fe42019-05-28 09:57:20 -07001// SPDX-License-Identifier: GPL-2.0-only
David Teiglande7fd4172006-01-18 09:30:29 +00002/******************************************************************************
3*******************************************************************************
4**
5** Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved.
David Teiglanddbcfc342008-01-29 14:52:10 -06006** Copyright (C) 2005-2008 Red Hat, Inc. All rights reserved.
David Teiglande7fd4172006-01-18 09:30:29 +00007**
David Teiglande7fd4172006-01-18 09:30:29 +00008**
9*******************************************************************************
10******************************************************************************/
11
12#include "dlm_internal.h"
13#include "lockspace.h"
14#include "member.h"
15#include "lowcomms.h"
16#include "midcomms.h"
17#include "rcom.h"
18#include "recover.h"
19#include "dir.h"
20#include "config.h"
21#include "memory.h"
22#include "lock.h"
23#include "util.h"
David Teiglande7fd4172006-01-18 09:30:29 +000024
25static int rcom_response(struct dlm_ls *ls)
26{
27 return test_bit(LSFL_RCOM_READY, &ls->ls_flags);
28}
29
Alexander Aringa070a912021-05-21 15:08:41 -040030static void _create_rcom(struct dlm_ls *ls, int to_nodeid, int type, int len,
31 struct dlm_rcom **rc_ret, char *mb, int mb_len)
David Teiglande7fd4172006-01-18 09:30:29 +000032{
33 struct dlm_rcom *rc;
David Teiglande7fd4172006-01-18 09:30:29 +000034
35 rc = (struct dlm_rcom *) mb;
36
37 rc->rc_header.h_version = (DLM_HEADER_MAJOR | DLM_HEADER_MINOR);
38 rc->rc_header.h_lockspace = ls->ls_global_id;
39 rc->rc_header.h_nodeid = dlm_our_nodeid();
40 rc->rc_header.h_length = mb_len;
41 rc->rc_header.h_cmd = DLM_RCOM;
42
43 rc->rc_type = type;
44
David Teigland38aa8b02006-12-13 10:37:16 -060045 spin_lock(&ls->ls_recover_lock);
46 rc->rc_seq = ls->ls_recover_seq;
47 spin_unlock(&ls->ls_recover_lock);
48
David Teiglande7fd4172006-01-18 09:30:29 +000049 *rc_ret = rc;
Alexander Aringa070a912021-05-21 15:08:41 -040050}
51
52static int create_rcom(struct dlm_ls *ls, int to_nodeid, int type, int len,
53 struct dlm_rcom **rc_ret, struct dlm_mhandle **mh_ret)
54{
55 int mb_len = sizeof(struct dlm_rcom) + len;
56 struct dlm_mhandle *mh;
57 char *mb;
58
59 mh = dlm_midcomms_get_mhandle(to_nodeid, mb_len, GFP_NOFS, &mb);
60 if (!mh) {
61 log_print("%s to %d type %d len %d ENOBUFS",
62 __func__, to_nodeid, type, len);
63 return -ENOBUFS;
64 }
65
66 _create_rcom(ls, to_nodeid, type, len, rc_ret, mb, mb_len);
67 *mh_ret = mh;
David Teiglande7fd4172006-01-18 09:30:29 +000068 return 0;
69}
70
Alexander Aringa070a912021-05-21 15:08:41 -040071static int create_rcom_stateless(struct dlm_ls *ls, int to_nodeid, int type,
72 int len, struct dlm_rcom **rc_ret,
73 void **mh_ret)
74{
75 int mb_len = sizeof(struct dlm_rcom) + len;
76 void *mh;
77 char *mb;
78
79 mh = dlm_lowcomms_get_buffer(to_nodeid, mb_len, GFP_NOFS, &mb);
80 if (!mh) {
81 log_print("create_rcom to %d type %d len %d ENOBUFS",
82 to_nodeid, type, len);
83 return -ENOBUFS;
84 }
85
86 _create_rcom(ls, to_nodeid, type, len, rc_ret, mb, mb_len);
87 *mh_ret = mh;
88 return 0;
89}
90
91static void _send_rcom(struct dlm_ls *ls, struct dlm_rcom *rc)
92{
93 dlm_rcom_out(rc);
94}
95
David Teiglande7fd4172006-01-18 09:30:29 +000096static void send_rcom(struct dlm_ls *ls, struct dlm_mhandle *mh,
97 struct dlm_rcom *rc)
98{
Alexander Aringa070a912021-05-21 15:08:41 -040099 _send_rcom(ls, rc);
100 dlm_midcomms_commit_mhandle(mh);
101}
102
103static void send_rcom_stateless(struct dlm_ls *ls, void *mh,
104 struct dlm_rcom *rc)
105{
106 _send_rcom(ls, rc);
David Teiglande7fd4172006-01-18 09:30:29 +0000107 dlm_lowcomms_commit_buffer(mh);
108}
109
David Teigland757a4272011-10-20 13:26:28 -0500110static void set_rcom_status(struct dlm_ls *ls, struct rcom_status *rs,
111 uint32_t flags)
112{
113 rs->rs_flags = cpu_to_le32(flags);
114}
115
David Teiglande7fd4172006-01-18 09:30:29 +0000116/* When replying to a status request, a node also sends back its
117 configuration values. The requesting node then checks that the remote
118 node is configured the same way as itself. */
119
David Teigland757a4272011-10-20 13:26:28 -0500120static void set_rcom_config(struct dlm_ls *ls, struct rcom_config *rf,
121 uint32_t num_slots)
David Teiglande7fd4172006-01-18 09:30:29 +0000122{
Al Viro93ff2972008-01-25 02:34:00 -0500123 rf->rf_lvblen = cpu_to_le32(ls->ls_lvblen);
124 rf->rf_lsflags = cpu_to_le32(ls->ls_exflags);
David Teigland757a4272011-10-20 13:26:28 -0500125
126 rf->rf_our_slot = cpu_to_le16(ls->ls_slot);
127 rf->rf_num_slots = cpu_to_le16(num_slots);
128 rf->rf_generation = cpu_to_le32(ls->ls_generation);
David Teiglande7fd4172006-01-18 09:30:29 +0000129}
130
David Teigland757a4272011-10-20 13:26:28 -0500131static int check_rcom_config(struct dlm_ls *ls, struct dlm_rcom *rc, int nodeid)
David Teiglande7fd4172006-01-18 09:30:29 +0000132{
David Teigland9e971b72006-12-13 10:37:55 -0600133 struct rcom_config *rf = (struct rcom_config *) rc->rc_buf;
134
135 if ((rc->rc_header.h_version & 0xFFFF0000) != DLM_HEADER_MAJOR) {
136 log_error(ls, "version mismatch: %x nodeid %d: %x",
137 DLM_HEADER_MAJOR | DLM_HEADER_MINOR, nodeid,
138 rc->rc_header.h_version);
David Teigland8b0e7b22007-05-18 09:03:35 -0500139 return -EPROTO;
David Teigland9e971b72006-12-13 10:37:55 -0600140 }
141
Al Viro93ff2972008-01-25 02:34:00 -0500142 if (le32_to_cpu(rf->rf_lvblen) != ls->ls_lvblen ||
143 le32_to_cpu(rf->rf_lsflags) != ls->ls_exflags) {
David Teiglande7fd4172006-01-18 09:30:29 +0000144 log_error(ls, "config mismatch: %d,%x nodeid %d: %d,%x",
Al Viro93ff2972008-01-25 02:34:00 -0500145 ls->ls_lvblen, ls->ls_exflags, nodeid,
146 le32_to_cpu(rf->rf_lvblen),
147 le32_to_cpu(rf->rf_lsflags));
David Teigland8b0e7b22007-05-18 09:03:35 -0500148 return -EPROTO;
David Teiglande7fd4172006-01-18 09:30:29 +0000149 }
150 return 0;
151}
152
David Teigland98f176f2006-11-27 13:19:28 -0600153static void allow_sync_reply(struct dlm_ls *ls, uint64_t *new_seq)
154{
155 spin_lock(&ls->ls_rcom_spin);
156 *new_seq = ++ls->ls_rcom_seq;
157 set_bit(LSFL_RCOM_WAIT, &ls->ls_flags);
158 spin_unlock(&ls->ls_rcom_spin);
159}
160
161static void disallow_sync_reply(struct dlm_ls *ls)
162{
163 spin_lock(&ls->ls_rcom_spin);
164 clear_bit(LSFL_RCOM_WAIT, &ls->ls_flags);
165 clear_bit(LSFL_RCOM_READY, &ls->ls_flags);
166 spin_unlock(&ls->ls_rcom_spin);
167}
168
David Teigland757a4272011-10-20 13:26:28 -0500169/*
170 * low nodeid gathers one slot value at a time from each node.
171 * it sets need_slots=0, and saves rf_our_slot returned from each
172 * rcom_config.
173 *
174 * other nodes gather all slot values at once from the low nodeid.
175 * they set need_slots=1, and ignore the rf_our_slot returned from each
176 * rcom_config. they use the rf_num_slots returned from the low
177 * node's rcom_config.
178 */
179
180int dlm_rcom_status(struct dlm_ls *ls, int nodeid, uint32_t status_flags)
David Teiglande7fd4172006-01-18 09:30:29 +0000181{
182 struct dlm_rcom *rc;
David Teiglande7fd4172006-01-18 09:30:29 +0000183 int error = 0;
Alexander Aringa070a912021-05-21 15:08:41 -0400184 void *mh;
David Teiglande7fd4172006-01-18 09:30:29 +0000185
David Teiglandfaa0f262006-08-08 17:08:42 -0500186 ls->ls_recover_nodeid = nodeid;
David Teiglande7fd4172006-01-18 09:30:29 +0000187
188 if (nodeid == dlm_our_nodeid()) {
Al Viro40076852008-01-25 03:01:51 -0500189 rc = ls->ls_recover_buf;
David Teiglande7fd4172006-01-18 09:30:29 +0000190 rc->rc_result = dlm_recover_status(ls);
191 goto out;
192 }
193
tsutomu.owa@toshiba.co.jp59661212017-09-12 08:56:08 +0000194retry:
Alexander Aringa070a912021-05-21 15:08:41 -0400195 error = create_rcom_stateless(ls, nodeid, DLM_RCOM_STATUS,
196 sizeof(struct rcom_status), &rc, &mh);
David Teiglande7fd4172006-01-18 09:30:29 +0000197 if (error)
198 goto out;
David Teigland98f176f2006-11-27 13:19:28 -0600199
David Teigland757a4272011-10-20 13:26:28 -0500200 set_rcom_status(ls, (struct rcom_status *)rc->rc_buf, status_flags);
201
David Teigland98f176f2006-11-27 13:19:28 -0600202 allow_sync_reply(ls, &rc->rc_id);
Alexander Aring9f8f9c72020-11-02 20:04:17 -0500203 memset(ls->ls_recover_buf, 0, LOWCOMMS_MAX_TX_BUFFER_LEN);
David Teiglande7fd4172006-01-18 09:30:29 +0000204
Alexander Aringa070a912021-05-21 15:08:41 -0400205 send_rcom_stateless(ls, mh, rc);
David Teiglande7fd4172006-01-18 09:30:29 +0000206
207 error = dlm_wait_function(ls, &rcom_response);
David Teigland98f176f2006-11-27 13:19:28 -0600208 disallow_sync_reply(ls);
tsutomu.owa@toshiba.co.jp59661212017-09-12 08:56:08 +0000209 if (error == -ETIMEDOUT)
210 goto retry;
David Teiglande7fd4172006-01-18 09:30:29 +0000211 if (error)
212 goto out;
213
Al Viro40076852008-01-25 03:01:51 -0500214 rc = ls->ls_recover_buf;
David Teiglande7fd4172006-01-18 09:30:29 +0000215
216 if (rc->rc_result == -ESRCH) {
217 /* we pretend the remote lockspace exists with 0 status */
218 log_debug(ls, "remote node %d not ready", nodeid);
219 rc->rc_result = 0;
David Teigland757a4272011-10-20 13:26:28 -0500220 error = 0;
221 } else {
222 error = check_rcom_config(ls, rc, nodeid);
223 }
224
David Teiglande7fd4172006-01-18 09:30:29 +0000225 /* the caller looks at rc_result for the remote recovery status */
226 out:
227 return error;
228}
229
230static void receive_rcom_status(struct dlm_ls *ls, struct dlm_rcom *rc_in)
231{
232 struct dlm_rcom *rc;
David Teigland757a4272011-10-20 13:26:28 -0500233 struct rcom_status *rs;
234 uint32_t status;
235 int nodeid = rc_in->rc_header.h_nodeid;
236 int len = sizeof(struct rcom_config);
237 int num_slots = 0;
238 int error;
Alexander Aringa070a912021-05-21 15:08:41 -0400239 void *mh;
David Teiglande7fd4172006-01-18 09:30:29 +0000240
David Teigland757a4272011-10-20 13:26:28 -0500241 if (!dlm_slots_version(&rc_in->rc_header)) {
242 status = dlm_recover_status(ls);
243 goto do_create;
244 }
245
246 rs = (struct rcom_status *)rc_in->rc_buf;
247
Neale Fergusonc07127b2014-10-14 15:10:48 -0500248 if (!(le32_to_cpu(rs->rs_flags) & DLM_RSF_NEED_SLOTS)) {
David Teigland757a4272011-10-20 13:26:28 -0500249 status = dlm_recover_status(ls);
250 goto do_create;
251 }
252
253 spin_lock(&ls->ls_recover_lock);
254 status = ls->ls_recover_status;
255 num_slots = ls->ls_num_slots;
256 spin_unlock(&ls->ls_recover_lock);
257 len += num_slots * sizeof(struct rcom_slot);
258
259 do_create:
Alexander Aringa070a912021-05-21 15:08:41 -0400260 error = create_rcom_stateless(ls, nodeid, DLM_RCOM_STATUS_REPLY,
261 len, &rc, &mh);
David Teiglande7fd4172006-01-18 09:30:29 +0000262 if (error)
263 return;
David Teigland757a4272011-10-20 13:26:28 -0500264
David Teigland4a99c3d2006-08-09 11:20:15 -0500265 rc->rc_id = rc_in->rc_id;
David Teigland38aa8b02006-12-13 10:37:16 -0600266 rc->rc_seq_reply = rc_in->rc_seq;
David Teigland757a4272011-10-20 13:26:28 -0500267 rc->rc_result = status;
David Teiglande7fd4172006-01-18 09:30:29 +0000268
David Teigland757a4272011-10-20 13:26:28 -0500269 set_rcom_config(ls, (struct rcom_config *)rc->rc_buf, num_slots);
270
271 if (!num_slots)
272 goto do_send;
273
274 spin_lock(&ls->ls_recover_lock);
275 if (ls->ls_num_slots != num_slots) {
276 spin_unlock(&ls->ls_recover_lock);
277 log_debug(ls, "receive_rcom_status num_slots %d to %d",
278 num_slots, ls->ls_num_slots);
279 rc->rc_result = 0;
280 set_rcom_config(ls, (struct rcom_config *)rc->rc_buf, 0);
281 goto do_send;
282 }
283
284 dlm_slots_copy_out(ls, rc);
285 spin_unlock(&ls->ls_recover_lock);
286
287 do_send:
Alexander Aringa070a912021-05-21 15:08:41 -0400288 send_rcom_stateless(ls, mh, rc);
David Teiglande7fd4172006-01-18 09:30:29 +0000289}
290
David Teigland4a99c3d2006-08-09 11:20:15 -0500291static void receive_sync_reply(struct dlm_ls *ls, struct dlm_rcom *rc_in)
David Teiglande7fd4172006-01-18 09:30:29 +0000292{
David Teigland98f176f2006-11-27 13:19:28 -0600293 spin_lock(&ls->ls_rcom_spin);
294 if (!test_bit(LSFL_RCOM_WAIT, &ls->ls_flags) ||
295 rc_in->rc_id != ls->ls_rcom_seq) {
296 log_debug(ls, "reject reply %d from %d seq %llx expect %llx",
297 rc_in->rc_type, rc_in->rc_header.h_nodeid,
Ryusuke Konishi57adf7e2006-11-29 09:33:48 -0500298 (unsigned long long)rc_in->rc_id,
299 (unsigned long long)ls->ls_rcom_seq);
David Teigland98f176f2006-11-27 13:19:28 -0600300 goto out;
David Teigland4a99c3d2006-08-09 11:20:15 -0500301 }
David Teiglande7fd4172006-01-18 09:30:29 +0000302 memcpy(ls->ls_recover_buf, rc_in, rc_in->rc_header.h_length);
303 set_bit(LSFL_RCOM_READY, &ls->ls_flags);
David Teigland98f176f2006-11-27 13:19:28 -0600304 clear_bit(LSFL_RCOM_WAIT, &ls->ls_flags);
David Teiglande7fd4172006-01-18 09:30:29 +0000305 wake_up(&ls->ls_wait_general);
David Teigland98f176f2006-11-27 13:19:28 -0600306 out:
307 spin_unlock(&ls->ls_rcom_spin);
David Teiglande7fd4172006-01-18 09:30:29 +0000308}
309
310int dlm_rcom_names(struct dlm_ls *ls, int nodeid, char *last_name, int last_len)
311{
312 struct dlm_rcom *rc;
Al Viro40076852008-01-25 03:01:51 -0500313 int error = 0;
Alexander Aringa070a912021-05-21 15:08:41 -0400314 void *mh;
David Teiglande7fd4172006-01-18 09:30:29 +0000315
David Teiglandfaa0f262006-08-08 17:08:42 -0500316 ls->ls_recover_nodeid = nodeid;
David Teiglande7fd4172006-01-18 09:30:29 +0000317
tsutomu.owa@toshiba.co.jp59661212017-09-12 08:56:08 +0000318retry:
Alexander Aringa070a912021-05-21 15:08:41 -0400319 error = create_rcom_stateless(ls, nodeid, DLM_RCOM_NAMES, last_len,
320 &rc, &mh);
David Teiglande7fd4172006-01-18 09:30:29 +0000321 if (error)
322 goto out;
323 memcpy(rc->rc_buf, last_name, last_len);
David Teigland98f176f2006-11-27 13:19:28 -0600324
325 allow_sync_reply(ls, &rc->rc_id);
Alexander Aring9f8f9c72020-11-02 20:04:17 -0500326 memset(ls->ls_recover_buf, 0, LOWCOMMS_MAX_TX_BUFFER_LEN);
David Teiglande7fd4172006-01-18 09:30:29 +0000327
Alexander Aringa070a912021-05-21 15:08:41 -0400328 send_rcom_stateless(ls, mh, rc);
David Teiglande7fd4172006-01-18 09:30:29 +0000329
330 error = dlm_wait_function(ls, &rcom_response);
David Teigland98f176f2006-11-27 13:19:28 -0600331 disallow_sync_reply(ls);
tsutomu.owa@toshiba.co.jp59661212017-09-12 08:56:08 +0000332 if (error == -ETIMEDOUT)
333 goto retry;
David Teiglande7fd4172006-01-18 09:30:29 +0000334 out:
335 return error;
336}
337
338static void receive_rcom_names(struct dlm_ls *ls, struct dlm_rcom *rc_in)
339{
340 struct dlm_rcom *rc;
David Teigland38aa8b02006-12-13 10:37:16 -0600341 int error, inlen, outlen, nodeid;
Alexander Aringa070a912021-05-21 15:08:41 -0400342 void *mh;
David Teiglande7fd4172006-01-18 09:30:29 +0000343
344 nodeid = rc_in->rc_header.h_nodeid;
345 inlen = rc_in->rc_header.h_length - sizeof(struct dlm_rcom);
Alexander Aring9f8f9c72020-11-02 20:04:17 -0500346 outlen = LOWCOMMS_MAX_TX_BUFFER_LEN - sizeof(struct dlm_rcom);
David Teiglande7fd4172006-01-18 09:30:29 +0000347
Alexander Aringa070a912021-05-21 15:08:41 -0400348 error = create_rcom_stateless(ls, nodeid, DLM_RCOM_NAMES_REPLY, outlen,
349 &rc, &mh);
David Teiglande7fd4172006-01-18 09:30:29 +0000350 if (error)
351 return;
David Teigland4a99c3d2006-08-09 11:20:15 -0500352 rc->rc_id = rc_in->rc_id;
David Teigland38aa8b02006-12-13 10:37:16 -0600353 rc->rc_seq_reply = rc_in->rc_seq;
David Teiglande7fd4172006-01-18 09:30:29 +0000354
355 dlm_copy_master_names(ls, rc_in->rc_buf, inlen, rc->rc_buf, outlen,
356 nodeid);
Alexander Aringa070a912021-05-21 15:08:41 -0400357 send_rcom_stateless(ls, mh, rc);
David Teiglande7fd4172006-01-18 09:30:29 +0000358}
359
David Teiglande7fd4172006-01-18 09:30:29 +0000360int dlm_send_rcom_lookup(struct dlm_rsb *r, int dir_nodeid)
361{
362 struct dlm_rcom *rc;
363 struct dlm_mhandle *mh;
364 struct dlm_ls *ls = r->res_ls;
365 int error;
366
367 error = create_rcom(ls, dir_nodeid, DLM_RCOM_LOOKUP, r->res_length,
368 &rc, &mh);
369 if (error)
370 goto out;
371 memcpy(rc->rc_buf, r->res_name, r->res_length);
David Teigland1d7c4842012-05-15 16:07:49 -0500372 rc->rc_id = (unsigned long) r->res_id;
David Teiglande7fd4172006-01-18 09:30:29 +0000373
374 send_rcom(ls, mh, rc);
375 out:
376 return error;
377}
378
379static void receive_rcom_lookup(struct dlm_ls *ls, struct dlm_rcom *rc_in)
380{
381 struct dlm_rcom *rc;
382 struct dlm_mhandle *mh;
383 int error, ret_nodeid, nodeid = rc_in->rc_header.h_nodeid;
384 int len = rc_in->rc_header.h_length - sizeof(struct dlm_rcom);
385
386 error = create_rcom(ls, nodeid, DLM_RCOM_LOOKUP_REPLY, 0, &rc, &mh);
387 if (error)
388 return;
389
David Teigland9250e522017-10-09 09:29:31 -0500390 /* Old code would send this special id to trigger a debug dump. */
David Teiglandc04fecb2012-05-10 10:18:07 -0500391 if (rc_in->rc_id == 0xFFFFFFFF) {
392 log_error(ls, "receive_rcom_lookup dump from %d", nodeid);
393 dlm_dump_rsb_name(ls, rc_in->rc_buf, len);
394 return;
395 }
396
397 error = dlm_master_lookup(ls, nodeid, rc_in->rc_buf, len,
398 DLM_LU_RECOVER_MASTER, &ret_nodeid, NULL);
David Teiglande7fd4172006-01-18 09:30:29 +0000399 if (error)
400 ret_nodeid = error;
401 rc->rc_result = ret_nodeid;
402 rc->rc_id = rc_in->rc_id;
David Teigland38aa8b02006-12-13 10:37:16 -0600403 rc->rc_seq_reply = rc_in->rc_seq;
David Teiglande7fd4172006-01-18 09:30:29 +0000404
405 send_rcom(ls, mh, rc);
406}
407
408static void receive_rcom_lookup_reply(struct dlm_ls *ls, struct dlm_rcom *rc_in)
409{
410 dlm_recover_master_reply(ls, rc_in);
411}
412
413static void pack_rcom_lock(struct dlm_rsb *r, struct dlm_lkb *lkb,
414 struct rcom_lock *rl)
415{
416 memset(rl, 0, sizeof(*rl));
417
Al Viro163a1852008-01-25 02:08:26 -0500418 rl->rl_ownpid = cpu_to_le32(lkb->lkb_ownpid);
419 rl->rl_lkid = cpu_to_le32(lkb->lkb_id);
420 rl->rl_exflags = cpu_to_le32(lkb->lkb_exflags);
421 rl->rl_flags = cpu_to_le32(lkb->lkb_flags);
422 rl->rl_lvbseq = cpu_to_le32(lkb->lkb_lvbseq);
David Teiglande7fd4172006-01-18 09:30:29 +0000423 rl->rl_rqmode = lkb->lkb_rqmode;
424 rl->rl_grmode = lkb->lkb_grmode;
425 rl->rl_status = lkb->lkb_status;
Al Viro163a1852008-01-25 02:08:26 -0500426 rl->rl_wait_type = cpu_to_le16(lkb->lkb_wait_type);
David Teiglande7fd4172006-01-18 09:30:29 +0000427
David Teiglande5dae542008-02-06 00:35:45 -0600428 if (lkb->lkb_bastfn)
David Teigland8304d6f2011-02-21 14:58:21 -0600429 rl->rl_asts |= DLM_CB_BAST;
David Teiglande5dae542008-02-06 00:35:45 -0600430 if (lkb->lkb_astfn)
David Teigland8304d6f2011-02-21 14:58:21 -0600431 rl->rl_asts |= DLM_CB_CAST;
David Teiglande7fd4172006-01-18 09:30:29 +0000432
Al Viro163a1852008-01-25 02:08:26 -0500433 rl->rl_namelen = cpu_to_le16(r->res_length);
David Teiglande7fd4172006-01-18 09:30:29 +0000434 memcpy(rl->rl_name, r->res_name, r->res_length);
435
436 /* FIXME: might we have an lvb without DLM_LKF_VALBLK set ?
437 If so, receive_rcom_lock_args() won't take this copy. */
438
439 if (lkb->lkb_lvbptr)
440 memcpy(rl->rl_lvb, lkb->lkb_lvbptr, r->res_ls->ls_lvblen);
441}
442
443int dlm_send_rcom_lock(struct dlm_rsb *r, struct dlm_lkb *lkb)
444{
445 struct dlm_ls *ls = r->res_ls;
446 struct dlm_rcom *rc;
447 struct dlm_mhandle *mh;
448 struct rcom_lock *rl;
449 int error, len = sizeof(struct rcom_lock);
450
451 if (lkb->lkb_lvbptr)
452 len += ls->ls_lvblen;
453
454 error = create_rcom(ls, r->res_nodeid, DLM_RCOM_LOCK, len, &rc, &mh);
455 if (error)
456 goto out;
457
458 rl = (struct rcom_lock *) rc->rc_buf;
459 pack_rcom_lock(r, lkb, rl);
460 rc->rc_id = (unsigned long) r;
461
462 send_rcom(ls, mh, rc);
463 out:
464 return error;
465}
466
Al Viroae773d02008-01-25 19:55:09 -0500467/* needs at least dlm_rcom + rcom_lock */
David Teiglande7fd4172006-01-18 09:30:29 +0000468static void receive_rcom_lock(struct dlm_ls *ls, struct dlm_rcom *rc_in)
469{
470 struct dlm_rcom *rc;
471 struct dlm_mhandle *mh;
472 int error, nodeid = rc_in->rc_header.h_nodeid;
473
474 dlm_recover_master_copy(ls, rc_in);
475
476 error = create_rcom(ls, nodeid, DLM_RCOM_LOCK_REPLY,
477 sizeof(struct rcom_lock), &rc, &mh);
478 if (error)
479 return;
480
481 /* We send back the same rcom_lock struct we received, but
482 dlm_recover_master_copy() has filled in rl_remid and rl_result */
483
484 memcpy(rc->rc_buf, rc_in->rc_buf, sizeof(struct rcom_lock));
485 rc->rc_id = rc_in->rc_id;
David Teigland38aa8b02006-12-13 10:37:16 -0600486 rc->rc_seq_reply = rc_in->rc_seq;
David Teiglande7fd4172006-01-18 09:30:29 +0000487
488 send_rcom(ls, mh, rc);
489}
490
David Teiglandc36258b2007-09-27 15:53:38 -0500491/* If the lockspace doesn't exist then still send a status message
492 back; it's possible that it just doesn't have its global_id yet. */
493
494int dlm_send_ls_not_ready(int nodeid, struct dlm_rcom *rc_in)
David Teiglande7fd4172006-01-18 09:30:29 +0000495{
496 struct dlm_rcom *rc;
David Teigland1babdb42006-11-27 13:18:41 -0600497 struct rcom_config *rf;
David Teiglande7fd4172006-01-18 09:30:29 +0000498 struct dlm_mhandle *mh;
499 char *mb;
David Teigland1babdb42006-11-27 13:18:41 -0600500 int mb_len = sizeof(struct dlm_rcom) + sizeof(struct rcom_config);
David Teiglande7fd4172006-01-18 09:30:29 +0000501
Alexander Aringa070a912021-05-21 15:08:41 -0400502 mh = dlm_midcomms_get_mhandle(nodeid, mb_len, GFP_NOFS, &mb);
David Teiglande7fd4172006-01-18 09:30:29 +0000503 if (!mh)
504 return -ENOBUFS;
David Teiglande7fd4172006-01-18 09:30:29 +0000505
506 rc = (struct dlm_rcom *) mb;
507
508 rc->rc_header.h_version = (DLM_HEADER_MAJOR | DLM_HEADER_MINOR);
509 rc->rc_header.h_lockspace = rc_in->rc_header.h_lockspace;
510 rc->rc_header.h_nodeid = dlm_our_nodeid();
511 rc->rc_header.h_length = mb_len;
512 rc->rc_header.h_cmd = DLM_RCOM;
513
514 rc->rc_type = DLM_RCOM_STATUS_REPLY;
David Teiglandf5888752006-08-23 12:50:54 -0500515 rc->rc_id = rc_in->rc_id;
David Teigland38aa8b02006-12-13 10:37:16 -0600516 rc->rc_seq_reply = rc_in->rc_seq;
David Teiglande7fd4172006-01-18 09:30:29 +0000517 rc->rc_result = -ESRCH;
518
David Teigland1babdb42006-11-27 13:18:41 -0600519 rf = (struct rcom_config *) rc->rc_buf;
Al Viro93ff2972008-01-25 02:34:00 -0500520 rf->rf_lvblen = cpu_to_le32(~0U);
David Teigland1babdb42006-11-27 13:18:41 -0600521
David Teiglande7fd4172006-01-18 09:30:29 +0000522 dlm_rcom_out(rc);
Alexander Aringa070a912021-05-21 15:08:41 -0400523 dlm_midcomms_commit_mhandle(mh);
David Teiglande7fd4172006-01-18 09:30:29 +0000524
525 return 0;
526}
527
David Teiglandc04fecb2012-05-10 10:18:07 -0500528/*
529 * Ignore messages for stage Y before we set
530 * recover_status bit for stage X:
531 *
532 * recover_status = 0
533 *
534 * dlm_recover_members()
535 * - send nothing
536 * - recv nothing
537 * - ignore NAMES, NAMES_REPLY
538 * - ignore LOOKUP, LOOKUP_REPLY
539 * - ignore LOCK, LOCK_REPLY
540 *
541 * recover_status |= NODES
542 *
543 * dlm_recover_members_wait()
544 *
545 * dlm_recover_directory()
546 * - send NAMES
547 * - recv NAMES_REPLY
548 * - ignore LOOKUP, LOOKUP_REPLY
549 * - ignore LOCK, LOCK_REPLY
550 *
551 * recover_status |= DIR
552 *
553 * dlm_recover_directory_wait()
554 *
555 * dlm_recover_masters()
556 * - send LOOKUP
557 * - recv LOOKUP_REPLY
558 *
559 * dlm_recover_locks()
560 * - send LOCKS
561 * - recv LOCKS_REPLY
562 *
563 * recover_status |= LOCKS
564 *
565 * dlm_recover_locks_wait()
566 *
567 * recover_status |= DONE
568 */
569
David Teiglandc36258b2007-09-27 15:53:38 -0500570/* Called by dlm_recv; corresponds to dlm_receive_message() but special
David Teiglande7fd4172006-01-18 09:30:29 +0000571 recovery-only comms are sent through here. */
572
David Teiglandc36258b2007-09-27 15:53:38 -0500573void dlm_receive_rcom(struct dlm_ls *ls, struct dlm_rcom *rc, int nodeid)
David Teiglande7fd4172006-01-18 09:30:29 +0000574{
Al Viroae773d02008-01-25 19:55:09 -0500575 int lock_size = sizeof(struct dlm_rcom) + sizeof(struct rcom_lock);
David Teiglandc04fecb2012-05-10 10:18:07 -0500576 int stop, reply = 0, names = 0, lookup = 0, lock = 0;
David Teigland48756472012-04-26 15:54:29 -0500577 uint32_t status;
David Teiglandd6e24782012-04-23 13:58:42 -0500578 uint64_t seq;
Al Viroae773d02008-01-25 19:55:09 -0500579
David Teiglandd6e24782012-04-23 13:58:42 -0500580 switch (rc->rc_type) {
David Teiglandc04fecb2012-05-10 10:18:07 -0500581 case DLM_RCOM_STATUS_REPLY:
582 reply = 1;
583 break;
584 case DLM_RCOM_NAMES:
585 names = 1;
586 break;
587 case DLM_RCOM_NAMES_REPLY:
588 names = 1;
589 reply = 1;
590 break;
591 case DLM_RCOM_LOOKUP:
592 lookup = 1;
593 break;
594 case DLM_RCOM_LOOKUP_REPLY:
595 lookup = 1;
596 reply = 1;
597 break;
David Teigland48756472012-04-26 15:54:29 -0500598 case DLM_RCOM_LOCK:
599 lock = 1;
600 break;
601 case DLM_RCOM_LOCK_REPLY:
602 lock = 1;
603 reply = 1;
604 break;
Wu Bo90db4f82020-04-22 14:59:27 +0800605 }
David Teiglandd6e24782012-04-23 13:58:42 -0500606
607 spin_lock(&ls->ls_recover_lock);
David Teigland48756472012-04-26 15:54:29 -0500608 status = ls->ls_recover_status;
David Teigland475f2302012-08-02 11:08:21 -0500609 stop = test_bit(LSFL_RECOVER_STOP, &ls->ls_flags);
David Teiglandd6e24782012-04-23 13:58:42 -0500610 seq = ls->ls_recover_seq;
611 spin_unlock(&ls->ls_recover_lock);
612
David Teiglandc04fecb2012-05-10 10:18:07 -0500613 if (stop && (rc->rc_type != DLM_RCOM_STATUS))
614 goto ignore;
615
616 if (reply && (rc->rc_seq_reply != seq))
617 goto ignore;
618
619 if (!(status & DLM_RS_NODES) && (names || lookup || lock))
620 goto ignore;
621
622 if (!(status & DLM_RS_DIR) && (lookup || lock))
623 goto ignore;
David Teiglande7fd4172006-01-18 09:30:29 +0000624
David Teiglande7fd4172006-01-18 09:30:29 +0000625 switch (rc->rc_type) {
626 case DLM_RCOM_STATUS:
627 receive_rcom_status(ls, rc);
628 break;
629
630 case DLM_RCOM_NAMES:
631 receive_rcom_names(ls, rc);
632 break;
633
634 case DLM_RCOM_LOOKUP:
635 receive_rcom_lookup(ls, rc);
636 break;
637
638 case DLM_RCOM_LOCK:
Al Viroae773d02008-01-25 19:55:09 -0500639 if (rc->rc_header.h_length < lock_size)
640 goto Eshort;
David Teiglande7fd4172006-01-18 09:30:29 +0000641 receive_rcom_lock(ls, rc);
642 break;
643
644 case DLM_RCOM_STATUS_REPLY:
David Teiglanddbcfc342008-01-29 14:52:10 -0600645 receive_sync_reply(ls, rc);
David Teiglande7fd4172006-01-18 09:30:29 +0000646 break;
647
648 case DLM_RCOM_NAMES_REPLY:
David Teiglanddbcfc342008-01-29 14:52:10 -0600649 receive_sync_reply(ls, rc);
David Teiglande7fd4172006-01-18 09:30:29 +0000650 break;
651
652 case DLM_RCOM_LOOKUP_REPLY:
653 receive_rcom_lookup_reply(ls, rc);
654 break;
655
656 case DLM_RCOM_LOCK_REPLY:
Al Viroae773d02008-01-25 19:55:09 -0500657 if (rc->rc_header.h_length < lock_size)
658 goto Eshort;
David Teiglanddbcfc342008-01-29 14:52:10 -0600659 dlm_recover_process_copy(ls, rc);
David Teiglande7fd4172006-01-18 09:30:29 +0000660 break;
661
662 default:
David Teiglanddbcfc342008-01-29 14:52:10 -0600663 log_error(ls, "receive_rcom bad type %d", rc->rc_type);
David Teiglande7fd4172006-01-18 09:30:29 +0000664 }
David Teiglandc04fecb2012-05-10 10:18:07 -0500665 return;
666
667ignore:
668 log_limit(ls, "dlm_receive_rcom ignore msg %d "
669 "from %d %llu %llu recover seq %llu sts %x gen %u",
670 rc->rc_type,
671 nodeid,
672 (unsigned long long)rc->rc_seq,
673 (unsigned long long)rc->rc_seq_reply,
674 (unsigned long long)seq,
675 status, ls->ls_generation);
David Teiglandc36258b2007-09-27 15:53:38 -0500676 return;
Al Viroae773d02008-01-25 19:55:09 -0500677Eshort:
David Teiglandc04fecb2012-05-10 10:18:07 -0500678 log_error(ls, "recovery message %d from %d is too short",
679 rc->rc_type, nodeid);
David Teiglande7fd4172006-01-18 09:30:29 +0000680}
681