[PATCH] smbcontrol pool-usage for "samba"

Volker Lendecke Volker.Lendecke at SerNet.DE
Fri Feb 13 00:16:49 MST 2015


Hi!

Attached find a patchset that makes

smbcontrol <pid> pool-usage

available for the "samba" process.

Review&push appreciated.

Thanks,

Volker

-- 
SerNet GmbH, Bahnhofsallee 1b, 37081 Göttingen
phone: +49-551-370000-0, fax: +49-551-370000-9
AG Göttingen, HRB 2816, GF: Dr. Johannes Loxen
http://www.sernet.de, mailto:kontakt at sernet.de
-------------- next part --------------
From 707adf1b93ec854125d5999b6aa476b504edd93e Mon Sep 17 00:00:00 2001
From: Volker Lendecke <vl at samba.org>
Date: Wed, 4 Feb 2015 11:31:24 +0000
Subject: [PATCH 01/16] messaging4: Use server_id_db

Signed-off-by: Volker Lendecke <vl at samba.org>
---
 source4/lib/messaging/messaging.c   | 154 +++++++-----------------------------
 source4/lib/messaging/wscript_build |   2 +-
 2 files changed, 30 insertions(+), 126 deletions(-)

diff --git a/source4/lib/messaging/messaging.c b/source4/lib/messaging/messaging.c
index 53c8a9a..0b4e109 100644
--- a/source4/lib/messaging/messaging.c
+++ b/source4/lib/messaging/messaging.c
@@ -27,21 +27,17 @@
 #include "lib/socket/socket.h"
 #include "librpc/gen_ndr/ndr_irpc.h"
 #include "lib/messaging/irpc.h"
-#include "lib/tdb_wrap/tdb_wrap.h"
 #include "../lib/util/unix_privs.h"
 #include "librpc/rpc/dcerpc.h"
-#include "../lib/tdb_compat/tdb_compat.h"
-#include "../lib/util/util_tdb.h"
 #include "cluster/cluster.h"
 #include "../lib/util/tevent_ntstatus.h"
 #include "lib/param/param.h"
+#include "lib/util/server_id_db.h"
+#include <tdb.h>
 
 /* change the message version with any incompatible changes in the protocol */
 #define IMESSAGING_VERSION 1
 
-static struct tdb_wrap *irpc_namedb_open(TALLOC_CTX *mem_ctx, const char *base_path,
-					 struct loadparm_context *lp_ctx);
-
 /*
   a pending irpc call
 */
@@ -66,8 +62,7 @@ struct imessaging_context {
 	struct imessaging_rec *retry_queue;
 	struct irpc_list *irpc;
 	struct idr_context *idr;
-	const char **names;
-	struct tdb_wrap *names_db;
+	struct server_id_db *names;
 	struct timeval start_time;
 	struct tevent_timer *retry_te;
 	struct {
@@ -549,9 +544,6 @@ int imessaging_cleanup(struct imessaging_context *msg)
 
 	DEBUG(5,("imessaging: cleaning up %s\n", msg->path));
 	unlink(msg->path);
-	while (msg->names && msg->names[0]) {
-		irpc_remove_name(msg, msg->names[0]);
-	}
 	return 0;
 }
 
@@ -619,8 +611,11 @@ struct imessaging_context *imessaging_init(TALLOC_CTX *mem_ctx,
 
 	msg->start_time    = timeval_current();
 
-	msg->names_db = irpc_namedb_open(msg, msg->base_path, lp_ctx);
-	if (msg->names_db == NULL) {
+	msg->names = server_id_db_init(
+		msg, server_id, msg->base_path, 0,
+		TDB_INCOMPATIBLE_HASH|TDB_CLEAR_IF_FIRST|
+		lpcfg_tdb_flags(lp_ctx, 0));
+	if (msg->names == NULL) {
 		goto fail;
 	}
 
@@ -896,49 +891,16 @@ static int irpc_destructor(struct irpc_request *irpc)
 }
 
 /*
-  open the naming database
-*/
-static struct tdb_wrap *irpc_namedb_open(TALLOC_CTX *mem_ctx, const char *base_path,
-					 struct loadparm_context *lp_ctx)
-{
-	struct tdb_wrap *t;
-	char *path = talloc_asprintf(mem_ctx, "%s/names.tdb", base_path);
-	if (path == NULL) {
-		return NULL;
-	}
-	t = tdb_wrap_open(mem_ctx, path, lpcfg_tdb_hash_size(lp_ctx, path),
-			  lpcfg_tdb_flags(lp_ctx, 0), O_RDWR|O_CREAT, 0660);
-	talloc_free(path);
-	return t;
-}
-
-
-/*
   add a string name that this irpc server can be called on
 */
 NTSTATUS irpc_add_name(struct imessaging_context *msg_ctx, const char *name)
 {
-	struct tdb_context *t = msg_ctx->names_db->tdb;
-	struct server_id pid = msg_ctx->server_id;
-	TDB_DATA key, data;
 	int ret;
 
-	msg_ctx->names = str_list_add(msg_ctx->names, name);
-	if (msg_ctx->names == NULL) {
-		return NT_STATUS_NO_MEMORY;
-	}
-	talloc_steal(msg_ctx, msg_ctx->names);
-
-	key = string_term_tdb_data(name);
-	data = (TDB_DATA) { .dptr = (uint8_t *)&pid, .dsize = sizeof(pid) };
-
-	ret = tdb_append(t, key, data);
+	ret = server_id_db_add(msg_ctx->names, name);
 	if (ret != 0) {
-		enum TDB_ERROR err = tdb_error(t);
-		str_list_remove(msg_ctx->names, name);
-		return map_nt_error_from_tdb(err);
+		return map_nt_error_from_unix_common(ret);
 	}
-
 	return NT_STATUS_OK;
 }
 
@@ -950,43 +912,22 @@ NTSTATUS irpc_servers_byname(struct imessaging_context *msg_ctx,
 			     unsigned *num_servers,
 			     struct server_id **servers)
 {
-	struct tdb_wrap *t = msg_ctx->names_db;
-	TDB_DATA rec;
-	unsigned count;
-	struct server_id *ret;
-
-	rec = tdb_fetch_bystring(t->tdb, name);
-	if (rec.dptr == NULL) {
-		enum TDB_ERROR err = tdb_error(t->tdb);
-		return map_nt_error_from_tdb(err);
-	}
-
-	count = rec.dsize / sizeof(struct server_id);
-	if (count == 0) {
-		/*
-		 * In a corrupted db we could end up with a record of size
-		 * less than a struct server_id. Don't leak in this case.
-		 */
-		free(rec.dptr);
-		return NT_STATUS_NOT_FOUND;
-	}
-
-	ret = talloc_array(mem_ctx, struct server_id, count);
-	if (ret == NULL) {
-		free(rec.dptr);
-		return NT_STATUS_NO_MEMORY;
-	}
-	memcpy(ret, rec.dptr, count * sizeof(struct server_id));
-	free(rec.dptr);
+	int ret;
 
-	*num_servers = count;
-	*servers = ret;
+	ret = server_id_db_lookup(msg_ctx->names, name, mem_ctx,
+				  num_servers, servers);
+	if (ret != 0) {
+		return map_nt_error_from_unix_common(ret);
+	}
 	return NT_STATUS_OK;
 }
 
-static int all_servers_func(struct tdb_context *tdb, TDB_DATA key, TDB_DATA data, void *state)
+static int all_servers_func(const char *name, unsigned num_servers,
+			    const struct server_id *servers,
+			    void *private_data)
 {
-	struct irpc_name_records *name_records = talloc_get_type(state, struct irpc_name_records);
+	struct irpc_name_records *name_records = talloc_get_type(
+		private_data, struct irpc_name_records);
 	struct irpc_name_record *name_record;
 	int i;
 
@@ -1006,22 +947,19 @@ static int all_servers_func(struct tdb_context *tdb, TDB_DATA key, TDB_DATA data
 
 	name_records->num_records++;
 
-	name_record->name
-		= talloc_strndup(name_record,
-				 (const char *)key.dptr, key.dsize);
+	name_record->name = talloc_strdup(name_record, name);
 	if (!name_record->name) {
 		return -1;
 	}
 
-	name_record->count = data.dsize / sizeof(struct server_id);
-	name_record->ids = talloc_array(name_record,
-					struct server_id,
-					name_record->count);
+	name_record->count = num_servers;
+	name_record->ids = talloc_array(name_record, struct server_id,
+					num_servers);
 	if (name_record->ids == NULL) {
 		return -1;
 	}
 	for (i=0;i<name_record->count;i++) {
-		name_record->ids[i] = ((struct server_id *)data.dptr)[i];
+		name_record->ids[i] = servers[i];
 	}
 	return 0;
 }
@@ -1032,14 +970,14 @@ static int all_servers_func(struct tdb_context *tdb, TDB_DATA key, TDB_DATA data
 struct irpc_name_records *irpc_all_servers(struct imessaging_context *msg_ctx,
 					   TALLOC_CTX *mem_ctx)
 {
-	struct tdb_wrap *t = msg_ctx->names_db;
 	int ret;
 	struct irpc_name_records *name_records = talloc_zero(mem_ctx, struct irpc_name_records);
 	if (name_records == NULL) {
 		return NULL;
 	}
 
-	ret = tdb_traverse_read(t->tdb, all_servers_func, name_records);
+	ret = server_id_db_traverse_read(msg_ctx->names, all_servers_func,
+					 name_records);
 	if (ret == -1) {
 		TALLOC_FREE(name_records);
 		return NULL;
@@ -1053,41 +991,7 @@ struct irpc_name_records *irpc_all_servers(struct imessaging_context *msg_ctx,
 */
 void irpc_remove_name(struct imessaging_context *msg_ctx, const char *name)
 {
-	struct tdb_wrap *t = msg_ctx->names_db;
-	TDB_DATA rec;
-	int count, i;
-	struct server_id *ids;
-
-	str_list_remove(msg_ctx->names, name);
-
-	if (tdb_lock_bystring(t->tdb, name) != 0) {
-		return;
-	}
-	rec = tdb_fetch_bystring(t->tdb, name);
-	if (rec.dptr == NULL) {
-		tdb_unlock_bystring(t->tdb, name);
-		return;
-	}
-	count = rec.dsize / sizeof(struct server_id);
-	if (count == 0) {
-		free(rec.dptr);
-		tdb_unlock_bystring(t->tdb, name);
-		return;
-	}
-	ids = (struct server_id *)rec.dptr;
-	for (i=0;i<count;i++) {
-		if (cluster_id_equal(&ids[i], &msg_ctx->server_id)) {
-			if (i < count-1) {
-				memmove(ids+i, ids+i+1,
-					sizeof(struct server_id) * (count-(i+1)));
-			}
-			rec.dsize -= sizeof(struct server_id);
-			break;
-		}
-	}
-	tdb_store_bystring(t->tdb, name, rec, 0);
-	free(rec.dptr);
-	tdb_unlock_bystring(t->tdb, name);
+	server_id_db_remove(msg_ctx->names, name);
 }
 
 struct server_id imessaging_get_server_id(struct imessaging_context *msg_ctx)
diff --git a/source4/lib/messaging/wscript_build b/source4/lib/messaging/wscript_build
index 31a97a2..48c490e 100644
--- a/source4/lib/messaging/wscript_build
+++ b/source4/lib/messaging/wscript_build
@@ -3,7 +3,7 @@
 
 bld.SAMBA_LIBRARY('MESSAGING',
 	source='messaging.c',
-	public_deps='samba-util tdb-wrap NDR_IRPC UNIX_PRIVS util_tdb cluster ndr samba_socket dcerpc',
+	public_deps='samba-util NDR_IRPC UNIX_PRIVS cluster ndr samba_socket dcerpc server_id_db',
 	private_library=True
 	)
 
-- 
1.9.1


From 612508d5ea3571c0af3628f30d28d6f81b37839f Mon Sep 17 00:00:00 2001
From: Volker Lendecke <vl at samba.org>
Date: Sat, 4 Oct 2014 10:40:24 +0200
Subject: [PATCH 02/16] messages_dgm: Only pass "unique" to messaging_dgm_init

We have only one context per pid, so messaging_dgm_init can do getpid()
itself.

Signed-off-by: Volker Lendecke <vl at samba.org>
---
 source3/lib/messages.c     |  4 ++--
 source3/lib/messages_dgm.c | 10 +++++-----
 source3/lib/messages_dgm.h |  2 +-
 3 files changed, 8 insertions(+), 8 deletions(-)

diff --git a/source3/lib/messages.c b/source3/lib/messages.c
index 0e53583..f14d149 100644
--- a/source3/lib/messages.c
+++ b/source3/lib/messages.c
@@ -307,7 +307,7 @@ struct messaging_context *messaging_init(TALLOC_CTX *mem_ctx,
 
 	sec_init();
 
-	ret = messaging_dgm_init(ctx->event_ctx, ctx->id,
+	ret = messaging_dgm_init(ctx->event_ctx, ctx->id.unique_id,
 				 lp_cache_directory(), sec_initial_uid(),
 				 messaging_recv_cb, ctx);
 
@@ -368,7 +368,7 @@ NTSTATUS messaging_reinit(struct messaging_context *msg_ctx)
 
 	msg_ctx->id = procid_self();
 
-	ret = messaging_dgm_init(msg_ctx->event_ctx, msg_ctx->id,
+	ret = messaging_dgm_init(msg_ctx->event_ctx, msg_ctx->id.unique_id,
 				 lp_cache_directory(), sec_initial_uid(),
 				 messaging_recv_cb, msg_ctx);
 	if (ret != 0) {
diff --git a/source3/lib/messages_dgm.c b/source3/lib/messages_dgm.c
index ae35282..8f5ac4d 100644
--- a/source3/lib/messages_dgm.c
+++ b/source3/lib/messages_dgm.c
@@ -176,7 +176,7 @@ static int messaging_dgm_lockfile_remove(const char *cache_dir, pid_t pid)
 }
 
 int messaging_dgm_init(struct tevent_context *ev,
-		       struct server_id pid,
+		       uint64_t unique,
 		       const char *cache_dir,
 		       uid_t dir_owner,
 		       void (*recv_cb)(const uint8_t *msg,
@@ -203,7 +203,7 @@ int messaging_dgm_init(struct tevent_context *ev,
 	if (ctx == NULL) {
 		goto fail_nomem;
 	}
-	ctx->pid = pid.pid;
+	ctx->pid = getpid();
 	ctx->recv_cb = recv_cb;
 	ctx->recv_cb_private_data = recv_cb_private_data;
 
@@ -220,14 +220,14 @@ int messaging_dgm_init(struct tevent_context *ev,
 	socket_address = (struct sockaddr_un) { .sun_family = AF_UNIX };
 	sockname_len = snprintf(socket_address.sun_path,
 				sizeof(socket_address.sun_path),
-				"%s/%u", socket_dir.buf, (unsigned)pid.pid);
+				"%s/%u", socket_dir.buf, (unsigned)ctx->pid);
 	if (sockname_len >= sizeof(socket_address.sun_path)) {
 		TALLOC_FREE(ctx);
 		return ENAMETOOLONG;
 	}
 
-	ret = messaging_dgm_lockfile_create(cache_dir, dir_owner, pid.pid,
-					    &ctx->lockfile_fd, pid.unique_id);
+	ret = messaging_dgm_lockfile_create(cache_dir, dir_owner, ctx->pid,
+					    &ctx->lockfile_fd, unique);
 	if (ret != 0) {
 		DEBUG(1, ("%s: messaging_dgm_create_lockfile failed: %s\n",
 			  __func__, strerror(ret)));
diff --git a/source3/lib/messages_dgm.h b/source3/lib/messages_dgm.h
index 00ff56f..9d01976 100644
--- a/source3/lib/messages_dgm.h
+++ b/source3/lib/messages_dgm.h
@@ -21,7 +21,7 @@
 #define _MESSAGES_DGM_H_
 
 int messaging_dgm_init(struct tevent_context *ev,
-		       struct server_id pid,
+		       uint64_t unique,
 		       const char *cache_dir,
 		       uid_t dir_owner,
 		       void (*recv_cb)(const uint8_t *msg,
-- 
1.9.1


From e6b735cf8402cab423a54a569774f223a7f768e1 Mon Sep 17 00:00:00 2001
From: Volker Lendecke <vl at samba.org>
Date: Sat, 4 Oct 2014 10:58:15 +0200
Subject: [PATCH 03/16] messages_dgm: Move directory handling up

When we want to use messages_dgm in source4, we need to find better
places for the lock and socket directories. Source4 does not have the
concept of a cache directory. So I chose "private dir"/sock and "lock
dir"/msg as subdirectories.

This moves directory creation from messages_dgm.c to messages.c,
source4/lib/messaging will have its own way of doing this.

Signed-off-by: Volker Lendecke <vl at samba.org>
---
 source3/lib/messages.c     |  38 ++++++++++-
 source3/lib/messages_dgm.c | 160 +++++++++++++++++----------------------------
 source3/lib/messages_dgm.h |   4 +-
 3 files changed, 98 insertions(+), 104 deletions(-)

diff --git a/source3/lib/messages.c b/source3/lib/messages.c
index f14d149..cdd6b05 100644
--- a/source3/lib/messages.c
+++ b/source3/lib/messages.c
@@ -291,12 +291,20 @@ static int messaging_context_destructor(struct messaging_context *ctx)
 	return 0;
 }
 
+static const char *private_path(const char *name)
+{
+	return talloc_asprintf(talloc_tos(), "%s/%s", lp_private_dir(), name);
+}
+
 struct messaging_context *messaging_init(TALLOC_CTX *mem_ctx, 
 					 struct tevent_context *ev)
 {
 	struct messaging_context *ctx;
 	NTSTATUS status;
 	int ret;
+	const char *lck_path;
+	const char *priv_path;
+	bool ok;
 
 	if (!(ctx = talloc_zero(mem_ctx, struct messaging_context))) {
 		return NULL;
@@ -307,8 +315,34 @@ struct messaging_context *messaging_init(TALLOC_CTX *mem_ctx,
 
 	sec_init();
 
+	lck_path = lock_path("msg");
+	if (lck_path == NULL) {
+		TALLOC_FREE(ctx);
+		return NULL;
+	}
+
+	ok = directory_create_or_exist_strict(lck_path, sec_initial_uid(),
+					      0755);
+	if (!ok) {
+		DEBUG(10, ("%s: Could not create lock directory: %s\n",
+			   __func__, strerror(errno)));
+		TALLOC_FREE(ctx);
+		return NULL;
+	}
+
+	priv_path = private_path("sock");
+
+	ok = directory_create_or_exist_strict(priv_path, sec_initial_uid(),
+					      0700);
+	if (!ok) {
+		DEBUG(10, ("%s: Could not create msg directory: %s\n",
+			   __func__, strerror(errno)));
+		TALLOC_FREE(ctx);
+		return NULL;
+	}
+
 	ret = messaging_dgm_init(ctx->event_ctx, ctx->id.unique_id,
-				 lp_cache_directory(), sec_initial_uid(),
+				 priv_path, lck_path,
 				 messaging_recv_cb, ctx);
 
 	if (ret != 0) {
@@ -369,7 +403,7 @@ NTSTATUS messaging_reinit(struct messaging_context *msg_ctx)
 	msg_ctx->id = procid_self();
 
 	ret = messaging_dgm_init(msg_ctx->event_ctx, msg_ctx->id.unique_id,
-				 lp_cache_directory(), sec_initial_uid(),
+				 private_path("sock"), lock_path("msg"),
 				 messaging_recv_cb, msg_ctx);
 	if (ret != 0) {
 		DEBUG(0, ("messaging_dgm_init failed: %s\n", strerror(errno)));
diff --git a/source3/lib/messages_dgm.c b/source3/lib/messages_dgm.c
index 8f5ac4d..b64b2b0 100644
--- a/source3/lib/messages_dgm.c
+++ b/source3/lib/messages_dgm.c
@@ -39,7 +39,8 @@ struct messaging_dgm_context {
 	struct poll_funcs *msg_callbacks;
 	void *tevent_handle;
 	struct unix_msg_ctx *dgm_ctx;
-	struct sun_path_buf cache_dir;
+	struct sun_path_buf socket_dir;
+	struct sun_path_buf lockfile_dir;
 	int lockfile_fd;
 
 	void (*recv_cb)(const uint8_t *msg,
@@ -59,49 +60,23 @@ static void messaging_dgm_recv(struct unix_msg_ctx *ctx,
 			       int *fds, size_t num_fds,
 			       void *private_data);
 
-static int messaging_dgm_lockfile_name(struct sun_path_buf *buf,
-				       const char *cache_dir,
-				       pid_t pid)
-{
-	int ret;
-
-	ret = snprintf(buf->buf, sizeof(buf->buf), "%s/lck/%u", cache_dir,
-		       (unsigned)pid);
-	if (ret >= sizeof(buf->buf)) {
-		return ENAMETOOLONG;
-	}
-	return 0;
-}
-
 static int messaging_dgm_context_destructor(struct messaging_dgm_context *c);
 
-static int messaging_dgm_lockfile_create(const char *cache_dir,
-					 uid_t dir_owner, pid_t pid,
-					 int *plockfile_fd, uint64_t unique)
+static int messaging_dgm_lockfile_create(struct messaging_dgm_context *ctx,
+					 pid_t pid, int *plockfile_fd,
+					 uint64_t unique)
 {
 	fstring buf;
-	struct sun_path_buf dir;
-	struct sun_path_buf lockfile_name;
 	int lockfile_fd;
+	struct sun_path_buf lockfile_name;
 	struct flock lck;
 	int unique_len, ret;
 	ssize_t written;
-	bool ok;
-
-	ret = messaging_dgm_lockfile_name(&lockfile_name, cache_dir, pid);
-	if (ret != 0) {
-		return ret;
-	}
 
-	/* shorter than lockfile_name, can't overflow */
-	snprintf(dir.buf, sizeof(dir.buf), "%s/lck", cache_dir);
-
-	ok = directory_create_or_exist_strict(dir.buf, dir_owner, 0755);
-	if (!ok) {
-		ret = errno;
-		DEBUG(1, ("%s: Could not create lock directory: %s\n",
-			  __func__, strerror(ret)));
-		return ret;
+	ret = snprintf(lockfile_name.buf, sizeof(lockfile_name.buf),
+		       "%s/%u", ctx->lockfile_dir.buf, (int)pid);
+	if (ret >= sizeof(lockfile_name.buf)) {
+		return ENAMETOOLONG;
 	}
 
 	/* no O_EXCL, existence check is via the fcntl lock */
@@ -155,30 +130,10 @@ fail_close:
 	return ret;
 }
 
-static int messaging_dgm_lockfile_remove(const char *cache_dir, pid_t pid)
-{
-	struct sun_path_buf lockfile_name;
-	int ret;
-
-	ret = messaging_dgm_lockfile_name(&lockfile_name, cache_dir, pid);
-	if (ret != 0) {
-		return ret;
-	}
-
-	ret = unlink(lockfile_name.buf);
-	if (ret == -1) {
-		ret = errno;
-		DEBUG(10, ("%s: unlink(%s) failed: %s\n", __func__,
-			   lockfile_name.buf, strerror(ret)));
-	}
-
-	return ret;
-}
-
 int messaging_dgm_init(struct tevent_context *ev,
 		       uint64_t unique,
-		       const char *cache_dir,
-		       uid_t dir_owner,
+		       const char *socket_dir,
+		       const char *lockfile_dir,
 		       void (*recv_cb)(const uint8_t *msg,
 				       size_t msg_len,
 				       int *fds,
@@ -188,11 +143,9 @@ int messaging_dgm_init(struct tevent_context *ev,
 {
 	struct messaging_dgm_context *ctx;
 	int ret;
-	bool ok;
-	struct sun_path_buf socket_dir;
 	struct sockaddr_un socket_address;
-	size_t sockname_len;
 	uint64_t cookie;
+	size_t len;
 	static bool have_dgm_context = false;
 
 	if (have_dgm_context) {
@@ -207,27 +160,31 @@ int messaging_dgm_init(struct tevent_context *ev,
 	ctx->recv_cb = recv_cb;
 	ctx->recv_cb_private_data = recv_cb_private_data;
 
-	ret = snprintf(socket_dir.buf, sizeof(socket_dir.buf),
-		       "%s/msg", cache_dir);
-	if (ret >= sizeof(socket_dir.buf)) {
+	len = strlcpy(ctx->lockfile_dir.buf, lockfile_dir,
+		      sizeof(ctx->lockfile_dir.buf));
+	if (len >= sizeof(ctx->lockfile_dir.buf)) {
 		TALLOC_FREE(ctx);
 		return ENAMETOOLONG;
 	}
 
-	/* shorter than socket_dir, can't overflow */
-	strlcpy(ctx->cache_dir.buf, cache_dir, sizeof(ctx->cache_dir.buf));
+	len = strlcpy(ctx->socket_dir.buf, socket_dir,
+		      sizeof(ctx->socket_dir.buf));
+	if (len >= sizeof(ctx->socket_dir.buf)) {
+		TALLOC_FREE(ctx);
+		return ENAMETOOLONG;
+	}
 
 	socket_address = (struct sockaddr_un) { .sun_family = AF_UNIX };
-	sockname_len = snprintf(socket_address.sun_path,
-				sizeof(socket_address.sun_path),
-				"%s/%u", socket_dir.buf, (unsigned)ctx->pid);
-	if (sockname_len >= sizeof(socket_address.sun_path)) {
+	len = snprintf(socket_address.sun_path,
+		       sizeof(socket_address.sun_path),
+		       "%s/%u", socket_dir, (unsigned)ctx->pid);
+	if (len >= sizeof(socket_address.sun_path)) {
 		TALLOC_FREE(ctx);
 		return ENAMETOOLONG;
 	}
 
-	ret = messaging_dgm_lockfile_create(cache_dir, dir_owner, ctx->pid,
-					    &ctx->lockfile_fd, unique);
+	ret = messaging_dgm_lockfile_create(ctx, ctx->pid, &ctx->lockfile_fd,
+					    unique);
 	if (ret != 0) {
 		DEBUG(1, ("%s: messaging_dgm_create_lockfile failed: %s\n",
 			  __func__, strerror(ret)));
@@ -246,13 +203,6 @@ int messaging_dgm_init(struct tevent_context *ev,
 		goto fail_nomem;
 	}
 
-	ok = directory_create_or_exist_strict(socket_dir.buf, dir_owner, 0700);
-	if (!ok) {
-		DEBUG(1, ("Could not create socket directory\n"));
-		TALLOC_FREE(ctx);
-		return EACCES;
-	}
-
 	unlink(socket_address.sun_path);
 
 	generate_random_buffer((uint8_t *)&cookie, sizeof(cookie));
@@ -285,7 +235,19 @@ static int messaging_dgm_context_destructor(struct messaging_dgm_context *c)
 	unix_msg_free(c->dgm_ctx);
 
 	if (getpid() == c->pid) {
-		(void)messaging_dgm_lockfile_remove(c->cache_dir.buf, c->pid);
+		struct sun_path_buf name;
+		int ret;
+
+		ret = snprintf(name.buf, sizeof(name.buf), "%s/%u",
+			       c->lockfile_dir.buf, (unsigned)c->pid);
+		if (ret >= sizeof(name.buf)) {
+			/*
+			 * We've checked the length when creating, so this
+			 * should never happen
+			 */
+			abort();
+		}
+		unlink(name.buf);
 	}
 	close(c->lockfile_fd);
 
@@ -317,7 +279,7 @@ int messaging_dgm_send(pid_t pid,
 	dst = (struct sockaddr_un) { .sun_family = AF_UNIX };
 
 	dst_pathlen = snprintf(dst.sun_path, sizeof(dst.sun_path),
-			       "%s/msg/%u", ctx->cache_dir.buf, (unsigned)pid);
+			       "%s/%u", ctx->socket_dir.buf, (unsigned)pid);
 	if (dst_pathlen >= sizeof(dst.sun_path)) {
 		return ENAMETOOLONG;
 	}
@@ -345,22 +307,24 @@ int messaging_dgm_cleanup(pid_t pid)
 {
 	struct messaging_dgm_context *ctx = global_dgm_context;
 	struct sun_path_buf lockfile_name, socket_name;
-	int fd, ret;
+	int fd, len, ret;
 	struct flock lck = {};
 
 	if (ctx == NULL) {
 		return ENOTCONN;
 	}
 
-	ret = messaging_dgm_lockfile_name(&lockfile_name, ctx->cache_dir.buf,
-					  pid);
-	if (ret != 0) {
-		return ret;
+	len = snprintf(socket_name.buf, sizeof(socket_name.buf), "%s/%u",
+		       ctx->socket_dir.buf, (unsigned)pid);
+	if (len >= sizeof(socket_name.buf)) {
+		return ENAMETOOLONG;
 	}
 
-	/* same length as lockfile_name, can't overflow */
-	snprintf(socket_name.buf, sizeof(socket_name.buf), "%s/msg/%u",
-		 ctx->cache_dir.buf, (unsigned)pid);
+	len = snprintf(lockfile_name.buf, sizeof(lockfile_name.buf), "%s/%u",
+		       ctx->lockfile_dir.buf, (unsigned)pid);
+	if (len >= sizeof(lockfile_name.buf)) {
+		return ENAMETOOLONG;
+	}
 
 	fd = open(lockfile_name.buf, O_NONBLOCK|O_WRONLY, 0);
 	if (fd == -1) {
@@ -380,12 +344,16 @@ int messaging_dgm_cleanup(pid_t pid)
 	ret = fcntl(fd, F_SETLK, &lck);
 	if (ret != 0) {
 		ret = errno;
-		DEBUG(10, ("%s: Could not get lock: %s\n", __func__,
-			   strerror(ret)));
+		if ((ret != EACCES) && (ret != EAGAIN)) {
+			DEBUG(10, ("%s: Could not get lock: %s\n", __func__,
+				   strerror(ret)));
+		}
 		close(fd);
 		return ret;
 	}
 
+	DEBUG(10, ("%s: Cleaning up : %s\n", __func__, strerror(ret)));
+
 	(void)unlink(socket_name.buf);
 	(void)unlink(lockfile_name.buf);
 	(void)close(fd);
@@ -395,7 +363,6 @@ int messaging_dgm_cleanup(pid_t pid)
 int messaging_dgm_wipe(void)
 {
 	struct messaging_dgm_context *ctx = global_dgm_context;
-	struct sun_path_buf msgdir_name;
 	DIR *msgdir;
 	struct dirent *dp;
 	pid_t our_pid = getpid();
@@ -411,16 +378,9 @@ int messaging_dgm_wipe(void)
 	 * and fcntl(SETLK).
 	 */
 
-	ret = snprintf(msgdir_name.buf, sizeof(msgdir_name.buf),
-		       "%s/msg", ctx->cache_dir.buf);
-	if (ret >= sizeof(msgdir_name.buf)) {
-		return ENAMETOOLONG;
-	}
-
-	msgdir = opendir(msgdir_name.buf);
+	msgdir = opendir(ctx->socket_dir.buf);
 	if (msgdir == NULL) {
-		ret = errno;
-		return ret;
+		return errno;
 	}
 
 	while ((dp = readdir(msgdir)) != NULL) {
diff --git a/source3/lib/messages_dgm.h b/source3/lib/messages_dgm.h
index 9d01976..54a1b31 100644
--- a/source3/lib/messages_dgm.h
+++ b/source3/lib/messages_dgm.h
@@ -22,8 +22,8 @@
 
 int messaging_dgm_init(struct tevent_context *ev,
 		       uint64_t unique,
-		       const char *cache_dir,
-		       uid_t dir_owner,
+		       const char *socket_dir,
+		       const char *lockfile_dir,
 		       void (*recv_cb)(const uint8_t *msg,
 				       size_t msg_len,
 				       int *fds,
-- 
1.9.1


From 858ea00a8ae741cb9007882bef4fed1c85c2aac2 Mon Sep 17 00:00:00 2001
From: Volker Lendecke <vl at samba.org>
Date: Sun, 14 Sep 2014 17:52:07 +0200
Subject: [PATCH 04/16] unix_msg: remove cookie from unix_msg_init

"pid" and "sock" are sufficient I guess as randomizers to distinguish messages.
In theory, a pid could be recycled very quickly, which might mix up in-flight
messages. But once a few messages have passed, "cookie" would be incremented as
another indicator of a fresh message.

Why? Remove messages_dgm dependency on samba-util

Signed-off-by: Volker Lendecke <vl at samba.org>
---
 source3/lib/messages_dgm.c         | 5 +----
 source3/lib/unix_msg/test_drain.c  | 2 +-
 source3/lib/unix_msg/test_source.c | 2 +-
 source3/lib/unix_msg/tests.c       | 9 +++------
 source3/lib/unix_msg/unix_msg.c    | 4 ++--
 source3/lib/unix_msg/unix_msg.h    | 3 +--
 6 files changed, 9 insertions(+), 16 deletions(-)

diff --git a/source3/lib/messages_dgm.c b/source3/lib/messages_dgm.c
index b64b2b0..1602caf 100644
--- a/source3/lib/messages_dgm.c
+++ b/source3/lib/messages_dgm.c
@@ -144,7 +144,6 @@ int messaging_dgm_init(struct tevent_context *ev,
 	struct messaging_dgm_context *ctx;
 	int ret;
 	struct sockaddr_un socket_address;
-	uint64_t cookie;
 	size_t len;
 	static bool have_dgm_context = false;
 
@@ -205,9 +204,7 @@ int messaging_dgm_init(struct tevent_context *ev,
 
 	unlink(socket_address.sun_path);
 
-	generate_random_buffer((uint8_t *)&cookie, sizeof(cookie));
-
-	ret = unix_msg_init(&socket_address, ctx->msg_callbacks, 1024, cookie,
+	ret = unix_msg_init(&socket_address, ctx->msg_callbacks, 1024,
 			    messaging_dgm_recv, ctx, &ctx->dgm_ctx);
 	if (ret != 0) {
 		DEBUG(1, ("unix_msg_init failed: %s\n", strerror(ret)));
diff --git a/source3/lib/unix_msg/test_drain.c b/source3/lib/unix_msg/test_drain.c
index 9d74042..675ac6f 100644
--- a/source3/lib/unix_msg/test_drain.c
+++ b/source3/lib/unix_msg/test_drain.c
@@ -52,7 +52,7 @@ int main(int argc, const char *argv[])
 		exit(1);
 	}
 
-	ret = unix_msg_init(&addr, funcs, 256, 1, recv_cb, &state, &ctx);
+	ret = unix_msg_init(&addr, funcs, 256, recv_cb, &state, &ctx);
 	if (ret != 0) {
 		fprintf(stderr, "unix_msg_init failed: %s\n",
 			strerror(ret));
diff --git a/source3/lib/unix_msg/test_source.c b/source3/lib/unix_msg/test_source.c
index 5224ebf..3b65267 100644
--- a/source3/lib/unix_msg/test_source.c
+++ b/source3/lib/unix_msg/test_source.c
@@ -46,7 +46,7 @@ int main(int argc, const char *argv[])
 	}
 
 	for (i=0; i<num_ctxs; i++) {
-		ret = unix_msg_init(NULL, funcs, 256, 1, NULL, NULL,
+		ret = unix_msg_init(NULL, funcs, 256, NULL, NULL,
 				    &ctxs[i]);
 		if (ret != 0) {
 			fprintf(stderr, "unix_msg_init failed: %s\n",
diff --git a/source3/lib/unix_msg/tests.c b/source3/lib/unix_msg/tests.c
index df094af..9a15f9d 100644
--- a/source3/lib/unix_msg/tests.c
+++ b/source3/lib/unix_msg/tests.c
@@ -70,16 +70,14 @@ int main(void)
 		return 1;
 	}
 
-	ret = unix_msg_init(&addr1, funcs, 256, 1,
-			    recv_cb, &state, &ctx1);
+	ret = unix_msg_init(&addr1, funcs, 256, recv_cb, &state, &ctx1);
 	if (ret != 0) {
 		fprintf(stderr, "unix_msg_init failed: %s\n",
 			strerror(ret));
 		return 1;
 	}
 
-	ret = unix_msg_init(&addr1, funcs, 256, 1,
-			    recv_cb, &state, &ctx1);
+	ret = unix_msg_init(&addr1, funcs, 256, recv_cb, &state, &ctx1);
 	if (ret == 0) {
 		fprintf(stderr, "unix_msg_init succeeded unexpectedly\n");
 		return 1;
@@ -90,8 +88,7 @@ int main(void)
 		return 1;
 	}
 
-	ret = unix_msg_init(&addr2, funcs, 256, 1,
-			    recv_cb, &state, &ctx2);
+	ret = unix_msg_init(&addr2, funcs, 256, recv_cb, &state, &ctx2);
 	if (ret != 0) {
 		fprintf(stderr, "unix_msg_init failed: %s\n",
 			strerror(ret));
diff --git a/source3/lib/unix_msg/unix_msg.c b/source3/lib/unix_msg/unix_msg.c
index e4eed1c..6714f0d 100644
--- a/source3/lib/unix_msg/unix_msg.c
+++ b/source3/lib/unix_msg/unix_msg.c
@@ -744,7 +744,7 @@ static void unix_msg_recv(struct unix_dgram_ctx *dgram_ctx,
 
 int unix_msg_init(const struct sockaddr_un *addr,
 		  const struct poll_funcs *ev_funcs,
-		  size_t fragment_len, uint64_t cookie,
+		  size_t fragment_len,
 		  void (*recv_callback)(struct unix_msg_ctx *ctx,
 					uint8_t *msg, size_t msg_len,
 					int *fds, size_t num_fds,
@@ -762,7 +762,7 @@ int unix_msg_init(const struct sockaddr_un *addr,
 
 	*ctx = (struct unix_msg_ctx) {
 		.fragment_len = fragment_len,
-		.cookie = cookie,
+		.cookie = 1,
 		.recv_callback = recv_callback,
 		.private_data = private_data
 	};
diff --git a/source3/lib/unix_msg/unix_msg.h b/source3/lib/unix_msg/unix_msg.h
index 83d7067..34c166b 100644
--- a/source3/lib/unix_msg/unix_msg.h
+++ b/source3/lib/unix_msg/unix_msg.h
@@ -75,7 +75,6 @@ struct unix_msg_ctx;
  * @param[in] path The socket path
  * @param[in] ev_funcs The event callback functions to use
  * @param[in] fragment_size Maximum datagram size to send/receive
- * @param[in] cookie Random number to identify this context
  * @param[in] recv_callback Function called when a message is received
  * @param[in] private_data Private pointer for recv_callback
  * @param[out] result The new struct unix_msg_ctx
@@ -85,7 +84,7 @@ struct unix_msg_ctx;
 
 int unix_msg_init(const struct sockaddr_un *addr,
 		  const struct poll_funcs *ev_funcs,
-		  size_t fragment_size, uint64_t cookie,
+		  size_t fragment_size,
 		  void (*recv_callback)(struct unix_msg_ctx *ctx,
 					uint8_t *msg, size_t msg_len,
 					int *fds, size_t num_fds,
-- 
1.9.1


From 301d8ecc8d609e6fd3b1d70d8931859b5bbdd179 Mon Sep 17 00:00:00 2001
From: Volker Lendecke <vl at samba.org>
Date: Sat, 4 Oct 2014 11:14:26 +0200
Subject: [PATCH 05/16] messages_dgm: Add a few #includes

Signed-off-by: Volker Lendecke <vl at samba.org>
---
 source3/lib/messages_dgm.h | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/source3/lib/messages_dgm.h b/source3/lib/messages_dgm.h
index 54a1b31..c9c9c61 100644
--- a/source3/lib/messages_dgm.h
+++ b/source3/lib/messages_dgm.h
@@ -20,6 +20,10 @@
 #ifndef _MESSAGES_DGM_H_
 #define _MESSAGES_DGM_H_
 
+#include "replace.h"
+#include "system/filesys.h"
+#include <tevent.h>
+
 int messaging_dgm_init(struct tevent_context *ev,
 		       uint64_t unique,
 		       const char *socket_dir,
-- 
1.9.1


From 1f73df278e228cd8771453701d81ec721b15a3f8 Mon Sep 17 00:00:00 2001
From: Volker Lendecke <vl at samba.org>
Date: Sat, 4 Oct 2014 11:11:46 +0200
Subject: [PATCH 06/16] messages_dgm: Make it an independent lib

Signed-off-by: Volker Lendecke <vl at samba.org>
---
 source3/wscript_build | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/source3/wscript_build b/source3/wscript_build
index a6ef584..8fcd0d2 100755
--- a/source3/wscript_build
+++ b/source3/wscript_build
@@ -308,9 +308,13 @@ bld.SAMBA3_SUBSYSTEM('TDB_LIB',
                      lib/g_lock.c''',
                      deps='dbwrap samba-cluster-support')
 
+bld.SAMBA3_LIBRARY('messages_dgm',
+                   source='''lib/messages_dgm.c''',
+                   deps='talloc UNIX_MSG POLL_FUNCS_TEVENT samba-debug',
+                   private_library=True)
+
 bld.SAMBA3_SUBSYSTEM('samba3core',
                    source='''lib/messages.c
-                   lib/messages_dgm.c
                    lib/util_cluster.c
                    lib/id_cache.c
                    lib/talloc_dict.c
@@ -358,6 +362,7 @@ bld.SAMBA3_SUBSYSTEM('samba3core',
                         samba3-util
                         errors3
                         server_id_db
+                        messages_dgm
                         TDB_LIB''')
 
 bld.SAMBA3_LIBRARY('smbd_shim',
-- 
1.9.1


From 52ad5c2aba7344513efe8cf5a3f0ee3d8ba8d36f Mon Sep 17 00:00:00 2001
From: Volker Lendecke <vl at samba.org>
Date: Sat, 4 Oct 2014 11:15:12 +0200
Subject: [PATCH 07/16] lib: Add messages_dgm_ref.[ch]

We only have one messaging_dgm context per process. But we will use this from
two completely independent messaging subsystems which are independently
initialized. We need to coordinate creation and destruction, do this via
talloc.

I know this looks like a step back, but when in the future we have really just
one messaging subsystem, this can go again. My immediate goal is to make
source3 and source4 transport-compatible, and this looks like a quick way
towards that goal.

Signed-off-by: Volker Lendecke <vl at samba.org>
---
 source3/lib/messages_dgm_ref.c | 121 +++++++++++++++++++++++++++++++++++++++++
 source3/lib/messages_dgm_ref.h |  37 +++++++++++++
 source3/wscript_build          |   2 +-
 3 files changed, 159 insertions(+), 1 deletion(-)
 create mode 100644 source3/lib/messages_dgm_ref.c
 create mode 100644 source3/lib/messages_dgm_ref.h

diff --git a/source3/lib/messages_dgm_ref.c b/source3/lib/messages_dgm_ref.c
new file mode 100644
index 0000000..32b9c98
--- /dev/null
+++ b/source3/lib/messages_dgm_ref.c
@@ -0,0 +1,121 @@
+/*
+ * Unix SMB/CIFS implementation.
+ * Samba internal messaging functions
+ * Copyright (C) 2014 by Volker Lendecke
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <talloc.h>
+#include "replace.h"
+#include "messages_dgm.h"
+#include "messages_dgm_ref.h"
+#include "lib/util/debug.h"
+#include "lib/util/dlinklist.h"
+
+struct msg_dgm_ref {
+	struct msg_dgm_ref *prev, *next;
+	void (*recv_cb)(const uint8_t *msg, size_t msg_len,
+			int *fds, size_t num_fds, void *private_data);
+	void *recv_cb_private_data;
+};
+
+static pid_t dgm_pid = 0;
+static struct msg_dgm_ref *refs = NULL;
+
+static int msg_dgm_ref_destructor(struct msg_dgm_ref *r);
+static void msg_dgm_ref_recv(const uint8_t *msg, size_t msg_len,
+			     int *fds, size_t num_fds, void *private_data);
+
+void *messaging_dgm_ref(TALLOC_CTX *mem_ctx, struct tevent_context *ev,
+			uint64_t unique,
+			const char *socket_dir,
+			const char *lockfile_dir,
+			void (*recv_cb)(const uint8_t *msg, size_t msg_len,
+					int *fds, size_t num_fds,
+					void *private_data),
+			void *recv_cb_private_data,
+			int *err)
+{
+	struct msg_dgm_ref *result, *tmp_refs;
+
+	result = talloc(mem_ctx, struct msg_dgm_ref);
+	if (result == NULL) {
+		*err = ENOMEM;
+		return NULL;
+	}
+
+	tmp_refs = refs;
+
+	if ((refs != NULL) && (dgm_pid != getpid())) {
+		/*
+		 * Have to reinit after fork
+		 */
+		messaging_dgm_destroy();
+		refs = NULL;
+	}
+
+	if (refs == NULL) {
+		int ret;
+
+		ret = messaging_dgm_init(ev, unique, socket_dir, lockfile_dir,
+					 msg_dgm_ref_recv, NULL);
+		if (ret != 0) {
+			DEBUG(10, ("messaging_dgm_init failed: %s\n",
+				   strerror(ret)));
+			TALLOC_FREE(result);
+			*err = ret;
+			return NULL;
+		}
+		dgm_pid = getpid();
+	}
+
+	refs = tmp_refs;
+
+	result->recv_cb = recv_cb;
+	result->recv_cb_private_data = recv_cb_private_data;
+	DLIST_ADD(refs, result);
+	talloc_set_destructor(result, msg_dgm_ref_destructor);
+
+	return result;
+}
+
+static void msg_dgm_ref_recv(const uint8_t *msg, size_t msg_len,
+			     int *fds, size_t num_fds, void *private_data)
+{
+	struct msg_dgm_ref *r, *next;
+
+	/*
+	 * We have to broadcast incoming messages to all refs. The first ref
+	 * that grabs the fd's will get them.
+	 */
+	for (r = refs; r != NULL; r = next) {
+		next = r->next;
+		r->recv_cb(msg, msg_len, fds, num_fds,
+			   r->recv_cb_private_data);
+	}
+}
+
+static int msg_dgm_ref_destructor(struct msg_dgm_ref *r)
+{
+	if (refs == NULL) {
+		abort();
+	}
+	DLIST_REMOVE(refs, r);
+
+	if (refs == NULL) {
+		messaging_dgm_destroy();
+	}
+	return 0;
+}
diff --git a/source3/lib/messages_dgm_ref.h b/source3/lib/messages_dgm_ref.h
new file mode 100644
index 0000000..3df0c06
--- /dev/null
+++ b/source3/lib/messages_dgm_ref.h
@@ -0,0 +1,37 @@
+/*
+ * Unix SMB/CIFS implementation.
+ * Samba internal messaging functions
+ * Copyright (C) 2014 by Volker Lendecke
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef _MESSAGES_DGM_REF_H_
+#define _MESSAGES_DGM_REF_H_
+
+#include <talloc.h>
+#include <tevent.h>
+#include "replace.h"
+
+void *messaging_dgm_ref(TALLOC_CTX *mem_ctx, struct tevent_context *ev,
+			uint64_t unique,
+			const char *socket_dir,
+			const char *lockfile_dir,
+			void (*recv_cb)(const uint8_t *msg, size_t msg_len,
+					int *fds, size_t num_fds,
+					void *private_data),
+			void *recv_cb_private_data,
+			int *err);
+
+#endif
diff --git a/source3/wscript_build b/source3/wscript_build
index 8fcd0d2..cb17ab4 100755
--- a/source3/wscript_build
+++ b/source3/wscript_build
@@ -309,7 +309,7 @@ bld.SAMBA3_SUBSYSTEM('TDB_LIB',
                      deps='dbwrap samba-cluster-support')
 
 bld.SAMBA3_LIBRARY('messages_dgm',
-                   source='''lib/messages_dgm.c''',
+                   source='''lib/messages_dgm.c lib/messages_dgm_ref.c''',
                    deps='talloc UNIX_MSG POLL_FUNCS_TEVENT samba-debug',
                    private_library=True)
 
-- 
1.9.1


From 72f5f9cb50accdfc0dcaa10365473d85c27d1f27 Mon Sep 17 00:00:00 2001
From: Volker Lendecke <vl at samba.org>
Date: Sat, 4 Oct 2014 11:21:18 +0200
Subject: [PATCH 08/16] messaging3: Use messaging_dgm_ref

Signed-off-by: Volker Lendecke <vl at samba.org>
---
 source3/lib/messages.c | 26 +++++++++++++++-----------
 1 file changed, 15 insertions(+), 11 deletions(-)

diff --git a/source3/lib/messages.c b/source3/lib/messages.c
index cdd6b05..454906a 100644
--- a/source3/lib/messages.c
+++ b/source3/lib/messages.c
@@ -54,6 +54,7 @@
 #include "lib/messages_dgm.h"
 #include "lib/iov_buf.h"
 #include "lib/util/server_id_db.h"
+#include "lib/messages_dgm_ref.h"
 
 struct messaging_callback {
 	struct messaging_callback *prev, *next;
@@ -75,6 +76,7 @@ struct messaging_context {
 	struct tevent_req **waiters;
 	unsigned num_waiters;
 
+	void *msg_dgm_ref;
 	struct messaging_backend *remote;
 
 	struct server_id_db *names_db;
@@ -341,12 +343,12 @@ struct messaging_context *messaging_init(TALLOC_CTX *mem_ctx,
 		return NULL;
 	}
 
-	ret = messaging_dgm_init(ctx->event_ctx, ctx->id.unique_id,
-				 priv_path, lck_path,
-				 messaging_recv_cb, ctx);
+	ctx->msg_dgm_ref = messaging_dgm_ref(
+		ctx, ctx->event_ctx, ctx->id.unique_id,
+		priv_path, lck_path, messaging_recv_cb, ctx, &ret);
 
-	if (ret != 0) {
-		DEBUG(2, ("messaging_dgm_init failed: %s\n", strerror(ret)));
+	if (ctx->msg_dgm_ref == NULL) {
+		DEBUG(2, ("messaging_dgm_ref failed: %s\n", strerror(ret)));
 		TALLOC_FREE(ctx);
 		return NULL;
 	}
@@ -398,15 +400,17 @@ NTSTATUS messaging_reinit(struct messaging_context *msg_ctx)
 	NTSTATUS status;
 	int ret;
 
-	messaging_dgm_destroy();
+	TALLOC_FREE(msg_ctx->msg_dgm_ref);
 
 	msg_ctx->id = procid_self();
 
-	ret = messaging_dgm_init(msg_ctx->event_ctx, msg_ctx->id.unique_id,
-				 private_path("sock"), lock_path("msg"),
-				 messaging_recv_cb, msg_ctx);
-	if (ret != 0) {
-		DEBUG(0, ("messaging_dgm_init failed: %s\n", strerror(errno)));
+	msg_ctx->msg_dgm_ref = messaging_dgm_ref(
+		msg_ctx, msg_ctx->event_ctx, msg_ctx->id.unique_id,
+		private_path("sock"), lock_path("msg"),
+		messaging_recv_cb, msg_ctx, &ret);
+
+	if (msg_ctx->msg_dgm_ref == NULL) {
+		DEBUG(2, ("messaging_dgm_ref failed: %s\n", strerror(ret)));
 		return map_nt_error_from_unix(ret);
 	}
 
-- 
1.9.1


From 36d5c197b92280dabd06625edefb541dd0f8a492 Mon Sep 17 00:00:00 2001
From: Volker Lendecke <vl at samba.org>
Date: Fri, 10 Oct 2014 08:35:08 +0200
Subject: [PATCH 09/16] ctdb: server_id_get->server_id_fetch

server_id_get with the next patch will be a global parsing function.
I've decided to rename this here in ctdb, as it's only a static function
in ctdb_client.c and apparently not intended for wider use. Please speak
up if you don't like this :-)

Signed-off-by: Volker Lendecke <vl at samba.org>
---
 ctdb/client/ctdb_client.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/ctdb/client/ctdb_client.c b/ctdb/client/ctdb_client.c
index da18826..533f36f 100644
--- a/ctdb/client/ctdb_client.c
+++ b/ctdb/client/ctdb_client.c
@@ -3807,7 +3807,7 @@ struct server_id {
 	uint64_t unique_id;
 };
 
-static struct server_id server_id_get(struct ctdb_context *ctdb, uint32_t reqid)
+static struct server_id server_id_fetch(struct ctdb_context *ctdb, uint32_t reqid)
 {
 	struct server_id id;
 
@@ -3957,7 +3957,7 @@ again:
 
 	talloc_free(data.dptr);
 
-	id = server_id_get(ctdb_db->ctdb, reqid);
+	id = server_id_fetch(ctdb_db->ctdb, reqid);
 
 	i = 0;
 	while (i < locks->num) {
@@ -4046,7 +4046,7 @@ static bool g_lock_unlock(TALLOC_CTX *mem_ctx,
 
 	talloc_free(data.dptr);
 
-	id = server_id_get(ctdb_db->ctdb, reqid);
+	id = server_id_fetch(ctdb_db->ctdb, reqid);
 
 	for (i=0; i<locks->num; i++) {
 		if (ctdb_server_id_equal(&locks->lock[i].id, &id)) {
-- 
1.9.1


From 3090d08592d9b70941ad8fc550486535dd5dddac Mon Sep 17 00:00:00 2001
From: Volker Lendecke <vl at samba.org>
Date: Tue, 16 Sep 2014 02:11:19 +0200
Subject: [PATCH 10/16] lib: Add server_id marshalling

Will be used soon to make source3 and source4 messaging-protocol
compatible.

Signed-off-by: Volker Lendecke <vl at samba.org>
---
 lib/util/samba_util.h |  3 +++
 lib/util/server_id.c  | 16 ++++++++++++++++
 2 files changed, 19 insertions(+)

diff --git a/lib/util/samba_util.h b/lib/util/samba_util.h
index 1c7ae79..7adcdba 100644
--- a/lib/util/samba_util.h
+++ b/lib/util/samba_util.h
@@ -899,6 +899,9 @@ void server_id_set_disconnected(struct server_id *id);
  */
 bool server_id_is_disconnected(const struct server_id *id);
 
+void server_id_put(uint8_t buf[24], const struct server_id id);
+void server_id_get(struct server_id *id, const uint8_t buf[24]);
+
 /*
  * Samba code should use samba_tevent_context_init() instead of
  * tevent_context_init() in order to get the debug output.
diff --git a/lib/util/server_id.c b/lib/util/server_id.c
index 7d3de2f..308ee2a 100644
--- a/lib/util/server_id.c
+++ b/lib/util/server_id.c
@@ -150,3 +150,19 @@ bool server_id_is_disconnected(const struct server_id *id)
 
 	return server_id_equal(id, &dis);
 }
+
+void server_id_put(uint8_t buf[24], const struct server_id id)
+{
+	SBVAL(buf, 0,  id.pid);
+	SIVAL(buf, 8,  id.task_id);
+	SIVAL(buf, 12, id.vnn);
+	SBVAL(buf, 16, id.unique_id);
+}
+
+void server_id_get(struct server_id *id, const uint8_t buf[24])
+{
+	id->pid       = BVAL(buf, 0);
+	id->task_id   = IVAL(buf, 8);
+	id->vnn       = IVAL(buf, 12);
+	id->unique_id = BVAL(buf, 16);
+}
-- 
1.9.1


From c30c3f503d9589653c844870a13872df8764e9d5 Mon Sep 17 00:00:00 2001
From: Volker Lendecke <vl at samba.org>
Date: Tue, 16 Sep 2014 14:09:35 +0200
Subject: [PATCH 11/16] messaging: Define a binary format for message headers

Signed-off-by: Volker Lendecke <vl at samba.org>
---
 source3/lib/messages_util.c | 41 +++++++++++++++++++++++++++++++++++++++++
 source3/lib/messages_util.h | 33 +++++++++++++++++++++++++++++++++
 source3/wscript_build       |  5 +++++
 3 files changed, 79 insertions(+)
 create mode 100644 source3/lib/messages_util.c
 create mode 100644 source3/lib/messages_util.h

diff --git a/source3/lib/messages_util.c b/source3/lib/messages_util.c
new file mode 100644
index 0000000..24c364c
--- /dev/null
+++ b/source3/lib/messages_util.c
@@ -0,0 +1,41 @@
+/*
+ * Unix SMB/CIFS implementation.
+ * Samba internal messaging functions
+ * Copyright (C) 2013 by Volker Lendecke
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "replace.h"
+#include "lib/util/samba_util.h"
+#include "librpc/gen_ndr/server_id.h"
+#include "lib/util/byteorder.h"
+#include "messages_util.h"
+
+void message_hdr_put(uint8_t buf[MESSAGE_HDR_LENGTH], uint32_t msg_type,
+		     struct server_id src, struct server_id dst)
+{
+	server_id_put(buf, dst);
+	server_id_put(buf + 24, src);
+	SIVAL(buf, 48, msg_type);
+}
+
+void message_hdr_get(uint32_t *msg_type, struct server_id *src,
+		     struct server_id *dst,
+		     const uint8_t buf[MESSAGE_HDR_LENGTH])
+{
+	server_id_get(dst, buf);
+	server_id_get(src, buf + 24);
+	*msg_type = IVAL(buf, 48);
+}
diff --git a/source3/lib/messages_util.h b/source3/lib/messages_util.h
new file mode 100644
index 0000000..5b22f5e
--- /dev/null
+++ b/source3/lib/messages_util.h
@@ -0,0 +1,33 @@
+/*
+ * Unix SMB/CIFS implementation.
+ * Samba internal messaging functions
+ * Copyright (C) 2013 by Volker Lendecke
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef _MESSAGES_UTIL_H_
+#define _MESSAGES_UTIL_H_
+
+struct message_hdr;
+
+#define MESSAGE_HDR_LENGTH 52
+
+void message_hdr_put(uint8_t buf[MESSAGE_HDR_LENGTH], uint32_t msg_type,
+		     struct server_id src, struct server_id dst);
+void message_hdr_get(uint32_t *msg_type, struct server_id *src,
+		     struct server_id *dst,
+		     const uint8_t buf[MESSAGE_HDR_LENGTH]);
+
+#endif
diff --git a/source3/wscript_build b/source3/wscript_build
index cb17ab4..ce8ee13 100755
--- a/source3/wscript_build
+++ b/source3/wscript_build
@@ -313,6 +313,11 @@ bld.SAMBA3_LIBRARY('messages_dgm',
                    deps='talloc UNIX_MSG POLL_FUNCS_TEVENT samba-debug',
                    private_library=True)
 
+bld.SAMBA3_LIBRARY('messages_util',
+                   source='''lib/messages_util.c''',
+                   deps='samba-util',
+                   private_library=True)
+
 bld.SAMBA3_SUBSYSTEM('samba3core',
                    source='''lib/messages.c
                    lib/util_cluster.c
-- 
1.9.1


From 5d65df72ee93ddf3b73975ffaef933836c1c33ca Mon Sep 17 00:00:00 2001
From: Volker Lendecke <vl at samba.org>
Date: Wed, 11 Feb 2015 15:28:55 +0000
Subject: [PATCH 12/16] messaging3: Use message_hdr_[put|get]

Signed-off-by: Volker Lendecke <vl at samba.org>
---
 source3/lib/messages.c | 48 ++++++++++++++++--------------------------------
 source3/wscript_build  |  1 +
 2 files changed, 17 insertions(+), 32 deletions(-)

diff --git a/source3/lib/messages.c b/source3/lib/messages.c
index 454906a..1f085e0 100644
--- a/source3/lib/messages.c
+++ b/source3/lib/messages.c
@@ -55,6 +55,7 @@
 #include "lib/iov_buf.h"
 #include "lib/util/server_id_db.h"
 #include "lib/messages_dgm_ref.h"
+#include "lib/messages_util.h"
 
 struct messaging_callback {
 	struct messaging_callback *prev, *next;
@@ -82,12 +83,6 @@ struct messaging_context {
 	struct server_id_db *names_db;
 };
 
-struct messaging_hdr {
-	uint32_t msg_type;
-	struct server_id dst;
-	struct server_id src;
-};
-
 /****************************************************************************
  A useful function for testing the message system.
 ****************************************************************************/
@@ -215,13 +210,13 @@ static void messaging_recv_cb(const uint8_t *msg, size_t msg_len,
 {
 	struct messaging_context *msg_ctx = talloc_get_type_abort(
 		private_data, struct messaging_context);
-	const struct messaging_hdr *hdr;
+	uint8_t hdr[MESSAGE_HDR_LENGTH];
 	struct server_id_buf idbuf;
 	struct messaging_rec rec;
 	int64_t fds64[MIN(num_fds, INT8_MAX)];
 	size_t i;
 
-	if (msg_len < sizeof(*hdr)) {
+	if (msg_len < sizeof(hdr)) {
 		for (i=0; i < num_fds; i++) {
 			close(fds[i]);
 		}
@@ -246,28 +241,22 @@ static void messaging_recv_cb(const uint8_t *msg, size_t msg_len,
 		fds[i] = -1;
 	}
 
-	/*
-	 * messages_dgm guarantees alignment, so we can cast here
-	 */
-	hdr = (const struct messaging_hdr *)msg;
-
-	DEBUG(10, ("%s: Received message 0x%x len %u (num_fds:%u) from %s\n",
-		   __func__, (unsigned)hdr->msg_type,
-		   (unsigned)(msg_len - sizeof(*hdr)),
-		   (unsigned)num_fds,
-		   server_id_str_buf(hdr->src, &idbuf)));
-
 	rec = (struct messaging_rec) {
 		.msg_version = MESSAGE_VERSION,
-		.msg_type = hdr->msg_type,
-		.src = hdr->src,
-		.dest = hdr->dst,
-		.buf.data = discard_const_p(uint8, msg) + sizeof(*hdr),
-		.buf.length = msg_len - sizeof(*hdr),
+		.buf.data = discard_const_p(uint8, msg) + sizeof(hdr),
+		.buf.length = msg_len - sizeof(hdr),
 		.num_fds = num_fds,
 		.fds = fds64,
 	};
 
+	message_hdr_get(&rec.msg_type, &rec.src, &rec.dest, msg);
+
+	DEBUG(10, ("%s: Received message 0x%x len %u (num_fds:%u) from %s\n",
+		   __func__, (unsigned)rec.msg_type,
+		   (unsigned)rec.buf.length,
+		   (unsigned)num_fds,
+		   server_id_str_buf(rec.src, &idbuf)));
+
 	messaging_dispatch_rec(msg_ctx, &rec);
 }
 
@@ -534,7 +523,7 @@ NTSTATUS messaging_send_iov_from(struct messaging_context *msg_ctx,
 				 const int *fds, size_t num_fds)
 {
 	int ret;
-	struct messaging_hdr hdr;
+	uint8_t hdr[MESSAGE_HDR_LENGTH];
 	struct iovec iov2[iovlen+1];
 
 	if (server_id_is_disconnected(&dst)) {
@@ -560,13 +549,8 @@ NTSTATUS messaging_send_iov_from(struct messaging_context *msg_ctx,
 		return NT_STATUS_OK;
 	}
 
-	ZERO_STRUCT(hdr);
-	hdr = (struct messaging_hdr) {
-		.msg_type = msg_type,
-		.dst = dst,
-		.src = src
-	};
-	iov2[0] = (struct iovec){ .iov_base = &hdr, .iov_len = sizeof(hdr) };
+	message_hdr_put(hdr, msg_type, src, dst);
+	iov2[0] = (struct iovec){ .iov_base = hdr, .iov_len = sizeof(hdr) };
 	memcpy(&iov2[1], iov, iovlen * sizeof(*iov));
 
 	become_root();
diff --git a/source3/wscript_build b/source3/wscript_build
index ce8ee13..151e68b 100755
--- a/source3/wscript_build
+++ b/source3/wscript_build
@@ -367,6 +367,7 @@ bld.SAMBA3_SUBSYSTEM('samba3core',
                         samba3-util
                         errors3
                         server_id_db
+                        messages_util
                         messages_dgm
                         TDB_LIB''')
 
-- 
1.9.1


From 3815ba131f5fe321fc6c72df4123a2ce72777bf8 Mon Sep 17 00:00:00 2001
From: Volker Lendecke <vl at samba.org>
Date: Sun, 8 Feb 2015 15:33:39 +0100
Subject: [PATCH 13/16] messaging4: Use messages_dgm

This replaces the transport mechanism in source4 with calls to the
messages_dgm code. It is supposed to enable "smbcontrol samba pool-usage"
as an example without having to rewrite smbcontrol using the source4
based messaging subsystem.

This moves the source3 based names.tdb (which is unused so far) to the
lock directory, source4 does not have a cache directory.

Signed-off-by: Volker Lendecke <vl at samba.org>

msg4
---
 source3/lib/messages.c              |   2 +-
 source4/lib/messaging/messaging.c   | 442 +++++++++---------------------------
 source4/lib/messaging/wscript_build |   2 +-
 3 files changed, 108 insertions(+), 338 deletions(-)

diff --git a/source3/lib/messages.c b/source3/lib/messages.c
index 1f085e0..7df7cdb 100644
--- a/source3/lib/messages.c
+++ b/source3/lib/messages.c
@@ -343,7 +343,7 @@ struct messaging_context *messaging_init(TALLOC_CTX *mem_ctx,
 	}
 
 	ctx->names_db = server_id_db_init(
-		ctx, ctx->id, lp_cache_directory(), 0,
+		ctx, ctx->id, lp_lock_directory(), 0,
 		TDB_INCOMPATIBLE_HASH|TDB_CLEAR_IF_FIRST);
 	if (ctx->names_db == NULL) {
 		DEBUG(10, ("%s: server_id_db_init failed\n", __func__));
diff --git a/source4/lib/messaging/messaging.c b/source4/lib/messaging/messaging.c
index 0b4e109..cad2d64 100644
--- a/source4/lib/messaging/messaging.c
+++ b/source4/lib/messaging/messaging.c
@@ -33,6 +33,9 @@
 #include "../lib/util/tevent_ntstatus.h"
 #include "lib/param/param.h"
 #include "lib/util/server_id_db.h"
+#include "../source3/lib/messages_dgm.h"
+#include "../source3/lib/messages_dgm_ref.h"
+#include "../source3/lib/messages_util.h"
 #include <tdb.h>
 
 /* change the message version with any incompatible changes in the protocol */
@@ -51,10 +54,10 @@ struct irpc_request {
 };
 
 struct imessaging_context {
+	struct imessaging_context *prev, *next;
 	struct server_id server_id;
-	struct socket_context *sock;
-	const char *base_path;
-	const char *path;
+	const char *sock_dir;
+	const char *lock_dir;
 	struct dispatch_fn **dispatch;
 	uint32_t num_types;
 	struct idr_context *dispatch_tree;
@@ -64,10 +67,7 @@ struct imessaging_context {
 	struct idr_context *idr;
 	struct server_id_db *names;
 	struct timeval start_time;
-	struct tevent_timer *retry_te;
-	struct {
-		struct tevent_fd *fde;
-	} event;
+	void *msg_dgm_ref;
 };
 
 /* we have a linked list of dispatch handlers for each msg_type that
@@ -126,248 +126,20 @@ static NTSTATUS irpc_uptime(struct irpc_message *msg,
 	return NT_STATUS_OK;
 }
 
-/*
-   return the path to a messaging socket
-*/
-static char *imessaging_path(struct imessaging_context *msg, struct server_id server_id)
-{
-	struct server_id_buf buf;
-
-	return talloc_asprintf(msg, "%s/msg.%s", msg->base_path,
-			       server_id_str_buf(server_id, &buf));
-}
-
-/*
-  dispatch a fully received message
-
-  note that this deliberately can match more than one message handler
-  per message. That allows a single messasging context to register
-  (for example) a debug handler for more than one piece of code
-*/
-static void imessaging_dispatch(struct imessaging_context *msg, struct imessaging_rec *rec)
+static struct dispatch_fn *imessaging_find_dispatch(
+	struct imessaging_context *msg, uint32_t msg_type)
 {
-	struct dispatch_fn *d, *next;
-
 	/* temporary IDs use an idtree, the rest use a array of pointers */
-	if (rec->header->msg_type >= MSG_TMP_BASE) {
-		d = (struct dispatch_fn *)idr_find(msg->dispatch_tree,
-						   rec->header->msg_type);
-	} else if (rec->header->msg_type < msg->num_types) {
-		d = msg->dispatch[rec->header->msg_type];
-	} else {
-		d = NULL;
-	}
-
-	for (; d; d = next) {
-		DATA_BLOB data;
-		next = d->next;
-		data.data = rec->packet.data + sizeof(*rec->header);
-		data.length = rec->header->length;
-		d->fn(msg, d->private_data, d->msg_type, rec->header->from, &data);
-	}
-	rec->header->length = 0;
-}
-
-/*
-  handler for messages that arrive from other nodes in the cluster
-*/
-static void cluster_message_handler(struct imessaging_context *msg, DATA_BLOB packet)
-{
-	struct imessaging_rec *rec;
-
-	rec = talloc(msg, struct imessaging_rec);
-	if (rec == NULL) {
-		smb_panic("Unable to allocate imessaging_rec");
-	}
-
-	rec->msg           = msg;
-	rec->path          = msg->path;
-	rec->header        = (struct imessaging_header *)packet.data;
-	rec->packet        = packet;
-	rec->retries       = 0;
-
-	if (packet.length != sizeof(*rec->header) + rec->header->length) {
-		DEBUG(0,("messaging: bad message header size %d should be %d\n",
-			 rec->header->length, (int)(packet.length - sizeof(*rec->header))));
-		talloc_free(rec);
-		return;
-	}
-
-	imessaging_dispatch(msg, rec);
-	talloc_free(rec);
-}
-
-
-
-/*
-  try to send the message
-*/
-static NTSTATUS try_send(struct imessaging_rec *rec)
-{
-	struct imessaging_context *msg = rec->msg;
-	size_t nsent;
-	void *priv;
-	NTSTATUS status;
-	struct socket_address *path;
-
-	/* rec->path is the path of the *other* socket, where we want
-	 * this to end up */
-	path = socket_address_from_strings(msg, msg->sock->backend_name,
-					   rec->path, 0);
-	if (!path) {
-		return NT_STATUS_NO_MEMORY;
-	}
-
-	/* we send with privileges so messages work from any context */
-	priv = root_privileges();
-	status = socket_sendto(msg->sock, &rec->packet, &nsent, path);
-	talloc_free(path);
-	talloc_free(priv);
-
-	return status;
-}
-
-/*
-  retry backed off messages
-*/
-static void msg_retry_timer(struct tevent_context *ev, struct tevent_timer *te,
-			    struct timeval t, void *private_data)
-{
-	struct imessaging_context *msg = talloc_get_type(private_data,
-							struct imessaging_context);
-	msg->retry_te = NULL;
-
-	/* put the messages back on the main queue */
-	while (msg->retry_queue) {
-		struct imessaging_rec *rec = msg->retry_queue;
-		DLIST_REMOVE(msg->retry_queue, rec);
-		DLIST_ADD_END(msg->pending, rec, struct imessaging_rec *);
-	}
-
-	TEVENT_FD_WRITEABLE(msg->event.fde);
-}
-
-/*
-  handle a socket write event
-*/
-static void imessaging_send_handler(struct imessaging_context *msg, struct tevent_context *ev)
-{
-	while (msg->pending) {
-		struct imessaging_rec *rec = msg->pending;
-		NTSTATUS status;
-		status = try_send(rec);
-		if (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) {
-			rec->retries++;
-			if (rec->retries > 3) {
-				/* we're getting continuous write errors -
-				   backoff this record */
-				DLIST_REMOVE(msg->pending, rec);
-				DLIST_ADD_END(msg->retry_queue, rec,
-					      struct imessaging_rec *);
-				if (msg->retry_te == NULL) {
-					msg->retry_te =
-						tevent_add_timer(ev, msg,
-								 timeval_current_ofs(1, 0),
-								 msg_retry_timer, msg);
-				}
-			}
-			break;
-		}
-		rec->retries = 0;
-		if (!NT_STATUS_IS_OK(status)) {
-			TALLOC_CTX *tmp_ctx = talloc_new(msg);
-			DEBUG(1,("messaging: Lost message from %s to %s of type %u - %s\n",
-				 server_id_str(tmp_ctx, &rec->header->from),
-				 server_id_str(tmp_ctx, &rec->header->to),
-				 rec->header->msg_type,
-				 nt_errstr(status)));
-			talloc_free(tmp_ctx);
-		}
-		DLIST_REMOVE(msg->pending, rec);
-		talloc_free(rec);
-	}
-	if (msg->pending == NULL) {
-		TEVENT_FD_NOT_WRITEABLE(msg->event.fde);
-	}
-}
-
-/*
-  handle a new incoming packet
-*/
-static void imessaging_recv_handler(struct imessaging_context *msg, struct tevent_context *ev)
-{
-	struct imessaging_rec *rec;
-	NTSTATUS status;
-	DATA_BLOB packet;
-	size_t msize;
-
-	/* see how many bytes are in the next packet */
-	status = socket_pending(msg->sock, &msize);
-	if (!NT_STATUS_IS_OK(status)) {
-		DEBUG(0,("socket_pending failed in messaging - %s\n",
-			 nt_errstr(status)));
-		return;
-	}
-
-	packet = data_blob_talloc(msg, NULL, msize);
-	if (packet.data == NULL) {
-		/* assume this is temporary and retry */
-		return;
-	}
-
-	status = socket_recv(msg->sock, packet.data, msize, &msize);
-	if (!NT_STATUS_IS_OK(status)) {
-		data_blob_free(&packet);
-		return;
-	}
-
-	if (msize < sizeof(*rec->header)) {
-		DEBUG(0,("messaging: bad message of size %d\n", (int)msize));
-		data_blob_free(&packet);
-		return;
-	}
-
-	rec = talloc(msg, struct imessaging_rec);
-	if (rec == NULL) {
-		smb_panic("Unable to allocate imessaging_rec");
-	}
-
-	talloc_steal(rec, packet.data);
-	rec->msg           = msg;
-	rec->path          = msg->path;
-	rec->header        = (struct imessaging_header *)packet.data;
-	rec->packet        = packet;
-	rec->retries       = 0;
-
-	if (msize != sizeof(*rec->header) + rec->header->length) {
-		DEBUG(0,("messaging: bad message header size %d should be %d\n",
-			 rec->header->length, (int)(msize - sizeof(*rec->header))));
-		talloc_free(rec);
-		return;
-	}
-
-	imessaging_dispatch(msg, rec);
-	talloc_free(rec);
-}
-
-
-/*
-  handle a socket event
-*/
-static void imessaging_handler(struct tevent_context *ev, struct tevent_fd *fde,
-			      uint16_t flags, void *private_data)
-{
-	struct imessaging_context *msg = talloc_get_type(private_data,
-							struct imessaging_context);
-	if (flags & TEVENT_FD_WRITE) {
-		imessaging_send_handler(msg, ev);
+	if (msg_type >= MSG_TMP_BASE) {
+		return (struct dispatch_fn *)idr_find(msg->dispatch_tree,
+						      msg_type);
 	}
-	if (flags & TEVENT_FD_READ) {
-		imessaging_recv_handler(msg, ev);
+	if (msg_type < msg->num_types) {
+		return msg->dispatch[msg_type];
 	}
+	return NULL;
 }
 
-
 /*
   Register a dispatch function for a particular message type.
 */
@@ -458,64 +230,40 @@ void imessaging_deregister(struct imessaging_context *msg, uint32_t msg_type, vo
 NTSTATUS imessaging_send(struct imessaging_context *msg, struct server_id server,
 			uint32_t msg_type, const DATA_BLOB *data)
 {
-	struct imessaging_rec *rec;
-	NTSTATUS status;
-	size_t dlength = data?data->length:0;
+	uint8_t hdr[MESSAGE_HDR_LENGTH];
+	struct iovec iov[2];
+	int num_iov, ret;
+	pid_t pid;
+	void *priv;
 
-	rec = talloc(msg, struct imessaging_rec);
-	if (rec == NULL) {
-		return NT_STATUS_NO_MEMORY;
+	if (!cluster_node_equal(&msg->server_id, &server)) {
+		/* No cluster in source4... */
+		return NT_STATUS_OK;
 	}
 
-	rec->packet = data_blob_talloc(rec, NULL, sizeof(*rec->header) + dlength);
-	if (rec->packet.data == NULL) {
-		talloc_free(rec);
-		return NT_STATUS_NO_MEMORY;
-	}
+	message_hdr_put(hdr, msg_type, msg->server_id, server);
 
-	rec->retries       = 0;
-	rec->msg              = msg;
-	rec->header           = (struct imessaging_header *)rec->packet.data;
-	/* zero padding */
-	ZERO_STRUCTP(rec->header);
-	rec->header->version  = IMESSAGING_VERSION;
-	rec->header->msg_type = msg_type;
-	rec->header->from     = msg->server_id;
-	rec->header->to       = server;
-	rec->header->length   = dlength;
-	if (dlength != 0) {
-		memcpy(rec->packet.data + sizeof(*rec->header),
-		       data->data, dlength);
-	}
+	iov[0] = (struct iovec) { .iov_base = &hdr, .iov_len = sizeof(hdr) };
+	num_iov = 1;
 
-	if (!cluster_node_equal(&msg->server_id, &server)) {
-		/* the destination is on another node - dispatch via
-		   the cluster layer */
-		status = cluster_message_send(server, &rec->packet);
-		talloc_free(rec);
-		return status;
+	if (data != NULL) {
+		iov[1] = (struct iovec) { .iov_base = data->data,
+					  .iov_len = data->length };
+		num_iov += 1;
 	}
 
-	rec->path = imessaging_path(msg, server);
-	talloc_steal(rec, rec->path);
-
-	if (msg->pending != NULL) {
-		status = STATUS_MORE_ENTRIES;
-	} else {
-		status = try_send(rec);
+	pid = server.pid;
+	if (pid == 0) {
+		pid = getpid();
 	}
 
-	if (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) {
-		if (msg->pending == NULL) {
-			TEVENT_FD_WRITEABLE(msg->event.fde);
-		}
-		DLIST_ADD_END(msg->pending, rec, struct imessaging_rec *);
-		return NT_STATUS_OK;
+	priv = root_privileges();
+	ret = messaging_dgm_send(pid, iov, num_iov, NULL, 0);
+	TALLOC_FREE(priv);
+	if (ret != 0) {
+		return map_nt_error_from_unix_common(ret);
 	}
-
-	talloc_free(rec);
-
-	return status;
+	return NT_STATUS_OK;
 }
 
 /*
@@ -541,12 +289,13 @@ int imessaging_cleanup(struct imessaging_context *msg)
 	if (!msg) {
 		return 0;
 	}
-
-	DEBUG(5,("imessaging: cleaning up %s\n", msg->path));
-	unlink(msg->path);
 	return 0;
 }
 
+static void imessaging_dgm_recv(const uint8_t *buf, size_t buf_len,
+				int *fds, size_t num_fds,
+				void *private_data);
+
 /*
   create the listening socket and setup the dispatcher
 
@@ -562,9 +311,8 @@ struct imessaging_context *imessaging_init(TALLOC_CTX *mem_ctx,
 					   bool auto_remove)
 {
 	struct imessaging_context *msg;
-	NTSTATUS status;
-	struct socket_address *path;
 	bool ok;
+	int ret;
 
 	if (ev == NULL) {
 		return NULL;
@@ -575,26 +323,31 @@ struct imessaging_context *imessaging_init(TALLOC_CTX *mem_ctx,
 		return NULL;
 	}
 
-	/* setup a handler for messages from other cluster nodes, if appropriate */
-	status = cluster_message_init(msg, server_id, cluster_message_handler);
-	if (!NT_STATUS_IS_OK(status)) {
-		goto fail;
-	}
-
 	/* create the messaging directory if needed */
 
-	msg->base_path     = lpcfg_imessaging_path(msg, lp_ctx);
-	if (msg->base_path == NULL) {
+	msg->sock_dir = lpcfg_private_path(msg, lp_ctx, "sock");
+	if (msg->sock_dir == NULL) {
+		goto fail;
+	}
+	ok = directory_create_or_exist_strict(msg->sock_dir, geteuid(), 0700);
+	if (!ok) {
 		goto fail;
 	}
 
-	ok = directory_create_or_exist_strict(msg->base_path, geteuid(), 0700);
+	msg->lock_dir = lpcfg_lock_path(msg, lp_ctx, "msg");
+	if (msg->lock_dir == NULL) {
+		goto fail;
+	}
+	ok = directory_create_or_exist_strict(msg->lock_dir, geteuid(), 0755);
 	if (!ok) {
 		goto fail;
 	}
 
-	msg->path          = imessaging_path(msg, server_id);
-	if (msg->path == NULL) {
+	msg->msg_dgm_ref = messaging_dgm_ref(
+		msg, ev, server_id.unique_id, msg->sock_dir, msg->lock_dir,
+		imessaging_dgm_recv, msg, &ret);
+
+	if (msg->msg_dgm_ref == NULL) {
 		goto fail;
 	}
 
@@ -612,41 +365,13 @@ struct imessaging_context *imessaging_init(TALLOC_CTX *mem_ctx,
 	msg->start_time    = timeval_current();
 
 	msg->names = server_id_db_init(
-		msg, server_id, msg->base_path, 0,
+		msg, server_id, msg->lock_dir, 0,
 		TDB_INCOMPATIBLE_HASH|TDB_CLEAR_IF_FIRST|
 		lpcfg_tdb_flags(lp_ctx, 0));
 	if (msg->names == NULL) {
 		goto fail;
 	}
 
-	status = socket_create("unix", SOCKET_TYPE_DGRAM, &msg->sock, 0);
-	if (!NT_STATUS_IS_OK(status)) {
-		goto fail;
-	}
-
-	/* by stealing here we ensure that the socket is cleaned up (and even
-	   deleted) on exit */
-	talloc_steal(msg, msg->sock);
-
-	path = socket_address_from_strings(msg, msg->sock->backend_name,
-					   msg->path, 0);
-	if (!path) {
-		goto fail;
-	}
-
-	status = socket_listen(msg->sock, path, 50, 0);
-	if (!NT_STATUS_IS_OK(status)) {
-		DEBUG(0,("Unable to setup messaging listener for '%s':%s\n", msg->path, nt_errstr(status)));
-		goto fail;
-	}
-
-	/* it needs to be non blocking for sends */
-	set_blocking(socket_get_fd(msg->sock), false);
-
-	msg->event.fde	= tevent_add_fd(ev, msg, socket_get_fd(msg->sock),
-				        TEVENT_FD_READ, imessaging_handler, msg);
-	tevent_fd_set_auto_close(msg->event.fde);
-
 	if (auto_remove) {
 		talloc_set_destructor(msg, imessaging_cleanup);
 	}
@@ -661,6 +386,51 @@ fail:
 	return NULL;
 }
 
+static void imessaging_dgm_recv(const uint8_t *buf, size_t buf_len,
+				int *fds, size_t num_fds,
+				void *private_data)
+{
+	struct imessaging_context *msg = talloc_get_type_abort(
+		private_data, struct imessaging_context);
+	uint32_t msg_type;
+	struct server_id src, dst;
+	struct server_id_buf srcbuf, dstbuf;
+	DATA_BLOB data;
+
+	if (buf_len < MESSAGE_HDR_LENGTH) {
+		/* Invalid message, ignore */
+		return;
+	}
+
+	message_hdr_get(&msg_type, &src, &dst, buf);
+
+	data.data = discard_const_p(uint8_t, buf + MESSAGE_HDR_LENGTH);
+	data.length = buf_len - MESSAGE_HDR_LENGTH;
+
+	if ((cluster_id_equal(&dst, &msg->server_id)) ||
+	    ((dst.task_id == 0) && (msg->server_id.pid == 0))) {
+		struct dispatch_fn *d, *next;
+
+		DEBUG(10, ("%s: dst %s matches my id: %s, type=0x%x\n",
+			   __func__,
+			   server_id_str_buf(dst, &dstbuf),
+			   server_id_str_buf(msg->server_id, &srcbuf),
+			   (unsigned)msg_type));
+
+		d = imessaging_find_dispatch(msg, msg_type);
+
+		for (; d; d = next) {
+			next = d->next;
+			d->fn(msg, d->private_data, d->msg_type, src, &data);
+		}
+	} else {
+		DEBUG(10, ("%s: Ignoring type=0x%x dst %s, I am %s, \n",
+			   __func__, (unsigned)msg_type,
+			   server_id_str_buf(dst, &dstbuf),
+			   server_id_str_buf(msg->server_id, &srcbuf)));
+	}
+}
+
 /*
    A hack, for the short term until we get 'client only' messaging in place
 */
diff --git a/source4/lib/messaging/wscript_build b/source4/lib/messaging/wscript_build
index 48c490e..efe1f79 100644
--- a/source4/lib/messaging/wscript_build
+++ b/source4/lib/messaging/wscript_build
@@ -3,7 +3,7 @@
 
 bld.SAMBA_LIBRARY('MESSAGING',
 	source='messaging.c',
-	public_deps='samba-util NDR_IRPC UNIX_PRIVS cluster ndr samba_socket dcerpc server_id_db',
+	public_deps='samba-util NDR_IRPC UNIX_PRIVS cluster ndr dcerpc messages_util server_id_db',
 	private_library=True
 	)
 
-- 
1.9.1


From 5f883889e1334880388bd6d32157d659ea4cc625 Mon Sep 17 00:00:00 2001
From: Volker Lendecke <vl at samba.org>
Date: Wed, 11 Feb 2015 12:19:05 +0000
Subject: [PATCH 14/16] lib: Add talloc_report_str()

This creates a talloc report into a string and will replace the code used in
source3/lib/tallocmsg.c

Signed-off-by: Volker Lendecke <vl at samba.org>
---
 lib/util/talloc_report.c | 174 +++++++++++++++++++++++++++++++++++++++++++++++
 lib/util/talloc_report.h |  27 ++++++++
 lib/util/wscript_build   |   7 ++
 3 files changed, 208 insertions(+)
 create mode 100644 lib/util/talloc_report.c
 create mode 100644 lib/util/talloc_report.h

diff --git a/lib/util/talloc_report.c b/lib/util/talloc_report.c
new file mode 100644
index 0000000..8d7d548
--- /dev/null
+++ b/lib/util/talloc_report.c
@@ -0,0 +1,174 @@
+/*
+ * talloc_report into a string
+ *
+ * Copyright Volker Lendecke <vl at samba.org> 2015
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "replace.h"
+#include "talloc_report.h"
+
+/*
+ * talloc_vasprintf into a buffer that doubles its size. The real string
+ * length is maintained in "pstr_len".
+ */
+
+static char *talloc_vasprintf_append_largebuf(char *buf, ssize_t *pstr_len,
+					      const char *fmt, va_list ap)
+{
+	ssize_t str_len = *pstr_len;
+	size_t buflen, needed, space;
+	char *start, *tmpbuf;
+	va_list ap2;
+	int printlen;
+
+	if (str_len == -1) {
+		return NULL;
+	}
+	if (buf == NULL) {
+		return NULL;
+	}
+	buflen = talloc_get_size(buf);
+
+	if (buflen > str_len) {
+		start = buf + str_len;
+		space = buflen - str_len;
+	} else {
+		start = NULL;
+		space = 0;
+	}
+
+	va_copy(ap2, ap);
+	printlen = vsnprintf(start, space, fmt, ap2);
+	va_end(ap2);
+
+	if (printlen < 0) {
+		goto fail;
+	}
+
+	needed = str_len + printlen + 1;
+
+	if (needed > buflen) {
+		buflen = MAX(128, buflen);
+
+		while (buflen < needed) {
+			buflen *= 2;
+		}
+
+		tmpbuf = talloc_realloc(NULL, buf, char, buflen);
+		if (tmpbuf == NULL) {
+			goto fail;
+		}
+		buf = tmpbuf;
+
+		va_copy(ap2, ap);
+		vsnprintf(buf + str_len, buflen - str_len, fmt, ap2);
+		va_end(ap2);
+	}
+	*pstr_len = (needed - 1);
+	return buf;
+fail:
+	*pstr_len = -1;
+	return buf;
+}
+
+static char *talloc_asprintf_append_largebuf(char *buf, ssize_t *pstr_len,
+					     const char *fmt, ...)
+{
+	va_list ap;
+
+	va_start(ap, fmt);
+	buf = talloc_vasprintf_append_largebuf(buf, pstr_len, fmt, ap);
+	va_end(ap);
+	return buf;
+}
+
+struct talloc_report_str_state {
+	ssize_t str_len;
+	char *s;
+};
+
+static void talloc_report_str_helper(const void *ptr, int depth, int max_depth,
+				     int is_ref, void *private_data)
+{
+	struct talloc_report_str_state *state = private_data;
+	const char *name = talloc_get_name(ptr);
+
+	if (ptr == state->s) {
+		return;
+	}
+
+	if (is_ref) {
+		state->s = talloc_asprintf_append_largebuf(
+			state->s, &state->str_len,
+			"%*sreference to: %s\n", depth*4, "", name);
+		return;
+	}
+
+	if (depth == 0) {
+		state->s = talloc_asprintf_append_largebuf(
+			state->s, &state->str_len,
+			"%stalloc report on '%s' "
+			"(total %6lu bytes in %3lu blocks)\n",
+			(max_depth < 0 ? "full " :""), name,
+			(unsigned long)talloc_total_size(ptr),
+			(unsigned long)talloc_total_blocks(ptr));
+		return;
+	}
+
+	if (strcmp(name, "char") == 0) {
+		/*
+		 * Print out the first 50 bytes of the string
+		 */
+		state->s = talloc_asprintf_append_largebuf(
+			state->s, &state->str_len,
+			"%*s%-30s contains %6lu bytes in %3lu blocks "
+			"(ref %d): %*s\n", depth*4, "",	name,
+			(unsigned long)talloc_total_size(ptr),
+			(unsigned long)talloc_total_blocks(ptr),
+			talloc_reference_count(ptr),
+			MIN(50, talloc_get_size(ptr)),
+			(const char *)ptr);
+		return;
+	}
+
+	state->s = talloc_asprintf_append_largebuf(
+		state->s, &state->str_len,
+		"%*s%-30s contains %6lu bytes in %3lu blocks (ref %d)\n",
+		depth*4, "", name,
+		(unsigned long)talloc_total_size(ptr),
+		(unsigned long)talloc_total_blocks(ptr),
+		talloc_reference_count(ptr));
+}
+
+char *talloc_report_str(TALLOC_CTX *mem_ctx, TALLOC_CTX *root)
+{
+	struct talloc_report_str_state state;
+
+	state.s = talloc_strdup(mem_ctx, "");
+	if (state.s == NULL) {
+		return NULL;
+	}
+	state.str_len = 0;
+
+	talloc_report_depth_cb(root, 0, -1, talloc_report_str_helper, &state);
+
+	if (state.str_len == -1) {
+		talloc_free(state.s);
+		return NULL;
+	}
+
+	return talloc_realloc(mem_ctx, state.s, char, state.str_len+1);
+}
diff --git a/lib/util/talloc_report.h b/lib/util/talloc_report.h
new file mode 100644
index 0000000..53d0385
--- /dev/null
+++ b/lib/util/talloc_report.h
@@ -0,0 +1,27 @@
+/*
+ * talloc_report into a string
+ *
+ * Copyright Volker Lendecke <vl at samba.org> 2015
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef _TALLOC_REPORT_H_
+#define _TALLOC_REPORT_H_
+
+#include <talloc.h>
+
+char *talloc_report_str(TALLOC_CTX *mem_ctx, TALLOC_CTX *root);
+
+#endif
diff --git a/lib/util/wscript_build b/lib/util/wscript_build
index c0d07e7..a1dec2a 100755
--- a/lib/util/wscript_build
+++ b/lib/util/wscript_build
@@ -95,6 +95,13 @@ if not bld.env.SAMBA_UTIL_CORE_ONLY:
                       private_library=True
                       )
 
+    bld.SAMBA_LIBRARY('talloc_report',
+                      source='talloc_report.c',
+                      local_include=False,
+                      public_deps='talloc',
+                      private_library=True
+                      )
+
     if not bld.env.disable_ntdb:
         bld.SAMBA_LIBRARY('util_ntdb',
                           source='util_ntdb.c',
-- 
1.9.1


From dadce3acc296289c3ca8d8f63c4fda31a8b9a3fc Mon Sep 17 00:00:00 2001
From: Volker Lendecke <vl at samba.org>
Date: Tue, 10 Feb 2015 22:17:44 +0100
Subject: [PATCH 15/16] lib: Use talloc_report_str

Signed-off-by: Volker Lendecke <vl at samba.org>
---
 source3/lib/tallocmsg.c | 84 +++++--------------------------------------------
 source3/wscript_build   |  1 +
 2 files changed, 9 insertions(+), 76 deletions(-)

diff --git a/source3/lib/tallocmsg.c b/source3/lib/tallocmsg.c
index 9a0ce8a..18b16ed 100644
--- a/source3/lib/tallocmsg.c
+++ b/source3/lib/tallocmsg.c
@@ -18,65 +18,7 @@
 
 #include "includes.h"
 #include "messages.h"
-
-/**
- * @file tallocmsg.c
- *
- * Glue code between talloc profiling and the Samba messaging system.
- **/
-
-struct msg_pool_usage_state {
-	TALLOC_CTX *mem_ctx;
-	ssize_t len;
-	size_t buflen;
-	char *s;
-};
-
-static void msg_pool_usage_helper(const void *ptr, int depth, int max_depth, int is_ref, void *_s)
-{
-	const char *name = talloc_get_name(ptr);
-	struct msg_pool_usage_state *state = (struct msg_pool_usage_state *)_s;
-
-	if (is_ref) {
-		sprintf_append(state->mem_ctx, &state->s, &state->len, &state->buflen,
-			       "%*sreference to: %s\n", depth*4, "", name);
-		return;
-	}
-
-	if (depth == 0) {
-		sprintf_append(state->mem_ctx, &state->s, &state->len, &state->buflen,
-			       "%stalloc report on '%s' (total %6lu bytes in %3lu blocks)\n", 
-			       (max_depth < 0 ? "full " :""), name,
-			       (unsigned long)talloc_total_size(ptr),
-			       (unsigned long)talloc_total_blocks(ptr));
-		return;
-	}
-
-	if (strcmp(name, "char") == 0) {
-		/*
-		 * Print out the first 50 bytes of the string
-		 */
-		sprintf_append(state->mem_ctx, &state->s, &state->len,
-			       &state->buflen,
-			       "%*s%-30s contains %6lu bytes in %3lu blocks "
-			       "(ref %d): %*s\n", depth*4, "",
-			       name,
-			       (unsigned long)talloc_total_size(ptr),
-			       (unsigned long)talloc_total_blocks(ptr),
-			       talloc_reference_count(ptr),
-			       MIN(50, talloc_get_size(ptr)),
-			       (const char *)ptr);
-		return;
-	}
-
-	sprintf_append(state->mem_ctx, &state->s, &state->len, &state->buflen,
-		       "%*s%-30s contains %6lu bytes in %3lu blocks (ref %d)\n", 
-		       depth*4, "",
-		       name,
-		       (unsigned long)talloc_total_size(ptr),
-		       (unsigned long)talloc_total_blocks(ptr),
-		       talloc_reference_count(ptr));
-}
+#include "lib/util/talloc_report.h"
 
 /**
  * Respond to a POOL_USAGE message by sending back string form of memory
@@ -88,31 +30,21 @@ static void msg_pool_usage(struct messaging_context *msg_ctx,
 			   struct server_id src,
 			   DATA_BLOB *data)
 {
-	struct msg_pool_usage_state state;
+	char *report;
 
 	SMB_ASSERT(msg_type == MSG_REQ_POOL_USAGE);
 
 	DEBUG(2,("Got POOL_USAGE\n"));
 
-	state.mem_ctx = talloc_init("msg_pool_usage");
-	if (!state.mem_ctx) {
-		return;
-	}
-	state.len	= 0;
-	state.buflen	= 512;
-	state.s		= NULL;
-
-	talloc_report_depth_cb(NULL, 0, -1, msg_pool_usage_helper, &state);
+	report = talloc_report_str(msg_ctx, NULL);
 
-	if (!state.s) {
-		talloc_destroy(state.mem_ctx);
-		return;
+	if (report != NULL) {
+		messaging_send_buf(msg_ctx, src, MSG_POOL_USAGE,
+				   (uint8_t *)report,
+				   talloc_get_size(report)-1);
 	}
 
-	messaging_send_buf(msg_ctx, src, MSG_POOL_USAGE,
-			   (uint8 *)state.s, strlen(state.s)+1);
-
-	talloc_destroy(state.mem_ctx);
+	talloc_free(report);
 }
 
 /**
diff --git a/source3/wscript_build b/source3/wscript_build
index 151e68b..d166d4e 100755
--- a/source3/wscript_build
+++ b/source3/wscript_build
@@ -369,6 +369,7 @@ bld.SAMBA3_SUBSYSTEM('samba3core',
                         server_id_db
                         messages_util
                         messages_dgm
+                        talloc_report
                         TDB_LIB''')
 
 bld.SAMBA3_LIBRARY('smbd_shim',
-- 
1.9.1


From 8e55f1a394db6081c371ba21e5e500e6a6e87616 Mon Sep 17 00:00:00 2001
From: Volker Lendecke <vl at samba.org>
Date: Wed, 11 Feb 2015 15:31:26 +0000
Subject: [PATCH 16/16] messaging4: Enable POOL_USAGE

With this you can watch "samba"'s talloc hierarchy live using

smbcontrol <pid> pool-usage

Enjoy :-)

Signed-off-by: Volker Lendecke <vl at samba.org>
---
 source4/lib/messaging/messaging.c   | 18 ++++++++++++++++++
 source4/lib/messaging/messaging.h   |  4 +++-
 source4/lib/messaging/wscript_build |  2 +-
 source4/smbd/server.c               |  2 ++
 4 files changed, 24 insertions(+), 2 deletions(-)

diff --git a/source4/lib/messaging/messaging.c b/source4/lib/messaging/messaging.c
index cad2d64..66f9f1c 100644
--- a/source4/lib/messaging/messaging.c
+++ b/source4/lib/messaging/messaging.c
@@ -33,6 +33,7 @@
 #include "../lib/util/tevent_ntstatus.h"
 #include "lib/param/param.h"
 #include "lib/util/server_id_db.h"
+#include "lib/util/talloc_report.h"
 #include "../source3/lib/messages_dgm.h"
 #include "../source3/lib/messages_dgm_ref.h"
 #include "../source3/lib/messages_util.h"
@@ -115,6 +116,22 @@ static void ping_message(struct imessaging_context *msg, void *private_data,
 	imessaging_send(msg, src, MSG_PONG, data);
 }
 
+static void pool_message(struct imessaging_context *msg, void *private_data,
+			 uint32_t msg_type, struct server_id src,
+			 DATA_BLOB *data)
+{
+	char *report;
+
+	report = talloc_report_str(msg, NULL);
+
+	if (report != NULL) {
+		DATA_BLOB blob = { .data = (uint8_t *)report,
+				   .length = talloc_get_size(report) - 1};
+		imessaging_send(msg, src, MSG_POOL_USAGE, &blob);
+	}
+	talloc_free(report);
+}
+
 /*
   return uptime of messaging server via irpc
 */
@@ -377,6 +394,7 @@ struct imessaging_context *imessaging_init(TALLOC_CTX *mem_ctx,
 	}
 
 	imessaging_register(msg, NULL, MSG_PING, ping_message);
+	imessaging_register(msg, NULL, MSG_REQ_POOL_USAGE, pool_message);
 	imessaging_register(msg, NULL, MSG_IRPC, irpc_handler);
 	IRPC_REGISTER(msg, irpc, IRPC_UPTIME, irpc_uptime, msg);
 
diff --git a/source4/lib/messaging/messaging.h b/source4/lib/messaging/messaging.h
index b84f5d8..920e39d 100644
--- a/source4/lib/messaging/messaging.h
+++ b/source4/lib/messaging/messaging.h
@@ -34,7 +34,9 @@ struct imessaging_context;
 #define MSG_IRPC                6
 #define MSG_PVFS_NOTIFY		7
 #define MSG_NTVFS_OPLOCK_BREAK	8
-#define MSG_DREPL_ALLOCATE_RID	9
+#define MSG_REQ_POOL_USAGE	9
+#define MSG_POOL_USAGE          10
+#define MSG_DREPL_ALLOCATE_RID	11
 
 /* temporary messaging endpoints are allocated above this line */
 #define MSG_TMP_BASE		1000
diff --git a/source4/lib/messaging/wscript_build b/source4/lib/messaging/wscript_build
index efe1f79..adcb2cc 100644
--- a/source4/lib/messaging/wscript_build
+++ b/source4/lib/messaging/wscript_build
@@ -3,7 +3,7 @@
 
 bld.SAMBA_LIBRARY('MESSAGING',
 	source='messaging.c',
-	public_deps='samba-util NDR_IRPC UNIX_PRIVS cluster ndr dcerpc messages_util server_id_db',
+	public_deps='samba-util NDR_IRPC UNIX_PRIVS cluster ndr dcerpc messages_util server_id_db talloc_report',
 	private_library=True
 	)
 
diff --git a/source4/smbd/server.c b/source4/smbd/server.c
index 1c80934..b0f67c9 100644
--- a/source4/smbd/server.c
+++ b/source4/smbd/server.c
@@ -360,6 +360,8 @@ static int binary_smbd_main(const char *binary_name, int argc, const char *argv[
 
 	poptFreeContext(pc);
 
+	talloc_enable_null_tracking();
+
 	setup_logging(binary_name, opt_interactive?DEBUG_STDOUT:DEBUG_FILE);
 	setup_signals();
 
-- 
1.9.1



More information about the samba-technical mailing list