Hello,

With the current hurd libc and tdb built with the attached patches,
making it use whole-file locking on platforms which don't support record
locking, tdb works fine, ./bin/tdbtorture -n 10 says "OK", it takes
3m to complete, which is not so bad compared to the 30s it takes with
proper record locking in Linux.

Again, we are fine with a slow tdb: we don't target supporting samba
servers or such, we just want to have tdb basically working, instead
of manually removing it as a dependency from various packages, only to
have to put that back when we have record locking working properly (that
looks like unnecessary work to me). Samba is currently a blocker for
various packages, including mplayer, vlc, kde runtime, etc.

Samuel
Index: tdb-1.3.0/common/lock.c
===================================================================
--- tdb-1.3.0.orig/common/lock.c
+++ tdb-1.3.0/common/lock.c
@@ -47,10 +47,28 @@ static int fcntl_lock(struct tdb_context
        }
 #endif
 
+#ifndef HAVE_FCNTL_LOCK_PARTIAL
+       /* Some platforms (like GNU/Hurd) only support whole file locking */
+       if (rw) {
+               if (tdb->nwr++)
+                       /* Alread WR-locked */
+                       return 0;
+       } else {
+               if (tdb->nrd++ || tdb->nwr)
+                       /* Alread RD or WR-locked */
+                       return 0;
+       }
+#endif
+
        fl.l_type = rw;
        fl.l_whence = SEEK_SET;
+#ifdef HAVE_FCNTL_LOCK_PARTIAL
        fl.l_start = off;
        fl.l_len = len;
+#else
+       fl.l_start = 0;
+       fl.l_len = 0;
+#endif
        fl.l_pid = 0;
 
        cmd = waitflag ? F_SETLKW : F_SETLK;
@@ -128,10 +146,37 @@ static int fcntl_unlock(struct tdb_conte
        }
 #endif
 
+#ifndef HAVE_FCNTL_LOCK_PARTIAL
+       /* Some platforms (like GNU/Hurd) only support whole file locking */
+       if (rw)
+               if (--tdb->nwr)
+                       /* Still WR-locked */
+                       return 0;
+               else if (tdb->nrd)
+                       /* Still RD-locked, downgrade to RD */
+                       fl.l_type = F_RDLCK;
+               else
+                       /* Not locked any more */
+                       fl.l_type = F_UNLCK;
+       else
+               if (--tdb->nrd || tdb->nwr)
+                       /* Still RD or WR-locked */
+                       return 0;
+               else
+                       /* Not locked any more */
+                       fl.l_type = F_UNLCK;
+#else
        fl.l_type = F_UNLCK;
+#endif
+
        fl.l_whence = SEEK_SET;
+#ifdef HAVE_FCNTL_LOCK_PARTIAL
        fl.l_start = off;
        fl.l_len = len;
+#else
+       fl.l_start = 0;
+       fl.l_len = 0;
+#endif
        fl.l_pid = 0;
 
        return fcntl(tdb->fd, F_SETLKW, &fl);
Index: tdb-1.3.0/lib/replace/wscript
===================================================================
--- tdb-1.3.0.orig/lib/replace/wscript
+++ tdb-1.3.0/lib/replace/wscript
@@ -134,6 +134,23 @@ struct foo bar = { .y = 'X', .x = 1 };
                     addmain=False,
                     msg='Checking for O_DIRECT flag to open(2)')
 
+    if conf.CHECK_HEADERS('fcntl.h'):
+        conf.CHECK_CODE('''
+                        #include <fcntl.h>
+                        int main (void) { int fd = open("/dev/null", O_RDWR); 
+                                          struct flock fl;
+                                          fl.l_type = F_WRLCK;
+                                          fl.l_whence = SEEK_SET;
+                                          fl.l_start = fl.l_len = 100;
+                                          fl.l_pid = 0;
+                                          return fcntl(fd, F_SETLK, &fl); }
+                        ''', 
+                        define='HAVE_FCNTL_LOCK_PARTIAL',
+                        addmain=False,
+                        execute=True,
+                        msg='Checking for partial locking support using 
fcntl(2)')
+                                             
+                    
     conf.CHECK_TYPES('"long long" intptr_t uintptr_t ptrdiff_t 
comparison_fn_t')
     conf.CHECK_TYPE('_Bool', define='HAVE__Bool')
     conf.CHECK_TYPE('bool', define='HAVE_BOOL')
Index: tdb-1.3.0/test/run-die-during-transaction.c
===================================================================
--- tdb-1.3.0.orig/test/run-die-during-transaction.c
+++ tdb-1.3.0/test/run-die-during-transaction.c
@@ -218,6 +218,9 @@ int main(int argc, char *argv[])
        struct agent *agent;
        int i;
 
+#ifndef HAVE_FCNTL_LOCK_PARTIAL
+       skip(1, "No partial locking support");
+#else
        plan_tests(12);
        unlock_callback = maybe_die;
 
@@ -227,6 +230,6 @@ int main(int argc, char *argv[])
                diag("Testing %s after death", operation_name(ops[i]));
                ok1(test_death(ops[i], agent));
        }
-
+#endif
        return exit_status();
 }
Index: tdb-1.3.0/test/run-no-lock-during-traverse.c
===================================================================
--- tdb-1.3.0.orig/test/run-no-lock-during-traverse.c
+++ tdb-1.3.0/test/run-no-lock-during-traverse.c
@@ -77,6 +77,9 @@ int main(int argc, char *argv[])
        struct tdb_context *tdb;
        int errors = 0;
 
+#ifndef HAVE_FCNTL_LOCK_PARTIAL
+       skip(1, "No partial locking support");
+#else
        plan_tests(41);
        tdb = tdb_open_ex("run-no-lock-during-traverse.tdb",
                          1024, TDB_CLEAR_IF_FIRST, O_CREAT|O_TRUNC|O_RDWR,
@@ -109,6 +112,7 @@ int main(int argc, char *argv[])
        ok1(tdb_unlockall(tdb) == 0);
 
        ok1(tdb_close(tdb) == 0);
+#endif
 
        return exit_status();
 }
Index: tdb-1.3.0/test/run-nested-traverse.c
===================================================================
--- tdb-1.3.0.orig/test/run-nested-traverse.c
+++ tdb-1.3.0/test/run-nested-traverse.c
@@ -61,6 +61,9 @@ int main(int argc, char *argv[])
        struct tdb_context *tdb;
        TDB_DATA key, data;
 
+#ifndef HAVE_FCNTL_LOCK_PARTIAL
+       skip(1, "No partial locking support");
+#else
        plan_tests(17);
        agent = prepare_external_agent();
 
@@ -83,6 +86,7 @@ int main(int argc, char *argv[])
        tdb_traverse(tdb, traverse1, NULL);
        tdb_traverse_read(tdb, traverse1, NULL);
        tdb_close(tdb);
+#endif
 
        return exit_status();
 }
Index: tdb-1.3.0/test/run-open-during-transaction.c
===================================================================
--- tdb-1.3.0.orig/test/run-open-during-transaction.c
+++ tdb-1.3.0/test/run-open-during-transaction.c
@@ -148,6 +148,9 @@ int main(int argc, char *argv[])
        struct tdb_context *tdb;
        TDB_DATA key, data;
 
+#ifndef HAVE_FCNTL_LOCK_PARTIAL
+       skip(1, "No partial locking support");
+#else
        plan_tests(20);
        agent = prepare_external_agent();
 
@@ -177,6 +180,7 @@ int main(int argc, char *argv[])
                opened = false;
                tdb_close(tdb);
        }
+#endif
 
        return exit_status();
 }
Index: tdb-1.3.0/test/run-marklock-deadlock.c
===================================================================
--- tdb-1.3.0.orig/test/run-marklock-deadlock.c
+++ tdb-1.3.0/test/run-marklock-deadlock.c
@@ -255,6 +255,9 @@ int main(int argc, char *argv[])
        int ret;
        bool mutex_support;
 
+#ifndef HAVE_FCNTL_LOCK_PARTIAL
+       skip(1, "No partial locking support");
+#else
        mutex_support = tdb_runtime_check_for_robust_mutexes();
 
        ret = do_tests("marklock-deadlock-fcntl.tdb",
@@ -273,6 +276,7 @@ int main(int argc, char *argv[])
                       TDB_MUTEX_LOCKING |
                       TDB_INCOMPATIBLE_HASH);
        ok(ret == 0, "marklock-deadlock-mutex.tdb tests should succeed");
+#endif
 
        return exit_status();
 }
Index: tdb-1.3.0/common/tdb_private.h
===================================================================
--- tdb-1.3.0.orig/common/tdb_private.h
+++ tdb-1.3.0/common/tdb_private.h
@@ -201,6 +201,10 @@ struct tdb_context {
        char *name; /* the name of the database */
        void *map_ptr; /* where it is currently mapped */
        int fd; /* open file descriptor for the database */
+#ifndef HAVE_FCNTL_LOCK_PARTIAL
+       int nrd; /* number of RD locks */
+       int nwr; /* number of WR locks */
+#endif
        tdb_len_t map_size; /* how much space has been mapped */
        int read_only; /* opened read-only */
        int traverse_read; /* read-only traversal */
Index: tdb-1.3.0/common/open.c
===================================================================
--- tdb-1.3.0.orig/common/open.c
+++ tdb-1.3.0/common/open.c
@@ -328,6 +328,10 @@ _PUBLIC_ struct tdb_context *tdb_open_ex
 #ifdef TDB_TRACE
        tdb->tracefd = -1;
 #endif
+#ifndef HAVE_FCNTL_LOCK_PARTIAL
+       tdb->nrd = 0;
+       tdb->nwr = 0;
+#endif
        tdb->name = NULL;
        tdb->map_ptr = NULL;
        tdb->flags = tdb_flags;
--- tdb-1.3.0.orig/test/run-traverse-in-transaction.c   2014-11-25 
23:47:30.000000000 +0000
+++ tdb-1.3.0/test/run-traverse-in-transaction.c        2014-11-25 
23:47:45.000000000 +0000
@@ -46,6 +46,9 @@
        struct tdb_context *tdb;
        TDB_DATA key, data;
 
+#ifndef HAVE_FCNTL_LOCK_PARTIAL
+       skip(1, "No partial locking support");
+#else
        plan_tests(13);
        agent = prepare_external_agent();
 
@@ -82,6 +85,7 @@
            == SUCCESS);
 
        tdb_close(tdb);
+#endif
 
        return exit_status();
 }
Index: tdb-1.3.0/common/transaction.c
===================================================================
--- tdb-1.3.0.orig/common/transaction.c
+++ tdb-1.3.0/common/transaction.c
@@ -554,7 +554,7 @@ static int transaction_sync(struct tdb_c
                TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction: fsync 
failed\n"));
                return -1;
        }
-#ifdef HAVE_MMAP
+#if defined(HAVE_MMAP) && defined(HAVE_MSYNC)
        if (tdb->map_ptr) {
                tdb_off_t moffset = offset & ~(tdb->page_size-1);
                if (msync(moffset + (char *)tdb->map_ptr,
Index: tdb-1.3.0/lib/replace/wscript
===================================================================
--- tdb-1.3.0.orig/lib/replace/wscript
+++ tdb-1.3.0/lib/replace/wscript
@@ -310,7 +310,7 @@ struct foo bar = { .y = 'X', .x = 1 };
     conf.CHECK_FUNCS('if_nametoindex strerror_r')
     conf.CHECK_FUNCS('getdirentries getdents syslog')
     conf.CHECK_FUNCS('gai_strerror get_current_dir_name')
-    conf.CHECK_FUNCS('timegm getifaddrs freeifaddrs mmap setgroups syscall 
setsid')
+    conf.CHECK_FUNCS('timegm getifaddrs freeifaddrs mmap msync setgroups 
syscall setsid')
     conf.CHECK_FUNCS('getgrent_r getgrgid_r getgrnam_r getgrouplist 
getpagesize')
     conf.CHECK_FUNCS('getpwent_r getpwnam_r getpwuid_r epoll_create')
 
Index: tdb-1.3.0/test/run-transaction-expand.c
===================================================================
--- tdb-1.3.0.orig/test/run-transaction-expand.c
+++ tdb-1.3.0/test/run-transaction-expand.c
@@ -9,7 +9,7 @@ static inline int fake_fsync(int fd)
 }
 #define fsync fake_fsync
 
-#ifdef MS_SYNC
+#ifdef HAVE_MSYNC
 static inline int fake_msync(void *addr, size_t length, int flags)
 {
        sync_counts++;
Index: tdb-1.3.0/common/io.c
===================================================================
--- tdb-1.3.0.orig/common/io.c
+++ tdb-1.3.0/common/io.c
@@ -295,7 +295,7 @@ int tdb_munmap(struct tdb_context *tdb)
        if (tdb->flags & TDB_INTERNAL)
                return 0;
 
-#ifdef HAVE_MMAP
+#if defined(HAVE_MMAP) && defined(HAVE_MSYNC)
        if (tdb->map_ptr) {
                int ret;
 
@@ -308,6 +308,7 @@ int tdb_munmap(struct tdb_context *tdb)
        return 0;
 }
 
+#ifdef HAVE_MSYNC
 /* If mmap isn't coherent, *everyone* must always mmap. */
 static bool should_mmap(const struct tdb_context *tdb)
 {
@@ -317,13 +318,14 @@ static bool should_mmap(const struct tdb
        return !(tdb->flags & TDB_NOMMAP);
 #endif
 }
+#endif
 
 int tdb_mmap(struct tdb_context *tdb)
 {
        if (tdb->flags & TDB_INTERNAL)
                return 0;
 
-#ifdef HAVE_MMAP
+#if defined(HAVE_MMAP) && defined(HAVE_MSYNC)
        if (should_mmap(tdb)) {
                tdb->map_ptr = mmap(NULL, tdb->map_size,
                                    PROT_READ|(tdb->read_only? 0:PROT_WRITE),

Reply via email to