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