aboutsummaryrefslogtreecommitdiffstats
path: root/tools/libxc/xc_core.c
diff options
context:
space:
mode:
authorkaf24@firebug.cl.cam.ac.uk <kaf24@firebug.cl.cam.ac.uk>2006-03-13 11:47:56 +0100
committerkaf24@firebug.cl.cam.ac.uk <kaf24@firebug.cl.cam.ac.uk>2006-03-13 11:47:56 +0100
commit8a68ed87f83749bbc21614176e8ae91677746a6f (patch)
tree3d5f837846c873df9254909a6ae6b8ea390dc0fa /tools/libxc/xc_core.c
parenta04a7ff5d7bbbc355cdfedfe71a70b5790626d61 (diff)
downloadxen-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.c136
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