dovecot: NFS cache flushing updates.
dovecot at dovecot.org
dovecot at dovecot.org
Sun Nov 25 15:47:41 EET 2007
details: http://hg.dovecot.org/dovecot/rev/41911abe6fa7
changeset: 6857:41911abe6fa7
user: Timo Sirainen <tss at iki.fi>
date: Sun Nov 25 15:47:36 2007 +0200
description:
NFS cache flushing updates.
diffstat:
12 files changed, 135 insertions(+), 117 deletions(-)
src/lib-index/mail-cache.c | 2
src/lib-index/mail-hash.c | 2
src/lib-index/mail-index.c | 2
src/lib-index/mail-transaction-log-file.c | 8
src/lib-index/mail-transaction-log.c | 8
src/lib-index/mailbox-list-index.c | 2
src/lib-storage/index/maildir/maildir-keywords.c | 7
src/lib-storage/index/maildir/maildir-uidlist.c | 1
src/lib-storage/index/mbox/mbox-lock.c | 5
src/lib/file-dotlock.c | 8
src/lib/nfs-workarounds.c | 203 +++++++++++-----------
src/lib/nfs-workarounds.h | 4
diffs (truncated from 453 to 300 lines):
diff -r a249d916f6e6 -r 41911abe6fa7 src/lib-index/mail-cache.c
--- a/src/lib-index/mail-cache.c Sun Nov 25 15:05:31 2007 +0200
+++ b/src/lib-index/mail-cache.c Sun Nov 25 15:47:36 2007 +0200
@@ -110,7 +110,7 @@ static bool mail_cache_need_reopen(struc
/* see if the file has changed */
if (cache->index->nfs_flush) {
i_assert(!cache->locked);
- nfs_flush_attr_cache_unlocked(cache->filepath);
+ nfs_flush_file_handle_cache(cache->filepath);
}
if (nfs_safe_stat(cache->filepath, &st) < 0) {
mail_cache_set_syscall_error(cache, "stat()");
diff -r a249d916f6e6 -r 41911abe6fa7 src/lib-index/mail-hash.c
--- a/src/lib-index/mail-hash.c Sun Nov 25 15:05:31 2007 +0200
+++ b/src/lib-index/mail-hash.c Sun Nov 25 15:47:36 2007 +0200
@@ -657,7 +657,7 @@ static int mail_hash_reopen_if_needed(st
return mail_hash_reopen(hash);
if (hash->index->nfs_flush)
- nfs_flush_attr_cache_unlocked(hash->filepath);
+ nfs_flush_file_handle_cache(hash->filepath);
if (nfs_safe_stat(hash->filepath, &st) < 0) {
if (errno != ENOENT) {
diff -r a249d916f6e6 -r 41911abe6fa7 src/lib-index/mail-index.c
--- a/src/lib-index/mail-index.c Sun Nov 25 15:05:31 2007 +0200
+++ b/src/lib-index/mail-index.c Sun Nov 25 15:47:36 2007 +0200
@@ -472,7 +472,7 @@ int mail_index_reopen_if_changed(struct
return mail_index_try_open_only(index);
if (index->nfs_flush)
- nfs_flush_attr_cache_unlocked(index->filepath);
+ nfs_flush_file_handle_cache(index->filepath);
if (nfs_safe_stat(index->filepath, &st2) < 0) {
if (errno == ENOENT)
return 0;
diff -r a249d916f6e6 -r 41911abe6fa7 src/lib-index/mail-transaction-log-file.c
--- a/src/lib-index/mail-transaction-log-file.c Sun Nov 25 15:05:31 2007 +0200
+++ b/src/lib-index/mail-transaction-log-file.c Sun Nov 25 15:47:36 2007 +0200
@@ -434,8 +434,12 @@ mail_transaction_log_file_create2(struct
int fd, ret;
bool rename_existing;
- if (index->nfs_flush)
- nfs_flush_attr_cache_unlocked(file->filepath);
+ if (index->nfs_flush) {
+ /* although we check also mtime and file size below, it's done
+ only to fix broken log files. we don't bother flushing
+ attribute cache just for that. */
+ nfs_flush_file_handle_cache(file->filepath);
+ }
/* 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 a249d916f6e6 -r 41911abe6fa7 src/lib-index/mail-transaction-log.c
--- a/src/lib-index/mail-transaction-log.c Sun Nov 25 15:05:31 2007 +0200
+++ b/src/lib-index/mail-transaction-log.c Sun Nov 25 15:47:36 2007 +0200
@@ -279,12 +279,8 @@ mail_transaction_log_refresh(struct mail
path = t_strconcat(log->index->filepath,
MAIL_TRANSACTION_LOG_SUFFIX, NULL);
- if (log->index->nfs_flush && nfs_flush) {
- if (!log->head->locked)
- nfs_flush_attr_cache_unlocked(path);
- else
- nfs_flush_attr_cache_dir(log->index->dir);
- }
+ if (log->index->nfs_flush && nfs_flush)
+ nfs_flush_file_handle_cache(path);
if (nfs_safe_stat(path, &st) < 0) {
if (errno != ENOENT) {
mail_index_file_set_syscall_error(log->index, path,
diff -r a249d916f6e6 -r 41911abe6fa7 src/lib-index/mailbox-list-index.c
--- a/src/lib-index/mailbox-list-index.c Sun Nov 25 15:05:31 2007 +0200
+++ b/src/lib-index/mailbox-list-index.c Sun Nov 25 15:47:36 2007 +0200
@@ -224,7 +224,7 @@ static int mailbox_list_index_is_recreat
return 1;
if (index->mail_index->nfs_flush)
- nfs_flush_attr_cache_unlocked(index->filepath);
+ nfs_flush_file_handle_cache(index->filepath);
if (nfs_safe_stat(index->filepath, &st1) < 0) {
if (errno == ENOENT || errno == ESTALE)
diff -r a249d916f6e6 -r 41911abe6fa7 src/lib-storage/index/maildir/maildir-keywords.c
--- a/src/lib-storage/index/maildir/maildir-keywords.c Sun Nov 25 15:05:31 2007 +0200
+++ b/src/lib-storage/index/maildir/maildir-keywords.c Sun Nov 25 15:47:36 2007 +0200
@@ -117,8 +117,11 @@ static int maildir_keywords_sync(struct
we rely on stat()'s timestamp and don't bother handling ESTALE
errors. */
- if ((mk->storage->flags & MAIL_STORAGE_FLAG_NFS_FLUSH_STORAGE) != 0)
- nfs_flush_attr_cache_unlocked(mk->path);
+ if ((mk->storage->flags & MAIL_STORAGE_FLAG_NFS_FLUSH_STORAGE) != 0) {
+ /* file is updated only by replacing it, no need to flush
+ attribute cache */
+ nfs_flush_file_handle_cache(mk->path);
+ }
if (nfs_safe_stat(mk->path, &st) < 0) {
if (errno == ENOENT) {
diff -r a249d916f6e6 -r 41911abe6fa7 src/lib-storage/index/maildir/maildir-uidlist.c
--- a/src/lib-storage/index/maildir/maildir-uidlist.c Sun Nov 25 15:05:31 2007 +0200
+++ b/src/lib-storage/index/maildir/maildir-uidlist.c Sun Nov 25 15:47:36 2007 +0200
@@ -687,6 +687,7 @@ int maildir_uidlist_refresh(struct maild
if (!nfs_flush)
uidlist->nfs_dirty_refresh = TRUE;
else {
+ nfs_flush_file_handle_cache(uidlist->path);
nfs_flush_attr_cache_unlocked(uidlist->path);
uidlist->nfs_dirty_refresh = FALSE;
}
diff -r a249d916f6e6 -r 41911abe6fa7 src/lib-storage/index/mbox/mbox-lock.c
--- a/src/lib-storage/index/mbox/mbox-lock.c Sun Nov 25 15:05:31 2007 +0200
+++ b/src/lib-storage/index/mbox/mbox-lock.c Sun Nov 25 15:47:36 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_maybe_locked(mbox->path);
+ nfs_flush_file_handle_cache(mbox->path);
if (nfs_safe_stat(mbox->path, &st) < 0) {
mbox_set_syscall_error(mbox, "stat()");
return -1;
@@ -568,9 +568,12 @@ int mbox_lock(struct mbox_mailbox *mbox,
if ((mbox->storage->storage.flags &
MAIL_STORAGE_FLAG_NFS_FLUSH_STORAGE) != 0) {
if (fcntl_locked) {
+ nfs_flush_attr_cache_fd_locked(mbox->path,
+ mbox->mbox_fd);
nfs_flush_read_cache_locked(mbox->path,
mbox->mbox_fd);
} else {
+ nfs_flush_attr_cache_unlocked(mbox->path);
nfs_flush_read_cache_unlocked(mbox->path,
mbox->mbox_fd);
}
diff -r a249d916f6e6 -r 41911abe6fa7 src/lib/file-dotlock.c
--- a/src/lib/file-dotlock.c Sun Nov 25 15:05:31 2007 +0200
+++ b/src/lib/file-dotlock.c Sun Nov 25 15:47:36 2007 +0200
@@ -158,8 +158,10 @@ static int update_lock_info(time_t now,
/* don't waste time flushing attribute cache the first time we're here.
if it's stale we'll get back here soon. */
- if (lock_info->set->nfs_flush && lock_info->lock_stated)
+ if (lock_info->set->nfs_flush && lock_info->lock_stated) {
+ nfs_flush_file_handle_cache(lock_info->lock_path);
nfs_flush_attr_cache_unlocked(lock_info->lock_path);
+ }
lock_info->lock_stated = TRUE;
if (nfs_safe_lstat(lock_info->lock_path, &st) < 0) {
@@ -248,8 +250,10 @@ 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)
+ if (lock_info->set->nfs_flush) {
+ nfs_flush_file_handle_cache(lock_info->path);
nfs_flush_attr_cache_maybe_locked(lock_info->path);
+ }
if (nfs_safe_stat(lock_info->path, &st) < 0) {
if (errno == ENOENT) {
/* file doesn't exist. treat it as if
diff -r a249d916f6e6 -r 41911abe6fa7 src/lib/nfs-workarounds.c
--- a/src/lib/nfs-workarounds.c Sun Nov 25 15:05:31 2007 +0200
+++ b/src/lib/nfs-workarounds.c Sun Nov 25 15:47:36 2007 +0200
@@ -41,12 +41,12 @@
# define ATTRCACHE_FLUSH_CHOWN_UID_1
#endif
+static void nfs_flush_file_handle_cache_parent_dir(const char *path);
+
static int
nfs_safe_do(const char *path, int (*callback)(const char *path, void *context),
void *context)
{
- const char *dir = NULL;
- struct stat st;
unsigned int i;
int ret;
@@ -57,26 +57,9 @@ nfs_safe_do(const char *path, int (*call
break;
/* ESTALE: Some operating systems may fail with this if they
- can't internally revalidating the NFS handle. It may also
- happen if the parent directory has been deleted. If the
- directory still exists, try reopening the file. */
- if (dir == NULL) {
- dir = strrchr(path, '/');
- if (dir == NULL)
- break;
- dir = t_strdup_until(path, dir);
- }
- nfs_flush_attr_cache_dir(path);
- 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
- with the original ESTALE error and let our caller
- handle it. */
- errno = ESTALE;
- break;
- }
-
- /* directory still exists, try reopening */
+ can't internally revalidate the NFS file handle. Flush the
+ file handle and try again */
+ nfs_flush_file_handle_cache(path);
}
t_pop();
return ret;
@@ -178,28 +161,57 @@ static void nfs_flush_chown_uid(const ch
/* ESTALE causes the OS to flush the attr cache */
return;
}
- if (errno != ENOENT) {
- i_error("nfs_flush_chown_uid: stat(%s) failed: %m",
- path);
- return;
- }
-
- /* flush a negative cache entry. use effective UID to chown.
- it probably doesn't really matter what UID is used, because
- as long as we're not root we don't have permission to really
- change it anyway */
- uid = geteuid();
+ if (likely(errno == ENOENT)) {
+ nfs_flush_file_handle_cache_parent_dir(path);
+ return;
+ }
+ i_error("nfs_flush_chown_uid: stat(%s) failed: %m", path);
+ return;
}
#endif
if (chown(path, uid, (gid_t)-1) < 0) {
- if (errno == ESTALE || errno == EACCES ||
- errno == EPERM || errno == ENOENT) {
+ if (errno == ESTALE || errno == EPERM || errno == ENOENT) {
/* attr cache is flushed */
return;
}
+ if (likely(errno == ENOENT)) {
+ nfs_flush_file_handle_cache_parent_dir(path);
+ return;
+ }
i_error("nfs_flush_chown_uid: chown(%s) failed: %m", path);
}
}
+
+#ifdef __FreeBSD__
+static bool nfs_flush_fchown_uid(const char *path, int fd)
+{
+ uid_t uid;
+#ifndef ATTRCACHE_FLUSH_CHOWN_UID_1
+ struct stat st;
+
+ if (fstat(fd, &st) < 0) {
+ if (likely(errno == ESTALE))
+ return FALSE;
+ i_error("nfs_flush_attr_cache_fchown: fstat(%s) failed: %m",
+ path);
+ return TRUE;
+ }
+ uid = st.st_uid;
+#endif
+ if (fchown(fd, uid, (gid_t)-1) < 0) {
+ if (errno == ESTALE)
+ return FALSE;
+ if (likely(errno == EACCES || errno == EPERM)) {
+ /* attr cache is flushed */
+ return TRUE;
+ }
+
+ i_error("nfs_flush_attr_cache_fd_locked: fchown(%s) failed: %m",
+ path);
+ }
+ return TRUE;
+}
+#endif
#ifdef READ_CACHE_FLUSH_FCNTL
static void nfs_flush_fcntl(const char *path, int fd)
@@ -230,47 +242,25 @@ static void nfs_flush_fcntl(const char *
}
#endif
-static void nfs_flush_attr_cache_parent_dir(const char *path)
-{
- const char *p;
-
- p = strrchr(path, '/');
- if (p == NULL)
- nfs_flush_attr_cache_dir(".");
- else {
- t_push();
- nfs_flush_attr_cache_dir(t_strdup_until(path, p));
- t_pop();
- }
-}
More information about the dovecot-cvs
mailing list