Commit 5661d806 authored by Kir Kolyshkin's avatar Kir Kolyshkin Committed by Cyrill Gorcunov

Move error reporting to inside open_proc and friends

...and make it correctly print the file name we were unable to open.
Also, error from fdopen[dir]() is now reported with file name as well.

Note that open_proc() and friends need to be macros in order for
pr_perror() to show actual file name and line number where error occured.

Historical note: the original version of this patch was way more radical,
changing openat() to open() and thus removing pid_dir (replacing with pid
when needed) and open_proc_dir(), changing openat() to open(). The word
from Pavel is he wants to keep the openat/pid_dir optimization because
it saves two dentry lookups in kernel code for each open(). Because of
this optimization (and desire to print correct file name in case
of error) we have to carry both pid and pid_dir everywhere.
Signed-off-by: 's avatarKir Kolyshkin <kir@openvz.org>
Acked-by: 's avatarPavel Emelyanov <xemul@parallels.com>
Signed-off-by: 's avatarCyrill Gorcunov <gorcunov@openvz.org>
parent 5434d99e
...@@ -138,29 +138,25 @@ err: ...@@ -138,29 +138,25 @@ err:
return ret; return ret;
} }
static int dump_task_special_files(int pid_dir, struct cr_fdset *cr_fdset) static int dump_task_special_files(pid_t pid, int pid_dir, struct cr_fdset *cr_fdset)
{ {
struct fd_parms params; struct fd_parms params;
int fd, ret; int fd, ret;
/* Dump /proc/pid/cwd */ /* Dump /proc/pid/cwd */
params = (struct fd_parms){ .fd_name = FDINFO_CWD, }; params = (struct fd_parms){ .fd_name = FDINFO_CWD, };
fd = open_proc(pid_dir, "cwd"); fd = open_proc(pid, pid_dir, "cwd");
if (fd < 0) { if (fd < 0)
pr_perror("Failed to openat cwd");
return -1; return -1;
}
ret = dump_one_reg_file(FDINFO_FD, &params, fd, cr_fdset, 1); ret = dump_one_reg_file(FDINFO_FD, &params, fd, cr_fdset, 1);
if (ret) if (ret)
return ret; return ret;
/* Dump /proc/pid/exe */ /* Dump /proc/pid/exe */
params = (struct fd_parms){ .fd_name = FDINFO_EXE, }; params = (struct fd_parms){ .fd_name = FDINFO_EXE, };
fd = open_proc(pid_dir, "exe"); fd = open_proc(pid, pid_dir, "exe");
if (fd < 0) { if (fd < 0)
pr_perror("Failed to openat exe");
return -1; return -1;
}
ret = dump_one_reg_file(FDINFO_FD, &params, fd, cr_fdset, 1); ret = dump_one_reg_file(FDINFO_FD, &params, fd, cr_fdset, 1);
return ret; return ret;
...@@ -311,11 +307,9 @@ static int read_fd_params(pid_t pid, int pid_dir, char *fd, struct fd_parms *p) ...@@ -311,11 +307,9 @@ static int read_fd_params(pid_t pid, int pid_dir, char *fd, struct fd_parms *p)
FILE *file; FILE *file;
int ret; int ret;
file = fopen_proc(pid_dir, "fdinfo/%s", fd); file = fopen_proc(pid, pid_dir, "fdinfo/%s", fd);
if (!file) { if (!file)
pr_perror("Can't open %d's %s fdinfo", pid, fd);
return -1; return -1;
}
p->fd_name = atoi(fd); p->fd_name = atoi(fd);
ret = fscanf(file, "pos:\t%li\nflags:\t%o\nid:\t%s\n", &p->pos, &p->flags, p->id); ret = fscanf(file, "pos:\t%li\nflags:\t%o\nid:\t%s\n", &p->pos, &p->flags, p->id);
...@@ -348,16 +342,14 @@ static int dump_task_files(pid_t pid, int pid_dir, struct cr_fdset *cr_fdset) ...@@ -348,16 +342,14 @@ static int dump_task_files(pid_t pid, int pid_dir, struct cr_fdset *cr_fdset)
* to re-read them in restorer, so better to make it * to re-read them in restorer, so better to make it
* fast. * fast.
*/ */
if (dump_task_special_files(pid_dir, cr_fdset)) { if (dump_task_special_files(pid, pid_dir, cr_fdset)) {
pr_err("Can't dump special files\n"); pr_err("Can't dump special files\n");
return -1; return -1;
} }
fd_dir = opendir_proc(pid_dir, "fd"); fd_dir = opendir_proc(pid, pid_dir, "fd");
if (!fd_dir) { if (!fd_dir)
pr_perror("Can't open %d's fd", pid);
return -1; return -1;
}
while ((de = readdir(fd_dir))) { while ((de = readdir(fd_dir))) {
char id[FD_ID_SIZE]; char id[FD_ID_SIZE];
...@@ -455,7 +447,7 @@ static int dump_task_creds(pid_t pid, int pid_dir, ...@@ -455,7 +447,7 @@ static int dump_task_creds(pid_t pid, int pid_dir,
pr_info("Dumping creds for %d)\n", pid); pr_info("Dumping creds for %d)\n", pid);
pr_info("----------------------------------------\n"); pr_info("----------------------------------------\n");
ret = parse_pid_status(pid_dir, &cr); ret = parse_pid_status(pid, pid_dir, &cr);
if (ret < 0) if (ret < 0)
return ret; return ret;
...@@ -497,11 +489,9 @@ static int get_task_sigmask(pid_t pid, int pid_dir, u64 *task_sigset) ...@@ -497,11 +489,9 @@ static int get_task_sigmask(pid_t pid, int pid_dir, u64 *task_sigset)
/* /*
* Now signals. * Now signals.
*/ */
file = fopen_proc(pid_dir, "status"); file = fopen_proc(pid, pid_dir, "status");
if (!file) { if (!file)
pr_perror("Can't open %d status", pid);
goto err; goto err;
}
while (fgets(loc_buf, sizeof(loc_buf), file)) { while (fgets(loc_buf, sizeof(loc_buf), file)) {
if (!strncmp(loc_buf, "SigBlk:", 7)) { if (!strncmp(loc_buf, "SigBlk:", 7)) {
...@@ -519,13 +509,11 @@ err: ...@@ -519,13 +509,11 @@ err:
static int get_task_auxv(pid_t pid, int pid_dir, struct core_entry *core) static int get_task_auxv(pid_t pid, int pid_dir, struct core_entry *core)
{ {
int fd = open_proc(pid_dir, "auxv"); int fd = open_proc(pid, pid_dir, "auxv");
int ret, i; int ret, i;
if (fd < 0) { if (fd < 0)
pr_perror("Can't open %d's auxv", pid);
return -1; return -1;
}
for (i = 0; i < AT_VECTOR_SIZE; i++) { for (i = 0; i < AT_VECTOR_SIZE; i++) {
ret = read(fd, &core->tc.mm_saved_auxv[i], ret = read(fd, &core->tc.mm_saved_auxv[i],
...@@ -552,11 +540,9 @@ static int get_task_personality(pid_t pid, int pid_dir, u32 *personality) ...@@ -552,11 +540,9 @@ static int get_task_personality(pid_t pid, int pid_dir, u32 *personality)
FILE *file = NULL; FILE *file = NULL;
int ret = -1; int ret = -1;
file = fopen_proc(pid_dir, "personality"); file = fopen_proc(pid, pid_dir, "personality");
if (!file) { if (!file)
pr_perror("Can't open %d personality", pid);
goto err; goto err;
}
if (!fgets(loc_buf, sizeof(loc_buf), file)) { if (!fgets(loc_buf, sizeof(loc_buf), file)) {
perror("Can't read task personality"); perror("Can't read task personality");
...@@ -738,18 +724,16 @@ err: ...@@ -738,18 +724,16 @@ err:
return ret; return ret;
} }
static int parse_threads(struct pstree_item *item, int pid_dir) static int parse_threads(struct pstree_item *item, pid_t pid, int pid_dir)
{ {
struct dirent *de; struct dirent *de;
DIR *dir; DIR *dir;
u32 *t = NULL; u32 *t = NULL;
int nr = 1; int nr = 1;
dir = opendir_proc(pid_dir, "task"); dir = opendir_proc(pid, pid_dir, "task");
if (!dir) { if (!dir)
pr_perror("Can't open %d/task", item->pid);
return -1; return -1;
}
while ((de = readdir(dir))) { while ((de = readdir(dir))) {
u32 *tmp; u32 *tmp;
...@@ -776,7 +760,7 @@ static int parse_threads(struct pstree_item *item, int pid_dir) ...@@ -776,7 +760,7 @@ static int parse_threads(struct pstree_item *item, int pid_dir)
return 0; return 0;
} }
static int parse_children(struct pstree_item *item, int pid_dir) static int parse_children(struct pstree_item *item, pid_t pid, int pid_dir)
{ {
FILE *file; FILE *file;
char *tok; char *tok;
...@@ -785,12 +769,9 @@ static int parse_children(struct pstree_item *item, int pid_dir) ...@@ -785,12 +769,9 @@ static int parse_children(struct pstree_item *item, int pid_dir)
for (i = 0; i < item->nr_threads; i++) { for (i = 0; i < item->nr_threads; i++) {
file = fopen_proc(pid_dir, "task/%d/children", item->threads[i]); file = fopen_proc(pid, pid_dir, "task/%d/children", item->threads[i]);
if (!file) { if (!file)
pr_perror("Can't open %d children %d",
item->pid, item->threads[i]);
goto err; goto err;
}
if (!(fgets(loc_buf, sizeof(loc_buf), file))) if (!(fgets(loc_buf, sizeof(loc_buf), file)))
loc_buf[0] = 0; loc_buf[0] = 0;
...@@ -918,7 +899,7 @@ static struct pstree_item *collect_task(pid_t pid, struct list_head *list) ...@@ -918,7 +899,7 @@ static struct pstree_item *collect_task(pid_t pid, struct list_head *list)
item->state = TASK_DEAD; item->state = TASK_DEAD;
} }
ret = parse_threads(item, pid_dir); ret = parse_threads(item, pid, pid_dir);
if (ret < 0) if (ret < 0)
goto err_close; goto err_close;
...@@ -926,7 +907,7 @@ static struct pstree_item *collect_task(pid_t pid, struct list_head *list) ...@@ -926,7 +907,7 @@ static struct pstree_item *collect_task(pid_t pid, struct list_head *list)
if (ret < 0) if (ret < 0)
goto err_close; goto err_close;
ret = parse_children(item, pid_dir); ret = parse_children(item, pid, pid_dir);
if (ret < 0) if (ret < 0)
goto err_close; goto err_close;
...@@ -1286,7 +1267,7 @@ int cr_dump_tasks(pid_t pid, struct cr_options *opts) ...@@ -1286,7 +1267,7 @@ int cr_dump_tasks(pid_t pid, struct cr_options *opts)
LIST_HEAD(pstree_list); LIST_HEAD(pstree_list);
struct cr_fdset *cr_fdset = NULL; struct cr_fdset *cr_fdset = NULL;
struct pstree_item *item; struct pstree_item *item;
int i, ret = -1, pid_dir; int i, ret = -1;
pr_info("========================================\n"); pr_info("========================================\n");
if (!opts->leader_only) if (!opts->leader_only)
......
...@@ -80,6 +80,6 @@ struct proc_status_creds { ...@@ -80,6 +80,6 @@ struct proc_status_creds {
extern int parse_pid_stat(pid_t pid, int pid_dir, struct proc_pid_stat *s); extern int parse_pid_stat(pid_t pid, int pid_dir, struct proc_pid_stat *s);
extern int parse_pid_stat_small(pid_t pid, int pid_dir, struct proc_pid_stat_small *s); extern int parse_pid_stat_small(pid_t pid, int pid_dir, struct proc_pid_stat_small *s);
extern int parse_maps(pid_t pid, int pid_dir, struct list_head *vma_area_list, bool use_map_files); extern int parse_maps(pid_t pid, int pid_dir, struct list_head *vma_area_list, bool use_map_files);
extern int parse_pid_status(int pid_dir, struct proc_status_creds *); extern int parse_pid_status(pid_t pid, int pid_dir, struct proc_status_creds *);
#endif /* PROC_PARSE_H__ */ #endif /* PROC_PARSE_H__ */
...@@ -205,10 +205,58 @@ extern int reopen_fd_as_safe(int new_fd, int old_fd, bool allow_reuse_fd); ...@@ -205,10 +205,58 @@ extern int reopen_fd_as_safe(int new_fd, int old_fd, bool allow_reuse_fd);
extern void hex_dump(void *addr, unsigned long len); extern void hex_dump(void *addr, unsigned long len);
int open_pid_proc(pid_t pid); int open_pid_proc(pid_t pid);
int open_proc(int pid_dir_fd, char *fmt, ...); int do_open_proc(int pid_dir, int flags, const char *fmt, ...);
int open_proc_rw(int pid_dir_fd, char *fmt, ...)
DIR *opendir_proc(int pid_dir_fd, char *fmt, ...); #define __open_proc(pid, pid_dir, flags, fmt, ...) \
FILE *fopen_proc(int pid_dir_fd, char *fmt, ...); ({ \
int __fd = do_open_proc(pid_dir, flags, \
fmt, ##__VA_ARGS__); \
if (__fd < 0) \
pr_perror("Can't open /proc/%d/" fmt, \
pid, ##__VA_ARGS__); \
\
__fd; \
})
/* int open_proc(pid_t pid, int pid_dir, const char *fmt, ...); */
#define open_proc(pid, pid_dir, fmt, ...) \
__open_proc(pid, pid_dir, O_RDONLY, fmt, ##__VA_ARGS__)
/* int open_proc_rw(pid_t pid, int pid_dir, const char *fmt, ...); */
#define open_proc_rw(pid, pid_dir, fmt, ...) \
__open_proc(pid, pid_dir, O_RDWR, fmt, ##__VA_ARGS__)
/* DIR *opendir_proc(pid_t pid, int pid_dir, const char *fmt, ...); */
#define opendir_proc(pid, pid_dir, fmt, ...) \
({ \
int __fd = open_proc(pid, pid_dir, fmt, ##__VA_ARGS__); \
DIR *__d = NULL; \
\
if (__fd >= 0) \
__d = fdopendir(__fd); \
if (__d == NULL) \
pr_perror("Can't fdopendir %d " \
"(/proc/%d/" fmt ")", \
__fd, pid, ##__VA_ARGS__); \
\
__d; \
})
/* FILE *fopen_proc(pid_t pid, int pid_dir, const char *fmt, ...); */
#define fopen_proc(pid, pid_dir, fmt, ...) \
({ \
int __fd = open_proc(pid, pid_dir, fmt, ##__VA_ARGS__); \
FILE *__f = NULL; \
\
if (__fd >= 0) \
__f = fdopen(__fd, "r"); \
if (__f == NULL) \
pr_perror("Can't fdopen %d " \
"(/proc/%d/" fmt ")", \
__fd, pid, ##__VA_ARGS__); \
\
__f; \
})
#define __xalloc(op, size, ...) \ #define __xalloc(op, size, ...) \
({ \ ({ \
......
...@@ -620,7 +620,7 @@ struct parasite_ctl *parasite_infect_seized(pid_t pid, int pid_dir, struct list_ ...@@ -620,7 +620,7 @@ struct parasite_ctl *parasite_infect_seized(pid_t pid, int pid_dir, struct list_
ctl->map_length = round_up(parasite_size, PAGE_SIZE); ctl->map_length = round_up(parasite_size, PAGE_SIZE);
fd = open_proc_rw(pid_dir, "map_files/%p-%p", fd = open_proc_rw(pid, pid_dir, "map_files/%p-%p",
ctl->remote_map, ctl->remote_map + ctl->map_length); ctl->remote_map, ctl->remote_map + ctl->map_length);
if (fd < 0) { if (fd < 0) {
pr_perror("Can't open remote parasite map"); pr_perror("Can't open remote parasite map");
......
...@@ -28,19 +28,15 @@ int parse_maps(pid_t pid, int pid_dir, struct list_head *vma_area_list, bool use ...@@ -28,19 +28,15 @@ int parse_maps(pid_t pid, int pid_dir, struct list_head *vma_area_list, bool use
DIR *map_files_dir = NULL; DIR *map_files_dir = NULL;
FILE *maps = NULL; FILE *maps = NULL;
maps = fopen_proc(pid_dir, "maps"); maps = fopen_proc(pid, pid_dir, "maps");
if (!maps) { if (!maps)
pr_perror("Can't open %d's maps", pid);
goto err; goto err;
}
if (use_map_files) { if (use_map_files) {
map_files_dir = opendir_proc(pid_dir, "map_files"); map_files_dir = opendir_proc(pid, pid_dir, "map_files");
if (!map_files_dir) { if (!map_files_dir) /* old kernel? */
pr_perror("Can't open %d's map_files (old kernel?)\n", pid);
goto err; goto err;
} }
}
while (fgets(big_buffer, sizeof(big_buffer), maps)) { while (fgets(big_buffer, sizeof(big_buffer), maps)) {
struct stat st_buf; struct stat st_buf;
...@@ -189,11 +185,9 @@ int parse_pid_stat_small(pid_t pid, int pid_dir, struct proc_pid_stat_small *s) ...@@ -189,11 +185,9 @@ int parse_pid_stat_small(pid_t pid, int pid_dir, struct proc_pid_stat_small *s)
char *tok; char *tok;
int n; int n;
f = fopen_proc(pid_dir, "stat"); f = fopen_proc(pid, pid_dir, "stat");
if (f == NULL) { if (f == NULL)
pr_perror("Can't open %d's stat", pid);
return -1; return -1;
}
memset(s, 0, sizeof(*s)); memset(s, 0, sizeof(*s));
n = fscanf(f, "%d " PROC_TASK_COMM_LEN_FMT " %c", n = fscanf(f, "%d " PROC_TASK_COMM_LEN_FMT " %c",
...@@ -219,11 +213,9 @@ int parse_pid_stat(pid_t pid, int pid_dir, struct proc_pid_stat *s) ...@@ -219,11 +213,9 @@ int parse_pid_stat(pid_t pid, int pid_dir, struct proc_pid_stat *s)
char *tok; char *tok;
int n; int n;
f = fopen_proc(pid_dir, "stat"); f = fopen_proc(pid, pid_dir, "stat");
if (f == NULL) { if (f == NULL)
pr_perror("Can't open %d's stat", pid);
return -1; return -1;
}
memset(s, 0, sizeof(*s)); memset(s, 0, sizeof(*s));
n = fscanf(f, n = fscanf(f,
...@@ -326,13 +318,13 @@ static int cap_parse(char *str, unsigned int *res) ...@@ -326,13 +318,13 @@ static int cap_parse(char *str, unsigned int *res)
return 0; return 0;
} }
int parse_pid_status(int pid_dir, struct proc_status_creds *cr) int parse_pid_status(pid_t pid, int pid_dir, struct proc_status_creds *cr)
{ {
int done = 0; int done = 0;
FILE *f; FILE *f;
char str[64]; char str[64];
f = fopen_proc(pid_dir, "status"); f = fopen_proc(pid, pid_dir, "status");
if (f == NULL) { if (f == NULL) {
pr_perror("Can't open proc status"); pr_perror("Can't open proc status");
return -1; return -1;
......
...@@ -217,46 +217,14 @@ int open_pid_proc(pid_t pid) ...@@ -217,46 +217,14 @@ int open_pid_proc(pid_t pid)
return fd; return fd;
} }
#define do_open_proc(pid_dir_fd, fmt, flags) \ int do_open_proc(int dirfd, int flags, const char *fmt, ...)
({ \
char fname[64]; \
va_list args; \
\
va_start(args, fmt); \
vsnprintf(fname, sizeof(fname), fmt, args); \
va_end(args); \
\
openat(pid_dir_fd, fname, flags); \
})
int open_proc(int pid_dir_fd, char *fmt, ...)
{ {
return do_open_proc(pid_dir_fd, fmt, O_RDONLY); char path[128];
} va_list args;
int open_proc_rw(int pid_dir_fd, char *fmt, ...)
{
return do_open_proc(pid_dir_fd, fmt, O_RDWR);
}
DIR *opendir_proc(int pid_dir_fd, char *fmt, ...)
{
int dirfd;
dirfd = do_open_proc(pid_dir_fd, fmt);
if (dirfd >= 0)
return fdopendir(dirfd);
return NULL;
}
FILE *fopen_proc(int pid_dir_fd, char *fmt, ...)
{
int fd;
fd = do_open_proc(pid_dir_fd, fmt); va_start(args, fmt);
if (fd >= 0) vsnprintf(path, sizeof(path), fmt, args);
return fdopen(fd, "r"); va_end(args);
return NULL; return openat(dirfd, path, flags);
} }
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