changeset 22551:a89fc39f2135

director: Fix tracking user move count when user is freed early users_moving_count wasn't updated if the user was freed before killing it finished. This caused "doveadm director flush" to hang while waiting for the move count to drop to 0, which it never did. Also following flushes were doing less work in parallel, or possibly even nothing since director thought there were too many users already being moved.
author Timo Sirainen <timo.sirainen@dovecot.fi>
date Wed, 04 Oct 2017 15:39:08 +0300
parents 73e9c31c22dd
children 7b8e95de2bff
files src/director/director.c
diffstat 1 files changed, 10 insertions(+), 4 deletions(-) [+]
line wrap: on
line diff
--- a/src/director/director.c	Wed Oct 04 10:32:17 2017 +0300
+++ b/src/director/director.c	Wed Oct 04 15:39:08 2017 +0300
@@ -835,6 +835,14 @@
 	program_client_run_async(ctx->pclient, director_flush_user_continue, ctx);
 }
 
+static void director_user_move_finished(struct director *dir)
+{
+	i_assert(dir->users_moving_count > 0);
+	dir->users_moving_count--;
+
+	director_set_state_changed(dir);
+}
+
 static void director_user_move_free(struct user *user)
 {
 	struct director *dir = user->kill_ctx->dir;
@@ -851,10 +859,7 @@
 	i_free(kill_ctx);
 	user->kill_ctx = NULL;
 
-	i_assert(dir->users_moving_count > 0);
-	dir->users_moving_count--;
-
-	director_set_state_changed(dir);
+	director_user_move_finished(dir);
 }
 
 static void
@@ -950,6 +955,7 @@
 	if (!DIRECTOR_KILL_CONTEXT_IS_VALID(user, ctx)) {
 		/* user was already freed - ignore */
 		i_assert(ctx->to_move == NULL);
+		director_user_move_finished(ctx->dir);
 		i_free(ctx);
 	} else {
 		i_assert(ctx->kill_state == USER_KILL_STATE_KILLING ||