[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [Xen-devel] [PATCH] libxc: Replace alloca() with mmap() in linux_privcmd_map_foreign_bulk()
On Fri, 2012-04-20 at 15:08 +0100, Andres Lagar-Cavilla wrote: > > On Thu, 2012-04-19 at 23:24 +0100, Aravindh Puthiyaparambil wrote: > >> 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(). > > > > The original reason for switching to alloca from malloc was because the > > similar gntmap path was a hot path and it seemed like if it was > > reasonable there it would be reasonable here too. > > > > So I have a couple of questions... > > > > Is it possible that we also introduced this same issue at the other > > callsites which were changed in that patch or are there other > > constraints on the size of the allocation which make it not a problem? > > I don't know how arbitrary or large can the buffer sizes be in the other > callsites. It would seem that they can be large enough. > > > > Where does this mmap approach fall in terms of performance relative to > > just switching back to malloc? I presume that alloca is faster than > > both, but if it doesn't work reliably then it's not an option. > > It's hard to dig out exactly how alloca is implemented, but it would seem > to simply move the stack pointer and return the old one (it's arguable > whether there is a buggy check for limits or a buggy lack of check against > the guard page going on -- man page says "behavior undefined"). So, if you > need new pages in the stack as a result of the stack pointer motion, those > pages will be demand allocated. > > mmap just short circuits straight to page allocation. Note that malloc may > or may not wind up calling mmap if it needs more pages, depending on its > internal machinations. > > MAP_POPULATE tells the mmap syscall to allocate right now, avoiding demand > allocation. Presumably this will batch all page allocations in the single > syscall, and avoid page faults down the line. > > Short story, I suggested mmap with MAP_POPULATE because it will do the > allocation of pages in the most optimal fashion, even better than malloc > or alloca. But it's only worth if the buffer is big enough such that new > pages will need to be allocated. I think in these cases the whole buffer will always be used, since they are sized precisely for what they need to contain. > I think a reasonable compromise would be to do alloca if the buffer is > less than one page (a fairly common case, single pfn buffers, etc), and do > mmap(MAP_POPULATE) for buffers larger than a page. I agree. Ian. > > Andres > > > > > If mmap and malloc have roughly equivalent performance properties, or > > the fast one is still too slow for Santosh's use case, then maybe we > > need to have a think about other options. > > > > e.g. use alloca for small numbers of mappings and mmap/malloc for larger > > ones. Or do large numbers of mappings in multiple batches. > > > > Ian. > > > >> > >> Signed-off-by: Aravindh Puthiyaparambil <aravindh@xxxxxxxxxxxx> > >> Acked-by: Andres Lagar-Cavilla <andres@xxxxxxxxxxxxxxxx> > >> > >> diff -r 7c777cb8f705 -r 2f68aefc46c3 tools/libxc/xc_linux_osdep.c > >> --- a/tools/libxc/xc_linux_osdep.c Wed Apr 18 16:49:55 2012 +0100 > >> +++ b/tools/libxc/xc_linux_osdep.c Thu Apr 19 15:21:43 2012 -0700 > >> @@ -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)) > >> @@ -286,7 +287,14 @@ 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 = mmap(NULL, ROUNDUP((num * sizeof(*pfn)), > >> XC_PAGE_SHIFT), > >> + 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 +336,8 @@ static void *linux_privcmd_map_foreign_b > >> break; > >> } > >> > >> + munmap(pfn, ROUNDUP((num * sizeof(*pfn)), XC_PAGE_SHIFT)); > >> + > >> if ( rc == -ENOENT && i == num ) > >> rc = 0; > >> else if ( rc ) > >> > >> _______________________________________________ > >> Xen-devel mailing list > >> Xen-devel@xxxxxxxxxxxxx > >> http://lists.xen.org/xen-devel > > > > > > > > _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxx http://lists.xen.org/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |