[SCM] Samba Shared Repository - branch master updated

Amitay Isaacs amitay at samba.org
Sat Sep 9 12:45:03 UTC 2017


The branch, master has been updated
       via  87f7d32 ctdb-tests: Fix ctdb process-exist tests
       via  3067db5 ctdb-tests: Add a dummy ctdb client for testing
       via  7dec80a ctdb-tests: Fix the implementation of process-exists in fake daemon
       via  d0a20ba ctdb-daemon: Fix implementation of process_exists control
       via  83039d6 ctdb-tools: Fix CID 1414746
       via  eb16d4a ctdb-tools: Use ssize_t instead of int for checking the status of read()
      from  4102697 s3/vfs: move ACE4_ADD_FILE/ACE4_DELETE_CHILD mapping from NFSv4 framework to vfs_zfsacl

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


- Log -----------------------------------------------------------------
commit 87f7d32a906799e83cb9b023978e689a630de017
Author: Amitay Isaacs <amitay at gmail.com>
Date:   Fri Aug 25 16:55:34 2017 +1000

    ctdb-tests: Fix ctdb process-exist tests
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=13012
    
    Signed-off-by: Amitay Isaacs <amitay at gmail.com>
    Reviewed-by: Martin Schwenke <martin at meltin.net>
    
    Autobuild-User(master): Amitay Isaacs <amitay at samba.org>
    Autobuild-Date(master): Sat Sep  9 14:44:57 CEST 2017 on sn-devel-144

commit 3067db5b50162fdae288aaad8e75beb924fc9494
Author: Amitay Isaacs <amitay at gmail.com>
Date:   Wed Aug 30 13:05:32 2017 +1000

    ctdb-tests: Add a dummy ctdb client for testing
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=13012
    
    Signed-off-by: Amitay Isaacs <amitay at gmail.com>
    Reviewed-by: Martin Schwenke <martin at meltin.net>

commit 7dec80a7c042d83f9d48c75a8717c3d1b59b1fbf
Author: Amitay Isaacs <amitay at gmail.com>
Date:   Fri Aug 25 16:54:47 2017 +1000

    ctdb-tests: Fix the implementation of process-exists in fake daemon
    
    Keep track of clients and their pids.
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=13012
    
    Signed-off-by: Amitay Isaacs <amitay at gmail.com>
    Reviewed-by: Martin Schwenke <martin at meltin.net>

commit d0a20baf43834c7290dfd8f256d9521724202f0c
Author: Amitay Isaacs <amitay at gmail.com>
Date:   Fri Aug 25 15:00:59 2017 +1000

    ctdb-daemon: Fix implementation of process_exists control
    
    Only check processes that are CTDB clients.
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=13012
    
    Signed-off-by: Amitay Isaacs <amitay at gmail.com>
    Reviewed-by: Martin Schwenke <martin at meltin.net>

commit 83039d6a5c98683ed2ba96c2be0f5490d22799ce
Author: Amitay Isaacs <amitay at gmail.com>
Date:   Thu Sep 7 11:38:41 2017 +1000

    ctdb-tools: Fix CID 1414746
    
    Signed-off-by: Amitay Isaacs <amitay at gmail.com>
    Reviewed-by: Martin Schwenke <martin at meltin.net>

commit eb16d4a61cecb0c3d44a344045b0856d7c040cb1
Author: Amitay Isaacs <amitay at gmail.com>
Date:   Tue Sep 5 16:42:58 2017 +1000

    ctdb-tools: Use ssize_t instead of int for checking the status of read()
    
    Signed-off-by: Amitay Isaacs <amitay at gmail.com>
    Reviewed-by: Martin Schwenke <martin at meltin.net>

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

Summary of changes:
 ctdb/server/ctdb_daemon.c                   |  16 +--
 ctdb/tests/simple/07_ctdb_process_exists.sh |  34 ++++---
 ctdb/tests/src/dummy_client.c               | 148 ++++++++++++++++++++++++++++
 ctdb/tests/src/fake_ctdbd.c                 |  81 ++++++++++++++-
 ctdb/tests/tool/ctdb.process-exists.001.sh  |  12 ++-
 ctdb/tools/ctdb.c                           |  14 ++-
 ctdb/wscript                                |   3 +-
 7 files changed, 276 insertions(+), 32 deletions(-)
 create mode 100644 ctdb/tests/src/dummy_client.c


Changeset truncated at 500 lines:

diff --git a/ctdb/server/ctdb_daemon.c b/ctdb/server/ctdb_daemon.c
index 41f042e..7fceed0 100644
--- a/ctdb/server/ctdb_daemon.c
+++ b/ctdb/server/ctdb_daemon.c
@@ -1754,12 +1754,16 @@ int32_t ctdb_control_process_exists(struct ctdb_context *ctdb, pid_t pid)
 {
         struct ctdb_client *client;
 
-	if (ctdb->nodes[ctdb->pnn]->flags & (NODE_FLAGS_BANNED|NODE_FLAGS_STOPPED)) {
-		client = ctdb_find_client_by_pid(ctdb, pid);
-		if (client != NULL) {
-			DEBUG(DEBUG_NOTICE,(__location__ " Killing client with pid:%d on banned/stopped node\n", (int)pid));
-			talloc_free(client);
-		}
+	client = ctdb_find_client_by_pid(ctdb, pid);
+	if (client == NULL) {
+		return -1;
+	}
+
+	if (ctdb->nodes[ctdb->pnn]->flags & NODE_FLAGS_INACTIVE) {
+		DEBUG(DEBUG_NOTICE,
+		      ("Killing client with pid:%d on banned/stopped node\n",
+		       (int)pid));
+		talloc_free(client);
 		return -1;
 	}
 
diff --git a/ctdb/tests/simple/07_ctdb_process_exists.sh b/ctdb/tests/simple/07_ctdb_process_exists.sh
index b7492a8..c44924b 100755
--- a/ctdb/tests/simple/07_ctdb_process_exists.sh
+++ b/ctdb/tests/simple/07_ctdb_process_exists.sh
@@ -15,11 +15,10 @@ Prerequisites:
 Steps:
 
 1. Verify that the status on all of the ctdb nodes is 'OK'.
-2. On one of the cluster nodes, get the PID of an existing process
-   (using ps wax).
+2. On one of the cluster nodes, get the PID of a ctdb client.
 3. Run 'ctdb process-exists <pid>' on the node and verify that the
    correct output is shown.
-4. Run 'ctdb process-exists <pid>' with a pid of a non-existent
+4. Run 'ctdb process-exists <pid>' with a pid of ctdb daemon
    process and verify that the correct output is shown.
 
 Expected results:
@@ -38,15 +37,25 @@ cluster_is_healthy
 
 test_node=1
 
-# Create a background process on $test_node that will last for 60 seconds.
+# Execute a ctdb client on $test_node that will last for 60 seconds.
 # It should still be there when we check.
-try_command_on_node $test_node 'sleep 60 >/dev/null 2>&1 & echo $!'
-pid="$out"
+try_command_on_node -v $test_node \
+	"$CTDB_TEST_WRAPPER exec dummy_client >/dev/null 2>&1 & echo \$!"
+client_pid="$out"
 
-echo "Checking for PID $pid on node $test_node"
-# set -e is good, but avoid it here
+cleanup ()
+{
+    if [ -n "$client_pid" ] ; then
+	onnode $test_node kill -9 "$client_pid"
+    fi
+}
+
+ctdb_test_exit_hook_add cleanup
+
+echo "Checking for PID $client_pid on node $test_node"
 status=0
-try_command_on_node $test_node "$CTDB process-exists ${pid}" || status=$?
+try_command_on_node $test_node \
+	"$CTDB process-exists ${client_pid}" || status=$?
 echo "$out"
 
 if [ $status -eq 0 ] ; then
@@ -56,10 +65,9 @@ else
     testfailures=1
 fi
 
-# Now just echo the PID of the shell from the onnode process on node
-# 2.  This PID will disappear and PIDs shouldn't roll around fast
-# enough to trick the test...  but there is a chance that will happen!
-try_command_on_node $test_node 'echo $$'
+# Now just echo the PID of the ctdb daemon on test node.
+# This is not a ctdb client and process-exists should return error.
+try_command_on_node $test_node "ctdb getpid"
 pid="$out"
 
 echo "Checking for PID $pid on node $test_node"
diff --git a/ctdb/tests/src/dummy_client.c b/ctdb/tests/src/dummy_client.c
new file mode 100644
index 0000000..6af41f3
--- /dev/null
+++ b/ctdb/tests/src/dummy_client.c
@@ -0,0 +1,148 @@
+/*
+   Dummy CTDB client for testing
+
+   Copyright (C) Amitay Isaacs  2017
+
+   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
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "replace.h"
+#include "system/network.h"
+
+#include <popt.h>
+#include <talloc.h>
+#include <tevent.h>
+
+#include "common/logging.h"
+
+#include "client/client.h"
+
+static struct {
+	const char *sockpath;
+	const char *debuglevel;
+	int timelimit;
+	const char *srvidstr;
+} options;
+
+static struct poptOption cmdline_options[] = {
+	POPT_AUTOHELP
+	{ "socket", 's', POPT_ARG_STRING, &options.sockpath, 0,
+		"Unix domain socket path", "filename" },
+	{ "debug", 'd', POPT_ARG_STRING, &options.debuglevel, 0,
+		"debug level", "ERR|WARNING|NOTICE|INFO|DEBUG" } ,
+	{ "timelimit", 't', POPT_ARG_INT, &options.timelimit, 0,
+		"time limit", "seconds" },
+	{ "srvid", 'S', POPT_ARG_STRING, &options.srvidstr, 0,
+		"srvid to register", "srvid" },
+	POPT_TABLEEND
+};
+
+static void dummy_handler(uint64_t srvid, TDB_DATA data, void *private_data)
+{
+	bool *done = (bool *)private_data;
+
+	*done = true;
+}
+
+int main(int argc, const char *argv[])
+{
+	TALLOC_CTX *mem_ctx;
+	struct tevent_context *ev;
+	struct ctdb_client_context *client;
+	const char *ctdb_socket;
+	poptContext pc;
+	int opt, ret;
+	int log_level;
+	bool status, done;
+
+	/* Set default options */
+	options.sockpath = CTDB_SOCKET;
+	options.debuglevel = "ERR";
+	options.timelimit = 60;
+	options.srvidstr = NULL;
+
+	ctdb_socket = getenv("CTDB_SOCKET");
+	if (ctdb_socket != NULL) {
+		options.sockpath = ctdb_socket;
+	}
+
+	pc = poptGetContext(argv[0], argc, argv, cmdline_options,
+			    POPT_CONTEXT_KEEP_FIRST);
+	while ((opt = poptGetNextOpt(pc)) != -1) {
+		fprintf(stderr, "Invalid option %s\n", poptBadOption(pc, 0));
+		exit(1);
+	}
+
+	if (options.sockpath == NULL) {
+		fprintf(stderr, "Please specify socket path\n");
+		poptPrintHelp(pc, stdout, 0);
+		exit(1);
+	}
+
+	mem_ctx = talloc_new(NULL);
+	if (mem_ctx == NULL) {
+		fprintf(stderr, "Memory allocation error\n");
+		exit(1);
+	}
+
+	ev = tevent_context_init(mem_ctx);
+	if (ev == NULL) {
+		fprintf(stderr, "Memory allocation error\n");
+		exit(1);
+	}
+
+	status = debug_level_parse(options.debuglevel, &log_level);
+	if (! status) {
+		fprintf(stderr, "Invalid debug level\n");
+		poptPrintHelp(pc, stdout, 0);
+		exit(1);
+	}
+
+	setup_logging("dummy_client", DEBUG_STDERR);
+	DEBUGLEVEL = log_level;
+
+	ret = ctdb_client_init(mem_ctx, ev, options.sockpath, &client);
+	if (ret != 0) {
+		D_ERR("Failed to initialize client, ret=%d\n", ret);
+		exit(1);
+	}
+
+	done = false;
+	if (options.srvidstr != NULL) {
+		uint64_t srvid;
+
+		srvid = strtoull(options.srvidstr, NULL, 0);
+
+		ret = ctdb_client_set_message_handler(ev, client, srvid,
+						      dummy_handler, &done);
+		if (ret != 0) {
+			D_ERR("Failed to register srvid, ret=%d\n", ret);
+			talloc_free(client);
+			exit(1);
+		}
+
+		D_INFO("Registered SRVID 0x%"PRIx64"\n", srvid);
+	}
+
+	ret = ctdb_client_wait_timeout(ev, &done,
+			tevent_timeval_current_ofs(options.timelimit, 0));
+	if (ret != 0 && ret == ETIME) {
+		D_ERR("client_wait_timeout() failed, ret=%d\n", ret);
+		talloc_free(client);
+		exit(1);
+	}
+
+	talloc_free(client);
+	exit(0);
+}
diff --git a/ctdb/tests/src/fake_ctdbd.c b/ctdb/tests/src/fake_ctdbd.c
index ef3f1c1..f99e1a2 100644
--- a/ctdb/tests/src/fake_ctdbd.c
+++ b/ctdb/tests/src/fake_ctdbd.c
@@ -108,6 +108,13 @@ struct fake_control_failure {
 	const char *comment;
 };
 
+struct ctdb_client {
+	struct ctdb_client *prev, *next;
+	struct ctdbd_context *ctdb;
+	pid_t pid;
+	void *state;
+};
+
 struct ctdbd_context {
 	struct node_map *node_map;
 	struct interface_map *iface_map;
@@ -126,6 +133,7 @@ struct ctdbd_context {
 	char *reclock;
 	struct ctdb_public_ip_list *known_ips;
 	struct fake_control_failure *control_failures;
+	struct ctdb_client *client_list;
 };
 
 /*
@@ -825,6 +833,48 @@ fail:
 }
 
 /*
+ * Manage clients
+ */
+
+static int ctdb_client_destructor(struct ctdb_client *client)
+{
+	DLIST_REMOVE(client->ctdb->client_list, client);
+	return 0;
+}
+
+static int client_add(struct ctdbd_context *ctdb, pid_t client_pid,
+		      void *client_state)
+{
+	struct ctdb_client *client;
+
+	client = talloc_zero(client_state, struct ctdb_client);
+	if (client == NULL) {
+		return ENOMEM;
+	}
+
+	client->ctdb = ctdb;
+	client->pid = client_pid;
+	client->state = client_state;
+
+	DLIST_ADD(ctdb->client_list, client);
+	talloc_set_destructor(client, ctdb_client_destructor);
+	return 0;
+}
+
+static void *client_find(struct ctdbd_context *ctdb, pid_t client_pid)
+{
+	struct ctdb_client *client;
+
+	for (client=ctdb->client_list; client != NULL; client=client->next) {
+		if (client->pid == client_pid) {
+			return client->state;
+		}
+	}
+
+	return NULL;
+}
+
+/*
  * CTDB context setup
  */
 
@@ -1148,6 +1198,7 @@ struct client_state {
 	int fd;
 	struct ctdbd_context *ctdb;
 	int pnn;
+	pid_t pid;
 	struct comm_context *comm;
 	struct srvid_register_state *rstate;
 	int status;
@@ -1261,11 +1312,22 @@ static void control_process_exists(TALLOC_CTX *mem_ctx,
 				   struct ctdb_req_header *header,
 				   struct ctdb_req_control *request)
 {
+	struct client_state *state = tevent_req_data(
+		req, struct client_state);
+	struct ctdbd_context *ctdb = state->ctdb;
+	struct client_state *cstate;
 	struct ctdb_reply_control reply;
 
 	reply.rdata.opcode = request->opcode;
-	reply.status = kill(request->rdata.data.pid, 0);
-	reply.errmsg = NULL;
+
+	cstate = client_find(ctdb, request->rdata.data.pid);
+	if (cstate == NULL) {
+		reply.status = -1;
+		reply.errmsg = "No client for PID";
+	} else {
+		reply.status = kill(request->rdata.data.pid, 0);
+		reply.errmsg = NULL;
+	}
 
 	client_send_control(req, header, &reply);
 }
@@ -2980,6 +3042,8 @@ static struct tevent_req *client_send(TALLOC_CTX *mem_ctx,
 {
 	struct tevent_req *req;
 	struct client_state *state;
+	struct ucred cr;
+	socklen_t crl = sizeof(struct ucred);
 	int ret;
 
 	req = tevent_req_create(mem_ctx, &state, struct client_state);
@@ -2992,6 +3056,13 @@ static struct tevent_req *client_send(TALLOC_CTX *mem_ctx,
 	state->ctdb = ctdb;
 	state->pnn = pnn;
 
+	ret = getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &cr, &crl);
+	if (ret != 0) {
+		tevent_req_error(req, ret);
+		return tevent_req_post(req, ev);
+	}
+	state->pid = cr.pid;
+
 	ret = comm_setup(state, ev, fd, client_read_handler, req,
 			 client_dead_handler, req, &state->comm);
 	if (ret != 0) {
@@ -2999,6 +3070,12 @@ static struct tevent_req *client_send(TALLOC_CTX *mem_ctx,
 		return tevent_req_post(req, ev);
 	}
 
+	ret = client_add(ctdb, state->pid, state);
+	if (ret != 0) {
+		tevent_req_error(req, ret);
+		return tevent_req_post(req, ev);
+	}
+
 	DEBUG(DEBUG_INFO, ("New client fd=%d\n", fd));
 
 	return req;
diff --git a/ctdb/tests/tool/ctdb.process-exists.001.sh b/ctdb/tests/tool/ctdb.process-exists.001.sh
index b153da1..2339344 100755
--- a/ctdb/tests/tool/ctdb.process-exists.001.sh
+++ b/ctdb/tests/tool/ctdb.process-exists.001.sh
@@ -11,12 +11,14 @@ NODEMAP
 2       192.168.20.43   0x0
 EOF
 
-pid=$(ctdbd_getpid)
+dummy_client -s $ctdbd_socket &
+pid=$!
 
 ok "PID $pid exists"
 simple_test "$pid"
 
-# Use a PID that is probably impossible.  It must fit into 32 bits but
-# should be larger than most settings for pid_max.
-required_result 1 "PID 99999999 does not exist"
-simple_test "99999999"
+kill -9 $pid
+
+pid=$(ctdbd_getpid)
+required_result 1 "PID $pid does not exist"
+simple_test "$pid"
diff --git a/ctdb/tools/ctdb.c b/ctdb/tools/ctdb.c
index f6ba758..52e4ea8 100644
--- a/ctdb/tools/ctdb.c
+++ b/ctdb/tools/ctdb.c
@@ -4139,8 +4139,10 @@ static int control_restoredb(TALLOC_CTX *mem_ctx, struct ctdb_context *ctdb,
 	uint32_t generation;
 	uint32_t *pnn_list;
 	char timebuf[128];
+	ssize_t n;
 	int fd, i;
 	int count, ret;
+	uint8_t db_flags;
 
 	if (argc < 1 || argc > 2) {
 		usage("restoredb");
@@ -4158,8 +4160,8 @@ static int control_restoredb(TALLOC_CTX *mem_ctx, struct ctdb_context *ctdb,
 		db_name = argv[1];
 	}
 
-	ret = read(fd, &db_hdr, sizeof(struct db_header));
-	if (ret == -1) {
+	n = read(fd, &db_hdr, sizeof(struct db_header));
+	if (n == -1) {
 		ret = errno;
 		close(fd);
 		fprintf(stderr, "Failed to read db header from file %s\n",
@@ -4184,8 +4186,9 @@ static int control_restoredb(TALLOC_CTX *mem_ctx, struct ctdb_context *ctdb,
 		 localtime(&db_hdr.timestamp));
 	printf("Restoring database %s from backup @ %s\n", db_name, timebuf);
 
+	db_flags = db_hdr.flags & 0xff;
 	ret = ctdb_attach(ctdb->ev, ctdb->client, TIMEOUT(), db_name,
-			  db_hdr.flags, &db);
+			  db_flags, &db);
 	if (ret != 0) {
 		fprintf(stderr, "Failed to attach to DB %s\n", db_name);
 		close(fd);
@@ -4377,6 +4380,7 @@ static int control_dumpdbbackup(TALLOC_CTX *mem_ctx, struct ctdb_context *ctdb,
 	struct db_header db_hdr;
 	char timebuf[128];
 	struct dumpdbbackup_state state;
+	ssize_t n;
 	int fd, ret, i;
 
 	if (argc != 1) {
@@ -4391,8 +4395,8 @@ static int control_dumpdbbackup(TALLOC_CTX *mem_ctx, struct ctdb_context *ctdb,
 		return ret;
 	}
 
-	ret = read(fd, &db_hdr, sizeof(struct db_header));
-	if (ret == -1) {
+	n = read(fd, &db_hdr, sizeof(struct db_header));
+	if (n == -1) {
 		ret = errno;
 		close(fd);
 		fprintf(stderr, "Failed to read db header from file %s\n",
diff --git a/ctdb/wscript b/ctdb/wscript
index a28dc58..151c1d0 100644
--- a/ctdb/wscript
+++ b/ctdb/wscript
@@ -814,7 +814,8 @@ def build(bld):
         'transaction_loop',
         'update_record',
         'update_record_persistent',
-        'lock_tdb'
+        'lock_tdb',
+        'dummy_client'
     ]
 
     for target in ctdb_tests:


-- 
Samba Shared Repository



More information about the samba-cvs mailing list