dovecot: nfs_safe_link(): Support linking files without original...

dovecot at dovecot.org dovecot at dovecot.org
Fri Nov 16 03:50:19 EET 2007


details:   http://hg.dovecot.org/dovecot/rev/575235932194
changeset: 6813:575235932194
user:      Timo Sirainen <tss at iki.fi>
date:      Fri Nov 16 03:50:15 2007 +0200
description:
nfs_safe_link(): Support linking files without original link count=1. Use it
when copying maildir files, but only if mail_nfs_storage=yes.

diffstat:

5 files changed, 26 insertions(+), 17 deletions(-)
src/lib-index/mail-transaction-log-file.c    |    2 +-
src/lib-storage/index/maildir/maildir-copy.c |    8 +++++++-
src/lib/file-dotlock.c                       |    3 ++-
src/lib/nfs-workarounds.c                    |   23 ++++++++++++-----------
src/lib/nfs-workarounds.h                    |    7 ++++---

diffs (107 lines):

diff -r ebe88bc73154 -r 575235932194 src/lib-index/mail-transaction-log-file.c
--- a/src/lib-index/mail-transaction-log-file.c	Thu Nov 15 16:27:53 2007 +0200
+++ b/src/lib-index/mail-transaction-log-file.c	Fri Nov 16 03:50:15 2007 +0200
@@ -532,7 +532,7 @@ mail_transaction_log_file_create2(struct
 					     path2);
 			/* try to link() anyway */
 		}
-		if (nfs_safe_link(file->filepath, path2) < 0 &&
+		if (nfs_safe_link(file->filepath, path2, FALSE) < 0 &&
 		    errno != ENOENT && errno != EEXIST) {
                         mail_index_set_error(index, "link(%s, %s) failed: %m",
 					     file->filepath, path2);
diff -r ebe88bc73154 -r 575235932194 src/lib-storage/index/maildir/maildir-copy.c
--- a/src/lib-storage/index/maildir/maildir-copy.c	Thu Nov 15 16:27:53 2007 +0200
+++ b/src/lib-storage/index/maildir/maildir-copy.c	Fri Nov 16 03:50:15 2007 +0200
@@ -4,6 +4,7 @@
 #include "array.h"
 #include "ioloop.h"
 #include "str.h"
+#include "nfs-workarounds.h"
 #include "maildir-storage.h"
 #include "maildir-uidlist.h"
 #include "maildir-filename.h"
@@ -67,7 +68,12 @@ static int do_hardlink(struct maildir_ma
 			return ret;
 	}
 
-	if (nfs_safe_link(path, str_c(ctx->dest_path)) < 0) {
+	if ((mbox->storage->storage.flags &
+	     MAIL_STORAGE_FLAG_NFS_FLUSH_STORAGE) != 0)
+		ret = nfs_safe_link(path, str_c(ctx->dest_path), FALSE);
+	else
+		ret = link(path, str_c(ctx->dest_path));
+	if (ret < 0) {
 		if (errno == ENOENT)
 			return 0;
 
diff -r ebe88bc73154 -r 575235932194 src/lib/file-dotlock.c
--- a/src/lib/file-dotlock.c	Thu Nov 15 16:27:53 2007 +0200
+++ b/src/lib/file-dotlock.c	Fri Nov 16 03:50:15 2007 +0200
@@ -342,7 +342,8 @@ static int try_create_lock_hardlink(stru
                 lock_info->temp_path = str_c(tmp_path);
 	}
 
-	if (nfs_safe_link(lock_info->temp_path, lock_info->lock_path) < 0) {
+	if (nfs_safe_link(lock_info->temp_path,
+			  lock_info->lock_path, TRUE) < 0) {
 		if (errno == EEXIST)
 			return 0;
 
diff -r ebe88bc73154 -r 575235932194 src/lib/nfs-workarounds.c
--- a/src/lib/nfs-workarounds.c	Thu Nov 15 16:27:53 2007 +0200
+++ b/src/lib/nfs-workarounds.c	Fri Nov 16 03:50:15 2007 +0200
@@ -129,16 +129,17 @@ int nfs_safe_lstat(const char *path, str
 	return nfs_safe_do(path, nfs_safe_lstat_callback, buf);
 }
 
-int nfs_safe_link(const char *oldpath, const char *newpath)
-{
-	struct stat st;
-
-#ifdef DEBUG
-	if (stat(oldpath, &st) == 0 && st.st_nlink != 1) {
-		i_panic("nfs_safe_link(): %s link count = %d",
-			oldpath, (int)st.st_nlink);
-	}
-#endif
+int nfs_safe_link(const char *oldpath, const char *newpath, bool links1)
+{
+	struct stat st;
+	nlink_t orig_link_count = 1;
+
+	if (!links1) {
+		if (stat(oldpath, &st) < 0)
+			return -1;
+		orig_link_count = st.st_nlink;
+	}
+
 	if (link(oldpath, newpath) == 0) {
 #ifndef __FreeBSD__
 		return 0;
@@ -151,7 +152,7 @@ int nfs_safe_link(const char *oldpath, c
 	/* We don't know if it succeeded or failed. stat() to make sure. */
 	if (stat(oldpath, &st) < 0)
 		return -1;
-	if (st.st_nlink < 2) {
+	if (st.st_nlink == orig_link_count) {
 		errno = EEXIST;
 		return -1;
 	}
diff -r ebe88bc73154 -r 575235932194 src/lib/nfs-workarounds.h
--- a/src/lib/nfs-workarounds.h	Thu Nov 15 16:27:53 2007 +0200
+++ b/src/lib/nfs-workarounds.h	Fri Nov 16 03:50:15 2007 +0200
@@ -14,9 +14,10 @@ int nfs_safe_open(const char *path, int 
    Doesn't flush attribute cache. */
 int nfs_safe_stat(const char *path, struct stat *buf);
 int nfs_safe_lstat(const char *path, struct stat *buf);
-/* Same as link(), but handle UDP retries by stat()ing to see if the success
-   reply just got lost. Assumes that oldpath's link count is initially 1. */
-int nfs_safe_link(const char *oldpath, const char *newpath);
+/* Same as link(), but handle problems with link() by verifying the file's
+   link count changes. If links1=TRUE, assume the original file's link count
+   is 1, otherwise stat() first to find it out. */
+int nfs_safe_link(const char *oldpath, const char *newpath, bool links1);
 
 /* Flush attribute cache for given path. If flush_dir is TRUE, also the
    directory's cache is flushed. */


More information about the dovecot-cvs mailing list