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