[CRIU] [PATCH 3/7] files: Pre-dump file descriptors

Pavel Emelyanov xemul at parallels.com
Thu Jan 30 02:23:55 PST 2014


We will generate some info about file-descriptors at that
stage. For now these pre-dumped ones would be fsnotifies,
so the pre-dump of a single fd is written as simple as
possible, but enough for that type of FDs pre-dump.

Signed-off-by: Pavel Emelyanov <xemul at parallels.com>
---
 cr-dump.c       |  6 ++++++
 files.c         | 64 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 fsnotify.c      | 22 ++++++++++++++++++++
 include/files.h |  2 ++
 4 files changed, 94 insertions(+)

diff --git a/cr-dump.c b/cr-dump.c
index c0f29b0..2c77810 100644
--- a/cr-dump.c
+++ b/cr-dump.c
@@ -1346,6 +1346,12 @@ static int pre_dump_one_task(struct pstree_item *item, struct list_head *ctls)
 		goto err_cure;
 	}
 
+	ret = predump_task_files(pid);
+	if (ret) {
+		pr_err("Pre-dumping files failed (pid: %d)\n", pid);
+		goto err_cure;
+	}
+
 	parasite_ctl->pid.virt = item->pid.virt = misc.pid;
 
 	ret = parasite_dump_pages_seized(parasite_ctl, &vmas, &parasite_ctl->mem_pp);
diff --git a/files.c b/files.c
index 412e2f8..df0e2f1 100644
--- a/files.c
+++ b/files.c
@@ -411,6 +411,70 @@ err:
 	return ret;
 }
 
+static int predump_one_fd(int pid, int fd)
+{
+	int lfd, ret = 0;
+	struct statfs buf;
+	const struct fdtype_ops *ops;
+
+	/*
+	 * This should look like the dump_task_files_seized,
+	 * but since we pre-dump only *notify-s, we use the
+	 * enightened version without fds draining.
+	 */
+
+	lfd = open_proc(pid, "fd/%d", fd);
+	if (lfd < 0)
+		return 0; /* That's OK, it can be a socket */
+
+	if (fstatfs(lfd, &buf)) {
+		pr_perror("Can't fstatfs file");
+		return -1;
+	}
+
+	if (buf.f_type != ANON_INODE_FS_MAGIC)
+		goto out;
+
+	if (is_inotify_link(lfd))
+		ops = &inotify_dump_ops;
+	else if (is_fanotify_link(lfd))
+		ops = &fanotify_dump_ops;
+	else
+		goto out;
+
+	pr_debug("Pre-dumping %d's %d fd\n", pid, fd);
+	ret = ops->pre_dump(pid, fd);
+out:
+	close(lfd);
+	return ret;
+}
+
+int predump_task_files(int pid)
+{
+	struct dirent *de;
+	DIR *fd_dir;
+	int ret = -1;
+
+	pr_info("Pre-dump fds for %d)\n", pid);
+
+	fd_dir = opendir_proc(pid, "fd");
+	if (!fd_dir)
+		return -1;
+
+	while ((de = readdir(fd_dir))) {
+		if (dir_dots(de))
+			continue;
+
+		if (predump_one_fd(pid, atoi(de->d_name)))
+			goto out;
+	}
+
+	ret = 0;
+out:
+	closedir(fd_dir);
+	return ret;
+}
+
 int restore_fown(int fd, FownEntry *fown)
 {
 	struct f_owner_ex owner;
diff --git a/fsnotify.c b/fsnotify.c
index 9430919..7464494 100644
--- a/fsnotify.c
+++ b/fsnotify.c
@@ -181,9 +181,20 @@ static int dump_one_inotify(int lfd, u32 id, const struct fd_parms *p)
 	return parse_fdinfo(lfd, FD_TYPES__INOTIFY, dump_inotify_entry, &id);
 }
 
+static int pre_dump_inotify_entry(union fdinfo_entries *e, void *arg)
+{
+	return 0;
+}
+
+static int pre_dump_one_inotify(int pid, int lfd)
+{
+	return parse_fdinfo_pid(pid, lfd, FD_TYPES__INOTIFY, pre_dump_inotify_entry, NULL);
+}
+
 const struct fdtype_ops inotify_dump_ops = {
 	.type		= FD_TYPES__INOTIFY,
 	.dump		= dump_one_inotify,
+	.pre_dump	= pre_dump_one_inotify,
 };
 
 static int dump_fanotify_entry(union fdinfo_entries *e, void *arg)
@@ -249,9 +260,20 @@ static int dump_one_fanotify(int lfd, u32 id, const struct fd_parms *p)
 	return pb_write_one(fdset_fd(glob_fdset, CR_FD_FANOTIFY_FILE), &fe, PB_FANOTIFY_FILE);
 }
 
+static int pre_dump_fanotify_entry(union fdinfo_entries *e, void *arg)
+{
+	return 0;
+}
+
+static int pre_dump_one_fanotify(int pid, int lfd)
+{
+	return parse_fdinfo_pid(pid, lfd, FD_TYPES__FANOTIFY, pre_dump_fanotify_entry, NULL);
+}
+
 const struct fdtype_ops fanotify_dump_ops = {
 	.type		= FD_TYPES__FANOTIFY,
 	.dump		= dump_one_fanotify,
+	.pre_dump	= pre_dump_one_fanotify,
 };
 
 static char *get_mark_path(const char *who, struct file_remap *remap,
diff --git a/include/files.h b/include/files.h
index 6d43a71..6a69955 100644
--- a/include/files.h
+++ b/include/files.h
@@ -112,6 +112,7 @@ struct file_desc {
 struct fdtype_ops {
 	unsigned int		type;
 	int			(*dump)(int lfd, u32 id, const struct fd_parms *p);
+	int			(*pre_dump)(int pid, int lfd);
 };
 
 extern int do_dump_gen_file(struct fd_parms *p, int lfd,
@@ -120,6 +121,7 @@ extern int do_dump_gen_file(struct fd_parms *p, int lfd,
 struct parasite_drain_fd;
 int dump_task_files_seized(struct parasite_ctl *ctl, struct pstree_item *item,
 		struct parasite_drain_fd *dfds);
+int predump_task_files(int pid);
 
 extern int file_desc_add(struct file_desc *d, u32 id, struct file_desc_ops *ops);
 extern struct fdinfo_list_entry *file_master(struct file_desc *d);
-- 
1.8.4.2


More information about the CRIU mailing list