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

[Xen-devel] [PATCH for 4.6 5/5] libxc: de-duplicate gpfns in populate_pfns



The original implementation didn't consider there can be same gpfns
present multiple times in the passed in array. The mechanism to prevent
populating same gpfn multiple times only works if the same gpfn appear
in different batch.

This bug is discovered by save / restore Linux 4.1 32 bit kernel, which
has several PTEs pointing to same gpfn. And gpfn pointed to by those
PTEs are populated in one batch by libxc.  When libxc calls
x86_pv_localise_page, the original implementation failed to detect
duplications in one batch.

The fix is to de-duplicate gpfns in populate_pfns.

Signed-off-by: Wei Liu <wei.liu2@xxxxxxxxxx>
---
 tools/libxc/xc_sr_restore.c | 19 ++++++++++++++++---
 1 file changed, 16 insertions(+), 3 deletions(-)

diff --git a/tools/libxc/xc_sr_restore.c b/tools/libxc/xc_sr_restore.c
index adb48da..09fe4c0 100644
--- a/tools/libxc/xc_sr_restore.c
+++ b/tools/libxc/xc_sr_restore.c
@@ -198,7 +198,7 @@ int populate_pfns(struct xc_sr_context *ctx, unsigned count,
     xc_interface *xch = ctx->xch;
     xen_pfn_t *mfns = malloc(count * sizeof(*mfns)),
         *pfns = malloc(count * sizeof(*pfns));
-    unsigned i, nr_pfns = 0;
+    unsigned i, j, nr_pfns = 0;
     int rc = -1;
 
     if ( !mfns || !pfns )
@@ -209,14 +209,27 @@ int populate_pfns(struct xc_sr_context *ctx, unsigned 
count,
     }
 
     for ( i = 0; i < count; ++i )
+        pfns[i] = mfns[i] = INVALID_MFN;
+
+    for ( i = 0; i < count; ++i )
     {
         if ( (!types || (types &&
                          (types[i] != XEN_DOMCTL_PFINFO_XTAB &&
                           types[i] != XEN_DOMCTL_PFINFO_BROKEN))) &&
              !pfn_is_populated(ctx, original_pfns[i]) )
         {
-            pfns[nr_pfns] = mfns[nr_pfns] = original_pfns[i];
-            ++nr_pfns;
+            bool present = false;
+
+            /* De-duplicate gpfns to avoid populating the same one twice */
+            for ( j = 0; j < nr_pfns; ++j )
+                if ( pfns[j] == original_pfns[i] )
+                    present = true;
+
+            if ( !present )
+            {
+                pfns[nr_pfns] = mfns[nr_pfns] = original_pfns[i];
+                ++nr_pfns;
+            }
         }
     }
 
-- 
2.1.4


_______________________________________________
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®.