[CRIU] [PATCH 3/9] vma: Introduce list-of-vmas object

Pavel Emelyanov xemul at parallels.com
Fri Mar 1 11:02:49 EST 2013


Right now when we collect list of vmas we need to know the
number of elements in it. In the future I will need to know
more, so it makes sense to create a vmas-list object for it.

Signed-off-by: Pavel Emelyanov <xemul at parallels.com>

---
 cr-dump.c                  | 35 +++++++++++++++++------------------
 cr-exec.c                  |  6 +++---
 cr-restore.c               | 45 ++++++++++++++++++++++-----------------------
 include/crtools.h          | 11 +++++++++--
 include/parasite-syscall.h |  7 ++++---
 include/proc_parse.h       |  4 +++-
 parasite-syscall.c         | 10 +++++-----
 proc_parse.c               | 13 ++++++++-----
 8 files changed, 71 insertions(+), 60 deletions(-)

diff --git a/cr-dump.c b/cr-dump.c
index 0486327..f9032b1 100644
--- a/cr-dump.c
+++ b/cr-dump.c
@@ -62,20 +62,21 @@
 static char loc_buf[PAGE_SIZE];
 static int pidns_proc = -1;
 
-void free_mappings(struct list_head *vma_area_list)
+void free_mappings(struct vm_area_list *vma_area_list)
 {
 	struct vma_area *vma_area, *p;
 
-	list_for_each_entry_safe(vma_area, p, vma_area_list, list) {
+	list_for_each_entry_safe(vma_area, p, &vma_area_list->h, list) {
 		if (vma_area->vm_file_fd > 0)
 			close(vma_area->vm_file_fd);
 		free(vma_area);
 	}
 
-	INIT_LIST_HEAD(vma_area_list);
+	INIT_LIST_HEAD(&vma_area_list->h);
+	vma_area_list->nr = 0;
 }
 
-int collect_mappings(pid_t pid, struct list_head *vma_area_list)
+int collect_mappings(pid_t pid, struct vm_area_list *vma_area_list)
 {
 	int ret = -1;
 
@@ -87,11 +88,9 @@ int collect_mappings(pid_t pid, struct list_head *vma_area_list)
 	if (ret < 0)
 		goto err;
 
-	pr_info_vma_list(vma_area_list);
+	pr_info_vma_list(&vma_area_list->h);
 
 	pr_info("----------------------------------------\n");
-	ret = 0;
-
 err:
 	return ret;
 }
@@ -300,7 +299,7 @@ static int dump_filemap(pid_t pid, VmaEntry *vma, int file_fd,
 	return dump_one_reg_file(file_fd, vma->shmid, &p);
 }
 
-static int dump_task_mappings(pid_t pid, const struct list_head *vma_area_list,
+static int dump_task_mappings(pid_t pid, const struct vm_area_list *vma_area_list,
 			      const struct cr_fdset *cr_fdset)
 {
 	struct vma_area *vma_area;
@@ -312,7 +311,7 @@ static int dump_task_mappings(pid_t pid, const struct list_head *vma_area_list,
 
 	fd = fdset_fd(cr_fdset, CR_FD_VMAS);
 
-	list_for_each_entry(vma_area, vma_area_list, list) {
+	list_for_each_entry(vma_area, &vma_area_list->h, list) {
 		VmaEntry *vma = &vma_area->vma;
 
 		pr_info_vma(vma_area);
@@ -610,7 +609,7 @@ static int dump_task_ids(struct pstree_item *item, const struct cr_fdset *cr_fds
 static int dump_task_core_all(pid_t pid, const struct proc_pid_stat *stat,
 		const struct parasite_dump_misc *misc, const struct parasite_ctl *ctl,
 		const struct cr_fdset *cr_fdset,
-		struct list_head *vma_area_list)
+		struct vm_area_list *vma_area_list)
 {
 	int fd_core = fdset_fd(cr_fdset, CR_FD_CORE);
 	CoreEntry *core;
@@ -632,7 +631,7 @@ static int dump_task_core_all(pid_t pid, const struct proc_pid_stat *stat,
 	if (ret)
 		goto err_free;
 
-	mark_stack_vma(CORE_THREAD_ARCH_INFO(core)->gpregs->sp, vma_area_list);
+	mark_stack_vma(CORE_THREAD_ARCH_INFO(core)->gpregs->sp, &vma_area_list->h);
 
 	ret = get_task_futex_robust_list(pid, core->thread_core);
 	if (ret)
@@ -1240,7 +1239,7 @@ err:
 static int dump_one_task(struct pstree_item *item)
 {
 	pid_t pid = item->pid.real;
-	LIST_HEAD(vma_area_list);
+	struct vm_area_list vmas;
 	struct parasite_ctl *parasite_ctl;
 	int ret = -1;
 	struct parasite_dump_misc misc;
@@ -1268,7 +1267,7 @@ static int dump_one_task(struct pstree_item *item)
 	if (ret < 0)
 		goto err;
 
-	ret = collect_mappings(pid, &vma_area_list);
+	ret = collect_mappings(pid, &vmas);
 	if (ret) {
 		pr_err("Collect mappings (pid: %d) failed with %d\n", pid, ret);
 		goto err;
@@ -1281,7 +1280,7 @@ static int dump_one_task(struct pstree_item *item)
 	}
 
 	ret = -1;
-	parasite_ctl = parasite_infect_seized(pid, item, &vma_area_list, dfds);
+	parasite_ctl = parasite_infect_seized(pid, item, &vmas, dfds);
 	if (!parasite_ctl) {
 		pr_err("Can't infect (pid: %d) with parasite\n", pid);
 		goto err;
@@ -1336,7 +1335,7 @@ static int dump_one_task(struct pstree_item *item)
 		}
 	}
 
-	ret = parasite_dump_pages_seized(parasite_ctl, &vma_area_list, cr_fdset);
+	ret = parasite_dump_pages_seized(parasite_ctl, &vmas, cr_fdset);
 	if (ret) {
 		pr_err("Can't dump pages (pid: %d) with parasite\n", pid);
 		goto err_cure;
@@ -1355,7 +1354,7 @@ static int dump_one_task(struct pstree_item *item)
 	}
 
 	ret = dump_task_core_all(pid, &pps_buf, &misc,
-					parasite_ctl, cr_fdset, &vma_area_list);
+					parasite_ctl, cr_fdset, &vmas);
 	if (ret) {
 		pr_err("Dump core (pid: %d) failed with %d\n", pid, ret);
 		goto err_cure;
@@ -1379,7 +1378,7 @@ static int dump_one_task(struct pstree_item *item)
 		goto err;
 	}
 
-	ret = dump_task_mappings(pid, &vma_area_list, cr_fdset);
+	ret = dump_task_mappings(pid, &vmas, cr_fdset);
 	if (ret) {
 		pr_err("Dump mappings (pid: %d) failed with %d\n", pid, ret);
 		goto err;
@@ -1401,7 +1400,7 @@ static int dump_one_task(struct pstree_item *item)
 err:
 	close_pid_proc();
 err_free:
-	free_mappings(&vma_area_list);
+	free_mappings(&vmas);
 	xfree(dfds);
 	return ret;
 
diff --git a/cr-exec.c b/cr-exec.c
index 4bdd72e..79c7461 100644
--- a/cr-exec.c
+++ b/cr-exec.c
@@ -84,7 +84,7 @@ int cr_exec(int pid, char **opt)
 	char *sys_name = opt[0];
 	struct syscall_exec_desc *si;
 	struct parasite_ctl *ctl;
-	LIST_HEAD(vma_area_list);
+	struct vm_area_list vmas;
 	int ret = -1, prev_state;
 
 	if (!sys_name) {
@@ -104,13 +104,13 @@ int cr_exec(int pid, char **opt)
 		goto out;
 	}
 
-	ret = collect_mappings(pid, &vma_area_list);
+	ret = collect_mappings(pid, &vmas);
 	if (ret) {
 		pr_err("Can't collect vmas for %d\n", pid);
 		goto out_unseize;
 	}
 
-	ctl = parasite_prep_ctl(pid, &vma_area_list);
+	ctl = parasite_prep_ctl(pid, &vmas);
 	if (!ctl) {
 		pr_err("Can't prep ctl %d\n", pid);
 		goto out_unseize;
diff --git a/cr-restore.c b/cr-restore.c
index bbe8220..53e0645 100644
--- a/cr-restore.c
+++ b/cr-restore.c
@@ -70,8 +70,7 @@ static int restore_task_with_children(void *);
 static int sigreturn_restore(pid_t pid, CoreEntry *core);
 static int prepare_restorer_blob(void);
 
-static LIST_HEAD(rst_vma_list);
-static int rst_nr_vmas;
+static VM_AREA_LIST(rst_vmas);
 
 static int shmem_remap(void *old_addr, void *new_addr, unsigned long size)
 {
@@ -267,7 +266,7 @@ static int restore_priv_vma_content(pid_t pid)
 	unsigned int nr_shared = 0;
 	unsigned int nr_droped = 0;
 
-	vma = list_first_entry(&rst_vma_list, struct vma_area, list);
+	vma = list_first_entry(&rst_vmas.h, struct vma_area, list);
 
 	fd = open_image_ro(CR_FD_PAGES, pid);
 	if (fd < 0)
@@ -293,7 +292,7 @@ static int restore_priv_vma_content(pid_t pid)
 		BUG_ON(va < vma->vma.start);
 
 		while (va >= vma->vma.end) {
-			BUG_ON(vma->list.next == &rst_vma_list);
+			BUG_ON(vma->list.next == &rst_vmas.h);
 			vma = list_entry(vma->list.next, struct vma_area, list);
 		}
 
@@ -322,7 +321,7 @@ static int restore_priv_vma_content(pid_t pid)
 	close(fd);
 
 	/* Remove pages, which were not shared with a child */
-	list_for_each_entry(vma, &rst_vma_list, list) {
+	list_for_each_entry(vma, &rst_vmas.h, list) {
 		unsigned long size, i = 0;
 		void *addr = decode_pointer(vma_premmaped_start(&vma->vma));
 
@@ -366,8 +365,8 @@ static int read_vmas(int pid)
 	void *old_premmapped_addr = NULL;
 	unsigned long old_premmapped_len, pstart = 0;
 
-	rst_nr_vmas = 0;
-	list_replace_init(&rst_vma_list, &old);
+	rst_vmas.nr = 0;
+	list_replace_init(&rst_vmas.h, &old);
 
 	/* Skip errors, because a zombie doesn't have an image of vmas */
 	fd = open_image_ro(CR_FD_VMAS, pid);
@@ -390,8 +389,8 @@ static int read_vmas(int pid)
 		if (ret <= 0)
 			break;
 
-		rst_nr_vmas++;
-		list_add_tail(&vma->list, &rst_vma_list);
+		rst_vmas.nr++;
+		list_add_tail(&vma->list, &rst_vmas.h);
 
 		if (e->fd != -1) {
 			ret = -1;
@@ -423,7 +422,7 @@ static int read_vmas(int pid)
 
 	pvma = list_entry(&old, struct vma_area, list);
 
-	list_for_each_entry(vma, &rst_vma_list, list) {
+	list_for_each_entry(vma, &rst_vmas.h, list) {
 		if (pstart > vma->vma.start) {
 			ret = -1;
 			pr_err("VMA-s are not sorted in the image file\n");
@@ -468,7 +467,7 @@ static int open_vmas(int pid)
 	struct vma_area *vma;
 	int ret = 0;
 
-	list_for_each_entry(vma, &rst_vma_list, list) {
+	list_for_each_entry(vma, &rst_vmas.h, list) {
 		if (!(vma_entry_is(&vma->vma, VMA_AREA_REGULAR)))
 			continue;
 
@@ -1445,7 +1444,7 @@ static int prepare_creds(int pid, struct task_restore_core_args *args)
 	return 0;
 }
 
-static VmaEntry *vma_list_remap(void *addr, unsigned long len, struct list_head *vmas)
+static VmaEntry *vma_list_remap(void *addr, unsigned long len, struct vm_area_list *vmas)
 {
 	VmaEntry *vma, *ret;
 	struct vma_area *vma_area;
@@ -1457,7 +1456,7 @@ static VmaEntry *vma_list_remap(void *addr, unsigned long len, struct list_head
 		return NULL;
 	}
 
-	list_for_each_entry(vma_area, vmas, list) {
+	list_for_each_entry(vma_area, &vmas->h, list) {
 		*vma = vma_area->vma;
 		vma++;
 	}
@@ -1656,7 +1655,7 @@ static int sigreturn_restore(pid_t pid, CoreEntry *core)
 	struct task_restore_core_args *task_args;
 	struct thread_restore_args *thread_args;
 
-	LIST_HEAD(self_vma_list);
+	struct vm_area_list self_vmas;
 	int i;
 
 	pr_info("Restore via sigreturn\n");
@@ -1664,16 +1663,16 @@ static int sigreturn_restore(pid_t pid, CoreEntry *core)
 	restore_task_vma_len	= 0;
 	restore_thread_vma_len	= 0;
 
-	ret = parse_smaps(pid, &self_vma_list, false);
+	ret = parse_smaps(pid, &self_vmas, false);
 	close_proc();
 	if (ret < 0)
 		goto err;
 
 	/* required to unmap stack _with_ guard page */
-	mark_stack_vma((long) &self_vma_list, &self_vma_list);
+	mark_stack_vma((long) &self_vmas, &self_vmas.h);
 
-	self_vmas_len = round_up((ret + 1) * sizeof(VmaEntry), PAGE_SIZE);
-	vmas_len = round_up((rst_nr_vmas + 1) * sizeof(VmaEntry), PAGE_SIZE);
+	self_vmas_len = round_up((self_vmas.nr + 1) * sizeof(VmaEntry), PAGE_SIZE);
+	vmas_len = round_up((rst_vmas.nr + 1) * sizeof(VmaEntry), PAGE_SIZE);
 
 	/* pr_info_vma_list(&self_vma_list); */
 
@@ -1707,7 +1706,7 @@ static int sigreturn_restore(pid_t pid, CoreEntry *core)
 	 * or inited from scratch).
 	 */
 
-	exec_mem_hint = restorer_get_vma_hint(pid, &rst_vma_list, &self_vma_list,
+	exec_mem_hint = restorer_get_vma_hint(pid, &rst_vmas.h, &self_vmas.h,
 					      restore_bootstrap_len);
 	if (exec_mem_hint == -1) {
 		pr_err("No suitable area for task_restore bootstrap (%ldK)\n",
@@ -1769,13 +1768,13 @@ static int sigreturn_restore(pid_t pid, CoreEntry *core)
 	task_args->task_entries = mem;
 
 	mem += TASK_ENTRIES_SIZE;
-	task_args->self_vmas = vma_list_remap(mem, self_vmas_len, &self_vma_list);
+	task_args->self_vmas = vma_list_remap(mem, self_vmas_len, &self_vmas);
 	if (!task_args->self_vmas)
 		goto err;
 
 	mem += self_vmas_len;
-	task_args->tgt_vmas = vma_list_remap(mem, vmas_len, &rst_vma_list);
-	task_args->nr_vmas = rst_nr_vmas;
+	task_args->nr_vmas = rst_vmas.nr;
+	task_args->tgt_vmas = vma_list_remap(mem, vmas_len, &rst_vmas);
 	task_args->premmapped_addr = (unsigned long) current->rst->premmapped_addr;
 	task_args->premmapped_len = current->rst->premmapped_len;
 	if (!task_args->tgt_vmas)
@@ -1924,7 +1923,7 @@ static int sigreturn_restore(pid_t pid, CoreEntry *core)
 	JUMP_TO_RESTORER_BLOB(new_sp, restore_task_exec_start, task_args);
 
 err:
-	free_mappings(&self_vma_list);
+	free_mappings(&self_vmas);
 
 	/* Just to be sure */
 	exit(1);
diff --git a/include/crtools.h b/include/crtools.h
index b83cd88..0bcac32 100644
--- a/include/crtools.h
+++ b/include/crtools.h
@@ -216,8 +216,15 @@ struct cr_fdset *cr_glob_fdset_open(int mode);
 
 void close_cr_fdset(struct cr_fdset **cr_fdset);
 
-int collect_mappings(pid_t pid, struct list_head *vma_area_list);
-void free_mappings(struct list_head *vma_area_list);
+struct vm_area_list {
+	struct list_head	h;
+	unsigned		nr;
+};
+
+#define VM_AREA_LIST(name)	struct vm_area_list name = { .h = LIST_HEAD_INIT(name.h), .nr = 0, }
+
+int collect_mappings(pid_t pid, struct vm_area_list *vma_area_list);
+void free_mappings(struct vm_area_list *vma_area_list);
 
 struct vma_area {
 	struct list_head	list;
diff --git a/include/parasite-syscall.h b/include/parasite-syscall.h
index ca7ff68..e06e736 100644
--- a/include/parasite-syscall.h
+++ b/include/parasite-syscall.h
@@ -30,11 +30,12 @@ extern int parasite_dump_sigacts_seized(struct parasite_ctl *ctl, struct cr_fdse
 extern int parasite_dump_itimers_seized(struct parasite_ctl *ctl, struct cr_fdset *cr_fdset);
 
 struct parasite_dump_misc;
+struct vm_area_list;
 extern int parasite_dump_misc_seized(struct parasite_ctl *ctl, struct parasite_dump_misc *misc);
 struct _CredsEntry;
 extern int parasite_dump_creds(struct parasite_ctl *ctl, struct _CredsEntry *ce);
 extern int parasite_dump_pages_seized(struct parasite_ctl *ctl,
-				      struct list_head *vma_area_list,
+				      struct vm_area_list *vma_area_list,
 				      struct cr_fdset *cr_fdset);
 struct parasite_dump_thread;
 struct pid;
@@ -53,9 +54,9 @@ struct pstree_item;
 extern int parasite_cure_seized(struct parasite_ctl *ctl, struct pstree_item *item);
 extern struct parasite_ctl *parasite_infect_seized(pid_t pid,
 						   struct pstree_item *item,
-						   struct list_head *vma_area_list,
+						   struct vm_area_list *vma_area_list,
 						   struct parasite_drain_fd *dfds);
-extern struct parasite_ctl *parasite_prep_ctl(pid_t pid, struct list_head *vma_area_list);
+extern struct parasite_ctl *parasite_prep_ctl(pid_t pid, struct vm_area_list *vma_area_list);
 extern int parasite_map_exchange(struct parasite_ctl *ctl, unsigned long size);
 
 extern struct parasite_tty_args *parasite_dump_tty(struct parasite_ctl *ctl, int fd);
diff --git a/include/proc_parse.h b/include/proc_parse.h
index 8d1c2df..659affb 100644
--- a/include/proc_parse.h
+++ b/include/proc_parse.h
@@ -123,10 +123,12 @@ static inline void mnt_entry_init(struct mount_info *pm)
 	INIT_LIST_HEAD(&pm->children);
 }
 
+struct vm_area_list;
+
 extern struct mount_info *parse_mountinfo(pid_t pid);
 extern int parse_pid_stat(pid_t pid, struct proc_pid_stat *s);
 extern int parse_pid_stat_small(pid_t pid, struct proc_pid_stat_small *s);
-extern int parse_smaps(pid_t pid, struct list_head *vma_area_list, bool use_map_files);
+extern int parse_smaps(pid_t pid, struct vm_area_list *vma_area_list, bool use_map_files);
 extern int parse_pid_status(pid_t pid, struct proc_status_creds *);
 
 union fdinfo_entries {
diff --git a/parasite-syscall.c b/parasite-syscall.c
index 2f29bc6..066ed2e 100644
--- a/parasite-syscall.c
+++ b/parasite-syscall.c
@@ -486,7 +486,7 @@ int parasite_dump_creds(struct parasite_ctl *ctl, CredsEntry *ce)
  * This routine drives parasite code (been previously injected into a victim
  * process) and tells it to dump pages into the file.
  */
-int parasite_dump_pages_seized(struct parasite_ctl *ctl, struct list_head *vma_area_list,
+int parasite_dump_pages_seized(struct parasite_ctl *ctl, struct vm_area_list *vma_area_list,
 			       struct cr_fdset *cr_fdset)
 {
 	struct parasite_dump_pages_args *parasite_dumppages;
@@ -510,7 +510,7 @@ int parasite_dump_pages_seized(struct parasite_ctl *ctl, struct list_head *vma_a
 
 	parasite_dumppages = parasite_args(ctl, struct parasite_dump_pages_args);
 
-	list_for_each_entry(vma_area, vma_area_list, list) {
+	list_for_each_entry(vma_area, &vma_area_list->h, list) {
 
 		/*
 		 * The special areas are not dumped.
@@ -708,7 +708,7 @@ int parasite_cure_seized(struct parasite_ctl *ctl, struct pstree_item *item)
 	return ret;
 }
 
-struct parasite_ctl *parasite_prep_ctl(pid_t pid, struct list_head *vma_area_list)
+struct parasite_ctl *parasite_prep_ctl(pid_t pid, struct vm_area_list *vma_area_list)
 {
 	struct parasite_ctl *ctl = NULL;
 	struct vma_area *vma_area;
@@ -734,7 +734,7 @@ struct parasite_ctl *parasite_prep_ctl(pid_t pid, struct list_head *vma_area_lis
 		goto err;
 	}
 
-	vma_area = get_vma_by_ip(vma_area_list, REG_IP(ctl->regs_orig));
+	vma_area = get_vma_by_ip(&vma_area_list->h, REG_IP(ctl->regs_orig));
 	if (!vma_area) {
 		pr_err("No suitable VMA found to run parasite "
 		       "bootstrap code (pid: %d)\n", pid);
@@ -804,7 +804,7 @@ static unsigned long parasite_args_size(struct parasite_drain_fd *dfds)
 }
 
 struct parasite_ctl *parasite_infect_seized(pid_t pid, struct pstree_item *item,
-		struct list_head *vma_area_list, struct parasite_drain_fd *dfds)
+		struct vm_area_list *vma_area_list, struct parasite_drain_fd *dfds)
 {
 	int ret;
 	struct parasite_ctl *ctl;
diff --git a/proc_parse.c b/proc_parse.c
index 0892792..95dcf8f 100644
--- a/proc_parse.c
+++ b/proc_parse.c
@@ -166,18 +166,21 @@ static int is_anon_shmem_map(dev_t dev)
 	return shmem_dev == dev;
 }
 
-int parse_smaps(pid_t pid, struct list_head *vma_area_list, bool use_map_files)
+int parse_smaps(pid_t pid, struct vm_area_list *vma_area_list, bool use_map_files)
 {
 	struct vma_area *vma_area = NULL;
 	unsigned long start, end, pgoff;
 	unsigned long ino;
 	char r, w, x, s;
 	int dev_maj, dev_min;
-	int ret = -1, nr = 0;
+	int ret = -1;
 
 	DIR *map_files_dir = NULL;
 	FILE *smaps = NULL;
 
+	vma_area_list->nr = 0;
+	INIT_LIST_HEAD(&vma_area_list->h);
+
 	smaps = fopen_proc(pid, "smaps");
 	if (!smaps)
 		goto err;
@@ -340,12 +343,12 @@ int parse_smaps(pid_t pid, struct list_head *vma_area_list, bool use_map_files)
 			vma_area->vma.flags  |= MAP_ANONYMOUS;
 		}
 done:
-		list_add_tail(&vma_area->list, vma_area_list);
-		nr++;
+		list_add_tail(&vma_area->list, &vma_area_list->h);
+		vma_area_list->nr++;
 	}
 
 	vma_area = NULL;
-	ret = nr;
+	ret = 0;
 
 err:
 	if (smaps)
-- 
1.7.11.7


More information about the CRIU mailing list