Commit f26cff07 authored by Andrew Vagin's avatar Andrew Vagin Committed by Pavel Emelyanov

criu: dump filemap as soon as possible

A process can have many vma-s and we can hit rlimit for files.

I suggest to dump vma files as soon as possible and close them.

v2: remove vm_file_fd from the vma_area structure

Cc: Cyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: 's avatarAndrew Vagin <avagin@virtuozzo.com>
Signed-off-by: 's avatarPavel Emelyanov <xemul@virtuozzo.com>
parent 8e778d29
...@@ -85,26 +85,11 @@ ...@@ -85,26 +85,11 @@
static char loc_buf[PAGE_SIZE]; static char loc_buf[PAGE_SIZE];
static void close_vma_file(struct vma_area *vma)
{
if (vma->vm_file_fd < 0)
return;
if (vma->e->status & VMA_AREA_SOCKET)
return;
if (vma->file_borrowed)
return;
if (vma_area_is(vma, VMA_AREA_AIORING))
return;
close(vma->vm_file_fd);
}
void free_mappings(struct vm_area_list *vma_area_list) void free_mappings(struct vm_area_list *vma_area_list)
{ {
struct vma_area *vma_area, *p; struct vma_area *vma_area, *p;
list_for_each_entry_safe(vma_area, p, &vma_area_list->h, list) { list_for_each_entry_safe(vma_area, p, &vma_area_list->h, list) {
close_vma_file(vma_area);
if (!vma_area->file_borrowed) if (!vma_area->file_borrowed)
free(vma_area->vmst); free(vma_area->vmst);
free(vma_area); free(vma_area);
...@@ -114,7 +99,8 @@ void free_mappings(struct vm_area_list *vma_area_list) ...@@ -114,7 +99,8 @@ void free_mappings(struct vm_area_list *vma_area_list)
vma_area_list->nr = 0; vma_area_list->nr = 0;
} }
int collect_mappings(pid_t pid, struct vm_area_list *vma_area_list) int collect_mappings(pid_t pid, struct vm_area_list *vma_area_list,
dump_filemap_t dump_file)
{ {
int ret = -1; int ret = -1;
...@@ -122,7 +108,7 @@ int collect_mappings(pid_t pid, struct vm_area_list *vma_area_list) ...@@ -122,7 +108,7 @@ int collect_mappings(pid_t pid, struct vm_area_list *vma_area_list)
pr_info("Collecting mappings (pid: %d)\n", pid); pr_info("Collecting mappings (pid: %d)\n", pid);
pr_info("----------------------------------------\n"); pr_info("----------------------------------------\n");
ret = parse_smaps(pid, vma_area_list); ret = parse_smaps(pid, vma_area_list, dump_file);
if (ret < 0) if (ret < 0)
goto err; goto err;
...@@ -364,8 +350,7 @@ static int dump_pid_misc(pid_t pid, TaskCoreEntry *tc) ...@@ -364,8 +350,7 @@ static int dump_pid_misc(pid_t pid, TaskCoreEntry *tc)
return 0; return 0;
} }
static int dump_filemap(pid_t pid, struct vma_area *vma_area, static int dump_filemap(struct vma_area *vma_area, int fd)
const struct cr_imgset *imgset)
{ {
struct fd_parms p = FD_PARMS_INIT; struct fd_parms p = FD_PARMS_INIT;
VmaEntry *vma = vma_area->e; VmaEntry *vma = vma_area->e;
...@@ -396,7 +381,7 @@ static int dump_filemap(pid_t pid, struct vma_area *vma_area, ...@@ -396,7 +381,7 @@ static int dump_filemap(pid_t pid, struct vma_area *vma_area,
/* Flags will be set during restore in get_filemap_fd() */ /* Flags will be set during restore in get_filemap_fd() */
if (fd_id_generate_special(&p, &id)) if (fd_id_generate_special(&p, &id))
ret = dump_one_reg_file(vma_area->vm_file_fd, id, &p); ret = dump_one_reg_file(fd, id, &p);
vma->shmid = id; vma->shmid = id;
return ret; return ret;
...@@ -469,9 +454,6 @@ static int dump_task_mm(pid_t pid, const struct proc_pid_stat *stat, ...@@ -469,9 +454,6 @@ static int dump_task_mm(pid_t pid, const struct proc_pid_stat *stat,
ret = check_sysvipc_map_dump(pid, vma); ret = check_sysvipc_map_dump(pid, vma);
else if (vma_entry_is(vma, VMA_ANON_SHARED)) else if (vma_entry_is(vma, VMA_ANON_SHARED))
ret = add_shmem_area(pid, vma); ret = add_shmem_area(pid, vma);
else if (vma_entry_is(vma, VMA_FILE_PRIVATE) ||
vma_entry_is(vma, VMA_FILE_SHARED))
ret = dump_filemap(pid, vma_area, imgset);
else if (vma_entry_is(vma, VMA_AREA_SOCKET)) else if (vma_entry_is(vma, VMA_AREA_SOCKET))
ret = dump_socket_map(vma_area); ret = dump_socket_map(vma_area);
else else
...@@ -1126,7 +1108,7 @@ static int pre_dump_one_task(struct pstree_item *item, struct list_head *ctls) ...@@ -1126,7 +1108,7 @@ static int pre_dump_one_task(struct pstree_item *item, struct list_head *ctls)
if (item->pid.state == TASK_DEAD) if (item->pid.state == TASK_DEAD)
return 0; return 0;
ret = collect_mappings(pid, &vmas); ret = collect_mappings(pid, &vmas, NULL);
if (ret) { if (ret) {
pr_err("Collect mappings (pid: %d) failed with %d\n", pid, ret); pr_err("Collect mappings (pid: %d) failed with %d\n", pid, ret);
goto err; goto err;
...@@ -1206,7 +1188,7 @@ static int dump_one_task(struct pstree_item *item) ...@@ -1206,7 +1188,7 @@ static int dump_one_task(struct pstree_item *item)
if (ret < 0) if (ret < 0)
goto err; goto err;
ret = collect_mappings(pid, &vmas); ret = collect_mappings(pid, &vmas, dump_filemap);
if (ret) { if (ret) {
pr_err("Collect mappings (pid: %d) failed with %d\n", pid, ret); pr_err("Collect mappings (pid: %d) failed with %d\n", pid, ret);
goto err; goto err;
......
...@@ -147,7 +147,7 @@ int cr_exec(int pid, char **opt) ...@@ -147,7 +147,7 @@ int cr_exec(int pid, char **opt)
*/ */
free(creds); free(creds);
ret = collect_mappings(pid, &vmas); ret = collect_mappings(pid, &vmas, NULL);
if (ret) { if (ret) {
pr_err("Can't collect vmas for %d\n", pid); pr_err("Can't collect vmas for %d\n", pid);
goto out_unseize; goto out_unseize;
......
...@@ -128,7 +128,9 @@ extern int parse_pid_stat(pid_t pid, struct proc_pid_stat *s); ...@@ -128,7 +128,9 @@ extern int parse_pid_stat(pid_t pid, struct proc_pid_stat *s);
extern unsigned int parse_pid_loginuid(pid_t pid, int *err, bool ignore_noent); extern unsigned int parse_pid_loginuid(pid_t pid, int *err, bool ignore_noent);
extern int parse_pid_oom_score_adj(pid_t pid, int *err); extern int parse_pid_oom_score_adj(pid_t pid, int *err);
extern int prepare_loginuid(unsigned int value, unsigned int loglevel); extern int prepare_loginuid(unsigned int value, unsigned int loglevel);
extern int parse_smaps(pid_t pid, struct vm_area_list *vma_area_list); struct vma_area;
typedef int (*dump_filemap_t)(struct vma_area *vma_area, int fd);
extern int parse_smaps(pid_t pid, struct vm_area_list *vma_area_list, dump_filemap_t cb);
extern int parse_self_maps_lite(struct vm_area_list *vms); extern int parse_self_maps_lite(struct vm_area_list *vms);
extern int parse_pid_status(pid_t pid, struct proc_status_creds *); extern int parse_pid_status(pid_t pid, struct proc_status_creds *);
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
#define AUFSBR_PATH_LEN (SBINFO_PATH_LEN + 6 + 1) /* /sys/fs/aufs/<sbinfo>/br%3d */ #define AUFSBR_PATH_LEN (SBINFO_PATH_LEN + 6 + 1) /* /sys/fs/aufs/<sbinfo>/br%3d */
extern int parse_aufs_branches(struct mount_info *mi); extern int parse_aufs_branches(struct mount_info *mi);
extern int fixup_aufs_vma_fd(struct vma_area *vma); extern int fixup_aufs_vma_fd(struct vma_area *vma, int vm_file_fd);
extern void free_aufs_branches(void); extern void free_aufs_branches(void);
#endif /* __CR_SYSFS_PARSE_H__ */ #endif /* __CR_SYSFS_PARSE_H__ */
......
...@@ -42,7 +42,6 @@ struct vma_area { ...@@ -42,7 +42,6 @@ struct vma_area {
* *
* The aio_nr_req is only for aio rings. * The aio_nr_req is only for aio rings.
*/ */
int vm_file_fd;
int vm_socket_id; int vm_socket_id;
unsigned int aio_nr_req; unsigned int aio_nr_req;
}; };
...@@ -69,8 +68,11 @@ struct vma_area { ...@@ -69,8 +68,11 @@ struct vma_area {
}; };
}; };
typedef int (*dump_filemap_t)(struct vma_area *vma_area, int fd);
extern struct vma_area *alloc_vma_area(void); extern struct vma_area *alloc_vma_area(void);
extern int collect_mappings(pid_t pid, struct vm_area_list *vma_area_list); extern int collect_mappings(pid_t pid,
struct vm_area_list *vma_area_list, dump_filemap_t cb);
extern void free_mappings(struct vm_area_list *vma_area_list); extern void free_mappings(struct vm_area_list *vma_area_list);
#define vma_area_is(vma_area, s) vma_entry_is((vma_area)->e, s) #define vma_area_is(vma_area, s) vma_entry_is((vma_area)->e, s)
......
...@@ -176,7 +176,9 @@ static inline int vfi_equal(struct vma_file_info *a, struct vma_file_info *b) ...@@ -176,7 +176,9 @@ static inline int vfi_equal(struct vma_file_info *a, struct vma_file_info *b)
} }
static int vma_get_mapfile(char *fname, struct vma_area *vma, DIR *mfd, static int vma_get_mapfile(char *fname, struct vma_area *vma, DIR *mfd,
struct vma_file_info *vfi, struct vma_file_info *prev_vfi) struct vma_file_info *vfi,
struct vma_file_info *prev_vfi,
int *vm_file_fd)
{ {
char path[32]; char path[32];
int flags; int flags;
...@@ -188,12 +190,11 @@ static int vma_get_mapfile(char *fname, struct vma_area *vma, DIR *mfd, ...@@ -188,12 +190,11 @@ static int vma_get_mapfile(char *fname, struct vma_area *vma, DIR *mfd,
* If vfi is equal (!) and negative @vm_file_fd -- * If vfi is equal (!) and negative @vm_file_fd --
* we have nothing to borrow for sure. * we have nothing to borrow for sure.
*/ */
if (prev->vm_file_fd < 0) if (*vm_file_fd < 0)
return 0; return 0;
pr_debug("vma %"PRIx64" borrows vfi from previous %"PRIx64"\n", pr_debug("vma %"PRIx64" borrows vfi from previous %"PRIx64"\n",
vma->e->start, prev->e->start); vma->e->start, prev->e->start);
vma->vm_file_fd = prev->vm_file_fd;
if (prev->e->status & VMA_AREA_SOCKET) if (prev->e->status & VMA_AREA_SOCKET)
vma->e->status |= VMA_AREA_SOCKET | VMA_AREA_REGULAR; vma->e->status |= VMA_AREA_SOCKET | VMA_AREA_REGULAR;
...@@ -208,6 +209,7 @@ static int vma_get_mapfile(char *fname, struct vma_area *vma, DIR *mfd, ...@@ -208,6 +209,7 @@ static int vma_get_mapfile(char *fname, struct vma_area *vma, DIR *mfd,
return 0; return 0;
} }
close_safe(vm_file_fd);
/* Figure out if it's file mapping */ /* Figure out if it's file mapping */
snprintf(path, sizeof(path), "%"PRIx64"-%"PRIx64, vma->e->start, vma->e->end); snprintf(path, sizeof(path), "%"PRIx64"-%"PRIx64, vma->e->start, vma->e->end);
...@@ -228,8 +230,8 @@ static int vma_get_mapfile(char *fname, struct vma_area *vma, DIR *mfd, ...@@ -228,8 +230,8 @@ static int vma_get_mapfile(char *fname, struct vma_area *vma, DIR *mfd,
*/ */
flags = O_RDONLY; flags = O_RDONLY;
vma->vm_file_fd = openat(dirfd(mfd), path, flags); *vm_file_fd = openat(dirfd(mfd), path, flags);
if (vma->vm_file_fd < 0) { if (*vm_file_fd < 0) {
if (errno == ENOENT) if (errno == ENOENT)
/* Just mapping w/o map_files link */ /* Just mapping w/o map_files link */
return 0; return 0;
...@@ -249,7 +251,7 @@ static int vma_get_mapfile(char *fname, struct vma_area *vma, DIR *mfd, ...@@ -249,7 +251,7 @@ static int vma_get_mapfile(char *fname, struct vma_area *vma, DIR *mfd,
if ((buf.st_mode & S_IFMT) == 0 && !strncmp(fname, AIO_FNAME, sizeof(AIO_FNAME) - 1)) { if ((buf.st_mode & S_IFMT) == 0 && !strncmp(fname, AIO_FNAME, sizeof(AIO_FNAME) - 1)) {
/* AIO ring, let's try */ /* AIO ring, let's try */
close(vma->vm_file_fd); close_safe(vm_file_fd);
vma->aio_nr_req = -1; vma->aio_nr_req = -1;
vma->e->status = VMA_AREA_AIORING; vma->e->status = VMA_AREA_AIORING;
return 0; return 0;
...@@ -340,7 +342,7 @@ static int vma_get_mapfile(char *fname, struct vma_area *vma, DIR *mfd, ...@@ -340,7 +342,7 @@ static int vma_get_mapfile(char *fname, struct vma_area *vma, DIR *mfd,
return -1; return -1;
} }
vma->vm_file_fd = fd; *vm_file_fd = fd;
return 0; return 0;
} }
...@@ -364,14 +366,14 @@ static int vma_get_mapfile(char *fname, struct vma_area *vma, DIR *mfd, ...@@ -364,14 +366,14 @@ static int vma_get_mapfile(char *fname, struct vma_area *vma, DIR *mfd,
if (opts.aufs) { if (opts.aufs) {
int ret; int ret;
ret = fixup_aufs_vma_fd(vma); ret = fixup_aufs_vma_fd(vma, *vm_file_fd);
if (ret < 0) if (ret < 0)
return -1; return -1;
if (ret > 0) if (ret > 0)
return 0; return 0;
} }
if (fstat(vma->vm_file_fd, vma->vmst) < 0) { if (fstat(*vm_file_fd, vma->vmst) < 0) {
pr_perror("Failed fstat on map %"PRIx64"", vma->e->start); pr_perror("Failed fstat on map %"PRIx64"", vma->e->start);
return -1; return -1;
} }
...@@ -447,9 +449,11 @@ static int handle_vma(pid_t pid, struct vma_area *vma_area, ...@@ -447,9 +449,11 @@ static int handle_vma(pid_t pid, struct vma_area *vma_area,
char *file_path, DIR *map_files_dir, char *file_path, DIR *map_files_dir,
struct vma_file_info *vfi, struct vma_file_info *vfi,
struct vma_file_info *prev_vfi, struct vma_file_info *prev_vfi,
struct vm_area_list *vma_area_list) struct vm_area_list *vma_area_list,
int *vm_file_fd)
{ {
if (vma_get_mapfile(file_path, vma_area, map_files_dir, vfi, prev_vfi)) if (vma_get_mapfile(file_path, vma_area, map_files_dir,
vfi, prev_vfi, vm_file_fd))
goto err_bogus_mapfile; goto err_bogus_mapfile;
if (vma_area->e->status != 0) { if (vma_area->e->status != 0) {
...@@ -488,7 +492,7 @@ static int handle_vma(pid_t pid, struct vma_area *vma_area, ...@@ -488,7 +492,7 @@ static int handle_vma(pid_t pid, struct vma_area *vma_area,
vma_area->e->shmid = prev->e->shmid; vma_area->e->shmid = prev->e->shmid;
vma_area->vmst = prev->vmst; vma_area->vmst = prev->vmst;
vma_area->mnt_id = prev->mnt_id; vma_area->mnt_id = prev->mnt_id;
} else if (vma_area->vm_file_fd >= 0) { } else if (*vm_file_fd >= 0) {
struct stat *st_buf = vma_area->vmst; struct stat *st_buf = vma_area->vmst;
if (S_ISREG(st_buf->st_mode)) if (S_ISREG(st_buf->st_mode))
...@@ -530,7 +534,7 @@ static int handle_vma(pid_t pid, struct vma_area *vma_area, ...@@ -530,7 +534,7 @@ static int handle_vma(pid_t pid, struct vma_area *vma_area,
* have mnt_id. * have mnt_id.
*/ */
if (vma_area->mnt_id != -1 && if (vma_area->mnt_id != -1 &&
get_fd_mntid(vma_area->vm_file_fd, &vma_area->mnt_id)) get_fd_mntid(*vm_file_fd, &vma_area->mnt_id))
return -1; return -1;
} else { } else {
/* /*
...@@ -551,7 +555,7 @@ err: ...@@ -551,7 +555,7 @@ err:
err_bogus_mapping: err_bogus_mapping:
pr_err("Bogus mapping 0x%"PRIx64"-0x%"PRIx64" (flags: %#x vm_file_fd: %d)\n", pr_err("Bogus mapping 0x%"PRIx64"-0x%"PRIx64" (flags: %#x vm_file_fd: %d)\n",
vma_area->e->start, vma_area->e->end, vma_area->e->start, vma_area->e->end,
vma_area->e->flags, vma_area->vm_file_fd); vma_area->e->flags, *vm_file_fd);
goto err; goto err;
err_bogus_mapfile: err_bogus_mapfile:
...@@ -592,12 +596,13 @@ static int vma_list_add(struct vma_area *vma_area, ...@@ -592,12 +596,13 @@ static int vma_list_add(struct vma_area *vma_area,
return 0; return 0;
} }
int parse_smaps(pid_t pid, struct vm_area_list *vma_area_list) int parse_smaps(pid_t pid, struct vm_area_list *vma_area_list,
dump_filemap_t dump_filemap)
{ {
struct vma_area *vma_area = NULL; struct vma_area *vma_area = NULL;
unsigned long start, end, pgoff, prev_end = 0; unsigned long start, end, pgoff, prev_end = 0;
char r, w, x, s; char r, w, x, s;
int ret = -1; int ret = -1, vm_file_fd = -1;
struct vma_file_info vfi; struct vma_file_info vfi;
struct vma_file_info prev_vfi = {}; struct vma_file_info prev_vfi = {};
...@@ -692,8 +697,14 @@ int parse_smaps(pid_t pid, struct vm_area_list *vma_area_list) ...@@ -692,8 +697,14 @@ int parse_smaps(pid_t pid, struct vm_area_list *vma_area_list)
} }
if (handle_vma(pid, vma_area, str + path_off, map_files_dir, if (handle_vma(pid, vma_area, str + path_off, map_files_dir,
&vfi, &prev_vfi, vma_area_list)) &vfi, &prev_vfi, vma_area_list, &vm_file_fd))
goto err; goto err;
if (vma_entry_is(vma_area->e, VMA_FILE_PRIVATE) ||
vma_entry_is(vma_area->e, VMA_FILE_SHARED)) {
if (dump_filemap && dump_filemap(vma_area, vm_file_fd))
goto err;
}
} }
vma_area = NULL; vma_area = NULL;
...@@ -702,6 +713,7 @@ int parse_smaps(pid_t pid, struct vm_area_list *vma_area_list) ...@@ -702,6 +713,7 @@ int parse_smaps(pid_t pid, struct vm_area_list *vma_area_list)
err: err:
bclose(&f); bclose(&f);
err_n: err_n:
close_safe(&vm_file_fd);
if (map_files_dir) if (map_files_dir)
closedir(map_files_dir); closedir(map_files_dir);
......
...@@ -272,13 +272,13 @@ err: ...@@ -272,13 +272,13 @@ err:
* globl root (/) for later use in dump_filemap() * globl root (/) for later use in dump_filemap()
* and parse_smaps(). * and parse_smaps().
*/ */
int fixup_aufs_vma_fd(struct vma_area *vma) int fixup_aufs_vma_fd(struct vma_area *vma, int vm_file_fd)
{ {
char path[PATH_MAX]; char path[PATH_MAX];
int len; int len;
path[0] = '.'; path[0] = '.';
len = read_fd_link(vma->vm_file_fd, &path[1], sizeof path - 1); len = read_fd_link(vm_file_fd, &path[0], sizeof path - 1);
if (len < 0) if (len < 0)
return -1; return -1;
......
...@@ -800,7 +800,6 @@ struct vma_area *alloc_vma_area(void) ...@@ -800,7 +800,6 @@ struct vma_area *alloc_vma_area(void)
if (p) { if (p) {
p->e = (VmaEntry *)(p + 1); p->e = (VmaEntry *)(p + 1);
vma_entry__init(p->e); vma_entry__init(p->e);
p->vm_file_fd = -1;
p->e->fd = -1; p->e->fd = -1;
} }
......
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