dovecot-2.0: lib-fs / posix: If create/link/rename fails with EN...
dovecot at dovecot.org
dovecot at dovecot.org
Thu Nov 4 19:50:46 EET 2010
details: http://hg.dovecot.org/dovecot-2.0/rev/952dc335eb75
changeset: 12388:952dc335eb75
user: Timo Sirainen <tss at iki.fi>
date: Thu Nov 04 17:50:42 2010 +0000
description:
lib-fs / posix: If create/link/rename fails with ENOENT, try creating parent dir multiple times.
This avoids random failures when the parent dir happens to be removed at
just the right time.
diffstat:
src/lib-fs/fs-posix.c | 26 ++++++++++++++++++++------
1 files changed, 20 insertions(+), 6 deletions(-)
diffs (90 lines):
diff -r ed94f6d615ef -r 952dc335eb75 src/lib-fs/fs-posix.c
--- a/src/lib-fs/fs-posix.c Thu Nov 04 17:00:42 2010 +0000
+++ b/src/lib-fs/fs-posix.c Thu Nov 04 17:50:42 2010 +0000
@@ -18,6 +18,7 @@
#include <sys/stat.h>
#define FS_POSIX_DOTLOCK_STALE_TIMEOUT_SECS (60*10)
+#define MAX_MKDIR_RETRY_COUNT 5
enum fs_posix_lock_method {
FS_POSIX_LOCK_METHOD_FLOCK,
@@ -85,13 +86,16 @@
fname = strrchr(path, '/');
if (fname == NULL)
+ return 1;
+ dir = t_strdup_until(path, fname);
+ if (mkdir_parents(dir, 0700) == 0)
return 0;
- dir = t_strdup_until(path, fname);
- if (mkdir_parents(dir, 0700) < 0 && errno != EEXIST) {
+ else if (errno == EEXIST)
+ return 1;
+ else {
fs_set_error(fs, "mkdir_parents(%s) failed: %m", dir);
return -1;
}
- return 0;
}
static int
@@ -101,6 +105,7 @@
struct fs *_fs = &fs->fs;
string_t *str = t_str_new(256);
const char *slash = strrchr(path, '/');
+ unsigned int try_count = 0;
int fd;
if (slash != NULL)
@@ -108,10 +113,13 @@
str_append(str, fs->temp_file_prefix);
fd = safe_mkstemp_hostpid(str, 0600, (uid_t)-1, (gid_t)-1);
- if (fd == -1 && errno == ENOENT && (flags & FS_OPEN_FLAG_MKDIR) != 0) {
+ while (fd == -1 && errno == ENOENT &&
+ try_count <= MAX_MKDIR_RETRY_COUNT &&
+ (flags & FS_OPEN_FLAG_MKDIR) != 0) {
if (fs_posix_create_parent_dir(_fs, path) < 0)
return -1;
fd = safe_mkstemp_hostpid(str, 0600, (uid_t)-1, (gid_t)-1);
+ try_count++;
}
if (fd == -1) {
fs_set_error(_fs, "safe_mkstemp(%s) failed: %m", str_c(str));
@@ -454,13 +462,16 @@
static int fs_posix_link(struct fs *fs, const char *src, const char *dest)
{
+ unsigned int try_count = 0;
int ret;
ret = link(src, dest);
- if (ret < 0 && errno == ENOENT) {
+ while (ret < 0 && errno == ENOENT &&
+ try_count <= MAX_MKDIR_RETRY_COUNT) {
if (fs_posix_create_parent_dir(fs, dest) < 0)
return -1;
ret = link(src, dest);
+ try_count++;
}
if (ret < 0) {
fs_set_error(fs, "link(%s, %s) failed: %m", src, dest);
@@ -471,13 +482,16 @@
static int fs_posix_rename(struct fs *fs, const char *src, const char *dest)
{
+ unsigned int try_count = 0;
int ret;
ret = rename(src, dest);
- if (ret < 0 && errno == ENOENT) {
+ while (ret < 0 && errno == ENOENT &&
+ try_count <= MAX_MKDIR_RETRY_COUNT) {
if (fs_posix_create_parent_dir(fs, dest) < 0)
return -1;
ret = rename(src, dest);
+ try_count++;
}
if (ret < 0) {
fs_set_error(fs, "link(%s, %s) failed: %m", src, dest);
More information about the dovecot-cvs
mailing list