Blame tests/run_tests.py

Packit Service 96f515
#! /usr/libexec/platform-python
Packit b131a5
Packit Service e2dccc
from __future__ import print_function
Packit Service 46f680
from __future__ import division
Packit Service e2dccc
Packit 2d622a
import subprocess
Packit 2d622a
import types
Packit 2d622a
import os
Packit 2d622a
import sys
Packit 2d622a
import getopt
Packit 2d622a
import resource
Packit 2d622a
import errno
Packit 2d622a
Packit 2d622a
# The superset of wordsizes that should be tested (default 32, 64)
Packit 2d622a
wordsizes = set()
Packit 2d622a
Packit 2d622a
# The super set of page sizes that should be tested.  Defaults to all supported
Packit 2d622a
# huge page sizes with an active mount and at least one huge page allocated
Packit 2d622a
pagesizes = set()
Packit 2d622a
Packit 2d622a
# Each page size may have a subset of valid wordsizes
Packit 2d622a
# This is a dictionary (indexed by page size) of sets
Packit 2d622a
wordsizes_by_pagesize = {}
Packit 2d622a
Packit 2d622a
# The linkhuge tests may only be valid on a subset of word sizes
Packit 2d622a
# This set contains the wordsizes valid for linkhuge tests
Packit 2d622a
linkhuge_wordsizes = set()
Packit 2d622a
Packit 2d622a
# A list of all discovered mountpoints that may be used by libhugetlbfs for
Packit 2d622a
# this run of tests.  This is used for cleaning up left-over share files.
Packit 2d622a
mounts = []
Packit 2d622a
Packit 2d622a
# Results matrix:  This 3-D dictionary is indexed as follows:
Packit 2d622a
#   [type]     - Test results fall into one of the 'result_types' categories
Packit 2d622a
#   [pagesize] - a page size from the set 'pagesizes'
Packit 2d622a
#   [bits]     - a word size from the set 'wordsizes'
Packit 2d622a
#   The indexed value is the number of tests matching the above traits
Packit 2d622a
R = {}
Packit 2d622a
result_types = ("total", "pass", "config", "fail", "xfail", "xpass",
Packit 2d622a
                "signal", "strange", "skip", "nofile")
Packit 2d622a
Packit 2d622a
def bash(cmd):
Packit 2d622a
    """
Packit 2d622a
    Run 'cmd' in the shell and return the exit code and output.
Packit 2d622a
    """
Packit 2d622a
    p = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE)
Packit 2d622a
    try:
Packit 2d622a
        rc = p.wait()
Packit 2d622a
    except KeyboardInterrupt:
Packit 2d622a
        # Abort and mark this a strange test result
Packit 2d622a
        return (127, "")
Packit Service c35f72
    out = p.stdout.read().decode().strip()
Packit 2d622a
    return (rc, out)
Packit 2d622a
Packit 2d622a
def snapshot_pool_state():
Packit 2d622a
    l = []
Packit 2d622a
    for d in os.listdir("/sys/kernel/mm/hugepages"):
Packit 2d622a
        substate = [(f, int(open("/sys/kernel/mm/hugepages/%s/%s" % (d, f)).read()))
Packit 2d622a
                    for f in os.listdir("/sys/kernel/mm/hugepages/%s" % d)]
Packit 2d622a
        l.append((d, tuple(substate)))
Packit 2d622a
    return tuple(l)
Packit 2d622a
Packit 2d622a
def run_test_prog(bits, pagesize, cmd, **env):
Packit 2d622a
    if paranoid_pool_check:
Packit 2d622a
        beforepool = snapshot_pool_state()
Packit Service e2dccc
        print("Pool state: %s" % str(beforepool))
Packit 2d622a
Packit 2d622a
    local_env = os.environ.copy()
Packit 2d622a
    local_env.update(env)
Packit 2d622a
    local_env["PATH"] = "./obj%d:../obj%d:%s" \
Packit 2d622a
        % (bits, bits, local_env.get("PATH", ""))
Packit 2d622a
    local_env["LD_LIBRARY_PATH"] = "../obj%d:obj%d:%s" \
Packit 2d622a
        % (bits, bits, local_env.get("LD_LIBRARY_PATH", ""))
Packit 2d622a
    local_env["HUGETLB_DEFAULT_PAGE_SIZE"] = repr(pagesize)
Packit 2d622a
Packit 2d622a
    try:
Packit 2d622a
        p = subprocess.Popen(cmd, env=local_env, stdout=subprocess.PIPE)
Packit 2d622a
        rc = p.wait()
Packit 2d622a
    except KeyboardInterrupt:
Packit 2d622a
        # Abort and mark this a strange test result
Packit 2d622a
        return (None, "")
Packit 2d622a
    except OSError as e:
Packit 2d622a
        return (-e.errno, "")
Packit Service c35f72
    out = p.stdout.read().decode().strip()
Packit 2d622a
Packit 2d622a
    if paranoid_pool_check:
Packit 2d622a
        afterpool = snapshot_pool_state()
Packit 2d622a
        if afterpool != beforepool:
Packit Service e2dccc
            print("Hugepage pool state not preserved!", file=sys.stderr)
Packit Service e2dccc
            print("BEFORE: %s" % str(beforepool), file=sys.stderr)
Packit Service e2dccc
            print("AFTER: %s" % str(afterpool), file=sys.stderr)
Packit 2d622a
            sys.exit(98)
Packit 2d622a
Packit 2d622a
    return (rc, out)
Packit 2d622a
Packit 2d622a
def setup_env(override, defaults):
Packit 2d622a
    """
Packit 2d622a
    Set up the environment for running commands in the shell.
Packit 2d622a
    """
Packit 2d622a
    # All items in override are unconditionally set or unset
Packit 2d622a
    for (var, val) in override.items():
Packit 2d622a
        if val == None:
Packit 2d622a
            if var in os.environ:
Packit 2d622a
                del os.environ[var]
Packit 2d622a
        else:
Packit 2d622a
            os.environ[var] = val
Packit 2d622a
    # If not already set, these variables are given default values
Packit 2d622a
    for (var, val) in defaults.items():
Packit 2d622a
        if var not in os.environ or os.environ[var] == "":
Packit 2d622a
            os.environ[var] = val
Packit 2d622a
Packit 2d622a
def init_results():
Packit 2d622a
    """
Packit 2d622a
    Define the structure of the results matrix and initialize all results to 0.
Packit 2d622a
    """
Packit 2d622a
    global R
Packit 2d622a
Packit 2d622a
    for t in result_types:
Packit 2d622a
        R[t] = {}
Packit 2d622a
        for p in pagesizes:
Packit 2d622a
            R[t][p] = {}
Packit 2d622a
            for bits in (32, 64):
Packit 2d622a
                R[t][p][bits] = 0
Packit 2d622a
Packit 2d622a
def pretty_page_size(size):
Packit 2d622a
    """
Packit 2d622a
    Convert a page size to a formatted string
Packit 2d622a
Packit 2d622a
    Given a page size in bytes, return a string that expresses the size in
Packit 2d622a
    a sensible unit (K, M, or G).
Packit 2d622a
    """
Packit 2d622a
    factor = 0
Packit 2d622a
    while size > 1024:
Packit 2d622a
        factor += 1
Packit 2d622a
        size /= 1024
Packit 2d622a
Packit 2d622a
    if   factor == 0: return "%iB" % size
Packit 2d622a
    elif factor == 1: return "%iK" % size
Packit 2d622a
    elif factor == 2: return "%iM" % size
Packit 2d622a
    elif factor == 3: return "%iG" % size
Packit 2d622a
Packit 2d622a
def print_per_size(title, values):
Packit 2d622a
    """
Packit 2d622a
    Print one line of test results
Packit 2d622a
Packit 2d622a
    Print the results of a given result type on one line.  The results for all
Packit 2d622a
    page sizes and word sizes are written in a table format.
Packit 2d622a
    """
Packit Service e2dccc
    print("*%20s: " % title, end=" ")
Packit 2d622a
    for sz in pagesizes:
Packit Service e2dccc
        print("%4s   %4s   " % (values[sz][32], values[sz][64]), end="")
Packit Service e2dccc
    print()
Packit 2d622a
Packit 2d622a
def results_summary():
Packit 2d622a
    """
Packit 2d622a
    Display a summary of the test results
Packit 2d622a
    """
Packit Service e2dccc
    print("********** TEST SUMMARY")
Packit Service e2dccc
    print("*%21s" % "", end=" ")
Packit Service e2dccc
    for p in pagesizes:
Packit Service e2dccc
        print("%-13s " % pretty_page_size(p), end="")
Packit Service e2dccc
    print()
Packit Service e2dccc
    print("*%21s" % "", end=" ")
Packit Service e2dccc
    for p in pagesizes:
Packit Service e2dccc
        print("32-bit 64-bit ", end="")
Packit Service e2dccc
    print()
Packit 2d622a
Packit 2d622a
    print_per_size("Total testcases", R["total"])
Packit 2d622a
    print_per_size("Skipped", R["skip"])
Packit 2d622a
    print_per_size("PASS", R["pass"])
Packit 2d622a
    print_per_size("FAIL", R["fail"])
Packit 2d622a
    print_per_size("Killed by signal", R["signal"])
Packit 2d622a
    print_per_size("Bad configuration", R["config"])
Packit 2d622a
    print_per_size("Expected FAIL", R["xfail"])
Packit 2d622a
    print_per_size("Unexpected PASS", R["xpass"])
Packit 2d622a
    print_per_size("Test not present", R["nofile"])
Packit 2d622a
    print_per_size("Strange test result", R["strange"])
Packit Service e2dccc
    print("**********")
Packit 2d622a
Packit Service 95a5c0
def free_hpages(size=None):
Packit 2d622a
    """
Packit Service 95a5c0
    Return the number of free huge pages for a given size. If size is not
Packit Service 95a5c0
    passed, use the default huge page size.
Packit 2d622a
Packit Service 95a5c0
    Parse /sys/kernel/mm/hugepages/hugepages-<size-in-kB>/free_hugepages to
Packit Service 95a5c0
    obtain the number of free huge pages for the given page size.
Packit 2d622a
    """
Packit Service 95a5c0
    if size == None: size = system_default_hpage_size
Packit Service 95a5c0
    size_kb = size / 1024
Packit Service 95a5c0
    cmd = "cat /sys/kernel/mm/hugepages/hugepages-%dkB/free_hugepages" % size_kb
Packit Service 95a5c0
    (rc, out) = bash(cmd)
Packit 2d622a
    return (rc, int(out))
Packit 2d622a
Packit Service 95a5c0
def total_hpages(size=None):
Packit 2d622a
    """
Packit Service 95a5c0
    Return the total number of huge pages in the pool for a given size. If
Packit Service 95a5c0
    size is not passed, use the default huge page size.
Packit 2d622a
Packit Service 95a5c0
    Parse /sys/kernel/mm/hugepages/hugepages-<size-in-kB>/nr_hugepages to
Packit Service 95a5c0
    obtain the number of huge pages for the given page size.
Packit 2d622a
    """
Packit Service 95a5c0
    if size == None: size = system_default_hpage_size
Packit Service 95a5c0
    size_kb = size / 1024
Packit Service 95a5c0
    cmd = "cat /sys/kernel/mm/hugepages/hugepages-%dkB/nr_hugepages" % size_kb
Packit Service 95a5c0
    (rc, out) = bash(cmd)
Packit 2d622a
    return (rc, int(out))
Packit 2d622a
Packit 2d622a
def hpage_size():
Packit 2d622a
    """
Packit 2d622a
    Return the size of the default huge page size in bytes.
Packit 2d622a
Packit 2d622a
    Parse /proc/meminfo to obtain the default huge page size.  This number is
Packit 2d622a
    reported in Kb so multiply it by 1024 to convert it to bytes.
Packit 2d622a
    XXX: This function is not multi-size aware yet.
Packit 2d622a
    """
Packit 2d622a
    (rc, out) = bash("grep 'Hugepagesize:' /proc/meminfo | awk '{print $2}'")
Packit 2d622a
    if out == "": out = 0
Packit 2d622a
    out = int(out) * 1024
Packit 2d622a
    return (rc, out)
Packit 2d622a
Packit 2d622a
def clear_hpages():
Packit 2d622a
    """
Packit 2d622a
    Remove stale hugetlbfs files after sharing tests.
Packit 2d622a
Packit 2d622a
    Traverse the mount points that are in use during testing to find left-over
Packit 2d622a
    files that were created by the elflink sharing tests.  These are not
Packit 2d622a
    cleaned up automatically and must be removed to free up the huge pages.
Packit 2d622a
    """
Packit 2d622a
    for mount in mounts:
Packit Service aea7d5
        dir = mount + "/elflink-uid-" + repr(os.getuid())
Packit 2d622a
        for root, dirs, files in os.walk(dir, topdown=False):
Packit 2d622a
            for name in files:
Packit 2d622a
                os.remove(os.path.join(root, name))
Packit 2d622a
            for name in dirs:
Packit 2d622a
                os.rmdir(os.path.join(root, name))
Packit 2d622a
        try:
Packit 2d622a
            os.rmdir(dir)
Packit 2d622a
        except OSError:
Packit 2d622a
            pass
Packit 2d622a
Packit 2d622a
def get_pagesizes():
Packit 2d622a
    """
Packit 2d622a
    Get a list of configured huge page sizes.
Packit 2d622a
Packit 2d622a
    Use libhugetlbfs' hugeadm utility to get a list of page sizes that have
Packit 2d622a
    active mount points and at least one huge page allocated to the pool.
Packit 2d622a
    """
Packit 2d622a
    sizes = set()
Packit 2d622a
    out = ""
Packit Service d8de40
    (rc, out) = bash("hugeadm --page-sizes")
Packit Service c35f72
    if rc != 0 or out == "":
Packit Service c35f72
        return sizes
Packit 2d622a
Packit Service c35f72
    for size in out.split("\n"):
Packit Service c35f72
        sizes.add(int(size))
Packit 2d622a
    return sizes
Packit 2d622a
Packit 2d622a
def get_wordsizes():
Packit 2d622a
    """
Packit 2d622a
    Checks for obj32 and obj64 subdirs to determine valid word sizes.
Packit 2d622a
    """
Packit 2d622a
    sizes = set()
Packit 2d622a
    if os.path.isdir("./obj32"): sizes.add(32)
Packit 2d622a
    if os.path.isdir("./obj64"): sizes.add(64)
Packit 2d622a
Packit 2d622a
    return sizes
Packit 2d622a
Packit 2d622a
def check_hugetlbfs_path():
Packit 2d622a
    """
Packit 2d622a
    Check each combination of page size and word size for validity.
Packit 2d622a
Packit 2d622a
    Some word sizes may not be valid for all page sizes.  For example, a 16G
Packit 2d622a
    page is too large to be used in a 32 bit process.  Use a helper program to
Packit 2d622a
    weed out invalid combinations and print informational messages as required.
Packit 2d622a
    """
Packit 2d622a
    global wordsizes, pagesizes, mounts, wordsizes_by_pagesize
Packit 2d622a
Packit 2d622a
    for p in pagesizes:
Packit 2d622a
        okbits = []
Packit 2d622a
        for b in wordsizes:
Packit 2d622a
            (rc, out) = run_test_prog(b, p, "get_hugetlbfs_path")
Packit 2d622a
            if rc == 0:
Packit 2d622a
                okbits.append(b)
Packit 2d622a
                mounts.append(out)
Packit 2d622a
        if len(okbits) == 0:
Packit Service e2dccc
            print("run_tests.py: No mountpoints available for page size %s" %
Packit Service e2dccc
                  pretty_page_size(p))
Packit 2d622a
            wordsizes_by_pagesize[p] = set()
Packit 2d622a
            continue
Packit 2d622a
        for b in wordsizes - set(okbits):
Packit Service e2dccc
            print("run_tests.py: The %i bit word size is not compatible with " \
Packit Service e2dccc
                  "%s pages" % (b, pretty_page_size(p)))
Packit 2d622a
        wordsizes_by_pagesize[p] = set(okbits)
Packit 2d622a
Packit 2d622a
def check_linkhuge_tests():
Packit 2d622a
    """
Packit 2d622a
    Check if the linkhuge tests are safe to run on this system.
Packit 2d622a
Packit 2d622a
    Newer versions of binutils (>= 2.18) are known to be incompatible with the
Packit 2d622a
    linkhuge tests and running them may cause unreliable behavior.  Determine
Packit 2d622a
    which word sizes can be tested with linkhuge.  The others will be skipped.
Packit 2d622a
    NOTE: The linhuge_rw tests are always safe to run and will not be skipped.
Packit 2d622a
    """
Packit 2d622a
    okbits = set()
Packit 2d622a
Packit 2d622a
    for bits in wordsizes:
Packit 2d622a
        script = open('obj%d/dummy.ldscript' % bits, 'r').read()
Packit 2d622a
        if script.count('SPECIAL') == 0:
Packit 2d622a
            okbits.add(bits)
Packit 2d622a
    return okbits
Packit 2d622a
Packit 2d622a
def print_cmd(pagesize, bits, cmd, env):
Packit 2d622a
    if env:
Packit Service e2dccc
        print(' '.join(['%s=%s' % (k, v) for k, v in env.items()]), end=" ")
Packit Service 31fd4d
    if not isinstance(cmd, str):
Packit 2d622a
        cmd = ' '.join(cmd)
Packit Service e2dccc
    print("%s (%s: %i):\t" % (cmd, pretty_page_size(pagesize), bits), end="")
Packit 2d622a
    sys.stdout.flush()
Packit 2d622a
Packit 2d622a
def run_test(pagesize, bits, cmd, **env):
Packit 2d622a
    """
Packit 2d622a
    Execute a test, print the output and log the result
Packit 2d622a
Packit 2d622a
    Run a test using the specified page size and word size.  The parameter
Packit 2d622a
    'pre' may contain additional environment settings and will be prepended to
Packit 2d622a
    cmd.  A line showing info about the test is printed and after completion
Packit 2d622a
    the test output is printed.  The result is recorded in the result matrix.
Packit 2d622a
    """
Packit 2d622a
    global R
Packit 2d622a
Packit 2d622a
    objdir = "obj%i" % bits
Packit 2d622a
    if not os.path.isdir(objdir):
Packit 2d622a
        return
Packit 2d622a
Packit 2d622a
    print_cmd(pagesize, bits, cmd, env)
Packit 2d622a
    (rc, out) = run_test_prog(bits, pagesize, cmd, **env)
Packit Service e2dccc
    print(out)
Packit 2d622a
Packit 2d622a
    R["total"][pagesize][bits] += 1
Packit 2d622a
    if rc == 0:    R["pass"][pagesize][bits] += 1
Packit 2d622a
    elif rc == 1:  R["config"][pagesize][bits] += 1
Packit 2d622a
    elif rc == 2:  R["fail"][pagesize][bits] += 1
Packit 2d622a
    elif rc == 3:  R["xfail"][pagesize][bits] += 1
Packit 2d622a
    elif rc == 4:  R["xpass"][pagesize][bits] += 1
Packit 2d622a
    elif rc == -errno.ENOENT:
Packit 2d622a
                   R["nofile"][pagesize][bits] += 1
Packit 2d622a
    elif rc < 0:   R["signal"][pagesize][bits] += 1
Packit 2d622a
    else:          R["strange"][pagesize][bits] += 1
Packit 2d622a
Packit 2d622a
def skip_test(pagesize, bits, cmd, **env):
Packit 2d622a
    """
Packit 2d622a
    Skip a test, print test information, and log that it was skipped.
Packit 2d622a
    """
Packit 2d622a
    global tot_tests, tot_skip
Packit 2d622a
    R["total"][pagesize][bits] += 1
Packit 2d622a
    R["skip"][pagesize][bits] += 1
Packit 2d622a
    print_cmd(pagesize, bits, cmd, env)
Packit Service e2dccc
    print("SKIPPED")
Packit 2d622a
Packit 2d622a
def do_test(cmd, bits=None, **env):
Packit 2d622a
    """
Packit 2d622a
    Run a test case, testing each page size and each indicated word size.
Packit 2d622a
    """
Packit 2d622a
    if bits == None: bits = wordsizes
Packit 2d622a
    for p in pagesizes:
Packit 2d622a
        for b in (set(bits) & wordsizes_by_pagesize[p]):
Packit 2d622a
            run_test(p, b, cmd, **env)
Packit 2d622a
Packit 2d622a
def do_test_with_rlimit(rtype, limit, cmd, bits=None, **env):
Packit 2d622a
    """
Packit 2d622a
    Run a test case with a temporarily altered resource limit.
Packit 2d622a
    """
Packit 2d622a
    oldlimit = resource.getrlimit(rtype)
Packit 2d622a
    resource.setrlimit(rtype, (limit, limit))
Packit 2d622a
    do_test(cmd, bits, **env)
Packit 2d622a
    resource.setrlimit(rtype, oldlimit)
Packit 2d622a
Packit Service d5fae0
def do_test_with_pagesize(pagesize, cmd, bits=None, **env):
Packit Service d5fae0
    """
Packit Service d5fae0
    Run a test case, testing with a specified huge page size and
Packit Service d5fae0
    each indicated word size.
Packit Service d5fae0
    """
Packit Service d5fae0
    if bits == None:
Packit Service d5fae0
        bits = wordsizes
Packit Service d5fae0
    for b in (set(bits) & wordsizes_by_pagesize[pagesize]):
Packit Service d5fae0
        run_test(pagesize, b, cmd, **env)
Packit Service d5fae0
Packit 2d622a
def do_elflink_test(cmd, **env):
Packit 2d622a
    """
Packit 2d622a
    Run an elflink test case, skipping known-bad configurations.
Packit 2d622a
    """
Packit Service 32f346
    for b in wordsizes_by_pagesize[system_default_hpage_size]:
Packit Service 32f346
        if b in linkhuge_wordsizes:
Packit Service 32f346
            run_test(system_default_hpage_size, b, cmd, **env)
Packit Service 32f346
        else:
Packit Service 32f346
            skip_test(system_default_hpage_size, b, cmd, **env)
Packit 2d622a
Packit 2d622a
def elflink_test(cmd, **env):
Packit 2d622a
    """
Packit 2d622a
    Run an elflink test case with different configuration combinations.
Packit 2d622a
Packit 2d622a
    Test various combinations of: preloading libhugetlbfs, B vs. BDT link
Packit 2d622a
    modes, minimal copying on or off, and disabling segment remapping.
Packit 2d622a
    """
Packit Service 32f346
    do_test_with_pagesize(system_default_hpage_size, cmd, **env)
Packit 2d622a
    # Test we don't blow up if not linked for hugepage
Packit Service 32f346
    do_test_with_pagesize(system_default_hpage_size, cmd,
Packit Service 32f346
                          LD_PRELOAD="libhugetlbfs.so", **env)
Packit 2d622a
Packit 2d622a
    # Only run custom ldscript tests when -l option is set
Packit 2d622a
    if not custom_ldscripts:
Packit 2d622a
        return
Packit 2d622a
Packit 2d622a
    do_elflink_test("xB." + cmd, **env)
Packit 2d622a
    do_elflink_test("xBDT." + cmd, **env)
Packit 2d622a
    # Test we don't blow up if HUGETLB_MINIMAL_COPY is diabled
Packit 2d622a
    do_elflink_test("xB." + cmd, HUGETLB_MINIMAL_COPY="no", **env)
Packit 2d622a
    do_elflink_test("xBDT." + cmd, HUGETLB_MINIMAL_COPY="no", **env)
Packit 2d622a
    # Test that HUGETLB_ELFMAP=no inhibits remapping as intended
Packit 2d622a
    do_elflink_test("xB." + cmd, HUGETLB_ELFMAP="no", **env)
Packit 2d622a
    do_elflink_test("xBDT." + cmd, HUGETLB_ELFMAP="no", **env)
Packit 2d622a
Packit 2d622a
def elflink_rw_test(cmd, **env):
Packit 2d622a
    """
Packit 2d622a
    Run the elflink_rw test with different configuration combinations.
Packit 2d622a
Packit 2d622a
    Test various combinations of: remapping modes and minimal copy on or off.
Packit 2d622a
    """
Packit 2d622a
    # Basic tests: None, Read-only, Write-only, Read-Write, exlicit disable
Packit Service 32f346
    do_test_with_pagesize(system_default_hpage_size, cmd, **env)
Packit Service 32f346
    do_test_with_pagesize(system_default_hpage_size, cmd,
Packit Service 32f346
                          HUGETLB_ELFMAP="R", **env)
Packit Service 32f346
    do_test_with_pagesize(system_default_hpage_size, cmd,
Packit Service 32f346
                          HUGETLB_ELFMAP="W", **env)
Packit Service 32f346
    do_test_with_pagesize(system_default_hpage_size, cmd,
Packit Service 32f346
                          HUGETLB_ELFMAP="RW", **env)
Packit Service 32f346
    do_test_with_pagesize(system_default_hpage_size, cmd,
Packit Service 32f346
                          HUGETLB_ELFMAP="no", **env)
Packit 2d622a
Packit 2d622a
    # Test we don't blow up if HUGETLB_MINIMAL_COPY is disabled
Packit Service 32f346
    do_test_with_pagesize(system_default_hpage_size, cmd,
Packit Service 32f346
                          HUGETLB_MINIMAL_COPY="no", HUGETLB_ELFMAP="R", **env)
Packit Service 32f346
    do_test_with_pagesize(system_default_hpage_size, cmd,
Packit Service 32f346
                          HUGETLB_MINIMAL_COPY="no", HUGETLB_ELFMAP="W", **env)
Packit Service 32f346
    do_test_with_pagesize(system_default_hpage_size, cmd,
Packit Service 32f346
                          HUGETLB_MINIMAL_COPY="no", HUGETLB_ELFMAP="RW", **env)
Packit 2d622a
Packit 2d622a
def elfshare_test(cmd, **env):
Packit 2d622a
    """
Packit 2d622a
    Test segment sharing with multiple configuration variations.
Packit 2d622a
    """
Packit 2d622a
    # Run each elfshare test invocation independently - clean up the
Packit 2d622a
    # sharefiles before and after in the first set of runs, but leave
Packit 2d622a
    # them there in the second:
Packit 2d622a
    clear_hpages()
Packit 2d622a
    do_elflink_test("xB." + cmd, HUGETLB_SHARE="1", **env)
Packit 2d622a
    clear_hpages()
Packit 2d622a
    do_elflink_test("xBDT." + cmd, HUGETLB_SHARE="1", **env)
Packit 2d622a
    clear_hpages()
Packit 2d622a
    do_elflink_test("xB." + cmd, HUGETLB_SHARE="1", **env)
Packit 2d622a
    do_elflink_test("xBDT." + cmd, HUGETLB_SHARE="1", **env)
Packit 2d622a
    clear_hpages()
Packit 2d622a
Packit 2d622a
def elflink_and_share_test(cmd, **env):
Packit 2d622a
    """
Packit 2d622a
    Run the ordinary linkhuge tests with sharing enabled
Packit 2d622a
    """
Packit 2d622a
    # Run each elflink test pair independently - clean up the sharefiles
Packit 2d622a
    # before and after each pair
Packit 2d622a
    clear_hpages()
Packit 2d622a
    for link_str in ("xB.", "xBDT."):
Packit 2d622a
        for i in range(2):
Packit 2d622a
            do_elflink_test(link_str + cmd, HUGETLB_SHARE=repr(i), **env)
Packit 2d622a
        clear_hpages()
Packit 2d622a
Packit 2d622a
def elflink_rw_and_share_test(cmd, **env):
Packit 2d622a
    """
Packit 2d622a
    Run the ordinary linkhuge_rw tests with sharing enabled
Packit 2d622a
    """
Packit 2d622a
    clear_hpages()
Packit 2d622a
    for mode in ("R", "W", "RW"):
Packit 2d622a
        for i in range(2):
Packit Service 32f346
            do_test_with_pagesize(system_default_hpage_size, cmd,
Packit Service 32f346
                                  HUGETLB_ELFMAP=mode, HUGETLB_SHARE=repr(i),
Packit Service 32f346
                                  **env)
Packit 2d622a
        clear_hpages()
Packit 2d622a
Packit 2d622a
def setup_shm_sysctl(limit):
Packit 2d622a
    """
Packit 2d622a
    Adjust the kernel shared memory limits to accomodate a desired size.
Packit 2d622a
Packit 2d622a
    The original values are returned in a dictionary that can be passed to
Packit 2d622a
    restore_shm_sysctl() to restore the system state.
Packit 2d622a
    """
Packit 2d622a
    if os.getuid() != 0: return {}
Packit 2d622a
    sysctls = {}
Packit 2d622a
    files = [ "/proc/sys/kernel/shmmax", "/proc/sys/kernel/shmall"]
Packit 2d622a
    for f in files:
Packit 2d622a
        fh = open(f, "r")
Packit 2d622a
        sysctls[f] = fh.read()
Packit 2d622a
        fh.close()
Packit 2d622a
        fh = open(f, "w")
Packit Service aea7d5
        fh.write(repr(limit))
Packit 2d622a
        fh.close()
Packit Service e2dccc
    print("set shmmax limit to %s" % limit)
Packit 2d622a
    return sysctls
Packit 2d622a
Packit 2d622a
def restore_shm_sysctl(sysctls):
Packit 2d622a
    """
Packit 2d622a
    Restore the sysctls named in 'sysctls' to the given values.
Packit 2d622a
    """
Packit 2d622a
    if os.getuid() != 0: return
Packit 2d622a
    for (file, val) in sysctls.items():
Packit 2d622a
        fh = open(file, "w")
Packit 2d622a
        fh.write(val)
Packit 2d622a
        fh.close()
Packit 2d622a
Packit 2d622a
def do_shm_test(cmd, limit=None, bits=None, **env):
Packit 2d622a
    """
Packit 2d622a
    Run a test case with temporarily expanded SysV shm limits, testing
Packit 2d622a
    each indicated word size.
Packit 2d622a
    """
Packit 2d622a
    if bits == None:
Packit 2d622a
        bits = wordsizes
Packit 2d622a
    if limit != None:
Packit 2d622a
        tmp = setup_shm_sysctl(limit)
Packit 2d622a
    for b in bits:
Packit 2d622a
        run_test(system_default_hpage_size, b, cmd, **env)
Packit 2d622a
    if limit != None:
Packit 2d622a
        restore_shm_sysctl(tmp)
Packit 2d622a
Packit 2d622a
def functional_tests():
Packit 2d622a
    """
Packit 2d622a
    Run the set of functional tests.
Packit 2d622a
    """
Packit 2d622a
    global linkhuge_wordsizes
Packit 2d622a
Packit 2d622a
    # Kernel background tests not requiring hugepage support
Packit 2d622a
    do_test("zero_filesize_segment")
Packit 2d622a
Packit 2d622a
    # Library background tests not requiring hugepage support
Packit 2d622a
    do_test("test_root")
Packit 2d622a
    do_test("meminfo_nohuge")
Packit 2d622a
Packit 2d622a
    # Library tests requiring kernel hugepage support
Packit 2d622a
    do_test("gethugepagesize")
Packit 2d622a
    do_test("gethugepagesizes")
Packit 2d622a
    do_test("empty_mounts", HUGETLB_VERBOSE="1")
Packit 2d622a
    do_test("large_mounts", HUGETLB_VERBOSE="1")
Packit 2d622a
Packit 2d622a
    # Tests requiring an active and usable hugepage mount
Packit 2d622a
    do_test("find_path")
Packit 2d622a
    do_test("unlinked_fd")
Packit 2d622a
    do_test("readback")
Packit 2d622a
    do_test("truncate")
Packit 2d622a
    do_test("shared")
Packit 2d622a
    do_test("mprotect")
Packit 2d622a
    do_test_with_rlimit(resource.RLIMIT_MEMLOCK, -1, "mlock")
Packit 2d622a
    do_test("misalign")
Packit 2d622a
    do_test("fallocate_basic.sh")
Packit 2d622a
    do_test("fallocate_align.sh")
Packit 2d622a
Packit 2d622a
    # Specific kernel bug tests
Packit 2d622a
    do_test("ptrace-write-hugepage")
Packit 2d622a
    do_test("icache-hygiene")
Packit 2d622a
    do_test("slbpacaflush")
Packit 2d622a
    do_test("straddle_4GB_static", bits=(64,))
Packit 2d622a
    do_test("huge_at_4GB_normal_below_static", bits=(64,))
Packit 2d622a
    do_test("huge_below_4GB_normal_above_static", bits=(64,))
Packit 2d622a
    do_test("map_high_truncate_2")
Packit 2d622a
    do_test("misaligned_offset")
Packit 2d622a
    do_test("truncate_above_4GB")
Packit 2d622a
    do_test("brk_near_huge")
Packit 2d622a
    do_test("task-size-overrun")
Packit 2d622a
    do_test_with_rlimit(resource.RLIMIT_STACK, -1, "stack_grow_into_huge")
Packit 2d622a
    do_test("corrupt-by-cow-opt")
Packit 2d622a
    do_test("noresv-preserve-resv-page")
Packit 2d622a
    do_test("noresv-regarded-as-resv")
Packit 2d622a
Packit 2d622a
    if dangerous == 1:
Packit 2d622a
        do_test("readahead_reserve")
Packit 2d622a
        do_test("madvise_reserve")
Packit 2d622a
        do_test("fadvise_reserve")
Packit 2d622a
        do_test("mremap-expand-slice-collision")
Packit 2d622a
        do_test("mremap-fixed-normal-near-huge")
Packit 2d622a
        do_test("mremap-fixed-huge-near-normal")
Packit 2d622a
    else:
Packit 2d622a
        do_test("readahead_reserve.sh")
Packit 2d622a
        do_test("madvise_reserve.sh")
Packit 2d622a
        do_test("fadvise_reserve.sh")
Packit 2d622a
        do_test("mremap-expand-slice-collision.sh")
Packit 2d622a
        do_test("mremap-fixed-normal-near-huge.sh")
Packit 2d622a
        do_test("mremap-fixed-huge-near-normal.sh")
Packit Service a44172
    do_shm_test("shm-perms", 1024*1024*1024)
Packit 2d622a
Packit 2d622a
    # Tests requiring an active mount and hugepage COW
Packit 2d622a
    do_test("private")
Packit 2d622a
    do_test("fork-cow")
Packit 2d622a
    do_test("direct")
Packit Service d5fae0
    do_test_with_pagesize(system_default_hpage_size, "malloc")
Packit Service d5fae0
    do_test_with_pagesize(system_default_hpage_size, "malloc",
Packit Service d5fae0
                          LD_PRELOAD="libhugetlbfs.so",
Packit Service d5fae0
                          HUGETLB_MORECORE="yes")
Packit Service d5fae0
    do_test_with_pagesize(system_default_hpage_size, "malloc",
Packit Service d5fae0
                          LD_PRELOAD="libhugetlbfs.so",
Packit Service d5fae0
                          HUGETLB_MORECORE="yes",
Packit Service d5fae0
                          HUGETLB_RESTRICT_EXE="unknown:none")
Packit Service d5fae0
    do_test_with_pagesize(system_default_hpage_size, "malloc",
Packit Service d5fae0
                          LD_PRELOAD="libhugetlbfs.so",
Packit Service d5fae0
                          HUGETLB_MORECORE="yes",
Packit Service d5fae0
                          HUGETLB_RESTRICT_EXE="unknown:malloc")
Packit Service d5fae0
    do_test_with_pagesize(system_default_hpage_size, "malloc_manysmall")
Packit Service d5fae0
    do_test_with_pagesize(system_default_hpage_size, "malloc_manysmall",
Packit Service d5fae0
                          LD_PRELOAD="libhugetlbfs.so",
Packit Service d5fae0
                          HUGETLB_MORECORE="yes")
Packit 2d622a
Packit 2d622a
    # After upstream commit: (glibc-2.25.90-688-gd5c3fafc43) glibc has a
Packit 2d622a
    # new per-thread caching mechanism that will NOT allow heapshrink test to
Packit 2d622a
    # successfully measure if heap has shrunk or not due to the fact that
Packit 2d622a
    # heap won't have its sized reduced right away.
Packit 2d622a
    #
Packit 2d622a
    # In order to disable it, you need to have the tunable GLIBC in place.
Packit 2d622a
    # Unfortunately, it requires to be set before program is loaded, as an
Packit 2d622a
    # environment variable, since we can't re-initialize malloc() from the
Packit 2d622a
    # program context (not even with a constructor function), and the tunable
Packit 2d622a
    # is only evaluated during malloc() initialization.
Packit 2d622a
Packit Service d5fae0
    do_test_with_pagesize(system_default_hpage_size, "heapshrink",
Packit Service d5fae0
                          GLIBC_TUNABLES="glibc.malloc.tcache_count=0")
Packit Service d5fae0
    do_test_with_pagesize(system_default_hpage_size, "heapshrink",
Packit Service d5fae0
                          GLIBC_TUNABLES="glibc.malloc.tcache_count=0",
Packit Service d5fae0
                          LD_PRELOAD="libheapshrink.so")
Packit Service d5fae0
    do_test_with_pagesize(system_default_hpage_size, "heapshrink",
Packit Service d5fae0
                          GLIBC_TUNABLES="glibc.malloc.tcache_count=0",
Packit Service d5fae0
                          LD_PRELOAD="libhugetlbfs.so",
Packit Service d5fae0
                          HUGETLB_MORECORE="yes")
Packit Service d5fae0
    do_test_with_pagesize(system_default_hpage_size, "heapshrink",
Packit Service d5fae0
                          GLIBC_TUNABLES="glibc.malloc.tcache_count=0",
Packit Service d5fae0
                          LD_PRELOAD="libhugetlbfs.so libheapshrink.so",
Packit Service d5fae0
                          HUGETLB_MORECORE="yes")
Packit Service d5fae0
    do_test_with_pagesize(system_default_hpage_size, "heapshrink",
Packit Service d5fae0
                          GLIBC_TUNABLES="glibc.malloc.tcache_count=0",
Packit Service d5fae0
                          LD_PRELOAD="libheapshrink.so",
Packit Service d5fae0
                          HUGETLB_MORECORE="yes",
Packit Service d5fae0
                          HUGETLB_MORECORE_SHRINK="yes")
Packit Service d5fae0
    do_test_with_pagesize(system_default_hpage_size, "heapshrink",
Packit Service d5fae0
                          GLIBC_TUNABLES="glibc.malloc.tcache_count=0",
Packit Service d5fae0
                          LD_PRELOAD="libhugetlbfs.so libheapshrink.so",
Packit Service d5fae0
                          HUGETLB_MORECORE="yes",
Packit Service d5fae0
                          HUGETLB_MORECORE_SHRINK="yes")
Packit 2d622a
Packit 2d622a
    do_test("heap-overflow", HUGETLB_VERBOSE="1", HUGETLB_MORECORE="yes")
Packit 2d622a
Packit 2d622a
    # Run the remapping tests' up-front checks
Packit 2d622a
    linkhuge_wordsizes = check_linkhuge_tests()
Packit 2d622a
    # Original elflink tests
Packit 2d622a
    elflink_test("linkhuge_nofd", HUGETLB_VERBOSE="0")
Packit 2d622a
    elflink_test("linkhuge")
Packit 2d622a
Packit 2d622a
    # Only run custom ldscript tests when -l option is set
Packit 2d622a
    if custom_ldscripts:
Packit 2d622a
        # Original elflink sharing tests
Packit 2d622a
        elfshare_test("linkshare")
Packit 2d622a
        elflink_and_share_test("linkhuge")
Packit 2d622a
Packit 2d622a
    # elflink_rw tests
Packit 2d622a
    elflink_rw_test("linkhuge_rw")
Packit 2d622a
    # elflink_rw sharing tests
Packit 2d622a
    elflink_rw_and_share_test("linkhuge_rw")
Packit 2d622a
Packit 2d622a
    # Accounting bug tests
Packit 2d622a
    # reset free hpages because sharing will have held some
Packit 2d622a
    # alternatively, use
Packit 2d622a
    do_test("chunk-overcommit")
Packit 2d622a
    do_test(("alloc-instantiate-race", "shared"))
Packit 2d622a
    do_test(("alloc-instantiate-race", "private"))
Packit 2d622a
    do_test("truncate_reserve_wraparound")
Packit 2d622a
    do_test("truncate_sigbus_versus_oom")
Packit 2d622a
Packit 2d622a
    # Test direct allocation API
Packit 2d622a
    do_test("get_huge_pages")
Packit 2d622a
Packit 2d622a
    # Test overriding of shmget()
Packit 2d622a
    do_shm_test("shmoverride_linked")
Packit 2d622a
    do_shm_test("shmoverride_linked", HUGETLB_SHM="yes")
Packit 2d622a
    do_shm_test("shmoverride_linked_static")
Packit 2d622a
    do_shm_test("shmoverride_linked_static", HUGETLB_SHM="yes")
Packit 2d622a
    do_shm_test("shmoverride_unlinked", LD_PRELOAD="libhugetlbfs.so")
Packit 2d622a
    do_shm_test("shmoverride_unlinked", LD_PRELOAD="libhugetlbfs.so", HUGETLB_SHM="yes")
Packit 2d622a
Packit 2d622a
    # Test hugetlbfs filesystem quota accounting
Packit 2d622a
    do_test("quota.sh")
Packit 2d622a
Packit 2d622a
    # Test accounting of HugePages_{Total|Free|Resv|Surp}
Packit 2d622a
    #  Alters the size of the hugepage pool so should probably be run last
Packit 2d622a
    do_test("counters.sh")
Packit 2d622a
Packit 2d622a
def stress_tests():
Packit 2d622a
    """
Packit 2d622a
    Run the set of stress tests.
Packit 2d622a
    """
Packit 2d622a
    iterations = 10	# Number of iterations for looping tests
Packit 2d622a
Packit 2d622a
    # Don't update NRPAGES every time like above because we want to catch the
Packit 2d622a
    # failures that happen when the kernel doesn't release all of the huge pages
Packit 2d622a
    # after a stress test terminates
Packit Service 608474
    nr_pages = {p: free_hpages(p)[1] for p in pagesizes}
Packit 2d622a
Packit Service 608474
    for p in pagesizes:
Packit Service 608474
        cmd = ("mmap-gettest", repr(iterations), repr(nr_pages[p]))
Packit Service 608474
        do_test_with_pagesize(p, cmd)
Packit 2d622a
Packit Service 608474
    for p in pagesizes:
Packit Service 608474
        # mmap-cow needs a hugepage for each thread plus one extra
Packit Service 608474
        cmd = ("mmap-cow", repr(nr_pages[p]-1), repr(nr_pages[p]))
Packit Service 608474
        do_test_with_pagesize(p, cmd)
Packit 2d622a
Packit 2d622a
    (rc, tot_pages) = total_hpages()
Packit Service 608474
    nr_pages = nr_pages[system_default_hpage_size]
Packit 2d622a
    limit = system_default_hpage_size * tot_pages
Packit 2d622a
    threads = 10	# Number of threads for shm-fork
Packit 2d622a
Packit 2d622a
    # Run shm-fork once using half available hugepages, then once using all
Packit 2d622a
    # This is to catch off-by-ones or races in the kernel allocated that
Packit 2d622a
    # can make allocating all hugepages a problem
Packit 2d622a
    if nr_pages > 1:
Packit Service 46f680
        do_shm_test(("shm-fork", repr(threads), repr(nr_pages // 2)), limit)
Packit 2d622a
    do_shm_test(("shm-fork", repr(threads), repr(nr_pages)), limit)
Packit 2d622a
Packit 2d622a
    do_shm_test(("shm-getraw", repr(nr_pages), "/dev/full"), limit)
Packit 2d622a
Packit 2d622a
    do_test("fallocate_stress.sh")
Packit 2d622a
Packit 2d622a
def print_help():
Packit Service e2dccc
    print("Usage: %s [options]" % sys.argv[0])
Packit Service e2dccc
    print("Options:")
Packit Service e2dccc
    print("  -v	\t Verbose output.")
Packit Service e2dccc
    print("  -V	\t Highly verbose output.")
Packit Service e2dccc
    print("  -f	\t Force all tests.")
Packit Service e2dccc
    print("  -t <set> 	 Run test set, allowed are func and stress.")
Packit Service e2dccc
    print("  -b <wordsize>  Define wordsizes to be used. ")
Packit Service e2dccc
    print("  -p <pagesize>  Define the page sizes to be used.")
Packit Service e2dccc
    print("  -c	\t Do a paranoid pool check.")
Packit Service e2dccc
    print("  -l	\t Use custom ld scripts.")
Packit Service e2dccc
    print("  -h	\t This help.")
Packit 2d622a
    sys.exit(0)
Packit 2d622a
Packit 2d622a
def main():
Packit 2d622a
    global wordsizes, pagesizes, dangerous, paranoid_pool_check, system_default_hpage_size
Packit 2d622a
    global custom_ldscripts
Packit 2d622a
    testsets = set()
Packit 2d622a
    env_override = {"QUIET_TEST": "1", "HUGETLBFS_MOUNTS": "",
Packit 2d622a
                    "HUGETLB_ELFMAP": None, "HUGETLB_MORECORE": None}
Packit 2d622a
    env_defaults = {"HUGETLB_VERBOSE": "0"}
Packit 2d622a
    dangerous = 0
Packit 2d622a
    paranoid_pool_check = False
Packit 2d622a
    custom_ldscripts = False
Packit 2d622a
Packit 2d622a
    try:
Packit 2d622a
        opts, args = getopt.getopt(sys.argv[1:], "vVft:b:p:c:lh")
Packit Service fd4cdd
    except getopt.GetoptError as err:
Packit Service e2dccc
        print(str(err))
Packit 2d622a
        sys.exit(1)
Packit 2d622a
    for opt, arg in opts:
Packit 2d622a
       if opt == "-v":
Packit 2d622a
           env_override["QUIET_TEST"] = None
Packit 2d622a
           env_defaults["HUGETLB_VERBOSE"] = "2"
Packit 2d622a
       elif opt == "-V":
Packit 2d622a
           env_defaults["HUGETLB_VERBOSE"] = "99"
Packit 2d622a
       elif opt == "-f":
Packit 2d622a
           dangerous = 1
Packit 2d622a
       elif opt == "-t":
Packit 2d622a
           for t in arg.split(): testsets.add(t)
Packit 2d622a
       elif opt == "-b":
Packit 2d622a
           for b in arg.split(): wordsizes.add(int(b))
Packit 2d622a
       elif opt == "-p":
Packit 2d622a
           for p in arg.split(): pagesizes.add(int(p))
Packit 2d622a
       elif opt == '-c':
Packit 2d622a
           paranoid_pool_check = True
Packit 2d622a
       elif opt == '-l':
Packit 2d622a
           custom_ldscripts = True
Packit 2d622a
       elif opt == '-h':
Packit 2d622a
           print_help()
Packit 2d622a
       else:
Packit 2d622a
           assert False, "unhandled option"
Packit 2d622a
    if len(testsets) == 0: testsets = set(["func", "stress"])
Packit 2d622a
    if len(wordsizes) == 0: wordsizes = get_wordsizes()
Packit 2d622a
    if len(pagesizes) == 0: pagesizes = get_pagesizes()
Packit 2d622a
Packit 2d622a
    if len(pagesizes) == 0:
Packit Service e2dccc
        print("Unable to find available page sizes, are you sure hugetlbfs")
Packit Service e2dccc
        print("is mounted and there are available huge pages?")
Packit 2d622a
        return 1
Packit 2d622a
Packit 2d622a
    setup_env(env_override, env_defaults)
Packit 2d622a
    init_results()
Packit 2d622a
Packit 2d622a
    (rc, system_default_hpage_size) = hpage_size()
Packit 2d622a
    if rc != 0:
Packit Service e2dccc
        print("Unable to find system default hugepage size.")
Packit Service e2dccc
        print("Is hugepage supported included in this kernel?")
Packit 2d622a
        return 1
Packit 2d622a
Packit 2d622a
    check_hugetlbfs_path()
Packit 2d622a
Packit 2d622a
    if "func" in testsets: functional_tests()
Packit 2d622a
    if "stress" in testsets: stress_tests()
Packit 2d622a
Packit 2d622a
    results_summary()
Packit 2d622a
Packit 2d622a
if __name__ == "__main__":
Packit 2d622a
    main()