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)
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(fd, id, &p);
......
......@@ -289,12 +289,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;
......@@ -672,7 +673,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) {
......@@ -683,27 +683,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;
......
......@@ -1580,9 +1580,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
......@@ -1599,7 +1600,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)
......
......@@ -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);
......
......@@ -151,7 +151,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);
......
......@@ -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);
......
......@@ -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
......
......@@ -60,6 +60,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 */
......
......@@ -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)
......
......@@ -513,7 +513,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)
......
......@@ -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);
......
......@@ -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;
......
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