Branch 'work3' - src/log.h
by David Teigland
src/log.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
New commits:
commit 5e76f09f9bcecbc9349dc3ee7faf43bcc7c1376c
Author: David Teigland <teigland(a)redhat.com>
Date: Fri Oct 5 10:13:52 2012 -0500
sanlock: print command output to stdout
instead of stderr
Signed-off-by: David Teigland <teigland(a)redhat.com>
diff --git a/src/log.h b/src/log.h
index db6d275..10b8c36 100644
--- a/src/log.h
+++ b/src/log.h
@@ -50,7 +50,7 @@ void copy_log_dump(char *buf, int *len);
#define log_tool(fmt, args...) \
do { \
- fprintf(stderr, fmt "\n", ##args); \
+ printf(fmt "\n", ##args); \
} while (0)
#endif
11 years, 6 months
Branch 'work3' - src/main.c
by David Teigland
src/main.c | 13 ++++++++++---
1 file changed, 10 insertions(+), 3 deletions(-)
New commits:
commit d05aac412b50baee23d2a0847e1676040d2efbff
Author: David Teigland <teigland(a)redhat.com>
Date: Thu Oct 4 16:47:58 2012 -0500
sanlock: client add_lockspace with timeout
When a -o io timeout value not equal to the
default (10) is used, the command will use
the add_lockspace_timeout api.
Signed-off-by: David Teigland <teigland(a)redhat.com>
diff --git a/src/main.c b/src/main.c
index a0b5145..33f90a7 100644
--- a/src/main.c
+++ b/src/main.c
@@ -2177,9 +2177,16 @@ static int do_client(void)
break;
case ACT_ADD_LOCKSPACE:
- log_tool("add_lockspace");
- rv = sanlock_add_lockspace(&com.lockspace, 0);
- log_tool("add_lockspace done %d", rv);
+ if (com.io_timeout_arg != DEFAULT_IO_TIMEOUT) {
+ log_tool("add_lockspace_timeout %d", com.io_timeout_arg);
+ rv = sanlock_add_lockspace_timeout(&com.lockspace, 0,
+ com.io_timeout_arg);
+ log_tool("add_lockspace_timeout done %d", rv);
+ } else {
+ log_tool("add_lockspace");
+ rv = sanlock_add_lockspace(&com.lockspace, 0);
+ log_tool("add_lockspace done %d", rv);
+ }
break;
case ACT_INQ_LOCKSPACE:
11 years, 6 months
Branch 'work3' - src/main.c
by David Teigland
src/main.c | 17 ++++++++++++++---
1 file changed, 14 insertions(+), 3 deletions(-)
New commits:
commit da94fe800c843b467f926420ccbe9961e8289f46
Author: David Teigland <teigland(a)redhat.com>
Date: Thu Oct 4 16:26:54 2012 -0500
sanlock: fix aborted command clearing
When clearing the remainder of an aborted
command, non-blocking recv is used to avoid
blocking the main thread, but this means it
needs to do a minimal amount of retrying when
EAGAIN is returned. It wasn't retrying at all,
so the remainder of the message was handled as
a new command, which caused errors when the
fragment was found to have a bad magic number.
Signed-off-by: David Teigland <teigland(a)redhat.com>
diff --git a/src/main.c b/src/main.c
index 522ae6a..a0b5145 100644
--- a/src/main.c
+++ b/src/main.c
@@ -396,13 +396,22 @@ void client_recv_all(int ci, struct sm_header *h_recv, int pos)
{
char trash[64];
int rem = h_recv->length - sizeof(struct sm_header) - pos;
- int rv, error = 0, total = 0;
+ int rv, error = 0, total = 0, retries = 0;
if (!rem)
return;
while (1) {
rv = recv(client[ci].fd, trash, sizeof(trash), MSG_DONTWAIT);
+
+ if (rv == -1 && errno == EAGAIN) {
+ usleep(1000);
+ if (retries < 20) {
+ retries++;
+ continue;
+ }
+ }
+
if (rv == -1)
error = errno;
if (rv <= 0)
@@ -413,8 +422,8 @@ void client_recv_all(int ci, struct sm_header *h_recv, int pos)
break;
}
- log_debug("recv_all %d,%d,%d pos %d rv %d error %d rem %d total %d",
- ci, client[ci].fd, client[ci].pid, pos, rv, error, rem, total);
+ log_debug("recv_all %d,%d,%d pos %d rv %d error %d retries %d rem %d total %d",
+ ci, client[ci].fd, client[ci].pid, pos, rv, error, retries, rem, total);
}
void send_result(int fd, struct sm_header *h_recv, int result);
@@ -998,6 +1007,8 @@ static void process_cmd_thread_registered(int ci_in, struct sm_header *h_recv)
break;
}
if (ci_target < 0) {
+ log_error("cmd %d target pid %d not found",
+ h_recv->cmd, h_recv->data2);
result = -ESRCH;
goto fail;
}
11 years, 6 months
Changes to 'wdmd-script'
by David Teigland
New branch 'wdmd-script' available with the following commits:
commit 3f8c91a91e2cdab8fc194a9010f887c344294534
Author: David Teigland <teigland(a)redhat.com>
Date: Wed Sep 19 15:15:05 2012 -0500
wdmd: new script handling
Rewrite the code for using test scripts,
enabled by -S 1. Also added dumping
daemon state by wdmd --dump.
Signed-off-by: David Teigland <teigland(a)redhat.com>
11 years, 6 months
Changes to 'wdmd-script'
by David Teigland
New branch 'wdmd-script' available with the following commits:
commit c7c95d6269d12e2c0ffb0127c6be9c883900e08c
Author: David Teigland <teigland(a)redhat.com>
Date: Wed Sep 19 15:15:05 2012 -0500
wdmd: new script handling
Rewrite the code for using test scripts,
enabled by -S 1. Also added dumping
daemon state by wdmd --dump.
Signed-off-by: David Teigland <teigland(a)redhat.com>
11 years, 6 months
Branch 'fence_sanlock' - fence_sanlock/fence_sanlock.in fence_sanlock/fence_sanlockd.c init.d/fence_sanlockd
by David Teigland
fence_sanlock/fence_sanlock.in | 79 ++++++++++----
fence_sanlock/fence_sanlockd.c | 221 +++++++++++++++++++++++++++++++++++++----
init.d/fence_sanlockd | 16 ++
3 files changed, 270 insertions(+), 46 deletions(-)
New commits:
commit 08b228eb4378fb206ad04f570f7cdff3b6504f43
Author: David Teigland <teigland(a)redhat.com>
Date: Thu Oct 4 14:22:20 2012 -0500
fence_sanlock: handle two node fence duel
Big change is handling fencing duel in two_node mode.
Makes the low host_id win.
Quite a few other changes and fixes.
Signed-off-by: David Teigland <teigland(a)redhat.com>
diff --git a/fence_sanlock/fence_sanlock.in b/fence_sanlock/fence_sanlock.in
index 764a516..dbc0f24 100755
--- a/fence_sanlock/fence_sanlock.in
+++ b/fence_sanlock/fence_sanlock.in
@@ -32,15 +32,7 @@
#
# <fencedevice name="wd" agent="fence_sanlock" path="/dev/fence_sanlock/leases"/>
-# setup (one time only):
-# fence_sanlock -o sanlock_init -p $path
-#
-# startup:
-# service wdmd start
-# service sanlock start
-# service cman start
-# - fence_node -U -> fence_sanlock -o on -> fence_sanlockd
-
+prog=fence_sanlock
max_hosts=128
opts=
action=
@@ -51,7 +43,7 @@ offset=
help() {
echo "Usage:"
echo ""
- echo "fence_sanlock [options]"
+ echo "$prog [options]"
echo ""
echo "Options:"
echo " -o <action> Action: off (default), on, status or metadata"
@@ -87,7 +79,7 @@ cli_options() {
exit 0
;;
-V)
- echo "fence_sanlock version @VERSION@"
+ echo "$prog version @VERSION@"
exit 0
;;
esac
@@ -170,19 +162,19 @@ read_leader() {
leader=$(sanlock direct read_leader -r fence:h$host_id:$path:$offset 2>&1)
[ "$?" != 0 ] && {
- echo "storage error: unable to read $path"
+ logger -t $prog "$action: storage error: unable to read $path"
return 1
}
magic="$(echo "$leader" | grep magic | awk '{print $NF}')"
[ -z "$magic" ] && {
- echo "storage error: no sanlock magic number at $path:$offset"
+ logger -t $prog "$action: storage error: no sanlock magic number at $path:$offset"
return 1
}
[ "$magic" != "0x6152010" ] && {
- echo "storage error: invalid sanlock magic number $magic at $path:$offset"
+ logger -t $prog "$action: storage error: invalid sanlock magic number $magic at $path:$offset"
return 1
}
@@ -193,7 +185,7 @@ action_on() {
read_leader || return 1
[ -z "$(pidof fence_sanlockd)" ] && {
- echo "fence_sanlockd is not running"
+ logger -t $prog "on fence_sanlockd is not running"
return 1
}
@@ -201,7 +193,7 @@ action_on() {
errmsg="$(fence_sanlockd -s -p $path -i $host_id 2>&1)"
[ "$?" != 0 ] && {
- echo "fence_sanlockd -s error: $errmsg"
+ logger -t $prog "on fence_sanlockd -s error: $errmsg"
return 1
}
@@ -214,13 +206,13 @@ action_on() {
# make sure sanlockd is alive
clientstatus="$(sanlock client status 2>&1)"
[ "$?" != 0 ] && {
- echo "sanlock client status error $?"
+ logger -t $prog "on sanlock client status error $?"
return 1
}
# make sure fence_sanlockd is alive
[ -z "$(pidof fence_sanlockd)" ] && {
- echo "fence_sanlockd stopped running"
+ logger -t $prog "on fence_sanlockd stopped running"
return 1
}
@@ -250,16 +242,26 @@ action_off() {
# owner_id should equal host_id
[ "$owner_id" != "$host_id" ] && {
- echo "victim lease $host_id owned by $owner_id:$owner_gen"
+ logger -t $prog "victim lease $host_id owned by $owner_id:$owner_gen"
return 1
}
pid="$(pidof fence_sanlockd)"
[ -z "$pid" ] && {
- echo "Unable to determine fence_sanlockd pid"
+ logger -t $prog "Unable to determine fence_sanlockd pid"
return 1
}
+ # pid file should be unique for each instance so multiple
+ # fence_sanlock's can run in parallel. fence_sanlockd may read
+ # this file to see which host_id we are fencing.
+
+ pidfile=/var/run/$prog/$prog.pid.$$
+
+ echo "$$ host_id $host_id gen $owner_gen ver $ver timestamp $timestamp" > $pidfile
+
+ logger -t $prog "$$ host_id $host_id gen $owner_gen ver $ver timestamp $timestamp"
+
loop=0
# FIXME: should this loop have a retry limit?
@@ -267,13 +269,21 @@ action_off() {
do
loop=$(($loop+1))
+ tmp_pid="$(pidof fence_sanlockd)"
+ [ -z "$tmp_pid" ] && {
+ logger -t $prog "fence_sanlockd not running"
+ unlink $pidfile
+ return 1
+ }
+
sanlock client acquire -r fence:h$host_id:$path:$offset -p $pid > /dev/null 2>&1
[ "$?" = 0 ] && {
# fence success
sanlock client release -r fence:h$host_id:$path:$offset -p $pid > /dev/null 2>&1
[ "$?" != 0 ] && {
- echo "release $host_id error $?"
+ logger -t $prog "release $host_id error $?"
}
+ unlink $pidfile
return 0
}
@@ -288,9 +298,20 @@ action_off() {
# reset. the -f 2 causes SIGUSR1 to be sent to
# fence_sanlockd on the victim.
+ # We send SIGUSR2 to our own fence_sanlockd to
+ # tell it that we are fencing someone else. If
+ # fence_sanlockd gets both SIGUSR1 indicating that
+ # someone is fencing it, and it gets SIGUSR2
+ # indicating that it is fencing someone, it knows
+ # that it's the special situation of two nodes
+ # fencing each other in a two node cluster. In
+ # this case, the low host_id can choose to survive.
+
+ kill -s SIGUSR2 $pid
+
sanlock client request -r fence:h$host_id:$path:$offset:$((ver + 1)) -f 2 > /dev/null 2>&1
[ "$?" != 0 ] && {
- echo "request $host_id error $?"
+ loggger -t $prog "request $host_id error $?"
}
fi
@@ -300,22 +321,30 @@ action_off() {
# reacquired cleanly by the victim host (same host_id, new
# generation), we can quit with success
- read_leader || return 1
+ read_leader
+
+ [ "$?" != 0 ] && {
+ unlink $pidfile
+ return 1
+ }
tmp_id="$(echo "$leader" | grep owner_id | awk '{print $NF}')"
tmp_gen="$(echo "$leader" | grep owner_gen | awk '{print $NF}')"
if [ "$owner_id" -eq "$tmp_id" ] && [ "$owner_gen" -lt "$tmp_gen" ]; then
- echo "victim $owner_id:$owner_gen reacquired lease gen $tmp_gen"
+ logger -t $prog "victim $owner_id:$owner_gen reacquired lease gen $tmp_gen"
+ unlink $pidfile
return 0
fi
if [ "$owner_id" -ne "$tmp_id" ]; then
- echo "victim $owner_id:$owner_gen acquired by $tmp_id:$tmp_gen"
+ logger -t $prog "victim $owner_id:$owner_gen acquired by $tmp_id:$tmp_gen"
+ unlink $pidfile
return 1
fi
done
+ unlink $pidfile
return 0
}
diff --git a/fence_sanlock/fence_sanlockd.c b/fence_sanlock/fence_sanlockd.c
index 9d4d03d..aa45736 100644
--- a/fence_sanlock/fence_sanlockd.c
+++ b/fence_sanlock/fence_sanlockd.c
@@ -20,6 +20,7 @@
#include <poll.h>
#include <signal.h>
#include <syslog.h>
+#include <dirent.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/wait.h>
@@ -36,16 +37,18 @@
#define LIVE_INTERVAL 5
#define EXPIRE_INTERVAL 20
-#define RUN_DIR "/var/run/fence_sanlockd"
+#define DAEMON_RUN_DIR "/var/run/fence_sanlockd"
+#define AGENT_RUN_DIR "/var/run/fence_sanlock"
static char *prog_name = (char *)"fence_sanlockd";
static int we_are_victim;
+static int we_are_fencing;
static int init_shutdown;
static int lockspace_recovery;
static int daemon_debug;
static int our_host_id;
-static char path[PATH_MAX];
+static char lease_path[PATH_MAX];
static struct sanlk_lockspace ls;
static struct sanlk_resource *r;
static struct sanlk_disk disk;
@@ -154,14 +157,14 @@ static int lockfile(void)
int fd, rv;
old_umask = umask(0022);
- rv = mkdir(RUN_DIR, 0775);
+ rv = mkdir(DAEMON_RUN_DIR, 0775);
if (rv < 0 && errno != EEXIST) {
umask(old_umask);
return rv;
}
umask(old_umask);
- sprintf(lockfile_path, "%s/%s.pid", RUN_DIR, prog_name);
+ sprintf(lockfile_path, "%s/%s.pid", DAEMON_RUN_DIR, prog_name);
fd = open(lockfile_path, O_CREAT|O_WRONLY|O_CLOEXEC, 0644);
if (fd < 0) {
@@ -216,6 +219,8 @@ static void process_signals(int ci)
return;
}
+ log_debug("signal %d from pid %d", fdsi.ssi_signo, fdsi.ssi_pid);
+
if (fdsi.ssi_signo == SIGHUP) {
init_shutdown = 1;
}
@@ -227,6 +232,10 @@ static void process_signals(int ci)
if (fdsi.ssi_signo == SIGUSR1) {
we_are_victim = 1;
}
+
+ if (fdsi.ssi_signo == SIGUSR2) {
+ we_are_fencing = 1;
+ }
}
static int setup_signals(void)
@@ -238,6 +247,7 @@ static int setup_signals(void)
sigaddset(&mask, SIGTERM);
sigaddset(&mask, SIGHUP);
sigaddset(&mask, SIGUSR1);
+ sigaddset(&mask, SIGUSR2);
rv = sigprocmask(SIG_BLOCK, &mask, NULL);
if (rv < 0)
@@ -255,7 +265,7 @@ static int wait_options(void)
{
int fd, rv;
- snprintf(fifo_path, PATH_MAX-1, "%s/%s.fifo", RUN_DIR, prog_name);
+ snprintf(fifo_path, PATH_MAX-1, "%s/%s.fifo", DAEMON_RUN_DIR, prog_name);
rv = mkfifo(fifo_path, (S_IRUSR | S_IWUSR));
if (rv && errno != EEXIST) {
@@ -291,7 +301,7 @@ static int wait_options(void)
goto out;
}
- strncpy(path, val1, PATH_MAX-1);
+ strncpy(lease_path, val1, PATH_MAX-1);
our_host_id = atoi(val2);
if (!our_host_id || our_host_id > MAX_HOSTS) {
@@ -300,13 +310,13 @@ static int wait_options(void)
goto out;
}
- if (!path[0]) {
+ if (!lease_path[0]) {
log_error("wait_options invalid path");
rv = -1;
goto out;
}
- log_debug("wait_options -p %s -i %d", path, our_host_id);
+ log_debug("wait_options -p %s -i %d", lease_path, our_host_id);
rv = 0;
out:
close(fd);
@@ -319,7 +329,7 @@ static int send_options(void)
{
int fd, rv;
- snprintf(fifo_path, PATH_MAX-1, "%s/%s.fifo", RUN_DIR, prog_name);
+ snprintf(fifo_path, PATH_MAX-1, "%s/%s.fifo", DAEMON_RUN_DIR, prog_name);
fd = open(fifo_path, O_WRONLY|O_CLOEXEC);
if (fd < 0) {
@@ -329,7 +339,7 @@ static int send_options(void)
memset(fifo_line, 0, sizeof(fifo_line));
- snprintf(fifo_line, PATH_MAX-1, "-p %s -i %d", path, our_host_id);
+ snprintf(fifo_line, PATH_MAX-1, "-p %s -i %d", lease_path, our_host_id);
rv = write(fd, fifo_line, sizeof(fifo_line));
if (rv < 0) {
@@ -342,6 +352,107 @@ static int send_options(void)
return rv;
}
+/*
+ * A running fence_sanlock agent has a pid file we can read.
+ * We use this to check what host_id it's fencing, so we can
+ * see if we are the low host_id in a two_node fencing duel.
+ * We also check /proc/<pid> to verify that the agent is
+ * still running (that the pid file isn't stale from the
+ * agent being killed).
+ */
+
+static int check_fence_agent(int *victim_host_id)
+{
+ DIR *d;
+ FILE *file;
+ struct dirent *de;
+ char path[PATH_MAX];
+ char rest[512];
+ char name[512];
+ int agent_pid, victim_id, rv;
+ int error = -ENOENT;
+
+ d = opendir(AGENT_RUN_DIR);
+ if (!d)
+ return -1;
+
+ while ((de = readdir(d))) {
+ if (de->d_name[0] == '.')
+ continue;
+
+ if (strncmp(de->d_name, "fence_sanlock.pid.", strlen("fence_sanlock.pid.")))
+ continue;
+
+ agent_pid = 0;
+ victim_id = 0;
+ memset(rest, 0, sizeof(rest));
+ memset(name, 0, sizeof(name));
+
+ log_debug("read %s", de->d_name);
+
+ /*
+ * read /var/run/fence_sanlock/fence_sanlock.pid.<pid>
+ * to get the pid of fence_sanlock and the victim's host_id
+ *
+ * read /proc/pid/comm to check that the pid from that file
+ * is still running and hasn't been killed
+ *
+ * if both of these checks are successful, then return 0
+ * with the victim host id
+ *
+ * if any fails, continue to check for another pid file
+ */
+
+ memset(path, 0, sizeof(path));
+ snprintf(path, PATH_MAX-1, "%s/%s", AGENT_RUN_DIR, de->d_name);
+
+ file = fopen(path, "r");
+ if (!file) {
+ log_debug("open error %d %s", errno, path);
+ continue;
+ }
+
+ rv = fscanf(file, "%d host_id %d %[^\n]s\n", &agent_pid, &victim_id, rest);
+ fclose(file);
+
+ log_debug("agent_pid %d victim %d %s", agent_pid, victim_id, rest);
+
+ if (rv != 3 || !agent_pid || !victim_id) {
+ log_debug("%s scan file error %d", de->d_name, rv);
+ continue;
+ }
+
+ memset(path, 0, sizeof(path));
+ snprintf(path, PATH_MAX-1, "/proc/%d/comm", agent_pid);
+
+ file = fopen(path, "r");
+ if (!file) {
+ log_debug("%s open proc error %d %s", de->d_name, errno, path);
+ continue;
+ }
+
+ rv = fscanf(file, "%s", name);
+ fclose(file);
+
+ if (rv != 1 || strncmp(name, "fence_sanlock", strlen("fence_sanlock"))) {
+ log_debug("%s scan proc error %d %s", de->d_name, rv, name);
+ continue;
+ }
+
+ /*
+ * we found a running fence_sanlock process,
+ * return the host_id that it's fencing
+ */
+
+ *victim_host_id = victim_id;
+ error = 0;
+ break;
+ }
+ closedir(d);
+
+ return error;
+}
+
static void print_usage(void)
{
printf("Usage:\n");
@@ -369,6 +480,7 @@ int main(int argc, char *argv[])
int optchar;
int sock, con, rv, i;
int align;
+ int victim_host_id;
while (cont) {
optchar = getopt(argc, argv, "Dp:i:hVws");
@@ -378,7 +490,7 @@ int main(int argc, char *argv[])
daemon_debug = 1;
break;
case 'p':
- strcpy(path, optarg);
+ strcpy(lease_path, optarg);
break;
case 'i':
our_host_id = atoi(optarg);
@@ -415,7 +527,7 @@ int main(int argc, char *argv[])
exit(1);
}
- if (!wait_opts && (!our_host_id || !path[0])) {
+ if (!wait_opts && (!our_host_id || !lease_path[0])) {
fprintf(stderr, "-i and -p options required\n");
exit(1);
}
@@ -479,7 +591,7 @@ int main(int argc, char *argv[])
}
memset(&disk, 0, sizeof(disk));
- sprintf(disk.path, "%s", path);
+ sprintf(disk.path, "%s", lease_path);
align = sanlock_direct_align(&disk);
if (align < 0) {
@@ -488,7 +600,7 @@ int main(int argc, char *argv[])
}
memset(&ls, 0, sizeof(ls));
- sprintf(ls.host_id_disk.path, "%s", path);
+ sprintf(ls.host_id_disk.path, "%s", lease_path);
strcpy(ls.name, "fence");
ls.host_id = our_host_id;
@@ -506,7 +618,7 @@ int main(int argc, char *argv[])
r = (struct sanlk_resource *)&rdbuf;
strcpy(r->lockspace_name, "fence");
sprintf(r->name, "h%d", our_host_id);
- sprintf(r->disks[0].path, "%s", path);
+ sprintf(r->disks[0].path, "%s", lease_path);
r->disks[0].offset = our_host_id * align;
r->num_disks = 1;
@@ -593,16 +705,80 @@ int main(int argc, char *argv[])
log_error("wdmd_test_live 0 error %d", rv);
break;
- } else if (lockspace_recovery) {
+ }
+
+ if (lockspace_recovery) {
/*
* The sanlock daemon sends SIGTERM when the lockspace
* host_id cannot be renewed for a while and it enters
* recovery.
*/
+
log_error("sanlock renewals failed, our watchdog will fire");
- break;
+ }
+
+ if (we_are_victim && we_are_fencing) {
+ /*
+ * Automatically resolve two_node fencing duel.
+ *
+ * Two nodes are fencing each other, which happens
+ * in a two_node cluster where each can has quorum
+ * by itself. We pick the low host_id to survive.
+ *
+ * (Might we get another SIGUSR1 callback due to
+ * the request not being cleared right away? Would
+ * that matter here?)
+ *
+ * Note that a global victim_host_id doesn't work
+ * if more than one fence_sanlock is run concurrently,
+ * i.e. we're fencing more than one host at a time.
+ * But, this doesn't matter because this case is
+ * only concerned about two_node fencing duels where
+ * we can only be fencing one other node.
+ */
+
+ rv = check_fence_agent(&victim_host_id);
+
+ if (!rv) {
+ if (our_host_id < victim_host_id) {
+ log_error("fence duel winner, our_host_id %d other %d",
+ our_host_id, victim_host_id);
+ we_are_victim = 0;
+ we_are_fencing = 0;
+ } else {
+ log_error("fence duel loser, our_host_id %d other %d",
+ our_host_id, victim_host_id);
+ we_are_fencing = 0;
+ }
+ } else {
+ log_error("fence duel ignore, agent %d", rv);
+ we_are_fencing = 0;
+ }
+ }
+
+ if (!we_are_victim && we_are_fencing) {
+ /*
+ * We can start fencing someone before we notice that
+ * we are also being fenced in a duel. So, don't clear
+ * we_are_fencing until fence_sanlock is finished and
+ * removes fence_sanlock.log
+ *
+ * We do this for all fencing, but it's only really
+ * needed for two_node fencing duels where we need
+ * to be aware of when we are fencing.
+ */
- } else if (we_are_victim) {
+ rv = check_fence_agent(&victim_host_id);
+ if (rv < 0) {
+ log_debug("fence agent not found %d", rv);
+ we_are_fencing = 0;
+ victim_host_id = 0;
+ } else {
+ log_debug("fence agent running host_id %d", victim_host_id);
+ }
+ }
+
+ if (we_are_victim) {
/*
* The sanlock daemon has seen someone request our
* lease, which happens when they run fence_sanlock
@@ -624,9 +800,12 @@ int main(int argc, char *argv[])
* kernel due to failure (cluster partition) that caused
* our fencing, and couldn't be forcibly cleaned up.
*/
+
log_error("we are being fenced, our watchdog will fire");
+ }
- } else if (now - live_time >= LIVE_INTERVAL) {
+ if (!we_are_victim && !lockspace_recovery &&
+ (now - live_time >= LIVE_INTERVAL)) {
/*
* How to pick the expire_time. From the perspective
* of fence_sanlockd the expire_time isn't really
@@ -661,7 +840,7 @@ int main(int argc, char *argv[])
log_error("wdmd_test_live error %d", rv);
}
- if (we_are_victim || lockspace_recovery) {
+ if (we_are_victim || lockspace_recovery || we_are_fencing) {
poll_timeout = 10000;
} else {
sleep_seconds = live_time + LIVE_INTERVAL - monotime();
@@ -672,7 +851,7 @@ int main(int argc, char *argv[])
out_release:
sanlock_release(sock, -1, 0, 1, &r);
out_lockspace:
- sanlock_rem_lockspace(&ls, 0);
+ sanlock_rem_lockspace(&ls, SANLK_REM_ASYNC);
out_refcount:
wdmd_refcount_clear(con);
out_lockfile:
diff --git a/init.d/fence_sanlockd b/init.d/fence_sanlockd
index c7210d7..fb5fae8 100755
--- a/init.d/fence_sanlockd
+++ b/init.d/fence_sanlockd
@@ -22,6 +22,7 @@
. /etc/rc.d/init.d/functions
prog="fence_sanlockd"
+agent="fence_sanlock"
runfile="/var/run/$prog/$prog.pid"
fifofile="/var/run/$prog/$prog.fifo"
lockfile="/var/lock/subsys/$prog"
@@ -42,10 +43,16 @@ start() {
[ ! -d /var/run/$prog ] && install -d -m 775 /var/run/$prog
+ [ ! -d /var/run/$agent ] && install -d -m 775 /var/run/$agent
+
[ -n "$(which restorecon)" ] && \
[ -x "$(which restorecon)" ] && \
restorecon /var/run/$prog
+ [ -n "$(which restorecon)" ] && \
+ [ -x "$(which restorecon)" ] && \
+ restorecon /var/run/$agent
+
echo -n $"Starting $prog: "
daemon $prog $FENCESANLOCKDOPTS
retval=$?
@@ -55,6 +62,15 @@ start() {
}
stop() {
+ agent_ps="$(ps ax -o pid,args | grep fence_sanlock | grep -v grep | grep -v fence_sanlockd)"
+
+ [ -n "$agent_ps" ] && {
+ agent_pid="$(echo $agent_ps | awk '{print $1}')"
+ echo -n "cannot stop while $agent $agent_pid is running"
+ failure; echo
+ return 1
+ }
+
# Ideally, we'd like a general way to check if anything
# needs fencing to continue running, but without that,
# check what we know, which is that dlm requires it.
11 years, 6 months
Changes to 'wdmd-script'
by David Teigland
New branch 'wdmd-script' available with the following commits:
commit 8b33cd7f861a075e0195507577baf8cbaed8ef5e
Author: David Teigland <teigland(a)redhat.com>
Date: Wed Sep 19 15:15:05 2012 -0500
wdmd: new script handling
Rewrite the code for using test scripts,
enabled by -S 1. Also added dumping
daemon state by wdmd --dump.
Signed-off-by: David Teigland <teigland(a)redhat.com>
11 years, 6 months