2019-05-28 16:57:20 +00:00
|
|
|
// SPDX-License-Identifier: GPL-2.0-only
|
2006-01-18 09:30:29 +00:00
|
|
|
/******************************************************************************
|
|
|
|
*******************************************************************************
|
|
|
|
**
|
|
|
|
** Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved.
|
2008-01-29 20:52:10 +00:00
|
|
|
** Copyright (C) 2005-2008 Red Hat, Inc. All rights reserved.
|
2006-01-18 09:30:29 +00:00
|
|
|
**
|
|
|
|
**
|
|
|
|
*******************************************************************************
|
|
|
|
******************************************************************************/
|
|
|
|
|
|
|
|
#include "dlm_internal.h"
|
|
|
|
#include "lockspace.h"
|
|
|
|
#include "member.h"
|
|
|
|
#include "lowcomms.h"
|
|
|
|
#include "midcomms.h"
|
|
|
|
#include "rcom.h"
|
|
|
|
#include "recover.h"
|
|
|
|
#include "dir.h"
|
|
|
|
#include "config.h"
|
|
|
|
#include "memory.h"
|
|
|
|
#include "lock.h"
|
|
|
|
#include "util.h"
|
|
|
|
|
|
|
|
static int rcom_response(struct dlm_ls *ls)
|
|
|
|
{
|
|
|
|
return test_bit(LSFL_RCOM_READY, &ls->ls_flags);
|
|
|
|
}
|
|
|
|
|
2021-05-21 19:08:41 +00:00
|
|
|
static void _create_rcom(struct dlm_ls *ls, int to_nodeid, int type, int len,
|
2023-08-01 18:09:45 +00:00
|
|
|
struct dlm_rcom **rc_ret, char *mb, int mb_len,
|
|
|
|
uint64_t seq)
|
2006-01-18 09:30:29 +00:00
|
|
|
{
|
|
|
|
struct dlm_rcom *rc;
|
|
|
|
|
|
|
|
rc = (struct dlm_rcom *) mb;
|
|
|
|
|
2022-04-04 20:06:39 +00:00
|
|
|
rc->rc_header.h_version = cpu_to_le32(DLM_HEADER_MAJOR | DLM_HEADER_MINOR);
|
|
|
|
rc->rc_header.u.h_lockspace = cpu_to_le32(ls->ls_global_id);
|
|
|
|
rc->rc_header.h_nodeid = cpu_to_le32(dlm_our_nodeid());
|
|
|
|
rc->rc_header.h_length = cpu_to_le16(mb_len);
|
2006-01-18 09:30:29 +00:00
|
|
|
rc->rc_header.h_cmd = DLM_RCOM;
|
|
|
|
|
2022-04-04 20:06:40 +00:00
|
|
|
rc->rc_type = cpu_to_le32(type);
|
2023-08-01 18:09:45 +00:00
|
|
|
rc->rc_seq = cpu_to_le64(seq);
|
2006-12-13 16:37:16 +00:00
|
|
|
|
2006-01-18 09:30:29 +00:00
|
|
|
*rc_ret = rc;
|
2021-05-21 19:08:41 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static int create_rcom(struct dlm_ls *ls, int to_nodeid, int type, int len,
|
2023-08-01 18:09:45 +00:00
|
|
|
struct dlm_rcom **rc_ret, struct dlm_mhandle **mh_ret,
|
|
|
|
uint64_t seq)
|
2021-05-21 19:08:41 +00:00
|
|
|
{
|
|
|
|
int mb_len = sizeof(struct dlm_rcom) + len;
|
|
|
|
struct dlm_mhandle *mh;
|
|
|
|
char *mb;
|
|
|
|
|
|
|
|
mh = dlm_midcomms_get_mhandle(to_nodeid, mb_len, GFP_NOFS, &mb);
|
|
|
|
if (!mh) {
|
|
|
|
log_print("%s to %d type %d len %d ENOBUFS",
|
|
|
|
__func__, to_nodeid, type, len);
|
|
|
|
return -ENOBUFS;
|
|
|
|
}
|
|
|
|
|
2023-08-01 18:09:45 +00:00
|
|
|
_create_rcom(ls, to_nodeid, type, len, rc_ret, mb, mb_len, seq);
|
2021-05-21 19:08:41 +00:00
|
|
|
*mh_ret = mh;
|
2006-01-18 09:30:29 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2021-05-21 19:08:41 +00:00
|
|
|
static int create_rcom_stateless(struct dlm_ls *ls, int to_nodeid, int type,
|
|
|
|
int len, struct dlm_rcom **rc_ret,
|
2023-08-01 18:09:45 +00:00
|
|
|
struct dlm_msg **msg_ret, uint64_t seq)
|
2021-05-21 19:08:41 +00:00
|
|
|
{
|
|
|
|
int mb_len = sizeof(struct dlm_rcom) + len;
|
2021-05-21 19:08:42 +00:00
|
|
|
struct dlm_msg *msg;
|
2021-05-21 19:08:41 +00:00
|
|
|
char *mb;
|
|
|
|
|
2021-05-21 19:08:42 +00:00
|
|
|
msg = dlm_lowcomms_new_msg(to_nodeid, mb_len, GFP_NOFS, &mb,
|
|
|
|
NULL, NULL);
|
|
|
|
if (!msg) {
|
2021-05-21 19:08:41 +00:00
|
|
|
log_print("create_rcom to %d type %d len %d ENOBUFS",
|
|
|
|
to_nodeid, type, len);
|
|
|
|
return -ENOBUFS;
|
|
|
|
}
|
|
|
|
|
2023-08-01 18:09:45 +00:00
|
|
|
_create_rcom(ls, to_nodeid, type, len, rc_ret, mb, mb_len, seq);
|
2021-05-21 19:08:42 +00:00
|
|
|
*msg_ret = msg;
|
2021-05-21 19:08:41 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2021-07-16 20:22:38 +00:00
|
|
|
static void send_rcom(struct dlm_mhandle *mh, struct dlm_rcom *rc)
|
2021-05-21 19:08:41 +00:00
|
|
|
{
|
2022-10-27 20:45:15 +00:00
|
|
|
dlm_midcomms_commit_mhandle(mh, NULL, 0);
|
2021-05-21 19:08:41 +00:00
|
|
|
}
|
|
|
|
|
2021-07-16 20:22:38 +00:00
|
|
|
static void send_rcom_stateless(struct dlm_msg *msg, struct dlm_rcom *rc)
|
2021-05-21 19:08:41 +00:00
|
|
|
{
|
2021-05-21 19:08:42 +00:00
|
|
|
dlm_lowcomms_commit_msg(msg);
|
|
|
|
dlm_lowcomms_put_msg(msg);
|
2006-01-18 09:30:29 +00:00
|
|
|
}
|
|
|
|
|
2011-10-20 18:26:28 +00:00
|
|
|
static void set_rcom_status(struct dlm_ls *ls, struct rcom_status *rs,
|
|
|
|
uint32_t flags)
|
|
|
|
{
|
|
|
|
rs->rs_flags = cpu_to_le32(flags);
|
|
|
|
}
|
|
|
|
|
2006-01-18 09:30:29 +00:00
|
|
|
/* When replying to a status request, a node also sends back its
|
|
|
|
configuration values. The requesting node then checks that the remote
|
|
|
|
node is configured the same way as itself. */
|
|
|
|
|
2011-10-20 18:26:28 +00:00
|
|
|
static void set_rcom_config(struct dlm_ls *ls, struct rcom_config *rf,
|
|
|
|
uint32_t num_slots)
|
2006-01-18 09:30:29 +00:00
|
|
|
{
|
2008-01-25 07:34:00 +00:00
|
|
|
rf->rf_lvblen = cpu_to_le32(ls->ls_lvblen);
|
|
|
|
rf->rf_lsflags = cpu_to_le32(ls->ls_exflags);
|
2011-10-20 18:26:28 +00:00
|
|
|
|
|
|
|
rf->rf_our_slot = cpu_to_le16(ls->ls_slot);
|
|
|
|
rf->rf_num_slots = cpu_to_le16(num_slots);
|
|
|
|
rf->rf_generation = cpu_to_le32(ls->ls_generation);
|
2006-01-18 09:30:29 +00:00
|
|
|
}
|
|
|
|
|
2011-10-20 18:26:28 +00:00
|
|
|
static int check_rcom_config(struct dlm_ls *ls, struct dlm_rcom *rc, int nodeid)
|
2006-01-18 09:30:29 +00:00
|
|
|
{
|
2006-12-13 16:37:55 +00:00
|
|
|
struct rcom_config *rf = (struct rcom_config *) rc->rc_buf;
|
|
|
|
|
2022-04-04 20:06:39 +00:00
|
|
|
if ((le32_to_cpu(rc->rc_header.h_version) & 0xFFFF0000) != DLM_HEADER_MAJOR) {
|
2006-12-13 16:37:55 +00:00
|
|
|
log_error(ls, "version mismatch: %x nodeid %d: %x",
|
|
|
|
DLM_HEADER_MAJOR | DLM_HEADER_MINOR, nodeid,
|
2022-04-04 20:06:39 +00:00
|
|
|
le32_to_cpu(rc->rc_header.h_version));
|
2007-05-18 14:03:35 +00:00
|
|
|
return -EPROTO;
|
2006-12-13 16:37:55 +00:00
|
|
|
}
|
|
|
|
|
2008-01-25 07:34:00 +00:00
|
|
|
if (le32_to_cpu(rf->rf_lvblen) != ls->ls_lvblen ||
|
|
|
|
le32_to_cpu(rf->rf_lsflags) != ls->ls_exflags) {
|
2006-01-18 09:30:29 +00:00
|
|
|
log_error(ls, "config mismatch: %d,%x nodeid %d: %d,%x",
|
2008-01-25 07:34:00 +00:00
|
|
|
ls->ls_lvblen, ls->ls_exflags, nodeid,
|
|
|
|
le32_to_cpu(rf->rf_lvblen),
|
|
|
|
le32_to_cpu(rf->rf_lsflags));
|
2007-05-18 14:03:35 +00:00
|
|
|
return -EPROTO;
|
2006-01-18 09:30:29 +00:00
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2022-04-04 20:06:40 +00:00
|
|
|
static void allow_sync_reply(struct dlm_ls *ls, __le64 *new_seq)
|
2006-11-27 19:19:28 +00:00
|
|
|
{
|
|
|
|
spin_lock(&ls->ls_rcom_spin);
|
2022-04-04 20:06:40 +00:00
|
|
|
*new_seq = cpu_to_le64(++ls->ls_rcom_seq);
|
2006-11-27 19:19:28 +00:00
|
|
|
set_bit(LSFL_RCOM_WAIT, &ls->ls_flags);
|
|
|
|
spin_unlock(&ls->ls_rcom_spin);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void disallow_sync_reply(struct dlm_ls *ls)
|
|
|
|
{
|
|
|
|
spin_lock(&ls->ls_rcom_spin);
|
|
|
|
clear_bit(LSFL_RCOM_WAIT, &ls->ls_flags);
|
|
|
|
clear_bit(LSFL_RCOM_READY, &ls->ls_flags);
|
|
|
|
spin_unlock(&ls->ls_rcom_spin);
|
|
|
|
}
|
|
|
|
|
2011-10-20 18:26:28 +00:00
|
|
|
/*
|
|
|
|
* low nodeid gathers one slot value at a time from each node.
|
|
|
|
* it sets need_slots=0, and saves rf_our_slot returned from each
|
|
|
|
* rcom_config.
|
|
|
|
*
|
|
|
|
* other nodes gather all slot values at once from the low nodeid.
|
|
|
|
* they set need_slots=1, and ignore the rf_our_slot returned from each
|
|
|
|
* rcom_config. they use the rf_num_slots returned from the low
|
|
|
|
* node's rcom_config.
|
|
|
|
*/
|
|
|
|
|
2023-08-01 18:09:45 +00:00
|
|
|
int dlm_rcom_status(struct dlm_ls *ls, int nodeid, uint32_t status_flags,
|
|
|
|
uint64_t seq)
|
2006-01-18 09:30:29 +00:00
|
|
|
{
|
|
|
|
struct dlm_rcom *rc;
|
2021-05-21 19:08:42 +00:00
|
|
|
struct dlm_msg *msg;
|
2006-01-18 09:30:29 +00:00
|
|
|
int error = 0;
|
|
|
|
|
2006-08-08 22:08:42 +00:00
|
|
|
ls->ls_recover_nodeid = nodeid;
|
2006-01-18 09:30:29 +00:00
|
|
|
|
|
|
|
if (nodeid == dlm_our_nodeid()) {
|
2008-01-25 08:01:51 +00:00
|
|
|
rc = ls->ls_recover_buf;
|
2022-04-04 20:06:40 +00:00
|
|
|
rc->rc_result = cpu_to_le32(dlm_recover_status(ls));
|
2006-01-18 09:30:29 +00:00
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
|
2017-09-12 08:56:08 +00:00
|
|
|
retry:
|
2021-05-21 19:08:41 +00:00
|
|
|
error = create_rcom_stateless(ls, nodeid, DLM_RCOM_STATUS,
|
2023-08-01 18:09:45 +00:00
|
|
|
sizeof(struct rcom_status), &rc, &msg,
|
|
|
|
seq);
|
2006-01-18 09:30:29 +00:00
|
|
|
if (error)
|
|
|
|
goto out;
|
2006-11-27 19:19:28 +00:00
|
|
|
|
2011-10-20 18:26:28 +00:00
|
|
|
set_rcom_status(ls, (struct rcom_status *)rc->rc_buf, status_flags);
|
|
|
|
|
2006-11-27 19:19:28 +00:00
|
|
|
allow_sync_reply(ls, &rc->rc_id);
|
2021-06-02 13:45:20 +00:00
|
|
|
memset(ls->ls_recover_buf, 0, DLM_MAX_SOCKET_BUFSIZE);
|
2006-01-18 09:30:29 +00:00
|
|
|
|
2021-07-16 20:22:38 +00:00
|
|
|
send_rcom_stateless(msg, rc);
|
2006-01-18 09:30:29 +00:00
|
|
|
|
|
|
|
error = dlm_wait_function(ls, &rcom_response);
|
2006-11-27 19:19:28 +00:00
|
|
|
disallow_sync_reply(ls);
|
2017-09-12 08:56:08 +00:00
|
|
|
if (error == -ETIMEDOUT)
|
|
|
|
goto retry;
|
2006-01-18 09:30:29 +00:00
|
|
|
if (error)
|
|
|
|
goto out;
|
|
|
|
|
2008-01-25 08:01:51 +00:00
|
|
|
rc = ls->ls_recover_buf;
|
2006-01-18 09:30:29 +00:00
|
|
|
|
2022-04-04 20:06:40 +00:00
|
|
|
if (rc->rc_result == cpu_to_le32(-ESRCH)) {
|
2006-01-18 09:30:29 +00:00
|
|
|
/* we pretend the remote lockspace exists with 0 status */
|
|
|
|
log_debug(ls, "remote node %d not ready", nodeid);
|
|
|
|
rc->rc_result = 0;
|
2011-10-20 18:26:28 +00:00
|
|
|
error = 0;
|
|
|
|
} else {
|
|
|
|
error = check_rcom_config(ls, rc, nodeid);
|
|
|
|
}
|
|
|
|
|
2006-01-18 09:30:29 +00:00
|
|
|
/* the caller looks at rc_result for the remote recovery status */
|
|
|
|
out:
|
|
|
|
return error;
|
|
|
|
}
|
|
|
|
|
2023-08-01 18:09:45 +00:00
|
|
|
static void receive_rcom_status(struct dlm_ls *ls, struct dlm_rcom *rc_in,
|
|
|
|
uint64_t seq)
|
2006-01-18 09:30:29 +00:00
|
|
|
{
|
|
|
|
struct dlm_rcom *rc;
|
2011-10-20 18:26:28 +00:00
|
|
|
struct rcom_status *rs;
|
|
|
|
uint32_t status;
|
2022-04-04 20:06:39 +00:00
|
|
|
int nodeid = le32_to_cpu(rc_in->rc_header.h_nodeid);
|
2011-10-20 18:26:28 +00:00
|
|
|
int len = sizeof(struct rcom_config);
|
2021-05-21 19:08:42 +00:00
|
|
|
struct dlm_msg *msg;
|
2011-10-20 18:26:28 +00:00
|
|
|
int num_slots = 0;
|
|
|
|
int error;
|
|
|
|
|
|
|
|
if (!dlm_slots_version(&rc_in->rc_header)) {
|
|
|
|
status = dlm_recover_status(ls);
|
|
|
|
goto do_create;
|
|
|
|
}
|
|
|
|
|
|
|
|
rs = (struct rcom_status *)rc_in->rc_buf;
|
2006-01-18 09:30:29 +00:00
|
|
|
|
2014-10-14 20:10:48 +00:00
|
|
|
if (!(le32_to_cpu(rs->rs_flags) & DLM_RSF_NEED_SLOTS)) {
|
2011-10-20 18:26:28 +00:00
|
|
|
status = dlm_recover_status(ls);
|
|
|
|
goto do_create;
|
|
|
|
}
|
|
|
|
|
|
|
|
spin_lock(&ls->ls_recover_lock);
|
|
|
|
status = ls->ls_recover_status;
|
|
|
|
num_slots = ls->ls_num_slots;
|
|
|
|
spin_unlock(&ls->ls_recover_lock);
|
|
|
|
len += num_slots * sizeof(struct rcom_slot);
|
|
|
|
|
|
|
|
do_create:
|
2021-05-21 19:08:41 +00:00
|
|
|
error = create_rcom_stateless(ls, nodeid, DLM_RCOM_STATUS_REPLY,
|
2023-08-01 18:09:45 +00:00
|
|
|
len, &rc, &msg, seq);
|
2006-01-18 09:30:29 +00:00
|
|
|
if (error)
|
|
|
|
return;
|
2011-10-20 18:26:28 +00:00
|
|
|
|
2006-08-09 16:20:15 +00:00
|
|
|
rc->rc_id = rc_in->rc_id;
|
2006-12-13 16:37:16 +00:00
|
|
|
rc->rc_seq_reply = rc_in->rc_seq;
|
2022-04-04 20:06:40 +00:00
|
|
|
rc->rc_result = cpu_to_le32(status);
|
2011-10-20 18:26:28 +00:00
|
|
|
|
|
|
|
set_rcom_config(ls, (struct rcom_config *)rc->rc_buf, num_slots);
|
|
|
|
|
|
|
|
if (!num_slots)
|
|
|
|
goto do_send;
|
|
|
|
|
|
|
|
spin_lock(&ls->ls_recover_lock);
|
|
|
|
if (ls->ls_num_slots != num_slots) {
|
|
|
|
spin_unlock(&ls->ls_recover_lock);
|
|
|
|
log_debug(ls, "receive_rcom_status num_slots %d to %d",
|
|
|
|
num_slots, ls->ls_num_slots);
|
|
|
|
rc->rc_result = 0;
|
|
|
|
set_rcom_config(ls, (struct rcom_config *)rc->rc_buf, 0);
|
|
|
|
goto do_send;
|
|
|
|
}
|
|
|
|
|
|
|
|
dlm_slots_copy_out(ls, rc);
|
|
|
|
spin_unlock(&ls->ls_recover_lock);
|
2006-01-18 09:30:29 +00:00
|
|
|
|
2011-10-20 18:26:28 +00:00
|
|
|
do_send:
|
2021-07-16 20:22:38 +00:00
|
|
|
send_rcom_stateless(msg, rc);
|
2006-01-18 09:30:29 +00:00
|
|
|
}
|
|
|
|
|
2006-08-09 16:20:15 +00:00
|
|
|
static void receive_sync_reply(struct dlm_ls *ls, struct dlm_rcom *rc_in)
|
2006-01-18 09:30:29 +00:00
|
|
|
{
|
2006-11-27 19:19:28 +00:00
|
|
|
spin_lock(&ls->ls_rcom_spin);
|
|
|
|
if (!test_bit(LSFL_RCOM_WAIT, &ls->ls_flags) ||
|
2022-04-04 20:06:40 +00:00
|
|
|
le64_to_cpu(rc_in->rc_id) != ls->ls_rcom_seq) {
|
2006-11-27 19:19:28 +00:00
|
|
|
log_debug(ls, "reject reply %d from %d seq %llx expect %llx",
|
2022-04-04 20:06:40 +00:00
|
|
|
le32_to_cpu(rc_in->rc_type),
|
2022-04-04 20:06:39 +00:00
|
|
|
le32_to_cpu(rc_in->rc_header.h_nodeid),
|
2022-04-04 20:06:40 +00:00
|
|
|
(unsigned long long)le64_to_cpu(rc_in->rc_id),
|
2006-11-29 14:33:48 +00:00
|
|
|
(unsigned long long)ls->ls_rcom_seq);
|
2006-11-27 19:19:28 +00:00
|
|
|
goto out;
|
2006-08-09 16:20:15 +00:00
|
|
|
}
|
2022-04-04 20:06:39 +00:00
|
|
|
memcpy(ls->ls_recover_buf, rc_in,
|
|
|
|
le16_to_cpu(rc_in->rc_header.h_length));
|
2006-01-18 09:30:29 +00:00
|
|
|
set_bit(LSFL_RCOM_READY, &ls->ls_flags);
|
2006-11-27 19:19:28 +00:00
|
|
|
clear_bit(LSFL_RCOM_WAIT, &ls->ls_flags);
|
2006-01-18 09:30:29 +00:00
|
|
|
wake_up(&ls->ls_wait_general);
|
2006-11-27 19:19:28 +00:00
|
|
|
out:
|
|
|
|
spin_unlock(&ls->ls_rcom_spin);
|
2006-01-18 09:30:29 +00:00
|
|
|
}
|
|
|
|
|
2023-08-01 18:09:45 +00:00
|
|
|
int dlm_rcom_names(struct dlm_ls *ls, int nodeid, char *last_name,
|
|
|
|
int last_len, uint64_t seq)
|
2006-01-18 09:30:29 +00:00
|
|
|
{
|
|
|
|
struct dlm_rcom *rc;
|
2021-05-21 19:08:42 +00:00
|
|
|
struct dlm_msg *msg;
|
2008-01-25 08:01:51 +00:00
|
|
|
int error = 0;
|
2006-01-18 09:30:29 +00:00
|
|
|
|
2006-08-08 22:08:42 +00:00
|
|
|
ls->ls_recover_nodeid = nodeid;
|
2006-01-18 09:30:29 +00:00
|
|
|
|
2017-09-12 08:56:08 +00:00
|
|
|
retry:
|
2021-05-21 19:08:41 +00:00
|
|
|
error = create_rcom_stateless(ls, nodeid, DLM_RCOM_NAMES, last_len,
|
2023-08-01 18:09:45 +00:00
|
|
|
&rc, &msg, seq);
|
2006-01-18 09:30:29 +00:00
|
|
|
if (error)
|
|
|
|
goto out;
|
|
|
|
memcpy(rc->rc_buf, last_name, last_len);
|
2006-11-27 19:19:28 +00:00
|
|
|
|
|
|
|
allow_sync_reply(ls, &rc->rc_id);
|
2021-06-02 13:45:20 +00:00
|
|
|
memset(ls->ls_recover_buf, 0, DLM_MAX_SOCKET_BUFSIZE);
|
2006-01-18 09:30:29 +00:00
|
|
|
|
2021-07-16 20:22:38 +00:00
|
|
|
send_rcom_stateless(msg, rc);
|
2006-01-18 09:30:29 +00:00
|
|
|
|
|
|
|
error = dlm_wait_function(ls, &rcom_response);
|
2006-11-27 19:19:28 +00:00
|
|
|
disallow_sync_reply(ls);
|
2017-09-12 08:56:08 +00:00
|
|
|
if (error == -ETIMEDOUT)
|
|
|
|
goto retry;
|
2006-01-18 09:30:29 +00:00
|
|
|
out:
|
|
|
|
return error;
|
|
|
|
}
|
|
|
|
|
2023-08-01 18:09:45 +00:00
|
|
|
static void receive_rcom_names(struct dlm_ls *ls, struct dlm_rcom *rc_in,
|
|
|
|
uint64_t seq)
|
2006-01-18 09:30:29 +00:00
|
|
|
{
|
|
|
|
struct dlm_rcom *rc;
|
2006-12-13 16:37:16 +00:00
|
|
|
int error, inlen, outlen, nodeid;
|
2021-05-21 19:08:42 +00:00
|
|
|
struct dlm_msg *msg;
|
2006-01-18 09:30:29 +00:00
|
|
|
|
2022-04-04 20:06:39 +00:00
|
|
|
nodeid = le32_to_cpu(rc_in->rc_header.h_nodeid);
|
|
|
|
inlen = le16_to_cpu(rc_in->rc_header.h_length) -
|
|
|
|
sizeof(struct dlm_rcom);
|
2021-06-02 13:45:20 +00:00
|
|
|
outlen = DLM_MAX_APP_BUFSIZE - sizeof(struct dlm_rcom);
|
2006-01-18 09:30:29 +00:00
|
|
|
|
2021-05-21 19:08:41 +00:00
|
|
|
error = create_rcom_stateless(ls, nodeid, DLM_RCOM_NAMES_REPLY, outlen,
|
2023-08-01 18:09:45 +00:00
|
|
|
&rc, &msg, seq);
|
2006-01-18 09:30:29 +00:00
|
|
|
if (error)
|
|
|
|
return;
|
2006-08-09 16:20:15 +00:00
|
|
|
rc->rc_id = rc_in->rc_id;
|
2006-12-13 16:37:16 +00:00
|
|
|
rc->rc_seq_reply = rc_in->rc_seq;
|
2006-01-18 09:30:29 +00:00
|
|
|
|
|
|
|
dlm_copy_master_names(ls, rc_in->rc_buf, inlen, rc->rc_buf, outlen,
|
|
|
|
nodeid);
|
2021-07-16 20:22:38 +00:00
|
|
|
send_rcom_stateless(msg, rc);
|
2006-01-18 09:30:29 +00:00
|
|
|
}
|
|
|
|
|
2023-08-01 18:09:45 +00:00
|
|
|
int dlm_send_rcom_lookup(struct dlm_rsb *r, int dir_nodeid, uint64_t seq)
|
2006-01-18 09:30:29 +00:00
|
|
|
{
|
|
|
|
struct dlm_rcom *rc;
|
|
|
|
struct dlm_mhandle *mh;
|
|
|
|
struct dlm_ls *ls = r->res_ls;
|
|
|
|
int error;
|
|
|
|
|
|
|
|
error = create_rcom(ls, dir_nodeid, DLM_RCOM_LOOKUP, r->res_length,
|
2023-08-01 18:09:45 +00:00
|
|
|
&rc, &mh, seq);
|
2006-01-18 09:30:29 +00:00
|
|
|
if (error)
|
|
|
|
goto out;
|
|
|
|
memcpy(rc->rc_buf, r->res_name, r->res_length);
|
2022-04-04 20:06:40 +00:00
|
|
|
rc->rc_id = cpu_to_le64(r->res_id);
|
2006-01-18 09:30:29 +00:00
|
|
|
|
2021-07-16 20:22:38 +00:00
|
|
|
send_rcom(mh, rc);
|
2006-01-18 09:30:29 +00:00
|
|
|
out:
|
|
|
|
return error;
|
|
|
|
}
|
|
|
|
|
2023-08-01 18:09:45 +00:00
|
|
|
static void receive_rcom_lookup(struct dlm_ls *ls, struct dlm_rcom *rc_in,
|
|
|
|
uint64_t seq)
|
2006-01-18 09:30:29 +00:00
|
|
|
{
|
|
|
|
struct dlm_rcom *rc;
|
|
|
|
struct dlm_mhandle *mh;
|
2022-04-04 20:06:39 +00:00
|
|
|
int error, ret_nodeid, nodeid = le32_to_cpu(rc_in->rc_header.h_nodeid);
|
|
|
|
int len = le16_to_cpu(rc_in->rc_header.h_length) -
|
|
|
|
sizeof(struct dlm_rcom);
|
2006-01-18 09:30:29 +00:00
|
|
|
|
2017-10-09 14:29:31 +00:00
|
|
|
/* Old code would send this special id to trigger a debug dump. */
|
2022-04-04 20:06:40 +00:00
|
|
|
if (rc_in->rc_id == cpu_to_le64(0xFFFFFFFF)) {
|
2012-05-10 15:18:07 +00:00
|
|
|
log_error(ls, "receive_rcom_lookup dump from %d", nodeid);
|
|
|
|
dlm_dump_rsb_name(ls, rc_in->rc_buf, len);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2023-08-01 18:09:45 +00:00
|
|
|
error = create_rcom(ls, nodeid, DLM_RCOM_LOOKUP_REPLY, 0, &rc, &mh,
|
|
|
|
seq);
|
2021-05-26 14:46:05 +00:00
|
|
|
if (error)
|
|
|
|
return;
|
|
|
|
|
2012-05-10 15:18:07 +00:00
|
|
|
error = dlm_master_lookup(ls, nodeid, rc_in->rc_buf, len,
|
|
|
|
DLM_LU_RECOVER_MASTER, &ret_nodeid, NULL);
|
2006-01-18 09:30:29 +00:00
|
|
|
if (error)
|
|
|
|
ret_nodeid = error;
|
2022-04-04 20:06:40 +00:00
|
|
|
rc->rc_result = cpu_to_le32(ret_nodeid);
|
2006-01-18 09:30:29 +00:00
|
|
|
rc->rc_id = rc_in->rc_id;
|
2006-12-13 16:37:16 +00:00
|
|
|
rc->rc_seq_reply = rc_in->rc_seq;
|
2006-01-18 09:30:29 +00:00
|
|
|
|
2021-07-16 20:22:38 +00:00
|
|
|
send_rcom(mh, rc);
|
2006-01-18 09:30:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void receive_rcom_lookup_reply(struct dlm_ls *ls, struct dlm_rcom *rc_in)
|
|
|
|
{
|
|
|
|
dlm_recover_master_reply(ls, rc_in);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void pack_rcom_lock(struct dlm_rsb *r, struct dlm_lkb *lkb,
|
|
|
|
struct rcom_lock *rl)
|
|
|
|
{
|
|
|
|
memset(rl, 0, sizeof(*rl));
|
|
|
|
|
2008-01-25 07:08:26 +00:00
|
|
|
rl->rl_ownpid = cpu_to_le32(lkb->lkb_ownpid);
|
|
|
|
rl->rl_lkid = cpu_to_le32(lkb->lkb_id);
|
|
|
|
rl->rl_exflags = cpu_to_le32(lkb->lkb_exflags);
|
2023-03-06 20:48:15 +00:00
|
|
|
rl->rl_flags = cpu_to_le32(dlm_dflags_val(lkb));
|
2008-01-25 07:08:26 +00:00
|
|
|
rl->rl_lvbseq = cpu_to_le32(lkb->lkb_lvbseq);
|
2006-01-18 09:30:29 +00:00
|
|
|
rl->rl_rqmode = lkb->lkb_rqmode;
|
|
|
|
rl->rl_grmode = lkb->lkb_grmode;
|
|
|
|
rl->rl_status = lkb->lkb_status;
|
2008-01-25 07:08:26 +00:00
|
|
|
rl->rl_wait_type = cpu_to_le16(lkb->lkb_wait_type);
|
2006-01-18 09:30:29 +00:00
|
|
|
|
2008-02-06 06:35:45 +00:00
|
|
|
if (lkb->lkb_bastfn)
|
2011-02-21 20:58:21 +00:00
|
|
|
rl->rl_asts |= DLM_CB_BAST;
|
2008-02-06 06:35:45 +00:00
|
|
|
if (lkb->lkb_astfn)
|
2011-02-21 20:58:21 +00:00
|
|
|
rl->rl_asts |= DLM_CB_CAST;
|
2006-01-18 09:30:29 +00:00
|
|
|
|
2008-01-25 07:08:26 +00:00
|
|
|
rl->rl_namelen = cpu_to_le16(r->res_length);
|
2006-01-18 09:30:29 +00:00
|
|
|
memcpy(rl->rl_name, r->res_name, r->res_length);
|
|
|
|
|
|
|
|
/* FIXME: might we have an lvb without DLM_LKF_VALBLK set ?
|
|
|
|
If so, receive_rcom_lock_args() won't take this copy. */
|
|
|
|
|
|
|
|
if (lkb->lkb_lvbptr)
|
|
|
|
memcpy(rl->rl_lvb, lkb->lkb_lvbptr, r->res_ls->ls_lvblen);
|
|
|
|
}
|
|
|
|
|
2023-08-01 18:09:45 +00:00
|
|
|
int dlm_send_rcom_lock(struct dlm_rsb *r, struct dlm_lkb *lkb, uint64_t seq)
|
2006-01-18 09:30:29 +00:00
|
|
|
{
|
|
|
|
struct dlm_ls *ls = r->res_ls;
|
|
|
|
struct dlm_rcom *rc;
|
|
|
|
struct dlm_mhandle *mh;
|
|
|
|
struct rcom_lock *rl;
|
|
|
|
int error, len = sizeof(struct rcom_lock);
|
|
|
|
|
|
|
|
if (lkb->lkb_lvbptr)
|
|
|
|
len += ls->ls_lvblen;
|
|
|
|
|
2023-08-01 18:09:45 +00:00
|
|
|
error = create_rcom(ls, r->res_nodeid, DLM_RCOM_LOCK, len, &rc, &mh,
|
|
|
|
seq);
|
2006-01-18 09:30:29 +00:00
|
|
|
if (error)
|
|
|
|
goto out;
|
|
|
|
|
|
|
|
rl = (struct rcom_lock *) rc->rc_buf;
|
|
|
|
pack_rcom_lock(r, lkb, rl);
|
fs: dlm: cast resource pointer to uintptr_t
This patch fixes the following warning when doing a 32 bit kernel build
when pointers are 4 byte long:
In file included from ./include/linux/byteorder/little_endian.h:5,
from ./arch/x86/include/uapi/asm/byteorder.h:5,
from ./include/asm-generic/qrwlock_types.h:6,
from ./arch/x86/include/asm/spinlock_types.h:7,
from ./include/linux/spinlock_types_raw.h:7,
from ./include/linux/ratelimit_types.h:7,
from ./include/linux/printk.h:10,
from ./include/asm-generic/bug.h:22,
from ./arch/x86/include/asm/bug.h:87,
from ./include/linux/bug.h:5,
from ./include/linux/mmdebug.h:5,
from ./include/linux/gfp.h:5,
from ./include/linux/slab.h:15,
from fs/dlm/dlm_internal.h:19,
from fs/dlm/rcom.c:12:
fs/dlm/rcom.c: In function ‘dlm_send_rcom_lock’:
./include/uapi/linux/byteorder/little_endian.h:32:43: warning: cast from pointer to integer of different size [-Wpointer-to-int-cast]
#define __cpu_to_le64(x) ((__force __le64)(__u64)(x))
^
./include/linux/byteorder/generic.h:86:21: note: in expansion of macro ‘__cpu_to_le64’
#define cpu_to_le64 __cpu_to_le64
^~~~~~~~~~~~~
fs/dlm/rcom.c:457:14: note: in expansion of macro ‘cpu_to_le64’
rc->rc_id = cpu_to_le64(r);
The rc_id value in dlm rcom is handled as u64. The rcom implementation
uses for an unique number generation the pointer value of the used
dlm_rsb instance. However if the pointer value is 4 bytes long
-Wpointer-to-int-cast will print a warning. We get rid of that warning
to cast the pointer to uintptr_t which is either 4 or 8 bytes. There
might be a very unlikely case where this number isn't unique anymore if
using dlm in a mixed cluster of nodes and sizeof(uintptr_t) returns 4 and
8.
However this problem was already been there and this patch should get
rid of the warning.
Fixes: 2f9dbeda8dc0 ("dlm: use __le types for rcom messages")
Reported-by: kernel test robot <lkp@intel.com>
Signed-off-by: Alexander Aring <aahringo@redhat.com>
Signed-off-by: David Teigland <teigland@redhat.com>
2022-04-07 14:45:42 +00:00
|
|
|
rc->rc_id = cpu_to_le64((uintptr_t)r);
|
2006-01-18 09:30:29 +00:00
|
|
|
|
2021-07-16 20:22:38 +00:00
|
|
|
send_rcom(mh, rc);
|
2006-01-18 09:30:29 +00:00
|
|
|
out:
|
|
|
|
return error;
|
|
|
|
}
|
|
|
|
|
2008-01-26 00:55:09 +00:00
|
|
|
/* needs at least dlm_rcom + rcom_lock */
|
2023-08-01 18:09:45 +00:00
|
|
|
static void receive_rcom_lock(struct dlm_ls *ls, struct dlm_rcom *rc_in,
|
|
|
|
uint64_t seq)
|
2006-01-18 09:30:29 +00:00
|
|
|
{
|
|
|
|
struct dlm_rcom *rc;
|
|
|
|
struct dlm_mhandle *mh;
|
2022-04-04 20:06:39 +00:00
|
|
|
int error, nodeid = le32_to_cpu(rc_in->rc_header.h_nodeid);
|
2006-01-18 09:30:29 +00:00
|
|
|
|
|
|
|
dlm_recover_master_copy(ls, rc_in);
|
|
|
|
|
|
|
|
error = create_rcom(ls, nodeid, DLM_RCOM_LOCK_REPLY,
|
2023-08-01 18:09:45 +00:00
|
|
|
sizeof(struct rcom_lock), &rc, &mh, seq);
|
2006-01-18 09:30:29 +00:00
|
|
|
if (error)
|
|
|
|
return;
|
|
|
|
|
|
|
|
/* We send back the same rcom_lock struct we received, but
|
|
|
|
dlm_recover_master_copy() has filled in rl_remid and rl_result */
|
|
|
|
|
|
|
|
memcpy(rc->rc_buf, rc_in->rc_buf, sizeof(struct rcom_lock));
|
|
|
|
rc->rc_id = rc_in->rc_id;
|
2006-12-13 16:37:16 +00:00
|
|
|
rc->rc_seq_reply = rc_in->rc_seq;
|
2006-01-18 09:30:29 +00:00
|
|
|
|
2021-07-16 20:22:38 +00:00
|
|
|
send_rcom(mh, rc);
|
2006-01-18 09:30:29 +00:00
|
|
|
}
|
|
|
|
|
2007-09-27 20:53:38 +00:00
|
|
|
/* If the lockspace doesn't exist then still send a status message
|
|
|
|
back; it's possible that it just doesn't have its global_id yet. */
|
|
|
|
|
|
|
|
int dlm_send_ls_not_ready(int nodeid, struct dlm_rcom *rc_in)
|
2006-01-18 09:30:29 +00:00
|
|
|
{
|
|
|
|
struct dlm_rcom *rc;
|
2006-11-27 19:18:41 +00:00
|
|
|
struct rcom_config *rf;
|
2006-01-18 09:30:29 +00:00
|
|
|
struct dlm_mhandle *mh;
|
|
|
|
char *mb;
|
2006-11-27 19:18:41 +00:00
|
|
|
int mb_len = sizeof(struct dlm_rcom) + sizeof(struct rcom_config);
|
2006-01-18 09:30:29 +00:00
|
|
|
|
2021-05-21 19:08:41 +00:00
|
|
|
mh = dlm_midcomms_get_mhandle(nodeid, mb_len, GFP_NOFS, &mb);
|
2006-01-18 09:30:29 +00:00
|
|
|
if (!mh)
|
|
|
|
return -ENOBUFS;
|
|
|
|
|
|
|
|
rc = (struct dlm_rcom *) mb;
|
|
|
|
|
2022-04-04 20:06:39 +00:00
|
|
|
rc->rc_header.h_version = cpu_to_le32(DLM_HEADER_MAJOR | DLM_HEADER_MINOR);
|
2021-05-21 19:08:45 +00:00
|
|
|
rc->rc_header.u.h_lockspace = rc_in->rc_header.u.h_lockspace;
|
2022-04-04 20:06:39 +00:00
|
|
|
rc->rc_header.h_nodeid = cpu_to_le32(dlm_our_nodeid());
|
|
|
|
rc->rc_header.h_length = cpu_to_le16(mb_len);
|
2006-01-18 09:30:29 +00:00
|
|
|
rc->rc_header.h_cmd = DLM_RCOM;
|
|
|
|
|
2022-04-04 20:06:40 +00:00
|
|
|
rc->rc_type = cpu_to_le32(DLM_RCOM_STATUS_REPLY);
|
2006-08-23 17:50:54 +00:00
|
|
|
rc->rc_id = rc_in->rc_id;
|
2006-12-13 16:37:16 +00:00
|
|
|
rc->rc_seq_reply = rc_in->rc_seq;
|
2022-04-04 20:06:40 +00:00
|
|
|
rc->rc_result = cpu_to_le32(-ESRCH);
|
2006-01-18 09:30:29 +00:00
|
|
|
|
2006-11-27 19:18:41 +00:00
|
|
|
rf = (struct rcom_config *) rc->rc_buf;
|
2008-01-25 07:34:00 +00:00
|
|
|
rf->rf_lvblen = cpu_to_le32(~0U);
|
2006-11-27 19:18:41 +00:00
|
|
|
|
2022-10-27 20:45:15 +00:00
|
|
|
dlm_midcomms_commit_mhandle(mh, NULL, 0);
|
2006-01-18 09:30:29 +00:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2012-05-10 15:18:07 +00:00
|
|
|
/*
|
|
|
|
* Ignore messages for stage Y before we set
|
|
|
|
* recover_status bit for stage X:
|
|
|
|
*
|
|
|
|
* recover_status = 0
|
|
|
|
*
|
|
|
|
* dlm_recover_members()
|
|
|
|
* - send nothing
|
|
|
|
* - recv nothing
|
|
|
|
* - ignore NAMES, NAMES_REPLY
|
|
|
|
* - ignore LOOKUP, LOOKUP_REPLY
|
|
|
|
* - ignore LOCK, LOCK_REPLY
|
|
|
|
*
|
|
|
|
* recover_status |= NODES
|
|
|
|
*
|
|
|
|
* dlm_recover_members_wait()
|
|
|
|
*
|
|
|
|
* dlm_recover_directory()
|
|
|
|
* - send NAMES
|
|
|
|
* - recv NAMES_REPLY
|
|
|
|
* - ignore LOOKUP, LOOKUP_REPLY
|
|
|
|
* - ignore LOCK, LOCK_REPLY
|
|
|
|
*
|
|
|
|
* recover_status |= DIR
|
|
|
|
*
|
|
|
|
* dlm_recover_directory_wait()
|
|
|
|
*
|
|
|
|
* dlm_recover_masters()
|
|
|
|
* - send LOOKUP
|
|
|
|
* - recv LOOKUP_REPLY
|
|
|
|
*
|
|
|
|
* dlm_recover_locks()
|
|
|
|
* - send LOCKS
|
|
|
|
* - recv LOCKS_REPLY
|
|
|
|
*
|
|
|
|
* recover_status |= LOCKS
|
|
|
|
*
|
|
|
|
* dlm_recover_locks_wait()
|
|
|
|
*
|
|
|
|
* recover_status |= DONE
|
|
|
|
*/
|
|
|
|
|
2012-04-23 18:58:42 +00:00
|
|
|
/* Called by dlm_recv; corresponds to dlm_receive_message() but special
|
|
|
|
recovery-only comms are sent through here. */
|
|
|
|
|
|
|
|
void dlm_receive_rcom(struct dlm_ls *ls, struct dlm_rcom *rc, int nodeid)
|
2006-12-13 16:37:16 +00:00
|
|
|
{
|
2012-04-23 18:58:42 +00:00
|
|
|
int lock_size = sizeof(struct dlm_rcom) + sizeof(struct rcom_lock);
|
2012-05-10 15:18:07 +00:00
|
|
|
int stop, reply = 0, names = 0, lookup = 0, lock = 0;
|
dlm: fixes for nodir mode
The "nodir" mode (statically assign master nodes instead
of using the resource directory) has always been highly
experimental, and never seriously used. This commit
fixes a number of problems, making nodir much more usable.
- Major change to recovery: recover all locks and restart
all in-progress operations after recovery. In some
cases it's not possible to know which in-progess locks
to recover, so recover all. (Most require recovery
in nodir mode anyway since rehashing changes most
master nodes.)
- Change the way nodir mode is enabled, from a command
line mount arg passed through gfs2, into a sysfs
file managed by dlm_controld, consistent with the
other config settings.
- Allow recovering MSTCPY locks on an rsb that has not
yet been turned into a master copy.
- Ignore RCOM_LOCK and RCOM_LOCK_REPLY recovery messages
from a previous, aborted recovery cycle. Base this
on the local recovery status not being in the state
where any nodes should be sending LOCK messages for the
current recovery cycle.
- Hold rsb lock around dlm_purge_mstcpy_locks() because it
may run concurrently with dlm_recover_master_copy().
- Maintain highbast on process-copy lkb's (in addition to
the master as is usual), because the lkb can switch
back and forth between being a master and being a
process copy as the master node changes in recovery.
- When recovering MSTCPY locks, flag rsb's that have
non-empty convert or waiting queues for granting
at the end of recovery. (Rename flag from LOCKS_PURGED
to RECOVER_GRANT and similar for the recovery function,
because it's not only resources with purged locks
that need grant a grant attempt.)
- Replace a couple of unnecessary assertion panics with
error messages.
Signed-off-by: David Teigland <teigland@redhat.com>
2012-04-26 20:54:29 +00:00
|
|
|
uint32_t status;
|
2006-12-13 16:37:16 +00:00
|
|
|
uint64_t seq;
|
|
|
|
|
|
|
|
switch (rc->rc_type) {
|
2022-04-04 20:06:40 +00:00
|
|
|
case cpu_to_le32(DLM_RCOM_STATUS_REPLY):
|
2012-05-10 15:18:07 +00:00
|
|
|
reply = 1;
|
|
|
|
break;
|
2022-04-04 20:06:40 +00:00
|
|
|
case cpu_to_le32(DLM_RCOM_NAMES):
|
2012-05-10 15:18:07 +00:00
|
|
|
names = 1;
|
|
|
|
break;
|
2022-04-04 20:06:40 +00:00
|
|
|
case cpu_to_le32(DLM_RCOM_NAMES_REPLY):
|
2012-05-10 15:18:07 +00:00
|
|
|
names = 1;
|
|
|
|
reply = 1;
|
|
|
|
break;
|
2022-04-04 20:06:40 +00:00
|
|
|
case cpu_to_le32(DLM_RCOM_LOOKUP):
|
2012-05-10 15:18:07 +00:00
|
|
|
lookup = 1;
|
|
|
|
break;
|
2022-04-04 20:06:40 +00:00
|
|
|
case cpu_to_le32(DLM_RCOM_LOOKUP_REPLY):
|
2012-05-10 15:18:07 +00:00
|
|
|
lookup = 1;
|
|
|
|
reply = 1;
|
|
|
|
break;
|
2022-04-04 20:06:40 +00:00
|
|
|
case cpu_to_le32(DLM_RCOM_LOCK):
|
dlm: fixes for nodir mode
The "nodir" mode (statically assign master nodes instead
of using the resource directory) has always been highly
experimental, and never seriously used. This commit
fixes a number of problems, making nodir much more usable.
- Major change to recovery: recover all locks and restart
all in-progress operations after recovery. In some
cases it's not possible to know which in-progess locks
to recover, so recover all. (Most require recovery
in nodir mode anyway since rehashing changes most
master nodes.)
- Change the way nodir mode is enabled, from a command
line mount arg passed through gfs2, into a sysfs
file managed by dlm_controld, consistent with the
other config settings.
- Allow recovering MSTCPY locks on an rsb that has not
yet been turned into a master copy.
- Ignore RCOM_LOCK and RCOM_LOCK_REPLY recovery messages
from a previous, aborted recovery cycle. Base this
on the local recovery status not being in the state
where any nodes should be sending LOCK messages for the
current recovery cycle.
- Hold rsb lock around dlm_purge_mstcpy_locks() because it
may run concurrently with dlm_recover_master_copy().
- Maintain highbast on process-copy lkb's (in addition to
the master as is usual), because the lkb can switch
back and forth between being a master and being a
process copy as the master node changes in recovery.
- When recovering MSTCPY locks, flag rsb's that have
non-empty convert or waiting queues for granting
at the end of recovery. (Rename flag from LOCKS_PURGED
to RECOVER_GRANT and similar for the recovery function,
because it's not only resources with purged locks
that need grant a grant attempt.)
- Replace a couple of unnecessary assertion panics with
error messages.
Signed-off-by: David Teigland <teigland@redhat.com>
2012-04-26 20:54:29 +00:00
|
|
|
lock = 1;
|
|
|
|
break;
|
2022-04-04 20:06:40 +00:00
|
|
|
case cpu_to_le32(DLM_RCOM_LOCK_REPLY):
|
dlm: fixes for nodir mode
The "nodir" mode (statically assign master nodes instead
of using the resource directory) has always been highly
experimental, and never seriously used. This commit
fixes a number of problems, making nodir much more usable.
- Major change to recovery: recover all locks and restart
all in-progress operations after recovery. In some
cases it's not possible to know which in-progess locks
to recover, so recover all. (Most require recovery
in nodir mode anyway since rehashing changes most
master nodes.)
- Change the way nodir mode is enabled, from a command
line mount arg passed through gfs2, into a sysfs
file managed by dlm_controld, consistent with the
other config settings.
- Allow recovering MSTCPY locks on an rsb that has not
yet been turned into a master copy.
- Ignore RCOM_LOCK and RCOM_LOCK_REPLY recovery messages
from a previous, aborted recovery cycle. Base this
on the local recovery status not being in the state
where any nodes should be sending LOCK messages for the
current recovery cycle.
- Hold rsb lock around dlm_purge_mstcpy_locks() because it
may run concurrently with dlm_recover_master_copy().
- Maintain highbast on process-copy lkb's (in addition to
the master as is usual), because the lkb can switch
back and forth between being a master and being a
process copy as the master node changes in recovery.
- When recovering MSTCPY locks, flag rsb's that have
non-empty convert or waiting queues for granting
at the end of recovery. (Rename flag from LOCKS_PURGED
to RECOVER_GRANT and similar for the recovery function,
because it's not only resources with purged locks
that need grant a grant attempt.)
- Replace a couple of unnecessary assertion panics with
error messages.
Signed-off-by: David Teigland <teigland@redhat.com>
2012-04-26 20:54:29 +00:00
|
|
|
lock = 1;
|
|
|
|
reply = 1;
|
|
|
|
break;
|
2020-04-22 06:59:27 +00:00
|
|
|
}
|
2006-12-13 16:37:16 +00:00
|
|
|
|
2012-04-23 18:58:42 +00:00
|
|
|
spin_lock(&ls->ls_recover_lock);
|
dlm: fixes for nodir mode
The "nodir" mode (statically assign master nodes instead
of using the resource directory) has always been highly
experimental, and never seriously used. This commit
fixes a number of problems, making nodir much more usable.
- Major change to recovery: recover all locks and restart
all in-progress operations after recovery. In some
cases it's not possible to know which in-progess locks
to recover, so recover all. (Most require recovery
in nodir mode anyway since rehashing changes most
master nodes.)
- Change the way nodir mode is enabled, from a command
line mount arg passed through gfs2, into a sysfs
file managed by dlm_controld, consistent with the
other config settings.
- Allow recovering MSTCPY locks on an rsb that has not
yet been turned into a master copy.
- Ignore RCOM_LOCK and RCOM_LOCK_REPLY recovery messages
from a previous, aborted recovery cycle. Base this
on the local recovery status not being in the state
where any nodes should be sending LOCK messages for the
current recovery cycle.
- Hold rsb lock around dlm_purge_mstcpy_locks() because it
may run concurrently with dlm_recover_master_copy().
- Maintain highbast on process-copy lkb's (in addition to
the master as is usual), because the lkb can switch
back and forth between being a master and being a
process copy as the master node changes in recovery.
- When recovering MSTCPY locks, flag rsb's that have
non-empty convert or waiting queues for granting
at the end of recovery. (Rename flag from LOCKS_PURGED
to RECOVER_GRANT and similar for the recovery function,
because it's not only resources with purged locks
that need grant a grant attempt.)
- Replace a couple of unnecessary assertion panics with
error messages.
Signed-off-by: David Teigland <teigland@redhat.com>
2012-04-26 20:54:29 +00:00
|
|
|
status = ls->ls_recover_status;
|
2021-11-02 19:17:12 +00:00
|
|
|
stop = dlm_recovery_stopped(ls);
|
2012-04-23 18:58:42 +00:00
|
|
|
seq = ls->ls_recover_seq;
|
|
|
|
spin_unlock(&ls->ls_recover_lock);
|
2008-01-26 00:55:09 +00:00
|
|
|
|
2022-04-04 20:06:40 +00:00
|
|
|
if (stop && (rc->rc_type != cpu_to_le32(DLM_RCOM_STATUS)))
|
2012-05-10 15:18:07 +00:00
|
|
|
goto ignore;
|
|
|
|
|
2022-04-04 20:06:40 +00:00
|
|
|
if (reply && (le64_to_cpu(rc->rc_seq_reply) != seq))
|
2012-05-10 15:18:07 +00:00
|
|
|
goto ignore;
|
|
|
|
|
|
|
|
if (!(status & DLM_RS_NODES) && (names || lookup || lock))
|
|
|
|
goto ignore;
|
|
|
|
|
|
|
|
if (!(status & DLM_RS_DIR) && (lookup || lock))
|
|
|
|
goto ignore;
|
2006-01-18 09:30:29 +00:00
|
|
|
|
|
|
|
switch (rc->rc_type) {
|
2022-04-04 20:06:40 +00:00
|
|
|
case cpu_to_le32(DLM_RCOM_STATUS):
|
2023-08-01 18:09:45 +00:00
|
|
|
receive_rcom_status(ls, rc, seq);
|
2006-01-18 09:30:29 +00:00
|
|
|
break;
|
|
|
|
|
2022-04-04 20:06:40 +00:00
|
|
|
case cpu_to_le32(DLM_RCOM_NAMES):
|
2023-08-01 18:09:45 +00:00
|
|
|
receive_rcom_names(ls, rc, seq);
|
2006-01-18 09:30:29 +00:00
|
|
|
break;
|
|
|
|
|
2022-04-04 20:06:40 +00:00
|
|
|
case cpu_to_le32(DLM_RCOM_LOOKUP):
|
2023-08-01 18:09:45 +00:00
|
|
|
receive_rcom_lookup(ls, rc, seq);
|
2006-01-18 09:30:29 +00:00
|
|
|
break;
|
|
|
|
|
2022-04-04 20:06:40 +00:00
|
|
|
case cpu_to_le32(DLM_RCOM_LOCK):
|
2022-04-04 20:06:39 +00:00
|
|
|
if (le16_to_cpu(rc->rc_header.h_length) < lock_size)
|
2008-01-26 00:55:09 +00:00
|
|
|
goto Eshort;
|
2023-08-01 18:09:45 +00:00
|
|
|
receive_rcom_lock(ls, rc, seq);
|
2006-01-18 09:30:29 +00:00
|
|
|
break;
|
|
|
|
|
2022-04-04 20:06:40 +00:00
|
|
|
case cpu_to_le32(DLM_RCOM_STATUS_REPLY):
|
2008-01-29 20:52:10 +00:00
|
|
|
receive_sync_reply(ls, rc);
|
2006-01-18 09:30:29 +00:00
|
|
|
break;
|
|
|
|
|
2022-04-04 20:06:40 +00:00
|
|
|
case cpu_to_le32(DLM_RCOM_NAMES_REPLY):
|
2008-01-29 20:52:10 +00:00
|
|
|
receive_sync_reply(ls, rc);
|
2006-01-18 09:30:29 +00:00
|
|
|
break;
|
|
|
|
|
2022-04-04 20:06:40 +00:00
|
|
|
case cpu_to_le32(DLM_RCOM_LOOKUP_REPLY):
|
2006-01-18 09:30:29 +00:00
|
|
|
receive_rcom_lookup_reply(ls, rc);
|
|
|
|
break;
|
|
|
|
|
2022-04-04 20:06:40 +00:00
|
|
|
case cpu_to_le32(DLM_RCOM_LOCK_REPLY):
|
2022-04-04 20:06:39 +00:00
|
|
|
if (le16_to_cpu(rc->rc_header.h_length) < lock_size)
|
2008-01-26 00:55:09 +00:00
|
|
|
goto Eshort;
|
2023-08-01 18:09:45 +00:00
|
|
|
dlm_recover_process_copy(ls, rc, seq);
|
2006-01-18 09:30:29 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
2022-04-04 20:06:40 +00:00
|
|
|
log_error(ls, "receive_rcom bad type %d",
|
|
|
|
le32_to_cpu(rc->rc_type));
|
2006-01-18 09:30:29 +00:00
|
|
|
}
|
2012-05-10 15:18:07 +00:00
|
|
|
return;
|
|
|
|
|
|
|
|
ignore:
|
|
|
|
log_limit(ls, "dlm_receive_rcom ignore msg %d "
|
|
|
|
"from %d %llu %llu recover seq %llu sts %x gen %u",
|
2022-04-04 20:06:40 +00:00
|
|
|
le32_to_cpu(rc->rc_type),
|
2012-05-10 15:18:07 +00:00
|
|
|
nodeid,
|
2022-04-04 20:06:40 +00:00
|
|
|
(unsigned long long)le64_to_cpu(rc->rc_seq),
|
|
|
|
(unsigned long long)le64_to_cpu(rc->rc_seq_reply),
|
2012-05-10 15:18:07 +00:00
|
|
|
(unsigned long long)seq,
|
|
|
|
status, ls->ls_generation);
|
2007-09-27 20:53:38 +00:00
|
|
|
return;
|
2008-01-26 00:55:09 +00:00
|
|
|
Eshort:
|
2012-05-10 15:18:07 +00:00
|
|
|
log_error(ls, "recovery message %d from %d is too short",
|
2022-04-04 20:06:40 +00:00
|
|
|
le32_to_cpu(rc->rc_type), nodeid);
|
2006-01-18 09:30:29 +00:00
|
|
|
}
|
|
|
|
|