merge some recent tdb changed from samba3
[samba.git] / source4 / lib / tdb / tdb.c
index 5367842cbba152f7ed1885f492ac8e8d6758ddee..47ba2cb52cd0fa878f8633034e8c66e69268bee0 100644 (file)
@@ -247,10 +247,14 @@ static int tdb_brlock(TDB_CONTEXT *tdb, tdb_off offset,
                                 tdb->fd, offset, rw_type, lck_type));
                        return TDB_ERRCODE(TDB_ERR_LOCK_TIMEOUT, -1);
                }
-               /* Otherwise - generic lock error. */
-               /* errno set by fcntl */
+               /* Otherwise - generic lock error. errno set by fcntl.
+                * EAGAIN is an expected return from non-blocking
+                * locks. */
+               if (errno != EAGAIN) {
                TDB_LOG((tdb, 5, "tdb_brlock failed (fd=%d) at offset %d rw_type=%d lck_type=%d: %s\n", 
-                        tdb->fd, offset, rw_type, lck_type, strerror(errno)));
+                                tdb->fd, offset, rw_type, lck_type, 
+                                strerror(errno)));
+               }
                return TDB_ERRCODE(TDB_ERR_LOCK, -1);
        }
        return 0;
@@ -858,6 +862,8 @@ static tdb_off tdb_allocate(TDB_CONTEXT *tdb, tdb_len length,
        tdb_off rec_ptr, last_ptr, newrec_ptr;
        struct list_struct newrec;
 
+       memset(&newrec, '\0', sizeof(newrec));
+
        if (tdb_lock(tdb, -1, F_WRLCK) == -1)
                return 0;
 
@@ -1706,7 +1712,7 @@ TDB_CONTEXT *tdb_open_ex(const char *name, int hash_size, int tdb_flags,
 {
        TDB_CONTEXT *tdb;
        struct stat st;
-       int rev = 0, locked;
+       int rev = 0, locked = 0;
        unsigned char *vp;
        u32 vertest;
 
@@ -1764,8 +1770,8 @@ TDB_CONTEXT *tdb_open_ex(const char *name, int hash_size, int tdb_flags,
        }
 
        /* we need to zero database if we are the only one with it open */
-       if ((locked = (tdb_brlock(tdb, ACTIVE_LOCK, F_WRLCK, F_SETLK, 0) == 0))
-           && (tdb_flags & TDB_CLEAR_IF_FIRST)) {
+       if ((tdb_flags & TDB_CLEAR_IF_FIRST) &&
+               (locked = (tdb_brlock(tdb, ACTIVE_LOCK, F_WRLCK, F_SETLK, 0) == 0))) {
                open_flags |= O_CREAT;
                if (ftruncate(tdb->fd, 0) == -1) {
                        TDB_LOG((tdb, 0, "tdb_open_ex: "
@@ -1838,10 +1844,19 @@ TDB_CONTEXT *tdb_open_ex(const char *name, int hash_size, int tdb_flags,
                                 name, strerror(errno)));
                        goto fail;
                }
+
        }
+
+       /* We always need to do this if the CLEAR_IF_FIRST flag is set, even if
+          we didn't get the initial exclusive lock as we need to let all other
+          users know we're using it. */
+
+       if (tdb_flags & TDB_CLEAR_IF_FIRST) {
        /* leave this lock in place to indicate it's in use */
        if (tdb_brlock(tdb, ACTIVE_LOCK, F_RDLCK, F_SETLKW, 0) == -1)
                goto fail;
+       }
+
 
  internal:
        /* Internal (memory-only) databases skip all the code above to
@@ -2019,12 +2034,14 @@ void tdb_logging_function(TDB_CONTEXT *tdb, void (*fn)(TDB_CONTEXT *, int , cons
 }
 
 
-/* reopen a tdb - this is used after a fork to ensure that we have an independent
+/* reopen a tdb - this can be used after a fork to ensure that we have an independent
    seek pointer from our parent and to re-establish locks */
 int tdb_reopen(TDB_CONTEXT *tdb)
 {
        struct stat st;
 
+       if (tdb->flags & TDB_INTERNAL)
+               return 0; /* Nothing to do. */
        if (tdb_munmap(tdb) != 0) {
                TDB_LOG((tdb, 0, "tdb_reopen: munmap failed (%s)\n", strerror(errno)));
                goto fail;
@@ -2045,7 +2062,7 @@ int tdb_reopen(TDB_CONTEXT *tdb)
                goto fail;
        }
        tdb_mmap(tdb);
-       if (tdb_brlock(tdb, ACTIVE_LOCK, F_RDLCK, F_SETLKW, 0) == -1) {
+       if ((tdb->flags & TDB_CLEAR_IF_FIRST) && (tdb_brlock(tdb, ACTIVE_LOCK, F_RDLCK, F_SETLKW, 0) == -1)) {
                TDB_LOG((tdb, 0, "tdb_reopen: failed to obtain active lock\n"));
                goto fail;
        }
@@ -2063,7 +2080,10 @@ int tdb_reopen_all(void)
        TDB_CONTEXT *tdb;
 
        for (tdb=tdbs; tdb; tdb = tdb->next) {
-               if (tdb_reopen(tdb) != 0) return -1;
+               /* Ensure no clear-if-first. */
+               tdb->flags &= ~TDB_CLEAR_IF_FIRST;
+               if (tdb_reopen(tdb) != 0)
+                       return -1;
        }
 
        return 0;