From: Sang Yan sangyan@huawei.com
Add new options "--file-locks-repair" to enable repair mode while dumping file locks. Repair mode keeps locks locked while process were killed in dumping operation. Then resume the locks from repair mode at process resuming.
Conflict:NA Reference:https://gitee.com/src-openeuler/criu/pulls/21 Signed-off-by: Sang Yan sangyan@huawei.com --- criu/config.c | 1 + criu/cr-dump.c | 8 ++++++ criu/crtools.c | 1 + criu/file-lock.c | 10 +++++++ criu/include/cr_options.h | 1 + criu/include/fcntl.h | 7 +++++ criu/include/parasite-syscall.h | 2 ++ criu/include/parasite.h | 10 +++++++ criu/parasite-syscall.c | 33 ++++++++++++++++++++++ criu/pie/parasite.c | 50 +++++++++++++++++++++++++++++++++ 10 files changed, 123 insertions(+)
diff --git a/criu/config.c b/criu/config.c index 006753a..7b6da0d 100644 --- a/criu/config.c +++ b/criu/config.c @@ -549,6 +549,7 @@ int parse_options(int argc, char **argv, bool *usage_error, BOOL_OPT("dump-char-dev", &opts.dump_char_dev), BOOL_OPT("mask-exit-notify", &opts.mask_exit_notify), BOOL_OPT("weak-file-check", &opts.weak_file_check), + BOOL_OPT("file-locks-repair", &opts.file_locks_repair), { }, };
diff --git a/criu/cr-dump.c b/criu/cr-dump.c index e76fe5a..db8e01c 100644 --- a/criu/cr-dump.c +++ b/criu/cr-dump.c @@ -1398,6 +1398,14 @@ static int dump_one_task(struct pstree_item *item, InventoryEntry *parent_ie) goto err_cure; }
+ if (opts.file_locks_repair) { + ret = parasite_dump_file_locks(parasite_ctl, pid); + if (ret) { + pr_err("Can't parasite dump file locks (pid: %d)\n", pid); + goto err_cure; + } + } + ret = dump_task_core_all(parasite_ctl, item, &pps_buf, cr_imgset, &misc); if (ret) { pr_err("Dump core (pid: %d) failed with %d\n", pid, ret); diff --git a/criu/crtools.c b/criu/crtools.c index 239464a..72d8514 100644 --- a/criu/crtools.c +++ b/criu/crtools.c @@ -453,6 +453,7 @@ usage: " --dump-char-dev Dump char dev files as normal file with repair cmd\n" " --mask-exit-notify Mask task exit notify during dump and restore\n" " --weak-file-check Allow file size and mod larger than dumping value\n" +" --file-locks-repair Use repair mode to dump and restore file locks\n" "\n" "Check options:\n" " Without options, "criu check" checks availability of absolutely required\n" diff --git a/criu/file-lock.c b/criu/file-lock.c index 8be7589..44ecc92 100644 --- a/criu/file-lock.c +++ b/criu/file-lock.c @@ -428,6 +428,8 @@ void discard_dup_locks_tail(pid_t pid, int fd) list_for_each_entry_safe_reverse(fl, p, &file_lock_list, list) { if (fl->owners_fd != fd || pid != fl->fl_holder) break; + if (fl->fl_kind == FL_POSIX) + continue;
list_del(&fl->list); xfree(fl); @@ -618,8 +620,12 @@ static int restore_file_lock(FileLockEntry *fle) cmd = fle->type; } else if (fle->type == F_RDLCK) { cmd = LOCK_SH; + if (opts.file_locks_repair) + cmd = LOCK_REPAIR; } else if (fle->type == F_WRLCK) { cmd = LOCK_EX; + if (opts.file_locks_repair) + cmd = LOCK_REPAIR; } else if (fle->type == F_UNLCK) { cmd = LOCK_UN; } else { @@ -645,6 +651,10 @@ static int restore_file_lock(FileLockEntry *fle) flk.l_pid = fle->pid; flk.l_type = fle->type;
+ if (opts.file_locks_repair) + if (fle->type == F_RDLCK || fle->type == F_WRLCK) + flk.l_type = F_REPAIR; + pr_info("(posix)flag: %d, type: %d, pid: %d, fd: %d, " "start: %8"PRIx64", len: %8"PRIx64"\n", fle->flag, fle->type, fle->pid, fle->fd, diff --git a/criu/include/cr_options.h b/criu/include/cr_options.h index fc7818c..607b528 100644 --- a/criu/include/cr_options.h +++ b/criu/include/cr_options.h @@ -183,6 +183,7 @@ struct cr_options { int dump_char_dev; int mask_exit_notify; int weak_file_check; + int file_locks_repair; };
extern struct cr_options opts; diff --git a/criu/include/fcntl.h b/criu/include/fcntl.h index 0936337..65f8b36 100644 --- a/criu/include/fcntl.h +++ b/criu/include/fcntl.h @@ -23,6 +23,13 @@ struct f_owner_ex { #define F_SETCRED 18 #endif
+#ifndef F_NEED_REPAIR +#define F_NEED_REPAIR 16 +#define F_REPAIR 32 +#define LOCK_NEED_REPAIR 256 /* REPAIRING lock */ +#define LOCK_REPAIR 512 /* REPAIR lock */ +#endif + /* * These things are required to compile on CentOS-6 */ diff --git a/criu/include/parasite-syscall.h b/criu/include/parasite-syscall.h index c86a724..14e1f31 100644 --- a/criu/include/parasite-syscall.h +++ b/criu/include/parasite-syscall.h @@ -54,4 +54,6 @@ extern int parasite_dump_cgroup(struct parasite_ctl *ctl, struct parasite_dump_c
extern struct parasite_tty_args *parasite_dump_tty(struct parasite_ctl *ctl, int fd, int type);
+extern int parasite_dump_file_locks(struct parasite_ctl *ctl, int pid); + #endif /* __CR_PARASITE_SYSCALL_H__ */ diff --git a/criu/include/parasite.h b/criu/include/parasite.h index d957094..1c702f0 100644 --- a/criu/include/parasite.h +++ b/criu/include/parasite.h @@ -35,6 +35,7 @@ enum { PARASITE_CMD_CHECK_VDSO_MARK, PARASITE_CMD_CHECK_AIOS, PARASITE_CMD_DUMP_CGROUP, + PARASITE_CMD_DUMP_FILELOCKS,
PARASITE_CMD_MAX, }; @@ -236,6 +237,15 @@ struct parasite_dump_cgroup_args { char contents[1 << 12]; };
+struct parasite_dump_filelocks_args { + short kind; + short type; + long start; + long len; + int pid; + int fd; +}; + #endif /* !__ASSEMBLY__ */
#endif /* __CR_PARASITE_H__ */ diff --git a/criu/parasite-syscall.c b/criu/parasite-syscall.c index 8d9e01b..8fdb475 100644 --- a/criu/parasite-syscall.c +++ b/criu/parasite-syscall.c @@ -32,6 +32,7 @@ #include <compel/plugins/std/syscall-codes.h> #include "signal.h" #include "sigframe.h" +#include "file-lock.h"
#include <string.h> #include <stdlib.h> @@ -591,3 +592,35 @@ struct parasite_ctl *parasite_infect_seized(pid_t pid, struct pstree_item *item,
return ctl; } + +int parasite_dump_file_locks(struct parasite_ctl *ctl, int pid) +{ + struct parasite_dump_filelocks_args *args; + struct file_lock *fl; + int ret; + + args = compel_parasite_args(ctl, struct parasite_dump_filelocks_args); + + list_for_each_entry(fl, &file_lock_list, list) { + if (fl->real_owner != pid) + continue; + + args->pid = fl->real_owner; + args->fd = fl->owners_fd; + args->kind = fl->fl_kind; + args->type = fl->fl_ltype; + args->start = fl->start; + if (!strncmp(fl->end, "EOF", 3)) + args->len = 0; + else + args->len = (atoll(fl->end) + 1) - fl->start; + + ret = compel_rpc_call_sync(PARASITE_CMD_DUMP_FILELOCKS, ctl); + if (ret < 0) { + pr_err("Parasite dump file lock failed! (pid: %d)\n", pid); + return ret; + } + } + + return 0; +} diff --git a/criu/pie/parasite.c b/criu/pie/parasite.c index d839783..635c3f8 100644 --- a/criu/pie/parasite.c +++ b/criu/pie/parasite.c @@ -7,6 +7,8 @@ #include <stdarg.h> #include <sys/ioctl.h> #include <sys/uio.h> +#include <unistd.h> +#include <fcntl.h>
#include "common/config.h" #include "int.h" @@ -20,6 +22,7 @@ #include "criu-log.h" #include "tty.h" #include "aio.h" +#include "file-lock.h"
#include "asm/parasite.h" #include "restorer.h" @@ -677,6 +680,50 @@ static int parasite_dump_cgroup(struct parasite_dump_cgroup_args *args) return 0; }
+static int set_filelocks_needrepair(struct parasite_dump_filelocks_args *args) +{ + int ret; + + if (args->kind == FL_FLOCK) { + if (args->type == F_RDLCK || args->type == F_WRLCK) { + int cmd = LOCK_NEED_REPAIR; + + pr_info("Need Repair flock kind: %d, type: %d, cmd: %d, pid: %d, fd: %d\n", + args->kind, args->type, cmd, args->pid, args->fd); + + ret = sys_flock(args->fd, cmd); + if (ret < 0) { + pr_err("Can not set NEED_REPAIR flock!\n"); + return ret; + } + } + } else if (args->kind == FL_POSIX) { + if (args->type == F_RDLCK || args->type == F_WRLCK) { + struct flock flk; + memset(&flk, 0, sizeof(flk)); + + flk.l_whence = SEEK_SET; + flk.l_start = args->start; + flk.l_len = args->len; + flk.l_pid = args->pid; + flk.l_type = F_NEED_REPAIR; + + pr_info("Need Repair posix lock kind: %d, type: %d, cmd: %d, pid: %d, fd: %d, " + "start: %8"PRIx64", len: %8"PRIx64"\n", + args->kind, args->type, flk.l_type, args->pid, args->fd, + args->start, args->len); + + ret = sys_fcntl(args->fd, F_SETLKW, (long)&flk); + if (ret < 0) { + pr_err("Can not set NEED_REPAIR posix lock!\n"); + return ret; + } + } + } + + return 0; +} + void parasite_cleanup(void) { if (mprotect_args) { @@ -729,6 +776,9 @@ int parasite_daemon_cmd(int cmd, void *args) case PARASITE_CMD_DUMP_CGROUP: ret = parasite_dump_cgroup(args); break; + case PARASITE_CMD_DUMP_FILELOCKS: + ret = set_filelocks_needrepair(args); + break; default: pr_err("Unknown command in parasite daemon thread leader: %d\n", cmd); ret = -1;