[PATCH] g_lock_ping_pong

classic Classic list List threaded Threaded
15 messages Options
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

[PATCH] g_lock_ping_pong

Samba - samba-technical mailing list
Hi!

Attached find a patchset that implements a g_lock performance test
along with some modifications for correctness and performance.

Review appreciated!

Thanks, Volker

--
SerNet GmbH, Bahnhofsallee 1b, 37081 Göttingen
phone: +49-551-370000-0, fax: +49-551-370000-9
AG Göttingen, HRB 2816, GF: Dr. Johannes Loxen
http://www.sernet.de, mailto:[hidden email]

patch.txt (202K) Download Attachment
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: [PATCH] g_lock_ping_pong

Samba - samba-technical mailing list
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:[hidden email]

> From d3c7576c58922731e1fa1c7f17c3d0ec94d8a7fa Mon Sep 17 00:00:00 2001
> From: Volker Lendecke <[hidden email]>
> 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 <[hidden email]>
> ---
>  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 <[hidden email]>
> 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 <[hidden email]>
> ---
>  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 <[hidden email]>
> 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 <[hidden email]>
> ---
>  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 <[hidden email]>
> Date: Tue, 13 Sep 2016 12:25:14 +0200
> Subject: [PATCH 04/41] dbwrap: Add dbwrap_record_storev
>
> Signed-off-by: Volker Lendecke <[hidden email]>
> ---
>  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 <[hidden email]>
> 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 <[hidden email]>
> ---
>  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 <[hidden email]>
> Date: Tue, 27 Jun 2017 08:25:36 +0200
> Subject: [PATCH 06/41] torture3: Test dbwrap_do_locked
>
> Signed-off-by: Volker Lendecke <[hidden email]>
> ---
>  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 <[hidden email]>
> Date: Tue, 27 Jun 2017 08:25:03 +0200
> Subject: [PATCH 07/41] dbwrap_tdb: Implement do_locked
>
> Signed-off-by: Volker Lendecke <[hidden email]>
> ---
>  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 <[hidden email]>
> 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 <[hidden email]>
> ---
>  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 <[hidden email]>
> Date: Tue, 27 Jun 2017 18:40:28 +0200
> Subject: [PATCH 09/41] dbwrap_watch: Implement do_locked
>
> Signed-off-by: Volker Lendecke <[hidden email]>
> ---
>  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 <[hidden email]>
> 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 <[hidden email]>
> ---
>  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 <[hidden email]>
> 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 <[hidden email]>
> ---
>  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 <[hidden email]>
> 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 <[hidden email]>
> ---
>  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 <[hidden email]>
> 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 <[hidden email]>
> ---
>  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 <[hidden email]>
> 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 <[hidden email]>
> ---
>  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 <[hidden email]>
> 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 <[hidden email]>
> ---
>  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 <[hidden email]>
> 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 <[hidden email]>
> ---
>  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 <[hidden email]>
> 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 <[hidden email]>
> ---
>  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 <[hidden email]>
> 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 <[hidden email]>
> ---
>  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 <[hidden email]>
> 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 <[hidden email]>
> ---
>  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 <[hidden email]>
> 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 <[hidden email]>
> ---
>  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 <[hidden email]>
> Date: Fri, 30 Jun 2017 22:14:58 +0200
> Subject: [PATCH 21/41] g_lock: Remove unused code
>
> Signed-off-by: Volker Lendecke <[hidden email]>
> ---
>  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 <[hidden email]>
> 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 <[hidden email]>
> ---
>  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 <[hidden email]>
> 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 <[hidden email]>
> ---
>  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 <[hidden email]>
> 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 <[hidden email]>
> ---
>  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 <[hidden email]>
> 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 <[hidden email]>
> ---
>  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 <[hidden email]>
> 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 <[hidden email]>
> ---
>  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 <[hidden email]>
> 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 <[hidden email]>
> ---
>  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 <[hidden email]>
> 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 <[hidden email]>
> ---
>  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 <[hidden email]>
> 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 <[hidden email]>
> ---
>  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 <[hidden email]>
> 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 <[hidden email]>
> ---
>  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 <[hidden email]>
> 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 <[hidden email]>
> ---
>  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 <[hidden email]>
> 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 <[hidden email]>
> ---
>  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 <[hidden email]>
> 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 <[hidden email]>
> ---
>  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 <[hidden email]>
> 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 <[hidden email]>
> ---
>  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 <[hidden email]>
> 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 <[hidden email]>
> ---
>  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 <[hidden email]>
> 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 <[hidden email]>
> ---
>  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 <[hidden email]>
> 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 <[hidden email]>
> ---
>  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 <[hidden email]>
> Date: Wed, 5 Jul 2017 19:20:09 +0200
> Subject: [PATCH 38/41] messaging: Use messaging_ctdb_ref()
>
> Signed-off-by: Volker Lendecke <[hidden email]>
> ---
>  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 <[hidden email]>
> 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 <[hidden email]>
> ---
>  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 <[hidden email]>
> 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 <[hidden email]>
> ---
>  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 <[hidden email]>
> Date: Wed, 5 Jul 2017 19:26:22 +0200
> Subject: [PATCH 41/41] messaging: Remove "struct messaging_backend"
>
> Signed-off-by: Volker Lendecke <[hidden email]>
> ---
>  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
>


Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: [PATCH] g_lock_ping_pong

Samba - samba-technical mailing list
On Thu, Jul 06, 2017 at 03:52:46PM -0700, Jeremy Allison via samba-technical wrote:

> 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.

This would be next on my list as well. How far did you get? Does it make sense
if I take a look as well?

Cheerio!
-slow

Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: [PATCH] g_lock_ping_pong

Samba - samba-technical mailing list
On Tue, Jul 11, 2017 at 10:53:56PM +0200, Ralph Böhme via samba-technical wrote:

> On Thu, Jul 06, 2017 at 03:52:46PM -0700, Jeremy Allison via samba-technical wrote:
> > 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.
>
> This would be next on my list as well. How far did you get? Does it make sense
> if I take a look as well?

Would it help if I split this up into smaller pieces? There are
functional blocks that could be pushed independently.

Thanks,

Volker

--
SerNet GmbH, Bahnhofsallee 1b, 37081 Göttingen
phone: +49-551-370000-0, fax: +49-551-370000-9
AG Göttingen, HRB 2816, GF: Dr. Johannes Loxen
http://www.sernet.de, mailto:[hidden email]

Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: [PATCH] g_lock_ping_pong

Samba - samba-technical mailing list
In reply to this post by Samba - samba-technical mailing list
On Tue, Jul 11, 2017 at 10:53:56PM +0200, Ralph Böhme wrote:

> On Thu, Jul 06, 2017 at 03:52:46PM -0700, Jeremy Allison via samba-technical wrote:
> > 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.
>
> This would be next on my list as well. How far did you get? Does it make sense
> if I take a look as well?

Yes it would. Sorry I haven't gotten to this yet, took yesterday
off and had a dental emergency, plus now have to look at this
Heimdal thing :-(.

More eyes certainly welcome !

Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: [PATCH] g_lock_ping_pong

Samba - samba-technical mailing list
In reply to this post by Samba - samba-technical mailing list
On Wed, Jul 12, 2017 at 08:52:39AM +0200, Volker Lendecke wrote:

> On Tue, Jul 11, 2017 at 10:53:56PM +0200, Ralph Böhme via samba-technical wrote:
> > On Thu, Jul 06, 2017 at 03:52:46PM -0700, Jeremy Allison via samba-technical wrote:
> > > 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.
> >
> > This would be next on my list as well. How far did you get? Does it make sense
> > if I take a look as well?
>
> Would it help if I split this up into smaller pieces? There are
> functional blocks that could be pushed independently.

nah, I'll try to swallow the big pill. :)

Cheerio!
-slow

Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: [PATCH] g_lock_ping_pong

Samba - samba-technical mailing list
On Thu, Jul 13, 2017 at 11:39:28AM +0200, Ralph Böhme wrote:

> On Wed, Jul 12, 2017 at 08:52:39AM +0200, Volker Lendecke wrote:
> > On Tue, Jul 11, 2017 at 10:53:56PM +0200, Ralph Böhme via samba-technical wrote:
> > > On Thu, Jul 06, 2017 at 03:52:46PM -0700, Jeremy Allison via samba-technical wrote:
> > > > 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.
> > >
> > > This would be next on my list as well. How far did you get? Does it make sense
> > > if I take a look as well?
> >
> > Would it help if I split this up into smaller pieces? There are
> > functional blocks that could be pushed independently.
>
> nah, I'll try to swallow the big pill. :)

doesn't apply to master, can you check?

Cheerio!
-slow

Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: [PATCH] g_lock_ping_pong

Samba - samba-technical mailing list
On Fri, Jul 14, 2017 at 02:39:38PM +0200, Ralph Böhme wrote:
> > nah, I'll try to swallow the big pill. :)
>
> doesn't apply to master, can you check?

The dbwrap flag patches came in between and I did not update the
patch. I'll go through and re-send when it survives another autobuild.

Thanks,

Volker

--
SerNet GmbH, Bahnhofsallee 1b, 37081 Göttingen
phone: +49-551-370000-0, fax: +49-551-370000-9
AG Göttingen, HRB 2816, GF: Dr. Johannes Loxen
http://www.sernet.de, mailto:[hidden email]

Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: [PATCH] g_lock_ping_pong

Samba - samba-technical mailing list
On Fri, Jul 14, 2017 at 02:49:43PM +0200, Volker Lendecke wrote:
> On Fri, Jul 14, 2017 at 02:39:38PM +0200, Ralph Böhme wrote:
> > > nah, I'll try to swallow the big pill. :)
> >
> > doesn't apply to master, can you check?
>
> The dbwrap flag patches came in between and I did not update the
> patch. I'll go through and re-send when it survives another autobuild.

yeah, thought so. Sorry for getting in between. :)

Cheerio!
-slow

Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: [PATCH] g_lock_ping_pong

Samba - samba-technical mailing list
In reply to this post by Samba - samba-technical mailing list
On Fri, Jul 14, 2017 at 02:39:38PM +0200, Ralph Böhme via samba-technical wrote:
> > nah, I'll try to swallow the big pill. :)
>
> doesn't apply to master, can you check?

The attached patchset survived a private autobuild against master as
of Friday around noon, and rebases properly on current master.

Thanks,

Volker

--
SerNet GmbH, Bahnhofsallee 1b, 37081 Göttingen
phone: +49-551-370000-0, fax: +49-551-370000-9
AG Göttingen, HRB 2816, GF: Dr. Johannes Loxen
http://www.sernet.de, mailto:[hidden email]

patch.txt (203K) Download Attachment
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: [PATCH] g_lock_ping_pong

Samba - samba-technical mailing list
On Sat, Jul 15, 2017 at 08:06:29AM +0200, Volker Lendecke wrote:
> On Fri, Jul 14, 2017 at 02:39:38PM +0200, Ralph Böhme via samba-technical wrote:
> > > nah, I'll try to swallow the big pill. :)
> >
> > doesn't apply to master, can you check?
>
> The attached patchset survived a private autobuild against master as
> of Friday around noon, and rebases properly on current master.

ok, took me a while to get through. Really really nice cleanup!

Everything reviewed-by-me, accept the missing lock-order checks already
mentioned over phone and a few commits that should be squashed to avoid
EFUNCTIONDEFINEDBUTNOTUSED, see:

<https://git.samba.org/?p=slow/samba.git;a=shortlog;h=refs/heads/glock>

SQUASH denotes commits that should be squashed with the preceeding one.

Cheerio!
-slow

Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: [PATCH] g_lock_ping_pong

Samba - samba-technical mailing list
On Wed, Jul 19, 2017 at 09:45:57AM +0200, Ralph Böhme wrote:

> On Sat, Jul 15, 2017 at 08:06:29AM +0200, Volker Lendecke wrote:
> > On Fri, Jul 14, 2017 at 02:39:38PM +0200, Ralph Böhme via samba-technical wrote:
> > > > nah, I'll try to swallow the big pill. :)
> > >
> > > doesn't apply to master, can you check?
> >
> > The attached patchset survived a private autobuild against master as
> > of Friday around noon, and rebases properly on current master.
>
> ok, took me a while to get through. Really really nice cleanup!
>
> Everything reviewed-by-me, accept the missing lock-order checks already
> mentioned over phone and a few commits that should be squashed to avoid
> EFUNCTIONDEFINEDBUTNOTUSED, see:

I'd propose a different approach: We should make the functions public
with a header file in one commit, remove their use in a second commit
and then remove the then-public functions in a third one. This ensures
full autobuildability in every commit and also maintains a clean patch
history.

Comments?

Volker

--
SerNet GmbH, Bahnhofsallee 1b, 37081 Göttingen
phone: +49-551-370000-0, fax: +49-551-370000-9
AG Göttingen, HRB 2816, GF: Dr. Johannes Loxen
http://www.sernet.de, mailto:[hidden email]

Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: [PATCH] g_lock_ping_pong

Samba - samba-technical mailing list
On Thu, Jul 20, 2017 at 10:42:59AM +0200, Volker Lendecke wrote:

> On Wed, Jul 19, 2017 at 09:45:57AM +0200, Ralph Böhme wrote:
> > On Sat, Jul 15, 2017 at 08:06:29AM +0200, Volker Lendecke wrote:
> > > On Fri, Jul 14, 2017 at 02:39:38PM +0200, Ralph Böhme via samba-technical wrote:
> > > > > nah, I'll try to swallow the big pill. :)
> > > >
> > > > doesn't apply to master, can you check?
> > >
> > > The attached patchset survived a private autobuild against master as
> > > of Friday around noon, and rebases properly on current master.
> >
> > ok, took me a while to get through. Really really nice cleanup!
> >
> > Everything reviewed-by-me, accept the missing lock-order checks already
> > mentioned over phone and a few commits that should be squashed to avoid
> > EFUNCTIONDEFINEDBUTNOTUSED, see:
>
> I'd propose a different approach: We should make the functions public
> with a header file in one commit, remove their use in a second commit
> and then remove the then-public functions in a third one. This ensures
> full autobuildability in every commit and also maintains a clean patch
> history.
>
> Comments?

if you prefer, I don't really care. :)

Cheerio!
-slow

Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: [PATCH] g_lock_ping_pong

Samba - samba-technical mailing list
Am 20.07.2017 um 10:57 schrieb Ralph Böhme via samba-technical:

> On Thu, Jul 20, 2017 at 10:42:59AM +0200, Volker Lendecke wrote:
>> On Wed, Jul 19, 2017 at 09:45:57AM +0200, Ralph Böhme wrote:
>>> On Sat, Jul 15, 2017 at 08:06:29AM +0200, Volker Lendecke wrote:
>>>> On Fri, Jul 14, 2017 at 02:39:38PM +0200, Ralph Böhme via samba-technical wrote:
>>>>>> nah, I'll try to swallow the big pill. :)
>>>>>
>>>>> doesn't apply to master, can you check?
>>>>
>>>> The attached patchset survived a private autobuild against master as
>>>> of Friday around noon, and rebases properly on current master.
>>>
>>> ok, took me a while to get through. Really really nice cleanup!
>>>
>>> Everything reviewed-by-me, accept the missing lock-order checks already
>>> mentioned over phone and a few commits that should be squashed to avoid
>>> EFUNCTIONDEFINEDBUTNOTUSED, see:
>>
>> I'd propose a different approach: We should make the functions public
>> with a header file in one commit, remove their use in a second commit
>> and then remove the then-public functions in a third one. This ensures
>> full autobuildability in every commit and also maintains a clean patch
>> history.
>>
>> Comments?
>
> if you prefer, I don't really care. :)
I typically use '#if 0' and '#endif' that to avoid to much changes.

metze



signature.asc (853 bytes) Download Attachment
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: [PATCH] g_lock_ping_pong

Samba - samba-technical mailing list
On Thu, Jul 20, 2017 at 01:35:54PM +0200, Stefan Metzmacher wrote:
> > if you prefer, I don't really care. :)
>
> I typically use '#if 0' and '#endif' that to avoid to much changes.

Please find the updated code under

https://git.samba.org/?p=vl/samba.git/.git;a=shortlog;h=refs/heads/g_lock

I've added REVIEW to the subject of the changed patches.

Thanks,

Volker

--
SerNet GmbH, Bahnhofsallee 1b, 37081 Göttingen
phone: +49-551-370000-0, fax: +49-551-370000-9
AG Göttingen, HRB 2816, GF: Dr. Johannes Loxen
http://www.sernet.de, mailto:[hidden email]

Loading...