Commit dbd92e90 authored by Pavel Emelyanov's avatar Pavel Emelyanov

mem: Rework vma open

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: 's avatarPavel Emelyanov <xemul@virtuozzo.com>
parent ce9b0400
...@@ -378,7 +378,7 @@ static int dump_filemap(struct vma_area *vma_area, int fd) ...@@ -378,7 +378,7 @@ static int dump_filemap(struct vma_area *vma_area, int fd)
p.link = &aufs_link; 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)) if (fd_id_generate_special(&p, &id))
ret = dump_one_reg_file(fd, id, &p); ret = dump_one_reg_file(fd, id, &p);
......
...@@ -289,12 +289,13 @@ static int map_private_vma(struct vma_area *vma, void **tgt_addr, ...@@ -289,12 +289,13 @@ static int map_private_vma(struct vma_area *vma, void **tgt_addr,
struct vma_area *p = *pvma; struct vma_area *p = *pvma;
if (vma_area_is(vma, VMA_FILE_PRIVATE)) { if (vma_area_is(vma, VMA_FILE_PRIVATE)) {
ret = get_filemap_fd(vma); ret = vma->vm_open(current->pid.virt, vma);
if (ret < 0) { if (ret < 0) {
pr_err("Can't fixup VMA's fd\n"); pr_err("Can't fixup VMA's fd\n");
return -1; 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; nr_pages = vma_entry_len(vma->e) / PAGE_SIZE;
...@@ -672,7 +673,6 @@ static int unmap_guard_pages() ...@@ -672,7 +673,6 @@ static int unmap_guard_pages()
static int open_vmas(int pid) static int open_vmas(int pid)
{ {
struct vma_area *vma; struct vma_area *vma;
int ret = 0;
struct list_head *vmas = &rsti(current)->vmas.h; struct list_head *vmas = &rsti(current)->vmas.h;
list_for_each_entry(vma, vmas, list) { list_for_each_entry(vma, vmas, list) {
...@@ -683,27 +683,13 @@ static int open_vmas(int pid) ...@@ -683,27 +683,13 @@ static int open_vmas(int pid)
vma->e->start, vma->e->end, vma->e->start, vma->e->end,
vma->e->pgoff, vma->e->status); vma->e->pgoff, vma->e->status);
if (vma_area_is(vma, VMA_AREA_SYSVIPC)) if (vma->vm_open && vma->vm_open(pid, vma)) {
ret = get_sysv_shmem_fd(vma->e); pr_err("`- Can't open vma\n");
else if (vma_area_is(vma, VMA_ANON_SHARED)) return -1;
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;
} }
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; static rt_sigaction_t sigchld_act;
......
...@@ -1580,9 +1580,10 @@ int open_reg_by_id(u32 id) ...@@ -1580,9 +1580,10 @@ int open_reg_by_id(u32 id)
return open_reg_fd(fd); 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; u32 flags;
int ret;
/* /*
* Thevma->fd should have been assigned in collect_filemap * Thevma->fd should have been assigned in collect_filemap
...@@ -1599,7 +1600,25 @@ int get_filemap_fd(struct vma_area *vma) ...@@ -1599,7 +1600,25 @@ int get_filemap_fd(struct vma_area *vma)
else else
flags = O_RDONLY; 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) static void remap_get(struct file_desc *fdesc, char typ)
......
...@@ -45,6 +45,7 @@ extern void remap_put(struct file_remap *remap); ...@@ -45,6 +45,7 @@ extern void remap_put(struct file_remap *remap);
extern struct file_desc *try_collect_special_file(u32 id, int optional); extern struct file_desc *try_collect_special_file(u32 id, int optional);
#define collect_special_file(id) try_collect_special_file(id, 0) #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); extern int collect_remaps_and_regfiles(void);
......
...@@ -151,7 +151,6 @@ extern int prepare_fds(struct pstree_item *me); ...@@ -151,7 +151,6 @@ extern int prepare_fds(struct pstree_item *me);
extern int prepare_fd_pid(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_ctl_tty(int pid, struct rst_info *rst_info, u32 ctl_tty_id);
extern int prepare_shared_fdinfo(void); extern int prepare_shared_fdinfo(void);
extern int get_filemap_fd(struct vma_area *);
extern int restore_fs(struct pstree_item *); extern int restore_fs(struct pstree_item *);
extern int prepare_fs_pid(struct pstree_item *); extern int prepare_fs_pid(struct pstree_item *);
extern int set_fd_flags(int fd, int flags); extern int set_fd_flags(int fd, int flags);
......
...@@ -5,11 +5,11 @@ ...@@ -5,11 +5,11 @@
#include "images/vma.pb-c.h" #include "images/vma.pb-c.h"
struct _VmaEntry; 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 int collect_sysv_shmem(unsigned long shmid, unsigned long size);
extern void show_saved_shmems(void); 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 cr_dump_shmem(void);
extern int add_shmem_area(pid_t pid, VmaEntry *vma); extern int add_shmem_area(pid_t pid, VmaEntry *vma);
extern int fixup_sysv_shmems(void); extern int fixup_sysv_shmems(void);
......
...@@ -12,8 +12,9 @@ struct vma_area; ...@@ -12,8 +12,9 @@ struct vma_area;
extern struct collect_image_info packet_sk_cinfo; extern struct collect_image_info packet_sk_cinfo;
extern int dump_socket_map(struct vma_area *vma); 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); extern int packet_receive_one(struct nlmsghdr *h, void *arg);
#ifndef PACKET_VNET_HDR #ifndef PACKET_VNET_HDR
......
...@@ -60,6 +60,7 @@ struct vma_area { ...@@ -60,6 +60,7 @@ struct vma_area {
}; };
struct /* for restore */ { struct /* for restore */ {
int (*vm_open)(int pid, struct vma_area *vma);
struct file_desc *vmfd; struct file_desc *vmfd;
unsigned long *page_bitmap; /* existent pages */ unsigned long *page_bitmap; /* existent pages */
unsigned long *ppage_bitmap; /* parent's existent pages */ unsigned long *ppage_bitmap; /* parent's existent pages */
......
...@@ -18,6 +18,7 @@ ...@@ -18,6 +18,7 @@
#include "shmem.h" #include "shmem.h"
#include "pstree.h" #include "pstree.h"
#include "restorer.h" #include "restorer.h"
#include "sk-packet.h"
#include "files-reg.h" #include "files-reg.h"
#include "pagemap-cache.h" #include "pagemap-cache.h"
#include "fault-injection.h" #include "fault-injection.h"
...@@ -405,18 +406,6 @@ int parasite_dump_pages_seized(struct parasite_ctl *ctl, ...@@ -405,18 +406,6 @@ int parasite_dump_pages_seized(struct parasite_ctl *ctl,
return ret; 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) int prepare_mm_pid(struct pstree_item *i)
{ {
pid_t pid = i->pid.virt; pid_t pid = i->pid.virt;
...@@ -478,12 +467,13 @@ int prepare_mm_pid(struct pstree_item *i) ...@@ -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); pr_info("vma 0x%"PRIx64" 0x%"PRIx64"\n", vma->e->start, vma->e->end);
if (vma_area_is(vma, VMA_ANON_SHARED) && if (vma_area_is(vma, VMA_ANON_SHARED))
!vma_area_is(vma, VMA_AREA_SYSVIPC)) ret = collect_shmem(pid, vma);
ret = collect_shmem(pid, vma->e);
else if (vma_area_is(vma, VMA_FILE_PRIVATE) || else if (vma_area_is(vma, VMA_FILE_PRIVATE) ||
vma_area_is(vma, VMA_FILE_SHARED)) vma_area_is(vma, VMA_FILE_SHARED))
ret = collect_filemap(vma); ret = collect_filemap(vma);
else if (vma_area_is(vma, VMA_AREA_SOCKET))
ret = collect_socket_map(vma);
else else
ret = 0; ret = 0;
if (ret) if (ret)
......
...@@ -513,7 +513,7 @@ static unsigned long restore_mapping(const VmaEntry *vma_entry) ...@@ -513,7 +513,7 @@ static unsigned long restore_mapping(const VmaEntry *vma_entry)
if (vma_entry_is(vma_entry, VMA_AREA_SYSVIPC)) { 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. * means and why we check for PROT_EXEC few lines below.
*/ */
if (vma_entry->fd == SYSV_SHMEM_SKIP_FD) if (vma_entry->fd == SYSV_SHMEM_SKIP_FD)
......
...@@ -136,7 +136,7 @@ int fixup_sysv_shmems(void) ...@@ -136,7 +136,7 @@ int fixup_sysv_shmems(void)
list_for_each_entry(att, &si->att, l) { 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. * intermediate holes.
*/ */
if (att->first->start + si->size != att->prev_end) { if (att->first->start + si->size != att->prev_end) {
...@@ -145,7 +145,7 @@ int fixup_sysv_shmems(void) ...@@ -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) if (si->want_write)
att->first->prot |= PROT_EXEC; att->first->prot |= PROT_EXEC;
...@@ -155,11 +155,12 @@ int fixup_sysv_shmems(void) ...@@ -155,11 +155,12 @@ int fixup_sysv_shmems(void)
return 0; 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_info *si;
struct shmem_sysv_att *att; struct shmem_sysv_att *att;
int ret_fd; uint64_t ret_fd;
si = (struct shmem_sysv_info *)find_shmem_by_id(vme->shmid); si = (struct shmem_sysv_info *)find_shmem_by_id(vme->shmid);
if (!si) { if (!si) {
...@@ -242,14 +243,25 @@ int get_sysv_shmem_fd(VmaEntry *vme) ...@@ -242,14 +243,25 @@ int get_sysv_shmem_fd(VmaEntry *vme)
*/ */
si->want_write = 1; 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; unsigned long size = vi->pgoff + vi->end - vi->start;
struct shmem_info *si; 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); si = find_shmem_by_id(vi->shmid);
if (si) { if (si) {
if (si->pid == SYSVIPC_SHMEM_PID) { if (si->pid == SYSVIPC_SHMEM_PID) {
...@@ -299,7 +311,7 @@ int collect_shmem(int pid, VmaEntry *vi) ...@@ -299,7 +311,7 @@ int collect_shmem(int pid, VmaEntry *vi)
return 0; 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]; char path[128];
int ret; int ret;
...@@ -316,7 +328,11 @@ static int shmem_wait_and_open(int pid, struct shmem_info *si) ...@@ -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", pr_perror(" %d: Can't stat shmem at %s",
si->pid, path); si->pid, path);
futex_inc_and_wake(&si->lock); 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) 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) ...@@ -368,8 +384,9 @@ static int restore_shmem_content(void *addr, struct shmem_info *si)
return ret; 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; struct shmem_info *si;
void *addr = MAP_FAILED; void *addr = MAP_FAILED;
int f = -1; int f = -1;
...@@ -385,10 +402,17 @@ int get_shmem_fd(int pid, VmaEntry *vi) ...@@ -385,10 +402,17 @@ int get_shmem_fd(int pid, VmaEntry *vi)
BUG_ON(si->pid == SYSVIPC_SHMEM_PID); BUG_ON(si->pid == SYSVIPC_SHMEM_PID);
if (si->pid != pid) if (si->pid != pid)
return shmem_wait_and_open(pid, si); return shmem_wait_and_open(pid, si, vi);
if (si->fd != -1) if (si->fd != -1) {
return dup(si->fd); f = dup(si->fd);
if (f < 0) {
pr_perror("Can't dup shmem fd");
return -1;
}
goto out;
}
flags = MAP_SHARED; flags = MAP_SHARED;
#ifdef CONFIG_HAS_MEMFD #ifdef CONFIG_HAS_MEMFD
...@@ -445,8 +469,9 @@ int get_shmem_fd(int pid, VmaEntry *vi) ...@@ -445,8 +469,9 @@ int get_shmem_fd(int pid, VmaEntry *vi)
* the file descriptor, so we don't wait them. * the file descriptor, so we don't wait them.
*/ */
futex_wait_until(&si->lock, si->count - si->self_count + 1); futex_wait_until(&si->lock, si->count - si->self_count + 1);
out:
return f; vi->fd = f;
return 0;
err: err:
if (addr != MAP_FAILED) if (addr != MAP_FAILED)
munmap(addr, si->size); munmap(addr, si->size);
......
...@@ -302,8 +302,9 @@ err: ...@@ -302,8 +302,9 @@ err:
return -1; 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 file_desc *fd;
struct fdinfo_list_entry *le; struct fdinfo_list_entry *le;
...@@ -329,13 +330,20 @@ int get_socket_fd(int pid, VmaEntry *vma) ...@@ -329,13 +330,20 @@ int get_socket_fd(int pid, VmaEntry *vma)
return -1; return -1;
} }
return fd; vma->fd = fd;
return 0;
} }
pr_err("No open packet socket %x by %d\n", (int)vma->shmid, pid); pr_err("No open packet socket %x by %d\n", (int)vma->shmid, pid);
return -1; 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) static int restore_mreqs(int sk, PacketSockEntry *pse)
{ {
int i; int i;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment