This testcase failed on some setups (ppc64): Starting testcase "./obj64/mremap-expand-slice-collision", pid 10840 do_readback(0x20001000000, 0x1000000, "huge above") do_readback(0x1ffffff0000, 0x10000, "normal below") Attempting to remap...disallowed do_readback(0x20001000000, 0x10000, "normal above") FAIL mmap(huge below): Device or resource busy
Problem is that SLICE_BOUNDARY was hardcoded to 0x20000000000. When testcase tries to mmap huge page below this address (0x1ffff000000), it fails with EBUSY because there is already heap (0x1????000000) at this slice which may not be using huge pages. See also kernel commit. which introduced slices on powerpc: commit d0f13e3c20b6fb73ccb467bdca97fa7cf5a574cd Author: Benjamin Herrenschmidt <b...@kernel.crashing.org> Date: Tue May 8 16:27:27 2007 +1000 [POWERPC] Introduce address space "slices" This patch removes hardcoded SLICE_BOUNDARY address and introduces function to find two free neighbour slices at runtime. Slice boundary is then set to address between these slices. With patch: Starting testcase "./obj64/mremap-expand-slice-collision", pid 12768 can't use slice_boundary: 0x20000000000 using slice_boundary: 0x30000000000 do_readback(0x30001000000, 0x1000000, "huge above") do_readback(0x2ffffff0000, 0x10000, "normal below") Attempting to remap...disallowed do_readback(0x30001000000, 0x10000, "normal above") do_readback(0x2ffff000000, 0x1000000, "huge below") Attempting to remap...disallowed PASS Signed-off-by: Jan Stancek <jstan...@redhat.com> --- tests/mremap-expand-slice-collision.c | 64 +++++++++++++++++++++++++++++---- 1 files changed, 57 insertions(+), 7 deletions(-) diff --git a/tests/mremap-expand-slice-collision.c b/tests/mremap-expand-slice-collision.c index 0cbff15..99b153a 100644 --- a/tests/mremap-expand-slice-collision.c +++ b/tests/mremap-expand-slice-collision.c @@ -30,13 +30,62 @@ #define RANDOM_CONSTANT 0x1234ABCD +unsigned long slice_boundary; +long hpage_size, page_size; + +void init_slice_boundary(int fd) +{ + unsigned long slice_size; + void *p1, *p2, *heap; + int slices_ok, i, rc; #ifdef __LP64__ -#define SLICE_BOUNDARY 0x20000000000 + /* powerpc: 1TB slices starting at 1 TB */ + slice_boundary = 0x10000000000; + slice_size = 0x10000000000; #else -#define SLICE_BOUNDARY 0xe0000000 + /* powerpc: 256MB slices up to 4GB */ + slice_boundary = 0x00000000; + slice_size = 0x10000000; #endif -long hpage_size, page_size; + /* dummy malloc so we know where is heap */ + heap = malloc(1); + free(heap); + + /* find 2 neighbour slices, which are both free, + * 16 is the maximum number of slices (low/high) */ + for (i = 0; i < 16-1; i++) { + slices_ok = 0; + p1 = mmap((void *)slice_boundary, hpage_size, + PROT_READ, MAP_SHARED | MAP_FIXED, fd, 0); + p2 = mmap((void *)(slice_boundary+slice_size), hpage_size, + PROT_READ, MAP_SHARED | MAP_FIXED, fd, 0); + + if (p1 != MAP_FAILED) { + slices_ok++; + rc = munmap(p1, hpage_size); + if (rc != 0) + FAIL("munmap(p1): %s", strerror(errno)); + } + if (p2 != MAP_FAILED) { + slices_ok++; + rc = munmap(p2, hpage_size); + if (rc != 0) + FAIL("munmap(p2): %s", strerror(errno)); + } + + slice_boundary += slice_size; + if (slices_ok == 2) + break; + else + verbose_printf("can't use slice_boundary: 0x%lx\n", + slice_boundary); + } + + if (slices_ok != 2) + FAIL("couldn't find 2 free neighbour slices"); + verbose_printf("using slice_boundary: 0x%lx\n", slice_boundary); +} void do_readback(void *p, size_t size, const char *stage) { @@ -102,9 +151,10 @@ int main(int argc, char *argv[]) fd = hugetlbfs_unlinked_fd(); if (fd < 0) FAIL("hugetlbfs_unlinked_fd()"); + init_slice_boundary(fd); /* First, hugepages above, normal below */ - p = mmap((void *)(SLICE_BOUNDARY + hpage_size), hpage_size, + p = mmap((void *)(slice_boundary + hpage_size), hpage_size, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_FIXED, fd, 0); if (p == MAP_FAILED) @@ -112,7 +162,7 @@ int main(int argc, char *argv[]) do_readback(p, hpage_size, "huge above"); - q = mmap((void *)(SLICE_BOUNDARY - page_size), page_size, + q = mmap((void *)(slice_boundary - page_size), page_size, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS | MAP_FIXED, -1, 0); if (q == MAP_FAILED) @@ -144,7 +194,7 @@ int main(int argc, char *argv[]) FAIL("munmap(huge above)"); /* Next, normal pages above, huge below */ - p = mmap((void *)(SLICE_BOUNDARY + hpage_size), page_size, + p = mmap((void *)(slice_boundary + hpage_size), page_size, PROT_READ|PROT_WRITE, MAP_SHARED | MAP_FIXED | MAP_ANONYMOUS, -1, 0); if (p == MAP_FAILED) @@ -152,7 +202,7 @@ int main(int argc, char *argv[]) do_readback(p, page_size, "normal above"); - q = mmap((void *)(SLICE_BOUNDARY - hpage_size), + q = mmap((void *)(slice_boundary - hpage_size), hpage_size, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_FIXED, fd, 0); if (q == MAP_FAILED) -- 1.7.1 ------------------------------------------------------------------------------ Live Security Virtual Conference Exclusive live event will cover all the ways today's security and threat landscape has changed and how IT managers can respond. Discussions will include endpoint security, mobile security and the latest in malware threats. http://www.accelacomm.com/jaw/sfrnl04242012/114/50122263/ _______________________________________________ Libhugetlbfs-devel mailing list Libhugetlbfs-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/libhugetlbfs-devel