[PATCHES] Cleanup dead records in messages.tdb

Christof Schmitt cs at samba.org
Tue Apr 1 14:49:13 MDT 2014


When a smbd process dies, pending messages.tdb records for this process
will not get cleaned up. I have seen one case where the messages.tdb
file grew very large after I/O requests were delayed and smbd child
processes died.

These patches implement cleanup of messages.tdb records that is
triggered after a smbd dies; any record with an invalid key or a
non-existing PID will get deleted.

Christof
-------------- next part --------------
>From e463819835673ed5cb349ee2556bb14733b3a4fb Mon Sep 17 00:00:00 2001
From: Christof Schmitt <cs at samba.org>
Date: Mon, 31 Mar 2014 16:35:28 -0700
Subject: [PATCH 1/3] messaging: Add helper function to get PID from tdb key string

Signed-off-by: Christof Schmitt <cs at samba.org>
---
 source3/lib/messages_local.c |   13 +++++++++++++
 1 files changed, 13 insertions(+), 0 deletions(-)

diff --git a/source3/lib/messages_local.c b/source3/lib/messages_local.c
index 1fe89c3..afff72f 100644
--- a/source3/lib/messages_local.c
+++ b/source3/lib/messages_local.c
@@ -221,6 +221,19 @@ static TDB_DATA message_key_pid(TALLOC_CTX *mem_ctx, struct server_id pid)
 	return kbuf;
 }
 
+static pid_t message_key_to_pid(TDB_DATA key)
+{
+	int ret;
+	pid_t pid;
+
+	ret = sscanf((char *)key.dptr, "PID/%d", &pid);
+	if (ret != 1) {
+		return -1;
+	}
+
+	return pid;
+}
+
 /*
   Fetch the messaging array for a process
  */
-- 
1.7.1


>From c191a6e7aa9e454989b608dc4d8d61082cb6cc68 Mon Sep 17 00:00:00 2001
From: Christof Schmitt <cs at samba.org>
Date: Mon, 31 Mar 2014 16:46:52 -0700
Subject: [PATCH 2/3] messaging: Return tdb from messaging_tdb_parent_init

Store the pointer in the parent smbd context to be used for the
messages.tdb cleanup.

Signed-off-by: Christof Schmitt <cs at samba.org>
---
 source3/include/messages.h   |    2 +-
 source3/lib/messages_local.c |    6 +++---
 source3/smbd/server.c        |    5 ++++-
 3 files changed, 8 insertions(+), 5 deletions(-)

diff --git a/source3/include/messages.h b/source3/include/messages.h
index d7a2853..cd51c2a 100644
--- a/source3/include/messages.h
+++ b/source3/include/messages.h
@@ -95,7 +95,7 @@ NTSTATUS messaging_tdb_init(struct messaging_context *msg_ctx,
 			    TALLOC_CTX *mem_ctx,
 			    struct messaging_backend **presult);
 
-bool messaging_tdb_parent_init(TALLOC_CTX *mem_ctx);
+struct tdb_context *messaging_tdb_parent_init(TALLOC_CTX *mem_ctx);
 
 NTSTATUS messaging_ctdbd_init(struct messaging_context *msg_ctx,
 			      TALLOC_CTX *mem_ctx,
diff --git a/source3/lib/messages_local.c b/source3/lib/messages_local.c
index afff72f..077c3fd 100644
--- a/source3/lib/messages_local.c
+++ b/source3/lib/messages_local.c
@@ -170,7 +170,7 @@ static int messaging_tdb_context_destructor(struct messaging_tdb_context *ctx)
 	return 0;
 }
 
-bool messaging_tdb_parent_init(TALLOC_CTX *mem_ctx)
+struct tdb_context *messaging_tdb_parent_init(TALLOC_CTX *mem_ctx)
 {
 	struct tdb_wrap *db;
 	struct loadparm_context *lp_ctx;
@@ -198,9 +198,9 @@ bool messaging_tdb_parent_init(TALLOC_CTX *mem_ctx)
 	if (db == NULL) {
 		DEBUG(1, ("could not open messaging.tdb: %s\n",
 			  strerror(errno)));
-		return false;
 	}
-	return true;
+
+	return db->tdb;
 }
 
 /*******************************************************************
diff --git a/source3/smbd/server.c b/source3/smbd/server.c
index 9d6a250..dd18320 100644
--- a/source3/smbd/server.c
+++ b/source3/smbd/server.c
@@ -65,6 +65,8 @@ struct smbd_parent_context {
 	size_t num_children;
 
 	struct tevent_timer *cleanup_te;
+
+	struct tdb_context *messaging;
 };
 
 struct smbd_open_socket {
@@ -1442,7 +1444,8 @@ extern void build_options(bool screen);
 	if (!locking_init())
 		exit(1);
 
-	if (!messaging_tdb_parent_init(ev_ctx)) {
+	parent->messaging = messaging_tdb_parent_init(ev_ctx);
+	if (parent->messaging == NULL) {
 		exit(1);
 	}
 
-- 
1.7.1


>From 03917d536c7af9d85b0c0a5264a81212a1441097 Mon Sep 17 00:00:00 2001
From: Christof Schmitt <cs at samba.org>
Date: Mon, 31 Mar 2014 16:36:31 -0700
Subject: [PATCH 3/3] messages: Implement cleanup of dead records

When a smbd process dies, pending messages.tdb records for this process
will not get cleaned up. Implement a cleanup for dead records that is
triggered after a smbd dies; any record with an invalid key or a
non-existing PID will get deleted.

Signed-off-by: Christof Schmitt <cs at samba.org>
---
 source3/include/messages.h   |    3 ++
 source3/lib/messages_local.c |   45 ++++++++++++++++++++++++++++++++++++++++++
 source3/smbd/server.c        |    1 +
 3 files changed, 49 insertions(+), 0 deletions(-)

diff --git a/source3/include/messages.h b/source3/include/messages.h
index cd51c2a..d7d1e04 100644
--- a/source3/include/messages.h
+++ b/source3/include/messages.h
@@ -18,6 +18,8 @@
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
 
+#include "tdb.h"
+
 #ifndef _MESSAGES_H_
 #define _MESSAGES_H_
 
@@ -96,6 +98,7 @@ NTSTATUS messaging_tdb_init(struct messaging_context *msg_ctx,
 			    struct messaging_backend **presult);
 
 struct tdb_context *messaging_tdb_parent_init(TALLOC_CTX *mem_ctx);
+int messages_cleanup_dead_records(struct tdb_context *tdb);
 
 NTSTATUS messaging_ctdbd_init(struct messaging_context *msg_ctx,
 			      TALLOC_CTX *mem_ctx,
diff --git a/source3/lib/messages_local.c b/source3/lib/messages_local.c
index 077c3fd..511463e 100644
--- a/source3/lib/messages_local.c
+++ b/source3/lib/messages_local.c
@@ -545,4 +545,49 @@ static void message_dispatch(struct messaging_context *msg_ctx)
 	TALLOC_FREE(msg_array);
 }
 
+/*
+ * Traverse messages.tdb to cleanup dead records
+ */
+
+static int messages_traverse_cleanup(struct tdb_context *tdb, TDB_DATA key, TDB_DATA data,
+				     void *private_data)
+{
+	int ret;
+	pid_t pid;
+
+	pid = message_key_to_pid(key);
+	if (pid == -1) {
+		char *hex;
+
+		hex = hex_encode_talloc(talloc_tos(),
+					(unsigned char *)key.dptr, key.dsize);
+
+		DEBUG(1, ("Invalid key (0x%s) in messages.tdb, "
+			  "removing record.\n", hex));
+		ret = tdb_delete(tdb, key);
+		if (ret == -1) {
+			DEBUG(0, ("Deleting record (key 0x%s) failed\n", hex));
+		}
+		return 0;
+	}
+
+	ret = kill(pid, 0);
+	if (ret == -1 && errno == ESRCH) {
+		DEBUG(1, ("messages.tdb record for non-existing PID %d, "
+			  "removing record\n", pid));
+		ret = tdb_delete(tdb, key);
+		if (ret == -1) {
+			DEBUG(0, ("Deleting record for PID %d failed\n", pid));
+		}
+	}
+
+	return 0;
+}
+
+int messages_cleanup_dead_records(struct tdb_context *tdb)
+{
+	DEBUG(10, ("Starting cleanup of messages.tdb\n"));
+	return tdb_traverse(tdb, messages_traverse_cleanup, NULL);
+}
+
 /** @} **/
diff --git a/source3/smbd/server.c b/source3/smbd/server.c
index dd18320..0984491 100644
--- a/source3/smbd/server.c
+++ b/source3/smbd/server.c
@@ -439,6 +439,7 @@ static void cleanup_timeout_fn(struct tevent_context *event_ctx,
 	messaging_send_buf(parent->msg_ctx,
 			   messaging_server_id(parent->msg_ctx),
 			   MSG_SMB_BRL_VALIDATE, NULL, 0);
+	messages_cleanup_dead_records(parent->messaging);
 }
 
 static void remove_child_pid(struct smbd_parent_context *parent,
-- 
1.7.1



More information about the samba-technical mailing list