Commit 608db864 authored by Pavel Emelyanov's avatar Pavel Emelyanov

vmas: Don't call stat on vm file twice

When parsing mappings in proc, we fstat vm file, later,
when dumping it, we stat it again to fill fd_parms.
The 2nd stat is not required, we can keep the stat in
vma_area.

This removed 35% of all stat calls on dump of basic container.
Signed-off-by: 's avatarPavel Emelyanov <xemul@parallels.com>
parent bd7bf7bd
...@@ -128,6 +128,8 @@ void free_mappings(struct vm_area_list *vma_area_list) ...@@ -128,6 +128,8 @@ void free_mappings(struct vm_area_list *vma_area_list)
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); close_vma_file(vma_area);
if (!vma_area->file_borrowed)
free(vma_area->st);
free(vma_area); free(vma_area);
} }
...@@ -341,15 +343,14 @@ static int dump_task_rlims(int pid, struct cr_fdset *fds) ...@@ -341,15 +343,14 @@ static int dump_task_rlims(int pid, struct cr_fdset *fds)
return 0; return 0;
} }
static int dump_filemap(pid_t pid, VmaEntry *vma, int file_fd, static int dump_filemap(pid_t pid, struct vma_area *vma_area,
const struct cr_fdset *fdset) const struct cr_fdset *fdset)
{ {
struct fd_parms p = FD_PARMS_INIT; struct fd_parms p = FD_PARMS_INIT;
VmaEntry *vma = &vma_area->vma;
if (fstat(file_fd, &p.stat) < 0) { BUG_ON(!vma_area->st);
pr_perror("Can't stat file for vma"); p.stat = *vma_area->st;
return -1;
}
if ((vma->prot & PROT_WRITE) && vma_entry_is(vma, VMA_FILE_SHARED)) if ((vma->prot & PROT_WRITE) && vma_entry_is(vma, VMA_FILE_SHARED))
p.flags = O_RDWR; p.flags = O_RDWR;
...@@ -357,7 +358,7 @@ static int dump_filemap(pid_t pid, VmaEntry *vma, int file_fd, ...@@ -357,7 +358,7 @@ static int dump_filemap(pid_t pid, VmaEntry *vma, int file_fd,
p.flags = O_RDONLY; p.flags = O_RDONLY;
vma->shmid = fd_id_generate_special(); vma->shmid = fd_id_generate_special();
return dump_one_reg_file(file_fd, vma->shmid, &p); return dump_one_reg_file(vma_area->vm_file_fd, vma->shmid, &p);
} }
static int check_sysvipc_map_dump(pid_t pid, VmaEntry *vma) static int check_sysvipc_map_dump(pid_t pid, VmaEntry *vma)
...@@ -395,7 +396,7 @@ static int dump_task_mappings(pid_t pid, const struct vm_area_list *vma_area_lis ...@@ -395,7 +396,7 @@ static int dump_task_mappings(pid_t pid, const struct vm_area_list *vma_area_lis
ret = add_shmem_area(pid, vma); ret = add_shmem_area(pid, vma);
else if (vma_entry_is(vma, VMA_FILE_PRIVATE) || else if (vma_entry_is(vma, VMA_FILE_PRIVATE) ||
vma_entry_is(vma, VMA_FILE_SHARED)) vma_entry_is(vma, VMA_FILE_SHARED))
ret = dump_filemap(pid, vma, vma_area->vm_file_fd, cr_fdset); ret = dump_filemap(pid, vma_area, cr_fdset);
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
......
...@@ -27,6 +27,8 @@ struct vma_area { ...@@ -27,6 +27,8 @@ struct vma_area {
unsigned long premmaped_addr; unsigned long premmaped_addr;
bool file_borrowed; bool file_borrowed;
struct stat *st;
}; };
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);
......
...@@ -351,16 +351,21 @@ int parse_smaps(pid_t pid, struct vm_area_list *vma_area_list, bool use_map_file ...@@ -351,16 +351,21 @@ int parse_smaps(pid_t pid, struct vm_area_list *vma_area_list, bool use_map_file
vma_area->vma.flags |= (prev->vma.flags & MAP_ANONYMOUS); vma_area->vma.flags |= (prev->vma.flags & MAP_ANONYMOUS);
vma_area->vma.status = prev->vma.status; vma_area->vma.status = prev->vma.status;
vma_area->vma.shmid = prev->vma.shmid; vma_area->vma.shmid = prev->vma.shmid;
vma_area->st = prev->st;
} else if (vma_area->vm_file_fd >= 0) { } else if (vma_area->vm_file_fd >= 0) {
struct stat st_buf; struct stat *st_buf;
if (fstat(vma_area->vm_file_fd, &st_buf) < 0) { st_buf = vma_area->st = xmalloc(sizeof(*st_buf));
if (!st_buf)
goto err;
if (fstat(vma_area->vm_file_fd, st_buf) < 0) {
pr_perror("Failed fstat on %d's map %lu", pid, start); pr_perror("Failed fstat on %d's map %lu", pid, start);
goto err; goto err;
} }
if (!S_ISREG(st_buf.st_mode) && if (!S_ISREG(st_buf->st_mode) &&
!(S_ISCHR(st_buf.st_mode) && st_buf.st_rdev == DEVZERO)) { !(S_ISCHR(st_buf->st_mode) && st_buf->st_rdev == DEVZERO)) {
pr_err("Can't handle non-regular mapping on %d's map %lu\n", pid, start); pr_err("Can't handle non-regular mapping on %d's map %lu\n", pid, start);
goto err; goto err;
} }
...@@ -369,12 +374,12 @@ int parse_smaps(pid_t pid, struct vm_area_list *vma_area_list, bool use_map_file ...@@ -369,12 +374,12 @@ int parse_smaps(pid_t pid, struct vm_area_list *vma_area_list, bool use_map_file
* /dev/zero stands for anon-shared mapping * /dev/zero stands for anon-shared mapping
* otherwise it's some file mapping. * otherwise it's some file mapping.
*/ */
if (is_anon_shmem_map(st_buf.st_dev)) { if (is_anon_shmem_map(st_buf->st_dev)) {
if (!(vma_area->vma.flags & MAP_SHARED)) if (!(vma_area->vma.flags & MAP_SHARED))
goto err_bogus_mapping; goto err_bogus_mapping;
vma_area->vma.flags |= MAP_ANONYMOUS; vma_area->vma.flags |= MAP_ANONYMOUS;
vma_area->vma.status |= VMA_ANON_SHARED; vma_area->vma.status |= VMA_ANON_SHARED;
vma_area->vma.shmid = st_buf.st_ino; vma_area->vma.shmid = st_buf->st_ino;
if (!strcmp(file_path, "/SYSV")) { if (!strcmp(file_path, "/SYSV")) {
pr_info("path: %s\n", file_path); pr_info("path: %s\n", file_path);
......
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