From a7b6e112372231fcc481bc29b2e81198bde7c942 Mon Sep 17 00:00:00 2001 From: Kirill Tkhai Date: Tue, 23 Jan 2018 13:32:13 +0300 Subject: [PATCH 1/5] spfs: Handle non-zero exit status in cleanup_spfs_mount() Consider non-zero exit status of spfs similar to killed status and do the same cleanups. Signed-off-by: Kirill Tkhai Acked-by: Stanislav Kinsburskiy --- manager/context.c | 8 ++++---- manager/spfs.c | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/manager/context.c b/manager/context.c index 1eb37c9..73d5ada 100644 --- a/manager/context.c +++ b/manager/context.c @@ -45,12 +45,12 @@ const char *mgr_ovz_id(void) static void cleanup_spfs_mount(struct spfs_manager_context_s *ctx, struct spfs_info_s *info, int status) { - bool killed = WIFSIGNALED(status); + bool failed = WIFSIGNALED(status) || !!WEXITSTATUS(status); pr_debug("removing info %s from the list\n", info->mnt.id); - if (killed) - /* SPFS master was killed. We need to release the reference */ + if (failed) + /* SPFS master was failed. We need to release the reference */ spfs_release_mnt(info); info->dead = true; @@ -59,7 +59,7 @@ static void cleanup_spfs_mount(struct spfs_manager_context_s *ctx, if (unlink(info->socket_path)) pr_perror("failed to unlink %s", info->socket_path); - spfs_cleanup_env(info, killed); + spfs_cleanup_env(info, failed); close_namespaces(info->ns_fds); } diff --git a/manager/spfs.c b/manager/spfs.c index 3e0f667..99845b1 100644 --- a/manager/spfs.c +++ b/manager/spfs.c @@ -409,9 +409,9 @@ int spfs_prepare_env(struct spfs_info_s *info, const char *proxy_dir) return err ? err : res; } -static int __spfs_cleanup_env(struct spfs_info_s *info, bool killed) +static int __spfs_cleanup_env(struct spfs_info_s *info, bool failed) { - if (killed && umount(info->work_dir)) { + if (failed && umount(info->work_dir)) { pr_perror("failed to umount %s", info->work_dir); return -errno; } @@ -423,7 +423,7 @@ static int __spfs_cleanup_env(struct spfs_info_s *info, bool killed) return 0; } -int spfs_cleanup_env(struct spfs_info_s *info, bool killed) +int spfs_cleanup_env(struct spfs_info_s *info, bool failed) { int err, res; unsigned orig_ns_mask; @@ -432,7 +432,7 @@ int spfs_cleanup_env(struct spfs_info_s *info, bool killed) if (res) return res; - err = __spfs_cleanup_env(info, killed); + err = __spfs_cleanup_env(info, failed); res = leave_spfs_context(info, orig_ns_mask); From 1aa22a79fa216a22bbbea6c3fad1e2d587ee5e36 Mon Sep 17 00:00:00 2001 From: Kirill Tkhai Date: Thu, 18 Jan 2018 16:14:42 +0300 Subject: [PATCH 2/5] spfs: Main process wakes and kills its children on exit Stanislav Kinsburskiy says: "SPFS manager has a special "--exit-with-spfs" options, which is used by CRIU. The idea of the option is simple: force SPFS manager to exit, when it has some SPFS processes among its children (i.e. spfs was mounted at least once), but all these processes have exited for whatever reason (which usually happens when restore has failed and spfs mounts where unmounted). Although it works in overall (main SPFS manager process exits), its children (responsible to SPFS replacement) may wait on FUTEX for "release" command for corresponding SPFS mount and thus never stop until they are killed". 1 spfs-manager 2 \_ spfs 3 \_ spfs-manager 4 \_ spfs 5 \_ spfs-manager 2 and 3 are pair of a mount, and 4 and 5 are pair of another mount. The patch makes spfs-manager 1 kill 3 in case of 2 exited. https://jira.sw.ru/browse/PSBM-80055 Signed-off-by: Kirill Tkhai Acked-by: Stanislav Kinsburskiy --- manager/context.c | 9 +++++++-- manager/spfs.c | 1 + 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/manager/context.c b/manager/context.c index 73d5ada..54667bb 100644 --- a/manager/context.c +++ b/manager/context.c @@ -47,11 +47,15 @@ static void cleanup_spfs_mount(struct spfs_manager_context_s *ctx, { bool failed = WIFSIGNALED(status) || !!WEXITSTATUS(status); - pr_debug("removing info %s from the list\n", info->mnt.id); + pr_debug("removing info %s from the list (replacer pid %d)\n", + info->mnt.id, info->replacer); - if (failed) + if (failed) { /* SPFS master was failed. We need to release the reference */ spfs_release_mnt(info); + if (info->replacer > 0 && kill(info->replacer, SIGKILL)) + pr_perror("Failed to kill replacer"); + } info->dead = true; del_spfs_info(ctx->spfs_mounts, info); @@ -88,6 +92,7 @@ static void sigchld_handler(int signal, siginfo_t *siginfo, void *data) * corresponding fd. */ spfs_release_mnt(info); + info->replacer = -1; } else { info = find_spfs_by_pid(ctx->spfs_mounts, pid); if (info) { diff --git a/manager/spfs.c b/manager/spfs.c index 99845b1..7ee582f 100644 --- a/manager/spfs.c +++ b/manager/spfs.c @@ -107,6 +107,7 @@ int create_spfs_info(const char *id, INIT_LIST_HEAD(&info->processes); info->mode = SPFS_REPLACE_MODE_HOLD; + info->replacer = -1; *i = info; From 387e19a98d5908af9bce4624a99d7cd3bb291dda Mon Sep 17 00:00:00 2001 From: Alexander Mikhalitsyn Date: Thu, 27 Feb 2020 17:24:44 +0300 Subject: [PATCH 3/5] file_obj: add symlinks support We already have support of symlinks in VZ CRIU. Ghost symlinks / SPFS symlinks: https://src.openvz.org/projects/OVZ/repos/criu/commits/de0e4ca6b8ba5daf6e5728391a14b1645934d4e4 Symlinks: https://src.openvz.org/projects/OVZ/repos/criu/commits/5ed081ed6d112d6158e4c15a8358d4d8778c4588 It make sense to add symlinks support to SPFS Signed-off-by: Alexander Mikhalitsyn Signed-off-by: Alexander Mikhalitsyn --- manager/file_obj.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/manager/file_obj.c b/manager/file_obj.c index 387a6dc..a97aaa4 100644 --- a/manager/file_obj.c +++ b/manager/file_obj.c @@ -198,6 +198,10 @@ fobj_ops_t fobj_ops[] = { .early_open = unix_sk_early_open, .close = reg_file_close, }, + [FTYPE_LINK] = { + .open = reg_file_open, + .close = reg_file_close, + }, }; static file_type_t convert_mode_to_type(mode_t mode) @@ -233,9 +237,9 @@ static int get_file_ops(mode_t mode, fobj_ops_t **ops) case FTYPE_DIR: case FTYPE_FIFO: case FTYPE_SOCK: + case FTYPE_LINK: *ops = &fobj_ops[type]; return 0; - case FTYPE_LINK: case FTYPE_CHR: case FTYPE_BLK: break; From 00966605aa1c2e4e503b51b1644c22bbccc672bb Mon Sep 17 00:00:00 2001 From: Alexander Mikhalitsyn Date: Wed, 4 Mar 2020 12:06:49 +0300 Subject: [PATCH 4/5] socket: add socket fd in log messages Signed-off-by: Alexander Mikhalitsyn Signed-off-by: Alexander Mikhalitsyn --- src/socket.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/socket.c b/src/socket.c index 05f171c..1184d69 100644 --- a/src/socket.c +++ b/src/socket.c @@ -76,7 +76,7 @@ int unreliable_conn_handler(int sock, void *data, return -errno; } if (bytes == 0) { - pr_debug("%s: peer was closed\n", __func__); + pr_debug("%s: peer was closed for fd %d\n", __func__, sock); return -ECONNABORTED; } @@ -105,7 +105,7 @@ int unreliable_socket_loop(int psock, void *data, bool async, break; } - pr_debug("%s: accepted new socket\n", __func__); + pr_debug("%s: accepted new socket fd %d\n", __func__, sock); do { err = unreliable_conn_handler(sock, data, packet_handler); From a52b76389459b129cebb054b5d84f71a8c9cd92d Mon Sep 17 00:00:00 2001 From: Alexander Mikhalitsyn Date: Wed, 4 Mar 2020 12:06:24 +0300 Subject: [PATCH 5/5] manager: add logs in sigchld_handler for "replacer" process exit event Signed-off-by: Alexander Mikhalitsyn Signed-off-by: Alexander Mikhalitsyn --- manager/context.c | 36 ++++++++++++++++++++---------------- 1 file changed, 20 insertions(+), 16 deletions(-) diff --git a/manager/context.c b/manager/context.c index 54667bb..c751495 100644 --- a/manager/context.c +++ b/manager/context.c @@ -68,6 +68,14 @@ static void cleanup_spfs_mount(struct spfs_manager_context_s *ctx, close_namespaces(info->ns_fds); } +static inline void pr_term_mnt_service_info(pid_t pid, int status, const char *mnt, const char* tag) +{ + if (WIFEXITED(status)) + pr_debug("spfs (mnt_id %s) %s (pid %d) exited, status=%d\n", mnt, tag, pid, WEXITSTATUS(status)); + else + pr_err("spfs (mnt_id %s) %s (pid %d) killed by signal %d (%s)\n", mnt, tag, pid, WTERMSIG(status), strsignal(WTERMSIG(status))); +} + static void sigchld_handler(int signal, siginfo_t *siginfo, void *data) { struct spfs_manager_context_s *ctx = &spfs_manager_context; @@ -79,30 +87,26 @@ static void sigchld_handler(int signal, siginfo_t *siginfo, void *data) while ((pid = waitpid(-1, &status, WNOHANG)) > 0) { struct spfs_info_s *info; - if (WIFEXITED(status)) - pr_debug("%d exited, status=%d\n", pid, WEXITSTATUS(status)); - else - pr_err("%d killed by signal %d (%s)\n", pid, WTERMSIG(status), strsignal(WTERMSIG(status))); - - info = find_spfs_by_replacer(ctx->spfs_mounts, pid); - if (info) { + if ((info = find_spfs_by_replacer(ctx->spfs_mounts, pid))) { if (WEXITSTATUS(status) == 0) /* SPFS has been successfully replaced. * Now we can release spfs mount by closing * corresponding fd. */ spfs_release_mnt(info); + + pr_term_mnt_service_info(pid, status, info->mnt.id, "replacer"); info->replacer = -1; - } else { - info = find_spfs_by_pid(ctx->spfs_mounts, pid); - if (info) { - pr_info("spfs %s master has exited\n", info->mnt.id); - cleanup_spfs_mount(ctx, info, status); - if (list_empty(&ctx->spfs_mounts->list) && ctx->exit_with_spfs) { - pr_info("spfs list is empty. Exiting.\n"); - exit(0); - } + } else if ((info = find_spfs_by_pid(ctx->spfs_mounts, pid))) { + pr_term_mnt_service_info(pid, status, info->mnt.id, "master"); + + cleanup_spfs_mount(ctx, info, status); + if (list_empty(&ctx->spfs_mounts->list) && ctx->exit_with_spfs) { + pr_info("spfs list is empty. Exiting.\n"); + exit(0); } + } else { + pr_term_mnt_service_info(pid, status, "unknown", "unknown"); } }