]> git.ozlabs.org Git - ccan/commitdiff
tdb2: use 64 bit file offsets on 32 bit systems if available.
authorRusty Russell <rusty@rustcorp.com.au>
Tue, 19 Apr 2011 07:24:41 +0000 (16:54 +0930)
committerRusty Russell <rusty@rustcorp.com.au>
Tue, 19 Apr 2011 07:24:41 +0000 (16:54 +0930)
And testing reveals a latent bug on 32 bit systems.

ccan/tdb2/io.c
ccan/tdb2/private.h
ccan/tdb2/test/run-64-bit-tdb.c [new file with mode: 0644]

index 240a1c038da368c274363cb3cfcd37945a517a0e..31756de341d8fd43d17a41d57c41284cbb650227 100644 (file)
@@ -48,8 +48,13 @@ void tdb_mmap(struct tdb_context *tdb)
        if (tdb->flags & TDB_NOMMAP)
                return;
 
-       tdb->file->map_ptr = mmap(NULL, tdb->file->map_size, tdb->mmap_flags,
-                                 MAP_SHARED, tdb->file->fd, 0);
+       /* size_t can be smaller than off_t. */
+       if ((size_t)tdb->file->map_size == tdb->file->map_size) {
+               tdb->file->map_ptr = mmap(NULL, tdb->file->map_size,
+                                         tdb->mmap_flags,
+                                         MAP_SHARED, tdb->file->fd, 0);
+       } else
+               tdb->file->map_ptr = MAP_FAILED;
 
        /*
         * NB. When mmap fails it returns MAP_FAILED *NOT* NULL !!!!
index cc791b0bb4e3da3226c22862b21d03e32304e931..14d319ce7aa6a128d9630b6676a517a2c0461887 100644 (file)
@@ -19,6 +19,9 @@
 */
 
 #include "config.h"
+#if HAVE_FILE_OFFSET_BITS
+#define _FILE_OFFSET_BITS 64
+#endif
 #include <stdint.h>
 #include <stdbool.h>
 #include <stdlib.h>
diff --git a/ccan/tdb2/test/run-64-bit-tdb.c b/ccan/tdb2/test/run-64-bit-tdb.c
new file mode 100644 (file)
index 0000000..206fc15
--- /dev/null
@@ -0,0 +1,80 @@
+#include <ccan/tdb2/tdb.c>
+#include <ccan/tdb2/open.c>
+#include <ccan/tdb2/free.c>
+#include <ccan/tdb2/lock.c>
+#include <ccan/tdb2/io.c>
+#include <ccan/tdb2/hash.c>
+#include <ccan/tdb2/check.c>
+#include <ccan/tdb2/traverse.c>
+#include <ccan/tdb2/transaction.c>
+#include <ccan/tap/tap.h>
+#include "logging.h"
+
+int main(int argc, char *argv[])
+{
+       unsigned int i;
+       struct tdb_context *tdb;
+       int flags[] = { TDB_DEFAULT, TDB_NOMMAP,
+                       TDB_CONVERT, 
+                       TDB_NOMMAP|TDB_CONVERT };
+
+       if (sizeof(off_t) <= 4) {
+               plan_tests(1);
+               pass("No 64 bit off_t");
+               return exit_status();
+       }
+
+       plan_tests(sizeof(flags) / sizeof(flags[0]) * 14);
+       for (i = 0; i < sizeof(flags) / sizeof(flags[0]); i++) {
+               off_t old_size;
+               TDB_DATA k, d;
+               struct hash_info h;
+               struct tdb_used_record rec;
+               tdb_off_t off;
+
+               tdb = tdb_open("run-64-bit-tdb.tdb", flags[i],
+                              O_RDWR|O_CREAT|O_TRUNC, 0600, &tap_log_attr);
+               ok1(tdb);
+               if (!tdb)
+                       continue;
+
+               old_size = tdb->file->map_size;
+
+               /* This makes a sparse file */
+               ok1(ftruncate(tdb->file->fd, 0xFFFFFFF0) == 0);
+               ok1(add_free_record(tdb, old_size, 0xFFFFFFF0 - old_size,
+                                   TDB_LOCK_WAIT) == TDB_SUCCESS);
+
+               /* Now add a little record past the 4G barrier. */
+               ok1(tdb_expand_file(tdb, 100) == TDB_SUCCESS);
+               ok1(add_free_record(tdb, 0xFFFFFFF0, 100, TDB_LOCK_WAIT)
+                   == TDB_SUCCESS);
+
+               ok1(tdb_check(tdb, NULL, NULL) == TDB_SUCCESS);
+
+               /* Test allocation path. */
+               k = tdb_mkdata("key", 4);
+               d = tdb_mkdata("data", 5);
+               ok1(tdb_store(tdb, k, d, TDB_INSERT) == 0);
+               ok1(tdb_check(tdb, NULL, NULL) == TDB_SUCCESS);
+
+               /* Make sure it put it at end as we expected. */
+               off = find_and_lock(tdb, k, F_RDLCK, &h, &rec, NULL);
+               ok1(off >= 0xFFFFFFF0);
+               tdb_unlock_hashes(tdb, h.hlock_start, h.hlock_range, F_RDLCK);
+
+               ok1(tdb_fetch(tdb, k, &d) == 0);
+               ok1(d.dsize == 5);
+               ok1(strcmp((char *)d.dptr, "data") == 0);
+               free(d.dptr);
+
+               ok1(tdb_delete(tdb, k) == 0);
+               ok1(tdb_check(tdb, NULL, NULL) == TDB_SUCCESS);
+
+               tdb_close(tdb);
+       }
+
+       /* We might get messages about mmap failing, so don't test
+        * tap_log_messages */
+       return exit_status();
+}