Index: trunk/tools/libxc/xc_core.c
===================================================================
--- trunk/tools/libxc/xc_core.c	(revision 9948)
+++ trunk/tools/libxc/xc_core.c	(working copy)
@@ -1,7 +1,13 @@
 #include "xg_private.h"
 #include <stdlib.h>
 #include <unistd.h>
+#include <fcntl.h>
 
+#ifndef O_DIRECT
+#define O_DIRECT 040000
+#endif
+#define SECTOR_SIZE 512
+
 /* number of pages to write at a time */
 #define DUMP_INCREMENT (4 * 1024)
 #define round_pgup(_p)    (((_p)+(PAGE_SIZE-1))&PAGE_MASK)
@@ -38,7 +44,10 @@
     int dummy_len;
     int sts;
 
-    if ( (dump_mem_start = malloc(DUMP_INCREMENT*PAGE_SIZE)) == NULL )
+    dump_mem_start = mmap(0, PAGE_SIZE*DUMP_INCREMENT, 
+                          PROT_READ|PROT_WRITE, 
+                          MAP_PRIVATE|MAP_ANONYMOUS, 0, 0);
+    if (dump_mem_start == NULL)
     {
         PERROR("Could not allocate dump_mem");
         goto error_out;
@@ -114,13 +123,15 @@
         }
     }
 
-    free(dump_mem_start);
+    munmap(dump_mem_start, PAGE_SIZE*DUMP_INCREMENT);
     free(page_array);
     return 0;
 
  error_out:
-    free(dump_mem_start);
-    free(page_array);
+    if (dump_mem_start)
+        munmap(dump_mem_start, PAGE_SIZE*DUMP_INCREMENT);
+    if (page_array)
+        free(page_array);
     return -1;
 }
 
@@ -130,14 +141,13 @@
 };
 
 /* Callback routine for writing to a local dump file. */
-static int local_file_dump(void *args, char *buffer, unsigned int length)
+static int local_file_dump(int fd, 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);
+        bytes = write(fd, &buffer[offset], length-offset);
         if ( bytes <= 0 )
         {
             PERROR("Failed to write buffer");
@@ -148,6 +158,84 @@
     return 0;
 }
 
+// Callback routine that support O_DIRECT i/o to dump file by converting
+// packed non-sector aligned output to sector aligned output.
+static int
+local_dumppacked_rtn(void *args, char *buffer, size_t length)
+{
+    static char *io_base = NULL;
+    static int   io_len  = 0;
+
+    struct dump_args *da = args;
+    int sts;
+    int remaining;
+    void *p;
+    int i;
+
+    if (io_base == NULL) {
+        // Initialize page aligned buffer to use to accumulate sector sized info
+        io_base = mmap(0, PAGE_SIZE, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, 0, 0);
+
+        if (!io_base) {
+            fprintf(stderr, "Could not allocate sector buffer: %s\n", strerror(errno));
+            return -errno;
+        }
+    }
+
+    // Quick check to see if we can simply write from buffer passed in - this is
+    // OK if:
+    // 1. We dont have any pending writes buffered in our internal buffer
+    // 2. The buffer address is sector aligned
+    // 3. The length is an integral number of sectors
+    if (io_len == 0 &&
+        !((unsigned long)buffer & (SECTOR_SIZE-1)) &&
+        !(length & (SECTOR_SIZE-1))) {
+	    // Yipee! no need to copy - just write
+	    return local_file_dump(da->fd, buffer, length);
+    }
+    else {
+	    remaining = PAGE_SIZE-io_len;
+	    p = (char *)io_base + io_len;
+
+	    // Convert packed to sector aligned and write
+	    while (length) {
+		    // Add as much as possible to buffer
+		    if (length < remaining)
+			    i = length;
+		    else
+			    i = remaining;
+
+		    memcpy(p,buffer,i);
+
+		    buffer += + i;
+		    io_len += i;
+
+		    // write if necessary
+		    if (io_len == PAGE_SIZE) {
+			    sts = local_file_dump(da->fd, io_base, io_len);
+			    if ( sts != 0 )
+				    return sts;
+
+			    remaining = PAGE_SIZE;
+			    p = io_base;
+			    io_len = 0;
+		    }
+
+		    length -= i;
+	    }
+
+	    // Now, write any remainder if it is an integral number of sectors long
+	    if (io_len && !(io_len % SECTOR_SIZE)) {
+		    sts = local_file_dump(da->fd, io_base, io_len);
+		    if (sts != 0)
+			    return sts;
+
+		    io_len = 0;
+	    }
+    }
+    return 0;
+}
+
 int
 xc_domain_dumpcore(int xc_handle,
                    uint32_t domid,
@@ -156,14 +244,14 @@
     struct dump_args da;
     int sts;
 
-    if ( (da.fd = open(corename, O_CREAT|O_RDWR, S_IWUSR|S_IRUSR)) < 0 )
+    if ( (da.fd = open(corename, O_CREAT|O_RDWR|O_DIRECT, S_IWUSR|S_IRUSR)) < 0 )
     {
         PERROR("Could not open corefile %s", corename);
         return -errno;
     }
 
     sts = xc_domain_dumpcore_via_callback(
-        xc_handle, domid, &da, &local_file_dump);
+        xc_handle, domid, &da, &local_dumppacked_rtn);
 
     close(da.fd);
 
