[CRIU] [PATCH] mem: Rework vma open
Pavel Emelyanov
xemul at virtuozzo.com
Fri May 20 04:15:02 PDT 2016
We now have two places where we if/elseif/elseif/else a vma
and take actions -- the prepare_mm_pid and open_vmas. I propose
to make this if/... onlce once (while preparing) and set up
a callback on vma to be called later (while opening).
This requires my patch that doesn't set -1 in alloc_vma or
Andrey's patch that does the same.
Signed-off-by: Pavel Emelyanov <xemul at virtuozzo.com>
---
criu/cr-dump.c | 2 +-
criu/cr-restore.c | 28 +++++++------------------
criu/files-reg.c | 23 +++++++++++++++++++--
criu/include/files-reg.h | 1 +
criu/include/files.h | 1 -
criu/include/shmem.h | 6 +++---
criu/include/sk-packet.h | 3 ++-
criu/include/vma.h | 1 +
criu/mem.c | 20 +++++-------------
criu/pie/restorer.c | 2 +-
criu/shmem.c | 53 +++++++++++++++++++++++++++++++++++-------------
criu/sk-packet.c | 12 +++++++++--
12 files changed, 91 insertions(+), 61 deletions(-)
diff --git a/criu/cr-dump.c b/criu/cr-dump.c
index 8ef46a4..3507aee 100644
--- a/criu/cr-dump.c
+++ b/criu/cr-dump.c
@@ -394,7 +394,7 @@ static int dump_filemap(pid_t pid, struct vma_area *vma_area,
p.link = &aufs_link;
}
- /* Flags will be set during restore in get_filemap_fd() */
+ /* Flags will be set during restore in open_filmap() */
if (fd_id_generate_special(&p, &id))
ret = dump_one_reg_file(vma_area->vm_file_fd, id, &p);
diff --git a/criu/cr-restore.c b/criu/cr-restore.c
index ceb40fb..cb25982 100644
--- a/criu/cr-restore.c
+++ b/criu/cr-restore.c
@@ -293,12 +293,13 @@ static int map_private_vma(struct vma_area *vma, void **tgt_addr,
struct vma_area *p = *pvma;
if (vma_area_is(vma, VMA_FILE_PRIVATE)) {
- ret = get_filemap_fd(vma);
+ ret = vma->vm_open(current->pid.virt, vma);
if (ret < 0) {
pr_err("Can't fixup VMA's fd\n");
return -1;
}
- vma->e->fd = ret;
+
+ vma->vm_open = NULL; /* prevent from 2nd open in open_vmas */
}
nr_pages = vma_entry_len(vma->e) / PAGE_SIZE;
@@ -689,7 +690,6 @@ static int unmap_guard_pages()
static int open_vmas(int pid)
{
struct vma_area *vma;
- int ret = 0;
struct list_head *vmas = &rsti(current)->vmas.h;
list_for_each_entry(vma, vmas, list) {
@@ -700,27 +700,13 @@ static int open_vmas(int pid)
vma->e->start, vma->e->end,
vma->e->pgoff, vma->e->status);
- if (vma_area_is(vma, VMA_AREA_SYSVIPC))
- ret = get_sysv_shmem_fd(vma->e);
- else if (vma_area_is(vma, VMA_ANON_SHARED))
- ret = get_shmem_fd(pid, vma->e);
- else if (vma_area_is(vma, VMA_FILE_SHARED))
- ret = get_filemap_fd(vma);
- else if (vma_area_is(vma, VMA_AREA_SOCKET))
- ret = get_socket_fd(pid, vma->e);
- else
- continue;
-
- if (ret < 0) {
- pr_err("Can't fixup fd\n");
- break;
+ if (vma->vm_open && vma->vm_open(pid, vma)) {
+ pr_err("`- Can't open vma\n");
+ return -1;
}
-
- pr_info("\t`- setting %d as mapping fd\n", ret);
- vma->e->fd = ret;
}
- return ret < 0 ? -1 : 0;
+ return 0;
}
static rt_sigaction_t sigchld_act;
diff --git a/criu/files-reg.c b/criu/files-reg.c
index fd36ae9..5bf0f5c 100644
--- a/criu/files-reg.c
+++ b/criu/files-reg.c
@@ -1572,9 +1572,10 @@ int open_reg_by_id(u32 id)
return open_reg_fd(fd);
}
-int get_filemap_fd(struct vma_area *vma)
+static int open_filemap(int pid, struct vma_area *vma)
{
u32 flags;
+ int ret;
/*
* Thevma->fd should have been assigned in collect_filemap
@@ -1591,7 +1592,25 @@ int get_filemap_fd(struct vma_area *vma)
else
flags = O_RDONLY;
- return open_path(vma->vmfd, do_open_reg_noseek_flags, &flags);
+ ret = open_path(vma->vmfd, do_open_reg_noseek_flags, &flags);
+ if (ret < 0)
+ return ret;
+
+ vma->e->fd = ret;
+ return 0;
+}
+
+int collect_filemap(struct vma_area *vma)
+{
+ struct file_desc *fd;
+
+ fd = collect_special_file(vma->e->shmid);
+ if (!fd)
+ return -1;
+
+ vma->vmfd = fd;
+ vma->vm_open = open_filemap;
+ return 0;
}
static void remap_get(struct file_desc *fdesc, char typ)
diff --git a/criu/include/files-reg.h b/criu/include/files-reg.h
index 9e5944d..4bf5cd5 100644
--- a/criu/include/files-reg.h
+++ b/criu/include/files-reg.h
@@ -45,6 +45,7 @@ extern void remap_put(struct file_remap *remap);
extern struct file_desc *try_collect_special_file(u32 id, int optional);
#define collect_special_file(id) try_collect_special_file(id, 0)
+extern int collect_filemap(struct vma_area *);
extern int collect_remaps_and_regfiles(void);
diff --git a/criu/include/files.h b/criu/include/files.h
index 1894f09..65b7d51 100644
--- a/criu/include/files.h
+++ b/criu/include/files.h
@@ -184,7 +184,6 @@ extern int prepare_fds(struct pstree_item *me);
extern int prepare_fd_pid(struct pstree_item *me);
extern int prepare_ctl_tty(int pid, struct rst_info *rst_info, u32 ctl_tty_id);
extern int prepare_shared_fdinfo(void);
-extern int get_filemap_fd(struct vma_area *);
extern int restore_fs(struct pstree_item *);
extern int prepare_fs_pid(struct pstree_item *);
extern int set_fd_flags(int fd, int flags);
diff --git a/criu/include/shmem.h b/criu/include/shmem.h
index 217394c..e07db1f 100644
--- a/criu/include/shmem.h
+++ b/criu/include/shmem.h
@@ -5,11 +5,11 @@
#include "images/vma.pb-c.h"
struct _VmaEntry;
-extern int collect_shmem(int pid, struct _VmaEntry *vi);
+struct vma_area;
+
+extern int collect_shmem(int pid, struct vma_area *vma);
extern int collect_sysv_shmem(unsigned long shmid, unsigned long size);
extern void show_saved_shmems(void);
-extern int get_shmem_fd(int pid, VmaEntry *vi);
-extern int get_sysv_shmem_fd(struct _VmaEntry *vi);
extern int cr_dump_shmem(void);
extern int add_shmem_area(pid_t pid, VmaEntry *vma);
extern int fixup_sysv_shmems(void);
diff --git a/criu/include/sk-packet.h b/criu/include/sk-packet.h
index 6c4398c..fda471f 100644
--- a/criu/include/sk-packet.h
+++ b/criu/include/sk-packet.h
@@ -12,8 +12,9 @@ struct vma_area;
extern struct collect_image_info packet_sk_cinfo;
extern int dump_socket_map(struct vma_area *vma);
-extern int get_socket_fd(int pid, VmaEntry *vma);
+extern int collect_socket_map(struct vma_area *);
+struct nlmsghdr;
extern int packet_receive_one(struct nlmsghdr *h, void *arg);
#ifndef PACKET_VNET_HDR
diff --git a/criu/include/vma.h b/criu/include/vma.h
index d69f5f0..44b3fdb 100644
--- a/criu/include/vma.h
+++ b/criu/include/vma.h
@@ -63,6 +63,7 @@ struct vma_area {
};
struct /* for restore */ {
+ int (*vm_open)(int pid, struct vma_area *vma);
struct file_desc *vmfd;
unsigned long *page_bitmap; /* existent pages */
unsigned long *ppage_bitmap; /* parent's existent pages */
diff --git a/criu/mem.c b/criu/mem.c
index 4d11a8d..e05dbc1 100644
--- a/criu/mem.c
+++ b/criu/mem.c
@@ -18,6 +18,7 @@
#include "shmem.h"
#include "pstree.h"
#include "restorer.h"
+#include "sk-packet.h"
#include "files-reg.h"
#include "pagemap-cache.h"
#include "fault-injection.h"
@@ -405,18 +406,6 @@ int parasite_dump_pages_seized(struct parasite_ctl *ctl,
return ret;
}
-static inline int collect_filemap(struct vma_area *vma)
-{
- struct file_desc *fd;
-
- fd = collect_special_file(vma->e->shmid);
- if (!fd)
- return -1;
-
- vma->vmfd = fd;
- return 0;
-}
-
int prepare_mm_pid(struct pstree_item *i)
{
pid_t pid = i->pid.virt;
@@ -478,12 +467,13 @@ int prepare_mm_pid(struct pstree_item *i)
pr_info("vma 0x%"PRIx64" 0x%"PRIx64"\n", vma->e->start, vma->e->end);
- if (vma_area_is(vma, VMA_ANON_SHARED) &&
- !vma_area_is(vma, VMA_AREA_SYSVIPC))
- ret = collect_shmem(pid, vma->e);
+ if (vma_area_is(vma, VMA_ANON_SHARED))
+ ret = collect_shmem(pid, vma);
else if (vma_area_is(vma, VMA_FILE_PRIVATE) ||
vma_area_is(vma, VMA_FILE_SHARED))
ret = collect_filemap(vma);
+ else if (vma_area_is(vma, VMA_AREA_SOCKET))
+ ret = collect_socket_map(vma);
else
ret = 0;
if (ret)
diff --git a/criu/pie/restorer.c b/criu/pie/restorer.c
index 2c439a9..4515222 100644
--- a/criu/pie/restorer.c
+++ b/criu/pie/restorer.c
@@ -524,7 +524,7 @@ static unsigned long restore_mapping(const VmaEntry *vma_entry)
if (vma_entry_is(vma_entry, VMA_AREA_SYSVIPC)) {
/*
- * See comment in get_sysv_shmem_fd() for what SYSV_SHMEM_SKIP_FD
+ * See comment in open_shmem_sysv() for what SYSV_SHMEM_SKIP_FD
* means and why we check for PROT_EXEC few lines below.
*/
if (vma_entry->fd == SYSV_SHMEM_SKIP_FD)
diff --git a/criu/shmem.c b/criu/shmem.c
index 49fa88a..99cd78c 100644
--- a/criu/shmem.c
+++ b/criu/shmem.c
@@ -136,7 +136,7 @@ int fixup_sysv_shmems(void)
list_for_each_entry(att, &si->att, l) {
/*
- * Same thing is checked in get_sysv_shmem_fd() for
+ * Same thing is checked in open_shmem_sysv() for
* intermediate holes.
*/
if (att->first->start + si->size != att->prev_end) {
@@ -145,7 +145,7 @@ int fixup_sysv_shmems(void)
}
/*
- * See comment in get_shmem_fd() about this PROT_EXEC
+ * See comment in open_shmem_sysv() about this PROT_EXEC
*/
if (si->want_write)
att->first->prot |= PROT_EXEC;
@@ -155,11 +155,12 @@ int fixup_sysv_shmems(void)
return 0;
}
-int get_sysv_shmem_fd(VmaEntry *vme)
+static int open_shmem_sysv(int pid, struct vma_area *vma)
{
+ VmaEntry *vme = vma->e;
struct shmem_sysv_info *si;
struct shmem_sysv_att *att;
- int ret_fd;
+ uint64_t ret_fd;
si = (struct shmem_sysv_info *)find_shmem_by_id(vme->shmid);
if (!si) {
@@ -242,14 +243,25 @@ int get_sysv_shmem_fd(VmaEntry *vme)
*/
si->want_write = 1;
- return ret_fd;
+ vme->fd = ret_fd;
+ return 0;
}
-int collect_shmem(int pid, VmaEntry *vi)
+static int open_shmem(int pid, struct vma_area *vma);
+
+int collect_shmem(int pid, struct vma_area *vma)
{
+ VmaEntry *vi = vma->e;
unsigned long size = vi->pgoff + vi->end - vi->start;
struct shmem_info *si;
+ if (vma_entry_is(vi, VMA_AREA_SYSVIPC)) {
+ vma->vm_open = open_shmem_sysv;
+ return 0;
+ }
+
+ vma->vm_open = open_shmem;
+
si = find_shmem_by_id(vi->shmid);
if (si) {
if (si->pid == SYSVIPC_SHMEM_PID) {
@@ -299,7 +311,7 @@ int collect_shmem(int pid, VmaEntry *vi)
return 0;
}
-static int shmem_wait_and_open(int pid, struct shmem_info *si)
+static int shmem_wait_and_open(int pid, struct shmem_info *si, VmaEntry *vi)
{
char path[128];
int ret;
@@ -316,7 +328,11 @@ static int shmem_wait_and_open(int pid, struct shmem_info *si)
pr_perror(" %d: Can't stat shmem at %s",
si->pid, path);
futex_inc_and_wake(&si->lock);
- return ret;
+ if (ret < 0)
+ return -1;
+
+ vi->fd = ret;
+ return 0;
}
static int restore_shmem_content(void *addr, struct shmem_info *si)
@@ -368,8 +384,9 @@ static int restore_shmem_content(void *addr, struct shmem_info *si)
return ret;
}
-int get_shmem_fd(int pid, VmaEntry *vi)
+static int open_shmem(int pid, struct vma_area *vma)
{
+ VmaEntry *vi = vma->e;
struct shmem_info *si;
void *addr = MAP_FAILED;
int f = -1;
@@ -385,10 +402,17 @@ int get_shmem_fd(int pid, VmaEntry *vi)
BUG_ON(si->pid == SYSVIPC_SHMEM_PID);
if (si->pid != pid)
- return shmem_wait_and_open(pid, si);
+ return shmem_wait_and_open(pid, si, vi);
- if (si->fd != -1)
- return dup(si->fd);
+ if (si->fd != -1) {
+ f = dup(si->fd);
+ if (f < 0) {
+ pr_perror("Can't dup shmem fd");
+ return -1;
+ }
+
+ goto out;
+ }
flags = MAP_SHARED;
#ifdef CONFIG_HAS_MEMFD
@@ -445,8 +469,9 @@ int get_shmem_fd(int pid, VmaEntry *vi)
* the file descriptor, so we don't wait them.
*/
futex_wait_until(&si->lock, si->count - si->self_count + 1);
-
- return f;
+out:
+ vi->fd = f;
+ return 0;
err:
if (addr != MAP_FAILED)
munmap(addr, si->size);
diff --git a/criu/sk-packet.c b/criu/sk-packet.c
index 73d9c7b..d82268e 100644
--- a/criu/sk-packet.c
+++ b/criu/sk-packet.c
@@ -302,8 +302,9 @@ err:
return -1;
}
-int get_socket_fd(int pid, VmaEntry *vma)
+static int open_socket_map(int pid, struct vma_area *vm)
{
+ VmaEntry *vma = vm->e;
struct file_desc *fd;
struct fdinfo_list_entry *le;
@@ -329,13 +330,20 @@ int get_socket_fd(int pid, VmaEntry *vma)
return -1;
}
- return fd;
+ vma->fd = fd;
+ return 0;
}
pr_err("No open packet socket %x by %d\n", (int)vma->shmid, pid);
return -1;
}
+int collect_socket_map(struct vma_area *vma)
+{
+ vma->vm_open = open_socket_map;
+ return 0;
+}
+
static int restore_mreqs(int sk, PacketSockEntry *pse)
{
int i;
--
2.5.0
More information about the CRIU
mailing list