dovecot: NFS attribute cache flushing fixes. nfs_flush_attr_cach...
dovecot at dovecot.org
dovecot at dovecot.org
Wed Nov 14 23:52:40 EET 2007
details: http://hg.dovecot.org/dovecot/rev/a59deefc552f
changeset: 6797:a59deefc552f
user: Timo Sirainen <tss at iki.fi>
date: Wed Nov 14 23:52:33 2007 +0200
description:
NFS attribute cache flushing fixes. nfs_flush_attr_cache() takes now
flush_dir parameter and nfs_flush_attr_cache_fd() returns FALSE if file
handle is already stale.
diffstat:
11 files changed, 83 insertions(+), 36 deletions(-)
src/lib-index/mail-hash.c | 2 -
src/lib-index/mail-index.c | 28 ++++++++++-----
src/lib-index/mail-transaction-log-file.c | 2 -
src/lib-index/mail-transaction-log.c | 9 +++--
src/lib-index/mailbox-list-index.c | 2 -
src/lib-storage/index/maildir/maildir-keywords.c | 2 -
src/lib-storage/index/maildir/maildir-uidlist.c | 22 ++++++++++--
src/lib-storage/index/mbox/mbox-lock.c | 2 -
src/lib/file-dotlock.c | 4 +-
src/lib/nfs-workarounds.c | 39 +++++++++++++++-------
src/lib/nfs-workarounds.h | 7 ++-
diffs (truncated from 319 to 300 lines):
diff -r 587a9d3054c1 -r a59deefc552f src/lib-index/mail-hash.c
--- a/src/lib-index/mail-hash.c Wed Nov 14 23:43:42 2007 +0200
+++ b/src/lib-index/mail-hash.c Wed Nov 14 23:52:33 2007 +0200
@@ -653,7 +653,7 @@ static int mail_hash_reopen_if_needed(st
return mail_hash_reopen(hash);
if (hash->index->nfs_flush)
- nfs_flush_attr_cache(hash->filepath);
+ nfs_flush_attr_cache(hash->filepath, TRUE);
if (nfs_safe_stat(hash->filepath, &st) < 0) {
if (errno == ENOENT)
diff -r 587a9d3054c1 -r a59deefc552f src/lib-index/mail-index.c
--- a/src/lib-index/mail-index.c Wed Nov 14 23:43:42 2007 +0200
+++ b/src/lib-index/mail-index.c Wed Nov 14 23:52:33 2007 +0200
@@ -248,6 +248,9 @@ int mail_index_try_open_only(struct mail
i_assert(index->fd == -1);
i_assert(!MAIL_INDEX_IS_IN_MEMORY(index));
+ if (index->nfs_flush)
+ nfs_flush_attr_cache(index->filepath, TRUE);
+
/* Note that our caller must close index->fd by itself. */
if (index->readonly)
errno = EACCES;
@@ -470,6 +473,22 @@ int mail_index_reopen_if_changed(struct
if (index->fd == -1)
return mail_index_try_open_only(index);
+ if (index->nfs_flush)
+ nfs_flush_attr_cache(index->filepath, TRUE);
+ if (nfs_safe_stat(index->filepath, &st2) < 0) {
+ if (errno == ENOENT)
+ return 0;
+
+ return mail_index_set_syscall_error(index, "stat()");
+ }
+
+ if (index->nfs_flush) {
+ if (!nfs_flush_attr_cache_fd(index->filepath, index->fd)) {
+ /* deleted/recreated, reopen */
+ mail_index_close_file(index);
+ return mail_index_try_open_only(index);
+ }
+ }
if (fstat(index->fd, &st1) < 0) {
if (errno != ESTALE)
return mail_index_set_syscall_error(index, "fstat()");
@@ -478,15 +497,6 @@ int mail_index_reopen_if_changed(struct
return mail_index_try_open_only(index);
}
- if (index->nfs_flush)
- nfs_flush_attr_cache(index->filepath);
- if (nfs_safe_stat(index->filepath, &st2) < 0) {
- if (errno == ENOENT)
- return 0;
-
- return mail_index_set_syscall_error(index, "stat()");
- }
-
if (st1.st_ino == st2.st_ino && CMP_DEV_T(st1.st_dev, st2.st_dev)) {
/* the same file */
return 1;
diff -r 587a9d3054c1 -r a59deefc552f src/lib-index/mail-transaction-log-file.c
--- a/src/lib-index/mail-transaction-log-file.c Wed Nov 14 23:43:42 2007 +0200
+++ b/src/lib-index/mail-transaction-log-file.c Wed Nov 14 23:52:33 2007 +0200
@@ -435,7 +435,7 @@ mail_transaction_log_file_create2(struct
bool rename_existing;
if (index->nfs_flush)
- nfs_flush_attr_cache(file->filepath);
+ nfs_flush_attr_cache(file->filepath, TRUE);
/* log creation is locked now - see if someone already created it.
note that if we're rotating, we need to keep the log locked until
diff -r 587a9d3054c1 -r a59deefc552f src/lib-index/mail-transaction-log.c
--- a/src/lib-index/mail-transaction-log.c Wed Nov 14 23:43:42 2007 +0200
+++ b/src/lib-index/mail-transaction-log.c Wed Nov 14 23:52:33 2007 +0200
@@ -279,7 +279,7 @@ static int mail_transaction_log_refresh(
path = t_strconcat(log->index->filepath,
MAIL_TRANSACTION_LOG_SUFFIX, NULL);
if (log->index->nfs_flush)
- nfs_flush_attr_cache(path);
+ nfs_flush_attr_cache(path, TRUE);
if (nfs_safe_stat(path, &st) < 0) {
if (errno != ENOENT) {
mail_index_file_set_syscall_error(log->index, path,
@@ -299,8 +299,11 @@ static int mail_transaction_log_refresh(
} else {
if (log->head->st_ino == st.st_ino &&
CMP_DEV_T(log->head->st_dev, st.st_dev)) {
- /* same file */
- return 0;
+ /* same file? */
+ if (nfs_flush_attr_cache_fd(log->head->filepath,
+ log->head->fd))
+ return 0;
+ /* nope */
}
}
diff -r 587a9d3054c1 -r a59deefc552f src/lib-index/mailbox-list-index.c
--- a/src/lib-index/mailbox-list-index.c Wed Nov 14 23:43:42 2007 +0200
+++ b/src/lib-index/mailbox-list-index.c Wed Nov 14 23:52:33 2007 +0200
@@ -229,7 +229,7 @@ static int mailbox_list_index_is_recreat
return 1;
if (index->mail_index->nfs_flush)
- nfs_flush_attr_cache(index->filepath);
+ nfs_flush_attr_cache(index->filepath, TRUE);
if (nfs_safe_stat(index->filepath, &st1) < 0) {
if (errno == ENOENT)
diff -r 587a9d3054c1 -r a59deefc552f src/lib-storage/index/maildir/maildir-keywords.c
--- a/src/lib-storage/index/maildir/maildir-keywords.c Wed Nov 14 23:43:42 2007 +0200
+++ b/src/lib-storage/index/maildir/maildir-keywords.c Wed Nov 14 23:52:33 2007 +0200
@@ -118,7 +118,7 @@ static int maildir_keywords_sync(struct
errors. */
if ((mk->storage->flags & MAIL_STORAGE_FLAG_NFS_FLUSH_STORAGE) != 0)
- nfs_flush_attr_cache(mk->path);
+ nfs_flush_attr_cache(mk->path, TRUE);
if (nfs_safe_stat(mk->path, &st) < 0) {
if (errno == ENOENT) {
diff -r 587a9d3054c1 -r a59deefc552f src/lib-storage/index/maildir/maildir-uidlist.c
--- a/src/lib-storage/index/maildir/maildir-uidlist.c Wed Nov 14 23:43:42 2007 +0200
+++ b/src/lib-storage/index/maildir/maildir-uidlist.c Wed Nov 14 23:52:33 2007 +0200
@@ -631,7 +631,7 @@ maildir_uidlist_has_changed(struct maild
*recreated_r = FALSE;
if ((storage->flags & MAIL_STORAGE_FLAG_NFS_FLUSH_STORAGE) != 0)
- nfs_flush_attr_cache(uidlist->path);
+ nfs_flush_attr_cache(uidlist->path, TRUE);
if (nfs_safe_stat(uidlist->path, &st) < 0) {
if (errno != ENOENT) {
@@ -647,7 +647,17 @@ maildir_uidlist_has_changed(struct maild
/* file recreated */
*recreated_r = TRUE;
return 1;
- } else if (st.st_size != uidlist->fd_size) {
+ }
+
+ /* either the file hasn't been changed, or it has already been deleted
+ and the inodes just happen to be the same. check if the fd is still
+ valid. */
+ if (!nfs_flush_attr_cache_fd(uidlist->path, uidlist->fd)) {
+ *recreated_r = TRUE;
+ return 1;
+ }
+
+ if (st.st_size != uidlist->fd_size) {
/* file modified but not recreated */
return 1;
} else {
@@ -658,6 +668,7 @@ maildir_uidlist_has_changed(struct maild
int maildir_uidlist_refresh(struct maildir_uidlist *uidlist)
{
+ struct mail_storage *storage = uidlist->ibox->box.storage;
unsigned int i;
bool retry, recreated;
int ret;
@@ -669,6 +680,9 @@ int maildir_uidlist_refresh(struct maild
if (recreated)
maildir_uidlist_close(uidlist);
+ } else {
+ if ((storage->flags & MAIL_STORAGE_FLAG_NFS_FLUSH_STORAGE) != 0)
+ nfs_flush_attr_cache(uidlist->path, TRUE);
}
for (i = 0; ; i++) {
@@ -676,7 +690,9 @@ int maildir_uidlist_refresh(struct maild
i < UIDLIST_ESTALE_RETRY_COUNT);
if (!retry)
break;
- /* ESTALE - try reopening and rereading */
+ /* ESTALE - try reopening and rereading */
+ maildir_uidlist_close(uidlist);
+ nfs_flush_attr_cache(uidlist->path, TRUE);
}
if (ret >= 0)
uidlist->initial_read = TRUE;
diff -r 587a9d3054c1 -r a59deefc552f src/lib-storage/index/mbox/mbox-lock.c
--- a/src/lib-storage/index/mbox/mbox-lock.c Wed Nov 14 23:43:42 2007 +0200
+++ b/src/lib-storage/index/mbox/mbox-lock.c Wed Nov 14 23:52:33 2007 +0200
@@ -173,7 +173,7 @@ static int mbox_file_open_latest(struct
if (mbox->mbox_fd != -1) {
if ((mbox->storage->storage.flags &
MAIL_STORAGE_FLAG_NFS_FLUSH_STORAGE) != 0)
- nfs_flush_attr_cache(mbox->path);
+ nfs_flush_attr_cache(mbox->path, TRUE);
if (nfs_safe_stat(mbox->path, &st) < 0) {
mbox_set_syscall_error(mbox, "stat()");
return -1;
diff -r 587a9d3054c1 -r a59deefc552f src/lib/file-dotlock.c
--- a/src/lib/file-dotlock.c Wed Nov 14 23:43:42 2007 +0200
+++ b/src/lib/file-dotlock.c Wed Nov 14 23:52:33 2007 +0200
@@ -156,7 +156,7 @@ static int update_lock_info(time_t now,
struct stat st;
if (lock_info->set->nfs_flush)
- nfs_flush_attr_cache(lock_info->lock_path);
+ nfs_flush_attr_cache(lock_info->lock_path, TRUE);
if (nfs_safe_lstat(lock_info->lock_path, &st) < 0) {
if (errno != ENOENT) {
i_error("lstat(%s) failed: %m", lock_info->lock_path);
@@ -244,7 +244,7 @@ static int check_lock(time_t now, struct
/* possibly stale lock file. check also the timestamp of the
file we're protecting. */
if (lock_info->set->nfs_flush)
- nfs_flush_attr_cache(lock_info->path);
+ nfs_flush_attr_cache(lock_info->path, TRUE);
if (nfs_safe_stat(lock_info->path, &st) < 0) {
if (errno == ENOENT) {
/* file doesn't exist. treat it as if
diff -r 587a9d3054c1 -r a59deefc552f src/lib/nfs-workarounds.c
--- a/src/lib/nfs-workarounds.c Wed Nov 14 23:43:42 2007 +0200
+++ b/src/lib/nfs-workarounds.c Wed Nov 14 23:52:33 2007 +0200
@@ -62,7 +62,8 @@ nfs_safe_do(const char *path, int (*call
if (dir == NULL)
break;
dir = t_strdup_until(path, dir);
- }
+ }
+ nfs_flush_attr_cache(dir, FALSE);
if (stat(dir, &st) < 0) {
/* maybe it's gone or something else bad happened to
it. in any case we can't open the file, so fail
@@ -128,26 +129,30 @@ int nfs_safe_lstat(const char *path, str
return nfs_safe_do(path, nfs_safe_lstat_callback, buf);
}
-static void nfs_flush_fchown_uid(const char *path, int fd)
+static bool nfs_flush_fchown_uid(const char *path, int fd)
{
struct stat st;
if (fstat(fd, &st) < 0) {
if (errno == ESTALE) {
/* ESTALE causes the OS to flush the attr cache */
- return;
+ return FALSE;
}
i_error("nfs_flush_fchown_uid: fstat(%s) failed: %m", path);
- return;
+ return TRUE;
}
if (fchown(fd, st.st_uid, (gid_t)-1) < 0) {
- if (errno == ESTALE || errno == EACCES || errno == EPERM) {
+ if (errno == ESTALE) {
+ return FALSE;
+ }
+ if (errno == EACCES || errno == EPERM) {
/* attr cache is flushed */
- return;
+ return TRUE;
}
i_error("nfs_flush_fchown_uid: fchown(%s) failed: %m", path);
}
+ return TRUE;
}
static void nfs_flush_chown_uid(const char *path)
@@ -212,14 +217,26 @@ static void nfs_flush_fcntl(const char *
}
#endif
-void nfs_flush_attr_cache(const char *path)
-{
+void nfs_flush_attr_cache(const char *path, bool flush_dir)
+{
+ const char *p;
+
+ if (flush_dir) {
+ p = strrchr(path, '/');
+ if (p == NULL)
+ nfs_flush_chown_uid(".");
+ else {
+ t_push();
+ nfs_flush_chown_uid(t_strdup_until(path, p));
+ t_pop();
+ }
+ }
nfs_flush_chown_uid(path);
}
-void nfs_flush_attr_cache_fd(const char *path, int fd)
-{
- nfs_flush_fchown_uid(path, fd);
+bool nfs_flush_attr_cache_fd(const char *path, int fd)
+{
+ return nfs_flush_fchown_uid(path, fd);
}
void nfs_flush_read_cache(const char *path, int fd,
More information about the dovecot-cvs
mailing list