From 1328e32ee05c59f7168039211c9d96176ff22791 Mon Sep 17 00:00:00 2001 From: Jingxian He Date: Sat, 14 Aug 2021 16:45:40 +0800 Subject: [PATCH 45/72] add reuse file method for recover deleted file state Orphan inode maybe exist in checkpoint process. Sometimes it can't be re-linked by `linkat()` syscall, e.g. sysfs. Therefore, add reuse file method for recover file state of deleted files. Signed-off-by: Jingxian He Signed-off-by: fu.lin --- criu/Makefile.crtools | 1 + criu/files-reg.c | 10 ++++-- criu/files.c | 22 +++++++++++- criu/include/orphan-inode.h | 16 +++++++++ criu/orphan-inode.c | 71 +++++++++++++++++++++++++++++++++++++ 5 files changed, 116 insertions(+), 4 deletions(-) create mode 100644 criu/include/orphan-inode.h create mode 100644 criu/orphan-inode.c diff --git a/criu/Makefile.crtools b/criu/Makefile.crtools index 3e522b4..7fee749 100644 --- a/criu/Makefile.crtools +++ b/criu/Makefile.crtools @@ -95,6 +95,7 @@ obj-y += devname.o obj-y += files-chr.o obj-y += exit-notify.o obj-y += reserved-ports.o +obj-y += orphan-inode.o obj-$(CONFIG_HAS_LIBBPF) += bpfmap.o obj-$(CONFIG_COMPAT) += pie-util-vdso-elf32.o CFLAGS_pie-util-vdso-elf32.o += -DCONFIG_VDSO_32 diff --git a/criu/files-reg.c b/criu/files-reg.c index 6dc8745..ed46764 100644 --- a/criu/files-reg.c +++ b/criu/files-reg.c @@ -46,6 +46,7 @@ #include "external.h" #include "memfd.h" #include "files-chr.h" +#include "orphan-inode.h" #include "protobuf.h" #include "util.h" @@ -1260,8 +1261,10 @@ static int check_path_remap(struct fd_link *link, const struct fd_parms *parms, */ if (errno == ENOENT) { - link_strip_deleted(link); - return dump_linked_remap(rpath + 1, plen - 1, ost, lfd, id, nsid); + pr_info("Start add no exist file: %s\n", rpath+1); + add_reuse_file(id, lfd, dst_pid); + need_reuse_flag = O_REUSE; + return 0; } pr_perror("Can't stat path"); @@ -1663,7 +1666,8 @@ ext: rfe.has_mode = true; rfe.mode = p->stat.st_mode; - if (S_ISREG(p->stat.st_mode) && should_check_size(rfe.flags) && !store_validation_data(&rfe, p, lfd)) + if (S_ISREG(p->stat.st_mode) && should_check_size(rfe.flags) + && (need_reuse_flag != O_REUSE) && !store_validation_data(&rfe, p, lfd)) return -1; fe.type = FD_TYPES__REG; diff --git a/criu/files.c b/criu/files.c index 1c52cf4..e79052e 100644 --- a/criu/files.c +++ b/criu/files.c @@ -50,6 +50,7 @@ #include "fdstore.h" #include "bpfmap.h" #include "files-chr.h" +#include "orphan-inode.h" #include "protobuf.h" #include "util.h" @@ -706,6 +707,7 @@ int dump_my_file(int lfd, u32 *id, int *type) } int dst_pid; +int need_reuse_flag; int dump_task_files_seized(struct parasite_ctl *ctl, struct pstree_item *item, struct parasite_drain_fd *dfds) { @@ -743,10 +745,13 @@ int dump_task_files_seized(struct parasite_ctl *ctl, struct pstree_item *item, s for (i = 0; i < nr_fds; i++) { FdinfoEntry e = FDINFO_ENTRY__INIT; + need_reuse_flag = 0; ret = dump_one_file(item->pid, dfds->fds[i + off], lfds[i], opts + i, ctl, &e, dfds); if (ret) break; + e.flags |= need_reuse_flag; + pr_info("write fdinfoEntry fd=%d id=%d\n", (&e)->fd, (&e)->id); ret = pb_write_one(img, &e, PB_FDINFO); if (ret) break; @@ -939,7 +944,8 @@ int collect_fd(int pid, FdinfoEntry *e, struct rst_info *rst_info, bool fake) { struct file_desc *fdesc; - pr_info("Collect fdinfo pid=%d fd=%d id=%#x\n", pid, e->fd, e->id); + pr_info("Collect fdinfo pid=%d fd=%d id=%#x flags: %#x\n", + pid, e->fd, e->id, e->flags); fdesc = find_file_desc(e); if (fdesc == NULL) { @@ -1230,6 +1236,7 @@ static int open_fd(struct fdinfo_list_entry *fle) int new_fd = -1, ret; struct chrfile_info *ci; + pr_info("open file flags: %#x\n", fle->fe->flags); flem = file_master(d); if (fle != flem) { BUG_ON(fle->stage != FLE_INITIALIZED); @@ -1251,6 +1258,19 @@ static int open_fd(struct fdinfo_list_entry *fle) return 0; } } + } else if (fle->fe->flags & O_REUSE) { + pr_info("find reuse file:%d\n", d->id); + ret = repair_reuse_file(d->id); + if (!ret) { + new_fd = get_reuse_file(); + pr_info("get reuse file:%d\n", new_fd); + if (new_fd <= 0 || setup_and_serve_out(fle, new_fd) < 0) { + pr_err("setup reuse file fail\n"); + return -1; + } + fle->stage = FLE_RESTORED; + return 0; + } } /* diff --git a/criu/include/orphan-inode.h b/criu/include/orphan-inode.h new file mode 100644 index 0000000..bc3b6ae --- /dev/null +++ b/criu/include/orphan-inode.h @@ -0,0 +1,16 @@ +#ifndef __CRIU_ORPHAN_INODE_H__ +#define __CRIU_ORPHAN_INODE_H__ + +#define ADD_REUSE_FILE_PATH "/sys/kernel/add_reuse_file" +#define REPAIR_REUSE_FILE_PATH "/sys/kernel/repair_reuse_file" +#define REUSE_FILE_PATH "/sys/kernel/reuse_file" +#define O_REUSE 0100000000 + +extern int dst_pid; +extern int need_reuse_flag; + +int add_reuse_file(u32 id, int fd, int pid); +int repair_reuse_file(int id); +int get_reuse_file(void); + +#endif /* __CRIU_ORPHAN_INODE_H__ */ diff --git a/criu/orphan-inode.c b/criu/orphan-inode.c new file mode 100644 index 0000000..c4e38dc --- /dev/null +++ b/criu/orphan-inode.c @@ -0,0 +1,71 @@ +#include +#include +#include +#include +#include + +#include "int.h" +#include "log.h" +#include "orphan-inode.h" + +int add_reuse_file(u32 id, int fd, int pid) +{ + int retval; + char buf[256] = {0}; + + retval = snprintf(buf, 256, "%u,%d,%d", id, fd, pid); + if (retval <= 0) + return -EFAULT; + + fd = open(ADD_REUSE_FILE_PATH, O_WRONLY, 0); + if (fd < 0) { + pr_err("open file:%s fail\n", ADD_REUSE_FILE_PATH); + return fd; + } + + retval = write(fd, buf, strlen(buf)); + close(fd); + + return retval < 0 ? -1 : 0; +} + +int repair_reuse_file(int id) +{ + int retval, fd; + char buf[256] = {0}; + + retval = snprintf(buf, 256, "%u", id); + if (retval <= 0) + return -EFAULT; + + fd = open(REPAIR_REUSE_FILE_PATH, O_WRONLY, 0); + if (fd < 0) { + pr_err("open file:%s fail\n", REPAIR_REUSE_FILE_PATH); + return fd; + } + retval = write(fd, buf, strlen(buf)); + + close(fd); + return retval < 0 ? -1 : 0; +} + +int get_reuse_file(void) +{ + int fd; + ssize_t count; + int retval = -1; + char buf[32] = {0}; + + fd = open(REUSE_FILE_PATH, O_RDONLY , 0); + if (fd < 0) { + pr_err("open file:%s fail\n", REUSE_FILE_PATH); + return fd; + } + + count = read(fd, buf, sizeof(buf)); + if (count > 0) + retval = atoi(buf); + + close(fd); + return retval; +} -- 2.34.1