[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Re: Bug#759008: libtdb1: FTBFS on hurd-i386



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 to: