diff options
author | kaf24@firebug.cl.cam.ac.uk <kaf24@firebug.cl.cam.ac.uk> | 2006-03-13 11:47:56 +0100 |
---|---|---|
committer | kaf24@firebug.cl.cam.ac.uk <kaf24@firebug.cl.cam.ac.uk> | 2006-03-13 11:47:56 +0100 |
commit | 8a68ed87f83749bbc21614176e8ae91677746a6f (patch) | |
tree | 3d5f837846c873df9254909a6ae6b8ea390dc0fa /tools/libxc/xc_core.c | |
parent | a04a7ff5d7bbbc355cdfedfe71a70b5790626d61 (diff) | |
download | xen-8a68ed87f83749bbc21614176e8ae91677746a6f.tar.gz xen-8a68ed87f83749bbc21614176e8ae91677746a6f.tar.bz2 xen-8a68ed87f83749bbc21614176e8ae91677746a6f.zip |
The existing xc_domain_dumpcore is very specific to disk/file based
output. Refactor the code slightly to allow more user-specified
control. This is done by adding a parallel
xc_domain_dumpcore_via_callback, which allows the specification of a
callback routine and an opaque argument block. The existing dumpcore
routine is modified to use the callback for all write operations and
to turn the single seek into a small write (it's for page alignment).
Signed-off-by: Ben Thomas <bthomas@virtualiron.com>
Diffstat (limited to 'tools/libxc/xc_core.c')
-rw-r--r-- | tools/libxc/xc_core.c | 136 |
1 files changed, 94 insertions, 42 deletions
diff --git a/tools/libxc/xc_core.c b/tools/libxc/xc_core.c index 7e198ba891..b5cb742325 100644 --- a/tools/libxc/xc_core.c +++ b/tools/libxc/xc_core.c @@ -26,100 +26,152 @@ copy_from_domain_page(int xc_handle, } int -xc_domain_dumpcore(int xc_handle, - uint32_t domid, - const char *corename) +xc_domain_dumpcore_via_callback(int xc_handle, + uint32_t domid, + void *args, + dumpcore_rtn_t dump_rtn) { unsigned long nr_pages; unsigned long *page_array; xc_dominfo_t info; - int i, nr_vcpus = 0, dump_fd; + int i, nr_vcpus = 0; char *dump_mem, *dump_mem_start = NULL; struct xc_core_header header; vcpu_guest_context_t ctxt[MAX_VIRT_CPUS]; + char dummy[PAGE_SIZE]; + int dummy_len; + int sts; - - if ((dump_fd = open(corename, O_CREAT|O_RDWR, S_IWUSR|S_IRUSR)) < 0) { - PERROR("Could not open corefile %s: %s", corename, strerror(errno)); - goto error_out; - } - - if ((dump_mem_start = malloc(DUMP_INCREMENT*PAGE_SIZE)) == NULL) { + if ( (dump_mem_start = malloc(DUMP_INCREMENT*PAGE_SIZE)) == NULL ) + { PERROR("Could not allocate dump_mem"); goto error_out; } - if (xc_domain_getinfo(xc_handle, domid, 1, &info) != 1) { + if ( xc_domain_getinfo(xc_handle, domid, 1, &info) != 1 ) + { PERROR("Could not get info for domain"); goto error_out; } - if (domid != info.domid) { + if ( domid != info.domid ) + { PERROR("Domain %d does not exist", domid); goto error_out; } - for (i = 0; i <= info.max_vcpu_id; i++) - if (xc_vcpu_getcontext(xc_handle, domid, - i, &ctxt[nr_vcpus]) == 0) + for ( i = 0; i <= info.max_vcpu_id; i++ ) + if ( xc_vcpu_getcontext(xc_handle, domid, i, &ctxt[nr_vcpus]) == 0) nr_vcpus++; nr_pages = info.nr_pages; - header.xch_magic = XC_CORE_MAGIC; + header.xch_magic = XC_CORE_MAGIC; header.xch_nr_vcpus = nr_vcpus; header.xch_nr_pages = nr_pages; header.xch_ctxt_offset = sizeof(struct xc_core_header); header.xch_index_offset = sizeof(struct xc_core_header) + sizeof(vcpu_guest_context_t)*nr_vcpus; - header.xch_pages_offset = round_pgup(sizeof(struct xc_core_header) + - (sizeof(vcpu_guest_context_t) * nr_vcpus) + - (nr_pages * sizeof(unsigned long))); + dummy_len = (sizeof(struct xc_core_header) + + (sizeof(vcpu_guest_context_t) * nr_vcpus) + + (nr_pages * sizeof(unsigned long))); + header.xch_pages_offset = round_pgup(dummy_len); + + sts = dump_rtn(args, (char *)&header, sizeof(struct xc_core_header)); + if ( sts != 0 ) + return sts; - if (write(dump_fd, &header, sizeof(struct xc_core_header)) < 0 || - write(dump_fd, &ctxt, sizeof(ctxt[0]) * nr_vcpus) < 0) - { - PERROR("write failed"); - goto error_out; - } + sts = dump_rtn(args, (char *)&ctxt, sizeof(ctxt[0]) * nr_vcpus); + if ( sts != 0 ) + return sts; - if ((page_array = malloc(nr_pages * sizeof(unsigned long))) == NULL) { + if ( (page_array = malloc(nr_pages * sizeof(unsigned long))) == NULL ) + { printf("Could not allocate memory\n"); goto error_out; } - if (xc_get_pfn_list(xc_handle, domid, page_array, nr_pages) != nr_pages) { + if ( xc_get_pfn_list(xc_handle, domid, page_array, nr_pages) != nr_pages ) + { printf("Could not get the page frame list\n"); goto error_out; } - if (write(dump_fd, page_array, nr_pages * sizeof(unsigned long)) < 0) + sts = dump_rtn(args, (char *)page_array, nr_pages * sizeof(unsigned long)); + if ( sts != 0 ) + return sts; + + /* Pad the output data to page alignment. */ + memset(dummy, 0, PAGE_SIZE); + sts = dump_rtn(args, dummy, header.xch_pages_offset - dummy_len); + if ( sts != 0 ) + return sts; + + for ( dump_mem = dump_mem_start, i = 0; i < nr_pages; i++ ) { - PERROR("write failed"); - goto error_out; - } - lseek(dump_fd, header.xch_pages_offset, SEEK_SET); - for (dump_mem = dump_mem_start, i = 0; i < nr_pages; i++) { copy_from_domain_page(xc_handle, domid, page_array, i, dump_mem); dump_mem += PAGE_SIZE; - if (((i + 1) % DUMP_INCREMENT == 0) || (i + 1) == nr_pages) { - if (write(dump_fd, dump_mem_start, dump_mem - dump_mem_start) < - dump_mem - dump_mem_start) { - PERROR("Partial write, file system full?"); + if ( ((i + 1) % DUMP_INCREMENT == 0) || ((i + 1) == nr_pages) ) + { + sts = dump_rtn(args, dump_mem_start, dump_mem - dump_mem_start); + if ( sts != 0 ) goto error_out; - } dump_mem = dump_mem_start; } } - close(dump_fd); free(dump_mem_start); return 0; + error_out: - if (dump_fd != -1) - close(dump_fd); free(dump_mem_start); return -1; } +/* Callback args for writing to a local dump file. */ +struct dump_args { + int fd; +}; + +/* Callback routine for writing to a local dump file. */ +static int local_file_dump(void *args, char *buffer, unsigned int length) +{ + struct dump_args *da = args; + int bytes, offset; + + for ( offset = 0; offset < length; offset += bytes ) + { + bytes = write(da->fd, &buffer[offset], length-offset); + if ( bytes <= 0 ) + { + PERROR("Failed to write buffer: %s", strerror(errno)); + return -errno; + } + } + + return 0; +} + +int +xc_domain_dumpcore(int xc_handle, + uint32_t domid, + const char *corename) +{ + struct dump_args da; + int sts; + + if ( (da.fd = open(corename, O_CREAT|O_RDWR, S_IWUSR|S_IRUSR)) < 0 ) + { + PERROR("Could not open corefile %s: %s", corename, strerror(errno)); + return -errno; + } + + sts = xc_domain_dumpcore_via_callback( + xc_handle, domid, &da, &local_file_dump); + + close(da.fd); + + return sts; +} + /* * Local variables: * mode: C |