[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