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

[Xen-changelog] [xen-unstable] libxc: Replace alloca() with mmap() for large array sizes


  • To: xen-changelog@xxxxxxxxxxxxxxxxxxx
  • From: Xen patchbot-unstable <patchbot@xxxxxxx>
  • Date: Mon, 14 May 2012 16:31:51 +0000
  • Delivery-date: Mon, 14 May 2012 16:31:58 +0000
  • List-id: "Change log for Mercurial \(receive only\)" <xen-changelog.lists.xen.org>

# HG changeset patch
# User Aravindh Puthiyaparambil <aravindh@xxxxxxxxxxxx>
# Date 1335274296 -3600
# Node ID cd7e5479ed828cff4a17125367ddaad6d0a73039
# Parent  1a8b47d80157d8671ccf5049c7e56ad2be339795
libxc: Replace alloca() with mmap() for large array sizes

Replace alloca() with mmap() for array sizes greater than a page in
xc_linux_osdep.c.

When mapping in large amounts of pages (in the GB range) from a guest
in to Dom0 using xc_map_foreign_bulk(), a segfault occurs in the libxc
client application. This is because the pfn array in
linux_privcmd_map_foreign_bulk() is being allocated using alloca() and
the subsequent memcpy causes the stack to blow. This patch replaces
the alloca() with mmap() for pfn array sizes greater than a page.

Fix an error print with the correct function name.

Do the same for the map array in linux_gnttab_grant_map()

Signed-off-by: Aravindh Puthiyaparambil <aravindh@xxxxxxxxxxxx>
Acked-by: Andres Lagar-Cavilla <andres@xxxxxxxxxxxxxxxx>
Acked-by: Ian Campbell <ian.campbell@xxxxxxxxxx>
Committed-by: Ian Jackson <ian.jackson@xxxxxxxxxxxxx>
---


diff -r 1a8b47d80157 -r cd7e5479ed82 tools/libxc/xc_linux_osdep.c
--- a/tools/libxc/xc_linux_osdep.c      Mon Apr 23 10:26:55 2012 +0200
+++ b/tools/libxc/xc_linux_osdep.c      Tue Apr 24 14:31:36 2012 +0100
@@ -39,6 +39,7 @@
 #include "xenctrl.h"
 #include "xenctrlosdep.h"
 
+#define ROUNDUP(_x,_w) (((unsigned long)(_x)+(1UL<<(_w))-1) & ~((1UL<<(_w))-1))
 #define ERROR(_m, _a...)  xc_osdep_log(xch,XTL_ERROR,XC_INTERNAL_ERROR,_m , ## 
_a )
 #define PERROR(_m, _a...) xc_osdep_log(xch,XTL_ERROR,XC_INTERNAL_ERROR,_m \
                   " (%d = %s)", ## _a , errno, xc_strerror(xch, errno))
@@ -258,7 +259,7 @@ static void *linux_privcmd_map_foreign_b
                 fd, 0);
     if ( addr == MAP_FAILED )
     {
-        PERROR("xc_map_foreign_batch: mmap failed");
+        PERROR("xc_map_foreign_bulk: mmap failed");
         return NULL;
     }
 
@@ -286,7 +287,21 @@ static void *linux_privcmd_map_foreign_b
          * IOCTL_PRIVCMD_MMAPBATCH.
          */
         privcmd_mmapbatch_t ioctlx;
-        xen_pfn_t *pfn = alloca(num * sizeof(*pfn));
+        xen_pfn_t *pfn;
+        unsigned int pfn_arr_size = ROUNDUP((num * sizeof(*pfn)), 
XC_PAGE_SHIFT);
+
+        if ( pfn_arr_size <= XC_PAGE_SIZE )
+            pfn = alloca(num * sizeof(*pfn));
+        else
+        {
+            pfn = mmap(NULL, pfn_arr_size, PROT_READ | PROT_WRITE,
+                       MAP_PRIVATE | MAP_ANON | MAP_POPULATE, -1, 0);
+            if ( pfn == MAP_FAILED )
+            {
+                PERROR("xc_map_foreign_bulk: mmap of pfn array failed");
+                return NULL;
+            }
+        }
 
         memcpy(pfn, arr, num * sizeof(*arr));
 
@@ -328,6 +343,9 @@ static void *linux_privcmd_map_foreign_b
             break;
         }
 
+        if ( pfn_arr_size > XC_PAGE_SIZE )
+            munmap(pfn, pfn_arr_size);
+
         if ( rc == -ENOENT && i == num )
             rc = 0;
         else if ( rc )
@@ -549,6 +567,9 @@ static void *linux_gnttab_grant_map(xc_g
 {
     int fd = (int)h;
     struct ioctl_gntdev_map_grant_ref *map;
+    unsigned int map_size = ROUNDUP((sizeof(*map) + (count - 1) *
+                                    sizeof(struct ioctl_gntdev_map_grant_ref)),
+                                    XC_PAGE_SHIFT);
     void *addr = NULL;
     int domids_stride = 1;
     int i;
@@ -556,8 +577,19 @@ static void *linux_gnttab_grant_map(xc_g
     if (flags & XC_GRANT_MAP_SINGLE_DOMAIN)
         domids_stride = 0;
 
-    map = alloca(sizeof(*map) +
-                 (count - 1) * sizeof(struct ioctl_gntdev_map_grant_ref));
+    if ( map_size <= XC_PAGE_SIZE )
+        map = alloca(sizeof(*map) +
+                     (count - 1) * sizeof(struct ioctl_gntdev_map_grant_ref));
+    else
+    {
+        map = mmap(NULL, map_size, PROT_READ | PROT_WRITE,
+                   MAP_PRIVATE | MAP_ANON | MAP_POPULATE, -1, 0);
+        if ( map == MAP_FAILED )
+        {
+            PERROR("linux_gnttab_grant_map: mmap of map failed");
+            return NULL;
+        }
+    }
 
     for ( i = 0; i < count; i++ )
     {
@@ -628,6 +660,8 @@ static void *linux_gnttab_grant_map(xc_g
     }
 
  out:
+    if ( map_size > XC_PAGE_SIZE )
+        munmap(map, map_size);
 
     return addr;
 }

_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog


 


Rackspace

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