[SCM] Samba Shared Repository - branch master updated

Martin Schwenke martins at samba.org
Fri Jul 26 04:53:02 UTC 2019


The branch, master has been updated
       via  ea7708d8c7f ctdb-scripts: Simplify 01.reclock.script
       via  38898775e6f ctdb-scripts: Drop monitoring of recovery lock
       via  5701f4aecaf ctdb-tests: Add some 01.reclock.script init event tests
       via  ecef4411302 ctdb-tests: Fix 01.reclock.script tests for non-default lock
       via  2bd316d01d3 ctdb-tests: Add tests for cluster mutex lost handling
       via  41cd44724e2 ctdb-mutex: Add support for exiting if the lock file disappears
       via  af8de1bcfd4 ctdb-mutex: Add an intermediate asynchronous computation for waiting
       via  fae8e438f01 ctdb-mutex: Change parent checking to use an asynchronous computation
       via  2f768a090e0 ctdb-mutex: Exit immediately if the lock isn't taken
       via  d716be19ea1 ctdb-tests: Add test to confirm need for cluster mutex lock file rechecking
       via  adcf313c49c ctdb-tests: Add cluster mutex tests
       via  2b6f1a8ee64 ctdb-mutex: Drop dependency on ctdb_set_helper
       via  76ab0a2b82d ctdb-mutex: Drop unneeded assignment
       via  98169241ef7 ctdb-mutex: Update to use modern debug macro
       via  c276723dd89 ctdb-tests: Set LANG=C for consistency of command output
       via  6fe963c3f72 ctdb-recoverd: Periodically log recovery master of incomplete cluster
       via  f2559ef8ce0 ctdb-recoverd: Log the master at the end of elections
       via  6b7b1e80800 ctdb-tests: Add tests for empty values in config file
       via  efd0c45a8b1 ctdb-common: Fix empty value handling in conf
       via  242ea955e67 ctdb-tests: Use required_error instead of required_result
      from  1f923e067db s3:rpc_server: Only dump passwords in developer builds

https://git.samba.org/?p=samba.git;a=shortlog;h=master


- Log -----------------------------------------------------------------
commit ea7708d8c7fa674111ccea58b3cd0757765c702a
Author: Martin Schwenke <martin at meltin.net>
Date:   Mon Jul 8 16:35:57 2019 +1000

    ctdb-scripts: Simplify 01.reclock.script
    
    The "init" event is only run once so don't bother caching the
    configured value of the recovery lock.  Add some extra error checking.
    
    Signed-off-by: Martin Schwenke <martin at meltin.net>
    Reviewed-by: Amitay Isaacs <amitay at gmail.com>
    
    Autobuild-User(master): Martin Schwenke <martins at samba.org>
    Autobuild-Date(master): Fri Jul 26 04:52:04 UTC 2019 on sn-devel-184

commit 38898775e6f1fb25171c920f2d8bcce24ec51476
Author: Martin Schwenke <martin at meltin.net>
Date:   Mon Jul 8 13:30:06 2019 +1000

    ctdb-scripts: Drop monitoring of recovery lock
    
    The fcntl helper now does a more meaningful check.
    
    Signed-off-by: Martin Schwenke <martin at meltin.net>
    Reviewed-by: Amitay Isaacs <amitay at gmail.com>

commit 5701f4aecafcd4efeba5bc12ace5da3101ea49d9
Author: Martin Schwenke <martin at meltin.net>
Date:   Mon Jul 8 16:37:41 2019 +1000

    ctdb-tests: Add some 01.reclock.script init event tests
    
    Signed-off-by: Martin Schwenke <martin at meltin.net>
    Reviewed-by: Amitay Isaacs <amitay at gmail.com>

commit ecef4411302113b0513db30169a8481a0a521316
Author: Martin Schwenke <martin at meltin.net>
Date:   Mon Jul 8 16:17:27 2019 +1000

    ctdb-tests: Fix 01.reclock.script tests for non-default lock
    
    These tests currently do not do what is expected.  They test the
    default case.
    
    Signed-off-by: Martin Schwenke <martin at meltin.net>
    Reviewed-by: Amitay Isaacs <amitay at gmail.com>

commit 2bd316d01d3ddf733787eba6092f5880b7feb65a
Author: Martin Schwenke <martin at meltin.net>
Date:   Fri Jul 19 13:41:30 2019 +1000

    ctdb-tests: Add tests for cluster mutex lost handling
    
    Signed-off-by: Martin Schwenke <martin at meltin.net>
    Reviewed-by: Amitay Isaacs <amitay at gmail.com>

commit 41cd44724e2d035d006645407ed623600d0ec6d8
Author: Martin Schwenke <martin at meltin.net>
Date:   Thu Jun 27 16:14:26 2019 +1000

    ctdb-mutex: Add support for exiting if the lock file disappears
    
    If the lock file is inaccessible or the inode number changes then the
    lock is lost, so exit.  This allows the recovery daemon to trigger an
    election.  The ensuing recovery will re-take the lock.
    
    By default the lock file is checked every 60 seconds.  A lot can
    happen in 60 seconds but being more aggressive and accessing the lock
    too often could result in a performance issue for the cluster
    filesystem.
    
    An new optional 2nd argument is added, which is the lock file re-check
    time in seconds.
    
    Signed-off-by: Martin Schwenke <martin at meltin.net>
    Reviewed-by: Amitay Isaacs <amitay at gmail.com>

commit af8de1bcfd4cfb2b2517b5badcc9ab564276fb92
Author: Martin Schwenke <martin at meltin.net>
Date:   Thu Jun 27 14:13:50 2019 +1000

    ctdb-mutex: Add an intermediate asynchronous computation for waiting
    
    This will allow more conditions to be waited on via additional
    sub-requests.  At the moment this just completes when the parent wait
    completes.
    
    Signed-off-by: Martin Schwenke <martin at meltin.net>
    Reviewed-by: Amitay Isaacs <amitay at gmail.com>

commit fae8e438f019e7c1d20582f167b3adeac781ddbe
Author: Martin Schwenke <martin at meltin.net>
Date:   Thu Jun 27 13:45:01 2019 +1000

    ctdb-mutex: Change parent checking to use an asynchronous computation
    
    Put the checking for the process being immediately re-parented into
    the computation too.  This will be very rare and doing it
    consistently makes testing saner.
    
    Signed-off-by: Martin Schwenke <martin at meltin.net>
    Reviewed-by: Amitay Isaacs <amitay at gmail.com>

commit 2f768a090e0a1f34660227e1aedc0ed03ea98534
Author: Martin Schwenke <martin at meltin.net>
Date:   Fri Jul 5 15:39:23 2019 +1000

    ctdb-mutex: Exit immediately if the lock isn't taken
    
    There is no need to wait until the parent kills the helper.  The
    parent will get the initial response, indicating contention or
    similar, and will then get a separate event indicating that the pipe
    is gone.
    
    Signed-off-by: Martin Schwenke <martin at meltin.net>
    Reviewed-by: Amitay Isaacs <amitay at gmail.com>

commit d716be19ea14f15984eab8ce3388eb90bbb49d0a
Author: Martin Schwenke <martin at meltin.net>
Date:   Mon Jul 8 20:51:11 2019 +1000

    ctdb-tests: Add test to confirm need for cluster mutex lock file rechecking
    
    Remove the lock and a second locker can take the it.
    
    Signed-off-by: Martin Schwenke <martin at meltin.net>
    Reviewed-by: Amitay Isaacs <amitay at gmail.com>

commit adcf313c49cbd4e411d6f3fb50e90642f3b7531c
Author: Martin Schwenke <martin at meltin.net>
Date:   Thu Jul 4 21:52:00 2019 +1000

    ctdb-tests: Add cluster mutex tests
    
    Signed-off-by: Martin Schwenke <martin at meltin.net>
    Reviewed-by: Amitay Isaacs <amitay at gmail.com>

commit 2b6f1a8ee648017dcdb595aacc0469d28e30d00e
Author: Martin Schwenke <martin at meltin.net>
Date:   Fri Jul 19 11:14:43 2019 +1000

    ctdb-mutex: Drop dependency on ctdb_set_helper
    
    This makes the code more explicit and makes testing easier due to less
    dependencies.
    
    Signed-off-by: Martin Schwenke <martin at meltin.net>
    Reviewed-by: Amitay Isaacs <amitay at gmail.com>

commit 76ab0a2b82db76ee48e98ae9ca6a4af18a99f68c
Author: Martin Schwenke <martin at meltin.net>
Date:   Wed Jul 17 13:31:27 2019 +1000

    ctdb-mutex: Drop unneeded assignment
    
    clang warns:
    
      ctdb/server/ctdb_mutex_fcntl_helper.c:61:3: warning: Value stored to 'fd' is never read
    
    Signed-off-by: Martin Schwenke <martin at meltin.net>
    Reviewed-by: Amitay Isaacs <amitay at gmail.com>

commit 98169241ef74d92beb433639834dfc0decc52a75
Author: Martin Schwenke <martin at meltin.net>
Date:   Fri Jul 5 13:13:16 2019 +1000

    ctdb-mutex: Update to use modern debug macro
    
    One of these had a missing space, so this implicitly fixes it.  It
    also drops the need to unnecessarily include common.h, which comes
    with some dependency baggage.
    
    Signed-off-by: Martin Schwenke <martin at meltin.net>
    Reviewed-by: Amitay Isaacs <amitay at gmail.com>

commit c276723dd89995100ec42402eee65d6e3a623d03
Author: Martin Schwenke <martin at meltin.net>
Date:   Tue Jul 9 12:42:24 2019 +1000

    ctdb-tests: Set LANG=C for consistency of command output
    
    Signed-off-by: Martin Schwenke <martin at meltin.net>
    Reviewed-by: Amitay Isaacs <amitay at gmail.com>

commit 6fe963c3f72680ecbed1b6f9c70a7af003115666
Author: Martin Schwenke <martin at meltin.net>
Date:   Tue Jul 16 08:58:33 2019 +1000

    ctdb-recoverd: Periodically log recovery master of incomplete cluster
    
    Only do this if the recovery lock is unset.  Log every minute for the
    first 10 minutes, then every 10 minutes, then every hour.
    
    This is useful for determining whether a split brain occurred.  It is
    particularly useful if logging failed or was throttled at startup, so
    there is no evidence of the split brain when it began.
    
    Signed-off-by: Martin Schwenke <martin at meltin.net>
    Reviewed-by: Amitay Isaacs <amitay at gmail.com>

commit f2559ef8ce01a46b33a9295e67da920a327f3929
Author: Martin Schwenke <martin at meltin.net>
Date:   Mon Jul 15 09:15:04 2019 +1000

    ctdb-recoverd: Log the master at the end of elections
    
    Signed-off-by: Martin Schwenke <martin at meltin.net>
    Reviewed-by: Amitay Isaacs <amitay at gmail.com>

commit 6b7b1e8080096ccf64bfa236db597cec0856e6b7
Author: Amitay Isaacs <amitay at gmail.com>
Date:   Thu Jul 25 15:15:43 2019 +1000

    ctdb-tests: Add tests for empty values in config file
    
    Signed-off-by: Amitay Isaacs <amitay at gmail.com>
    Reviewed-by: Martin Schwenke <martin at meltin.net>

commit efd0c45a8b152eb4716193bea6cf95e9e0b97d8b
Author: Amitay Isaacs <amitay at gmail.com>
Date:   Thu Jul 25 15:14:32 2019 +1000

    ctdb-common: Fix empty value handling in conf
    
    In tini, allow_empty_value=false causes the parser to ignore the lines
    without '=' sign, but lines with nothing after '=' sign are allowed and
    cause empty string ("") to be passed as a value.
    
    This is counter-intuitive, so conf requires special handling for empty
    values (which are treated as invalid).
    
    Signed-off-by: Amitay Isaacs <amitay at gmail.com>
    Reviewed-by: Martin Schwenke <martin at meltin.net>

commit 242ea955e672799c45aba47f454900a5a52ce9f6
Author: Amitay Isaacs <amitay at gmail.com>
Date:   Thu Jul 25 15:15:23 2019 +1000

    ctdb-tests: Use required_error instead of required_result
    
    Signed-off-by: Amitay Isaacs <amitay at gmail.com>
    Reviewed-by: Martin Schwenke <martin at meltin.net>

-----------------------------------------------------------------------

Summary of changes:
 ctdb/common/conf.c                                 |   8 +
 ctdb/config/events/legacy/01.reclock.script        |  80 +--
 ctdb/server/ctdb_cluster_mutex.c                   |  66 +-
 ctdb/server/ctdb_mutex_fcntl_helper.c              | 361 +++++++++-
 ctdb/server/ctdb_recoverd.c                        | 121 +++-
 ctdb/tests/cunit/cluster_mutex_001.sh              |  59 ++
 ctdb/tests/cunit/cluster_mutex_002.sh              |  91 +++
 ctdb/tests/cunit/cluster_mutex_003.sh              |  68 ++
 ctdb/tests/cunit/conf_test_001.sh                  |  34 +-
 ...clock.monitor.001.sh => 01.reclock.init.001.sh} |   4 +-
 ...clock.monitor.003.sh => 01.reclock.init.002.sh} |   4 +-
 ctdb/tests/eventscripts/01.reclock.init.003.sh     |  30 +
 ctdb/tests/eventscripts/01.reclock.monitor.002.sh  |  12 -
 ctdb/tests/eventscripts/01.reclock.monitor.004.sh  |  18 -
 ctdb/tests/eventscripts/01.reclock.monitor.005.sh  |  28 -
 ctdb/tests/eventscripts/scripts/01.reclock.sh      |  22 +-
 ctdb/tests/scripts/common.sh                       |   5 +
 ctdb/tests/src/cluster_mutex_test.c                | 725 +++++++++++++++++++++
 ctdb/wscript                                       |   9 +-
 19 files changed, 1572 insertions(+), 173 deletions(-)
 create mode 100755 ctdb/tests/cunit/cluster_mutex_001.sh
 create mode 100755 ctdb/tests/cunit/cluster_mutex_002.sh
 create mode 100755 ctdb/tests/cunit/cluster_mutex_003.sh
 rename ctdb/tests/eventscripts/{01.reclock.monitor.001.sh => 01.reclock.init.001.sh} (77%)
 rename ctdb/tests/eventscripts/{01.reclock.monitor.003.sh => 01.reclock.init.002.sh} (50%)
 create mode 100755 ctdb/tests/eventscripts/01.reclock.init.003.sh
 delete mode 100755 ctdb/tests/eventscripts/01.reclock.monitor.002.sh
 delete mode 100755 ctdb/tests/eventscripts/01.reclock.monitor.004.sh
 delete mode 100755 ctdb/tests/eventscripts/01.reclock.monitor.005.sh
 create mode 100644 ctdb/tests/src/cluster_mutex_test.c


Changeset truncated at 500 lines:

diff --git a/ctdb/common/conf.c b/ctdb/common/conf.c
index 3d668de3122..e849ff4322f 100644
--- a/ctdb/common/conf.c
+++ b/ctdb/common/conf.c
@@ -1130,6 +1130,14 @@ static bool conf_load_option(const char *name,
 		}
 	}
 
+	if (strlen(value_str) == 0) {
+		D_ERR("conf: empty value [%s] -> \"%s\"\n",
+		      state->s->name,
+		      name);
+		state->err = EINVAL;
+		return true;
+	}
+
 	tmp_ctx = talloc_new(state->conf);
 	if (tmp_ctx == NULL) {
 		state->err = ENOMEM;
diff --git a/ctdb/config/events/legacy/01.reclock.script b/ctdb/config/events/legacy/01.reclock.script
index e14d8c22f48..29822e1d48c 100755
--- a/ctdb/config/events/legacy/01.reclock.script
+++ b/ctdb/config/events/legacy/01.reclock.script
@@ -4,71 +4,29 @@
 [ -n "$CTDB_BASE" ] || \
     CTDB_BASE=$(d=$(dirname "$0") ; cd -P "$d" ; dirname "$PWD")
 
-. "${CTDB_BASE}/functions"
-
-load_script_options
-
-ctdb_setup_state_dir "service" "reclock"
-
-ctdb_get_reclock_option ()
-{
-	_reclock_opt_file="${CTDB_SCRIPT_VARDIR}/recovery_lock.cache"
-
-	if [ -f "$_reclock_opt_file" ] ; then
-		. "$_reclock_opt_file"
-		return
-	fi
-
-	ctdb_translate_option "cluster" \
-			      "recovery lock" \
-			      "CTDB_RECOVERY_LOCK" >"$_reclock_opt_file"
-
-	. "$_reclock_opt_file"
-}
-
-ctdb_get_reclock_option
-
-# If CTDB_RECOVERY_LOCK specifies a helper then exit because this
-# script can't do anything useful.
-case "$CTDB_RECOVERY_LOCK" in
-!*) exit 0 ;;
-esac
-
 case "$1" in
 init)
-	ctdb_counter_init
-
-	if [ -n "$CTDB_RECOVERY_LOCK" ] ; then
-	    d=$(dirname "$CTDB_RECOVERY_LOCK")
-	    mkdir -vp "$d"
+	recovery_lock=$("${CTDB_HELPER_BINDIR}/ctdb-config" \
+				get cluster "recovery lock")
+	# xshellcheck disable=SC2181
+	# Above is already complicated enough without embedding into "if"
+	case $? in
+	0) : ;;
+	2) exit 0 ;; # ENOENT: not configured
+	*) die "Unexpected error getting recovery lock configuration"
+	esac
+
+	if [ -z "$recovery_lock" ] ; then
+		exit 0
 	fi
-	;;
-
-monitor)
-	# Early exit if not using a reclock file
-	[ -n "$CTDB_RECOVERY_LOCK" ] || exit 0
 
-	# Try to stat the reclock file as a background process so that
-	# we don't block in case the cluster filesystem is unavailable
-	(
-	    if stat "$CTDB_RECOVERY_LOCK" ; then
-		# We could stat the file, reset the counter
-		ctdb_counter_init
-	    fi
-	) >/dev/null 2>&1 &
+	# If a helper is specified then exit because this script can't
+	# do anything useful
+	case "$recovery_lock" in
+	!*) exit 0 ;;
+	esac
 
-	ctdb_counter_incr
-	num_fails=$(ctdb_counter_get)
-	if [ "$num_fails" -ge 200 ] ; then
-	    echo "Reclock file \"$CTDB_RECOVERY_LOCK\" can not be accessed. Shutting down."
-	    df
-	    sleep 1
-	    $CTDB shutdown
-	    exit 1
-	elif [ "$num_fails" -ge 4 ] ; then
-		die "ERROR: ${num_fails} consecutive failures checking reclock"
-	fi
+	d=$(dirname "$recovery_lock")
+	mkdir -vp "$d"
 	;;
 esac
-
-exit 0
diff --git a/ctdb/server/ctdb_cluster_mutex.c b/ctdb/server/ctdb_cluster_mutex.c
index 719b5c14f7a..2fbe301420e 100644
--- a/ctdb/server/ctdb_cluster_mutex.c
+++ b/ctdb/server/ctdb_cluster_mutex.c
@@ -21,6 +21,7 @@
 
 #include "replace.h"
 #include "system/network.h"
+#include "system/filesys.h"
 
 #include <tevent.h>
 
@@ -32,8 +33,6 @@
 #include "lib/util/blocking.h"
 
 #include "ctdb_private.h"
-#include "common/common.h"
-#include "common/logging.h"
 
 #include "ctdb_cluster_mutex.h"
 
@@ -122,21 +121,56 @@ static bool cluster_mutex_helper_args_file(TALLOC_CTX *mem_ctx,
 					   const char *argstring,
 					   char ***argv)
 {
-	bool ok;
+	struct stat st;
+	size_t size = sizeof(cluster_mutex_helper);
+	const char *t;
 	char **args = NULL;
+	int ret;
+
+	if (cluster_mutex_helper[0] != '\0') {
+		goto helper_done;
+	}
 
-	ok = ctdb_set_helper("cluster mutex helper",
-			     cluster_mutex_helper,
-			     sizeof(cluster_mutex_helper),
-			     "CTDB_CLUSTER_MUTEX_HELPER",
-			     CTDB_HELPER_BINDIR,
-			     "ctdb_mutex_fcntl_helper");
-	if (! ok) {
-		DBG_ERR("ctdb exiting with error: "
-			"Unable to set cluster mutex helper\n");
+	t = getenv("CTDB_CLUSTER_MUTEX_HELPER");
+	if (t != NULL) {
+		size_t len;
+
+		len = strlcpy(cluster_mutex_helper, t, size);
+		if (len >= size) {
+			DBG_ERR("error: CTDB_CLUSTER_MUTEX_HELPER too long\n");
+			exit(1);
+		}
+	} else {
+		ret = snprintf(cluster_mutex_helper,
+			       size,
+			       "%s/%s",
+			       CTDB_HELPER_BINDIR,
+			       "ctdb_mutex_fcntl_helper");
+		if (ret < 0 || (size_t)ret >= size) {
+			D_ERR("Unable to set cluster mutex helper - "
+			      "path too long\n");
+			exit(1);
+		}
+	}
+
+	ret = stat(cluster_mutex_helper, &st);
+	if (ret != 0) {
+		D_ERR("Unable to set cluster mutex helper \"%s\" - %s\n",
+		      cluster_mutex_helper,
+		      strerror(errno));
 		exit(1);
 	}
 
+	if ((st.st_mode & S_IXUSR) == 0) {
+		D_ERR("Unable to set cluster_mutex helper \"%s\" - "
+		      "not executable\n",
+		      cluster_mutex_helper);
+		exit(1);
+	}
+
+	D_NOTICE("Set cluster mutex helper to \"%s\"\n", cluster_mutex_helper);
+
+helper_done:
 
 	/* Array includes default helper, file and NULL */
 	args = talloc_array(mem_ctx, char *, 3);
@@ -234,7 +268,7 @@ ctdb_cluster_mutex(TALLOC_CTX *mem_ctx,
 
 	h = talloc(mem_ctx, struct ctdb_cluster_mutex_handle);
 	if (h == NULL) {
-		DEBUG(DEBUG_ERR, (__location__ " out of memory\n"));
+		DBG_ERR("out of memory\n");
 		return NULL;
 	}
 
@@ -246,7 +280,7 @@ ctdb_cluster_mutex(TALLOC_CTX *mem_ctx,
 	ret = pipe(h->fd);
 	if (ret != 0) {
 		talloc_free(h);
-		DEBUG(DEBUG_ERR, (__location__ " Failed to open pipe\n"));
+		DBG_ERR("Failed to open pipe\n");
 		return NULL;
 	}
 	set_close_on_exec(h->fd[0]);
@@ -302,7 +336,7 @@ ctdb_cluster_mutex(TALLOC_CTX *mem_ctx,
 		execv(args[0], args);
 
 		/* Only happens on error */
-		DEBUG(DEBUG_ERR, (__location__ "execv() failed\n"));
+		DBG_ERR("execv() failed\n");
 		_exit(1);
 	}
 
@@ -313,7 +347,7 @@ ctdb_cluster_mutex(TALLOC_CTX *mem_ctx,
 		DBG_WARNING("Failed to unblock SIGTERM (%d)\n", errno);
 	}
 
-	DEBUG(DEBUG_DEBUG, (__location__ " Created PIPE FD:%d\n", h->fd[0]));
+	DBG_DEBUG("Created PIPE FD:%d\n", h->fd[0]);
 	set_close_on_exec(h->fd[0]);
 
 	close(h->fd[1]);
diff --git a/ctdb/server/ctdb_mutex_fcntl_helper.c b/ctdb/server/ctdb_mutex_fcntl_helper.c
index 7b66c78cd8e..1448a9062a0 100644
--- a/ctdb/server/ctdb_mutex_fcntl_helper.c
+++ b/ctdb/server/ctdb_mutex_fcntl_helper.c
@@ -3,6 +3,10 @@
 
    Copyright (C) Martin Schwenke 2015
 
+   wait_for_parent() code from ctdb_lock_helper.c:
+
+   Copyright (C) Amitay Isaacs  2013
+
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 3 of the License, or
@@ -21,7 +25,11 @@
 #include "system/filesys.h"
 #include "system/network.h"
 
+#include <tevent.h>
+
 #include "lib/util/sys_rw.h"
+#include "lib/util/tevent_unix.h"
+#include "lib/util/util.h"
 
 /* protocol.h is just needed for ctdb_sock_addr, which is used in system.h */
 #include "protocol/protocol.h"
@@ -50,7 +58,6 @@ static char fcntl_lock(const char *file, int *outfd)
 	if (fcntl(fd, F_SETLK, &lock) != 0) {
 		int saved_errno = errno;
 		close(fd);
-		fd = -1;
 		if (saved_errno == EACCES ||
 		    saved_errno == EAGAIN) {
 			/* Lock contention, fail silently */
@@ -69,40 +76,364 @@ static char fcntl_lock(const char *file, int *outfd)
 	return '0';
 }
 
+/*
+ * Wait and see if the parent exits
+ */
+
+struct wait_for_parent_state {
+	struct tevent_context *ev;
+	pid_t ppid;
+};
+
+static void wait_for_parent_check(struct tevent_req *subreq);
+
+static struct tevent_req *wait_for_parent_send(TALLOC_CTX *mem_ctx,
+					       struct tevent_context *ev,
+					       pid_t ppid)
+{
+	struct tevent_req *req, *subreq;
+	struct wait_for_parent_state *state;
+
+	req = tevent_req_create(mem_ctx, &state, struct wait_for_parent_state);
+	if (req == NULL) {
+		return NULL;
+	}
+
+	state->ev = ev;
+	state->ppid = ppid;
+
+	if (ppid == 1) {
+		fprintf(stderr, "parent == 1\n");
+		tevent_req_done(req);
+		return tevent_req_post(req, ev);
+	}
+
+	subreq = tevent_wakeup_send(state, ev,
+				    tevent_timeval_current_ofs(5,0));
+	if (tevent_req_nomem(subreq, req)) {
+		return tevent_req_post(req, ev);
+	}
+	tevent_req_set_callback(subreq, wait_for_parent_check, req);
+
+	return req;
+}
+
+static void wait_for_parent_check(struct tevent_req *subreq)
+{
+	struct tevent_req *req = tevent_req_callback_data(
+		subreq, struct tevent_req);
+	struct wait_for_parent_state *state = tevent_req_data(
+		req, struct wait_for_parent_state);
+	bool status;
+
+	status = tevent_wakeup_recv(subreq);
+	TALLOC_FREE(subreq);
+	if (! status) {
+		/* Ignore error */
+		fprintf(stderr,
+			"ctdb_mutex_fcntl_helper: "
+			"tevent_wakeup_recv() failed\n");
+	}
+
+	if (kill(state->ppid, 0) == -1 && errno == ESRCH) {
+		fprintf(stderr, "parent gone\n");
+		tevent_req_done(req);
+		return;
+	}
+
+	subreq = tevent_wakeup_send(state, state->ev,
+				    tevent_timeval_current_ofs(5,0));
+	if (tevent_req_nomem(subreq, req)) {
+		return;
+	}
+	tevent_req_set_callback(subreq, wait_for_parent_check, req);
+}
+
+static bool wait_for_parent_recv(struct tevent_req *req)
+{
+	if (tevent_req_is_unix_error(req, NULL)) {
+		return false;
+	}
+
+	return true;
+}
+
+/*
+ * Wait and check for lost lock - file removed or replaced
+ */
+
+struct wait_for_lost_state {
+	struct tevent_context *ev;
+	const char *lock_file;
+	ino_t inode;
+	unsigned long recheck_time;
+};
+
+static void wait_for_lost_check(struct tevent_req *subreq);
+
+static struct tevent_req *wait_for_lost_send(TALLOC_CTX *mem_ctx,
+					     struct tevent_context *ev,
+					     const char *lock_file,
+					     int fd,
+					     unsigned long recheck_time)
+{
+	struct tevent_req *req, *subreq;
+	struct wait_for_lost_state *state;
+	struct stat sb;
+	int ret;
+
+	req = tevent_req_create(mem_ctx, &state, struct wait_for_lost_state);
+	if (req == NULL) {
+		return NULL;
+	}
+
+	state->ev = ev;
+	state->lock_file = lock_file;
+	state->recheck_time = recheck_time;
+
+	ret = fstat(fd, &sb);
+	if (ret != 0) {
+		fprintf(stderr,
+			"ctdb_mutex_fcntl_helper: "
+			"lock lost - lock file \"%s\" check failed (ret=%d)\n",
+			state->lock_file,
+			errno);
+		tevent_req_done(req);
+		return tevent_req_post(req, ev);
+	}
+	state->inode = sb.st_ino;
+
+	subreq = tevent_wakeup_send(
+			state,
+			ev,
+			tevent_timeval_current_ofs(state->recheck_time, 0));
+	if (tevent_req_nomem(subreq, req)) {
+		return tevent_req_post(req, ev);
+	}
+	tevent_req_set_callback(subreq, wait_for_lost_check, req);
+
+	return req;
+}
+
+static void wait_for_lost_check(struct tevent_req *subreq)
+{
+	struct tevent_req *req = tevent_req_callback_data(
+		subreq, struct tevent_req);
+	struct wait_for_lost_state *state = tevent_req_data(
+		req, struct wait_for_lost_state);
+	bool status;
+	struct stat sb;
+	int ret;
+
+	status = tevent_wakeup_recv(subreq);
+	TALLOC_FREE(subreq);
+	if (! status) {
+		/* Ignore error */
+		fprintf(stderr,
+			"ctdb_mutex_fcntl_helper: "
+			"tevent_wakeup_recv() failed\n");
+	}
+
+	ret = stat(state->lock_file, &sb);
+	if (ret != 0) {
+		fprintf(stderr,
+			"ctdb_mutex_fcntl_helper: "
+			"lock lost - lock file \"%s\" check failed (ret=%d)\n",
+			state->lock_file,
+			errno);
+		tevent_req_done(req);
+		return;
+	}
+
+	if (sb.st_ino != state->inode) {
+		fprintf(stderr,
+			"ctdb_mutex_fcntl_helper: "
+			"lock lost - lock file \"%s\" inode changed\n",
+			state->lock_file);
+		tevent_req_done(req);
+		return;
+	}
+
+	subreq = tevent_wakeup_send(
+			state,
+			state->ev,
+			tevent_timeval_current_ofs(state->recheck_time, 0));
+	if (tevent_req_nomem(subreq, req)) {
+		return;
+	}
+	tevent_req_set_callback(subreq, wait_for_lost_check, req);
+}
+
+static bool wait_for_lost_recv(struct tevent_req *req)
+{
+	if (tevent_req_is_unix_error(req, NULL)) {
+		return false;
+	}
+
+	return true;
+}
+
+/*
+ * Wait for a reason to exit, indicating that the lock is lost
+ */
+
+struct wait_for_exit_state {
+};
+
+static void wait_for_exit_parent_done(struct tevent_req *subreq);
+static void wait_for_exit_lost_done(struct tevent_req *subreq);
+
+static struct tevent_req *wait_for_exit_send(TALLOC_CTX *mem_ctx,
+					     struct tevent_context *ev,
+					     pid_t ppid,
+					     const char *lock_file,
+					     int fd,
+					     unsigned long recheck_time)
+{
+	struct tevent_req *req, *subreq;
+	struct wait_for_exit_state *state;
+
+	req = tevent_req_create(mem_ctx, &state, struct wait_for_exit_state);
+	if (req == NULL) {
+		return NULL;
+	}
+
+	subreq = wait_for_parent_send(state, ev, ppid);


-- 
Samba Shared Repository



More information about the samba-cvs mailing list