]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
mdbox: If flock() isn't available, use dotlock files.
authorTimo Sirainen <tss@iki.fi>
Tue, 20 Apr 2010 15:07:56 +0000 (18:07 +0300)
committerTimo Sirainen <tss@iki.fi>
Tue, 20 Apr 2010 15:07:56 +0000 (18:07 +0300)
This allows again using client_limit > 1 without corrupting dbox files.

--HG--
branch : HEAD

src/lib-storage/index/dbox-common/dbox-file.c
src/lib-storage/index/dbox-common/dbox-file.h

index 22eda6bda79031c6abab8f1012f69424388f2aec..40402c5c080cc47af47721d4b64abf1df19bca2a 100644 (file)
@@ -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"
 
 #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 @@ int dbox_file_try_lock(struct dbox_file *file)
 
        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 @@ void dbox_file_unlock(struct dbox_file *file)
 {
        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);
 }
index 8fefa95c9561b7b5bf817f67fc9e234f6b9259a8..1476a2be030445de420c4bfb3535920480fbe388 100644 (file)
 #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 @@ struct dbox_file {
        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;