changeset 4225:abdef9d86a94 HEAD

Added nfs_safe_stat() to transparently work around ESTALE with stat().
author Timo Sirainen <timo.sirainen@movial.fi>
date Tue, 25 Apr 2006 16:40:18 +0300
parents 8736c4deb253
children 83322a523c91
files src/lib-index/mail-index.c src/lib-index/mail-transaction-log.c src/lib-storage/index/maildir/maildir-uidlist.c src/lib/nfs-workarounds.c src/lib/nfs-workarounds.h
diffstat 5 files changed, 52 insertions(+), 10 deletions(-) [+]
line wrap: on
line diff
--- a/src/lib-index/mail-index.c	Mon Apr 24 16:18:45 2006 +0300
+++ b/src/lib-index/mail-index.c	Tue Apr 25 16:40:18 2006 +0300
@@ -1664,7 +1664,7 @@
 		}
 		return mail_index_set_syscall_error(index, "fstat()");
 	}
-	if (stat(index->filepath, &st2) < 0) {
+	if (nfs_safe_stat(index->filepath, &st2) < 0) {
 		mail_index_set_syscall_error(index, "stat()");
 		if (errno != ENOENT)
 			return -1;
--- a/src/lib-index/mail-transaction-log.c	Mon Apr 24 16:18:45 2006 +0300
+++ b/src/lib-index/mail-transaction-log.c	Tue Apr 25 16:40:18 2006 +0300
@@ -920,7 +920,7 @@
 
 	path = t_strconcat(log->index->filepath,
 			   MAIL_TRANSACTION_LOG_SUFFIX, NULL);
-	if (stat(path, &st) < 0) {
+	if (nfs_safe_stat(path, &st) < 0) {
 		mail_index_file_set_syscall_error(log->index, path, "stat()");
 		return -1;
 	}
--- a/src/lib-storage/index/maildir/maildir-uidlist.c	Mon Apr 24 16:18:45 2006 +0300
+++ b/src/lib-storage/index/maildir/maildir-uidlist.c	Tue Apr 25 16:40:18 2006 +0300
@@ -375,7 +375,7 @@
         int ret;
 
 	if (uidlist->last_mtime != 0) {
-		if (stat(uidlist->fname, &st) < 0) {
+		if (nfs_safe_stat(uidlist->fname, &st) < 0) {
 			if (errno != ENOENT) {
 				mail_storage_set_critical(storage,
 					"stat(%s) failed: %m", uidlist->fname);
--- a/src/lib/nfs-workarounds.c	Mon Apr 24 16:18:45 2006 +0300
+++ b/src/lib/nfs-workarounds.c	Tue Apr 25 16:40:18 2006 +0300
@@ -7,19 +7,19 @@
 #include <unistd.h>
 #include <sys/stat.h>
 
-int nfs_safe_open(const char *path, int flags)
+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 fd;
-
-        i_assert((flags & O_CREAT) == 0);
+	int ret;
 
         t_push();
         for (i = 1;; i++) {
-                fd = open(path, flags);
-                if (fd != -1 || errno != ESTALE || i == NFS_ESTALE_RETRY_COUNT)
+		ret = callback(path, context);
+                if (ret == 0 || errno != ESTALE || i == NFS_ESTALE_RETRY_COUNT)
                         break;
 
                 /* ESTALE: Some operating systems may fail with this if they
@@ -44,5 +44,43 @@
                 /* directory still exists, try reopening */
         }
         t_pop();
-        return fd;
+        return ret;
+}
+
+struct nfs_safe_open_context {
+	int flags;
+	int fd;
+};
+
+static int nfs_safe_open_callback(const char *path, void *context)
+{
+	struct nfs_safe_open_context *ctx = context;
+
+	ctx->fd = open(path, ctx->flags);
+	return ctx->fd == -1 ? -1 : 0;
 }
+
+int nfs_safe_open(const char *path, int flags)
+{
+	struct nfs_safe_open_context ctx;
+
+        i_assert((flags & O_CREAT) == 0);
+
+	ctx.flags = flags;
+	if (nfs_safe_do(path, nfs_safe_open_callback, &ctx) < 0)
+		return -1;
+
+	return ctx.fd;
+}
+
+static int nfs_safe_stat_callback(const char *path, void *context)
+{
+	struct stat *buf = context;
+
+	return stat(path, buf);
+}
+
+int nfs_safe_stat(const char *path, struct stat *buf)
+{
+	return nfs_safe_do(path, nfs_safe_stat_callback, buf);
+}
--- a/src/lib/nfs-workarounds.h	Mon Apr 24 16:18:45 2006 +0300
+++ b/src/lib/nfs-workarounds.h	Tue Apr 25 16:40:18 2006 +0300
@@ -1,11 +1,15 @@
 #ifndef __NFS_WORKAROUNDS_H
 #define __NFS_WORKAROUNDS_H
 
+struct stat;
+
 /* When syscall fails with ESTALE error, how many times to try reopening the
    file and retrying the operation. */
 #define NFS_ESTALE_RETRY_COUNT 10
 
 /* open() with some NFS workarounds */
 int nfs_safe_open(const char *path, int flags);
+/* stat() with some NFS workarounds */
+int nfs_safe_stat(const char *path, struct stat *buf);
 
 #endif