Mercurial > dovecot > core-2.2
changeset 22506:3afbfedcdd31
director: Fix crash when flush is run and all backends are down.
Instead of moving the users elsewhere, just kill them and flush the backend.
author | Timo Sirainen <timo.sirainen@dovecot.fi> |
---|---|
date | Tue, 22 Aug 2017 16:32:32 +0300 |
parents | 3bf3e3364e14 |
children | 633b90217c62 |
files | src/director/director.c src/director/director.h src/director/doveadm-connection.c |
diffstat | 3 files changed, 23 insertions(+), 6 deletions(-) [+] |
line wrap: on
line diff
--- a/src/director/director.c Wed Sep 20 15:03:55 2017 +0300 +++ b/src/director/director.c Tue Aug 22 16:32:32 2017 +0300 @@ -984,10 +984,9 @@ director_user_move_free(user); } -static void -director_kill_user(struct director *dir, struct director_host *src, - struct user *user, struct mail_tag *tag, - struct mail_host *old_host) +void director_kill_user(struct director *dir, struct director_host *src, + struct user *user, struct mail_tag *tag, + struct mail_host *old_host) { struct director_kill_context *ctx; const char *cmd;
--- a/src/director/director.h Wed Sep 20 15:03:55 2017 +0300 +++ b/src/director/director.h Tue Aug 22 16:32:32 2017 +0300 @@ -201,6 +201,9 @@ struct director_connection *src_conn, struct director_host *orig_src, struct user *user) ATTR_NULL(3); +void director_kill_user(struct director *dir, struct director_host *src, + struct user *user, struct mail_tag *tag, + struct mail_host *old_host); void director_move_user(struct director *dir, struct director_host *src, struct director_host *orig_src, unsigned int username_hash, struct mail_host *host)
--- a/src/director/doveadm-connection.c Wed Sep 20 15:03:55 2017 +0300 +++ b/src/director/doveadm-connection.c Tue Aug 22 16:32:32 2017 +0300 @@ -443,6 +443,7 @@ struct director *dir = cmd->dir; struct user *user; struct mail_host *new_host; + bool users_killed = FALSE; if (dir->users_moving_count >= cmd->max_moving_users) return FALSE; @@ -456,18 +457,32 @@ while ((user = director_iterate_users_next(cmd->iter)) != NULL) { if (user->host != host) continue; + new_host = mail_host_get_by_hash(dir->mail_hosts, user->username_hash, mail_host_get_tag(host)); if (new_host != host) T_BEGIN { - director_move_user(dir, dir->self_host, NULL, - user->username_hash, new_host); + if (new_host != NULL) { + director_move_user(dir, dir->self_host, NULL, + user->username_hash, new_host); + } else { + /* there are no more available backends. + kick the user instead. */ + director_kill_user(dir, dir->self_host, user, + user->host->tag, user->host); + users_killed = TRUE; + } } T_END; if (dir->users_moving_count >= cmd->max_moving_users) break; } if (user == NULL) director_iterate_users_deinit(&cmd->iter); + if (users_killed) { + /* no more backends. we already sent kills. now remove the + users entirely from the host. */ + director_flush_host(dir, dir->self_host, NULL, host); + } if (dir->right != NULL) director_connection_uncork(dir->right); return user == NULL;