diff -r 6137bc40962e src/lib-index/mail-index-view.c --- a/src/lib-index/mail-index-view.c Wed Mar 04 18:24:41 2009 -0500 +++ b/src/lib-index/mail-index-view.c Wed Mar 04 19:23:43 2009 -0500 @@ -333,25 +333,30 @@ } } +static const void * +view_map_lookup_ext_full(struct mail_index_map *map, + const struct mail_index_record *rec, uint32_t ext_id) +{ + const struct mail_index_ext *ext; + uint32_t idx; + + if (!mail_index_map_get_ext_idx(map, ext_id, &idx)) + return NULL; + + ext = array_idx(&map->extensions, idx); + return ext->record_offset == 0 ? NULL : + CONST_PTR_OFFSET(rec, ext->record_offset); +} + static void view_lookup_ext_full(struct mail_index_view *view, uint32_t seq, uint32_t ext_id, struct mail_index_map **map_r, const void **data_r, bool *expunged_r) { - const struct mail_index_ext *ext; const struct mail_index_record *rec; - uint32_t idx, offset; rec = view->v.lookup_full(view, seq, map_r, expunged_r); - if (!mail_index_map_get_ext_idx(*map_r, ext_id, &idx)) { - *data_r = NULL; - return; - } - - ext = array_idx(&(*map_r)->extensions, idx); - offset = ext->record_offset; - - *data_r = offset == 0 ? NULL : CONST_PTR_OFFSET(rec, offset); + *data_r = view_map_lookup_ext_full(*map_r, rec, ext_id); } static void view_get_header_ext(struct mail_index_view *view, @@ -443,30 +448,25 @@ return expunged; } -void mail_index_lookup_keywords(struct mail_index_view *view, uint32_t seq, - ARRAY_TYPE(keyword_indexes) *keyword_idx) +static void +mail_index_lookup_map_keywords(struct mail_index_view *view, + struct mail_index_map *map, + const unsigned char *keyword_data, + ARRAY_TYPE(keyword_indexes) *keyword_idx) { - struct mail_index_map *map; - const void *data; - const unsigned char *keyword_data; const unsigned int *keyword_idx_map; unsigned int i, j, keyword_count, index_idx; - uint32_t ext_id, idx; + uint32_t idx; uint16_t record_size; array_clear(keyword_idx); - - /* get the keywords data. */ - ext_id = view->index->keywords_ext_id; - mail_index_lookup_ext_full(view, seq, ext_id, &map, &data, NULL); - if (data == NULL) { + if (keyword_data == NULL) { /* no keywords at all in index */ return; } - keyword_data = data; - (void)mail_index_ext_get_size(view, ext_id, map, NULL, - &record_size, NULL); + (void)mail_index_ext_get_size(view, view->index->keywords_ext_id, + map, NULL, &record_size, NULL); /* keyword_idx_map[] contains file => index keyword mapping */ if (!array_is_created(&map->keyword_idx_map)) @@ -493,6 +493,35 @@ array_append(keyword_idx, &index_idx, 1); } } +} + +void mail_index_lookup_keywords(struct mail_index_view *view, uint32_t seq, + ARRAY_TYPE(keyword_indexes) *keyword_idx) +{ + struct mail_index_map *map; + const void *data; + + mail_index_lookup_ext_full(view, seq, view->index->keywords_ext_id, + &map, &data, NULL); + mail_index_lookup_map_keywords(view, map, data, keyword_idx); +} + +void mail_index_lookup_view_flags(struct mail_index_view *view, uint32_t seq, + enum mail_flags *flags_r, + ARRAY_TYPE(keyword_indexes) *keyword_idx) +{ + const struct mail_index_record *rec; + const unsigned char *keyword_data; + + i_assert(seq > 0 && seq <= mail_index_view_get_messages_count(view)); + + rec = MAIL_INDEX_MAP_IDX(view->map, seq-1); + *flags_r = rec->flags; + + keyword_data = view_map_lookup_ext_full(view->map, rec, + view->index->keywords_ext_id); + mail_index_lookup_map_keywords(view, view->map, keyword_data, + keyword_idx); } void mail_index_lookup_uid(struct mail_index_view *view, uint32_t seq, diff -r 6137bc40962e src/lib-index/mail-index.h --- a/src/lib-index/mail-index.h Wed Mar 04 18:24:41 2009 -0500 +++ b/src/lib-index/mail-index.h Wed Mar 04 19:23:43 2009 -0500 @@ -325,6 +325,12 @@ /* Note that returned keyword indexes aren't sorted. */ void mail_index_lookup_keywords(struct mail_index_view *view, uint32_t seq, ARRAY_TYPE(keyword_indexes) *keyword_idx); +/* mail_index_lookup[_keywords]() returns the latest flag changes. + This function instead attempts to return the flags and keywords done by the + last view sync. */ +void mail_index_lookup_view_flags(struct mail_index_view *view, uint32_t seq, + enum mail_flags *flags_r, + ARRAY_TYPE(keyword_indexes) *keyword_idx); /* Returns the UID for given message. May be slightly faster than mail_index_lookup()->uid. */ void mail_index_lookup_uid(struct mail_index_view *view, uint32_t seq, diff -r 6137bc40962e src/lib-storage/index/maildir/maildir-keywords.c --- a/src/lib-storage/index/maildir/maildir-keywords.c Wed Mar 04 18:24:41 2009 -0500 +++ b/src/lib-storage/index/maildir/maildir-keywords.c Wed Mar 04 19:23:43 2009 -0500 @@ -47,6 +47,7 @@ const ARRAY_TYPE(keywords) *keywords; ARRAY_DEFINE(idx_to_chr, char); unsigned int chridx_to_idx[MAILDIR_MAX_KEYWORDS]; + bool readonly; }; struct maildir_keywords *maildir_keywords_init(struct maildir_mailbox *mbox) @@ -190,27 +191,30 @@ } static int -maildir_keywords_lookup(struct maildir_keywords *mk, const char *name) +maildir_keywords_lookup(struct maildir_keywords *mk, const char *name, + unsigned int *chridx_r) { void *p; - i_assert(mk->mbox == NULL || + i_assert(mk->mbox == NULL || mk->mbox->very_dirty_syncs || maildir_uidlist_is_locked(mk->mbox->uidlist)); p = hash_lookup(mk->hash, name); if (p == NULL) { if (mk->synced) - return -1; + return 0; if (maildir_keywords_sync(mk) < 0) return -1; + i_assert(mk->synced); p = hash_lookup(mk->hash, name); if (p == NULL) - return -1; + return 0; } - return POINTER_CAST_TO(p, int)-1; + *chridx_r = POINTER_CAST_TO(p, int)-1; + return 1; } static void @@ -232,19 +236,15 @@ } static int -maildir_keywords_lookup_or_create(struct maildir_keywords *mk, const char *name) +maildir_keywords_lookup_or_create(struct maildir_keywords *mk, const char *name, + unsigned int *chridx_r) { const char *const *keywords; unsigned int i, count; - int idx; + int ret; - idx = maildir_keywords_lookup(mk, name); - if (idx >= 0) - return idx; - if (!mk->synced) { - /* we couldn't open the dovecot-keywords file. */ - return -1; - } + if ((ret = maildir_keywords_lookup(mk, name, chridx_r)) != 0) + return ret; /* see if we are full */ keywords = array_get(&mk->list, &count); @@ -254,10 +254,11 @@ } if (i == count && count >= MAILDIR_MAX_KEYWORDS) - return -1; + return 0; - maildir_keywords_create(mk, name, i); - return i; + maildir_keywords_create(mk, name, i); + *chridx_r = i; + return 1; } static const char * @@ -276,6 +277,7 @@ if (maildir_keywords_sync(mk) < 0) return NULL; + i_assert(mk->synced); keywords = array_get(&mk->list, &count); } @@ -406,6 +408,17 @@ return ctx; } +struct maildir_keywords_sync_ctx * +maildir_keywords_sync_init_readonly(struct maildir_keywords *mk, + struct mail_index *index) +{ + struct maildir_keywords_sync_ctx *ctx; + + ctx = maildir_keywords_sync_init(mk, index); + ctx->readonly = TRUE; + return ctx; +} + void maildir_keywords_sync_deinit(struct maildir_keywords_sync_ctx **_ctx) { struct maildir_keywords_sync_ctx *ctx = *_ctx; @@ -438,7 +451,7 @@ if (name == NULL) { /* name is lost. just generate one ourself. */ name = t_strdup_printf("unknown-%u", chridx); - while (maildir_keywords_lookup(ctx->mk, name) >= 0) { + while (maildir_keywords_lookup(ctx->mk, name, &idx) > 0) { /* don't create a duplicate name. keep changing the name until it doesn't exist */ name = t_strconcat(name, "?", NULL); @@ -456,15 +469,18 @@ { const char *const *name_p; char *chr_p; - int chridx; + unsigned int chridx; + int ret; chr_p = array_idx_modifiable(&ctx->idx_to_chr, idx); if (*chr_p != '\0') return *chr_p; name_p = array_idx(ctx->keywords, idx); - chridx = maildir_keywords_lookup_or_create(ctx->mk, *name_p); - if (chridx < 0) + ret = !ctx->readonly ? + maildir_keywords_lookup_or_create(ctx->mk, *name_p, &chridx) : + maildir_keywords_lookup(ctx->mk, *name_p, &chridx); + if (ret <= 0) return '\0'; *chr_p = chridx + MAILDIR_KEYWORD_FIRST; diff -r 6137bc40962e src/lib-storage/index/maildir/maildir-keywords.h --- a/src/lib-storage/index/maildir/maildir-keywords.h Wed Mar 04 18:24:41 2009 -0500 +++ b/src/lib-storage/index/maildir/maildir-keywords.h Wed Mar 04 19:23:43 2009 -0500 @@ -19,6 +19,10 @@ struct maildir_keywords_sync_ctx * maildir_keywords_sync_init(struct maildir_keywords *mk, struct mail_index *index); +/* Don't try to add any nonexisting keywords */ +struct maildir_keywords_sync_ctx * +maildir_keywords_sync_init_readonly(struct maildir_keywords *mk, + struct mail_index *index); void maildir_keywords_sync_deinit(struct maildir_keywords_sync_ctx **ctx); /* Returns keyword index. */ diff -r 6137bc40962e src/lib-storage/index/maildir/maildir-storage.c --- a/src/lib-storage/index/maildir/maildir-storage.c Wed Mar 04 18:24:41 2009 -0500 +++ b/src/lib-storage/index/maildir/maildir-storage.c Wed Mar 04 19:23:43 2009 -0500 @@ -427,6 +427,7 @@ index = index_storage_alloc(&storage->storage, name, flags, MAILDIR_INDEX_PREFIX); mbox->ibox.index = index; + mbox->very_dirty_syncs = getenv("MAILDIR_VERY_DIRTY_SYNCS") != NULL; /* for shared mailboxes get the create mode from the permissions of dovecot-shared file. */ @@ -860,6 +861,8 @@ timeout_remove(&mbox->keep_lock_to); } + if (mbox->flags_view != NULL) + mail_index_view_close(&mbox->flags_view); if (mbox->keywords != NULL) maildir_keywords_deinit(&mbox->keywords); maildir_uidlist_deinit(&mbox->uidlist); diff -r 6137bc40962e src/lib-storage/index/maildir/maildir-storage.h --- a/src/lib-storage/index/maildir/maildir-storage.h Wed Mar 04 18:24:41 2009 -0500 +++ b/src/lib-storage/index/maildir/maildir-storage.h Wed Mar 04 19:23:43 2009 -0500 @@ -82,6 +82,7 @@ struct maildir_mailbox { struct index_mailbox ibox; struct maildir_storage *storage; + struct mail_index_view *flags_view; const char *path; struct timeout *keep_lock_to; @@ -94,6 +95,7 @@ uint32_t maildir_ext_id; unsigned int syncing_commit:1; + unsigned int very_dirty_syncs:1; }; struct maildir_transaction_context { diff -r 6137bc40962e src/lib-storage/index/maildir/maildir-sync-index.c --- a/src/lib-storage/index/maildir/maildir-sync-index.c Wed Mar 04 18:24:41 2009 -0500 +++ b/src/lib-storage/index/maildir/maildir-sync-index.c Wed Mar 04 19:23:43 2009 -0500 @@ -385,6 +385,8 @@ uint32_t first_uid; unsigned int changes = 0; int ret = 0; + time_t time_before_sync; + struct stat st; bool expunged, full_rescan = FALSE; i_assert(!mbox->syncing_commit); @@ -411,6 +413,7 @@ } hdr_next_uid = hdr->next_uid; + time_before_sync = time(NULL); mbox->syncing_commit = TRUE; seq = prev_uid = 0; first_recent_uid = I_MAX(hdr->first_recent_uid, 1); t_array_init(&ctx->keywords, MAILDIR_MAX_KEYWORDS); @@ -556,8 +559,12 @@ if (mbox->ibox.box.v.sync_notify != NULL) mbox->ibox.box.v.sync_notify(&mbox->ibox.box, 0, 0); - if (ctx->changed) - mbox->maildir_hdr.cur_mtime = time(NULL); + if (stat(t_strconcat(mbox->path, "/cur", NULL), &st) == 0) { + mbox->maildir_hdr.new_check_time = + I_MAX(st.st_mtime, time_before_sync); + mbox->maildir_hdr.cur_mtime = st.st_mtime; + mbox->maildir_hdr.cur_mtime_nsecs = ST_MTIME_NSEC(st); + } if (uid_validity == 0) { uid_validity = hdr->uid_validity != 0 ? hdr->uid_validity : diff -r 6137bc40962e src/lib-storage/index/maildir/maildir-sync.c --- a/src/lib-storage/index/maildir/maildir-sync.c Wed Mar 04 18:24:41 2009 -0500 +++ b/src/lib-storage/index/maildir/maildir-sync.c Wed Mar 04 19:23:43 2009 -0500 @@ -494,10 +494,23 @@ } if (dir_changed) { - if (new_dir) - ctx->mbox->maildir_hdr.new_mtime = now; - else - ctx->mbox->maildir_hdr.cur_mtime = now; + /* save the exact new times. the new mtimes should be >= + "now", but just in case something weird happens and mtime + doesn't update, use "now". */ + if (stat(ctx->new_dir, &st) == 0) { + ctx->mbox->maildir_hdr.new_check_time = + I_MAX(st.st_mtime, now); + ctx->mbox->maildir_hdr.new_mtime = st.st_mtime; + ctx->mbox->maildir_hdr.new_mtime_nsecs = + ST_MTIME_NSEC(st); + } + if (stat(ctx->cur_dir, &st) == 0) { + ctx->mbox->maildir_hdr.new_check_time = + I_MAX(st.st_mtime, now); + ctx->mbox->maildir_hdr.cur_mtime = st.st_mtime; + ctx->mbox->maildir_hdr.cur_mtime_nsecs = + ST_MTIME_NSEC(st); + } } return ret < 0 ? -1 : @@ -558,7 +571,7 @@ /* try to avoid stat()ing by first checking delayed changes */ if (DIR_DELAYED_REFRESH(hdr, new) || - DIR_DELAYED_REFRESH(hdr, cur)) { + (DIR_DELAYED_REFRESH(hdr, cur) && !mbox->very_dirty_syncs)) { /* refresh index and try again */ if (maildir_sync_header_refresh(mbox) < 0) return -1; @@ -566,7 +579,7 @@ if (DIR_DELAYED_REFRESH(hdr, new)) *new_changed_r = TRUE; - if (DIR_DELAYED_REFRESH(hdr, cur)) + if (DIR_DELAYED_REFRESH(hdr, cur) && !mbox->very_dirty_syncs) *cur_changed_r = TRUE; if (*new_changed_r && *cur_changed_r) return 0; @@ -870,6 +883,32 @@ } } + if (mbox->very_dirty_syncs) { + struct mail_index_view_sync_ctx *sync_ctx; + + if (mbox->flags_view == NULL) { + mbox->flags_view = + mail_index_view_open(mbox->ibox.index); + } + if (mail_index_view_sync_begin(mbox->flags_view, + MAIL_INDEX_VIEW_SYNC_FLAG_FIX_INCONSISTENT, + &sync_ctx) < 0 || + mail_index_view_sync_commit(&sync_ctx) < 0) { + mail_storage_set_index_error(&mbox->ibox); + ret = -1; + } + /* make sure the map stays in private memory */ + if (mbox->flags_view->map->refcount > 1) { + struct mail_index_map *map; + + map = mail_index_map_clone(mbox->flags_view->map); + mail_index_unmap(&mbox->flags_view->map); + mbox->flags_view->map = map; + } + mail_index_record_map_move_to_private(mbox->flags_view->map); + mail_index_map_move_to_memory(mbox->flags_view->map); + maildir_uidlist_set_all_nonsynced(mbox->uidlist); + } return index_mailbox_sync_init(box, flags, ret < 0); } diff -r 6137bc40962e src/lib-storage/index/maildir/maildir-uidlist.c --- a/src/lib-storage/index/maildir/maildir-uidlist.c Wed Mar 04 18:24:41 2009 -0500 +++ b/src/lib-storage/index/maildir/maildir-uidlist.c Wed Mar 04 19:23:43 2009 -0500 @@ -1298,6 +1298,11 @@ } } +void maildir_uidlist_set_all_nonsynced(struct maildir_uidlist *uidlist) +{ + maildir_uidlist_mark_all(uidlist, TRUE); +} + int maildir_uidlist_sync_init(struct maildir_uidlist *uidlist, enum maildir_uidlist_sync_flags sync_flags, struct maildir_uidlist_sync_ctx **sync_ctx_r) diff -r 6137bc40962e src/lib-storage/index/maildir/maildir-uidlist.h --- a/src/lib-storage/index/maildir/maildir-uidlist.h Wed Mar 04 18:24:41 2009 -0500 +++ b/src/lib-storage/index/maildir/maildir-uidlist.h Wed Mar 04 19:23:43 2009 -0500 @@ -92,6 +92,7 @@ maildir_uidlist_set_ext() */ int maildir_uidlist_update(struct maildir_uidlist *uidlist); +void maildir_uidlist_set_all_nonsynced(struct maildir_uidlist *uidlist); /* Sync uidlist with what's actually on maildir. Returns same as maildir_uidlist_lock(). */ int maildir_uidlist_sync_init(struct maildir_uidlist *uidlist, diff -r 6137bc40962e src/lib-storage/index/maildir/maildir-util.c --- a/src/lib-storage/index/maildir/maildir-util.c Wed Mar 04 18:24:41 2009 -0500 +++ b/src/lib-storage/index/maildir/maildir-util.c Wed Mar 04 19:23:43 2009 -0500 @@ -1,11 +1,14 @@ /* Copyright (c) 2004-2009 Dovecot authors, see the included COPYING file */ #include "lib.h" +#include "array.h" #include "ioloop.h" #include "str.h" #include "mkdir-parents.h" #include "maildir-storage.h" #include "maildir-uidlist.h" +#include "maildir-keywords.h" +#include "maildir-filename.h" #include "maildir-sync.h" #include @@ -16,35 +19,69 @@ #define MAILDIR_RESYNC_RETRY_COUNT 10 +static const char * +maildir_filename_guess(struct maildir_mailbox *mbox, uint32_t uid, + const char *fname, bool *have_flags_r) + +{ + struct mail_index_view *view = mbox->flags_view; + struct maildir_keywords_sync_ctx *kw_ctx; + enum mail_flags flags; + ARRAY_TYPE(keyword_indexes) keywords; + uint32_t seq; + + if (view == NULL || !mail_index_lookup_seq(view, uid, &seq)) { + *have_flags_r = FALSE; + return fname; + } + + t_array_init(&keywords, 32); + mail_index_lookup_view_flags(view, seq, &flags, &keywords); + if (array_count(&keywords) == 0) { + *have_flags_r = (flags & MAIL_FLAGS_NONRECENT) != 0; + fname = maildir_filename_set_flags(NULL, fname, flags, NULL); + } else { + *have_flags_r = TRUE; + kw_ctx = maildir_keywords_sync_init_readonly(mbox->keywords, + mbox->ibox.index); + fname = maildir_filename_set_flags(kw_ctx, fname, + flags, &keywords); + maildir_keywords_sync_deinit(&kw_ctx); + } + return fname; +} + static int maildir_file_do_try(struct maildir_mailbox *mbox, uint32_t uid, maildir_file_do_func *callback, void *context) { - const char *fname; - enum maildir_uidlist_rec_flag flags; + const char *path, *fname; + enum maildir_uidlist_rec_flag flags; + bool have_flags; int ret; fname = maildir_uidlist_lookup(mbox->uidlist, uid, &flags); if (fname == NULL) return -2; /* expunged */ + if ((flags & MAILDIR_UIDLIST_REC_FLAG_NONSYNCED) != 0) { + /* let's see if we can guess the filename based on index */ + fname = maildir_filename_guess(mbox, uid, fname, &have_flags); + if (have_flags) { + /* don't even bother looking into new/ dir */ + flags &= MAILDIR_UIDLIST_REC_FLAG_NEW_DIR; + } + } + if ((flags & MAILDIR_UIDLIST_REC_FLAG_NEW_DIR) != 0) { /* probably in new/ dir */ - T_BEGIN { - const char *path; - - path = t_strconcat(mbox->path, "/new/", fname, NULL); - ret = callback(mbox, path, context); - } T_END; + path = t_strconcat(mbox->path, "/new/", fname, NULL); + ret = callback(mbox, path, context); if (ret != 0) return ret; } - T_BEGIN { - const char *path; - - path = t_strconcat(mbox->path, "/cur/", fname, NULL); - ret = callback(mbox, path, context); - } T_END; + path = t_strconcat(mbox->path, "/cur/", fname, NULL); + ret = callback(mbox, path, context); return ret; } @@ -71,7 +108,9 @@ { int i, ret; - ret = maildir_file_do_try(mbox, uid, callback, context); + T_BEGIN { + ret = maildir_file_do_try(mbox, uid, callback, context); + } T_END; for (i = 0; i < MAILDIR_RESYNC_RETRY_COUNT && ret == 0; i++) { /* file is either renamed or deleted. sync the maildir and see which one. if file appears to be renamed constantly, @@ -79,11 +118,14 @@ if (maildir_storage_sync_force(mbox, uid) < 0) return -1; - ret = maildir_file_do_try(mbox, uid, callback, context); + T_BEGIN { + ret = maildir_file_do_try(mbox, uid, callback, context); + } T_END; } - if (i == MAILDIR_RESYNC_RETRY_COUNT) + if (i == MAILDIR_RESYNC_RETRY_COUNT) T_BEGIN { ret = maildir_file_do_try(mbox, uid, do_racecheck, context); + } T_END; return ret == -2 ? 0 : ret; } diff -r 6137bc40962e src/master/mail-process.c --- a/src/master/mail-process.c Wed Mar 04 18:24:41 2009 -0500 +++ b/src/master/mail-process.c Wed Mar 04 19:23:43 2009 -0500 @@ -357,6 +357,8 @@ env_put("MAILDIR_COPY_WITH_HARDLINKS=1"); if (set->maildir_copy_preserve_filename) env_put("MAILDIR_COPY_PRESERVE_FILENAME=1"); + if (set->maildir_very_dirty_syncs) + env_put("MAILDIR_VERY_DIRTY_SYNCS=1"); if (set->mail_debug) env_put("DEBUG=1"); if (set->mail_full_filesystem_access) diff -r 6137bc40962e src/master/master-settings-defs.c --- a/src/master/master-settings-defs.c Wed Mar 04 18:24:41 2009 -0500 +++ b/src/master/master-settings-defs.c Wed Mar 04 19:23:43 2009 -0500 @@ -88,6 +88,7 @@ DEF_BOOL(maildir_stat_dirs), DEF_BOOL(maildir_copy_with_hardlinks), DEF_BOOL(maildir_copy_preserve_filename), + DEF_BOOL(maildir_very_dirty_syncs), DEF_STR(mbox_read_locks), DEF_STR(mbox_write_locks), DEF_INT(mbox_lock_timeout), diff -r 6137bc40962e src/master/master-settings.c --- a/src/master/master-settings.c Wed Mar 04 18:24:41 2009 -0500 +++ b/src/master/master-settings.c Wed Mar 04 19:23:43 2009 -0500 @@ -254,6 +254,7 @@ MEMBER(maildir_stat_dirs) FALSE, MEMBER(maildir_copy_with_hardlinks) TRUE, MEMBER(maildir_copy_preserve_filename) FALSE, + MEMBER(maildir_very_dirty_syncs) FALSE, MEMBER(mbox_read_locks) "fcntl", MEMBER(mbox_write_locks) "dotlock fcntl", MEMBER(mbox_lock_timeout) 300, diff -r 6137bc40962e src/master/master-settings.h --- a/src/master/master-settings.h Wed Mar 04 18:24:41 2009 -0500 +++ b/src/master/master-settings.h Wed Mar 04 19:23:43 2009 -0500 @@ -100,6 +100,7 @@ bool maildir_stat_dirs; bool maildir_copy_with_hardlinks; bool maildir_copy_preserve_filename; + bool maildir_very_dirty_syncs; const char *mbox_read_locks; const char *mbox_write_locks; unsigned int mbox_lock_timeout;