Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package libdlm for openSUSE:Factory checked 
in at 2021-10-20 20:22:59
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/libdlm (Old)
 and      /work/SRC/openSUSE:Factory/.libdlm.new.1890 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "libdlm"

Wed Oct 20 20:22:59 2021 rev:53 rq:926153 version:4.1.0

Changes:
--------
--- /work/SRC/openSUSE:Factory/libdlm/libdlm.changes    2020-10-18 
16:19:52.328449454 +0200
+++ /work/SRC/openSUSE:Factory/.libdlm.new.1890/libdlm.changes  2021-10-20 
20:23:24.345345536 +0200
@@ -1,0 +2,30 @@
+Mon Oct 18 08:29:00 UTC 2021 - [email protected]
+
+- Update to v4.1.0+ (bsc#1191734)
+ * include some fixes/enhancements upstream patches based on 4.1.0 tag
+   + bug-1191734_0001-libdlm-add-stdint.h-to-api-header.patch
+   + bug-1191734_0002-dlm_controld-create-var-parent-directories.patch
+   + bug-1191734_0003-stonith_helper-fix-build.patch
+   + bug-1191734_0004-plock-move-clear-waiter-to-debug-info.patch
+   + bug-1191734_0005-treewide-try-to-resolve-symbols-at-linking-time.patch
+   + bug-1191734_0006-dlm_controld-add-version-check-for-libquorum.patch
+   + bug-1191734_0007-dlm_tool-man-add-command-joinleave-USAGE.patch
+   + bug-1191734_0008-man-add-reload_config-in-dlm_tool-dlm.conf.patch
+   + bug-1191734_0009-add-new-dlm_tool-command-reload_config.patch
+   + bug-1191734_0010-dlm_tool-man-add-new-command-set_config.patch
+   + bug-1191734_0011-dlm_tool-dlm_controld-add-new-feature-set_config.patch
+   + bug-1191734_0012-fix-some-minor-bugs.patch
+   + bug-1191734_0013-dlm_controld-fix-string-copies.patch
+   + bug-1191734_0014-man-page-updates.patch
+ * patch for compatible with corosync-2.4.5+
+   + bug-1191734_0015-Revert-dlm_controld-add-version-check-for-libquorum.patch
+   + 
bug-1191734_0016-Revert-dlm_controld-use-new-quorum-api-to-detect-mis.patch
+ * drop 2 patches which are already included in upstream code
+   - cluster-ringid-seq.patch
+   - sysmacros.patch
+ * change name and modify patch for code changed
+   - dlm_controld-add-note-that-the-dlm-file-is-not-creat.patch
+   + 0004-man-dlm.conf-add-note-that-the-file-is-not-creat.patch
+ * change libdlm.spec to seperate upsteam patch and suse special patch
+
+-------------------------------------------------------------------

Old:
----
  cluster-ringid-seq.patch
  dlm-4.0.9.tar.gz
  dlm_controld-add-note-that-the-dlm-file-is-not-creat.patch
  sysmacros.patch

New:
----
  0004-man-dlm.conf-add-note-that-the-file-is-not-creat.patch
  bug-1191734_0001-libdlm-add-stdint.h-to-api-header.patch
  bug-1191734_0002-dlm_controld-create-var-parent-directories.patch
  bug-1191734_0003-stonith_helper-fix-build.patch
  bug-1191734_0004-plock-move-clear-waiter-to-debug-info.patch
  bug-1191734_0005-treewide-try-to-resolve-symbols-at-linking-time.patch
  bug-1191734_0006-dlm_controld-add-version-check-for-libquorum.patch
  bug-1191734_0007-dlm_tool-man-add-command-joinleave-USAGE.patch
  bug-1191734_0008-man-add-reload_config-in-dlm_tool-dlm.conf.patch
  bug-1191734_0009-add-new-dlm_tool-command-reload_config.patch
  bug-1191734_0010-dlm_tool-man-add-new-command-set_config.patch
  bug-1191734_0011-dlm_tool-dlm_controld-add-new-feature-set_config.patch
  bug-1191734_0012-fix-some-minor-bugs.patch
  bug-1191734_0013-dlm_controld-fix-string-copies.patch
  bug-1191734_0014-man-page-updates.patch
  bug-1191734_0015-Revert-dlm_controld-add-version-check-for-libquorum.patch
  bug-1191734_0016-Revert-dlm_controld-use-new-quorum-api-to-detect-mis.patch
  dlm-4.1.0.tar.gz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ libdlm.spec ++++++
--- /var/tmp/diff_new_pack.ITu25V/_old  2021-10-20 20:23:25.089345996 +0200
+++ /var/tmp/diff_new_pack.ITu25V/_new  2021-10-20 20:23:25.093345998 +0200
@@ -1,7 +1,7 @@
 #
 # spec file for package libdlm
 #
-# Copyright (c) 2020 SUSE LLC
+# Copyright (c) 2021 SUSE LLC
 #
 # All modifications and additions to the file contributed by third parties
 # remain the property of their copyright owners, unless otherwise agreed
@@ -34,16 +34,34 @@
 Summary:        Application interface to the kernel's distributed lock manager
 License:        GPL-2.0-only AND GPL-2.0-or-later AND LGPL-2.1-or-later
 Group:          Productivity/Clustering/HA
-Version:        4.0.9
+Version:        4.1.0
 Release:        0
 URL:            https://pagure.io/dlm/
 Source:         https://releases.pagure.org/dlm/dlm-%{version}.tar.gz
-Patch1:         0001-makefile-for-diff-arch.patch
-Patch2:         0002-remove-sd-notify.patch
-Patch3:         0003-bnc#874705-nodes-without-quorum.patch
-Patch4:         sysmacros.patch
-Patch5:         cluster-ringid-seq.patch
-Patch6:         dlm_controld-add-note-that-the-dlm-file-is-not-creat.patch
+####################
+# upstream patch
+Patch001:       bug-1191734_0001-libdlm-add-stdint.h-to-api-header.patch
+Patch002:       
bug-1191734_0002-dlm_controld-create-var-parent-directories.patch
+Patch003:       bug-1191734_0003-stonith_helper-fix-build.patch
+Patch004:       bug-1191734_0004-plock-move-clear-waiter-to-debug-info.patch
+Patch005:       
bug-1191734_0005-treewide-try-to-resolve-symbols-at-linking-time.patch
+Patch006:       
bug-1191734_0006-dlm_controld-add-version-check-for-libquorum.patch
+Patch007:       bug-1191734_0007-dlm_tool-man-add-command-joinleave-USAGE.patch
+Patch008:       
bug-1191734_0008-man-add-reload_config-in-dlm_tool-dlm.conf.patch
+Patch009:       bug-1191734_0009-add-new-dlm_tool-command-reload_config.patch
+Patch010:       bug-1191734_0010-dlm_tool-man-add-new-command-set_config.patch
+Patch011:       
bug-1191734_0011-dlm_tool-dlm_controld-add-new-feature-set_config.patch
+Patch012:       bug-1191734_0012-fix-some-minor-bugs.patch
+Patch013:       bug-1191734_0013-dlm_controld-fix-string-copies.patch
+Patch014:       bug-1191734_0014-man-page-updates.patch
+# suse special patch
+Patch101:       0001-makefile-for-diff-arch.patch
+Patch102:       0002-remove-sd-notify.patch
+Patch103:       0003-bnc#874705-nodes-without-quorum.patch
+Patch104:       0004-man-dlm.conf-add-note-that-the-file-is-not-creat.patch
+Patch105:       
bug-1191734_0015-Revert-dlm_controld-add-version-check-for-libquorum.patch
+Patch106:       
bug-1191734_0016-Revert-dlm_controld-use-new-quorum-api-to-detect-mis.patch
+###################
 BuildRequires:  fdupes
 BuildRequires:  glib2-devel
 BuildRequires:  libcorosync-devel

++++++ 0004-man-dlm.conf-add-note-that-the-file-is-not-creat.patch ++++++
>From 74595a9400f20c4d4fd83c0a748ddb875d39f578 Mon Sep 17 00:00:00 2001
From: Gang He <[email protected]>
Date: Mon, 14 Sep 2020 15:51:01 +0800
Subject: [PATCH] man dlm.conf: add note that the file is not created

/etc/dlm/dlm.conf file is not created during installation.
we need to tell the user this configuration file does not exist.

Signed-off-by: Gang He <[email protected]>
---
 dlm_controld/dlm.conf.5 | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/dlm_controld/dlm.conf.5 b/dlm_controld/dlm.conf.5
index 0eb226358100..02a52e977f54 100644
--- a/dlm_controld/dlm.conf.5
+++ b/dlm_controld/dlm.conf.5
@@ -422,6 +422,12 @@ node id=1 mark=42
 
 For local nodes this value doesn't have any effect.
 
+.SH NOTES
+.B /etc/dlm/dlm.conf
+file is not created during installation.
+.br
+If you want to modify any default configuration items, you need to create and 
edit the file.
+
 .SH SEE ALSO
 .BR dlm_controld (8),
 .BR dlm_tool (8)
-- 
2.12.3

++++++ bug-1191734_0001-libdlm-add-stdint.h-to-api-header.patch ++++++
>From 2baadda85cdc3d5d1e247732b736dc4897ac1556 Mon Sep 17 00:00:00 2001
From: Alexander Aring <[email protected]>
Date: Thu, 11 Feb 2021 16:40:11 -0500
Subject: [PATCH 01/14] libdlm: add stdint.h to api header

This patch adds a include of stdint.h to the libdlm api header,
otherwise application linking to it need to be sure to include the stdint
header before libdlm header as a workaround.
---
 libdlm/libdlm.h | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/libdlm/libdlm.h b/libdlm/libdlm.h
index d025ef8cf0f0..9255181cdb6f 100644
--- a/libdlm/libdlm.h
+++ b/libdlm/libdlm.h
@@ -10,6 +10,8 @@
 #ifndef __LIBDLM_H
 #define __LIBDLM_H
 
+#include <stdint.h>
+
 /*
  * Typedefs for things that are compatible with the kernel but replicated here
  * so that users only need the libdlm include file.  libdlm itself needs the
-- 
2.33.0

++++++ bug-1191734_0002-dlm_controld-create-var-parent-directories.patch ++++++
>From 4c774ebe7358d4ce773502d1703046c29371b4ec Mon Sep 17 00:00:00 2001
From: Alexander Aring <[email protected]>
Date: Wed, 31 Mar 2021 16:20:42 -0400
Subject: [PATCH 02/14] dlm_controld: create var parent directories

This patch creates /var/log/dlm_controld and /var/run/dlm_controld
and it's parents if not exists before. In case of logging there was a
likely issue no log file is created when /var/log/dlm_controld didn't
exists before starting dlm_controld.

Reported-by: Bob Peterson <[email protected]>
---
 dlm_controld/dlm_daemon.h |  8 ++++++--
 dlm_controld/logging.c    | 24 ++++++++++++++++++++++++
 dlm_controld/main.c       | 20 ++++++++++++++++----
 3 files changed, 46 insertions(+), 6 deletions(-)

diff --git a/dlm_controld/dlm_daemon.h b/dlm_controld/dlm_daemon.h
index 45b295eafe2b..436fc9109aa6 100644
--- a/dlm_controld/dlm_daemon.h
+++ b/dlm_controld/dlm_daemon.h
@@ -65,8 +65,12 @@
 
 /* TODO: get CONFDIR, LOGDIR, RUNDIR from build */
 
-#define RUNDIR                   "/var/run/dlm_controld"
-#define LOGDIR                   "/var/log/dlm_controld"
+#define SYS_VARDIR              "/var"
+#define SYS_RUNDIR              SYS_VARDIR "/run"
+#define SYS_LOGDIR              SYS_VARDIR "/log"
+
+#define RUNDIR                  SYS_RUNDIR "/dlm_controld"
+#define LOGDIR                  SYS_LOGDIR "/dlm_controld"
 #define CONFDIR                  "/etc/dlm"
 
 #define RUN_FILE_NAME            "dlm_controld.pid"
diff --git a/dlm_controld/logging.c b/dlm_controld/logging.c
index 4aa3406c0725..d48b8aebc237 100644
--- a/dlm_controld/logging.c
+++ b/dlm_controld/logging.c
@@ -16,6 +16,9 @@ static FILE *logfile_fp;
 
 void init_logging(void)
 {
+       mode_t old_umask;
+       int rv;
+
        syslog_facility = DEFAULT_SYSLOG_FACILITY;
        syslog_priority = DEFAULT_SYSLOG_PRIORITY;
        logfile_priority = DEFAULT_LOGFILE_PRIORITY;
@@ -28,6 +31,26 @@ void init_logging(void)
                logfile_priority = LOG_DEBUG;
 
        if (logfile[0]) {
+               old_umask = umask(0077);
+               rv = mkdir(SYS_VARDIR, 0700);
+               if (rv < 0 && errno != EEXIST) {
+                       umask(old_umask);
+                       goto skip_logfile;
+               }
+
+               rv = mkdir(SYS_LOGDIR, 0700);
+               if (rv < 0 && errno != EEXIST) {
+                       umask(old_umask);
+                       goto skip_logfile;
+               }
+
+               rv = mkdir(LOGDIR, 0700);
+               if (rv < 0 && errno != EEXIST) {
+                       umask(old_umask);
+                       goto skip_logfile;
+               }
+               umask(old_umask);
+
                logfile_fp = fopen(logfile, "a+");
                if (logfile_fp != NULL) {
                        int fd = fileno(logfile_fp);
@@ -35,6 +58,7 @@ void init_logging(void)
                }
        }
 
+skip_logfile:
        openlog(DAEMON_NAME, LOG_CONS | LOG_PID, syslog_facility);
 }
 
diff --git a/dlm_controld/main.c b/dlm_controld/main.c
index c35756d48c0b..504cafa12ec6 100644
--- a/dlm_controld/main.c
+++ b/dlm_controld/main.c
@@ -1598,7 +1598,7 @@ static int loop(void)
        return rv;
 }
 
-static int lockfile(const char *dir, const char *name)
+static int lockfile(const char *name)
 {
        char path[PATH_MAX];
        char buf[16];
@@ -1607,14 +1607,26 @@ static int lockfile(const char *dir, const char *name)
        int fd, rv;
 
        old_umask = umask(0022);
-       rv = mkdir(dir, 0775);
+       rv = mkdir(SYS_VARDIR, 0775);
+       if (rv < 0 && errno != EEXIST) {
+               umask(old_umask);
+               return rv;
+       }
+
+       rv = mkdir(SYS_RUNDIR, 0775);
+       if (rv < 0 && errno != EEXIST) {
+               umask(old_umask);
+               return rv;
+       }
+
+       rv = mkdir(RUNDIR, 0775);
        if (rv < 0 && errno != EEXIST) {
                umask(old_umask);
                return rv;
        }
        umask(old_umask);
 
-       snprintf(path, PATH_MAX, "%s/%s", dir, name);
+       snprintf(path, PATH_MAX, "%s/%s", RUNDIR, name);
 
        fd = open(path, O_CREAT|O_WRONLY|O_CLOEXEC, 0644);
        if (fd < 0) {
@@ -2125,7 +2137,7 @@ int main(int argc, char **argv)
 
        init_logging();
 
-       fd = lockfile(RUNDIR, RUN_FILE_NAME);
+       fd = lockfile(RUN_FILE_NAME);
        if (fd < 0)
                return 1;
 
-- 
2.33.0

++++++ bug-1191734_0003-stonith_helper-fix-build.patch ++++++
>From 5afd9fdc0ef202633f57abc063a5a2c6cef1d61d Mon Sep 17 00:00:00 2001
From: David Teigland <[email protected]>
Date: Wed, 28 Jul 2021 16:12:43 -0500
Subject: [PATCH 03/14] stonith_helper: fix build

include stdlib
use pkg-config to get pacemaker headers
---
 fence/Makefile         | 1 +
 fence/stonith_helper.c | 1 +
 2 files changed, 2 insertions(+)

diff --git a/fence/Makefile b/fence/Makefile
index b927879eb141..1f6dd6b2c40e 100644
--- a/fence/Makefile
+++ b/fence/Makefile
@@ -20,6 +20,7 @@ CFLAGS += -D_GNU_SOURCE -O2 -ggdb \
 CFLAGS += -fPIE -DPIE
 CFLAGS += `xml2-config --cflags`
 CFLAGS += -I../include
+CFLAGS += $(shell pkg-config --cflags pacemaker-fencing)
 
 LDFLAGS += -Wl,-z,relro -pie
 LDFLAGS += `xml2-config --libs`
diff --git a/fence/stonith_helper.c b/fence/stonith_helper.c
index 3a0768af2830..b1db352ae04f 100644
--- a/fence/stonith_helper.c
+++ b/fence/stonith_helper.c
@@ -8,6 +8,7 @@
 
 #include <stdio.h>
 #include <stdint.h>
+#include <stdlib.h>
 #include <string.h>
 #include <unistd.h>
 #include <syslog.h>
-- 
2.33.0

++++++ bug-1191734_0004-plock-move-clear-waiter-to-debug-info.patch ++++++
>From 52c7bf79d447d9d015d676239cf1f2f9b2e5860c Mon Sep 17 00:00:00 2001
From: Alexander Aring <[email protected]>
Date: Wed, 4 Aug 2021 10:15:37 -0400
Subject: [PATCH 04/14] plock: move clear waiter to debug info

This patch moves the clear waiter log message for a killed/interrupted
posix lock of a user space from error to debug. It can be confused to
see it as error in the log but it's necessary to cleanup all waiters who
are waiting for the lock.

Reported-by: Shane Bradley <[email protected]>
---
 dlm_controld/plock.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/dlm_controld/plock.c b/dlm_controld/plock.c
index 992fb16fef1f..692787e2b758 100644
--- a/dlm_controld/plock.c
+++ b/dlm_controld/plock.c
@@ -660,7 +660,7 @@ static void clear_waiters(struct lockspace *ls, struct 
resource *r,
 
                list_del(&w->list);
 
-               log_elock(ls, "clear waiter %llx %llx-%llx %d/%u/%llx",
+               log_dlock(ls, "clear waiter %llx %llx-%llx %d/%u/%llx",
                          (unsigned long long)in->number,
                          (unsigned long long)in->start,
                          (unsigned long long)in->end,
-- 
2.33.0

++++++ bug-1191734_0005-treewide-try-to-resolve-symbols-at-linking-time.patch 
++++++
>From 7bb5570aa5b215ebbcd2f8cce88d112d17c0e998 Mon Sep 17 00:00:00 2001
From: Alexander Aring <[email protected]>
Date: Tue, 7 Sep 2021 11:44:41 -0400
Subject: [PATCH 05/14] treewide: try to resolve symbols at linking time

This patch passes linker flags to the linker that all symbols should be
resolved at linking time. If this is not possible the linker will fail
to link.
---
 dlm_controld/Makefile | 4 ++--
 dlm_tool/Makefile     | 2 +-
 fence/Makefile        | 2 +-
 libdlm/Makefile       | 4 ++--
 4 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/dlm_controld/Makefile b/dlm_controld/Makefile
index fbc8926c8676..667998076acc 100644
--- a/dlm_controld/Makefile
+++ b/dlm_controld/Makefile
@@ -49,9 +49,9 @@ BIN_CFLAGS += $(CFLAGS) -fPIE -DPIE
 BIN_CFLAGS += -I../include -I../libdlm
 LIB_CFLAGS += $(CFLAGS) -fPIC
 
-BIN_LDFLAGS += $(LDFLAGS) -Wl,-z,relro -pie
+BIN_LDFLAGS += $(LDFLAGS) -Wl,-z,relro -Wl,-z,defs -pie
 BIN_LDFLAGS += -lpthread -lrt -lcpg -lcmap -lcfg -lquorum -luuid
-LIB_LDFLAGS += $(LDFLAGS) -Wl,-z,relro -pie
+LIB_LDFLAGS += $(LDFLAGS) -Wl,-z,relro -Wl,-z,defs -pie
 
 PKG_CONFIG ?= pkg-config
 ifeq ($(USE_SD_NOTIFY),yes)
diff --git a/dlm_tool/Makefile b/dlm_tool/Makefile
index 80d7725791f3..7b42638c0e4a 100644
--- a/dlm_tool/Makefile
+++ b/dlm_tool/Makefile
@@ -20,7 +20,7 @@ CFLAGS += -D_GNU_SOURCE -O2 -ggdb \
 CFLAGS += -fPIE -DPIE
 CFLAGS += -I../include -I../libdlm -I../dlm_controld
 
-LDFLAGS += -Wl,-z,relro -pie
+LDFLAGS += -Wl,-z,relro -Wl,-z,defs -pie
 LDFLAGS += -L../libdlm -L../dlm_controld
 LDFLAGS += -lpthread -ldlm -ldlmcontrol
 
diff --git a/fence/Makefile b/fence/Makefile
index 1f6dd6b2c40e..2b080468eaa0 100644
--- a/fence/Makefile
+++ b/fence/Makefile
@@ -22,7 +22,7 @@ CFLAGS += `xml2-config --cflags`
 CFLAGS += -I../include
 CFLAGS += $(shell pkg-config --cflags pacemaker-fencing)
 
-LDFLAGS += -Wl,-z,relro -pie
+LDFLAGS += -Wl,-z,relro -Wl,-z,defs -pie
 LDFLAGS += `xml2-config --libs`
 LDFLAGS += -ldl
 
diff --git a/libdlm/Makefile b/libdlm/Makefile
index ab32761912b3..313c2a08f17e 100644
--- a/libdlm/Makefile
+++ b/libdlm/Makefile
@@ -84,8 +84,8 @@ CFLAGS += -D_GNU_SOURCE -O2 -ggdb \
 LIB_CFLAGS += $(CFLAGS) -D_REENTRANT
 LLT_CFLAGS += $(CFLAGS)
 
-LIB_LDFLAGS += $(LDFLAGS) -lpthread
-LLT_LDFLAGS += $(LDFLAGS)
+LIB_LDFLAGS += $(LDFLAGS) -lpthread -Wl,-z,defs
+LLT_LDFLAGS += $(LDFLAGS) -Wl,-z,defs
 
 all: $(LIB_TARGET) $(LLT_TARGET) $(LIB_PC) $(LLT_PC)
 
-- 
2.33.0

++++++ bug-1191734_0006-dlm_controld-add-version-check-for-libquorum.patch 
++++++
>From 3201db3835c85a1d9a407e621bff7902896e8a82 Mon Sep 17 00:00:00 2001
From: Alexander Aring <[email protected]>
Date: Tue, 7 Sep 2021 12:06:00 -0400
Subject: [PATCH 06/14] dlm_controld: add version check for libquorum

This patch adds a simple version check for libquorum. Since commit
2e893b98 ("dlm_controld: use new quorum api to detect missed failures")
dlm_controld uses functionality which is only available in libquorum
3.1.0 and upwards.
---
 dlm_controld/Makefile | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/dlm_controld/Makefile b/dlm_controld/Makefile
index 667998076acc..8cfc97e6909a 100644
--- a/dlm_controld/Makefile
+++ b/dlm_controld/Makefile
@@ -60,6 +60,10 @@ ifeq ($(USE_SD_NOTIFY),yes)
        BIN_LDFLAGS += $(shell $(PKG_CONFIG) --libs libsystemd)
 endif
 
+ifeq (, $(shell $(PKG_CONFIG) --libs "libquorum >= 3.1.0"))
+        $(error "Requires libquorum at least version 3.1.0")
+endif
+
 all: $(LIB_TARGET) $(BIN_TARGET) $(LIB_PC)
 
 $(BIN_TARGET): $(BIN_SOURCE)
-- 
2.33.0

++++++ bug-1191734_0007-dlm_tool-man-add-command-joinleave-USAGE.patch ++++++
>From c4828edd9dae2d606a693788d7724b8411722f19 Mon Sep 17 00:00:00 2001
From: Heming Zhao <[email protected]>
Date: Fri, 8 Oct 2021 09:33:35 +0800
Subject: [PATCH 07/14] dlm_tool man: add command "joinleave" & "USAGE"

add missing command "joinleave".
add "USAGE" section to show detail usage.

Signed-off-by: Heming Zhao <[email protected]>
---
 dlm_tool/dlm_tool.8 | 80 +++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 80 insertions(+)

diff --git a/dlm_tool/dlm_tool.8 b/dlm_tool/dlm_tool.8
index bbc11c261b7e..7e82f8908ed6 100644
--- a/dlm_tool/dlm_tool.8
+++ b/dlm_tool/dlm_tool.8
@@ -48,6 +48,10 @@ dlm_tool \- a utility for the dlm and dlm_controld daemon
 .br
        Leave a lockspace.
 
+.BI joinleave " name"
+.br
+       Do two actions: first Join then Leave a lockspace. (mainly for test)
+
 .BI lockdebug " name"
 .br
        Complete display of locks from the lockspace.
@@ -112,6 +116,82 @@ Print help, then exit
 .B \-V
 Print program version information, then exit
 
+.SH USAGE
+
+.B dlm_tool ls [-n] [ls_name]
+
+-
+
+.B dlm_tool status [-v]
+
+-
+
+.B dlm_tool dump
+
+-
+
+.B dlm_tool dump_config
+
+-
+
+.B dlm_tool fence_ack \fInodeid\fP
+
+* run "dlm_tool status -v" to get \fInodeid\fP
+
+-
+
+.B dlm_tool log_plock
+
+-
+
+.B dlm_tool plocks \fIls-name\fP
+
+-
+
+.B dlm_tool join [-e 0|1] [-f 0|1] \fIls-name\fP
+
+-
+
+.B dlm_tool leave \fIls-name\fP
+
+-
+
+.B dlm_tool joinleave [-e 0|1] [-f 0|1] \fIls-name\fP
+
+-
+
+.B dlm_tool lockdebug [-s] [-v] [-w] \fIls-name\fP
+
+-
+
+.B dlm_tool lockdump [-M] \fIls-name\fP
+
+-
+
+.B dlm_tool run|run_start [-n] \fIcommand\fP
+
+* current run & run_start support \fIcommand\fP:
+.br
+  - "lvm lvchange --refresh"
+.br
+  - "lvm lvs"
+
+-
+
+.B dlm_tool run_check|run_cancel [-i "sec"] \fIuuid\fP
+
+-
+
+.B dlm_tool run_list
+
+-
+
+.B dlm_tool -h
+
+-
+
+.B dlm_tool -V
+
 .SH SEE ALSO
 .BR dlm_controld (8),
 .BR dlm.conf (5)
-- 
2.33.0

++++++ bug-1191734_0008-man-add-reload_config-in-dlm_tool-dlm.conf.patch ++++++
>From 6f764cceeb7350d8da33765da07462578f07e988 Mon Sep 17 00:00:00 2001
From: Heming Zhao <[email protected]>
Date: Fri, 8 Oct 2021 09:33:36 +0800
Subject: [PATCH 08/14] man: add reload_config in dlm_tool & dlm.conf

reload_config is a new command of dlm_tool. We could use this command
to change dlm_controld some settings on the fly.

This patch modifies man page to add usage for this new command.

Signed-off-by: Heming Zhao <[email protected]>
---
 dlm_controld/dlm.conf.5 | 42 ++++++++++++++++++++++++++++++-----------
 dlm_tool/dlm_tool.8     | 10 ++++++++++
 2 files changed, 41 insertions(+), 11 deletions(-)

diff --git a/dlm_controld/dlm.conf.5 b/dlm_controld/dlm.conf.5
index 1ce0c6445ee1..99e302a92bd2 100644
--- a/dlm_controld/dlm.conf.5
+++ b/dlm_controld/dlm.conf.5
@@ -34,7 +34,9 @@ protocol=tcp
 
 Options:
 
-log_debug
+daemon_debug(*)
+.br
+log_debug(*)
 .br
 protocol
 .br
@@ -42,23 +44,23 @@ bind_all
 .br
 mark
 .br
-debug_logfile
+debug_logfile(*)
 .br
 enable_plock
 .br
-plock_debug
+plock_debug(*)
 .br
-plock_rate_limit
+plock_rate_limit(*)
 .br
 plock_ownership
 .br
-drop_resources_time
+drop_resources_time(*)
 .br
-drop_resources_count
+drop_resources_count(*)
 .br
-drop_resources_age
+drop_resources_age(*)
 .br
-post_join_delay
+post_join_delay(*)
 .br
 enable_fencing
 .br
@@ -66,15 +68,33 @@ enable_concurrent_fencing
 .br
 enable_startup_fencing
 .br
-enable_quorum_fencing
+enable_quorum_fencing(*)
 .br
-enable_quorum_lockspace
+enable_quorum_lockspace(*)
 .br
-repeat_failed_fencing
+repeat_failed_fencing(*)
 .br
 enable_helper
 .br
 
+Option with tail (*) means this item can be reload on the fly by "dlm_tool 
reload_config". See \fB"Reload config"\fP for more examples.
+
+.SH Reload config
+
+dlm.conf can be changed then reloaded some settings on the fly, it gives users 
more flexible and powerful ability to manage dlm.
+
+The supported reload operations:
+.br
+- add a new item
+.br
+- remove an exist item
+.br
+- commented out an item
+.br
+- change an item value
+
+After modifying settings in dlm.conf, run "dlm_tool reload_config" to take 
effect. User can use "dlm_tool dump_config" to check the result. Again, only 
reloadable item can be changed.
+
 .SH Fencing
 
 A fence device definition begins with a
diff --git a/dlm_tool/dlm_tool.8 b/dlm_tool/dlm_tool.8
index 7e82f8908ed6..6c1d471abe68 100644
--- a/dlm_tool/dlm_tool.8
+++ b/dlm_tool/dlm_tool.8
@@ -28,6 +28,10 @@ dlm_tool \- a utility for the dlm and dlm_controld daemon
 .br
        Dump dlm_controld config settings.
 
+.B reload_config
+.br
+       Reload dlm_controld config settings from dlm.conf.
+
 .BI fence_ack " nodeid"
 .br
        Quit trying to fence a node.
@@ -134,6 +138,12 @@ Print program version information, then exit
 
 -
 
+.B dlm_tool reload_config
+
+* see examples in \fBdlm.conf(5)\fP
+
+-
+
 .B dlm_tool fence_ack \fInodeid\fP
 
 * run "dlm_tool status -v" to get \fInodeid\fP
-- 
2.33.0

++++++ bug-1191734_0009-add-new-dlm_tool-command-reload_config.patch ++++++
++++ 729 lines (skipped)

++++++ bug-1191734_0010-dlm_tool-man-add-new-command-set_config.patch ++++++
>From 041c136eb5f843369ec3fa5f0bbebde621121397 Mon Sep 17 00:00:00 2001
From: Heming Zhao <[email protected]>
Date: Fri, 8 Oct 2021 09:33:38 +0800
Subject: [PATCH 10/14] dlm_tool man: add new command set_config

add new command set_config and examples

Signed-off-by: Heming Zhao <[email protected]>
---
 dlm_tool/dlm_tool.8 | 131 +++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 128 insertions(+), 3 deletions(-)

diff --git a/dlm_tool/dlm_tool.8 b/dlm_tool/dlm_tool.8
index 6c1d471abe68..f6d869620822 100644
--- a/dlm_tool/dlm_tool.8
+++ b/dlm_tool/dlm_tool.8
@@ -32,6 +32,10 @@ dlm_tool \- a utility for the dlm and dlm_controld daemon
 .br
        Reload dlm_controld config settings from dlm.conf.
 
+.B set_config
+.br
+       Set dlm_controld config settings on the fly.
+
 .BI fence_ack " nodeid"
 .br
        Quit trying to fence a node.
@@ -144,6 +148,12 @@ Print program version information, then exit
 
 -
 
+.B dlm_tool set_config "dlm_controld-config-item=x"
+
+* see below \fBset_config EXAMPLES\fP section
+
+-
+
 .B dlm_tool fence_ack \fInodeid\fP
 
 * run "dlm_tool status -v" to get \fInodeid\fP
@@ -181,9 +191,9 @@ Print program version information, then exit
 .B dlm_tool run|run_start [-n] \fIcommand\fP
 
 * current run & run_start support \fIcommand\fP:
-.br
+.
   - "lvm lvchange --refresh"
-.br
+.
   - "lvm lvs"
 
 -
@@ -202,7 +212,122 @@ Print program version information, then exit
 
 .B dlm_tool -V
 
+.SH set_config EXAMPLES
+
+\fIdlm_tool set_config "xxx"\fP can do the dynamic config job. It makes 
possible to debug, or to do flexible operations on the fly.
+
+supported option items
+
+.RS
+.EX
+daemon_debug
+log_debug
+debug_logfile
+plock_debug
+plock_rate_limit
+drop_resources_time
+drop_resources_count
+drop_resources_age
+post_join_delay
+enable_quorum_fencing
+enable_quorum_lockspace
+repeat_failed_fencing
+.EE
+.RE
+
+.SS display style
+
+Currently, there are 5 ways of setting: default, cli, dlm.conf, reload_config, 
set_config
+
+The "dlm_tool dump_config" shows the config item by 4 styles.
+
+.TP
+key=val
+For default values that have not been set by cli or config file or dynamically.
+
+.TP
+key=val (cli option)
+For values that have been last set from a command line option.
+
+.TP
+key=val (dlm.conf)
+For values that have been last set from dlm.conf. (reload_config also belongs 
to this style)
+
+.TP
+key=val (set_config)
+For values that have been last set by dlm_tool set_config.
+
+.TP
+i.e.
+
+.EX
+# dlm_tool dump_config | head -n 5
+daemon_debug=1 (set_config)
+foreground=0
+log_debug=1 (dlm.conf)
+timewarn=0
+protocol=detect
+.EE
+
+In this case, the "daemon_debug" is set by set_config, the "log_debug" is set 
by dlm.conf.
+meanwhile foreground, timewarn & protocol are using default values.
+
+.SS set_config usage
+
+log_debug is set by dlm.conf (value is 1), then run "set_config" to change to 
0. at last use "restore" to restore to dlm.conf setting.
+
+.RS
+.EX
+# dlm_tool dump_config | grep log_debug
+log_debug=1 (dlm.conf)
+
+# dlm_tool set_config "log_debug=0"
+set_config done
+
+# dlm_tool dump_config | grep log_debug
+log_debug=0 (set_config)
+
+# dlm_tool set_config "log_debug=restore"
+set_config done
+
+# dlm_tool dump_config | grep log_debug
+log_debug=1 (dlm.conf)
+.EE
+.RE
+
+restore method
+
+Once user uses "set_config key=val" to change value, whatever user sets 0 or 
1, the related item belongs to "set_config" type. There are 2 ways to do 
restoration job: key=restore, restore_all
+
+restore - to reset single option item (see above example)
+
+restore_all -  to reset all set_config items.
+
+.RS
+.EX
+# dlm_tool dump_config | grep _debug
+daemon_debug=0
+log_debug=1 (dlm.conf)
+plock_debug=0
+
+# dlm_tool set_config "daemon_debug=1 log_debug=1 plock_debug=1"
+set_config done
+
+# dlm_tool dump_config | grep _debug
+daemon_debug=1 (set_config)
+log_debug=1 (set_config)
+plock_debug=1 (set_config)
+
+# dlm_tool set_config "restore_all"
+set_config done
+
+# dlm_tool dump_config | grep _debug
+daemon_debug=0
+log_debug=1 (dlm.conf)
+plock_debug=0
+.EE
+.RE
+
 .SH SEE ALSO
 .BR dlm_controld (8),
 .BR dlm.conf (5)
-
-- 
2.33.0

++++++ bug-1191734_0011-dlm_tool-dlm_controld-add-new-feature-set_config.patch 
++++++
>From 0e814226e081d228c96a8cc43e5cec484dc78306 Mon Sep 17 00:00:00 2001
From: Heming Zhao <[email protected]>
Date: Fri, 8 Oct 2021 09:33:39 +0800
Subject: [PATCH 11/14] dlm_tool dlm_controld: add new feature set_config

set_config command makes dlm_controld could change options value dynamically.

Signed-off-by: Heming Zhao <[email protected]>
---
 dlm_controld/config.c        | 169 +++++++++++++++++++++++++++++++++++
 dlm_controld/dlm_controld.h  |   1 +
 dlm_controld/dlm_daemon.h    |  11 +++
 dlm_controld/helper.c        |   4 -
 dlm_controld/lib.c           |  38 +++++++-
 dlm_controld/libdlmcontrol.h |   1 +
 dlm_controld/main.c          |  22 ++++-
 dlm_tool/main.c              |  29 +++++-
 8 files changed, 264 insertions(+), 11 deletions(-)

diff --git a/dlm_controld/config.c b/dlm_controld/config.c
index c60be8d47ef0..a7ebb120a6b8 100644
--- a/dlm_controld/config.c
+++ b/dlm_controld/config.c
@@ -387,3 +387,172 @@ void set_opt_file(int update)
        fclose(file);
 }
 
+/*
+ * do the clean/restore job:
+ * - clean up dlm_options[].dynamic_xx
+ * - using top priority item to set use option
+ */
+static void reset_dynamic(int index)
+{
+       struct dlm_option *o = &dlm_options[index];
+
+       if (!o->reload)
+               return;
+
+       o->dynamic_set = 0;
+       o->dynamic_int = 0;
+       if (o->dynamic_str){
+               free(o->dynamic_str);
+               o->dynamic_str = NULL;
+       }
+       o->dynamic_uint = 0;
+       reset_opt_value(index);
+
+       return;
+}
+
+/* copy code from exec_command() */
+void set_opt_online(char *cmd_str, int cmd_len)
+{
+       int i, ind, val = 0;
+       int av_count = 0;
+       int arg_len;
+       unsigned int uval = 0;
+       struct dlm_option *o;
+       char str[MAX_LINE];
+       char arg[ONE_ARG_LEN];
+       char *av[MAX_AV_COUNT + 1]; /* +1 for NULL */
+
+       if (cmd_len > RUN_COMMAND_LEN)
+               return;
+
+       for (i = 0; i < MAX_AV_COUNT + 1; i++)
+               av[i] = NULL;
+
+       if (!cmd_str[0])
+               return;
+
+       /* this should already be done, but make sure */
+       cmd_str[cmd_len - 1] = '\0';
+
+       memset(&arg, 0, sizeof(arg));
+       arg_len = 0;
+       cmd_len = strlen(cmd_str);
+
+       for (i = 0; i < cmd_len; i++) {
+               if (!cmd_str[i])
+                       break;
+
+               if (av_count == MAX_AV_COUNT)
+                       break;
+
+               if (cmd_str[i] == '\\') {
+                       if (i == (cmd_len - 1))
+                               break;
+                       i++;
+
+                       if (cmd_str[i] == '\\') {
+                               arg[arg_len++] = cmd_str[i];
+                               continue;
+                       }
+                       if (isspace(cmd_str[i])) {
+                               arg[arg_len++] = cmd_str[i];
+                               continue;
+                       } else {
+                               break;
+                       }
+               }
+
+               if (isalnum(cmd_str[i]) || ispunct(cmd_str[i])) {
+                       arg[arg_len++] = cmd_str[i];
+               } else if (isspace(cmd_str[i])) {
+                       if (arg_len)
+                               av[av_count++] = strdup(arg);
+
+                       memset(arg, 0, sizeof(arg));
+                       arg_len = 0;
+               } else {
+                       break;
+               }
+       }
+
+       if ((av_count < MAX_AV_COUNT) && arg_len) {
+               av[av_count++] = strdup(arg);
+       }
+
+       /*
+       for (i = 0; i < MAX_AV_COUNT + 1; i++) {
+               if (!av[i])
+                       break;
+
+               syslog(LOG_ERR, "command av[%d] \"%s\"", i, av[i]);
+       }
+       */
+
+       if (!strcmp(av[0], "restore_all")) {
+               for (i = 0; i < dlm_options_max; i++)
+                       reset_dynamic(i);
+               return;
+       }
+
+    i = -1;
+       while (++i < av_count) {
+
+               ind = get_ind_name(av[i]);
+               if (ind < 0)
+                       continue;
+               o = &dlm_options[ind];
+               if (!o || !o->reload)
+                       continue;
+
+               get_val_str(av[i], str);
+               if (!strcmp(str, "restore")) {
+                       reset_dynamic(ind);
+                       continue;
+               }
+
+               o->dynamic_set++;
+
+               if (!o->req_arg || o->req_arg == req_arg_int) {
+                       get_val_int(av[i], &val);
+                       if (!o->req_arg)
+                               val = val ? 1 : 0;
+
+                       o->dynamic_int = val;
+
+                       log_debug("config dynamic %s = %d previous use %d",
+                                 o->name, o->dynamic_int, o->use_int);
+                       o->use_int = o->dynamic_int;
+
+               } else if (o->req_arg == req_arg_uint) {
+                       get_val_uint(av[i], &uval);
+                       o->dynamic_uint = uval;
+
+                       log_debug("config dynamic %s = %u previous use %u",
+                                 o->name, o->dynamic_uint, o->use_uint);
+                       o->use_uint = o->dynamic_uint;
+
+               } else if (o->req_arg == req_arg_bool) {
+                       get_val_int(av[i], &val);
+                       o->dynamic_int = val ? 1 : 0;
+
+                       log_debug("config dynamic %s = %d previous use %d",
+                                 o->name, o->dynamic_int, o->use_int);
+                       o->use_int = o->dynamic_int;
+
+               } else if (o->req_arg == req_arg_str) {
+                       memset(str, 0, sizeof(str));
+                       get_val_str(av[i], str);
+
+                       o->dynamic_str = strdup(str);
+
+                       log_debug("config dynamic %s = %s previous use %s",
+                                 o->name, o->dynamic_str, o->use_str);
+                       o->use_str = o->dynamic_str;
+               }
+
+               reload_setting(ind);
+       }
+
+       return;
+}
diff --git a/dlm_controld/dlm_controld.h b/dlm_controld/dlm_controld.h
index 0ea3548fce7d..94e5c49e88bd 100644
--- a/dlm_controld/dlm_controld.h
+++ b/dlm_controld/dlm_controld.h
@@ -36,6 +36,7 @@
 #define DLMC_CMD_RUN_CHECK             16
 #define DLMC_CMD_DUMP_RUN              17
 #define DLMC_CMD_RELOAD_CONFIG 18
+#define DLMC_CMD_SET_CONFIG            19
 
 struct dlmc_header {
        unsigned int magic;
diff --git a/dlm_controld/dlm_daemon.h b/dlm_controld/dlm_daemon.h
index 9e68f8257cb5..da261774bee0 100644
--- a/dlm_controld/dlm_daemon.h
+++ b/dlm_controld/dlm_daemon.h
@@ -25,6 +25,7 @@
 #include <arpa/inet.h>
 #include <net/if.h>
 #include <stdio.h>
+#include <ctype.h>
 #include <errno.h>
 #include <string.h>
 #include <stdlib.h>
@@ -133,6 +134,7 @@ struct dlm_option {
        char letter;
        int req_arg;
        char reload;
+       char dynamic;
        const char *desc;
 
        int use_int;
@@ -152,6 +154,11 @@ struct dlm_option {
        int file_int;
        char *file_str;
        unsigned int file_uint;
+
+       int dynamic_set;
+       int dynamic_int;
+       char *dynamic_str;
+       unsigned int dynamic_uint;
 };
 
 EXTERN struct dlm_option dlm_options[dlm_options_max];
@@ -328,6 +335,9 @@ struct lockspace {
 
 #define RUN_COMMAND_LEN DLMC_RUN_COMMAND_LEN /* 1024 */
 
+#define MAX_AV_COUNT 32
+#define ONE_ARG_LEN 256
+
 struct run_info {
        int dest_nodeid;
        int start_nodeid;
@@ -390,6 +400,7 @@ int set_configfs_opt(const char *name, char *str, int num);
 void set_opt_file(int update);
 int get_weight(struct lockspace *ls, int nodeid);
 void setup_lockspace_config(struct lockspace *ls);
+void set_opt_online(char *cmd_str, int cmd_len);
 
 /* cpg.c */
 void process_lockspace_changes(void);
diff --git a/dlm_controld/helper.c b/dlm_controld/helper.c
index a20965b76195..469dd22095f0 100644
--- a/dlm_controld/helper.c
+++ b/dlm_controld/helper.c
@@ -20,7 +20,6 @@
 #include <time.h>
 #include <stdarg.h>
 #include <signal.h>
-#include <ctype.h>
 #include <sys/time.h>
 #include <sys/types.h>
 #include <sys/wait.h>
@@ -29,9 +28,6 @@
 
 #include "dlm_daemon.h"
 
-#define MAX_AV_COUNT 32
-#define ONE_ARG_LEN 256
-
 
 static int _log_stderr;
 
diff --git a/dlm_controld/lib.c b/dlm_controld/lib.c
index 951eb6561ba9..8cbdd27f15e2 100644
--- a/dlm_controld/lib.c
+++ b/dlm_controld/lib.c
@@ -189,7 +189,43 @@ int dlmc_reload_config(void)
 
        rv = do_write(fd, &h, sizeof(h));
        close(fd);
- out:
+out:
+       return rv;
+}
+
+int dlmc_set_config(char *command)
+{
+       struct dlmc_header h;
+       char *cmdbuf;
+       int fd, rv;
+
+       cmdbuf = malloc(DLMC_RUN_COMMAND_LEN);
+       if (!cmdbuf)
+               return -1;
+
+       memset(cmdbuf, 0, DLMC_RUN_COMMAND_LEN);
+       strncpy(cmdbuf, command, DLMC_RUN_COMMAND_LEN-1);
+
+       init_header(&h, DLMC_CMD_SET_CONFIG, NULL, DLMC_RUN_COMMAND_LEN);
+
+       fd = do_connect(DLMC_SOCK_PATH);
+       if (fd < 0) {
+               rv = fd;
+               goto out;
+       }
+
+       rv = do_write(fd, &h, sizeof(h));
+       if (rv < 0)
+               goto out_close;
+
+       rv = do_write(fd, cmdbuf, DLMC_RUN_COMMAND_LEN);
+       if (rv < 0)
+               goto out_close;
+
+out_close:
+       close(fd);
+out:
+       free(cmdbuf);
        return rv;
 }
 
diff --git a/dlm_controld/libdlmcontrol.h b/dlm_controld/libdlmcontrol.h
index ac84e702fb58..a106171b1073 100644
--- a/dlm_controld/libdlmcontrol.h
+++ b/dlm_controld/libdlmcontrol.h
@@ -92,6 +92,7 @@ int dlmc_lockspace_nodes(char *lsname, int type, int max, int 
*count,
                         struct dlmc_node *nodes);
 int dlmc_print_status(uint32_t flags);
 int dlmc_reload_config(void);
+int dlmc_set_config(char *command);
 
 #define DLMC_RESULT_REGISTER   1
 #define DLMC_RESULT_NOTIFIED   2
diff --git a/dlm_controld/main.c b/dlm_controld/main.c
index 8104d8f906ac..3a081c802056 100644
--- a/dlm_controld/main.c
+++ b/dlm_controld/main.c
@@ -919,7 +919,7 @@ static void copy_options(char *buf, int *len)
 {
        struct dlm_option *o;
        char tmp[256];
-       int i, ret, pos = 0;
+       int i, ret, pos = 0, l = 0;
 
        for (i = 0; i < dlm_options_max; i++) {
                o = &dlm_options[i];
@@ -927,9 +927,20 @@ static void copy_options(char *buf, int *len)
                memset(tmp, 0, sizeof(tmp));
 
                if (o->req_arg == req_arg_str)
-                       snprintf(tmp, 255, "%s=%s\n", o->name, o->use_str);
+                       l = snprintf(tmp, 250, "%s=%s", o->name, o->use_str);
+               else if (o->req_arg == req_arg_uint)
+                       l = snprintf(tmp, 250, "%s=%u", o->name, o->use_uint);
+               else
+                       l = snprintf(tmp, 250, "%s=%d", o->name, o->use_int);
+
+               if (o->dynamic_set)
+                       snprintf(tmp + l, 15, " (set_config)\n");
+               else if (o->cli_set)
+                       snprintf(tmp + l, 15, " (cli option)\n");
+               else if (o->file_set)
+                       snprintf(tmp + l, 15, " (dlm.conf)\n");
                else
-                       snprintf(tmp, 255, "%s=%d\n", o->name, o->use_int);
+                       snprintf(tmp + l, 15, "\n");
 
                if (pos + strlen(tmp) >= LOG_DUMP_SIZE)
                        break;
@@ -1234,6 +1245,11 @@ static void process_connection(int ci)
                set_opt_file(1);
                break;
 
+       case DLMC_CMD_SET_CONFIG:
+               if (extra_len)
+                       set_opt_online(extra, extra_len);
+               break;
+
        default:
                log_error("process_connection %d unknown command %d",
                          ci, h.command);
diff --git a/dlm_tool/main.c b/dlm_tool/main.c
index 774835192bbf..bce5c1da3c95 100644
--- a/dlm_tool/main.c
+++ b/dlm_tool/main.c
@@ -48,6 +48,7 @@
 #define OP_RUN_LIST                    18
 #define OP_DUMP_RUN                    19
 #define OP_RELOAD_CONFIG       20
+#define OP_SET_CONFIG          21
 
 static char *prog_name;
 static char *lsname;
@@ -197,7 +198,8 @@ static void print_usage(void)
        printf("dlm_tool [command] [options] [name]\n");
        printf("\n");
        printf("Commands:\n");
-       printf("ls, status, dump, dump_config, reload_config, fence_ack\n");
+       printf("ls, status, dump, fence_ack\n");
+       printf("dump_config, reload_config, set_config\n");
        printf("log_plock, plocks\n");
        printf("join, leave, lockdebug\n");
        printf("run, run_start, run_check, run_cancel, run_list\n");
@@ -370,6 +372,13 @@ static void decode_arguments(int argc, char **argv)
                        opt_ind = optind + 1;
                        need_lsname = 0;
                        break;
+               } else if (!strncmp(argv[optind], "set_config", 10) &&
+                          (strlen(argv[optind]) == 10)) {
+                       operation = OP_SET_CONFIG;
+                       opt_ind = optind + 1;
+                       need_lsname = 0;
+                       need_command = 1;
+                       break;
                } else if (!strncmp(argv[optind], "plocks", 6) &&
                           (strlen(argv[optind]) == 6)) {
                        operation = OP_PLOCKS;
@@ -477,8 +486,10 @@ static void decode_arguments(int argc, char **argv)
                        exit(EXIT_FAILURE);
                }
 
-               strcat(run_command, argv[i]);
-               strcat(run_command, " ");
+               if (strlen(argv[i])) {
+                       strcat(run_command, argv[i]);
+                       strcat(run_command, " ");
+               }
        }
 }
 
@@ -1487,6 +1498,14 @@ static void do_reload_config(void)
                printf("reload_config done\n");
 }
 
+static void do_set_config(void)
+{
+       if (dlmc_set_config(run_command) < 0)
+               printf("set_config failed\n");
+       else
+               printf("set_config done\n");
+}
+
 static void do_log_plock(void)
 {
        char buf[DLMC_DUMP_SIZE];
@@ -1589,6 +1608,10 @@ int main(int argc, char **argv)
                do_reload_config();
                break;
 
+       case OP_SET_CONFIG:
+               do_set_config();
+               break;
+
        case OP_LOG_PLOCK:
                do_log_plock();
                break;
-- 
2.33.0

++++++ bug-1191734_0012-fix-some-minor-bugs.patch ++++++
>From cf99a9770359cef56a5aabce8c5bf2d4aeb4f2f8 Mon Sep 17 00:00:00 2001
From: Heming Zhao <[email protected]>
Date: Fri, 8 Oct 2021 09:33:40 +0800
Subject: [PATCH 12/14] fix some minor bugs
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

1>
log_config() should print "0" when m_buf or j_buf or l_buf is empty.

2>
parameter "%d" lacks object in confchg_cb_daemon().

3>
in run_helper():
running_count doesn't work for run_helper process.
running_count limits cmd numbers not to beyond 32. This assessment should
be put in run_helper while(1).

4>
fix decode_arguments() naming mistake for fence_ack command.

5>
removing a gcc warning for decode_arguments()

message:

```
/usr/include/bits/string_fortified.h:95:10: warning: ???__builtin_strncpy???
specified bound 64 equals destination size [-Wstringop-truncation]
   95 |   return __builtin___strncpy_chk (__dest, __src, __len,
      |          ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   96 |                                   __glibc_objsize (__dest));
      |                                   ~~~~~~~~~~~~~~~~~~~~~~~~~
```

uuid is generated by uuid_generate(), which is 37-byte (36-byte uuid
plus tailing '\0'). In exist code, uuid[] is 64-byte array, which has
enough space to fill 37-byte string. So we could safely do one-byte
less copy in strncpy().

Signed-off-by: Heming Zhao <[email protected]>
---
 dlm_controld/daemon_cpg.c |  5 +++--
 dlm_controld/helper.c     | 10 +++++-----
 dlm_tool/main.c           | 12 ++++++++----
 3 files changed, 16 insertions(+), 11 deletions(-)

diff --git a/dlm_controld/daemon_cpg.c b/dlm_controld/daemon_cpg.c
index 392e0ff63cd8..65593e80dec4 100644
--- a/dlm_controld/daemon_cpg.c
+++ b/dlm_controld/daemon_cpg.c
@@ -174,7 +174,8 @@ void log_config(const struct cpg_name *group_name,
 
        log_debug("%s conf %zu %zu %zu memb%s join%s left%s", group_name->value,
                  member_list_entries, joined_list_entries, left_list_entries,
-                 m_buf, j_buf, l_buf);
+                 strlen(m_buf) ? m_buf : " 0", strlen(j_buf) ? j_buf : " 0",
+                 strlen(l_buf) ? l_buf : " 0");
 }
 
 void log_ringid(const char *name,
@@ -2335,7 +2336,7 @@ static void confchg_cb_daemon(cpg_handle_t handle,
                                   valid proto from it (is_clean_daemon_member) 
*/
                                log_error("daemon joined %d needs fencing", 
node->nodeid);
                        } else {
-                               log_debug("daemon joined %d");
+                               log_debug("daemon joined %d", node->nodeid);
                        }
                } else {
                        if (!node->daemon_member)
diff --git a/dlm_controld/helper.c b/dlm_controld/helper.c
index 469dd22095f0..f31ccd954826 100644
--- a/dlm_controld/helper.c
+++ b/dlm_controld/helper.c
@@ -286,11 +286,6 @@ int run_helper(int in_fd, int out_fd, int log_stderr)
 
        _log_stderr = log_stderr;
 
-       if (running_count >= MAX_RUNNING) {
-               log_helper("too many running commands");
-               return -1;
-       }
-
        rv = setgroups(0, NULL);
        if (rv < 0)
                log_helper("error clearing helper groups errno %i", errno);
@@ -335,6 +330,11 @@ int run_helper(int in_fd, int out_fd, int log_stderr)
                        if (hd->type == DLM_MSG_RUN_REQUEST) {
                                int cmd_pipe[2];
 
+                               if (running_count >= MAX_RUNNING) {
+                                       log_helper("too many running commands");
+                                       exit(1);
+                               }
+
                                /*
                                 * Child writes cmd_buf to cmd_pipe, parent 
reads
                                 * cmd_buf from cmd_pipe.  cmd_buf contains the
diff --git a/dlm_tool/main.c b/dlm_tool/main.c
index bce5c1da3c95..04ff40f874c8 100644
--- a/dlm_tool/main.c
+++ b/dlm_tool/main.c
@@ -461,12 +461,16 @@ static void decode_arguments(int argc, char **argv)
        if (optind < argc - 1) {
                if (need_lsname)
                        lsname = argv[opt_ind];
-               else if (need_uuid)
-                       strncpy(run_uuid, argv[opt_ind], DLMC_RUN_UUID_LEN);
-               else if (need_command)
+               else if (need_uuid) {
+                       strncpy(run_uuid, argv[opt_ind], DLMC_RUN_UUID_LEN - 1);
+                       run_uuid[DLMC_RUN_UUID_LEN - 1] = '\0';
+               } else if (need_command)
                        goto copy_command;
        } else if (need_lsname) {
-               fprintf(stderr, "lockspace name required\n");
+               if (operation == OP_FENCE_ACK)
+                       fprintf(stderr, "nodeid required\n");
+               else
+                       fprintf(stderr, "lockspace name required\n");
                exit(EXIT_FAILURE);
        } else if (need_command) {
                fprintf(stderr, "command required\n");
-- 
2.33.0

++++++ bug-1191734_0013-dlm_controld-fix-string-copies.patch ++++++
>From a877e55c4661cfceabcb566ad49afd27b245cb65 Mon Sep 17 00:00:00 2001
From: David Teigland <[email protected]>
Date: Fri, 15 Oct 2021 12:02:34 -0500
Subject: [PATCH 13/14] dlm_controld fix string copies

---
 dlm_controld/config.c | 4 +---
 dlm_controld/main.c   | 6 +++---
 2 files changed, 4 insertions(+), 6 deletions(-)

diff --git a/dlm_controld/config.c b/dlm_controld/config.c
index a7ebb120a6b8..b15527b949b1 100644
--- a/dlm_controld/config.c
+++ b/dlm_controld/config.c
@@ -495,9 +495,7 @@ void set_opt_online(char *cmd_str, int cmd_len)
                return;
        }
 
-    i = -1;
-       while (++i < av_count) {
-
+       for (i = 0; i < av_count; i++) {
                ind = get_ind_name(av[i]);
                if (ind < 0)
                        continue;
diff --git a/dlm_controld/main.c b/dlm_controld/main.c
index 3a081c802056..57844dc10129 100644
--- a/dlm_controld/main.c
+++ b/dlm_controld/main.c
@@ -927,11 +927,11 @@ static void copy_options(char *buf, int *len)
                memset(tmp, 0, sizeof(tmp));
 
                if (o->req_arg == req_arg_str)
-                       l = snprintf(tmp, 250, "%s=%s", o->name, o->use_str);
+                       l = snprintf(tmp, 240, "%s=%s", o->name, o->use_str);
                else if (o->req_arg == req_arg_uint)
-                       l = snprintf(tmp, 250, "%s=%u", o->name, o->use_uint);
+                       l = snprintf(tmp, 240, "%s=%u", o->name, o->use_uint);
                else
-                       l = snprintf(tmp, 250, "%s=%d", o->name, o->use_int);
+                       l = snprintf(tmp, 240, "%s=%d", o->name, o->use_int);
 
                if (o->dynamic_set)
                        snprintf(tmp + l, 15, " (set_config)\n");
-- 
2.33.0

++++++ bug-1191734_0014-man-page-updates.patch ++++++
>From 694237c7b7857ff18b5057758b5550162cc85149 Mon Sep 17 00:00:00 2001
From: David Teigland <[email protected]>
Date: Fri, 15 Oct 2021 12:12:18 -0500
Subject: [PATCH 14/14] man page updates

---
 dlm_controld/dlm.conf.5 |  21 ++--
 dlm_tool/dlm_tool.8     | 224 ++++++++++++++--------------------------
 2 files changed, 81 insertions(+), 164 deletions(-)

diff --git a/dlm_controld/dlm.conf.5 b/dlm_controld/dlm.conf.5
index 99e302a92bd2..0eb226358100 100644
--- a/dlm_controld/dlm.conf.5
+++ b/dlm_controld/dlm.conf.5
@@ -22,7 +22,7 @@ for descriptions and dlm_controld -h for defaults.
 
 Format:
 
-key=val
+setting=value
 
 Example:
 
@@ -77,23 +77,14 @@ repeat_failed_fencing(*)
 enable_helper
 .br
 
-Option with tail (*) means this item can be reload on the fly by "dlm_tool 
reload_config". See \fB"Reload config"\fP for more examples.
+Options with (*) can be reloaded, see Reload config.
 
 .SH Reload config
 
-dlm.conf can be changed then reloaded some settings on the fly, it gives users 
more flexible and powerful ability to manage dlm.
-
-The supported reload operations:
-.br
-- add a new item
-.br
-- remove an exist item
-.br
-- commented out an item
-.br
-- change an item value
-
-After modifying settings in dlm.conf, run "dlm_tool reload_config" to take 
effect. User can use "dlm_tool dump_config" to check the result. Again, only 
reloadable item can be changed.
+Some dlm.conf settings can be changed while dlm_controld is running using
+dlm_tool reload_config.  Edit dlm.conf, adding, removing, commenting or
+changing values, then run dlm_tool reload_config to apply the changes in
+dlm_controld.  dlm_tool dump_config will show the new settings.
 
 .SH Fencing
 
diff --git a/dlm_tool/dlm_tool.8 b/dlm_tool/dlm_tool.8
index f6d869620822..2a14fe0292a7 100644
--- a/dlm_tool/dlm_tool.8
+++ b/dlm_tool/dlm_tool.8
@@ -32,45 +32,45 @@ dlm_tool \- a utility for the dlm and dlm_controld daemon
 .br
        Reload dlm_controld config settings from dlm.conf.
 
-.B set_config
+.BI set_config " setting" = "value"
 .br
-       Set dlm_controld config settings on the fly.
+       Set dlm_controld config settings in the currently running daemon.
 
 .BI fence_ack " nodeid"
 .br
-       Quit trying to fence a node.
+       Cancel a waiting fencing operation and consider it successful.
 
 .B log_plock
 .br
        Dump dlm_controld plock debug buffer.
 
-.BI plocks " name"
+.BI plocks " lockspace_name"
 .br
        Dump posix locks from dlm_controld for the lockspace.
 
-.BI join " name"
+.BI join " lockspace_name"
 .br
        Join a lockspace.
 
-.BI leave " name"
+.BI leave " lockspace_name"
 .br
        Leave a lockspace.
 
-.BI joinleave " name"
+.BI joinleave " lockspace_name"
 .br
-       Do two actions: first Join then Leave a lockspace. (mainly for test)
+       Join then immediately leave a lockspace (for testing only.)
 
-.BI lockdebug " name"
+.BI lockdebug " lockspace_name"
 .br
        Complete display of locks from the lockspace.
 
-.BI lockdump " name"
+.BI lockdump " lockspace_name"
 .br
        Minimal display of locks from the lockspace (deprecated).
 
 .BI run " command"
 .br
-       Run command and check for result.
+       Run command and check for result (for lvmlockd only.)
 
 .BI run_start " command"
 .br
@@ -92,7 +92,7 @@ dlm_tool \- a utility for the dlm and dlm_controld daemon
 .SH OPTIONS
 
 .B \-n
-Show all node information in ls.
+Show all node information from dlm_tool ls.
 
 .B \-d
 0|1 Resource directory off/on in join, default 0
@@ -103,6 +103,9 @@ Show all node information in ls.
 .B \-f
 0|1 FS (filesystem) flag off/on in join, default 0
 
+.BI \-i " sec"
+Seconds to wait in run_check.
+
 .BI \-m " mode"
 Permission mode for lockspace device (octal), default 0600
 
@@ -110,7 +113,7 @@ Permission mode for lockspace device (octal), default 0600
 Summary following lockdebug output (experiemental)
 
 .B \-v
-Verbose lockdebug output
+Verbose lockdebug or status output
 
 .B \-w
 Wide lockdebug output
@@ -124,102 +127,20 @@ Print help, then exit
 .B \-V
 Print program version information, then exit
 
-.SH USAGE
-
-.B dlm_tool ls [-n] [ls_name]
-
--
-
-.B dlm_tool status [-v]
-
--
-
-.B dlm_tool dump
-
--
-
-.B dlm_tool dump_config
-
--
-
-.B dlm_tool reload_config
-
-* see examples in \fBdlm.conf(5)\fP
-
--
-
-.B dlm_tool set_config "dlm_controld-config-item=x"
-
-* see below \fBset_config EXAMPLES\fP section
-
--
-
-.B dlm_tool fence_ack \fInodeid\fP
-
-* run "dlm_tool status -v" to get \fInodeid\fP
-
--
-
-.B dlm_tool log_plock
-
--
-
-.B dlm_tool plocks \fIls-name\fP
-
--
-
-.B dlm_tool join [-e 0|1] [-f 0|1] \fIls-name\fP
-
--
-
-.B dlm_tool leave \fIls-name\fP
 
--
-
-.B dlm_tool joinleave [-e 0|1] [-f 0|1] \fIls-name\fP
-
--
-
-.B dlm_tool lockdebug [-s] [-v] [-w] \fIls-name\fP
-
--
-
-.B dlm_tool lockdump [-M] \fIls-name\fP
-
--
-
-.B dlm_tool run|run_start [-n] \fIcommand\fP
-
-* current run & run_start support \fIcommand\fP:
-.
-  - "lvm lvchange --refresh"
-.
-  - "lvm lvs"
-
--
-
-.B dlm_tool run_check|run_cancel [-i "sec"] \fIuuid\fP
-
--
-
-.B dlm_tool run_list
-
--
-
-.B dlm_tool -h
-
--
+.SH USAGE
 
-.B dlm_tool -V
+.SS fence_ack
 
-.SH set_config EXAMPLES
+See dlm_tool status for information about waiting fencing operations for
+specific nodeid's.
 
-\fIdlm_tool set_config "xxx"\fP can do the dynamic config job. It makes 
possible to debug, or to do flexible operations on the fly.
+.SS set_config
 
-supported option items
+dlm_tool set_config can change certain config settings in the currently
+running dlm_controld.  Supported options:
 
-.RS
-.EX
+.nf
 daemon_debug
 log_debug
 debug_logfile
@@ -232,101 +153,106 @@ post_join_delay
 enable_quorum_fencing
 enable_quorum_lockspace
 repeat_failed_fencing
-.EE
-.RE
+.fi
 
-.SS display style
+Special cases to revert a previous set_config and restore the previous
+value (from default or dlm.conf):
 
-Currently, there are 5 ways of setting: default, cli, dlm.conf, reload_config, 
set_config
+\fBdlm_tool set_config\fP \fIsetting\fP=\fBrestore\fP
+.br
+restores a single setting.
 
-The "dlm_tool dump_config" shows the config item by 4 styles.
+\fBdlm_tool set_config restore_all\fP
+.br
+restores all settings.
 
-.TP
-key=val
-For default values that have not been set by cli or config file or dynamically.
+.SS dump_config
+
+A config setting may have been set from: the default, the dlm_controld
+command line, dlm.conf at startup, dlm.conf from reload_config, dlm_tool
+set_config.  The dump_config output indicates how values were set:
 
 .TP
-key=val (cli option)
-For values that have been last set from a command line option.
+setting=value
+default value.
 
 .TP
-key=val (dlm.conf)
-For values that have been last set from dlm.conf. (reload_config also belongs 
to this style)
+setting=value (cli option)
+Set from a dlm_controld command line option.
 
 .TP
-key=val (set_config)
-For values that have been last set by dlm_tool set_config.
+setting=value (dlm.conf)
+Set from dlm.conf (at startup or reload.)
 
 .TP
-i.e.
+setting=value (set_config)
+Set from dlm_tool set_config.
 
-.EX
-# dlm_tool dump_config | head -n 5
+
+.SH EXAMPLES
+
+.SS dump_config
+
+.nf
+$ dlm_tool dump_config | head -n 5
 daemon_debug=1 (set_config)
 foreground=0
 log_debug=1 (dlm.conf)
 timewarn=0
 protocol=detect
-.EE
+.fi
 
-In this case, the "daemon_debug" is set by set_config, the "log_debug" is set 
by dlm.conf.
-meanwhile foreground, timewarn & protocol are using default values.
+In this case, daemon_debug is set by set_config, log_debug is set from
+dlm.conf, foreground, timewarn and protocol are using default values.
 
-.SS set_config usage
+.SS set_config
 
-log_debug is set by dlm.conf (value is 1), then run "set_config" to change to 
0. at last use "restore" to restore to dlm.conf setting.
-
-.RS
-.EX
-# dlm_tool dump_config | grep log_debug
+.nf
+$ dlm_tool dump_config | grep log_debug
 log_debug=1 (dlm.conf)
 
-# dlm_tool set_config "log_debug=0"
+$ dlm_tool set_config "log_debug=0"
 set_config done
 
-# dlm_tool dump_config | grep log_debug
+$ dlm_tool dump_config | grep log_debug
 log_debug=0 (set_config)
 
-# dlm_tool set_config "log_debug=restore"
+$ dlm_tool set_config "log_debug=restore"
 set_config done
 
-# dlm_tool dump_config | grep log_debug
+$ dlm_tool dump_config | grep log_debug
 log_debug=1 (dlm.conf)
-.EE
-.RE
-
-restore method
+.fi
 
-Once user uses "set_config key=val" to change value, whatever user sets 0 or 
1, the related item belongs to "set_config" type. There are 2 ways to do 
restoration job: key=restore, restore_all
+log_debug is set by dlm.conf (value is 1), then run set_config to change
+to 0, then use restore to restore to dlm.conf setting.
 
-restore - to reset single option item (see above example)
 
-restore_all -  to reset all set_config items.
+.SS set_config
 
-.RS
-.EX
-# dlm_tool dump_config | grep _debug
+.nf
+$ dlm_tool dump_config | grep _debug
 daemon_debug=0
 log_debug=1 (dlm.conf)
 plock_debug=0
 
-# dlm_tool set_config "daemon_debug=1 log_debug=1 plock_debug=1"
+$ dlm_tool set_config "daemon_debug=1 log_debug=1 plock_debug=1"
 set_config done
 
-# dlm_tool dump_config | grep _debug
+$ dlm_tool dump_config | grep _debug
 daemon_debug=1 (set_config)
 log_debug=1 (set_config)
 plock_debug=1 (set_config)
 
-# dlm_tool set_config "restore_all"
+$ dlm_tool set_config "restore_all"
 set_config done
 
-# dlm_tool dump_config | grep _debug
+$ dlm_tool dump_config | grep _debug
 daemon_debug=0
 log_debug=1 (dlm.conf)
 plock_debug=0
-.EE
-.RE
+.fi
+
 
 .SH SEE ALSO
 .BR dlm_controld (8),
-- 
2.33.0

++++++ 
bug-1191734_0015-Revert-dlm_controld-add-version-check-for-libquorum.patch 
++++++
>From 6579bebc5c8843c4b7dfc3252267708990b097fc Mon Sep 17 00:00:00 2001
From: Heming Zhao <[email protected]>
Date: Mon, 18 Oct 2021 16:19:32 +0800
Subject: [PATCH 1/2] Revert "dlm_controld: add version check for libquorum"

This reverts commit 3201db3835c85a1d9a407e621bff7902896e8a82.
---
 dlm_controld/Makefile | 4 ----
 1 file changed, 4 deletions(-)

diff --git a/dlm_controld/Makefile b/dlm_controld/Makefile
index 8cfc97e6909a..667998076acc 100644
--- a/dlm_controld/Makefile
+++ b/dlm_controld/Makefile
@@ -60,10 +60,6 @@ ifeq ($(USE_SD_NOTIFY),yes)
        BIN_LDFLAGS += $(shell $(PKG_CONFIG) --libs libsystemd)
 endif
 
-ifeq (, $(shell $(PKG_CONFIG) --libs "libquorum >= 3.1.0"))
-        $(error "Requires libquorum at least version 3.1.0")
-endif
-
 all: $(LIB_TARGET) $(BIN_TARGET) $(LIB_PC)
 
 $(BIN_TARGET): $(BIN_SOURCE)
-- 
2.33.0

++++++ 
bug-1191734_0016-Revert-dlm_controld-use-new-quorum-api-to-detect-mis.patch 
++++++
>From fd4aa4e5eec8477b08b279fbf6ed0eb1406c8fa8 Mon Sep 17 00:00:00 2001
From: Heming Zhao <[email protected]>
Date: Mon, 18 Oct 2021 16:20:32 +0800
Subject: [PATCH 2/2] Revert "dlm_controld: use new quorum api to detect missed
 failures"

This reverts commit 2e893b981b19430aeca983dd63fb3ac0979d0b35.
---
 dlm_controld/member.c | 106 ++++++------------------------------------
 1 file changed, 15 insertions(+), 91 deletions(-)

diff --git a/dlm_controld/member.c b/dlm_controld/member.c
index d567c114b259..1d5bfa3d9166 100644
--- a/dlm_controld/member.c
+++ b/dlm_controld/member.c
@@ -20,8 +20,6 @@ static int                    old_node_count;
 static uint32_t                        quorum_nodes[MAX_NODES];
 static int                     quorum_node_count;
 static struct list_head                cluster_nodes;
-static uint32_t                        leavejoin_nodes[MAX_NODES];
-static int                     leavejoin_count;
 
 struct node_cluster {
        struct list_head list;
@@ -105,51 +103,15 @@ int is_cluster_member(uint32_t nodeid)
        return is_member(quorum_nodes, quorum_node_count, nodeid);
 }
 
-static int is_leavejoin_node(uint32_t nodeid)
-{
-       return is_member(leavejoin_nodes, leavejoin_count, nodeid);
-}
-
-static void quorum_nodelist_callback(quorum_handle_t cbhandle, struct 
quorum_ring_id ring_id,
-                                    uint32_t member_list_entries, const 
uint32_t *member_list,
-                                    uint32_t joined_list_entries, const 
uint32_t *joined_list,
-                                    uint32_t left_list_entries, const uint32_t 
*left_list)
-{
-       uint64_t ring_seq = ring_id.seq;
-       int i, j;
-
-       for (i = 0; i < left_list_entries; i++) {
-               log_debug("cluster left_list %u seq %llu",
-                         left_list[i], (unsigned long long)ring_seq);
-       }
-
-       for (j = 0; j < joined_list_entries; j++) {
-               log_debug("cluster joined_list %u seq %llu",
-                         joined_list[j], (unsigned long long)ring_seq);
-       }
-
-       for (i = 0; i < left_list_entries; i++) {
-               for (j = 0; j < joined_list_entries; j++) {
-                       if (joined_list[j] == left_list[i]) {
-                               log_debug("cluster node %d left and joined", 
joined_list[j]);
-                               if (!is_leavejoin_node(joined_list[j]))
-                                       leavejoin_nodes[leavejoin_count++] = 
joined_list[j];
-                       }
-               }
-       }
-}
-
-static void quorum_callback(quorum_handle_t cbhandle, uint32_t quorate,
-                           struct quorum_ring_id ring_id, uint32_t 
node_list_entries,
-                           const uint32_t *node_list)
+static void quorum_callback(quorum_handle_t h, uint32_t quorate,
+                           uint64_t ring_seq, uint32_t node_list_entries,
+                           uint32_t *node_list)
 {
        corosync_cfg_node_address_t addrs[MAX_NODE_ADDRESSES];
        corosync_cfg_node_address_t *addrptr = addrs;
        const struct node_config *nc;
        cs_error_t err;
        int i, j, num_addrs;
-       uint32_t nodeid;
-       uint64_t ring_seq = ring_id.seq;
        uint64_t now = monotime();
 
        if (!cluster_joined_monotime) {
@@ -180,55 +142,15 @@ static void quorum_callback(quorum_handle_t cbhandle, 
uint32_t quorate,
                if (!is_cluster_member(old_nodes[i])) {
                        log_debug("cluster node %u removed seq %llu",
                                  old_nodes[i], (unsigned long 
long)cluster_ringid_seq);
-
                        rem_cluster_node(old_nodes[i], now);
                        del_configfs_node(old_nodes[i]);
                }
        }
 
-       for (i = 0; i < leavejoin_count; i++) {
-               nodeid = leavejoin_nodes[i];
-
-               log_debug("cluster node %u leavejoin seq %llu",
-                         nodeid, (unsigned long long)cluster_ringid_seq);
-
-               /* remove */
-
-               rem_cluster_node(nodeid, now);
-               del_configfs_node(nodeid);
-
-               /* add */
-
-               add_cluster_node(nodeid, now);
-
-               fence_delay_begin = now;
-
-               err = corosync_cfg_get_node_addrs(ch, nodeid,
-                                                 MAX_NODE_ADDRESSES,
-                                                 &num_addrs, addrs);
-               if (err != CS_OK) {
-                       log_error("corosync_cfg_get_node_addrs failed nodeid 
%u", nodeid);
-                       continue;
-               }
-
-               nc = node_config_get(nodeid);
-
-               for (j = 0; j < num_addrs; j++) {
-                       add_configfs_node(nodeid,
-                                         addrptr[j].address,
-                                         addrptr[j].address_length,
-                                         (nodeid == our_nodeid),
-                                         nc->mark);
-               }
-       }
-
        for (i = 0; i < quorum_node_count; i++) {
-               if (is_leavejoin_node(quorum_nodes[i]))
-                       continue;
                if (!is_old_member(quorum_nodes[i])) {
                        log_debug("cluster node %u added seq %llu",
                                  quorum_nodes[i], (unsigned long 
long)cluster_ringid_seq);
-
                        add_cluster_node(quorum_nodes[i], now);
 
                        fence_delay_begin = now;
@@ -254,11 +176,13 @@ static void quorum_callback(quorum_handle_t cbhandle, 
uint32_t quorate,
                        }
                }
        }
-
-       memset(leavejoin_nodes, 0, sizeof(leavejoin_nodes));
-       leavejoin_count = 0;
 }
 
+static quorum_callbacks_t quorum_callbacks =
+{
+       .quorum_notify_fn = quorum_callback,
+};
+
 void process_cluster(int ci)
 {
        cs_error_t err;
@@ -284,23 +208,23 @@ void update_cluster(void)
 
 int setup_cluster(void)
 {
-       quorum_model_v1_data_t model_data;
        cs_error_t err;
        int fd;
-       uint32_t quorum_type = 0;
+       uint32_t quorum_type;
 
        INIT_LIST_HEAD(&cluster_nodes);
 
-       memset(&model_data, 0, sizeof(model_data));
-       model_data.quorum_notify_fn = quorum_callback;
-       model_data.nodelist_notify_fn = quorum_nodelist_callback;
-
-       err = quorum_model_initialize(&qh, QUORUM_MODEL_V1, 
(quorum_model_data_t *)&model_data, &quorum_type, NULL);
+       err = quorum_initialize(&qh, &quorum_callbacks, &quorum_type);
        if (err != CS_OK) {
                log_error("quorum init error %d", err);
                return -1;
        }
 
+       if (quorum_type == QUORUM_FREE) {
+               log_error("no quorum provider configured in corosync, unable to 
operate");
+               goto fail;
+       }
+
        err = quorum_fd_get(qh, &fd);
        if (err != CS_OK) {
                log_error("quorum fd_get error %d", err);
-- 
2.33.0

++++++ dlm-4.0.9.tar.gz -> dlm-4.1.0.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/dlm-4.0.9/dlm_controld/Makefile 
new/dlm-4.1.0/dlm_controld/Makefile
--- old/dlm-4.0.9/dlm_controld/Makefile 2019-06-11 18:59:32.000000000 +0200
+++ new/dlm-4.1.0/dlm_controld/Makefile 2021-01-12 21:24:20.000000000 +0100
@@ -32,7 +32,8 @@
              config.c \
              member.c \
              logging.c \
-             rbtree.c
+             rbtree.c \
+             node_config.c
 LIB_SOURCE = lib.c
 
 CFLAGS += -D_GNU_SOURCE -O2 -ggdb \
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/dlm-4.0.9/dlm_controld/action.c 
new/dlm-4.1.0/dlm_controld/action.c
--- old/dlm-4.0.9/dlm_controld/action.c 2019-06-11 18:59:32.000000000 +0200
+++ new/dlm-4.1.0/dlm_controld/action.c 2021-01-12 21:24:20.000000000 +0100
@@ -570,15 +570,16 @@
        return rv;
 }
 
-int add_configfs_node(int nodeid, char *addr, int addrlen, int local)
+int add_configfs_node(int nodeid, char *addr, int addrlen, int local,
+                     uint32_t mark)
 {
        char path[PATH_MAX];
        char padded_addr[sizeof(struct sockaddr_storage)];
        char buf[32];
        int rv, fd;
 
-       log_debug("set_configfs_node %d %s local %d",
-                 nodeid, str_ip(addr), local);
+       log_debug("set_configfs_node %d %s local %d mark %" PRIu32,
+                 nodeid, str_ip(addr), local, mark);
 
        /*
         * create comm dir for this node
@@ -640,6 +641,35 @@
        close(fd);
 
        /*
+        * set skb mark for nodeid
+        *
+        * If open() fails we skip it because kernel doesn't support it.
+        * It's not a required confiuration. It will show up in the log.
+        */
+
+       memset(path, 0, PATH_MAX);
+       snprintf(path, PATH_MAX, "%s/%d/mark", COMMS_DIR, nodeid);
+
+       fd = open(path, O_WRONLY);
+       if (fd < 0) {
+               log_error("%s: open failed: %d", path, errno);
+               goto skip_non_required;
+       }
+
+       memset(buf, 0, sizeof(buf));
+       snprintf(buf, 32, "%" PRIu32, mark);
+
+       rv = do_write(fd, buf, strlen(buf));
+       if (rv < 0) {
+               log_error("%s: write failed: %d, %s", path, errno, buf);
+               close(fd);
+               return -1;
+       }
+       close(fd);
+
+skip_non_required:
+
+       /*
         * set local
         */
 
@@ -851,6 +881,12 @@
            dlm_options[timewarn_ind].file_set)
                set_configfs_cluster("timewarn_cs", NULL, opt(timewarn_ind));
 
+       if (dlm_options[port_ind].cli_set ||
+           dlm_options[port_ind].file_set)
+               set_configfs_cluster("tcp_port", NULL, optu(port_ind));
+
+       set_configfs_cluster("mark", NULL, optu(mark_ind));
+
        proto_name = opts(protocol_ind);
        proto_num = -1;
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/dlm-4.0.9/dlm_controld/config.c 
new/dlm-4.1.0/dlm_controld/config.c
--- old/dlm-4.0.9/dlm_controld/config.c 2019-06-11 18:59:32.000000000 +0200
+++ new/dlm-4.1.0/dlm_controld/config.c 2021-01-12 21:24:20.000000000 +0100
@@ -150,12 +150,29 @@
        int rv;
 
        rv = sscanf(line, "%[^=]=%s", key, val);
-       if (rv != 2)
+       if (rv != 2) {
+               log_error("Failed to parse config line %s", line);
                return;
+       }
 
        *val_out = atoi(val);
 }
 
+static void get_val_uint(char *line, unsigned int *val_out)
+{
+       char key[MAX_LINE];
+       char val[MAX_LINE];
+       int rv;
+
+       rv = sscanf(line, "%[^=]=%s", key, val);
+       if (rv != 2) {
+               log_error("Failed to parse config line %s", line);
+               return;
+       }
+
+       *val_out = strtoul(val, NULL, 0);
+}
+
 static void get_val_str(char *line, char *val_out)
 {
        char key[MAX_LINE];
@@ -163,19 +180,22 @@
        int rv;
 
        rv = sscanf(line, "%[^=]=%s", key, val);
-       if (rv != 2)
+       if (rv != 2) {
+               log_error("Failed to parse config line %s", line);
                return;
+       }
 
        strcpy(val_out, val);
 }
 
 void set_opt_file(int update)
 {
+       unsigned int uval = 0;
        struct dlm_option *o;
        FILE *file;
        char line[MAX_LINE];
        char str[MAX_LINE];
-       int i, val;
+       int i, val = 0;
 
        if (!path_exists(CONF_FILE_PATH))
                return;
@@ -238,6 +258,17 @@
                        log_debug("config file %s = %d cli_set %d use %d",
                                  o->name, o->file_int, o->cli_set, o->use_int);
 
+               } else if (o->req_arg == req_arg_uint) {
+                       get_val_uint(line, &uval);
+
+                       o->file_uint = uval;
+
+                       if (!o->cli_set)
+                               o->use_uint = o->file_uint;
+
+                       log_debug("config file %s = %u cli_set %d use %u",
+                                 o->name, o->file_uint, o->cli_set, 
o->use_uint);
+
                } else if (o->req_arg == req_arg_bool) {
                        get_val_int(line, &val);
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/dlm-4.0.9/dlm_controld/cpg.c 
new/dlm-4.1.0/dlm_controld/cpg.c
--- old/dlm-4.0.9/dlm_controld/cpg.c    2019-06-11 18:59:32.000000000 +0200
+++ new/dlm-4.1.0/dlm_controld/cpg.c    2021-01-12 21:24:20.000000000 +0100
@@ -450,21 +450,24 @@
           but that's probably not guaranteed.) */
 
        if (ls->cpg_ringid_wait) {
-               log_group(ls, "check_ringid wait cluster %u cpg %u:%llu",
-                         cluster_ringid_seq, ls->cpg_ringid.nodeid,
+               log_group(ls, "check_ringid wait cluster %u cpg %llu:%llu",
+                         (unsigned long long)cluster_ringid_seq,
+                         ls->cpg_ringid.nodeid,
                          (unsigned long long)ls->cpg_ringid.seq);
                return 0;
        }
 
-       if (cluster_ringid_seq != (uint32_t)ls->cpg_ringid.seq) {
-               log_group(ls, "check_ringid cluster %u cpg %u:%llu",
-                         cluster_ringid_seq, ls->cpg_ringid.nodeid,
+       if (cluster_ringid_seq != ls->cpg_ringid.seq) {
+               log_group(ls, "check_ringid cluster %llu cpg %u:%llu",
+                         (unsigned long long)cluster_ringid_seq,
+                         ls->cpg_ringid.nodeid,
                          (unsigned long long)ls->cpg_ringid.seq);
                return 0;
        }
 
-       log_limit(ls, "check_ringid done cluster %u cpg %u:%llu",
-                 cluster_ringid_seq, ls->cpg_ringid.nodeid,
+       log_limit(ls, "check_ringid done cluster %llu cpg %u:%llu",
+                 (unsigned long long)cluster_ringid_seq,
+                 ls->cpg_ringid.nodeid,
                  (unsigned long long)ls->cpg_ringid.seq);
 
        return 1;
@@ -1864,7 +1867,8 @@
 {
        struct change *cg, *last = NULL;
 
-       strncpy(lockspace->name, ls->name, DLM_LOCKSPACE_LEN);
+       strncpy(lockspace->name, ls->name, DLM_LOCKSPACE_LEN + 1);
+       lockspace->name[DLM_LOCKSPACE_LEN] = '\0';
        lockspace->global_id = ls->global_id;
 
        if (ls->joining)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/dlm-4.0.9/dlm_controld/daemon_cpg.c 
new/dlm-4.1.0/dlm_controld/daemon_cpg.c
--- old/dlm-4.0.9/dlm_controld/daemon_cpg.c     2019-06-11 18:59:32.000000000 
+0200
+++ new/dlm-4.1.0/dlm_controld/daemon_cpg.c     2021-01-12 21:24:20.000000000 
+0100
@@ -2115,7 +2115,7 @@
 int receive_run_request(struct dlm_header *hd, int len)
 {
        struct run_request *req = (struct run_request *)hd;
-       struct run *run;
+       struct run *run = NULL;
 
        run_request_in(req);
 
@@ -2153,7 +2153,7 @@
                return 0;
        }
 
-       if (!opt(enable_helper_ind)) {
+       if (!opt(enable_helper_ind) && run) {
                log_debug("receive_run_request %s helper not enabled", 
req->uuid);
                run->info.reply_count++;
                run->info.need_replies--;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/dlm-4.0.9/dlm_controld/dlm.conf.5 
new/dlm-4.1.0/dlm_controld/dlm.conf.5
--- old/dlm-4.0.9/dlm_controld/dlm.conf.5       2019-06-11 18:59:32.000000000 
+0200
+++ new/dlm-4.1.0/dlm_controld/dlm.conf.5       2021-01-12 21:24:20.000000000 
+0100
@@ -40,6 +40,8 @@
 .br
 bind_all
 .br
+mark
+.br
 debug_logfile
 .br
 enable_plock
@@ -390,6 +392,25 @@
 In which case node 1 will master 2/3 of the total resources and node 2
 will master the other 1/3.
 
+.SS Node configuration
+
+Node configurations can be set by the node keyword followed of key-value
+pairs.
+
+.B Keys:
+
+.B mark
+The mark key can be used to set a specific mark value which is then used
+by the in-kernel DLM socket creation. This can be used to match for DLM
+specfic packets for e.g. routing.
+
+Example of setting a per socket value for nodeid 1 and a mark value
+of 42:
+
+node id=1 mark=42
+
+For local nodes this value doesn't have any effect.
+
 .SH SEE ALSO
 .BR dlm_controld (8),
 .BR dlm_tool (8)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/dlm-4.0.9/dlm_controld/dlm_daemon.h 
new/dlm-4.1.0/dlm_controld/dlm_daemon.h
--- old/dlm-4.0.9/dlm_controld/dlm_daemon.h     2019-06-11 18:59:32.000000000 
+0200
+++ new/dlm-4.1.0/dlm_controld/dlm_daemon.h     2021-01-12 21:24:20.000000000 
+0100
@@ -40,6 +40,7 @@
 #include <sched.h>
 #include <signal.h>
 #include <dirent.h>
+#include <inttypes.h>
 #include <sys/sysmacros.h>
 
 #include <corosync/cpg.h>
@@ -48,6 +49,7 @@
 #include "libdlmcontrol.h"
 #include "dlm_controld.h"
 #include "fence_config.h"
+#include "node_config.h"
 #include "list.h"
 #include "rbtree.h"
 #include "linux_endian.h"
@@ -81,11 +83,14 @@
 #define DEFAULT_LOGFILE_PRIORITY LOG_INFO
 #define DEFAULT_LOGFILE          LOG_FILE_PATH
 
+#define DEFAULT_NETLINK_RCVBUF (2 * 1024 * 1024)
+
 enum {
         no_arg = 0,
         req_arg_bool = 1,
         req_arg_int = 2,
         req_arg_str = 3,
+        req_arg_uint = 4,
 };
 
 enum {
@@ -94,8 +99,10 @@
         log_debug_ind,
         timewarn_ind,
         protocol_ind,
+        port_ind,
         debug_logfile_ind,
        bind_all_ind,
+        mark_ind,
         enable_fscontrol_ind,
         enable_plock_ind,
         plock_debug_ind,
@@ -125,22 +132,27 @@
 
        int use_int;
        char *use_str;
+       unsigned int use_uint;
 
        int default_int;
        const char *default_str;
+       unsigned int default_uint;
 
        int cli_set;
        int cli_int;
        char *cli_str;
+       unsigned int cli_uint;
 
        int file_set;
        int file_int;
        char *file_str;
+       unsigned int file_uint;
 };
 
 EXTERN struct dlm_option dlm_options[dlm_options_max];
 #define opt(x) dlm_options[x].use_int
 #define opts(x) dlm_options[x].use_str
+#define optu(x) dlm_options[x].use_uint
 
 
 /* DLM_LOCKSPACE_LEN: maximum lockspace name length, from linux/dlmconstants.h.
@@ -179,7 +191,7 @@
 EXTERN uint64_t cluster_quorate_monotime;
 EXTERN uint64_t cluster_joined_monotime;
 EXTERN uint64_t cluster_joined_walltime;
-EXTERN uint32_t cluster_ringid_seq;
+EXTERN uint64_t cluster_ringid_seq;
 EXTERN char cluster_name[DLM_LOCKSPACE_LEN+1];
 EXTERN int our_nodeid;
 EXTERN uint32_t control_minor;
@@ -358,7 +370,8 @@
 int set_configfs_members(struct lockspace *ls, char *name,
                         int new_count, int *new_members,
                         int renew_count, int *renew_members);
-int add_configfs_node(int nodeid, char *addr, int addrlen, int local);
+int add_configfs_node(int nodeid, char *addr, int addrlen, int local,
+                     uint32_t mark);
 void del_configfs_node(int nodeid);
 void clear_configfs(void);
 int setup_configfs_options(void);
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/dlm-4.0.9/dlm_controld/fence_config.c 
new/dlm-4.1.0/dlm_controld/fence_config.c
--- old/dlm-4.0.9/dlm_controld/fence_config.c   2019-06-11 18:59:32.000000000 
+0200
+++ new/dlm-4.1.0/dlm_controld/fence_config.c   2021-01-12 21:24:20.000000000 
+0100
@@ -180,11 +180,21 @@
                memset(dev, 0, sizeof(struct fence_device));
                memset(con, 0, sizeof(struct fence_connect));
 
-               strncpy(dev->name, dev_name, FENCE_CONFIG_NAME_MAX-1);
-               strncpy(dev->agent, agent, FENCE_CONFIG_NAME_MAX-1);
-               strncpy(dev->args, dev_args, FENCE_CONFIG_ARGS_MAX-1);
-               strncpy(con->name, con_name, FENCE_CONFIG_NAME_MAX-1);
-               strncpy(con->args, con_args, FENCE_CONFIG_ARGS_MAX-1);
+               strncpy(dev->name, dev_name, FENCE_CONFIG_NAME_MAX);
+               dev->name[FENCE_CONFIG_NAME_MAX - 1] = '\0';
+
+               strncpy(dev->agent, agent, FENCE_CONFIG_NAME_MAX);
+               dev->agent[FENCE_CONFIG_NAME_MAX - 1] = '\0';
+
+               strncpy(dev->args, dev_args, FENCE_CONFIG_ARGS_MAX);
+               dev->args[FENCE_CONFIG_ARGS_MAX - 1] = '\0';
+
+               strncpy(con->name, con_name, FENCE_CONFIG_NAME_MAX);
+               con->name[FENCE_CONFIG_NAME_MAX - 1] = '\0';
+
+               strncpy(con->args, con_args, FENCE_CONFIG_ARGS_MAX);
+               con->args[FENCE_CONFIG_ARGS_MAX - 1] = '\0';
+
                dev->unfence = unfence;
 
                *dev_out = dev;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/dlm-4.0.9/dlm_controld/lib.c 
new/dlm-4.1.0/dlm_controld/lib.c
--- old/dlm-4.0.9/dlm_controld/lib.c    2019-06-11 18:59:32.000000000 +0200
+++ new/dlm-4.1.0/dlm_controld/lib.c    2021-01-12 21:24:20.000000000 +0100
@@ -81,6 +81,17 @@
        return fd;
 }
 
+static inline void init_header_name(struct dlmc_header *h,
+                                   const char *name, size_t len)
+{
+#pragma GCC diagnostic push
+#if __GNUC__ >= 8
+#pragma GCC diagnostic ignored "-Wstringop-truncation"
+#endif
+       strncpy(h->name, name, len);
+#pragma GCC diagnostic pop
+}
+
 static void init_header(struct dlmc_header *h, int cmd, char *name,
                        int extra_len)
 {
@@ -92,7 +103,7 @@
        h->command = cmd;
 
        if (name)
-               strncpy(h->name, name, DLM_LOCKSPACE_LEN);
+               init_header_name(h, name, DLM_LOCKSPACE_LEN);
 }
 
 static char copy_buf[DLMC_DUMP_SIZE];
@@ -881,7 +892,7 @@
 
        init_header(&h, DLMC_CMD_RUN_CHECK, NULL, 0);
        h.flags = flags;
-       strncpy(h.name, run_uuid, DLMC_RUN_UUID_LEN);
+       init_header_name(&h, run_uuid, DLMC_RUN_UUID_LEN);
 
        memset(&rh, 0, sizeof(rh));
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/dlm-4.0.9/dlm_controld/main.c 
new/dlm-4.1.0/dlm_controld/main.c
--- old/dlm-4.0.9/dlm_controld/main.c   2019-06-11 18:59:32.000000000 +0200
+++ new/dlm-4.1.0/dlm_controld/main.c   2021-01-12 21:24:20.000000000 +0100
@@ -765,7 +765,7 @@
 static int setup_uevent(void)
 {
        struct sockaddr_nl snl;
-       int s, rv;
+       int s, rv, val;
 
        s = socket(AF_NETLINK, SOCK_DGRAM, NETLINK_KOBJECT_UEVENT);
        if (s < 0) {
@@ -773,6 +773,41 @@
                return s;
        }
 
+       /* man 7 netlink:
+        *
+        * However,  reliable  transmissions from kernel to user are impossible 
in
+        * any case.  The kernel can't send a netlink message if the socket 
buffer
+        * is  full: the message will be dropped and the kernel and the 
user-space
+        * process will no longer have the same view of kernel state.  It is up 
to
+        * the  application  to  detect  when  this happens (via the ENOBUFS 
error
+        * returned by recvmsg(2)) and resynchronize.
+        *
+        * To avoid ENOBUFS errors we set the netlink socket to realiable
+        * transmission mode which can be turned on by NETLINK_NO_ENOBUFS
+        * option. This option is available since kernel 2.6.30. If this setting
+        * fails we fallback to increase the netlink socket receive buffer.
+        */
+       val = 1;
+       rv = setsockopt(s, SOL_NETLINK, NETLINK_NO_ENOBUFS, &val, sizeof(val));
+       if (rv == -1) {
+               /* Fallback handling if NETLINK_NO_ENOBUFS fails to set.
+                *
+                * To prevent ENOBUFS errors we just set the receive buffer to
+                * two megabyte as other applications do it. This will not
+                * ensure that we never receive ENOBUFS but it's more unlikely.
+                */
+               val = DEFAULT_NETLINK_RCVBUF;
+               log_error("uevent netlink NETLINK_NO_ENOBUFS errno %d, will set 
rcvbuf to %d bytes", errno, val);
+
+               rv = setsockopt(s, SOL_SOCKET, SO_RCVBUF, &val, sizeof(val));
+               if (rv == -1)
+                       log_error("uevent netlink SO_RCVBUF errno %d", errno);
+
+               rv = setsockopt(s, SOL_SOCKET, SO_RCVBUFFORCE, &val, 
sizeof(val));
+               if (rv == -1)
+                       log_error("uevent netlink SO_RCVBUFFORCE errno %d", 
errno);
+       }
+
        memset(&snl, 0, sizeof(snl));
        snl.nl_family = AF_NETLINK;
        snl.nl_pid = getpid();
@@ -788,6 +823,17 @@
        return s;
 }
 
+static inline void init_header_name(struct dlmc_header *h,
+                                   const char *name, size_t len)
+{
+#pragma GCC diagnostic push
+#if __GNUC__ >= 8
+#pragma GCC diagnostic ignored "-Wstringop-truncation"
+#endif
+       strncpy(h->name, name, len);
+#pragma GCC diagnostic pop
+}
+
 static void init_header(struct dlmc_header *h, int cmd, char *name, int result,
                        int extra_len)
 {
@@ -800,7 +846,7 @@
        h->data = result;
 
        if (name)
-               strncpy(h->name, name, DLM_LOCKSPACE_LEN);
+               init_header_name(h, name, DLM_LOCKSPACE_LEN);
 }
 
 static char copy_buf[LOG_DUMP_SIZE];
@@ -1678,6 +1724,8 @@
                        printf(" [%d]\n", o->default_int);
                else if (o->req_arg == req_arg_bool)
                        printf(" [%d]\n", o->default_int);
+               else if (o->req_arg == req_arg_uint)
+                       printf(" [%u]\n", o->default_uint);
                else if (o->req_arg == no_arg && !o->default_int)
                        printf(" [0]\n");
                else
@@ -1688,7 +1736,8 @@
 }
 
 static void set_opt_default(int ind, const char *name, char letter, int 
arg_type,
-                           int default_int, const char *default_str, const 
char *desc)
+                           int default_int, const char *default_str,
+                           unsigned int default_uint, const char *desc)
 {
        dlm_options[ind].name = name;
        dlm_options[ind].letter = letter;
@@ -1696,135 +1745,147 @@
        dlm_options[ind].desc = desc;
        dlm_options[ind].default_int = default_int;
        dlm_options[ind].default_str = default_str;
+       dlm_options[ind].default_uint = default_uint;
        dlm_options[ind].use_int = default_int;
        dlm_options[ind].use_str = (char *)default_str;
+       dlm_options[ind].use_uint = default_uint;
 }
 
 static void set_opt_defaults(void)
 {
        set_opt_default(daemon_debug_ind,
                        "daemon_debug", 'D', no_arg,
-                       0, NULL,
+                       0, NULL, 0,
                        "enable debugging to stderr and don't fork");
 
        set_opt_default(foreground_ind,
                        "foreground", '\0', no_arg,
-                       0, NULL,
+                       0, NULL, 0,
                        "don't fork");
 
        set_opt_default(log_debug_ind,
                        "log_debug", 'K', no_arg,
-                       0, NULL,
+                       0, NULL, 0,
                        "enable kernel dlm debugging messages");
 
        set_opt_default(timewarn_ind,
                        "timewarn", '\0', req_arg_int,
-                       0, NULL,
+                       0, NULL, 0,
                        ""); /* do not advertise */
 
        set_opt_default(protocol_ind,
                        "protocol", 'r', req_arg_str,
-                       -1, "detect",
+                       -1, "detect", 0,
                        "dlm kernel lowcomms protocol: tcp, sctp, detect");
 
+       set_opt_default(port_ind,
+                       "port", 'R', req_arg_uint,
+                       -1, NULL, 21064,
+                       "dlm kernel lowcomms protocol port");
+
        set_opt_default(bind_all_ind,
                        "bind_all", '\0', req_arg_int,
-                       0, NULL,
+                       0, NULL, 0,
                        ""); /* do not advertise */
 
+       set_opt_default(mark_ind,
+                       "mark", '\0', req_arg_uint,
+                       0, NULL, 0,
+                       "set mark value for DLM if not explicit by nodeid 
specified");
+
        set_opt_default(debug_logfile_ind,
                        "debug_logfile", 'L', no_arg,
-                       0, NULL,
+                       0, NULL, 0,
                        "write debugging to log file");
 
        set_opt_default(enable_fscontrol_ind,
                        "enable_fscontrol", '\0', req_arg_bool,
-                       0, NULL,
+                       0, NULL, 0,
                        ""); /* do not advertise */
 
        set_opt_default(enable_plock_ind,
                        "enable_plock", 'p', req_arg_bool,
-                       1, NULL,
+                       1, NULL, 0,
                        "enable/disable posix lock support for cluster fs");
 
        set_opt_default(plock_debug_ind,
                        "plock_debug", 'P', no_arg,
-                       0, NULL,
+                       0, NULL, 0,
                        "enable plock debugging");
 
        set_opt_default(plock_rate_limit_ind,
                        "plock_rate_limit", 'l', req_arg_int,
-                       0, NULL,
+                       0, NULL, 0,
                        "limit rate of plock operations (0 for none)");
 
        set_opt_default(plock_ownership_ind,
                        "plock_ownership", 'o', req_arg_bool,
-                       0, NULL,
+                       0, NULL, 0,
                        "enable/disable plock ownership");
 
        set_opt_default(drop_resources_time_ind,
                        "drop_resources_time", 't', req_arg_int,
-                       10000, NULL,
+                       10000, NULL, 0,
                        "plock ownership drop resources time (milliseconds)");
 
        set_opt_default(drop_resources_count_ind,
                        "drop_resources_count", 'c', req_arg_int,
-                       10, NULL,
+                       10, NULL, 0,
                        "plock ownership drop resources count");
 
        set_opt_default(drop_resources_age_ind,
                        "drop_resources_age", 'a', req_arg_int,
-                       10000, NULL,
+                       10000, NULL, 0,
                        "plock ownership drop resources age (milliseconds)");
 
        set_opt_default(post_join_delay_ind,
                        "post_join_delay", 'j', req_arg_int,
-                       30, NULL,
+                       30, NULL, 0,
                        "seconds to delay fencing after cluster join");
 
        set_opt_default(enable_fencing_ind,
                        "enable_fencing", 'f', req_arg_bool,
-                       1, NULL,
+                       1, NULL, 0,
                        "enable/disable fencing");
 
        set_opt_default(enable_concurrent_fencing_ind,
                        "enable_concurrent_fencing", '\0', req_arg_bool,
-                       0, NULL,
+                       0, NULL, 0,
                        "enable/disable concurrent fencing");
 
        set_opt_default(enable_startup_fencing_ind,
                        "enable_startup_fencing", 's', req_arg_bool,
-                       1, NULL,
+                       1, NULL, 0,
                        "enable/disable startup fencing");
 
        set_opt_default(repeat_failed_fencing_ind,
                        "repeat_failed_fencing", '\0', req_arg_bool,
-                       1, NULL,
+                       1, NULL, 0,
                        "enable/disable retrying after fencing fails");
 
        set_opt_default(enable_quorum_fencing_ind,
                        "enable_quorum_fencing", 'q', req_arg_bool,
-                       1, NULL,
+                       1, NULL, 0,
                        "enable/disable quorum requirement for fencing");
 
        set_opt_default(enable_quorum_lockspace_ind,
                        "enable_quorum_lockspace", '\0', req_arg_bool,
-                       1, NULL,
+                       1, NULL, 0,
                        "enable/disable quorum requirement for lockspace 
operations");
 
        set_opt_default(enable_helper_ind,
                        "enable_helper", '\0', req_arg_bool,
-                       1, NULL,
+                       1, NULL, 0,
                        "enable/disable helper process for running commands");
 
        set_opt_default(help_ind,
                        "help", 'h', no_arg,
-                       -1, NULL,
+                       -1, NULL, 0,
                        "print this help, then exit");
 
        set_opt_default(version_ind,
                        "version", 'V', no_arg,
-                       -1, NULL,
+                       -1, NULL, 0,
                        "Print program version information, then exit");
 }
 
@@ -1972,6 +2033,9 @@
                } else if (o->req_arg == req_arg_bool) {
                        o->cli_int = atoi(arg_str) ? 1 : 0;
                        o->use_int = o->cli_int;
+               } else if (o->req_arg == req_arg_uint) {
+                       o->cli_uint = strtoul(arg_str, NULL, 0);
+                       o->use_uint = o->cli_uint;
                }
        }
 
@@ -2039,6 +2103,10 @@
        set_opt_cli(argc, argv);
        set_opt_file(0);
 
+       rv = node_config_init(CONF_FILE_PATH);
+       if (rv)
+               return 1;
+
        strcpy(fence_all_device.name, "fence_all");
        strcpy(fence_all_device.agent, "dlm_stonith");
        fence_all_device.unfence = 0;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/dlm-4.0.9/dlm_controld/member.c 
new/dlm-4.1.0/dlm_controld/member.c
--- old/dlm-4.0.9/dlm_controld/member.c 2019-06-11 18:59:32.000000000 +0200
+++ new/dlm-4.1.0/dlm_controld/member.c 2021-01-12 21:24:20.000000000 +0100
@@ -20,6 +20,8 @@
 static uint32_t                        quorum_nodes[MAX_NODES];
 static int                     quorum_node_count;
 static struct list_head                cluster_nodes;
+static uint32_t                        leavejoin_nodes[MAX_NODES];
+static int                     leavejoin_count;
 
 struct node_cluster {
        struct list_head list;
@@ -103,14 +105,51 @@
        return is_member(quorum_nodes, quorum_node_count, nodeid);
 }
 
-static void quorum_callback(quorum_handle_t h, uint32_t quorate,
-                           uint64_t ring_seq, uint32_t node_list_entries,
-                           uint32_t *node_list)
+static int is_leavejoin_node(uint32_t nodeid)
+{
+       return is_member(leavejoin_nodes, leavejoin_count, nodeid);
+}
+
+static void quorum_nodelist_callback(quorum_handle_t cbhandle, struct 
quorum_ring_id ring_id,
+                                    uint32_t member_list_entries, const 
uint32_t *member_list,
+                                    uint32_t joined_list_entries, const 
uint32_t *joined_list,
+                                    uint32_t left_list_entries, const uint32_t 
*left_list)
+{
+       uint64_t ring_seq = ring_id.seq;
+       int i, j;
+
+       for (i = 0; i < left_list_entries; i++) {
+               log_debug("cluster left_list %u seq %llu",
+                         left_list[i], (unsigned long long)ring_seq);
+       }
+
+       for (j = 0; j < joined_list_entries; j++) {
+               log_debug("cluster joined_list %u seq %llu",
+                         joined_list[j], (unsigned long long)ring_seq);
+       }
+
+       for (i = 0; i < left_list_entries; i++) {
+               for (j = 0; j < joined_list_entries; j++) {
+                       if (joined_list[j] == left_list[i]) {
+                               log_debug("cluster node %d left and joined", 
joined_list[j]);
+                               if (!is_leavejoin_node(joined_list[j]))
+                                       leavejoin_nodes[leavejoin_count++] = 
joined_list[j];
+                       }
+               }
+       }
+}
+
+static void quorum_callback(quorum_handle_t cbhandle, uint32_t quorate,
+                           struct quorum_ring_id ring_id, uint32_t 
node_list_entries,
+                           const uint32_t *node_list)
 {
        corosync_cfg_node_address_t addrs[MAX_NODE_ADDRESSES];
        corosync_cfg_node_address_t *addrptr = addrs;
+       const struct node_config *nc;
        cs_error_t err;
        int i, j, num_addrs;
+       uint32_t nodeid;
+       uint64_t ring_seq = ring_id.seq;
        uint64_t now = monotime();
 
        if (!cluster_joined_monotime) {
@@ -122,10 +161,10 @@
                cluster_quorate_monotime = now;
 
        cluster_quorate = quorate;
-       cluster_ringid_seq = (uint32_t)ring_seq;
+       cluster_ringid_seq = ring_seq;
 
-       log_debug("cluster quorum %u seq %u nodes %u",
-                 cluster_quorate, cluster_ringid_seq, node_list_entries);
+       log_debug("cluster quorum %u seq %llu nodes %u",
+                 cluster_quorate, (unsigned long long)cluster_ringid_seq, 
node_list_entries);
 
        old_node_count = quorum_node_count;
        memcpy(&old_nodes, &quorum_nodes, sizeof(old_nodes));
@@ -139,17 +178,57 @@
 
        for (i = 0; i < old_node_count; i++) {
                if (!is_cluster_member(old_nodes[i])) {
-                       log_debug("cluster node %u removed seq %u",
-                                 old_nodes[i], cluster_ringid_seq);
+                       log_debug("cluster node %u removed seq %llu",
+                                 old_nodes[i], (unsigned long 
long)cluster_ringid_seq);
+
                        rem_cluster_node(old_nodes[i], now);
                        del_configfs_node(old_nodes[i]);
                }
        }
 
+       for (i = 0; i < leavejoin_count; i++) {
+               nodeid = leavejoin_nodes[i];
+
+               log_debug("cluster node %u leavejoin seq %llu",
+                         nodeid, (unsigned long long)cluster_ringid_seq);
+
+               /* remove */
+
+               rem_cluster_node(nodeid, now);
+               del_configfs_node(nodeid);
+
+               /* add */
+
+               add_cluster_node(nodeid, now);
+
+               fence_delay_begin = now;
+
+               err = corosync_cfg_get_node_addrs(ch, nodeid,
+                                                 MAX_NODE_ADDRESSES,
+                                                 &num_addrs, addrs);
+               if (err != CS_OK) {
+                       log_error("corosync_cfg_get_node_addrs failed nodeid 
%u", nodeid);
+                       continue;
+               }
+
+               nc = node_config_get(nodeid);
+
+               for (j = 0; j < num_addrs; j++) {
+                       add_configfs_node(nodeid,
+                                         addrptr[j].address,
+                                         addrptr[j].address_length,
+                                         (nodeid == our_nodeid),
+                                         nc->mark);
+               }
+       }
+
        for (i = 0; i < quorum_node_count; i++) {
+               if (is_leavejoin_node(quorum_nodes[i]))
+                       continue;
                if (!is_old_member(quorum_nodes[i])) {
-                       log_debug("cluster node %u added seq %u",
-                                 quorum_nodes[i], cluster_ringid_seq);
+                       log_debug("cluster node %u added seq %llu",
+                                 quorum_nodes[i], (unsigned long 
long)cluster_ringid_seq);
+
                        add_cluster_node(quorum_nodes[i], now);
 
                        fence_delay_begin = now;
@@ -163,21 +242,22 @@
                                continue;
                        }
 
+                       nc = node_config_get(quorum_nodes[i]);
+
                        for (j = 0; j < num_addrs; j++) {
                                add_configfs_node(quorum_nodes[i],
                                                  addrptr[j].address,
                                                  addrptr[j].address_length,
                                                  (quorum_nodes[i] ==
-                                                  our_nodeid));
+                                                  our_nodeid),
+                                                 nc->mark);
                        }
                }
        }
-}
 
-static quorum_callbacks_t quorum_callbacks =
-{
-       .quorum_notify_fn = quorum_callback,
-};
+       memset(leavejoin_nodes, 0, sizeof(leavejoin_nodes));
+       leavejoin_count = 0;
+}
 
 void process_cluster(int ci)
 {
@@ -204,23 +284,23 @@
 
 int setup_cluster(void)
 {
+       quorum_model_v1_data_t model_data;
        cs_error_t err;
        int fd;
-       uint32_t quorum_type;
+       uint32_t quorum_type = 0;
 
        INIT_LIST_HEAD(&cluster_nodes);
 
-       err = quorum_initialize(&qh, &quorum_callbacks, &quorum_type);
+       memset(&model_data, 0, sizeof(model_data));
+       model_data.quorum_notify_fn = quorum_callback;
+       model_data.nodelist_notify_fn = quorum_nodelist_callback;
+
+       err = quorum_model_initialize(&qh, QUORUM_MODEL_V1, 
(quorum_model_data_t *)&model_data, &quorum_type, NULL);
        if (err != CS_OK) {
                log_error("quorum init error %d", err);
                return -1;
        }
 
-       if (quorum_type == QUORUM_FREE) {
-               log_error("no quorum provider configured in corosync, unable to 
operate");
-               goto fail;
-       }
-
        err = quorum_fd_get(qh, &fd);
        if (err != CS_OK) {
                log_error("quorum fd_get error %d", err);
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/dlm-4.0.9/dlm_controld/node_config.c 
new/dlm-4.1.0/dlm_controld/node_config.c
--- old/dlm-4.0.9/dlm_controld/node_config.c    1970-01-01 01:00:00.000000000 
+0100
+++ new/dlm-4.1.0/dlm_controld/node_config.c    2021-01-12 21:24:20.000000000 
+0100
@@ -0,0 +1,82 @@
+/*
+ * Copyright 2020 Red Hat, Inc.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU General Public License v2 or (at your option) any later version.
+ */
+
+#include "dlm_daemon.h"
+
+#define MAX_LINE 4096
+
+static struct node_config nc[MAX_NODES];
+
+static const struct node_config nc_default = {
+       .mark = 0,
+};
+
+int node_config_init(const char *path)
+{
+       char line[MAX_LINE], tmp[MAX_LINE];
+       unsigned long mark;
+       FILE *file;
+       int nodeid;
+       int rv;
+
+       /* if no config file is given we assume default node configuration */
+       file = fopen(path, "r");
+       if (!file) {
+               log_debug("No config file %s, we assume default node 
configuration: mark %" PRIu32,
+                         path, nc_default.mark);
+               return 0;
+       }
+
+       while (fgets(line, MAX_LINE, file)) {
+               if (line[0] == '#')
+                       continue;
+               if (line[0] == '\n')
+                       continue;
+
+               if (!strncmp(line, "node", strlen("node"))) {
+                       rv = sscanf(line, "node id=%d mark=%s", &nodeid, tmp);
+                       if (rv < 2) {
+                               log_error("Invalid configuration line: %s", 
line);
+                               rv = -EINVAL;
+                               goto out;
+                       }
+
+                       /* skip invalid nodeid's */
+                       if (nodeid <= 0 || nodeid > MAX_NODES - 1)
+                               continue;
+
+                       mark = strtoul(tmp, NULL, 0);
+                       if (mark == ULONG_MAX) {
+                               log_error("Failed to pars mark value %s will 
use %" PRIu32,
+                                         tmp, nc_default.mark);
+                               mark = nc_default.mark;
+                       }
+                       nc[nodeid].mark = mark;
+
+                       log_debug("parsed node config id=%d mark=%" PRIu32,
+                                 nodeid, mark);
+               }
+       }
+
+       fclose(file);
+       return 0;
+
+out:
+       fclose(file);
+       return rv;
+}
+
+const struct node_config *node_config_get(int nodeid)
+{
+       if (nodeid <= 0 || nodeid > MAX_NODES - 1) {
+               log_debug("node config requested for id=%d returning defaults", 
nodeid);
+               return &nc_default;
+       }
+
+       return &nc[nodeid];
+}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/dlm-4.0.9/dlm_controld/node_config.h 
new/dlm-4.1.0/dlm_controld/node_config.h
--- old/dlm-4.0.9/dlm_controld/node_config.h    1970-01-01 01:00:00.000000000 
+0100
+++ new/dlm-4.1.0/dlm_controld/node_config.h    2021-01-12 21:24:20.000000000 
+0100
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2020 Red Hat, Inc.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU General Public License v2 or (at your option) any later version.
+ */
+
+#ifndef _NODE_CONFIG_H_
+#define _NODE_CONFIG_H_
+
+#include <stdint.h>
+
+struct node_config {
+       uint32_t mark;
+};
+
+/*
+ * Returns -ENOENT if path does not exist or there is no
+ * config for nodeid in the file.
+ *
+ * Returns -EXYZ if there's a problem with the config.
+ *
+ * Returns 0 if a config was found with no problems.
+ */
+
+int node_config_init(const char *path);
+
+const struct node_config *node_config_get(int nodeid);
+
+#endif
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/dlm-4.0.9/dlm_tool/main.c 
new/dlm-4.1.0/dlm_tool/main.c
--- old/dlm-4.0.9/dlm_tool/main.c       2019-06-11 18:59:32.000000000 +0200
+++ new/dlm-4.1.0/dlm_tool/main.c       2021-01-12 21:24:20.000000000 +0100
@@ -224,6 +224,7 @@
        int need_lsname;
        int need_command = 0;
        int need_uuid = 0;
+       int optional_lsname = 0;
        int i;
        char modebuf[8];
 
@@ -332,6 +333,7 @@
                        operation = OP_LIST;
                        opt_ind = optind + 1;
                        need_lsname = 0;
+                       optional_lsname = 1;
                        break;
                } else if (!strncmp(argv[optind], "status", 6) &&
                           (strlen(argv[optind]) == 6)) {
@@ -428,8 +430,17 @@
                exit(EXIT_FAILURE);
        }
 
-       if (!need_lsname && !need_uuid && !need_command)
+       /*
+        * The operation does not require an arg, but may
+        * accept an optional arg, i.e. dlm_tool ls [name]
+        */
+       if (!need_lsname && !need_uuid && !need_command) {
+               if (optind < argc - 1) {
+                       if (optional_lsname)
+                               lsname = argv[opt_ind];
+               }
                return;
+       }
 
        if (optind < argc - 1) {
                if (need_lsname)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/dlm-4.0.9/include/version.cf 
new/dlm-4.1.0/include/version.cf
--- old/dlm-4.0.9/include/version.cf    2019-06-11 18:59:32.000000000 +0200
+++ new/dlm-4.1.0/include/version.cf    2021-01-12 21:24:20.000000000 +0100
@@ -1,6 +1,6 @@
 #ifndef _RELEASE_VERSION_CF_
 #define _RELEASE_VERSION_CF_
 
-#define RELEASE_VERSION "4.0.9"
+#define RELEASE_VERSION "4.1.0"
 
 #endif

Reply via email to