tdb: suppress record write locks when allrecord lock is taken.
authorRusty Russell <rusty@rustcorp.com.au>
Wed, 24 Feb 2010 00:15:26 +0000 (10:45 +1030)
committerRusty Russell <rusty@rustcorp.com.au>
Wed, 24 Feb 2010 00:15:26 +0000 (10:45 +1030)
Records themselves get (read) locked by the traversal code against delete.
Interestingly, this locking isn't done when the allrecord lock has been
taken, though the allrecord lock until recently didn't cover the actual
records (it now goes to end of file).

The write record lock, grabbed by the delete code, is not suppressed
by the allrecord lock.  This is now bad: it causes us to punch a hole
in the allrecord lock when we release the write record lock.  Make this
consistent: *no* record locks of any kind when the allrecord lock is
taken.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
lib/tdb/common/lock.c

index b1153b2e6f72b20f81e65f135d1d56f051036727..8401cb7f8fd32bb1fa486bc1f33757857aa38d7a 100644 (file)
@@ -631,11 +631,20 @@ int tdb_write_lock_record(struct tdb_context *tdb, tdb_off_t off)
        for (i = &tdb->travlocks; i; i = i->next)
                if (i->off == off)
                        return -1;
        for (i = &tdb->travlocks; i; i = i->next)
                if (i->off == off)
                        return -1;
+       if (tdb->allrecord_lock.count) {
+               if (tdb->allrecord_lock.ltype == F_WRLCK) {
+                       return 0;
+               }
+               return -1;
+       }
        return tdb->methods->brlock(tdb, F_WRLCK, off, 1, TDB_LOCK_NOWAIT|TDB_LOCK_PROBE);
 }
 
 int tdb_write_unlock_record(struct tdb_context *tdb, tdb_off_t off)
 {
        return tdb->methods->brlock(tdb, F_WRLCK, off, 1, TDB_LOCK_NOWAIT|TDB_LOCK_PROBE);
 }
 
 int tdb_write_unlock_record(struct tdb_context *tdb, tdb_off_t off)
 {
+       if (tdb->allrecord_lock.count) {
+               return 0;
+       }
        return tdb->methods->brunlock(tdb, F_WRLCK, off, 1);
 }
 
        return tdb->methods->brunlock(tdb, F_WRLCK, off, 1);
 }