dovecot-2.0: mdbox: If flock() isn't available, use dotlock files.

dovecot at dovecot.org dovecot at dovecot.org
Tue Apr 20 18:08:00 EEST 2010


details:   http://hg.dovecot.org/dovecot-2.0/rev/0eff8ef104e6
changeset: 11180:0eff8ef104e6
user:      Timo Sirainen <tss at iki.fi>
date:      Tue Apr 20 18:07:56 2010 +0300
description:
mdbox: If flock() isn't available, use dotlock files.
This allows again using client_limit > 1 without corrupting dbox files.

diffstat:

 src/lib-storage/index/dbox-common/dbox-file.c |  28 +++++++++++++++++++++-------
 src/lib-storage/index/dbox-common/dbox-file.h |  13 +++++++++++++
 2 files changed, 34 insertions(+), 7 deletions(-)

diffs (97 lines):

diff -r 944f4335845f -r 0eff8ef104e6 src/lib-storage/index/dbox-common/dbox-file.c
--- a/src/lib-storage/index/dbox-common/dbox-file.c	Tue Apr 20 18:05:08 2010 +0300
+++ b/src/lib-storage/index/dbox-common/dbox-file.c	Tue Apr 20 18:07:56 2010 +0300
@@ -9,6 +9,7 @@
 #include "istream.h"
 #include "ostream.h"
 #include "file-lock.h"
+#include "file-dotlock.h"
 #include "mkdir-parents.h"
 #include "fdatasync-path.h"
 #include "eacces-error.h"
@@ -24,12 +25,11 @@
 
 #define DBOX_READ_BLOCK_SIZE 4096
 
-/* prefer flock(). fcntl() locking currently breaks if trying to access the
-   same file from multiple mail_storages within same process. */
-#ifdef HAVE_FLOCK
-#  define DBOX_FILE_LOCK_METHOD FILE_LOCK_METHOD_FLOCK
-#else
-#  define DBOX_FILE_LOCK_METHOD FILE_LOCK_METHOD_FCNTL
+#if DBOX_FILE_LOCK_METHOD == FILE_LOCK_METHOD_DOTLOCK
+static const struct dotlock_settings dotlock_set = {
+	.stale_timeout = 60*10,
+	.use_excl_lock = TRUE
+};
 #endif
 
 const char *dbox_generate_tmp_filename(void)
@@ -298,12 +298,21 @@
 
 	i_assert(file->fd != -1);
 
+#if DBOX_FILE_LOCK_METHOD == FILE_LOCK_METHOD_DOTLOCK
+	ret = file_dotlock_create(&dotlock_set, file->cur_path,
+				  DOTLOCK_CREATE_FLAG_NONBLOCK, &file->lock);
+	if (ret < 0) {
+		mail_storage_set_critical(&file->storage->storage,
+			"file_dotlock_create(%s) failed: %m", file->cur_path);
+	}
+#else
 	ret = file_try_lock(file->fd, file->cur_path, F_WRLCK,
 			    DBOX_FILE_LOCK_METHOD, &file->lock);
 	if (ret < 0) {
 		mail_storage_set_critical(&file->storage->storage,
 			"file_try_lock(%s) failed: %m", file->cur_path);
 	}
+#endif
 	return ret;
 }
 
@@ -311,8 +320,13 @@
 {
 	i_assert(!file->appending || file->lock == NULL);
 
-	if (file->lock != NULL)
+	if (file->lock != NULL) {
+#if DBOX_FILE_LOCK_METHOD == FILE_LOCK_METHOD_DOTLOCK
+		(void)file_dotlock_delete(&file->lock);
+#else
 		file_unlock(&file->lock);
+#endif
+	}
 	if (file->input != NULL)
 		i_stream_sync(file->input);
 }
diff -r 944f4335845f -r 0eff8ef104e6 src/lib-storage/index/dbox-common/dbox-file.h
--- a/src/lib-storage/index/dbox-common/dbox-file.h	Tue Apr 20 18:05:08 2010 +0300
+++ b/src/lib-storage/index/dbox-common/dbox-file.h	Tue Apr 20 18:07:56 2010 +0300
@@ -19,6 +19,15 @@
 #define DBOX_MAGIC_PRE "\001\002"
 #define DBOX_MAGIC_POST "\n\001\003\n"
 
+/* prefer flock(). fcntl() locking currently breaks if trying to access the
+   same file from multiple mail_storages within same process. that's why we
+   fallback to dotlocks. */
+#ifdef HAVE_FLOCK
+#  define DBOX_FILE_LOCK_METHOD FILE_LOCK_METHOD_FLOCK
+#else
+#  define DBOX_FILE_LOCK_METHOD FILE_LOCK_METHOD_DOTLOCK
+#endif
+
 struct dbox_file;
 
 enum dbox_header_key {
@@ -97,7 +106,11 @@
 	char *primary_path, *alt_path;
 	int fd;
 	struct istream *input;
+#if DBOX_FILE_LOCK_METHOD == FILE_LOCK_METHOD_DOTLOCK
+	struct dotlock *lock;
+#else
 	struct file_lock *lock;
+#endif
 
 	uoff_t cur_offset;
 	uoff_t cur_physical_size;


More information about the dovecot-cvs mailing list