OSDN Git Service

Update to latest samba tdb library before LGPLv3 change
authorTheodore Ts'o <tytso@mit.edu>
Sun, 17 Feb 2008 11:59:21 +0000 (06:59 -0500)
committerTheodore Ts'o <tytso@mit.edu>
Sun, 17 Feb 2008 22:35:54 +0000 (17:35 -0500)
The major changes were:

* Fix realloc() leak on failure case from Jim Meyering
* Fixed various problems in transaction lock code
* Made transaction_brlock() static
* Added more fine-grained locking features

Moved from svn revision #22080 to #23590

Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
lib/ext2fs/tdb.c
lib/ext2fs/tdb.h
lib/ext2fs/tdb/build-tdb
lib/ext2fs/tdb/patches/copyright
lib/ext2fs/tdb/patches/ext2tdb-rename
lib/ext2fs/tdb/patches/replace-includes
lib/ext2fs/tdb/patches/static-functions
lib/ext2fs/tdb/patches/static-prototypes
lib/ext2fs/tdb/patches/tdbtool-includes

index 822817b..c868958 100644 (file)
@@ -1,7 +1,7 @@
-/* 
-URL: svn://svnanon.samba.org/samba/branches/SAMBA_4_0/source/lib/tdb
-Rev: 22080
-Last Changed: 2007-04-03 05:08:18 -0400
+/*
+URL: svn://svnanon.samba.org/samba/branches/SAMBA_4_0/source/lib/tdb/common
+Rev: 23590
+Last Changed Date: 2007-06-22 13:36:10 -0400 (Fri, 22 Jun 2007)
 */
  /* 
    trivial database library - standalone version
@@ -103,6 +103,8 @@ static char *rep_strdup(const char *s)
 #endif
 #endif
 
+typedef int bool;
+
 #include "tdb.h"
 
 #ifndef u32
@@ -244,6 +246,7 @@ struct tdb_context {
        struct tdb_transaction *transaction;
        int page_size;
        int max_dead_records;
+       bool have_transaction_lock;
 };
 
 
@@ -255,6 +258,8 @@ static void tdb_mmap(struct tdb_context *tdb);
 static int tdb_lock(struct tdb_context *tdb, int list, int ltype);
 static int tdb_unlock(struct tdb_context *tdb, int list, int ltype);
 static int tdb_brlock(struct tdb_context *tdb, tdb_off_t offset, int rw_type, int lck_type, int probe, size_t len);
+static int tdb_transaction_lock(struct tdb_context *tdb, int ltype);
+static int tdb_transaction_unlock(struct tdb_context *tdb);
 static int tdb_brlock_upgrade(struct tdb_context *tdb, tdb_off_t offset, size_t len);
 static int tdb_write_lock_record(struct tdb_context *tdb, tdb_off_t off);
 static int tdb_write_unlock_record(struct tdb_context *tdb, tdb_off_t off);
@@ -280,6 +285,8 @@ static tdb_off_t tdb_find_lock_hash(struct tdb_context *tdb, TDB_DATA key, u32 h
                           struct list_struct *rec);
 static void tdb_io_init(struct tdb_context *tdb);
 static int tdb_expand(struct tdb_context *tdb, tdb_off_t size);
+static int tdb_rec_free_read(struct tdb_context *tdb, tdb_off_t off,
+                     struct list_struct *rec);
 
 
 /* file: error.c */
@@ -314,6 +321,8 @@ const char *tdb_errorstr(struct tdb_context *tdb)
 
 /* file: lock.c */
 
+#define TDB_MARK_LOCK 0x80000000
+
 /* a byte range locking function - return 0 on success
    this functions locks/unlocks 1 byte at the specified offset.
 
@@ -391,10 +400,13 @@ int tdb_brlock_upgrade(struct tdb_context *tdb, tdb_off_t offset, size_t len)
 
 
 /* lock a list in the database. list -1 is the alloc list */
-int tdb_lock(struct tdb_context *tdb, int list, int ltype)
+static int _tdb_lock(struct tdb_context *tdb, int list, int ltype, int op)
 {
        struct tdb_lock_type *new_lck;
        int i;
+       bool mark_lock = ((ltype & TDB_MARK_LOCK) == TDB_MARK_LOCK);
+
+       ltype &= ~TDB_MARK_LOCK;
 
        /* a global lock allows us to avoid per chain locks */
        if (tdb->global_lock.count && 
@@ -444,10 +456,9 @@ int tdb_lock(struct tdb_context *tdb, int list, int ltype)
 
        /* Since fcntl locks don't nest, we do a lock for the first one,
           and simply bump the count for future ones */
-       if (tdb->methods->tdb_brlock(tdb,FREELIST_TOP+4*list,ltype,F_SETLKW,
+       if (!mark_lock &&
+           tdb->methods->tdb_brlock(tdb,FREELIST_TOP+4*list, ltype, op,
                                     0, 1)) {
-               TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_lock failed on list %d "
-                        "ltype=%d (%s)\n",  list, ltype, strerror(errno)));
                return -1;
        }
 
@@ -461,6 +472,25 @@ int tdb_lock(struct tdb_context *tdb, int list, int ltype)
        return 0;
 }
 
+/* lock a list in the database. list -1 is the alloc list */
+int tdb_lock(struct tdb_context *tdb, int list, int ltype)
+{
+       int ret;
+       ret = _tdb_lock(tdb, list, ltype, F_SETLKW);
+       if (ret) {
+               TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_lock failed on list %d "
+                        "ltype=%d (%s)\n",  list, ltype, strerror(errno)));
+       }
+       return ret;
+}
+
+/* lock a list in the database. list -1 is the alloc list. non-blocking lock */
+int tdb_lock_nonblock(struct tdb_context *tdb, int list, int ltype)
+{
+       return _tdb_lock(tdb, list, ltype, F_SETLK);
+}
+
+
 /* unlock the database: returns void because it's too late for errors. */
        /* changed to return int it may be interesting to know there
           has been an error  --simo */
@@ -469,6 +499,9 @@ int tdb_unlock(struct tdb_context *tdb, int list, int ltype)
        int ret = -1;
        int i;
        struct tdb_lock_type *lck = NULL;
+       bool mark_lock = ((ltype & TDB_MARK_LOCK) == TDB_MARK_LOCK);
+
+       ltype &= ~TDB_MARK_LOCK;
 
        /* a global lock allows us to avoid per chain locks */
        if (tdb->global_lock.count && 
@@ -513,8 +546,12 @@ int tdb_unlock(struct tdb_context *tdb, int list, int ltype)
         * anyway.
         */
 
-       ret = tdb->methods->tdb_brlock(tdb, FREELIST_TOP+4*list, F_UNLCK,
-                                      F_SETLKW, 0, 1);
+       if (mark_lock) {
+               ret = 0;
+       } else {
+               ret = tdb->methods->tdb_brlock(tdb, FREELIST_TOP+4*list, F_UNLCK,
+                                              F_SETLKW, 0, 1);
+       }
        tdb->num_locks--;
 
        /*
@@ -541,11 +578,50 @@ int tdb_unlock(struct tdb_context *tdb, int list, int ltype)
        return ret;
 }
 
+/*
+  get the transaction lock
+ */
+int tdb_transaction_lock(struct tdb_context *tdb, int ltype)
+{
+       if (tdb->have_transaction_lock || tdb->global_lock.count) {
+               return 0;
+       }
+       if (tdb->methods->tdb_brlock(tdb, TRANSACTION_LOCK, ltype, 
+                                    F_SETLKW, 0, 1) == -1) {
+               TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_transaction_lock: failed to get transaction lock\n"));
+               tdb->ecode = TDB_ERR_LOCK;
+               return -1;
+       }
+       tdb->have_transaction_lock = 1;
+       return 0;
+}
+
+/*
+  release the transaction lock
+ */
+int tdb_transaction_unlock(struct tdb_context *tdb)
+{
+       int ret;
+       if (!tdb->have_transaction_lock) {
+               return 0;
+       }
+       ret = tdb->methods->tdb_brlock(tdb, TRANSACTION_LOCK, F_UNLCK, F_SETLKW, 0, 1);
+       if (ret == 0) {
+               tdb->have_transaction_lock = 0;
+       }
+       return ret;
+}
+
+
 
 
 /* lock/unlock entire database */
-static int _tdb_lockall(struct tdb_context *tdb, int ltype)
+static int _tdb_lockall(struct tdb_context *tdb, int ltype, int op)
 {
+       bool mark_lock = ((ltype & TDB_MARK_LOCK) == TDB_MARK_LOCK);
+
+       ltype &= ~TDB_MARK_LOCK;
+
        /* There are no locks on read-only dbs */
        if (tdb->read_only || tdb->traverse_read)
                return TDB_ERRCODE(TDB_ERR_LOCK, -1);
@@ -565,9 +641,12 @@ static int _tdb_lockall(struct tdb_context *tdb, int ltype)
                return TDB_ERRCODE(TDB_ERR_LOCK, -1);
        }
 
-       if (tdb->methods->tdb_brlock(tdb, FREELIST_TOP, ltype, F_SETLKW, 
+       if (!mark_lock &&
+           tdb->methods->tdb_brlock(tdb, FREELIST_TOP, ltype, op,
                                     0, 4*tdb->header.hash_size)) {
-               TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_lockall failed (%s)\n", strerror(errno)));
+               if (op == F_SETLKW) {
+                       TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_lockall failed (%s)\n", strerror(errno)));
+               }
                return -1;
        }
 
@@ -577,9 +656,15 @@ static int _tdb_lockall(struct tdb_context *tdb, int ltype)
        return 0;
 }
 
+
+
 /* unlock entire db */
 static int _tdb_unlockall(struct tdb_context *tdb, int ltype)
 {
+       bool mark_lock = ((ltype & TDB_MARK_LOCK) == TDB_MARK_LOCK);
+
+       ltype &= ~TDB_MARK_LOCK;
+
        /* There are no locks on read-only dbs */
        if (tdb->read_only || tdb->traverse_read) {
                return TDB_ERRCODE(TDB_ERR_LOCK, -1);
@@ -594,7 +679,8 @@ static int _tdb_unlockall(struct tdb_context *tdb, int ltype)
                return 0;
        }
 
-       if (tdb->methods->tdb_brlock(tdb, FREELIST_TOP, F_UNLCK, F_SETLKW, 
+       if (!mark_lock &&
+           tdb->methods->tdb_brlock(tdb, FREELIST_TOP, F_UNLCK, F_SETLKW, 
                                     0, 4*tdb->header.hash_size)) {
                TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_unlockall failed (%s)\n", strerror(errno)));
                return -1;
@@ -609,7 +695,25 @@ static int _tdb_unlockall(struct tdb_context *tdb, int ltype)
 /* lock entire database with write lock */
 int tdb_lockall(struct tdb_context *tdb)
 {
-       return _tdb_lockall(tdb, F_WRLCK);
+       return _tdb_lockall(tdb, F_WRLCK, F_SETLKW);
+}
+
+/* lock entire database with write lock - mark only */
+int tdb_lockall_mark(struct tdb_context *tdb)
+{
+       return _tdb_lockall(tdb, F_WRLCK | TDB_MARK_LOCK, F_SETLKW);
+}
+
+/* unlock entire database with write lock - unmark only */
+int tdb_lockall_unmark(struct tdb_context *tdb)
+{
+       return _tdb_unlockall(tdb, F_WRLCK | TDB_MARK_LOCK);
+}
+
+/* lock entire database with write lock - nonblocking varient */
+int tdb_lockall_nonblock(struct tdb_context *tdb)
+{
+       return _tdb_lockall(tdb, F_WRLCK, F_SETLK);
 }
 
 /* unlock entire database with write lock */
@@ -621,7 +725,13 @@ int tdb_unlockall(struct tdb_context *tdb)
 /* lock entire database with read lock */
 int tdb_lockall_read(struct tdb_context *tdb)
 {
-       return _tdb_lockall(tdb, F_RDLCK);
+       return _tdb_lockall(tdb, F_RDLCK, F_SETLKW);
+}
+
+/* lock entire database with read lock - nonblock varient */
+int tdb_lockall_read_nonblock(struct tdb_context *tdb)
+{
+       return _tdb_lockall(tdb, F_RDLCK, F_SETLK);
 }
 
 /* unlock entire database with read lock */
@@ -637,6 +747,26 @@ int tdb_chainlock(struct tdb_context *tdb, TDB_DATA key)
        return tdb_lock(tdb, BUCKET(tdb->hash_fn(&key)), F_WRLCK);
 }
 
+/* lock/unlock one hash chain, non-blocking. This is meant to be used
+   to reduce contention - it cannot guarantee how many records will be
+   locked */
+int tdb_chainlock_nonblock(struct tdb_context *tdb, TDB_DATA key)
+{
+       return tdb_lock_nonblock(tdb, BUCKET(tdb->hash_fn(&key)), F_WRLCK);
+}
+
+/* mark a chain as locked without actually locking it. Warning! use with great caution! */
+int tdb_chainlock_mark(struct tdb_context *tdb, TDB_DATA key)
+{
+       return tdb_lock(tdb, BUCKET(tdb->hash_fn(&key)), F_WRLCK | TDB_MARK_LOCK);
+}
+
+/* unmark a chain as locked without actually locking it. Warning! use with great caution! */
+int tdb_chainlock_unmark(struct tdb_context *tdb, TDB_DATA key)
+{
+       return tdb_unlock(tdb, BUCKET(tdb->hash_fn(&key)), F_WRLCK | TDB_MARK_LOCK);
+}
+
 int tdb_chainunlock(struct tdb_context *tdb, TDB_DATA key)
 {
        return tdb_unlock(tdb, BUCKET(tdb->hash_fn(&key)), F_WRLCK);
@@ -1430,7 +1560,7 @@ static int transaction_expand_file(struct tdb_context *tdb, tdb_off_t size,
 /*
   brlock during a transaction - ignore them
 */
-static int transaction_brlock(struct tdb_context *tdb, tdb_off_t offset,
+static int transaction_brlock(struct tdb_context *tdb, tdb_off_t offset, 
                              int rw_type, int lck_type, int probe, size_t len)
 {
        return 0;
@@ -1495,9 +1625,7 @@ int tdb_transaction_start(struct tdb_context *tdb)
        /* get the transaction write lock. This is a blocking lock. As
           discussed with Volker, there are a number of ways we could
           make this async, which we will probably do in the future */
-       if (tdb_brlock(tdb, TRANSACTION_LOCK, F_WRLCK, F_SETLKW, 0, 1) == -1) {
-               TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_transaction_start: failed to get transaction lock\n"));
-               tdb->ecode = TDB_ERR_LOCK;
+       if (tdb_transaction_lock(tdb, F_WRLCK) == -1) {
                SAFE_FREE(tdb->transaction);
                return -1;
        }
@@ -1541,6 +1669,7 @@ int tdb_transaction_start(struct tdb_context *tdb)
                              TDB_HASHTABLE_SIZE(tdb)) != 0) {
                TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction_start: failed to prime hash table\n"));
                tdb->ecode = TDB_ERR_IO;
+               tdb->methods = tdb->transaction->io_methods;
                goto fail;
        }
 
@@ -1548,7 +1677,7 @@ int tdb_transaction_start(struct tdb_context *tdb)
        
 fail:
        tdb_brlock(tdb, FREELIST_TOP, F_UNLCK, F_SETLKW, 0, 0);
-       tdb_brlock(tdb, TRANSACTION_LOCK, F_UNLCK, F_SETLKW, 0, 1);
+       tdb_transaction_unlock(tdb);
        SAFE_FREE(tdb->transaction->hash_heads);
        SAFE_FREE(tdb->transaction);
        return -1;
@@ -1595,13 +1724,15 @@ int tdb_transaction_cancel(struct tdb_context *tdb)
                                   F_UNLCK,F_SETLKW, 0, 1);
                }
                tdb->num_locks = 0;
+               tdb->num_lockrecs = 0;
+               SAFE_FREE(tdb->lockrecs);
        }
 
        /* restore the normal io methods */
        tdb->methods = tdb->transaction->io_methods;
 
        tdb_brlock(tdb, FREELIST_TOP, F_UNLCK, F_SETLKW, 0, 0);
-       tdb_brlock(tdb, TRANSACTION_LOCK, F_UNLCK, F_SETLKW, 0, 1);
+       tdb_transaction_unlock(tdb);
        SAFE_FREE(tdb->transaction->hash_heads);
        SAFE_FREE(tdb->transaction);
        
@@ -2125,7 +2256,7 @@ int tdb_transaction_recover(struct tdb_context *tdb)
 /* file: freelist.c */
 
 /* read a freelist record and check for simple errors */
-static int rec_free_read(struct tdb_context *tdb, tdb_off_t off, struct list_struct *rec)
+static int tdb_rec_free_read(struct tdb_context *tdb, tdb_off_t off, struct list_struct *rec)
 {
        if (tdb->methods->tdb_read(tdb, off, rec, sizeof(*rec),DOCONV()) == -1)
                return -1;
@@ -2133,7 +2264,7 @@ static int rec_free_read(struct tdb_context *tdb, tdb_off_t off, struct list_str
        if (rec->magic == TDB_MAGIC) {
                /* this happens when a app is showdown while deleting a record - we should
                   not completely fail when this happens */
-               TDB_LOG((tdb, TDB_DEBUG_WARNING, "rec_free_read non-free magic 0x%x at offset=%d - fixing\n", 
+               TDB_LOG((tdb, TDB_DEBUG_WARNING, "tdb_rec_free_read non-free magic 0x%x at offset=%d - fixing\n", 
                         rec->magic, off));
                rec->magic = TDB_FREE_MAGIC;
                if (tdb->methods->tdb_write(tdb, off, rec, sizeof(*rec)) == -1)
@@ -2143,7 +2274,7 @@ static int rec_free_read(struct tdb_context *tdb, tdb_off_t off, struct list_str
        if (rec->magic != TDB_FREE_MAGIC) {
                /* Ensure ecode is set for log fn. */
                tdb->ecode = TDB_ERR_CORRUPT;
-               TDB_LOG((tdb, TDB_DEBUG_WARNING, "rec_free_read bad magic 0x%x at offset=%d\n", 
+               TDB_LOG((tdb, TDB_DEBUG_WARNING, "tdb_rec_free_read bad magic 0x%x at offset=%d\n", 
                           rec->magic, off));
                return TDB_ERRCODE(TDB_ERR_CORRUPT, -1);
        }
@@ -2382,7 +2513,7 @@ tdb_off_t tdb_allocate(struct tdb_context *tdb, tdb_len_t length, struct list_st
           issues when faced with a slowly increasing record size.
         */
        while (rec_ptr) {
-               if (rec_free_read(tdb, rec_ptr, rec) == -1) {
+               if (tdb_rec_free_read(tdb, rec_ptr, rec) == -1) {
                        goto fail;
                }
 
@@ -2407,7 +2538,7 @@ tdb_off_t tdb_allocate(struct tdb_context *tdb, tdb_len_t length, struct list_st
        }
 
        if (bestfit.rec_ptr != 0) {
-               if (rec_free_read(tdb, bestfit.rec_ptr, rec) == -1) {
+               if (tdb_rec_free_read(tdb, bestfit.rec_ptr, rec) == -1) {
                        goto fail;
                }
 
@@ -2489,7 +2620,7 @@ int tdb_validate_freelist(struct tdb_context *tdb, int *pnum_entries)
                        goto fail;
                }
 
-               if (rec_free_read(tdb, rec_ptr, &rec) == -1) {
+               if (tdb_rec_free_read(tdb, rec_ptr, &rec) == -1) {
                        goto fail;
                }
 
@@ -2687,12 +2818,10 @@ int tdb_traverse_read(struct tdb_context *tdb,
 {
        struct tdb_traverse_lock tl = { NULL, 0, 0, F_RDLCK };
        int ret;
-       
+
        /* we need to get a read lock on the transaction lock here to
           cope with the lock ordering semantics of solaris10 */
-       if (tdb->methods->tdb_brlock(tdb, TRANSACTION_LOCK, F_RDLCK, F_SETLKW, 0, 1) == -1) {
-               TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_traverse_read: failed to get transaction lock\n"));
-               tdb->ecode = TDB_ERR_LOCK;
+       if (tdb_transaction_lock(tdb, F_RDLCK)) {
                return -1;
        }
 
@@ -2700,7 +2829,7 @@ int tdb_traverse_read(struct tdb_context *tdb,
        ret = tdb_traverse_internal(tdb, fn, private_data, &tl);
        tdb->traverse_read--;
 
-       tdb->methods->tdb_brlock(tdb, TRANSACTION_LOCK, F_UNLCK, F_SETLKW, 0, 1);
+       tdb_transaction_unlock(tdb);
 
        return ret;
 }
@@ -2719,15 +2848,13 @@ int tdb_traverse(struct tdb_context *tdb,
                return tdb_traverse_read(tdb, fn, private_data);
        }
        
-       if (tdb->methods->tdb_brlock(tdb, TRANSACTION_LOCK, F_WRLCK, F_SETLKW, 0, 1) == -1) {
-               TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_traverse: failed to get transaction lock\n"));
-               tdb->ecode = TDB_ERR_LOCK;
+       if (tdb_transaction_lock(tdb, F_WRLCK)) {
                return -1;
        }
 
        ret = tdb_traverse_internal(tdb, fn, private_data, &tl);
 
-       tdb->methods->tdb_brlock(tdb, TRANSACTION_LOCK, F_UNLCK, F_SETLKW, 0, 1);
+       tdb_transaction_unlock(tdb);
 
        return ret;
 }
@@ -2745,12 +2872,15 @@ TDB_DATA tdb_firstkey(struct tdb_context *tdb)
        tdb->travlocks.off = tdb->travlocks.hash = 0;
        tdb->travlocks.lock_rw = F_RDLCK;
 
+       /* Grab first record: locks chain and returned record. */
        if (tdb_next_lock(tdb, &tdb->travlocks, &rec) <= 0)
                return tdb_null;
        /* now read the key */
        key.dsize = rec.key_len;
        key.dptr =tdb_alloc_read(tdb,tdb->travlocks.off+sizeof(rec),key.dsize);
-       if (tdb_unlock(tdb, BUCKET(tdb->travlocks.hash), F_WRLCK) != 0)
+
+       /* Unlock the hash chain of the record we just read. */
+       if (tdb_unlock(tdb, tdb->travlocks.hash, tdb->travlocks.lock_rw) != 0)
                TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_firstkey: error occurred while tdb_unlocking!\n"));
        return key;
 }
@@ -2765,7 +2895,7 @@ TDB_DATA tdb_nextkey(struct tdb_context *tdb, TDB_DATA oldkey)
 
        /* Is locked key the old key?  If so, traverse will be reliable. */
        if (tdb->travlocks.off) {
-               if (tdb_lock(tdb,tdb->travlocks.hash,F_WRLCK))
+               if (tdb_lock(tdb,tdb->travlocks.hash,tdb->travlocks.lock_rw))
                        return tdb_null;
                if (tdb_rec_read(tdb, tdb->travlocks.off, &rec) == -1
                    || !(k = tdb_alloc_read(tdb,tdb->travlocks.off+sizeof(rec),
@@ -2776,7 +2906,7 @@ TDB_DATA tdb_nextkey(struct tdb_context *tdb, TDB_DATA oldkey)
                                SAFE_FREE(k);
                                return tdb_null;
                        }
-                       if (tdb_unlock(tdb, tdb->travlocks.hash, F_WRLCK) != 0) {
+                       if (tdb_unlock(tdb, tdb->travlocks.hash, tdb->travlocks.lock_rw) != 0) {
                                SAFE_FREE(k);
                                return tdb_null;
                        }
@@ -2788,7 +2918,7 @@ TDB_DATA tdb_nextkey(struct tdb_context *tdb, TDB_DATA oldkey)
 
        if (!tdb->travlocks.off) {
                /* No previous element: do normal find, and lock record */
-               tdb->travlocks.off = tdb_find_lock_hash(tdb, oldkey, tdb->hash_fn(&oldkey), F_WRLCK, &rec);
+               tdb->travlocks.off = tdb_find_lock_hash(tdb, oldkey, tdb->hash_fn(&oldkey), tdb->travlocks.lock_rw, &rec);
                if (!tdb->travlocks.off)
                        return tdb_null;
                tdb->travlocks.hash = BUCKET(rec.full_hash);
@@ -2806,18 +2936,19 @@ TDB_DATA tdb_nextkey(struct tdb_context *tdb, TDB_DATA oldkey)
                key.dptr = tdb_alloc_read(tdb, tdb->travlocks.off+sizeof(rec),
                                          key.dsize);
                /* Unlock the chain of this new record */
-               if (tdb_unlock(tdb, tdb->travlocks.hash, F_WRLCK) != 0)
+               if (tdb_unlock(tdb, tdb->travlocks.hash, tdb->travlocks.lock_rw) != 0)
                        TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_nextkey: WARNING tdb_unlock failed!\n"));
        }
        /* Unlock the chain of old record */
-       if (tdb_unlock(tdb, BUCKET(oldhash), F_WRLCK) != 0)
+       if (tdb_unlock(tdb, BUCKET(oldhash), tdb->travlocks.lock_rw) != 0)
                TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_nextkey: WARNING tdb_unlock failed!\n"));
        return key;
 }
 
 /* file: dump.c */
 
-static tdb_off_t tdb_dump_record(struct tdb_context *tdb, tdb_off_t offset)
+static tdb_off_t tdb_dump_record(struct tdb_context *tdb, int hash,
+                                tdb_off_t offset)
 {
        struct list_struct rec;
        tdb_off_t tailer_ofs, tailer;
@@ -2828,8 +2959,10 @@ static tdb_off_t tdb_dump_record(struct tdb_context *tdb, tdb_off_t offset)
                return 0;
        }
 
-       printf(" rec: offset=0x%08x next=0x%08x rec_len=%d key_len=%d data_len=%d full_hash=0x%x magic=0x%x\n",
-              offset, rec.next, rec.rec_len, rec.key_len, rec.data_len, rec.full_hash, rec.magic);
+       printf(" rec: hash=%d offset=0x%08x next=0x%08x rec_len=%d "
+              "key_len=%d data_len=%d full_hash=0x%x magic=0x%x\n",
+              hash, offset, rec.next, rec.rec_len, rec.key_len, rec.data_len,
+              rec.full_hash, rec.magic);
 
        tailer_ofs = offset + sizeof(rec) + rec.rec_len - sizeof(tdb_off_t);
 
@@ -2861,7 +2994,7 @@ static int tdb_dump_chain(struct tdb_context *tdb, int i)
                printf("hash=%d\n", i);
 
        while (rec_ptr) {
-               rec_ptr = tdb_dump_record(tdb, rec_ptr);
+               rec_ptr = tdb_dump_record(tdb, i, rec_ptr);
        }
 
        return tdb_unlock(tdb, i, F_WRLCK);
@@ -2927,10 +3060,10 @@ int tdb_printfreelist(struct tdb_context *tdb)
 TDB_DATA tdb_null;
 
 /*
-  increment the tdb sequence number if the tdb has been opened using
+  non-blocking increment of the tdb sequence number if the tdb has been opened using
   the TDB_SEQNUM flag
 */
-static void tdb_increment_seqnum(struct tdb_context *tdb)
+void tdb_increment_seqnum_nonblock(struct tdb_context *tdb)
 {
        tdb_off_t seqnum=0;
        
@@ -2938,16 +3071,29 @@ static void tdb_increment_seqnum(struct tdb_context *tdb)
                return;
        }
 
-       if (tdb_brlock(tdb, TDB_SEQNUM_OFS, F_WRLCK, F_SETLKW, 1, 1) != 0) {
-               return;
-       }
-
        /* we ignore errors from this, as we have no sane way of
           dealing with them.
        */
        tdb_ofs_read(tdb, TDB_SEQNUM_OFS, &seqnum);
        seqnum++;
        tdb_ofs_write(tdb, TDB_SEQNUM_OFS, &seqnum);
+}
+
+/*
+  increment the tdb sequence number if the tdb has been opened using
+  the TDB_SEQNUM flag
+*/
+static void tdb_increment_seqnum(struct tdb_context *tdb)
+{
+       if (!(tdb->flags & TDB_SEQNUM)) {
+               return;
+       }
+
+       if (tdb_brlock(tdb, TDB_SEQNUM_OFS, F_WRLCK, F_SETLKW, 1, 1) != 0) {
+               return;
+       }
+
+       tdb_increment_seqnum_nonblock(tdb);
 
        tdb_brlock(tdb, TDB_SEQNUM_OFS, F_UNLCK, F_SETLKW, 1, 1);
 }
@@ -3462,8 +3608,12 @@ int tdb_append(struct tdb_context *tdb, TDB_DATA key, TDB_DATA new_dbuf)
        if (dbuf.dptr == NULL) {
                dbuf.dptr = (unsigned char *)malloc(new_dbuf.dsize);
        } else {
-               dbuf.dptr = (unsigned char *)realloc(dbuf.dptr,
+               unsigned char *new_dptr = (unsigned char *)realloc(dbuf.dptr,
                                                     dbuf.dsize + new_dbuf.dsize);
+               if (new_dptr == NULL) {
+                       free(dbuf.dptr);
+               }
+               dbuf.dptr = new_dptr;
        }
 
        if (dbuf.dptr == NULL) {
@@ -3545,6 +3695,15 @@ int tdb_get_flags(struct tdb_context *tdb)
        return tdb->flags;
 }
 
+
+/*
+  enable sequence number handling on an open tdb
+*/
+void tdb_enable_seqnum(struct tdb_context *tdb)
+{
+       tdb->flags |= TDB_SEQNUM;
+}
+
 /* file: open.c */
 
 /* all contexts, to ensure no double-opens (fcntl locks don't nest!) */
index 7ba7ac7..447d6a1 100644 (file)
@@ -119,7 +119,16 @@ typedef struct TDB_DATA {
 #define tdb_dump_all ext2fs_tdb_dump_all
 #define tdb_printfreelist ext2fs_tdb_printfreelist
 #define tdb_validate_freelist ext2fs_tdb_validate_freelist
-
+#define tdb_chainlock_mark ext2fs_tdb_chainlock_mark
+#define tdb_chainlock_nonblock ext2fs_tdb_chainlock_nonblock
+#define tdb_chainlock_unmark ext2fs_tdb_chainlock_unmark
+#define tdb_enable_seqnum ext2fs_tdb_enable_seqnum
+#define tdb_increment_seqnum_nonblock ext2fs_tdb_increment_seqnum_nonblock
+#define tdb_lock_nonblock ext2fs_tdb_lock_nonblock
+#define tdb_lockall_mark ext2fs_tdb_lockall_mark
+#define tdb_lockall_nonblock ext2fs_tdb_lockall_nonblock
+#define tdb_lockall_read_nonblock ext2fs_tdb_lockall_read_nonblock
+#define tdb_lockall_unmark ext2fs_tdb_lockall_unmark
 
 /* this is the context structure that is returned from a db open */
 typedef struct tdb_context TDB_CONTEXT;
@@ -161,9 +170,13 @@ int tdb_traverse(struct tdb_context *tdb, tdb_traverse_func fn, void *);
 int tdb_traverse_read(struct tdb_context *tdb, tdb_traverse_func fn, void *);
 int tdb_exists(struct tdb_context *tdb, TDB_DATA key);
 int tdb_lockall(struct tdb_context *tdb);
+int tdb_lockall_nonblock(struct tdb_context *tdb);
 int tdb_unlockall(struct tdb_context *tdb);
 int tdb_lockall_read(struct tdb_context *tdb);
+int tdb_lockall_read_nonblock(struct tdb_context *tdb);
 int tdb_unlockall_read(struct tdb_context *tdb);
+int tdb_lockall_mark(struct tdb_context *tdb);
+int tdb_lockall_unmark(struct tdb_context *tdb);
 const char *tdb_name(struct tdb_context *tdb);
 int tdb_fd(struct tdb_context *tdb);
 tdb_log_func tdb_log_fn(struct tdb_context *tdb);
@@ -176,12 +189,17 @@ int tdb_get_seqnum(struct tdb_context *tdb);
 int tdb_hash_size(struct tdb_context *tdb);
 size_t tdb_map_size(struct tdb_context *tdb);
 int tdb_get_flags(struct tdb_context *tdb);
+void tdb_enable_seqnum(struct tdb_context *tdb);
+void tdb_increment_seqnum_nonblock(struct tdb_context *tdb);
 
 /* Low level locking functions: use with care */
 int tdb_chainlock(struct tdb_context *tdb, TDB_DATA key);
+int tdb_chainlock_nonblock(struct tdb_context *tdb, TDB_DATA key);
 int tdb_chainunlock(struct tdb_context *tdb, TDB_DATA key);
 int tdb_chainlock_read(struct tdb_context *tdb, TDB_DATA key);
 int tdb_chainunlock_read(struct tdb_context *tdb, TDB_DATA key);
+int tdb_chainlock_mark(struct tdb_context *tdb, TDB_DATA key);
+int tdb_chainlock_unmark(struct tdb_context *tdb, TDB_DATA key);
 
 /* Debug functions. Not used in production. */
 void tdb_dump_all(struct tdb_context *tdb);
index f0eaa7f..1cc18f7 100755 (executable)
@@ -6,10 +6,19 @@
 #BASE_DIR=/usr/projects/samba/samba-4.0.0tp4/source/lib/tdb
 BASE_DIR=/usr/projects/samba/tdb
 
+rm -rf .pc
+
 FILES="error.c lock.c io.c transaction.c freelist.c \
        freelistcheck.c traverse.c dump.c tdb.c open.c"
 
-cp $BASE_DIR/common/tdb_private.h tdb.c
+(cd $BASE_DIR/common; svn info ) > .svninfo
+echo "/*" > tdb.c
+grep ^URL .svninfo >> tdb.c
+grep "^Last Changed Rev" .svninfo | sed -e 's/Last Changed //' >> tdb.c
+grep "^Last Changed Date" .svninfo >> tdb.c
+echo "*/" >> tdb.c
+
+cat $BASE_DIR/common/tdb_private.h >> tdb.c
 for i in $FILES; do
        if [ `tail -n 1 tdb.c | wc -c` -gt 1 ]; then
                printf "\n" >> tdb.c
@@ -21,3 +30,5 @@ done
 cp $BASE_DIR/include/tdb.h .
 cp $BASE_DIR/tools/tdbtool.c .
 
+quilt push -a
+
index f519ac6..d9d1d84 100644 (file)
@@ -1,8 +1,10 @@
-Index: tdb-sa/tdb.c
+Index: tdbsa/tdb.c
 ===================================================================
---- tdb-sa.orig/tdb.c  2007-04-04 12:16:26.000000000 -0400
-+++ tdb-sa/tdb.c       2007-04-04 12:16:53.000000000 -0400
-@@ -1,9 +1,9 @@
+--- tdbsa.orig/tdb.c
++++ tdbsa/tdb.c
+@@ -4,11 +4,11 @@ Rev: 23371
+ Last Changed Date: 2007-06-06 20:14:06 -0400 (Wed, 06 Jun 2007)
+ */
   /* 
 -   Unix SMB/CIFS implementation.
 +   trivial database library - standalone version
index 44a3705..15bf085 100644 (file)
@@ -1,8 +1,8 @@
 Index: tdb/tdb.h
 ===================================================================
---- tdb.orig/tdb.h     2007-04-04 20:39:26.000000000 -0400
-+++ tdb/tdb.h  2007-04-04 20:40:13.000000000 -0400
-@@ -76,6 +76,51 @@
+--- tdb.orig/tdb.h
++++ tdb/tdb.h
+@@ -76,6 +76,60 @@ typedef struct TDB_DATA {
  #endif
  #endif
  
@@ -49,7 +49,16 @@ Index: tdb/tdb.h
 +#define tdb_dump_all ext2fs_tdb_dump_all
 +#define tdb_printfreelist ext2fs_tdb_printfreelist
 +#define tdb_validate_freelist ext2fs_tdb_validate_freelist
-+
++#define tdb_chainlock_mark ext2fs_tdb_chainlock_mark
++#define tdb_chainlock_nonblock ext2fs_tdb_chainlock_nonblock
++#define tdb_chainlock_unmark ext2fs_tdb_chainlock_unmark
++#define tdb_enable_seqnum ext2fs_tdb_enable_seqnum
++#define tdb_increment_seqnum_nonblock ext2fs_tdb_increment_seqnum_nonblock
++#define tdb_lock_nonblock ext2fs_tdb_lock_nonblock
++#define tdb_lockall_mark ext2fs_tdb_lockall_mark
++#define tdb_lockall_nonblock ext2fs_tdb_lockall_nonblock
++#define tdb_lockall_read_nonblock ext2fs_tdb_lockall_read_nonblock
++#define tdb_lockall_unmark ext2fs_tdb_lockall_unmark
 +
  /* this is the context structure that is returned from a db open */
  typedef struct tdb_context TDB_CONTEXT;
index e552533..b1d0d57 100644 (file)
@@ -1,8 +1,8 @@
 Index: tdb/tdb.c
 ===================================================================
---- tdb.orig/tdb.c     2007-04-04 20:26:11.000000000 -0400
-+++ tdb/tdb.c  2007-04-04 20:39:58.000000000 -0400
-@@ -24,11 +24,78 @@
+--- tdb.orig/tdb.c
++++ tdb/tdb.c
+@@ -29,11 +29,82 @@ Last Changed Date: 2007-06-22 13:36:10 -
     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
  
@@ -27,7 +27,9 @@ Index: tdb/tdb.c
 +#include <stddef.h>
 +#include <errno.h>
 +#include <string.h>
++#ifdef HAVE_SYS_SELECT_H
 +#include <sys/select.h>
++#endif
 +#include <sys/time.h>
 +#include <sys/types.h>
 +#include <time.h>
@@ -83,6 +85,8 @@ Index: tdb/tdb.c
 +#endif
 +#endif
 +
++typedef int bool;
++
  #include "tdb.h"
  
  #ifndef u32
index 7fb76ef..ab0fbef 100644 (file)
@@ -1,24 +1,13 @@
-Index: tdb/tdb.c
+Index: tdbsa/tdb.c
 ===================================================================
---- tdb.orig/tdb.c     2007-04-04 20:40:06.000000000 -0400
-+++ tdb/tdb.c  2007-04-04 20:40:08.000000000 -0400
-@@ -1423,8 +1423,8 @@
- /*
-   brlock during a transaction - ignore them
- */
--int transaction_brlock(struct tdb_context *tdb, tdb_off_t offset, 
--                     int rw_type, int lck_type, int probe, size_t len)
-+static int transaction_brlock(struct tdb_context *tdb, tdb_off_t offset,
-+                            int rw_type, int lck_type, int probe, size_t len)
- {
-       return 0;
- }
-@@ -2118,7 +2118,7 @@
+--- tdbsa.orig/tdb.c
++++ tdbsa/tdb.c
+@@ -2254,7 +2254,7 @@ int tdb_transaction_recover(struct tdb_c
  /* file: freelist.c */
  
  /* read a freelist record and check for simple errors */
--int rec_free_read(struct tdb_context *tdb, tdb_off_t off, struct list_struct *rec)
-+static int rec_free_read(struct tdb_context *tdb, tdb_off_t off, struct list_struct *rec)
+-int tdb_rec_free_read(struct tdb_context *tdb, tdb_off_t off, struct list_struct *rec)
++static int tdb_rec_free_read(struct tdb_context *tdb, tdb_off_t off, struct list_struct *rec)
  {
        if (tdb->methods->tdb_read(tdb, off, rec, sizeof(*rec),DOCONV()) == -1)
                return -1;
index c1049df..cf8af61 100644 (file)
@@ -1,8 +1,8 @@
-Index: tdb/tdb.c
+Index: tdbsa/tdb.c
 ===================================================================
---- tdb.orig/tdb.c     2007-04-04 20:39:58.000000000 -0400
-+++ tdb/tdb.c  2007-04-04 20:40:06.000000000 -0400
-@@ -243,36 +243,36 @@
+--- tdbsa.orig/tdb.c
++++ tdbsa/tdb.c
+@@ -251,39 +251,39 @@ struct tdb_context {
  /*
    internal prototypes
  */
@@ -11,6 +11,8 @@ Index: tdb/tdb.c
 -int tdb_lock(struct tdb_context *tdb, int list, int ltype);
 -int tdb_unlock(struct tdb_context *tdb, int list, int ltype);
 -int tdb_brlock(struct tdb_context *tdb, tdb_off_t offset, int rw_type, int lck_type, int probe, size_t len);
+-int tdb_transaction_lock(struct tdb_context *tdb, int ltype);
+-int tdb_transaction_unlock(struct tdb_context *tdb);
 -int tdb_brlock_upgrade(struct tdb_context *tdb, tdb_off_t offset, size_t len);
 -int tdb_write_lock_record(struct tdb_context *tdb, tdb_off_t off);
 -int tdb_write_unlock_record(struct tdb_context *tdb, tdb_off_t off);
@@ -33,6 +35,8 @@ Index: tdb/tdb.c
 +static int tdb_lock(struct tdb_context *tdb, int list, int ltype);
 +static int tdb_unlock(struct tdb_context *tdb, int list, int ltype);
 +static int tdb_brlock(struct tdb_context *tdb, tdb_off_t offset, int rw_type, int lck_type, int probe, size_t len);
++static int tdb_transaction_lock(struct tdb_context *tdb, int ltype);
++static int tdb_transaction_unlock(struct tdb_context *tdb);
 +static int tdb_brlock_upgrade(struct tdb_context *tdb, tdb_off_t offset, size_t len);
 +static int tdb_write_lock_record(struct tdb_context *tdb, tdb_off_t off);
 +static int tdb_write_unlock_record(struct tdb_context *tdb, tdb_off_t off);
@@ -59,8 +63,10 @@ Index: tdb/tdb.c
                           struct list_struct *rec);
 -void tdb_io_init(struct tdb_context *tdb);
 -int tdb_expand(struct tdb_context *tdb, tdb_off_t size);
+-int tdb_rec_free_read(struct tdb_context *tdb, tdb_off_t off,
 +static void tdb_io_init(struct tdb_context *tdb);
 +static int tdb_expand(struct tdb_context *tdb, tdb_off_t size);
++static int tdb_rec_free_read(struct tdb_context *tdb, tdb_off_t off,
+                     struct list_struct *rec);
  
  
- /* file: error.c */
index 3743edf..c076c79 100644 (file)
@@ -1,7 +1,7 @@
-Index: tdb/tdbtool.c
+Index: tdbsa/tdbtool.c
 ===================================================================
---- tdb.orig/tdbtool.c 2007-04-04 20:39:28.000000000 -0400
-+++ tdb/tdbtool.c      2007-04-04 20:40:10.000000000 -0400
+--- tdbsa.orig/tdbtool.c
++++ tdbsa/tdbtool.c
 @@ -21,10 +21,21 @@
     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */