WARNING - OLD ARCHIVES

This is an archived copy of the Xen.org mailing list, which we have preserved to ensure that existing links to archives are not broken. The live archive, which contains the latest emails, can be found at http://lists.xen.org/
   
 
 
Xen 
 
Home Products Support Community News
 
   
 

xen-devel

[Xen-devel] [PATCH] - xc_core.c/xenctrl.h - refactor slightly to allow u

To: xen-devel@xxxxxxxxxxxxxxxxxxx
Subject: [Xen-devel] [PATCH] - xc_core.c/xenctrl.h - refactor slightly to allow user specified output routines
From: Ben Thomas <bthomas@xxxxxxxxxxxxxxx>
Date: Fri, 10 Mar 2006 17:06:24 -0500
Delivery-date: Fri, 10 Mar 2006 22:07:20 +0000
Envelope-to: www-data@xxxxxxxxxxxxxxxxxxx
List-help: <mailto:xen-devel-request@lists.xensource.com?subject=help>
List-id: Xen developer discussion <xen-devel.lists.xensource.com>
List-post: <mailto:xen-devel@lists.xensource.com>
List-subscribe: <http://lists.xensource.com/cgi-bin/mailman/listinfo/xen-devel>, <mailto:xen-devel-request@lists.xensource.com?subject=subscribe>
List-unsubscribe: <http://lists.xensource.com/cgi-bin/mailman/listinfo/xen-devel>, <mailto:xen-devel-request@lists.xensource.com?subject=unsubscribe>
Sender: xen-devel-bounces@xxxxxxxxxxxxxxxxxxx
User-agent: Mozilla Thunderbird 1.0.7-1.1.fc4 (X11/20050929)
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_dumpcore2 (naming
isn't always my strong suit), 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).

I've also included a small test routine, testdump.c, which drives
both APIs and allows writing core to either a local disk file or
across a network.  And, I've included a sample network "catcher"
program that receives a cross-network dump from testdump.

And, good news, this probably ends my current hacking/interest
in xc_domain_dumpcore.


Signed-off-by: Ben Thomas (bthomas@xxxxxxxxxxxxxxx)

--
------------------------------------------------------------------------
Ben Thomas                                         Virtual Iron Software
bthomas@xxxxxxxxxxxxxxx                            Tower 1, Floor 2
978-849-1214                                       900 Chelmsford Street
                                                   Lowell, MA 01851
diff -r 3ea1c6118fc2 tools/libxc/xc_core.c
--- a/tools/libxc/xc_core.c     Fri Mar 10 01:08:59 2006 +0100
+++ b/tools/libxc/xc_core.c     Fri Mar 10 16:58:15 2006 -0500
@@ -8,6 +8,14 @@
 /* number of pages to write at a time */
 #define DUMP_INCREMENT (4 * 1024)
 #define round_pgup(_p)    (((_p)+(PAGE_SIZE-1))&PAGE_MASK)
+
+/* Define the local structure for local_fd_dump.
+ * A structure is overkill, but someone may use this as an example
+ */
+
+typedef struct dump_args_s {
+    int     fd;
+} dump_args_t;
 
 static int
 copy_from_domain_page(int xc_handle,
@@ -26,24 +34,21 @@ copy_from_domain_page(int xc_handle,
 }
 
 int 
-xc_domain_dumpcore(int xc_handle,
-                   uint32_t domid,
-                   const char *corename)
+xc_domain_dumpcore2(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];
+    unsigned 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) {
         PERROR("Could not allocate dump_mem");
         goto error_out;
@@ -61,27 +66,29 @@ xc_domain_dumpcore(int xc_handle,
 
     for (i = 0; i <= info.max_vcpu_id; i++)
         if (xc_vcpu_getcontext(xc_handle, domid,
-                               i, &ctxt[nr_vcpus]) == 0)
+                                       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, &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, &ctxt, sizeof(ctxt[0]) * nr_vcpus);
+    if (sts != 0)
+        return sts;
 
     if ((page_array = malloc(nr_pages * sizeof(unsigned long))) == NULL) {
         printf("Could not allocate memory\n");
@@ -91,18 +98,21 @@ xc_domain_dumpcore(int xc_handle,
         printf("Could not get the page frame list\n");
         goto error_out;
     }
-    if (write(dump_fd, page_array, nr_pages * sizeof(unsigned long)) < 0)
-    {
-        PERROR("write failed");
-        goto error_out;
-    }
-    lseek(dump_fd, header.xch_pages_offset, SEEK_SET);
+    sts = dump_rtn(args, page_array, nr_pages * sizeof(unsigned long));
+    if (sts != 0)
+        return sts;
+
+    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++) {
         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) {
+            sts = dump_rtn(args, dump_mem_start, dump_mem - dump_mem_start);
+            if (sts != 0) {
                 PERROR("Partial write, file system full?");
                 goto error_out;
             }
@@ -110,14 +120,59 @@ xc_domain_dumpcore(int xc_handle,
         }
     }
 
-    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 routine for writing to a local dump file */
+
+static int local_file_dump(void *args, void *buffer, int length)
+{
+    dump_args_t *da = args;
+    int bytes;
+    int offset;
+    unsigned char *buf = buffer;
+    
+
+    if ( (args == NULL) || (buffer == NULL) || (length < 0) )
+        return -EINVAL;
+
+    /* This is to a local disk, so in practice a simple single "write" */
+    /* would also work just as well as this loop which probably only */
+    /* executes for 1 iteration anyhow */
+
+    offset = 0;
+    while (offset < length) {
+        bytes = write(da->fd, &buf[offset], length-offset);
+        if (bytes <= 0) {
+            PERROR("Failed to write buffer: %s", strerror(errno));
+            return -errno;
+        }
+        offset += bytes;
+    }
+    return 0;
+}
+
+int 
+xc_domain_dumpcore(int xc_handle,
+                   uint32_t domid,
+                   const char *corename)
+{
+    dump_args_t 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_dumpcore2(xc_handle, domid, &da, &local_file_dump);
+    close(da.fd);
+
+    return sts;
 }
 
 /*
diff -r 3ea1c6118fc2 tools/libxc/xenctrl.h
--- a/tools/libxc/xenctrl.h     Fri Mar 10 01:08:59 2006 +0100
+++ b/tools/libxc/xenctrl.h     Fri Mar 10 16:58:15 2006 -0500
@@ -139,9 +139,28 @@ int xc_domain_create(int xc_handle,
                      uint32_t *pdomid);
 
 
+/* Functions to produce a dump of a given domain
+ *  xc_domain_dumpcore - produces a dump to a specified file
+ *  xc_domain_dumpcore2 - produces a dump, using a specified callback
+ */
+
 int xc_domain_dumpcore(int xc_handle, 
                        uint32_t domid,
                        const char *corename);
+
+/* Define the callback function type for xc_domain_dumpcore2
+ *
+ * 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_dumpcore2
+ */
+
+typedef int (dumpcore_rtn_t)(void *arg, void *buffer, int length);
+
+int xc_domain_dumpcore2(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.
// Copyright (c) 2006,  Virtual Iron Software, Inc.
// All Rights Reserved

// Sample program to catch network dumps

#include <sys/types.h>
#include <ctype.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <poll.h>
#include <unistd.h>
#include <fcntl.h>

#include <xenctrl.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>

#define DUMP_PORT 778

// Definitions and typedefs

typedef struct sockaddr SA_t;
typedef struct sockaddr_in SIN_t;

static int verbose = 0;

/* create_listen_socket - create socket for new connections
 *
 * Input:
 *      port    port number desired
 *
 * Output:
 *      none
 *
 * Returns:
 *      socket number or -1 on error
 */

static int create_listen_socket(port) {
  SIN_t         listenAddr;
  int           listenSock;
  int           sts;

  listenSock = socket(AF_INET, SOCK_STREAM, 0);
  if (listenSock < 0) {
    fprintf(stderr, "? %s: Unable to create listen socket, errno %d (%s)\n",
                __FUNCTION__, errno, strerror(errno));
    return -errno;
  }

  bzero(&listenAddr, sizeof(listenAddr));
  listenAddr.sin_family = AF_INET;
  listenAddr.sin_addr.s_addr = htonl(INADDR_ANY);
  listenAddr.sin_port = htons(port);
  if (verbose)
    fprintf(stdout, "[Listening on port %d]\n", port);

  sts = bind(listenSock, (SA_t *)&listenAddr, sizeof(listenAddr));
  if (sts < 0) {
    fprintf(stderr, "? %s: Bind failed, errno %d (%s)\n",
                __FUNCTION__, errno, strerror(errno));
    return -errno;
  }

  sts = listen(listenSock, SOMAXCONN);
  if (sts < 0) {
    fprintf(stderr, "? %s: Listen failed, errno %d (%s)\n",
                __FUNCTION__, errno, strerror(errno));
    return -errno;
  }

  return listenSock;
}

/* process_dump - process a dump
 *
 * Input:
 *      sockFD  socket to read from
 *      fileFD  file to write to
 *
 * Output:
 *      none
 *
 * Returns:
 *      status
 */

static int process_dump(int sockFD, int fileFD) {
  int           bytes;
  struct xc_core_header core;
  unsigned char *buffer;
  int           bufferSize;
  int           fileBytes;
  long          totalSize;
  long          last;
  int           linepos;

  // Get the initial header

  totalSize = 0;
  bytes = read(sockFD, &core, sizeof(core));
  if (bytes < 0) {
    fprintf(stderr, "? %s: failed to read from socket, errno %d (%s)\n",
                __FUNCTION__, errno, strerror(errno));
    return errno;
  }
  if (bytes != sizeof(core)) {
    fprintf(stderr, "? %s: failed to read enough bytes from socket, got %d 
expected %lu\n",
                __FUNCTION__, bytes, sizeof(core));
    return EINVAL;
  }

  if (verbose) {
    fprintf(stdout, "New header: Magic 0x%x, VCPUs %d, Pages %d\n",
            core.xch_magic,core.xch_nr_vcpus, core.xch_nr_pages);
    fprintf(stdout, "    CTXT offset 0x%x   Index offset 0x%x   Pages Offset 
0x%x\n",
            core.xch_ctxt_offset, core.xch_index_offset, core.xch_pages_offset);
  }

  // Now, start reading the rest of the dump info

  bufferSize = 32 * 1024;
  buffer = malloc(bufferSize);
  if (buffer == NULL) {
    fprintf(stderr, "? %s: failed to allocate input buffer\n", __FUNCTION__);
    return ENOMEM;
  }

  fileBytes = write(fileFD, &core, bytes);
  if (fileBytes < 0) {
    fprintf(stderr, "? %s: failed to write to file, errno %d (%s)\n",
                __FUNCTION__, errno, strerror(errno));
    return errno;
  }
  totalSize += fileBytes;

  linepos = 0;
  last = totalSize;

  while (1) {
    bytes = read(sockFD, buffer, bufferSize);
    if (bytes < 0) {
      fprintf(stderr, "? %s: failed to read from socket, errno %d (%s)\n",
                  __FUNCTION__, errno, strerror(errno));
      return errno;
    } else if (bytes == 0) {
      break;
    }

    fileBytes = write(fileFD, buffer, bytes);
    if (fileBytes < 0) {
      fprintf(stderr, "? %s: failed to write to file, errno %d (%s)\n",
                  __FUNCTION__, errno, strerror(errno));
      return errno;
    }
    totalSize += fileBytes;
    if (verbose) {
      if (totalSize-last > (1024*1024)) {
        fprintf(stdout, "!");
        linepos++;
        if ( (linepos % 64) == 0)
          fprintf(stdout, "\n");
        fflush(stdout);
        last = totalSize;
      }
    }
  }

  if (verbose)
    fprintf(stdout, "\n");

  fprintf(stdout, "[Wrote %ld bytes]\n", totalSize);

  return 0;
}

/* show_usage - output program usage infomration
 *
 * Input:
 *      none
 *
 * Output:
 *      none
 *
 * Returns:
 *      status          0 for success
 */

static void show_usage(void) {

  fprintf(stdout, "Usage: dump [options]\n");
  fprintf(stdout, "       -p:<port>   port number on which to listen (778 is 
the default)\n");
  fprintf(stdout, "       -f:<name>   dump filename prefix\n");
  fprintf(stdout, "       -v          be more verbose\n");
  return;
}

/* main - main routine for config
 *
 * Input:
 *      argc            size of argv vector
 *      argv            ASCII arguments from command line
 *
 * Output:
 *      none
 *
 * Returns:
 *      status          0 for success
 */

int main(int argc, char *argv[]) {
  SIN_t         connAddr;
  socklen_t     connAddrLen;
  int           listenSock;
  int           sts;
  int           newSock;
  struct pollfd pf;
  char          ch;
  int           port;
  int           fileFD;
  char          fileName[128];
  char          hostName[32];
  const char    *csts;
  char          *prefix;

  port = 778;
  prefix = strdup("DUMP");

  while ((ch = getopt(argc, argv, "f:hp:v")) != -1) {
    switch(ch) {

      case 'f':
        free(prefix);
        prefix = strdup(optarg);
        break;

      case 'h':
        show_usage();
        return 0;

      case 'p':
        port = atol(optarg);
        break;

      case 'v':
        verbose++;
        break;

      default:
        fprintf(stderr, "? Unknown argument '%c'\n", ch);
        show_usage();
        return 0;
    }
  }

  argc -= optind;
  if (argc != 0) {
    fprintf(stderr, "? Unknown arguments\n");
    show_usage();
    return 0;
  }
    
  listenSock = create_listen_socket(port);
  if (listenSock < 0)
    return -1;

  // Loop awaiting commands

  while (1) {
    newSock = accept(listenSock, (SA_t *)&connAddr, &connAddrLen);
    if (newSock < 0) {
      fprintf(stderr, "? %s: Accept failed, errno %d (%s), pf.revents 0x%x\n",
             __FUNCTION__, errno, strerror(errno), pf.revents);
      continue;
    }
    
    csts = inet_ntop(AF_INET, &connAddr.sin_addr, hostName, sizeof(hostName));
    if (csts == NULL) {
      fprintf(stderr, "? %s: inet_ntop failed, errno %d (%s)\n",
              __FUNCTION__, errno, strerror(errno));
      strcpy(hostName, "Unknown");
    }

    strcpy(fileName, prefix);
    strcat(fileName, hostName);
    fileFD = creat(fileName, 0x666);
    if (fileFD < 0) {
      fprintf(stderr, "? %s: failed to open dump file '%s', errno %d (%s)\n",
             __FUNCTION__, fileName, errno, strerror(errno));
      close(newSock);
      return errno;
    }

    fprintf(stdout, "[Starting new dump from '%s' into '%s']\n",
            hostName, fileName);
    sts = process_dump(newSock, fileFD);

    free(prefix);
    close(newSock);
    close(fileFD);
  }

  return 0;
}

/*
 * Local variables:
 * mode: C
 * c-set-style: "BSD"
 * c-basic-offset: 2
 * tab-width: 8
 * indent-tabs-mode: t
 * End:
 */
// Copyright (c) 2006,  Virtual Iron Software, Inc.
// All Rights Reserved

// Sample program to generate dumps

#include <stdio.h>
#include <stdlib.h>
#include <xenctrl.h>
#include <netinet/in.h>
#include <sys/poll.h>
#include <string.h>
#include <netdb.h>
#include <errno.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>

typedef struct sockaddr SA_t;
typedef struct sockaddr_in SIN_t;

// Opaque local structure for dumpcore

typedef struct dump_args_s {
  int   fd;
  long  total;
  long  last;
  int   linepos;
} dump_args_t;

static int verbose = 0;

/* net_dump - dumpcore callback routine for network connection
 *
 * Input:
 *      args    dump_args private data pointer
 *      buffer  pointer to buffer to be written
 *      length  length of buffer
 *
 * Output:
 *      none
 *
 * Returns:
 *      status
 */

static int net_dump(void *args, void *buffer, int length) {
  dump_args_t *da = args;
  int           bytes;
  int           offset;
  unsigned char *buf = buffer;
  int           max;
  int           linepos;

  if ( (args == NULL) || (buffer == NULL) || (length < 0) )
    return -EINVAL;

  offset = 0;
  linepos = 0;

  while (offset < length) {
    max = (length-offset > 2048) ? 2048 : length-offset;
    bytes = write(da->fd, &buf[offset], max);
    if (bytes < 0) {
      fprintf(stderr, "? %s: Failed to write buffer, errno %d (%s)\n",
              __FUNCTION__, errno, strerror(errno));
      return -errno;
    }

    // Currently, ignore the 0 bytes case of a full buffer. It doesn't
    // appear to be happening in my testing.  If needed, one other
    // approach might be:  if (bytes==0) sleep(1);

    offset += bytes;
    da->total += bytes;

    if ( (da->total - da->last) > (1024*1024)) {
      if (verbose) {
        fprintf(stdout, "#");
        da->linepos++;
        if ((da->linepos % 64) == 0)
          fprintf(stdout, "\n");
        fflush(stdout);
      }
      da->last = da->total;
    }
  }

  return 0;
}

/* connect_net_dump - form connection to dump catcher on network
 *
 * Input:
 *      host    host name in addr:port format
 *
 * Output:
 *      none
 *
 * Returns:
 *      status
 */

static int connect_net_dump(char *host) {
  int                   cmdSock;
  SIN_t                 cmdAddr;
  int                   sts;
  char                  *portString;
  int                   port;
  char                  *destString;

  // Check input

  if (host == NULL) {
    fprintf(stderr, "? %s: host name required\n", __FUNCTION__);
    return -EINVAL;
  }

  // Get host and port

  destString = strdup(host);
  portString = strchr(destString, ':');
  if (portString != NULL) {
    *portString = '\0';
    portString++;
    port = strtol(portString, NULL, 10);
  } else
    port = 778;

  bzero(&cmdAddr, sizeof(cmdAddr));
  cmdAddr.sin_family = AF_INET;
  cmdAddr.sin_port = htons(port);

  sts = inet_pton(AF_INET, destString, &cmdAddr.sin_addr.s_addr);
  if (sts <= 0) {
    fprintf(stderr, "? %s: inet_pton failed\n", __FUNCTION__);
    free(destString);
    return -errno;
  }
  if (verbose)
    fprintf(stdout, "%s: Connecting to %s:%d\n",
            __FUNCTION__, destString, port);
  free(destString);

  // Create socket and connect

  cmdSock = socket(AF_INET, SOCK_STREAM, 0);
  if (cmdSock < 0) {
    fprintf(stderr, "? %s: Unable to create listen socket, errno %d(%s)\n",
           __FUNCTION__, errno, strerror(errno));
    return -errno;
  }

  sts = connect(cmdSock, (SA_t *)&cmdAddr, sizeof(cmdAddr));
  if (sts == 0)                         // Return if immediate success
    return cmdSock;
  if (errno != EINPROGRESS) {
    fprintf(stderr, "? %s: Connect failed, errno %d (%s)\n",
            __FUNCTION__, errno, strerror(errno));
    close(cmdSock);
    return -errno;
  }

  return -errno;
}

/* show_usage - output program usage infomration
 *
 * Input:
 *      none
 *
 * Output:
 *      none
 *
 * Returns:
 *      status          0 for success
 */

static void show_usage(void) {

  fprintf(stdout, "Usage: testdump [options]\n");

  fprintf(stdout, "       -d:<domid>     dump domain <domid>\n");
  fprintf(stdout, "       -f:<name>      dump to with file <name>\n");
  fprintf(stdout, "       -h:<host:port> dump to network\n");
  fprintf(stdout, "       -v             be more verbose\n");
  return;
}

int main(int argc, char *argv[]) {
  int   sts;
  dump_args_t   da;
  int   xc_handle;
  int   domid = -1;
  int   fileFlag;
  int   netFlag;
  char  *destName;
  int   ch;

  destName = strdup("");

  while ((ch = getopt(argc, argv, "d:f:h:v")) != -1) {
    switch(ch) {

      case 'd':
        domid = atoi(optarg);
        break;

      case 'f':
        free(destName);
        destName = strdup(optarg);
        fileFlag = 1;
        break;

      case 'h':
        free(destName);
        destName = strdup(optarg);
        netFlag = 1;
        break;

      case 'v':
        verbose = 1;
        break;

      default:
        fprintf(stderr, "? Unknown argument '%c'\n", ch);
        show_usage();
        return 0;
    }
  }

  argc -= optind;
  if (argc != 0) {
    fprintf(stderr, "? Unknown arguments\n");
    show_usage();
    return 0;
  }

  if ( ( (fileFlag == 0) && (netFlag == 0) ) ||
       ( (fileFlag != 0) && (netFlag != 0) ) ) {
    fprintf(stderr, "? Must specify one dump type of either -f<name> or 
-h<ipaddr:port>\n");
    return EINVAL;
  }

  if (domid < 0) {
    fprintf(stderr, "? Must specify domain id with -d\n");
    return EINVAL;
  }

  xc_handle = xc_interface_open();

  if (netFlag) {
    da.fd = connect_net_dump(destName);
    if (da.fd < 0) {
      return -1;
    }

    da.total = 0;
    da.last = 0;
    da.linepos = 0;
    sts = xc_domain_dumpcore2(xc_handle, domid, &da, &net_dump);
    close(da.fd);
  } else {
    sts = xc_domain_dumpcore(xc_handle, domid, destName);
  }
  
  printf("%% %s: xc_dump_domain returned %d\n", __FUNCTION__, sts);

  return 0;
}
_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-devel
<Prev in Thread] Current Thread [Next in Thread>