dovecot-2.2: dsync: Added support back for dsync locking.

dovecot at dovecot.org dovecot at dovecot.org
Thu Jan 10 10:21:34 EET 2013


details:   http://hg.dovecot.org/dovecot-2.2/rev/ce0bd8ab1459
changeset: 15629:ce0bd8ab1459
user:      Timo Sirainen <tss at iki.fi>
date:      Thu Jan 10 10:21:27 2013 +0200
description:
dsync: Added support back for dsync locking.
Only the source directory is now locked to avoid deadlocks when both source
and destination are locked. This of course now means that both source and
destination is allowed to run dsync at the same time, which isn't ideal
either..

diffstat:

 src/doveadm/dsync/doveadm-dsync.c |  76 +++++++++++++++++++++++++++++++++-----
 1 files changed, 66 insertions(+), 10 deletions(-)

diffs (129 lines):

diff -r f6d69bc1beed -r ce0bd8ab1459 src/doveadm/dsync/doveadm-dsync.c
--- a/src/doveadm/dsync/doveadm-dsync.c	Thu Jan 10 10:02:47 2013 +0200
+++ b/src/doveadm/dsync/doveadm-dsync.c	Thu Jan 10 10:21:27 2013 +0200
@@ -28,7 +28,8 @@
 #include <unistd.h>
 #include <ctype.h>
 
-#define DSYNC_COMMON_GETOPT_ARGS "+adEfm:n:r:Rs:"
+#define DSYNC_LOCK_FILENAME ".dovecot-sync.lock"
+#define DSYNC_COMMON_GETOPT_ARGS "+adEfl:m:n:r:Rs:"
 
 struct dsync_cmd_context {
 	struct doveadm_mail_cmd_context ctx;
@@ -348,9 +349,8 @@
 }
 
 static int
-cmd_dsync_run(struct doveadm_mail_cmd_context *_ctx, struct mail_user *user)
+cmd_dsync_run_real(struct dsync_cmd_context *ctx, struct mail_user *user)
 {
-	struct dsync_cmd_context *ctx = (struct dsync_cmd_context *)_ctx;
 	struct dsync_ibc *ibc, *ibc2 = NULL;
 	struct dsync_brain *brain;
 	struct mail_namespace *sync_ns = NULL;
@@ -407,7 +407,7 @@
 	}
 
 	if (dsync_brain_deinit(&brain) < 0)
-		_ctx->exit_code = EX_TEMPFAIL;
+		ctx->ctx.exit_code = EX_TEMPFAIL;
 	dsync_ibc_deinit(&ibc);
 	if (ibc2 != NULL)
 		dsync_ibc_deinit(&ibc2);
@@ -427,6 +427,62 @@
 	return ret;
 }
 
+static int dsync_lock(struct mail_user *user, unsigned int lock_timeout,
+		      const char **path_r, struct file_lock **lock_r)
+{
+	const char *home, *path;
+	int ret, fd;
+
+	if ((ret = mail_user_get_home(user, &home)) < 0) {
+		i_error("Couldn't look up user's home dir");
+		return -1;
+	}
+	if (ret == 0) {
+		i_error("User has no home directory");
+		return -1;
+	}
+
+	path = t_strconcat(home, "/"DSYNC_LOCK_FILENAME, NULL);
+	fd = creat(path, 0600);
+	if (fd == -1) {
+		i_error("Couldn't create lock %s: %m", path);
+		return -1;
+	}
+
+	if (file_wait_lock(fd, path, F_WRLCK, FILE_LOCK_METHOD_FCNTL,
+			   lock_timeout, lock_r) <= 0) {
+		i_error("Couldn't lock %s: %m", path);
+		(void)close(fd);
+		return -1;
+	}
+	*path_r = path;
+	return fd;
+}
+
+static int
+cmd_dsync_run(struct doveadm_mail_cmd_context *_ctx, struct mail_user *user)
+{
+	struct dsync_cmd_context *ctx = (struct dsync_cmd_context *)_ctx;
+	const char *lock_path;
+	struct file_lock *lock;
+	int lock_fd, ret;
+
+	if (!ctx->lock)
+		return cmd_dsync_run_real(ctx, user);
+
+	lock_fd = dsync_lock(user, ctx->lock_timeout, &lock_path, &lock);
+	if (lock_fd == -1) {
+		_ctx->exit_code = EX_TEMPFAIL;
+		return -1;
+	} else {
+		ret = cmd_dsync_run_real(ctx, user);
+		file_lock_free(&lock);
+		if (close(lock_fd) < 0)
+			i_error("close(%s) failed: %m", lock_path);
+		return ret;
+	}
+}
+
 static int cmd_dsync_prerun(struct doveadm_mail_cmd_context *_ctx,
 			    struct mail_storage_service_user *service_user,
 			    const char **error_r)
@@ -527,6 +583,11 @@
 	case 'f':
 		ctx->sync_type = DSYNC_BRAIN_SYNC_TYPE_FULL;
 		break;
+	case 'l':
+		ctx->lock = TRUE;
+		if (str_to_uint(optarg, &ctx->lock_timeout) < 0)
+			i_error("Invalid -l parameter: %s", optarg);
+		break;
 	case 'm':
 		ctx->mailbox = optarg;
 		break;
@@ -623,11 +684,6 @@
 		/* dsync wrapper detection flag */
 		legacy_dsync = TRUE;
 		break;
-	case 'l':
-		ctx->lock = TRUE;
-		if (str_to_uint(optarg, &ctx->lock_timeout) < 0)
-			i_error("Invalid -l parameter: %s", optarg);
-		break;
 	case 'r':
 		ctx->rawlog_path = optarg;
 		break;
@@ -642,7 +698,7 @@
 	struct dsync_cmd_context *ctx;
 
 	ctx = doveadm_mail_cmd_alloc(struct dsync_cmd_context);
-	ctx->ctx.getopt_args = "El:r:";
+	ctx->ctx.getopt_args = "Er:";
 	ctx->ctx.v.parse_arg = cmd_mailbox_dsync_server_parse_arg;
 	ctx->ctx.v.run = cmd_dsync_server_run;
 	ctx->sync_type = DSYNC_BRAIN_SYNC_TYPE_CHANGED;


More information about the dovecot-cvs mailing list