[PATCH] g_lock_ping_pong
Jeremy Allison
jra at samba.org
Thu Jul 6 22:52:46 UTC 2017
On Thu, Jul 06, 2017 at 04:17:22PM +0200, Volker Lendecke via samba-technical wrote:
> Hi!
>
> Attached find a patchset that implements a g_lock performance test
> along with some modifications for correctness and performance.
>
> Review appreciated!
This looks great - lots of code deletion :-) :-).
Going to take a little while to go through though,
but just wanted to let you know I'm looking at it.
Cheers,
Jeremy.
> --
> 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
> From d3c7576c58922731e1fa1c7f17c3d0ec94d8a7fa Mon Sep 17 00:00:00 2001
> From: Volker Lendecke <vl at samba.org>
> Date: Mon, 22 May 2017 21:55:11 +0200
> Subject: [PATCH 01/41] torture: Add local-g-lock-ping-pong
>
> This is similar to the ctdb ping_pong test.
>
> Signed-off-by: Volker Lendecke <vl at samba.org>
> ---
> source3/torture/proto.h | 1 +
> source3/torture/test_g_lock.c | 100 ++++++++++++++++++++++++++++++++++++++++--
> source3/torture/torture.c | 1 +
> 3 files changed, 98 insertions(+), 4 deletions(-)
>
> diff --git a/source3/torture/proto.h b/source3/torture/proto.h
> index 4c3e540..fc46898 100644
> --- a/source3/torture/proto.h
> +++ b/source3/torture/proto.h
> @@ -130,5 +130,6 @@ bool run_g_lock2(int dummy);
> bool run_g_lock3(int dummy);
> bool run_g_lock4(int dummy);
> bool run_g_lock5(int dummy);
> +bool run_g_lock_ping_pong(int dummy);
>
> #endif /* __TORTURE_H__ */
> diff --git a/source3/torture/test_g_lock.c b/source3/torture/test_g_lock.c
> index ca37312..61ec69d 100644
> --- a/source3/torture/test_g_lock.c
> +++ b/source3/torture/test_g_lock.c
> @@ -30,12 +30,12 @@ static bool get_g_lock_ctx(TALLOC_CTX *mem_ctx,
> struct messaging_context **msg,
> struct g_lock_ctx **ctx)
> {
> - *ev = samba_tevent_context_init(mem_ctx);
> + *ev = server_event_context();
> if (*ev == NULL) {
> fprintf(stderr, "tevent_context_init failed\n");
> return false;
> }
> - *msg = messaging_init(*ev, *ev);
> + *msg = server_messaging_context();
> if (*msg == NULL) {
> fprintf(stderr, "messaging_init failed\n");
> TALLOC_FREE(*ev);
> @@ -558,8 +558,8 @@ bool run_g_lock5(int dummy)
>
> if (child == 0) {
> TALLOC_FREE(ctx);
> - TALLOC_FREE(msg);
> - TALLOC_FREE(ev);
> +
> + status = reinit_after_fork(msg, ev, false, "");
>
> close(ready_pipe[0]);
> close(exit_pipe[1]);
> @@ -642,3 +642,95 @@ bool run_g_lock5(int dummy)
>
> return true;
> }
> +
> +extern int torture_numops;
> +extern int torture_nprocs;
> +
> +static struct timeval tp1, tp2;
> +
> +static void start_timer(void)
> +{
> + gettimeofday(&tp1,NULL);
> +}
> +
> +static double end_timer(void)
> +{
> + gettimeofday(&tp2,NULL);
> + return (tp2.tv_sec + (tp2.tv_usec*1.0e-6)) -
> + (tp1.tv_sec + (tp1.tv_usec*1.0e-6));
> +}
> +
> +/*
> + * g_lock ping_pong
> + */
> +
> +bool run_g_lock_ping_pong(int dummy)
> +{
> + struct tevent_context *ev = NULL;
> + struct messaging_context *msg = NULL;
> + struct g_lock_ctx *ctx = NULL;
> + fstring name;
> + NTSTATUS status;
> + int i = 0;
> + bool ret = false;
> + bool ok;
> + unsigned count = 0;
> +
> + torture_nprocs = MAX(2, torture_nprocs);
> +
> + ok = get_g_lock_ctx(talloc_tos(), &ev, &msg, &ctx);
> + if (!ok) {
> + goto fail;
> + }
> +
> + start_timer();
> +
> + snprintf(name, sizeof(name), "ping_pong_%d", i);
> +
> + status = g_lock_lock(ctx, name, G_LOCK_WRITE,
> + (struct timeval) { .tv_sec = 60 });
> + if (!NT_STATUS_IS_OK(status)) {
> + fprintf(stderr, "g_lock_lock failed: %s\n",
> + nt_errstr(status));
> + goto fail;
> + }
> +
> + for (i=0; i<torture_numops; i++) {
> +
> + name[10] = '0' + ((i+1) % torture_nprocs);
> +
> + status = g_lock_lock(ctx, name, G_LOCK_WRITE,
> + (struct timeval) { .tv_sec = 60 });
> + if (!NT_STATUS_IS_OK(status)) {
> + fprintf(stderr, "g_lock_lock failed: %s\n",
> + nt_errstr(status));
> + goto fail;
> + }
> +
> + name[10] = '0' + ((i) % torture_nprocs);
> +
> + status = g_lock_unlock(ctx, name);
> + if (!NT_STATUS_IS_OK(status)) {
> + fprintf(stderr, "g_lock_unlock failed: %s\n",
> + nt_errstr(status));
> + goto fail;
> + }
> +
> + count++;
> +
> + if (end_timer() > 1.0) {
> + printf("%8u locks/sec\r",
> + (unsigned)(2*count/end_timer()));
> + fflush(stdout);
> + start_timer();
> + count=0;
> + }
> + }
> +
> + ret = true;
> +fail:
> + TALLOC_FREE(ctx);
> + TALLOC_FREE(msg);
> + TALLOC_FREE(ev);
> + return ret;
> +}
> diff --git a/source3/torture/torture.c b/source3/torture/torture.c
> index 6959b71..64caca5 100644
> --- a/source3/torture/torture.c
> +++ b/source3/torture/torture.c
> @@ -11556,6 +11556,7 @@ static struct {
> { "LOCAL-G-LOCK3", run_g_lock3, 0 },
> { "LOCAL-G-LOCK4", run_g_lock4, 0 },
> { "LOCAL-G-LOCK5", run_g_lock5, 0 },
> + { "LOCAL-G-LOCK-PING-PONG", run_g_lock_ping_pong, 0 },
> { "LOCAL-CANONICALIZE-PATH", run_local_canonicalize_path, 0 },
> { "qpathinfo-bufsize", run_qpathinfo_bufsize, 0 },
> {NULL, NULL, 0}};
> --
> 2.1.4
>
>
> From fe92b743b974d7464a03232a2db06c3df30544e0 Mon Sep 17 00:00:00 2001
> From: Volker Lendecke <vl at samba.org>
> Date: Mon, 12 Sep 2016 17:11:09 +0200
> Subject: [PATCH 02/41] dbwrap: Add dbwrap_merge_dbufs
>
> Transitional code to implement dbwrap_record_storev
>
> Signed-off-by: Volker Lendecke <vl at samba.org>
> ---
> lib/dbwrap/dbwrap.c | 48 ++++++++++++++++++++++++++++++++++++++++++++++++
> lib/dbwrap/dbwrap.h | 3 +++
> 2 files changed, 51 insertions(+)
>
> diff --git a/lib/dbwrap/dbwrap.c b/lib/dbwrap/dbwrap.c
> index 025d463..1f45558 100644
> --- a/lib/dbwrap/dbwrap.c
> +++ b/lib/dbwrap/dbwrap.c
> @@ -556,3 +556,51 @@ const char *dbwrap_name(struct db_context *db)
> {
> return db->name;
> }
> +
> +static ssize_t tdb_data_buf(const TDB_DATA *dbufs, int num_dbufs,
> + uint8_t *buf, size_t buflen)
> +{
> + size_t needed = 0;
> + uint8_t *p = buf;
> + int i;
> +
> + for (i=0; i<num_dbufs; i++) {
> + size_t thislen = dbufs[i].dsize;
> + size_t tmp;
> +
> + tmp = needed + thislen;
> + if (tmp < needed) {
> + /* wrap */
> + return -1;
> + }
> + needed = tmp;
> +
> + if (needed <= buflen) {
> + memcpy(p, dbufs[i].dptr, thislen);
> + p += thislen;
> + }
> + }
> +
> + return needed;
> +}
> +
> +
> +TDB_DATA dbwrap_merge_dbufs(TALLOC_CTX *mem_ctx,
> + const TDB_DATA *dbufs, int num_dbufs)
> +{
> + ssize_t len = tdb_data_buf(dbufs, num_dbufs, NULL, 0);
> + uint8_t *buf;
> +
> + if (len == -1) {
> + return (TDB_DATA) {0};
> + }
> +
> + buf = talloc_array(mem_ctx, uint8_t, len);
> + if (buf == NULL) {
> + return (TDB_DATA) {0};
> + }
> +
> + tdb_data_buf(dbufs, num_dbufs, buf, len);
> +
> + return (TDB_DATA) { .dptr = buf, .dsize = len };
> +}
> diff --git a/lib/dbwrap/dbwrap.h b/lib/dbwrap/dbwrap.h
> index fac65ee..e34b2ab 100644
> --- a/lib/dbwrap/dbwrap.h
> +++ b/lib/dbwrap/dbwrap.h
> @@ -216,6 +216,9 @@ NTSTATUS dbwrap_parse_marshall_buf(const uint8_t *buf, size_t buflen,
> NTSTATUS dbwrap_unmarshall(struct db_context *db, const uint8_t *buf,
> size_t buflen);
>
> +TDB_DATA dbwrap_merge_dbufs(TALLOC_CTX *mem_ctx,
> + const TDB_DATA *dbufs, int num_dbufs);
> +
>
> /**
> * This opens a tdb file
> --
> 2.1.4
>
>
> From 311b01fed0711e101357059e038e7641bbd0145c Mon Sep 17 00:00:00 2001
> From: Volker Lendecke <vl at samba.org>
> Date: Mon, 12 Sep 2016 17:30:55 +0200
> Subject: [PATCH 03/41] dbwrap: Convert backend store to storev
>
> Convert all implementors of dbwrap_store to a storev-style call
> by using the dbwrap_merge_dbufs call
>
> For dbwrap_tdb, this matches tdb_storev.
>
> Signed-off-by: Volker Lendecke <vl at samba.org>
> ---
> lib/dbwrap/dbwrap.c | 2 +-
> lib/dbwrap/dbwrap_private.h | 3 ++-
> lib/dbwrap/dbwrap_rbt.c | 25 ++++++++++++++++++----
> lib/dbwrap/dbwrap_tdb.c | 22 ++++++++++++--------
> source3/lib/dbwrap/dbwrap_ctdb.c | 44 ++++++++++++++++++++++++++++++---------
> source3/lib/dbwrap/dbwrap_watch.c | 24 +++++++++++++++------
> 6 files changed, 89 insertions(+), 31 deletions(-)
>
> diff --git a/lib/dbwrap/dbwrap.c b/lib/dbwrap/dbwrap.c
> index 1f45558..85f2213 100644
> --- a/lib/dbwrap/dbwrap.c
> +++ b/lib/dbwrap/dbwrap.c
> @@ -86,7 +86,7 @@ NTSTATUS dbwrap_record_store(struct db_record *rec, TDB_DATA data, int flags)
> {
> NTSTATUS status;
>
> - status = rec->store(rec, data, flags);
> + status = rec->storev(rec, &data, 1, flags);
> if (!NT_STATUS_IS_OK(status)) {
> return status;
> }
> diff --git a/lib/dbwrap/dbwrap_private.h b/lib/dbwrap/dbwrap_private.h
> index 9b50ccc..2858afd 100644
> --- a/lib/dbwrap/dbwrap_private.h
> +++ b/lib/dbwrap/dbwrap_private.h
> @@ -29,7 +29,8 @@ struct tevent_req;
> struct db_record {
> struct db_context *db;
> TDB_DATA key, value;
> - NTSTATUS (*store)(struct db_record *rec, TDB_DATA data, int flag);
> + NTSTATUS (*storev)(struct db_record *rec, const TDB_DATA *dbufs,
> + int num_dbufs, int flag);
> NTSTATUS (*delete_rec)(struct db_record *rec);
> void *private_data;
> };
> diff --git a/lib/dbwrap/dbwrap_rbt.c b/lib/dbwrap/dbwrap_rbt.c
> index eb5ef10..d9c743b 100644
> --- a/lib/dbwrap/dbwrap_rbt.c
> +++ b/lib/dbwrap/dbwrap_rbt.c
> @@ -118,7 +118,8 @@ overflow:
> return -1;
> }
>
> -static NTSTATUS db_rbt_store(struct db_record *rec, TDB_DATA data, int flag)
> +static NTSTATUS db_rbt_storev(struct db_record *rec,
> + const TDB_DATA *dbufs, int num_dbufs, int flag)
> {
> struct db_rbt_ctx *db_ctx = talloc_get_type_abort(
> rec->db->private_data, struct db_rbt_ctx);
> @@ -130,12 +131,23 @@ static NTSTATUS db_rbt_store(struct db_record *rec, TDB_DATA data, int flag)
> struct db_rbt_node *parent_node = NULL;
>
> ssize_t reclen;
> - TDB_DATA this_key, this_val;
> + TDB_DATA data, this_key, this_val;
> + void *to_free = NULL;
>
> if (db_ctx->traverse_read > 0) {
> return NT_STATUS_MEDIA_WRITE_PROTECTED;
> }
>
> + if (num_dbufs == 1) {
> + data = dbufs[0];
> + } else {
> + data = dbwrap_merge_dbufs(rec, dbufs, num_dbufs);
> + if (data.dptr == NULL) {
> + return NT_STATUS_NO_MEMORY;
> + }
> + to_free = data.dptr;
> + }
> +
> if (rec_priv->node != NULL) {
>
> /*
> @@ -154,17 +166,20 @@ static NTSTATUS db_rbt_store(struct db_record *rec, TDB_DATA data, int flag)
> */
> memcpy(this_val.dptr, data.dptr, data.dsize);
> rec_priv->node->valuesize = data.dsize;
> + TALLOC_FREE(to_free);
> return NT_STATUS_OK;
> }
> }
>
> reclen = db_rbt_reclen(rec->key.dsize, data.dsize);
> if (reclen == -1) {
> + TALLOC_FREE(to_free);
> return NT_STATUS_INSUFFICIENT_RESOURCES;
> }
>
> node = talloc_zero_size(db_ctx, reclen);
> if (node == NULL) {
> + TALLOC_FREE(to_free);
> return NT_STATUS_NO_MEMORY;
> }
>
> @@ -232,6 +247,8 @@ static NTSTATUS db_rbt_store(struct db_record *rec, TDB_DATA data, int flag)
> DLIST_ADD_AFTER(db_ctx->nodes, node, parent_node);
> rb_insert_color(&node->rb_node, &db_ctx->tree);
>
> + TALLOC_FREE(to_free);
> +
> return NT_STATUS_OK;
> }
>
> @@ -350,7 +367,7 @@ static struct db_record *db_rbt_fetch_locked(struct db_context *db_ctx,
> rec_priv = (struct db_rbt_rec *)
> ((char *)result + DBWRAP_RBT_ALIGN(sizeof(struct db_record)));
>
> - result->store = db_rbt_store;
> + result->storev = db_rbt_storev;
> result->delete_rec = db_rbt_delete;
> result->private_data = rec_priv;
>
> @@ -425,7 +442,7 @@ static int db_rbt_traverse_internal(struct db_context *db,
> ZERO_STRUCT(rec);
> rec.db = db;
> rec.private_data = &rec_priv;
> - rec.store = db_rbt_store;
> + rec.storev = db_rbt_storev;
> rec.delete_rec = db_rbt_delete;
> db_rbt_parse_node(rec_priv.node, &rec.key, &rec.value);
>
> diff --git a/lib/dbwrap/dbwrap_tdb.c b/lib/dbwrap/dbwrap_tdb.c
> index e12ec44..9f8a9a6 100644
> --- a/lib/dbwrap/dbwrap_tdb.c
> +++ b/lib/dbwrap/dbwrap_tdb.c
> @@ -35,7 +35,8 @@ struct db_tdb_ctx {
> } id;
> };
>
> -static NTSTATUS db_tdb_store(struct db_record *rec, TDB_DATA data, int flag);
> +static NTSTATUS db_tdb_storev(struct db_record *rec,
> + const TDB_DATA *dbufs, int num_dbufs, int flag);
> static NTSTATUS db_tdb_delete(struct db_record *rec);
>
> static void db_tdb_log_key(const char *prefix, TDB_DATA key)
> @@ -137,7 +138,7 @@ static struct db_record *db_tdb_fetch_locked_internal(
> talloc_set_destructor(state.result, db_tdb_record_destr);
>
> state.result->private_data = ctx;
> - state.result->store = db_tdb_store;
> + state.result->storev = db_tdb_storev;
> state.result->delete_rec = db_tdb_delete;
>
> DEBUG(10, ("Allocated locked data 0x%p\n", state.result));
> @@ -173,7 +174,6 @@ static struct db_record *db_tdb_try_fetch_locked(
> return db_tdb_fetch_locked_internal(db, mem_ctx, key);
> }
>
> -
> static int db_tdb_exists(struct db_context *db, TDB_DATA key)
> {
> struct db_tdb_ctx *ctx = talloc_get_type_abort(
> @@ -236,10 +236,12 @@ static NTSTATUS db_tdb_parse(struct db_context *db, TDB_DATA key,
> return NT_STATUS_OK;
> }
>
> -static NTSTATUS db_tdb_store(struct db_record *rec, TDB_DATA data, int flag)
> +static NTSTATUS db_tdb_storev(struct db_record *rec,
> + const TDB_DATA *dbufs, int num_dbufs, int flag)
> {
> struct db_tdb_ctx *ctx = talloc_get_type_abort(rec->private_data,
> struct db_tdb_ctx);
> + int ret;
>
> /*
> * This has a bug: We need to replace rec->value for correct
> @@ -247,8 +249,8 @@ static NTSTATUS db_tdb_store(struct db_record *rec, TDB_DATA data, int flag)
> * anymore after it was stored.
> */
>
> - return (tdb_store(ctx->wtdb->tdb, rec->key, data, flag) == 0) ?
> - NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
> + ret = tdb_storev(ctx->wtdb->tdb, rec->key, dbufs, num_dbufs, flag);
> + return (ret == 0) ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
> }
>
> static NTSTATUS db_tdb_delete(struct db_record *rec)
> @@ -282,7 +284,7 @@ static int db_tdb_traverse_func(TDB_CONTEXT *tdb, TDB_DATA kbuf, TDB_DATA dbuf,
>
> rec.key = kbuf;
> rec.value = dbuf;
> - rec.store = db_tdb_store;
> + rec.storev = db_tdb_storev;
> rec.delete_rec = db_tdb_delete;
> rec.private_data = ctx->db->private_data;
> rec.db = ctx->db;
> @@ -304,7 +306,9 @@ static int db_tdb_traverse(struct db_context *db,
> return tdb_traverse(db_ctx->wtdb->tdb, db_tdb_traverse_func, &ctx);
> }
>
> -static NTSTATUS db_tdb_store_deny(struct db_record *rec, TDB_DATA data, int flag)
> +static NTSTATUS db_tdb_storev_deny(struct db_record *rec,
> + const TDB_DATA *dbufs, int num_dbufs,
> + int flag)
> {
> return NT_STATUS_MEDIA_WRITE_PROTECTED;
> }
> @@ -323,7 +327,7 @@ static int db_tdb_traverse_read_func(TDB_CONTEXT *tdb, TDB_DATA kbuf, TDB_DATA d
>
> rec.key = kbuf;
> rec.value = dbuf;
> - rec.store = db_tdb_store_deny;
> + rec.storev = db_tdb_storev_deny;
> rec.delete_rec = db_tdb_delete_deny;
> rec.private_data = ctx->db->private_data;
> rec.db = ctx->db;
> diff --git a/source3/lib/dbwrap/dbwrap_ctdb.c b/source3/lib/dbwrap/dbwrap_ctdb.c
> index 8e303e6..2969183 100644
> --- a/source3/lib/dbwrap/dbwrap_ctdb.c
> +++ b/source3/lib/dbwrap/dbwrap_ctdb.c
> @@ -494,7 +494,9 @@ static bool pull_newest_from_marshall_buffer(struct ctdb_marshall_buffer *buf,
> return true;
> }
>
> -static NTSTATUS db_ctdb_store_transaction(struct db_record *rec, TDB_DATA data, int flag);
> +static NTSTATUS db_ctdb_storev_transaction(struct db_record *rec,
> + const TDB_DATA *dbufs, int num_dbufs,
> + int flag);
> static NTSTATUS db_ctdb_delete_transaction(struct db_record *rec);
>
> static struct db_record *db_ctdb_fetch_locked_transaction(struct db_ctdb_ctx *ctx,
> @@ -521,7 +523,7 @@ static struct db_record *db_ctdb_fetch_locked_transaction(struct db_ctdb_ctx *ct
> return NULL;
> }
>
> - result->store = db_ctdb_store_transaction;
> + result->storev = db_ctdb_storev_transaction;
> result->delete_rec = db_ctdb_delete_transaction;
>
> if (pull_newest_from_marshall_buffer(ctx->transaction->m_write, key,
> @@ -656,13 +658,23 @@ static NTSTATUS db_ctdb_transaction_store(struct db_ctdb_transaction_handle *h,
> /*
> a record store inside a transaction
> */
> -static NTSTATUS db_ctdb_store_transaction(struct db_record *rec, TDB_DATA data, int flag)
> +static NTSTATUS db_ctdb_storev_transaction(
> + struct db_record *rec, const TDB_DATA *dbufs, int num_dbufs, int flag)
> {
> struct db_ctdb_transaction_handle *h = talloc_get_type_abort(
> rec->private_data, struct db_ctdb_transaction_handle);
> NTSTATUS status;
> + TDB_DATA data;
> +
> + data = dbwrap_merge_dbufs(rec, dbufs, num_dbufs);
> + if (data.dptr == NULL) {
> + return NT_STATUS_NO_MEMORY;
> + }
>
> status = db_ctdb_transaction_store(h, rec->key, data);
> +
> + TALLOC_FREE(data.dptr);
> +
> return status;
> }
>
> @@ -887,12 +899,23 @@ static int db_ctdb_transaction_cancel(struct db_context *db)
> }
>
>
> -static NTSTATUS db_ctdb_store(struct db_record *rec, TDB_DATA data, int flag)
> +static NTSTATUS db_ctdb_storev(struct db_record *rec,
> + const TDB_DATA *dbufs, int num_dbufs, int flag)
> {
> struct db_ctdb_rec *crec = talloc_get_type_abort(
> rec->private_data, struct db_ctdb_rec);
> + NTSTATUS status;
> + TDB_DATA data;
> +
> + data = dbwrap_merge_dbufs(rec, dbufs, num_dbufs);
> + if (data.dptr == NULL) {
> + return NT_STATUS_NO_MEMORY;
> + }
>
> - return db_ctdb_ltdb_store(crec->ctdb_ctx, rec->key, &(crec->header), data);
> + status = db_ctdb_ltdb_store(crec->ctdb_ctx, rec->key, &(crec->header),
> + data);
> + TALLOC_FREE(data.dptr);
> + return status;
> }
>
>
> @@ -954,7 +977,7 @@ static NTSTATUS db_ctdb_delete(struct db_record *rec)
> * tdb-level cleanup
> */
>
> - status = db_ctdb_store(rec, tdb_null, 0);
> + status = db_ctdb_storev(rec, &tdb_null, 1, 0);
> if (!NT_STATUS_IS_OK(status)) {
> return status;
> }
> @@ -1125,7 +1148,7 @@ again:
> return NULL;
> }
>
> - result->store = db_ctdb_store;
> + result->storev = db_ctdb_storev;
> result->delete_rec = db_ctdb_delete;
> talloc_set_destructor(result, db_ctdb_record_destr);
>
> @@ -1658,7 +1681,8 @@ static int db_ctdb_traverse(struct db_context *db,
> return state.count;
> }
>
> -static NTSTATUS db_ctdb_store_deny(struct db_record *rec, TDB_DATA data, int flag)
> +static NTSTATUS db_ctdb_storev_deny(struct db_record *rec,
> + const TDB_DATA *dbufs, int num_dbufs, int flag)
> {
> return NT_STATUS_MEDIA_WRITE_PROTECTED;
> }
> @@ -1677,7 +1701,7 @@ static void traverse_read_callback(TDB_DATA key, TDB_DATA data, void *private_da
> rec.db = state->db;
> rec.key = key;
> rec.value = data;
> - rec.store = db_ctdb_store_deny;
> + rec.storev = db_ctdb_storev_deny;
> rec.delete_rec = db_ctdb_delete_deny;
> rec.private_data = NULL;
> state->fn(&rec, state->private_data);
> @@ -1704,7 +1728,7 @@ static int traverse_persistent_callback_read(TDB_CONTEXT *tdb, TDB_DATA kbuf, TD
> rec.db = state->db;
> rec.key = kbuf;
> rec.value = dbuf;
> - rec.store = db_ctdb_store_deny;
> + rec.storev = db_ctdb_storev_deny;
> rec.delete_rec = db_ctdb_delete_deny;
> rec.private_data = NULL;
>
> diff --git a/source3/lib/dbwrap/dbwrap_watch.c b/source3/lib/dbwrap/dbwrap_watch.c
> index 585010f..ab59803 100644
> --- a/source3/lib/dbwrap/dbwrap_watch.c
> +++ b/source3/lib/dbwrap/dbwrap_watch.c
> @@ -238,8 +238,9 @@ struct db_watched_subrec {
> bool deleted;
> };
>
> -static NTSTATUS dbwrap_watched_store(struct db_record *rec, TDB_DATA data,
> - int flag);
> +static NTSTATUS dbwrap_watched_storev(struct db_record *rec,
> + const TDB_DATA *dbufs, int num_dbufs,
> + int flag);
> static NTSTATUS dbwrap_watched_delete(struct db_record *rec);
>
> static struct db_record *dbwrap_watched_fetch_locked(
> @@ -271,7 +272,7 @@ static struct db_record *dbwrap_watched_fetch_locked(
>
> rec->db = db;
> rec->key = dbwrap_record_get_key(subrec->subrec);
> - rec->store = dbwrap_watched_store;
> + rec->storev = dbwrap_watched_storev;
> rec->delete_rec = dbwrap_watched_delete;
>
> subrec_value = dbwrap_record_get_value(subrec->subrec);
> @@ -383,18 +384,29 @@ static NTSTATUS dbwrap_watched_save(struct db_watched_subrec *subrec,
> return status;
> }
>
> -static NTSTATUS dbwrap_watched_store(struct db_record *rec, TDB_DATA data,
> - int flag)
> +static NTSTATUS dbwrap_watched_storev(struct db_record *rec,
> + const TDB_DATA *dbufs, int num_dbufs,
> + int flag)
> {
> struct db_watched_subrec *subrec = talloc_get_type_abort(
> rec->private_data, struct db_watched_subrec);
> + NTSTATUS status;
> + TDB_DATA data;
> +
> + data = dbwrap_merge_dbufs(rec, dbufs, num_dbufs);
> + if (data.dptr == NULL) {
> + return NT_STATUS_NO_MEMORY;
> + }
>
> dbwrap_watched_wakeup(rec, subrec);
>
> subrec->deleted = false;
>
> - return dbwrap_watched_save(subrec, data, flag);
> + status = dbwrap_watched_save(subrec, data, flag);
> +
> + TALLOC_FREE(data.dptr);
>
> + return status;
> }
>
> static NTSTATUS dbwrap_watched_delete(struct db_record *rec)
> --
> 2.1.4
>
>
> From 6b9acf9b413cc221268d2bcf90e88000c35ed55c Mon Sep 17 00:00:00 2001
> From: Volker Lendecke <vl at samba.org>
> Date: Tue, 13 Sep 2016 12:25:14 +0200
> Subject: [PATCH 04/41] dbwrap: Add dbwrap_record_storev
>
> Signed-off-by: Volker Lendecke <vl at samba.org>
> ---
> lib/dbwrap/dbwrap.c | 10 ++++++++--
> lib/dbwrap/dbwrap.h | 2 ++
> 2 files changed, 10 insertions(+), 2 deletions(-)
>
> diff --git a/lib/dbwrap/dbwrap.c b/lib/dbwrap/dbwrap.c
> index 85f2213..713c420 100644
> --- a/lib/dbwrap/dbwrap.c
> +++ b/lib/dbwrap/dbwrap.c
> @@ -82,17 +82,23 @@ TDB_DATA dbwrap_record_get_value(const struct db_record *rec)
> return rec->value;
> }
>
> -NTSTATUS dbwrap_record_store(struct db_record *rec, TDB_DATA data, int flags)
> +NTSTATUS dbwrap_record_storev(struct db_record *rec,
> + const TDB_DATA *dbufs, int num_dbufs, int flags)
> {
> NTSTATUS status;
>
> - status = rec->storev(rec, &data, 1, flags);
> + status = rec->storev(rec, dbufs, num_dbufs, flags);
> if (!NT_STATUS_IS_OK(status)) {
> return status;
> }
> return NT_STATUS_OK;
> }
>
> +NTSTATUS dbwrap_record_store(struct db_record *rec, TDB_DATA data, int flags)
> +{
> + return dbwrap_record_storev(rec, &data, 1, flags);
> +}
> +
> NTSTATUS dbwrap_record_delete(struct db_record *rec)
> {
> NTSTATUS status;
> diff --git a/lib/dbwrap/dbwrap.h b/lib/dbwrap/dbwrap.h
> index e34b2ab..04e179e 100644
> --- a/lib/dbwrap/dbwrap.h
> +++ b/lib/dbwrap/dbwrap.h
> @@ -72,6 +72,8 @@ enum dbwrap_req_state {
> TDB_DATA dbwrap_record_get_key(const struct db_record *rec);
> TDB_DATA dbwrap_record_get_value(const struct db_record *rec);
> NTSTATUS dbwrap_record_store(struct db_record *rec, TDB_DATA data, int flags);
> +NTSTATUS dbwrap_record_storev(struct db_record *rec,
> + const TDB_DATA *dbufs, int num_dbufs, int flags);
> NTSTATUS dbwrap_record_delete(struct db_record *rec);
> struct db_record *dbwrap_fetch_locked(struct db_context *db,
> TALLOC_CTX *mem_ctx,
> --
> 2.1.4
>
>
> From 89448c6c9a47ebc0778a4837b94c197ed159fcde Mon Sep 17 00:00:00 2001
> From: Volker Lendecke <vl at samba.org>
> Date: Wed, 9 Nov 2016 08:45:59 +0100
> Subject: [PATCH 05/41] dbwrap: Add dbwrap_do_locked
>
> With a proper implementation this enables modifications without
> having to allocate a record. In really performance sensitive code
> paths this matters.
>
> Signed-off-by: Volker Lendecke <vl at samba.org>
> ---
> lib/dbwrap/dbwrap.c | 25 +++++++++++++++++++++++++
> lib/dbwrap/dbwrap.h | 5 +++++
> lib/dbwrap/dbwrap_private.h | 4 ++++
> 3 files changed, 34 insertions(+)
>
> diff --git a/lib/dbwrap/dbwrap.c b/lib/dbwrap/dbwrap.c
> index 713c420..fc70491 100644
> --- a/lib/dbwrap/dbwrap.c
> +++ b/lib/dbwrap/dbwrap.c
> @@ -486,6 +486,31 @@ NTSTATUS dbwrap_parse_record_recv(struct tevent_req *req)
> return tevent_req_simple_recv_ntstatus(req);
> }
>
> +NTSTATUS dbwrap_do_locked(struct db_context *db, TDB_DATA key,
> + void (*fn)(struct db_record *rec,
> + void *private_data),
> + void *private_data)
> +{
> + struct db_record *rec;
> +
> + if (db->do_locked != NULL) {
> + NTSTATUS status;
> + status = db->do_locked(db, key, fn, private_data);
> + return status;
> + }
> +
> + rec = dbwrap_fetch_locked(db, db, key);
> + if (rec == NULL) {
> + return NT_STATUS_NO_MEMORY;
> + }
> +
> + fn(rec, private_data);
> +
> + TALLOC_FREE(rec);
> +
> + return NT_STATUS_OK;
> +}
> +
> int dbwrap_wipe(struct db_context *db)
> {
> if (db->wipe == NULL) {
> diff --git a/lib/dbwrap/dbwrap.h b/lib/dbwrap/dbwrap.h
> index 04e179e..1161bf0 100644
> --- a/lib/dbwrap/dbwrap.h
> +++ b/lib/dbwrap/dbwrap.h
> @@ -83,6 +83,11 @@ struct db_record *dbwrap_try_fetch_locked(struct db_context *db,
> TDB_DATA key);
> struct db_context *dbwrap_record_get_db(struct db_record *rec);
>
> +NTSTATUS dbwrap_do_locked(struct db_context *db, TDB_DATA key,
> + void (*fn)(struct db_record *rec,
> + void *private_data),
> + void *private_data);
> +
> NTSTATUS dbwrap_delete(struct db_context *db, TDB_DATA key);
> NTSTATUS dbwrap_store(struct db_context *db, TDB_DATA key,
> TDB_DATA data, int flags);
> diff --git a/lib/dbwrap/dbwrap_private.h b/lib/dbwrap/dbwrap_private.h
> index 2858afd..e757215 100644
> --- a/lib/dbwrap/dbwrap_private.h
> +++ b/lib/dbwrap/dbwrap_private.h
> @@ -68,6 +68,10 @@ struct db_context {
> void *private_data,
> enum dbwrap_req_state *req_state);
> NTSTATUS (*parse_record_recv)(struct tevent_req *req);
> + NTSTATUS (*do_locked)(struct db_context *db, TDB_DATA key,
> + void (*fn)(struct db_record *rec,
> + void *private_data),
> + void *private_data);
> int (*exists)(struct db_context *db,TDB_DATA key);
> int (*wipe)(struct db_context *db);
> int (*check)(struct db_context *db);
> --
> 2.1.4
>
>
> From 0c758c69923b1082d369bcc9f5536bc063a07eda Mon Sep 17 00:00:00 2001
> From: Volker Lendecke <vl at samba.org>
> Date: Tue, 27 Jun 2017 08:25:36 +0200
> Subject: [PATCH 06/41] torture3: Test dbwrap_do_locked
>
> Signed-off-by: Volker Lendecke <vl at samba.org>
> ---
> source3/selftest/tests.py | 1 +
> source3/torture/proto.h | 1 +
> source3/torture/test_dbwrap_do_locked.c | 132 ++++++++++++++++++++++++++++++++
> source3/torture/torture.c | 1 +
> source3/wscript_build | 1 +
> 5 files changed, 136 insertions(+)
> create mode 100644 source3/torture/test_dbwrap_do_locked.c
>
> diff --git a/source3/selftest/tests.py b/source3/selftest/tests.py
> index d459ede..1594c19 100755
> --- a/source3/selftest/tests.py
> +++ b/source3/selftest/tests.py
> @@ -148,6 +148,7 @@ local_tests = [
> "LOCAL-CANONICALIZE-PATH",
> "LOCAL-DBWRAP-WATCH1",
> "LOCAL-DBWRAP-WATCH2",
> + "LOCAL-DBWRAP-DO-LOCKED1",
> "LOCAL-G-LOCK1",
> "LOCAL-G-LOCK2",
> "LOCAL-G-LOCK3",
> diff --git a/source3/torture/proto.h b/source3/torture/proto.h
> index fc46898..8a032da 100644
> --- a/source3/torture/proto.h
> +++ b/source3/torture/proto.h
> @@ -111,6 +111,7 @@ bool run_notify_bench2(int dummy);
> bool run_notify_bench3(int dummy);
> bool run_dbwrap_watch1(int dummy);
> bool run_dbwrap_watch2(int dummy);
> +bool run_dbwrap_do_locked1(int dummy);
> bool run_idmap_tdb_common_test(int dummy);
> bool run_local_dbwrap_ctdb(int dummy);
> bool run_qpathinfo_bufsize(int dummy);
> diff --git a/source3/torture/test_dbwrap_do_locked.c b/source3/torture/test_dbwrap_do_locked.c
> new file mode 100644
> index 0000000..92dec38
> --- /dev/null
> +++ b/source3/torture/test_dbwrap_do_locked.c
> @@ -0,0 +1,132 @@
> +/*
> + * Unix SMB/CIFS implementation.
> + * Test dbwrap_watch API
> + * Copyright (C) Volker Lendecke 2017
> + *
> + * 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 "includes.h"
> +#include "torture/proto.h"
> +#include "system/filesys.h"
> +#include "lib/dbwrap/dbwrap.h"
> +#include "lib/dbwrap/dbwrap_open.h"
> +#include "lib/dbwrap/dbwrap_watch.h"
> +#include "lib/util/util_tdb.h"
> +#include "source3/include/util_tdb.h"
> +
> +struct do_locked1_state {
> + TDB_DATA value;
> + NTSTATUS status;
> +};
> +
> +static void do_locked1_cb(struct db_record *rec, void *private_data)
> +{
> + struct do_locked1_state *state =
> + (struct do_locked1_state *)private_data;
> +
> + state->status = dbwrap_record_store(rec, state->value, 0);
> +}
> +
> +static void do_locked1_check(TDB_DATA key, TDB_DATA value,
> + void *private_data)
> +{
> + struct do_locked1_state *state =
> + (struct do_locked1_state *)private_data;
> + int ret;
> +
> + ret = tdb_data_cmp(value, state->value);
> + if (ret != 0) {
> + state->status = NT_STATUS_DATA_ERROR;
> + return;
> + }
> +
> + state->status = NT_STATUS_OK;
> +}
> +
> +static void do_locked1_del(struct db_record *rec, void *private_data)
> +{
> + struct do_locked1_state *state =
> + (struct do_locked1_state *)private_data;
> +
> + state->status = dbwrap_record_delete(rec);
> +}
> +
> +bool run_dbwrap_do_locked1(int dummy)
> +{
> + struct db_context *db;
> + const char *dbname = "test_do_locked.tdb";
> + const char *keystr = "key";
> + TDB_DATA key = string_term_tdb_data(keystr);
> + const char *valuestr = "value";
> + TDB_DATA value = string_term_tdb_data(valuestr);
> + struct do_locked1_state state = { .value = value };
> + int ret = false;
> + NTSTATUS status;
> +
> + db = db_open(talloc_tos(), dbname, 0, TDB_CLEAR_IF_FIRST,
> + O_CREAT|O_RDWR, 0644, DBWRAP_LOCK_ORDER_1,
> + DBWRAP_FLAG_NONE);
> + if (db == NULL) {
> + fprintf(stderr, "db_open failed: %s\n", strerror(errno));
> + return false;
> + }
> +
> + status = dbwrap_do_locked(db, key, do_locked1_cb, &state);
> + if (!NT_STATUS_IS_OK(status)) {
> + fprintf(stderr, "dbwrap_do_locked failed: %s\n",
> + nt_errstr(status));
> + goto fail;
> + }
> + if (!NT_STATUS_IS_OK(state.status)) {
> + fprintf(stderr, "store returned %s\n", nt_errstr(status));
> + goto fail;
> + }
> +
> + status = dbwrap_parse_record(db, key, do_locked1_check, &state);
> + if (!NT_STATUS_IS_OK(status)) {
> + fprintf(stderr, "dbwrap_parse_record failed: %s\n",
> + nt_errstr(status));
> + goto fail;
> + }
> + if (!NT_STATUS_IS_OK(state.status)) {
> + fprintf(stderr, "data compare returned %s\n",
> + nt_errstr(status));
> + goto fail;
> + }
> +
> + status = dbwrap_do_locked(db, key, do_locked1_del, &state);
> + if (!NT_STATUS_IS_OK(status)) {
> + fprintf(stderr, "dbwrap_do_locked failed: %s\n",
> + nt_errstr(status));
> + goto fail;
> + }
> + if (!NT_STATUS_IS_OK(state.status)) {
> + fprintf(stderr, "delete returned %s\n", nt_errstr(status));
> + goto fail;
> + }
> +
> + status = dbwrap_parse_record(db, key, do_locked1_check, &state);
> + if (!NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) {
> + fprintf(stderr, "parse_record returned %s, "
> + "expected NOT_FOUND\n", nt_errstr(status));
> + goto fail;
> + }
> +
> + ret = true;
> +fail:
> + TALLOC_FREE(db);
> + unlink(dbname);
> + return ret;
> +}
> diff --git a/source3/torture/torture.c b/source3/torture/torture.c
> index 64caca5..b8d4f5e 100644
> --- a/source3/torture/torture.c
> +++ b/source3/torture/torture.c
> @@ -11523,6 +11523,7 @@ static struct {
> { "LOCAL-TALLOC-DICT", run_local_talloc_dict, 0},
> { "LOCAL-DBWRAP-WATCH1", run_dbwrap_watch1, 0 },
> { "LOCAL-DBWRAP-WATCH2", run_dbwrap_watch2, 0 },
> + { "LOCAL-DBWRAP-DO-LOCKED1", run_dbwrap_do_locked1, 0 },
> { "LOCAL-MESSAGING-READ1", run_messaging_read1, 0 },
> { "LOCAL-MESSAGING-READ2", run_messaging_read2, 0 },
> { "LOCAL-MESSAGING-READ3", run_messaging_read3, 0 },
> diff --git a/source3/wscript_build b/source3/wscript_build
> index a030b8a..99f4a2b 100644
> --- a/source3/wscript_build
> +++ b/source3/wscript_build
> @@ -1203,6 +1203,7 @@ bld.SAMBA3_BINARY('smbtorture' + bld.env.suffix3,
> torture/test_notify.c
> lib/tevent_barrier.c
> torture/test_dbwrap_watch.c
> + torture/test_dbwrap_do_locked.c
> torture/test_idmap_tdb_common.c
> torture/test_dbwrap_ctdb.c
> torture/test_buffersize.c
> --
> 2.1.4
>
>
> From 580a069ca0412a1f3e6efd67b8aac3b2a2d37ed5 Mon Sep 17 00:00:00 2001
> From: Volker Lendecke <vl at samba.org>
> Date: Tue, 27 Jun 2017 08:25:03 +0200
> Subject: [PATCH 07/41] dbwrap_tdb: Implement do_locked
>
> Signed-off-by: Volker Lendecke <vl at samba.org>
> ---
> lib/dbwrap/dbwrap_tdb.c | 47 +++++++++++++++++++++++++++++++++++++++++++++++
> 1 file changed, 47 insertions(+)
>
> diff --git a/lib/dbwrap/dbwrap_tdb.c b/lib/dbwrap/dbwrap_tdb.c
> index 9f8a9a6..c30bede 100644
> --- a/lib/dbwrap/dbwrap_tdb.c
> +++ b/lib/dbwrap/dbwrap_tdb.c
> @@ -25,6 +25,7 @@
> #include "lib/util/util_tdb.h"
> #include "system/filesys.h"
> #include "lib/param/param.h"
> +#include "libcli/util/error.h"
>
> struct db_tdb_ctx {
> struct tdb_wrap *wtdb;
> @@ -174,6 +175,51 @@ static struct db_record *db_tdb_try_fetch_locked(
> return db_tdb_fetch_locked_internal(db, mem_ctx, key);
> }
>
> +static NTSTATUS db_tdb_do_locked(struct db_context *db, TDB_DATA key,
> + void (*fn)(struct db_record *rec,
> + void *private_data),
> + void *private_data)
> +{
> + struct db_tdb_ctx *ctx = talloc_get_type_abort(
> + db->private_data, struct db_tdb_ctx);
> + uint8_t *buf = NULL;
> + struct db_record rec;
> + int ret;
> +
> + ret = tdb_chainlock(ctx->wtdb->tdb, key);
> + if (ret == -1) {
> + enum TDB_ERROR err = tdb_error(ctx->wtdb->tdb);
> + DBG_DEBUG("tdb_chainlock failed: %s\n",
> + tdb_errorstr(ctx->wtdb->tdb));
> + return map_nt_error_from_tdb(err);
> + }
> +
> + ret = tdb_fetch_talloc(ctx->wtdb->tdb, key, ctx, &buf);
> +
> + if ((ret != 0) && (ret != ENOENT)) {
> + DBG_DEBUG("tdb_fetch_talloc failed: %s\n",
> + strerror(errno));
> + tdb_chainunlock(ctx->wtdb->tdb, key);
> + return map_nt_error_from_unix_common(ret);
> + }
> +
> + rec = (struct db_record) {
> + .db = db, .key = key,
> + .value = (struct TDB_DATA) { .dptr = buf,
> + .dsize = talloc_get_size(buf) },
> + .storev = db_tdb_storev, .delete_rec = db_tdb_delete,
> + .private_data = ctx
> + };
> +
> + fn(&rec, private_data);
> +
> + talloc_free(buf);
> +
> + tdb_chainunlock(ctx->wtdb->tdb, key);
> +
> + return NT_STATUS_OK;
> +}
> +
> static int db_tdb_exists(struct db_context *db, TDB_DATA key)
> {
> struct db_tdb_ctx *ctx = talloc_get_type_abort(
> @@ -446,6 +492,7 @@ struct db_context *db_open_tdb(TALLOC_CTX *mem_ctx,
>
> result->fetch_locked = db_tdb_fetch_locked;
> result->try_fetch_locked = db_tdb_try_fetch_locked;
> + result->do_locked = db_tdb_do_locked;
> result->traverse = db_tdb_traverse;
> result->traverse_read = db_tdb_traverse_read;
> result->parse_record = db_tdb_parse;
> --
> 2.1.4
>
>
> From bd8fad4cadce98d9f864fd578288822685a93692 Mon Sep 17 00:00:00 2001
> From: Volker Lendecke <vl at samba.org>
> Date: Sat, 1 Jul 2017 18:13:44 +0200
> Subject: [PATCH 08/41] dbwrap_watch: Introduce dbwrap_watch_rec
>
> The idea is to leave the "watchers" array unparsed until it's needed. This
> avoids a few talloc calls and unnecessary parsing.
>
> Also, it deletes quite a few lines of code and .text bytes.
>
> Signed-off-by: Volker Lendecke <vl at samba.org>
> ---
> source3/lib/dbwrap/dbwrap_watch.c | 325 +++++++++++++++-----------------------
> 1 file changed, 130 insertions(+), 195 deletions(-)
>
> diff --git a/source3/lib/dbwrap/dbwrap_watch.c b/source3/lib/dbwrap/dbwrap_watch.c
> index ab59803..6461067 100644
> --- a/source3/lib/dbwrap/dbwrap_watch.c
> +++ b/source3/lib/dbwrap/dbwrap_watch.c
> @@ -116,16 +116,23 @@ static bool dbwrap_record_watchers_key_parse(
> #define NUM_WATCHERS_DELETED_BIT (1UL<<31)
> #define NUM_WATCHERS_MASK (NUM_WATCHERS_DELETED_BIT-1)
>
> -static ssize_t dbwrap_watched_parse(TDB_DATA data, struct server_id *ids,
> - size_t num_ids, bool *pdeleted,
> - TDB_DATA *pdata)
> +struct dbwrap_watch_rec {
> + uint8_t *watchers;
> + size_t num_watchers;
> + bool deleted;
> + TDB_DATA data;
> +};
> +
> +static bool dbwrap_watch_rec_parse(TDB_DATA data,
> + struct dbwrap_watch_rec *wrec)
> {
> - size_t i, num_watchers;
> + size_t num_watchers;
> bool deleted;
> + TDB_DATA userdata = { 0 };
>
> if (data.dsize < sizeof(uint32_t)) {
> /* Fresh or invalid record */
> - return -1;
> + return false;
> }
>
> num_watchers = IVAL(data.dptr, 0);
> @@ -138,93 +145,47 @@ static ssize_t dbwrap_watched_parse(TDB_DATA data, struct server_id *ids,
>
> if (num_watchers > data.dsize/SERVER_ID_BUF_LENGTH) {
> /* Invalid record */
> - return -1;
> - }
> -
> - if (num_watchers > num_ids) {
> - /*
> - * Not enough space to store the watchers server_id's.
> - * Just move past all of them to allow the remaining part
> - * of the record to be returned.
> - */
> - data.dptr += num_watchers * SERVER_ID_BUF_LENGTH;
> - data.dsize -= num_watchers * SERVER_ID_BUF_LENGTH;
> - goto done;
> + return false;
> }
>
> - /*
> - * Note, even if marked deleted we still must
> - * return the id's array to allow awoken
> - * watchers to remove themselves.
> - */
> -
> - for (i=0; i<num_watchers; i++) {
> - server_id_get(&ids[i], data.dptr);
> - data.dptr += SERVER_ID_BUF_LENGTH;
> - data.dsize -= SERVER_ID_BUF_LENGTH;
> + if (!deleted) {
> + size_t watchers_len = num_watchers * SERVER_ID_BUF_LENGTH;
> + userdata = (TDB_DATA) {
> + .dptr = data.dptr + watchers_len,
> + .dsize = data.dsize - watchers_len
> + };
> }
>
> -done:
> - if (deleted) {
> - data = (TDB_DATA) {0};
> - }
> - if (pdata != NULL) {
> - *pdata = data;
> - }
> - if (pdeleted != NULL) {
> - *pdeleted = deleted;
> - }
> + *wrec = (struct dbwrap_watch_rec) {
> + .watchers = data.dptr, .num_watchers = num_watchers,
> + .deleted = deleted, .data = userdata
> + };
>
> - return num_watchers;
> + return true;
> }
>
> -static ssize_t dbwrap_watched_unparse(const struct server_id *watchers,
> - size_t num_watchers, bool deleted,
> - TDB_DATA data,
> - uint8_t *buf, size_t buflen)
> +static void dbwrap_watch_rec_get_watcher(
> + struct dbwrap_watch_rec *wrec, size_t i, struct server_id *watcher)
> {
> - size_t i, len, ofs;
> - uint32_t num_watchers_buf;
> -
> - if (num_watchers > UINT32_MAX/SERVER_ID_BUF_LENGTH) {
> - return -1;
> + if (i >= wrec->num_watchers) {
> + abort();
> }
> + server_id_get(watcher, wrec->watchers + i * SERVER_ID_BUF_LENGTH);
> +}
>
> - len = num_watchers * SERVER_ID_BUF_LENGTH;
> -
> - len += sizeof(uint32_t);
> - if (len < sizeof(uint32_t)) {
> - return -1;
> - }
> -
> - len += data.dsize;
> - if (len < data.dsize) {
> - return -1;
> - }
> -
> - if (len > buflen) {
> - return len;
> - }
> -
> - num_watchers_buf = num_watchers;
> - if (deleted) {
> - num_watchers_buf |= NUM_WATCHERS_DELETED_BIT;
> - }
> -
> - ofs = 0;
> - SIVAL(buf, ofs, num_watchers_buf);
> - ofs += 4;
> -
> - for (i=0; i<num_watchers; i++) {
> - server_id_put(buf+ofs, watchers[i]);
> - ofs += SERVER_ID_BUF_LENGTH;
> +static void dbwrap_watch_rec_del_watcher(struct dbwrap_watch_rec *wrec,
> + size_t i)
> +{
> + if (i >= wrec->num_watchers) {
> + abort();
> }
> -
> - if ((data.dptr != NULL) && (data.dsize != 0)) {
> - memcpy(buf + ofs, data.dptr, data.dsize);
> + wrec->num_watchers -= 1;
> + if (i < wrec->num_watchers) {
> + uint8_t *wptr = wrec->watchers + i*SERVER_ID_BUF_LENGTH;
> + memcpy(wptr,
> + wrec->watchers+wrec->num_watchers*SERVER_ID_BUF_LENGTH,
> + SERVER_ID_BUF_LENGTH);
> }
> -
> - return len;
> }
>
> struct db_watched_ctx {
> @@ -234,8 +195,7 @@ struct db_watched_ctx {
>
> struct db_watched_subrec {
> struct db_record *subrec;
> - struct server_id *watchers;
> - bool deleted;
> + struct dbwrap_watch_rec wrec;
> };
>
> static NTSTATUS dbwrap_watched_storev(struct db_record *rec,
> @@ -251,7 +211,7 @@ static struct db_record *dbwrap_watched_fetch_locked(
> struct db_record *rec;
> struct db_watched_subrec *subrec;
> TDB_DATA subrec_value;
> - ssize_t num_watchers;
> + bool ok;
>
> rec = talloc_zero(mem_ctx, struct db_record);
> if (rec == NULL) {
> @@ -277,33 +237,21 @@ static struct db_record *dbwrap_watched_fetch_locked(
>
> subrec_value = dbwrap_record_get_value(subrec->subrec);
>
> - num_watchers = dbwrap_watched_parse(subrec_value, NULL, 0, NULL, NULL);
> - if (num_watchers == -1) {
> - /* Fresh or invalid record */
> - rec->value = (TDB_DATA) { 0 };
> - return rec;
> - }
> -
> - subrec->watchers = talloc_array(subrec, struct server_id,
> - num_watchers);
> - if (subrec->watchers == NULL) {
> - TALLOC_FREE(rec);
> - return NULL;
> + ok = dbwrap_watch_rec_parse(subrec_value, &subrec->wrec);
> + if (ok) {
> + rec->value = subrec->wrec.data;
> }
>
> - dbwrap_watched_parse(subrec_value, subrec->watchers, num_watchers,
> - &subrec->deleted, &rec->value);
> -
> return rec;
> }
>
> static void dbwrap_watched_wakeup(struct db_record *rec,
> - struct db_watched_subrec *subrec)
> + struct dbwrap_watch_rec *wrec)
> {
> - struct db_context *db = dbwrap_record_get_db(rec);
> + struct db_context *db = rec->db;
> struct db_watched_ctx *ctx = talloc_get_type_abort(
> db->private_data, struct db_watched_ctx);
> - size_t i, num_watchers;
> + size_t i;
> size_t db_id_len = dbwrap_db_id(db, NULL, 0);
> uint8_t db_id[db_id_len];
> uint8_t len_buf[4];
> @@ -318,32 +266,27 @@ static void dbwrap_watched_wakeup(struct db_record *rec,
>
> dbwrap_db_id(db, db_id, db_id_len);
>
> - num_watchers = talloc_array_length(subrec->watchers);
> -
> i = 0;
>
> - while (i < num_watchers) {
> + while (i < wrec->num_watchers) {
> + struct server_id watcher;
> NTSTATUS status;
> struct server_id_buf tmp;
>
> - DBG_DEBUG("Alerting %s\n",
> - server_id_str_buf(subrec->watchers[i], &tmp));
> + dbwrap_watch_rec_get_watcher(wrec, i, &watcher);
>
> - status = messaging_send_iov(ctx->msg, subrec->watchers[i],
> + DBG_DEBUG("Alerting %s\n", server_id_str_buf(watcher, &tmp));
> +
> + status = messaging_send_iov(ctx->msg, watcher,
> MSG_DBWRAP_MODIFIED,
> iov, ARRAY_SIZE(iov), NULL, 0);
> if (!NT_STATUS_IS_OK(status)) {
> DBG_DEBUG("messaging_send_iov to %s failed: %s\n",
> - server_id_str_buf(subrec->watchers[i], &tmp),
> + server_id_str_buf(watcher, &tmp),
> nt_errstr(status));
> }
> if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
> - subrec->watchers[i] = subrec->watchers[num_watchers-1];
> - num_watchers -= 1;
> -
> - subrec->watchers = talloc_realloc(
> - subrec, subrec->watchers, struct server_id,
> - num_watchers);
> + dbwrap_watch_rec_del_watcher(wrec, i);
> continue;
> }
>
> @@ -351,61 +294,68 @@ static void dbwrap_watched_wakeup(struct db_record *rec,
> }
> }
>
> -static NTSTATUS dbwrap_watched_save(struct db_watched_subrec *subrec,
> - TDB_DATA data, int flag)
> +static NTSTATUS dbwrap_watched_save(struct db_record *rec,
> + struct dbwrap_watch_rec *wrec,
> + struct server_id *addwatch,
> + const TDB_DATA *databufs,
> + size_t num_databufs,
> + int flags)
> {
> - size_t num_watchers;
> - ssize_t len;
> - uint8_t *buf;
> + uint32_t num_watchers_buf;
> + uint8_t sizebuf[4];
> + uint8_t addbuf[SERVER_ID_BUF_LENGTH];
> NTSTATUS status;
> + struct TDB_DATA dbufs[num_databufs+3];
>
> - num_watchers = talloc_array_length(subrec->watchers);
> + dbufs[0] = (TDB_DATA) {
> + .dptr = sizebuf, .dsize = sizeof(sizebuf)
> + };
>
> - len = dbwrap_watched_unparse(subrec->watchers, num_watchers,
> - subrec->deleted, data, NULL, 0);
> - if (len == -1) {
> - return NT_STATUS_INSUFFICIENT_RESOURCES;
> - }
> + dbufs[1] = (TDB_DATA) {
> + .dptr = wrec->watchers,
> + .dsize = wrec->num_watchers * SERVER_ID_BUF_LENGTH
> + };
>
> - buf = talloc_array(subrec, uint8_t, len);
> - if (buf == NULL) {
> - return NT_STATUS_NO_MEMORY;
> + if (addwatch != NULL) {
> + server_id_put(addbuf, *addwatch);
> +
> + dbufs[2] = (TDB_DATA) {
> + .dptr = addbuf, .dsize = SERVER_ID_BUF_LENGTH
> + };
> + wrec->num_watchers += 1;
> + } else {
> + dbufs[2] = (TDB_DATA) { 0 };
> }
>
> - dbwrap_watched_unparse(subrec->watchers, num_watchers,
> - subrec->deleted, data, buf, len);
> + if (num_databufs != 0) {
> + memcpy(&dbufs[3], databufs, sizeof(TDB_DATA) * num_databufs);
> + }
>
> - status = dbwrap_record_store(
> - subrec->subrec, (TDB_DATA) { .dptr = buf, .dsize = len },
> - flag);
> + num_watchers_buf = wrec->num_watchers;
> + if (wrec->deleted) {
> + num_watchers_buf |= NUM_WATCHERS_DELETED_BIT;
> + }
>
> - TALLOC_FREE(buf);
> + SIVAL(sizebuf, 0, num_watchers_buf);
>
> + status = dbwrap_record_storev(rec, dbufs, ARRAY_SIZE(dbufs), flags);
> return status;
> }
>
> static NTSTATUS dbwrap_watched_storev(struct db_record *rec,
> const TDB_DATA *dbufs, int num_dbufs,
> - int flag)
> + int flags)
> {
> struct db_watched_subrec *subrec = talloc_get_type_abort(
> rec->private_data, struct db_watched_subrec);
> NTSTATUS status;
> - TDB_DATA data;
>
> - data = dbwrap_merge_dbufs(rec, dbufs, num_dbufs);
> - if (data.dptr == NULL) {
> - return NT_STATUS_NO_MEMORY;
> - }
> -
> - dbwrap_watched_wakeup(rec, subrec);
> -
> - subrec->deleted = false;
> + dbwrap_watched_wakeup(rec, &subrec->wrec);
>
> - status = dbwrap_watched_save(subrec, data, flag);
> -
> - TALLOC_FREE(data.dptr);
> + subrec->wrec.deleted = false;
>
> + status = dbwrap_watched_save(subrec->subrec, &subrec->wrec, NULL,
> + dbufs, num_dbufs, flags);
> return status;
> }
>
> @@ -413,18 +363,17 @@ static NTSTATUS dbwrap_watched_delete(struct db_record *rec)
> {
> struct db_watched_subrec *subrec = talloc_get_type_abort(
> rec->private_data, struct db_watched_subrec);
> - size_t num_watchers;
>
> - dbwrap_watched_wakeup(rec, subrec);
> + dbwrap_watched_wakeup(rec, &subrec->wrec);
>
> - num_watchers = talloc_array_length(subrec->watchers);
> - if (num_watchers == 0) {
> + if (subrec->wrec.num_watchers == 0) {
> return dbwrap_record_delete(subrec->subrec);
> }
>
> - subrec->deleted = true;
> + subrec->wrec.deleted = true;
>
> - return dbwrap_watched_save(subrec, (TDB_DATA) {0}, 0);
> + return dbwrap_watched_save(subrec->subrec, &subrec->wrec,
> + NULL, NULL, 0, 0);
> }
>
> struct dbwrap_watched_traverse_state {
> @@ -436,17 +385,17 @@ static int dbwrap_watched_traverse_fn(struct db_record *rec,
> void *private_data)
> {
> struct dbwrap_watched_traverse_state *state = private_data;
> - ssize_t num_watchers;
> struct db_record prec = *rec;
> - bool deleted;
> -
> - num_watchers = dbwrap_watched_parse(rec->value, NULL, 0, &deleted,
> - &prec.value);
> + struct dbwrap_watch_rec wrec;
> + bool ok;
>
> - if ((num_watchers == -1) || deleted) {
> + ok = dbwrap_watch_rec_parse(rec->value, &wrec);
> + if (!ok || wrec.deleted) {
> return 0;
> }
>
> + prec.value = wrec.data;
> +
> return state->fn(&prec, state->private_data);
> }
>
> @@ -528,18 +477,16 @@ static void dbwrap_watched_parse_record_parser(TDB_DATA key, TDB_DATA data,
> void *private_data)
> {
> struct dbwrap_watched_parse_record_state *state = private_data;
> - ssize_t num_watchers;
> - TDB_DATA userdata;
> + struct dbwrap_watch_rec wrec;
> + bool ok;
>
> - num_watchers = dbwrap_watched_parse(data, NULL, 0, &state->deleted,
> - &userdata);
> - if (num_watchers == -1) {
> + ok = dbwrap_watch_rec_parse(data, &wrec);
> + if ((!ok) || (wrec.deleted)) {
> state->deleted = true;
> - }
> - if (state->deleted) {
> return;
> }
> - state->parser(key, userdata, state->private_data);
> +
> + state->parser(key, wrec.data, state->private_data);
> }
>
> static NTSTATUS dbwrap_watched_parse_record(
> @@ -736,8 +683,6 @@ struct tevent_req *dbwrap_watched_watch_send(TALLOC_CTX *mem_ctx,
> struct tevent_req *req, *subreq;
> struct dbwrap_watched_watch_state *state;
> ssize_t needed;
> - size_t num_watchers;
> - struct server_id *tmp;
> NTSTATUS status;
>
> req = tevent_req_create(mem_ctx, &state,
> @@ -776,17 +721,8 @@ struct tevent_req *dbwrap_watched_watch_send(TALLOC_CTX *mem_ctx,
> }
> tevent_req_set_callback(subreq, dbwrap_watched_watch_done, req);
>
> - num_watchers = talloc_array_length(subrec->watchers);
> -
> - tmp = talloc_realloc(subrec, subrec->watchers, struct server_id,
> - num_watchers + 1);
> - if (tevent_req_nomem(tmp, req)) {
> - return tevent_req_post(req, ev);
> - }
> - subrec->watchers = tmp;
> - subrec->watchers[num_watchers] = state->me;
> -
> - status = dbwrap_watched_save(subrec, rec->value, 0);
> + status = dbwrap_watched_save(subrec->subrec, &subrec->wrec, &state->me,
> + &subrec->wrec.data, 1, 0);
> if (tevent_req_nterror(req, status)) {
> return tevent_req_post(req, ev);
> }
> @@ -823,30 +759,27 @@ static void dbwrap_watched_watch_blocker_died(struct tevent_req *subreq)
> tevent_req_done(req);
> }
>
> -static bool dbwrap_watched_remove_waiter(struct db_watched_subrec *subrec,
> +static bool dbwrap_watched_remove_waiter(struct dbwrap_watch_rec *wrec,
> struct server_id id)
> {
> - size_t i, num_watchers;
> + size_t i;
>
> - num_watchers = talloc_array_length(subrec->watchers);
> -
> - for (i=0; i<num_watchers; i++) {
> - if (server_id_equal(&id, &subrec->watchers[i])) {
> + for (i=0; i<wrec->num_watchers; i++) {
> + struct server_id watcher;
> + dbwrap_watch_rec_get_watcher(wrec, i, &watcher);
> + if (server_id_equal(&id, &watcher)) {
> break;
> }
> }
>
> - if (i == num_watchers) {
> + if (i == wrec->num_watchers) {
> struct server_id_buf buf;
> DBG_WARNING("Did not find %s in state->watchers\n",
> server_id_str_buf(id, &buf));
> return false;
> }
>
> - subrec->watchers[i] = subrec->watchers[num_watchers-1];
> - subrec->watchers = talloc_realloc(subrec, subrec->watchers,
> - struct server_id, num_watchers-1);
> -
> + dbwrap_watch_rec_del_watcher(wrec, i);
> return true;
> }
>
> @@ -873,10 +806,11 @@ static int dbwrap_watched_watch_state_destructor(
> subrec = talloc_get_type_abort(
> rec->private_data, struct db_watched_subrec);
>
> - ok = dbwrap_watched_remove_waiter(subrec, state->me);
> + ok = dbwrap_watched_remove_waiter(&subrec->wrec, state->me);
> if (ok) {
> NTSTATUS status;
> - status = dbwrap_watched_save(subrec, rec->value, 0);
> + status = dbwrap_watched_save(subrec->subrec, &subrec->wrec,
> + NULL, &subrec->wrec.data, 1, 0);
> if (!NT_STATUS_IS_OK(status)) {
> DBG_WARNING("dbwrap_watched_save failed: %s\n",
> nt_errstr(status));
> @@ -967,9 +901,10 @@ NTSTATUS dbwrap_watched_watch_recv(struct tevent_req *req,
> subrec = talloc_get_type_abort(
> rec->private_data, struct db_watched_subrec);
>
> - ok = dbwrap_watched_remove_waiter(subrec, state->me);
> + ok = dbwrap_watched_remove_waiter(&subrec->wrec, state->me);
> if (ok) {
> - status = dbwrap_watched_save(subrec, rec->value, 0);
> + status = dbwrap_watched_save(subrec->subrec, &subrec->wrec,
> + NULL, &subrec->wrec.data, 1, 0);
> if (!NT_STATUS_IS_OK(status)) {
> DBG_WARNING("dbwrap_watched_save failed: %s\n",
> nt_errstr(status));
> --
> 2.1.4
>
>
> From 8e8a3709330f06a38d148f9dbd75ceda4bcf548a Mon Sep 17 00:00:00 2001
> From: Volker Lendecke <vl at samba.org>
> Date: Tue, 27 Jun 2017 18:40:28 +0200
> Subject: [PATCH 09/41] dbwrap_watch: Implement do_locked
>
> Signed-off-by: Volker Lendecke <vl at samba.org>
> ---
> source3/lib/dbwrap/dbwrap_watch.c | 167 +++++++++++++++++++++++++++++---
> source3/torture/test_dbwrap_do_locked.c | 32 +++++-
> 2 files changed, 182 insertions(+), 17 deletions(-)
>
> diff --git a/source3/lib/dbwrap/dbwrap_watch.c b/source3/lib/dbwrap/dbwrap_watch.c
> index 6461067..be0a0d3 100644
> --- a/source3/lib/dbwrap/dbwrap_watch.c
> +++ b/source3/lib/dbwrap/dbwrap_watch.c
> @@ -198,10 +198,23 @@ struct db_watched_subrec {
> struct dbwrap_watch_rec wrec;
> };
>
> +static NTSTATUS dbwrap_watched_subrec_storev(
> + struct db_record *rec, struct db_watched_subrec *subrec,
> + const TDB_DATA *dbufs, int num_dbufs, int flags);
> +static NTSTATUS dbwrap_watched_subrec_delete(
> + struct db_record *rec, struct db_watched_subrec *subrec);
> static NTSTATUS dbwrap_watched_storev(struct db_record *rec,
> const TDB_DATA *dbufs, int num_dbufs,
> - int flag);
> + int flags);
> static NTSTATUS dbwrap_watched_delete(struct db_record *rec);
> +static void dbwrap_watched_wakeup(struct db_record *rec,
> + struct dbwrap_watch_rec *wrec);
> +static NTSTATUS dbwrap_watched_save(struct db_record *rec,
> + struct dbwrap_watch_rec *wrec,
> + struct server_id *addwatch,
> + const TDB_DATA *databufs,
> + size_t num_databufs,
> + int flags);
>
> static struct db_record *dbwrap_watched_fetch_locked(
> struct db_context *db, TALLOC_CTX *mem_ctx, TDB_DATA key)
> @@ -245,6 +258,95 @@ static struct db_record *dbwrap_watched_fetch_locked(
> return rec;
> }
>
> +struct dbwrap_watched_do_locked_state {
> + TALLOC_CTX *mem_ctx;
> + struct db_context *db;
> + void (*fn)(struct db_record *rec, void *private_data);
> + void *private_data;
> +
> + struct db_watched_subrec subrec;
> +
> + NTSTATUS status;
> +};
> +
> +static NTSTATUS dbwrap_watched_do_locked_storev(
> + struct db_record *rec, const TDB_DATA *dbufs, int num_dbufs,
> + int flags)
> +{
> + struct dbwrap_watched_do_locked_state *state = rec->private_data;
> + struct db_watched_subrec *subrec = &state->subrec;
> + NTSTATUS status;
> +
> + status = dbwrap_watched_subrec_storev(rec, subrec, dbufs, num_dbufs,
> + flags);
> + return status;
> +}
> +
> +static NTSTATUS dbwrap_watched_do_locked_delete(struct db_record *rec)
> +{
> + struct dbwrap_watched_do_locked_state *state = rec->private_data;
> + struct db_watched_subrec *subrec = &state->subrec;
> + NTSTATUS status;
> +
> + status = dbwrap_watched_subrec_delete(rec, subrec);
> + return status;
> +}
> +
> +static void dbwrap_watched_do_locked_fn(struct db_record *subrec,
> + void *private_data)
> +{
> + struct dbwrap_watched_do_locked_state *state =
> + (struct dbwrap_watched_do_locked_state *)private_data;
> + TDB_DATA subrec_value = dbwrap_record_get_value(subrec);
> + struct db_record rec;
> + bool ok;
> +
> + rec = (struct db_record) {
> + .db = state->db, .key = dbwrap_record_get_key(subrec),
> + .storev = dbwrap_watched_do_locked_storev,
> + .delete_rec = dbwrap_watched_do_locked_delete,
> + .private_data = state
> + };
> +
> + state->subrec = (struct db_watched_subrec) {
> + .subrec = subrec
> + };
> +
> + ok = dbwrap_watch_rec_parse(subrec_value, &state->subrec.wrec);
> + if (ok) {
> + rec.value = state->subrec.wrec.data;
> + }
> +
> + state->fn(&rec, state->private_data);
> +}
> +
> +static NTSTATUS dbwrap_watched_do_locked(struct db_context *db, TDB_DATA key,
> + void (*fn)(struct db_record *rec,
> + void *private_data),
> + void *private_data)
> +{
> + struct db_watched_ctx *ctx = talloc_get_type_abort(
> + db->private_data, struct db_watched_ctx);
> + struct dbwrap_watched_do_locked_state state = {
> + .mem_ctx = talloc_stackframe(),
> + .db = db, .fn = fn, .private_data = private_data
> + };
> + NTSTATUS status;
> +
> + status = dbwrap_do_locked(
> + ctx->backend, key, dbwrap_watched_do_locked_fn, &state);
> + TALLOC_FREE(state.mem_ctx);
> + if (!NT_STATUS_IS_OK(status)) {
> + DBG_DEBUG("dbwrap_do_locked returned %s\n", nt_errstr(status));
> + return status;
> + }
> +
> + DBG_DEBUG("dbwrap_watched_do_locked_fn returned %s\n",
> + nt_errstr(state.status));
> +
> + return state.status;
> +}
> +
> static void dbwrap_watched_wakeup(struct db_record *rec,
> struct dbwrap_watch_rec *wrec)
> {
> @@ -342,12 +444,10 @@ static NTSTATUS dbwrap_watched_save(struct db_record *rec,
> return status;
> }
>
> -static NTSTATUS dbwrap_watched_storev(struct db_record *rec,
> - const TDB_DATA *dbufs, int num_dbufs,
> - int flags)
> +static NTSTATUS dbwrap_watched_subrec_storev(
> + struct db_record *rec, struct db_watched_subrec *subrec,
> + const TDB_DATA *dbufs, int num_dbufs, int flags)
> {
> - struct db_watched_subrec *subrec = talloc_get_type_abort(
> - rec->private_data, struct db_watched_subrec);
> NTSTATUS status;
>
> dbwrap_watched_wakeup(rec, &subrec->wrec);
> @@ -359,10 +459,23 @@ static NTSTATUS dbwrap_watched_storev(struct db_record *rec,
> return status;
> }
>
> -static NTSTATUS dbwrap_watched_delete(struct db_record *rec)
> +static NTSTATUS dbwrap_watched_storev(struct db_record *rec,
> + const TDB_DATA *dbufs, int num_dbufs,
> + int flags)
> {
> struct db_watched_subrec *subrec = talloc_get_type_abort(
> rec->private_data, struct db_watched_subrec);
> + NTSTATUS status;
> +
> + status = dbwrap_watched_subrec_storev(rec, subrec, dbufs, num_dbufs,
> + flags);
> + return status;
> +}
> +
> +static NTSTATUS dbwrap_watched_subrec_delete(
> + struct db_record *rec, struct db_watched_subrec *subrec)
> +{
> + NTSTATUS status;
>
> dbwrap_watched_wakeup(rec, &subrec->wrec);
>
> @@ -372,8 +485,19 @@ static NTSTATUS dbwrap_watched_delete(struct db_record *rec)
>
> subrec->wrec.deleted = true;
>
> - return dbwrap_watched_save(subrec->subrec, &subrec->wrec,
> - NULL, NULL, 0, 0);
> + status = dbwrap_watched_save(subrec->subrec, &subrec->wrec,
> + NULL, NULL, 0, 0);
> + return status;
> +}
> +
> +static NTSTATUS dbwrap_watched_delete(struct db_record *rec)
> +{
> + struct db_watched_subrec *subrec = talloc_get_type_abort(
> + rec->private_data, struct db_watched_subrec);
> + NTSTATUS status;
> +
> + status = dbwrap_watched_subrec_delete(rec, subrec);
> + return status;
> }
>
> struct dbwrap_watched_traverse_state {
> @@ -638,6 +762,7 @@ struct db_context *db_open_watched(TALLOC_CTX *mem_ctx,
> ctx->backend = talloc_move(ctx, &backend);
>
> db->fetch_locked = dbwrap_watched_fetch_locked;
> + db->do_locked = dbwrap_watched_do_locked;
> db->traverse = dbwrap_watched_traverse;
> db->traverse_read = dbwrap_watched_traverse_read;
> db->get_seqnum = dbwrap_watched_get_seqnum;
> @@ -674,12 +799,10 @@ struct tevent_req *dbwrap_watched_watch_send(TALLOC_CTX *mem_ctx,
> struct db_record *rec,
> struct server_id blocker)
> {
> - struct db_watched_subrec *subrec = talloc_get_type_abort(
> - rec->private_data, struct db_watched_subrec);
> struct db_context *db = dbwrap_record_get_db(rec);
> struct db_watched_ctx *ctx = talloc_get_type_abort(
> db->private_data, struct db_watched_ctx);
> -
> + struct db_watched_subrec *subrec = NULL;
> struct tevent_req *req, *subreq;
> struct dbwrap_watched_watch_state *state;
> ssize_t needed;
> @@ -698,6 +821,26 @@ struct tevent_req *dbwrap_watched_watch_send(TALLOC_CTX *mem_ctx,
> return tevent_req_post(req, ev);
> }
>
> + /*
> + * Figure out whether we're called as part of do_locked. If
> + * so, we can't use talloc_get_type_abort, the
> + * db_watched_subrec is stack-allocated in that case.
> + */
> +
> + if (rec->storev == dbwrap_watched_storev) {
> + subrec = talloc_get_type_abort(rec->private_data,
> + struct db_watched_subrec);
> + }
> + if (rec->storev == dbwrap_watched_do_locked_storev) {
> + struct dbwrap_watched_do_locked_state *do_locked_state;
> + do_locked_state = rec->private_data;
> + subrec = &do_locked_state->subrec;
> + }
> + if (subrec == NULL) {
> + tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
> + return tevent_req_post(req, ev);
> + }
> +
> state->me = messaging_server_id(ctx->msg);
>
> needed = dbwrap_record_watchers_key(db, rec, NULL, 0);
> diff --git a/source3/torture/test_dbwrap_do_locked.c b/source3/torture/test_dbwrap_do_locked.c
> index 92dec38..46b326b 100644
> --- a/source3/torture/test_dbwrap_do_locked.c
> +++ b/source3/torture/test_dbwrap_do_locked.c
> @@ -65,6 +65,9 @@ static void do_locked1_del(struct db_record *rec, void *private_data)
>
> bool run_dbwrap_do_locked1(int dummy)
> {
> + struct tevent_context *ev;
> + struct messaging_context *msg;
> + struct db_context *backend;
> struct db_context *db;
> const char *dbname = "test_do_locked.tdb";
> const char *keystr = "key";
> @@ -75,14 +78,32 @@ bool run_dbwrap_do_locked1(int dummy)
> int ret = false;
> NTSTATUS status;
>
> - db = db_open(talloc_tos(), dbname, 0, TDB_CLEAR_IF_FIRST,
> - O_CREAT|O_RDWR, 0644, DBWRAP_LOCK_ORDER_1,
> - DBWRAP_FLAG_NONE);
> - if (db == NULL) {
> + ev = server_event_context();
> + if (ev == NULL) {
> + fprintf(stderr, "server_event_context() failed\n");
> + return false;
> + }
> + msg = server_messaging_context();
> + if (msg == NULL) {
> + fprintf(stderr, "server_messaging_context() failed\n");
> + return false;
> + }
> +
> + backend = db_open(talloc_tos(), dbname, 0,
> + TDB_CLEAR_IF_FIRST, O_CREAT|O_RDWR, 0644,
> + DBWRAP_LOCK_ORDER_1, DBWRAP_FLAG_NONE);
> + if (backend == NULL) {
> fprintf(stderr, "db_open failed: %s\n", strerror(errno));
> return false;
> }
>
> + db = db_open_watched(talloc_tos(), backend, msg);
> + if (db == NULL) {
> + fprintf(stderr, "db_open_watched failed: %s\n",
> + strerror(errno));
> + return false;
> + }
> +
> status = dbwrap_do_locked(db, key, do_locked1_cb, &state);
> if (!NT_STATUS_IS_OK(status)) {
> fprintf(stderr, "dbwrap_do_locked failed: %s\n",
> @@ -90,7 +111,8 @@ bool run_dbwrap_do_locked1(int dummy)
> goto fail;
> }
> if (!NT_STATUS_IS_OK(state.status)) {
> - fprintf(stderr, "store returned %s\n", nt_errstr(status));
> + fprintf(stderr, "store returned %s\n",
> + nt_errstr(state.status));
> goto fail;
> }
>
> --
> 2.1.4
>
>
> From db5f5766f8384891f7c0fbd96997a03908c74730 Mon Sep 17 00:00:00 2001
> From: Volker Lendecke <vl at samba.org>
> Date: Wed, 28 Jun 2017 16:21:19 +0200
> Subject: [PATCH 10/41] g_lock: Walk locks only once in g_lock_trylock
>
> Signed-off-by: Volker Lendecke <vl at samba.org>
> ---
> source3/lib/g_lock.c | 13 +++----------
> 1 file changed, 3 insertions(+), 10 deletions(-)
>
> diff --git a/source3/lib/g_lock.c b/source3/lib/g_lock.c
> index 198fe56..a22ec94 100644
> --- a/source3/lib/g_lock.c
> +++ b/source3/lib/g_lock.c
> @@ -297,18 +297,11 @@ static NTSTATUS g_lock_trylock(struct db_record *rec, struct server_id self,
> goto done;
> }
> my_lock = i;
> - break;
> - }
> - }
> -
> - for (i=0; i<num_locks; i++) {
> -
> - if (i == my_lock) {
> continue;
> }
>
> - if (g_lock_conflicts(type, locks[i].lock_type)) {
> - struct server_id pid = locks[i].pid;
> + if (g_lock_conflicts(type, lock->lock_type)) {
> + struct server_id pid = lock->pid;
>
> /*
> * As the serverid_exists might recurse into
> @@ -319,7 +312,7 @@ static NTSTATUS g_lock_trylock(struct db_record *rec, struct server_id self,
>
> if (serverid_exists(&pid)) {
> status = NT_STATUS_LOCK_NOT_GRANTED;
> - *blocker = locks[i].pid;
> + *blocker = lock->pid;
> goto done;
> }
>
> --
> 2.1.4
>
>
> From 0aeadbd41d9dfdf601b18856a8c0e91c807e160a Mon Sep 17 00:00:00 2001
> From: Volker Lendecke <vl at samba.org>
> Date: Wed, 28 Jun 2017 19:12:36 +0200
> Subject: [PATCH 11/41] g_lock: simplify g_lock_trylock
>
> The now mandatory talloc_realloc_array will go away soon
>
> Signed-off-by: Volker Lendecke <vl at samba.org>
> ---
> source3/lib/g_lock.c | 33 ++++++++++++++++++---------------
> 1 file changed, 18 insertions(+), 15 deletions(-)
>
> diff --git a/source3/lib/g_lock.c b/source3/lib/g_lock.c
> index a22ec94..e93ef3f 100644
> --- a/source3/lib/g_lock.c
> +++ b/source3/lib/g_lock.c
> @@ -257,7 +257,7 @@ static NTSTATUS g_lock_trylock(struct db_record *rec, struct server_id self,
> struct server_id *blocker)
> {
> TDB_DATA data, userdata;
> - size_t i, num_locks, my_lock;
> + size_t i, num_locks;
> struct g_lock_rec *locks, *tmp;
> NTSTATUS status;
> bool modified = false;
> @@ -270,8 +270,6 @@ static NTSTATUS g_lock_trylock(struct db_record *rec, struct server_id self,
> return status;
> }
>
> - my_lock = num_locks; /* doesn't exist yet */
> -
> if ((type == G_LOCK_READ) && (num_locks > 0)) {
> /*
> * Read locks can stay around forever if the process
> @@ -296,7 +294,12 @@ static NTSTATUS g_lock_trylock(struct db_record *rec, struct server_id self,
> status = NT_STATUS_WAS_LOCKED;
> goto done;
> }
> - my_lock = i;
> + /*
> + * Remove "our" lock entry. Re-add it later
> + * with our new lock type.
> + */
> + locks[i] = locks[num_locks-1];
> + num_locks -= 1;
> continue;
> }
>
> @@ -325,19 +328,19 @@ static NTSTATUS g_lock_trylock(struct db_record *rec, struct server_id self,
> }
> }
>
> - if (my_lock >= num_locks) {
> - tmp = talloc_realloc(talloc_tos(), locks, struct g_lock_rec,
> - num_locks+1);
> - if (tmp == NULL) {
> - status = NT_STATUS_NO_MEMORY;
> - goto done;
> - }
> - locks = tmp;
> - my_lock = num_locks;
> - num_locks += 1;
> + tmp = talloc_realloc(talloc_tos(), locks, struct g_lock_rec,
> + num_locks+1);
> + if (tmp == NULL) {
> + status = NT_STATUS_NO_MEMORY;
> + goto done;
> }
> + locks = tmp;
> +
> + locks[num_locks] = (struct g_lock_rec) {
> + .pid = self, .lock_type = type
> + };
> + num_locks +=1 ;
>
> - locks[my_lock] = (struct g_lock_rec){ .pid = self, .lock_type = type };
> modified = true;
>
> status = NT_STATUS_OK;
> --
> 2.1.4
>
>
> From 35934b7fa74ae76313f88da470a139490a64e865 Mon Sep 17 00:00:00 2001
> From: Volker Lendecke <vl at samba.org>
> Date: Wed, 28 Jun 2017 13:36:53 +0200
> Subject: [PATCH 12/41] g_lock: add "struct g_lock" without talloc
>
> Enable handing the g_lock.tdb content without having to talloc
>
> Signed-off-by: Volker Lendecke <vl at samba.org>
> ---
> source3/lib/g_lock.c | 85 ++++++++++++++++++++++++++++++++++++++++++++++++++++
> 1 file changed, 85 insertions(+)
>
> diff --git a/source3/lib/g_lock.c b/source3/lib/g_lock.c
> index e93ef3f..e08f6a3 100644
> --- a/source3/lib/g_lock.c
> +++ b/source3/lib/g_lock.c
> @@ -56,6 +56,91 @@ static void g_lock_rec_get(struct g_lock_rec *rec,
> server_id_get(&rec->pid, buf+1);
> }
>
> +struct g_lock {
> + uint8_t *recsbuf;
> + size_t num_recs;
> + uint8_t *data;
> + size_t datalen;
> +};
> +
> +static bool g_lock_parse(uint8_t *buf, size_t buflen, struct g_lock *lck)
> +{
> + size_t found_recs, data_ofs;
> +
> + if (buflen < sizeof(uint32_t)) {
> + *lck = (struct g_lock) {0};
> + return true;
> + }
> +
> + found_recs = IVAL(buf, 0);
> +
> + if (found_recs > buflen/G_LOCK_REC_LENGTH) {
> + return false;
> + }
> +
> + buf += sizeof(uint32_t);
> + buflen -= sizeof(uint32_t);
> + data_ofs = found_recs * G_LOCK_REC_LENGTH;
> +
> + *lck = (struct g_lock) {
> + .recsbuf = buf, .num_recs = found_recs,
> + .data = buf+data_ofs, .datalen = buflen-data_ofs
> + };
> +
> + return true;
> +}
> +
> +static void g_lock_get_rec(struct g_lock *lck, size_t i,
> + struct g_lock_rec *rec)
> +{
> + if (i >= lck->num_recs) {
> + abort();
> + }
> + g_lock_rec_get(rec, lck->recsbuf + i*G_LOCK_REC_LENGTH);
> +}
> +
> +static void g_lock_rec_del(struct g_lock *lck, size_t i)
> +{
> + if (i >= lck->num_recs) {
> + abort();
> + }
> + lck->num_recs -= 1;
> + if (i < lck->num_recs) {
> + uint8_t *recptr = lck->recsbuf + i*G_LOCK_REC_LENGTH;
> + memcpy(recptr, lck->recsbuf + lck->num_recs*G_LOCK_REC_LENGTH,
> + G_LOCK_REC_LENGTH);
> + }
> +}
> +
> +static NTSTATUS g_lock_store(struct db_record *rec, struct g_lock *lck,
> + struct g_lock_rec *add)
> +{
> + uint8_t sizebuf[4];
> + uint8_t addbuf[G_LOCK_REC_LENGTH];
> +
> + struct TDB_DATA dbufs[] = {
> + { .dptr = sizebuf, .dsize = sizeof(sizebuf) },
> + { .dptr = lck->recsbuf,
> + .dsize = lck->num_recs * G_LOCK_REC_LENGTH },
> + { 0 },
> + { .dptr = lck->data, .dsize = lck->datalen }
> + };
> +
> + if (add != NULL) {
> + g_lock_rec_put(addbuf, *add);
> +
> + dbufs[2] = (TDB_DATA) {
> + .dptr = addbuf, .dsize = G_LOCK_REC_LENGTH
> + };
> +
> + lck->num_recs += 1;
> + }
> +
> + SIVAL(sizebuf, 0, lck->num_recs);
> +
> + return dbwrap_record_storev(rec, dbufs, ARRAY_SIZE(dbufs), 0);
> +}
> +
> static ssize_t g_lock_put(uint8_t *buf, size_t buflen,
> const struct g_lock_rec *locks,
> size_t num_locks,
> --
> 2.1.4
>
>
> From 79af16a45e34c5207661569d7492104371689f8f Mon Sep 17 00:00:00 2001
> From: Volker Lendecke <vl at samba.org>
> Date: Wed, 28 Jun 2017 15:39:49 +0200
> Subject: [PATCH 13/41] g_lock: Implement g_lock_unlock without talloc
>
> Signed-off-by: Volker Lendecke <vl at samba.org>
> ---
> source3/lib/g_lock.c | 91 +++++++++++++++++++++++++++++-----------------------
> 1 file changed, 50 insertions(+), 41 deletions(-)
>
> diff --git a/source3/lib/g_lock.c b/source3/lib/g_lock.c
> index e08f6a3..7a924b9 100644
> --- a/source3/lib/g_lock.c
> +++ b/source3/lib/g_lock.c
> @@ -601,63 +601,72 @@ NTSTATUS g_lock_lock(struct g_lock_ctx *ctx, const char *name,
> return status;
> }
>
> -NTSTATUS g_lock_unlock(struct g_lock_ctx *ctx, const char *name)
> -{
> - struct server_id self = messaging_server_id(ctx->msg);
> - struct db_record *rec = NULL;
> - struct g_lock_rec *locks = NULL;
> - size_t i, num_locks;
> +struct g_lock_unlock_state {
> + const char *name;
> + struct server_id self;
> NTSTATUS status;
> - TDB_DATA value, userdata;
> +};
>
> - rec = dbwrap_fetch_locked(ctx->db, talloc_tos(),
> - string_term_tdb_data(name));
> - if (rec == NULL) {
> - DEBUG(10, ("fetch_locked(\"%s\") failed\n", name));
> - status = NT_STATUS_INTERNAL_ERROR;
> - goto done;
> - }
> +static void g_lock_unlock_fn(struct db_record *rec,
> + void *private_data)
> +{
> + struct g_lock_unlock_state *state = private_data;
> + TDB_DATA value;
> + struct g_lock lck;
> + size_t i;
> + bool ok;
>
> value = dbwrap_record_get_value(rec);
>
> - status = g_lock_get_talloc(talloc_tos(), value, &locks, &num_locks,
> - &userdata.dptr, &userdata.dsize);
> - if (!NT_STATUS_IS_OK(status)) {
> - DBG_DEBUG("g_lock_get for %s failed: %s\n", name,
> - nt_errstr(status));
> - status = NT_STATUS_FILE_INVALID;
> - goto done;
> + ok = g_lock_parse(value.dptr, value.dsize, &lck);
> + if (!ok) {
> + DBG_DEBUG("g_lock_get for %s failed\n", state->name);
> + state->status = NT_STATUS_FILE_INVALID;
> + return;
> }
> - for (i=0; i<num_locks; i++) {
> - if (serverid_equal(&self, &locks[i].pid)) {
> + for (i=0; i<lck.num_recs; i++) {
> + struct g_lock_rec lockrec;
> + g_lock_get_rec(&lck, i, &lockrec);
> + if (serverid_equal(&state->self, &lockrec.pid)) {
> break;
> }
> }
> - if (i == num_locks) {
> - DBG_DEBUG("Lock not found, num_locks=%zu\n", num_locks);
> - status = NT_STATUS_NOT_FOUND;
> - goto done;
> + if (i == lck.num_recs) {
> + DBG_DEBUG("Lock not found, num_rec=%zu\n", lck.num_recs);
> + state->status = NT_STATUS_NOT_FOUND;
> + return;
> }
>
> - locks[i] = locks[num_locks-1];
> - num_locks -= 1;
> + g_lock_rec_del(&lck, i);
>
> - if ((num_locks == 0) && (userdata.dsize == 0)) {
> - status = dbwrap_record_delete(rec);
> - } else {
> - status = g_lock_record_store(
> - rec, locks, num_locks, userdata.dptr, userdata.dsize);
> + if ((lck.num_recs == 0) && (lck.datalen == 0)) {
> + state->status = dbwrap_record_delete(rec);
> + return;
> }
> + state->status = g_lock_store(rec, &lck, NULL);
> +}
> +
> +NTSTATUS g_lock_unlock(struct g_lock_ctx *ctx, const char *name)
> +{
> + struct g_lock_unlock_state state = {
> + .self = messaging_server_id(ctx->msg), .name = name
> + };
> + NTSTATUS status;
> +
> + status = dbwrap_do_locked(ctx->db, string_term_tdb_data(name),
> + g_lock_unlock_fn, &state);
> if (!NT_STATUS_IS_OK(status)) {
> - DBG_WARNING("Could not store record: %s\n", nt_errstr(status));
> - goto done;
> + DBG_WARNING("dbwrap_do_locked failed: %s\n",
> + nt_errstr(status));
> + return status;
> + }
> + if (!NT_STATUS_IS_OK(state.status)) {
> + DBG_WARNING("g_lock_unlock_fn failed: %s\n",
> + nt_errstr(state.status));
> + return state.status;
> }
>
> - status = NT_STATUS_OK;
> -done:
> - TALLOC_FREE(rec);
> - TALLOC_FREE(locks);
> - return status;
> + return NT_STATUS_OK;
> }
>
> NTSTATUS g_lock_write_data(struct g_lock_ctx *ctx, const char *name,
> --
> 2.1.4
>
>
> From 12e24655135e4cb1fe3603db73fa3fa0e68437b6 Mon Sep 17 00:00:00 2001
> From: Volker Lendecke <vl at samba.org>
> Date: Wed, 5 Jul 2017 12:16:02 +0200
> Subject: [PATCH 14/41] g_lock: Initialize variables
>
> gcc -O3 complains, but I think this is a false positive
>
> Signed-off-by: Volker Lendecke <vl at samba.org>
> ---
> source3/lib/g_lock.c | 4 ++--
> 1 file changed, 2 insertions(+), 2 deletions(-)
>
> diff --git a/source3/lib/g_lock.c b/source3/lib/g_lock.c
> index 7a924b9..a79a9cc 100644
> --- a/source3/lib/g_lock.c
> +++ b/source3/lib/g_lock.c
> @@ -765,8 +765,8 @@ NTSTATUS g_lock_dump(struct g_lock_ctx *ctx, const char *name,
> TDB_DATA data;
> size_t num_locks;
> struct g_lock_rec *locks = NULL;
> - uint8_t *userdata;
> - size_t userdatalen;
> + uint8_t *userdata = NULL;
> + size_t userdatalen = 0;
> NTSTATUS status;
>
> status = dbwrap_fetch_bystring(ctx->db, talloc_tos(), name, &data);
> --
> 2.1.4
>
>
> From df73403c69afc391a6ae40f37a82b3e6abf9bc02 Mon Sep 17 00:00:00 2001
> From: Volker Lendecke <vl at samba.org>
> Date: Wed, 28 Jun 2017 19:39:33 +0200
> Subject: [PATCH 15/41] g_lock: Avoid talloc in g_lock_trylock
>
> Signed-off-by: Volker Lendecke <vl at samba.org>
> ---
> source3/lib/g_lock.c | 67 ++++++++++++++++++++++------------------------------
> 1 file changed, 28 insertions(+), 39 deletions(-)
>
> diff --git a/source3/lib/g_lock.c b/source3/lib/g_lock.c
> index a79a9cc..7dcede4 100644
> --- a/source3/lib/g_lock.c
> +++ b/source3/lib/g_lock.c
> @@ -341,41 +341,46 @@ static NTSTATUS g_lock_trylock(struct db_record *rec, struct server_id self,
> enum g_lock_type type,
> struct server_id *blocker)
> {
> - TDB_DATA data, userdata;
> - size_t i, num_locks;
> - struct g_lock_rec *locks, *tmp;
> + TDB_DATA data;
> + size_t i;
> + struct g_lock lck;
> NTSTATUS status;
> bool modified = false;
> + bool ok;
>
> data = dbwrap_record_get_value(rec);
>
> - status = g_lock_get_talloc(talloc_tos(), data, &locks, &num_locks,
> - &userdata.dptr, &userdata.dsize);
> - if (!NT_STATUS_IS_OK(status)) {
> - return status;
> + ok = g_lock_parse(data.dptr, data.dsize, &lck);
> + if (!ok) {
> + return NT_STATUS_INTERNAL_DB_CORRUPTION;
> }
>
> - if ((type == G_LOCK_READ) && (num_locks > 0)) {
> + if ((type == G_LOCK_READ) && (lck.num_recs > 0)) {
> + struct g_lock_rec check_rec;
> +
> /*
> * Read locks can stay around forever if the process
> * dies. Do a heuristic check for process existence:
> * Check one random process for existence. Hopefully
> * this will keep runaway read locks under control.
> */
> - i = generate_random() % num_locks;
> + i = generate_random() % lck.num_recs;
>
> - if (!serverid_exists(&locks[i].pid)) {
> - locks[i] = locks[num_locks-1];
> - num_locks -=1;
> + g_lock_get_rec(&lck, i, &check_rec);
> +
> + if (!serverid_exists(&check_rec.pid)) {
> + g_lock_rec_del(&lck, i);
> modified = true;
> }
> }
>
> - for (i=0; i<num_locks; i++) {
> - struct g_lock_rec *lock = &locks[i];
> + for (i=0; i<lck.num_recs; i++) {
> + struct g_lock_rec lock;
>
> - if (serverid_equal(&self, &lock->pid)) {
> - if (lock->lock_type == type) {
> + g_lock_get_rec(&lck, i, &lock);
> +
> + if (serverid_equal(&self, &lock.pid)) {
> + if (lock.lock_type == type) {
> status = NT_STATUS_WAS_LOCKED;
> goto done;
> }
> @@ -383,13 +388,12 @@ static NTSTATUS g_lock_trylock(struct db_record *rec, struct server_id self,
> * Remove "our" lock entry. Re-add it later
> * with our new lock type.
> */
> - locks[i] = locks[num_locks-1];
> - num_locks -= 1;
> + g_lock_rec_del(&lck, i);
> continue;
> }
>
> - if (g_lock_conflicts(type, lock->lock_type)) {
> - struct server_id pid = lock->pid;
> + if (g_lock_conflicts(type, lock.lock_type)) {
> + struct server_id pid = lock.pid;
>
> /*
> * As the serverid_exists might recurse into
> @@ -400,47 +404,32 @@ static NTSTATUS g_lock_trylock(struct db_record *rec, struct server_id self,
>
> if (serverid_exists(&pid)) {
> status = NT_STATUS_LOCK_NOT_GRANTED;
> - *blocker = lock->pid;
> + *blocker = lock.pid;
> goto done;
> }
>
> /*
> * Delete stale conflicting entry
> */
> - locks[i] = locks[num_locks-1];
> - num_locks -= 1;
> + g_lock_rec_del(&lck, i);
> modified = true;
> }
> }
>
> - tmp = talloc_realloc(talloc_tos(), locks, struct g_lock_rec,
> - num_locks+1);
> - if (tmp == NULL) {
> - status = NT_STATUS_NO_MEMORY;
> - goto done;
> - }
> - locks = tmp;
> -
> - locks[num_locks] = (struct g_lock_rec) {
> - .pid = self, .lock_type = type
> - };
> - num_locks +=1 ;
> -
> modified = true;
>
> status = NT_STATUS_OK;
> done:
> if (modified) {
> + struct g_lock_rec mylock = { .pid = self, .lock_type = type };
> NTSTATUS store_status;
> - store_status = g_lock_record_store(
> - rec, locks, num_locks, userdata.dptr, userdata.dsize);
> + store_status = g_lock_store(rec, &lck, &mylock);
> if (!NT_STATUS_IS_OK(store_status)) {
> DBG_WARNING("g_lock_record_store failed: %s\n",
> nt_errstr(store_status));
> status = store_status;
> }
> }
> - TALLOC_FREE(locks);
> return status;
> }
>
> --
> 2.1.4
>
>
> From 12bfbc5d50b7b81e039eaa9a680ab708e0ac6f6b Mon Sep 17 00:00:00 2001
> From: Volker Lendecke <vl at samba.org>
> Date: Wed, 28 Jun 2017 20:01:34 +0200
> Subject: [PATCH 16/41] g_lock: Use dbwrap_do_locked for g_lock_lock
>
> Don't talloc the record
>
> Signed-off-by: Volker Lendecke <vl at samba.org>
> ---
> source3/lib/g_lock.c | 64 +++++++++++++++++++++++++++++++++++-----------------
> 1 file changed, 43 insertions(+), 21 deletions(-)
>
> diff --git a/source3/lib/g_lock.c b/source3/lib/g_lock.c
> index 7dcede4..a6d341f 100644
> --- a/source3/lib/g_lock.c
> +++ b/source3/lib/g_lock.c
> @@ -442,16 +442,38 @@ struct g_lock_lock_state {
>
> static void g_lock_lock_retry(struct tevent_req *subreq);
>
> +struct g_lock_lock_fn_state {
> + struct g_lock_lock_state *state;
> + struct server_id self;
> +
> + struct tevent_req *watch_req;
> + NTSTATUS status;
> +};
> +
> +static void g_lock_lock_fn(struct db_record *rec, void *private_data)
> +{
> + struct g_lock_lock_fn_state *state = private_data;
> + struct server_id blocker;
> +
> + state->status = g_lock_trylock(rec, state->self, state->state->type,
> + &blocker);
> + if (!NT_STATUS_EQUAL(state->status, NT_STATUS_LOCK_NOT_GRANTED)) {
> + return;
> + }
> +
> + state->watch_req = dbwrap_watched_watch_send(
> + state->state, state->state->ev, rec, blocker);
> +}
> +
> struct tevent_req *g_lock_lock_send(TALLOC_CTX *mem_ctx,
> struct tevent_context *ev,
> struct g_lock_ctx *ctx,
> const char *name,
> enum g_lock_type type)
> {
> - struct tevent_req *req, *subreq;
> + struct tevent_req *req;
> struct g_lock_lock_state *state;
> - struct db_record *rec;
> - struct server_id self, blocker;
> + struct g_lock_lock_fn_state fn_state;
> NTSTATUS status;
>
> req = tevent_req_create(mem_ctx, &state, struct g_lock_lock_state);
> @@ -463,39 +485,39 @@ struct tevent_req *g_lock_lock_send(TALLOC_CTX *mem_ctx,
> state->name = name;
> state->type = type;
>
> - rec = dbwrap_fetch_locked(ctx->db, talloc_tos(),
> - string_term_tdb_data(state->name));
> - if (rec == NULL) {
> - DEBUG(10, ("fetch_locked(\"%s\") failed\n", name));
> - tevent_req_nterror(req, NT_STATUS_LOCK_NOT_GRANTED);
> + fn_state = (struct g_lock_lock_fn_state) {
> + .state = state, .self = messaging_server_id(ctx->msg)
> + };
> +
> + status = dbwrap_do_locked(ctx->db, string_term_tdb_data(name),
> + g_lock_lock_fn, &fn_state);
> + if (tevent_req_nterror(req, status)) {
> + DBG_DEBUG("dbwrap_do_locked failed: %s\n",
> + nt_errstr(status));
> return tevent_req_post(req, ev);
> }
>
> - self = messaging_server_id(state->ctx->msg);
> -
> - status = g_lock_trylock(rec, self, state->type, &blocker);
> - if (NT_STATUS_IS_OK(status)) {
> - TALLOC_FREE(rec);
> + if (NT_STATUS_IS_OK(fn_state.status)) {
> tevent_req_done(req);
> return tevent_req_post(req, ev);
> }
> - if (!NT_STATUS_EQUAL(status, NT_STATUS_LOCK_NOT_GRANTED)) {
> - TALLOC_FREE(rec);
> - tevent_req_nterror(req, status);
> + if (!NT_STATUS_EQUAL(fn_state.status, NT_STATUS_LOCK_NOT_GRANTED)) {
> + tevent_req_nterror(req, fn_state.status);
> return tevent_req_post(req, ev);
> }
> - subreq = dbwrap_watched_watch_send(state, state->ev, rec, blocker);
> - TALLOC_FREE(rec);
> - if (tevent_req_nomem(subreq, req)) {
> +
> + if (tevent_req_nomem(fn_state.watch_req, req)) {
> return tevent_req_post(req, ev);
> }
> +
> +
> if (!tevent_req_set_endtime(
> - subreq, state->ev,
> + fn_state.watch_req, state->ev,
> timeval_current_ofs(5 + sys_random() % 5, 0))) {
> tevent_req_oom(req);
> return tevent_req_post(req, ev);
> }
> - tevent_req_set_callback(subreq, g_lock_lock_retry, req);
> + tevent_req_set_callback(fn_state.watch_req, g_lock_lock_retry, req);
> return req;
> }
>
> --
> 2.1.4
>
>
> From f0434a2f7a87ff721585d7e49f394510306e6cd5 Mon Sep 17 00:00:00 2001
> From: Volker Lendecke <vl at samba.org>
> Date: Fri, 30 Jun 2017 22:20:41 +0200
> Subject: [PATCH 17/41] g_lock: Use dbwrap_do_locked in g_lock_lock_retry
>
> Signed-off-by: Volker Lendecke <vl at samba.org>
> ---
> source3/lib/g_lock.c | 53 +++++++++++++++++++++++++---------------------------
> 1 file changed, 25 insertions(+), 28 deletions(-)
>
> diff --git a/source3/lib/g_lock.c b/source3/lib/g_lock.c
> index a6d341f..3c4bcbf 100644
> --- a/source3/lib/g_lock.c
> +++ b/source3/lib/g_lock.c
> @@ -510,7 +510,6 @@ struct tevent_req *g_lock_lock_send(TALLOC_CTX *mem_ctx,
> return tevent_req_post(req, ev);
> }
>
> -
> if (!tevent_req_set_endtime(
> fn_state.watch_req, state->ev,
> timeval_current_ofs(5 + sys_random() % 5, 0))) {
> @@ -527,54 +526,52 @@ static void g_lock_lock_retry(struct tevent_req *subreq)
> subreq, struct tevent_req);
> struct g_lock_lock_state *state = tevent_req_data(
> req, struct g_lock_lock_state);
> - struct server_id self = messaging_server_id(state->ctx->msg);
> - struct server_id blocker;
> - struct db_record *rec;
> + struct g_lock_lock_fn_state fn_state;
> NTSTATUS status;
>
> - status = dbwrap_watched_watch_recv(subreq, talloc_tos(), &rec, NULL,
> - NULL);
> + status = dbwrap_watched_watch_recv(subreq, NULL, NULL, NULL, NULL);
> + DBG_DEBUG("watch_recv returned %s\n", nt_errstr(status));
> TALLOC_FREE(subreq);
>
> - if (NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT)) {
> - rec = dbwrap_fetch_locked(
> - state->ctx->db, talloc_tos(),
> - string_term_tdb_data(state->name));
> - if (rec == NULL) {
> - status = map_nt_error_from_unix(errno);
> - } else {
> - status = NT_STATUS_OK;
> - }
> + if (!NT_STATUS_IS_OK(status) &&
> + !NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT)) {
> + tevent_req_nterror(req, status);
> + return;
> }
>
> + fn_state = (struct g_lock_lock_fn_state) {
> + .state = state, .self = messaging_server_id(state->ctx->msg)
> + };
> +
> + status = dbwrap_do_locked(state->ctx->db,
> + string_term_tdb_data(state->name),
> + g_lock_lock_fn, &fn_state);
> if (tevent_req_nterror(req, status)) {
> + DBG_DEBUG("dbwrap_do_locked failed: %s\n",
> + nt_errstr(status));
> return;
> }
> - status = g_lock_trylock(rec, self, state->type, &blocker);
> - if (NT_STATUS_IS_OK(status)) {
> - TALLOC_FREE(rec);
> +
> + if (NT_STATUS_IS_OK(fn_state.status)) {
> tevent_req_done(req);
> return;
> }
> - if (!NT_STATUS_EQUAL(status, NT_STATUS_LOCK_NOT_GRANTED)) {
> - TALLOC_FREE(rec);
> - tevent_req_nterror(req, status);
> + if (!NT_STATUS_EQUAL(fn_state.status, NT_STATUS_LOCK_NOT_GRANTED)) {
> + tevent_req_nterror(req, fn_state.status);
> return;
> }
> - subreq = dbwrap_watched_watch_send(state, state->ev, rec, blocker);
> - TALLOC_FREE(rec);
> - if (tevent_req_nomem(subreq, req)) {
> +
> + if (tevent_req_nomem(fn_state.watch_req, req)) {
> return;
> }
> +
> if (!tevent_req_set_endtime(
> - subreq, state->ev,
> + fn_state.watch_req, state->ev,
> timeval_current_ofs(5 + sys_random() % 5, 0))) {
> tevent_req_oom(req);
> return;
> }
> - tevent_req_set_callback(subreq, g_lock_lock_retry, req);
> - return;
> -
> + tevent_req_set_callback(fn_state.watch_req, g_lock_lock_retry, req);
> }
>
> NTSTATUS g_lock_lock_recv(struct tevent_req *req)
> --
> 2.1.4
>
>
> From 1beeb25069057c9f4d580eadaf0d2b85eb823c11 Mon Sep 17 00:00:00 2001
> From: Volker Lendecke <vl at samba.org>
> Date: Mon, 3 Jul 2017 08:09:18 +0200
> Subject: [PATCH 18/41] torture3: Add verification for g_lock_retry
>
> During development I had a bug that would have been found early
> by this
>
> Signed-off-by: Volker Lendecke <vl at samba.org>
> ---
> source3/torture/test_g_lock.c | 52 +++++++++++++++++++++++++++++++++++++++++++
> 1 file changed, 52 insertions(+)
>
> diff --git a/source3/torture/test_g_lock.c b/source3/torture/test_g_lock.c
> index 61ec69d..253d20c 100644
> --- a/source3/torture/test_g_lock.c
> +++ b/source3/torture/test_g_lock.c
> @@ -397,6 +397,41 @@ static void lock4_waited(struct tevent_req *subreq)
> printf("child %d exited with %d\n", (int)child, status);
> }
>
> +struct lock4_check_state {
> + struct server_id me;
> + bool ok;
> +};
> +
> +static void lock4_check(const struct g_lock_rec *locks,
> + size_t num_locks,
> + const uint8_t *data,
> + size_t datalen,
> + void *private_data)
> +{
> + struct lock4_check_state *state = private_data;
> +
> + if (num_locks != 1) {
> + fprintf(stderr, "num_locks=%zu\n", num_locks);
> + return;
> + }
> +
> + if (!serverid_equal(&state->me, &locks[0].pid)) {
> + struct server_id_buf buf1, buf2;
> + fprintf(stderr, "me=%s, locker=%s\n",
> + server_id_str_buf(state->me, &buf1),
> + server_id_str_buf(locks[0].pid, &buf2));
> + return;
> + }
> +
> + if (locks[0].lock_type != G_LOCK_WRITE) {
> + fprintf(stderr, "wrong lock type: %d\n",
> + (int)locks[0].lock_type);
> + return;
> + }
> +
> + state->ok = true;
> +}
> +
> /*
> * Test a lock conflict
> */
> @@ -493,6 +528,23 @@ bool run_g_lock4(int dummy)
> }
> }
>
> + {
> + struct lock4_check_state state = {
> + .me = messaging_server_id(msg)
> + };
> +
> + status = g_lock_dump(ctx, lockname, lock4_check, &state);
> + if (!NT_STATUS_IS_OK(status)) {
> + fprintf(stderr, "g_lock_dump failed: %s\n",
> + nt_errstr(status));
> + goto fail;
> + }
> + if (!state.ok) {
> + fprintf(stderr, "lock4_check failed\n");
> + goto fail;
> + }
> + }
> +
> ret = true;
> fail:
> TALLOC_FREE(ctx);
> --
> 2.1.4
>
>
> From f48527c3a8d4328f4997e596fe40b34eb00bc8e3 Mon Sep 17 00:00:00 2001
> From: Volker Lendecke <vl at samba.org>
> Date: Fri, 30 Jun 2017 19:42:50 +0200
> Subject: [PATCH 19/41] g_lock: Use dbwrap_do_locked in g_lock_write_data
>
> Signed-off-by: Volker Lendecke <vl at samba.org>
> ---
> source3/lib/g_lock.c | 88 ++++++++++++++++++++++++++++++++--------------------
> 1 file changed, 54 insertions(+), 34 deletions(-)
>
> diff --git a/source3/lib/g_lock.c b/source3/lib/g_lock.c
> index 3c4bcbf..25d9629 100644
> --- a/source3/lib/g_lock.c
> +++ b/source3/lib/g_lock.c
> @@ -677,53 +677,73 @@ NTSTATUS g_lock_unlock(struct g_lock_ctx *ctx, const char *name)
> return NT_STATUS_OK;
> }
>
> -NTSTATUS g_lock_write_data(struct g_lock_ctx *ctx, const char *name,
> - const uint8_t *buf, size_t buflen)
> -{
> - struct server_id self = messaging_server_id(ctx->msg);
> - struct db_record *rec = NULL;
> - struct g_lock_rec *locks = NULL;
> - size_t i, num_locks;
> +struct g_lock_write_data_state {
> + const char *name;
> + struct server_id self;
> + const uint8_t *data;
> + size_t datalen;
> NTSTATUS status;
> - TDB_DATA value;
> +};
>
> - rec = dbwrap_fetch_locked(ctx->db, talloc_tos(),
> - string_term_tdb_data(name));
> - if (rec == NULL) {
> - DEBUG(10, ("fetch_locked(\"%s\") failed\n", name));
> - status = NT_STATUS_INTERNAL_ERROR;
> - goto done;
> - }
> +static void g_lock_write_data_fn(struct db_record *rec,
> + void *private_data)
> +{
> + struct g_lock_write_data_state *state = private_data;
> + TDB_DATA value;
> + struct g_lock lck;
> + size_t i;
> + bool ok;
>
> value = dbwrap_record_get_value(rec);
>
> - status = g_lock_get_talloc(talloc_tos(), value, &locks, &num_locks,
> - NULL, NULL);
> - if (!NT_STATUS_IS_OK(status)) {
> - DBG_DEBUG("g_lock_get for %s failed: %s\n", name,
> - nt_errstr(status));
> - status = NT_STATUS_FILE_INVALID;
> - goto done;
> + ok = g_lock_parse(value.dptr, value.dsize, &lck);
> + if (!ok) {
> + DBG_DEBUG("g_lock_parse for %s failed\n", state->name);
> + state->status = NT_STATUS_INTERNAL_DB_CORRUPTION;
> + return;
> }
> -
> - for (i=0; i<num_locks; i++) {
> - if (server_id_equal(&self, &locks[i].pid) &&
> - (locks[i].lock_type == G_LOCK_WRITE)) {
> + for (i=0; i<lck.num_recs; i++) {
> + struct g_lock_rec lockrec;
> + g_lock_get_rec(&lck, i, &lockrec);
> + if ((lockrec.lock_type == G_LOCK_WRITE) &&
> + serverid_equal(&state->self, &lockrec.pid)) {
> break;
> }
> }
> - if (i == num_locks) {
> + if (i == lck.num_recs) {
> DBG_DEBUG("Not locked by us\n");
> - status = NT_STATUS_NOT_LOCKED;
> - goto done;
> + state->status = NT_STATUS_NOT_LOCKED;
> + return;
> }
>
> - status = g_lock_record_store(rec, locks, num_locks, buf, buflen);
> + lck.data = discard_const_p(uint8_t, state->data);
> + lck.datalen = state->datalen;
> + state->status = g_lock_store(rec, &lck, NULL);
> +}
>
> -done:
> - TALLOC_FREE(locks);
> - TALLOC_FREE(rec);
> - return status;
> +NTSTATUS g_lock_write_data(struct g_lock_ctx *ctx, const char *name,
> + const uint8_t *buf, size_t buflen)
> +{
> + struct g_lock_write_data_state state = {
> + .name = name, .self = messaging_server_id(ctx->msg),
> + .data = buf, .datalen = buflen
> + };
> + NTSTATUS status;
> +
> + status = dbwrap_do_locked(ctx->db, string_term_tdb_data(name),
> + g_lock_write_data_fn, &state);
> + if (!NT_STATUS_IS_OK(status)) {
> + DBG_WARNING("dbwrap_do_locked failed: %s\n",
> + nt_errstr(status));
> + return status;
> + }
> + if (!NT_STATUS_IS_OK(state.status)) {
> + DBG_WARNING("g_lock_write_data_fn failed: %s\n",
> + nt_errstr(state.status));
> + return state.status;
> + }
> +
> + return NT_STATUS_OK;
> }
>
> struct g_lock_locks_state {
> --
> 2.1.4
>
>
> From c018d3cab53282f8f5b9b50eb3875f327c479711 Mon Sep 17 00:00:00 2001
> From: Volker Lendecke <vl at samba.org>
> Date: Fri, 30 Jun 2017 22:09:12 +0200
> Subject: [PATCH 20/41] g_lock: Use parse_record in g_lock_dump
>
> Signed-off-by: Volker Lendecke <vl at samba.org>
> ---
> source3/lib/g_lock.c | 84 +++++++++++++++++++++++++++++++++++++---------------
> 1 file changed, 60 insertions(+), 24 deletions(-)
>
> diff --git a/source3/lib/g_lock.c b/source3/lib/g_lock.c
> index 25d9629..9b971ae 100644
> --- a/source3/lib/g_lock.c
> +++ b/source3/lib/g_lock.c
> @@ -782,6 +782,54 @@ int g_lock_locks(struct g_lock_ctx *ctx,
> return count;
> }
>
> +struct g_lock_dump_state {
> + TALLOC_CTX *mem_ctx;
> + const char *name;
> + void (*fn)(const struct g_lock_rec *locks,
> + size_t num_locks,
> + const uint8_t *data,
> + size_t datalen,
> + void *private_data);
> + void *private_data;
> + NTSTATUS status;
> +};
> +
> +static void g_lock_dump_fn(TDB_DATA key, TDB_DATA data,
> + void *private_data)
> +{
> + struct g_lock_dump_state *state = private_data;
> + struct g_lock_rec *recs;
> + struct g_lock lck;
> + size_t i;
> + bool ok;
> +
> + ok = g_lock_parse(data.dptr, data.dsize, &lck);
> + if (!ok) {
> + DBG_DEBUG("g_lock_parse failed for %s\n",
> + state->name);
> + state->status = NT_STATUS_INTERNAL_DB_CORRUPTION;
> + return;
> + }
> +
> + recs = talloc_array(state->mem_ctx, struct g_lock_rec, lck.num_recs);
> + if (recs == NULL) {
> + DBG_DEBUG("talloc failed\n");
> + state->status = NT_STATUS_NO_MEMORY;
> + return;
> + }
> +
> + for (i=0; i<lck.num_recs; i++) {
> + g_lock_get_rec(&lck, i, &recs[i]);
> + }
> +
> + state->fn(recs, lck.num_recs, lck.data, lck.datalen,
> + state->private_data);
> +
> + TALLOC_FREE(recs);
> +
> + state->status = NT_STATUS_OK;
> +}
> +
> NTSTATUS g_lock_dump(struct g_lock_ctx *ctx, const char *name,
> void (*fn)(const struct g_lock_rec *locks,
> size_t num_locks,
> @@ -790,36 +838,24 @@ NTSTATUS g_lock_dump(struct g_lock_ctx *ctx, const char *name,
> void *private_data),
> void *private_data)
> {
> - TDB_DATA data;
> - size_t num_locks;
> - struct g_lock_rec *locks = NULL;
> - uint8_t *userdata = NULL;
> - size_t userdatalen = 0;
> + struct g_lock_dump_state state = {
> + .mem_ctx = ctx, .name = name,
> + .fn = fn, .private_data = private_data
> + };
> NTSTATUS status;
>
> - status = dbwrap_fetch_bystring(ctx->db, talloc_tos(), name, &data);
> + status = dbwrap_parse_record(ctx->db, string_term_tdb_data(name),
> + g_lock_dump_fn, &state);
> if (!NT_STATUS_IS_OK(status)) {
> + DBG_DEBUG("dbwrap_parse_record returned %s\n",
> + nt_errstr(status));
> return status;
> }
> -
> - if ((data.dsize == 0) || (data.dptr == NULL)) {
> - return NT_STATUS_OK;
> - }
> -
> - status = g_lock_get_talloc(talloc_tos(), data, &locks, &num_locks,
> - &userdata, &userdatalen);
> -
> - if (!NT_STATUS_IS_OK(status)) {
> - DBG_DEBUG("g_lock_get for %s failed: %s\n", name,
> - nt_errstr(status));
> - TALLOC_FREE(data.dptr);
> - return NT_STATUS_INTERNAL_ERROR;
> + if (!NT_STATUS_IS_OK(state.status)) {
> + DBG_DEBUG("g_lock_dump_fn returned %s\n",
> + nt_errstr(state.status));
> + return state.status;
> }
> -
> - fn(locks, num_locks, userdata, userdatalen, private_data);
> -
> - TALLOC_FREE(locks);
> - TALLOC_FREE(data.dptr);
> return NT_STATUS_OK;
> }
>
> --
> 2.1.4
>
>
> From cd82f112847a8149342ee8a23cf4a8e765bf3765 Mon Sep 17 00:00:00 2001
> From: Volker Lendecke <vl at samba.org>
> Date: Fri, 30 Jun 2017 22:14:58 +0200
> Subject: [PATCH 21/41] g_lock: Remove unused code
>
> Signed-off-by: Volker Lendecke <vl at samba.org>
> ---
> source3/lib/g_lock.c | 144 ---------------------------------------------------
> 1 file changed, 144 deletions(-)
>
> diff --git a/source3/lib/g_lock.c b/source3/lib/g_lock.c
> index 9b971ae..8709052 100644
> --- a/source3/lib/g_lock.c
> +++ b/source3/lib/g_lock.c
> @@ -141,121 +141,6 @@ static NTSTATUS g_lock_store(struct db_record *rec, struct g_lock *lck,
> return dbwrap_record_storev(rec, dbufs, ARRAY_SIZE(dbufs), 0);
> }
>
> -static ssize_t g_lock_put(uint8_t *buf, size_t buflen,
> - const struct g_lock_rec *locks,
> - size_t num_locks,
> - const uint8_t *data, size_t datalen)
> -{
> - size_t i, len, ofs;
> -
> - if (num_locks > UINT32_MAX/G_LOCK_REC_LENGTH) {
> - return -1;
> - }
> -
> - len = num_locks * G_LOCK_REC_LENGTH;
> -
> - len += sizeof(uint32_t);
> - if (len < sizeof(uint32_t)) {
> - return -1;
> - }
> -
> - len += datalen;
> - if (len < datalen) {
> - return -1;
> - }
> -
> - if (len > buflen) {
> - return len;
> - }
> -
> - ofs = 0;
> - SIVAL(buf, ofs, num_locks);
> - ofs += sizeof(uint32_t);
> -
> - for (i=0; i<num_locks; i++) {
> - g_lock_rec_put(buf+ofs, locks[i]);
> - ofs += G_LOCK_REC_LENGTH;
> - }
> -
> - if ((data != NULL) && (datalen != 0)) {
> - memcpy(buf+ofs, data, datalen);
> - }
> -
> - return len;
> -}
> -
> -static ssize_t g_lock_get(TDB_DATA recval,
> - struct g_lock_rec *locks, size_t num_locks,
> - uint8_t **data, size_t *datalen)
> -{
> - size_t found_locks;
> -
> - if (recval.dsize < sizeof(uint32_t)) {
> - /* Fresh or invalid record */
> - found_locks = 0;
> - goto done;
> - }
> -
> - found_locks = IVAL(recval.dptr, 0);
> - recval.dptr += sizeof(uint32_t);
> - recval.dsize -= sizeof(uint32_t);
> -
> - if (found_locks > recval.dsize/G_LOCK_REC_LENGTH) {
> - /* Invalid record */
> - return 0;
> - }
> -
> - if (found_locks <= num_locks) {
> - size_t i;
> -
> - for (i=0; i<found_locks; i++) {
> - g_lock_rec_get(&locks[i], recval.dptr);
> - recval.dptr += G_LOCK_REC_LENGTH;
> - recval.dsize -= G_LOCK_REC_LENGTH;
> - }
> - } else {
> - /*
> - * Not enough space passed in by the caller, don't
> - * parse the locks.
> - */
> - recval.dptr += found_locks * G_LOCK_REC_LENGTH;
> - recval.dsize -= found_locks * G_LOCK_REC_LENGTH;
> - }
> -
> -done:
> - if (data != NULL) {
> - *data = recval.dptr;
> - }
> - if (datalen != NULL) {
> - *datalen = recval.dsize;
> - }
> - return found_locks;
> -}
> -
> -static NTSTATUS g_lock_get_talloc(TALLOC_CTX *mem_ctx, TDB_DATA recval,
> - struct g_lock_rec **plocks,
> - size_t *pnum_locks,
> - uint8_t **data, size_t *datalen)
> -{
> - struct g_lock_rec *locks;
> - ssize_t num_locks;
> -
> - num_locks = g_lock_get(recval, NULL, 0, NULL, NULL);
> - if (num_locks == -1) {
> - return NT_STATUS_INTERNAL_DB_CORRUPTION;
> - }
> - locks = talloc_array(mem_ctx, struct g_lock_rec, num_locks);
> - if (locks == NULL) {
> - return NT_STATUS_NO_MEMORY;
> - }
> - g_lock_get(recval, locks, num_locks, data, datalen);
> -
> - *plocks = locks;
> - *pnum_locks = num_locks;
> -
> - return NT_STATUS_OK;
> -}
> -
> struct g_lock_ctx *g_lock_ctx_init(TALLOC_CTX *mem_ctx,
> struct messaging_context *msg)
> {
> @@ -308,35 +193,6 @@ static bool g_lock_conflicts(enum g_lock_type l1, enum g_lock_type l2)
> return true;
> }
>
> -static NTSTATUS g_lock_record_store(struct db_record *rec,
> - const struct g_lock_rec *locks,
> - size_t num_locks,
> - const uint8_t *data, size_t datalen)
> -{
> - ssize_t len;
> - uint8_t *buf;
> - NTSTATUS status;
> -
> - len = g_lock_put(NULL, 0, locks, num_locks, data, datalen);
> - if (len == -1) {
> - return NT_STATUS_BUFFER_TOO_SMALL;
> - }
> -
> - buf = talloc_array(rec, uint8_t, len);
> - if (buf == NULL) {
> - return NT_STATUS_NO_MEMORY;
> - }
> -
> - g_lock_put(buf, len, locks, num_locks, data, datalen);
> -
> - status = dbwrap_record_store(
> - rec, (TDB_DATA) { .dptr = buf, .dsize = len }, 0);
> -
> - TALLOC_FREE(buf);
> -
> - return status;
> -}
> -
> static NTSTATUS g_lock_trylock(struct db_record *rec, struct server_id self,
> enum g_lock_type type,
> struct server_id *blocker)
> --
> 2.1.4
>
>
> From 5a7ed6737f91afaf5b353ed731457e9bf7982eb1 Mon Sep 17 00:00:00 2001
> From: Volker Lendecke <vl at samba.org>
> Date: Sat, 17 Jun 2017 15:43:14 +0200
> Subject: [PATCH 22/41] messaging: Factor out messaging_dispatch_waiters
>
> No real code change: This makes dispatching to non-classic receives available
> for other callers.
>
> Signed-off-by: Volker Lendecke <vl at samba.org>
> ---
> source3/lib/messages.c | 56 +++++++++++++++++++++++++++++---------------------
> 1 file changed, 33 insertions(+), 23 deletions(-)
>
> diff --git a/source3/lib/messages.c b/source3/lib/messages.c
> index b94a696..02aa16c 100644
> --- a/source3/lib/messages.c
> +++ b/source3/lib/messages.c
> @@ -87,6 +87,9 @@ struct messaging_context {
>
> static struct messaging_rec *messaging_rec_dup(TALLOC_CTX *mem_ctx,
> struct messaging_rec *rec);
> +static bool messaging_dispatch_waiters(struct messaging_context *msg_ctx,
> + struct tevent_context *ev,
> + struct messaging_rec *rec);
> static void messaging_dispatch_rec(struct messaging_context *msg_ctx,
> struct tevent_context *ev,
> struct messaging_rec *rec);
> @@ -966,32 +969,14 @@ static bool messaging_dispatch_classic(struct messaging_context *msg_ctx,
> return false;
> }
>
> -/*
> - Dispatch one messaging_rec
> -*/
> -static void messaging_dispatch_rec(struct messaging_context *msg_ctx,
> - struct tevent_context *ev,
> - struct messaging_rec *rec)
> +static bool messaging_dispatch_waiters(struct messaging_context *msg_ctx,
> + struct tevent_context *ev,
> + struct messaging_rec *rec)
> {
> size_t i;
> - bool consumed;
> -
> - if (ev == msg_ctx->event_ctx) {
> - consumed = messaging_dispatch_classic(msg_ctx, rec);
> - if (consumed) {
> - return;
> - }
> - }
>
> if (!messaging_append_new_waiters(msg_ctx)) {
> - size_t j;
> - for (j=0; j < rec->num_fds; j++) {
> - int fd = rec->fds[j];
> - close(fd);
> - }
> - rec->num_fds = 0;
> - rec->fds = NULL;
> - return;
> + return false;
> }
>
> i = 0;
> @@ -1022,12 +1007,37 @@ static void messaging_dispatch_rec(struct messaging_context *msg_ctx,
> if ((ev == state->ev) &&
> state->filter(rec, state->private_data)) {
> messaging_filtered_read_done(req, rec);
> - return;
> + return true;
> }
>
> i += 1;
> }
>
> + return false;
> +}
> +
> +/*
> + Dispatch one messaging_rec
> +*/
> +static void messaging_dispatch_rec(struct messaging_context *msg_ctx,
> + struct tevent_context *ev,
> + struct messaging_rec *rec)
> +{
> + bool consumed;
> + size_t i;
> +
> + if (ev == msg_ctx->event_ctx) {
> + consumed = messaging_dispatch_classic(msg_ctx, rec);
> + if (consumed) {
> + return;
> + }
> + }
> +
> + consumed = messaging_dispatch_waiters(msg_ctx, ev, rec);
> + if (consumed) {
> + return;
> + }
> +
> if (ev != msg_ctx->event_ctx) {
> struct iovec iov;
> int fds[rec->num_fds];
> --
> 2.1.4
>
>
> From 51f1f74184fdd0b6e0d6aa636ba57f9e59c0a697 Mon Sep 17 00:00:00 2001
> From: Volker Lendecke <vl at samba.org>
> Date: Sat, 17 Jun 2017 08:48:35 +0200
> Subject: [PATCH 23/41] messaging: Add DLIST pointers to messaging_rec
>
> Signed-off-by: Volker Lendecke <vl at samba.org>
> ---
> librpc/idl/messaging.idl | 2 ++
> 1 file changed, 2 insertions(+)
>
> diff --git a/librpc/idl/messaging.idl b/librpc/idl/messaging.idl
> index b962ab1..37f8fcc 100644
> --- a/librpc/idl/messaging.idl
> +++ b/librpc/idl/messaging.idl
> @@ -159,6 +159,8 @@ interface messaging
> /* messaging struct sent across the sockets and stored in the tdb */
>
> typedef [public] struct {
> + [skip] messaging_rec *prev;
> + [skip] messaging_rec *next;
> uint32 msg_version;
> messaging_type msg_type;
> server_id dest;
> --
> 2.1.4
>
>
> From 42dce196fc5d4b25c1aa3361d16aa5abbc8c058a Mon Sep 17 00:00:00 2001
> From: Volker Lendecke <vl at samba.org>
> Date: Thu, 22 Jun 2017 08:34:34 +0200
> Subject: [PATCH 24/41] messaging: Keep an array of event contexts registered
>
> This is done with an explicit reference-counting and without talloc
> destructors. The code is isolated enough for now that explicit refcount
> management seems simpler. This might change in the future, but for
> now keep it simple.
>
> Signed-off-by: Volker Lendecke <vl at samba.org>
> ---
> source3/lib/messages.c | 96 ++++++++++++++++++++++++++++++++++++++++++++++++++
> 1 file changed, 96 insertions(+)
>
> diff --git a/source3/lib/messages.c b/source3/lib/messages.c
> index 02aa16c..61005ab 100644
> --- a/source3/lib/messages.c
> +++ b/source3/lib/messages.c
> @@ -68,11 +68,18 @@ struct messaging_callback {
> void *private_data;
> };
>
> +struct messaging_registered_ev {
> + struct tevent_context *ev;
> + size_t refcount;
> +};
> +
> struct messaging_context {
> struct server_id id;
> struct tevent_context *event_ctx;
> struct messaging_callback *callbacks;
>
> + struct messaging_registered_ev *event_contexts;
> +
> struct tevent_req **new_waiters;
> size_t num_new_waiters;
>
> @@ -160,6 +167,76 @@ struct messaging_rec *messaging_rec_create(
> return result;
> }
>
> +static bool messaging_register_event_context(struct messaging_context *ctx,
> + struct tevent_context *ev)
> +{
> + size_t i, num_event_contexts;
> + struct messaging_registered_ev *free_reg = NULL;
> + struct messaging_registered_ev *tmp;
> +
> + num_event_contexts = talloc_array_length(ctx->event_contexts);
> +
> + for (i=0; i<num_event_contexts; i++) {
> + struct messaging_registered_ev *reg = &ctx->event_contexts[i];
> +
> + if (reg->ev == ev) {
> + reg->refcount += 1;
> + return true;
> + }
> + if (reg->refcount == 0) {
> + if (reg->ev != NULL) {
> + abort();
> + }
> + free_reg = reg;
> + }
> + }
> +
> + if (free_reg == NULL) {
> + tmp = talloc_realloc(ctx, ctx->event_contexts,
> + struct messaging_registered_ev,
> + num_event_contexts+1);
> + if (tmp == NULL) {
> + return false;
> + }
> + ctx->event_contexts = tmp;
> +
> + free_reg = &ctx->event_contexts[num_event_contexts];
> + }
> +
> + *free_reg = (struct messaging_registered_ev) { .ev = ev, .refcount = 1 };
> +
> + return true;
> +}
> +
> +static bool messaging_deregister_event_context(struct messaging_context *ctx,
> + struct tevent_context *ev)
> +{
> + size_t i, num_event_contexts;
> +
> + num_event_contexts = talloc_array_length(ctx->event_contexts);
> +
> + for (i=0; i<num_event_contexts; i++) {
> + struct messaging_registered_ev *reg = &ctx->event_contexts[i];
> +
> + if (reg->ev == ev) {
> + if (reg->refcount == 0) {
> + return false;
> + }
> + reg->refcount -= 1;
> +
> + if (reg->refcount == 0) {
> + /*
> + * Not strictly necessary, just
> + * paranoia
> + */
> + reg->ev = NULL;
> + }
> + return true;
> + }
> + }
> + return false;
> +}
> +
> static void messaging_recv_cb(struct tevent_context *ev,
> const uint8_t *msg, size_t msg_len,
> int *fds, size_t num_fds,
> @@ -295,6 +372,12 @@ static NTSTATUS messaging_init_internal(TALLOC_CTX *mem_ctx,
>
> ctx->event_ctx = ev;
>
> + ok = messaging_register_event_context(ctx, ev);
> + if (!ok) {
> + status = NT_STATUS_NO_MEMORY;
> + goto done;
> + }
> +
> sec_init();
>
> ctx->msg_dgm_ref = messaging_dgm_ref(ctx,
> @@ -716,6 +799,7 @@ struct tevent_req *messaging_filtered_read_send(
> struct tevent_req *req;
> struct messaging_filtered_read_state *state;
> size_t new_waiters_len;
> + bool ok;
>
> req = tevent_req_create(mem_ctx, &state,
> struct messaging_filtered_read_state);
> @@ -763,6 +847,12 @@ struct tevent_req *messaging_filtered_read_send(
> msg_ctx->num_new_waiters += 1;
> tevent_req_set_cleanup_fn(req, messaging_filtered_read_cleanup);
>
> + ok = messaging_register_event_context(msg_ctx, ev);
> + if (!ok) {
> + tevent_req_oom(req);
> + return tevent_req_post(req, ev);
> + }
> +
> return req;
> }
>
> @@ -773,11 +863,17 @@ static void messaging_filtered_read_cleanup(struct tevent_req *req,
> req, struct messaging_filtered_read_state);
> struct messaging_context *msg_ctx = state->msg_ctx;
> size_t i;
> + bool ok;
>
> tevent_req_set_cleanup_fn(req, NULL);
>
> TALLOC_FREE(state->fde);
>
> + ok = messaging_deregister_event_context(msg_ctx, state->ev);
> + if (!ok) {
> + abort();
> + }
> +
> /*
> * Just set the [new_]waiters entry to NULL, be careful not to mess
> * with the other "waiters" array contents. We are often called from
> --
> 2.1.4
>
>
> From b3a18d4cb8468b78a10320b9028c9bc8a6221b3a Mon Sep 17 00:00:00 2001
> From: Volker Lendecke <vl at samba.org>
> Date: Thu, 22 Jun 2017 08:54:56 +0200
> Subject: [PATCH 25/41] messaging: Broadcast messages to all event contexts
>
> We must give all event contexts that might be interested the chance to pick up
> the message. If we send a message to ourselves via messaging_send_iov_from,
> nested event contexts need to get a chance to see the message. Before this
> patch only the main event context in msg_ctx got it.
>
> Signed-off-by: Volker Lendecke <vl at samba.org>
> ---
> source3/lib/messages.c | 165 +++++++++++++++++++++++++++++++++++++------------
> 1 file changed, 127 insertions(+), 38 deletions(-)
>
> diff --git a/source3/lib/messages.c b/source3/lib/messages.c
> index 61005ab..5c10013 100644
> --- a/source3/lib/messages.c
> +++ b/source3/lib/messages.c
> @@ -70,6 +70,7 @@ struct messaging_callback {
>
> struct messaging_registered_ev {
> struct tevent_context *ev;
> + struct tevent_immediate *im;
> size_t refcount;
> };
>
> @@ -78,6 +79,8 @@ struct messaging_context {
> struct tevent_context *event_ctx;
> struct messaging_callback *callbacks;
>
> + struct messaging_rec *posted_msgs;
> +
> struct messaging_registered_ev *event_contexts;
>
> struct tevent_req **new_waiters;
> @@ -94,6 +97,8 @@ struct messaging_context {
>
> static struct messaging_rec *messaging_rec_dup(TALLOC_CTX *mem_ctx,
> struct messaging_rec *rec);
> +static bool messaging_dispatch_classic(struct messaging_context *msg_ctx,
> + struct messaging_rec *rec);
> static bool messaging_dispatch_waiters(struct messaging_context *msg_ctx,
> struct tevent_context *ev,
> struct messaging_rec *rec);
> @@ -230,6 +235,11 @@ static bool messaging_deregister_event_context(struct messaging_context *ctx,
> * paranoia
> */
> reg->ev = NULL;
> +
> + /*
> + * Do not talloc_free(reg->im),
> + * recycle immediates events.
> + */
> }
> return true;
> }
> @@ -237,6 +247,105 @@ static bool messaging_deregister_event_context(struct messaging_context *ctx,
> return false;
> }
>
> +static void messaging_post_main_event_context(struct tevent_context *ev,
> + struct tevent_immediate *im,
> + void *private_data)
> +{
> + struct messaging_context *ctx = talloc_get_type_abort(
> + private_data, struct messaging_context);
> +
> + while (ctx->posted_msgs != NULL) {
> + struct messaging_rec *rec = ctx->posted_msgs;
> + bool consumed;
> +
> + DLIST_REMOVE(ctx->posted_msgs, rec);
> +
> + consumed = messaging_dispatch_classic(ctx, rec);
> + if (!consumed) {
> + consumed = messaging_dispatch_waiters(
> + ctx, ctx->event_ctx, rec);
> + }
> +
> + if (!consumed) {
> + uint8_t i;
> +
> + for (i=0; i<rec->num_fds; i++) {
> + close(rec->fds[i]);
> + }
> + }
> +
> + TALLOC_FREE(rec);
> + }
> +}
> +
> +static void messaging_post_sub_event_context(struct tevent_context *ev,
> + struct tevent_immediate *im,
> + void *private_data)
> +{
> + struct messaging_context *ctx = talloc_get_type_abort(
> + private_data, struct messaging_context);
> + struct messaging_rec *rec, *next;
> +
> + for (rec = ctx->posted_msgs; rec != NULL; rec = next) {
> + bool consumed;
> +
> + next = rec->next;
> +
> + consumed = messaging_dispatch_waiters(ctx, ev, rec);
> + if (consumed) {
> + DLIST_REMOVE(ctx->posted_msgs, rec);
> + TALLOC_FREE(rec);
> + }
> + }
> +}
> +
> +static bool messaging_alert_event_contexts(struct messaging_context *ctx)
> +{
> + size_t i, num_event_contexts;
> +
> + num_event_contexts = talloc_array_length(ctx->event_contexts);
> +
> + for (i=0; i<num_event_contexts; i++) {
> + struct messaging_registered_ev *reg = &ctx->event_contexts[i];
> +
> + if (reg->refcount == 0) {
> + continue;
> + }
> +
> + if (reg->im == NULL) {
> + reg->im = tevent_create_immediate(
> + ctx->event_contexts);
> + }
> + if (reg->im == NULL) {
> + DBG_WARNING("Could not create immediate\n");
> + continue;
> + }
> +
> + /*
> + * We depend on schedule_immediate to work
> + * multiple times. Might be a bit inefficient,
> + * but this needs to be proven in tests. The
> + * alternatively would be to track whether the
> + * immediate has already been scheduled. For
> + * now, avoid that complexity here.
> + */
> +
> + if (reg->ev == ctx->event_ctx) {
> + tevent_schedule_immediate(
> + reg->im, reg->ev,
> + messaging_post_main_event_context,
> + ctx);
> + } else {
> + tevent_schedule_immediate(
> + reg->im, reg->ev,
> + messaging_post_sub_event_context,
> + ctx);
> + }
> +
> + }
> + return true;
> +}
> +
> static void messaging_recv_cb(struct tevent_context *ev,
> const uint8_t *msg, size_t msg_len,
> int *fds, size_t num_fds,
> @@ -308,6 +417,13 @@ static int messaging_context_destructor(struct messaging_context *ctx)
> }
> }
>
> + /*
> + * The immediates from messaging_alert_event_contexts
> + * reference "ctx". Don't let them outlive the
> + * messaging_context we're destroying here.
> + */
> + TALLOC_FREE(ctx->event_contexts);
> +
> return 0;
> }
>
> @@ -612,57 +728,30 @@ NTSTATUS messaging_send_buf(struct messaging_context *msg_ctx,
> return messaging_send(msg_ctx, server, msg_type, &blob);
> }
>
> -struct messaging_post_state {
> - struct messaging_context *msg_ctx;
> - struct messaging_rec *rec;
> -};
> -
> -static void messaging_post_handler(struct tevent_context *ev,
> - struct tevent_immediate *ti,
> - void *private_data);
> -
> static int messaging_post_self(struct messaging_context *msg_ctx,
> struct server_id src, struct server_id dst,
> uint32_t msg_type,
> const struct iovec *iov, int iovlen,
> const int *fds, size_t num_fds)
> {
> - struct tevent_immediate *ti;
> - struct messaging_post_state *state;
> + struct messaging_rec *rec;
> + bool ok;
>
> - state = talloc(msg_ctx, struct messaging_post_state);
> - if (state == NULL) {
> + rec = messaging_rec_create(
> + msg_ctx, src, dst, msg_type, iov, iovlen, fds, num_fds);
> + if (rec == NULL) {
> return ENOMEM;
> }
> - state->msg_ctx = msg_ctx;
>
> - ti = tevent_create_immediate(state);
> - if (ti == NULL) {
> - goto fail;
> - }
> - state->rec = messaging_rec_create(
> - state, src, dst, msg_type, iov, iovlen, fds, num_fds);
> - if (state->rec == NULL) {
> - goto fail;
> + ok = messaging_alert_event_contexts(msg_ctx);
> + if (!ok) {
> + TALLOC_FREE(rec);
> + return ENOMEM;
> }
>
> - tevent_schedule_immediate(ti, msg_ctx->event_ctx,
> - messaging_post_handler, state);
> - return 0;
> + DLIST_ADD_END(msg_ctx->posted_msgs, rec);
>
> -fail:
> - TALLOC_FREE(state);
> - return ENOMEM;
> -}
> -
> -static void messaging_post_handler(struct tevent_context *ev,
> - struct tevent_immediate *ti,
> - void *private_data)
> -{
> - struct messaging_post_state *state = talloc_get_type_abort(
> - private_data, struct messaging_post_state);
> - messaging_dispatch_rec(state->msg_ctx, ev, state->rec);
> - TALLOC_FREE(state);
> + return 0;
> }
>
> int messaging_send_iov_from(struct messaging_context *msg_ctx,
> --
> 2.1.4
>
>
> From 11d72abc872688fb08d4a11eaf36413e9ab69cb2 Mon Sep 17 00:00:00 2001
> From: Volker Lendecke <vl at samba.org>
> Date: Thu, 1 Jun 2017 17:45:47 +0200
> Subject: [PATCH 26/41] ctdbd_conn: Pass "ev" through ctdb connection callbacks
>
> This prepares the same logic we've implemented in messages_dgm for clustering
> that is used in 6d3c064f1a5: We need to reply for messages from ctdb in nested
> event contexts properly.
>
> Signed-off-by: Volker Lendecke <vl at samba.org>
> ---
> source3/include/ctdbd_conn.h | 6 ++++--
> source3/lib/ctdb_dummy.c | 6 ++++--
> source3/lib/ctdbd_conn.c | 12 ++++++++----
> source3/lib/messages_ctdbd.c | 1 +
> source3/smbd/notifyd/notifyd.c | 6 ++++--
> source3/smbd/process.c | 3 ++-
> source3/smbd/server.c | 1 +
> 7 files changed, 24 insertions(+), 11 deletions(-)
>
> diff --git a/source3/include/ctdbd_conn.h b/source3/include/ctdbd_conn.h
> index 06fbcc3..44ee8ab 100644
> --- a/source3/include/ctdbd_conn.h
> +++ b/source3/include/ctdbd_conn.h
> @@ -73,7 +73,8 @@ int ctdbd_traverse(struct ctdbd_connection *master, uint32_t db_id,
> int ctdbd_register_ips(struct ctdbd_connection *conn,
> const struct sockaddr_storage *server,
> const struct sockaddr_storage *client,
> - int (*cb)(uint32_t src_vnn, uint32_t dst_vnn,
> + int (*cb)(struct tevent_context *ev,
> + uint32_t src_vnn, uint32_t dst_vnn,
> uint64_t dst_srvid,
> const uint8_t *msg, size_t msglen,
> void *private_data),
> @@ -89,7 +90,8 @@ int ctdb_unwatch(struct ctdbd_connection *conn);
> struct ctdb_req_message_old;
>
> int register_with_ctdbd(struct ctdbd_connection *conn, uint64_t srvid,
> - int (*cb)(uint32_t src_vnn, uint32_t dst_vnn,
> + int (*cb)(struct tevent_context *ev,
> + uint32_t src_vnn, uint32_t dst_vnn,
> uint64_t dst_srvid,
> const uint8_t *msg, size_t msglen,
> void *private_data),
> diff --git a/source3/lib/ctdb_dummy.c b/source3/lib/ctdb_dummy.c
> index 2ed7b10..4e3e4bc 100644
> --- a/source3/lib/ctdb_dummy.c
> +++ b/source3/lib/ctdb_dummy.c
> @@ -38,7 +38,8 @@ int ctdbd_messaging_send_iov(struct ctdbd_connection *conn,
> }
>
> int register_with_ctdbd(struct ctdbd_connection *conn, uint64_t srvid,
> - int (*cb)(uint32_t src_vnn, uint32_t dst_vnn,
> + int (*cb)(struct tevent_context *ev,
> + uint32_t src_vnn, uint32_t dst_vnn,
> uint64_t dst_srvid,
> const uint8_t *msg, size_t msglen,
> void *private_data),
> @@ -50,7 +51,8 @@ int register_with_ctdbd(struct ctdbd_connection *conn, uint64_t srvid,
> int ctdbd_register_ips(struct ctdbd_connection *conn,
> const struct sockaddr_storage *_server,
> const struct sockaddr_storage *_client,
> - int (*cb)(uint32_t src_vnn, uint32_t dst_vnn,
> + int (*cb)(struct tevent_context *ev,
> + uint32_t src_vnn, uint32_t dst_vnn,
> uint64_t dst_srvid,
> const uint8_t *msg, size_t msglen,
> void *private_data),
> diff --git a/source3/lib/ctdbd_conn.c b/source3/lib/ctdbd_conn.c
> index 3adb57d..88d45b4 100644
> --- a/source3/lib/ctdbd_conn.c
> +++ b/source3/lib/ctdbd_conn.c
> @@ -41,7 +41,8 @@
>
> struct ctdbd_srvid_cb {
> uint64_t srvid;
> - int (*cb)(uint32_t src_vnn, uint32_t dst_vnn,
> + int (*cb)(struct tevent_context *ev,
> + uint32_t src_vnn, uint32_t dst_vnn,
> uint64_t dst_srvid,
> const uint8_t *msg, size_t msglen,
> void *private_data);
> @@ -143,7 +144,8 @@ static void ctdb_packet_dump(struct ctdb_req_header *hdr)
> * Register a srvid with ctdbd
> */
> int register_with_ctdbd(struct ctdbd_connection *conn, uint64_t srvid,
> - int (*cb)(uint32_t src_vnn, uint32_t dst_vnn,
> + int (*cb)(struct tevent_context *ev,
> + uint32_t src_vnn, uint32_t dst_vnn,
> uint64_t dst_srvid,
> const uint8_t *msg, size_t msglen,
> void *private_data),
> @@ -204,7 +206,8 @@ static int ctdbd_msg_call_back(struct ctdbd_connection *conn,
> if ((cb->srvid == msg->srvid) && (cb->cb != NULL)) {
> int ret;
>
> - ret = cb->cb(msg->hdr.srcnode, msg->hdr.destnode,
> + ret = cb->cb(NULL,
> + msg->hdr.srcnode, msg->hdr.destnode,
> msg->srvid, msg->data, msg->datalen,
> cb->private_data);
> if (ret != 0) {
> @@ -1154,7 +1157,8 @@ static void smbd_ctdb_canonicalize_ip(const struct sockaddr_storage *in,
> int ctdbd_register_ips(struct ctdbd_connection *conn,
> const struct sockaddr_storage *_server,
> const struct sockaddr_storage *_client,
> - int (*cb)(uint32_t src_vnn, uint32_t dst_vnn,
> + int (*cb)(struct tevent_context *ev,
> + uint32_t src_vnn, uint32_t dst_vnn,
> uint64_t dst_srvid,
> const uint8_t *msg, size_t msglen,
> void *private_data),
> diff --git a/source3/lib/messages_ctdbd.c b/source3/lib/messages_ctdbd.c
> index 6ecec32..10696ac 100644
> --- a/source3/lib/messages_ctdbd.c
> +++ b/source3/lib/messages_ctdbd.c
> @@ -109,6 +109,7 @@ static int messaging_ctdbd_destructor(struct messaging_ctdbd_context *ctx)
> }
>
> static int messaging_ctdb_recv(
> + struct tevent_context *ev,
> uint32_t src_vnn, uint32_t dst_vnn, uint64_t dst_srvid,
> const uint8_t *msg, size_t msg_len, void *private_data)
> {
> diff --git a/source3/smbd/notifyd/notifyd.c b/source3/smbd/notifyd/notifyd.c
> index caf894e..11059ec 100644
> --- a/source3/smbd/notifyd/notifyd.c
> +++ b/source3/smbd/notifyd/notifyd.c
> @@ -179,7 +179,8 @@ static int sys_notify_watch_dummy(
> #ifdef CLUSTER_SUPPORT
> static void notifyd_broadcast_reclog_finished(struct tevent_req *subreq);
> static void notifyd_clean_peers_finished(struct tevent_req *subreq);
> -static int notifyd_snoop_broadcast(uint32_t src_vnn, uint32_t dst_vnn,
> +static int notifyd_snoop_broadcast(struct tevent_context *ev,
> + uint32_t src_vnn, uint32_t dst_vnn,
> uint64_t dst_srvid,
> const uint8_t *msg, size_t msglen,
> void *private_data);
> @@ -1387,7 +1388,8 @@ fail:
> * broadcast, which will then trigger a fresh database pull.
> */
>
> -static int notifyd_snoop_broadcast(uint32_t src_vnn, uint32_t dst_vnn,
> +static int notifyd_snoop_broadcast(struct tevent_context *ev,
> + uint32_t src_vnn, uint32_t dst_vnn,
> uint64_t dst_srvid,
> const uint8_t *msg, size_t msglen,
> void *private_data)
> diff --git a/source3/smbd/process.c b/source3/smbd/process.c
> index a19b8b7..4abaf37 100644
> --- a/source3/smbd/process.c
> +++ b/source3/smbd/process.c
> @@ -2695,7 +2695,8 @@ static void smbd_release_ip_immediate(struct tevent_context *ctx,
> /****************************************************************************
> received when we should release a specific IP
> ****************************************************************************/
> -static int release_ip(uint32_t src_vnn, uint32_t dst_vnn,
> +static int release_ip(struct tevent_context *ev,
> + uint32_t src_vnn, uint32_t dst_vnn,
> uint64_t dst_srvid,
> const uint8_t *msg, size_t msglen,
> void *private_data)
> diff --git a/source3/smbd/server.c b/source3/smbd/server.c
> index e18a4e5..91fa1c3 100644
> --- a/source3/smbd/server.c
> +++ b/source3/smbd/server.c
> @@ -276,6 +276,7 @@ static void smbd_parent_id_cache_delete(struct messaging_context *ctx,
>
> #ifdef CLUSTER_SUPPORT
> static int smbd_parent_ctdb_reconfigured(
> + struct tevent_context *ev,
> uint32_t src_vnn, uint32_t dst_vnn, uint64_t dst_srvid,
> const uint8_t *msg, size_t msglen, void *private_data)
> {
> --
> 2.1.4
>
>
> From 1ac08cb17739a4588eb5d64c76ccd04f4bcf474e Mon Sep 17 00:00:00 2001
> From: Volker Lendecke <vl at samba.org>
> Date: Thu, 1 Jun 2017 17:49:56 +0200
> Subject: [PATCH 27/41] ctdbd_conn: Pass "ev" through ctdbd_msg_call_back
>
> Signed-off-by: Volker Lendecke <vl at samba.org>
> ---
> source3/lib/ctdbd_conn.c | 9 +++++----
> 1 file changed, 5 insertions(+), 4 deletions(-)
>
> diff --git a/source3/lib/ctdbd_conn.c b/source3/lib/ctdbd_conn.c
> index 88d45b4..8fb951d 100644
> --- a/source3/lib/ctdbd_conn.c
> +++ b/source3/lib/ctdbd_conn.c
> @@ -179,7 +179,8 @@ int register_with_ctdbd(struct ctdbd_connection *conn, uint64_t srvid,
> return 0;
> }
>
> -static int ctdbd_msg_call_back(struct ctdbd_connection *conn,
> +static int ctdbd_msg_call_back(struct tevent_context *ev,
> + struct ctdbd_connection *conn,
> struct ctdb_req_message_old *msg)
> {
> uint32_t msg_len;
> @@ -206,7 +207,7 @@ static int ctdbd_msg_call_back(struct ctdbd_connection *conn,
> if ((cb->srvid == msg->srvid) && (cb->cb != NULL)) {
> int ret;
>
> - ret = cb->cb(NULL,
> + ret = cb->cb(ev,
> msg->hdr.srcnode, msg->hdr.destnode,
> msg->srvid, msg->data, msg->datalen,
> cb->private_data);
> @@ -414,7 +415,7 @@ static int ctdb_read_req(struct ctdbd_connection *conn, uint32_t reqid,
> if (hdr->operation == CTDB_REQ_MESSAGE) {
> struct ctdb_req_message_old *msg = (struct ctdb_req_message_old *)hdr;
>
> - ret = ctdbd_msg_call_back(conn, msg);
> + ret = ctdbd_msg_call_back(NULL, conn, msg);
> if (ret != 0) {
> TALLOC_FREE(hdr);
> return ret;
> @@ -586,7 +587,7 @@ static int ctdb_handle_message(struct ctdbd_connection *conn,
>
> msg = (struct ctdb_req_message_old *)hdr;
>
> - ctdbd_msg_call_back(conn, msg);
> + ctdbd_msg_call_back(NULL, conn, msg);
>
> return 0;
> }
> --
> 2.1.4
>
>
> From 585a44ea0c232f846e0105e28ccca39e414e333e Mon Sep 17 00:00:00 2001
> From: Volker Lendecke <vl at samba.org>
> Date: Thu, 1 Jun 2017 17:55:06 +0200
> Subject: [PATCH 28/41] ctdbd_conn: Pass "ev" through ctdb_handle_message
>
> Signed-off-by: Volker Lendecke <vl at samba.org>
> ---
> source3/lib/ctdbd_conn.c | 7 ++++---
> 1 file changed, 4 insertions(+), 3 deletions(-)
>
> diff --git a/source3/lib/ctdbd_conn.c b/source3/lib/ctdbd_conn.c
> index 8fb951d..41c9af0 100644
> --- a/source3/lib/ctdbd_conn.c
> +++ b/source3/lib/ctdbd_conn.c
> @@ -574,7 +574,8 @@ int ctdbd_conn_get_fd(struct ctdbd_connection *conn)
> /*
> * Packet handler to receive and handle a ctdb message
> */
> -static int ctdb_handle_message(struct ctdbd_connection *conn,
> +static int ctdb_handle_message(struct tevent_context *ev,
> + struct ctdbd_connection *conn,
> struct ctdb_req_header *hdr)
> {
> struct ctdb_req_message_old *msg;
> @@ -587,7 +588,7 @@ static int ctdb_handle_message(struct ctdbd_connection *conn,
>
> msg = (struct ctdb_req_message_old *)hdr;
>
> - ctdbd_msg_call_back(NULL, conn, msg);
> + ctdbd_msg_call_back(ev, conn, msg);
>
> return 0;
> }
> @@ -603,7 +604,7 @@ void ctdbd_socket_readable(struct ctdbd_connection *conn)
> cluster_fatal("ctdbd died\n");
> }
>
> - ret = ctdb_handle_message(conn, hdr);
> + ret = ctdb_handle_message(NULL, conn, hdr);
>
> TALLOC_FREE(hdr);
>
> --
> 2.1.4
>
>
> From 2ac86e871cbd56224b3993a75c513eeb633249ba Mon Sep 17 00:00:00 2001
> From: Volker Lendecke <vl at samba.org>
> Date: Thu, 1 Jun 2017 18:00:45 +0200
> Subject: [PATCH 29/41] ctdbd_conn: Pass "ev" through ctdbd_socket_readable
>
> Signed-off-by: Volker Lendecke <vl at samba.org>
> ---
> source3/include/ctdbd_conn.h | 3 ++-
> source3/lib/ctdbd_conn.c | 5 +++--
> source3/lib/messages_ctdbd.c | 2 +-
> 3 files changed, 6 insertions(+), 4 deletions(-)
>
> diff --git a/source3/include/ctdbd_conn.h b/source3/include/ctdbd_conn.h
> index 44ee8ab..1a21c75 100644
> --- a/source3/include/ctdbd_conn.h
> +++ b/source3/include/ctdbd_conn.h
> @@ -42,7 +42,8 @@ int ctdbd_setup_fde(struct ctdbd_connection *conn, struct tevent_context *ev);
> uint32_t ctdbd_vnn(const struct ctdbd_connection *conn);
>
> int ctdbd_conn_get_fd(struct ctdbd_connection *conn);
> -void ctdbd_socket_readable(struct ctdbd_connection *conn);
> +void ctdbd_socket_readable(struct tevent_context *ev,
> + struct ctdbd_connection *conn);
>
> int ctdbd_messaging_send_iov(struct ctdbd_connection *conn,
> uint32_t dst_vnn, uint64_t dst_srvid,
> diff --git a/source3/lib/ctdbd_conn.c b/source3/lib/ctdbd_conn.c
> index 41c9af0..94cd22e 100644
> --- a/source3/lib/ctdbd_conn.c
> +++ b/source3/lib/ctdbd_conn.c
> @@ -593,7 +593,8 @@ static int ctdb_handle_message(struct tevent_context *ev,
> return 0;
> }
>
> -void ctdbd_socket_readable(struct ctdbd_connection *conn)
> +void ctdbd_socket_readable(struct tevent_context *ev,
> + struct ctdbd_connection *conn)
> {
> struct ctdb_req_header *hdr = NULL;
> int ret;
> @@ -604,7 +605,7 @@ void ctdbd_socket_readable(struct ctdbd_connection *conn)
> cluster_fatal("ctdbd died\n");
> }
>
> - ret = ctdb_handle_message(NULL, conn, hdr);
> + ret = ctdb_handle_message(ev, conn, hdr);
>
> TALLOC_FREE(hdr);
>
> diff --git a/source3/lib/messages_ctdbd.c b/source3/lib/messages_ctdbd.c
> index 10696ac..48d5488 100644
> --- a/source3/lib/messages_ctdbd.c
> +++ b/source3/lib/messages_ctdbd.c
> @@ -174,7 +174,7 @@ static void messaging_ctdbd_readable(struct tevent_context *ev,
> if ((flags & TEVENT_FD_READ) == 0) {
> return;
> }
> - ctdbd_socket_readable(conn);
> + ctdbd_socket_readable(ev, conn);
> }
>
> static int messaging_ctdbd_init_internal(struct messaging_context *msg_ctx,
> --
> 2.1.4
>
>
> From 5f5a735a1f3c7088ec6e8eeba378d237bfe8230b Mon Sep 17 00:00:00 2001
> From: Volker Lendecke <vl at samba.org>
> Date: Thu, 8 Jun 2017 12:51:29 +0200
> Subject: [PATCH 30/41] messaging: Add messaging_ctdbd_register_tevent_context
>
> We need to listen for the ctdb socket in nested event contexts
>
> Signed-off-by: Volker Lendecke <vl at samba.org>
> ---
> source3/lib/ctdb_dummy.c | 7 +++
> source3/lib/messages.c | 30 +++++++++++-
> source3/lib/messages_ctdbd.c | 109 +++++++++++++++++++++++++++++++++++++------
> source3/lib/messages_ctdbd.h | 5 ++
> 4 files changed, 135 insertions(+), 16 deletions(-)
>
> diff --git a/source3/lib/ctdb_dummy.c b/source3/lib/ctdb_dummy.c
> index 4e3e4bc..4c0403c 100644
> --- a/source3/lib/ctdb_dummy.c
> +++ b/source3/lib/ctdb_dummy.c
> @@ -93,6 +93,13 @@ int messaging_ctdbd_reinit(struct messaging_context *msg_ctx,
> return ENOSYS;
> }
>
> +struct messaging_ctdbd_fde *messaging_ctdbd_register_tevent_context(
> + TALLOC_CTX *mem_ctx, struct tevent_context *ev,
> + struct messaging_backend *backend)
> +{
> + return NULL;
> +}
> +
> struct ctdbd_connection *messaging_ctdbd_connection(void)
> {
> return NULL;
> diff --git a/source3/lib/messages.c b/source3/lib/messages.c
> index 5c10013..759cc8b 100644
> --- a/source3/lib/messages.c
> +++ b/source3/lib/messages.c
> @@ -91,6 +91,7 @@ struct messaging_context {
>
> void *msg_dgm_ref;
> struct messaging_backend *remote;
> + struct messaging_ctdbd_fde *cluster_fde;
>
> struct server_id_db *names_db;
> };
> @@ -520,6 +521,14 @@ static NTSTATUS messaging_init_internal(TALLOC_CTX *mem_ctx,
> status = map_nt_error_from_unix(ret);
> goto done;
> }
> + ctx->cluster_fde = messaging_ctdbd_register_tevent_context(
> + ctx, ctx->event_ctx, ctx->remote);
> + if (ctx->cluster_fde == NULL) {
> + DBG_WARNING("messaging_ctdbd_register_tevent_context "
> + "failed\n");
> + status = NT_STATUS_NO_MEMORY;
> + goto done;
> + }
> }
> ctx->id.vnn = get_my_vnn();
>
> @@ -616,14 +625,23 @@ NTSTATUS messaging_reinit(struct messaging_context *msg_ctx)
> }
>
> if (lp_clustering()) {
> + TALLOC_FREE(msg_ctx->cluster_fde);
> +
> ret = messaging_ctdbd_reinit(msg_ctx, msg_ctx,
> msg_ctx->remote);
> -
> if (ret != 0) {
> DEBUG(1, ("messaging_ctdbd_init failed: %s\n",
> strerror(ret)));
> return map_nt_error_from_unix(ret);
> }
> +
> + msg_ctx->cluster_fde = messaging_ctdbd_register_tevent_context(
> + msg_ctx, msg_ctx->event_ctx, msg_ctx->remote);
> + if (msg_ctx->cluster_fde == NULL) {
> + DBG_WARNING("messaging_ctdbd_register_tevent_context "
> + "failed\n");
> + return NT_STATUS_NO_MEMORY;
> + }
> }
>
> server_id_db_reinit(msg_ctx->names_db, msg_ctx->id);
> @@ -869,6 +887,7 @@ struct messaging_filtered_read_state {
> struct tevent_context *ev;
> struct messaging_context *msg_ctx;
> struct messaging_dgm_fde *fde;
> + struct messaging_ctdbd_fde *cluster_fde;
>
> bool (*filter)(struct messaging_rec *rec, void *private_data);
> void *private_data;
> @@ -911,6 +930,14 @@ struct tevent_req *messaging_filtered_read_send(
> return tevent_req_post(req, ev);
> }
>
> + if (msg_ctx->remote != NULL) {
> + state->cluster_fde = messaging_ctdbd_register_tevent_context(
> + state, ev, msg_ctx->remote);
> + if (tevent_req_nomem(state->cluster_fde, req)) {
> + return tevent_req_post(req, ev);
> + }
> + }
> +
> /*
> * We add ourselves to the "new_waiters" array, not the "waiters"
> * array. If we are called from within messaging_read_done,
> @@ -957,6 +984,7 @@ static void messaging_filtered_read_cleanup(struct tevent_req *req,
> tevent_req_set_cleanup_fn(req, NULL);
>
> TALLOC_FREE(state->fde);
> + TALLOC_FREE(state->cluster_fde);
>
> ok = messaging_deregister_event_context(msg_ctx, state->ev);
> if (!ok) {
> diff --git a/source3/lib/messages_ctdbd.c b/source3/lib/messages_ctdbd.c
> index 48d5488..62b5082 100644
> --- a/source3/lib/messages_ctdbd.c
> +++ b/source3/lib/messages_ctdbd.c
> @@ -27,10 +27,26 @@
> #include "ctdbd_conn.h"
> #include "lib/cluster_support.h"
>
> +struct messaging_ctdbd_context;
> +
> +struct messaging_ctdbd_fde_ev {
> + struct messaging_ctdbd_fde_ev *prev, *next;
> +
> + /*
> + * Backreference to enable DLIST_REMOVE from our
> + * destructor. Also, set to NULL when the dgm_context dies
> + * before the messaging_dgm_fde_ev.
> + */
> + struct messaging_ctdbd_context *ctx;
> +
> + struct tevent_context *ev;
> + struct tevent_fd *fde;
> +};
>
> struct messaging_ctdbd_context {
> struct ctdbd_connection *conn;
> - struct tevent_fd *fde;
> +
> + struct messaging_ctdbd_fde_ev *fde_evs;
> };
>
> /*
> @@ -182,12 +198,9 @@ static int messaging_ctdbd_init_internal(struct messaging_context *msg_ctx,
> struct messaging_ctdbd_context *ctx,
> bool reinit)
> {
> - struct tevent_context *ev;
> - int ret, ctdb_fd;
> + int ret;
>
> if (reinit) {
> - TALLOC_FREE(ctx->fde);
> -
> ret = ctdbd_reinit_connection(ctx,
> lp_ctdbd_socket(),
> lp_ctdb_timeout(),
> @@ -224,15 +237,6 @@ static int messaging_ctdbd_init_internal(struct messaging_context *msg_ctx,
> return ret;
> }
>
> - ctdb_fd = ctdbd_conn_get_fd(ctx->conn);
> - ev = messaging_tevent_context(msg_ctx);
> -
> - ctx->fde = tevent_add_fd(ev, ctx, ctdb_fd, TEVENT_FD_READ,
> - messaging_ctdbd_readable, ctx->conn);
> - if (ctx->fde == NULL) {
> - return ENOMEM;
> - }
> -
> global_ctdb_connection_pid = getpid();
> global_ctdbd_connection = ctx->conn;
> talloc_set_destructor(ctx, messaging_ctdbd_destructor);
> @@ -255,7 +259,7 @@ int messaging_ctdbd_init(struct messaging_context *msg_ctx,
> return ENOMEM;
> }
>
> - if (!(ctx = talloc(result, struct messaging_ctdbd_context))) {
> + if (!(ctx = talloc_zero(result, struct messaging_ctdbd_context))) {
> DEBUG(0, ("talloc failed\n"));
> TALLOC_FREE(result);
> return ENOMEM;
> @@ -289,3 +293,78 @@ int messaging_ctdbd_reinit(struct messaging_context *msg_ctx,
>
> return 0;
> }
> +
> +struct messaging_ctdbd_fde {
> + struct tevent_fd *fde;
> +};
> +
> +static int messaging_ctdbd_fde_ev_destructor(
> + struct messaging_ctdbd_fde_ev *fde_ev)
> +{
> + if (fde_ev->ctx != NULL) {
> + DLIST_REMOVE(fde_ev->ctx->fde_evs, fde_ev);
> + fde_ev->ctx = NULL;
> + }
> + return 0;
> +}
> +
> +struct messaging_ctdbd_fde *messaging_ctdbd_register_tevent_context(
> + TALLOC_CTX *mem_ctx, struct tevent_context *ev,
> + struct messaging_backend *backend)
> +{
> + struct messaging_ctdbd_context *ctx = talloc_get_type_abort(
> + backend->private_data, struct messaging_ctdbd_context);
> + struct messaging_ctdbd_fde_ev *fde_ev;
> + struct messaging_ctdbd_fde *fde;
> +
> + if (ctx == NULL) {
> + return NULL;
> + }
> +
> + fde = talloc(mem_ctx, struct messaging_ctdbd_fde);
> + if (fde == NULL) {
> + return NULL;
> + }
> +
> + for (fde_ev = ctx->fde_evs; fde_ev != NULL; fde_ev = fde_ev->next) {
> + if ((fde_ev->ev == ev) &&
> + (tevent_fd_get_flags(fde_ev->fde) != 0)) {
> + break;
> + }
> + }
> +
> + if (fde_ev == NULL) {
> + int fd = ctdbd_conn_get_fd(ctx->conn);
> +
> + fde_ev = talloc(fde, struct messaging_ctdbd_fde_ev);
> + if (fde_ev == NULL) {
> + return NULL;
> + }
> + fde_ev->fde = tevent_add_fd(
> + ev, fde_ev, fd, TEVENT_FD_READ,
> + messaging_ctdbd_readable, ctx->conn);
> + if (fde_ev->fde == NULL) {
> + TALLOC_FREE(fde);
> + return NULL;
> + }
> + fde_ev->ev = ev;
> + fde_ev->ctx = ctx;
> + DLIST_ADD(ctx->fde_evs, fde_ev);
> + talloc_set_destructor(
> + fde_ev, messaging_ctdbd_fde_ev_destructor);
> + } else {
> + /*
> + * Same trick as with tdb_wrap: The caller will never
> + * see the talloc_referenced object, the
> + * messaging_ctdbd_fde_ev, so problems with
> + * talloc_unlink will not happen.
> + */
> + if (talloc_reference(fde, fde_ev) == NULL) {
> + TALLOC_FREE(fde);
> + return NULL;
> + }
> + }
> +
> + fde->fde = fde_ev->fde;
> + return fde;
> +}
> diff --git a/source3/lib/messages_ctdbd.h b/source3/lib/messages_ctdbd.h
> index 67ec4b7..c13079d 100644
> --- a/source3/lib/messages_ctdbd.h
> +++ b/source3/lib/messages_ctdbd.h
> @@ -35,4 +35,9 @@ int messaging_ctdbd_reinit(struct messaging_context *msg_ctx,
> struct messaging_backend *backend);
> struct ctdbd_connection *messaging_ctdbd_connection(void);
>
> +struct messaging_ctdbd_fde;
> +struct messaging_ctdbd_fde *messaging_ctdbd_register_tevent_context(
> + TALLOC_CTX *mem_ctx, struct tevent_context *ev,
> + struct messaging_backend *backend);
> +
> #endif
> --
> 2.1.4
>
>
> From 44b399093c5e9ca31bdc835af6c74d80bd39a53f Mon Sep 17 00:00:00 2001
> From: Volker Lendecke <vl at samba.org>
> Date: Thu, 1 Jun 2017 18:58:16 +0200
> Subject: [PATCH 31/41] messages_ctdb: Handle async msgs for nested event
> contexts
>
> Signed-off-by: Volker Lendecke <vl at samba.org>
> ---
> source3/lib/ctdb_dummy.c | 10 +++++
> source3/lib/messages.c | 9 +++--
> source3/lib/messages_ctdbd.c | 88 ++++++++++++++++++--------------------------
> source3/lib/messages_ctdbd.h | 10 +++++
> 4 files changed, 62 insertions(+), 55 deletions(-)
>
> diff --git a/source3/lib/ctdb_dummy.c b/source3/lib/ctdb_dummy.c
> index 4c0403c..b6ec228 100644
> --- a/source3/lib/ctdb_dummy.c
> +++ b/source3/lib/ctdb_dummy.c
> @@ -81,6 +81,11 @@ struct db_context *db_open_ctdb(TALLOC_CTX *mem_ctx,
>
> int messaging_ctdbd_init(struct messaging_context *msg_ctx,
> TALLOC_CTX *mem_ctx,
> + void (*recv_cb)(struct tevent_context *ev,
> + const uint8_t *msg, size_t msg_len,
> + int *fds, size_t num_fds,
> + void *private_data),
> + void *private_data,
> struct messaging_backend **presult)
> {
> return ENOSYS;
> @@ -88,6 +93,11 @@ int messaging_ctdbd_init(struct messaging_context *msg_ctx,
>
> int messaging_ctdbd_reinit(struct messaging_context *msg_ctx,
> TALLOC_CTX *mem_ctx,
> + void (*recv_cb)(struct tevent_context *ev,
> + const uint8_t *msg, size_t msg_len,
> + int *fds, size_t num_fds,
> + void *private_data),
> + void *private_data,
> struct messaging_backend *backend)
> {
> return ENOSYS;
> diff --git a/source3/lib/messages.c b/source3/lib/messages.c
> index 759cc8b..4e838b0 100644
> --- a/source3/lib/messages.c
> +++ b/source3/lib/messages.c
> @@ -513,7 +513,8 @@ static NTSTATUS messaging_init_internal(TALLOC_CTX *mem_ctx,
> talloc_set_destructor(ctx, messaging_context_destructor);
>
> if (lp_clustering()) {
> - ret = messaging_ctdbd_init(ctx, ctx, &ctx->remote);
> + ret = messaging_ctdbd_init(
> + ctx, ctx, messaging_recv_cb, ctx, &ctx->remote);
>
> if (ret != 0) {
> DEBUG(2, ("messaging_ctdbd_init failed: %s\n",
> @@ -627,8 +628,10 @@ NTSTATUS messaging_reinit(struct messaging_context *msg_ctx)
> if (lp_clustering()) {
> TALLOC_FREE(msg_ctx->cluster_fde);
>
> - ret = messaging_ctdbd_reinit(msg_ctx, msg_ctx,
> - msg_ctx->remote);
> + ret = messaging_ctdbd_reinit(
> + msg_ctx, msg_ctx, messaging_recv_cb, msg_ctx,
> + msg_ctx->remote);
> +
> if (ret != 0) {
> DEBUG(1, ("messaging_ctdbd_init failed: %s\n",
> strerror(ret)));
> diff --git a/source3/lib/messages_ctdbd.c b/source3/lib/messages_ctdbd.c
> index 62b5082..b1af4f8 100644
> --- a/source3/lib/messages_ctdbd.c
> +++ b/source3/lib/messages_ctdbd.c
> @@ -47,6 +47,12 @@ struct messaging_ctdbd_context {
> struct ctdbd_connection *conn;
>
> struct messaging_ctdbd_fde_ev *fde_evs;
> +
> + void (*recv_cb)(struct tevent_context *ev,
> + const uint8_t *msg, size_t msg_len,
> + int *fds, size_t num_fds,
> + void *private_data);
> + void *private_data;
> };
>
> /*
> @@ -129,52 +135,10 @@ static int messaging_ctdb_recv(
> uint32_t src_vnn, uint32_t dst_vnn, uint64_t dst_srvid,
> const uint8_t *msg, size_t msg_len, void *private_data)
> {
> - struct messaging_context *msg_ctx = talloc_get_type_abort(
> - private_data, struct messaging_context);
> - struct server_id me = messaging_server_id(msg_ctx);
> - int ret;
> - struct iovec iov;
> - struct server_id src, dst;
> - enum messaging_type msg_type;
> - struct server_id_buf idbuf;
> -
> - if (msg_len < MESSAGE_HDR_LENGTH) {
> - DEBUG(1, ("%s: message too short: %u\n", __func__,
> - (unsigned)msg_len));
> - return 0;
> - }
> -
> - message_hdr_get(&msg_type, &src, &dst, msg);
> -
> - iov = (struct iovec) {
> - .iov_base = discard_const_p(uint8_t, msg) + MESSAGE_HDR_LENGTH,
> - .iov_len = msg_len - MESSAGE_HDR_LENGTH
> - };
> -
> - DEBUG(10, ("%s: Received message 0x%x len %u from %s\n",
> - __func__, (unsigned)msg_type, (unsigned)msg_len,
> - server_id_str_buf(src, &idbuf)));
> -
> - if (!server_id_same_process(&me, &dst)) {
> - struct server_id_buf id1, id2;
> -
> - DEBUG(10, ("%s: I'm %s, ignoring msg to %s\n", __func__,
> - server_id_str_buf(me, &id1),
> - server_id_str_buf(dst, &id2)));
> - return 0;
> - }
> -
> - /*
> - * Go through the event loop
> - */
> -
> - ret = messaging_send_iov_from(msg_ctx, src, dst, msg_type,
> - &iov, 1, NULL, 0);
> + struct messaging_ctdbd_context *ctx = talloc_get_type_abort(
> + private_data, struct messaging_ctdbd_context);
>
> - if (ret != 0) {
> - DEBUG(10, ("%s: messaging_send_iov_from failed: %s\n",
> - __func__, strerror(ret)));
> - }
> + ctx->recv_cb(ev, msg, msg_len, NULL, 0, ctx->private_data);
>
> return 0;
> }
> @@ -193,10 +157,15 @@ static void messaging_ctdbd_readable(struct tevent_context *ev,
> ctdbd_socket_readable(ev, conn);
> }
>
> -static int messaging_ctdbd_init_internal(struct messaging_context *msg_ctx,
> - TALLOC_CTX *mem_ctx,
> - struct messaging_ctdbd_context *ctx,
> - bool reinit)
> +static int messaging_ctdbd_init_internal(
> + struct messaging_context *msg_ctx, TALLOC_CTX *mem_ctx,
> + struct messaging_ctdbd_context *ctx,
> + void (*recv_cb)(struct tevent_context *ev,
> + const uint8_t *msg, size_t msg_len,
> + int *fds, size_t num_fds,
> + void *private_data),
> + void *private_data,
> + bool reinit)
> {
> int ret;
>
> @@ -229,8 +198,11 @@ static int messaging_ctdbd_init_internal(struct messaging_context *msg_ctx,
> return ret;
> }
>
> + ctx->recv_cb = recv_cb;
> + ctx->private_data = private_data;
> +
> ret = register_with_ctdbd(ctx->conn, getpid(),
> - messaging_ctdb_recv, msg_ctx);
> + messaging_ctdb_recv, ctx);
> if (ret != 0) {
> DEBUG(10, ("register_with_ctdbd failed: %s\n",
> strerror(ret)));
> @@ -248,6 +220,11 @@ static int messaging_ctdbd_init_internal(struct messaging_context *msg_ctx,
>
> int messaging_ctdbd_init(struct messaging_context *msg_ctx,
> TALLOC_CTX *mem_ctx,
> + void (*recv_cb)(struct tevent_context *ev,
> + const uint8_t *msg, size_t msg_len,
> + int *fds, size_t num_fds,
> + void *private_data),
> + void *private_data,
> struct messaging_backend **presult)
> {
> struct messaging_backend *result;
> @@ -265,7 +242,8 @@ int messaging_ctdbd_init(struct messaging_context *msg_ctx,
> return ENOMEM;
> }
>
> - ret = messaging_ctdbd_init_internal(msg_ctx, mem_ctx, ctx, false);
> + ret = messaging_ctdbd_init_internal(msg_ctx, mem_ctx, ctx,
> + recv_cb, private_data, false);
> if (ret != 0) {
> TALLOC_FREE(result);
> return ret;
> @@ -280,13 +258,19 @@ int messaging_ctdbd_init(struct messaging_context *msg_ctx,
>
> int messaging_ctdbd_reinit(struct messaging_context *msg_ctx,
> TALLOC_CTX *mem_ctx,
> + void (*recv_cb)(struct tevent_context *ev,
> + const uint8_t *msg, size_t msg_len,
> + int *fds, size_t num_fds,
> + void *private_data),
> + void *private_data,
> struct messaging_backend *backend)
> {
> struct messaging_ctdbd_context *ctx = talloc_get_type_abort(
> backend->private_data, struct messaging_ctdbd_context);
> int ret;
>
> - ret = messaging_ctdbd_init_internal(msg_ctx, mem_ctx, ctx, true);
> + ret = messaging_ctdbd_init_internal(msg_ctx, mem_ctx, ctx,
> + recv_cb, private_data, true);
> if (ret != 0) {
> return ret;
> }
> diff --git a/source3/lib/messages_ctdbd.h b/source3/lib/messages_ctdbd.h
> index c13079d..7d928fe 100644
> --- a/source3/lib/messages_ctdbd.h
> +++ b/source3/lib/messages_ctdbd.h
> @@ -29,9 +29,19 @@ struct ctdbd_connection;
>
> int messaging_ctdbd_init(struct messaging_context *msg_ctx,
> TALLOC_CTX *mem_ctx,
> + void (*recv_cb)(struct tevent_context *ev,
> + const uint8_t *msg, size_t msg_len,
> + int *fds, size_t num_fds,
> + void *private_data),
> + void *private_data,
> struct messaging_backend **presult);
> int messaging_ctdbd_reinit(struct messaging_context *msg_ctx,
> TALLOC_CTX *mem_ctx,
> + void (*recv_cb)(struct tevent_context *ev,
> + const uint8_t *msg, size_t msg_len,
> + int *fds, size_t num_fds,
> + void *private_data),
> + void *private_data,
> struct messaging_backend *backend);
> struct ctdbd_connection *messaging_ctdbd_connection(void);
>
> --
> 2.1.4
>
>
> From 962359dc5c074763d4be1ade8058103e2f7c35eb Mon Sep 17 00:00:00 2001
> From: Volker Lendecke <vl at samba.org>
> Date: Tue, 13 Sep 2016 14:22:05 +0200
> Subject: [PATCH 32/41] dbwrap: Avoid dbwrap_merge_dbufs in db_ctdb_storev
>
> Signed-off-by: Volker Lendecke <vl at samba.org>
> ---
> source3/lib/dbwrap/dbwrap_ctdb.c | 17 +++++------------
> 1 file changed, 5 insertions(+), 12 deletions(-)
>
> diff --git a/source3/lib/dbwrap/dbwrap_ctdb.c b/source3/lib/dbwrap/dbwrap_ctdb.c
> index 2969183..b722714 100644
> --- a/source3/lib/dbwrap/dbwrap_ctdb.c
> +++ b/source3/lib/dbwrap/dbwrap_ctdb.c
> @@ -182,16 +182,16 @@ static NTSTATUS db_ctdb_ltdb_parse(
> static NTSTATUS db_ctdb_ltdb_store(struct db_ctdb_ctx *db,
> TDB_DATA key,
> struct ctdb_ltdb_header *header,
> - TDB_DATA data)
> + const TDB_DATA *dbufs, int num_dbufs)
> {
> - TDB_DATA recs[2];
> + TDB_DATA recs[num_dbufs+1];
> int ret;
>
> recs[0] = (TDB_DATA) { .dptr = (uint8_t *)header,
> .dsize = sizeof(struct ctdb_ltdb_header) };
> - recs[1] = data;
> + memcpy(&recs[1], dbufs, sizeof(TDB_DATA) * num_dbufs);
>
> - ret = tdb_storev(db->wtdb->tdb, key, recs, 2, TDB_REPLACE);
> + ret = tdb_storev(db->wtdb->tdb, key, recs, num_dbufs + 1, TDB_REPLACE);
>
> return (ret == 0) ? NT_STATUS_OK
> : tdb_error_to_ntstatus(db->wtdb->tdb);
> @@ -905,16 +905,9 @@ static NTSTATUS db_ctdb_storev(struct db_record *rec,
> struct db_ctdb_rec *crec = talloc_get_type_abort(
> rec->private_data, struct db_ctdb_rec);
> NTSTATUS status;
> - TDB_DATA data;
> -
> - data = dbwrap_merge_dbufs(rec, dbufs, num_dbufs);
> - if (data.dptr == NULL) {
> - return NT_STATUS_NO_MEMORY;
> - }
>
> status = db_ctdb_ltdb_store(crec->ctdb_ctx, rec->key, &(crec->header),
> - data);
> - TALLOC_FREE(data.dptr);
> + dbufs, num_dbufs);
> return status;
> }
>
> --
> 2.1.4
>
>
> From 5163e1d5937dfacc6942b15b3f4970496f3e7c38 Mon Sep 17 00:00:00 2001
> From: Volker Lendecke <vl at samba.org>
> Date: Sun, 11 Jun 2017 10:45:25 +0200
> Subject: [PATCH 33/41] messaging: Add messaging_ctdb_init/destroy
>
> This models connecting to ctdb after the dgm code. The main point
> is that we should never open more than more ctdb socket for messaging.
>
> With more than one socket, we might end up with our pid registered with
> ctdb on more than one socket. This could lead to memory overconsumption
> in ctdb. ctdbd will eventually throw away messages, but they will take
> up space unnecessarily.
>
> Signed-off-by: Volker Lendecke <vl at samba.org>
> ---
> source3/lib/ctdb_dummy.c | 13 +++
> source3/lib/messages_ctdb.c | 260 ++++++++++++++++++++++++++++++++++++++++++++
> source3/lib/messages_ctdb.h | 42 +++++++
> source3/wscript_build | 1 +
> 4 files changed, 316 insertions(+)
> create mode 100644 source3/lib/messages_ctdb.c
> create mode 100644 source3/lib/messages_ctdb.h
>
> diff --git a/source3/lib/ctdb_dummy.c b/source3/lib/ctdb_dummy.c
> index b6ec228..855f56d 100644
> --- a/source3/lib/ctdb_dummy.c
> +++ b/source3/lib/ctdb_dummy.c
> @@ -20,6 +20,7 @@
> #include "includes.h"
> #include "messages.h"
> #include "lib/messages_ctdbd.h"
> +#include "lib/messages_ctdb.h"
> #include "ctdbd_conn.h"
> #include "lib/dbwrap/dbwrap.h"
> #include "lib/dbwrap/dbwrap_ctdb.h"
> @@ -91,6 +92,18 @@ int messaging_ctdbd_init(struct messaging_context *msg_ctx,
> return ENOSYS;
> }
>
> +int messaging_ctdb_send(uint32_t dst_vnn, uint64_t dst_srvid,
> + const struct iovec *iov, int iovlen)
> +{
> + return ENOSYS;
> +}
> +
> +struct messaging_ctdb_fde *messaging_ctdb_register_tevent_context(
> + TALLOC_CTX *mem_ctx, struct tevent_context *ev)
> +{
> + return NULL;
> +}
> +
> int messaging_ctdbd_reinit(struct messaging_context *msg_ctx,
> TALLOC_CTX *mem_ctx,
> void (*recv_cb)(struct tevent_context *ev,
> diff --git a/source3/lib/messages_ctdb.c b/source3/lib/messages_ctdb.c
> new file mode 100644
> index 0000000..5bc494d
> --- /dev/null
> +++ b/source3/lib/messages_ctdb.c
> @@ -0,0 +1,260 @@
> +/*
> + * Unix SMB/CIFS implementation.
> + * Samba internal messaging functions
> + * Copyright (C) 2017 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 "includes.h"
> +#include "lib/messages_ctdb.h"
> +#include "lib/util/server_id.h"
> +#include "messages.h"
> +#include "util_tdb.h"
> +#include "lib/util/iov_buf.h"
> +#include "lib/messages_util.h"
> +#include "ctdbd_conn.h"
> +#include "lib/cluster_support.h"
> +
> +struct messaging_ctdb_context;
> +
> +/*
> + * We can only have one tevent_fd per ctdb_context and per
> + * tevent_context. Maintain a list of registered tevent_contexts per
> + * ctdb_context.
> + */
> +struct messaging_ctdb_fde_ev {
> + struct messaging_ctdb_fde_ev *prev, *next;
> +
> + /*
> + * Backreference to enable DLIST_REMOVE from our
> + * destructor. Also, set to NULL when the ctdb_context dies
> + * before the messaging_ctdb_fde_ev.
> + */
> + struct messaging_ctdb_context *ctx;
> +
> + struct tevent_context *ev;
> + struct tevent_fd *fde;
> +};
> +
> +struct messaging_ctdb_context {
> + struct ctdbd_connection *conn;
> +
> + void (*recv_cb)(struct tevent_context *ev,
> + const uint8_t *msg, size_t msg_len,
> + int *fds, size_t num_fds,
> + void *private_data);
> + void *recv_cb_private_data;
> +
> + struct messaging_ctdb_fde_ev *fde_evs;
> +};
> +
> +static int messaging_ctdb_recv(
> + struct tevent_context *ev,
> + uint32_t src_vnn, uint32_t dst_vnn, uint64_t dst_srvid,
> + const uint8_t *msg, size_t msg_len, void *private_data)
> +{
> + struct messaging_ctdb_context *state = talloc_get_type_abort(
> + private_data, struct messaging_ctdb_context);
> +
> + state->recv_cb(ev, msg, msg_len, NULL, 0, state->recv_cb_private_data);
> +
> + return 0;
> +}
> +
> +struct messaging_ctdb_context *global_ctdb_context;
> +
> +int messaging_ctdb_init(const char *sockname, int timeout, uint64_t unique_id,
> + void (*recv_cb)(struct tevent_context *ev,
> + const uint8_t *msg, size_t msg_len,
> + int *fds, size_t num_fds,
> + void *private_data),
> + void *private_data)
> +{
> + struct messaging_ctdb_context *ctx;
> + int ret;
> +
> + if (global_ctdb_context != NULL) {
> + return EBUSY;
> + }
> +
> + ctx = talloc_zero(NULL, struct messaging_ctdb_context);
> + if (ctx == NULL) {
> + return ENOMEM;
> + }
> + ctx->recv_cb = recv_cb;
> + ctx->recv_cb_private_data = private_data;
> +
> + ret = ctdbd_init_connection(ctx, sockname, timeout, &ctx->conn);
> + if (ret != 0) {
> + DBG_DEBUG("ctdbd_init_connection returned %s\n",
> + strerror(ret));
> + goto fail;
> + }
> +
> + ret = register_with_ctdbd(ctx->conn, getpid(), messaging_ctdb_recv,
> + ctx);
> + if (ret != 0) {
> + DBG_DEBUG("register_with_ctdbd returned %s (%d)\n",
> + strerror(ret), ret);
> + goto fail;
> + }
> +
> + ret = register_with_ctdbd(ctx->conn, unique_id, NULL, NULL);
> + if (ret != 0) {
> + DBG_DEBUG("register_with_ctdbd returned %s (%d)\n",
> + strerror(ret), ret);
> + goto fail;
> + }
> +
> + set_my_vnn(ctdbd_vnn(ctx->conn));
> +
> + global_ctdb_context = ctx;
> + return 0;
> +fail:
> + TALLOC_FREE(ctx);
> + return ret;
> +}
> +
> +void messaging_ctdb_destroy(void)
> +{
> + TALLOC_FREE(global_ctdb_context);
> +}
> +
> +int messaging_ctdb_send(uint32_t dst_vnn, uint64_t dst_srvid,
> + const struct iovec *iov, int iovlen)
> +{
> + struct messaging_ctdb_context *ctx = global_ctdb_context;
> + int ret;
> +
> + if (ctx == NULL) {
> + return ENOTCONN;
> + }
> +
> + ret = ctdbd_messaging_send_iov(ctx->conn, dst_vnn, dst_srvid,
> + iov, iovlen);
> + return ret;
> +}
> +
> +static void messaging_ctdb_read_handler(struct tevent_context *ev,
> + struct tevent_fd *fde,
> + uint16_t flags,
> + void *private_data)
> +{
> + struct messaging_ctdb_context *ctx = talloc_get_type_abort(
> + private_data, struct messaging_ctdb_context);
> +
> + if ((flags & TEVENT_FD_READ) == 0) {
> + return;
> + }
> + ctdbd_socket_readable(ev, ctx->conn);
> +}
> +
> +struct messaging_ctdb_fde {
> + struct tevent_fd *fde;
> +};
> +
> +static int messaging_ctdb_fde_ev_destructor(
> + struct messaging_ctdb_fde_ev *fde_ev)
> +{
> + if (fde_ev->ctx != NULL) {
> + DLIST_REMOVE(fde_ev->ctx->fde_evs, fde_ev);
> + fde_ev->ctx = NULL;
> + }
> + return 0;
> +}
> +
> +/*
> + * Reference counter for a struct tevent_fd messaging read event
> + * (with callback function) on a struct tevent_context registered
> + * on a messaging context.
> + *
> + * If we've already registered this struct tevent_context before
> + * (so already have a read event), just increase the reference count.
> + *
> + * Otherwise create a new struct tevent_fd messaging read event on the
> + * previously unseen struct tevent_context - this is what drives
> + * the message receive processing.
> + *
> + */
> +
> +struct messaging_ctdb_fde *messaging_ctdb_register_tevent_context(
> + TALLOC_CTX *mem_ctx, struct tevent_context *ev)
> +{
> + struct messaging_ctdb_context *ctx = global_ctdb_context;
> + struct messaging_ctdb_fde_ev *fde_ev;
> + struct messaging_ctdb_fde *fde;
> +
> + if (ctx == NULL) {
> + return NULL;
> + }
> +
> + fde = talloc(mem_ctx, struct messaging_ctdb_fde);
> + if (fde == NULL) {
> + return NULL;
> + }
> +
> + for (fde_ev = ctx->fde_evs; fde_ev != NULL; fde_ev = fde_ev->next) {
> + if ((fde_ev->ev == ev) &&
> + (tevent_fd_get_flags(fde_ev->fde) != 0)) {
> + break;
> + }
> + }
> +
> + if (fde_ev == NULL) {
> + int sock = ctdbd_conn_get_fd(ctx->conn);
> +
> + fde_ev = talloc(fde, struct messaging_ctdb_fde_ev);
> + if (fde_ev == NULL) {
> + return NULL;
> + }
> + fde_ev->fde = tevent_add_fd(
> + ev, fde_ev, sock, TEVENT_FD_READ,
> + messaging_ctdb_read_handler, ctx);
> + if (fde_ev->fde == NULL) {
> + TALLOC_FREE(fde);
> + return NULL;
> + }
> + fde_ev->ev = ev;
> + fde_ev->ctx = ctx;
> + DLIST_ADD(ctx->fde_evs, fde_ev);
> + talloc_set_destructor(
> + fde_ev, messaging_ctdb_fde_ev_destructor);
> + } else {
> + /*
> + * Same trick as with tdb_wrap: The caller will never
> + * see the talloc_referenced object, the
> + * messaging_ctdb_fde_ev, so problems with
> + * talloc_unlink will not happen.
> + */
> + if (talloc_reference(fde, fde_ev) == NULL) {
> + TALLOC_FREE(fde);
> + return NULL;
> + }
> + }
> +
> + fde->fde = fde_ev->fde;
> + return fde;
> +}
> +
> +bool messaging_ctdb_fde_active(struct messaging_ctdb_fde *fde)
> +{
> + uint16_t flags;
> +
> + if (fde == NULL) {
> + return false;
> + }
> + flags = tevent_fd_get_flags(fde->fde);
> + return (flags != 0);
> +}
> diff --git a/source3/lib/messages_ctdb.h b/source3/lib/messages_ctdb.h
> new file mode 100644
> index 0000000..006821b
> --- /dev/null
> +++ b/source3/lib/messages_ctdb.h
> @@ -0,0 +1,42 @@
> +/*
> + * Unix SMB/CIFS implementation.
> + * Samba internal messaging functions
> + * Copyright (C) 2017 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_CTDB_H__
> +#define __MESSAGES_CTDB_H__
> +
> +#include "replace.h"
> +#include "system/filesys.h"
> +#include <tevent.h>
> +
> +int messaging_ctdb_init(const char *sockname, int timeout, uint64_t unique_id,
> + void (*recv_cb)(struct tevent_context *ev,
> + const uint8_t *msg, size_t msg_len,
> + int *fds, size_t num_fds,
> + void *private_data),
> + void *private_data);
> +void messaging_ctdb_destroy(void);
> +int messaging_ctdb_send(uint32_t dst_vnn, uint64_t dst_srvid,
> + const struct iovec *iov, int iovlen);
> +
> +struct messaging_ctdb_fde;
> +struct messaging_ctdb_fde *messaging_ctdb_register_tevent_context(
> + TALLOC_CTX *mem_ctx, struct tevent_context *ev);
> +bool messaging_ctdb_fde_active(struct messaging_ctdb_fde *fde);
> +
> +#endif
> diff --git a/source3/wscript_build b/source3/wscript_build
> index 99f4a2b..a57217c 100644
> --- a/source3/wscript_build
> +++ b/source3/wscript_build
> @@ -331,6 +331,7 @@ if bld.env.with_ctdb:
> lib/cluster_support.c
> lib/dbwrap/dbwrap_ctdb.c
> lib/messages_ctdbd.c
> + lib/messages_ctdb.c
> lib/ctdbd_conn.c
> '''
> SAMBA_CLUSTER_SUPPORT_DEPS='''
> --
> 2.1.4
>
>
> From a49a4c25116eced0859491b834154a7b4143744a Mon Sep 17 00:00:00 2001
> From: Volker Lendecke <vl at samba.org>
> Date: Mon, 12 Jun 2017 16:50:16 +0200
> Subject: [PATCH 34/41] messaging: Add messages_ctdb_ref
>
> Modeled after messages_dgm_ref
>
> Signed-off-by: Volker Lendecke <vl at samba.org>
> ---
> source3/lib/ctdb_dummy.c | 13 ++++
> source3/lib/messages_ctdb_ref.c | 145 ++++++++++++++++++++++++++++++++++++++++
> source3/lib/messages_ctdb_ref.h | 35 ++++++++++
> source3/wscript_build | 1 +
> 4 files changed, 194 insertions(+)
> create mode 100644 source3/lib/messages_ctdb_ref.c
> create mode 100644 source3/lib/messages_ctdb_ref.h
>
> diff --git a/source3/lib/ctdb_dummy.c b/source3/lib/ctdb_dummy.c
> index 855f56d..2d7ba25 100644
> --- a/source3/lib/ctdb_dummy.c
> +++ b/source3/lib/ctdb_dummy.c
> @@ -21,6 +21,7 @@
> #include "messages.h"
> #include "lib/messages_ctdbd.h"
> #include "lib/messages_ctdb.h"
> +#include "lib/messages_ctdb_ref.h"
> #include "ctdbd_conn.h"
> #include "lib/dbwrap/dbwrap.h"
> #include "lib/dbwrap/dbwrap_ctdb.h"
> @@ -98,6 +99,18 @@ int messaging_ctdb_send(uint32_t dst_vnn, uint64_t dst_srvid,
> return ENOSYS;
> }
>
> +void *messaging_ctdb_ref(TALLOC_CTX *mem_ctx, struct tevent_context *ev,
> + const char *sockname, int timeout, uint64_t unique_id,
> + void (*recv_cb)(struct tevent_context *ev,
> + const uint8_t *msg, size_t msg_len,
> + int *fds, size_t num_fds,
> + void *private_data),
> + void *private_data,
> + int *err)
> +{
> + return NULL;
> +}
> +
> struct messaging_ctdb_fde *messaging_ctdb_register_tevent_context(
> TALLOC_CTX *mem_ctx, struct tevent_context *ev)
> {
> diff --git a/source3/lib/messages_ctdb_ref.c b/source3/lib/messages_ctdb_ref.c
> new file mode 100644
> index 0000000..3570ed8
> --- /dev/null
> +++ b/source3/lib/messages_ctdb_ref.c
> @@ -0,0 +1,145 @@
> +/*
> + * Unix SMB/CIFS implementation.
> + * Samba internal messaging functions
> + * Copyright (C) 2017 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 <talloc.h>
> +#include "messages_ctdb.h"
> +#include "messages_ctdb_ref.h"
> +#include "lib/util/debug.h"
> +#include "lib/util/dlinklist.h"
> +
> +struct msg_ctdb_ref {
> + struct msg_ctdb_ref *prev, *next;
> + struct messaging_ctdb_fde *fde;
> + void (*recv_cb)(struct tevent_context *ev,
> + 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 ctdb_pid = 0;
> +static struct msg_ctdb_ref *refs = NULL;
> +
> +static int msg_ctdb_ref_destructor(struct msg_ctdb_ref *r);
> +static void msg_ctdb_ref_recv(struct tevent_context *ev,
> + const uint8_t *msg, size_t msg_len,
> + int *fds, size_t num_fds, void *private_data);
> +
> +void *messaging_ctdb_ref(TALLOC_CTX *mem_ctx, struct tevent_context *ev,
> + const char *sockname, int timeout, uint64_t unique_id,
> + void (*recv_cb)(struct tevent_context *ev,
> + 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_ctdb_ref *result, *tmp_refs;
> +
> + result = talloc(mem_ctx, struct msg_ctdb_ref);
> + if (result == NULL) {
> + *err = ENOMEM;
> + return NULL;
> + }
> + result->fde = NULL;
> +
> + tmp_refs = refs;
> +
> + if ((refs != NULL) && (ctdb_pid != getpid())) {
> + /*
> + * Have to reinit after fork
> + */
> + messaging_ctdb_destroy();
> + refs = NULL;
> + }
> +
> + if (refs == NULL) {
> + int ret;
> +
> + ret = messaging_ctdb_init(sockname, timeout, unique_id,
> + msg_ctdb_ref_recv, NULL);
> + DBG_DEBUG("messaging_ctdb_init returned %s\n", strerror(ret));
> + if (ret != 0) {
> + DEBUG(10, ("messaging_ctdb_init failed: %s\n",
> + strerror(ret)));
> + TALLOC_FREE(result);
> + *err = ret;
> + return NULL;
> + }
> + ctdb_pid = getpid();
> + }
> +
> + result->fde = messaging_ctdb_register_tevent_context(result, ev);
> + if (result->fde == NULL) {
> + TALLOC_FREE(result);
> + *err = ENOMEM;
> + return NULL;
> + }
> +
> + 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_ctdb_ref_destructor);
> +
> + return result;
> +}
> +
> +static void msg_ctdb_ref_recv(struct tevent_context *ev,
> + const uint8_t *msg, size_t msg_len,
> + int *fds, size_t num_fds, void *private_data)
> +{
> + struct msg_ctdb_ref *r, *next;
> +
> + for (r = refs; r != NULL; r = next) {
> + bool active;
> +
> + next = r->next;
> +
> + active = messaging_ctdb_fde_active(r->fde);
> + if (!active) {
> + /*
> + * r's tevent_context has died.
> + */
> + continue;
> + }
> +
> + r->recv_cb(ev, msg, msg_len, fds, num_fds,
> + r->recv_cb_private_data);
> + break;
> + }
> +}
> +
> +static int msg_ctdb_ref_destructor(struct msg_ctdb_ref *r)
> +{
> + if (refs == NULL) {
> + abort();
> + }
> + DLIST_REMOVE(refs, r);
> +
> + TALLOC_FREE(r->fde);
> +
> + DBG_DEBUG("refs=%p\n", refs);
> +
> + if (refs == NULL) {
> + messaging_ctdb_destroy();
> + }
> + return 0;
> +}
> diff --git a/source3/lib/messages_ctdb_ref.h b/source3/lib/messages_ctdb_ref.h
> new file mode 100644
> index 0000000..44541d8
> --- /dev/null
> +++ b/source3/lib/messages_ctdb_ref.h
> @@ -0,0 +1,35 @@
> +/*
> + * Unix SMB/CIFS implementation.
> + * Samba internal messaging functions
> + * Copyright (C) 2017 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_CTDB_REF_H__
> +#define __MESSAGES_CTDB_REF_H__
> +
> +#include "replace.h"
> +#include <tevent.h>
> +
> +void *messaging_ctdb_ref(TALLOC_CTX *mem_ctx, struct tevent_context *ev,
> + const char *sockname, int timeout, uint64_t unique_id,
> + void (*recv_cb)(struct tevent_context *ev,
> + const uint8_t *msg, size_t msg_len,
> + int *fds, size_t num_fds,
> + void *private_data),
> + void *private_data,
> + int *err);
> +
> +#endif
> diff --git a/source3/wscript_build b/source3/wscript_build
> index a57217c..cffcca3 100644
> --- a/source3/wscript_build
> +++ b/source3/wscript_build
> @@ -332,6 +332,7 @@ if bld.env.with_ctdb:
> lib/dbwrap/dbwrap_ctdb.c
> lib/messages_ctdbd.c
> lib/messages_ctdb.c
> + lib/messages_ctdb_ref.c
> lib/ctdbd_conn.c
> '''
> SAMBA_CLUSTER_SUPPORT_DEPS='''
> --
> 2.1.4
>
>
> From 63e8dfd533a64881bc8f11a94abfcd144054b07e Mon Sep 17 00:00:00 2001
> From: Volker Lendecke <vl at samba.org>
> Date: Fri, 16 Jun 2017 17:11:48 +0200
> Subject: [PATCH 35/41] dbwrap_ctdb: Use messaging_ctdbd_connection
>
> With messages_ctdb, the global ctdb connection will change after fork.
>
> Don't store the wrong parent connection across a fork. The alternative would
> be to do a reinit on all dbwrap_ctdb databases, but that seems overkill
> given that we only have one "standard" ctdb connection anyway.
>
> Signed-off-by: Volker Lendecke <vl at samba.org>
> ---
> source3/lib/ctdb_dummy.c | 1 -
> source3/lib/dbwrap/dbwrap_ctdb.c | 34 ++++++++++++++++++----------------
> source3/lib/dbwrap/dbwrap_ctdb.h | 1 -
> source3/lib/dbwrap/dbwrap_open.c | 2 +-
> source3/torture/test_dbwrap_ctdb.c | 8 +-------
> 5 files changed, 20 insertions(+), 26 deletions(-)
>
> diff --git a/source3/lib/ctdb_dummy.c b/source3/lib/ctdb_dummy.c
> index 2d7ba25..891e7c3 100644
> --- a/source3/lib/ctdb_dummy.c
> +++ b/source3/lib/ctdb_dummy.c
> @@ -70,7 +70,6 @@ bool ctdbd_process_exists(struct ctdbd_connection *conn, uint32_t vnn, pid_t pid
>
> struct db_context *db_open_ctdb(TALLOC_CTX *mem_ctx,
> struct messaging_context *msg_ctx,
> - struct ctdbd_connection *conn,
> const char *name,
> int hash_size, int tdb_flags,
> int open_flags, mode_t mode,
> diff --git a/source3/lib/dbwrap/dbwrap_ctdb.c b/source3/lib/dbwrap/dbwrap_ctdb.c
> index b722714..2cee058 100644
> --- a/source3/lib/dbwrap/dbwrap_ctdb.c
> +++ b/source3/lib/dbwrap/dbwrap_ctdb.c
> @@ -34,6 +34,7 @@
> #include "dbwrap/dbwrap_ctdb.h"
> #include "g_lock.h"
> #include "messages.h"
> +#include "messages_ctdbd.h"
> #include "lib/cluster_support.h"
> #include "lib/util/tevent_ntstatus.h"
>
> @@ -50,7 +51,6 @@ struct db_ctdb_transaction_handle {
>
> struct db_ctdb_ctx {
> struct db_context *db;
> - struct ctdbd_connection *conn;
> struct tdb_wrap *wtdb;
> uint32_t db_id;
> struct db_ctdb_transaction_handle *transaction;
> @@ -640,7 +640,7 @@ static NTSTATUS db_ctdb_transaction_store(struct db_ctdb_transaction_handle *h,
> SAFE_FREE(rec.dptr);
> }
>
> - header.dmaster = ctdbd_vnn(h->ctx->conn);
> + header.dmaster = get_my_vnn();
> header.rsn++;
>
> h->m_write = db_ctdb_marshall_add(h, h->m_write, h->ctx->db_id, 0, key, &header, data);
> @@ -821,7 +821,8 @@ static int db_ctdb_transaction_commit(struct db_context *db)
>
> again:
> /* tell ctdbd to commit to the other nodes */
> - ret = ctdbd_control_local(ctx->conn, CTDB_CONTROL_TRANS3_COMMIT,
> + ret = ctdbd_control_local(messaging_ctdbd_connection(),
> + CTDB_CONTROL_TRANS3_COMMIT,
> h->ctx->db_id, 0,
> db_ctdb_marshall_finish(h->m_write),
> NULL, NULL, &status);
> @@ -937,7 +938,7 @@ static NTSTATUS db_ctdb_send_schedule_for_deletion(struct db_record *rec)
> dd->keylen = rec->key.dsize;
> memcpy(dd->key, rec->key.dptr, rec->key.dsize);
>
> - ret = ctdbd_control_local(ctx->conn,
> + ret = ctdbd_control_local(messaging_ctdbd_connection(),
> CTDB_CONTROL_SCHEDULE_FOR_DELETION,
> crec->ctdb_ctx->db_id,
> CTDB_CTRL_FLAG_NOREPLY, /* flags */
> @@ -1152,8 +1153,7 @@ again:
> * take the shortcut and just return it.
> */
>
> - if (!db_ctdb_can_use_local_copy(ctdb_data, ctdbd_vnn(ctx->conn),
> - false)) {
> + if (!db_ctdb_can_use_local_copy(ctdb_data, get_my_vnn(), false)) {
> SAFE_FREE(ctdb_data.dptr);
> tdb_chainunlock(ctx->wtdb->tdb, key);
> talloc_set_destructor(result, NULL);
> @@ -1171,12 +1171,13 @@ again:
> ctdb_data.dptr, ctdb_data.dptr ?
> ((struct ctdb_ltdb_header *)ctdb_data.dptr)->dmaster :
> UINT32_MAX,
> - ctdbd_vnn(ctx->conn),
> + get_my_vnn(),
> ctdb_data.dptr ?
> ((struct ctdb_ltdb_header *)ctdb_data.dptr)->flags : 0));
>
> GetTimeOfDay(&ctdb_start_time);
> - ret = ctdbd_migrate(ctx->conn, ctx->db_id, key);
> + ret = ctdbd_migrate(messaging_ctdbd_connection(), ctx->db_id,
> + key);
> ctdb_time += timeval_elapsed(&ctdb_start_time);
>
> if (ret != 0) {
> @@ -1396,7 +1397,7 @@ static NTSTATUS db_ctdb_parse_record(struct db_context *db, TDB_DATA key,
>
> state.parser = parser;
> state.private_data = private_data;
> - state.my_vnn = ctdbd_vnn(ctx->conn);
> + state.my_vnn = get_my_vnn();
> state.empty_record = false;
>
> status = db_ctdb_try_parse_local_record(ctx, key, &state);
> @@ -1404,7 +1405,7 @@ static NTSTATUS db_ctdb_parse_record(struct db_context *db, TDB_DATA key,
> return status;
> }
>
> - ret = ctdbd_parse(ctx->conn, ctx->db_id, key,
> + ret = ctdbd_parse(messaging_ctdbd_connection(), ctx->db_id, key,
> state.ask_for_readonly_copy, parser, private_data);
> if (ret != 0) {
> if (ret == ENOENT) {
> @@ -1453,7 +1454,7 @@ static struct tevent_req *db_ctdb_parse_record_send(
> *state = (struct db_ctdb_parse_record_state) {
> .parser = parser,
> .private_data = private_data,
> - .my_vnn = ctdbd_vnn(ctx->conn),
> + .my_vnn = get_my_vnn(),
> .empty_record = false,
> };
>
> @@ -1785,7 +1786,6 @@ static size_t db_ctdb_id(struct db_context *db, uint8_t *id, size_t idlen)
>
> struct db_context *db_open_ctdb(TALLOC_CTX *mem_ctx,
> struct messaging_context *msg_ctx,
> - struct ctdbd_connection *conn,
> const char *name,
> int hash_size, int tdb_flags,
> int open_flags, mode_t mode,
> @@ -1825,9 +1825,9 @@ struct db_context *db_open_ctdb(TALLOC_CTX *mem_ctx,
>
> db_ctdb->transaction = NULL;
> db_ctdb->db = result;
> - db_ctdb->conn = conn;
>
> - ret = ctdbd_db_attach(db_ctdb->conn, name, &db_ctdb->db_id, tdb_flags);
> + ret = ctdbd_db_attach(messaging_ctdbd_connection(), name,
> + &db_ctdb->db_id, tdb_flags);
> if (ret != 0) {
> DEBUG(0, ("ctdbd_db_attach failed for %s: %s\n", name,
> strerror(ret)));
> @@ -1835,7 +1835,8 @@ struct db_context *db_open_ctdb(TALLOC_CTX *mem_ctx,
> return NULL;
> }
>
> - db_path = ctdbd_dbpath(db_ctdb->conn, db_ctdb, db_ctdb->db_id);
> + db_path = ctdbd_dbpath(messaging_ctdbd_connection(), db_ctdb,
> + db_ctdb->db_id);
>
> result->persistent = ((tdb_flags & TDB_CLEAR_IF_FIRST) == 0);
> result->lock_order = lock_order;
> @@ -1862,7 +1863,8 @@ struct db_context *db_open_ctdb(TALLOC_CTX *mem_ctx,
> sizeof(db_ctdb->db_id));
>
> ret = ctdbd_control_local(
> - db_ctdb->conn, CTDB_CONTROL_SET_DB_READONLY, 0, 0,
> + messaging_ctdbd_connection(),
> + CTDB_CONTROL_SET_DB_READONLY, 0, 0,
> indata, NULL, NULL, &cstatus);
> if ((ret != 0) || (cstatus != 0)) {
> DEBUG(1, ("CTDB_CONTROL_SET_DB_READONLY failed: "
> diff --git a/source3/lib/dbwrap/dbwrap_ctdb.h b/source3/lib/dbwrap/dbwrap_ctdb.h
> index 42c831f..0b82479 100644
> --- a/source3/lib/dbwrap/dbwrap_ctdb.h
> +++ b/source3/lib/dbwrap/dbwrap_ctdb.h
> @@ -30,7 +30,6 @@ struct ctdbd_connection;
>
> struct db_context *db_open_ctdb(TALLOC_CTX *mem_ctx,
> struct messaging_context *msg_ctx,
> - struct ctdbd_connection *conn,
> const char *name,
> int hash_size, int tdb_flags,
> int open_flags, mode_t mode,
> diff --git a/source3/lib/dbwrap/dbwrap_open.c b/source3/lib/dbwrap/dbwrap_open.c
> index 55e0adb..dfb87e1 100644
> --- a/source3/lib/dbwrap/dbwrap_open.c
> +++ b/source3/lib/dbwrap/dbwrap_open.c
> @@ -156,7 +156,7 @@ struct db_context *db_open(TALLOC_CTX *mem_ctx,
> }
> msg_ctx = server_messaging_context();
>
> - result = db_open_ctdb(mem_ctx, msg_ctx, conn, partname,
> + result = db_open_ctdb(mem_ctx, msg_ctx, partname,
> hash_size,
> tdb_flags, open_flags, mode,
> lock_order, dbwrap_flags);
> diff --git a/source3/torture/test_dbwrap_ctdb.c b/source3/torture/test_dbwrap_ctdb.c
> index 4512358..cc6fd0c 100644
> --- a/source3/torture/test_dbwrap_ctdb.c
> +++ b/source3/torture/test_dbwrap_ctdb.c
> @@ -33,16 +33,10 @@ bool run_local_dbwrap_ctdb(int dummy)
> NTSTATUS status;
> uint32_t val;
> struct messaging_context *msg_ctx;
> - struct ctdbd_connection *conn;
>
> msg_ctx = server_messaging_context();
> - conn = messaging_ctdbd_connection();
> - if (conn == NULL) {
> - fprintf(stderr, "no ctdbd connection\n");
> - goto fail;
> - }
>
> - db = db_open_ctdb(talloc_tos(), msg_ctx, conn, "torture.tdb",
> + db = db_open_ctdb(talloc_tos(), msg_ctx, "torture.tdb",
> 0, TDB_DEFAULT,
> O_RDWR, 0755, DBWRAP_LOCK_ORDER_1, DBWRAP_FLAG_NONE);
> if (db == NULL) {
> --
> 2.1.4
>
>
> From 1d66e896110db886554043a16d128607e9575115 Mon Sep 17 00:00:00 2001
> From: Volker Lendecke <vl at samba.org>
> Date: Fri, 16 Jun 2017 15:20:39 +0200
> Subject: [PATCH 36/41] smbpasswd: Initialize messaging for messaging_ctdb_conn
>
> Signed-off-by: Volker Lendecke <vl at samba.org>
> ---
> source3/utils/smbpasswd.c | 4 ++++
> 1 file changed, 4 insertions(+)
>
> diff --git a/source3/utils/smbpasswd.c b/source3/utils/smbpasswd.c
> index 437a5e5..aa6b857 100644
> --- a/source3/utils/smbpasswd.c
> +++ b/source3/utils/smbpasswd.c
> @@ -603,6 +603,10 @@ int main(int argc, char **argv)
>
> setup_logging("smbpasswd", DEBUG_STDERR);
>
> + if (server_messaging_context() == NULL) {
> + return 1;
> + }
> +
> /*
> * Set the machine NETBIOS name if not already
> * set from the config file.
> --
> 2.1.4
>
>
> From f3c7775b1d0a23d2223ab72aa0806418d1644e6d Mon Sep 17 00:00:00 2001
> From: Volker Lendecke <vl at samba.org>
> Date: Wed, 5 Jul 2017 19:13:23 +0200
> Subject: [PATCH 37/41] messages_ctdb: Add messaging_ctdb_connection
>
> This will be the replacement for messaging_ctdbd_connection(). This does not
> default to initializing messaging but panics. We just don't have correct
> default arguments for messaging_init. Implicit multiple messaging and event
> contexts is a bug also.
>
> It *might* be that some tools fail due to this, but this needs fixing in
> different ways. See the previous commit for smbpasswd.
>
> Signed-off-by: Volker Lendecke <vl at samba.org>
> ---
> source3/lib/messages_ctdb.c | 8 ++++++++
> source3/lib/messages_ctdb.h | 2 ++
> 2 files changed, 10 insertions(+)
>
> diff --git a/source3/lib/messages_ctdb.c b/source3/lib/messages_ctdb.c
> index 5bc494d..a2a7c21 100644
> --- a/source3/lib/messages_ctdb.c
> +++ b/source3/lib/messages_ctdb.c
> @@ -258,3 +258,11 @@ bool messaging_ctdb_fde_active(struct messaging_ctdb_fde *fde)
> flags = tevent_fd_get_flags(fde->fde);
> return (flags != 0);
> }
> +
> +struct ctdbd_connection *messaging_ctdb_connection(void)
> +{
> + if (global_ctdb_context == NULL) {
> + smb_panic("messaging not initialized\n");
> + }
> + return global_ctdb_context->conn;
> +}
> diff --git a/source3/lib/messages_ctdb.h b/source3/lib/messages_ctdb.h
> index 006821b..9d56343 100644
> --- a/source3/lib/messages_ctdb.h
> +++ b/source3/lib/messages_ctdb.h
> @@ -39,4 +39,6 @@ struct messaging_ctdb_fde *messaging_ctdb_register_tevent_context(
> TALLOC_CTX *mem_ctx, struct tevent_context *ev);
> bool messaging_ctdb_fde_active(struct messaging_ctdb_fde *fde);
>
> +struct ctdbd_connection *messaging_ctdb_connection(void);
> +
> #endif
> --
> 2.1.4
>
>
> From 1d8de56b4fd79306bf28d55231785999708d6498 Mon Sep 17 00:00:00 2001
> From: Volker Lendecke <vl at samba.org>
> Date: Wed, 5 Jul 2017 19:20:09 +0200
> Subject: [PATCH 38/41] messaging: Use messaging_ctdb_ref()
>
> Signed-off-by: Volker Lendecke <vl at samba.org>
> ---
> source3/lib/messages.c | 83 ++++++++++++++++++++------------------------------
> 1 file changed, 33 insertions(+), 50 deletions(-)
>
> diff --git a/source3/lib/messages.c b/source3/lib/messages.c
> index 4e838b0..765add9 100644
> --- a/source3/lib/messages.c
> +++ b/source3/lib/messages.c
> @@ -53,11 +53,13 @@
> #include "lib/util/tevent_unix.h"
> #include "lib/background.h"
> #include "lib/messages_dgm.h"
> -#include "lib/messages_ctdbd.h"
> #include "lib/util/iov_buf.h"
> #include "lib/util/server_id_db.h"
> #include "lib/messages_dgm_ref.h"
> +#include "lib/messages_ctdb.h"
> +#include "lib/messages_ctdb_ref.h"
> #include "lib/messages_util.h"
> +#include "cluster_support.h"
>
> struct messaging_callback {
> struct messaging_callback *prev, *next;
> @@ -90,8 +92,7 @@ struct messaging_context {
> size_t num_waiters;
>
> void *msg_dgm_ref;
> - struct messaging_backend *remote;
> - struct messaging_ctdbd_fde *cluster_fde;
> + void *msg_ctdb_ref;
>
> struct server_id_db *names_db;
> };
> @@ -513,23 +514,16 @@ static NTSTATUS messaging_init_internal(TALLOC_CTX *mem_ctx,
> talloc_set_destructor(ctx, messaging_context_destructor);
>
> if (lp_clustering()) {
> - ret = messaging_ctdbd_init(
> - ctx, ctx, messaging_recv_cb, ctx, &ctx->remote);
> -
> - if (ret != 0) {
> - DEBUG(2, ("messaging_ctdbd_init failed: %s\n",
> - strerror(ret)));
> + ctx->msg_ctdb_ref = messaging_ctdb_ref(
> + ctx, ctx->event_ctx,
> + lp_ctdbd_socket(), lp_ctdb_timeout(),
> + ctx->id.unique_id, messaging_recv_cb, ctx, &ret);
> + if (ctx->msg_ctdb_ref == NULL) {
> + DBG_NOTICE("messaging_ctdb_ref failed: %s\n",
> + strerror(ret));
> status = map_nt_error_from_unix(ret);
> goto done;
> }
> - ctx->cluster_fde = messaging_ctdbd_register_tevent_context(
> - ctx, ctx->event_ctx, ctx->remote);
> - if (ctx->cluster_fde == NULL) {
> - DBG_WARNING("messaging_ctdbd_register_tevent_context "
> - "failed\n");
> - status = NT_STATUS_NO_MEMORY;
> - goto done;
> - }
> }
> ctx->id.vnn = get_my_vnn();
>
> @@ -605,6 +599,7 @@ NTSTATUS messaging_reinit(struct messaging_context *msg_ctx)
> char *lck_path;
>
> TALLOC_FREE(msg_ctx->msg_dgm_ref);
> + TALLOC_FREE(msg_ctx->msg_ctdb_ref);
>
> msg_ctx->id = (struct server_id) {
> .pid = getpid(), .vnn = msg_ctx->id.vnn
> @@ -626,25 +621,16 @@ NTSTATUS messaging_reinit(struct messaging_context *msg_ctx)
> }
>
> if (lp_clustering()) {
> - TALLOC_FREE(msg_ctx->cluster_fde);
> -
> - ret = messaging_ctdbd_reinit(
> - msg_ctx, msg_ctx, messaging_recv_cb, msg_ctx,
> - msg_ctx->remote);
> -
> - if (ret != 0) {
> - DEBUG(1, ("messaging_ctdbd_init failed: %s\n",
> - strerror(ret)));
> + msg_ctx->msg_ctdb_ref = messaging_ctdb_ref(
> + msg_ctx, msg_ctx->event_ctx,
> + lp_ctdbd_socket(), lp_ctdb_timeout(),
> + msg_ctx->id.unique_id, messaging_recv_cb, msg_ctx,
> + &ret);
> + if (msg_ctx->msg_ctdb_ref == NULL) {
> + DBG_NOTICE("messaging_ctdb_ref failed: %s\n",
> + strerror(ret));
> return map_nt_error_from_unix(ret);
> }
> -
> - msg_ctx->cluster_fde = messaging_ctdbd_register_tevent_context(
> - msg_ctx, msg_ctx->event_ctx, msg_ctx->remote);
> - if (msg_ctx->cluster_fde == NULL) {
> - DBG_WARNING("messaging_ctdbd_register_tevent_context "
> - "failed\n");
> - return NT_STATUS_NO_MEMORY;
> - }
> }
>
> server_id_db_reinit(msg_ctx->names_db, msg_ctx->id);
> @@ -793,18 +779,6 @@ int messaging_send_iov_from(struct messaging_context *msg_ctx,
> return EINVAL;
> }
>
> - if (dst.vnn != msg_ctx->id.vnn) {
> - if (num_fds > 0) {
> - return ENOSYS;
> - }
> -
> - ret = msg_ctx->remote->send_fn(src, dst,
> - msg_type, iov, iovlen,
> - NULL, 0,
> - msg_ctx->remote);
> - return ret;
> - }
> -
> if (server_id_equal(&dst, &msg_ctx->id)) {
> ret = messaging_post_self(msg_ctx, src, dst, msg_type,
> iov, iovlen, fds, num_fds);
> @@ -815,6 +789,15 @@ int messaging_send_iov_from(struct messaging_context *msg_ctx,
> iov2[0] = (struct iovec){ .iov_base = hdr, .iov_len = sizeof(hdr) };
> memcpy(&iov2[1], iov, iovlen * sizeof(*iov));
>
> + if (dst.vnn != msg_ctx->id.vnn) {
> + if (num_fds > 0) {
> + return ENOSYS;
> + }
> +
> + ret = messaging_ctdb_send(dst.vnn, dst.pid, iov2, iovlen+1);
> + return ret;
> + }
> +
> ret = messaging_dgm_send(dst.pid, iov2, iovlen+1, fds, num_fds);
>
> if (ret == EACCES) {
> @@ -890,7 +873,7 @@ struct messaging_filtered_read_state {
> struct tevent_context *ev;
> struct messaging_context *msg_ctx;
> struct messaging_dgm_fde *fde;
> - struct messaging_ctdbd_fde *cluster_fde;
> + struct messaging_ctdb_fde *cluster_fde;
>
> bool (*filter)(struct messaging_rec *rec, void *private_data);
> void *private_data;
> @@ -933,9 +916,9 @@ struct tevent_req *messaging_filtered_read_send(
> return tevent_req_post(req, ev);
> }
>
> - if (msg_ctx->remote != NULL) {
> - state->cluster_fde = messaging_ctdbd_register_tevent_context(
> - state, ev, msg_ctx->remote);
> + if (lp_clustering()) {
> + state->cluster_fde =
> + messaging_ctdb_register_tevent_context(state, ev);
> if (tevent_req_nomem(state->cluster_fde, req)) {
> return tevent_req_post(req, ev);
> }
> --
> 2.1.4
>
>
> From 815850ea501f04901767797b33bc764d1650e686 Mon Sep 17 00:00:00 2001
> From: Volker Lendecke <vl at samba.org>
> Date: Fri, 16 Jun 2017 13:00:59 +0200
> Subject: [PATCH 39/41] ctdb_conn: Use messaging_ctdb_connection
>
> Replace messaging_ctdbd_connection
>
> Signed-off-by: Volker Lendecke <vl at samba.org>
> ---
> source3/lib/ctdb_dummy.c | 2 +-
> source3/lib/dbwrap/dbwrap_ctdb.c | 16 ++++++++--------
> source3/lib/dbwrap/dbwrap_open.c | 4 ++--
> source3/lib/serverid.c | 6 +++---
> source3/smbd/notifyd/notifydd.c | 4 ++--
> source3/smbd/process.c | 4 ++--
> source3/smbd/server.c | 6 +++---
> source3/torture/test_dbwrap_ctdb.c | 2 +-
> source3/wscript_build | 1 -
> 9 files changed, 22 insertions(+), 23 deletions(-)
>
> diff --git a/source3/lib/ctdb_dummy.c b/source3/lib/ctdb_dummy.c
> index 891e7c3..f301c1f 100644
> --- a/source3/lib/ctdb_dummy.c
> +++ b/source3/lib/ctdb_dummy.c
> @@ -135,7 +135,7 @@ struct messaging_ctdbd_fde *messaging_ctdbd_register_tevent_context(
> return NULL;
> }
>
> -struct ctdbd_connection *messaging_ctdbd_connection(void)
> +struct ctdbd_connection *messaging_ctdb_connection(void)
> {
> return NULL;
> }
> diff --git a/source3/lib/dbwrap/dbwrap_ctdb.c b/source3/lib/dbwrap/dbwrap_ctdb.c
> index 2cee058..3dba85d 100644
> --- a/source3/lib/dbwrap/dbwrap_ctdb.c
> +++ b/source3/lib/dbwrap/dbwrap_ctdb.c
> @@ -34,7 +34,7 @@
> #include "dbwrap/dbwrap_ctdb.h"
> #include "g_lock.h"
> #include "messages.h"
> -#include "messages_ctdbd.h"
> +#include "messages_ctdb.h"
> #include "lib/cluster_support.h"
> #include "lib/util/tevent_ntstatus.h"
>
> @@ -821,7 +821,7 @@ static int db_ctdb_transaction_commit(struct db_context *db)
>
> again:
> /* tell ctdbd to commit to the other nodes */
> - ret = ctdbd_control_local(messaging_ctdbd_connection(),
> + ret = ctdbd_control_local(messaging_ctdb_connection(),
> CTDB_CONTROL_TRANS3_COMMIT,
> h->ctx->db_id, 0,
> db_ctdb_marshall_finish(h->m_write),
> @@ -938,7 +938,7 @@ static NTSTATUS db_ctdb_send_schedule_for_deletion(struct db_record *rec)
> dd->keylen = rec->key.dsize;
> memcpy(dd->key, rec->key.dptr, rec->key.dsize);
>
> - ret = ctdbd_control_local(messaging_ctdbd_connection(),
> + ret = ctdbd_control_local(messaging_ctdb_connection(),
> CTDB_CONTROL_SCHEDULE_FOR_DELETION,
> crec->ctdb_ctx->db_id,
> CTDB_CTRL_FLAG_NOREPLY, /* flags */
> @@ -1176,7 +1176,7 @@ again:
> ((struct ctdb_ltdb_header *)ctdb_data.dptr)->flags : 0));
>
> GetTimeOfDay(&ctdb_start_time);
> - ret = ctdbd_migrate(messaging_ctdbd_connection(), ctx->db_id,
> + ret = ctdbd_migrate(messaging_ctdb_connection(), ctx->db_id,
> key);
> ctdb_time += timeval_elapsed(&ctdb_start_time);
>
> @@ -1405,7 +1405,7 @@ static NTSTATUS db_ctdb_parse_record(struct db_context *db, TDB_DATA key,
> return status;
> }
>
> - ret = ctdbd_parse(messaging_ctdbd_connection(), ctx->db_id, key,
> + ret = ctdbd_parse(messaging_ctdb_connection(), ctx->db_id, key,
> state.ask_for_readonly_copy, parser, private_data);
> if (ret != 0) {
> if (ret == ENOENT) {
> @@ -1826,7 +1826,7 @@ struct db_context *db_open_ctdb(TALLOC_CTX *mem_ctx,
> db_ctdb->transaction = NULL;
> db_ctdb->db = result;
>
> - ret = ctdbd_db_attach(messaging_ctdbd_connection(), name,
> + ret = ctdbd_db_attach(messaging_ctdb_connection(), name,
> &db_ctdb->db_id, tdb_flags);
> if (ret != 0) {
> DEBUG(0, ("ctdbd_db_attach failed for %s: %s\n", name,
> @@ -1835,7 +1835,7 @@ struct db_context *db_open_ctdb(TALLOC_CTX *mem_ctx,
> return NULL;
> }
>
> - db_path = ctdbd_dbpath(messaging_ctdbd_connection(), db_ctdb,
> + db_path = ctdbd_dbpath(messaging_ctdb_connection(), db_ctdb,
> db_ctdb->db_id);
>
> result->persistent = ((tdb_flags & TDB_CLEAR_IF_FIRST) == 0);
> @@ -1863,7 +1863,7 @@ struct db_context *db_open_ctdb(TALLOC_CTX *mem_ctx,
> sizeof(db_ctdb->db_id));
>
> ret = ctdbd_control_local(
> - messaging_ctdbd_connection(),
> + messaging_ctdb_connection(),
> CTDB_CONTROL_SET_DB_READONLY, 0, 0,
> indata, NULL, NULL, &cstatus);
> if ((ret != 0) || (cstatus != 0)) {
> diff --git a/source3/lib/dbwrap/dbwrap_open.c b/source3/lib/dbwrap/dbwrap_open.c
> index dfb87e1..64627d1 100644
> --- a/source3/lib/dbwrap/dbwrap_open.c
> +++ b/source3/lib/dbwrap/dbwrap_open.c
> @@ -26,7 +26,7 @@
> #include "dbwrap/dbwrap_ctdb.h"
> #include "lib/param/param.h"
> #include "lib/cluster_support.h"
> -#include "lib/messages_ctdbd.h"
> +#include "lib/messages_ctdb.h"
> #include "util_tdb.h"
> #include "ctdbd_conn.h"
> #include "messages.h"
> @@ -148,7 +148,7 @@ struct db_context *db_open(TALLOC_CTX *mem_ctx,
> struct messaging_context *msg_ctx;
> struct ctdbd_connection *conn;
>
> - conn = messaging_ctdbd_connection();
> + conn = messaging_ctdb_connection();
> if (conn == NULL) {
> DBG_WARNING("No ctdb connection\n");
> errno = EIO;
> diff --git a/source3/lib/serverid.c b/source3/lib/serverid.c
> index fb32526..ca4bb27 100644
> --- a/source3/lib/serverid.c
> +++ b/source3/lib/serverid.c
> @@ -28,7 +28,7 @@
> #include "lib/param/param.h"
> #include "ctdbd_conn.h"
> #include "messages.h"
> -#include "lib/messages_ctdbd.h"
> +#include "lib/messages_ctdb.h"
> #include "lib/messages_dgm.h"
>
> struct serverid_key {
> @@ -124,7 +124,7 @@ bool serverid_register(const struct server_id id, uint32_t msg_flags)
> }
>
> if (lp_clustering()) {
> - register_with_ctdbd(messaging_ctdbd_connection(), id.unique_id,
> + register_with_ctdbd(messaging_ctdb_connection(), id.unique_id,
> NULL, NULL);
> }
>
> @@ -198,7 +198,7 @@ bool serverid_exists(const struct server_id *id)
> }
>
> if (lp_clustering()) {
> - return ctdbd_process_exists(messaging_ctdbd_connection(),
> + return ctdbd_process_exists(messaging_ctdb_connection(),
> id->vnn, id->pid);
> }
>
> diff --git a/source3/smbd/notifyd/notifydd.c b/source3/smbd/notifyd/notifydd.c
> index ad3621a..faad4e7 100644
> --- a/source3/smbd/notifyd/notifydd.c
> +++ b/source3/smbd/notifyd/notifydd.c
> @@ -19,7 +19,7 @@
>
> #include "replace.h"
> #include "notifyd.h"
> -#include "lib/messages_ctdbd.h"
> +#include "lib/messages_ctdb.h"
> #include <tevent.h>
> #include "lib/util/tevent_unix.h"
>
> @@ -59,7 +59,7 @@ int main(int argc, const char *argv[])
> return 1;
> }
>
> - req = notifyd_send(ev, ev, msg, messaging_ctdbd_connection(),
> + req = notifyd_send(ev, ev, msg, messaging_ctdb_connection(),
> NULL, NULL);
> if (req == NULL) {
> fprintf(stderr, "notifyd_send failed\n");
> diff --git a/source3/smbd/process.c b/source3/smbd/process.c
> index 4abaf37..7dc9b34 100644
> --- a/source3/smbd/process.c
> +++ b/source3/smbd/process.c
> @@ -32,7 +32,7 @@
> #include "passdb.h"
> #include "auth.h"
> #include "messages.h"
> -#include "lib/messages_ctdbd.h"
> +#include "lib/messages_ctdb.h"
> #include "smbprofile.h"
> #include "rpc_server/spoolss/srv_spoolss_nt.h"
> #include "libsmb/libsmb.h"
> @@ -2775,7 +2775,7 @@ static NTSTATUS smbd_register_ips(struct smbXsrv_connection *xconn,
> struct ctdbd_connection *cconn;
> int ret;
>
> - cconn = messaging_ctdbd_connection();
> + cconn = messaging_ctdb_connection();
> if (cconn == NULL) {
> return NT_STATUS_NO_MEMORY;
> }
> diff --git a/source3/smbd/server.c b/source3/smbd/server.c
> index 91fa1c3..f87bb0d 100644
> --- a/source3/smbd/server.c
> +++ b/source3/smbd/server.c
> @@ -40,7 +40,7 @@
> #include "passdb.h"
> #include "auth.h"
> #include "messages.h"
> -#include "messages_ctdbd.h"
> +#include "messages_ctdb.h"
> #include "smbprofile.h"
> #include "lib/id_cache.h"
> #include "lib/param/param.h"
> @@ -361,7 +361,7 @@ static struct tevent_req *notifyd_req(struct messaging_context *msg_ctx,
> }
>
> if (lp_clustering()) {
> - ctdbd_conn = messaging_ctdbd_connection();
> + ctdbd_conn = messaging_ctdb_connection();
> }
>
> req = notifyd_send(msg_ctx, ev, msg_ctx, ctdbd_conn,
> @@ -1296,7 +1296,7 @@ static bool open_sockets_smbd(struct smbd_parent_context *parent,
>
> #ifdef CLUSTER_SUPPORT
> if (lp_clustering()) {
> - struct ctdbd_connection *conn = messaging_ctdbd_connection();
> + struct ctdbd_connection *conn = messaging_ctdb_connection();
>
> register_with_ctdbd(conn, CTDB_SRVID_RECONFIGURE,
> smbd_parent_ctdb_reconfigured, msg_ctx);
> diff --git a/source3/torture/test_dbwrap_ctdb.c b/source3/torture/test_dbwrap_ctdb.c
> index cc6fd0c..1da5c94 100644
> --- a/source3/torture/test_dbwrap_ctdb.c
> +++ b/source3/torture/test_dbwrap_ctdb.c
> @@ -23,7 +23,7 @@
> #include "lib/dbwrap/dbwrap.h"
> #include "lib/dbwrap/dbwrap_ctdb.h"
> #include "messages.h"
> -#include "lib/messages_ctdbd.h"
> +#include "lib/messages_ctdb.h"
>
> bool run_local_dbwrap_ctdb(int dummy)
> {
> diff --git a/source3/wscript_build b/source3/wscript_build
> index cffcca3..3f62bc2 100644
> --- a/source3/wscript_build
> +++ b/source3/wscript_build
> @@ -330,7 +330,6 @@ if bld.env.with_ctdb:
> SAMBA_CLUSTER_SUPPORT_SOURCES='''
> lib/cluster_support.c
> lib/dbwrap/dbwrap_ctdb.c
> - lib/messages_ctdbd.c
> lib/messages_ctdb.c
> lib/messages_ctdb_ref.c
> lib/ctdbd_conn.c
> --
> 2.1.4
>
>
> From 448620755d1fc43864242cdf2aa0853614d4e764 Mon Sep 17 00:00:00 2001
> From: Volker Lendecke <vl at samba.org>
> Date: Wed, 5 Jul 2017 19:24:32 +0200
> Subject: [PATCH 40/41] messaging: Remove messages_ctdbd.c
>
> Replaced by messages_ctdb.[ch]
>
> Signed-off-by: Volker Lendecke <vl at samba.org>
> ---
> source3/lib/ctdb_dummy.c | 32 ----
> source3/lib/messages_ctdbd.c | 354 -------------------------------------------
> source3/lib/messages_ctdbd.h | 53 -------
> 3 files changed, 439 deletions(-)
> delete mode 100644 source3/lib/messages_ctdbd.c
> delete mode 100644 source3/lib/messages_ctdbd.h
>
> diff --git a/source3/lib/ctdb_dummy.c b/source3/lib/ctdb_dummy.c
> index f301c1f..8a06b0c 100644
> --- a/source3/lib/ctdb_dummy.c
> +++ b/source3/lib/ctdb_dummy.c
> @@ -19,7 +19,6 @@
>
> #include "includes.h"
> #include "messages.h"
> -#include "lib/messages_ctdbd.h"
> #include "lib/messages_ctdb.h"
> #include "lib/messages_ctdb_ref.h"
> #include "ctdbd_conn.h"
> @@ -80,18 +79,6 @@ struct db_context *db_open_ctdb(TALLOC_CTX *mem_ctx,
> return NULL;
> }
>
> -int messaging_ctdbd_init(struct messaging_context *msg_ctx,
> - TALLOC_CTX *mem_ctx,
> - void (*recv_cb)(struct tevent_context *ev,
> - const uint8_t *msg, size_t msg_len,
> - int *fds, size_t num_fds,
> - void *private_data),
> - void *private_data,
> - struct messaging_backend **presult)
> -{
> - return ENOSYS;
> -}
> -
> int messaging_ctdb_send(uint32_t dst_vnn, uint64_t dst_srvid,
> const struct iovec *iov, int iovlen)
> {
> @@ -116,25 +103,6 @@ struct messaging_ctdb_fde *messaging_ctdb_register_tevent_context(
> return NULL;
> }
>
> -int messaging_ctdbd_reinit(struct messaging_context *msg_ctx,
> - TALLOC_CTX *mem_ctx,
> - void (*recv_cb)(struct tevent_context *ev,
> - const uint8_t *msg, size_t msg_len,
> - int *fds, size_t num_fds,
> - void *private_data),
> - void *private_data,
> - struct messaging_backend *backend)
> -{
> - return ENOSYS;
> -}
> -
> -struct messaging_ctdbd_fde *messaging_ctdbd_register_tevent_context(
> - TALLOC_CTX *mem_ctx, struct tevent_context *ev,
> - struct messaging_backend *backend)
> -{
> - return NULL;
> -}
> -
> struct ctdbd_connection *messaging_ctdb_connection(void)
> {
> return NULL;
> diff --git a/source3/lib/messages_ctdbd.c b/source3/lib/messages_ctdbd.c
> deleted file mode 100644
> index b1af4f8..0000000
> --- a/source3/lib/messages_ctdbd.c
> +++ /dev/null
> @@ -1,354 +0,0 @@
> -/*
> - Unix SMB/CIFS implementation.
> - Samba internal messaging functions
> - Copyright (C) 2007 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 "includes.h"
> -#include "lib/messages_ctdbd.h"
> -#include "lib/util/server_id.h"
> -#include "messages.h"
> -#include "util_tdb.h"
> -#include "lib/util/iov_buf.h"
> -#include "lib/messages_util.h"
> -#include "ctdbd_conn.h"
> -#include "lib/cluster_support.h"
> -
> -struct messaging_ctdbd_context;
> -
> -struct messaging_ctdbd_fde_ev {
> - struct messaging_ctdbd_fde_ev *prev, *next;
> -
> - /*
> - * Backreference to enable DLIST_REMOVE from our
> - * destructor. Also, set to NULL when the dgm_context dies
> - * before the messaging_dgm_fde_ev.
> - */
> - struct messaging_ctdbd_context *ctx;
> -
> - struct tevent_context *ev;
> - struct tevent_fd *fde;
> -};
> -
> -struct messaging_ctdbd_context {
> - struct ctdbd_connection *conn;
> -
> - struct messaging_ctdbd_fde_ev *fde_evs;
> -
> - void (*recv_cb)(struct tevent_context *ev,
> - const uint8_t *msg, size_t msg_len,
> - int *fds, size_t num_fds,
> - void *private_data);
> - void *private_data;
> -};
> -
> -/*
> - * This is a Samba3 hack/optimization. Routines like process_exists need to
> - * talk to ctdbd, and they don't get handed a messaging context.
> - */
> -static struct ctdbd_connection *global_ctdbd_connection;
> -static int global_ctdb_connection_pid;
> -
> -struct ctdbd_connection *messaging_ctdbd_connection(void)
> -{
> - if (!lp_clustering()) {
> - return NULL;
> - }
> -
> - if (global_ctdb_connection_pid == 0 &&
> - global_ctdbd_connection == NULL) {
> - struct tevent_context *ev;
> - struct messaging_context *msg;
> -
> - ev = samba_tevent_context_init(NULL);
> - if (!ev) {
> - DEBUG(0,("samba_tevent_context_init failed\n"));
> - return NULL;
> - }
> -
> - msg = messaging_init(NULL, ev);
> - if (!msg) {
> - DEBUG(0,("messaging_init failed\n"));
> - return NULL;
> - }
> - }
> -
> - if (global_ctdb_connection_pid != getpid()) {
> - DEBUG(0,("messaging_ctdbd_connection():"
> - "valid for pid[%jd] but it's [%jd]\n",
> - (intmax_t)global_ctdb_connection_pid,
> - (intmax_t)getpid()));
> - smb_panic("messaging_ctdbd_connection() invalid process\n");
> - }
> -
> - return global_ctdbd_connection;
> -}
> -
> -static int messaging_ctdb_send(struct server_id src,
> - struct server_id pid, int msg_type,
> - const struct iovec *iov, int iovlen,
> - const int *fds, size_t num_fds,
> - struct messaging_backend *backend)
> -{
> - struct messaging_ctdbd_context *ctx = talloc_get_type_abort(
> - backend->private_data, struct messaging_ctdbd_context);
> - uint8_t hdr[MESSAGE_HDR_LENGTH];
> - struct iovec iov2[iovlen+1];
> -
> - if (num_fds > 0) {
> - return ENOSYS;
> - }
> -
> - message_hdr_put(hdr, msg_type, src, pid);
> - iov2[0] = (struct iovec){ .iov_base = hdr, .iov_len = sizeof(hdr) };
> - memcpy(&iov2[1], iov, iovlen * sizeof(*iov));
> -
> - return ctdbd_messaging_send_iov(ctx->conn, pid.vnn, pid.pid,
> - iov2, iovlen+1);
> -}
> -
> -static int messaging_ctdbd_destructor(struct messaging_ctdbd_context *ctx)
> -{
> - /*
> - * The global connection just went away
> - */
> - global_ctdb_connection_pid = 0;
> - global_ctdbd_connection = NULL;
> - return 0;
> -}
> -
> -static int messaging_ctdb_recv(
> - struct tevent_context *ev,
> - uint32_t src_vnn, uint32_t dst_vnn, uint64_t dst_srvid,
> - const uint8_t *msg, size_t msg_len, void *private_data)
> -{
> - struct messaging_ctdbd_context *ctx = talloc_get_type_abort(
> - private_data, struct messaging_ctdbd_context);
> -
> - ctx->recv_cb(ev, msg, msg_len, NULL, 0, ctx->private_data);
> -
> - return 0;
> -}
> -
> -static void messaging_ctdbd_readable(struct tevent_context *ev,
> - struct tevent_fd *fde,
> - uint16_t flags,
> - void *private_data)
> -{
> - struct ctdbd_connection *conn = talloc_get_type_abort(
> - private_data, struct ctdbd_connection);
> -
> - if ((flags & TEVENT_FD_READ) == 0) {
> - return;
> - }
> - ctdbd_socket_readable(ev, conn);
> -}
> -
> -static int messaging_ctdbd_init_internal(
> - struct messaging_context *msg_ctx, TALLOC_CTX *mem_ctx,
> - struct messaging_ctdbd_context *ctx,
> - void (*recv_cb)(struct tevent_context *ev,
> - const uint8_t *msg, size_t msg_len,
> - int *fds, size_t num_fds,
> - void *private_data),
> - void *private_data,
> - bool reinit)
> -{
> - int ret;
> -
> - if (reinit) {
> - ret = ctdbd_reinit_connection(ctx,
> - lp_ctdbd_socket(),
> - lp_ctdb_timeout(),
> - ctx->conn);
> - if (ret != 0) {
> - DBG_ERR("ctdbd_reinit_connection failed: %s\n",
> - strerror(ret));
> - return ret;
> - }
> - } else {
> - ret = ctdbd_init_connection(ctx,
> - lp_ctdbd_socket(),
> - lp_ctdb_timeout(),
> - &ctx->conn);
> - if (ret != 0) {
> - DBG_ERR("ctdbd_init_connection failed: %s\n",
> - strerror(ret));
> - return ret;
> - }
> - }
> -
> - ret = register_with_ctdbd(ctx->conn, MSG_SRVID_SAMBA, NULL, NULL);
> - if (ret != 0) {
> - DBG_DEBUG("Could not register MSG_SRVID_SAMBA: %s\n",
> - strerror(ret));
> - return ret;
> - }
> -
> - ctx->recv_cb = recv_cb;
> - ctx->private_data = private_data;
> -
> - ret = register_with_ctdbd(ctx->conn, getpid(),
> - messaging_ctdb_recv, ctx);
> - if (ret != 0) {
> - DEBUG(10, ("register_with_ctdbd failed: %s\n",
> - strerror(ret)));
> - return ret;
> - }
> -
> - global_ctdb_connection_pid = getpid();
> - global_ctdbd_connection = ctx->conn;
> - talloc_set_destructor(ctx, messaging_ctdbd_destructor);
> -
> - set_my_vnn(ctdbd_vnn(ctx->conn));
> -
> - return 0;
> -}
> -
> -int messaging_ctdbd_init(struct messaging_context *msg_ctx,
> - TALLOC_CTX *mem_ctx,
> - void (*recv_cb)(struct tevent_context *ev,
> - const uint8_t *msg, size_t msg_len,
> - int *fds, size_t num_fds,
> - void *private_data),
> - void *private_data,
> - struct messaging_backend **presult)
> -{
> - struct messaging_backend *result;
> - struct messaging_ctdbd_context *ctx;
> - int ret;
> -
> - if (!(result = talloc(mem_ctx, struct messaging_backend))) {
> - DEBUG(0, ("talloc failed\n"));
> - return ENOMEM;
> - }
> -
> - if (!(ctx = talloc_zero(result, struct messaging_ctdbd_context))) {
> - DEBUG(0, ("talloc failed\n"));
> - TALLOC_FREE(result);
> - return ENOMEM;
> - }
> -
> - ret = messaging_ctdbd_init_internal(msg_ctx, mem_ctx, ctx,
> - recv_cb, private_data, false);
> - if (ret != 0) {
> - TALLOC_FREE(result);
> - return ret;
> - }
> -
> - result->send_fn = messaging_ctdb_send;
> - result->private_data = (void *)ctx;
> -
> - *presult = result;
> - return 0;
> -}
> -
> -int messaging_ctdbd_reinit(struct messaging_context *msg_ctx,
> - TALLOC_CTX *mem_ctx,
> - void (*recv_cb)(struct tevent_context *ev,
> - const uint8_t *msg, size_t msg_len,
> - int *fds, size_t num_fds,
> - void *private_data),
> - void *private_data,
> - struct messaging_backend *backend)
> -{
> - struct messaging_ctdbd_context *ctx = talloc_get_type_abort(
> - backend->private_data, struct messaging_ctdbd_context);
> - int ret;
> -
> - ret = messaging_ctdbd_init_internal(msg_ctx, mem_ctx, ctx,
> - recv_cb, private_data, true);
> - if (ret != 0) {
> - return ret;
> - }
> -
> - return 0;
> -}
> -
> -struct messaging_ctdbd_fde {
> - struct tevent_fd *fde;
> -};
> -
> -static int messaging_ctdbd_fde_ev_destructor(
> - struct messaging_ctdbd_fde_ev *fde_ev)
> -{
> - if (fde_ev->ctx != NULL) {
> - DLIST_REMOVE(fde_ev->ctx->fde_evs, fde_ev);
> - fde_ev->ctx = NULL;
> - }
> - return 0;
> -}
> -
> -struct messaging_ctdbd_fde *messaging_ctdbd_register_tevent_context(
> - TALLOC_CTX *mem_ctx, struct tevent_context *ev,
> - struct messaging_backend *backend)
> -{
> - struct messaging_ctdbd_context *ctx = talloc_get_type_abort(
> - backend->private_data, struct messaging_ctdbd_context);
> - struct messaging_ctdbd_fde_ev *fde_ev;
> - struct messaging_ctdbd_fde *fde;
> -
> - if (ctx == NULL) {
> - return NULL;
> - }
> -
> - fde = talloc(mem_ctx, struct messaging_ctdbd_fde);
> - if (fde == NULL) {
> - return NULL;
> - }
> -
> - for (fde_ev = ctx->fde_evs; fde_ev != NULL; fde_ev = fde_ev->next) {
> - if ((fde_ev->ev == ev) &&
> - (tevent_fd_get_flags(fde_ev->fde) != 0)) {
> - break;
> - }
> - }
> -
> - if (fde_ev == NULL) {
> - int fd = ctdbd_conn_get_fd(ctx->conn);
> -
> - fde_ev = talloc(fde, struct messaging_ctdbd_fde_ev);
> - if (fde_ev == NULL) {
> - return NULL;
> - }
> - fde_ev->fde = tevent_add_fd(
> - ev, fde_ev, fd, TEVENT_FD_READ,
> - messaging_ctdbd_readable, ctx->conn);
> - if (fde_ev->fde == NULL) {
> - TALLOC_FREE(fde);
> - return NULL;
> - }
> - fde_ev->ev = ev;
> - fde_ev->ctx = ctx;
> - DLIST_ADD(ctx->fde_evs, fde_ev);
> - talloc_set_destructor(
> - fde_ev, messaging_ctdbd_fde_ev_destructor);
> - } else {
> - /*
> - * Same trick as with tdb_wrap: The caller will never
> - * see the talloc_referenced object, the
> - * messaging_ctdbd_fde_ev, so problems with
> - * talloc_unlink will not happen.
> - */
> - if (talloc_reference(fde, fde_ev) == NULL) {
> - TALLOC_FREE(fde);
> - return NULL;
> - }
> - }
> -
> - fde->fde = fde_ev->fde;
> - return fde;
> -}
> diff --git a/source3/lib/messages_ctdbd.h b/source3/lib/messages_ctdbd.h
> deleted file mode 100644
> index 7d928fe..0000000
> --- a/source3/lib/messages_ctdbd.h
> +++ /dev/null
> @@ -1,53 +0,0 @@
> -/*
> - * Unix SMB/CIFS implementation.
> - * messages_ctdb.c header
> - * Copyright (C) Volker Lendecke 2017
> - *
> - * 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_CTDB_H_
> -#define _MESSAGES_CTDB_H_
> -
> -#include "replace.h"
> -#include <talloc.h>
> -
> -struct messaging_context;
> -struct messaging_backend;
> -struct ctdbd_connection;
> -
> -int messaging_ctdbd_init(struct messaging_context *msg_ctx,
> - TALLOC_CTX *mem_ctx,
> - void (*recv_cb)(struct tevent_context *ev,
> - const uint8_t *msg, size_t msg_len,
> - int *fds, size_t num_fds,
> - void *private_data),
> - void *private_data,
> - struct messaging_backend **presult);
> -int messaging_ctdbd_reinit(struct messaging_context *msg_ctx,
> - TALLOC_CTX *mem_ctx,
> - void (*recv_cb)(struct tevent_context *ev,
> - const uint8_t *msg, size_t msg_len,
> - int *fds, size_t num_fds,
> - void *private_data),
> - void *private_data,
> - struct messaging_backend *backend);
> -struct ctdbd_connection *messaging_ctdbd_connection(void);
> -
> -struct messaging_ctdbd_fde;
> -struct messaging_ctdbd_fde *messaging_ctdbd_register_tevent_context(
> - TALLOC_CTX *mem_ctx, struct tevent_context *ev,
> - struct messaging_backend *backend);
> -
> -#endif
> --
> 2.1.4
>
>
> From 889967a52fc6727e1b6528eb6b37b40c8a713d63 Mon Sep 17 00:00:00 2001
> From: Volker Lendecke <vl at samba.org>
> Date: Wed, 5 Jul 2017 19:26:22 +0200
> Subject: [PATCH 41/41] messaging: Remove "struct messaging_backend"
>
> Signed-off-by: Volker Lendecke <vl at samba.org>
> ---
> source3/include/messages.h | 9 ---------
> 1 file changed, 9 deletions(-)
>
> diff --git a/source3/include/messages.h b/source3/include/messages.h
> index 970dc38..8d3b1d8 100644
> --- a/source3/include/messages.h
> +++ b/source3/include/messages.h
> @@ -56,15 +56,6 @@
> struct messaging_context;
> struct messaging_rec;
>
> -struct messaging_backend {
> - int (*send_fn)(struct server_id src,
> - struct server_id pid, int msg_type,
> - const struct iovec *iov, int iovlen,
> - const int *fds, size_t num_fds,
> - struct messaging_backend *backend);
> - void *private_data;
> -};
> -
> struct messaging_context *messaging_init(TALLOC_CTX *mem_ctx,
> struct tevent_context *ev);
> NTSTATUS messaging_init_client(TALLOC_CTX *mem_ctx,
> --
> 2.1.4
>
More information about the samba-technical
mailing list