dovecot: NFS: Delay flushing dovecot-uidlist's attribute cache u...
dovecot at dovecot.org
dovecot at dovecot.org
Thu Nov 15 01:55:02 EET 2007
details: http://hg.dovecot.org/dovecot/rev/ca849e28a062
changeset: 6800:ca849e28a062
user: Timo Sirainen <tss at iki.fi>
date: Thu Nov 15 01:54:56 2007 +0200
description:
NFS: Delay flushing dovecot-uidlist's attribute cache until we find an
unseen file or UID.
diffstat:
5 files changed, 55 insertions(+), 18 deletions(-)
src/lib-storage/index/dbox/dbox-sync-rebuild.c | 2
src/lib-storage/index/maildir/maildir-copy.c | 2
src/lib-storage/index/maildir/maildir-sync.c | 2
src/lib-storage/index/maildir/maildir-uidlist.c | 61 ++++++++++++++++++-----
src/lib-storage/index/maildir/maildir-uidlist.h | 6 +-
diffs (192 lines):
diff -r c1bd43be8f9a -r ca849e28a062 src/lib-storage/index/dbox/dbox-sync-rebuild.c
--- a/src/lib-storage/index/dbox/dbox-sync-rebuild.c Thu Nov 15 00:46:43 2007 +0200
+++ b/src/lib-storage/index/dbox/dbox-sync-rebuild.c Thu Nov 15 01:54:56 2007 +0200
@@ -250,7 +250,7 @@ dbox_sync_index_maildir_file(struct dbox
maildir_keywords_sync_init(ctx->mk,
ctx->mbox->ibox.index);
- if (maildir_uidlist_refresh(ctx->maildir_uidlist) < 0)
+ if (maildir_uidlist_refresh(ctx->maildir_uidlist, FALSE) < 0)
return -1;
}
diff -r c1bd43be8f9a -r ca849e28a062 src/lib-storage/index/maildir/maildir-copy.c
--- a/src/lib-storage/index/maildir/maildir-copy.c Thu Nov 15 00:46:43 2007 +0200
+++ b/src/lib-storage/index/maildir/maildir-copy.c Thu Nov 15 01:54:56 2007 +0200
@@ -132,7 +132,7 @@ maildir_copy_hardlink(struct maildir_tra
src_fname = maildir_uidlist_lookup(src_mbox->uidlist,
mail->uid, &src_flags);
if (src_fname != NULL &&
- maildir_uidlist_refresh(dest_mbox->uidlist) >= 0 &&
+ maildir_uidlist_refresh(dest_mbox->uidlist, FALSE) >= 0 &&
maildir_uidlist_get_full_filename(dest_mbox->uidlist,
src_fname) == NULL)
filename = t_strcut(src_fname, ':');
diff -r c1bd43be8f9a -r ca849e28a062 src/lib-storage/index/maildir/maildir-sync.c
--- a/src/lib-storage/index/maildir/maildir-sync.c Thu Nov 15 00:46:43 2007 +0200
+++ b/src/lib-storage/index/maildir/maildir-sync.c Thu Nov 15 01:54:56 2007 +0200
@@ -660,7 +660,7 @@ static bool move_recent_messages(struct
if (ctx->mbox->ibox.keep_recent)
return FALSE;
- (void)maildir_uidlist_refresh(ctx->mbox->uidlist);
+ (void)maildir_uidlist_refresh(ctx->mbox->uidlist, FALSE);
/* if there are files in new/, we'll need to move them. we'll check
this by checking if we have any recent messages */
diff -r c1bd43be8f9a -r ca849e28a062 src/lib-storage/index/maildir/maildir-uidlist.c
--- a/src/lib-storage/index/maildir/maildir-uidlist.c Thu Nov 15 00:46:43 2007 +0200
+++ b/src/lib-storage/index/maildir/maildir-uidlist.c Thu Nov 15 01:54:56 2007 +0200
@@ -91,6 +91,7 @@ struct maildir_uidlist {
unsigned int recreate:1;
unsigned int initial_read:1;
unsigned int initial_sync:1;
+ unsigned int nfs_dirty_refresh:1;
};
struct maildir_uidlist_sync_ctx {
@@ -169,7 +170,7 @@ static int maildir_uidlist_lock_timeout(
uidlist->lock_count++;
/* make sure we have the latest changes before changing anything */
- if (maildir_uidlist_refresh(uidlist) < 0) {
+ if (maildir_uidlist_refresh(uidlist, FALSE) < 0) {
maildir_uidlist_unlock(uidlist);
return -1;
}
@@ -630,11 +631,6 @@ maildir_uidlist_has_changed(struct maild
*recreated_r = FALSE;
- /* don't bother flushing attribute caches unless uidlist is locked */
- if ((storage->flags & MAIL_STORAGE_FLAG_NFS_FLUSH_STORAGE) != 0 &&
- UIDLIST_IS_LOCKED(uidlist))
- nfs_flush_attr_cache(uidlist->path, TRUE);
-
if (nfs_safe_stat(uidlist->path, &st) < 0) {
if (errno != ENOENT) {
mail_storage_set_critical(storage,
@@ -671,13 +667,25 @@ maildir_uidlist_has_changed(struct maild
}
}
-int maildir_uidlist_refresh(struct maildir_uidlist *uidlist)
+int maildir_uidlist_refresh(struct maildir_uidlist *uidlist, bool nfs_flush)
{
struct mail_storage *storage = uidlist->ibox->box.storage;
unsigned int i;
bool retry, recreated;
int ret;
+ if ((storage->flags & MAIL_STORAGE_FLAG_NFS_FLUSH_STORAGE) != 0) {
+ /* delay flushing attribute cache until we find a file that
+ doesn't exist in the uidlist. only then we really must have
+ the latest uidlist. */
+ if (!nfs_flush)
+ uidlist->nfs_dirty_refresh = TRUE;
+ else {
+ nfs_flush_attr_cache(uidlist->path, TRUE);
+ uidlist->nfs_dirty_refresh = FALSE;
+ }
+ }
+
if (uidlist->fd != -1) {
ret = maildir_uidlist_has_changed(uidlist, &recreated);
if (ret <= 0)
@@ -685,10 +693,6 @@ int maildir_uidlist_refresh(struct maild
if (recreated)
maildir_uidlist_close(uidlist);
- } else {
- if (UIDLIST_IS_LOCKED(uidlist) &&
- (storage->flags & MAIL_STORAGE_FLAG_NFS_FLUSH_STORAGE) != 0)
- nfs_flush_attr_cache(uidlist->path, TRUE);
}
for (i = 0; ; i++) {
@@ -714,7 +718,7 @@ maildir_uidlist_lookup_rec(struct maildi
if (!uidlist->initial_read) {
/* first time we need to read uidlist */
- if (maildir_uidlist_refresh(uidlist) < 0)
+ if (maildir_uidlist_refresh(uidlist, FALSE) < 0)
return NULL;
}
@@ -731,6 +735,14 @@ maildir_uidlist_lookup_rec(struct maildi
*idx_r = idx;
return recs[idx];
}
+ }
+
+ if (uidlist->nfs_dirty_refresh) {
+ /* We haven't flushed NFS attribute cache yet, do that
+ to make sure the UID really doesn't exist */
+ if (maildir_uidlist_refresh(uidlist, TRUE) < 0)
+ return NULL;
+ return maildir_uidlist_lookup_rec(uidlist, uid, idx_r);
}
if (idx > 0) idx--;
@@ -1111,6 +1123,18 @@ maildir_uidlist_sync_next_partial(struct
i_assert(rec != NULL || UIDLIST_IS_LOCKED(uidlist));
if (rec == NULL) {
+ /* doesn't exist in uidlist */
+ if (uidlist->nfs_dirty_refresh) {
+ /* We haven't flushed NFS attribute cache yet, do that
+ to make sure the file doesn't exist */
+ if (maildir_uidlist_refresh(uidlist, TRUE) < 0) {
+ ctx->failed = TRUE;
+ return;
+ }
+ i_assert(!uidlist->nfs_dirty_refresh);
+ return maildir_uidlist_sync_next_partial(ctx, filename,
+ flags);
+ }
if (ctx->first_nouid_pos == (unsigned int)-1)
ctx->first_nouid_pos = array_count(&uidlist->records);
ctx->new_files_count++;
@@ -1145,7 +1169,7 @@ int maildir_uidlist_sync_next_pre(struct
(ctx->partial || hash_lookup(ctx->files, filename) == NULL)) {
if (!ctx->uidlist->initial_read) {
/* first time reading the uidlist */
- if (maildir_uidlist_refresh(ctx->uidlist) < 0) {
+ if (maildir_uidlist_refresh(ctx->uidlist, FALSE) < 0) {
ctx->failed = TRUE;
return -1;
}
@@ -1189,6 +1213,17 @@ int maildir_uidlist_sync_next(struct mai
} else {
old_rec = hash_lookup(uidlist->files, filename);
i_assert(old_rec != NULL || UIDLIST_IS_LOCKED(uidlist));
+
+ if (old_rec == NULL && uidlist->nfs_dirty_refresh) {
+ /* We haven't flushed NFS attribute cache yet, do that
+ to make sure the file doesn't exist */
+ if (maildir_uidlist_refresh(uidlist, TRUE) < 0) {
+ ctx->failed = TRUE;
+ return -1;
+ }
+ i_assert(!uidlist->nfs_dirty_refresh);
+ return maildir_uidlist_sync_next(ctx, filename, flags);
+ }
rec = p_new(ctx->record_pool, struct maildir_uidlist_rec, 1);
diff -r c1bd43be8f9a -r ca849e28a062 src/lib-storage/index/maildir/maildir-uidlist.h
--- a/src/lib-storage/index/maildir/maildir-uidlist.h Thu Nov 15 00:46:43 2007 +0200
+++ b/src/lib-storage/index/maildir/maildir-uidlist.h Thu Nov 15 01:54:56 2007 +0200
@@ -46,8 +46,10 @@ maildir_uidlist_init_readonly(struct ind
maildir_uidlist_init_readonly(struct index_mailbox *ibox);
void maildir_uidlist_deinit(struct maildir_uidlist **uidlist);
-/* Returns -1 if error, 0 if file is broken or lost, 1 if ok. */
-int maildir_uidlist_refresh(struct maildir_uidlist *uidlist);
+/* Returns -1 if error, 0 if file is broken or lost, 1 if ok. If nfs_flush=TRUE
+ and storage has NFS_FLUSH flag set, the NFS attribute cache is flushed to
+ make sure that we see the latest uidlist file. */
+int maildir_uidlist_refresh(struct maildir_uidlist *uidlist, bool nfs_flush);
/* Returns uidlist record for given filename, or NULL if not found. */
const char *
More information about the dovecot-cvs
mailing list