xen-devel.lists.xenproject.org archive mirror
 help / color / mirror / Atom feed
* [PATCH] seperate xen checkpoint file as three parts(for xen-4.1.2)
@ 2012-12-28  9:26 马磊
  2013-01-05  6:52 ` 马磊
  0 siblings, 1 reply; 8+ messages in thread
From: 马磊 @ 2012-12-28  9:26 UTC (permalink / raw)
  To: xen-devel; +Cc: Ian Campbell


[-- Attachment #1.1: Type: text/plain, Size: 1231 bytes --]

Hi,
    We can seperate the xen checkpoint file as three parts: xl config file,
memory dump file of the virtual machine and qemu state file.
    So I add two xl sub-commands: `xl save2` and `xl restore2`, the final
effect is as follows:


[malei@xentest-4-1 Fri Dec 28 ~/honeypot/xen/xen-4.1.2]$ sudo xl save2
*Usage: xl [-v] save2 [options] <Domain> <CheckpointFile1>
<CheckpointFile2> <CheckpointFile3> [<ConfigFile>]*
*
*
*Save a domain state as three seperated files to restore later.*
*
*
*Options:*
*
*
*-h  Print this help.*
*-c  Leave domain running after creating the snapshot.*

[malei@xentest-4-1 Fri Dec 28 ~/honeypot/xen/xen-4.1.2]$ sudo xl restore2
*Usage: xl [-v] restore2 [options] [<ConfigFile>] <CheckpointFile1>
<CheckpointFile2> <CheckpointFile3>*
*
*
*Restore a domain from a saved state.*
*
*
*Options:*
*
*
*-h  Print this help.*
*-p  Do not unpause domain after restoring it.*
*-e  Do not wait in the background for the death of the domain.*
*-d  Enable debug messages.*
*
*

*Besides, the `vncdisplay` option in xl config file will determine the ID
of the domainU shown in `xl list`, so it's convenient to judge th vm-id
according the xl config file. *
*
*
*For more details, please check the attachment.*

[-- Attachment #1.2: Type: text/html, Size: 1942 bytes --]

[-- Attachment #2: xl-save2-restore2.patch --]
[-- Type: application/octet-stream, Size: 36096 bytes --]

diff --exclude=.svn --exclude='*.rej' --exclude='*.orig' -rpN -U8 xen-4.1.2-a/tools/libxl/libxl.c xen-4.1.2-b/tools/libxl/libxl.c
--- xen-4.1.2-a/tools/libxl/libxl.c	2011-10-21 01:05:42.000000000 +0800
+++ xen-4.1.2-b/tools/libxl/libxl.c	2012-12-28 17:00:03.485662280 +0800
@@ -461,16 +461,30 @@ int libxl_domain_suspend(libxl_ctx *ctx,
     int rc = 0;
 
     rc = libxl__domain_suspend_common(ctx, domid, fd, hvm, live, debug);
     if (!rc && hvm)
         rc = libxl__domain_save_device_model(ctx, domid, fd);
     return rc;
 }
 
+int libxl_domain_suspend2(libxl_ctx *ctx, libxl_domain_suspend_info *info,
+                         uint32_t domid, int fd2, int fd3)
+{
+    int hvm = libxl__domain_is_hvm(ctx, domid);
+    int live = info != NULL && info->flags & XL_SUSPEND_LIVE;
+    int debug = info != NULL && info->flags & XL_SUSPEND_DEBUG;
+    int rc = 0;
+
+    rc = libxl__domain_suspend_common(ctx, domid, fd2, hvm, live, debug);
+    if (!rc && hvm)
+      rc = libxl__domain_save_device_model2(ctx, domid, fd2, fd3);
+    return rc;
+}
+
 int libxl_domain_pause(libxl_ctx *ctx, uint32_t domid)
 {
     int ret;
     ret = xc_domain_pause(ctx->xch, domid);
     if (ret<0) {
         LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR, "pausing domain %d", domid);
         return ERROR_FAIL;
     }
diff --exclude=.svn --exclude='*.rej' --exclude='*.orig' -rpN -U8 xen-4.1.2-a/tools/libxl/libxl_create.c xen-4.1.2-b/tools/libxl/libxl_create.c
--- xen-4.1.2-a/tools/libxl/libxl_create.c	2011-10-21 01:05:42.000000000 +0800
+++ xen-4.1.2-b/tools/libxl/libxl_create.c	2012-12-28 17:00:45.617935019 +0800
@@ -196,33 +196,52 @@ int libxl__domain_build(libxl_ctx *ctx, 
     }
     ret = libxl__build_post(ctx, domid, info, state, vments, localents);
 out:
 
     libxl__free_all(&gc);
     return ret;
 }
 
+
+static int override_qemu_state(libxl_ctx *ctx, uint32_t *domid, int restore_fd3);
+
+
 static int domain_restore(libxl_ctx *ctx, libxl_domain_build_info *info,
                          uint32_t domid, int fd, libxl_domain_build_state *state,
                          libxl_device_model_info *dm_info)
 {
     libxl__gc gc = LIBXL_INIT_GC(ctx);
     char **vments = NULL, **localents = NULL;
     struct timeval start_time;
     int i, ret, esave, flags;
+    int seperated = 0;
+    int restore_fd3 = -1;
 
     ret = libxl__build_pre(ctx, domid, info, state);
     if (ret)
         goto out;
 
     ret = libxl__domain_restore_common(ctx, domid, info, state, fd);
     if (ret)
         goto out;
 
+    if (VERSION_RESTORE_FROM_3F == ctx->xl_save_restore.xl_restore_version)
+      {
+	INFO("going to overide qemu state file at /var/lib/xen/ after xc_domain_restore!");
+	restore_fd3 = open(ctx->xl_save_restore.f3, O_RDONLY);
+	seperated = 1;
+	ret = override_qemu_state(ctx, &domid, restore_fd3);
+	if (ret)
+	  {
+	    ERROR("overide qemu state file failed!");
+	    goto out;
+	  }
+      }
+
     gettimeofday(&start_time, NULL);
 
     if (info->hvm) {
         vments = libxl__calloc(&gc, 7, sizeof(char *));
         vments[0] = "rtc/timeoffset";
         vments[1] = (info->u.hvm.timeoffset) ? info->u.hvm.timeoffset : "";
         vments[2] = "image/ostype";
         vments[3] = "hvm";
@@ -271,16 +290,20 @@ out:
         flags &= ~O_NONBLOCK;
         if (fcntl(fd, F_SETFL, flags) == -1)
             LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR, "unable to put restore fd"
                          " back to blocking mode");
     }
 
     errno = esave;
     libxl__free_all(&gc);
+    
+    if (-1 != restore_fd3)
+      close(restore_fd3);
+
     return ret;
 }
 
 int libxl__domain_make(libxl_ctx *ctx, libxl_domain_create_info *info,
                        uint32_t *domid)
  /* on entry, libxl_domid_valid_guest(domid) must be false;
   * on exit (even error exit), domid may be valid and refer to a domain */
 {
@@ -291,28 +314,33 @@ int libxl__domain_make(libxl_ctx *ctx, l
     char *ro_paths[] = { "cpu", "memory", "device", "error", "drivers",
                          "control", "attr", "messages" };
     char *dom_path, *vm_path;
     struct xs_permissions roperm[2];
     struct xs_permissions rwperm[1];
     xs_transaction_t t = 0;
     xen_domain_handle_t handle;
 
+    uint32_t real_domid = *domid;
+    *domid = 0;
+    INFO("temporarily revert domid as 0 to make sure invalid domain id : ^0<x<max");
     assert(!libxl_domid_valid_guest(*domid));
 
     uuid_string = libxl__uuid2string(&gc, info->uuid);
     if (!uuid_string) {
         rc = ERROR_NOMEM;
         goto out;
     }
 
     flags = info->hvm ? XEN_DOMCTL_CDF_hvm_guest : 0;
     flags |= info->hap ? XEN_DOMCTL_CDF_hap : 0;
     flags |= info->oos ? 0 : XEN_DOMCTL_CDF_oos_off;
     *domid = -1;
+    *domid = real_domid;
+    INFO("change domid back to vncdisplay %u ...", *domid);
 
     /* Ultimately, handle is an array of 16 uint8_t, same as uuid */
     libxl_uuid_copy((libxl_uuid *)handle, &info->uuid);
 
     ret = xc_domain_create(ctx->xch, info->ssidref, handle, flags, domid);
     if (ret < 0) {
         LIBXL__LOG_ERRNOVAL(ctx, LIBXL__LOG_ERROR, ret, "domain creation fail");
         rc = ERROR_FAIL;
@@ -403,20 +431,23 @@ retry_transaction:
 
 static int do_domain_create(libxl_ctx *ctx, libxl_domain_config *d_config,
                             libxl_console_ready cb, void *priv,
                             uint32_t *domid_out, int restore_fd)
 {
     libxl__device_model_starting *dm_starting = 0;
     libxl_device_model_info *dm_info = &d_config->dm_info;
     libxl_domain_build_state state;
-    uint32_t domid;
+    uint32_t domid, customize_domid;
     int i, ret;
 
+    customize_domid = d_config->dm_info.vncdisplay;
     domid = 0;
+    domid = customize_domid;
+    INFO("customize current domid as %u...", domid);
 
     ret = libxl__domain_make(ctx, &d_config->c_info, &domid);
     if (ret) {
         fprintf(stderr, "cannot make domain: %d\n", ret);
         ret = ERROR_FAIL;
         goto error_out;
     }
 
@@ -560,8 +591,237 @@ int libxl_domain_create_new(libxl_ctx *c
     return do_domain_create(ctx, d_config, cb, priv, domid, -1);
 }
 
 int libxl_domain_create_restore(libxl_ctx *ctx, libxl_domain_config *d_config,
                                 libxl_console_ready cb, void *priv, uint32_t *domid, int restore_fd)
 {
     return do_domain_create(ctx, d_config, cb, priv, domid, restore_fd);
 }
+
+/*
+ *refer to libxc/xenguest.h 
+ *define XC_DEVICE_MODEL_RESTORE_FILE "/var/lib/xen/qemu-resume"
+ */
+
+#define RDEXACT(fd, buf, size) rdexact(ctx, fd, buf, size)
+
+static ssize_t rdexact(libxl_ctx *ctx, int fd, void* buf, size_t size)
+{
+  size_t offset = 0;
+  ssize_t len;
+  
+  while (offset < size)
+    {
+      len = read(fd, buf + offset, size - offset);
+      if (0 == len)
+	{
+	  LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR, "xl read exact : 0-LENGTH read!");
+	  return -2;
+	}
+      else if (len < 0)
+	{
+	  if ( -1 == len && errno == EINTR)
+	    {
+	      continue;
+	    }
+	  LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR, "xl read exact : negative read!");
+	  return -1;
+	}
+      offset += len;
+    }
+
+  return 0;
+}
+
+typedef struct qemu_buf
+{
+  char signature[21 + 1];
+  uint32_t bufsize;
+  uint8_t *buf;
+}qemu_buf_t;
+
+
+static int compat_buffer_qemu(libxl_ctx *ctx, int fd, qemu_buf_t *qemubuf)
+{
+  uint8_t *qbuf, *tmp;
+  int blen = 0, dlen = 0;
+  int rc;
+
+  blen = 8192;
+  if ( !(qbuf = malloc(blen)))
+    {
+      ERROR("error allocating QEMU buffer");
+      return -1;
+    } 
+
+  while( (rc = read(fd, qbuf+dlen, blen-dlen)) > 0 )
+    {
+      INFO("xl read %d bytes QEMU DATA", rc);
+      dlen += rc;
+      
+      if (dlen == blen)
+	{
+	  INFO("%d-byte QEMU buffer full, reallocating...", dlen);
+	  blen += 4096;
+	  tmp = realloc(qbuf, blen);
+	  if( !tmp )
+	    {
+	      ERROR("error growing QEMU buffer to %d bytes", blen);
+	      free(qbuf);
+	      return -1;
+	    }
+	  qbuf = tmp;
+	}
+    }
+  
+  if (rc < 0)
+    {
+      ERROR("error reading QEMU data");
+      free(qbuf);
+      return -1;
+    }
+
+  if( memcmp(qbuf, "QEVM", 4) )
+    {
+      ERROR("invalid QEMU magic : 0x%08x (expected : `QEVM`)", *(unsigned int*)qbuf);
+      free(qbuf);
+      return -1;
+    }
+
+  qemubuf->bufsize = dlen;
+  qemubuf->buf = qbuf;
+
+  return 0;
+}
+
+
+static int buffer_qemu(libxl_ctx *ctx, int fd, qemu_buf_t *qemubuf)
+{
+  uint32_t qlen;
+  uint8_t *tmp;
+
+  if( RDEXACT(fd, &qlen, sizeof(qlen)) )
+    {
+      ERROR("error reading QEMU data length field in header");
+      return -1;
+    }
+
+  if(qlen > qemubuf->bufsize)
+    {
+      if(qemubuf->buf)
+	{
+	  tmp = realloc(qemubuf->buf, qlen);
+	  if(tmp)
+	    qemubuf->buf = tmp;
+	  else
+	    {
+	      ERROR("error reallocating QEMU buffer");
+	      return -1;
+	    }
+	}
+      else
+	{
+	  qemubuf->buf = malloc(qlen);
+	  if ( !qemubuf->buf )
+	    {
+	      ERROR("error allocating QEMU buffer");
+	      return -1;
+	    }
+	}
+    }
+  
+  qemubuf->bufsize = qlen;
+
+  if( RDEXACT(fd, qemubuf->buf, qemubuf->bufsize) )
+    {
+      ERROR("error reading QEMU data");
+      return -1;
+    }
+  
+  return 0;
+}
+
+
+
+static int override_qemu_state(libxl_ctx *ctx, uint32_t *domid, int restore_fd3)
+{
+  uint32_t domid_r = 0;
+  char path[256]={};
+  qemu_buf_t qemubuf={};
+  int dm_fd = -1;
+  unsigned char qemusig[21] = {};
+  int ret = 0;
+
+  domid_r = *domid;
+  sprintf(path, XC_DEVICE_MODEL_RESTORE_FILE".%u", domid_r);
+
+  
+    {
+      INFO("begin to override %s with part III of the savefile", path);
+      
+      dm_fd = open(path, O_CREAT|O_WRONLY|O_TRUNC);
+      if (-1 != dm_fd)
+	{
+	  if( RDEXACT(restore_fd3, qemusig, sizeof(qemusig)) )
+	    {
+	      ERROR("read qemu signature fail");
+	      return -1;
+	    }
+
+	  if ( !memcmp(qemusig, "QemuDeviceModelRecord", sizeof(qemusig)) )
+	    {
+	      memcpy(qemubuf.signature, qemusig, sizeof(qemusig));
+	      ret = compat_buffer_qemu(ctx, restore_fd3, &qemubuf);
+	    }
+	  else if ( !memcmp(qemusig, "DeviceModelRecord0002", sizeof(qemusig)) ||
+		    !memcmp(qemusig, "RemusDeviceModelState", sizeof(qemusig)) )
+	    {
+	      memcpy(qemubuf.signature, qemusig, sizeof(qemusig));
+	      ret = buffer_qemu(ctx, restore_fd3, &qemubuf);
+	    }
+	  
+	  if (ret)
+	    {
+	      ERROR("error reading QEMU data from save state file-3");
+	      if (qemubuf.buf)
+		free(qemubuf.buf);
+	      return -1;
+     	    }
+	  
+	  if( -1 == write(dm_fd, qemubuf.buf, qemubuf.bufsize) )
+	    {
+	      ERROR("error writing QEMU data to %s", path);
+	      if (qemubuf.buf)
+		free(qemubuf.buf);
+	      return -1;
+	    }
+	}
+      else
+	{
+	  ERROR("error open %s for writing QEMU state", path);
+	  return -1;
+	}
+    }
+ 
+  INFO("write QEMU state to %s done", path);
+  
+  return 0;
+}
+
+
+
+
+
+
+int libxl_domain_create_restore2(libxl_ctx *ctx, libxl_domain_config *d_config,
+                                libxl_console_ready cb, void *priv, uint32_t *domid, 
+				 int restore_fd2, int restore_fd3)
+{
+  int ret = 0;
+
+  ret = do_domain_create(ctx, d_config, cb, priv, domid, restore_fd2);
+
+  if (ret)
+    return ret;
+
+  return 0;
+}
diff --exclude=.svn --exclude='*.rej' --exclude='*.orig' -rpN -U8 xen-4.1.2-a/tools/libxl/libxl_dom.c xen-4.1.2-b/tools/libxl/libxl_dom.c
--- xen-4.1.2-a/tools/libxl/libxl_dom.c	2011-10-21 01:05:42.000000000 +0800
+++ xen-4.1.2-b/tools/libxl/libxl_dom.c	2012-12-28 17:00:03.485662280 +0800
@@ -575,16 +575,96 @@ int libxl__domain_save_device_model(libx
         }
     }
     close(fd2);
     unlink(filename);
     libxl__free_all(&gc);
     return 0;
 }
 
+int libxl__domain_save_device_model2(libxl_ctx *ctx, uint32_t domid, int fd2, int fd3)
+{
+    libxl__gc gc = LIBXL_INIT_GC(ctx);
+    int fd_dm, c, c2;
+    char buf[1024];
+    char *filename = libxl__sprintf(&gc, "/var/lib/xen/qemu-save.%d", domid);
+    struct stat st;
+    uint32_t qemu_state_len;
+
+    LIBXL__LOG(ctx, LIBXL__LOG_DEBUG, "Saving device model state to %s", filename);
+    libxl__xs_write(&gc, XBT_NULL, libxl__sprintf(&gc, "/local/domain/0/device-model/%d/command", domid), "save");
+    libxl__wait_for_device_model(ctx, domid, "paused", NULL, NULL);
+
+    if (stat(filename, &st) < 0)
+    {
+        LIBXL__LOG(ctx, LIBXL__LOG_ERROR, "Unable to stat qemu save file\n");
+        libxl__free_all(&gc);
+        return ERROR_FAIL;
+    }
+
+    qemu_state_len = st.st_size;
+    LIBXL__LOG(ctx, LIBXL__LOG_DEBUG, "Qemu state is %d bytes\n", qemu_state_len);
+
+    c = libxl_write_exactly(ctx, fd2, QEMU_SIGNATURE, strlen(QEMU_SIGNATURE),
+                            "saved-state file part 2", "qemu signature");
+    if (c) {
+        libxl__free_all(&gc);
+        return c;
+    }
+    
+    c = libxl_write_exactly(ctx, fd3, QEMU_SIGNATURE, strlen(QEMU_SIGNATURE),
+                            "saved-state file part 3", "qemu signature");
+    if (c) {
+        libxl__free_all(&gc);
+        return c;
+    }
+
+    c = libxl_write_exactly(ctx, fd2, &qemu_state_len, sizeof(qemu_state_len),
+                            "saved-state file part 2", "saved-state length");
+    if (c) {
+        libxl__free_all(&gc);
+        return c;
+    }
+
+    c = libxl_write_exactly(ctx, fd3, &qemu_state_len, sizeof(qemu_state_len),
+                            "saved-state file part 3", "saved-state length");
+    if (c) {
+        libxl__free_all(&gc);
+        return c;
+    }
+
+
+    fd_dm = open(filename, O_RDONLY);
+    while ((c = read(fd_dm, buf, sizeof(buf))) != 0) {
+        if (c < 0) {
+            if (errno == EINTR)
+                continue;
+            libxl__free_all(&gc);
+            return errno;
+        }
+	c2 = c;
+        c = libxl_write_exactly(
+            ctx, fd2, buf, c2, "saved-state file part 2", "qemu state");
+        if (c) {
+            libxl__free_all(&gc);
+            return c;
+        }
+	c = libxl_write_exactly(
+            ctx, fd3, buf, c2, "saved-state file part 3", "qemu state");
+        if (c) {
+            libxl__free_all(&gc);
+            return c;
+        }
+    }
+    close(fd_dm);
+    unlink(filename);
+    libxl__free_all(&gc);
+    return 0;
+}
+
 char *libxl__uuid2string(libxl__gc *gc, const libxl_uuid uuid)
 {
     char *s = libxl__sprintf(gc, LIBXL_UUID_FMT, LIBXL_UUID_BYTES(uuid));
     if (!s)
         LIBXL__LOG(libxl__gc_owner(gc), LIBXL__LOG_ERROR, "cannot allocate for uuid");
     return s;
 }
 
diff --exclude=.svn --exclude='*.rej' --exclude='*.orig' -rpN -U8 xen-4.1.2-a/tools/libxl/libxl.h xen-4.1.2-b/tools/libxl/libxl.h
--- xen-4.1.2-a/tools/libxl/libxl.h	2011-10-21 01:05:42.000000000 +0800
+++ xen-4.1.2-b/tools/libxl/libxl.h	2012-12-28 16:59:38.008934399 +0800
@@ -211,26 +211,42 @@ void libxl_file_reference_destroy(libxl_
 typedef struct libxl__cpuid_policy libxl_cpuid_policy;
 typedef libxl_cpuid_policy * libxl_cpuid_policy_list;
 void libxl_cpuid_destroy(libxl_cpuid_policy_list *cpuid_list);
 
 #define LIBXL_PCI_FUNC_ALL (~0U)
 
 #include "_libxl_types.h"
 
+
+#define VERSION_RESTORE_FROM_1F 1
+#define VERSION_RESTORE_FROM_3F 2
+
+struct save_restore_specific
+{
+  uint8_t xl_save_version;
+  uint8_t xl_restore_version;
+  const char *f1;
+  const char *f2;
+  const char *f3;
+};
+
 typedef struct {
     xentoollog_logger *lg;
     xc_interface *xch;
     struct xs_handle *xsh;
 
     /* for callers who reap children willy-nilly; caller must only
      * set this after libxl_init and before any other call - or
      * may leave them untouched */
     int (*waitpid_instead)(pid_t pid, int *status, int flags);
     libxl_version_info version_info;
+    
+  /*another save and restore feature, operate on three sperated files*/
+  struct save_restore_specific xl_save_restore;
 } libxl_ctx;
 
 const libxl_version_info* libxl_get_version_info(libxl_ctx *ctx);
 
 typedef struct {
 #define XL_SUSPEND_DEBUG 1
 #define XL_SUSPEND_LIVE 2
     int flags;
@@ -290,19 +306,24 @@ int libxl_ctx_postfork(libxl_ctx *ctx);
 
 /* domain related functions */
 void libxl_init_create_info(libxl_domain_create_info *c_info);
 void libxl_init_build_info(libxl_domain_build_info *b_info, libxl_domain_create_info *c_info);
 void libxl_init_dm_info(libxl_device_model_info *dm_info, libxl_domain_create_info *c_info, libxl_domain_build_info *b_info);
 typedef int (*libxl_console_ready)(libxl_ctx *ctx, uint32_t domid, void *priv);
 int libxl_domain_create_new(libxl_ctx *ctx, libxl_domain_config *d_config, libxl_console_ready cb, void *priv, uint32_t *domid);
 int libxl_domain_create_restore(libxl_ctx *ctx, libxl_domain_config *d_config, libxl_console_ready cb, void *priv, uint32_t *domid, int restore_fd);
+int libxl_domain_create_restore2(libxl_ctx *ctx, libxl_domain_config *d_config,
+                                libxl_console_ready cb, void *priv, uint32_t *domid, 
+				 int restore_fd2, int restore_fd3);
 void libxl_domain_config_destroy(libxl_domain_config *d_config);
 int libxl_domain_suspend(libxl_ctx *ctx, libxl_domain_suspend_info *info,
                           uint32_t domid, int fd);
+int libxl_domain_suspend2(libxl_ctx *ctx, libxl_domain_suspend_info *info,
+			 uint32_t domid, int fd2, int fd3);
 int libxl_domain_resume(libxl_ctx *ctx, uint32_t domid);
 int libxl_domain_shutdown(libxl_ctx *ctx, uint32_t domid, int req);
 int libxl_domain_destroy(libxl_ctx *ctx, uint32_t domid, int force);
 int libxl_domain_preserve(libxl_ctx *ctx, uint32_t domid, libxl_domain_create_info *info, const char *name_suffix, libxl_uuid new_uuid);
 
 /* get max. number of cpus supported by hypervisor */
 int libxl_get_max_cpus(libxl_ctx *ctx);
 
diff --exclude=.svn --exclude='*.rej' --exclude='*.orig' -rpN -U8 xen-4.1.2-a/tools/libxl/libxl_internal.h xen-4.1.2-b/tools/libxl/libxl_internal.h
--- xen-4.1.2-a/tools/libxl/libxl_internal.h	2011-10-21 01:05:43.000000000 +0800
+++ xen-4.1.2-b/tools/libxl/libxl_internal.h	2012-12-28 17:00:03.492681674 +0800
@@ -170,16 +170,17 @@ _hidden int libxl__build_pv(libxl_ctx *c
              libxl_domain_build_info *info, libxl_domain_build_state *state);
 _hidden int libxl__build_hvm(libxl_ctx *ctx, uint32_t domid,
               libxl_domain_build_info *info, libxl_domain_build_state *state);
 
 _hidden int libxl__domain_restore_common(libxl_ctx *ctx, uint32_t domid,
                    libxl_domain_build_info *info, libxl_domain_build_state *state, int fd);
 _hidden int libxl__domain_suspend_common(libxl_ctx *ctx, uint32_t domid, int fd, int hvm, int live, int debug);
 _hidden int libxl__domain_save_device_model(libxl_ctx *ctx, uint32_t domid, int fd);
+_hidden int libxl__domain_save_device_model2(libxl_ctx *ctx, uint32_t domid, int fd2, int fd3);
 _hidden void libxl__userdata_destroyall(libxl_ctx *ctx, uint32_t domid);
 
 /* from xl_device */
 _hidden char *libxl__device_disk_string_of_backend(libxl_disk_backend backend);
 _hidden char *libxl__device_disk_string_of_format(libxl_disk_format format);
 
 _hidden int libxl__device_physdisk_major_minor(const char *physpath, int *major, int *minor);
 _hidden int libxl__device_disk_dev_number(const char *virtpath);
diff --exclude=.svn --exclude='*.rej' --exclude='*.orig' -rpN -U8 xen-4.1.2-a/tools/libxl/libxl_utils.h xen-4.1.2-b/tools/libxl/libxl_utils.h
--- xen-4.1.2-a/tools/libxl/libxl_utils.h	2011-10-21 01:05:43.000000000 +0800
+++ xen-4.1.2-b/tools/libxl/libxl_utils.h	2012-12-28 16:59:54.463934310 +0800
@@ -84,10 +84,23 @@ void libxl_cpumap_reset(libxl_cpumap *cp
 #define libxl_for_each_cpu(var, map) for (var = 0; var < (map).size * 8; var++)
 
 int libxl_cpuarray_alloc(libxl_ctx *ctx, libxl_cpuarray *cpuarray);
 
 static inline uint32_t libxl__sizekb_to_mb(uint32_t s) {
     return (s + 1023) / 1024;
 }
 
+
+
+/*
+ *for simple debug log statement
+ */
+#define INFO(_m, _a...) LIBXL__LOG(ctx, LIBXL__LOG_INFO, _m, ## _a);
+#define ERROR(_m, _a...) LIBXL__LOG(ctx, LIBXL__LOG_ERROR, _m, ## _a);
+
+
+
+
+
+
 #endif
 
diff --exclude=.svn --exclude='*.rej' --exclude='*.orig' -rpN -U8 xen-4.1.2-a/tools/libxl/Makefile xen-4.1.2-b/tools/libxl/Makefile
--- xen-4.1.2-a/tools/libxl/Makefile	2011-10-21 01:05:42.000000000 +0800
+++ xen-4.1.2-b/tools/libxl/Makefile	2012-12-28 17:00:45.611933897 +0800
@@ -6,16 +6,17 @@ XEN_ROOT = $(CURDIR)/../..
 include $(XEN_ROOT)/tools/Rules.mk
 
 MAJOR = 1.0
 MINOR = 0
 
 XLUMAJOR = 1.0
 XLUMINOR = 0
 
+# CFLAGS += -ggdb -O0
 CFLAGS += -Werror -Wno-format-zero-length -Wmissing-declarations
 CFLAGS += -I. -fPIC
 CFLAGS += $(CFLAGS_libxenctrl) $(CFLAGS_libxenguest) $(CFLAGS_libxenstore) $(CFLAGS_libblktapctl)
 
 LIBS = $(LDLIBS_libxenctrl) $(LDLIBS_libxenguest) $(LDLIBS_libxenstore) $(LDLIBS_libblktapctl) $(UTIL_LIBS)
 ifeq ($(CONFIG_Linux),y)
 LIBS += -luuid
 endif
diff --exclude=.svn --exclude='*.rej' --exclude='*.orig' -rpN -U8 xen-4.1.2-a/tools/libxl/xl_cmdimpl.c xen-4.1.2-b/tools/libxl/xl_cmdimpl.c
--- xen-4.1.2-a/tools/libxl/xl_cmdimpl.c	2011-10-21 01:05:43.000000000 +0800
+++ xen-4.1.2-b/tools/libxl/xl_cmdimpl.c	2012-12-28 17:00:45.611933897 +0800
@@ -53,16 +53,23 @@
         int must_rc = (call);                                           \
         if (must_rc < 0) {                                                  \
             fprintf(stderr,"xl: fatal error: %s:%d, rc=%d: %s\n",       \
                     __FILE__,__LINE__, must_rc, #call);                 \
             exit(-must_rc);                                             \
         }                                                               \
     })
 
+#define CLOSEFD(_fd) ({				\
+        if (_fd != -1)                          \
+	  {                                     \
+	    close(_fd);                         \
+	    _fd = -1;                           \
+	  }                                     \
+    })
 
 int logfile = 2;
 
 /* every libxl action in xl uses this same libxl context */
 libxl_ctx ctx;
 
 /* when we operate on a domain, it is this one: */
 static uint32_t domid;
@@ -1363,29 +1370,51 @@ static int create_domain(struct domain_c
     libxl_waiter *w1 = NULL, *w2 = NULL;
     void *config_data = 0;
     int config_len = 0;
     int restore_fd = -1;
     int status = 0;
     libxl_console_ready cb;
     pid_t child_console_pid = -1;
     struct save_file_header hdr;
+    int restore_fd1 = -1, restore_fd2 = -1, restore_fd3 = -1, seperated = 0;
+    int real_restore_fd = -1;
 
     memset(&d_config, 0x00, sizeof(d_config));
 
     if (restore_file) {
         uint8_t *optdata_begin = 0;
         const uint8_t *optdata_here = 0;
         union { uint32_t u32; char b[4]; } u32buf;
         uint32_t badflags;
 
-        restore_fd = migrate_fd >= 0 ? migrate_fd :
-            open(restore_file, O_RDONLY);
+	if (VERSION_RESTORE_FROM_3F == ctx.xl_save_restore.xl_restore_version)
+	  {
+	    restore_fd1 = open(ctx.xl_save_restore.f1, O_RDONLY);
+	    restore_fd2 = open(ctx.xl_save_restore.f2, O_RDONLY);
+	    restore_fd3 = -1;
+	    seperated = 1;
+	  }
+	else
+	  {
+	    seperated = 0;
+	    restore_fd = migrate_fd >= 0 ? migrate_fd :
+	      open(restore_file, O_RDONLY);
+	  }
+	
+	if (seperated)
+	  {
+	    real_restore_fd = restore_fd1;
+	  }
+	else
+	  {
+	    real_restore_fd = restore_fd;
+	  }
 
-        CHK_ERRNO( libxl_read_exactly(&ctx, restore_fd, &hdr,
+        CHK_ERRNO( libxl_read_exactly(&ctx, real_restore_fd, &hdr,
                    sizeof(hdr), restore_file, "header") );
         if (memcmp(hdr.magic, savefileheader_magic, sizeof(hdr.magic))) {
             fprintf(stderr, "File has wrong magic number -"
                     " corrupt or for a different tool?\n");
             return ERROR_INVAL;
         }
         if (hdr.byteorder != SAVEFILE_BYTEORDER_VALUE) {
             fprintf(stderr, "File has wrong byte order\n");
@@ -1401,17 +1430,17 @@ static int create_domain(struct domain_c
         if (badflags) {
             fprintf(stderr, "Savefile has mandatory flag(s) 0x%"PRIx32" "
                     "which are not supported; need newer xl\n",
                     badflags);
             return ERROR_INVAL;
         }
         if (hdr.optional_data_len) {
             optdata_begin = xmalloc(hdr.optional_data_len);
-            CHK_ERRNO( libxl_read_exactly(&ctx, restore_fd, optdata_begin,
+            CHK_ERRNO( libxl_read_exactly(&ctx, real_restore_fd, optdata_begin,
                    hdr.optional_data_len, restore_file, "optdata") );
         }
 
 #define OPTDATA_LEFT  (hdr.optional_data_len - (optdata_here - optdata_begin))
 #define WITH_OPTDATA(amt, body)                                 \
             if (OPTDATA_LEFT < (amt)) {                         \
                 fprintf(stderr, "Savefile truncated.\n");       \
                 return ERROR_INVAL;                             \
@@ -1512,19 +1541,29 @@ start:
 
     if ( dom_info->console_autoconnect ) {
         cb = autoconnect_console;
     }else{
         cb = NULL;
     }
 
     if ( restore_file ) {
-        ret = libxl_domain_create_restore(&ctx, &d_config,
+      if (seperated)
+	{
+	  ret = libxl_domain_create_restore2(&ctx, &d_config,
+					     cb, &child_console_pid,
+					     &domid, restore_fd2, restore_fd3);
+	}
+      else
+	{
+	  ret = libxl_domain_create_restore(&ctx, &d_config,
                                             cb, &child_console_pid,
                                             &domid, restore_fd);
+	}
+        
     }else{
         ret = libxl_domain_create_new(&ctx, &d_config,
                                         cb, &child_console_pid, &domid);
     }
     if ( ret )
         goto error_out;
 
     ret = libxl_userdata_store(&ctx, domid, "xl",
@@ -1698,16 +1737,20 @@ error_out:
 
 out:
     if (logfile != 2)
         close(logfile);
 
     libxl_domain_config_destroy(&d_config);
 
     free(config_data);
+    CLOSEFD(restore_fd);
+    CLOSEFD(restore_fd1);
+    CLOSEFD(restore_fd2);
+    CLOSEFD(restore_fd3);
 
 waitpid_out:
     if (child_console_pid > 0 &&
             waitpid(child_console_pid, &status, 0) < 0 && errno == EINTR)
         goto waitpid_out;
 
     /*
      * If we have daemonized then do not return to the caller -- this has
@@ -2455,16 +2498,66 @@ static int save_domain(const char *p, co
     if (checkpoint)
         libxl_domain_unpause(&ctx, domid);
     else
         libxl_domain_destroy(&ctx, domid, 0);
 
     exit(0);
 }
 
+
+static int save_domain2(const char *p, const char *f1, const char *f2, const char *f3,
+			int checkpoint,
+			const char *override_config_file)
+{
+  int fd1, fd2, fd3;
+    uint8_t *config_data;
+    int config_len;
+
+    LOG("using save2...");
+
+    save_domain_core_begin(p, override_config_file, &config_data, &config_len);
+
+    if (!config_len) {
+        fputs(" Savefile will not contain xl domain config\n", stderr);
+    }
+
+    fd1 = open(f1, O_WRONLY|O_CREAT|O_TRUNC, 0644);
+    if (fd1 < 0) {
+        fprintf(stderr, "Failed to open temp file %s for writing\n", f1);
+        exit(2);
+    }
+
+    save_domain_core_writeconfig(fd1, f1, config_data, config_len);
+    close(fd1);
+
+      fd2 = open(f2, O_WRONLY|O_CREAT|O_TRUNC, 0644);
+    if (fd2 < 0) {
+        fprintf(stderr, "Failed to open temp file %s for writing\n", f2);
+        exit(2);
+    }
+    fd3 = open(f3, O_WRONLY|O_CREAT|O_TRUNC, 0644);
+    if (fd3 < 0) {
+        fprintf(stderr, "Failed to open temp file %s for writing\n", f3);
+        exit(2);
+    }
+      CHK_ERRNO(libxl_domain_suspend2(&ctx, NULL, domid, fd2, fd3));
+    close(fd2);
+    close(fd3);
+
+    if (checkpoint)
+        libxl_domain_unpause(&ctx, domid);
+    else
+        libxl_domain_destroy(&ctx, domid, 0);
+
+    exit(0);
+}
+
+
+
 static int migrate_read_fixedmessage(int fd, const void *msg, int msgsz,
                                      const char *what, const char *rune) {
     char buf[msgsz];
     const char *stream;
     int rc;
 
     stream = rune ? "migration receiver stream" : "migration stream";
     rc = libxl_read_exactly(&ctx, fd, buf, msgsz, stream, what);
@@ -2864,32 +2957,104 @@ int main_restore(int argc, char **argv)
     } else if (argc-optind == 2) {
         config_file = argv[optind];
         checkpoint_file = argv[optind + 1];
     } else {
         help("restore");
         return 2;
     }
 
+    ctx.xl_save_restore.xl_restore_version = VERSION_RESTORE_FROM_1F;
+
     memset(&dom_info, 0, sizeof(dom_info));
     dom_info.debug = debug;
     dom_info.daemonize = daemonize;
     dom_info.paused = paused;
     dom_info.config_file = config_file;
     dom_info.restore_file = checkpoint_file;
     dom_info.migrate_fd = -1;
     dom_info.console_autoconnect = console_autoconnect;
 
     rc = create_domain(&dom_info);
     if (rc < 0)
         return -rc;
 
     return 0;
 }
 
+int main_restore2(int argc, char **argv)
+{
+  const char *checkpoint_file1 = NULL;
+  const char *checkpoint_file2 = NULL;
+  const char *checkpoint_file3 = NULL;
+    const char *config_file = NULL;
+    struct domain_create dom_info;
+    int paused = 0, debug = 0, daemonize = 1, console_autoconnect = 0;
+    int opt, rc;
+
+    while ((opt = getopt(argc, argv, "chpde")) != -1) {
+        switch (opt) {
+        case 'c':
+            console_autoconnect = 1;
+            break;
+        case 'p':
+            paused = 1;
+            break;
+        case 'd':
+            debug = 1;
+            break;
+        case 'e':
+            daemonize = 0;
+            break;
+        case 'h':
+            help("restore2");
+            return 0;
+        default:
+            fprintf(stderr, "option `%c' not supported.\n", optopt);
+            break;
+        }
+    }
+
+    if (argc-optind == 3) {
+        checkpoint_file1 = argv[optind];
+	checkpoint_file2 = argv[optind + 1];
+	checkpoint_file3 = argv[optind + 2];
+    } else if (argc-optind == 4) {
+        config_file = argv[optind];
+        checkpoint_file1 = argv[optind + 1];
+	checkpoint_file2 = argv[optind + 2];
+	checkpoint_file3 = argv[optind + 3];
+    } else {
+        help("restore2");
+        return 2;
+    }
+
+    ctx.xl_save_restore.xl_restore_version = VERSION_RESTORE_FROM_3F;
+    ctx.xl_save_restore.f1 = checkpoint_file1;
+    ctx.xl_save_restore.f2 = checkpoint_file2;
+    ctx.xl_save_restore.f3 = checkpoint_file3;
+  
+    memset(&dom_info, 0, sizeof(dom_info));
+    dom_info.debug = debug;
+    dom_info.daemonize = daemonize;
+    dom_info.paused = paused;
+    dom_info.config_file = config_file;
+    dom_info.restore_file = checkpoint_file1;
+    dom_info.migrate_fd = -1;
+    dom_info.console_autoconnect = console_autoconnect;
+
+    rc = create_domain(&dom_info);
+    if (rc < 0)
+        return -rc;
+
+    return 0;
+}
+
+
+
 int main_migrate_receive(int argc, char **argv)
 {
     int debug = 0, daemonize = 1;
     int opt;
 
     while ((opt = getopt(argc, argv, "hed")) != -1) {
         switch (opt) {
         case 'h':
@@ -2923,17 +3088,17 @@ int main_save(int argc, char **argv)
     int checkpoint = 0;
     int opt;
 
     while ((opt = getopt(argc, argv, "hc")) != -1) {
         switch (opt) {
         case 'c':
             checkpoint = 1;
             break;
-        case 'h':
+	case 'h':
             help("save");
             return 0;
         default:
             fprintf(stderr, "option `%c' not supported.\n", optopt);
             break;
         }
     }
 
@@ -2944,16 +3109,51 @@ int main_save(int argc, char **argv)
 
     p = argv[optind];
     filename = argv[optind + 1];
     config_filename = argv[optind + 2];
     save_domain(p, filename, checkpoint, config_filename);
     return 0;
 }
 
+int main_save2(int argc, char **argv)
+{
+  const char *sf1 = NULL, *sf2 = NULL, *sf3 = NULL, *p = NULL;
+    const char *config_filename;
+    int checkpoint = 0;
+    int opt;
+
+    while ((opt = getopt(argc, argv, "hc")) != -1) {
+        switch (opt) {
+        case 'c':
+            checkpoint = 1;
+            break;
+	case 'h':
+            help("save2");
+            return 0;
+        default:
+            fprintf(stderr, "option `%c' not supported.\n", optopt);
+            break;
+        }
+    }
+
+    if (argc-optind < 3 || argc-optind > 5) {
+        help("save2");
+        return 2;
+    }
+
+    p = argv[optind];
+    sf1 = argv[optind + 1];
+    sf2 = argv[optind + 2];
+    sf3 = argv[optind + 3];
+    config_filename = argv[optind + 4];
+    save_domain2(p, sf1, sf2, sf3, checkpoint, config_filename);
+    return 0;
+}
+
 int main_migrate(int argc, char **argv)
 {
     const char *p = NULL;
     const char *config_filename = NULL;
     const char *ssh_command = "ssh";
     char *rune = NULL;
     char *host;
     int opt, daemonize = 1, debug = 0;
diff --exclude=.svn --exclude='*.rej' --exclude='*.orig' -rpN -U8 xen-4.1.2-a/tools/libxl/xl_cmdtable.c xen-4.1.2-b/tools/libxl/xl_cmdtable.c
--- xen-4.1.2-a/tools/libxl/xl_cmdtable.c	2011-10-21 01:05:43.000000000 +0800
+++ xen-4.1.2-b/tools/libxl/xl_cmdtable.c	2012-12-28 16:59:38.007934942 +0800
@@ -100,16 +100,23 @@ struct cmd_spec cmd_table[] = {
     },
     { "save",
       &main_save,
       "Save a domain state to restore later",
       "[options] <Domain> <CheckpointFile> [<ConfigFile>]",
       "-h  Print this help.\n"
       "-c  Leave domain running after creating the snapshot."
     },
+    { "save2",
+      &main_save2,
+      "Save a domain state as three seperated files to restore later",
+      "[options] <Domain> <CheckpointFile1> <CheckpointFile2> <CheckpointFile3> [<ConfigFile>]",
+      "-h  Print this help.\n"
+      "-c  Leave domain running after creating the snapshot."
+    },
     { "migrate",
       &main_migrate,
       "Save a domain state to restore later",
       "[options] <Domain> <host>",
       "-h              Print this help.\n"
       "-C <config>     Send <config> instead of config file from creation.\n"
       "-s <sshcommand> Use <sshcommand> instead of ssh.  String will be passed\n"
       "                to sh. If empty, run <host> instead of ssh <host> xl\n"
@@ -126,16 +133,25 @@ struct cmd_spec cmd_table[] = {
       &main_restore,
       "Restore a domain from a saved state",
       "[options] [<ConfigFile>] <CheckpointFile>",
       "-h  Print this help.\n"
       "-p  Do not unpause domain after restoring it.\n"
       "-e  Do not wait in the background for the death of the domain.\n"
       "-d  Enable debug messages."
     },
+    { "restore2",
+      &main_restore2,
+      "Restore a domain from a saved state",
+      "[options] [<ConfigFile>] <CheckpointFile1> <CheckpointFile2> <CheckpointFile3>",
+      "-h  Print this help.\n"
+      "-p  Do not unpause domain after restoring it.\n"
+      "-e  Do not wait in the background for the death of the domain.\n"
+      "-d  Enable debug messages."
+    },
     { "migrate-receive",
       &main_migrate_receive,
       "Restore a domain from a saved state",
       "- for internal use only",
     },
     { "cd-insert",
       &main_cd_insert,
       "Insert a cdrom into a guest's cd drive",
diff --exclude=.svn --exclude='*.rej' --exclude='*.orig' -rpN -U8 xen-4.1.2-a/tools/libxl/xl.h xen-4.1.2-b/tools/libxl/xl.h
--- xen-4.1.2-a/tools/libxl/xl.h	2011-10-21 01:05:43.000000000 +0800
+++ xen-4.1.2-b/tools/libxl/xl.h	2012-12-28 16:59:38.020828513 +0800
@@ -31,18 +31,20 @@ int main_cd_eject(int argc, char **argv)
 int main_cd_insert(int argc, char **argv);
 int main_console(int argc, char **argv);
 int main_vncviewer(int argc, char **argv);
 int main_pcilist(int argc, char **argv);
 int main_pcilist_assignable(int argc, char **argv);
 int main_pcidetach(int argc, char **argv);
 int main_pciattach(int argc, char **argv);
 int main_restore(int argc, char **argv);
+int main_restore2(int argc, char **argv);
 int main_migrate_receive(int argc, char **argv);
 int main_save(int argc, char **argv);
+int main_save2(int argc, char **argv);
 int main_migrate(int argc, char **argv);
 int main_dump_core(int argc, char **argv);
 int main_pause(int argc, char **argv);
 int main_unpause(int argc, char **argv);
 int main_destroy(int argc, char **argv);
 int main_shutdown(int argc, char **argv);
 int main_reboot(int argc, char **argv);
 int main_list(int argc, char **argv);

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

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

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

end of thread, other threads:[~2013-03-11  7:29 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2012-12-28  9:26 [PATCH] seperate xen checkpoint file as three parts(for xen-4.1.2) 马磊
2013-01-05  6:52 ` 马磊
2013-01-05 12:26   ` Pasi Kärkkäinen
2013-01-06  2:27     ` 马磊
2013-01-06 10:58       ` Keir Fraser
2013-01-12  5:36         ` 马磊
2013-02-12 17:35           ` Ian Jackson
2013-03-11  7:29             ` 马磊

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).