[SCM] CTDB repository - branch 1.0.112 updated - ctdb-1.0.111-23-g82f2ed8

Ronnie Sahlberg sahlberg at samba.org
Wed Feb 3 21:41:52 MST 2010


The branch, 1.0.112 has been updated
       via  82f2ed827caab8999cb3f958c70821a23490fdde (commit)
       via  ac885788678255f0c8a091f88ee4d440edf818a9 (commit)
       via  a781f05f9b80e288ae43ca16f109890942937e62 (commit)
       via  3ec469339e56f5221960ac5b3a69bf8fb553b8f5 (commit)
      from  4af34ca1bdb4895c2dd1ec280ef14cffab7fc815 (commit)

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


- Log -----------------------------------------------------------------
commit 82f2ed827caab8999cb3f958c70821a23490fdde
Author: Andrew Tridgell <tridge at samba.org>
Date:   Thu Feb 4 14:36:14 2010 +1100

    ctdb: when we fill the client packet queue we need to drop the client
    
    We can't just drop packets to the list, as those packets could be part
    of the core protocol the client is using. This happens (for example)
    when Samba is doing a traverse. If we drop a traverse packet then
    Samba hangs indefinately. We are better off dropping the ctdb socket
    to Samba.

commit ac885788678255f0c8a091f88ee4d440edf818a9
Author: Andrew Tridgell <tridge at samba.org>
Date:   Thu Feb 4 14:14:18 2010 +1100

    ctdb: move ctdb_io.c to use TLIST_*() macros
    
    This will make large packet queues much more efficient

commit a781f05f9b80e288ae43ca16f109890942937e62
Author: Andrew Tridgell <tridge at samba.org>
Date:   Thu Feb 4 14:13:49 2010 +1100

    util: added TLIST_*() macros
    
    The TLIST_*() macros are like the DLIST_*() macros, but take both a
    head and tail pointer for the list. This means that adding an element
    to the end of the list is efficient (it doesn't need to walk the
    list).
    
    We should move all uses of the DLIST_*() macros which use
    DLIST_ADD_END() to use the TLIST_*() macros instead.

commit 3ec469339e56f5221960ac5b3a69bf8fb553b8f5
Author: Ronnie Sahlberg <ronniesahlberg at gmail.com>
Date:   Thu Feb 4 09:54:06 2010 +1100

    We only queued up to 1000 packets per queue before we start dropping
    packets, to avoid the queue to grow excessively if smbd has blocked.
    
    This could cause traverse packets to become discarded in case the main
    smbd daemon does a traverse of a database while there is a recovery
    (sending a erconfigured message to smbd, causing an avalanche of unlock
    messages to be sent across the cluster.)
    
    This avalance of messages could cause also the tranversal message to be
    discarded  causing the main smbd process to hang indefinitely waiting
    for the traversal message that will never arrive.
    
    Bump the maximum queue length before starting to discard messages from
    1000 to 1000000 and at the same time rework the queueing slightly so we
    can append messages cheaply to the queue instead of walking the list
    from head to tail every time.

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

Summary of changes:
 common/ctdb_io.c       |   10 ++++++----
 lib/util/dlinklist.h   |   46 ++++++++++++++++++++++++++++++++++++++++++++++
 server/ctdb_daemon.c   |   17 ++++++++++++-----
 server/ctdb_tunables.c |    2 +-
 4 files changed, 65 insertions(+), 10 deletions(-)


Changeset truncated at 500 lines:

diff --git a/common/ctdb_io.c b/common/ctdb_io.c
index 28830d5..3fa784d 100644
--- a/common/ctdb_io.c
+++ b/common/ctdb_io.c
@@ -45,7 +45,7 @@ struct ctdb_queue_pkt {
 struct ctdb_queue {
 	struct ctdb_context *ctdb;
 	struct ctdb_partial partial; /* partial input packet */
-	struct ctdb_queue_pkt *out_queue;
+	struct ctdb_queue_pkt *out_queue, *out_queue_tail;
 	uint32_t out_queue_length;
 	struct fd_event *fde;
 	int fd;
@@ -194,7 +194,8 @@ static void queue_io_write(struct ctdb_queue *queue)
 		if (n == -1 && errno != EAGAIN && errno != EWOULDBLOCK) {
 			if (pkt->length != pkt->full_length) {
 				/* partial packet sent - we have to drop it */
-				DLIST_REMOVE(queue->out_queue, pkt);
+				TLIST_REMOVE(queue->out_queue, queue->out_queue_tail,
+					     pkt);
 				queue->out_queue_length--;
 				talloc_free(pkt);
 			}
@@ -213,7 +214,7 @@ static void queue_io_write(struct ctdb_queue *queue)
 			return;
 		}
 
-		DLIST_REMOVE(queue->out_queue, pkt);
+		TLIST_REMOVE(queue->out_queue, queue->out_queue_tail, pkt);
 		queue->out_queue_length--;
 		talloc_free(pkt);
 	}
@@ -294,7 +295,8 @@ int ctdb_queue_send(struct ctdb_queue *queue, uint8_t *data, uint32_t length)
 		EVENT_FD_WRITEABLE(queue->fde);
 	}
 
-	DLIST_ADD_END(queue->out_queue, pkt, struct ctdb_queue_pkt *);
+	TLIST_ADD_END(queue->out_queue, queue->out_queue_tail, pkt);
+
 	queue->out_queue_length++;
 
 	if (queue->ctdb->tunable.verbose_memory_names != 0) {
diff --git a/lib/util/dlinklist.h b/lib/util/dlinklist.h
index f018d87..44747d6 100644
--- a/lib/util/dlinklist.h
+++ b/lib/util/dlinklist.h
@@ -110,4 +110,50 @@ do { \
 		} \
 } while (0)
 
+/*
+   The TLIST_*() macros are meant for when you have two list pointers,
+   one pointing at the head of the list and one pointing at the tail
+   of the list. This makes the common case of adding to the end of the
+   list and removing from the front of the list efficient
+
+   TLIST stands for "tailed list"
+
+   Note: When initialising the structure containing your lists, make
+   sure that you set both head and tail to NULL
+
+   Also, do not mix the TLIST_*() macros with the DLIST_* macros!
+*/
+
+/* TLIST_ADD_FRONT adds elements to the front of the list. */
+#define TLIST_ADD_FRONT(listhead, listtail, p) \
+do { \
+	DLIST_ADD(listhead, p); \
+	if (NULL == (listtail)) { \
+		(listtail) = (p); \
+	} \
+} while (0)
+
+/* TLIST_ADD_END adds elements to the end of the list. */
+#define TLIST_ADD_END(listhead, listtail, p) \
+do { \
+	if ((listtail) == NULL) { \
+		DLIST_ADD(listhead, p); \
+		(listtail) = (listhead); \
+	} else { \
+		(listtail)->next = (p); \
+		(p)->prev = (listtail); \
+		(p)->next = NULL; \
+		(listtail) = (p); \
+	} \
+} while (0)
+
+/* TLIST_REMOVE removes an element from the list */
+#define TLIST_REMOVE(listhead, listtail, p) \
+do { \
+	if ((p) == (listtail)) { \
+		(listtail) = (p)->prev; \
+	} \
+	DLIST_REMOVE(listhead, p); \
+} while (0)
+
 #endif /* _DLINKLIST_H */
diff --git a/server/ctdb_daemon.c b/server/ctdb_daemon.c
index e96b369..1f7efee 100644
--- a/server/ctdb_daemon.c
+++ b/server/ctdb_daemon.c
@@ -100,8 +100,9 @@ static int daemon_queue_send(struct ctdb_client *client, struct ctdb_req_header
 	client->ctdb->statistics.client_packets_sent++;
 	if (hdr->operation == CTDB_REQ_MESSAGE) {
 		if (ctdb_queue_length(client->queue) > client->ctdb->tunable.max_queue_depth_drop_msg) {
-			DEBUG(DEBUG_ERR,("Drop CTDB_REQ_MESSAGE to client. Queue full.\n"));
-			return 0;
+			DEBUG(DEBUG_ERR,("CTDB_REQ_MESSAGE queue full - killing client connection.\n"));
+			talloc_free(client);
+			return -1;
 		}
 	}
 	return ctdb_queue_send(client->queue, (uint8_t *)hdr, hdr->length);
@@ -280,6 +281,10 @@ static void daemon_call_from_client_callback(struct ctdb_call_state *state)
 	memcpy(&r->data[0], dstate->call->reply_data.dptr, r->datalen);
 
 	res = daemon_queue_send(client, &r->hdr);
+	if (res == -1) {
+		/* client is dead - return immediately */
+		return;
+	}
 	if (res != 0) {
 		DEBUG(DEBUG_ERR, (__location__ " Failed to queue packet from daemon to client\n"));
 	}
@@ -884,6 +889,7 @@ static void daemon_control_callback(struct ctdb_context *ctdb,
 	struct ctdb_client *client = state->client;
 	struct ctdb_reply_control *r;
 	size_t len;
+	int ret;
 
 	/* construct a message to send to the client containing the data */
 	len = offsetof(struct ctdb_reply_control, data) + data.dsize;
@@ -904,9 +910,10 @@ static void daemon_control_callback(struct ctdb_context *ctdb,
 		memcpy(&r->data[r->datalen], errormsg, r->errorlen);
 	}
 
-	daemon_queue_send(client, &r->hdr);
-
-	talloc_free(state);
+	ret = daemon_queue_send(client, &r->hdr);
+	if (ret != -1) {
+		talloc_free(state);
+	}
 }
 
 /*
diff --git a/server/ctdb_tunables.c b/server/ctdb_tunables.c
index e75dcbd..cca270b 100644
--- a/server/ctdb_tunables.c
+++ b/server/ctdb_tunables.c
@@ -62,7 +62,7 @@ static const struct {
 	{ "VacuumLimit",       5000,  offsetof(struct ctdb_tunable, vacuum_limit) },
 	{ "VacuumMinInterval",   60,  offsetof(struct ctdb_tunable, vacuum_min_interval) },
 	{ "VacuumMaxInterval",  600,  offsetof(struct ctdb_tunable, vacuum_max_interval) },
-	{ "MaxQueueDropMsg",  1000,  offsetof(struct ctdb_tunable, max_queue_depth_drop_msg) },
+	{ "MaxQueueDropMsg",  1000000, offsetof(struct ctdb_tunable, max_queue_depth_drop_msg) },
 	{ "UseStatusEvents",     0,  offsetof(struct ctdb_tunable, use_status_events_for_monitoring) },
 	{ "AllowUnhealthyDBRead", 0,  offsetof(struct ctdb_tunable, allow_unhealthy_db_read) }
 };


-- 
CTDB repository


More information about the samba-cvs mailing list