tdb: Reimplementation of Metze's "lib/tdb: if we know pwrite and pread are thread...
authorRusty Russell <rusty@rustcorp.com.au>
Thu, 30 Jul 2009 02:22:08 +0000 (11:52 +0930)
committerKarolin Seeger <kseeger@samba.org>
Fri, 14 Aug 2009 08:15:08 +0000 (10:15 +0200)
This version just wraps the reopen code, so we still re-grab the lock and do
the normal sanity checks.

The reason we do this at all is to avoid global fd limits, see:
http://forums.fedoraforum.org/showthread.php?t=210393

Note also that this whole reopen concept is fundamentally racy: if the parent
goes away before the child calls tdb_reopen_all, the database can be left
without an active lock and another TDB_CLEAR_IF_FIRST opener will clear it.
A fork_with_tdbs() wrapper could use a pipe to solve this, but it's hardly
elegant (what if there are other independent things which have similar needs?).

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Signed-off-by: Stefan Metzmacher <metze@samba.org>
(cherry picked from commit 3b2f074bda8734a0b30a3e31117c0217d890809c)

Addresses bug #6601.

lib/tdb/common/open.c

index b19e4cea293df769a588db89c71df25529d677ec..49b8e85f1264f00c57e874916972350712b8a437 100644 (file)
@@ -425,6 +425,9 @@ int tdb_reopen(struct tdb_context *tdb)
                goto fail;
        }
 
+/* If we have real pread & pwrite, we can skip reopen. */
+#if !defined(LIBREPLACE_PREAD_NOT_REPLACED) || \
+       !defined(LIBREPLACE_PWRITE_NOT_REPLACED)
        if (tdb_munmap(tdb) != 0) {
                TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_reopen: munmap failed (%s)\n", strerror(errno)));
                goto fail;
@@ -436,11 +439,6 @@ int tdb_reopen(struct tdb_context *tdb)
                TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_reopen: open failed (%s)\n", strerror(errno)));
                goto fail;
        }
-       if ((tdb->flags & TDB_CLEAR_IF_FIRST) && 
-           (tdb->methods->tdb_brlock(tdb, ACTIVE_LOCK, F_RDLCK, F_SETLKW, 0, 1) == -1)) {
-               TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_reopen: failed to obtain active lock\n"));
-               goto fail;
-       }
        if (fstat(tdb->fd, &st) != 0) {
                TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_reopen: fstat failed (%s)\n", strerror(errno)));
                goto fail;
@@ -450,6 +448,13 @@ int tdb_reopen(struct tdb_context *tdb)
                goto fail;
        }
        tdb_mmap(tdb);
+#endif /* fake pread or pwrite */
+
+       if ((tdb->flags & TDB_CLEAR_IF_FIRST) &&
+           (tdb->methods->tdb_brlock(tdb, ACTIVE_LOCK, F_RDLCK, F_SETLKW, 0, 1) == -1)) {
+               TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_reopen: failed to obtain active lock\n"));
+               goto fail;
+       }
 
        return 0;