# HG changeset patch
# User kaf24@xxxxxxxxxxxxxxxxxxxx
# Node ID 1439cfa5ee8c1ee5a1d3e6ade3ab0185afc329e7
# Parent 68b4edadd1614f9cae7e1951dd35dc7b52d28d27
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@xxxxxxxxxxxxxxx>
diff -r 68b4edadd161 -r 1439cfa5ee8c tools/libxc/xc_core.c
--- a/tools/libxc/xc_core.c Mon Mar 13 10:10:27 2006
+++ b/tools/libxc/xc_core.c Mon Mar 13 10:47:56 2006
@@ -26,98 +26,150 @@
}
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)
+ 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 )
{
- PERROR("write failed");
- goto error_out;
- }
-
- 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;
}
/*
diff -r 68b4edadd161 -r 1439cfa5ee8c tools/libxc/xenctrl.h
--- a/tools/libxc/xenctrl.h Mon Mar 13 10:10:27 2006
+++ b/tools/libxc/xenctrl.h Mon Mar 13 10:47:56 2006
@@ -139,9 +139,27 @@
uint32_t *pdomid);
+/* Functions to produce a dump of a given domain
+ * xc_domain_dumpcore - produces a dump to a specified file
+ * xc_domain_dumpcore_via_callback - produces a dump, using a specified
+ * callback function
+ */
int xc_domain_dumpcore(int xc_handle,
uint32_t domid,
const char *corename);
+
+/* Define the callback function type for xc_domain_dumpcore_via_callback.
+ *
+ * This function is called by the coredump code for every "write",
+ * and passes an opaque object for the use of the function and
+ * created by the caller of xc_domain_dumpcore_via_callback.
+ */
+typedef int (dumpcore_rtn_t)(void *arg, char *buffer, unsigned int length);
+
+int xc_domain_dumpcore_via_callback(int xc_handle,
+ uint32_t domid,
+ void *arg,
+ dumpcore_rtn_t dump_rtn);
/*
* This function sets the maximum number of vcpus that a domain may create.
@@ -372,13 +390,13 @@
unsigned long nr_extents,
unsigned int extent_order,
unsigned int address_bits,
- unsigned long *extent_start);
+ unsigned long *extent_start);
int xc_domain_memory_decrease_reservation(int xc_handle,
uint32_t domid,
unsigned long nr_extents,
unsigned int extent_order,
- unsigned long *extent_start);
+ unsigned long *extent_start);
int xc_domain_memory_populate_physmap(int xc_handle,
uint32_t domid,
@@ -411,7 +429,7 @@
uint8_t allow_access);
unsigned long xc_make_page_below_4G(int xc_handle, uint32_t domid,
- unsigned long mfn);
+ unsigned long mfn);
typedef dom0_perfc_desc_t xc_perfc_desc_t;
/* IMPORTANT: The caller is responsible for mlock()'ing the @desc array. */
@@ -457,7 +475,7 @@
* @parm virt the virtual address to translate
*/
unsigned long xc_translate_foreign_address(int xc_handle, uint32_t dom,
- int vcpu, unsigned long long virt);
+ int vcpu, unsigned long long virt);
int xc_get_pfn_list(int xc_handle, uint32_t domid, unsigned long *pfn_buf,
unsigned long max_pfns);
@@ -467,7 +485,7 @@
unsigned int start_page, unsigned int nr_pages);
int xc_copy_to_domain_page(int xc_handle, uint32_t domid,
- unsigned long dst_pfn, const char *src_page);
+ unsigned long dst_pfn, const char *src_page);
int xc_clear_domain_page(int xc_handle, uint32_t domid,
unsigned long dst_pfn);
@@ -478,7 +496,7 @@
long xc_get_max_pages(int xc_handle, uint32_t domid);
int xc_mmuext_op(int xc_handle, struct mmuext_op *op, unsigned int nr_ops,
- domid_t dom);
+ domid_t dom);
int xc_memory_op(int xc_handle, int cmd, void *arg);
_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog
|