[PATCH] ctdb: calculate queue input buffer size correctly

Swen Schillig swen at vnet.ibm.com
Thu Jul 26 11:21:05 UTC 2018


Please review and push if happy.

Thanks in advance for your support.

Cheers Swen
-------------- next part --------------
From 7570afe2126110c78619eec1c893238c88cb650d Mon Sep 17 00:00:00 2001
From: Swen Schillig <swen at vnet.ibm.com>
Date: Wed, 7 Mar 2018 13:54:45 +0100
Subject: [PATCH] ctdb: calculate queue input buffer size correctly

The queue's input buffer is calculated in an iterative way.
This can result in a few back and forth jumping and
a few memory allocations and mem-free cycles.
This is very time consuming and not required, because the required
memory size can be calculated right away.

Signed-off-by: Swen Schillig <swen at vnet.ibm.com>
---
 ctdb/common/ctdb_io.c | 37 +++++++++++++++++++++----------------
 1 file changed, 21 insertions(+), 16 deletions(-)

diff --git a/ctdb/common/ctdb_io.c b/ctdb/common/ctdb_io.c
index c6941241883..d307d2b8bd8 100644
--- a/ctdb/common/ctdb_io.c
+++ b/ctdb/common/ctdb_io.c
@@ -43,7 +43,6 @@ struct ctdb_buffer {
 	uint8_t *data;
 	uint32_t length;
 	uint32_t size;
-	uint32_t extend;
 };
 
 struct ctdb_queue_pkt {
@@ -103,16 +102,15 @@ static void queue_process(struct ctdb_queue *queue)
 		return;
 	}
 
+	/* Did we at least read the size into the buffer */
 	pkt_size = *(uint32_t *)queue->buffer.data;
 	if (pkt_size == 0) {
 		DEBUG(DEBUG_CRIT, ("Invalid packet of length 0\n"));
 		goto failed;
 	}
 
+	/* the buffer doesn't contain the full packet, return to get the rest */
 	if (queue->buffer.length < pkt_size) {
-		if (pkt_size > queue->buffer_size) {
-			queue->buffer.extend = pkt_size;
-		}
 		return;
 	}
 
@@ -158,10 +156,10 @@ failed:
 */
 static void queue_io_read(struct ctdb_queue *queue)
 {
-	int num_ready = 0;
+	uint32_t num_ready;
+	uint32_t pkt_size;
 	ssize_t nread;
 	uint8_t *data;
-	int navail;
 
 	/* check how much data is available on the socket for immediately
 	   guaranteed nonblocking access.
@@ -185,22 +183,29 @@ static void queue_io_read(struct ctdb_queue *queue)
 			goto failed;
 		}
 		queue->buffer.size = queue->buffer_size;
-	} else if (queue->buffer.extend > 0) {
-		/* extending buffer */
-		data = talloc_realloc_size(queue, queue->buffer.data, queue->buffer.extend);
+		goto data_read;
+	}
+
+	if (queue->buffer.length < sizeof(pkt_size)) {
+		/* data read is not sufficient to gather message size */
+		goto data_read;
+	}
+
+	pkt_size = *(uint32_t *)queue->buffer.data;
+	if (pkt_size > queue->buffer.size) {
+		data = talloc_realloc_size(queue,
+					   queue->buffer.data,
+					   pkt_size);
 		if (data == NULL) {
-			DEBUG(DEBUG_ERR, ("read error realloc failed for %u\n", queue->buffer.extend));
+			DBG_ERR("read error realloc failed for %u\n", pkt_size);
 			goto failed;
 		}
 		queue->buffer.data = data;
-		queue->buffer.size = queue->buffer.extend;
-		queue->buffer.extend = 0;
+		queue->buffer.size = pkt_size;
 	}
 
-	navail = queue->buffer.size - queue->buffer.length;
-	if (num_ready > navail) {
-		num_ready = navail;
-	}
+data_read:
+	num_ready = MIN(num_ready, queue->buffer.size - queue->buffer.length);
 
 	if (num_ready > 0) {
 		nread = sys_read(queue->fd,
-- 
2.14.4



More information about the samba-technical mailing list