Commit 85463321 authored by Joel Savitz's avatar Joel Savitz Committed by Andrew Morton
Browse files

selftests/vm: enable running select groups of tests

Our memory management kernel CI testing at Red Hat uses the VM
selftests and we have run into two problems:

First, our LTP tests overlap with the VM selftests.

We want to avoid unhelpful redundancy in our testing practices.

Second, we have observed the current run_vmtests.sh to report overall
failure/ambiguous results in the case that a machine lacks the necessary
hardware to perform one or more of the tests. E.g. ksm tests that
require more than one numa node.

We want to be able to run the vm selftests suitable to particular hardware.

Add the ability to run one or more groups of vm tests via run_vmtests.sh
instead of simply all-or-none in order to solve these problems.

Preserve existing default behavior of running all tests when the script
is invoked with no arguments.

Documentation of test groups is included in the patch as follows:

    # ./run_vmtests.sh [ -h || --help ]

    usage: ./tools/testing/selftests/vm/run_vmtests.sh [ -h | -t "<categories>"]
      -t: specify specific categories to tests to run
      -h: display this message

    The default behavior is to run all tests.

    Alternatively, specific groups tests can be run by passing a string
    to the -t argument containing one or more of the following categories
    separated by spaces:
    - mmap
	    tests for mmap(2)
    - gup_test
	    tests for gup using gup_test interface
    - userfaultfd
	    tests for  userfaultfd(2)
    - compaction
	    a test for the patch "Allow compaction of unevictable pages"
    - mlock
	    tests for mlock(2)
    - mremap
	    tests for mremap(2)
    - hugevm
	    tests for very large virtual address space
    - vmalloc
	    vmalloc smoke tests
    - hmm
	    hmm smoke tests
    - madv_populate
	    test memadvise(2) MADV_POPULATE_{READ,WRITE} options
    - memfd_secret
	    test memfd_secret(2)
    - process_mrelease
	    test process_mrelease(2)
    - ksm
	    ksm tests that do not require >=2 NUMA nodes
    - ksm_numa
	    ksm tests that require >=2 NUMA nodes
    - pkey
	    memory protection key tests
    - soft_dirty
    	    test soft dirty page bit semantics
    - anon_cow
            test anonymous copy-on-write semantics
    example: ./run_vmtests.sh -t "hmm mmap ksm"

Link: https://lkml.kernel.org/r/20221018231222.1884715-1-jsavitz@redhat.com


Signed-off-by: default avatarJoel Savitz <jsavitz@redhat.com>
Cc: Joel Savitz <jsavitz@redhat.com>
Cc: Nico Pache <npache@redhat.com>
Cc: Shuah Khan <shuah@kernel.org>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
parent 3b910105
Loading
Loading
Loading
Loading
+144 −63
Original line number Diff line number Diff line
#!/bin/bash
# SPDX-License-Identifier: GPL-2.0
#please run as root
# Please run as root

# Kselftest framework requirement - SKIP code is 4.
ksft_skip=4

exitcode=0

usage() {
	cat <<EOF
usage: ${BASH_SOURCE[0]:-$0} [ -h | -t "<categories>"]
  -t: specify specific categories to tests to run
  -h: display this message

The default behavior is to run all tests.

Alternatively, specific groups tests can be run by passing a string
to the -t argument containing one or more of the following categories
separated by spaces:
- mmap
	tests for mmap(2)
- gup_test
	tests for gup using gup_test interface
- userfaultfd
	tests for  userfaultfd(2)
- compaction
	a test for the patch "Allow compaction of unevictable pages"
- mlock
	tests for mlock(2)
- mremap
	tests for mremap(2)
- hugevm
	tests for very large virtual address space
- vmalloc
	vmalloc smoke tests
- hmm
	hmm smoke tests
- madv_populate
	test memadvise(2) MADV_POPULATE_{READ,WRITE} options
- memfd_secret
	test memfd_secret(2)
- process_mrelease
	test process_mrelease(2)
- ksm
	ksm tests that do not require >=2 NUMA nodes
- ksm_numa
	ksm tests that require >=2 NUMA nodes
- pkey
	memory protection key tests
- soft_dirty
	test soft dirty page bit semantics
- cow
	test copy-on-write semantics
example: ./run_vmtests.sh -t "hmm mmap ksm"
EOF
	exit 0
}


while getopts "ht:" OPT; do
	case ${OPT} in
		"h") usage ;;
		"t") VM_SELFTEST_ITEMS=${OPTARG} ;;
	esac
done
shift $((OPTIND -1))

# default behavior: run all tests
VM_SELFTEST_ITEMS=${VM_SELFTEST_ITEMS:-default}

test_selected() {
	if [ "$VM_SELFTEST_ITEMS" == "default" ]; then
		# If no VM_SELFTEST_ITEMS are specified, run all tests
		return 0
	fi
	# If test selected argument is one of the test items
	if [[ " ${VM_SELFTEST_ITEMS[*]} " =~ " ${1} " ]]; then
	        return 0
	else
	        return 1
	fi
}

# get huge pagesize and freepages from /proc/meminfo
while read -r name size unit; do
	if [ "$name" = "HugePages_Free:" ]; then
@@ -62,10 +137,11 @@ if [ -z "$ARCH" ]; then
	ARCH=$(uname -m 2>/dev/null | sed -e 's/aarch64.*/arm64/')
fi
VADDR64=0
echo "$ARCH64STR" | grep "$ARCH" && VADDR64=1
echo "$ARCH64STR" | grep "$ARCH" &>/dev/null && VADDR64=1

# Usage: run_test [test binary] [arbitrary test arguments...]
run_test() {
	if test_selected ${CATEGORY}; then
		local title="running $*"
		local sep=$(echo -n "$title" | tr "[:graph:][:space:]" -)
		printf "%s\n%s\n%s\n" "$sep" "$title" "$sep"
@@ -81,111 +157,116 @@ run_test() {
			echo "[FAIL]"
			exitcode=1
		fi
	fi # test_selected
}

run_test ./hugepage-mmap
CATEGORY="hugetlb" run_test ./hugepage-mmap

shmmax=$(cat /proc/sys/kernel/shmmax)
shmall=$(cat /proc/sys/kernel/shmall)
echo 268435456 > /proc/sys/kernel/shmmax
echo 4194304 > /proc/sys/kernel/shmall
run_test ./hugepage-shm
CATEGORY="hugetlb" run_test ./hugepage-shm
echo "$shmmax" > /proc/sys/kernel/shmmax
echo "$shmall" > /proc/sys/kernel/shmall

run_test ./map_hugetlb
run_test ./hugepage-mremap
run_test ./hugepage-vmemmap
run_test ./hugetlb-madvise
CATEGORY="hugetlb" run_test ./map_hugetlb
CATEGORY="hugetlb" run_test ./hugepage-mremap
CATEGORY="hugetlb" run_test ./hugepage-vmemmap
CATEGORY="hugetlb" run_test ./hugetlb-madvise

echo "NOTE: The above hugetlb tests provide minimal coverage.  Use"
if test_selected "hugetlb"; then
	echo "NOTE: These hugetlb tests provide minimal coverage.  Use"
	echo "      https://github.com/libhugetlbfs/libhugetlbfs.git for"
	echo "      hugetlb regression testing."
fi

run_test ./map_fixed_noreplace
CATEGORY="mmap" run_test ./map_fixed_noreplace

# get_user_pages_fast() benchmark
run_test ./gup_test -u
CATEGORY="gup_test" run_test ./gup_test -u
# pin_user_pages_fast() benchmark
run_test ./gup_test -a
CATEGORY="gup_test" run_test ./gup_test -a
# Dump pages 0, 19, and 4096, using pin_user_pages:
run_test ./gup_test -ct -F 0x1 0 19 0x1000
CATEGORY="gup_test" run_test ./gup_test -ct -F 0x1 0 19 0x1000

uffd_mods=("" ":dev")
for mod in "${uffd_mods[@]}"; do
	run_test ./userfaultfd anon${mod} 20 16
	CATEGORY="userfaultfd" run_test ./userfaultfd anon${mod} 20 16
	# Hugetlb tests require source and destination huge pages. Pass in half
	# the size ($half_ufd_size_MB), which is used for *each*.
	run_test ./userfaultfd hugetlb${mod} "$half_ufd_size_MB" 32
	run_test ./userfaultfd hugetlb_shared${mod} "$half_ufd_size_MB" 32
	run_test ./userfaultfd shmem${mod} 20 16
	CATEGORY="userfaultfd" run_test ./userfaultfd hugetlb${mod} "$half_ufd_size_MB" 32
	CATEGORY="userfaultfd" run_test ./userfaultfd hugetlb_shared${mod} "$half_ufd_size_MB" 32
	CATEGORY="userfaultfd" run_test ./userfaultfd shmem${mod} 20 16
done

#cleanup
echo "$nr_hugepgs" > /proc/sys/vm/nr_hugepages

run_test ./compaction_test
CATEGORY="compaction" run_test ./compaction_test

run_test sudo -u nobody ./on-fault-limit
CATEGORY="mlock" run_test sudo -u nobody ./on-fault-limit

run_test ./map_populate
CATEGORY="mmap" run_test ./map_populate

run_test ./mlock-random-test
CATEGORY="mlock" run_test ./mlock-random-test

run_test ./mlock2-tests
CATEGORY="mlock" run_test ./mlock2-tests

run_test ./mrelease_test
CATEGORY="process_mrelease" run_test ./mrelease_test

run_test ./mremap_test
CATEGORY="mremap" run_test ./mremap_test

run_test ./thuge-gen
CATEGORY="hugetlb" run_test ./thuge-gen

if [ $VADDR64 -ne 0 ]; then
	run_test ./virtual_address_range
	CATEGORY="hugevm" run_test ./virtual_address_range

	# virtual address 128TB switch test
	run_test ./va_128TBswitch.sh
	CATEGORY="hugevm" run_test ./va_128TBswitch.sh
fi # VADDR64

# vmalloc stability smoke test
run_test ./test_vmalloc.sh smoke
CATEGORY="vmalloc" run_test ./test_vmalloc.sh smoke

run_test ./mremap_dontunmap
CATEGORY="mremap" run_test ./mremap_dontunmap

run_test ./test_hmm.sh smoke
CATEGORY="hmm" run_test ./test_hmm.sh smoke

# MADV_POPULATE_READ and MADV_POPULATE_WRITE tests
run_test ./madv_populate
CATEGORY="madv_populate" run_test ./madv_populate

run_test ./memfd_secret
CATEGORY="memfd_secret" run_test ./memfd_secret

# KSM MADV_MERGEABLE test with 10 identical pages
run_test ./ksm_tests -M -p 10
CATEGORY="ksm" run_test ./ksm_tests -M -p 10
# KSM unmerge test
run_test ./ksm_tests -U
CATEGORY="ksm" run_test ./ksm_tests -U
# KSM test with 10 zero pages and use_zero_pages = 0
run_test ./ksm_tests -Z -p 10 -z 0
CATEGORY="ksm" run_test ./ksm_tests -Z -p 10 -z 0
# KSM test with 10 zero pages and use_zero_pages = 1
run_test ./ksm_tests -Z -p 10 -z 1
CATEGORY="ksm" run_test ./ksm_tests -Z -p 10 -z 1
# KSM test with 2 NUMA nodes and merge_across_nodes = 1
run_test ./ksm_tests -N -m 1
CATEGORY="ksm_numa" run_test ./ksm_tests -N -m 1
# KSM test with 2 NUMA nodes and merge_across_nodes = 0
run_test ./ksm_tests -N -m 0
CATEGORY="ksm_numa" run_test ./ksm_tests -N -m 0

CATEGORY="ksm" run_test ./ksm_functional_tests

# protection_keys tests
if [ -x ./protection_keys_32 ]
then
	run_test ./protection_keys_32
	CATEGORY="pkey" run_test ./protection_keys_32
fi

if [ -x ./protection_keys_64 ]
then
	run_test ./protection_keys_64
	CATEGORY="pkey" run_test ./protection_keys_64
fi

run_test ./soft-dirty
CATEGORY="soft_dirty" run_test ./soft-dirty

# COW tests for anonymous memory
run_test ./cow
# COW tests
CATEGORY="cow" run_test ./cow

exit $exitcode