[SCM] Samba Shared Repository - branch master updated

Jeremy Allison jra at samba.org
Fri May 15 02:28:03 UTC 2020


The branch, master has been updated
       via  49951b283d9 smbd: Store share_entries in locking.tdb again
       via  7bdd5ad4b5e smbd: Move share mode entry parsing up in the file
       via  8020f013084 smbd: Base locking.tdb on g_lock.c
       via  3bf576bb2a8 lib: Add g_lock_dump_send/recv
       via  0a043e64b63 lib: Add g_lock_set_lock_order()
       via  6fb6a6992d9 lib: Add g_lock_writev_data
       via  4f2117d6870 lib: Allow additional dbufs in g_lock_store()
       via  3d0cfb82ec6 lib: Add g_lock_seqnum()
       via  c38f37147d1 lib: Add g_lock_wake_watchers()
       via  90dcfa4e592 torture: Test g_lock_watch_data_send()/recv()
       via  46e8e0cd7eb lib: Add g_lock_watch_data_send/recv()
       via  66d62ed7978 lib: Allow DBWRAP_LOCK_ORDER_NONE in db_open()
       via  5ae58cd0db3 dbwrap: Make dbwrap_lock_order_[un]lock() public
       via  38a80a30052 dbwrap: Simplify dbwrap_lock_order_[un]lock()
      from  01db877c776 srvsvc: Move brl_get_locks() out of enum_file_fn()

https://git.samba.org/?p=samba.git;a=shortlog;h=master


- Log -----------------------------------------------------------------
commit 49951b283d98d81a2201341624b4bcdd3eba9ec4
Author: Volker Lendecke <vl at samba.org>
Date:   Tue Apr 14 16:51:15 2020 +0200

    smbd: Store share_entries in locking.tdb again
    
    The "base on g_lock" patch is a slowdown because we do more tdb
    operations. Getting share_entries.tdb back into locking.tdb tries to
    speed things up again.
    
    Now that we're based on g_lock we'll most likely use a different
    method in order to spread the entries across multiple records.
    
    It still maintains the sorted array of share modes within locking.tdb,
    but not as part of the expensive ndr marshalling of the complete
    array.
    
    Signed-off-by: Volker Lendecke <vl at samba.org>
    Reviewed-by: Jeremy Allison <jra at samba.org>
    
    Autobuild-User(master): Jeremy Allison <jra at samba.org>
    Autobuild-Date(master): Fri May 15 02:27:49 UTC 2020 on sn-devel-184

commit 7bdd5ad4b5e73937ffbbb9b7365639e360733d95
Author: Volker Lendecke <vl at samba.org>
Date:   Thu Mar 26 19:45:10 2020 +0100

    smbd: Move share mode entry parsing up in the file
    
    Will be used by parsing code soon
    
    Signed-off-by: Volker Lendecke <vl at samba.org>
    Reviewed-by: Jeremy Allison <jra at samba.org>

commit 8020f013084e4424e761b405634b03aa6466bd88
Author: Volker Lendecke <vl at samba.org>
Date:   Tue Nov 5 12:01:52 2019 +0100

    smbd: Base locking.tdb on g_lock.c
    
    This means we don't hold locking.tdb mutexes anymore while we do
    filesystem-level operations. This has hurt ctdb quite a bit: A smbd hanging in
    an unlink() syscall prevents ctdb from recovering locking.tdb.
    
    Signed-off-by: Volker Lendecke <vl at samba.org>
    Reviewed-by: Jeremy Allison <jra at samba.org>

commit 3bf576bb2a8eaf1ede44b6327e2eb9272b73c5f9
Author: Volker Lendecke <vl at samba.org>
Date:   Tue Mar 24 09:54:26 2020 +0100

    lib: Add g_lock_dump_send/recv
    
    Signed-off-by: Volker Lendecke <vl at samba.org>
    Reviewed-by: Jeremy Allison <jra at samba.org>

commit 0a043e64b639ff2d29eb052abcd894c5ee185936
Author: Volker Lendecke <vl at samba.org>
Date:   Thu Nov 21 15:20:07 2019 +0100

    lib: Add g_lock_set_lock_order()
    
    Optionally allow a database with g_lock format to participate in the dbwarp
    lock order check. Will be used once locking.tdb is based upon g_lock.c
    
    Signed-off-by: Volker Lendecke <vl at samba.org>
    Reviewed-by: Jeremy Allison <jra at samba.org>

commit 6fb6a6992d959d2904baf3448a09bb3575ca91f1
Author: Volker Lendecke <vl at samba.org>
Date:   Wed Apr 29 15:35:39 2020 +0200

    lib: Add g_lock_writev_data
    
    Signed-off-by: Volker Lendecke <vl at samba.org>
    Reviewed-by: Jeremy Allison <jra at samba.org>

commit 4f2117d68706d9e723b582f29623dfd7177d9251
Author: Volker Lendecke <vl at samba.org>
Date:   Wed Apr 29 15:28:03 2020 +0200

    lib: Allow additional dbufs in g_lock_store()
    
    Preparation for g_lock_writev_data()
    
    Signed-off-by: Volker Lendecke <vl at samba.org>
    Reviewed-by: Jeremy Allison <jra at samba.org>

commit 3d0cfb82ec6aa1accba27040c17880a43c3f155c
Author: Volker Lendecke <vl at samba.org>
Date:   Tue Nov 5 16:36:59 2019 +0100

    lib: Add g_lock_seqnum()
    
    Signed-off-by: Volker Lendecke <vl at samba.org>
    Reviewed-by: Jeremy Allison <jra at samba.org>

commit c38f37147d127672398a4a05fc731d4bb9726947
Author: Volker Lendecke <vl at samba.org>
Date:   Mon Nov 4 16:03:52 2019 +0100

    lib: Add g_lock_wake_watchers()
    
    Signed-off-by: Volker Lendecke <vl at samba.org>
    Reviewed-by: Jeremy Allison <jra at samba.org>

commit 90dcfa4e59276467b89d07c1fc6fc14ed4c225ff
Author: Volker Lendecke <vl at samba.org>
Date:   Thu Oct 31 11:45:36 2019 +0100

    torture: Test g_lock_watch_data_send()/recv()
    
    Signed-off-by: Volker Lendecke <vl at samba.org>
    Reviewed-by: Jeremy Allison <jra at samba.org>

commit 46e8e0cd7eb69e2c8ee9b65491e198134fab1b61
Author: Volker Lendecke <vl at samba.org>
Date:   Wed Oct 30 16:12:11 2019 +0100

    lib: Add g_lock_watch_data_send/recv()
    
    Same concept as dbwrap_watched_watch_send/recv: Get informed if the
    underlying data of a record changes. This utilizes the watched
    database that g_lock is based upon anyway. To avoid spurious wakeups
    by pure g_lock operations this patch adds a sequence number for the
    data that is stored in the g_lock data field.
    
    Signed-off-by: Volker Lendecke <vl at samba.org>
    Reviewed-by: Jeremy Allison <jra at samba.org>

commit 66d62ed7978cc0bc1d7bb6c495e32738802f4420
Author: Volker Lendecke <vl at samba.org>
Date:   Thu Nov 21 15:20:33 2019 +0100

    lib: Allow DBWRAP_LOCK_ORDER_NONE in db_open()
    
    locking.tdb will not have a LOCK_ORDER anymore, this will be done by
    the code in g_lock.c. We need to allow opening a database with dbwrap
    without having a lock order.
    
    Signed-off-by: Volker Lendecke <vl at samba.org>
    Reviewed-by: Jeremy Allison <jra at samba.org>

commit 5ae58cd0db34d6c406794fa2301df81d835c2ea8
Author: Volker Lendecke <vl at samba.org>
Date:   Thu Nov 21 15:19:16 2019 +0100

    dbwrap: Make dbwrap_lock_order_[un]lock() public
    
    Signed-off-by: Volker Lendecke <vl at samba.org>
    Reviewed-by: Jeremy Allison <jra at samba.org>

commit 38a80a300529719934bba135334506346a7a4a6f
Author: Volker Lendecke <vl at samba.org>
Date:   Thu Nov 21 13:23:39 2019 +0100

    dbwrap: Simplify dbwrap_lock_order_[un]lock()
    
    Directly pass the database name and lock order to the core functions,
    avoid passing struct db_context.
    
    In the next steps these functions will become public: locking.tdb will
    be based on g_lock.c to avoid holding a tdb-level locking.tdb mutex
    while doing complex file system operations like unlink() which can
    take ages on FAT for example.
    
    This means that g_lock.c will participate in the dbwrap lock order
    protection and needs access to dbwrap_lock_order_[un]lock() without
    providing a direct db_context.
    
    Signed-off-by: Volker Lendecke <vl at samba.org>
    Reviewed-by: Jeremy Allison <jra at samba.org>

-----------------------------------------------------------------------

Summary of changes:
 lib/dbwrap/dbwrap.c               |   83 +-
 lib/dbwrap/dbwrap.h               |    5 +
 source3/include/g_lock.h          |   33 +
 source3/lib/dbwrap/dbwrap_open.c  |    3 +-
 source3/lib/g_lock.c              |  451 ++++++++++-
 source3/locking/share_mode_lock.c | 1589 ++++++++++++++++++++-----------------
 source3/selftest/tests.py         |    1 +
 source3/torture/proto.h           |    1 +
 source3/torture/test_g_lock.c     |   76 ++
 source3/torture/torture.c         |    4 +
 10 files changed, 1461 insertions(+), 785 deletions(-)


Changeset truncated at 500 lines:

diff --git a/lib/dbwrap/dbwrap.c b/lib/dbwrap/dbwrap.c
index baab0338088..735ed169690 100644
--- a/lib/dbwrap/dbwrap.c
+++ b/lib/dbwrap/dbwrap.c
@@ -123,79 +123,96 @@ NTSTATUS dbwrap_record_delete(struct db_record *rec)
 	return NT_STATUS_OK;
 }
 
-static void debug_lock_order(int level, struct db_context *dbs[])
+const char *locked_dbs[DBWRAP_LOCK_ORDER_MAX];
+
+static void debug_lock_order(int level)
 {
 	int i;
 	DEBUG(level, ("lock order: "));
 	for (i=0; i<DBWRAP_LOCK_ORDER_MAX; i++) {
-		DEBUGADD(level, (" %d:%s", i + 1, dbs[i] ? dbs[i]->name : "<none>"));
+		DEBUGADD(level,
+			 (" %d:%s",
+			  i + 1,
+			  locked_dbs[i] ? locked_dbs[i] : "<none>"));
 	}
 	DEBUGADD(level, ("\n"));
 }
 
-static void dbwrap_lock_order_lock(struct db_context *db,
-				   struct db_context ***lockptr)
+void dbwrap_lock_order_lock(const char *db_name,
+			    enum dbwrap_lock_order lock_order)
 {
-	static struct db_context *locked_dbs[DBWRAP_LOCK_ORDER_MAX];
 	int idx;
 
-	DBG_INFO("check lock order %d for %s\n", (int)db->lock_order,
-		 db->name);
+	DBG_INFO("check lock order %d for %s\n",
+		 (int)lock_order,
+		 db_name);
 
-	if (!DBWRAP_LOCK_ORDER_VALID(db->lock_order)) {
+	if (!DBWRAP_LOCK_ORDER_VALID(lock_order)) {
 		DBG_ERR("Invalid lock order %d of %s\n",
-			(int)db->lock_order, db->name);
+			lock_order,
+			db_name);
 		smb_panic("lock order violation");
 	}
 
-	for (idx=db->lock_order-1; idx<DBWRAP_LOCK_ORDER_MAX; idx++) {
+	for (idx=lock_order-1; idx<DBWRAP_LOCK_ORDER_MAX; idx++) {
 		if (locked_dbs[idx] != NULL) {
 			DBG_ERR("Lock order violation: Trying %s at %d while "
 				"%s at %d is locked\n",
-				db->name, (int)db->lock_order,
-				locked_dbs[idx]->name, idx + 1);
-			debug_lock_order(0, locked_dbs);
+				db_name,
+				(int)lock_order,
+				locked_dbs[idx],
+				idx + 1);
+			debug_lock_order(0);
 			smb_panic("lock order violation");
 		}
 	}
 
-	locked_dbs[db->lock_order-1] = db;
-	*lockptr = &locked_dbs[db->lock_order-1];
+	locked_dbs[lock_order-1] = db_name;
 
-	debug_lock_order(10, locked_dbs);
+	debug_lock_order(10);
 }
 
-static void dbwrap_lock_order_unlock(struct db_context *db,
-				     struct db_context **lockptr)
+void dbwrap_lock_order_unlock(const char *db_name,
+			      enum dbwrap_lock_order lock_order)
 {
 	DBG_INFO("release lock order %d for %s\n",
-		 (int)db->lock_order, db->name);
+		 (int)lock_order,
+		 db_name);
+
+	if (!DBWRAP_LOCK_ORDER_VALID(lock_order)) {
+		DBG_ERR("Invalid lock order %d of %s\n",
+			lock_order,
+			db_name);
+		smb_panic("lock order violation");
+	}
 
-	if (*lockptr == NULL) {
-		DBG_ERR("db %s at order %d unlocked\n", db->name,
-			(int)db->lock_order);
+	if (locked_dbs[lock_order-1] == NULL) {
+		DBG_ERR("db %s at order %d unlocked\n",
+			db_name,
+			(int)lock_order);
 		smb_panic("lock order violation");
 	}
 
-	if (*lockptr != db) {
+	if (locked_dbs[lock_order-1] != db_name) {
 		DBG_ERR("locked db at lock order %d is %s, expected %s\n",
-			(int)(*lockptr)->lock_order, (*lockptr)->name,
-			db->name);
+			(int)lock_order,
+			locked_dbs[lock_order-1],
+			db_name);
 		smb_panic("lock order violation");
 	}
 
-	*lockptr = NULL;
+	locked_dbs[lock_order-1] = NULL;
 }
 
 struct dbwrap_lock_order_state {
 	struct db_context *db;
-	struct db_context **lockptr;
 };
 
 static int dbwrap_lock_order_state_destructor(
 	struct dbwrap_lock_order_state *s)
 {
-	dbwrap_lock_order_unlock(s->db, s->lockptr);
+	struct db_context *db = s->db;
+	dbwrap_lock_order_unlock(db->name, db->lock_order);
 	return 0;
 }
 
@@ -211,7 +228,7 @@ static struct dbwrap_lock_order_state *dbwrap_check_lock_order(
 	}
 	state->db = db;
 
-	dbwrap_lock_order_lock(db, &state->lockptr);
+	dbwrap_lock_order_lock(db->name, db->lock_order);
 	talloc_set_destructor(state, dbwrap_lock_order_state_destructor);
 
 	return state;
@@ -540,18 +557,16 @@ NTSTATUS dbwrap_do_locked(struct db_context *db, TDB_DATA key,
 	struct db_record *rec;
 
 	if (db->do_locked != NULL) {
-		struct db_context **lockptr = NULL;
 		NTSTATUS status;
 
 		if (db->lock_order != DBWRAP_LOCK_ORDER_NONE) {
-			dbwrap_lock_order_lock(db, &lockptr);
+			dbwrap_lock_order_lock(db->name, db->lock_order);
 		}
 
 		status = db->do_locked(db, key, fn, private_data);
 
-		if (db->lock_order != DBWRAP_LOCK_ORDER_NONE &&
-		    lockptr != NULL) {
-			dbwrap_lock_order_unlock(db, lockptr);
+		if (db->lock_order != DBWRAP_LOCK_ORDER_NONE) {
+			dbwrap_lock_order_unlock(db->name, db->lock_order);
 		}
 
 		return status;
diff --git a/lib/dbwrap/dbwrap.h b/lib/dbwrap/dbwrap.h
index b5a7fb315c7..0069353fae5 100644
--- a/lib/dbwrap/dbwrap.h
+++ b/lib/dbwrap/dbwrap.h
@@ -79,6 +79,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);
 
+void dbwrap_lock_order_lock(const char *db_name,
+			    enum dbwrap_lock_order lock_order);
+void dbwrap_lock_order_unlock(const char *db_name,
+			      enum dbwrap_lock_order lock_order);
+
 NTSTATUS dbwrap_do_locked(struct db_context *db, TDB_DATA key,
 			  void (*fn)(struct db_record *rec,
 				     TDB_DATA value,
diff --git a/source3/include/g_lock.h b/source3/include/g_lock.h
index 54f60e410ba..5892f10fcd6 100644
--- a/source3/include/g_lock.h
+++ b/source3/include/g_lock.h
@@ -36,6 +36,8 @@ struct g_lock_ctx *g_lock_ctx_init_backend(
 	TALLOC_CTX *mem_ctx,
 	struct messaging_context *msg,
 	struct db_context **backend);
+void g_lock_set_lock_order(struct g_lock_ctx *ctx,
+			   enum dbwrap_lock_order lock_order);
 struct g_lock_ctx *g_lock_ctx_init(TALLOC_CTX *mem_ctx,
 				   struct messaging_context *msg);
 
@@ -49,12 +51,30 @@ NTSTATUS g_lock_lock(struct g_lock_ctx *ctx, TDB_DATA key,
 		     enum g_lock_type lock_type, struct timeval timeout);
 NTSTATUS g_lock_unlock(struct g_lock_ctx *ctx, TDB_DATA key);
 
+NTSTATUS g_lock_writev_data(
+	struct g_lock_ctx *ctx,
+	TDB_DATA key,
+	const TDB_DATA *dbufs,
+	size_t num_dbufs);
 NTSTATUS g_lock_write_data(struct g_lock_ctx *ctx, TDB_DATA key,
 			   const uint8_t *buf, size_t buflen);
 
 int g_lock_locks(struct g_lock_ctx *ctx,
 		 int (*fn)(TDB_DATA key, void *private_data),
 		 void *private_data);
+struct tevent_req *g_lock_dump_send(
+	TALLOC_CTX *mem_ctx,
+	struct tevent_context *ev,
+	struct g_lock_ctx *ctx,
+	TDB_DATA key,
+	void (*fn)(struct server_id exclusive,
+		   size_t num_shared,
+		   struct server_id *shared,
+		   const uint8_t *data,
+		   size_t datalen,
+		   void *private_data),
+	void *private_data);
+NTSTATUS g_lock_dump_recv(struct tevent_req *req);
 NTSTATUS g_lock_dump(struct g_lock_ctx *ctx,
 		     TDB_DATA key,
 		     void (*fn)(struct server_id exclusive,
@@ -64,5 +84,18 @@ NTSTATUS g_lock_dump(struct g_lock_ctx *ctx,
 				size_t datalen,
 				void *private_data),
 		     void *private_data);
+int g_lock_seqnum(struct g_lock_ctx *ctx);
+
+struct tevent_req *g_lock_watch_data_send(
+	TALLOC_CTX *mem_ctx,
+	struct tevent_context *ev,
+	struct g_lock_ctx *ctx,
+	TDB_DATA key,
+	struct server_id blocker);
+NTSTATUS g_lock_watch_data_recv(
+	struct tevent_req *req,
+	bool *blockerdead,
+	struct server_id *blocker);
+void g_lock_wake_watchers(struct g_lock_ctx *ctx, TDB_DATA key);
 
 #endif
diff --git a/source3/lib/dbwrap/dbwrap_open.c b/source3/lib/dbwrap/dbwrap_open.c
index eac52c5a431..e67341607a4 100644
--- a/source3/lib/dbwrap/dbwrap_open.c
+++ b/source3/lib/dbwrap/dbwrap_open.c
@@ -67,7 +67,8 @@ struct db_context *db_open(TALLOC_CTX *mem_ctx,
 	const char *base;
 	struct loadparm_context *lp_ctx = NULL;
 
-	if (!DBWRAP_LOCK_ORDER_VALID(lock_order)) {
+	if ((lock_order != DBWRAP_LOCK_ORDER_NONE) &&
+	    !DBWRAP_LOCK_ORDER_VALID(lock_order)) {
 		errno = EINVAL;
 		return NULL;
 	}
diff --git a/source3/lib/g_lock.c b/source3/lib/g_lock.c
index 4bf30188a43..d9843359dd1 100644
--- a/source3/lib/g_lock.c
+++ b/source3/lib/g_lock.c
@@ -36,12 +36,14 @@
 struct g_lock_ctx {
 	struct db_context *db;
 	struct messaging_context *msg;
+	enum dbwrap_lock_order lock_order;
 };
 
 struct g_lock {
 	struct server_id exclusive;
 	size_t num_shared;
 	uint8_t *shared;
+	uint64_t data_seqnum;
 	size_t datalen;
 	uint8_t *data;
 };
@@ -50,9 +52,16 @@ static bool g_lock_parse(uint8_t *buf, size_t buflen, struct g_lock *lck)
 {
 	struct server_id exclusive;
 	size_t num_shared, shared_len;
-
-	if (buflen < (SERVER_ID_BUF_LENGTH + sizeof(uint32_t))) {
-		*lck = (struct g_lock) { .exclusive.pid = 0 };
+	uint64_t data_seqnum;
+
+	if (buflen < (SERVER_ID_BUF_LENGTH + /* exclusive */
+		      sizeof(uint64_t) +     /* seqnum */
+		      sizeof(uint32_t))) {   /* num_shared */
+		struct g_lock ret = { .exclusive.pid = 0 };
+		generate_random_buffer(
+			(uint8_t *)&ret.data_seqnum,
+			sizeof(ret.data_seqnum));
+		*lck = ret;
 		return true;
 	}
 
@@ -60,11 +69,18 @@ static bool g_lock_parse(uint8_t *buf, size_t buflen, struct g_lock *lck)
 	buf += SERVER_ID_BUF_LENGTH;
 	buflen -= SERVER_ID_BUF_LENGTH;
 
+	data_seqnum = BVAL(buf, 0);
+	buf += sizeof(uint64_t);
+	buflen -= sizeof(uint64_t);
+
 	num_shared = IVAL(buf, 0);
 	buf += sizeof(uint32_t);
 	buflen -= sizeof(uint32_t);
 
 	if (num_shared > buflen/SERVER_ID_BUF_LENGTH) {
+		DBG_DEBUG("num_shared=%zu, buflen=%zu\n",
+			  num_shared,
+			  buflen);
 		return false;
 	}
 
@@ -74,6 +90,7 @@ static bool g_lock_parse(uint8_t *buf, size_t buflen, struct g_lock *lck)
 		.exclusive = exclusive,
 		.num_shared = num_shared,
 		.shared = buf,
+		.data_seqnum = data_seqnum,
 		.datalen = buflen-shared_len,
 		.data = buf+shared_len,
 	};
@@ -107,32 +124,54 @@ static void g_lock_del_shared(struct g_lock *lck, size_t i)
 static NTSTATUS g_lock_store(
 	struct db_record *rec,
 	struct g_lock *lck,
-	struct server_id *new_shared)
+	struct server_id *new_shared,
+	const TDB_DATA *new_dbufs,
+	size_t num_new_dbufs)
 {
 	uint8_t exclusive[SERVER_ID_BUF_LENGTH];
+	uint8_t seqnum_buf[sizeof(uint64_t)];
 	uint8_t sizebuf[sizeof(uint32_t)];
-	uint8_t shared[SERVER_ID_BUF_LENGTH];
-
-	struct TDB_DATA dbufs[] = {
-		{ .dptr = exclusive, .dsize = sizeof(exclusive) },
-		{ .dptr = sizebuf, .dsize = sizeof(sizebuf) },
-		{ .dptr = lck->shared,
-		  .dsize = lck->num_shared * SERVER_ID_BUF_LENGTH },
-		{ 0 },
-		{ .dptr = lck->data, .dsize = lck->datalen }
+	uint8_t new_shared_buf[SERVER_ID_BUF_LENGTH];
+
+	struct TDB_DATA dbufs[6 + num_new_dbufs];
+
+	dbufs[0] = (TDB_DATA) {
+		.dptr = exclusive, .dsize = sizeof(exclusive),
+	};
+	dbufs[1] = (TDB_DATA) {
+		.dptr = seqnum_buf, .dsize = sizeof(seqnum_buf),
+	};
+	dbufs[2] = (TDB_DATA) {
+		.dptr = sizebuf, .dsize = sizeof(sizebuf),
+	};
+	dbufs[3] = (TDB_DATA) {
+		.dptr = lck->shared,
+		.dsize = lck->num_shared * SERVER_ID_BUF_LENGTH,
 	};
+	dbufs[4] = (TDB_DATA) { 0 };
+	dbufs[5] = (TDB_DATA) {
+		.dptr = lck->data, .dsize = lck->datalen,
+	};
+
+	if (num_new_dbufs != 0) {
+		memcpy(&dbufs[6],
+		       new_dbufs,
+		       num_new_dbufs * sizeof(TDB_DATA));
+	}
 
 	server_id_put(exclusive, lck->exclusive);
+	SBVAL(seqnum_buf, 0, lck->data_seqnum);
 
 	if (new_shared != NULL) {
 		if (lck->num_shared >= UINT32_MAX) {
 			return NT_STATUS_BUFFER_OVERFLOW;
 		}
 
-		server_id_put(shared, *new_shared);
+		server_id_put(new_shared_buf, *new_shared);
 
-		dbufs[3] = (TDB_DATA) {
-			.dptr = shared, .dsize = sizeof(shared),
+		dbufs[4] = (TDB_DATA) {
+			.dptr = new_shared_buf,
+			.dsize = sizeof(new_shared_buf),
 		};
 
 		lck->num_shared += 1;
@@ -155,6 +194,7 @@ struct g_lock_ctx *g_lock_ctx_init_backend(
 		return NULL;
 	}
 	result->msg = msg;
+	result->lock_order = DBWRAP_LOCK_ORDER_NONE;
 
 	result->db = db_open_watched(result, backend, msg);
 	if (result->db == NULL) {
@@ -165,6 +205,12 @@ struct g_lock_ctx *g_lock_ctx_init_backend(
 	return result;
 }
 
+void g_lock_set_lock_order(struct g_lock_ctx *ctx,
+			   enum dbwrap_lock_order lock_order)
+{
+	ctx->lock_order = lock_order;
+}
+
 struct g_lock_ctx *g_lock_ctx_init(TALLOC_CTX *mem_ctx,
 				   struct messaging_context *msg)
 {
@@ -235,7 +281,7 @@ static NTSTATUS g_lock_cleanup_dead(
 	}
 
 	if (modified) {
-		status = g_lock_store(rec, lck, NULL);
+		status = g_lock_store(rec, lck, NULL, NULL, 0);
 		if (!NT_STATUS_IS_OK(status)) {
 			DBG_DEBUG("g_lock_store() failed: %s\n",
 				  nt_errstr(status));
@@ -454,7 +500,7 @@ noexclusive:
 
 		lck.exclusive = self;
 
-		status = g_lock_store(rec, &lck, NULL);
+		status = g_lock_store(rec, &lck, NULL, NULL, 0);
 		if (!NT_STATUS_IS_OK(status)) {
 			DBG_DEBUG("g_lock_store() failed: %s\n",
 				  nt_errstr(status));
@@ -483,7 +529,7 @@ noexclusive:
 do_shared:
 
 	if (lck.num_shared == 0) {
-		status = g_lock_store(rec, &lck, &self);
+		status = g_lock_store(rec, &lck, &self, NULL, 0);
 		if (!NT_STATUS_IS_OK(status)) {
 			DBG_DEBUG("g_lock_store() failed: %s\n",
 				  nt_errstr(status));
@@ -494,7 +540,7 @@ do_shared:
 
 	g_lock_cleanup_shared(&lck);
 
-	status = g_lock_store(rec, &lck, &self);
+	status = g_lock_store(rec, &lck, &self, NULL, 0);
 	if (!NT_STATUS_IS_OK(status)) {
 		DBG_DEBUG("g_lock_store() failed: %s\n",
 			  nt_errstr(status));
@@ -652,7 +698,23 @@ static void g_lock_lock_retry(struct tevent_req *subreq)
 
 NTSTATUS g_lock_lock_recv(struct tevent_req *req)
 {
-	return tevent_req_simple_recv_ntstatus(req);
+	struct g_lock_lock_state *state = tevent_req_data(
+		req, struct g_lock_lock_state);
+	struct g_lock_ctx *ctx = state->ctx;
+	NTSTATUS status;
+
+	if (tevent_req_is_nterror(req, &status)) {
+		return status;
+	}
+
+	if ((ctx->lock_order != DBWRAP_LOCK_ORDER_NONE) &&
+	    ((state->type == G_LOCK_READ) ||
+	     (state->type == G_LOCK_WRITE))) {
+		const char *name = dbwrap_name(ctx->db);
+		dbwrap_lock_order_lock(name, ctx->lock_order);
+	}
+
+	return NT_STATUS_OK;
 }
 
 struct g_lock_lock_simple_state {
@@ -686,13 +748,13 @@ static void g_lock_lock_simple_fn(
 			goto not_granted;
 		}
 		lck.exclusive = state->me;
-		state->status = g_lock_store(rec, &lck, NULL);
+		state->status = g_lock_store(rec, &lck, NULL, NULL, 0);
 		return;
 	}
 
 	if (state->type == G_LOCK_READ) {
 		g_lock_cleanup_shared(&lck);
-		state->status = g_lock_store(rec, &lck, &state->me);
+		state->status = g_lock_store(rec, &lck, &state->me, NULL, 0);
 		return;
 	}
 
@@ -731,6 +793,10 @@ NTSTATUS g_lock_lock(struct g_lock_ctx *ctx, TDB_DATA key,
 			return status;
 		}
 		if (NT_STATUS_IS_OK(state.status)) {
+			if (ctx->lock_order != DBWRAP_LOCK_ORDER_NONE) {
+				const char *name = dbwrap_name(ctx->db);
+				dbwrap_lock_order_lock(name, ctx->lock_order);
+			}
 			return NT_STATUS_OK;
 		}
 		if (!NT_STATUS_EQUAL(
@@ -829,7 +895,7 @@ static void g_lock_unlock_fn(
 		return;
 	}
 


-- 
Samba Shared Repository



More information about the samba-cvs mailing list