309 lines
8.9 KiB
Diff
309 lines
8.9 KiB
Diff
From 61ca95f5434573e89151d3557185c517cd69447a Mon Sep 17 00:00:00 2001
|
|
From: Sang Yan <sangyan@huawei.com>
|
|
Date: Thu, 8 Jul 2021 14:12:42 +0800
|
|
Subject: [PATCH 38/72] file-lock: add repair mode to dump file locks
|
|
|
|
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.
|
|
|
|
Signed-off-by: Sang Yan <sangyan@huawei.com>
|
|
Signed-off-by: fu.lin <fulin10@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 | 16 +++++++++++
|
|
criu/include/parasite-syscall.h | 2 ++
|
|
criu/include/parasite.h | 10 +++++++
|
|
criu/parasite-syscall.c | 33 +++++++++++++++++++++++
|
|
criu/pie/parasite.c | 48 +++++++++++++++++++++++++++++++++
|
|
10 files changed, 130 insertions(+)
|
|
|
|
diff --git a/criu/config.c b/criu/config.c
|
|
index a9eb699..0a0623a 100644
|
|
--- a/criu/config.c
|
|
+++ b/criu/config.c
|
|
@@ -705,6 +705,7 @@ int parse_options(int argc, char **argv, bool *usage_error, bool *has_exec_cmd,
|
|
BOOL_OPT("with-fd-cred", &opts.with_fd_cred),
|
|
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 e7b5787..607eac2 100644
|
|
--- a/criu/cr-dump.c
|
|
+++ b/criu/cr-dump.c
|
|
@@ -1679,6 +1679,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 e1afeca..7358918 100644
|
|
--- a/criu/crtools.c
|
|
+++ b/criu/crtools.c
|
|
@@ -456,6 +456,7 @@ usage:
|
|
" --with-fd-cred Allow to make the restored process has the same cred\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 6334462..c893083 100644
|
|
--- a/criu/file-lock.c
|
|
+++ b/criu/file-lock.c
|
|
@@ -424,6 +424,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);
|
|
@@ -611,8 +613,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 {
|
|
@@ -638,6 +644,10 @@ static int restore_file_lock(FileLockEntry *fle)
|
|
flk.l_pid = fle->pid;
|
|
flk.l_type = fle->type;
|
|
|
|
+ if (opts.file_locks_repair
|
|
+ && (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, fle->start, fle->len);
|
|
diff --git a/criu/include/cr_options.h b/criu/include/cr_options.h
|
|
index dec0082..9ec8034 100644
|
|
--- a/criu/include/cr_options.h
|
|
+++ b/criu/include/cr_options.h
|
|
@@ -197,6 +197,7 @@ struct cr_options {
|
|
int with_fd_cred;
|
|
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 568977c..0627818 100644
|
|
--- a/criu/include/fcntl.h
|
|
+++ b/criu/include/fcntl.h
|
|
@@ -23,6 +23,22 @@ struct f_owner_ex {
|
|
#define F_SETCRED 18
|
|
#endif
|
|
|
|
+#ifndef F_NEED_REPAIR
|
|
+#define F_NEED_REPAIR 16
|
|
+#endif
|
|
+
|
|
+#ifndef F_REPAIR
|
|
+#define F_REPAIR 32
|
|
+#endif
|
|
+
|
|
+#ifndef LOCK_NEED_REPAIR
|
|
+#define LOCK_NEED_REPAIR 256 /* REPAIRING lock */
|
|
+#endif
|
|
+
|
|
+#ifndef LOCK_REPAIR
|
|
+#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 4540e11..9f2d3e0 100644
|
|
--- a/criu/include/parasite-syscall.h
|
|
+++ b/criu/include/parasite-syscall.h
|
|
@@ -48,4 +48,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 d2a0688..230c453 100644
|
|
--- a/criu/include/parasite.h
|
|
+++ b/criu/include/parasite.h
|
|
@@ -37,6 +37,7 @@ enum {
|
|
PARASITE_CMD_CHECK_VDSO_MARK,
|
|
PARASITE_CMD_CHECK_AIOS,
|
|
PARASITE_CMD_DUMP_CGROUP,
|
|
+ PARASITE_CMD_DUMP_FILELOCKS,
|
|
|
|
PARASITE_CMD_MAX,
|
|
};
|
|
@@ -244,6 +245,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 ee4fa86..c57f854 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>
|
|
@@ -654,3 +655,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 e49958b..c781303 100644
|
|
--- a/criu/pie/parasite.c
|
|
+++ b/criu/pie/parasite.c
|
|
@@ -22,6 +22,7 @@
|
|
#include "criu-log.h"
|
|
#include "tty.h"
|
|
#include "aio.h"
|
|
+#include "file-lock.h"
|
|
|
|
#include "asm/parasite.h"
|
|
#include "restorer.h"
|
|
@@ -769,6 +770,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) {
|
|
@@ -821,6 +866,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;
|
|
--
|
|
2.34.1
|
|
|