aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJan Stancek <jstancek@redhat.com>2012-09-10 16:33:15 +0200
committerEric B Munson <emunson@mgebm.net>2012-11-06 08:17:52 -0500
commit8ee2462f3f6eea72067641a197214610443576b8 (patch)
treea4af86b8e3b3937da7367b41238b866873d692a2
parent64dedcf4eac90c0b35438be9e2ad3bb34f584ed3 (diff)
downloadlibhugetlbfs-8ee2462f3f6eea72067641a197214610443576b8.tar.gz
set slice boundary at runtime
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 <benh@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 <jstancek@redhat.com> Signed-off-by: Eric B Munson <emunson@mgebm.net>
-rw-r--r--tests/mremap-expand-slice-collision.c64
1 files changed, 57 insertions, 7 deletions
diff --git a/tests/mremap-expand-slice-collision.c b/tests/mremap-expand-slice-collision.c
index 7178c6a..c25f4c6 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_PRIVATE | 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)