From: Timo Sirainen Date: Tue, 13 Apr 2010 09:33:17 +0000 (+0300) Subject: dbox: Use flock() for file locking if possible. If not, require client_limit=1. X-Git-Tag: 2.0.beta5~142 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=bca919b207e27d0d08b431bdb0f2ac099ef8b512;p=thirdparty%2Fdovecot%2Fcore.git dbox: Use flock() for file locking if possible. If not, require client_limit=1. Maybe some day dbox code can be redesigned in a way that allows it to work with fcntl() locking too. --HG-- branch : HEAD --- diff --git a/src/lib-storage/index/dbox-common/dbox-file.c b/src/lib-storage/index/dbox-common/dbox-file.c index f474294a76..22eda6bda7 100644 --- a/src/lib-storage/index/dbox-common/dbox-file.c +++ b/src/lib-storage/index/dbox-common/dbox-file.c @@ -24,6 +24,14 @@ #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 +#endif + const char *dbox_generate_tmp_filename(void) { static unsigned int create_count = 0; @@ -291,7 +299,7 @@ int dbox_file_try_lock(struct dbox_file *file) i_assert(file->fd != -1); ret = file_try_lock(file->fd, file->cur_path, F_WRLCK, - FILE_LOCK_METHOD_FCNTL, &file->lock); + 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); diff --git a/src/lib-storage/index/dbox-multi/Makefile.am b/src/lib-storage/index/dbox-multi/Makefile.am index 89dcd34f8b..ccc5d67cb6 100644 --- a/src/lib-storage/index/dbox-multi/Makefile.am +++ b/src/lib-storage/index/dbox-multi/Makefile.am @@ -3,6 +3,7 @@ noinst_LTLIBRARIES = libstorage_dbox_multi.la AM_CPPFLAGS = \ -I$(top_srcdir)/src/lib \ -I$(top_srcdir)/src/lib-settings \ + -I$(top_srcdir)/src/lib-master \ -I$(top_srcdir)/src/lib-mail \ -I$(top_srcdir)/src/lib-imap \ -I$(top_srcdir)/src/lib-index \ diff --git a/src/lib-storage/index/dbox-multi/mdbox-storage.c b/src/lib-storage/index/dbox-multi/mdbox-storage.c index f4fcab0e23..99ce0c93b1 100644 --- a/src/lib-storage/index/dbox-multi/mdbox-storage.c +++ b/src/lib-storage/index/dbox-multi/mdbox-storage.c @@ -4,6 +4,7 @@ #include "array.h" #include "ioloop.h" #include "mkdir-parents.h" +#include "master-service.h" #include "mail-index-modseq.h" #include "mail-index-alloc-cache.h" #include "mailbox-log.h" @@ -46,6 +47,14 @@ mdbox_storage_create(struct mail_storage *_storage, struct mail_namespace *ns, return -1; } +#ifndef HAVE_FLOCK + if (master_service_get_client_limit(master_service) > 1) { + *error_r = "mdbox requires client_limit=1 for service " + "since your OS doesn't support flock()"; + return -1; + } +#endif + _storage->unique_root_dir = p_strdup(_storage->pool, ns->list->set.root_dir); diff --git a/src/lib-storage/index/dbox-single/Makefile.am b/src/lib-storage/index/dbox-single/Makefile.am index e8f54ff663..d810f5b183 100644 --- a/src/lib-storage/index/dbox-single/Makefile.am +++ b/src/lib-storage/index/dbox-single/Makefile.am @@ -3,6 +3,7 @@ noinst_LTLIBRARIES = libstorage_dbox_single.la AM_CPPFLAGS = \ -I$(top_srcdir)/src/lib \ -I$(top_srcdir)/src/lib-settings \ + -I$(top_srcdir)/src/lib-master \ -I$(top_srcdir)/src/lib-mail \ -I$(top_srcdir)/src/lib-imap \ -I$(top_srcdir)/src/lib-index \ diff --git a/src/lib-storage/index/dbox-single/sdbox-storage.c b/src/lib-storage/index/dbox-single/sdbox-storage.c index f315e63180..953cca6550 100644 --- a/src/lib-storage/index/dbox-single/sdbox-storage.c +++ b/src/lib-storage/index/dbox-single/sdbox-storage.c @@ -1,6 +1,7 @@ /* Copyright (c) 2007-2010 Dovecot authors, see the included COPYING file */ #include "lib.h" +#include "master-service.h" #include "mail-index-modseq.h" #include "dbox-mail.h" #include "dbox-save.h" @@ -25,6 +26,21 @@ static struct mail_storage *sdbox_storage_alloc(void) return &storage->storage.storage; } +static int +sdbox_storage_create(struct mail_storage *storage ATTR_UNUSED, + struct mail_namespace *ns ATTR_UNUSED, + const char **error_r ATTR_UNUSED) +{ +#ifndef HAVE_FLOCK + if (master_service_get_client_limit(master_service) > 1) { + *error_r = "dbox requires client_limit=1 for service " + "since your OS doesn't support flock()"; + return -1; + } +#endif + return 0; +} + static struct mailbox * sdbox_mailbox_alloc(struct mail_storage *storage, struct mailbox_list *list, const char *name, enum mailbox_flags flags) @@ -211,7 +227,7 @@ struct mail_storage dbox_storage = { .v = { NULL, sdbox_storage_alloc, - NULL, + sdbox_storage_create, NULL, NULL, dbox_storage_get_list_settings,