PATCHSET: Speed up tdb a bit

Michael Adam obnox at samba.org
Tue Mar 18 05:11:35 MDT 2014


A heads up:
I am currently reviewing this patchset.

Cheers - Michael

On 2014-03-18 at 09:30 +0100, Volker Lendecke wrote:
> On Tue, Mar 18, 2014 at 08:41:58AM +0100, Volker Lendecke wrote:
> > On Tue, Mar 18, 2014 at 08:36:36AM +0100, Volker Lendecke wrote:
> > > Hi!
> > > 
> > > Attached find a patchset resulting from a large-scale
> > > benchmark.
> > > 
> > > Review would be appreciated.
> > 
> > ARGL!
> > 
> > For more than an hour, tdbtorture went fine with this
> > patchset. But in the very moment when I hit "send" it failed
> > :-(
> > 
> > Will re-send something later.
> 
> Here it is. The bug was a missed hunk when reshuffling the
> patches for presentation. "last_ptr = rec_ptr;" was missing
> in the 'tdb: Add "last_ptr" to tdb_find_dead' patch.
> 
> 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

> From 10c4bdc19dae257f1b1d8f2e89cbe2908752de0f Mon Sep 17 00:00:00 2001
> From: Volker Lendecke <vl at samba.org>
> Date: Sun, 16 Mar 2014 20:08:32 +0000
> Subject: [PATCH 1/8] tdb: Fix a tdb corruption
> 
> tdb_purge_dead can change the next pointer of "rec" if we purge the record
> right behind the current record to be deleted. Just overwrite the magic,
> not the whole record with stale data.
> 
> Signed-off-by: Volker Lendecke <vl at samba.org>
> ---
>  lib/tdb/common/tdb.c |    7 +++++--
>  1 file changed, 5 insertions(+), 2 deletions(-)
> 
> diff --git a/lib/tdb/common/tdb.c b/lib/tdb/common/tdb.c
> index 1e41e84..3aabcfa 100644
> --- a/lib/tdb/common/tdb.c
> +++ b/lib/tdb/common/tdb.c
> @@ -394,6 +394,8 @@ static int tdb_delete_hash(struct tdb_context *tdb, TDB_DATA key, uint32_t hash)
>  
>  	if (tdb->max_dead_records != 0) {
>  
> +		uint32_t magic = TDB_DEAD_MAGIC;
> +
>  		/*
>  		 * Allow for some dead records per hash chain, mainly for
>  		 * tdb's with a very high create/delete rate like locking.tdb.
> @@ -410,8 +412,9 @@ static int tdb_delete_hash(struct tdb_context *tdb, TDB_DATA key, uint32_t hash)
>  		/*
>  		 * Just mark the record as dead.
>  		 */
> -		rec.magic = TDB_DEAD_MAGIC;
> -		ret = tdb_rec_write(tdb, rec_ptr, &rec);
> +		ret = tdb_ofs_write(
> +			tdb, rec_ptr + offsetof(struct tdb_record, magic),
> +			&magic);
>  	}
>  	else {
>  		ret = tdb_do_delete(tdb, rec_ptr, &rec);
> -- 
> 1.7.9.5
> 
> 
> From 44c6bcf17a76107ddb9c390e3d2b9eec05a3f688 Mon Sep 17 00:00:00 2001
> From: Volker Lendecke <vl at samba.org>
> Date: Mon, 17 Mar 2014 06:47:11 +0100
> Subject: [PATCH 2/8] tdb: Don't purge records to a blocked freelist
> 
> If the freelist is heavily contended, we should avoid accessing it
> 
> Signed-off-by: Volker Lendecke <vl at samba.org>
> ---
>  lib/tdb/common/tdb.c |    5 ++++-
>  1 file changed, 4 insertions(+), 1 deletion(-)
> 
> diff --git a/lib/tdb/common/tdb.c b/lib/tdb/common/tdb.c
> index 3aabcfa..634a552 100644
> --- a/lib/tdb/common/tdb.c
> +++ b/lib/tdb/common/tdb.c
> @@ -351,7 +351,10 @@ static int tdb_purge_dead(struct tdb_context *tdb, uint32_t hash)
>  	struct tdb_record rec;
>  	tdb_off_t rec_ptr;
>  
> -	if (tdb_lock(tdb, -1, F_WRLCK) == -1) {
> +	if (tdb_lock_nonblock(tdb, -1, F_WRLCK) == -1) {
> +		/*
> +		 * Don't block the freelist if not strictly necessary
> +		 */
>  		return -1;
>  	}
>  
> -- 
> 1.7.9.5
> 
> 
> From 15d77dd886154def44492a6a163ed7f3888fb1c3 Mon Sep 17 00:00:00 2001
> From: Volker Lendecke <vl at samba.org>
> Date: Tue, 18 Mar 2014 07:46:38 +0100
> Subject: [PATCH 3/8] tdb: Do a best fit search for dead records
> 
> Hash chains are (or can be made) short enough that a full search for the
> best-fitting dead record is feasible. The freelist can become much longer,
> there we don't do the full search but accept record which are too large.
> 
> Signed-off-by: Volker Lendecke <vl at samba.org>
> ---
>  lib/tdb/common/tdb.c |   20 +++++++++++++-------
>  1 file changed, 13 insertions(+), 7 deletions(-)
> 
> diff --git a/lib/tdb/common/tdb.c b/lib/tdb/common/tdb.c
> index 634a552..8242d2b 100644
> --- a/lib/tdb/common/tdb.c
> +++ b/lib/tdb/common/tdb.c
> @@ -449,6 +449,8 @@ static tdb_off_t tdb_find_dead(struct tdb_context *tdb, uint32_t hash,
>  			       struct tdb_record *r, tdb_len_t length)
>  {
>  	tdb_off_t rec_ptr;
> +	tdb_off_t best_rec_ptr = 0;
> +	struct tdb_record best = { .rec_len = UINT32_MAX };
>  
>  	/* read in the hash top */
>  	if (tdb_ofs_read(tdb, TDB_HASH_TOP(hash), &rec_ptr) == -1)
> @@ -459,16 +461,20 @@ static tdb_off_t tdb_find_dead(struct tdb_context *tdb, uint32_t hash,
>  		if (tdb_rec_read(tdb, rec_ptr, r) == -1)
>  			return 0;
>  
> -		if (TDB_DEAD(r) && r->rec_len >= length) {
> -			/*
> -			 * First fit for simple coding, TODO: change to best
> -			 * fit
> -			 */
> -			return rec_ptr;
> +		if (TDB_DEAD(r) && (r->rec_len >= length) &&
> +		    (r->rec_len < best.rec_len)) {
> +			best_rec_ptr = rec_ptr;
> +			best = *r;
>  		}
>  		rec_ptr = r->next;
>  	}
> -	return 0;
> +
> +	if (best.rec_len == UINT32_MAX) {
> +		return 0;
> +	}
> +
> +	*r = best;
> +	return best_rec_ptr;
>  }
>  
>  static int _tdb_store(struct tdb_context *tdb, TDB_DATA key,
> -- 
> 1.7.9.5
> 
> 
> From a4e3e2fe057b5637e390cad54102c40cfac79969 Mon Sep 17 00:00:00 2001
> From: Volker Lendecke <vl at samba.org>
> Date: Tue, 18 Mar 2014 07:52:59 +0100
> Subject: [PATCH 4/8] tdb: Move adding tailer space to tdb_find_dead
> 
> This aligns the tdb_find_dead API with the tdb_allocate API and thus makes it a
> bit easier to understand, at least for me.
> 
> Signed-off-by: Volker Lendecke <vl at samba.org>
> ---
>  lib/tdb/common/tdb.c |    7 ++++---
>  1 file changed, 4 insertions(+), 3 deletions(-)
> 
> diff --git a/lib/tdb/common/tdb.c b/lib/tdb/common/tdb.c
> index 8242d2b..742680a 100644
> --- a/lib/tdb/common/tdb.c
> +++ b/lib/tdb/common/tdb.c
> @@ -452,6 +452,8 @@ static tdb_off_t tdb_find_dead(struct tdb_context *tdb, uint32_t hash,
>  	tdb_off_t best_rec_ptr = 0;
>  	struct tdb_record best = { .rec_len = UINT32_MAX };
>  
> +	length += sizeof(tdb_off_t); /* tailer */
> +
>  	/* read in the hash top */
>  	if (tdb_ofs_read(tdb, TDB_HASH_TOP(hash), &rec_ptr) == -1)
>  		return 0;
> @@ -518,9 +520,8 @@ static int _tdb_store(struct tdb_context *tdb, TDB_DATA key,
>  		 * for key, data and tailer. If we find one, we don't have to
>  		 * consult the central freelist.
>  		 */
> -		rec_ptr = tdb_find_dead(
> -			tdb, hash, &rec,
> -			key.dsize + dbuf.dsize + sizeof(tdb_off_t));
> +		rec_ptr = tdb_find_dead(tdb, hash, &rec,
> +					key.dsize + dbuf.dsize);
>  
>  		if (rec_ptr != 0) {
>  			rec.key_len = key.dsize;
> -- 
> 1.7.9.5
> 
> 
> From 32d7555c8d8af4dfd7d79d78f4d50a9111cc6b3b Mon Sep 17 00:00:00 2001
> From: Volker Lendecke <vl at samba.org>
> Date: Tue, 18 Mar 2014 08:00:45 +0100
> Subject: [PATCH 5/8] tdb: Add "last_ptr" to tdb_find_dead
> 
> Will be used soon to unlink a dead record from a chain
> 
> Signed-off-by: Volker Lendecke <vl at samba.org>
> ---
>  lib/tdb/common/tdb.c |   17 +++++++++++++----
>  1 file changed, 13 insertions(+), 4 deletions(-)
> 
> diff --git a/lib/tdb/common/tdb.c b/lib/tdb/common/tdb.c
> index 742680a..b71be98 100644
> --- a/lib/tdb/common/tdb.c
> +++ b/lib/tdb/common/tdb.c
> @@ -446,16 +446,20 @@ _PUBLIC_ int tdb_delete(struct tdb_context *tdb, TDB_DATA key)
>   * See if we have a dead record around with enough space
>   */
>  static tdb_off_t tdb_find_dead(struct tdb_context *tdb, uint32_t hash,
> -			       struct tdb_record *r, tdb_len_t length)
> +			       struct tdb_record *r, tdb_len_t length,
> +			       tdb_off_t *p_last_ptr)
>  {
> -	tdb_off_t rec_ptr;
> +	tdb_off_t rec_ptr, last_ptr;
>  	tdb_off_t best_rec_ptr = 0;
> +	tdb_off_t best_last_ptr = 0;
>  	struct tdb_record best = { .rec_len = UINT32_MAX };
>  
>  	length += sizeof(tdb_off_t); /* tailer */
>  
> +	last_ptr = TDB_HASH_TOP(hash);
> +
>  	/* read in the hash top */
> -	if (tdb_ofs_read(tdb, TDB_HASH_TOP(hash), &rec_ptr) == -1)
> +	if (tdb_ofs_read(tdb, last_ptr, &rec_ptr) == -1)
>  		return 0;
>  
>  	/* keep looking until we find the right record */
> @@ -466,8 +470,10 @@ static tdb_off_t tdb_find_dead(struct tdb_context *tdb, uint32_t hash,
>  		if (TDB_DEAD(r) && (r->rec_len >= length) &&
>  		    (r->rec_len < best.rec_len)) {
>  			best_rec_ptr = rec_ptr;
> +			best_last_ptr = last_ptr;
>  			best = *r;
>  		}
> +		last_ptr = rec_ptr;
>  		rec_ptr = r->next;
>  	}
>  
> @@ -476,6 +482,7 @@ static tdb_off_t tdb_find_dead(struct tdb_context *tdb, uint32_t hash,
>  	}
>  
>  	*r = best;
> +	*p_last_ptr = best_last_ptr;
>  	return best_rec_ptr;
>  }
>  
> @@ -514,6 +521,7 @@ static int _tdb_store(struct tdb_context *tdb, TDB_DATA key,
>  		tdb_delete_hash(tdb, key, hash);
>  
>  	if (tdb->max_dead_records != 0) {
> +		tdb_off_t last_ptr;
>  		/*
>  		 * Allow for some dead records per hash chain, look if we can
>  		 * find one that can hold the new record. We need enough space
> @@ -521,7 +529,8 @@ static int _tdb_store(struct tdb_context *tdb, TDB_DATA key,
>  		 * consult the central freelist.
>  		 */
>  		rec_ptr = tdb_find_dead(tdb, hash, &rec,
> -					key.dsize + dbuf.dsize);
> +					key.dsize + dbuf.dsize,
> +					&last_ptr);
>  
>  		if (rec_ptr != 0) {
>  			rec.key_len = key.dsize;
> -- 
> 1.7.9.5
> 
> 
> From 766067a7b0446008bfb3a15e28d6ba876be294b6 Mon Sep 17 00:00:00 2001
> From: Volker Lendecke <vl at samba.org>
> Date: Tue, 18 Mar 2014 08:01:40 +0100
> Subject: [PATCH 6/8] tdb: Make "tdb_find_dead" internally public
> 
> Signed-off-by: Volker Lendecke <vl at samba.org>
> ---
>  lib/tdb/common/tdb.c         |    6 +++---
>  lib/tdb/common/tdb_private.h |    3 +++
>  2 files changed, 6 insertions(+), 3 deletions(-)
> 
> diff --git a/lib/tdb/common/tdb.c b/lib/tdb/common/tdb.c
> index b71be98..df4dd4d 100644
> --- a/lib/tdb/common/tdb.c
> +++ b/lib/tdb/common/tdb.c
> @@ -445,9 +445,9 @@ _PUBLIC_ int tdb_delete(struct tdb_context *tdb, TDB_DATA key)
>  /*
>   * See if we have a dead record around with enough space
>   */
> -static tdb_off_t tdb_find_dead(struct tdb_context *tdb, uint32_t hash,
> -			       struct tdb_record *r, tdb_len_t length,
> -			       tdb_off_t *p_last_ptr)
> +tdb_off_t tdb_find_dead(struct tdb_context *tdb, uint32_t hash,
> +			struct tdb_record *r, tdb_len_t length,
> +			tdb_off_t *p_last_ptr)
>  {
>  	tdb_off_t rec_ptr, last_ptr;
>  	tdb_off_t best_rec_ptr = 0;
> diff --git a/lib/tdb/common/tdb_private.h b/lib/tdb/common/tdb_private.h
> index 7227b43..4c73bb6 100644
> --- a/lib/tdb/common/tdb_private.h
> +++ b/lib/tdb/common/tdb_private.h
> @@ -272,6 +272,9 @@ int tdb_parse_data(struct tdb_context *tdb, TDB_DATA key,
>  		   void *private_data);
>  tdb_off_t tdb_find_lock_hash(struct tdb_context *tdb, TDB_DATA key, uint32_t hash, int locktype,
>  			   struct tdb_record *rec);
> +tdb_off_t tdb_find_dead(struct tdb_context *tdb, uint32_t hash,
> +			struct tdb_record *r, tdb_len_t length,
> +			tdb_off_t *p_last_ptr);
>  void tdb_io_init(struct tdb_context *tdb);
>  int tdb_expand(struct tdb_context *tdb, tdb_off_t size);
>  tdb_off_t tdb_expand_adjust(tdb_off_t map_size, tdb_off_t size, int page_size);
> -- 
> 1.7.9.5
> 
> 
> From 324d86c23765a77c11283d10371c952c358ed759 Mon Sep 17 00:00:00 2001
> From: Volker Lendecke <vl at samba.org>
> Date: Tue, 18 Mar 2014 08:03:16 +0100
> Subject: [PATCH 7/8] tdb: Make "tdb_purge_dead" internally public
> 
> Signed-off-by: Volker Lendecke <vl at samba.org>
> ---
>  lib/tdb/common/tdb.c         |    2 +-
>  lib/tdb/common/tdb_private.h |    1 +
>  2 files changed, 2 insertions(+), 1 deletion(-)
> 
> diff --git a/lib/tdb/common/tdb.c b/lib/tdb/common/tdb.c
> index df4dd4d..a7111de 100644
> --- a/lib/tdb/common/tdb.c
> +++ b/lib/tdb/common/tdb.c
> @@ -345,7 +345,7 @@ static int tdb_count_dead(struct tdb_context *tdb, uint32_t hash)
>  /*
>   * Purge all DEAD records from a hash chain
>   */
> -static int tdb_purge_dead(struct tdb_context *tdb, uint32_t hash)
> +int tdb_purge_dead(struct tdb_context *tdb, uint32_t hash)
>  {
>  	int res = -1;
>  	struct tdb_record rec;
> diff --git a/lib/tdb/common/tdb_private.h b/lib/tdb/common/tdb_private.h
> index 4c73bb6..f62c0a3 100644
> --- a/lib/tdb/common/tdb_private.h
> +++ b/lib/tdb/common/tdb_private.h
> @@ -275,6 +275,7 @@ tdb_off_t tdb_find_lock_hash(struct tdb_context *tdb, TDB_DATA key, uint32_t has
>  tdb_off_t tdb_find_dead(struct tdb_context *tdb, uint32_t hash,
>  			struct tdb_record *r, tdb_len_t length,
>  			tdb_off_t *p_last_ptr);
> +int tdb_purge_dead(struct tdb_context *tdb, uint32_t hash);
>  void tdb_io_init(struct tdb_context *tdb);
>  int tdb_expand(struct tdb_context *tdb, tdb_off_t size);
>  tdb_off_t tdb_expand_adjust(tdb_off_t map_size, tdb_off_t size, int page_size);
> -- 
> 1.7.9.5
> 
> 
> From 39d35984cff147bee79b3c5a100a53425e2725f9 Mon Sep 17 00:00:00 2001
> From: Volker Lendecke <vl at samba.org>
> Date: Tue, 18 Mar 2014 08:04:42 +0100
> Subject: [PATCH 8/8] tdb: Reduce freelist contention
> 
> In a metadata-intensive benchmark we have seen the locking.tdb freelist to be
> one of the central contention points. This patch removes most of the contention
> on the freelist. Ages ago we already reduced freelist contention by using the
> even much older DEAD records: If TDB_VOLATILE is set, don't directly put
> deleted records on the freelist, but just mark a few of them just as DEAD. The
> next new record can them re-use that space without consulting the freelist.
> 
> This patch builds upon the DEAD records: If we need space and the freelist is
> busy, instead of doing a blocking wait on the freelist, start looking into
> other chains for DEAD records and steal them from there. This way every hash
> chain becomes a small freelist. Just wander around the hash chains as long as
> the freelist is still busy.
> 
> With this patch and the tdb mutex patch (following hopefully some time soon)
> you can see a heavily busy clustered smbd run without locking.tdb futex
> syscalls.
> 
> Signed-off-by: Volker Lendecke <vl at samba.org>
> ---
>  lib/tdb/common/freelist.c    |  100 +++++++++++++++++++++++++++++++++++++-----
>  lib/tdb/common/tdb.c         |   20 +--------
>  lib/tdb/common/tdb_private.h |    3 +-
>  3 files changed, 93 insertions(+), 30 deletions(-)
> 
> diff --git a/lib/tdb/common/freelist.c b/lib/tdb/common/freelist.c
> index ea14dd0..6f8f812 100644
> --- a/lib/tdb/common/freelist.c
> +++ b/lib/tdb/common/freelist.c
> @@ -273,7 +273,8 @@ static tdb_off_t tdb_allocate_ofs(struct tdb_context *tdb,
>  
>     0 is returned if the space could not be allocated
>   */
> -tdb_off_t tdb_allocate(struct tdb_context *tdb, tdb_len_t length, struct tdb_record *rec)
> +static tdb_off_t tdb_allocate_from_freelist(
> +	struct tdb_context *tdb, tdb_len_t length, struct tdb_record *rec)
>  {
>  	tdb_off_t rec_ptr, last_ptr, newrec_ptr;
>  	struct {
> @@ -282,9 +283,6 @@ tdb_off_t tdb_allocate(struct tdb_context *tdb, tdb_len_t length, struct tdb_rec
>  	} bestfit;
>  	float multiplier = 1.0;
>  
> -	if (tdb_lock(tdb, -1, F_WRLCK) == -1)
> -		return 0;
> -
>  	/* over-allocate to reduce fragmentation */
>  	length *= 1.25;
>  
> @@ -297,7 +295,7 @@ tdb_off_t tdb_allocate(struct tdb_context *tdb, tdb_len_t length, struct tdb_rec
>  
>  	/* read in the freelist top */
>  	if (tdb_ofs_read(tdb, FREELIST_TOP, &rec_ptr) == -1)
> -		goto fail;
> +		return 0;
>  
>  	bestfit.rec_ptr = 0;
>  	bestfit.last_ptr = 0;
> @@ -310,7 +308,7 @@ tdb_off_t tdb_allocate(struct tdb_context *tdb, tdb_len_t length, struct tdb_rec
>  	 */
>  	while (rec_ptr) {
>  		if (tdb_rec_free_read(tdb, rec_ptr, rec) == -1) {
> -			goto fail;
> +			return 0;
>  		}
>  
>  		if (rec->rec_len >= length) {
> @@ -344,12 +342,11 @@ tdb_off_t tdb_allocate(struct tdb_context *tdb, tdb_len_t length, struct tdb_rec
>  
>  	if (bestfit.rec_ptr != 0) {
>  		if (tdb_rec_free_read(tdb, bestfit.rec_ptr, rec) == -1) {
> -			goto fail;
> +			return 0;
>  		}
>  
>  		newrec_ptr = tdb_allocate_ofs(tdb, length, bestfit.rec_ptr,
>  					      rec, bestfit.last_ptr);
> -		tdb_unlock(tdb, -1, F_WRLCK);
>  		return newrec_ptr;
>  	}
>  
> @@ -357,12 +354,95 @@ tdb_off_t tdb_allocate(struct tdb_context *tdb, tdb_len_t length, struct tdb_rec
>  	   database and if we can then try again */
>  	if (tdb_expand(tdb, length + sizeof(*rec)) == 0)
>  		goto again;
> - fail:
> -	tdb_unlock(tdb, -1, F_WRLCK);
> +
>  	return 0;
>  }
>  
> +static bool tdb_alloc_dead(
> +	struct tdb_context *tdb, int hash, tdb_len_t length,
> +	tdb_off_t *rec_ptr, struct tdb_record *rec)
> +{
> +	tdb_off_t last_ptr;
> +
> +	*rec_ptr = tdb_find_dead(tdb, hash, rec, length, &last_ptr);
> +	if (*rec_ptr == 0) {
> +		return false;
> +	}
> +	/*
> +	 * Unlink the record from the hash chain, it's about to be moved into
> +	 * another one.
> +	 */
> +	return (tdb_ofs_write(tdb, last_ptr, &rec->next) == 0);
> +}
> +
> +/*
> + * Chain "hash" is assumed to be locked
> + */
> +
> +tdb_off_t tdb_allocate(struct tdb_context *tdb, int hash, tdb_len_t length,
> +		       struct tdb_record *rec)
> +{
> +	tdb_off_t ret;
> +	int i;
> +
> +	if (tdb->max_dead_records == 0) {
> +		/*
> +		 * No dead records to expect anywhere. Do the blocking
> +		 * freelist lock without trying to steal from others
> +		 */
> +		goto blocking_freelist_allocate;
> +	}
> +
> +	/*
> +	 * The following loop tries to get the freelist lock nonblocking. If
> +	 * it gets the lock, allocate from there. If the freelist is busy,
> +	 * instead of waiting we try to steal dead records from other hash
> +	 * chains.
> +	 *
> +	 * Be aware that we do nonblocking locks on the other hash chains as
> +	 * well and fail gracefully. This way we avoid deadlocks (we block two
> +	 * hash chains, something which is pretty bad normally)
> +	 */
> +
> +	for (i=1; i<tdb->hash_size; i++) {
> +
> +		int list;
> +
> +		if (tdb_lock_nonblock(tdb, -1, F_WRLCK) == 0) {
> +			/*
> +			 * Under the freelist lock take the chance to give
> +			 * back our dead records.
> +			 */
> +			tdb_purge_dead(tdb, hash);
> +
> +			ret = tdb_allocate_from_freelist(tdb, length, rec);
> +			tdb_unlock(tdb, -1, F_WRLCK);
> +			return ret;
> +		}
> +
> +		list = BUCKET(hash+i);
> +
> +		if (tdb_lock_nonblock(tdb, list, F_WRLCK) == 0) {
> +			bool got_dead;
>  
> +			got_dead = tdb_alloc_dead(tdb, list, length, &ret, rec);
> +			tdb_unlock(tdb, list, F_WRLCK);
> +
> +			if (got_dead) {
> +				return ret;
> +			}
> +		}
> +	}
> +
> +blocking_freelist_allocate:
> +
> +	if (tdb_lock(tdb, -1, F_WRLCK) == -1) {
> +		return 0;
> +	}
> +	ret = tdb_allocate_from_freelist(tdb, length, rec);
> +	tdb_unlock(tdb, -1, F_WRLCK);
> +	return ret;
> +}
>  
>  /*
>     return the size of the freelist - used to decide if we should repack
> diff --git a/lib/tdb/common/tdb.c b/lib/tdb/common/tdb.c
> index a7111de..ba1c98e 100644
> --- a/lib/tdb/common/tdb.c
> +++ b/lib/tdb/common/tdb.c
> @@ -550,26 +550,8 @@ static int _tdb_store(struct tdb_context *tdb, TDB_DATA key,
>  		}
>  	}
>  
> -	/*
> -	 * We have to allocate some space from the freelist, so this means we
> -	 * have to lock it. Use the chance to purge all the DEAD records from
> -	 * the hash chain under the freelist lock.
> -	 */
> -
> -	if (tdb_lock(tdb, -1, F_WRLCK) == -1) {
> -		goto fail;
> -	}
> -
> -	if ((tdb->max_dead_records != 0)
> -	    && (tdb_purge_dead(tdb, hash) == -1)) {
> -		tdb_unlock(tdb, -1, F_WRLCK);
> -		goto fail;
> -	}
> -
>  	/* we have to allocate some space */
> -	rec_ptr = tdb_allocate(tdb, key.dsize + dbuf.dsize, &rec);
> -
> -	tdb_unlock(tdb, -1, F_WRLCK);
> +	rec_ptr = tdb_allocate(tdb, hash, key.dsize + dbuf.dsize, &rec);
>  
>  	if (rec_ptr == 0) {
>  		goto fail;
> diff --git a/lib/tdb/common/tdb_private.h b/lib/tdb/common/tdb_private.h
> index f62c0a3..a672159 100644
> --- a/lib/tdb/common/tdb_private.h
> +++ b/lib/tdb/common/tdb_private.h
> @@ -255,7 +255,8 @@ int tdb_ofs_read(struct tdb_context *tdb, tdb_off_t offset, tdb_off_t *d);
>  int tdb_ofs_write(struct tdb_context *tdb, tdb_off_t offset, tdb_off_t *d);
>  void *tdb_convert(void *buf, uint32_t size);
>  int tdb_free(struct tdb_context *tdb, tdb_off_t offset, struct tdb_record *rec);
> -tdb_off_t tdb_allocate(struct tdb_context *tdb, tdb_len_t length, struct tdb_record *rec);
> +tdb_off_t tdb_allocate(struct tdb_context *tdb, int hash, tdb_len_t length,
> +		       struct tdb_record *rec);
>  int tdb_ofs_read(struct tdb_context *tdb, tdb_off_t offset, tdb_off_t *d);
>  int tdb_ofs_write(struct tdb_context *tdb, tdb_off_t offset, tdb_off_t *d);
>  int tdb_lock_record(struct tdb_context *tdb, tdb_off_t off);
> -- 
> 1.7.9.5
> 

-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 215 bytes
Desc: Digital signature
URL: <http://lists.samba.org/pipermail/samba-technical/attachments/20140318/d9fd4c85/attachment.pgp>


More information about the samba-technical mailing list