Patchset: Improve nbench performance

Volker Lendecke Volker.Lendecke at SerNet.DE
Sat Dec 14 01:24:19 MST 2013


Hi!

Amitay Isaacs pointed out that we regressed on netbench
performance 3.6 against 4.0, so I did some work on it. This
patchset gets back some of the performance we had, not all.
In 4.0 and above we have two big additional features that
slow us down in the metadata-heavy netbench test: Durable
file handles and much improved acl checking. Reading and
translating an acl on every open costs, as does maintaining
the open state in a separate tdb. This patchset does not fix
those, but it cuts down user-space CPU usage in netbench
according to callgrind by something around 15%. In
particular on slow CPUs this will definitely matter, and
even on a beefy server this is equally visible by netbench
results.

Please review & push!

Thanks,

Volker

-- 
SerNet GmbH, Bahnhofsallee 1b, 37081 Göttingen
phone: +49-551-370000-0, fax: +49-551-370000-9
AG Göttingen, HRB 2816, GF: Dr. Johannes Loxen
http://www.sernet.de, mailto:kontakt at sernet.de
-------------- next part --------------
>From 077353eac910ffe45110c6e5db37c42bcfa7b86b Mon Sep 17 00:00:00 2001
From: Volker Lendecke <vl at samba.org>
Date: Fri, 6 Dec 2013 10:31:07 +0000
Subject: [PATCH 01/10] iconv: Use a static buffer in iconf not to spoil the
 talloc_pool

This is a buffer that is strictly used like a stack variable. This
patch makes it one and while there it fixes an error path memleak.
In the "pull_failed" case we did not talloc_free(cvtbuf). With
talloc_tos(), this does not really matter, but for code without
this it does.

Signed-off-by: Volker Lendecke <vl at samba.org>
---
 lib/util/charset/iconv.c |   16 +---------------
 1 file changed, 1 insertion(+), 15 deletions(-)

diff --git a/lib/util/charset/iconv.c b/lib/util/charset/iconv.c
index 1c507b4..c5b45fe 100644
--- a/lib/util/charset/iconv.c
+++ b/lib/util/charset/iconv.c
@@ -127,20 +127,8 @@ _PUBLIC_ size_t smb_iconv(smb_iconv_t cd,
 #ifndef SMB_ICONV_BUFSIZE
 #define SMB_ICONV_BUFSIZE 2048
 #endif
-		TALLOC_CTX *mem_ctx;
 		size_t bufsize;
-		char *cvtbuf;
-
-#if _SAMBA_BUILD_ == 3
-		mem_ctx = talloc_tos();
-#else
-		mem_ctx = cd;
-#endif
-		cvtbuf = talloc_array(mem_ctx, char, SMB_ICONV_BUFSIZE);
-
-		if (!cvtbuf) {
-			return (size_t)-1;
-		}
+		char cvtbuf[SMB_ICONV_BUFSIZE];
 
 		while (*inbytesleft > 0) {
 			char *bufp1 = cvtbuf;
@@ -161,7 +149,6 @@ _PUBLIC_ size_t smb_iconv(smb_iconv_t cd,
 			if (cd->push(cd->cd_push,
 				     &bufp2, &bufsize,
 				     outbuf, outbytesleft) == -1) {
-				talloc_free(cvtbuf);
 				return -1;
 			} else if (pull_failed) {
 				/* We want the pull errno if possible */
@@ -169,7 +156,6 @@ _PUBLIC_ size_t smb_iconv(smb_iconv_t cd,
 				return -1;
 			}
 		}
-		talloc_free(cvtbuf);
 	}
 
 	return 0;
-- 
1.7.9.5


>From f7c526964c217fa9a5bfae7c2180ae7ac2d75c22 Mon Sep 17 00:00:00 2001
From: Volker Lendecke <vl at samba.org>
Date: Fri, 6 Dec 2013 11:38:12 +0000
Subject: [PATCH 02/10] dbwrap: Avoid a stackframe in fetch_locked_internal

This shows in profiles. We call this so often that this is a pretty
hot code path.

Signed-off-by: Volker Lendecke <vl at samba.org>
---
 lib/dbwrap/dbwrap.c |    7 ++-----
 1 file changed, 2 insertions(+), 5 deletions(-)

diff --git a/lib/dbwrap/dbwrap.c b/lib/dbwrap/dbwrap.c
index 44e20bc..2c633cf 100644
--- a/lib/dbwrap/dbwrap.c
+++ b/lib/dbwrap/dbwrap.c
@@ -220,21 +220,18 @@ static struct db_record *dbwrap_fetch_locked_internal(
 {
 	struct db_record *rec;
 	struct dbwrap_lock_order_state *lock_order;
-	TALLOC_CTX *frame = talloc_stackframe();
 
-	lock_order = dbwrap_check_lock_order(db, frame);
+	lock_order = dbwrap_check_lock_order(db, mem_ctx);
 	if (lock_order == NULL) {
-		TALLOC_FREE(frame);
 		return NULL;
 	}
 	rec = db_fn(db, mem_ctx, key);
 	if (rec == NULL) {
-		TALLOC_FREE(frame);
+		TALLOC_FREE(lock_order);
 		return NULL;
 	}
 	(void)talloc_steal(rec, lock_order);
 	rec->db = db;
-	TALLOC_FREE(frame);
 	return rec;
 }
 
-- 
1.7.9.5


>From e8acffc6a98c1eb41d411f0efca5141f02bdae89 Mon Sep 17 00:00:00 2001
From: Volker Lendecke <vl at samba.org>
Date: Fri, 6 Dec 2013 07:40:03 +0000
Subject: [PATCH 03/10] smbd: Simplify get_share_mode_lock a bit

This does two things: It gets rid of a talloc_stackframe in a hot
code path and to me it makes the code easier to understand. It makes
the talloc hierarchy more obvious to follow.

Signed-off-by: Volker Lendecke <vl at samba.org>
---
 source3/locking/share_mode_lock.c |   27 +++++++++++++--------------
 1 file changed, 13 insertions(+), 14 deletions(-)

diff --git a/source3/locking/share_mode_lock.c b/source3/locking/share_mode_lock.c
index 5d7a08c..940d125 100644
--- a/source3/locking/share_mode_lock.c
+++ b/source3/locking/share_mode_lock.c
@@ -369,36 +369,35 @@ struct share_mode_lock *get_share_mode_lock(
 	const struct smb_filename *smb_fname,
 	const struct timespec *old_write_time)
 {
-	TALLOC_CTX *frame = talloc_stackframe();
-
 	struct share_mode_lock *lck;
 
+	lck = talloc(mem_ctx, struct share_mode_lock);
+	if (lck == NULL) {
+		DEBUG(1, ("talloc failed\n"));
+		return NULL;
+	}
+
 	if (the_lock == NULL) {
 		the_lock = get_share_mode_lock_internal(
-			frame, id, servicepath, smb_fname, old_write_time);
+			lck, id, servicepath, smb_fname, old_write_time);
 		if (the_lock == NULL) {
 			goto fail;
 		}
 		talloc_set_destructor(the_lock, the_lock_destructor);
+	} else {
+		if (talloc_reference(lck, the_lock) == NULL) {
+			DEBUG(1, ("talloc_reference failed\n"));
+			goto fail;
+		}
 	}
 	if (!file_id_equal(&the_lock->data->id, &id)) {
 		DEBUG(1, ("Can not lock two share modes simultaneously\n"));
 		goto fail;
 	}
-	lck = talloc(mem_ctx, struct share_mode_lock);
-	if (lck == NULL) {
-		DEBUG(1, ("talloc failed\n"));
-		goto fail;
-	}
-	if (talloc_reference(lck, the_lock) == NULL) {
-		DEBUG(1, ("talloc_reference failed\n"));
-		goto fail;
-	}
 	lck->data = the_lock->data;
-	TALLOC_FREE(frame);
 	return lck;
 fail:
-	TALLOC_FREE(frame);
+	TALLOC_FREE(lck);
 	return NULL;
 }
 
-- 
1.7.9.5


>From 943f6c896da218fc410a582330cfeeb4f381cff3 Mon Sep 17 00:00:00 2001
From: Volker Lendecke <vl at samba.org>
Date: Sat, 7 Dec 2013 12:58:07 +0000
Subject: [PATCH 04/10] dbwrap_cache: Fix dbwrap_cache_validate

Classic brown paper bag bug :-(

Signed-off-by: Volker Lendecke <vl at samba.org>
---
 lib/dbwrap/dbwrap_cache.c |   16 ++++++++++++++--
 1 file changed, 14 insertions(+), 2 deletions(-)

diff --git a/lib/dbwrap/dbwrap_cache.c b/lib/dbwrap/dbwrap_cache.c
index d97242e..6c6b795 100644
--- a/lib/dbwrap/dbwrap_cache.c
+++ b/lib/dbwrap/dbwrap_cache.c
@@ -32,15 +32,27 @@ struct db_cache_ctx {
 
 static bool dbwrap_cache_validate(struct db_cache_ctx *ctx)
 {
-	if (ctx->seqnum == dbwrap_get_seqnum(ctx->backing)) {
+	int backing_seqnum;
+
+	backing_seqnum = dbwrap_get_seqnum(ctx->backing);
+	if (backing_seqnum == ctx->seqnum) {
 		return true;
 	}
+
 	TALLOC_FREE(ctx->positive);
 	ctx->positive = db_open_rbt(ctx);
+	if (ctx->positive == NULL) {
+		return false;
+	}
+
 	TALLOC_FREE(ctx->negative);
 	ctx->negative = db_open_rbt(ctx);
+	if (ctx->negative == NULL) {
+		return false;
+	}
 
-	return ((ctx->positive != NULL) && (ctx->negative != NULL));
+	ctx->seqnum = backing_seqnum;
+	return true;
 }
 
 static NTSTATUS dbwrap_cache_parse_record(
-- 
1.7.9.5


>From 1aad2e0c1a61b28576af8fef0204cd27aebbe524 Mon Sep 17 00:00:00 2001
From: Volker Lendecke <vl at samba.org>
Date: Sat, 7 Dec 2013 12:58:43 +0000
Subject: [PATCH 05/10] dbwrap_cache: Check negative first

dbwrap_cache is right now used for notify most, and we hope to have very
few notifies around. So negative hits will be more likely than positive

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

diff --git a/lib/dbwrap/dbwrap_cache.c b/lib/dbwrap/dbwrap_cache.c
index 6c6b795..c5f7cce 100644
--- a/lib/dbwrap/dbwrap_cache.c
+++ b/lib/dbwrap/dbwrap_cache.c
@@ -69,13 +69,13 @@ static NTSTATUS dbwrap_cache_parse_record(
 		return NT_STATUS_NO_MEMORY;
 	}
 
+	if (dbwrap_exists(ctx->negative, key)) {
+		return NT_STATUS_NOT_FOUND;
+	}
 	status = dbwrap_parse_record(ctx->positive, key, parser, private_data);
 	if (NT_STATUS_IS_OK(status)) {
 		return status;
 	}
-	if (dbwrap_exists(ctx->negative, key)) {
-		return NT_STATUS_NOT_FOUND;
-	}
 
 	status = dbwrap_fetch(ctx->backing, talloc_tos(), key, &value);
 
-- 
1.7.9.5


>From 51deca91a4f4863a8d5ea14ee3835aa5d5333fe4 Mon Sep 17 00:00:00 2001
From: Volker Lendecke <vl at samba.org>
Date: Fri, 6 Dec 2013 11:57:42 +0000
Subject: [PATCH 06/10] dbwrap: No lock_order check if not required

Signed-off-by: Volker Lendecke <vl at samba.org>
---
 lib/dbwrap/dbwrap.c |   19 ++++++-------------
 1 file changed, 6 insertions(+), 13 deletions(-)

diff --git a/lib/dbwrap/dbwrap.c b/lib/dbwrap/dbwrap.c
index 2c633cf..8270b63 100644
--- a/lib/dbwrap/dbwrap.c
+++ b/lib/dbwrap/dbwrap.c
@@ -167,15 +167,6 @@ static struct dbwrap_lock_order_state *dbwrap_check_lock_order(
 	static struct db_context *locked_dbs[DBWRAP_LOCK_ORDER_MAX];
 	struct dbwrap_lock_order_state *state = NULL;
 
-	if (db->lock_order == 0) {
-		/*
-		 * lock order 0 is for example for dbwrap_rbt without
-		 * real locking. Return state nevertheless to avoid
-		 * special cases.
-		 */
-		return talloc_zero(mem_ctx, struct dbwrap_lock_order_state);
-	}
-
 	if (db->lock_order > DBWRAP_LOCK_ORDER_MAX) {
 		DEBUG(0,("Invalid lock order %d of %s\n",
 			 (int)db->lock_order, db->name));
@@ -219,11 +210,13 @@ static struct db_record *dbwrap_fetch_locked_internal(
 				   TDB_DATA key))
 {
 	struct db_record *rec;
-	struct dbwrap_lock_order_state *lock_order;
+	struct dbwrap_lock_order_state *lock_order = NULL;
 
-	lock_order = dbwrap_check_lock_order(db, mem_ctx);
-	if (lock_order == NULL) {
-		return NULL;
+	if (db->lock_order != 0) {
+		lock_order = dbwrap_check_lock_order(db, mem_ctx);
+		if (lock_order == NULL) {
+			return NULL;
+		}
 	}
 	rec = db_fn(db, mem_ctx, key);
 	if (rec == NULL) {
-- 
1.7.9.5


>From a1cc70c73f40c721f8bad85f6645fd9281e1d82f Mon Sep 17 00:00:00 2001
From: Volker Lendecke <vl at samba.org>
Date: Fri, 6 Dec 2013 12:10:37 +0000
Subject: [PATCH 07/10] smbd: Avoid pointless strcsequal calls

Signed-off-by: Volker Lendecke <vl at samba.org>
---
 source3/smbd/vfs.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/source3/smbd/vfs.c b/source3/smbd/vfs.c
index a8e181a..44690c2 100644
--- a/source3/smbd/vfs.c
+++ b/source3/smbd/vfs.c
@@ -828,7 +828,7 @@ int vfs_ChDir(connection_struct *conn, const char *path)
 		LastDir = SMB_STRDUP("");
 	}
 
-	if (strcsequal(path,".")) {
+	if (ISDOT(path)) {
 		return 0;
 	}
 
-- 
1.7.9.5


>From d6f56188e600f327c2b32d6b2f6ca908319be074 Mon Sep 17 00:00:00 2001
From: Volker Lendecke <vl at samba.org>
Date: Fri, 6 Dec 2013 14:34:05 +0000
Subject: [PATCH 08/10] smbd: Implement and use full_path_tos

Yes, this looks like a hack, but talloc_asprintf does show up high in
profiles called from these routines

Signed-off-by: Volker Lendecke <vl at samba.org>
---
 source3/smbd/files.c  |   58 +++++++++++++++++++++++++++++++++++++++++--------
 source3/smbd/notify.c |   14 +++++++-----
 source3/smbd/proto.h  |    3 +++
 3 files changed, 60 insertions(+), 15 deletions(-)

diff --git a/source3/smbd/files.c b/source3/smbd/files.c
index c64c841..ba24eda 100644
--- a/source3/smbd/files.c
+++ b/source3/smbd/files.c
@@ -688,6 +688,45 @@ NTSTATUS dup_file_fsp(struct smb_request *req, files_struct *from,
 	return fsp_set_smb_fname(to, from->fsp_name);
 }
 
+/*
+ * This routine improves performance for operations temporarily acting on a
+ * full path. It is equivalent to the much more expensive
+ *
+ * talloc_asprintf(talloc_tos(), "%s/%s", dir, name)
+ *
+ * This actually does make a difference in metadata-heavy workloads (i.e. the
+ * "standard" client.txt nbench run.
+ */
+
+ssize_t full_path_tos(const char *dir, const char *name,
+		      char *tmpbuf, size_t tmpbuf_len,
+		      char **pdst, char **to_free)
+{
+	size_t dirlen, namelen, len;
+	char *dst;
+
+	dirlen = strlen(dir);
+	namelen = strlen(name);
+	len = dirlen + namelen + 1;
+
+	if (len < tmpbuf_len) {
+		dst = tmpbuf;
+		*to_free = NULL;
+	} else {
+		dst = talloc_array(talloc_tos(), char, len+1);
+		if (dst == NULL) {
+			return -1;
+		}
+		*to_free = dst;
+	}
+
+	memcpy(dst, dir, dirlen);
+	dst[dirlen] = '/';
+	memcpy(dst+dirlen+1, name, namelen+1);
+	*pdst = dst;
+	return len;
+}
+
 /**
  * Return a jenkins hash of a pathname on a connection.
  */
@@ -695,23 +734,24 @@ NTSTATUS dup_file_fsp(struct smb_request *req, files_struct *from,
 NTSTATUS file_name_hash(connection_struct *conn,
 			const char *name, uint32_t *p_name_hash)
 {
-	char *fullpath = NULL;
+	char tmpbuf[1024];
+	char *fullpath, *to_free;
+	size_t len;
 
 	/* Set the hash of the full pathname. */
-	fullpath = talloc_asprintf(talloc_tos(),
-			"%s/%s",
-			conn->connectpath,
-			name);
-	if (!fullpath) {
+
+	len = full_path_tos(conn->connectpath, name, tmpbuf, sizeof(tmpbuf),
+			    &fullpath, &to_free);
+	if (len == -1) {
 		return NT_STATUS_NO_MEMORY;
 	}
-	*p_name_hash = hash(fullpath, talloc_get_size(fullpath), 0);
+	*p_name_hash = hash(fullpath, len+1, 0);
 
 	DEBUG(10,("file_name_hash: %s hash 0x%x\n",
-		fullpath,
+		  fullpath,
 		(unsigned int)*p_name_hash ));
 
-	TALLOC_FREE(fullpath);
+	TALLOC_FREE(to_free);
 	return NT_STATUS_OK;
 }
 
diff --git a/source3/smbd/notify.c b/source3/smbd/notify.c
index 4842d6f..078bc99 100644
--- a/source3/smbd/notify.c
+++ b/source3/smbd/notify.c
@@ -418,19 +418,21 @@ void notify_fname(connection_struct *conn, uint32 action, uint32 filter,
 		  const char *path)
 {
 	struct notify_context *notify_ctx = conn->sconn->notify_ctx;
-	char *fullpath;
+	char *fullpath, *to_free;
+	char tmpbuf[1024];
+	ssize_t len;
 
 	if (path[0] == '.' && path[1] == '/') {
 		path += 2;
 	}
-	fullpath = talloc_asprintf(talloc_tos(), "%s/%s", conn->connectpath,
-				   path);
-	if (fullpath == NULL) {
-		DEBUG(0, ("asprintf failed\n"));
+	len = full_path_tos(conn->connectpath, path, tmpbuf, sizeof(tmpbuf),
+			    &fullpath, &to_free);
+	if (len == -1) {
+		DEBUG(0, ("full_path_tos failed\n"));
 		return;
 	}
 	notify_trigger(notify_ctx, action, filter, fullpath);
-	TALLOC_FREE(fullpath);
+	TALLOC_FREE(to_free);
 }
 
 static void notify_fsp(files_struct *fsp, uint32 action, const char *name)
diff --git a/source3/smbd/proto.h b/source3/smbd/proto.h
index a550dd7..36012e6 100644
--- a/source3/smbd/proto.h
+++ b/source3/smbd/proto.h
@@ -397,6 +397,9 @@ NTSTATUS file_name_hash(connection_struct *conn,
 			const char *name, uint32_t *p_name_hash);
 NTSTATUS fsp_set_smb_fname(struct files_struct *fsp,
 			   const struct smb_filename *smb_fname_in);
+ssize_t full_path_tos(const char *dir, const char *name,
+		      char *tmpbuf, size_t tmpbuf_len,
+		      char **pdst, char **to_free);
 
 /* The following definitions come from smbd/ipc.c  */
 
-- 
1.7.9.5


>From 072180012ad2cfa31f8706668cdc42b967056908 Mon Sep 17 00:00:00 2001
From: Volker Lendecke <vl at samba.org>
Date: Fri, 6 Dec 2013 10:31:22 +0000
Subject: [PATCH 09/10] smbd: Early exit

Yes, this also showed up in profiles

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

diff --git a/source3/locking/brlock.c b/source3/locking/brlock.c
index e92a2cf..c51d66b 100644
--- a/source3/locking/brlock.c
+++ b/source3/locking/brlock.c
@@ -1699,10 +1699,16 @@ static bool validate_lock_entries(TALLOC_CTX *mem_ctx,
 	unsigned int i;
 	unsigned int num_valid_entries = 0;
 	struct lock_struct *locks = *pplocks;
-	TALLOC_CTX *frame = talloc_stackframe();
+	TALLOC_CTX *frame;
 	struct server_id *ids;
 	bool *exists;
 
+	if (*pnum_entries == 0) {
+		return true;
+	}
+
+	frame = talloc_stackframe();
+
 	ids = talloc_array(frame, struct server_id, *pnum_entries);
 	if (ids == NULL) {
 		DEBUG(0, ("validate_lock_entries: "
-- 
1.7.9.5


>From 9c20b1ddb4c359cb799c89c3c282fd39788b5aad Mon Sep 17 00:00:00 2001
From: Volker Lendecke <vl at samba.org>
Date: Mon, 9 Dec 2013 09:56:33 +0000
Subject: [PATCH 10/10] tdb: Avoid reallocs for lockrecs

In normal operations we have at most 3 entries in this array. Don't
bother with shrinking.

Signed-off-by: Volker Lendecke <vl at samba.org>
---
 lib/tdb/common/lock.c        |   32 +++++++++++++++-----------------
 lib/tdb/common/open.c        |    1 +
 lib/tdb/common/tdb_private.h |    1 +
 3 files changed, 17 insertions(+), 17 deletions(-)

diff --git a/lib/tdb/common/lock.c b/lib/tdb/common/lock.c
index 4dfefd5..486de79 100644
--- a/lib/tdb/common/lock.c
+++ b/lib/tdb/common/lock.c
@@ -297,14 +297,17 @@ int tdb_nest_lock(struct tdb_context *tdb, uint32_t offset, int ltype,
 		return 0;
 	}
 
-	new_lck = (struct tdb_lock_type *)realloc(
-		tdb->lockrecs,
-		sizeof(*tdb->lockrecs) * (tdb->num_lockrecs+1));
-	if (new_lck == NULL) {
-		errno = ENOMEM;
-		return -1;
+	if (tdb->num_lockrecs == tdb->lockrecs_array_length) {
+		new_lck = (struct tdb_lock_type *)realloc(
+			tdb->lockrecs,
+			sizeof(*tdb->lockrecs) * (tdb->num_lockrecs+1));
+		if (new_lck == NULL) {
+			errno = ENOMEM;
+			return -1;
+		}
+		tdb->lockrecs_array_length = tdb->num_lockrecs+1;
+		tdb->lockrecs = new_lck;
 	}
-	tdb->lockrecs = new_lck;
 
 	/* Since fcntl locks don't nest, we do a lock for the first one,
 	   and simply bump the count for future ones */
@@ -312,9 +315,11 @@ int tdb_nest_lock(struct tdb_context *tdb, uint32_t offset, int ltype,
 		return -1;
 	}
 
-	tdb->lockrecs[tdb->num_lockrecs].off = offset;
-	tdb->lockrecs[tdb->num_lockrecs].count = 1;
-	tdb->lockrecs[tdb->num_lockrecs].ltype = ltype;
+	new_lck = &tdb->lockrecs[tdb->num_lockrecs];
+
+	new_lck->off = offset;
+	new_lck->count = 1;
+	new_lck->ltype = ltype;
 	tdb->num_lockrecs++;
 
 	return 0;
@@ -481,10 +486,6 @@ int tdb_nest_unlock(struct tdb_context *tdb, uint32_t offset, int ltype,
 	 * a completely idle tdb we should get rid of the locked array.
 	 */
 
-	if (tdb->num_lockrecs == 0) {
-		SAFE_FREE(tdb->lockrecs);
-	}
-
 	if (ret)
 		TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_unlock: An error occurred unlocking!\n"));
 	return ret;
@@ -894,9 +895,6 @@ void tdb_release_transaction_locks(struct tdb_context *tdb)
 		}
 	}
 	tdb->num_lockrecs = active;
-	if (tdb->num_lockrecs == 0) {
-		SAFE_FREE(tdb->lockrecs);
-	}
 }
 
 /* Following functions are added specifically to support CTDB. */
diff --git a/lib/tdb/common/open.c b/lib/tdb/common/open.c
index 05d7cae..6ff37ca 100644
--- a/lib/tdb/common/open.c
+++ b/lib/tdb/common/open.c
@@ -629,6 +629,7 @@ static int tdb_reopen_internal(struct tdb_context *tdb, bool active_lock)
 	/* We may still think we hold the active lock. */
 	tdb->num_lockrecs = 0;
 	SAFE_FREE(tdb->lockrecs);
+	tdb->lockrecs_array_length = 0;
 
 	if (active_lock && tdb_nest_lock(tdb, ACTIVE_LOCK, F_RDLCK, TDB_LOCK_WAIT) == -1) {
 		TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_reopen: failed to obtain active lock\n"));
diff --git a/lib/tdb/common/tdb_private.h b/lib/tdb/common/tdb_private.h
index ce92188..7227b43 100644
--- a/lib/tdb/common/tdb_private.h
+++ b/lib/tdb/common/tdb_private.h
@@ -197,6 +197,7 @@ struct tdb_context {
 	struct tdb_lock_type allrecord_lock; /* .offset == upgradable */
 	int num_lockrecs;
 	struct tdb_lock_type *lockrecs; /* only real locks, all with count>0 */
+	int lockrecs_array_length;
 	enum TDB_ERROR ecode; /* error code for last tdb error */
 	uint32_t hash_size;
 	uint32_t flags; /* the flags passed to tdb_open */
-- 
1.7.9.5



More information about the samba-technical mailing list