All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] - xc_core.c/xenctrl.h - refactor slightly to allow user specified output routines
@ 2006-03-10 22:06 Ben Thomas
  2006-03-14  8:36 ` NAHieu
  0 siblings, 1 reply; 3+ messages in thread
From: Ben Thomas @ 2006-03-10 22:06 UTC (permalink / raw)
  To: xen-devel

[-- Attachment #1: Type: text/plain, Size: 1237 bytes --]

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@virtualiron.com)

-- 
------------------------------------------------------------------------
Ben Thomas                                         Virtual Iron Software
bthomas@virtualiron.com                            Tower 1, Floor 2
978-849-1214                                       900 Chelmsford Street
                                                    Lowell, MA 01851

[-- Attachment #2: core.patch --]
[-- Type: text/x-patch, Size: 7048 bytes --]

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.

[-- Attachment #3: dump.c --]
[-- Type: text/x-csrc, Size: 6810 bytes --]

// 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:
 */

[-- Attachment #4: testdump.c --]
[-- Type: text/x-csrc, Size: 5562 bytes --]

// 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;
}

[-- Attachment #5: Type: text/plain, Size: 138 bytes --]

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xensource.com
http://lists.xensource.com/xen-devel

^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [PATCH] - xc_core.c/xenctrl.h - refactor slightly to allow user specified output routines
  2006-03-10 22:06 [PATCH] - xc_core.c/xenctrl.h - refactor slightly to allow user specified output routines Ben Thomas
@ 2006-03-14  8:36 ` NAHieu
  2006-03-14  8:59   ` NAHieu
  0 siblings, 1 reply; 3+ messages in thread
From: NAHieu @ 2006-03-14  8:36 UTC (permalink / raw)
  To: Ben Thomas, Keir Fraser; +Cc: xen-devel

It seems that there is a memory leak in xc_domain_dumpcore2 (renamed
to xc_domain_dumpcore_via_callback() by Keir): you failed to
free(page_array) it in the function?


Thanks.
H

On 3/11/06, Ben Thomas <bthomas@virtualiron.com> wrote:
> 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@virtualiron.com)
>
> --
> ------------------------------------------------------------------------
> Ben Thomas                                         Virtual Iron Software
> bthomas@virtualiron.com                            Tower 1, Floor 2
> 978-849-1214                                       900 Chelmsford Street
>                                                     Lowell, MA 01851
>
>
> _______________________________________________
> Xen-devel mailing list
> Xen-devel@lists.xensource.com
> http://lists.xensource.com/xen-devel
>
>
>
>

^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [PATCH] - xc_core.c/xenctrl.h - refactor slightly to allow user specified output routines
  2006-03-14  8:36 ` NAHieu
@ 2006-03-14  8:59   ` NAHieu
  0 siblings, 0 replies; 3+ messages in thread
From: NAHieu @ 2006-03-14  8:59 UTC (permalink / raw)
  To: Ben Thomas, Keir Fraser; +Cc: xen-devel

[-- Attachment #1: Type: text/plain, Size: 2007 bytes --]

This patch fixes the memory leak in xc_domain_dumpcore_via_callback.
It also get rid one parameter of copy_from_domain_page() function.

Thanks.
H

On 3/14/06, NAHieu <nahieu@gmail.com> wrote:
> It seems that there is a memory leak in xc_domain_dumpcore2 (renamed
> to xc_domain_dumpcore_via_callback() by Keir): you failed to
> free(page_array) it in the function?
>
>
> Thanks.
> H
>
> On 3/11/06, Ben Thomas <bthomas@virtualiron.com> wrote:
> > 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@virtualiron.com)
> >
> > --
> > ------------------------------------------------------------------------
> > Ben Thomas                                         Virtual Iron Software
> > bthomas@virtualiron.com                            Tower 1, Floor 2
> > 978-849-1214                                       900 Chelmsford Street
> >                                                     Lowell, MA 01851
> >
> >
> > _______________________________________________
> > Xen-devel mailing list
> > Xen-devel@lists.xensource.com
> > http://lists.xensource.com/xen-devel
> >
> >
> >
> >
>

[-- Attachment #2: dumpcore.patch --]
[-- Type: text/x-patch, Size: 1657 bytes --]

diff -r 36cf47cfea4e tools/libxc/xc_core.c
--- a/tools/libxc/xc_core.c	Mon Mar 13 15:06:58 2006 +0100
+++ b/tools/libxc/xc_core.c	Tue Mar 14 18:00:32 2006 +0900
@@ -12,12 +12,11 @@ static int
 static int
 copy_from_domain_page(int xc_handle,
                       uint32_t domid,
-                      unsigned long *page_array,
-                      unsigned long src_pfn,
+                      unsigned long pfn,
                       void *dst_page)
 {
     void *vaddr = xc_map_foreign_range(
-        xc_handle, domid, PAGE_SIZE, PROT_READ, page_array[src_pfn]);
+        xc_handle, domid, PAGE_SIZE, PROT_READ, pfn);
     if ( vaddr == NULL )
         return -1;
     memcpy(dst_page, vaddr, PAGE_SIZE);
@@ -32,7 +31,7 @@ xc_domain_dumpcore_via_callback(int xc_h
                                 dumpcore_rtn_t dump_rtn)
 {
     unsigned long nr_pages;
-    unsigned long *page_array;
+    unsigned long *page_array = NULL;
     xc_dominfo_t info;
     int i, nr_vcpus = 0;
     char *dump_mem, *dump_mem_start = NULL;
@@ -107,7 +106,7 @@ xc_domain_dumpcore_via_callback(int xc_h
 
     for ( dump_mem = dump_mem_start, i = 0; i < nr_pages; i++ )
     {
-        copy_from_domain_page(xc_handle, domid, page_array, i, dump_mem);
+        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) )
         {
@@ -118,10 +117,12 @@ xc_domain_dumpcore_via_callback(int xc_h
         }
     }
 
+	free(page_array);
     free(dump_mem_start);
     return 0;
 
  error_out:
+	free(page_array);
     free(dump_mem_start);
     return -1;
 }

[-- Attachment #3: Type: text/plain, Size: 138 bytes --]

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xensource.com
http://lists.xensource.com/xen-devel

^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2006-03-14  8:59 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2006-03-10 22:06 [PATCH] - xc_core.c/xenctrl.h - refactor slightly to allow user specified output routines Ben Thomas
2006-03-14  8:36 ` NAHieu
2006-03-14  8:59   ` NAHieu

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.