From 1915794fd39cf1b0e998eb86b93f7e6005c54a47 Mon Sep 17 00:00:00 2001
From: Jingxian He <hejingxian@huawei.com>
Date: Sat, 14 Aug 2021 16:45:40 +0800
Subject: [PATCH 35/54] add reuse file method for recover deleted file state

Add reuse file method for recover file state of deleted files.

Signed-off-by: Jingxian He <hejingxian@huawei.com>
---
 criu/files-reg.c         | 75 +++++++++++++++++++++++++++++++++++++---
 criu/files.c             | 24 ++++++++++---
 criu/include/files-reg.h |  9 +++++
 3 files changed, 99 insertions(+), 9 deletions(-)

diff --git a/criu/files-reg.c b/criu/files-reg.c
index 6bbcbee..46e9eab 100644
--- a/criu/files-reg.c
+++ b/criu/files-reg.c
@@ -1184,6 +1184,70 @@ int strip_deleted(struct fd_link *link)
 	return 0;
 }
 
+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;
+}
+
+extern int dst_pid;
+extern int need_reuse_flag;
 static int check_path_remap(struct fd_link *link, const struct fd_parms *parms,
 				int lfd, u32 id, struct ns_id *nsid)
 {
@@ -1301,9 +1365,12 @@ static int check_path_remap(struct fd_link *link, const struct fd_parms *parms,
 		 * name.
 		 */
 
-		if (errno == ENOENT)
-			return dump_linked_remap(rpath + 1, plen - 1,
-							ost, lfd, id, nsid);
+		if (errno == ENOENT) {
+			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");
 		return -1;
@@ -1724,7 +1791,7 @@ ext:
 	rfe.mode	= p->stat.st_mode;
 
 	if (S_ISREG(p->stat.st_mode) && should_check_size(rfe.flags) &&
-		!store_validation_data(&rfe, p, lfd))
+		(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 0ebf26e..16d34fd 100644
--- a/criu/files.c
+++ b/criu/files.c
@@ -720,7 +720,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)
 {
@@ -758,7 +758,7 @@ int dump_task_files_seized(struct parasite_ctl *ctl, struct pstree_item *item,
 
 		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 < 0)
@@ -768,7 +768,7 @@ int dump_task_files_seized(struct parasite_ctl *ctl, struct pstree_item *item,
 				ret = 0;
 				continue;
 			}
-
+			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)
@@ -964,8 +964,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) {
@@ -1255,6 +1255,7 @@ static int open_fd(struct fdinfo_list_entry *fle)
 	struct fdinfo_list_entry *flem;
 	int new_fd = -1, ret;
 
+	pr_info("open file flags:%x\n", fle->fe->flags);
 	flem = file_master(d);
 	if (fle != flem) {
 		BUG_ON (fle->stage != FLE_INITIALIZED);
@@ -1276,6 +1277,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/files-reg.h b/criu/include/files-reg.h
index 458fe89..4ec0e14 100644
--- a/criu/include/files-reg.h
+++ b/criu/include/files-reg.h
@@ -64,4 +64,13 @@ extern int strip_deleted(struct fd_link *link);
 
 extern int dead_pid_conflict(void);
 
+#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 add_reuse_file(u32 id, int fd, int pid);
+extern int repair_reuse_file(int id);
+extern int get_reuse_file(void);
+
 #endif /* __CR_FILES_REG_H__ */
-- 
2.33.1

