Compare commits

...

No commits in common. "c8" and "c10s" have entirely different histories.
c8 ... c10s

15 changed files with 538 additions and 601 deletions

37
.gitignore vendored
View File

@ -1 +1,36 @@
SOURCES/sanlock-3.8.4.tar.gz
/sanlock-1.0.tar.gz
/sanlock-1.1.0.tar.bz2
/sanlock-1.2.0.tar.bz2
/sanlock-1.3.tar.gz
/sanlock-1.4.tar.gz
/sanlock-1.6.tar.gz
/sanlock-1.8.tar.gz
/sanlock-2.1.tar.gz
/sanlock-2.2.tar.gz
/sanlock-2.3.tar.gz
/sanlock-2.4.tar.gz
/sanlock-2.5.tar.gz
/sanlock-2.6.tar.gz
/sanlock-2.7.tar.gz
/sanlock-2.8.tar.gz
/sanlock-3.0.0.tar.gz
/sanlock-3.1.0.tar.gz
/sanlock-3.2.0.tar.gz
/sanlock-3.2.1.tar.gz
/sanlock-3.2.2.tar.gz
/sanlock-3.2.4.tar.gz
/sanlock-3.3.0.tar.gz
/sanlock-3.4.0.tar.gz
/sanlock-3.5.0.tar.gz
/sanlock-3.6.0.tar.gz
/sanlock-3.7.0.tar.gz
/sanlock-3.7.1.tar.gz
/sanlock-3.7.3.tar.gz
/sanlock-3.8.0.tar.gz
/sanlock-3.8.1.tar.gz
/sanlock-3.8.3.tar.gz
/sanlock-3.8.4.tar.gz
/sanlock-3.8.5.tar.gz
/sanlock-3.9.0.tar.gz
/sanlock-3.9.4.tar.gz
/sanlock-3.9.5.tar.gz

View File

@ -0,0 +1,108 @@
From 5044719a27cb41889ec08177cba977596b783e83 Mon Sep 17 00:00:00 2001
From: Nir Soffer <nsoffer@redhat.com>
Date: Sun, 2 Aug 2020 02:01:06 +0300
Subject: [PATCH] python: Remove extra link args
Fedora 33 builds fails now with:
/usr/bin/ld: /tmp/sanlock.cpython-39-x86_64-linux-gnu.so.mpvMfj.ltrans0.ltrans.o:
relocation R_X86_64_PC32 against undefined symbol `PyExc_ValueError' can
not be used when making a shared object; recompile with -fPIC
We use these extra link args:
extra_link_args=['-fPIE', '-Wl,-z,relro,-z,now'],
Looking the generated compiler command[1]:
gcc -pthread \
-shared \
-Wl,-z,relro \
-Wl,--as-needed \
-Wl,-z,now \
-g \
-Wl,-z,relro \
-Wl,--as-needed \
-Wl,-z,now \
-g \
-Wl,-z,relro \
-Wl,--as-needed \
-Wl,-z,now \
-specs=/usr/lib/rpm/redhat/redhat-hardened-ld \
-O2 \
-fexceptions \
-g \
-grecord-gcc-switches \
-pipe \
-Wall \
-Werror=format-security \
-Wp,-D_FORTIFY_SOURCE=2 \
-Wp,-D_GLIBCXX_ASSERTIONS \
-specs=/usr/lib/rpm/redhat/redhat-hardened-cc1 \
-fstack-protector-strong \
-specs=/usr/lib/rpm/redhat/redhat-annobin-cc1 \
-m64 \
-mtune=generic \
-fasynchronous-unwind-tables \
-fstack-clash-protection \
-fcf-protection build/temp.linux-x86_64-3.9/sanlock.o \
-L../src \
-L/usr/lib64 \
-lsanlock \
-o build/lib.linux-x86_64-3.9/sanlock.cpython-39-x86_64-linux-gnu.so \
-fPIE \
-Wl,-z,relro,-z,now
This looks like a complete mess. These arguments are repeated 3 times:
-Wl,-z,relro \
-Wl,--as-needed \
-Wl,-z,now \
And our extra compiler flags adds the forth copy.
gcc says this about -fPIE:
These options are similar to -fpic and -fPIC, but the generated
position-independent code can be only linked into executables
But our python extension is a shared object, so I don't think -fPIE
makes sense.
The extra arguments were added in:
commit a1929080a6ce51879139eb8d05a425ccd3d37082
Author: David Teigland <teigland@redhat.com>
Date: Wed Oct 14 13:21:04 2015 -0500
python: add compile flags
Without any justification. I assume the intent was good, but it looks
like this change was not needed, and somehow it worked until now.
If some hardening is needed, it should be done by python build
infrastructure, not in sanlock. And it seems that python do use some
hardening specs (e.g. -specs=/usr/lib/rpm/redhat/redhat-hardened-ld).
[1] https://kojipkgs.fedoraproject.org//work/tasks/8900/48358900/build.log
Signed-off-by: Nir Soffer <nsoffer@redhat.com>
---
python/setup.py | 1 -
1 file changed, 1 deletion(-)
diff --git a/python/setup.py b/python/setup.py
index 0f3d683..b3bfaf1 100644
--- a/python/setup.py
+++ b/python/setup.py
@@ -12,7 +12,6 @@ sanlock = Extension(name='sanlock',
include_dirs=['../src'],
library_dirs=['../src'],
extra_compile_args=["-std=c99"],
- extra_link_args=['-fPIE', '-Wl,-z,relro,-z,now'],
libraries=sanlocklib)
version = None
--
2.25.4

View File

@ -0,0 +1,50 @@
From 5b34da78d33c2fca7dc3d2c49ae6d395d90c48c1 Mon Sep 17 00:00:00 2001
From: David Teigland <teigland@redhat.com>
Date: Wed, 14 Aug 2024 11:51:17 -0500
Subject: [PATCH] sanlock: fix invalid strcpy in direct dump
If a lockspace or resource name is the full 48 characters
in length, then the ondisk name field does not contain a
terminating null character and strcpy fails.
---
src/direct.c | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/src/direct.c b/src/direct.c
index f70dc19d5ef2..3bc7659e905c 100644
--- a/src/direct.c
+++ b/src/direct.c
@@ -730,8 +730,8 @@ int direct_dump(struct task *task, char *dump_path, int force_mode)
if (!lr->owner_id && !lr->owner_generation)
continue;
- strcpy(sname, lr->space_name);
- strcpy(rname, lr->resource_name);
+ memcpy(sname, lr->space_name, NAME_ID_SIZE);
+ memcpy(rname, lr->resource_name, NAME_ID_SIZE);
printf("%08llu %36s %48s %010llu %04llu %04llu",
(unsigned long long)(start_offset + ((sector_nr + i) * sector_size)),
@@ -754,8 +754,8 @@ int direct_dump(struct task *task, char *dump_path, int force_mode)
leader_record_in(lr_end, &lr_in);
lr = &lr_in;
- strcpy(sname, lr->space_name);
- strcpy(rname, lr->resource_name);
+ memcpy(sname, lr->space_name, NAME_ID_SIZE);
+ memcpy(rname, lr->resource_name, NAME_ID_SIZE);
printf("%08llu %36s %48s %010llu %04llu %04llu %llu",
(unsigned long long)(start_offset + (sector_nr * sector_size)),
@@ -806,7 +806,7 @@ int direct_dump(struct task *task, char *dump_path, int force_mode)
rindex_header_in(rh_end, &rh_in);
rh = &rh_in;
- strcpy(sname, rh->lockspace_name);
+ memcpy(sname, rh->lockspace_name, NAME_ID_SIZE);
printf("%08llu %36s rindex_header 0x%x %d %u %llu\n",
(unsigned long long)(start_offset + (sector_nr * sector_size)),
--
2.46.0

View File

@ -0,0 +1,29 @@
From 9c626f97b25bf1973ece91c6f5dd67628bb0abd1 Mon Sep 17 00:00:00 2001
From: David Teigland <teigland@redhat.com>
Date: Fri, 18 Oct 2024 12:57:49 -0500
Subject: [PATCH] systemd-wdmd: work around race with udev setting softdog
label
After modprobe softdog, udev wants to set permission and/or label
on the watchdog device. Wait until that's done before trying to
test/probe the watchdog device. RHEL-56479
---
init.d/systemd-wdmd | 2 ++
1 file changed, 2 insertions(+)
diff --git a/init.d/systemd-wdmd b/init.d/systemd-wdmd
index 001609736287..c3126c408a89 100644
--- a/init.d/systemd-wdmd
+++ b/init.d/systemd-wdmd
@@ -19,6 +19,8 @@ watchdog_check() {
if [ $retval -ne 0 ]; then
echo -n $"Loading the softdog kernel module: "
modprobe softdog
+ # handle delay in udev setting permission/label
+ udevadm settle
watchdog_probe
retval=$?
--
2.46.2

View File

@ -0,0 +1,167 @@
From 6240d633b229e15d445868a8b1463fb8ee6ddbc6 Mon Sep 17 00:00:00 2001
From: David Teigland <teigland@redhat.com>
Date: Wed, 23 Oct 2024 14:51:04 -0500
Subject: [PATCH] sanlock: new NODELAY flag for add_lockspace
Forces the existing "no delay" path for acquiring a host_id
delta lease. This avoids delays in add_lockspace that are
used to detect machines using the same host_id. So, using
this flag is unsafe if multiple hosts may end up using the
same host_id.
---
src/cmd.c | 3 ++-
src/delta_lease.c | 8 ++++++--
src/delta_lease.h | 1 +
src/direct.c | 1 +
src/lockspace.c | 5 +++--
src/lockspace.h | 2 +-
src/sanlock_admin.h | 1 +
src/sanlock_internal.h | 1 +
8 files changed, 16 insertions(+), 6 deletions(-)
diff --git a/src/cmd.c b/src/cmd.c
index e91da9d3eb41..47656bbb7f75 100644
--- a/src/cmd.c
+++ b/src/cmd.c
@@ -1306,6 +1306,7 @@ static void cmd_add_lockspace(struct cmd_args *ca, uint32_t cmd)
struct space *sp;
uint32_t io_timeout;
int async = ca->header.cmd_flags & SANLK_ADD_ASYNC;
+ int nodelay = (ca->header.cmd_flags & SANLK_ADD_NODELAY) ? 1 : 0;
int fd, rv, result;
fd = client[ca->ci_in].fd;
@@ -1329,7 +1330,7 @@ static void cmd_add_lockspace(struct cmd_args *ca, uint32_t cmd)
if (!io_timeout)
io_timeout = com.io_timeout;
- rv = add_lockspace_start(&lockspace, io_timeout, &sp);
+ rv = add_lockspace_start(&lockspace, io_timeout, nodelay, &sp);
if (rv < 0) {
result = rv;
goto reply;
diff --git a/src/delta_lease.c b/src/delta_lease.c
index fb4a6402858d..144c0ea0ee11 100644
--- a/src/delta_lease.c
+++ b/src/delta_lease.c
@@ -332,6 +332,7 @@ int delta_lease_acquire(struct task *task,
char *space_name,
char *our_host_name,
uint64_t host_id,
+ int nodelay,
struct leader_record *leader_ret)
{
struct leader_record leader;
@@ -394,13 +395,16 @@ int delta_lease_acquire(struct task *task,
no_delay = 1;
if (is_same && our_host_name_matches_product_uuid)
no_delay = 1;
+ if (nodelay)
+ no_delay = 1;
- log_space(sp, "delta_acquire %s owner, %s free, %s our_product_uuid, %s delay, other_io_timeout %d",
+ log_space(sp, "delta_acquire %s owner, %s free, %s our_product_uuid, %s delay, other_io_timeout %d, flag_nodelay %d",
is_same ? "same" : "new",
is_free ? "is" : "not",
our_host_name_matches_product_uuid ? "is" : "not",
no_delay ? "no" : "short",
- other_io_timeout);
+ other_io_timeout,
+ nodelay);
goto write_new;
}
diff --git a/src/delta_lease.h b/src/delta_lease.h
index ec1c3468bf72..22c6faa16995 100644
--- a/src/delta_lease.h
+++ b/src/delta_lease.h
@@ -24,6 +24,7 @@ int delta_lease_acquire(struct task *task,
char *space_name,
char *our_host_name,
uint64_t host_id,
+ int nodelay,
struct leader_record *leader_ret);
int delta_lease_renew(struct task *task,
diff --git a/src/direct.c b/src/direct.c
index 3bc7659e905c..1f4064795c4a 100644
--- a/src/direct.c
+++ b/src/direct.c
@@ -364,6 +364,7 @@ static int do_delta_action(int action,
ls->name,
our_host_name,
ls->host_id,
+ 0,
&leader);
break;
case ACT_RENEW_ID:
diff --git a/src/lockspace.c b/src/lockspace.c
index a2bee3f478fd..1cea79d41618 100644
--- a/src/lockspace.c
+++ b/src/lockspace.c
@@ -973,7 +973,7 @@ static void *lockspace_thread(void *arg_in)
delta_result = delta_lease_acquire(&task, sp, &sp->host_id_disk,
sp->space_name, our_host_name_global,
- sp->host_id, &leader);
+ sp->host_id, sp->nodelay, &leader);
delta_length = monotime() - delta_begin;
if (delta_result == SANLK_OK)
@@ -1152,7 +1152,7 @@ static void free_sp(struct space *sp)
free(sp);
}
-int add_lockspace_start(struct sanlk_lockspace *ls, uint32_t io_timeout, struct space **sp_out)
+int add_lockspace_start(struct sanlk_lockspace *ls, uint32_t io_timeout, int nodelay, struct space **sp_out)
{
struct space *sp, *sp2;
int listnum = 0;
@@ -1178,6 +1178,7 @@ int add_lockspace_start(struct sanlk_lockspace *ls, uint32_t io_timeout, struct
sp->host_id_disk.fd = -1;
sp->host_id = ls->host_id;
sp->io_timeout = io_timeout;
+ sp->nodelay = nodelay;
sp->set_bitmap_seconds = calc_set_bitmap_seconds(io_timeout);
pthread_mutex_init(&sp->mutex, NULL);
diff --git a/src/lockspace.h b/src/lockspace.h
index 0c3cba324e31..790a5cc68499 100644
--- a/src/lockspace.h
+++ b/src/lockspace.h
@@ -42,7 +42,7 @@ int check_our_lease(struct space *sp, int *check_all, char *check_buf);
void check_other_leases(struct space *sp, char *buf);
/* locks spaces_mutex */
-int add_lockspace_start(struct sanlk_lockspace *ls, uint32_t io_timeout, struct space **sp_out);
+int add_lockspace_start(struct sanlk_lockspace *ls, uint32_t io_timeout, int nodelay, struct space **sp_out);
/* locks sp, locks spaces_mutex */
int add_lockspace_wait(struct space *sp);
diff --git a/src/sanlock_admin.h b/src/sanlock_admin.h
index 685cce11d6f3..10bfc49b312b 100644
--- a/src/sanlock_admin.h
+++ b/src/sanlock_admin.h
@@ -12,6 +12,7 @@
/* add flags */
#define SANLK_ADD_ASYNC 0x00000001
+#define SANLK_ADD_NODELAY 0x00000002 /* can be unsafe */
/* rem flags */
#define SANLK_REM_ASYNC 0x00000001
diff --git a/src/sanlock_internal.h b/src/sanlock_internal.h
index ebb0a9c319c1..e57127b17233 100644
--- a/src/sanlock_internal.h
+++ b/src/sanlock_internal.h
@@ -217,6 +217,7 @@ struct space {
uint32_t renewal_read_extend_sec; /* defaults to io_timeout */
uint32_t rindex_op;
unsigned int set_max_sectors_kb;
+ int nodelay;
int sector_size;
int align_size;
int max_hosts;
--
2.46.2

View File

@ -1,30 +0,0 @@
From e82899fd996f4901e1ec89d77e4a17a1032fee8f Mon Sep 17 00:00:00 2001
From: David Teigland <teigland@redhat.com>
Date: Thu, 3 Mar 2022 09:39:52 -0600
Subject: [PATCH 1/4] sanlock: fix memory leak of lockspace renewal_history
Leak was in original commit for "sanlock: renewal history"
6313c709722b3ba63234a75d1651a160bf1728ee.
With the default renewal history size, each lockspace that
was created would leak about 4kb of memory.
---
src/lockspace.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/src/lockspace.c b/src/lockspace.c
index 2ebc247dce41..d23dccd84815 100644
--- a/src/lockspace.c
+++ b/src/lockspace.c
@@ -939,6 +939,8 @@ static void free_sp(struct space *sp)
{
if (sp->lease_status.renewal_read_buf)
free(sp->lease_status.renewal_read_buf);
+ if (sp->renewal_history)
+ free(sp->renewal_history);
free(sp);
}
--
2.7.5

View File

@ -1,51 +0,0 @@
From e44c47c48a3a71502deacbafda851cb6d93e78c8 Mon Sep 17 00:00:00 2001
From: David Teigland <teigland@redhat.com>
Date: Wed, 9 Mar 2022 15:25:11 -0600
Subject: [PATCH 2/4] sanlock: fix pthread_create error check
for non-zero rather than less than zero
---
src/lockspace.c | 4 ++--
src/main.c | 4 ++--
2 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/src/lockspace.c b/src/lockspace.c
index d23dccd84815..582a0e973566 100644
--- a/src/lockspace.c
+++ b/src/lockspace.c
@@ -1070,8 +1070,8 @@ int add_lockspace_start(struct sanlk_lockspace *ls, uint32_t io_timeout, struct
(unsigned long long)sp->host_id_disk.offset);
rv = pthread_create(&sp->thread, NULL, lockspace_thread, sp);
- if (rv < 0) {
- log_erros(sp, "add_lockspace create thread failed");
+ if (rv) {
+ log_erros(sp, "add_lockspace create thread failed %d", rv);
goto fail_del;
}
diff --git a/src/main.c b/src/main.c
index 5b6fabc6d0b8..613fb0ee23d5 100644
--- a/src/main.c
+++ b/src/main.c
@@ -995,7 +995,7 @@ static int thread_pool_add_work(struct cmd_args *ca)
if (!pool.free_workers && pool.num_workers < pool.max_workers) {
rv = pthread_create(&th, NULL, thread_pool_worker,
(void *)(long)pool.num_workers);
- if (rv < 0) {
+ if (rv) {
log_error("thread_pool_add_work ci %d error %d", ca->ci_in, rv);
list_del(&ca->list);
pthread_mutex_unlock(&pool.mutex);
@@ -1035,7 +1035,7 @@ static int thread_pool_create(int min_workers, int max_workers)
for (i = 0; i < min_workers; i++) {
rv = pthread_create(&th, NULL, thread_pool_worker,
(void *)(long)i);
- if (rv < 0)
+ if (rv)
break;
pool.num_workers++;
}
--
2.7.5

View File

@ -1,42 +0,0 @@
From 4ed90cfb2462d3463ae74935c5eeb9d9588ea098 Mon Sep 17 00:00:00 2001
From: David Teigland <teigland@redhat.com>
Date: Thu, 17 Mar 2022 13:41:31 -0500
Subject: [PATCH 3/4] Revert "sanlock: Shrink thread pool when there is no
work"
This reverts commit 0ff9c1ab8852bec846822ee2af55ebcb7e5f5967.
This patch causes unexplained growth in memory usage.
Part of the problem may be that the worker threads are
not joined and the detached state is not set, but an
initial test setting the detached state didn't seem
to fix the problem.
---
src/main.c | 4 ----
1 file changed, 4 deletions(-)
diff --git a/src/main.c b/src/main.c
index 613fb0ee23d5..b447b723a490 100644
--- a/src/main.c
+++ b/src/main.c
@@ -946,9 +946,6 @@ static void *thread_pool_worker(void *data)
while (1) {
while (!pool.quit && list_empty(&pool.work_data)) {
- if (pool.free_workers >= DEFAULT_MIN_WORKER_THREADS)
- goto out;
-
pool.free_workers++;
pthread_cond_wait(&pool.cond, &pool.mutex);
pool.free_workers--;
@@ -969,7 +966,6 @@ static void *thread_pool_worker(void *data)
break;
}
-out:
pool.num_workers--;
if (!pool.num_workers)
pthread_cond_signal(&pool.quit_wait);
--
2.7.5

View File

@ -1,63 +0,0 @@
From 574d3cc3ecccd1e8a6c1a8a861dd4847a05789f5 Mon Sep 17 00:00:00 2001
From: David Teigland <teigland@redhat.com>
Date: Fri, 18 Mar 2022 09:32:06 -0500
Subject: [PATCH 4/4] sanlock: fix pthread_create error paths
The fix for pthread_create errors in commit
5abb9d50616d399914958b99352b8cf016e4928a
sanlock: fix pthread_create error check
missed error handling further in the exit path.
---
src/lockspace.c | 1 +
src/main.c | 8 ++++++--
2 files changed, 7 insertions(+), 2 deletions(-)
diff --git a/src/lockspace.c b/src/lockspace.c
index 582a0e973566..d9b79f6de257 100644
--- a/src/lockspace.c
+++ b/src/lockspace.c
@@ -1072,6 +1072,7 @@ int add_lockspace_start(struct sanlk_lockspace *ls, uint32_t io_timeout, struct
rv = pthread_create(&sp->thread, NULL, lockspace_thread, sp);
if (rv) {
log_erros(sp, "add_lockspace create thread failed %d", rv);
+ rv = -1;
goto fail_del;
}
diff --git a/src/main.c b/src/main.c
index b447b723a490..5a0f9ba677ff 100644
--- a/src/main.c
+++ b/src/main.c
@@ -995,6 +995,7 @@ static int thread_pool_add_work(struct cmd_args *ca)
log_error("thread_pool_add_work ci %d error %d", ca->ci_in, rv);
list_del(&ca->list);
pthread_mutex_unlock(&pool.mutex);
+ rv = -1;
return rv;
}
pool.num_workers++;
@@ -1019,7 +1020,7 @@ static void thread_pool_free(void)
static int thread_pool_create(int min_workers, int max_workers)
{
pthread_t th;
- int i, rv;
+ int i, rv = 0;
memset(&pool, 0, sizeof(pool));
INIT_LIST_HEAD(&pool.work_data);
@@ -1031,8 +1032,11 @@ static int thread_pool_create(int min_workers, int max_workers)
for (i = 0; i < min_workers; i++) {
rv = pthread_create(&th, NULL, thread_pool_worker,
(void *)(long)i);
- if (rv)
+ if (rv) {
+ log_error("thread_pool_create failed %d", rv);
+ rv = -1;
break;
+ }
pool.num_workers++;
}
--
2.7.5

View File

@ -1,308 +0,0 @@
From acc0021a9490ae4964c08a6839308efa2709f926 Mon Sep 17 00:00:00 2001
From: David Teigland <teigland@redhat.com>
Date: Tue, 16 Jan 2024 11:01:01 -0600
Subject: [PATCH] wdmd: adjust values for iTCO_wdt
iTCO_wdt does not fire until two successive timeouts, so the
values for set/get need to be adjusted by a factor or 2 to
make the watchdog fire at the correct time.
---
wdmd/main.c | 162 ++++++++++++++++++++++++++++++++++++++++++++--------
1 file changed, 139 insertions(+), 23 deletions(-)
diff --git a/wdmd/main.c b/wdmd/main.c
index aebacbea1ead..de54e6ddcdf1 100644
--- a/wdmd/main.c
+++ b/wdmd/main.c
@@ -31,6 +31,7 @@
#include <sys/un.h>
#include <sys/stat.h>
#include <sys/mman.h>
+#include <sys/time.h>
#include <sys/signalfd.h>
#include <linux/watchdog.h>
@@ -55,6 +56,7 @@
#define DEFAULT_SOCKET_MODE (S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP)
#define WDPATH_SIZE 64
+#define WD_ID_SIZE 64
static int test_interval = DEFAULT_TEST_INTERVAL;
static int fire_timeout = DEFAULT_FIRE_TIMEOUT;
@@ -68,6 +70,8 @@ static time_t last_closeunclean;
static char lockfile_path[PATH_MAX];
static int dev_fd = -1;
static int shm_fd;
+static int forcefire;
+static int itco; /* watchdog_identity is "iTCO_wdt" */
static int allow_scripts;
static int kill_script_sec;
@@ -75,6 +79,7 @@ static const char *scripts_dir = "/etc/wdmd.d";
static char watchdog_path[WDPATH_SIZE];
static char option_path[WDPATH_SIZE];
static char saved_path[WDPATH_SIZE];
+static char watchdog_identity[WD_ID_SIZE];
struct script_status {
uint64_t start;
@@ -141,6 +146,19 @@ static uint64_t monotime(void)
return ts.tv_sec;
}
+char time_str_buf[128];
+
+static char *time_str(void)
+{
+ struct timeval cur_time;
+ struct tm time_info;
+
+ gettimeofday(&cur_time, NULL);
+ localtime_r(&cur_time.tv_sec, &time_info);
+ strftime(time_str_buf, sizeof(time_str_buf), "%Y-%m-%d %H:%M:%S ", &time_info);
+ return time_str_buf;
+}
+
/*
* test clients
*/
@@ -979,6 +997,49 @@ static void close_watchdog(void)
dev_fd = -1;
}
+static int setup_identity(char *wdpath)
+{
+ char sysfs_path[PATH_MAX] = { 0 };
+ char *base, *p;
+ int fd, rv;
+
+ /*
+ * This function will be called multiple times when probing
+ * different watchdog paths for one that works.
+ */
+ itco = 0;
+ memset(watchdog_identity, 0, sizeof(watchdog_identity));
+
+ /*
+ * $ cat /sys/class/watchdog/watchdog0/identity
+ * iTCO_wdt
+ */
+ if (!(base = basename(wdpath)))
+ return -1;
+
+ snprintf(sysfs_path, PATH_MAX-1, "/sys/class/watchdog/%s/identity", base);
+
+ if ((fd = open(sysfs_path, O_RDONLY)) < 0)
+ return -1;
+
+ rv = read(fd, watchdog_identity, WD_ID_SIZE-1);
+
+ close(fd);
+
+ if (rv <= 0)
+ return -1;
+
+ if ((p = strchr(watchdog_identity, '\n')))
+ *p = '\0';
+
+ log_debug("%s %s %s", wdpath, sysfs_path, watchdog_identity);
+
+ if (!strcmp(watchdog_identity, "iTCO_wdt"))
+ itco = 1;
+
+ return 0;
+}
+
static int _setup_watchdog(char *path)
{
struct stat buf;
@@ -991,6 +1052,8 @@ static int _setup_watchdog(char *path)
if (rv < 0)
return -1;
+ setup_identity(path); /* Sets watchdog_identity and itco */
+
rv = open_dev();
if (rv < 0)
return -1;
@@ -1004,10 +1067,15 @@ static int _setup_watchdog(char *path)
return -1;
}
- if (timeout == fire_timeout)
- goto out;
-
- timeout = fire_timeout;
+ if (itco) {
+ if ((2 * timeout) == fire_timeout)
+ goto out;
+ timeout = fire_timeout / 2;
+ } else {
+ if (timeout == fire_timeout)
+ goto out;
+ timeout = fire_timeout;
+ }
rv = ioctl(dev_fd, WDIOC_SETTIMEOUT, &timeout);
if (rv < 0) {
@@ -1016,13 +1084,20 @@ static int _setup_watchdog(char *path)
return -1;
}
- if (timeout != fire_timeout) {
- log_error("%s failed to set new timeout", watchdog_path);
- close_watchdog();
- return -1;
+ if (itco) {
+ if ((2 * timeout) != fire_timeout) {
+ log_error("%s failed to set new timeout", watchdog_path);
+ close_watchdog();
+ return -1;
+ }
+ } else {
+ if (timeout != fire_timeout) {
+ log_error("%s failed to set new timeout", watchdog_path);
+ close_watchdog();
+ return -1;
+ }
}
out:
- log_error("%s armed with fire_timeout %d", watchdog_path, fire_timeout);
/* TODO: save watchdog_path in /run/wdmd/saved_path,
* and in startup read that file, copying it to saved_path */
@@ -1102,6 +1177,8 @@ static int probe_dev(const char *path)
return -1;
}
+ setup_identity((char *)path); /* Sets watchdog_identity and itco */
+
fd = open(path, O_WRONLY | O_CLOEXEC);
if (fd < 0) {
fprintf(stderr, "error %d open %s\n", errno, path);
@@ -1117,14 +1194,22 @@ static int probe_dev(const char *path)
goto out;
}
- if (timeout == fire_timeout) {
- printf("%s\n", path);
- rv = 0;
- goto out;
+ if (itco) {
+ if ((2 * timeout) == fire_timeout) {
+ printf("%s\n", path);
+ rv = 0;
+ goto out;
+ }
+ timeout = fire_timeout / 2;
+ } else {
+ if (timeout == fire_timeout) {
+ printf("%s\n", path);
+ rv = 0;
+ goto out;
+ }
+ timeout = fire_timeout;
}
- timeout = fire_timeout;
-
rv = ioctl(fd, WDIOC_SETTIMEOUT, &timeout);
if (rv < 0) {
fprintf(stderr, "error %d ioctl settimeout %s\n", errno, path);
@@ -1132,10 +1217,18 @@ static int probe_dev(const char *path)
goto out;
}
- if (timeout != fire_timeout) {
- fprintf(stderr, "error %d invalid timeout %s\n", errno, path);
- rv = -1;
- goto out;
+ if (itco) {
+ if ((2 * timeout) != fire_timeout) {
+ fprintf(stderr, "error %d invalid timeout %s\n", errno, path);
+ rv = -1;
+ goto out;
+ }
+ } else {
+ if (timeout != fire_timeout) {
+ fprintf(stderr, "error %d invalid timeout %s\n", errno, path);
+ rv = -1;
+ goto out;
+ }
}
printf("%s\n", path);
@@ -1518,6 +1611,7 @@ static void print_usage_and_exit(int status)
printf("--dump, -d print debug from daemon\n");
printf("--probe, -p print path of functional watchdog device\n");
printf("-D debug: no fork and print all logging to stderr\n");
+ printf("-F force watchdog reset for testing (use with -D)\n");
printf("-H 0|1 use high priority features (1 yes, 0 no, default %d)\n",
DEFAULT_HIGH_PRIORITY);
printf("-G <name> group ownership for the socket\n");
@@ -1556,11 +1650,12 @@ int main(int argc, char *argv[])
{"help", no_argument, 0, 'h' },
{"probe", no_argument, 0, 'p' },
{"dump", no_argument, 0, 'd' },
+ {"forcefire", no_argument, 0, 'F' },
{"version", no_argument, 0, 'V' },
{0, 0, 0, 0 }
};
- c = getopt_long(argc, argv, "hpdVDH:G:S:s:k:w:",
+ c = getopt_long(argc, argv, "hpdVDFH:G:S:s:k:w:",
long_options, &option_index);
if (c == -1)
break;
@@ -1581,6 +1676,9 @@ int main(int argc, char *argv[])
case 'D':
daemon_debug = 1;
break;
+ case 'F':
+ forcefire = 1;
+ break;
case 'G':
socket_gname = strdup(optarg);
break;
@@ -1633,9 +1731,6 @@ int main(int argc, char *argv[])
openlog("wdmd", LOG_CONS | LOG_PID, LOG_DAEMON);
- log_error("wdmd started S%d H%d G%d", allow_scripts, high_priority,
- socket_gid);
-
setup_priority();
rv = lockfile();
@@ -1666,6 +1761,27 @@ int main(int argc, char *argv[])
if (rv < 0)
goto out_clients;
+ log_error("wdmd started S%d H%d G%d using %s \"%s\"", allow_scripts, high_priority,
+ socket_gid, watchdog_path, watchdog_identity[0] ? watchdog_identity : "unknown");
+ log_error("%s armed with fire_timeout %d", watchdog_path, fire_timeout);
+
+ if (daemon_debug && forcefire) {
+ int sleep_sec = 0;
+ int i;
+ setbuf(stdout, NULL);
+ printf("%s waiting for watchdog to reset machine:\n", time_str());
+ for (i = 1; i < fire_timeout + 5; i++) {
+ sleep(1);
+ sleep_sec++;
+ if (sleep_sec >= fire_timeout+1)
+ printf("%s %d %s failed to fire after timeout %d seconds\n", time_str(), i, watchdog_path, fire_timeout);
+ else
+ printf("%s %d\n", time_str(), i);
+ }
+ close_watchdog();
+ return -1;
+ }
+
rv = test_loop();
close_watchdog();
--
2.43.0

View File

@ -0,0 +1,12 @@
diff --git a/init.d/systemd-wdmd b/init.d/systemd-wdmd
index 001609736287..c358afa14af7 100644
--- a/init.d/systemd-wdmd
+++ b/init.d/systemd-wdmd
@@ -19,6 +19,7 @@ watchdog_check() {
if [ $retval -ne 0 ]; then
echo -n $"Loading the softdog kernel module: "
modprobe softdog
+ udevadm settle
watchdog_probe
retval=$?

BIN
sanlock-3.9.1.tar.gz Normal file

Binary file not shown.

BIN
sanlock-3.9.3.tar.gz Normal file

Binary file not shown.

View File

@ -1,54 +1,41 @@
Name: sanlock
Version: 3.8.4
Release: 5%{?dist}
Version: 3.9.5
Release: 3%{?dist}
Summary: A shared storage lock manager
Group: System Environment/Base
License: GPLv2 and GPLv2+ and LGPLv2+
License: GPL-2.0-only AND GPL-2.0-or-later AND LGPL-2.0-or-later
URL: https://pagure.io/sanlock/
BuildRequires: gcc
BuildRequires: libaio-devel
BuildRequires: libblkid-devel
BuildRequires: libuuid-devel
BuildRequires: make
BuildRequires: python3
BuildRequires: python3-devel
BuildRequires: systemd-units
BuildRequires: systemd-rpm-macros
%{?sysusers_requires_compat}
Requires: %{name}-lib = %{version}-%{release}
Requires(pre): /usr/sbin/groupadd
Requires(pre): /usr/sbin/useradd
Requires(post): systemd-units
Requires(post): systemd-sysv
Requires(preun): systemd-units
Requires(postun): systemd-units
Source0: https://releases.pagure.org/sanlock/%{name}-%{version}.tar.gz
Patch1: 0001-sanlock-fix-memory-leak-of-lockspace-renewal_history.patch
Patch2: 0002-sanlock-fix-pthread_create-error-check.patch
Patch3: 0003-Revert-sanlock-Shrink-thread-pool-when-there-is-no-w.patch
Patch4: 0004-sanlock-fix-pthread_create-error-paths.patch
Patch5: 0005-wdmd-adjust-values-for-iTCO_wdt.patch
%global python_package python3-%{name}
Patch0: 0001-systemd-wdmd-work-around-race-with-udev-setting-soft.patch
Patch1: 0002-sanlock-new-NODELAY-flag-for-add_lockspace.patch
%description
The sanlock daemon manages leases for applications on hosts using shared storage.
%prep
%setup -q
%patch0 -p1 -b .backup0
%patch1 -p1 -b .backup1
%patch2 -p1 -b .backup2
%patch3 -p1 -b .backup3
%patch4 -p1 -b .backup4
%patch5 -p1 -b .backup5
%build
%set_build_flags
# upstream does not require configure
# upstream does not support _smp_mflags
CFLAGS=$RPM_OPT_FLAGS make -C wdmd
CFLAGS=$RPM_OPT_FLAGS make -C src
CFLAGS=$RPM_OPT_FLAGS make -C python PY_VERSION=3.6
CFLAGS=$RPM_OPT_FLAGS make -C reset
%install
rm -rf $RPM_BUILD_ROOT
@ -58,19 +45,12 @@ make -C src \
make -C wdmd \
install LIBDIR=%{_libdir} \
DESTDIR=$RPM_BUILD_ROOT
make -C python \
install LIBDIR=%{_libdir} \
DESTDIR=$RPM_BUILD_ROOT \
PY_VERSION=3.6
make -C reset \
install LIBDIR=%{_libdir} \
DESTDIR=$RPM_BUILD_ROOT
install -D -m 0644 init.d/sanlock.service.native $RPM_BUILD_ROOT/%{_unitdir}/sanlock.service
install -D -m 0755 init.d/wdmd $RPM_BUILD_ROOT/usr/lib/systemd/systemd-wdmd
install -D -m 0644 init.d/wdmd.service.native $RPM_BUILD_ROOT/%{_unitdir}/wdmd.service
install -D -m 0644 init.d/sanlk-resetd.service $RPM_BUILD_ROOT/%{_unitdir}/sanlk-resetd.service
install -D -m 0755 init.d/systemd-wdmd $RPM_BUILD_ROOT/usr/lib/systemd/systemd-wdmd
install -D -m 0644 init.d/wdmd.service $RPM_BUILD_ROOT/%{_unitdir}/wdmd.service
install -p -D -m 0644 src/sanlock.sysusers $RPM_BUILD_ROOT/%{_sysusersdir}/sanlock.conf
install -D -m 0644 src/logrotate.sanlock \
$RPM_BUILD_ROOT/etc/logrotate.d/sanlock
@ -82,16 +62,9 @@ install -D -m 0644 init.d/wdmd.sysconfig \
$RPM_BUILD_ROOT/etc/sysconfig/wdmd
install -Dd -m 0755 $RPM_BUILD_ROOT/etc/wdmd.d
install -Dd -m 0775 $RPM_BUILD_ROOT/%{_rundir}/sanlock
install -Dd -m 0775 $RPM_BUILD_ROOT/%{_rundir}/sanlk-resetd
%pre
getent group sanlock > /dev/null || /usr/sbin/groupadd \
-g 179 sanlock
getent passwd sanlock > /dev/null || /usr/sbin/useradd \
-u 179 -c "sanlock" -s /sbin/nologin -r \
-g 179 -d /run/sanlock sanlock
/usr/sbin/usermod -a -G disk sanlock
%sysusers_create_compat src/sanlock.sysusers
%post
%systemd_post wdmd.service sanlock.service
@ -110,19 +83,15 @@ getent passwd sanlock > /dev/null || /usr/sbin/useradd \
%{_sbindir}/wdmd
%dir %{_sysconfdir}/wdmd.d
%dir %{_sysconfdir}/sanlock
%dir %attr(-,sanlock,sanlock) %{_rundir}/sanlock
%{_mandir}/man8/wdmd*
%{_mandir}/man8/sanlock*
%config(noreplace) %{_sysconfdir}/logrotate.d/sanlock
%config(noreplace) %{_sysconfdir}/sanlock/sanlock.conf
%config(noreplace) %{_sysconfdir}/sysconfig/wdmd
%doc init.d/sanlock
%doc init.d/sanlock.service
%doc init.d/wdmd.service
%{_sysusersdir}/sanlock.conf
%package lib
Summary: A shared storage lock manager library
Group: System Environment/Libraries
%description lib
The %{name}-lib package contains the runtime libraries for sanlock,
@ -137,23 +106,8 @@ access to the shared disks.
%{_libdir}/libsanlock_client.so.*
%{_libdir}/libwdmd.so.*
%package -n %{python_package}
Summary: Python bindings for the sanlock library
Group: Development/Libraries
Requires: %{name}-lib = %{version}-%{release}
%description -n %{python_package}
The %{python_package} package contains a module that permits applications
written in the Python programming language to use the interface
supplied by the sanlock library.
%files -n %{python_package}
%{python3_sitearch}/sanlock_python-*.egg-info
%{python3_sitearch}/sanlock*.so
%package devel
Summary: Development files for %{name}
Group: Development/Libraries
Requires: %{name}-lib = %{version}-%{release}
%description devel
@ -173,65 +127,140 @@ developing applications that use %{name}.
%{_libdir}/pkgconfig/libsanlock.pc
%{_libdir}/pkgconfig/libsanlock_client.pc
%package -n sanlk-reset
Summary: Host reset daemon and client using sanlock
Group: System Environment/Base
Requires: sanlock = %{version}-%{release}
Requires: sanlock-lib = %{version}-%{release}
%description -n sanlk-reset
The sanlk-reset package contains the reset daemon and client.
A cooperating host running the daemon can be reset by a host
running the client, so long as both maintain access to a
common sanlock lockspace.
%files -n sanlk-reset
%{_sbindir}/sanlk-reset
%{_sbindir}/sanlk-resetd
%{_unitdir}/sanlk-resetd.service
%dir %attr(-,root,root) %{_rundir}/sanlk-resetd
%{_mandir}/man8/sanlk-reset*
%changelog
* Tue Jan 30 2024 David Teigland <teigland@redhat.com> - 3.8.4-5
- adjust wdmd values for iTCO_wdt watchdog driver
* Tue Oct 29 2024 Troy Dawson <tdawson@redhat.com> - 3.9.5-3
- Bump release for October 2024 mass rebuild:
Resolves: RHEL-64018
* Wed Jul 06 2022 David Teigland <teigland@redhat.com> - 3.8.4-4
- rebuild with larger release number
* Wed Oct 23 2024 David Teigland <teigland@redhat.com> - 3.9.5-2
- new nodelay flag for add_lockspace
* Fri Mar 18 2022 David Teigland <teigland@redhat.com> - 3.8.4-2
- Resolves: rhbz#2058438
* Tue Oct 22 2024 David Teigland <teigland@redhat.com> - 3.9.5-1
- new upstream release
* Tue Jun 01 2021 David Teigland <teigland@redhat.com> 3.8.4-1
- Update to sanlock-3.8.4
* Thu Oct 03 2024 David Teigland <teigland@redhat.com> - 3.9.4-3
- fix install of sanlock.sysusers
* Thu May 20 2021 David Teigland <teigland@redhat.com> 3.8.3-2
- Fix connection close and add python inquire api
* Wed Aug 14 2024 David Teigland <teigland@redhat.com> - 3.9.4-2
- fix invalid strcpy in direct dump
* Tue Jan 19 2021 David Teigland <teigland@redhat.com> 3.8.3-1
- Update to sanlock-3.8.3
* Fri Aug 09 2024 David Teigland <teigland@redhat.com> - 3.9.4-1
- new upstream release, adopt sysusers, drop python bindings
* Mon Aug 10 2020 David Teigland <teigland@redhat.com> 3.8.2-1
- Update to sanlock-3.8.2
* Mon Jun 24 2024 Troy Dawson <tdawson@redhat.com> - 3.9.0-3
- Bump release for June 2024 mass rebuild
* Thu Jul 09 2020 David Teigland <teigland@redhat.com> 3.8.1-1
* Sat Jan 27 2024 Fedora Release Engineering <releng@fedoraproject.org> - 3.9.0-2
- Rebuilt for https://fedoraproject.org/wiki/Fedora_40_Mass_Rebuild
* Fri Dec 15 2023 David Teigland <teigland@redhat.com> - 3.9.0-1
- rebase to new upstream release
* Sat Jul 22 2023 Fedora Release Engineering <releng@fedoraproject.org> - 3.8.5-4
- Rebuilt for https://fedoraproject.org/wiki/Fedora_39_Mass_Rebuild
* Tue Jun 13 2023 Python Maint <python-maint@redhat.com> - 3.8.5-3
- Rebuilt for Python 3.12
* Sat Jan 21 2023 Fedora Release Engineering <releng@fedoraproject.org> - 3.8.5-2
- Rebuilt for https://fedoraproject.org/wiki/Fedora_38_Mass_Rebuild
* Tue Oct 18 2022 David Teigland <teigland@redhat.com> - 3.8.5-1
- Update to sanlock-3.8.5
* Sat Jul 23 2022 Fedora Release Engineering <releng@fedoraproject.org> - 3.8.4-6
- Rebuilt for https://fedoraproject.org/wiki/Fedora_37_Mass_Rebuild
* Mon Jun 13 2022 Python Maint <python-maint@redhat.com> - 3.8.4-5
- Rebuilt for Python 3.11
* Sat Jan 22 2022 Fedora Release Engineering <releng@fedoraproject.org> - 3.8.4-4
- Rebuilt for https://fedoraproject.org/wiki/Fedora_36_Mass_Rebuild
* Fri Jul 23 2021 Fedora Release Engineering <releng@fedoraproject.org> - 3.8.4-3
- Rebuilt for https://fedoraproject.org/wiki/Fedora_35_Mass_Rebuild
* Fri Jun 04 2021 Python Maint <python-maint@redhat.com> - 3.8.4-2
- Rebuilt for Python 3.10
* Thu Jun 03 2021 David Teigland <teigland@redhat.com> 3.8.4-1
- New upstream release
* Wed Feb 24 2021 David Teigland <teigland@redhat.com> 3.8.3-1
- New upstream release
- Drop sanlk-reset which is not used.
* Wed Jan 27 2021 Fedora Release Engineering <releng@fedoraproject.org> - 3.8.1-8
- Rebuilt for https://fedoraproject.org/wiki/Fedora_34_Mass_Rebuild
* Sat Aug 08 2020 Nir Soffer <nsoffer@redhat.com> - 3.8.1-7
- Enable LTO
* Sun Aug 02 2020 Nir Soffer <nsoffer@redhat.com> - 3.8.1-6
- Removing extra linkeer args, hopefully fix python build
* Sat Aug 01 2020 Fedora Release Engineering <releng@fedoraproject.org> - 3.8.1-5
- Second attempt - Rebuilt for
https://fedoraproject.org/wiki/Fedora_33_Mass_Rebuild
* Wed Jul 29 2020 Fedora Release Engineering <releng@fedoraproject.org> - 3.8.1-4
- Rebuilt for https://fedoraproject.org/wiki/Fedora_33_Mass_Rebuild
* Tue Jul 08 2020 Jeff Law <law@redhat.com> - 3.8.1-3
- Disable LTO
* Tue May 26 2020 Miro Hrončok <mhroncok@redhat.com> - 3.8.1-2
- Rebuilt for Python 3.9
* Sat May 2 2020 Nir Soffer <nsoffer@redhat.com> - 3.8.1-1
- Update to sanlock-3.8.1
* Wed Jun 12 2019 Nir Soffer <nsoffer@redhat.com> 3.8.0-2
- kick the gating tests to run
* Thu Jan 30 2020 Fedora Release Engineering <releng@fedoraproject.org> - 3.8.0-4
- Rebuilt for https://fedoraproject.org/wiki/Fedora_32_Mass_Rebuild
* Wed Jun 12 2019 Nir Soffer <nsoffer@redhat.com> 3.8.0-1
- Cleanup spec and convert to python3
* Mon Aug 19 2019 Miro Hrončok <mhroncok@redhat.com> - 3.8.0-3
- Rebuilt for Python 3.8
* Thu Dec 06 2018 David Teigland <teigland@redhat.com> - 3.6.0-5
- Fix selinux lockfile error
* Fri Jul 26 2019 Fedora Release Engineering <releng@fedoraproject.org> - 3.8.0-2
- Rebuilt for https://fedoraproject.org/wiki/Fedora_31_Mass_Rebuild
* Thu Oct 04 2018 David Teigland <teigland@redhat.com> - 3.6.0-4
- makefile gcc flags
* Wed Jun 12 2019 Nir Soffer <nsoffer@redhat.com> - 3.8.0-1
- Update to sanlock-3.8.0
- Convert spec to python 3
* Tue Jun 12 2018 Charalampos Stratakis <cstratak@redhat.com> - 3.6.0-3
- Conditionalize the python2 subpackage
* Tue May 21 2019 Nir Soffer <nsoffer@redhat.com> - 3.7.3-1
- Update to sanlock-3.7.3
- Add missing BuildRequires and Requires
* Fri Apr 12 2019 Nir Soffer <nsoffer@redhat.com> - 3.7.1-2
- Cleanup up align and sector constants
* Mon Apr 8 2019 Nir Soffer <nsoffer@redhat.com> - 3.7.1-1
- Update to sanlock 3.7.1
- Fix read_resource_owners (414abfe)
* Wed Mar 20 2019 Nir Soffer <nsoffer@redhat.com> - 3.7.0-1
- remove unneeded with_systemd macro
- update to sanlock 3.7.0
* Sat Feb 2 2019 Nir Soffer <nsoffer@redhat.com> - 3.6.0-8
- fix build on Fedora rawhide
* Thu Jan 24 2019 David Teigland <teigland@redhat.com> - 3.6.0-7
- lockfile ownership
* Sat Jul 14 2018 Fedora Release Engineering <releng@fedoraproject.org> - 3.6.0-6
- Rebuilt for https://fedoraproject.org/wiki/Fedora_29_Mass_Rebuild
* Thu Apr 12 2018 Iryna Shcherbina <shcherbina.iryna@gmail.com> - 3.6.0-5
- Update Python 2 dependency declarations to new packaging standards
(See https://fedoraproject.org/wiki/FinalizingFedoraSwitchtoPython3)
* Wed Mar 14 2018 David Teigland <teigland@redhat.com> - 3.6.0-4
- change makefile flags
* Wed Mar 14 2018 David Teigland <teigland@redhat.com> - 3.6.0-3
- rebuild with set_build_flags
* Fri Feb 09 2018 Fedora Release Engineering <releng@fedoraproject.org> - 3.6.0-2
- Rebuilt for https://fedoraproject.org/wiki/Fedora_28_Mass_Rebuild

1
sources Normal file
View File

@ -0,0 +1 @@
SHA512 (sanlock-3.9.5.tar.gz) = 2342ee57d98c0e209d92ad809aae22f919c02920a2db194be2fc4f60677c32c2f27621ab0183b69c36ae1d0814753fb3461985bc4a8d1bced879b403ff0cf400