X-Git-Url: https://git.ozlabs.org/?a=blobdiff_plain;f=ccan%2Ftdb%2Flock.c;h=920ba95fe0515a7773ddefd61098510974c18f23;hb=bc1c29d566924ebb7a303dfeb732a5303a59a9b3;hp=e3759a3f8dddd38465fa4da4fdaea992cecb264c;hpb=acf1a21e440b2908df0ce57c48dab1aca9e23cad;p=ccan diff --git a/ccan/tdb/lock.c b/ccan/tdb/lock.c index e3759a3f..920ba95f 100644 --- a/ccan/tdb/lock.c +++ b/ccan/tdb/lock.c @@ -224,12 +224,24 @@ static tdb_off_t lock_offset(int list) return FREELIST_TOP + 4*list; } +static struct tdb_lock_type *find_nestlock(struct tdb_context *tdb, + tdb_off_t offset) +{ + unsigned int i; + + for (i=0; inum_lockrecs; i++) { + if (tdb->lockrecs[i].off == offset) { + return &tdb->lockrecs[i]; + } + } + return NULL; +} + /* lock an offset in the database. */ int tdb_nest_lock(struct tdb_context *tdb, uint32_t offset, int ltype, enum tdb_lock_flags flags) { struct tdb_lock_type *new_lck; - int i; if (offset >= lock_offset(tdb->header.hash_size)) { tdb->ecode = TDB_ERR_LOCK; @@ -240,24 +252,14 @@ int tdb_nest_lock(struct tdb_context *tdb, uint32_t offset, int ltype, if (tdb->flags & TDB_NOLOCK) return 0; - for (i=0; inum_lockrecs; i++) { - if (tdb->lockrecs[i].off == offset) { - if (tdb->lockrecs[i].count == 0) { - /* - * Can't happen, see tdb_unlock(). It should - * be an assert. - */ - TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_lock: " - "lck->count == 0 for offset %u", - offset)); - } - /* - * Just increment the in-memory struct, posix locks - * don't stack. - */ - tdb->lockrecs[i].count++; - return 0; - } + new_lck = find_nestlock(tdb, offset); + if (new_lck) { + /* + * Just increment the in-memory struct, posix locks + * don't stack. + */ + new_lck->count++; + return 0; } new_lck = (struct tdb_lock_type *)realloc( @@ -332,8 +334,7 @@ int tdb_nest_unlock(struct tdb_context *tdb, uint32_t offset, int ltype, bool mark_lock) { int ret = -1; - int i; - struct tdb_lock_type *lck = NULL; + struct tdb_lock_type *lck; if (tdb->flags & TDB_NOLOCK) return 0; @@ -344,13 +345,7 @@ int tdb_nest_unlock(struct tdb_context *tdb, uint32_t offset, int ltype, return ret; } - for (i=0; inum_lockrecs; i++) { - if (tdb->lockrecs[i].off == offset) { - lck = &tdb->lockrecs[i]; - break; - } - } - + lck = find_nestlock(tdb, offset); if ((lck == NULL) || (lck->count == 0)) { TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_unlock: count is 0\n")); return -1; @@ -420,9 +415,6 @@ int tdb_unlock(struct tdb_context *tdb, int list, int ltype) */ int tdb_transaction_lock(struct tdb_context *tdb, int ltype) { - if (tdb->allrecord_lock.count) { - return 0; - } if (tdb->transaction_lock_count > 0) { tdb->transaction_lock_count++; return 0; @@ -443,9 +435,6 @@ int tdb_transaction_lock(struct tdb_context *tdb, int ltype) int tdb_transaction_unlock(struct tdb_context *tdb, int ltype) { int ret; - if (tdb->allrecord_lock.count) { - return 0; - } if (tdb->transaction_lock_count > 1) { tdb->transaction_lock_count--; return 0; @@ -480,8 +469,8 @@ static int _tdb_lockall(struct tdb_context *tdb, int ltype, tdb->ecode = TDB_ERR_LOCK; return -1; } - - if (tdb->num_locks != 0) { + + if (tdb_have_extra_locks(tdb)) { /* can't combine global and chain locks */ tdb->ecode = TDB_ERR_LOCK; return -1; @@ -697,3 +686,34 @@ int tdb_unlock_record(struct tdb_context *tdb, tdb_off_t off) count++; return (count == 1 ? tdb->methods->brunlock(tdb, F_RDLCK, off, 1) : 0); } + +bool tdb_have_extra_locks(struct tdb_context *tdb) +{ + if (tdb->allrecord_lock.count) { + return true; + } + if (tdb->num_lockrecs) { + return true; + } + return false; +} + +/* The transaction code uses this to remove all locks. */ +void tdb_release_extra_locks(struct tdb_context *tdb) +{ + unsigned int i; + + if (tdb->allrecord_lock.count != 0) { + tdb_brunlock(tdb, tdb->allrecord_lock.ltype, + FREELIST_TOP, 4*tdb->header.hash_size); + tdb->allrecord_lock.count = 0; + } + + for (i=0;inum_lockrecs;i++) { + tdb_brunlock(tdb, tdb->lockrecs[i].ltype, + tdb->lockrecs[i].off, 1); + } + tdb->num_locks = 0; + tdb->num_lockrecs = 0; + SAFE_FREE(tdb->lockrecs); +}