[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-devel] [PATCH] tools: set migration constraints from cmdline


  • To: xen-devel@xxxxxxxxxxxxx
  • From: Olaf Hering <olaf@xxxxxxxxx>
  • Date: Mon, 28 Jan 2013 18:32:40 +0100
  • Delivery-date: Mon, 28 Jan 2013 17:33:11 +0000
  • List-id: Xen developer discussion <xen-devel.lists.xen.org>

# HG changeset patch
# User Olaf Hering <olaf@xxxxxxxxx>
# Date 1359394320 -3600
# Node ID 577b051fca174be9f7b3d6590c62735cdf214021
# Parent  6727070b4129cf852199b66b6a81042ee6966a98
tools: set migration constraints from cmdline

Add new options to xm/xl migrate to control the process of migration.
The intention is to optionally abort the migration if it takes too long
to migrate a busy guest due to the high number of dirty pages. Currently
the guest is suspended to transfer the remaining dirty pages. This
transfer can take too long, which can confuse the guest if its suspended
for too long.

-M <number>   Number of iterations before final suspend (default: 30)
--max_iters <number>

-m <factor>   Max amount of memory to transfer before final suspend (default: 
3*RAM)
--max_factor <factor>

-N            Abort migration instead of doing final suspend.
--no_suspend


A variant of this change has been tested with xend, the patch below is
only compile tested. The changes to libxl change the API, is that
approach acceptable?

Signed-off-by: Olaf Hering <olaf@xxxxxxxxx>

diff -r 6727070b4129 -r 577b051fca17 tools/libxc/xc_domain_save.c
--- a/tools/libxc/xc_domain_save.c
+++ b/tools/libxc/xc_domain_save.c
@@ -43,6 +43,8 @@
 */
 #define DEF_MAX_ITERS   29   /* limit us to 30 times round loop   */
 #define DEF_MAX_FACTOR   3   /* never send more than 3x p2m_size  */
+/* Suspend guest for final transit once number of dirty pages is that low */
+#define DEF_MIN_REMAINING 50
 
 struct save_ctx {
     unsigned long hvirt_start; /* virtual starting address of the hypervisor */
@@ -804,9 +806,11 @@ int xc_domain_save(xc_interface *xch, in
     int rc = 1, frc, i, j, last_iter = 0, iter = 0;
     int live  = (flags & XCFLAGS_LIVE);
     int debug = (flags & XCFLAGS_DEBUG);
+    int nosuspend = (flags & XCFLAGS_DOMSAVE_NOSUSPEND);
     int superpages = !!hvm;
     int race = 0, sent_last_iter, skip_this_iter = 0;
     unsigned int sent_this_iter = 0;
+    int min_reached;
     int tmem_saved = 0;
 
     /* The new domain's shared-info frame number. */
@@ -1525,10 +1529,20 @@ int xc_domain_save(xc_interface *xch, in
 
         if ( live )
         {
+            min_reached = sent_this_iter + skip_this_iter < DEF_MIN_REMAINING;
             if ( (iter >= max_iters) ||
-                 (sent_this_iter+skip_this_iter < 50) ||
+                 min_reached ||
                  (total_sent > dinfo->p2m_size*max_factor) )
             {
+                if ( min_reached && nosuspend )
+                {
+                    ERROR("Live migration aborted, as requested. (guest too 
busy?)"
+                     " total_sent %lu iter %d, max_iters %u max_factor %u",
+                      total_sent, iter, max_iters, max_factor);
+                    rc = 1;
+                    goto out;
+                }
+
                 DPRINTF("Start last iteration\n");
                 last_iter = 1;
 
diff -r 6727070b4129 -r 577b051fca17 tools/libxc/xenguest.h
--- a/tools/libxc/xenguest.h
+++ b/tools/libxc/xenguest.h
@@ -28,6 +28,8 @@
 #define XCFLAGS_HVM       4
 #define XCFLAGS_STDVGA    8
 #define XCFLAGS_CHECKPOINT_COMPRESS    16
+#define XCFLAGS_DOMSAVE_NOSUSPEND      32
+
 #define X86_64_B_SIZE   64 
 #define X86_32_B_SIZE   32
 
diff -r 6727070b4129 -r 577b051fca17 tools/libxl/libxl.c
--- a/tools/libxl/libxl.c
+++ b/tools/libxl/libxl.c
@@ -757,6 +757,7 @@ static void domain_suspend_cb(libxl__egc
 }
 
 int libxl_domain_suspend(libxl_ctx *ctx, uint32_t domid, int fd, int flags,
+                         int max_iters, int max_factor,
                          const libxl_asyncop_how *ao_how)
 {
     AO_CREATE(ctx, domid, ao_how);
@@ -779,6 +780,9 @@ int libxl_domain_suspend(libxl_ctx *ctx,
     dss->type = type;
     dss->live = flags & LIBXL_SUSPEND_LIVE;
     dss->debug = flags & LIBXL_SUSPEND_DEBUG;
+    dss->max_iters = max_iters;
+    dss->max_factor = max_factor;
+    dss->xlflags = flags;
 
     libxl__domain_suspend(egc, dss);
     return AO_INPROGRESS;
diff -r 6727070b4129 -r 577b051fca17 tools/libxl/libxl.h
--- a/tools/libxl/libxl.h
+++ b/tools/libxl/libxl.h
@@ -502,10 +502,12 @@ void libxl_domain_config_dispose(libxl_d
 
 int libxl_domain_suspend(libxl_ctx *ctx, uint32_t domid, int fd,
                          int flags, /* LIBXL_SUSPEND_* */
+                         int max_iters, int max_factor,
                          const libxl_asyncop_how *ao_how)
                          LIBXL_EXTERNAL_CALLERS_ONLY;
 #define LIBXL_SUSPEND_DEBUG 1
 #define LIBXL_SUSPEND_LIVE 2
+#define LIBXL_SUSPEND_NO_FINAL_SUSPEND 4
 
 /* @param suspend_cancel [from xenctrl.h:xc_domain_resume( @param fast )]
  *   If this parameter is true, use co-operative resume. The guest
diff -r 6727070b4129 -r 577b051fca17 tools/libxl/libxl_dom.c
--- a/tools/libxl/libxl_dom.c
+++ b/tools/libxl/libxl_dom.c
@@ -1240,6 +1240,7 @@ void libxl__domain_suspend(libxl__egc *e
 
     dss->xcflags = (live) ? XCFLAGS_LIVE : 0
           | (debug) ? XCFLAGS_DEBUG : 0
+          | (dss->xlflags & LIBXL_SUSPEND_NO_FINAL_SUSPEND) ? 
XCFLAGS_DOMSAVE_NOSUSPEND : 0
           | (dss->hvm) ? XCFLAGS_HVM : 0;
 
     dss->suspend_eventchn = -1;
diff -r 6727070b4129 -r 577b051fca17 tools/libxl/libxl_internal.h
--- a/tools/libxl/libxl_internal.h
+++ b/tools/libxl/libxl_internal.h
@@ -2253,6 +2253,9 @@ struct libxl__domain_suspend_state {
     xc_evtchn *xce; /* event channel handle */
     int suspend_eventchn;
     int hvm;
+    int max_iters;
+    int max_factor;
+    int xlflags;
     int xcflags;
     int guest_responded;
     const char *dm_savefile;
diff -r 6727070b4129 -r 577b051fca17 tools/libxl/xl_cmdimpl.c
--- a/tools/libxl/xl_cmdimpl.c
+++ b/tools/libxl/xl_cmdimpl.c
@@ -3172,7 +3172,7 @@ static int save_domain(uint32_t domid, c
 
     save_domain_core_writeconfig(fd, filename, config_data, config_len);
 
-    int rc = libxl_domain_suspend(ctx, domid, fd, 0, NULL);
+    int rc = libxl_domain_suspend(ctx, domid, fd, 0, 0, 0, NULL);
     close(fd);
 
     if (rc < 0)
@@ -3332,6 +3332,8 @@ static void migrate_do_preamble(int send
 }
 
 static void migrate_domain(uint32_t domid, const char *rune,
+                           int max_iters, int max_factor,
+                           int no_suspend,
                            const char *override_config_file)
 {
     pid_t child = -1;
@@ -3341,6 +3343,7 @@ static void migrate_domain(uint32_t domi
     char rc_buf;
     uint8_t *config_data;
     int config_len;
+    int flags = LIBXL_SUSPEND_LIVE;
 
     save_domain_core_begin(domid, override_config_file,
                            &config_data, &config_len);
@@ -3358,7 +3361,10 @@ static void migrate_domain(uint32_t domi
 
     xtl_stdiostream_adjust_flags(logger, XTL_STDIOSTREAM_HIDE_PROGRESS, 0);
 
-    rc = libxl_domain_suspend(ctx, domid, send_fd, LIBXL_SUSPEND_LIVE, NULL);
+    if (no_suspend)
+        flags |= LIBXL_SUSPEND_NO_FINAL_SUSPEND;
+
+    rc = libxl_domain_suspend(ctx, domid, send_fd, flags, max_iters, 
max_factor, NULL);
     if (rc) {
         fprintf(stderr, "migration sender: libxl_domain_suspend failed"
                 " (rc=%d)\n", rc);
@@ -3751,8 +3757,9 @@ int main_migrate(int argc, char **argv)
     char *rune = NULL;
     char *host;
     int opt, daemonize = 1, monitor = 1, debug = 0;
-
-    SWITCH_FOREACH_OPT(opt, "FC:s:ed", NULL, "migrate", 2) {
+    int max_iters = 0, max_factor = 0, no_suspend = 0;
+
+    SWITCH_FOREACH_OPT(opt, "FC:s:edM:m:N", NULL, "migrate", 2) {
     case 'C':
         config_filename = optarg;
         break;
@@ -3769,6 +3776,15 @@ int main_migrate(int argc, char **argv)
     case 'd':
         debug = 1;
         break;
+    case 'M':
+        max_iters = atoi(optarg);
+        break;
+    case 'm':
+        max_factor = atoi(optarg);
+        break;
+    case 'N':
+        no_suspend = 1;
+        break;
     }
 
     domid = find_domain(argv[optind]);
@@ -3784,7 +3800,7 @@ int main_migrate(int argc, char **argv)
             return 1;
     }
 
-    migrate_domain(domid, rune, config_filename);
+    migrate_domain(domid, rune, max_iters, max_factor, no_suspend, 
config_filename);
     return 0;
 }
 
diff -r 6727070b4129 -r 577b051fca17 tools/libxl/xl_cmdtable.c
--- a/tools/libxl/xl_cmdtable.c
+++ b/tools/libxl/xl_cmdtable.c
@@ -152,6 +152,9 @@ struct cmd_spec cmd_table[] = {
       "-s <sshcommand> Use <sshcommand> instead of ssh.  String will be 
passed\n"
       "                to sh. If empty, run <host> instead of ssh <host> xl\n"
       "                migrate-receive [-d -e]\n"
+      "-M --max_iters <number>  Number of iterations before final suspend 
(default: 30)\n"
+      "-m --max_factor <factor> Max amount of memory to transfer before final 
suspend (default: 3*RAM).\n"
+      "-N --no_suspend Abort migration instead of doing final suspend.\n"
       "-e              Do not wait in the background (on <host>) for the 
death\n"
       "                of the domain."
     },
diff -r 6727070b4129 -r 577b051fca17 tools/python/xen/xend/XendCheckpoint.py
--- a/tools/python/xen/xend/XendCheckpoint.py
+++ b/tools/python/xen/xend/XendCheckpoint.py
@@ -118,9 +118,19 @@ def save(fd, dominfo, network, live, dst
         # enabled. Passing "0" simply uses the defaults compiled into
         # libxenguest; see the comments and/or code in xc_linux_save() for
         # more information.
+        max_iters = dominfo.info.get('max_iters', "0")
+        max_factor = dominfo.info.get('max_factor', "0")
+        no_suspend = dominfo.info.get('no_suspend', None)
+        if max_iters == "None":
+            max_iters = "0"
+        if max_factor == "None":
+            max_factor = "0"
+        if no_suspend == "None":
+            no_suspend = "0"
         cmd = [xen.util.auxbin.pathTo(XC_SAVE), str(fd),
-               str(dominfo.getDomid()), "0", "0", 
-               str(int(live) | (int(hvm) << 2)) ]
+               str(dominfo.getDomid()),
+               max_iters, max_factor,
+               str(int(live) | (int(hvm) << 2) | (int(no_suspend) << 5) ]
         log.debug("[xc_save]: %s", string.join(cmd))
 
         def saveInputHandler(line, tochild):
diff -r 6727070b4129 -r 577b051fca17 tools/python/xen/xend/XendDomain.py
--- a/tools/python/xen/xend/XendDomain.py
+++ b/tools/python/xen/xend/XendDomain.py
@@ -1832,6 +1832,18 @@ class XendDomain:
             log.exception(ex)
             raise XendError(str(ex))
 
+    def domain_migrate_constraints_set((self, domid, max_iters, max_factor, 
no_suspend):
+        """Set the Migrate Constraints of this domain.
+        @param domid: Domain ID or Name
+        @param max_iters: Number of iterations before final suspend
+        @param max_factor: Max amount of memory to transfer before final 
suspend
+        @param no_suspend: Abort migration instead of doing final suspend
+        """
+        dominfo = self.domain_lookup_nr(domid)
+        if not dominfo:
+            raise XendInvalidDomain(str(domid))
+        dominfo.setMigrateConstraints(max_iters, max_factor, no_suspend)
+
     def domain_maxmem_set(self, domid, mem):
         """Set the memory limit for a domain.
 
diff -r 6727070b4129 -r 577b051fca17 tools/python/xen/xend/XendDomainInfo.py
--- a/tools/python/xen/xend/XendDomainInfo.py
+++ b/tools/python/xen/xend/XendDomainInfo.py
@@ -1459,6 +1459,18 @@ class XendDomainInfo:
         pci_conf = self.info['devices'][dev_uuid][1]
         return map(pci_dict_to_bdf_str, pci_conf['devs'])
 
+    def setMigrateConstraints(self, max_iters, max_factor, no_suspend):
+        """Set the Migrate Constraints of this domain.
+        @param max_iters: Number of iterations before final suspend
+        @param max_factor: Max amount of memory to transfer before final 
suspend
+        @param no_suspend: Abort migration instead of doing final suspend
+        """
+        log.debug("Setting setMigrateConstraints of domain %s (%s) to '%s' 
'%s' '%s'.",
+                  self.info['name_label'], str(self.domid), max_iters, 
max_factor, no_suspend)
+        self.info['max_iters'] = str(max_iters)
+        self.info['max_factor'] = str(max_factor)
+        self.info['no_suspend'] = str(no_suspend)
+
     def setMemoryTarget(self, target):
         """Set the memory target of this domain.
         @param target: In MiB.
diff -r 6727070b4129 -r 577b051fca17 tools/python/xen/xm/migrate.py
--- a/tools/python/xen/xm/migrate.py
+++ b/tools/python/xen/xm/migrate.py
@@ -55,6 +55,18 @@ gopts.opt('change_home_server', short='c
           fn=set_true, default=0,
           use="Change home server for managed domains.")
 
+gopts.opt('max_iters', short='M', val='max_iters',
+          fn=set_int, default=None,
+          use="Number of iterations before final suspend (default: 30).")
+
+gopts.opt('max_factor', short='m', val='max_factor',
+          fn=set_int, default=None,
+          use="Max amount of memory to transfer before final suspend (default: 
3*RAM).")
+
+gopts.opt('no_suspend', short='S',
+          fn=set_true, default=None,
+          use="Abort migration instead of doing final suspend.")
+
 def help():
     return str(gopts)
     
@@ -80,6 +92,10 @@ def main(argv):
         server.xenapi.VM.migrate(vm_ref, dst, bool(opts.vals.live),
                                  other_config)
     else:
+        server.xend.domain.migrate_constraints_set(dom,
+                                                   opts.vals.max_iters,
+                                                   opts.vals.max_factor,
+                                                   opts.vals.no_suspend)
         server.xend.domain.migrate(dom, dst, opts.vals.live,
                                    opts.vals.port,
                                    opts.vals.node,

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


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.