[SCM] CTDB repository - branch master updated - e3cdb8f2be6a44ec877efcd75c7297edb008a80b

Andrew Tridgell tridge at samba.org
Wed May 14 10:58:47 GMT 2008


The branch, master has been updated
       via  e3cdb8f2be6a44ec877efcd75c7297edb008a80b (commit)
       via  b616961c16667328a81efa00a1c880efa4e791f1 (commit)
       via  13d3eb9a8bc7fad14fcd3e7e023c1336657424d6 (commit)
       via  8d6ecf47318188448d934ab76e40da7e4cece67d (commit)
       via  423a2b0965ed6aaaf1dce8864a07ed93944bcf16 (commit)
       via  7c569720beb626617d800211faaf9029f0deb4cf (commit)
       via  c4c2c53918da6fb566d6e9cbd6b02e61ae2921e7 (commit)
      from  3e6160e5d90a0661eb833b163c11be2267117d0b (commit)

http://gitweb.samba.org/?p=tridge/ctdb.git;a=shortlog;h=master


- Log -----------------------------------------------------------------
commit e3cdb8f2be6a44ec877efcd75c7297edb008a80b
Author: Andrew Tridgell <tridge at samba.org>
Date:   Wed May 14 20:57:04 2008 +1000

    Fix the chicken and egg problem with ctdb/samba and a registry smb.conf
    
    This attempts to fix the problem of ctdb event scripts blocking due to
    attempted access to the ctdb databases during recovery. The changes are:
    
      - now only the 'shutdown' and 'startrecovery' events can be called
        with the databases locked in recovery. The event scripts must ensure
        that for these two events no database access is attempted
    
      - the recovered, takeip and releaseip events could previously be called
        inside a recovery. The code now ensures that this doesn't happen, delaying
        the events till after recovery has finished
    
      - the 50.samba event script now avoids using testparm unless it is really
        needed
    
    This needs extensive testing.

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

Summary of changes:
 common/ctdb_ltdb.c        |   26 +++++++++++++++++++++++++-
 config/ctdb.init          |   13 +++++++++++++
 config/events.d/50.samba  |   12 ++++++++----
 config/events.d/60.nfs    |    2 +-
 config/events.d/README    |    5 ++++-
 include/ctdb_private.h    |    3 ++-
 packaging/RPM/ctdb.spec   |   11 ++++++++++-
 server/ctdb_control.c     |    8 +++++---
 server/ctdb_daemon.c      |   16 ++++++++++++++++
 server/ctdb_ltdb_server.c |   13 ++++++++++++-
 server/ctdb_recover.c     |    9 ++++++++-
 server/ctdb_recoverd.c    |   29 +++++++++++++++++------------
 server/ctdb_server.c      |   10 ++++++++++
 server/eventscript.c      |   24 ++++++++++++++++++------
 14 files changed, 149 insertions(+), 32 deletions(-)


Changeset truncated at 500 lines:

diff --git a/common/ctdb_ltdb.c b/common/ctdb_ltdb.c
index e8a334a..a3df65e 100644
--- a/common/ctdb_ltdb.c
+++ b/common/ctdb_ltdb.c
@@ -150,7 +150,31 @@ int ctdb_ltdb_store(struct ctdb_db_context *ctdb_db, TDB_DATA key,
 	memcpy(rec.dptr, header, sizeof(*header));
 	memcpy(rec.dptr + sizeof(*header), data.dptr, data.dsize);
 
-	ret = tdb_store(ctdb_db->ltdb->tdb, key, rec, TDB_REPLACE);
+	/* if this is a persistent database without NOSYNC then we
+	   will do this via a transaction */
+	if (ctdb_db->persistent && !(ctdb_db->client_tdb_flags & TDB_NOSYNC)) {
+		bool transaction_started = true;
+
+		ret = tdb_transaction_start(ctdb_db->ltdb->tdb);
+		if (ret != 0) {
+			transaction_started = false;
+			DEBUG(DEBUG_NOTICE, ("Failed to start local transaction\n"));
+		}
+		ret = tdb_store(ctdb_db->ltdb->tdb, key, rec, TDB_REPLACE);
+		if (ret != 0) {
+			if (transaction_started) {
+				tdb_transaction_cancel(ctdb_db->ltdb->tdb);
+			}
+			goto failed;
+		}
+		if (transaction_started) {
+			ret = tdb_transaction_commit(ctdb_db->ltdb->tdb);
+		}
+	} else {
+		ret = tdb_store(ctdb_db->ltdb->tdb, key, rec, TDB_REPLACE);
+	}
+
+failed:
 	talloc_free(rec.dptr);
 
 	return ret;
diff --git a/config/ctdb.init b/config/ctdb.init
index 922a53d..95845d1 100755
--- a/config/ctdb.init
+++ b/config/ctdb.init
@@ -85,6 +85,19 @@ fi
 start() {
         killall -q ctdbd
 	echo -n $"Starting ctdbd service: "
+
+	# check all persistent databases that they look ok
+	PERSISTENT_DB_DIR="/var/ctdb/persistent"
+	[ -z "$CTDB_DBDIR" ] || {
+		PERSISTENT_DB_DIR="$CTDB_DBDIR/persistent"
+	}
+	for PDBASE in `ls $PERSISTENT_DB_DIR/*.tdb.[0-9]`; do
+		/usr/bin/tdbdump $PDBASE >/dev/null 2>/dev/null || {
+			echo "Persistent database $PDBASE is corrupted! CTDB will not start."
+			return 1
+		}
+	done
+
 	case $init_style in
 	    suse)
 		startproc /usr/sbin/ctdbd $CTDB_OPTIONS
diff --git a/config/events.d/50.samba b/config/events.d/50.samba
index c67dbda..784c059 100755
--- a/config/events.d/50.samba
+++ b/config/events.d/50.samba
@@ -16,9 +16,9 @@ shift
     SAMBA_CLEANUP_PERIOD=10
 }
 
-
-# autodetect use of winbind if not set in config file
-[ -z "$CTDB_MANAGES_WINBIND" ] && {
+# function to see if ctdb manages winbind
+check_ctdb_manages_winbind() {
+  [ -z "$CTDB_MANAGES_WINBIND" ] && {
     secmode=`testparm -s --parameter-name=security 2> /dev/null`
     case $secmode in
 	ADS|DOMAIN)
@@ -28,6 +28,7 @@ shift
 	    CTDB_MANAGES_WINBIND="no";
 	    ;;
     esac
+  }
 }
 
 ###########################
@@ -53,11 +54,12 @@ case $cmd in
 	}
 
 	# restart the winbind service
+	check_ctdb_manages_winbind
 	[ "$CTDB_MANAGES_WINBIND" = "yes" ] && {
 		service winbind stop > /dev/null 2>&1
 		killall -0 -q winbindd && {
 		    sleep 1
-		    # make absolutely sure winbindd is dead
+          	    # make absolutely sure winbindd is dead
 		    killall -q -9 winbindd
 		}
 		service winbind start
@@ -87,6 +89,7 @@ case $cmd in
 	service smb stop
 
 	# stop the winbind service
+	check_ctdb_manages_winbind
 	[ "$CTDB_MANAGES_WINBIND" = "yes" ] && {
 		service winbind stop
 	}
@@ -116,6 +119,7 @@ case $cmd in
 	ctdb_check_tcp_ports "Samba" $smb_ports
 
 	# check winbind is OK
+	check_ctdb_manages_winbind
 	[ "$CTDB_MANAGES_WINBIND" = "yes" ] && {
 		ctdb_check_command "winbind" "wbinfo -p"
 	}
diff --git a/config/events.d/60.nfs b/config/events.d/60.nfs
index 182d250..5aaf693 100755
--- a/config/events.d/60.nfs
+++ b/config/events.d/60.nfs
@@ -96,7 +96,7 @@ case $cmd in
 	ctdb_check_rpc "NFS" 100003 3
 
 	# and that its directories are available
-	nfs_dirs=$(exportfs | grep -v '^#' | awk {'print $1;'})
+	nfs_dirs=$(exportfs | grep -v '^#' | grep '^/' | awk {'print $1;'})
 	ctdb_check_directories "nfs" $nfs_dirs
 
 	# check that lockd responds to rpc requests
diff --git a/config/events.d/README b/config/events.d/README
index bfa4372..a75da38 100644
--- a/config/events.d/README
+++ b/config/events.d/README
@@ -18,6 +18,9 @@ The eventscripts are called with varying number of arguments.
 The first argument is the "event" and the rest of the arguments depend
 on which event was triggered.
 
+All of the events except the 'shutdown' and 'startrecovery' events will be
+called with the ctdb daemon in NORMAL mode (ie. not in recovery)
+
 The events currently implemented are
 startup
 	This event does not take any additional arguments.
@@ -74,7 +77,7 @@ takeip
 
 	Before this event there will always be a 'startrecovery' event.
 
-	This event will always be followed by a 'recovered' event onse
+	This event will always be followed by a 'recovered' event once
 	all ipaddresses have been reassigned to new nodes and the ctdb database
 	has been recovered.
 	If multiple ip addresses are reassigned during recovery it is
diff --git a/include/ctdb_private.h b/include/ctdb_private.h
index d31b148..bc8bde3 100644
--- a/include/ctdb_private.h
+++ b/include/ctdb_private.h
@@ -410,6 +410,7 @@ struct ctdb_db_context {
 	struct ctdb_registered_call *calls; /* list of registered calls */
 	uint32_t seqnum;
 	struct timed_event *te;
+	uint32_t client_tdb_flags;
 };
 
 
@@ -921,7 +922,7 @@ int ctdb_daemon_send_control(struct ctdb_context *ctdb, uint32_t destnode,
 			     void *private_data);
 
 int32_t ctdb_control_db_attach(struct ctdb_context *ctdb, TDB_DATA indata, 
-			       TDB_DATA *outdata, bool persistent);
+			       TDB_DATA *outdata, uint64_t tdb_flags, bool persistent);
 
 int ctdb_daemon_set_call(struct ctdb_context *ctdb, uint32_t db_id,
 			 ctdb_fn_t fn, int id);
diff --git a/packaging/RPM/ctdb.spec b/packaging/RPM/ctdb.spec
index 689e70f..a62b91a 100644
--- a/packaging/RPM/ctdb.spec
+++ b/packaging/RPM/ctdb.spec
@@ -5,7 +5,7 @@ Vendor: Samba Team
 Packager: Samba Team <samba at samba.org>
 Name: ctdb
 Version: 1.0
-Release: 36
+Release: 37
 Epoch: 0
 License: GNU GPL version 3
 Group: System Environment/Daemons
@@ -120,6 +120,15 @@ fi
 %{_includedir}/ctdb_private.h
 
 %changelog
+* Mon May 12 2008 : Version 1.0.37
+ - When we shutdown ctdb we close the transport down before we run the 
+   "shutdown" eventscripts. If ctdb decides to send a packet to a remote node
+   after we have shutdown the transport but before we have shutdown ctdbd
+   itself this could lead to a SEGV instead of a clean shutdown. Fix.
+ - When using the "exportfs" command to extract which NFS export directories
+   to monitor,  exportfs violates the "principle of least surprise" and
+   sometimes report a single export line as two lines of text output
+   causing the monitoring to fail.
 * Fri May 9 2008 : Version 1.0.36
  - fix a memory corruption bug that could cause the recovery daemon to crash.
  - fix a bug with distributing public ip addresses during recovery.
diff --git a/server/ctdb_control.c b/server/ctdb_control.c
index 6c8a4fc..7d55413 100644
--- a/server/ctdb_control.c
+++ b/server/ctdb_control.c
@@ -206,10 +206,10 @@ static int32_t ctdb_control_dispatch(struct ctdb_context *ctdb,
 	}
 
 	case CTDB_CONTROL_DB_ATTACH:
-		return ctdb_control_db_attach(ctdb, indata, outdata, false);
+		return ctdb_control_db_attach(ctdb, indata, outdata, srvid, false);
 
 	case CTDB_CONTROL_DB_ATTACH_PERSISTENT:
-		return ctdb_control_db_attach(ctdb, indata, outdata, true);
+		return ctdb_control_db_attach(ctdb, indata, outdata, srvid, true);
 
 	case CTDB_CONTROL_SET_CALL: {
 		struct ctdb_control_set_call *sc = 
@@ -276,7 +276,9 @@ static int32_t ctdb_control_dispatch(struct ctdb_context *ctdb,
 		ctdb_stop_keepalive(ctdb);
 		ctdb_stop_monitoring(ctdb);
 		ctdb_release_all_ips(ctdb);
-		ctdb->methods->shutdown(ctdb);
+		if (ctdb->methods != NULL) {
+			ctdb->methods->shutdown(ctdb);
+		}
 		ctdb_event_script(ctdb, "shutdown");
 		DEBUG(DEBUG_NOTICE,("Received SHUTDOWN command. Stopping CTDB daemon.\n"));
 		exit(0);
diff --git a/server/ctdb_daemon.c b/server/ctdb_daemon.c
index 93af56c..326ab60 100644
--- a/server/ctdb_daemon.c
+++ b/server/ctdb_daemon.c
@@ -71,6 +71,11 @@ static void print_exit_message(void)
 /* called when the "startup" event script has finished */
 static void ctdb_start_transport(struct ctdb_context *ctdb)
 {
+	if (ctdb->methods == NULL) {
+		DEBUG(DEBUG_ALERT,(__location__ " startup event finished but transport is DOWN.\n"));
+		ctdb_fatal(ctdb, "transport is not initialized but startup completed");
+	}
+
 	/* start the transport running */
 	if (ctdb->methods->start(ctdb) != 0) {
 		DEBUG(DEBUG_ALERT,("transport failed to start!\n"));
@@ -689,6 +694,11 @@ int ctdb_start_daemon(struct ctdb_context *ctdb, bool do_fork)
 		return -1;
 	}
 
+	if (ctdb->methods == NULL) {
+		DEBUG(DEBUG_ALERT,(__location__ " Can not initialize transport. ctdb->methods is NULL\n"));
+		ctdb_fatal(ctdb, "transport is unavailable. can not initialize.");
+	}
+
 	/* initialise the transport  */
 	if (ctdb->methods->initialise(ctdb) != 0) {
 		ctdb_fatal(ctdb, "transport failed to initialise");
@@ -743,6 +753,12 @@ struct ctdb_req_header *_ctdb_transport_allocate(struct ctdb_context *ctdb,
 	length = MAX(length, slength);
 	size = (length+(CTDB_DS_ALIGNMENT-1)) & ~(CTDB_DS_ALIGNMENT-1);
 
+	if (ctdb->methods == NULL) {
+		DEBUG(DEBUG_ERR,(__location__ " Unable to allocate transport packet for operation %u of length %u. Transport is DOWN.\n",
+			 operation, (unsigned)length));
+		return NULL;
+	}
+
 	hdr = (struct ctdb_req_header *)ctdb->methods->allocate_pkt(mem_ctx, size);
 	if (hdr == NULL) {
 		DEBUG(DEBUG_ERR,("Unable to allocate transport packet for operation %u of length %u\n",
diff --git a/server/ctdb_ltdb_server.c b/server/ctdb_ltdb_server.c
index e900f7b..5146ed8 100644
--- a/server/ctdb_ltdb_server.c
+++ b/server/ctdb_ltdb_server.c
@@ -296,12 +296,19 @@ static int ctdb_local_attach(struct ctdb_context *ctdb, const char *db_name, boo
   a client has asked to attach a new database
  */
 int32_t ctdb_control_db_attach(struct ctdb_context *ctdb, TDB_DATA indata,
-			       TDB_DATA *outdata, bool persistent)
+			       TDB_DATA *outdata, uint64_t tdb_flags, 
+			       bool persistent)
 {
 	const char *db_name = (const char *)indata.dptr;
 	struct ctdb_db_context *db;
 	struct ctdb_node *node = ctdb->nodes[ctdb->pnn];
 
+	/* the client can optionally pass additional tdb flags, but we
+	   only allow a subset of those on the database in ctdb. Note
+	   that tdb_flags is passed in via the (otherwise unused)
+	   srvid to the attach control */
+	tdb_flags &= TDB_NOSYNC;
+
 	/* If the node is inactive it is not part of the cluster
 	   and we should not allow clients to attach to any
 	   databases
@@ -317,6 +324,7 @@ int32_t ctdb_control_db_attach(struct ctdb_context *ctdb, TDB_DATA indata,
 	if (db) {
 		outdata->dptr  = (uint8_t *)&db->db_id;
 		outdata->dsize = sizeof(db->db_id);
+		db->client_tdb_flags |= tdb_flags;
 		return 0;
 	}
 
@@ -330,6 +338,9 @@ int32_t ctdb_control_db_attach(struct ctdb_context *ctdb, TDB_DATA indata,
 		return -1;
 	}
 
+	/* remember the flags the client has specified */
+	db->client_tdb_flags = tdb_flags;
+
 	outdata->dptr  = (uint8_t *)&db->db_id;
 	outdata->dsize = sizeof(db->db_id);
 
diff --git a/server/ctdb_recover.c b/server/ctdb_recover.c
index 7a96733..3da3b56 100644
--- a/server/ctdb_recover.c
+++ b/server/ctdb_recover.c
@@ -180,7 +180,9 @@ ctdb_reload_nodes_event(struct event_context *ev, struct timed_event *te,
 	int ctdb_tcp_init(struct ctdb_context *);
 
 	/* shut down the transport */
-	ctdb->methods->shutdown(ctdb);
+	if (ctdb->methods != NULL) {
+		ctdb->methods->shutdown(ctdb);
+	}
 
 	/* start the transport again */
 	ctdb_load_nodes_file(ctdb);
@@ -189,6 +191,11 @@ ctdb_reload_nodes_event(struct event_context *ev, struct timed_event *te,
 		DEBUG(DEBUG_CRIT, (__location__ " Failed to init TCP\n"));
 		exit(1);
 	}
+
+	if (ctdb->methods == NULL) {
+		DEBUG(DEBUG_ALERT,(__location__ " Can not restart transport. ctdb->methods==NULL\n"));
+		ctdb_fatal(ctdb, "can not reinitialize transport.");
+	}
 	ctdb->methods->initialise(ctdb);
 	ctdb->methods->start(ctdb);
 
diff --git a/server/ctdb_recoverd.c b/server/ctdb_recoverd.c
index 95dd94f..5f8eb83 100644
--- a/server/ctdb_recoverd.c
+++ b/server/ctdb_recoverd.c
@@ -247,7 +247,8 @@ static int run_startrecovery_eventscript(struct ctdb_context *ctdb, struct ctdb_
 static void async_getcap_callback(struct ctdb_context *ctdb, uint32_t node_pnn, int32_t res, TDB_DATA outdata)
 {
 	if ( (outdata.dsize != sizeof(uint32_t)) || (outdata.dptr == NULL) ) {
-		DEBUG(DEBUG_ERR, (__location__ " Invalid lenght/pointer for getcap callback : %d %p\n", outdata.dsize, outdata.dptr));
+		DEBUG(DEBUG_ERR, (__location__ " Invalid lenght/pointer for getcap callback : %u %p\n", 
+				  (unsigned)outdata.dsize, outdata.dptr));
 		return;
 	}
 	ctdb->nodes[node_pnn]->capabilities = *((uint32_t *)outdata.dptr);
@@ -1451,6 +1452,15 @@ static int do_recovery(struct ctdb_recoverd *rec,
 	
 	DEBUG(DEBUG_NOTICE, (__location__ " Recovery - updated flags\n"));
 
+	/* disable recovery mode */
+	ret = set_recovery_mode(ctdb, nodemap, CTDB_RECOVERY_NORMAL);
+	if (ret!=0) {
+		DEBUG(DEBUG_ERR, (__location__ " Unable to set recovery mode to normal on cluster\n"));
+		return -1;
+	}
+
+	DEBUG(DEBUG_NOTICE, (__location__ " Recovery - disabled recovery mode\n"));
+
 	/*
 	  tell nodes to takeover their public IPs
 	 */
@@ -1471,15 +1481,6 @@ static int do_recovery(struct ctdb_recoverd *rec,
 
 	DEBUG(DEBUG_NOTICE, (__location__ " Recovery - finished the recovered event\n"));
 
-	/* disable recovery mode */
-	ret = set_recovery_mode(ctdb, nodemap, CTDB_RECOVERY_NORMAL);
-	if (ret!=0) {
-		DEBUG(DEBUG_ERR, (__location__ " Unable to set recovery mode to normal on cluster\n"));
-		return -1;
-	}
-
-	DEBUG(DEBUG_NOTICE, (__location__ " Recovery - disabled recovery mode\n"));
-
 	/* send a message to all clients telling them that the cluster 
 	   has been reconfigured */
 	ctdb_send_message(ctdb, CTDB_BROADCAST_CONNECTED, CTDB_SRVID_RECONFIGURE, tdb_null);
@@ -2790,7 +2791,9 @@ static void ctdb_check_recd(struct event_context *ev, struct timed_event *te,
 		ctdb_stop_keepalive(ctdb);
 		ctdb_stop_monitoring(ctdb);
 		ctdb_release_all_ips(ctdb);
-		ctdb->methods->shutdown(ctdb);
+		if (ctdb->methods != NULL) {
+			ctdb->methods->shutdown(ctdb);
+		}
 		ctdb_event_script(ctdb, "shutdown");
 
 		exit(10);	
@@ -2831,7 +2834,9 @@ int ctdb_start_recoverd(struct ctdb_context *ctdb)
 	close(fd[1]);
 
 	/* shutdown the transport */
-	ctdb->methods->shutdown(ctdb);
+	if (ctdb->methods) {
+		ctdb->methods->shutdown(ctdb);
+	}
 
 	/* get a new event context */
 	talloc_free(ctdb->ev);
diff --git a/server/ctdb_server.c b/server/ctdb_server.c
index 546d618..a4c09a9 100644
--- a/server/ctdb_server.c
+++ b/server/ctdb_server.c
@@ -345,6 +345,11 @@ void ctdb_node_dead(struct ctdb_node *node)
 		 node->ctdb->name, node->name, node->ctdb->num_connected));
 	ctdb_daemon_cancel_controls(node->ctdb, node);
 
+	if (node->ctdb->methods == NULL) {
+		DEBUG(DEBUG_ALERT,(__location__ " Can not restart transport. ctdb->methods==NULL\n"));
+		ctdb_fatal(node->ctdb, "can not restart transport.");
+	}
+
 	node->ctdb->methods->restart(node);
 }
 
@@ -484,6 +489,11 @@ void ctdb_queue_packet(struct ctdb_context *ctdb, struct ctdb_req_header *hdr)
 	if (hdr->destnode == ctdb->pnn) {
 		ctdb_defer_packet(ctdb, hdr);
 	} else {
+		if (ctdb->methods == NULL) {
+			DEBUG(DEBUG_ALERT, (__location__ " Can not queue packet. Transport is DOWN\n"));
+			return;
+		}
+
 		node->tx_cnt++;
 		if (ctdb->methods->queue_pkt(node, (uint8_t *)hdr, hdr->length) != 0) {
 			ctdb_fatal(ctdb, "Unable to queue packet\n");
diff --git a/server/eventscript.c b/server/eventscript.c
index f6afd47..f8a5077 100644
--- a/server/eventscript.c
+++ b/server/eventscript.c
@@ -52,7 +52,6 @@ static int ctdb_event_script_v(struct ctdb_context *ctdb, const char *fmt, va_li
 {
 	char *options, *cmdstr;
 	int ret;
-	va_list ap2;
 	struct stat st;
 	TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
 	trbt_tree_t *tree;
@@ -60,6 +59,24 @@ static int ctdb_event_script_v(struct ctdb_context *ctdb, const char *fmt, va_li
 	struct dirent *de;
 	char *script;
 
+	options  = talloc_vasprintf(tmp_ctx, fmt, ap);
+	CTDB_NO_MEMORY(ctdb, options);
+
+	if (ctdb->recovery_mode != CTDB_RECOVERY_NORMAL) {
+		/* we guarantee that only some specifically allowed event scripts are run
+		   while in recovery */
+		const char *allowed_scripts[] = {"startrecovery", "shutdown" };
+		int i;
+		for (i=0;i<ARRAY_SIZE(allowed_scripts);i++) {
+			if (strcmp(options, allowed_scripts[i]) == 0) break;
+		}
+		if (i == ARRAY_SIZE(allowed_scripts)) {
+			DEBUG(0,("Refusing to run event scripts with option '%s' while in recovery\n",
+				 options));
+		}
+		return -1;
+	}
+
 	if (setpgid(0,0) != 0) {
 		DEBUG(DEBUG_ERR,("Failed to create process group for event scripts - %s\n",
 			 strerror(errno)));
@@ -146,11 +163,6 @@ static int ctdb_event_script_v(struct ctdb_context *ctdb, const char *fmt, va_li
 	   them
 	 */
 	while ((script=trbt_findfirstarray32(tree, 1)) != NULL) {
-		va_copy(ap2, ap);
-		options  = talloc_vasprintf(tmp_ctx, fmt, ap2);
-		va_end(ap2);
-		CTDB_NO_MEMORY(ctdb, options);
-
 		cmdstr = talloc_asprintf(tmp_ctx, "%s/%s %s", 
 				ctdb->event_script_dir,
 				script, options);


-- 
CTDB repository


More information about the samba-cvs mailing list