tools: Introduce "allocate-only" page type for migration
authorGeorge Dunlap <george.dunlap@eu.citrix.com>
Thu, 26 May 2011 14:27:33 +0000 (15:27 +0100)
committerGeorge Dunlap <george.dunlap@eu.citrix.com>
Thu, 26 May 2011 14:27:33 +0000 (15:27 +0100)
To detect presence of superpages on the receiver side, we need
to have strings of sequential pfns sent across on the first iteration
through the memory.  However, as we go through the memory, more and
more of it will be marked dirty, making it wasteful to send those pages.

This patch introduces a new PFINFO type, "XALLOC".  Like PFINFO_XTAB, it
indicates that there is no corresponding page present in the subsquent
page buffer.  However, unlike PFINFO_XTAB, it contains a pfn which should be
allocated.

This new type is only used for migration; but it's placed in
xen/public/domctl.h so that the value isn't reused.

Signed-off-by: George Dunlap <george.dunlap@eu.citrix.com>
Committed-by: Ian Jackson <ian.jackson.citrix.com>
tools/libxc/xc_domain_restore.c
tools/libxc/xc_domain_save.c
xen/include/public/domctl.h

index 1a39c2cebc276de2c7ac8089cbb0c7dc4ee534d2..5cf099c92e9198562e5ddc0e0981c216860fc844 100644 (file)
@@ -839,7 +839,8 @@ static int pagebuf_get_one(xc_interface *xch, struct restore_ctx *ctx,
 
     countpages = count;
     for (i = oldcount; i < buf->nr_pages; ++i)
-        if ((buf->pfn_types[i] & XEN_DOMCTL_PFINFO_LTAB_MASK) == XEN_DOMCTL_PFINFO_XTAB)
+        if ((buf->pfn_types[i] & XEN_DOMCTL_PFINFO_LTAB_MASK) == XEN_DOMCTL_PFINFO_XTAB
+            ||(buf->pfn_types[i] & XEN_DOMCTL_PFINFO_LTAB_MASK) == XEN_DOMCTL_PFINFO_XALLOC)
             --countpages;
 
     if (!countpages)
@@ -917,6 +918,7 @@ static int apply_batch(xc_interface *xch, uint32_t dom, struct restore_ctx *ctx,
         pfn      = pagebuf->pfn_types[i + curbatch] & ~XEN_DOMCTL_PFINFO_LTAB_MASK;
         pagetype = pagebuf->pfn_types[i + curbatch] &  XEN_DOMCTL_PFINFO_LTAB_MASK;
 
+        /* For allocation purposes, treat XEN_DOMCTL_PFINFO_XALLOC as a normal page */
         if ( (pagetype != XEN_DOMCTL_PFINFO_XTAB) && 
              (ctx->p2m[pfn] == INVALID_P2M_ENTRY) )
         {
@@ -1028,21 +1030,21 @@ static int apply_batch(xc_interface *xch, uint32_t dom, struct restore_ctx *ctx,
         pfn      = pagebuf->pfn_types[i + curbatch] & ~XEN_DOMCTL_PFINFO_LTAB_MASK;
         pagetype = pagebuf->pfn_types[i + curbatch] &  XEN_DOMCTL_PFINFO_LTAB_MASK;
 
-        if ( pagetype == XEN_DOMCTL_PFINFO_XTAB )
-            region_mfn[i] = ~0UL; /* map will fail but we don't care */
-        else 
+        if ( pagetype != XEN_DOMCTL_PFINFO_XTAB
+             && ctx->p2m[pfn] == (INVALID_P2M_ENTRY-1) )
         {
-            if ( ctx->p2m[pfn] == (INVALID_P2M_ENTRY-1) )
-            {
-                /* We just allocated a new mfn above; update p2m */
-                ctx->p2m[pfn] = ctx->p2m_batch[nr_mfns++]; 
-                ctx->nr_pfns++; 
-            }
+            /* We just allocated a new mfn above; update p2m */
+            ctx->p2m[pfn] = ctx->p2m_batch[nr_mfns++]; 
+            ctx->nr_pfns++; 
+        }
 
-            /* setup region_mfn[] for batch map.
-             * For HVM guests, this interface takes PFNs, not MFNs */
+        /* setup region_mfn[] for batch map, if necessary.
+         * For HVM guests, this interface takes PFNs, not MFNs */
+        if ( pagetype == XEN_DOMCTL_PFINFO_XTAB
+             || pagetype == XEN_DOMCTL_PFINFO_XALLOC )
+            region_mfn[i] = ~0UL; /* map will fail but we don't care */
+        else
             region_mfn[i] = hvm ? pfn : ctx->p2m[pfn]; 
-        }
     }
 
     /* Map relevant mfns */
@@ -1062,8 +1064,9 @@ static int apply_batch(xc_interface *xch, uint32_t dom, struct restore_ctx *ctx,
         pfn      = pagebuf->pfn_types[i + curbatch] & ~XEN_DOMCTL_PFINFO_LTAB_MASK;
         pagetype = pagebuf->pfn_types[i + curbatch] &  XEN_DOMCTL_PFINFO_LTAB_MASK;
 
-        if ( pagetype == XEN_DOMCTL_PFINFO_XTAB )
-            /* a bogus/unmapped page: skip it */
+        if ( pagetype == XEN_DOMCTL_PFINFO_XTAB 
+             || pagetype == XEN_DOMCTL_PFINFO_XALLOC)
+            /* a bogus/unmapped/allocate-only page: skip it */
             continue;
 
         if (pfn_err[i])
index 0c0e2fabdeb59bc9523453f404b8f7e2b6bf3b9c..aec822c6c27c570a5413fc7159c51ef0cb74ed64 100644 (file)
@@ -1155,13 +1155,15 @@ int xc_domain_save(xc_interface *xch, int io_fd, uint32_t dom, uint32_t max_iter
                 }
                 else
                 {
-                    if ( !last_iter &&
+                    int dont_skip = (last_iter || (superpages && iter==1));
+
+                    if ( !dont_skip &&
                          test_bit(n, to_send) &&
                          test_bit(n, to_skip) )
                         skip_this_iter++; /* stats keeping */
 
                     if ( !((test_bit(n, to_send) && !test_bit(n, to_skip)) ||
-                           (test_bit(n, to_send) && last_iter) ||
+                           (test_bit(n, to_send) && dont_skip) ||
                            (test_bit(n, to_fix)  && last_iter)) )
                         continue;
 
@@ -1174,7 +1176,7 @@ int xc_domain_save(xc_interface *xch, int io_fd, uint32_t dom, uint32_t max_iter
                     /*
                     ** we get here if:
                     **  1. page is marked to_send & hasn't already been re-dirtied
-                    **  2. (ignore to_skip in last iteration)
+                    **  2. (ignore to_skip in first and last iterations)
                     **  3. add in pages that still need fixup (net bufs)
                     */
 
@@ -1198,7 +1200,7 @@ int xc_domain_save(xc_interface *xch, int io_fd, uint32_t dom, uint32_t max_iter
                         set_bit(n, to_fix);
                         continue;
                     }
-
+                    
                     if ( last_iter &&
                          test_bit(n, to_fix) &&
                          !test_bit(n, to_send) )
@@ -1243,6 +1245,7 @@ int xc_domain_save(xc_interface *xch, int io_fd, uint32_t dom, uint32_t max_iter
                 {
                     if ( pfn_type[j] == XEN_DOMCTL_PFINFO_XTAB )
                         continue;
+
                     DPRINTF("map fail: page %i mfn %08lx err %d\n",
                             j, gmfn, pfn_err[j]);
                     pfn_type[j] = XEN_DOMCTL_PFINFO_XTAB;
@@ -1255,6 +1258,9 @@ int xc_domain_save(xc_interface *xch, int io_fd, uint32_t dom, uint32_t max_iter
                     continue;
                 }
 
+                if ( superpages && iter==1 && test_bit(gmfn, to_skip))
+                    pfn_type[j] = XEN_DOMCTL_PFINFO_XALLOC;
+
                 /* canonicalise mfn->pfn */
                 pfn_type[j] |= pfn_batch[j];
                 ++run;
@@ -1329,8 +1335,9 @@ int xc_domain_save(xc_interface *xch, int io_fd, uint32_t dom, uint32_t max_iter
                     }
                 }
 
-                /* skip pages that aren't present */
-                if ( pagetype == XEN_DOMCTL_PFINFO_XTAB )
+                /* skip pages that aren't present or are alloc-only */
+                if ( pagetype == XEN_DOMCTL_PFINFO_XTAB
+                    || pagetype == XEN_DOMCTL_PFINFO_XALLOC )
                     continue;
 
                 pagetype &= XEN_DOMCTL_PFINFO_LTABTYPE_MASK;
index f5c661b5abe7db8d3e3014e4a1c333044590d789..c0dbc0234eab9aa3150fa8328b9b939066c68e80 100644 (file)
@@ -133,6 +133,7 @@ DEFINE_XEN_GUEST_HANDLE(xen_domctl_getmemlist_t);
 #define XEN_DOMCTL_PFINFO_LTABTYPE_MASK (0x7U<<28)
 #define XEN_DOMCTL_PFINFO_LPINTAB (0x1U<<31)
 #define XEN_DOMCTL_PFINFO_XTAB    (0xfU<<28) /* invalid page */
+#define XEN_DOMCTL_PFINFO_XALLOC  (0xeU<<28) /* allocate-only page */
 #define XEN_DOMCTL_PFINFO_PAGEDTAB (0x8U<<28)
 #define XEN_DOMCTL_PFINFO_LTAB_MASK (0xfU<<28)