From fd8b93ca5cbeba64fe6fa5dc98a3e580fb046791 Mon Sep 17 00:00:00 2001 From: Timo Sirainen Date: Thu, 22 Jun 2017 01:28:57 +0300 Subject: [PATCH] lib-storage: Add VOLATILEDIR setting to mail_location This is useful for creating temporary locks that could exist in tmpfs. Currently this is used for .vsize.lock and dovecot.autoexpunge.lock. --- src/lib-storage/mail-storage.c | 23 ++++++++++++++++++++++- src/lib-storage/mail-user.c | 12 +++++++++++- src/lib-storage/mailbox-list.c | 4 ++++ src/lib-storage/mailbox-list.h | 5 +++++ 4 files changed, 42 insertions(+), 2 deletions(-) diff --git a/src/lib-storage/mail-storage.c b/src/lib-storage/mail-storage.c index 1130e1f944..832b58d13d 100644 --- a/src/lib-storage/mail-storage.c +++ b/src/lib-storage/mail-storage.c @@ -6,7 +6,9 @@ #include "llist.h" #include "str.h" #include "str-sanitize.h" +#include "sha1.h" #include "unichar.h" +#include "hex-binary.h" #include "file-create-locked.h" #include "istream.h" #include "eacces-error.h" @@ -2787,7 +2789,26 @@ int mailbox_lock_file_create(struct mailbox *box, const char *lock_fname, set.gid = perm->file_create_gid; set.gid_origin = perm->file_create_gid_origin; - lock_path = t_strdup_printf("%s/%s", box->index->dir, lock_fname); + if (box->list->set.volatile_dir == NULL) + lock_path = t_strdup_printf("%s/%s", box->index->dir, lock_fname); + else { + unsigned char box_name_sha1[SHA1_RESULTLEN]; + string_t *str = t_str_new(128); + + /* Keep this simple: Use the lock_fname with a SHA1 of the + mailbox name as the suffix. The mailbox name itself could + be too large as a filename and creating the full directory + structure would be pretty troublesome. It would also make + it more difficult to perform the automated deletion of empty + lock directories. */ + str_printfa(str, "%s/%s.", box->list->set.volatile_dir, + lock_fname); + sha1_get_digest(box->name, strlen(box->name), box_name_sha1); + binary_to_hex_append(str, box_name_sha1, sizeof(box_name_sha1)); + lock_path = str_c(str); + set.mkdir_mode = 0700; + } + if (file_create_locked(lock_path, &set, lock_r, &created, error_r) == -1) { *error_r = t_strdup_printf("file_create_locked(%s) failed: %s", lock_path, *error_r); diff --git a/src/lib-storage/mail-user.c b/src/lib-storage/mail-user.c index b84113b24c..ca04e31180 100644 --- a/src/lib-storage/mail-user.c +++ b/src/lib-storage/mail-user.c @@ -23,6 +23,7 @@ #include "mail-storage-service.h" #include "mail-namespace.h" #include "mail-storage.h" +#include "mailbox-list-private.h" #include "mail-autoexpunge.h" #include "mail-user.h" @@ -564,7 +565,16 @@ int mail_user_lock_file_create(struct mail_user *user, const char *lock_fname, .lock_timeout_secs = lock_secs, .lock_method = mail_set->parsed_lock_method, }; - path = t_strdup_printf("%s/%s", home, lock_fname); + struct mailbox_list *inbox_list = + mail_namespace_find_inbox(user->namespaces)->list; + if (inbox_list->set.volatile_dir == NULL) + path = t_strdup_printf("%s/%s", home, lock_fname); + else { + path = t_strdup_printf("%s/%s", inbox_list->set.volatile_dir, + lock_fname); + lock_set.mkdir_mode = 0700; + } + if (file_create_locked(path, &lock_set, lock_r, &created, &error) == -1) { *error_r = t_strdup_printf("file_create_locked(%s) failed: %s", path, error); return errno == EAGAIN ? 0 : -1; diff --git a/src/lib-storage/mailbox-list.c b/src/lib-storage/mailbox-list.c index 9c7ce2e6b9..2873cbfe38 100644 --- a/src/lib-storage/mailbox-list.c +++ b/src/lib-storage/mailbox-list.c @@ -4,6 +4,7 @@ #include "array.h" #include "path-util.h" #include "ioloop.h" +#include "file-create-locked.h" #include "mkdir-parents.h" #include "str.h" #include "sha1.h" @@ -171,6 +172,7 @@ int mailbox_list_create(const char *driver, struct mail_namespace *ns, p_strdup(list->pool, set->mailbox_dir_name); list->set.alt_dir = p_strdup(list->pool, set->alt_dir); list->set.alt_dir_nocheck = set->alt_dir_nocheck; + list->set.volatile_dir = p_strdup(list->pool, set->volatile_dir); list->set.index_control_use_maildir_name = set->index_control_use_maildir_name; @@ -336,6 +338,8 @@ mailbox_list_settings_parse_full(struct mail_user *user, const char *data, dest = &set_r->maildir_name; else if (strcmp(key, "MAILBOXDIR") == 0) dest = &set_r->mailbox_dir_name; + else if (strcmp(key, "VOLATILEDIR") == 0) + dest = &set_r->volatile_dir; else if (strcmp(key, "LISTINDEX") == 0) dest = &set_r->list_index_fname; else if (strcmp(key, "FULLDIRNAME") == 0) { diff --git a/src/lib-storage/mailbox-list.h b/src/lib-storage/mailbox-list.h index b6835d03de..3232e17260 100644 --- a/src/lib-storage/mailbox-list.h +++ b/src/lib-storage/mailbox-list.h @@ -98,6 +98,11 @@ struct mailbox_list_settings { const char *index_pvt_dir; const char *control_dir; const char *alt_dir; /* FIXME: dbox-specific.. */ + /* Backend-local directory where volatile data, such as lock files, + can be temporarily created. This setting allows specifying a + separate directory for them to reduce disk I/O on the real storage. + The volatile_dir can point to an in-memory filesystem. */ + const char *volatile_dir; const char *inbox_path; const char *subscription_fname;