[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