diff --git a/lib/tdb/common/lock.c b/lib/tdb/common/lock.c index 4dfefd563dc..486de797381 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 05d7cae6beb..6ff37ca1f36 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 ce92188688b..7227b43d2c8 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 */