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