Commit 164ccc09 authored by Pavel Emelyanov's avatar Pavel Emelyanov Committed by Cyrill Gorcunov

crtools: R/W API rewrite

Kill all the macros for reading/writing image parts. New API looks like

* write_img_buf/write_img
  Write an object into an image. Reports 0 for OK, -1 for error. The _buf
  version accepts object size as an argument, the other one uses sizeof()

* read_img_buf/read_img
  Reads an object from image. Reports 0 for OK, -1 for error or EOF.

* read_img_buf_eof/read_img
  Reads an object from image. Reports 1 for OK, 0 for EOF and -1 for error.
  This is not symmetrical with the previous one, but it was done deliberately
  to make it possible to write code like

  ret = read_img_bug_eof();
  if (ret <= 0)
	return ret; /* 0 means OK, all is done, -1 means error was met */.

  ... /* 1 means object was read, can proceed */
Signed-off-by: 's avatarPavel Emelyanov <xemul@parallels.com>
Signed-off-by: 's avatarCyrill Gorcunov <gorcunov@openvz.org>
parent dbf3c1a8
......@@ -127,8 +127,10 @@ static int dump_one_reg_file(int type, struct fd_parms *p, int lfd,
pr_info("fdinfo: type: %2x len: %2x flags: %4x pos: %8x addr: %16lx\n",
type, len, p->flags, p->pos, p->fd_name);
write_ptr_safe(cr_fdset->fds[CR_FD_FDINFO], &e, err);
write_safe(cr_fdset->fds[CR_FD_FDINFO], big_buffer, e.len, err);
if (write_img(cr_fdset->fds[CR_FD_FDINFO], &e))
goto err;
if (write_img_buf(cr_fdset->fds[CR_FD_FDINFO], big_buffer, e.len))
goto err;
ret = 0;
err:
......@@ -189,7 +191,8 @@ static int dump_pipe_and_data(int lfd, struct pipe_entry *e,
}
e->bytes = has_bytes;
write_ptr_safe(fd_pipes, e, err_close);
if (write_img(fd_pipes, e))
goto err_close;
if (has_bytes) {
ret = splice(steal_pipe[0], NULL, fd_pipes,
......@@ -224,8 +227,7 @@ static int dump_one_pipe(struct fd_parms *p, unsigned int id, int lfd,
if (p->flags & O_WRONLY) {
e.bytes = 0;
write_ptr_safe(cr_fdset->fds[CR_FD_PIPES], &e, err);
ret = 0;
ret = write_img(cr_fdset->fds[CR_FD_PIPES], &e);
} else
ret = dump_pipe_and_data(lfd, &e, cr_fdset);
......@@ -395,7 +397,8 @@ static int dump_task_mappings(pid_t pid, struct list_head *vma_area_list, struct
pr_info("shmem: s: %16lx e: %16lx shmid: %16lx\n",
e.start, e.end, e.shmid);
write_ptr_safe(cr_fdset->fds[CR_FD_SHMEM], &e, err);
if (write_img(cr_fdset->fds[CR_FD_SHMEM], &e))
goto err;
} else if (vma_entry_is(vma, VMA_FILE_PRIVATE) ||
vma_entry_is(vma, VMA_FILE_SHARED)) {
struct fd_parms p = {
......@@ -612,7 +615,8 @@ static int dump_task_core_seized(pid_t pid, int pid_dir, struct proc_pid_stat *s
core->header.arch = HEADER_ARCH_X86_64;
core->header.flags = 0;
write_ptr_safe(fd_core, core, err_free);
if (write_img(fd_core, core))
goto err_free;
pr_info("OK\n");
ret = 0;
......@@ -814,21 +818,24 @@ static int dump_pstree(pid_t pid, struct list_head *pstree_list, struct cr_fdset
e.nr_children = item->nr_children;
e.nr_threads = item->nr_threads;
write_ptr_safe(cr_fdset->fds[CR_FD_PSTREE], &e, err);
if (write_img(cr_fdset->fds[CR_FD_PSTREE], &e))
goto err;
pr_info("Children:");
for (i = 0; i < item->nr_children; i++) {
pr_info(" %d", item->children[i]);
write_ptr_safe(cr_fdset->fds[CR_FD_PSTREE],
&item->children[i], err);
if (write_img(cr_fdset->fds[CR_FD_PSTREE],
&item->children[i]))
goto err;
}
pr_info("\n");
pr_info("Threads:\n");
for (i = 0; i < item->nr_threads; i++) {
pr_info(" %d", item->threads[i]);
write_ptr_safe(cr_fdset->fds[CR_FD_PSTREE],
&item->threads[i], err);
if (write_img(cr_fdset->fds[CR_FD_PSTREE],
&item->threads[i]))
goto err;
}
pr_info("\n");
}
......@@ -889,7 +896,8 @@ static int finalize_core(pid_t pid, struct list_head *vma_area_list, struct cr_f
/* Ending marker */
memzero_p(&ve);
write_ptr_safe(fd_core, &ve, err);
if (write_img(fd_core, &ve))
goto err;
pr_info("OK (%li written)\n", num);
......@@ -908,8 +916,10 @@ static int finalize_core(pid_t pid, struct list_head *vma_area_list, struct cr_f
/* Ending marker */
if (va == 0) {
write_ptr_safe(fd_core, &zero_page_entry, err);
write_ptr_safe(fd_pages_shmem, &zero_page_entry, err);
if (write_img(fd_core, &zero_page_entry))
goto err;
if (write_img(fd_pages_shmem, &zero_page_entry))
goto err;
break;
}
......@@ -1007,7 +1017,8 @@ static int dump_task_thread(pid_t pid, struct cr_fdset *cr_fdset)
core->header.arch = HEADER_ARCH_X86_64;
core->header.flags = 0;
write_ptr_safe(fd_core, core, err_free);
if (write_img(fd_core, core))
goto err_free;
pr_info("OK\n");
ret = 0;
......
......@@ -1104,7 +1104,8 @@ static inline int fork_with_pid(int pid)
goto err;
}
write_safe(fd, buf, strlen(buf), err_unlock);
if (write_img_buf(fd, buf, strlen(buf)))
goto err_unlock;
ret = fork();
if (ret < 0) {
......@@ -1460,8 +1461,8 @@ static void sigreturn_restore(pid_t pstree_pid, pid_t pid)
*/
lseek(fd_pstree, MAGIC_OFFSET, SEEK_SET);
while (1) {
ret = read_ptr_safe_eof(fd_pstree, &pstree_entry, err);
if (!ret) {
ret = read_img_eof(fd_pstree, &pstree_entry);
if (ret <= 0) {
pr_perror("Pid %d not found in process tree\n", pid);
goto err;
}
......@@ -1595,7 +1596,8 @@ static void sigreturn_restore(pid_t pstree_pid, pid_t pid)
*/
lseek(fd_pstree, sizeof(u32) * pstree_entry.nr_children, SEEK_CUR);
for (i = 0; i < pstree_entry.nr_threads; i++) {
read_ptr_safe(fd_pstree, &thread_args[i].pid, err);
if (read_img(fd_pstree, &thread_args[i].pid) < 0)
goto err;
/* skip self */
if (thread_args[i].pid == pid)
......
......@@ -58,8 +58,10 @@ static void show_shmem(int fd_shmem)
pr_img_head(CR_FD_SHMEM);
while (1) {
int ret = read_ptr_safe_eof(fd_shmem, &e, out);
if (!ret)
int ret;
ret = read_img_eof(fd_shmem, &e);
if (ret <= 0)
goto out;
pr_info("0x%lx-0x%lx id %lu\n", e.start, e.end, e.shmid);
}
......@@ -75,8 +77,10 @@ static void show_files(int fd_files)
pr_img_head(CR_FD_FDINFO);
while (1) {
int ret = read_ptr_safe_eof(fd_files, &e, out);
if (!ret)
int ret;
ret = read_img_eof(fd_files, &e);
if (ret <= 0)
goto out;
pr_info("type: %02x len: %02x flags: %4x pos: %8x addr: %16lx id: %s",
......@@ -107,8 +111,10 @@ static void show_pipes(int fd_pipes)
pr_img_head(CR_FD_PIPES);
while (1) {
int ret = read_ptr_safe_eof(fd_pipes, &e, out);
if (!ret)
int ret;
ret = read_img_eof(fd_pipes, &e);
if (ret <= 0)
goto out;
pr_info("fd: %8lx pipeid: %8lx flags: %8lx bytes: %8lx\n",
e.fd, e.pipeid, e.flags, e.bytes);
......@@ -127,7 +133,8 @@ static void show_vma(int fd_vma)
pr_info("\n\t---[VMA areas]---\n");
while (1) {
read_ptr_safe(fd_vma, &ve, out);
if (read_img(fd_vma, &ve) < 0)
break;
if (final_vma_entry(&ve))
break;
......@@ -136,8 +143,6 @@ static void show_vma(int fd_vma)
vma_area.vma = ve;
pr_info_vma(&vma_area);
}
out:
; /* to placate gcc */
}
static void show_pages(int fd_pages, bool show_content)
......@@ -150,7 +155,8 @@ static void show_pages(int fd_pages, bool show_content)
unsigned long addr;
int i, j;
read_ptr_safe(fd_pages, &e, out);
if (read_img(fd_pages, &e) < 0)
break;
if (final_page_entry(&e))
break;
......@@ -181,7 +187,8 @@ static void show_pages(int fd_pages, bool show_content)
pr_info("\t");
for (i = 0; i < DEF_PAGES_PER_LINE; i++) {
read_ptr_safe(fd_pages, &e, out);
if (read_img(fd_pages, &e) < 0)
goto out;
if (final_page_entry(&e)) {
pr_info("\n");
goto out;
......@@ -203,8 +210,10 @@ static void show_sigacts(int fd_sigacts)
pr_img_head(CR_FD_SIGACT);
while (1) {
int ret = read_ptr_safe_eof(fd_sigacts, &e, out);
if (!ret)
int ret;
ret = read_img_eof(fd_sigacts, &e);
if (ret <= 0)
goto out;
pr_info("sigaction: %016lx mask: %08lx "
"flags: %016lx restorer: %016lx\n",
......@@ -229,8 +238,8 @@ static int show_pstree(int fd_pstree, struct list_head *collect)
int ret;
struct pstree_item *item = NULL;
ret = read_ptr_safe_eof(fd_pstree, &e, out);
if (!ret)
ret = read_img_eof(fd_pstree, &e);
if (ret <= 0)
goto out;
pr_info("pid: %8d nr_children: %8d nr_threads: %8d\n",
e.pid, e.nr_children, e.nr_threads);
......@@ -255,8 +264,8 @@ static int show_pstree(int fd_pstree, struct list_head *collect)
pr_info("\\\n");
pr_info(" +--- children: ");
while (e.nr_children--) {
ret = read_ptr_safe_eof(fd_pstree, &pid, out);
if (!ret)
ret = read_img_eof(fd_pstree, &pid);
if (ret <= 0)
goto out;
pr_info(" %6d", pid);
}
......@@ -267,8 +276,8 @@ static int show_pstree(int fd_pstree, struct list_head *collect)
pr_info(" \\\n");
pr_info(" --- threads: ");
while (e.nr_threads--) {
ret = read_ptr_safe_eof(fd_pstree, &pid, out);
if (!ret)
ret = read_img_eof(fd_pstree, &pid);
if (ret <= 0)
goto out;
pr_info(" %6d", pid);
if (item)
......@@ -294,7 +303,8 @@ static void show_core_regs(int fd_core)
lseek(fd_core, GET_FILE_OFF(struct core_entry, arch.gpregs), SEEK_SET);
read_ptr_safe(fd_core, &regs, err);
if (read_img(fd_core, &regs) < 0)
goto err;
pr_regs4(regs, cs, ip, ds, es);
pr_regs4(regs, ss, sp, fs, gs);
......@@ -311,49 +321,23 @@ err:
static void show_core_rest(int fd_core)
{
u64 mm_start_data, mm_end_data, mm_start_stack, mm_start_brk;
u64 mm_brk, mm_start_code, mm_end_code;
char comm[TASK_COMM_LEN];
u32 personality;
struct task_core_entry tc;
int i;
lseek(fd_core, GET_FILE_OFF(struct core_entry, tc.personality), SEEK_SET);
read_ptr_safe(fd_core, &personality, err);
lseek(fd_core, GET_FILE_OFF(struct core_entry, tc.comm), SEEK_SET);
read_safe(fd_core, comm, TASK_COMM_LEN, err);
lseek(fd_core, GET_FILE_OFF(struct core_entry, tc.mm_brk), SEEK_SET);
read_ptr_safe(fd_core, &mm_brk, err);
lseek(fd_core, GET_FILE_OFF(struct core_entry, tc.mm_start_code), SEEK_SET);
read_ptr_safe(fd_core, &mm_start_code, err);
lseek(fd_core, GET_FILE_OFF(struct core_entry, tc.mm_end_code), SEEK_SET);
read_ptr_safe(fd_core, &mm_end_code, err);
lseek(fd_core, GET_FILE_OFF(struct core_entry, tc.mm_start_stack), SEEK_SET);
read_ptr_safe(fd_core, &mm_start_stack, err);
lseek(fd_core, GET_FILE_OFF(struct core_entry, tc.mm_start_data), SEEK_SET);
read_ptr_safe(fd_core, &mm_start_data, err);
lseek(fd_core, GET_FILE_OFF(struct core_entry, tc.mm_end_data), SEEK_SET);
read_ptr_safe(fd_core, &mm_end_data, err);
lseek(fd_core, GET_FILE_OFF(struct core_entry, tc.mm_start_brk), SEEK_SET);
read_ptr_safe(fd_core, &mm_start_brk, err);
lseek(fd_core, GET_FILE_OFF(struct core_entry, tc), SEEK_SET);
if (read_img(fd_core, &tc) < 0)
goto err;
pr_info("\n\t---[Task parameters]---\n");
pr_info("\tPersonality: %x\n", personality);
pr_info("\tCommand: %s\n", comm);
pr_info("\tBrk: %lx\n", mm_brk);
pr_info("\tStart code: %lx\n", mm_start_code);
pr_info("\tEnd code: %lx\n", mm_end_code);
pr_info("\tStart stack: %lx\n", mm_start_stack);
pr_info("\tStart data: %lx\n", mm_start_data);
pr_info("\tEnd data: %lx\n", mm_end_data);
pr_info("\tStart brk: %lx\n", mm_start_brk);
pr_info("\tPersonality: %x\n", tc.personality);
pr_info("\tCommand: %s\n", tc.comm);
pr_info("\tBrk: %lx\n", tc.mm_brk);
pr_info("\tStart code: %lx\n", tc.mm_start_code);
pr_info("\tEnd code: %lx\n", tc.mm_end_code);
pr_info("\tStart stack: %lx\n", tc.mm_start_stack);
pr_info("\tStart data: %lx\n", tc.mm_start_data);
pr_info("\tEnd data: %lx\n", tc.mm_end_data);
pr_info("\tStart brk: %lx\n", tc.mm_start_brk);
pr_info("\n");
err:
......@@ -410,7 +394,8 @@ static int cr_parse_file(struct cr_options *opts)
goto err;
}
read_ptr_safe(fd, &magic, err);
if (read_img(fd, &magic) < 0)
goto err;
switch (magic) {
case FDINFO_MAGIC:
......
......@@ -142,7 +142,9 @@ struct cr_fdset *cr_fdset_open(int pid, unsigned long use_mask, struct cr_fdset
}
pr_debug("Opened %s with %d\n", path, ret);
write_ptr_safe(ret, &fdset_template[i].magic, err);
if (write_img(ret, &fdset_template[i].magic))
goto err;
cr_fdset->fds[i] = ret;
}
err:
......@@ -177,7 +179,8 @@ struct cr_fdset *prep_cr_fdset_for_restore(int pid, unsigned long use_mask)
}
pr_debug("Opened %s with %d\n", path, ret);
read_ptr_safe(ret, &magic, err);
if (read_img(ret, &magic) < 0)
goto err;
if (magic != fdset_template[i].magic) {
close(ret);
pr_err("Magic doesn't match for %s\n", path);
......
......@@ -603,7 +603,8 @@ int try_fixup_file_map(int pid, struct vma_entry *vma_entry, int fd)
lseek(fd, -sizeof(*vma_entry), SEEK_CUR);
vma_entry->fd = fmap_fd->fd;
write_ptr_safe(fd, vma_entry, err);
if (write_img(fd, vma_entry))
goto err;
free(fmap_fd);
}
......
......@@ -8,6 +8,7 @@
#include <stdlib.h>
#include <signal.h>
#include <stdio.h>
#include <errno.h>
#include <sys/types.h>
#include <dirent.h>
......@@ -116,40 +117,73 @@ extern void printk(const char *format, ...);
#define BUG_ON(condition) BUG_ON_HANDLER((condition))
#define write_ptr(fd, ptr) \
write(fd, (ptr), sizeof(*(ptr)))
#define write_ptr_safe(fd, ptr, err) \
jerr(write_ptr(fd, ptr) != sizeof(*(ptr)), err)
#define write_safe(fd, ptr, size, err) \
jerr(write(fd, (ptr), (size)) != (size), err)
/*
* Write buffer @ptr of @size bytes into @fd file
* Returns
* 0 on success
* -1 on error (error message is printed)
*/
static inline int write_img_buf(int fd, void *ptr, int size)
{
int ret;
ret = write(fd, ptr, size);
if (ret == size)
return 0;
if (ret < 0)
pr_perror("Can't write img file\n");
else
pr_err("Img trimmed %d/%d\n", ret, size);
return -1;
}
#define write_img(fd, ptr) write_img_buf((fd), (ptr), sizeof(*(ptr)))
#define write_safe_imm(fd, imm, err) \
do { \
typeof(imm) x__ = imm; \
write_ptr_safe(fd, &x__, err); \
} while (0)
/*
* Read buffer @ptr of @size bytes from @fd file
* Returns
* 1 on success
* 0 on EOF (silently)
* -1 on error (error message is printed)
*/
static inline int read_img_buf_eof(int fd, void *ptr, int size)
{
int ret;
ret = read(fd, ptr, size);
if (ret == size)
return 1;
if (ret == 0)
return 0;
if (ret < 0)
pr_perror("Can't read img file\n");
else
pr_err("Img trimmed %d/%d\n", ret, size);
return -1;
}
#define read_img_eof(fd, ptr) read_img_buf_eof((fd), (ptr), sizeof(*(ptr)))
#define read_safe(fd, ptr, size, err) \
jerr(read(fd, ptr, (size)) != (size), err)
/*
* Read buffer @ptr of @size bytes from @fd file
* Returns
* 1 on success
* -1 on error or EOF (error message is printed)
*/
static inline int read_img_buf(int fd, void *ptr, int size)
{
int ret;
#define read_ptr_safe(fd, ptr, err) \
jerr(read(fd, ptr, sizeof(*(ptr))) != sizeof(*(ptr)), err)
ret = read_img_buf_eof(fd, ptr, size);
if (ret == 0) {
pr_err("Unexpected EOF\n");
ret = -1;
}
#define read_safe_eof(fd, ptr, size, err) \
({ \
size_t rc__ = read(fd, ptr, (size)); \
if (rc__ && rc__ != (size)) { \
pr_err("img corruption %d/%d\n", \
rc__, (size)); \
goto err; \
} \
rc__; \
})
return ret;
}
#define read_ptr_safe_eof(fd, ptr, err) \
read_safe_eof(fd, ptr, sizeof(*(ptr)), err)
#define read_img(fd, ptr) read_img_buf((fd), (ptr), sizeof(*(ptr)))
#define memzero_p(p) memset(p, 0, sizeof(*p))
#define memzero(p, size) memset(p, 0, size)
......
......@@ -2,6 +2,7 @@
#include <sys/socket.h>
#include <linux/netlink.h>
#include <string.h>
#include <unistd.h>
#include "libnetlink.h"
#include "util.h"
......
......@@ -472,7 +472,8 @@ int parasite_dump_pages_seized(struct parasite_ctl *ctl, struct list_head *vma_a
lseek(cr_fdset->fds[CR_FD_PAGES], 0, SEEK_END);
/* Ending page */
write_ptr_safe(cr_fdset->fds[CR_FD_PAGES], &zero_page_entry, err_restore);
if (write_img(cr_fdset->fds[CR_FD_PAGES], &zero_page_entry))
goto err_restore;
pr_info("\n");
pr_info("Summary: %16li pages dumped\n", nrpages_dumped);
......
......@@ -187,7 +187,8 @@ static int dump_one_inet(struct socket_desc *_sk, int fd, struct cr_fdset *cr_fd
ie.backlog = sk->wqlen;
memcpy(ie.src_addr, sk->src_addr, sizeof(u32) * 4);
write_ptr_safe(cr_fdset->fds[CR_FD_INETSK], &ie, err);
if (write_img(cr_fdset->fds[CR_FD_INETSK], &ie))
goto err;
pr_info("Dumping inet socket at %d\n", fd);
show_one_inet("Dumping", sk);
......@@ -270,8 +271,10 @@ static int dump_one_unix(struct socket_desc *_sk, int fd, struct cr_fdset *cr_fd
ue.pad = 0;
ue.peer = sk->peer_ino;
write_ptr_safe(cr_fdset->fds[CR_FD_UNIXSK], &ue, err);
write_safe(cr_fdset->fds[CR_FD_UNIXSK], sk->name, ue.namelen, err);
if (write_img(cr_fdset->fds[CR_FD_UNIXSK], &ue))
goto err;
if (write_img_buf(cr_fdset->fds[CR_FD_UNIXSK], sk->name, ue.namelen))
goto err;
pr_info("Dumping unix socket at %d\n", fd);
show_one_unix("Dumping", sk);
......@@ -941,8 +944,8 @@ static int prepare_unix_sockets(int pid)
while (1) {
struct unix_sk_entry ue;
ret = read_ptr_safe_eof(usk_fd, &ue, err);
if (ret == 0)
ret = read_img_eof(usk_fd, &ue);
if (ret <= 0)
break;
ret = open_unix_sk(&ue, &usk_fd);
......@@ -1025,8 +1028,8 @@ static int prepare_inet_sockets(int pid)
while (1) {
struct inet_sk_entry ie;
ret = read_ptr_safe_eof(isk_fd, &ie, err);
if (ret == 0)
ret = read_img_eof(isk_fd, &ie);
if (ret <= 0)
break;
ret = open_inet_sk(&ie, &isk_fd);
......@@ -1059,8 +1062,8 @@ void show_inetsk(int fd)
while (1) {
char src_addr[INET_ADDR_LEN] = "<unknown>";
ret = read_ptr_safe_eof(fd, &ie, out);
if (!ret)
ret = read_img_eof(fd, &ie);
if (ret <= 0)
goto out;
if (inet_ntop(AF_INET, (void *)ie.src_addr, src_addr,
......@@ -1087,27 +1090,26 @@ void show_unixsk(int fd)
pr_img_head(CR_FD_UNIXSK);
while (1) {
ret = read_ptr_safe_eof(fd, &ue, out);
if (!ret)
ret = read_img_eof(fd, &ue);
if (ret <= 0)
goto out;
pr_info("fd %4d type %2d state %2d namelen %4d backlog %4d id %6d peer %6d",
ue.fd, ue.type, ue.state, ue.namelen, ue.namelen, ue.id, ue.peer);
if (ue.namelen) {
ret = read_safe_eof(fd, buf, ue.namelen, out);
if (!ret)
ret = read_img_buf(fd, buf, ue.namelen);
if (ret < 0) {
pr_info("\n");
goto out;
}
if (!buf[0])
buf[0] = '@';
pr_info(" --> %s\n", buf);
} else
pr_info("\n");
}
out:
if (ret)
pr_info("\n");
pr_img_tail(CR_FD_UNIXSK);
}
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