criu/include/vma.h
Pavel Emelyanov e651a6eba4 filemap: Get vma mnt_id early
We have a, well, issue with how we calculate the vma's mnt_id.

Right now get one via criu side file descriptor that it got by
opening the /proc/pid/map_files/ link. The problem is that these
descriptors are 'merged' or 'borrowed' by adjacent vmas from
previous ones. Thus, getting the mnt_id value for each of them
makes no sense -- these files are the same.

So move this mnt_id getting earlier into vma parsing code. This
brings a potential problem -- if we have two adjacent vmas
mapping the same inode (dev:ino pair) but living in different
mount namespaces -- this check would produce wrong result.
"Wrong" from the perspective that on restore correct file would
be opened from wrong namespace.

I propose to live with it, since this is not worse than the
--evasive-devices option, it's _very_ unlikely, but saves a lot
of openeings.

Note, that in case app switched mount namespace and then mapped
some new library (with dlopen) things would work correctly -- new
vmas will likely be not adjacent and for different dev:ino.

Signed-off-by: Pavel Emelyanov <xemul@parallels.com>
2014-09-29 13:20:55 +04:00

89 lines
2.4 KiB
C

#ifndef __CR_VMA_H__
#define __CR_VMA_H__
#include "list.h"
#include "protobuf/vma.pb-c.h"
struct vm_area_list {
struct list_head h;
unsigned nr;
unsigned long priv_size; /* nr of pages in private VMAs */
unsigned long longest; /* nr of pages in longest VMA */
};
#define VM_AREA_LIST(name) struct vm_area_list name = { .h = LIST_HEAD_INIT(name.h), .nr = 0, }
static inline void vm_area_list_init(struct vm_area_list *vml)
{
INIT_LIST_HEAD(&vml->h);
vml->nr = 0;
vml->priv_size = 0;
vml->longest = 0;
}
struct file_desc;
struct vma_area {
struct list_head list;
VmaEntry *e;
union {
struct /* for dump */ {
union {
/*
* These two cannot be assigned at once.
* The file_fd is an fd for a regular file and
* the socket_id is the inode number of the
* mapped (PF_PACKET) socket.
*/
int vm_file_fd;
int vm_socket_id;
};
char *aufs_rpath; /* path from aufs root */
char *aufs_fpath; /* full path from global root */
/*
* When several subsequent vmas have the same
* dev:ino pair all 'tail' ones set this to true
* and the vmst points to the head's stat buf.
*/
bool file_borrowed;
struct stat *vmst;
int mnt_id;
};
struct /* for restore */ {
struct file_desc *vmfd;
unsigned long *page_bitmap; /* existent pages */
unsigned long *ppage_bitmap; /* parent's existent pages */
unsigned long premmaped_addr; /* restore only */
};
};
};
extern struct vma_area *alloc_vma_area(void);
extern int collect_mappings(pid_t pid, struct vm_area_list *vma_area_list);
extern void free_mappings(struct vm_area_list *vma_area_list);
extern bool privately_dump_vma(struct vma_area *vma);
#define vma_area_is(vma_area, s) vma_entry_is((vma_area)->e, s)
#define vma_area_len(vma_area) vma_entry_len((vma_area)->e)
#define vma_entry_is(vma, s) (((vma)->status & (s)) == (s))
#define vma_entry_len(vma) ((vma)->end - (vma)->start)
/*
* vma_premmaped_start() can be used only in restorer.
* In other cases vma_area->premmaped_addr must be used.
* This hack is required, because vma_area isn't tranfered in restorer and
* shmid is used to determing which vma-s are cowed.
*/
#define vma_premmaped_start(vma) ((vma)->shmid)
static inline int in_vma_area(struct vma_area *vma, unsigned long addr)
{
return addr >= (unsigned long)vma->e->start &&
addr < (unsigned long)vma->e->end;
}
#endif /* __CR_VMA_H__ */