ltp version update to 20250930

Signed-off-by: ccdu <duchangcheng1@h-partners.com>
This commit is contained in:
ccdu
2025-12-19 10:01:59 +08:00
parent 01cd29b193
commit 893ac31e33
2181 changed files with 50479 additions and 62022 deletions
+9
View File
@@ -0,0 +1,9 @@
# Configuration for the `b4` tool
# See https://b4.docs.kernel.org/en/latest/config.html
[b4]
send-series-to = Linux Test Project <ltp@lists.linux.it>
pw-url = https://patchwork.ozlabs.org/
pw-project = ltp
prep-perpatch-check-cmd = ./scripts/checkpatch.pl -q --terse --no-summary --mailback --showfile --no-tree --ignore CONST_STRUCT,VOLATILE,SPLIT_STRING,FILE_PATH_CHANGES
am-perpatch-check-cmd = ./scripts/checkpatch.pl -q --terse --no-summary --mailback --no-tree --ignore CONST_STRUCT,VOLATILE,SPLIT_STRING,FILE_PATH_CHANGES
+1
View File
@@ -0,0 +1 @@
Containerfile
+1
View File
@@ -1,2 +1,3 @@
Petr Vorel <pvorel@suse.cz> <petr.vorel@gmail.com>
Petr Vorel <pvorel@suse.cz> <pevik@users.noreply.github.com>
Xinjian Ma (Fujitsu) <maxj.fnst@fujitsu.com> <maxj.fnst@fujitsu.com>
+26
View File
@@ -0,0 +1,26 @@
version: 2
build:
os: "ubuntu-24.04"
tools:
python: "3.12"
apt_packages:
- autoconf
- enchant-2
- hunspell-en-us
- make
jobs:
# Doc requires to have ltp.json
pre_build:
- make autotools
- ./configure
- make -C metadata/
# Build from the doc/ directory with Sphinx
sphinx:
configuration: doc/conf.py
# Explicitly set the version of Python and its requirements
python:
install:
- requirements: doc/requirements.txt
+35
View File
@@ -0,0 +1,35 @@
# SPDX-License-Identifier: GPL-2.0-or-later
# Copyright (c) 2023 SUSE LLC
ARG PREFIX=docker.io/
ARG DISTRO_NAME=alpine
ARG DISTRO_RELEASE=3.18
FROM $PREFIX$DISTRO_NAME:$DISTRO_RELEASE AS build
ARG LTPROOT=/opt/ltp
ARG DISTRO_NAME=alpine
ARG DISTRO_RELEASE=3.18
RUN mkdir /build
WORKDIR /build
COPY . /build
RUN ./ci/${DISTRO_NAME}.sh
RUN git clean -fdX
RUN ./build.sh -p $LTPROOT -i
FROM $PREFIX$DISTRO_NAME:$DISTRO_RELEASE
ARG LTPROOT=/opt/ltp
ARG KIRKROOT=/opt/kirk
ARG DISTRO_NAME=alpine
COPY --from=build /build/ci/${DISTRO_NAME}-runtime.sh $LTPROOT/runtime-deps.sh
RUN $LTPROOT/runtime-deps.sh
COPY --from=build $LTPROOT $LTPROOT
ENV LTPROOT=$LTPROOT
ENV PATH=$LTPROOT/testcases/bin:$LTPROOT/bin:$PATH
RUN mkdir -p $KIRKROOT
COPY --from=build /build/tools/kirk $KIRKROOT
USER ltp
+18 -57
View File
@@ -55,13 +55,10 @@ in the same directory where the source files reside.
$ make all
$ make \
"DESTDIR=$SYSROOT" \
SKIP_IDCHECK=[0|1] \
install
- Specifying DESTDIR is optional, but required when installing to a non-host
sysroot, as opposed to the host system's sysroot.
- Specify SKIP_IDCHECK=1 if and when you don't want to modify /etc/{group,passwd}
on the target system's sysroot.
If you get a build error, please report it to ltp@lists.linux.it with
following information,
@@ -95,13 +92,10 @@ items which need fixing in the LTP tree.
"top_srcdir=$TOP_SRCDIR" \
"top_builddir=$OUT_OF_BUILD_TREE_DIR" \
"DESTDIR=$SYSROOT" \
SKIP_IDCHECK=[0|1]
install
- Specifying DESTDIR is optional, but required when installing to a non-host
sysroot, as opposed to the host system's sysroot.
- Specify SKIP_IDCHECK=1 if and when you don't want to modify /etc/{group,passwd}
on the target system's sysroot.
Quick Start
-----------
@@ -143,13 +137,7 @@ contributions are welcome.
3. Build and install everything, as described above. Note the minimum software
requirements above before doing so.
4. The disk I/O tests can be run by executing the diskio.sh script. In order
for these tests to successfully operate a writable high-density 3.5" floppy
must be in the disk drive and a CD-ROM with more than 100Mb of data must be
in the CD-ROM drive. The corresponding tests will fail if either disk is
missing.
5. The network tests related installation see testcases/network/README.md.
4. The network tests related installation see testcases/network/README.md.
Cross compiling
---------------
@@ -177,6 +165,22 @@ PKG_CONFIG_LIBDIR=/usr/lib/i386-linux-gnu/pkgconfig CFLAGS=-m32 LDFLAGS=-m32 ./c
* Arch Linux
PKG_CONFIG_LIBDIR=/usr/lib32/pkgconfig CFLAGS=-m32 LDFLAGS=-m32 ./configure
Kernel modules
--------------
LTP contains few kernel modules and tests which are using them.
These require to be built with the same kernel headers as the running kernel (SUT).
Sometimes the best way to achieve this is to compile them on the SUT.
Due Linux Kernel Driver Interface unstability [1], error during building kernel
modules does not break the build. Make errors fatal can be done by FORCE_MODULES=1
make variable.
'modules', 'modules-clean' and 'modules-install' make targets are shortcuts
to build just these modules and tests.
[1] https://docs.kernel.org/process/stable-api-nonsense.html
Android Users
-------------
@@ -202,47 +206,4 @@ LDLIBS - libraries listed after objects during link, e.g. -lc, -lpthread,
-lltp.
For other variables and more info about the build systems see
doc/build-system-guide.txt.
Common Issues
-------------
Issue: When executing configure it says:
checking for a BSD-compatible install... /usr/bin/install -c
checking whether build environment is sane... yes
checking for gawk... gawk
checking whether make sets $(MAKE)... yes
configure: error: cannot run /bin/sh ./config.sub
Solution: You must upgrade autoconf to 0.10.2+ and m4 to 1.4.7+; config.guess and config.sub aren't necessarily generated with older revisions of the Gnu autotools chain.
Issue: When executing make [all] it says:
" *** No rule to make target `/$*', needed by `pan-all'. Stop."
Solution: You must upgrade to make 3.81. Please see the Requirements section above.
Issue: When executing make [all] it says something like:
# ...
install -m 00644 "/scratch/ltp-dev2/ltp/include/test.h" "/scratch/ltp-install12/include/test.h"
install -m 00644 "/scratch/ltp-dev2/ltp/include/tlibio.h" "/scratch/ltp-install12/include/tlibio.h"
install -m 00644 "/scratch/ltp-dev2/ltp/include/usctest.h" "/scratch/ltp-install12/include/usctest.h"
install -m 00644 "/scratch/ltp-dev2/ltp/include/write_log.h" "/scratch/ltp-install12/include/write_log.h"
make[1]: Leaving directory `/scratch/ltp-dev2/ltp/include'
make -C lib -f "/scratch/ltp-dev2/ltp/lib/Makefile" all
make[1]: Entering directory `/scratch/ltp-dev2/ltp/lib'
" *** No rule to make target `dataascii.o', needed by `libltp.a'. Stop." # <-- the error
Solution: You cannot build LTP with -r / --no-builtin-rules and/or
-R / --no-builtin-variables specified. LTP relies heavily on built-in
implicit rules and variables to function properly.
Issue: When executing make (no target, 3.80), it does the following, and doesn't execute all:
#
make -C testcases/realtime autotools
make[1]: Entering directory `/scratch/ltp/testcases/realtime'
autoheader
make[1]: Leaving directory `/scratch/ltp/testcases/realtime'
doc/developers/build_system.rst.
+35 -19
View File
@@ -1,5 +1,5 @@
# SPDX-License-Identifier: GPL-2.0-or-later
# Copyright (c) Linux Test Project, 2009-2022
# Copyright (c) Linux Test Project, 2009-2025
# Copyright (c) Cisco Systems Inc., 2009-2010
# Ngie Cooper, July 2009
@@ -13,7 +13,6 @@ top_srcdir ?= $(CURDIR)
include $(top_srcdir)/include/mk/env_pre.mk
include $(top_srcdir)/include/mk/automake.mk
include $(top_srcdir)/include/mk/gitignore.mk
.SUFFIXES:
.SUFFIXES: .am .default .h .in .m4 .mk
@@ -25,10 +24,6 @@ vpath %.in $(top_srcdir)/include
vpath %.m4 $(top_srcdir)/m4
vpath %.mk $(top_srcdir)/mk:$(top_srcdir)/mk/include
# User wants uclinux binaries?
UCLINUX ?= 0
export UCLINUX
# CLEAN_TARGETS: Targets which exist solely in clean.
# COMMON_TARGETS: Targets which exist in all, clean, and install.
# INSTALL_TARGETS: Targets which exist in clean and install (contains
@@ -36,11 +31,7 @@ export UCLINUX
# BOOTSTRAP_TARGETS: Directories required to bootstrap out-of-build-tree
# support.
# We're not using uclinux based targets (default).
ifneq ($(UCLINUX),1)
COMMON_TARGETS := pan utils
INSTALL_TARGETS := doc
endif
define target_to_dir_dep_mapping
ifeq ($$(filter %-clean,$(1)),) # not *-clean
@@ -105,8 +96,8 @@ $(filter-out include-clean,$(CLEAN_TARGETS))::
# Just like everything depends on include-all / -install, we need to get rid
# of include last to ensure that things won't be monkey screwed up. Only do
# this if we're invoking clean or a subclean directly though.
ifneq ($(filter clean,$(MAKECMDGOALS)),)
# this if we're invoking clean, distclean or a subclean directly though.
ifneq ($(filter clean distclean,$(MAKECMDGOALS)),)
INCLUDE_CLEAN_RDEP_SUBJECT := $(CLEAN_TARGETS)
else
ifneq ($(filter %clean,$(MAKECMDGOALS)),)
@@ -178,6 +169,9 @@ INSTALL_TARGETS += $(addprefix $(DESTDIR)/$(bindir)/,$(BINDIR_INSTALL_SCRIPTS))
$(INSTALL_TARGETS): $(INSTALL_DIR) $(DESTDIR)/$(bindir)
.PHONY: doc
doc: metadata-all
.PHONY: check
check: $(CHECK_TARGETS)
@@ -194,6 +188,7 @@ ifneq ($(build),$(host))
$(error running tests on cross-compile build not supported)
endif
$(call _test)
$(MAKE) test-shell-loader
$(MAKE) test-metadata
test-c: lib-all
@@ -208,17 +203,38 @@ ifneq ($(build),$(host))
endif
$(call _test,-s)
test-shell-loader: lib-all
ifneq ($(build),$(host))
$(error running tests on cross-compile build not supported)
endif
$(top_srcdir)/testcases/lib/run_tests.sh -b $(abs_builddir)
test-metadata: metadata-all
$(MAKE) -C $(abs_srcdir)/metadata/ test
$(MAKE) -C $(abs_srcdir)/metadata test
MODULE_DIRS := $(shell \
dirname $$(grep -l 'include.*module\.mk' $$(find $(abs_srcdir)/testcases/ -type f -name 'Makefile')))
.PHONY: modules modules-clean modules-install
modules:
@$(foreach dir,$(MODULE_DIRS),\
echo "Build $(dir)";\
$(MAKE) -C $(dir) || exit $$?; \
)
modules-clean:
@$(foreach dir,$(MODULE_DIRS),\
echo "Build $(dir)";\
$(MAKE) -C $(dir) clean || exit $$?; \
)
modules-install: modules
@$(foreach dir,$(MODULE_DIRS),\
echo "Build $(dir)";\
$(MAKE) -C $(dir) install || exit $$?; \
)
## Help
.PHONY: help
help:
@echo "Please read the Configuration section in $(top_srcdir)/INSTALL"
@exit 1
## Menuconfig
menuconfig:
@$(SHELL) "$(top_srcdir)/ltpmenu"
## End misc targets.
+1 -1
View File
@@ -3,7 +3,7 @@
"Name" : "ltp",
"License" : "GPL V2.0",
"License File" : "COPYING",
"Version Number" : "20230929",
"Version Number" : "20250930",
"Owner" : "liuxun@huawei.com",
"Upstream URL" : "https://github.com/linux-test-project/ltp",
"Description" : "The LTP testsuite contains a collection of tools for testing the Linux kernel and related features."
-213
View File
@@ -1,213 +0,0 @@
Linux Test Project
==================
Linux Test Project is a joint project started by SGI, OSDL and Bull developed
and maintained by IBM, Cisco, Fujitsu, SUSE, Red Hat, Oracle and others. The
project goal is to deliver tests to the open source community that validate the
reliability, robustness, and stability of Linux.
The LTP testsuite contains a collection of tools for testing the Linux kernel
and related features. Our goal is to improve the Linux kernel and system
libraries by bringing test automation to the testing effort. Interested open
source contributors are encouraged to join.
Project pages are located at: http://linux-test-project.github.io/
The latest image is always available at:
https://github.com/linux-test-project/ltp/releases
The discussion about the project happens at LTP mailing list:
http://lists.linux.it/listinfo/ltp
LTP mailing list is archived at:
https://lore.kernel.org/ltp/
IRC #ltp at: [irc.libera.chat](https://libera.chat/)
The git repository is located at GitHub at:
https://github.com/linux-test-project/ltp
The patchwork instance is at:
https://patchwork.ozlabs.org/project/ltp/list/
Warning!
========
**Be careful with these tests!**
Don't run them on production systems. Growfiles, doio, and iogen in particular
stress the I/O capabilities of systems and while they should not cause problems
on properly functioning systems, they are intended to find (or cause) problems.
Quick guide to running the tests
================================
If you have git, autoconf, automake, m4, pkgconf / pkg-config, libc headers,
linux kernel headers and other common development packages installed (see
INSTALL and ci/*.sh), the chances are the following will work:
```
$ git clone https://github.com/linux-test-project/ltp.git
$ cd ltp
$ make autotools
$ ./configure
```
Now you can continue either with compiling and running a single test or with
compiling and installing the whole testsuite.
For optional library dependencies look into scripts for major distros in
`ci/` directory. You can also build whole LTP with `./build.sh` script.
Shortcut to running a single test
---------------------------------
If you need to execute a single test you actually do not need to compile
the whole LTP, if you want to run a syscall testcase following should work.
```
$ cd testcases/kernel/syscalls/foo
$ make
$ PATH=$PATH:$PWD ./foo01
```
Shell testcases are a bit more complicated since these need a path to a shell
library as well as to compiled binary helpers, but generally following should
work.
```
$ cd testcases/lib
$ make
$ cd ../commands/foo
$ PATH=$PATH:$PWD:$PWD/../../lib/ ./foo01.sh
```
Open Posix Testsuite has it's own build system which needs Makefiles to be
generated first, then compilation should work in subdirectories as well.
```
$ cd testcases/open_posix_testsuite/
$ make generate-makefiles
$ cd conformance/interfaces/foo
$ make
$ ./foo_1-1.run-test
```
Compiling and installing all testcases
--------------------------------------
```
$ make
$ make install
```
This will install LTP to `/opt/ltp`.
* If you have a problem see `INSTALL` and `./configure --help`.
* Failing that, ask for help on the mailing list or Github.
Some tests will be disabled if the configure script can not find their build
dependencies.
* If a test returns `TCONF` due to a missing component, check the `./configure`
output.
* If a tests fails due to a missing user or group, see the Quick Start section
of `INSTALL`.
Running tests
-------------
To run all the test suites
```
$ cd /opt/ltp
$ ./runltp
```
Note that many test cases have to be executed as root.
To run a particular test suite
```
$ ./runltp -f syscalls
```
To run all tests with `madvise` in the name
```
$ ./runltp -f syscalls -s madvise
```
Also see
```
$ ./runltp --help
```
Test suites (e.g. syscalls) are defined in the runtest directory. Each file
contains a list of test cases in a simple format, see doc/ltp-run-files.txt.
Each test case has its own executable or script, these can be executed
directly
```
$ testcases/bin/abort01
```
Some have arguments
```
$ testcases/bin/mesgq\_nstest -m none
```
The vast majority of test cases accept the -h (help) switch
```
$ testcases/bin/ioctl01 -h
```
Many require certain environment variables to be set
```
$ LTPROOT=/opt/ltp PATH="$PATH:$LTPROOT/testcases/bin" testcases/bin/wc01.sh
```
Most commonly, the path variable needs to be set and also `LTPROOT`, but there
are a number of other variables, `runltp` usually sets these for you.
Note that all shell scripts need the `PATH` to be set. However this is not
limited to shell scripts, many C based tests need environment variables as
well.
For more info see `doc/user-guide.txt` or online at
https://github.com/linux-test-project/ltp/wiki/User-Guidelines.
Network tests
-------------
Network tests require certain setup, described in `testcases/network/README.md`
(online at https://github.com/linux-test-project/ltp/tree/master/testcases/network).
Developers corner
=================
Before you start you should read following documents:
* `doc/test-writing-guidelines.txt`
* `doc/build-system-guide.txt`
* `doc/library-api-writing-guidelines.txt`
There is also a step-by-step tutorial:
* `doc/c-test-tutorial-simple.txt`
If something is not covered there don't hesitate to ask on the LTP mailing
list. Also note that these documents are available online at:
* https://github.com/linux-test-project/ltp/wiki/Test-Writing-Guidelines
* https://github.com/linux-test-project/ltp/wiki/LTP-Library-API-Writing-Guidelines
* https://github.com/linux-test-project/ltp/wiki/Build-System
* https://github.com/linux-test-project/ltp/wiki/C-Test-Case-Tutorial
Although we accept GitHub pull requests, the preferred way is sending patches to our mailing list.
It's a good idea to test patches on GitHub Actions before posting to mailing
list. Our GitHub Actions setup covers various architectures and distributions in
order to make sure LTP compiles cleanly on most common configurations.
For testing you need to just push your changes to your own LTP fork on GitHub.
+29
View File
@@ -0,0 +1,29 @@
.. SPDX-License-Identifier: GPL-2.0-or-later
Linux Test Project
==================
Linux Test Project is a joint project started by SGI, OSDL and Bull developed
and maintained by SUSE, Red Hat, Fujitsu, IBM, Cisco, Oracle and others. The
project goal is to deliver tests to the open source community that validate
reliability, robustness, and stability of the Linux Kernel.
The testing suites contain a collection of tools for testing the Linux kernel
and related features. Our goal is to improve the Linux kernel and system
libraries by bringing test automation.
.. warning::
LTP tests shouldn't run in production systems. In particular,
growfiles, doio, and iogen, stress the I/O capabilities of the systems and
they are intended to find (or cause) problems.
Some references:
* `Documentation <http://linux-test-project.rtfd.io/>`_
* `Source code <https://github.com/linux-test-project/ltp>`_
* `Releases <https://github.com/linux-test-project/ltp/releases>`_
* `Mailing List <http://lists.linux.it/listinfo/ltp>`_
* `Working patches (patchwork) <https://patchwork.ozlabs.org/project/ltp/list/>`_
* `Working patches (lore.kernel.org) <https://lore.kernel.org/ltp>`_
* `#ltp @ libera chat <https://libera.chat/>`_
+1 -1
View File
@@ -1 +1 @@
20230929
20250930
+11 -10
View File
@@ -138,7 +138,7 @@ install_in_tree()
install_out_tree()
{
cd $BUILD_DIR
make $MAKE_OPTS_OUT_TREE DESTDIR="$prefix" SKIP_IDCHECK=1 install
make $MAKE_OPTS_OUT_TREE DESTDIR="$prefix" install
}
usage()
@@ -173,13 +173,14 @@ cross cross-compile build (requires set compiler via -c switch)
native native build
RUN:
autotools run only 'make autotools'
configure run only 'configure'
build run only 'make'
test run only 'make test' (not supported for cross-compile build)
test-c run only 'make test-c' (not supported for cross-compile build)
test-shell run only 'make test-shell' (not supported for cross-compile build)
install run only 'make install'
autotools run only 'make autotools'
configure run only 'configure'
build run only 'make'
test run only 'make test' (not supported for cross-compile build)
test-c run only 'make test-c' (not supported for cross-compile build)
test-shell run only 'make test-shell' (not supported for cross-compile build)
test-shell-loader run only 'make test-shell-loader' (not supported for cross-compile build)
install run only 'make install'
Default configure options:
in-tree: $CONFIGURE_OPTS_IN_TREE
@@ -206,7 +207,7 @@ while getopts "c:hio:p:r:t:" opt; do
esac;;
p) prefix="$OPTARG";;
r) case "$OPTARG" in
autotools|configure|build|test|test-c|test-shell|install) run="$OPTARG";;
autotools|configure|build|test|test-c|test-shell|test-shell-loader|install) run="$OPTARG";;
*) echo "Wrong run type '$OPTARG'" >&2; usage; exit 1;;
esac;;
t) case "$OPTARG" in
@@ -232,7 +233,7 @@ if [ -z "$run" -o "$run" = "build" ]; then
eval build_${tree}_tree
fi
if [ -z "$run" -o "$run" = "test" -o "$run" = "test-c" -o "$run" = "test-shell" ]; then
if [ -z "$run" -o "$run" = "test" -o "$run" = "test-c" -o "$run" = "test-shell" -o "$run" = "test-shell-loader" ]; then
if [ "$build" = "cross" ]; then
echo "cross-compile build, skipping running tests" >&2
else
+20
View File
@@ -0,0 +1,20 @@
#!/bin/sh -eux
# SPDX-License-Identifier: GPL-2.0-or-later
# Copyright (c) 2023 SUSE LLC
apk add \
acl \
curl \
jq \
keyutils \
libaio \
libacl \
libcap \
libselinux \
libsepol \
libtirpc \
numactl \
openssl \
py3-msgpack
adduser -D -g "Unprivileged LTP user" ltp
+6 -8
View File
@@ -1,21 +1,21 @@
#!/bin/sh
# Copyright (c) 2019-2022 Petr Vorel <petr.vorel@gmail.com>
set -ex
#!/bin/sh -eux
# SPDX-License-Identifier: GPL-2.0-or-later
# Copyright (c) 2019-2024 Petr Vorel <petr.vorel@gmail.com>
apk update
apk add \
acl-dev \
asciidoc \
asciidoctor \
autoconf \
automake \
clang \
curl \
jq \
gcc \
git \
acl-dev \
keyutils-dev \
libaio-dev \
libacl \
libcap-dev \
libselinux-dev \
libsepol-dev \
@@ -25,7 +25,6 @@ apk add \
musl-dev \
numactl-dev \
openssl-dev \
perl-json \
pkgconfig
cat /etc/os-release
@@ -34,7 +33,6 @@ echo "WARNING: remove unsupported tests (until they're fixed)"
cd $(dirname $0)/..
rm -rfv \
testcases/kernel/syscalls/fmtmsg/fmtmsg01.c \
testcases/kernel/syscalls/rt_tgsigqueueinfo/rt_tgsigqueueinfo01.c \
testcases/kernel/syscalls/timer_create/timer_create01.c \
testcases/kernel/syscalls/timer_create/timer_create03.c
-1
View File
@@ -1 +0,0 @@
fedora.sh
+2 -2
View File
@@ -1,6 +1,6 @@
#!/bin/sh
#!/bin/sh -eux
# SPDX-License-Identifier: GPL-2.0-or-later
# Copyright (c) 2018-2020 Petr Vorel <pvorel@suse.cz>
set -ex
if [ -z "$ARCH" ]; then
echo "missing \$ARCH!" >&2
+10 -8
View File
@@ -1,20 +1,22 @@
#!/bin/sh
# Copyright (c) 2018-2020 Petr Vorel <pvorel@suse.cz>
set -ex
#!/bin/sh -eux
# SPDX-License-Identifier: GPL-2.0-or-later
# Copyright (c) 2018-2024 Petr Vorel <pvorel@suse.cz>
dpkg --add-architecture i386
apt update
apt install -y --no-install-recommends \
curl \
jq \
linux-libc-dev:i386 \
gcc-multilib \
libacl1:i386 \
libaio1:i386 \
libcap2:i386 \
libacl1-dev:i386 \
libaio-dev:i386 \
libcap-dev:i386 \
libc6-dev-i386 \
libc6:i386 \
libkeyutils1:i386 \
libnuma1:i386 \
libkeyutils-dev:i386 \
libnuma-dev:i386 \
libssl-dev:i386 \
libtirpc-dev:i386 \
pkg-config:i386
+4 -20
View File
@@ -1,21 +1,5 @@
#!/bin/sh
# Copyright (c) 2018-2023 Petr Vorel <pvorel@suse.cz>
set -ex
#!/bin/sh -eux
# SPDX-License-Identifier: GPL-2.0-or-later
# Copyright (c) 2018-2024 Petr Vorel <pvorel@suse.cz>
apt="apt remove -y"
$apt \
asciidoc \
asciidoctor \
libacl1-dev \
libaio-dev \
libaio1 \
libcap-dev \
libkeyutils-dev \
libnuma-dev \
libnuma1 \
libselinux1-dev \
libsepol-dev \
libssl-dev
$apt asciidoc-base ruby-asciidoctor || true
ACTION="remove-nonessential" $(dirname $0)/debian.sh
+51 -39
View File
@@ -1,6 +1,6 @@
#!/bin/sh
# Copyright (c) 2018-2021 Petr Vorel <pvorel@suse.cz>
set -ex
#!/bin/sh -eux
# SPDX-License-Identifier: GPL-2.0-or-later
# Copyright (c) 2018-2024 Petr Vorel <pvorel@suse.cz>
# workaround for missing oldstable-updates repository
# W: Failed to fetch http://deb.debian.org/debian/dists/oldstable-updates/main/binary-amd64/Packages
@@ -11,44 +11,56 @@ apt update
# workaround for Ubuntu impish asking to interactively configure tzdata
export DEBIAN_FRONTEND="noninteractive"
apt="apt install -y --no-install-recommends"
install="apt install -y --no-install-recommends"
remove="apt remove -y"
$apt \
acl-dev \
asciidoc \
asciidoctor \
autoconf \
automake \
build-essential \
debhelper \
devscripts \
clang \
gcc \
git \
iproute2 \
libacl1 \
libacl1-dev \
libaio-dev \
libaio1 \
libcap-dev \
libcap2 \
libc6 \
libc6-dev \
libjson-perl \
libkeyutils-dev \
libkeyutils1 \
libmnl-dev \
libnuma-dev \
libnuma1 \
libselinux1-dev \
libsepol-dev \
libssl-dev \
libtirpc-dev \
linux-libc-dev \
lsb-release \
# libc6-dev and libtirpc-dev are hard dependencies for gcc toolchain
# LTP should be compilable without linux-libc-dev, but we expect kernel headers.
pkg_minimal="
autoconf
automake
build-essential
debhelper
devscripts
clang
curl
jq
gcc
git
iproute2
libc6-dev
libtirpc-dev
linux-libc-dev
lsb-release
pkg-config
"
$apt ruby-asciidoctor-pdf || true
$apt asciidoc-dblatex || true
pkg_nonessential="
acl-dev
libacl1-dev
libaio-dev
libcap-dev
libkeyutils-dev
libnuma-dev
libmnl-dev
libselinux1-dev
libsepol-dev
libssl-dev
"
case "$ACTION" in
minimal)
echo "=== Installing only minimal dependencies ==="
$install $pkg_minimal
;;
remove-nonessential)
echo "=== Make sure devel libraries are removed ==="
$remove $pkg_nonessential
;;
*)
echo "=== Installing dependencies ==="
$install $pkg_minimal $pkg_nonessential
;;
esac
df -hT
+12 -7
View File
@@ -1,15 +1,23 @@
#!/bin/sh
#!/bin/sh -eux
# SPDX-License-Identifier: GPL-2.0-or-later
# Copyright (c) 2018-2021 Petr Vorel <pvorel@suse.cz>
set -ex
yum="yum -y install --skip-broken"
if command -v dnf5 >/dev/null 2>&1; then
yum="dnf5 -y install --skip-broken --skip-unavailable"
elif command -v dnf >/dev/null 2>&1; then
yum="dnf -y install --skip-broken"
else
yum="yum -y install --skip-broken"
fi
$yum \
asciidoc \
autoconf \
automake \
make \
clang \
gawk \
curl \
jq \
gcc \
git \
findutils \
@@ -17,11 +25,8 @@ $yum \
numactl-devel \
libtirpc \
libtirpc-devel \
perl-JSON \
perl-libwww-perl \
pkg-config \
redhat-lsb-core
# CentOS 8 fixes
$yum libmnl-devel || $yum libmnl
$yum rubygem-asciidoctor || true
+46 -1
View File
@@ -1 +1,46 @@
tumbleweed.sh
#!/bin/sh -eux
# SPDX-License-Identifier: GPL-2.0-or-later
# Copyright (c) 2018-2025 Petr Vorel <pvorel@suse.cz>
zyp="zypper --non-interactive install --force-resolution --no-recommends"
i=10
while [ $i != 0 ]; do
$zyp \
autoconf \
automake \
clang \
curl \
jq \
findutils \
gcc \
git \
gzip \
iproute2 \
make \
kernel-default-devel \
keyutils-devel \
libacl-devel \
libaio-devel \
libcap-devel \
libmnl-devel \
libnuma-devel \
libopenssl-devel \
libselinux-devel \
libtirpc-devel \
linux-glibc-devel \
lsb-release \
pkg-config
ret=$?
if [ $ret -eq 106 ]; then
echo "Broken repositories, try $i..."
sleep 5
i=$((i-1))
continue
fi
break
done
exit $ret
+32
View File
@@ -0,0 +1,32 @@
#!/bin/sh -eux
# SPDX-License-Identifier: GPL-2.0-or-later
# Copyright (c) 2018-2021 Petr Vorel <pvorel@suse.cz>
if command -v dnf5 >/dev/null 2>&1; then
yum="dnf5 -y install --skip-broken --skip-unavailable"
elif command -v dnf >/dev/null 2>&1; then
yum="dnf -y install --skip-broken"
else
yum="yum -y install --skip-broken"
fi
$yum \
autoconf \
automake \
make \
clang \
gawk \
curl \
jq \
gcc \
git \
findutils \
iproute \
numactl-devel \
libtirpc \
libtirpc-devel \
pkg-config \
redhat-lsb-core
# CentOS 8 fixes
$yum libmnl-devel || $yum libmnl
+197
View File
@@ -0,0 +1,197 @@
#!/bin/sh
# SPDX-License-Identifier: GPL-2.0-or-later
#
# Shell script to communicate with Patchwork via REST API.
# It has been mainly created for CI purposes, but it can be used in the shell
# by satisfying minimum requirements.
#
# Copyright (c) 2025 Andrea Cervesato <andrea.cervesato@suse.com>
PATCHWORK_URL="${PATCHWORK_URL:-https://patchwork.ozlabs.org}"
PATCHWORK_SINCE="${PATCHWORK_SINCE:-3600}"
command_exists() {
local cmd
for cmd in "$@"; do
if ! command -v "$cmd" >/dev/null 2>&1; then
echo "'$1' must be present in the system" >&2
exit 1
fi
done
}
command_exists "curl" "jq"
fetch_series() {
local current_time=$(date +%s)
local since_time=$(expr $current_time - $PATCHWORK_SINCE)
local date=$(date -u -d @$since_time +"%Y-%m-%dT%H:%M:%SZ")
local stdout
stdout=$(curl -k -G "$PATCHWORK_URL/api/events/" \
--data "category=series-completed" \
--data "project=ltp" \
--data "state=new" \
--data "since=$date" \
--data "archive=no")
[ $? -eq 0 ] || exit 1
echo "$stdout" | jq -r '.[] | "\(.payload.series.id) \(.payload.series.mbox)"'
}
get_patches() {
local series_id="$1"
local stdout
stdout="$(curl -k -G $PATCHWORK_URL/api/patches/ \
--data project=ltp \
--data series=$series_id)"
[ $? -eq 0 ] || exit 1
echo "$stdout" | jq -r '.[] | "\(.id)"'
}
verify_token_exists() {
if [ -z "$PATCHWORK_TOKEN" ]; then
echo "For this feature you need \$PATCHWORK_TOKEN"
exit 1
fi
}
set_patch_state() {
local patch_id="$1"
local state="$2"
verify_token_exists
curl -k -X PATCH \
-H "Authorization: Token $PATCHWORK_TOKEN" \
-F "state=$state" \
"$PATCHWORK_URL/api/patches/$patch_id/"
[ $? -eq 0 ] || exit 1
}
set_series_state() {
if [ $# -ne 2 ]; then
echo "'state' command expects 2 parameters ($#)"
exit 1
fi
local series_id="$1"
local state="$2"
get_patches "$series_id" | while read -r patch_id; do
if [ "$patch_id" ]; then
set_patch_state "$patch_id" "$state"
fi
done
}
get_checks() {
local patch_id="$1"
local stdout
stdout="$(curl -k -G $PATCHWORK_URL/api/patches/$patch_id/checks/)"
[ $? -eq 0 ] || exit 1
echo "$stdout" | jq -r '.[] | "\(.id)"'
}
already_tested() {
local series_id="$1"
get_patches "$series_id" | while read -r patch_id; do
[ "$patch_id" ] || continue
get_checks "$patch_id" | while read -r check_id; do
if [ -n "$check_id" ]; then
echo "$check_id"
return
fi
done
done
}
verify_new_patches() {
local tmp=$(mktemp -d)
local output="$tmp/series_ids.txt"
touch "$output"
fetch_series | while read -r series_id series_mbox; do
[ "$series_id" ] || continue
tested=$(already_tested "$series_id")
[ "$tested" ] && continue
echo "$series_id|$series_mbox" >>"$output"
done
cat "$output"
}
send_results() {
if [ $# -ne 4 -a $# -ne 5 ]; then
echo "'check' command expects 4 or 5 parameters ($#)"
exit 1
fi
local series_id="$1"
local target_url="$2"
verify_token_exists
local context=$(echo "$3" | sed 's/:/_/g; s/\//-/g; s/\./-/g')
[ "$CC" ] && context="${context}_${CC}"
[ "$ARCH" ] && context="${context}_${ARCH}"
local result="$4"
[ "$result" = "cancelled" ] && return
local description="${5:-$result}"
local state="fail"
# patchwork REST API allowed states: pending, success, warning, fail.
# https://github.com/getpatchwork/patchwork/blob/main/docs/api/schemas/v1.2/patchwork.yaml#L708
# https://patchwork.readthedocs.io/en/latest/api/rest/schemas/v1.2/#get--api-1.2-patches-patch_id-checks
case "$result" in
success|pending) state=$result;;
esac
get_patches "$series_id" | while read -r patch_id; do
[ "$patch_id" ] || continue
curl -k -X POST \
-H "Authorization: Token $PATCHWORK_TOKEN" \
-F "state=$state" \
-F "context=$context" \
-F "target_url=$target_url" \
-F "description=$description" \
"$PATCHWORK_URL/api/patches/$patch_id/checks/"
[ $? -eq 0 ] || exit 1
done
}
case "$1" in
state)
set_series_state "$2" "$3"
;;
check)
send_results "$2" "$3" "$4" "$5" "$6"
;;
verify)
verify_new_patches
;;
*)
echo "Available commands: state, check, verify" >&2
exit 1
;;
esac
+15
View File
@@ -0,0 +1,15 @@
#!/bin/sh -eux
# SPDX-License-Identifier: GPL-2.0-or-later
# Copyright (c) 2023 SUSE LLC
zyp="zypper --non-interactive install --force-resolution --no-recommends"
$zyp \
iproute2 \
keyutils \
libaio1 \
libmnl0 \
libnuma1 \
libtirpc3
useradd ltp
+42 -29
View File
@@ -1,33 +1,46 @@
#!/bin/sh
# Copyright (c) 2018-2021 Petr Vorel <pvorel@suse.cz>
set -ex
#!/bin/sh -eux
# SPDX-License-Identifier: GPL-2.0-or-later
# Copyright (c) 2018-2025 Petr Vorel <pvorel@suse.cz>
zyp="zypper --non-interactive install --force-resolution --no-recommends"
$zyp \
asciidoc \
autoconf \
automake \
clang \
findutils \
gcc \
git \
gzip \
iproute2 \
make \
kernel-default-devel \
keyutils-devel \
libacl-devel \
libaio-devel \
libcap-devel \
libmnl-devel \
libnuma-devel \
libopenssl-devel \
libselinux-devel \
libtirpc-devel \
linux-glibc-devel \
lsb-release \
perl-JSON \
pkg-config
i=10
while [ $i != 0 ]; do
$zyp \
autoconf \
automake \
clang \
curl \
jq \
findutils \
gcc \
git \
gzip \
iproute2 \
make \
kernel-default-devel \
keyutils-devel \
libacl-devel \
libaio-devel \
libcap-devel \
libmnl-devel \
libnuma-devel \
libopenssl-devel \
libselinux-devel \
libtirpc-devel \
linux-glibc-devel \
lsb-release \
pkg-config
$zyp ruby2.7-rubygem-asciidoctor || $zyp ruby2.5-rubygem-asciidoctor || true
ret=$?
if [ $ret -eq 106 ]; then
echo "Broken repositories, try $i..."
sleep 5
i=$((i-1))
continue
fi
break
done
exit $ret
+66 -1
View File
@@ -1 +1,66 @@
debian.sh
#!/bin/sh -eux
# SPDX-License-Identifier: GPL-2.0-or-later
# Copyright (c) 2018-2024 Petr Vorel <pvorel@suse.cz>
# workaround for missing oldstable-updates repository
# W: Failed to fetch http://deb.debian.org/debian/dists/oldstable-updates/main/binary-amd64/Packages
grep -v oldstable-updates /etc/apt/sources.list > /tmp/sources.list && mv /tmp/sources.list /etc/apt/sources.list
apt update
# workaround for Ubuntu impish asking to interactively configure tzdata
export DEBIAN_FRONTEND="noninteractive"
install="apt install -y --no-install-recommends"
remove="apt remove -y"
# libc6-dev and libtirpc-dev are hard dependencies for gcc toolchain
# LTP should be compilable without linux-libc-dev, but we expect kernel headers.
pkg_minimal="
autoconf
automake
build-essential
debhelper
devscripts
clang
curl
jq
gcc
git
iproute2
libc6-dev
libtirpc-dev
linux-libc-dev
lsb-release
pkg-config
"
pkg_nonessential="
acl-dev
libacl1-dev
libaio-dev
libcap-dev
libkeyutils-dev
libnuma-dev
libmnl-dev
libselinux1-dev
libsepol-dev
libssl-dev
"
case "$ACTION" in
minimal)
echo "=== Installing only minimal dependencies ==="
$install $pkg_minimal
;;
remove-nonessential)
echo "=== Make sure devel libraries are removed ==="
$remove $pkg_nonessential
;;
*)
echo "=== Installing dependencies ==="
$install $pkg_minimal $pkg_nonessential
;;
esac
df -hT
+66 -51
View File
@@ -1,9 +1,14 @@
# Copyright (c) Linux Test Project, 2008-2025
# SPDX-License-Identifier: GPL-2.0-or-later
AC_PREREQ(2.64)
AC_INIT([ltp], [LTP_VERSION], [ltp@lists.linux.it])
AC_CONFIG_AUX_DIR([.])
AM_INIT_AUTOMAKE
AC_CONFIG_HEADERS([include/config.h])
AC_CONFIG_MACRO_DIR([m4])
# Adding files here? Please update include/mk/automake.mk
AC_CONFIG_FILES([ \
include/mk/config.mk \
include/mk/config-openposix.mk \
@@ -27,6 +32,7 @@ AC_PROG_RANLIB
AC_DEFUN([AC_PROG_STRIP], [AC_CHECK_TOOL(STRIP, strip, :)])
AC_PROG_STRIP
AC_PROG_YACC
AC_CHECK_TOOL([OBJCOPY], [objcopy], [:])
m4_ifndef([PKG_CHECK_EXISTS],
[m4_fatal([must install pkg-config or pkgconfig and pkg.m4 macro (usual dependency), see INSTALL])])
@@ -34,16 +40,22 @@ m4_ifndef([PKG_CHECK_EXISTS],
AC_PREFIX_DEFAULT(/opt/ltp)
AC_CHECK_DECLS([IFLA_NET_NS_PID],,,[#include <linux/if_link.h>])
AC_CHECK_DECLS([LANDLOCK_RULE_PATH_BENEATH],,,[#include <linux/landlock.h>])
AC_CHECK_DECLS([LANDLOCK_RULE_NET_PORT],,,[#include <linux/landlock.h>])
AC_CHECK_DECLS([MADV_MERGEABLE],,,[#include <sys/mman.h>])
AC_CHECK_DECLS([NFTA_CHAIN_ID, NFTA_VERDICT_CHAIN_ID],,,[#include <linux/netfilter/nf_tables.h>])
AC_CHECK_DECLS([PR_CAPBSET_DROP, PR_CAPBSET_READ],,,[#include <sys/prctl.h>])
AC_CHECK_DECLS([SEM_STAT_ANY],,,[#include <sys/sem.h>])
AC_CHECK_HEADERS_ONCE([ \
aio.h \
asm/ldt.h \
asm/prctl.h \
cpuid.h \
emmintrin.h \
ifaddrs.h \
keyutils.h \
linux/blkdev.h \
linux/can.h \
linux/cgroupstats.h \
linux/cryptouser.h \
@@ -52,18 +64,22 @@ AC_CHECK_HEADERS_ONCE([ \
linux/fs.h \
linux/futex.h \
linux/genetlink.h \
linux/genhd.h \
linux/if_alg.h \
linux/if_ether.h \
linux/if_packet.h \
linux/io_uring.h \
linux/ioprio.h \
linux/keyctl.h \
linux/landlock.h \
linux/lsm.h \
linux/mempolicy.h \
linux/module.h \
linux/mount.h \
linux/netlink.h \
linux/seccomp.h \
linux/securebits.h \
linux/tls.h \
linux/tty.h \
linux/types.h \
linux/userfaultfd.h \
@@ -74,6 +90,7 @@ AC_CHECK_HEADERS_ONCE([ \
sys/inotify.h \
sys/pidfd.h
sys/prctl.h \
sys/random.h \
sys/shm.h \
sys/timerfd.h \
sys/ustat.h \
@@ -86,6 +103,7 @@ AC_SUBST(HAVE_FTS_H, $have_fts)
AC_CHECK_HEADERS(linux/vm_sockets.h, [], [], [#include <sys/socket.h>])
AC_CHECK_FUNCS_ONCE([ \
cachestat \
clone3 \
close_range \
copy_file_range \
@@ -94,7 +112,8 @@ AC_CHECK_FUNCS_ONCE([ \
execveat \
faccessat2 \
fallocate \
fchownat \
file_getattr \
file_setattr \
fsconfig \
fsmount \
fsopen \
@@ -113,8 +132,6 @@ AC_CHECK_FUNCS_ONCE([ \
mallinfo \
mallinfo2 \
mallopt \
mkdirat \
mknodat \
modify_ldt \
mount_setattr \
move_mount \
@@ -133,9 +150,7 @@ AC_CHECK_FUNCS_ONCE([ \
pwritev2 \
quotactl_fd \
rand_r \
readlinkat \
recvmmsg \
renameat \
renameat2 \
sched_getcpu \
sendmmsg \
@@ -174,20 +189,29 @@ AC_CHECK_TYPES([enum kcmp_type],,,[#include <linux/kcmp.h>])
AC_CHECK_TYPES([struct acct_v3],,,[#include <sys/acct.h>])
AC_CHECK_TYPES([struct af_alg_iv, struct sockaddr_alg],,,[# include <linux/if_alg.h>])
AC_CHECK_TYPES([struct fanotify_event_info_fid, struct fanotify_event_info_error,
struct fanotify_event_info_header, struct fanotify_event_info_pidfd],,,[#include <sys/fanotify.h>])
struct fanotify_event_info_header, struct fanotify_event_info_pidfd,
struct fanotify_event_info_range],,,[#include <sys/fanotify.h>])
AC_CHECK_TYPES([struct file_clone_range],,,[#include <linux/fs.h>])
AC_CHECK_TYPES([struct file_dedupe_range],,,[#include <linux/fs.h>])
AC_CHECK_TYPES([struct procmap_query],,,[#include <linux/fs.h>])
AC_CHECK_TYPES([struct file_handle],,,[
#define _GNU_SOURCE
#include <fcntl.h>
])
AC_CHECK_TYPES([struct fs_quota_statv],,,[#include <xfs/xqm.h>])
AC_CHECK_TYPES([struct fs_quota_statv],,,[
#define _GNU_SOURCE
#include <xfs/xqm.h>
])
AC_CHECK_TYPES([struct if_nextdqblk],,,[#include <linux/quota.h>])
AC_CHECK_TYPES([struct iovec],,,[#include <sys/uio.h>])
AC_CHECK_TYPES([struct ipc64_perm],,,[#include <sys/ipcbuf.h>])
AC_CHECK_TYPES([struct loop_config],,,[#include <linux/loop.h>])
AC_CHECK_TYPES([struct landlock_path_beneath_attr],,,[#include <linux/landlock.h>])
AC_CHECK_TYPES([struct landlock_net_port_attr],,,[#include <linux/landlock.h>])
AC_CHECK_TYPES([struct lsm_ctx],,,[#include <linux/lsm.h>])
AC_CHECK_TYPES([struct mmsghdr],,,[
#define _GNU_SOURCE
#include <sys/types.h>
@@ -222,7 +246,8 @@ AC_CHECK_TYPES([struct xt_entry_match, struct xt_entry_target],,,[
])
AC_CHECK_TYPES([struct __kernel_old_timeval, struct __kernel_old_timespec, struct __kernel_timespec,
struct __kernel_old_itimerspec, struct __kernel_itimerspec],,,[#include <sys/socket.h>])
struct __kernel_old_itimerspec, struct __kernel_itimerspec,
struct __kernel_old_itimerval],,,[#include <sys/socket.h>])
AC_CHECK_TYPES([struct futex_waitv],,,[#include <linux/futex.h>])
AC_CHECK_TYPES([struct mount_attr],,,[
@@ -233,6 +258,25 @@ AC_CHECK_TYPES([struct mount_attr],,,[
#endif
])
AC_CHECK_TYPES([struct cachestat_range],,,[#include <sys/mman.h>])
AC_CHECK_TYPES([struct cachestat],,,[#include <sys/mman.h>])
# Defined in <linux/mount.h>, but include/lapi/mount.h includes <sys/mount.h> */
AC_CHECK_TYPES([struct mnt_id_req],,,[#include <sys/mount.h>])
AC_CHECK_TYPES([struct statmount],,,[#include <sys/mount.h>])
AC_CHECK_MEMBERS([struct statmount.mnt_ns_id],,,[#include <unistd.h>
#include <linux/mount.h>])
AC_CHECK_TYPES([struct pidfd_info],,,[#include <sys/pidfd.h>])
AC_CHECK_TYPES([struct file_attr],,,[#include <linux/fs.h>])
AC_CHECK_TYPES([struct fsxattr],,,[#include <linux/fs.h>])
AC_CHECK_TYPES([struct sockaddr_vm],,,[
#include <sys/socket.h>
#include <linux/vm_sockets.h>
])
# Tools knobs
# Bash
@@ -248,33 +292,6 @@ else
AC_SUBST([WITH_BASH],["no"])
fi
# metadata
AC_ARG_ENABLE([metadata],
[AS_HELP_STRING([--disable-metadata],
[Disable metadata generation (both HTML and PDF, default no)])],
[], [enable_metadata=yes]
)
AC_ARG_ENABLE([metadata_html],
[AS_HELP_STRING([--disable-metadata-html],
[Disable metadata HTML generation (default no)])],
[], [enable_metadata_html=yes]
)
AC_ARG_ENABLE([metadata_pdf],
[AS_HELP_STRING([--enable-metadata-pdf],
[Enable metadata PDF generation (default no)])],
[], [enable_metadata_pdf=no]
)
AC_ARG_WITH([metadata_generator],
[AS_HELP_STRING([--with-metadata-generator=asciidoc|asciidoctor],
[Specify metadata generator to use (default autodetect)])],
[with_metadata_generator=$withval],
[with_metadata_generator=detect]
)
LTP_DOCPARSE
# Expect
AC_ARG_WITH([expect],
[AS_HELP_STRING([--with-expect],
@@ -359,20 +376,18 @@ fi
# TODO: testcases/realtime requires bash and python.
AC_ARG_WITH([realtime-testsuite],
[AS_HELP_STRING([--with-realtime-testsuite],
[compile and install the realtime testsuite])],
[unused, kept for compatibility reason])],
[with_realtime_testsuite=$withval],
[with_realtime_testsuite=no]
)
if test "x$with_realtime_testsuite" = xyes; then
AC_SUBST([WITH_REALTIME_TESTSUITE],["yes"])
# Run configure on testcases/realtime as well.
AC_CONFIG_SUBDIRS([testcases/realtime])
else
AC_SUBST([WITH_REALTIME_TESTSUITE],["no"])
fi
AC_CONFIG_COMMANDS([syscalls.h], [cd ${ac_top_srcdir}/include/lapi/syscalls; ./regen.sh])
AC_CONFIG_COMMANDS([syscalls.h], [cd ${ac_top_srcdir}/include/lapi/syscalls; ./generate_syscalls.sh ../syscalls.h; cd - >/dev/null])
# custom functions
# NOTE: don't create custom functions for simple checks, put them into this file
@@ -386,17 +401,15 @@ LTP_CHECK_FORTIFY_SOURCE
LTP_CHECK_KERNEL_DEVEL
LTP_CHECK_KEYUTILS_SUPPORT
LTP_CHECK_LIBMNL
LTP_CHECK_LINUX_PTRACE
LTP_CHECK_LINUXRANDOM
LTP_CHECK_NOMMU_LINUX
LTP_CHECK_SELINUX
LTP_CHECK_SYNC_ADD_AND_FETCH
LTP_CHECK_SYSCALL_EVENTFD
LTP_CHECK_SYSCALL_FCNTL
LTP_CHECK_FSVERITY
AX_CHECK_COMPILE_FLAG([-no-pie], [LTP_CFLAGS_NOPIE=1])
AX_CHECK_COMPILE_FLAG([-ffixed-ebp], [LTP_CFLAGS_FFIXED_EBP=1])
AC_SUBST([LTP_CFLAGS_NOPIE])
AC_SUBST([LTP_CFLAGS_FFIXED_EBP])
if test "x$with_numa" = xyes; then
LTP_CHECK_SYSCALL_NUMA
@@ -407,7 +420,6 @@ fi
AC_DEFINE_UNQUOTED(NUMA_ERROR_MSG, ["$numa_error_msg"], [Error message when no NUMA support])
LTP_CHECK_SYSCALL_SIGNALFD
LTP_CHECK_SYSCALL_UTIMENSAT
LTP_CHECK_TASKSTATS
test "x$with_tirpc" = xyes && LTP_CHECK_TIRPC
@@ -422,10 +434,12 @@ AC_LINK_IFELSE([AC_LANG_PROGRAM()],
[
AC_MSG_RESULT([yes])
AC_SUBST([WITH_KVM_TESTSUITE],["yes"])
have_kvm=yes
],
[
AC_MSG_RESULT([no])
AC_SUBST([WITH_KVM_TESTSUITE],["no"])
have_kvm=no
])
_AC_LANG_PREFIX[]FLAGS="$ltp_backup_flags"
LDFLAGS="$ltp_backup_ldflags"
@@ -435,8 +449,10 @@ AC_OUTPUT
cat << EOF
TESTSUITES
kernel modules: $WITH_MODULES (kernel: $LINUX_VERSION)
KVM testsuite: $have_kvm
open posix testsuite: ${with_open_posix_testsuite:-no}
realtime testsuite: ${with_realtime_testsuite:-no}
TI-RPC testsuite: ${with_tirpc:-yes}
LIBRARIES
keyutils: ${have_keyutils:-yes}
@@ -448,9 +464,8 @@ libmnl: ${have_libmnl:-yes}
libnuma: ${have_libnuma:-no} (headers: ${have_numa_headers:-yes}, v2 headers: ${have_numa_headers_v2:-no})
libtirpc: ${have_libtirpc:-no}
glibc SUN-RPC: ${have_rpc_glibc:-no}
METADATA
metadata generator: $with_metadata_generator
HTML metadata: $with_metadata_html
PDF metadata: $with_metadata_pdf
EOF
if test "x$with_realtime_testsuite" = xyes; then
AC_MSG_WARN([--with-realtime-testsuite has no effect and is kept for compatibilty reason. It will be removed in the future.])
fi
+6
View File
@@ -0,0 +1,6 @@
.venv/
html/
build/
_static/syscalls.rst
_static/tests.rst
syscalls.tbl
-218
View File
@@ -1,218 +0,0 @@
Short introduction into LTP build system
========================================
******************************************************************************
The following document briefly describes the steps and methodologies used for
the new and improved Makefile system.
Changelog:
* Initial version: Ngie Cooper <yaneurabeya@gmail.com>
* Reformated for asciidoc: Cyril Hrubis <chrubis@suse.cz>
******************************************************************************
The Problem
-----------
The problem with the old Makefile system is that it was very difficult to
maintain and it lacked any sense of formal structure, thus developing for LTP
and including new targets was more difficult than it should have been
(maintenance). Furthermore, proper option-based cross-compilation was
impossible due to the fact that the Makefiles didn't support a prefixing
system, and the appropriate implicit / static rules hadn't been configured to
compile into multiple object directories for out-of-tree build support (ease of
use / functionality). Finally, there wasn't a means to setup dependencies
between components, such that if a component required libltp.a in order to
compile, it would go off and compile libltp.a first (ease of use).
These items needed to be fixed to reduce maintenance nightmares for the
development community contributing to LTP, and the project maintainers.
Design
------
The system was designed such that including a single GNU Makefile compatible
set in each new directory component is all that's essentially required to
build the system.
Say you had a directory like the following (with .c files in them which
directly tie into applications, e.g. baz.c -> baz):
-------------------------------------------------------------------------------
.../foo/
|--> Makefile
|
--> bar/
|
--> Makefile
|
--> baz.c
-------------------------------------------------------------------------------
Here's an example of how one would accomplish that:
-------------------------------------------------------------------------------
.../foo/Makefile:
#
# Copyright disclaimer goes here -- please use GPLv2.
#
top_srcdir ?= ..
include $(top_srcdir)/include/mk/env_pre.mk
include $(top_srcdir)/include/mk/generic_trunk_target.mk
.../foo/bar/Makefile:
#
# Copyright disclaimer goes here -- please use GPLv2.
#
top_srcdir ?= ..
include $(top_srcdir)/include/mk/env_pre.mk
include $(top_srcdir)/include/mk/generic_leaf_target.mk
-------------------------------------------------------------------------------
Kernel Modules
--------------
Some of the tests need to build kernel modules, happily LTP has
infrastructure for this.
-------------------------------------------------------------------------------
ifneq ($(KERNELRELEASE),)
obj-m := module01.o
else
top_srcdir ?= ../../../..
include $(top_srcdir)/include/mk/testcases.mk
REQ_VERSION_MAJOR := 2
REQ_VERSION_PATCH := 6
MAKE_TARGETS := test01 test02 module01.ko
include $(top_srcdir)/include/mk/module.mk
include $(top_srcdir)/include/mk/generic_leaf_target.mk
endif
-------------------------------------------------------------------------------
This is example Makefile that allows you build kernel modules inside of LTP.
The prerequisites for the build are detected by the 'configure' script.
The 'REQ_VERSION_MAJOR' and 'REQ_VERSION_PATCH' describe minimal kernel
version for which the build system tries to build the module.
The buildsystem is also forward compatible with changes in Linux kernel
internal API so that if module fails to build the failure is ignored both on
build and installation. If the userspace counterpart of the test fails to load
the module because the file does not exists, the test is skipped.
Note the 'ifneq($(KERNELRELEASE),)', the reason it's there is that the
Makefile is executed twice, once by LTP build system and once by kernel
kbuild, see 'Documentation/kbuild/modules.txt' in the Linux kernel tree for
details on external module build.
Make Rules and Make Variables
-----------------------------
When using make rules, avoid writing ad hoc rules like:
-------------------------------------------------------------------------------
[prog]: [dependencies]
cc -I../../include $(CFLAGS) $(CPPFLAGS) $(LDFLAGS) $(LDLIBS) \
-o [prog] [dependencies]
-------------------------------------------------------------------------------
etc. This makes cross-compilation and determinism difficult, if not impossible.
Besides, implicit rules are your friends and as long as you use `MAKEOPTS=;' in
the top-level caller (or do $(subst r,$(MAKEOPTS)) to remove -r), the compile
will complete successfully, assuming all other prerequisites have been
fulfilled (libraries, headers, etc).
-------------------------------------------------------------------------------
$(AR) : The library archiver.
$(CC) : The system C compiler.
$(CPP) : The system C preprocessor.
$(CFLAGS) : C compiler flags.
$(CPPFLAGS) : Preprocessor flags, e.g. -I arguments.
$(DEBUG_CFLAGS) : Debug flags to pass to $(CC), -g, etc.
$(KVM_LD) : Special linker for wrapping KVM payload binaries
into linkable object files. Defaults to $(LD).
Change this variable if the KVM Makefile fails
to build files named *-payload.o.
$(LD) : The system linker (typically $(CC), but not
necessarily).
$(LDFLAGS) : What to pass in to the linker, including -L arguments
and other ld arguments, apart from -l library
includes (see $(LDLIBS)).
This should be done in the $(CC) args passing style
when LD := $(CC), e.g. `-Wl,-foo', as opposed to
`-foo'.
$(LDLIBS) : Libraries to pass to the linker (e.g. -lltp, etc).
$(LTPLDLIBS) : LTP internal libraries i.e. these in libs/ directory.
$(OPT_CFLAGS) : Optimization flags to pass into the C compiler, -O2,
etc. If you specify -O2 or higher, you should also
specify -fno-strict-aliasing, because of gcc
fstrict-aliasing optimization bugs in the tree
optimizer. Search for `fstrict-aliasing optimization
bug' with your favorite search engine.
Examples of more recent bugs:
1. tree-optimization/17510
2. tree-optimization/39100
Various bugs have occurred in the past due to buggy
logic in the tree-optimization portion of the gcc
compiler, from 3.3.x to 4.4.
$(RANLIB) : What to run after archiving a library.
$(WCFLAGS) : Warning flags to pass to $(CC), e.g. -Werror,
-Wall, etc.
-------------------------------------------------------------------------------
Make System Variables
---------------------
A series of variables are used within the make system that direct what actions
need to be taken. Rather than me listing the variables here, please with their
intended uses, please refer to the comments contained in
+.../include/mk/env_pre.mk+.
Guidelines and Recommendations
------------------------------
Of course, the GNU Make manual is key to understanding the Make system, but
here are the following sections and chapters I suggest reviewing:
link:http://www.gnu.org/software/make/manual/make.html#Implicit-Rules[Implicit Rules]
link:http://www.gnu.org/software/make/manual/make.html#Using-Variables[Variables and Expansion]
link:http://www.gnu.org/software/make/manual/make.html#Origin-Function[Origin Use]
link:http://www.gnu.org/software/make/manual/make.html#Directory-Search[VPath Use]
Before Committing
-----------------
One should rebuild from scratch before committing. Please see INSTALL for more
details.
Other Errata
------------
Please see TODO for any issues related to the Makefile infrastructure, and
build structure / source tree in general.
File diff suppressed because it is too large Load Diff
-487
View File
@@ -1,487 +0,0 @@
LTP KVM Test API
================
Testing KVM is more complex than other Linux features. Some KVM bugs allow
userspace code running inside the virtual machine to bypass (emulated) hardware
access restrictions and elevate its privileges inside the guest operating
system. The worst types of KVM bugs may even allow the guest code to crash or
compromise the physical host. KVM tests therefore need to be split into two
components a KVM controller program running on the physical host and a guest
payload program running inside the VM. The cooperation of these two components
allows testing even of bugs that somehow cross the virtualization boundary.
NOTE: See also
https://github.com/linux-test-project/ltp/wiki/Test-Writing-Guidelines[Test Writing Guidelines],
https://github.com/linux-test-project/ltp/wiki/C-Test-Case-Tutorial[C Test Case Tutorial],
https://github.com/linux-test-project/ltp/wiki/C-Test-API[C Test API].
1. Basic KVM test structure
---------------------------
KVM tests are simple C source files containing both the KVM controller code
and the guest payload code separated by `#ifdef COMPILE_PAYLOAD` preprocessor
condition. The file will be compiled twice. Once to compile the payload part,
once to compile the KVM controller part and embed the payload binary inside.
The result is a single self-contained binary that'll execute the embedded
payload inside a KVM virtual machine and print results in the same format as
a normal LTP test.
A KVM test source should start with `#include "kvm_test.h"` instead of the
usual `tst_test.h`. The `kvm_test.h` header file will include the other basic
headers appropriate for the current compilation pass. Everything else in the
source file should be enclosed in `#ifdef COMPILE_PAYLOAD ... #else ... #endif`
condition, including any other header file includes. Note that the standard
LTP headers are not available in the payload compilation pass, only the KVM
guest library headers can be included.
.Example KVM test
[source,c]
-------------------------------------------------------------------------------
#include "kvm_test.h"
#ifdef COMPILE_PAYLOAD
/* Guest payload code */
void main(void)
{
tst_res(TPASS, "Hello, world!");
}
#else /* COMPILE_PAYLOAD */
/* KVM controller code */
static struct tst_test test = {
.test_all = tst_kvm_run,
.setup = tst_kvm_setup,
.cleanup = tst_kvm_cleanup,
};
#endif /* COMPILE_PAYLOAD */
-------------------------------------------------------------------------------
The KVM controller code is a normal LTP test and needs to define an instance
of `struct tst_test` with metadata and the usual setup, cleanup, and test
functions. Basic implementation of all three functions is provided by the KVM
host library.
On the other hand, the payload is essentially a tiny kernel that'll run
on bare virtual hardware. It cannot access any files, Linux syscalls, standard
library functions, etc. except for the small subset provided by the KVM guest
library. The payload code must define a `void main(void)` function which will
be the VM entry point of the test.
2. KVM host library
-------------------
The KVM host library provides helper functions for creating and running
a minimal KVM virtual machine.
2.1 Data structures
~~~~~~~~~~~~~~~~~~~
[source,c]
-------------------------------------------------------------------------------
struct tst_kvm_instance {
int vm_fd, vcpu_fd;
struct kvm_run *vcpu_info;
size_t vcpu_info_size;
struct kvm_userspace_memory_region ram[MAX_KVM_MEMSLOTS];
struct tst_kvm_result *result;
};
-------------------------------------------------------------------------------
`struct tst_kvm_instance` holds the file descriptors and memory buffers
of a single KVM virtual machine:
- `int vm_fd` is the main VM file descriptor created by `ioctl(KVM_CREATE_VM)`
- `int vcpu_fd` is the virtual CPU filedescriptor created by
`ioctl(KVM_CREATE_VCPU)`
- `struct kvm_run *vcpu_info` is the VCPU state structure created by
`mmap(vcpu_fd)`
- `size_t vcpu_info_size` is the size of `vcpu_info` buffer
- `struct kvm_userspace_memory_region ram[MAX_KVM_MEMSLOTS]` is the list
of memory slots defined in this VM. Unused memory slots have zero
in the `userspace_addr` field.
- `struct tst_kvm_result *result` is a buffer for passing test result data
from the VM to the controller program, mainly `tst_res()`/`tst_brk()` flags
and messages.
[source,c]
-------------------------------------------------------------------------------
struct tst_kvm_result {
int32_t result;
int32_t lineno;
uint64_t file_addr;
char message[0];
};
-------------------------------------------------------------------------------
`struct tst_kvm_result` is used to pass test results and synchronization data
between the KVM guest and the controller program. Most often, it is used
to pass `tst_res()` and `tst_brk()` messages from the VM, but special values
can also be used to send control flow requests both ways.
- `int32_t result` is the message type, either one of the `TPASS`, `TFAIL`,
`TWARN`, `TBROK`, `TINFO` flags or a special control flow value. Errno flags
are not supported.
- `int32_t lineno` is the line number for `tst_res()`/`tst_brk()` messages.
- `uint64_t file_addr` is the VM address of the filename string for
`tst_res()`/`tst_brk()` messages.
- `char message[0]` is the buffer for arbitrary message data, most often used
to pass `tst_res()`/`tst_brk()` message strings.
2.2 Working with virtual machines
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The KVM host library provides default implementation of the setup, cleanup
and test functions for `struct tst_test` in cases where you do not need
to customize the VM configuration. You can either assign these functions
to the `struct tst_test` instance directly or call them from your own function
that does some additional steps. All three function must be used together.
- `void tst_kvm_setup(void)`
- `void tst_kvm_run(void)`
- `void tst_kvm_cleanup(void)`
Note: `tst_kvm_run()` calls `tst_free_all()`. Calling it will free all
previously allocated guarded buffers.
- `void tst_kvm_validate_result(int value)` Validate whether the value
returned in `struct tst_kvm_result.result` can be safely passed
to `tst_res()` or `tst_brk()`. If the value is not valid, the controller
program will be terminated with error.
- `uint64_t tst_kvm_get_phys_address(const struct tst_kvm_instance *inst,
uint64_t addr)` Converts pointer value (virtual address) from KVM virtual
machine `inst` to the corresponding physical address. Returns 0 if
the virtual address is not mapped to any physical address. If virtual memory
mapping is not enabled in the VM or not available on the arch at all, this
function simply returns `addr` as is.
- `int tst_kvm_find_phys_memslot(const struct tst_kvm_instance *inst,
uint64_t paddr)` Returns index of the memory slot in KVM virtual machine
`inst` which contains the physical address `paddr`. If the address is not
backed by a memory buffer, returns -1.
- `int tst_kvm_find_memslot(const struct tst_kvm_instance *inst,
uint64_t addr)` Returns index of the memory slot in KVM virtual machine
`inst` which contains the virtual address `addr`. If the virtual address
is not mapped to a valid physical address backed by a memory buffer,
returns -1.
- `void *tst_kvm_get_memptr(const struct tst_kvm_instance *inst,
uint64_t addr)` Converts pointer value (virtual address) from KVM virtual
machine `inst` to host-side pointer.
- `void *tst_kvm_alloc_memory(struct tst_kvm_instance *inst, unsigned int slot,
uint64_t baseaddr, size_t size, unsigned int flags)` Allocates a guarded
buffer of given `size` in bytes and installs it into specified memory `slot`
of the KVM virtual machine `inst` at base address `baseaddr`. The buffer
will be automatically page aligned at both ends. See the kernel
documentation of `KVM_SET_USER_MEMORY_REGION` ioctl for list of valid
`flags`. Returns pointer to page-aligned beginning of the allocated buffer.
The actual requested `baseaddr` will be located at
`ret + baseaddr % pagesize`.
- `struct kvm_cpuid2 *tst_kvm_get_cpuid(int sysfd)` Get a list of supported
virtual CPU features returned by `ioctl(KVM_GET_SUPPORTED_CPUID)`.
The argument must be an open file descriptor returned by `open("/dev/kvm")`.
- `void tst_kvm_create_instance(struct tst_kvm_instance *inst,
size_t ram_size)` Creates and fully initializes a new KVM virtual machine
with at least `ram_size` bytes of memory. The VM instance info will be
stored in `inst`.
- `int tst_kvm_run_instance(struct tst_kvm_instance *inst, int exp_errno)`
Executes the program installed in KVM virtual machine `inst`. Any result
messages returned by the VM will be automatically printed to controller
program output. Returns zero. If `exp_errno` is non-zero, the VM execution
syscall is allowed to fail with the `exp_errno` error code and
`tst_kvm_run_instance()` will return -1 instead of terminating the test.
- `void tst_kvm_destroy_instance(struct tst_kvm_instance *inst)` Deletes
the KVM virtual machine `inst`. Note that the guarded buffers assigned
to the VM by `tst_kvm_create_instance()` or `tst_kvm_alloc_memory()` will
not be freed.
The KVM host library does not provide any way to reset a VM instance back
to initial state. Running multiple iterations of the test requires destroying
the old VM instance and creating a new one. Otherwise the VM will exit
without reporting any results on the second iteration and the test will fail.
The `tst_kvm_run()` function handles this issue correctly.
3. KVM guest library
--------------------
The KVM guest library provides a minimal implementation of both the LTP
test library and the standard C library functions. Do not try to include
the usual LTP or C headers in guest payload code, it will not work.
3.1 Standard C functions
~~~~~~~~~~~~~~~~~~~~~~~~
`#include "kvm_test.h"`
The functions listed below are implemented according to the C standard:
- `void *memset(void *dest, int val, size_t size)`
- `void *memzero(void *dest, size_t size)`
- `void *memcpy(void *dest, const void *src, size_t size)`
- `char *strcpy(char *dest, const char *src)`
- `char *strcat(char *dest, const char *src)`
- `size_t strlen(const char *str)`
3.2 LTP library functions
~~~~~~~~~~~~~~~~~~~~~~~~~
`#include "kvm_test.h"`
The KVM guest library currently provides the LTP functions for reporting test
results. All standard result flags except for `T*ERRNO` are supported
with the same rules as usual. However, the printf-like formatting is not
implemented yet.
- `void tst_res(int result, const char *message)`
- `void tst_brk(int result, const char *message) __attribute__((noreturn))`
A handful of useful macros is also available:
- `TST_TEST_TCONF(message)` Generates a test program that will simply print
a `TCONF` message and exit. This is useful when the real test cannot be
built due to missing dependencies or arch limitations.
- `ARRAY_SIZE(arr)` Returns the number of items in statically allocated
array `arr`.
- `LTP_ALIGN(x, a)` Aligns integer `x` to be a multiple of `a`, which
must be a power of 2.
3.3 Arch independent functions
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
`#include "kvm_test.h"`
Memory management in KVM guest library currently uses only primitive linear
buffer for memory allocation. There are no checks whether the VM can allocate
more memory and the already allocated memory cannot be freed.
- `void *tst_heap_alloc(size_t size)` Allocates a block of memory on the heap.
- `void *tst_heap_alloc_aligned(size_t size, size_t align)` Allocates
a block of memory on the heap with the starting address aligned to given
value.
3.4 x86 specific functions
~~~~~~~~~~~~~~~~~~~~~~~~~~
`#include "kvm_test.h"` +
`#include "kvm_x86.h"`
- `struct kvm_interrupt_frame` Opaque arch-dependent structure which holds
interrupt frame information. Use the functions below to get individual values:
- `uintptr_t kvm_get_interrupt_ip(const struct kvm_interrupt_frame *ifrm)`
Get instruction pointer value from interrupt frame structure. This may be
the instruction which caused an interrupt or the one immediately after,
depending on the interrupt vector semantics.
- `int (*tst_interrupt_callback)(void *userdata,
struct kvm_interrupt_frame *ifrm, unsigned long errcode)` Interrupt handler
callback prototype. When an interrupt occurs, the assigned callback function
will be passed the `userdata` pointer that was given
to `tst_set_interrupt_callback()`, interrupt frame `ifrm` and the error
code `errcode` defined by the interrupt vector semantics. If the interrupt
vector does not generate an error code, `errcode` will be set to zero.
The callback function must return 0 if the interrupt was successfully
handled and test execution should resume. Non-zero return value means that
the interrupt could not be handled and the test will terminate with error.
- `void tst_set_interrupt_callback(unsigned int vector,
tst_interrupt_callback func, void *userdata)` Register new interrupt
handler callback function `func` for interrupt `vector`. The `userdata`
argument is an arbitrary pointer that will be passed to `func()` every time
it gets called. The previous interrupt handler callback will be removed.
Setting `func` to `NULL` will remove any existing interrupt handler
from `vector` and the interrupt will become fatal error.
[source,c]
-------------------------------------------------------------------------------
struct page_table_entry_pae {
unsigned int present: 1;
unsigned int writable: 1;
unsigned int user_access: 1;
unsigned int write_through: 1;
unsigned int disable_cache: 1;
unsigned int accessed: 1;
unsigned int dirty: 1;
unsigned int page_type: 1;
unsigned int global: 1;
unsigned int padding: 3;
uint64_t address: 40;
unsigned int padding2: 7;
unsigned int prot_key: 4;
unsigned int noexec: 1;
} __attribute__((__packed__));
struct kvm_cpuid {
unsigned int eax, ebx, ecx, edx;
};
struct kvm_cregs {
unsigned long cr0, cr2, cr3, cr4;
};
struct kvm_sregs {
uint16_t cs, ds, es, fs, gs, ss;
};
-------------------------------------------------------------------------------
`struct page_table_entry_pae` is the page table entry structure for PAE and
64bit paging modes. See Intel(R) 64 and IA-32 Architectures Software
Developer's Manual, Volume 3, Chapter 4 for explanation of the fields.
- `uintptr_t kvm_get_page_address_pae(const struct page_table_entry_pae *entry)`
Returns the physical address of the memory page referenced by the given
page table `entry`. Depending on memory mapping changes done by the test,
the physical address may not be a valid pointer. The caller must determine
whether the address points to another page table entry or a data page, using
the known position in page table hierarchy and `entry->page_type`. Returns
zero if the `entry` does not reference any memory page.
- `void kvm_set_segment_descriptor(struct segment_descriptor *dst, uint64_t baseaddr, uint32_t limit, unsigned int flags)` -
Fill the `dst` segment descriptor with given values. The maximum value
of `limit` is `0xfffff` (inclusive) regardless of `flags`.
- `void kvm_parse_segment_descriptor(struct segment_descriptor *src, uint64_t *baseaddr, uint32_t *limit, unsigned int *flags)` -
Parse data in the `src` segment descriptor and copy them to variables
pointed to by the other arguments. Any parameter except the first one can
be `NULL`.
- `int kvm_find_free_descriptor(const struct segment_descriptor *table, size_t size)` -
Find the first segment descriptor in `table` which does not have
the `SEGFLAG_PRESENT` bit set. The function handles double-size descriptors
correctly. Returns index of the first available descriptor or -1 if all
`size` descriptors are taken.
- `unsigned int kvm_create_stack_descriptor(struct segment_descriptor *table, size_t tabsize, void *stack_base)` -
Convenience function for registering a stack segment descriptor. It'll
automatically find a free slot in `table` and fill the necessary flags.
The `stack_base` pointer must point to the bottom of the stack.
- `void kvm_get_cpuid(unsigned int eax, unsigned int ecx,
struct kvm_cpuid *buf)` Executes the CPUID instruction with the given
`eax` and `ecx` arguments and stores the results in `buf`.
- `void kvm_read_cregs(struct kvm_cregs *buf)` Copies the current values
of control registers to `buf`.
- `void kvm_read_sregs(struct kvm_sregs *buf)` - Copies the current values
of segment registers to `buf`.
- `uint64_t kvm_rdmsr(unsigned int msr)` Returns the current value
of model-specific register `msr`.
- `void kvm_wrmsr(unsigned int msr, uint64_t value)` Stores `value`
into model-specific register `msr`.
- `void kvm_exit(void) __attribute__((noreturn))` Terminate the test.
Similar to calling `exit(0)` in a regular LTP test, although `kvm_exit()`
will terminate only one iteration of the test, not the whole host process.
See Intel(R) 64 and IA-32 Architectures Software Developer's Manual
for documentation of standard and model-specific x86 registers.
3.5 AMD SVM helper functions
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
`#include "kvm_test.h"` +
`#include "kvm_x86.h"` +
`#include "kvm_x86_svm.h"`
The KVM guest library provides basic helper functions for creating and running
nested virtual machines using the AMD SVM technology.
.Example code to execute nested VM
[source,c]
-------------------------------------------------------------------------------
int guest_main(void)
{
...
return 0;
}
void main(void)
{
struct kvm_svm_vcpu *vm;
kvm_init_svm();
vm = kvm_create_svm_vcpu(guest_main, 1);
kvm_svm_vmrun(vm);
}
-------------------------------------------------------------------------------
- `int kvm_is_svm_supported(void)` - Returns non-zero value if the CPU
supports AMD SVM, otherwise returns 0.
- `int kvm_get_svm_state(void)` - Returns non-zero value if SVM is currently
enabled, otherwise returns 0.
- `void kvm_set_svm_state(int enabled)` - Enable or disable SVM according
to argument. If SVM is disabled by host or not supported, the test will exit
with `TCONF`.
- `void kvm_init_svm(void)` - Enable and fully initialize SVM, including
allocating and setting up host save area VMCB. If SVM is disabled by host or
not supported, the test will exit with `TCONF`.
- `struct kvm_vmcb *kvm_alloc_vmcb(void)` - Allocate new VMCB structure
with correct memory alignment and fill it with zeroes.
- `void kvm_vmcb_set_intercept(struct kvm_vmcb *vmcb, unsigned int id, unsigned int state)` -
Set SVM intercept bit `id` to given `state`.
- `void kvm_init_guest_vmcb(struct kvm_vmcb *vmcb, uint32_t asid, uint16_t ss, void *rsp, int (*guest_main)(void))` -
Initialize new SVM virtual machine. The `asid` parameter is the nested
page table ID. The `ss` and `rsp` parameters set the stack segment and stack
pointer values, respectively. The `guest_main` parameter sets the code entry
point of the virtual machine. All control registers, segment registers
(except stack segment register), GDTR and IDTR will be copied
from the current CPU state.
- `struct kvm_svm_vcpu *kvm_create_svm_vcpu(int (*guest_main)(void), int alloc_stack)` -
Convenience function for allocating and initializing new SVM virtual CPU.
The `guest_main` parameter is passed to `kvm_init_guest_vmcb()`,
the `alloc_stack` parameter controls whether a new 8KB stack will be
allocated and registered in GDT. Interception will be enabled for `VMSAVE`
and `HLT` instructions. If you set `alloc_stack` to zero, you must configure
the stack segment register and stack pointer manually.
- `void kvm_svm_vmrun(struct kvm_svm_vcpu *cpu)` - Start or continue execution
of a nested virtual machine. Beware that FPU state is not saved. Do not use
floating point types or values in nested guest code. Also do not use
`tst_res()` or `tst_brk()` functions in nested guest code.
See AMD64 Architecture Programmer's Manual Volume 2 for documentation
of the Secure Virtual Machine (SVM) technology.
4. KVM guest environment
------------------------
KVM guest payload execution begins with bootstrap code which will perform
the minimal guest environment setup required for running C code:
- Activate the appropriate CPU execution mode (IA-32 protected mode
on 32-bit x86 or the 64-bit mode on x86_64).
- Create indentity mapping (virtual address = physical address) of the lower
2GB memory region, even if parts of the region are not backed by any host
memory buffers. The memory region above 2GB threshold is left unmapped
except for one memory page reserved for the `struct tst_kvm_result` buffer.
- Initialize 8KB stack.
- Install default interrupt handlers for standard CPU exception vectors.
When the environment setup is complete, bootstrap will call `void main(void)`
function implemented by the test program. To finish execution of guest payload,
the test can either return from the `main()` function or call `kvm_exit()`
at any point.
@@ -1,84 +0,0 @@
LTP Library API Writing Guidelines
==================================
NOTE: See also
https://github.com/linux-test-project/ltp/wiki/Test-Writing-Guidelines[Test Writing Guidelines],
https://github.com/linux-test-project/ltp/wiki/C-Test-API[C Test API],
https://github.com/linux-test-project/ltp/wiki/Shell-Test-API[Shell Test API].
1. General Rules
----------------
For extending library API it applies the same general rules as for writing tests,
(see https://github.com/linux-test-project/ltp/wiki/Test-Writing-Guidelines[Test Writing Guidelines],
offline: 'doc/test-writing-guidelines.txt'),
with strong focus on readability and simplicity.
Library tests are in 'lib/newlib_tests' directory.
Don't forget to update docs when you change the API.
Environment variables should be listed in
https://github.com/linux-test-project/ltp/wiki/User-Guidelines[LTP User Guidelines]
and in help output (`-h`) for both C and shell API.
2. C API
--------
2.1 LTP-001: Sources have tst_ prefix
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
API source code is in headers in 'include/{empty}*.h', 'include/lapi/{empty}*.h'
(backward compatibility for old kernel and libc) and C sources in 'lib/{empty}*.c'.
Files have `tst_` prefix.
2.2 LTP-002: TST_RET and TST_ERR are not modified
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The test author is guaranteed that the test API will not modify these
variables. This prevents silent errors where the return value and
errno are overwritten before the test has chance to check them.
The macros which are clearly intended to update these variables. That
is `TEST` and those in 'tst_test_macros.h'. Are of course allowed to
update these variables.
2.3 LTP-003: Externally visible library symbols have the tst_ prefix
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Functions, types and variables in the public test API should have the
tst_ prefix. With some exceptions for symbols already prefixed with
`safe_` or `ltp_`.
Static (private) symbols should not have the prefix.
3. Shell API
------------
API source code is in 'tst_test.sh', 'tst_security.sh' and 'tst_net.sh'
(all in 'testcases/lib' directory).
Changes in the shell API should not introduce uncommon dependencies
(use basic commands installed everywhere by default).
3.1 Shell libraries
~~~~~~~~~~~~~~~~~~~
Aside from shell API libraries in 'testcases/lib', it's worth putting
common code for a group of tests into a shell library. The filename
should end with '_lib.sh' and the library should load 'tst_test.sh' or
'tst_net.sh'.
Shell libraries should have conditional expansion for 'TST_SETUP' or 'TST_CLEANUP',
to avoid surprises when test specific setup/cleanup function is redefined by
shell library.
[source,sh]
-------------------------------------------------------------------------------
# ipsec_lib.sh
# SPDX-License-Identifier: GPL-2.0-or-later
TST_SETUP="${TST_SETUP:-ipsec_lib_setup}"
...
. tst_test.sh
-------------------------------------------------------------------------------
-170
View File
@@ -1,170 +0,0 @@
LTP Release Procedure
=====================
1. Release preparations
-----------------------
The release procedure generally takes a few weeks. In the first week or two,
patches that should go into the release are reviewed and possibly merged. These
patches are either fixes or patches pointed out by the community.
Patch review, when finished, is followed by a git freeze, which is a period
where only fixes are pushed to the git. During that period community is
expected to run a LTP pre-release tests, reports problems, and/or send fixes to
the mailing list. In this period we are especially making sure that there are
no regressions in the test results on a wide range of distributions and
architectures.
Once the stabilization period has ended the time has finally come to proceed
with the release.
2. Prepare the release notes
----------------------------
Part of the preparation is also to write the release notes, which are then
added to the GitHub release and also sent as announcement to various mailing
lists (see below).
Have a look at https://lore.kernel.org/ltp/ZGNiQ1sMGvPU_ETp@yuki/ to get the
idea how it should look.
3. Tag the git and push changes to github
-----------------------------------------
[source,sh]
--------------------------------------------------------------------
cd ltp
echo YYYYMMDD > VERSION
git commit -S -s -m 'LTP YYYYMMDD' VERSION
git tag -s -a YYYYMMDD -m 'LTP YYYYMMDD'
git push origin master:master
git push origin YYYYMMDD
--------------------------------------------------------------------
NOTE: The string YYYYMMDD should be substituted to the current date.
NOTE: You can use './tools/tag-release.sh' script to have the above automated.
It allows you to verify the tag before pushing it and does other checks.
[source,sh]
--------------------------------------------------------------------
$ ./tools/tag-release.sh
===== git push =====
new tag: 'YYYYMMDD', previous tag: '20230127'
tag YYYYMMDD
Tagger: Person-who-released LTP <foo@example.com>
Date: ...
LTP YYYYMMDD
-----BEGIN PGP SIGNATURE-----
...
-----END PGP SIGNATURE-----
commit 3ebc2dfa85c2445bb68d8c0d66e33c4da1e1b3a7
gpg: using RSA key ...
...
Primary key fingerprint: ...
Author: Person-who-released LTP <foo@example.com>
Date: ...
LTP YYYYMMDD
Signed-off-by: Person-who-released LTP <foo@example.com>
diff --git a/VERSION b/VERSION
index af4c41fec..ae488c0e7 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-20230127
+YYYYMMDD
Please check tag and signature. Proceed? [N/y]: y
Pushing changes to upstream git. Proceed? [N/y]: y
...
To github.com:linux-test-project/ltp.git
* [new tag] YYYYMMDD -> YYYYMMDD
--------------------------------------------------------------------
4. Prepare tarballs and metadata documentation
----------------------------------------------
[source,sh]
--------------------------------------------------------------------
# clone already clonned git repository to new folder
cd ..
git clone ltp ltp-full-YYYYMMDD
cd ltp-full-YYYYMMDD
# update all submodules
git submodule update --init
# Generate configure script
make autotools
# Generate tarballs
cd ..
tar -cjf ltp-full-YYYYMMDD.tar.bz2 ltp-full-YYYYMMDD --exclude .git
tar -cJf ltp-full-YYYYMMDD.tar.xz ltp-full-YYYYMMDD --exclude .git
# Generate checksums
md5 ltp-full-YYYYMMDD.tar.xz > ltp-full-YYYYMMDD.tar.xz.md5
sha1 ltp-full-YYYYMMDD.tar.xz > ltp-full-YYYYMMDD.tar.xz.sha1
sha256sum ltp-full-YYYYMMDD.tar.xz > ltp-full-YYYYMMDD.tar.xz.sha256
# Generate metadata documentation
./configure --with-metadata-generator=asciidoctor
make -C metadata
cp -v docparse/metadata.html ../metadata.YYYYMMDD.html
--------------------------------------------------------------------
NOTE: You can use './tools/create-tarballs-metadata.sh' script to have the
above automated. All generated files are placed in ltp-release-YYYYMMDD
directory.
[source,sh]
--------------------------------------------------------------------
$ ./tools/create-tarballs-metadata.sh
===== git clone =====
Cloning into 'ltp-full-YYYYMMDD'...
done.
===== Update submodules =====
Submodule 'tools/kirk' (https://github.com/linux-test-project/kirk.git) registered for path 'tools/kirk'
...
===== Generate configure script =====
sed -n '1{s:LTP-:m4_define([LTP_VERSION],[:;s:$:]):;p;q}' VERSION > m4/ltp-version.m4
aclocal -I m4
...
===== Generate tarballs =====
===== Generate checksums =====
===== Generate metadata documentation =====
checking for a BSD-compatible install... /usr/bin/install -c
...
'docparse/metadata.html' -> '/home/foo/ltp-release-YYYYMMDD/metadata.YYYYMMDD.html'
Generated files are in '/home/foo/ltp-release-YYYYMMDD', upload them to github
--------------------------------------------------------------------
5. Upload the generated files to GitHub
---------------------------------------
Click on https://github.com/linux-test-project/ltp/releases['Releases'] then
switch to https://github.com/linux-test-project/ltp/tags['Tags'], then click on
'Add release notes'. There should be 'Attach binaries ...' link at the
bottom of the page.
Don't forget to upload checksums for the tarballs and metadata documentation as well.
5. Send release announcement
----------------------------
The announcement is sent to:
* ltp at lists.linux.it
* linux-kernel at vger.kernel.org
* libc-alpha at sourceware.org
CCed to:
* lwn at lwn.net
* akpm at linux-foundation.org
* torvalds at linux-foundation.org
@@ -1,141 +0,0 @@
# Patch Review
Anyone can and should review patches. It's the only way to get good at
patch review and for the project to scale.
## Goals of patch review
1. Prevent false positive test results
2. Prevent false negative test results
3. Keep the code as simple as possible, but no simpler
## How to find clear errors
A clear error is one where there is unlikely to be any argument if you
provide evidence of it. Evidence being an error trace or logical proof
that an error will occur in a common situation.
The following are examples and may not be appropriate for all tests.
* Merge the patch locally. It should apply cleanly to master.
* Compile the patch with default and non-default configurations.
- Use sanitizers e.g. undefined behaviour, address.
- Compile on non-x86
- Compile on x86 with -m32
* Use `make check`
* Run effected tests in a VM
- Use single vCPU
- Use many vCPUs and enable NUMA
- Restrict RAM to < 1GB.
* Run effected tests on an embedded device
* Run effected tests on non-x86 machine in general
* Run reproducers on a kernel where the bug is present
* Run tests with "-i0"
* Compare usage of system calls with man page descriptions
* Compare usage of system calls with kernel code
* Search the LTP library for existing helper functions
## How to find subtle errors
A subtle error is one where you can expect some argument because you
do not have clear evidence of an error. It is best to state these as
questions and not make assertions if possible.
Although if it is a matter of style or "taste" then senior maintainers
can assert what is correct to avoid bike shedding.
* Ask what happens if there is an error, could it be debugged just
with the test output?
* Are we testing undefined behavior?
- Could future kernel behaviour change without "breaking userland"?
- Does the kernel behave differently depending on hardware?
- Does it behave differently depending on kernel configuration?
- Does it behave differently depending on the compiler?
- Would it behave differently if the order of checks on syscall parameters
changed in the kernel?
* Will it scale to tiny and huge systems?
- What happens if there are 100+ CPUs?
- What happens if each CPU core is very slow?
- What happens if there are 2TB of RAM?
* Are we repeating a pattern that can be turned into a library function?
* Is a single test trying to do too much?
* Could multiple similar tests be merged?
* Race conditions
- What happens if a process gets preempted?
- Could checkpoints or fuzzsync by used instead?
- Note, usually you can insert a sleep to prove a race condition
exists however finding them is hard
* Is there a simpler way to achieve the same kernel coverage?
## How to get patches merged
Once you think a patch is good enough you should add your Reviewed-by
and/or Tested-by tags. This means you will get some credit for getting
the patch merged. Also some blame if there are problems.
If you ran the test you can add the Tested-by tag. If you read the
code or used static analysis tools on it, you can add the Reviewed-by
tag.
In addition you can expect others to review your patches and add their
tags. This will speed up the process of getting your patches merged.
## Maintainers Checklist
Patchset should be tested locally and ideally also in maintainer's fork in
GitHub Actions on GitHub.
NOTE: GitHub Actions do only build testing, passing the CI means only that
the test compiles fine on variety of different distributions and releases.
The test should be executed at least once locally and should PASS as well.
Commit messages should have
* Author's `Signed-off-by` tag
* Committer's `Reviewed-by` or `Signed-off-by` tag
* Check also mailing lists for other reviewers / testers tags, notes and failure reports
* `Fixes: hash` if it fixes particular LTP commit
* `Fixes: #N` if it fixes github issue number N, so it's automatically closed
After patch is accepted or rejected, set correct state and archive in
https://patchwork.ozlabs.org/project/ltp/list/[LTP patchwork instance].
Also update `.github/workflows/wiki-mirror.yml` script which mirrors
`doc/*.txt` to LTP wiki (git URL https://github.com/linux-test-project/ltp.wiki.git)
if new wiki page is added.
## New tests
New test should
* Have a record in runtest file
* Test should work fine with more than one iteration
(e.g. run with `-i 100`)
* Run with `-i 0` to check that setup and cleanup are coded properly (no test is being run)
* Have a brief description
* License: the default license for new tests is GPL v2 or later, use
GPL-2.0-or-later; the licence for test (e.g. GPL-2.0) should not change
unless test is completely rewritten
* Old copyrights should be kept unless test is completely rewritten
### C tests
* Use new https://github.com/linux-test-project/ltp/wiki/Test-Writing-Guidelines#22-writing-a-test-in-c[C API]
* Test binaries are added into corresponding `.gitignore` files
* Check coding style with `make check`
(more in https://github.com/linux-test-project/ltp/wiki/Test-Writing-Guidelines#21-c-coding-style[C coding style])
* Docparse documentation
* If a test is a regression test it should include tags
(more in https://github.com/linux-test-project/ltp/wiki/Test-Writing-Guidelines#2238-test-tags[Test tags])
* When rewriting old tests, https://en.wikipedia.org/wiki/%CE%9CClinux[uClinux]
support should be removed (project has been discontinued).
E.g. remove `#ifdef UCLINUX`, replace `FORK_OR_VFORK()` with simple `fork()` or `SAFE_FORK()`.
### Shell tests
* Use new https://github.com/linux-test-project/ltp/wiki/Test-Writing-Guidelines#23-writing-a-testcase-in-shell[shell API]
* Check coding style with `make check`
(more in https://github.com/linux-test-project/ltp/wiki/Test-Writing-Guidelines#132-shell-coding-style[Shell coding style])
* If a test is a regression test it should include related kernel or glibc commits as a comment
## LTP library
For patchset touching library please check also
https://github.com/linux-test-project/ltp/wiki/LTP-Library-API-Writing-Guidelines[LTP Library API Writing Guidelines].
+31 -5
View File
@@ -1,11 +1,37 @@
# Copyright (c) Linux Test Project, 2024-2025
# SPDX-License-Identifier: GPL-2.0-or-later
# Copyright (C) 2009, Cisco Systems Inc.
# Ngie Cooper, July 2009
top_srcdir ?= ..
top_srcdir ?= ..
include $(top_srcdir)/include/mk/env_pre.mk
RECURSIVE_TARGETS := install
PYTHON := python3
VENV_DIR := .venv
include $(top_srcdir)/include/mk/generic_trunk_target.mk
# only fish and bash/zsh supported
VENV_CMD := if [ "x${FISH_VERSION}" != "x" ]; then . $(VENV_DIR)/bin/activate.fish; else . $(VENV_DIR)/bin/activate; fi
RUN_VENV := if [ -d $(VENV_DIR) ]; then $(VENV_CMD); fi
$(VENV_DIR):
$(PYTHON) -m virtualenv $(VENV_DIR)
$(VENV_CMD) && pip install -r requirements.txt
.PHONY: setup
setup: $(VENV_DIR)
${abs_top_builddir}/metadata/ltp.json:
$(MAKE) -C ${abs_top_builddir}/metadata
all: ${abs_top_builddir}/metadata/ltp.json
$(RUN_VENV); sphinx-build -v -b html . html
spelling:
$(RUN_VENV); sphinx-build -b spelling -d build/doctree . build/spelling
clean:
rm -rf html/ build/ _static/syscalls.rst _static/tests.rst syscalls.tbl \
${abs_top_builddir}/metadata/ltp.json
distclean: clean
rm -rf $(VENV_DIR)
@@ -1,77 +0,0 @@
Supported kernel, libc, toolchain versions
==========================================
1. Build testing with GitHub Actions
------------------------------------
We test master branch in https://github.com/linux-test-project/ltp/actions[GitHub Actions]
to ensure LTP builds on various distributions including old, current and bleeding edge.
We test both gcc and clang toolchains, various architectures with cross-compilation.
For list of tested distros see
https://github.com/linux-test-project/ltp/blob/master/.github/workflows/ci.yml[.github/workflows/ci.yml].
NOTE: GitHub Actions does only build testing, passing the CI means only that
the test compiles fine on variety of different distributions and releases.
GitHub Actions also uses the latest distribution image of a particular release.
1.1 Oldest tested distributions
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
[align="center",options="header"]
|==============================================================
| Distro | kernel | glibc | gcc | clang
| CentOS 7 | 3.10 | 2.17 | 4.8.5 | -
| Ubuntu 18.04 LTS bionic | 4.15 | 2.27 | 7.3.0 | -
| Debian 10 oldstable (buster) | 4.19.37 | 2.28 | 8.3.0 | 7.0
|==============================================================
Older distributions are not officially supported, which means that it
may or may not work. It all depends on your luck. It should be possible
to compile latest LTP even on slightly older distributions than we
support with a few manual tweaks, e.g. disabling manually tests for
newly added syscalls, etc. Trivial fixes/workarounds may be accepted,
but users are encouraged to move to a newer distro.
If latest LTP cannot be compiled even with some amount of workarounds,
you may result to older LTP releases, however these are _not_ supported
in any way. Also if you are trying to run LTP on more than 10 years old
distribution you may as well reconsider you life choices.
1.2 Tested architectures
~~~~~~~~~~~~~~~~~~~~~~~~
[align="center",options="header"]
|==================================
| arch | build
| x86_64 | native
| x86 emulation | native
| aarch64 | cross compilation
| ppc64le | cross compilation
| s390x | cross compilation
|==================================
1.3 Minimal supported kernel version
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Minimal supported kernel version is 3.10.
1.4 Supported libc
~~~~~~~~~~~~~~~~~~
[align="center",options="header"]
|==================================
| Libc | Note
| https://www.gnu.org/software/libc/[GNU C Library (glibc)] | Targeted libc, tested both compilation and actual test results.
| https://uclibc-ng.org/[uClibc-ng] | Although not being tested it should work as well as it attempt to maintain a glibc compatible interface.
| https://www.uclibc.org/[uClibc] | Older https://www.uclibc.org/[uClibc] might have problems.
| https://musl.libc.org/[musl] | Not yet fully supported (see
https://github.com/linux-test-project/ltp/blob/master/ci/alpine.sh[CI script]
for list of files which need to be deleted in order to compile under musl).
| binder (Android) | Please use https://android.googlesource.com/platform/external/ltp/[AOSP fork].
|==================================
1.5 Used C standard
~~~~~~~~~~~~~~~~~~~
LTP compiles with '-std=gnu99'.
-412
View File
@@ -1,412 +0,0 @@
LTP Test Writing Guidelines
===========================
This document describes LTP guidelines and is intended for anybody who want to
write or modify a LTP testcase. It's not a definitive guide and it's not, by
any means, a substitute for common sense.
NOTE: See also
https://github.com/linux-test-project/ltp/wiki/C-Test-API[C Test API],
https://github.com/linux-test-project/ltp/wiki/Shell-Test-API[Shell Test API],
https://github.com/linux-test-project/ltp/wiki/LTP-Library-API-Writing-Guidelines[LTP Library API Writing Guidelines].
Rules and recommendations which are "machine checkable" should be
tagged with an ID like +LTP-XXX+. There will be a corresponding entry
in
https://github.com/linux-test-project/ltp/tree/master/doc/rules.tsv[doc/rules.tsv]. When
you run 'make check' or 'make check-test' it will display these IDs as
a reference.
1. Guide to clean and understandable code
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
For testcases it's required that the source code is as easy to follow as
possible. When a test starts to fail the failure has to be analyzed, clean
test codebase makes this task much easier and quicker.
Here are some hints on how to write clean and understandable code, a few of
these points are further discussed below:
* First of all *Keep things simple*
* Keep function and variable names short but descriptive
* Keep functions reasonably short and focused on a single task
* Do not overcomment
* Be consistent
* Avoid deep nesting
* DRY
1.1 Keep things simple
~~~~~~~~~~~~~~~~~~~~~~
For all it's worth keep the testcases simple or better as simple as possible.
The kernel and libc are tricky beasts and the complexity imposed by their
interfaces is quite high. Concentrate on the interface you want to test and
follow the UNIX philosophy.
It's a good idea to make the test as self-contained as possible too, ideally
tests should not depend on tools or libraries that are not widely available.
Do not reinvent the wheel!
* Use LTP standard interface
* Do not add custom PASS/FAIL reporting functions
* Do not write Makefiles from scratch, use LTP build system instead
* Etc.
1.2 Keep functions and variable names short
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Choosing a good name for an API functions or even variables is a difficult
task do not underestimate it.
There are a couple of customary names for different things that help people to
understand code, for example:
* For loop variables are usually named with a single letter 'i', 'j', ...
* File descriptors 'fd' or 'fd_foo'.
* Number of bytes stored in file are usually named as 'size' or 'len'
* Etc.
1.3 Do not overcomment
~~~~~~~~~~~~~~~~~~~~~~
Comments can sometimes save you day but they can easily do more harm than
good. There has been several cases where comments and actual implementation
drifted slowly apart which yielded into API misuses and hard to find bugs.
Remember there is only one thing worse than no documentation, wrong
documentation.
Ideally everybody should write code that is obvious, which unfortunately isn't
always possible. If there is a code that requires to be commented keep it
short and to the point. These comments should explain *why* and not *how*
things are done.
Never ever comment the obvious.
In case of LTP testcases it's customary to add an asciidoc formatted comment
paragraph with highlevel test description at the beginning of the file right
under the GPL SPDX header. This helps other people to understand the overall
goal of the test before they dive into the technical details. It's also
exported into generated documentation hence it should mostly explain what is
tested.
1.4 DRY (Code duplication)
~~~~~~~~~~~~~~~~~~~~~~~~~~
Copy & paste is a good servant but very poor master. If you are about to copy a
large part of the code from one testcase to another, think what would happen if
you find bug in the code that has been copied all around the tree. What about
moving it to a library instead?
The same goes for short but complicated parts, whenever you are about to copy &
paste a syscall wrapper that packs arguments accordingly to machine
architecture or similarly complicated code, put it into a header instead.
2 Coding style
~~~~~~~~~~~~~~
2.1 C coding style
^^^^^^^^^^^^^^^^^^
LTP adopted Linux kernel coding style:
https://www.kernel.org/doc/html/latest/process/coding-style.html
If you aren't familiar with its rules please read it, it's a well written
introduction.
Run `make check` in the test's directory and/or use `make check-$TCID`,
it uses (among other checks) our vendored version of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/plain/scripts/checkpatch.pl[checkpatch.pl]
script from kernel git tree.
NOTE: If `make check` does not report any problems, the code still may be wrong
as all tools used for checking only look for common mistakes.
2.1.1 LTP-004: Test executable symbols are marked static
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Test executables should not export symbols unnecessarily. This means
that all top-level variables and functions should be marked with the
static keyword. The only visible symbols should be those included from
shared object files.
2.2 Shell coding style
^^^^^^^^^^^^^^^^^^^^^^
When writing testcases in shell write in *portable shell* only, it's a good
idea to try to run the test using alternative shell (alternative to bash, for
example dash) too.
*Portable shell* means Shell Command Language as defined by POSIX with an
exception of few widely used extensions, namely 'local' keyword used inside of
functions and '-o' and '-a' test parameters (that are marked as obsolete in
POSIX).
You can either try to run the testcases on Debian which has '/bin/sh' pointing
to 'dash' by default or install 'dash' on your favorite distribution and use
it to run the tests. If your distribution lacks 'dash' package you can always
compile it from http://gondor.apana.org.au/~herbert/dash/files/[source].
Run `make check` in the test's directory and/or use `make check-$TCID.sh`,
it uses (among other checks) our vendored version of
https://salsa.debian.org/debian/devscripts/raw/master/scripts/checkbashisms.pl[checkbashism.pl]
from Debian, that is used to check for non-portable shell code.
NOTE: If `make check` does not report any problems, the code still may be wrong
as `checkbashisms.pl` used for checking only looks for common mistakes.
Here are some common sense style rules for shell
* Keep lines under 80 chars
* Use tabs for indentation
* Keep things simple, avoid unnecessary subshells
* Don't do confusing things (i.e. don't name your functions like common shell
commands, etc.)
* Quote variables
* Be consistent
3 Backwards compatibility
~~~~~~~~~~~~~~~~~~~~~~~~~
LTP test should be as backward compatible as possible. Think of an enterprise
distributions with long term support (more than five years since the initial
release) or of an embedded platform that needs to use several years old
toolchain supplied by the manufacturer.
Therefore LTP test for more current features should be able to cope with older
systems. It should at least compile fine and if it's not appropriate for the
configuration it should return 'TCONF'.
There are several types of checks we use:
The *configure script* is usually used to detect availability of a function
declarations in system headers. It's used to disable tests at compile time or
to enable fallback definitions.
Checking the *errno* value is another type of runtime check. Most of the
syscalls returns either 'EINVAL' or 'ENOSYS' when syscall was not implemented
or was disabled upon kernel compilation.
LTP has kernel version detection that can be used to disable tests at runtime,
unfortunately kernel version does not always corresponds to a well defined
feature set as distributions tend to backport hundreds of patches while the
kernel version stays the same. Use with caution.
Lately we added kernel '.config' parser, a test can define a boolean
expression of kernel config variables that has to be satisfied in order for a
test to run. This is mostly used for kernel namespaces at the moment.
Sometimes it also makes sense to define a few macros instead of creating
configure test. One example is Linux specific POSIX clock ids in
'include/lapi/posix_clocks.h'.
3.1 Dealing with messed up legacy code
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
LTP still contains a lot of old and messy code and we are cleaning it up as
fast as we can but despite the decade of efforts there is still a lot. If you
start modifying old or a messy testcase and your changes are more complicated
than simple typo fixes you should convert the test into a new library first.
It's also much easier to review the changes if you split them into a smaller
logical groups. The same goes for moving files. If you need a rename or move
file do it in a separate patch.
4 License
~~~~~~~~~
Code contributed to LTP should be licensed under GPLv2+ (GNU GPL version 2 or
any later version).
Use `SPDX-License-Identifier: GPL-2.0-or-later`
5 LTP Structure
~~~~~~~~~~~~~~~
The structure of LTP is quite simple. Each test is a binary written either in
portable shell or C. The test gets a configuration via environment variables
and/or command line parameters, it prints additional information into the
stdout and reports overall success/failure via the exit value.
Tests are generally placed under the 'testcases/' directory. Everything that
is a syscall or (slightly confusingly) libc syscall wrapper goes under
'testcases/kernel/syscalls/'.
Then there is 'testcases/open_posix_testsuite/' which is a well maintained fork
of the upstream project that has been dead since 2005 and also a number of
directories with tests for more specific features.
5.1 Runtest Files
^^^^^^^^^^^^^^^^^
The list of tests to be executed is stored in runtest files under the
'runtest/' directory. The default set of runtest files to be executed is
stored in 'scenario_groups/default'. When you add a test you should add
corresponding entries into some runtest file(s) as well.
For syscall tests (these placed under 'testcases/kernel/syscalls/') use
'runtest/syscalls' file, for kernel related tests for memory management we
have 'runtest/mm', etc.
IMPORTANT: The runtest files should have one entry per a test. Creating a
wrapper that runs all your tests and adding it as a single test
into runtest file is strongly discouraged.
5.2 Datafiles
^^^^^^^^^^^^^
If your test needs datafiles to work, these should be put into a subdirectory
named 'datafiles' and installed into the 'testcases/data/$TCID' directory (to
do that you have to add 'INSTALL_DIR := testcases/data/TCID' into the
'datafiles/Makefile').
You can obtain path to datafiles via $TST_DATAROOT provided by test.sh
'$TST_DATAROOT/...'
or via C function 'tst_dataroot()' provided by libltp:
[source,c]
-------------------------------------------------------------------------------
const char *dataroot = tst_dataroot();
-------------------------------------------------------------------------------
Datafiles can also be accessed as '$LTPROOT/testcases/data/$TCID/...',
but '$TST_DATAROOT' and 'tst_dataroot()' are preferred as these can be used
when running testcases directly in git tree as well as from install
location.
The path is constructed according to these rules:
1. if '$LTPROOT' is set, return '$LTPROOT/testcases/data/$TCID'
2. else if 'tst_tmpdir()' was called return '$STARTWD/datafiles'
(where '$STARTWD' is initial working directory as recorded by 'tst_tmpdir()')
3. else return '$CWD/datafiles'
See 'testcases/commands/file/' for example.
5.3 Subexecutables
^^^^^^^^^^^^^^^^^^
If your test needs to execute a binary, place it in the same directory as the
testcase and name the file starting with '${test_binary_name}_'. Once the
test is executed by the framework, the path to the directory with all LTP
binaries is added to the '$PATH' and you can execute it just by its name.
TIP: If you need to execute such test from the LTP tree, you can add path to
current directory to '$PATH' manually with: 'PATH="$PATH:$PWD" ./foo01'.
6 Test Contribution Checklist
------------------------------
NOTE: See also
https://github.com/linux-test-project/ltp/wiki/Maintainer-Patch-Review-Checklist[Maintainer Patch Review Checklist].
1. Test compiles and runs fine (check with `-i 10` too)
2. `make check` does not emit any warnings for the test you are working on
(hint: run it in the test's directory and/or use `make check-$TCID`)
3. The runtest entries are in place
4. Test binaries are added into corresponding '.gitignore' files
5. Patches apply over the latest git
6.1 About .gitignore files
~~~~~~~~~~~~~~~~~~~~~~~~~~
There are numerous '.gitignore' files in the LTP tree. Usually there is a
'.gitignore' file per a group of tests. The reason for this setup is simple.
It's easier to maintain a '.gitignore' file per directory with tests, rather
than having single file in the project root directory. This way, we don't have
to update all the gitignore files when moving directories, and they get deleted
automatically when a directory with tests is removed.
7 Testing pre-release kernel features
-------------------------------------
Tests for features not yet in a mainline kernel release are accepted. However
they must only be added to the +staging+ runtest file. Once a feature is part
of the stable kernel ABI the associated test must be moved out of staging.
This is primarily to help test kernel RCs by avoiding the need to download
separate LTP patchsets.
8 LTP C And Shell Test API Comparison
-------------------------------------
Comparison of
https://github.com/linux-test-project/ltp/wiki/C-Test-API[C Test API] and
https://github.com/linux-test-project/ltp/wiki/Shell-Test-API[Shell Test API].
[options="header"]
|================================================================================
| C API ('struct tst_test' members) | shell API ('$TST_*' environment variables)
| '.all_filesystems' | 'TST_ALL_FILESYSTEMS'
| '.bufs' |
| '.caps' |
| '.child_needs_reinit' | not applicable
| '.cleanup' | 'TST_CLEANUP'
| '.dev_extra_opts' | 'TST_DEV_EXTRA_OPTS'
| '.dev_fs_opts' | 'TST_DEV_FS_OPTS'
| '.dev_fs_type' | 'TST_FS_TYPE'
| '.dev_min_size' | not applicable
| '.format_device' | 'TST_FORMAT_DEVICE'
| '.max_runtime' |
| '.min_cpus' | not applicable
| '.min_kver' | 'TST_MIN_KVER'
| '.min_mem_avail' | not applicable
| '.mnt_flags' | 'TST_MNT_PARAMS'
| '.min_swap_avail' | not applicable
| '.mntpoint', '.mnt_data' | 'TST_MNTPOINT'
| '.mount_device' | 'TST_MOUNT_DEVICE'
| '.needs_cgroup_ctrls' |
| '.needs_checkpoints' | 'TST_NEEDS_CHECKPOINTS'
| '.needs_cmds' | 'TST_NEEDS_CMDS'
| '.needs_devfs' |
| '.needs_device' | 'TST_NEEDS_DEVICE'
| '.needs_drivers' | 'TST_NEEDS_DRIVERS'
| '.needs_kconfigs' | 'TST_NEEDS_KCONFIGS'
| '.needs_overlay' |
| '.needs_rofs' |
| '.needs_root' | 'TST_NEEDS_ROOT'
| '.needs_tmpdir' | 'TST_NEEDS_TMPDIR'
| '.options' | 'TST_PARSE_ARGS', 'TST_OPTS'
| '.resource_files' |
| '.restore_wallclock' | not applicable
| '.sample' |
| '.save_restore' |
| '.scall' | not applicable
| '.setup' | 'TST_SETUP'
| '.skip_filesystems' | 'TST_SKIP_FILESYSTEMS'
| '.skip_in_compat' |
| '.skip_in_lockdown' | 'TST_SKIP_IN_LOCKDOWN'
| '.skip_in_secureboot' | 'TST_SKIP_IN_SECUREBOOT'
| '.supported_archs' | not applicable
| '.tags' |
| '.taint_check' |
| '.tcnt' | 'TST_CNT'
| '.tconf_msg' | not applicable
| '.test', '.test_all' | 'TST_TESTFUNC'
| '.test_variants' |
| '.timeout' | 'TST_TIMEOUT'
| '.tst_hugepage' | not applicable
| .format_device | 'TST_DEVICE'
| not applicable | 'TST_NEEDS_KCONFIGS_IFS'
| not applicable | 'TST_NEEDS_MODULE'
| not applicable | 'TST_POS_ARGS'
| not applicable | 'TST_USAGE'
|================================================================================
-68
View File
@@ -1,68 +0,0 @@
LTP User Guidelines
===================
For compiling, installing and running the tests see `README.md`.
For running LTP network tests see `testcases/network/README.md`.
1. Library environment variables
--------------------------------
|==============================================================================
| 'KCONFIG_PATH' | The path to the kernel config file, (if not set, it tries
the usual paths '/boot/config-RELEASE' or '/proc/config.gz').
| 'KCONFIG_SKIP_CHECK' | Skip kernel config check if variable set (not set by default).
| 'LTPROOT' | Prefix for installed LTP. **Should be always set**
as some tests need it for path to test data files
('LTP_DATAROOT'). LTP is by default installed into '/opt/ltp'.
| 'LTP_COLORIZE_OUTPUT' | By default LTP colorizes it's output unless it's redirected
to a pipe or file. Force colorized output behaviour:
'y' or '1': always colorize, 'n' or '0': never colorize.
| 'LTP_DEV' | Path to the block device to be used
(C: '.needs_device = 1', shell: 'TST_NEEDS_DEVICE=1').
| 'LTP_SINGLE_FS_TYPE' | Testing only - specifies filesystem instead all
supported (for tests with '.all_filesystems').
| 'LTP_DEV_FS_TYPE' | Filesystem used for testing (default: 'ext2').
| 'LTP_TIMEOUT_MUL' | Multiplies timeout, must be number >= 0.1 (> 1 is useful for
slow machines to avoid unexpected timeout).
Variable is also used in shell tests, but ceiled to int.
| 'LTP_RUNTIME_MUL' | Multiplies maximal test iteration runtime. Tests
that run for more than a second or two are capped on
runtime. You can scale the default runtime both up
and down with this multiplier. NOTE: Not yet implemented
in shell API.
| 'LTP_VIRT_OVERRIDE' | Overrides virtual machine detection in the test
library. Setting it to empty string tell the library
that system is not a virtual machine. Other possible
values are 'kvm', 'xen', 'zvm' and 'microsoft' that
describe different types supervisors.
| 'PATH' | It's required to addjust path:
`PATH="$PATH:$LTPROOT/testcases/bin"`
| 'TMPDIR' | Base directory for template directory (C: '.needs_tmpdir = 1'
and others, which imply it, shell: 'TST_NEEDS_TMPDIR=1').
Must be an absolute path (default: '/tmp').
| 'TST_NO_CLEANUP' | Disable running test cleanup (defined in 'TST_CLEANUP').
|==============================================================================
2. Test execution time and timeout
----------------------------------
The limit on how long a test can run does compose of two parts max_runtime and
timeout. The limit does apply to a single test variant, that means for example
that tests that run for all available filesystems will apply this limit for a
single filesystem only.
The max_runtime is a cap on how long the run() function can take, for most
testcases this part is set to zero. For tests that do run for more than a
second or two the max_runtime has to be defined and the run() function has to
check actively how much runtime is left.
Test runtime can be scaled up and down with 'LTP_RUNTIME_MUL' environment
variable or set on a commandline by the '-I' parameter. Hoewever be vary that
setting the runtime too low will cause long running tests to exit prematurely
possibly before the have a chance actually test anyting.
The timeout part is a limit for the test setup and cleanup and also safety
margin for the runtime accounting. It's currently set to 30 seconds but may
change later. If your target machine is too slow it can be scaled up with the
'LTP_TIMEOUT_MUL' environment variable.
+9
View File
@@ -0,0 +1,9 @@
/* set multiline tables cells */
.wy-table-responsive table td {
white-space: normal;
}
/* remove margin for multiline cells */
.rst-content table td div.line-block {
margin-bottom: 0;
}
+542
View File
@@ -0,0 +1,542 @@
# Configuration file for the Sphinx documentation builder.
#
# For the full list of built-in configuration values, see the documentation:
# https://www.sphinx-doc.org/en/master/usage/configuration.html
import os
import re
import json
import socket
import urllib.request
import sphinx
# -- Project information -----------------------------------------------------
# https://www.sphinx-doc.org/en/master/usage/configuration.html#project-information
project = 'Linux Test Project'
copyright = '2024, Linux Test Project'
author = 'Linux Test Project'
release = '1.0'
ltp_repo = 'https://github.com/linux-test-project/ltp'
ltp_repo_base_url = f"{ltp_repo}/tree/master"
# -- General configuration ---------------------------------------------------
# https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration
extensions = [
'linuxdoc.rstKernelDoc',
'sphinxcontrib.spelling',
'sphinx.ext.autosectionlabel',
'sphinx.ext.extlinks',
]
exclude_patterns = ["html*", '_static*', '.venv*']
extlinks = {
'repo': (f'{ltp_repo}/%s', '%s'),
'master': (f'{ltp_repo}/blob/master/%s', '%s'),
'git_man': ('https://git-scm.com/docs/git-%s', 'git %s'),
'man2': ('https://man7.org/linux/man-pages/man2/%s.2.html', '%s(2)'),
# TODO: allow 2nd parameter to show page description instead of plain URL
'kernel_doc': ('https://docs.kernel.org/%s.html', 'https://docs.kernel.org/%s.html'),
'kernel_tree': ('https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/%s', '%s'),
}
spelling_lang = "en_US"
spelling_warning = True
spelling_exclude_patterns = ['users/stats.rst']
spelling_word_list_filename = "spelling_wordlist"
# -- Options for HTML output -------------------------------------------------
# https://www.sphinx-doc.org/en/master/usage/configuration.html#options-for-html-output
html_theme = 'sphinx_rtd_theme'
html_static_path = ['_static']
def generate_syscalls_stats(_):
"""
Generate statistics for syscalls. We fetch the syscalls list from the kernel
sources, then we compare it with testcases/kernel/syscalls folder and
generate a file that is included in the statistics documentation section.
"""
output = '_static/syscalls.rst'
# sometimes checking testcases/kernel/syscalls file names are not enough,
# because in some cases (i.e. io_ring) syscalls are tested, but they are
# part of a more complex scenario. In the following list, we define syscalls
# which we know they are 100% tested already.
ltp_syscalls_path = "testcases/kernel/syscalls"
white_list = {
'bpf': f'{ltp_syscalls_path}/bpf',
'epoll_pwait2': f'{ltp_syscalls_path}/epoll_pwait',
'fadvise64': f'{ltp_syscalls_path}/fadvise',
'fanotify_init': f'{ltp_syscalls_path}/fanotify',
'fanotify_mark': f'{ltp_syscalls_path}/fanotify',
'file_getattr': f'{ltp_syscalls_path}/file_attr',
'file_setattr': f'{ltp_syscalls_path}/file_attr',
'futex': f'{ltp_syscalls_path}/futex',
'getdents64': f'{ltp_syscalls_path}/gettdents',
'inotify_add_watch': f'{ltp_syscalls_path}/inotify',
'inotify_init': f'{ltp_syscalls_path}/inotify',
'inotify_rm_watch': f'{ltp_syscalls_path}/inotify',
'io_uring_enter': f'{ltp_syscalls_path}/io_uring',
'io_uring_register': f'{ltp_syscalls_path}/io_uring',
'io_uring_setup': f'{ltp_syscalls_path}/io_uring',
'landlock_add_rule': f'{ltp_syscalls_path}/landlock',
'landlock_create_ruleset': f'{ltp_syscalls_path}/landlock',
'landlock_restrict_self': f'{ltp_syscalls_path}/landlock',
'lsetxattr': f'{ltp_syscalls_path}/lgetxattr',
'newfstatat': f'{ltp_syscalls_path}/fstatat',
'pkey_alloc': f'{ltp_syscalls_path}/pkeys',
'pkey_free': f'{ltp_syscalls_path}/pkeys',
'pkey_mprotect': f'{ltp_syscalls_path}/pkeys',
'prlimit64': f'{ltp_syscalls_path}/getrlimit',
'pread64': f'{ltp_syscalls_path}/pread',
'pselect6': f'{ltp_syscalls_path}/pselect',
'pwrite64': f'{ltp_syscalls_path}/pwrite',
'quotactl_fd': f'{ltp_syscalls_path}/quotactl',
'rt_sigpending': f'{ltp_syscalls_path}/sigpending',
'semtimedop': f'{ltp_syscalls_path}/ipc/semop',
'sethostname': f'{ltp_syscalls_path}/sethostname'
}
# populate with not implemented, reserved, unmaintained syscalls defined
# inside the syscalls file
black_list = [
'_newselect',
'_sysctl',
'afs_syscall',
'cachectl',
'create_module',
'get_kernel_syms',
'getmsg',
'getpmsg',
'mq_getsetattr',
'nfsservctl',
'putmsg',
'putpmsg',
'query_module',
'reserved177',
'reserved193',
'restart_syscall',
'rseq',
'sysmips',
'vserver',
]
# fetch syscalls file
syscalls_url = "https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/plain/arch/mips/kernel/syscalls"
error = False
try:
socket.setdefaulttimeout(3)
# kernel.org doesn't always allow to download syscalls file, so we need
# to emulate a different client in order to download it. Browser
# emulation might fail due to captcha request and for this reason we
# use the 'curl' command instead
req = urllib.request.Request(
f"{syscalls_url}/syscall_n64.tbl",
headers={'User-Agent': 'curl/8.6.0'})
with urllib.request.urlopen(req) as response:
with open("syscalls.tbl", 'wb') as out_file:
out_file.write(response.read())
except urllib.error.URLError as err:
error = True
logger = sphinx.util.logging.getLogger(__name__)
msg = f"Can't download syscall_n64.tbl from kernel sources ({err})"
logger.warning(msg)
with open(output, 'w+', encoding='utf-8') as stats:
stats.write(f".. warning::\n\n {msg}")
if error:
return
text = [
'Syscalls\n',
'--------\n\n',
]
# collect all available kernel syscalls
regexp = re.compile(r'\d+\s+n64\s+(?P<syscall>\w+)\s+\w+')
ker_syscalls = []
with open("syscalls.tbl", 'r', encoding='utf-8') as data:
for line in data:
match = regexp.search(line)
if not match:
continue
ker_syscalls.append(match.group('syscall'))
# collect all LTP tested syscalls
name_patterns = [
re.compile(r'(?P<name>[a-zA-Z_]+[^_])\d{2}\.c'),
re.compile(r'(?P<name>[a-zA-Z_]+[1-9])_\d{2}\.c'),
]
ltp_syscalls = {}
for dirpath, _, files in os.walk(f'../{ltp_syscalls_path}'):
for myfile in files:
match = None
for pattern in name_patterns:
match = pattern.search(myfile)
if match:
break
if not match:
continue
# we need to use relative path from the project root
path = dirpath.replace('../', '')
name = match.group('name')
ltp_syscalls[name] = f'{ltp_repo_base_url}/{path}'
# compare kernel syscalls with LTP tested syscalls
syscalls = {}
for kersc in ker_syscalls:
if kersc in black_list:
continue
if kersc not in syscalls:
if kersc in white_list:
syscalls[kersc] = f'{ltp_repo_base_url}/{white_list[kersc]}'
continue
syscalls[kersc] = None
for ltpsc, ltpsp in ltp_syscalls.items():
if ltpsc == kersc:
syscalls[kersc] = ltpsp
# generate the statistics file
tested_syscalls = [key for key, val in syscalls.items() if val is not None]
text.append('syscalls which are tested under '
':master:`testcases/kernel/syscalls`:\n\n')
text.append(f'* kernel syscalls: {len(ker_syscalls)}\n')
text.append(f'* tested syscalls: {len(tested_syscalls)}\n\n')
# create tested/untested syscalls table
index_tested = 0
table_tested = [
'Tested syscalls\n',
'~~~~~~~~~~~~~~~\n\n',
'.. list-table::\n',
' :header-rows: 0\n\n',
]
index_untest = 0
table_untest = [
'Untested syscalls\n',
'~~~~~~~~~~~~~~~~~\n\n',
'.. list-table::\n',
' :header-rows: 0\n\n',
]
max_columns = 3
for sysname, path in syscalls.items():
if path is not None:
if (index_tested % max_columns) == 0:
table_tested.append(f' * - `{sysname} <{path}>`_\n')
else:
table_tested.append(f' - `{sysname} <{path}>`_\n')
index_tested += 1
else:
if (index_untest % max_columns) == 0:
table_untest.append(f' * - {sysname}\n')
else:
table_untest.append(f' - {sysname}\n')
index_untest += 1
left = index_tested % max_columns
if left > 0:
for _ in range(0, max_columns - left):
table_tested.append(' -\n')
left = index_untest % max_columns
if left > 0:
for _ in range(0, max_columns - left):
table_untest.append(' -\n')
text.extend(table_tested)
text.append('\n')
text.extend(table_untest)
# write the file
with open(output, 'w+', encoding='utf-8') as stats:
stats.writelines(text)
def _generate_tags_table(tags):
"""
Generate the tags table from tags hash.
"""
supported_url_ref = {
"linux-git": "https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=",
"linux-stable-git": "https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=",
"glibc-git": "https://sourceware.org/git/?p=glibc.git;a=commit;h=",
"musl-git": "https://git.musl-libc.org/cgit/musl/commit/src/linux/clone.c?id=",
"CVE": "https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-",
}
table = [
'.. list-table::',
' :header-rows: 1',
'',
' * - Tag',
' - Info',
]
for tag in tags:
tag_key = tag[0]
tag_val = tag[1]
tag_url = supported_url_ref.get(tag_key, None)
if tag_url:
tag_val = f'`{tag_val} <{tag_url}{tag_val}>`_'
table.extend([
f' * - :c:struct:`{tag_key} <tst_tag>`',
f' - {tag_val}',
])
return table
def _generate_options_table(options):
"""
Generate the options table from the options hash.
"""
table = [
'.. list-table::',
' :header-rows: 1',
'',
' * - Option',
' - Description',
]
for opt in options:
if not isinstance(opt, list):
table.clear()
break
key = opt[0]
val = opt[2]
if key.endswith(':'):
key = key[:-1] if key.endswith(':') else key
key = f'-{key}'
table.extend([
f' * - {key}',
f' - {val}',
])
return table
def _generate_table_cell(key, values):
"""
Generate a cell which can be multiline if value is a list.
"""
cell = []
key = f' :c:struct:`{key} <tst_test>`'
if len(values) > 1:
cell.extend([
f' * - {key}',
f' - | {values[0]}',
])
for item in values[1:]:
cell.append(f' | {item}')
else:
cell.extend([
f' * - {key}',
f' - {values[0]}',
])
return cell
def _generate_setup_table(keys):
"""
Generate the table with test setup configuration.
"""
exclude = [
# following keys are already handled
'options',
'runtime',
'timeout',
'fname',
'doc',
# following keys don't need to be shown
'child_needs_reinit',
'needs_checkpoints',
'forks_child',
'tags',
]
my_keys = {k: v for k, v in keys.items() if k not in exclude}
if len(my_keys) == 0:
return []
table = [
'.. list-table::',
' :header-rows: 1',
'',
' * - Key',
' - Value',
]
values = []
for key, value in my_keys.items():
if key in exclude:
continue
values.clear()
if key == 'ulimit':
for item in value:
values.append(f'{item[0]} : {item[1]}')
elif key == 'hugepages':
if len(value) == 1:
values.append(f'{value[0]}')
else:
values.append(f'{value[0]}, {value[1]}')
elif key == 'filesystems':
for params in value:
for pkey, pval in params.items():
if pkey == "type":
values.append(f"- {pval}")
else:
values.append(f" {pkey}: {pval}")
elif key == "save_restore":
for item in value:
values.append(item[0])
else:
if isinstance(value, list):
values.extend(value)
else:
values.append(value)
if values:
table.extend(_generate_table_cell(key, values))
return table
def generate_test_catalog(_):
"""
Generate the test catalog from ltp.json metadata file.
"""
output = '_static/tests.rst'
metadata_file = '../metadata/ltp.json'
text = [
'.. warning::',
' The following catalog has been generated using LTP metadata',
' which is including only tests using the new :ref:`LTP C API`.',
''
]
metadata = None
with open(metadata_file, 'r', encoding='utf-8') as data:
metadata = json.load(data)
timeout_def = metadata['defaults']['timeout']
regexp = re.compile(r'^\[([A-Za-z][\w\W]+)\]')
for test_name, conf in sorted(metadata['tests'].items()):
text.extend([
f'{test_name}',
len(test_name) * '-'
])
# source url location
test_fname = conf.get('fname', None)
if test_fname:
text.extend([
'',
f"`source <{ltp_repo_base_url}/{test_fname}>`__",
''
])
# test description
desc = conf.get('doc', None)
if desc:
desc_text = []
for line in desc:
line = regexp.sub(r'**\1**', line)
desc_text.append(line)
text.extend([
'\n'.join(desc_text),
])
# timeout information
timeout = conf.get('timeout', None)
if timeout:
text.extend([
'',
f'Test timeout is {timeout} seconds.',
])
else:
text.extend([
'',
f'Test timeout defaults is {timeout_def} seconds.',
])
# runtime information
runtime = conf.get('runtime', None)
if runtime:
text.extend([
f'Maximum runtime is {runtime} seconds.',
''
])
else:
text.append('')
# options information
opts = conf.get('options', None)
if opts:
text.append('')
text.extend(_generate_options_table(opts))
text.append('')
# tags information
tags = conf.get('tags', None)
if tags:
text.append('')
text.extend(_generate_tags_table(tags))
text.append('')
# parse struct tst_test content
text.append('')
text.extend(_generate_setup_table(conf))
text.append('')
# small separator between tests
text.extend([
'',
'.. raw:: html',
'',
' <hr>',
'',
])
with open(output, 'w+', encoding='utf-8') as new_tests:
new_tests.write('\n'.join(text))
def setup(app):
"""
Setup the current documentation, using self generated data and graphics
customizations.
"""
app.add_css_file('custom.css')
app.connect('builder-inited', generate_syscalls_stats)
app.connect('builder-inited', generate_test_catalog)
+56
View File
@@ -0,0 +1,56 @@
.. SPDX-License-Identifier: GPL-2.0-or-later
.. Copyright (c) Linux Test Project, 2024
.. Include headers in this file with:
.. .. kernel-doc:: ../../include/tst_test.h
LTP C API
=========
Core LTP API
------------
.. kernel-doc:: ../../include/tst_res_flags.h
.. kernel-doc:: ../../include/tst_test.h
Test macros
-----------
.. kernel-doc:: ../../include/tst_test_macros.h
Capabilities
------------
.. kernel-doc:: ../../include/tst_capability.h
Checkpoints
-----------
.. kernel-doc:: ../../include/tst_checkpoint.h
Crypto
------
.. kernel-doc:: ../../include/tst_crypto.h
.. kernel-doc:: ../../include/tst_af_alg.h
Guarded buffers
---------------
.. kernel-doc:: ../../include/tst_buffers.h
Kernel
------
.. kernel-doc:: ../../include/tst_kernel.h
NUMA
----
.. kernel-doc:: ../../include/tst_numa.h
Option parsing
--------------
.. kernel-doc:: ../../include/tst_parse.h
Temporary directory
-------------------
.. kernel-doc:: ../../include/tst_tmpdir.h
LTP libraries
-------------
.. kernel-doc:: ../../include/libswap.h
+485
View File
@@ -0,0 +1,485 @@
.. SPDX-License-Identifier: GPL-2.0-or-later
.. Include headers in this file with:
.. .. kernel-doc:: ../../include/tst_test.h
Developing using KVM API
========================
Testing KVM is more complex than other Linux features. Some KVM bugs allow
userspace code running inside the virtual machine to bypass (emulated) hardware
access restrictions and elevate its privileges inside the guest operating
system. The worst types of KVM bugs may even allow the guest code to crash or
compromise the physical host. KVM tests therefore need to be split into two
components a KVM controller program running on the physical host and a guest
payload program running inside the VM. The cooperation of these two components
allows testing even of bugs that somehow cross the virtualization boundary.
Basic KVM Test Structure
------------------------
KVM tests are simple C source files containing both the KVM controller code
and the guest payload code separated by ``#ifdef COMPILE_PAYLOAD`` preprocessor
condition. The file will be compiled twice: once to compile the payload part,
and once to compile the KVM controller part and embed the payload binary inside.
The result is a single self-contained binary that will execute the embedded
payload inside a KVM virtual machine and print results in the same format as
a normal LTP test.
A KVM test source should start with ``#include "kvm_test.h"`` instead of the
usual ``tst_test.h``. The ``kvm_test.h`` header file will include the other basic
headers appropriate for the current compilation pass. Everything else in the
source file should be enclosed in ``#ifdef COMPILE_PAYLOAD ... #else ... #endif``
condition, including any other header file includes. Note that the standard
LTP headers are not available in the payload compilation pass; only the KVM
guest library headers can be included.
.. _example-kvm-test:
.. rubric:: Example KVM Test
.. code-block:: c
#include "kvm_test.h"
#ifdef COMPILE_PAYLOAD
/* Guest payload code */
void main(void)
{
tst_res(TPASS, "Hello, world!");
}
#else /* COMPILE_PAYLOAD */
/* KVM controller code */
static struct tst_test test = {
.test_all = tst_kvm_run,
.setup = tst_kvm_setup,
.cleanup = tst_kvm_cleanup,
};
#endif /* COMPILE_PAYLOAD */
The KVM controller code is a normal LTP test and needs to define an instance
of ``struct tst_test`` with metadata and the usual setup, cleanup, and test
functions. Basic implementation of all three functions is provided by the KVM
host library.
On the other hand, the payload is essentially a tiny kernel that will run
on bare virtual hardware. It cannot access any files, Linux syscalls, standard
library functions, etc., except for the small subset provided by the KVM guest
library. The payload code must define a ``void main(void)`` function which will
be the VM entry point of the test.
KVM Host Library
----------------
The KVM host library provides helper functions for creating and running
a minimal KVM virtual machine.
Data Structures
~~~~~~~~~~~~~~~
.. code-block:: c
struct tst_kvm_instance {
int vm_fd, vcpu_fd;
struct kvm_run *vcpu_info;
size_t vcpu_info_size;
struct kvm_userspace_memory_region ram[MAX_KVM_MEMSLOTS];
struct tst_kvm_result *result;
};
``struct tst_kvm_instance`` holds the file descriptors and memory buffers
of a single KVM virtual machine:
* ``int vm_fd`` is the main VM file descriptor created by ``ioctl(KVM_CREATE_VM)``
* ``int vcpu_fd`` is the virtual CPU file descriptor created by
``ioctl(KVM_CREATE_VCPU)``
* ``struct kvm_run *vcpu_info`` is the VCPU state structure created by
``mmap(vcpu_fd)``
* ``size_t vcpu_info_size`` is the size of ``vcpu_info`` buffer
* ``struct kvm_userspace_memory_region ram[MAX_KVM_MEMSLOTS]`` is the list
of memory slots defined in this VM. Unused memory slots have zero
in the ``userspace_addr`` field.
* ``struct tst_kvm_result *result`` is a buffer for passing test result data
from the VM to the controller program, mainly ``tst_res()``/``tst_brk()`` flags
and messages.
.. code-block:: c
struct tst_kvm_result {
int32_t result;
int32_t lineno;
uint64_t file_addr;
char message[0];
};
``struct tst_kvm_result`` is used to pass test results and synchronization data
between the KVM guest and the controller program. Most often, it is used
to pass ``tst_res()`` and ``tst_brk()`` messages from the VM, but special values
can also be used to send control flow requests both ways.
* ``int32_t result`` is the message type, either one of the ``TPASS``, ``TFAIL``,
``TWARN``, ``TBROK``, ``TINFO`` flags or a special control flow value. Errno flags
are not supported.
* ``int32_t lineno`` is the line number for ``tst_res()``/``tst_brk()`` messages.
* ``uint64_t file_addr`` is the VM address of the filename string for
``tst_res()``/``tst_brk()`` messages.
* ``char message[0]`` is the buffer for arbitrary message data, most often used
to pass ``tst_res()``/``tst_brk()`` message strings.
Working with Virtual Machines
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The KVM host library provides default implementation of the setup, cleanup
and test functions for ``struct tst_test`` in cases where you do not need
to customize the VM configuration. You can either assign these functions
to the ``struct tst_test`` instance directly or call them from your own function
that does some additional steps. All three functions must be used together.
* ``void tst_kvm_setup(void)``
* ``void tst_kvm_run(void)``
* ``void tst_kvm_cleanup(void)``
.. note:: ``tst_kvm_run()`` calls ``tst_free_all()``. Calling it will free all
previously allocated guarded buffers.
* ``void tst_kvm_validate_result(int value)`` Validates whether the value
returned in ``struct tst_kvm_result.result`` can be safely passed
to ``tst_res()`` or ``tst_brk()``. If the value is not valid, the controller
program will be terminated with an error.
* ``uint64_t tst_kvm_get_phys_address(const struct tst_kvm_instance *inst, uint64_t addr)``
Converts pointer value (virtual address) from KVM virtual
machine ``inst`` to the corresponding physical address. Returns 0 if
the virtual address is not mapped to any physical address. If virtual memory
mapping is not enabled in the VM or not available on the architecture at all, this
function simply returns ``addr`` as is.
* ``int tst_kvm_find_phys_memslot(const struct tst_kvm_instance *inst, uint64_t paddr)``
Returns index of the memory slot in KVM virtual machine
``inst`` which contains the physical address ``paddr``. If the address is not
backed by a memory buffer, returns -1.
* ``int tst_kvm_find_memslot(const struct tst_kvm_instance *inst, uint64_t addr)``
Returns index of the memory slot in KVM virtual machine
``inst`` which contains the virtual address ``addr``. If the virtual address
is not mapped to a valid physical address backed by a memory buffer,
returns -1.
* ``void *tst_kvm_get_memptr(const struct tst_kvm_instance *inst, uint64_t addr)``
Converts pointer value (virtual address) from KVM virtual
machine ``inst`` to host-side pointer.
* ``void *tst_kvm_alloc_memory(struct tst_kvm_instance *inst, unsigned int slot, uint64_t baseaddr, size_t size, unsigned int flags)``
Allocates a guarded buffer of given ``size`` in bytes and installs it into specified memory ``slot``
of the KVM virtual machine ``inst`` at base address ``baseaddr``. The buffer
will be automatically page aligned at both ends. See the kernel
documentation of ``KVM_SET_USER_MEMORY_REGION`` ioctl for a list of valid
``flags``. Returns pointer to page-aligned beginning of the allocated buffer.
The actual requested ``baseaddr`` will be located at
``ret + baseaddr % pagesize``.
* ``struct kvm_cpuid2 *tst_kvm_get_cpuid(int sysfd)`` Gets a list of supported
virtual CPU features returned by ``ioctl(KVM_GET_SUPPORTED_CPUID)``.
The argument must be an open file descriptor returned by ``open("/dev/kvm")``.
* ``void tst_kvm_create_instance(struct tst_kvm_instance *inst, size_t ram_size)``
Creates and fully initializes a new KVM virtual machine
with at least ``ram_size`` bytes of memory. The VM instance info will be
stored in ``inst``.
* ``int tst_kvm_run_instance(struct tst_kvm_instance *inst, int exp_errno)``
Executes the program installed in KVM virtual machine ``inst``. Any result
messages returned by the VM will be automatically printed to the controller
program output. Returns zero. If ``exp_errno`` is non-zero, the VM execution
syscall is allowed to fail with the ``exp_errno`` error code and
``tst_kvm_run_instance()`` will return -1 instead of terminating the test.
* ``void tst_kvm_destroy_instance(struct tst_kvm_instance *inst)`` Deletes
the KVM virtual machine ``inst``. Note that the guarded buffers assigned
to the VM by ``tst_kvm_create_instance()`` or ``tst_kvm_alloc_memory()`` will
not be freed.
The KVM host library does not provide any way to reset a VM instance back
to its initial state. Running multiple iterations of the test requires destroying
the old VM instance and creating a new one. Otherwise, the VM will exit
without reporting any results on the second iteration, and the test will fail.
The ``tst_kvm_run()`` function handles this issue correctly.
KVM Guest Library
-----------------
The KVM guest library provides a minimal implementation of both the LTP
test library and the standard C library functions. Do not try to include
the usual LTP or C headers in guest payload code; it will not work.
Standard C Functions
~~~~~~~~~~~~~~~~~~~~
``#include "kvm_test.h"``
The functions listed below are implemented according to the C standard:
* ``void *memset(void *dest, int val, size_t size)``
* ``void *memzero(void *dest, size_t size)``
* ``void *memcpy(void *dest, const void *src, size_t size)``
* ``char *strcpy(char *dest, const char *src)``
* ``char *strcat(char *dest, const char *src)``
* ``size_t strlen(const char *str)``
LTP Library Functions
~~~~~~~~~~~~~~~~~~~~~
``#include "kvm_test.h"``
The KVM guest library currently provides the LTP functions for reporting test
results. All standard result flags except for ``T*ERRNO`` are supported
with the same rules as usual. However, printf-like formatting is not
implemented yet.
* ``void tst_res(int result, const char *message)``
* ``void tst_brk(int result, const char *message) __attribute__((noreturn))``
A handful of useful macros is also available:
* ``TST_TEST_TCONF(message)`` Generates a test program that will simply print
a ``TCONF`` message and exit. This is useful when the real test cannot be
built due to missing dependencies or architecture limitations.
* ``ARRAY_SIZE(arr)`` Returns the number of items in statically allocated
array ``arr``.
* ``LTP_ALIGN(x, a)`` Aligns integer ``x`` to be a multiple of ``a``, which
must be a power of 2.
Architecture Independent Functions
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
``#include "kvm_test.h"``
Memory management in the KVM guest library currently uses only a primitive linear
buffer for memory allocation. There are no checks whether the VM can allocate
more memory, and the already allocated memory cannot be freed.
* ``void *tst_heap_alloc(size_t size)`` Allocates a block of memory on the heap.
* ``void *tst_heap_alloc_aligned(size_t size, size_t align)`` Allocates
a block of memory on the heap with the starting address aligned to a given
value.
x86 Specific Functions
~~~~~~~~~~~~~~~~~~~~~~
``#include "kvm_test.h"``
``#include "kvm_x86.h"``
* ``struct kvm_interrupt_frame`` Opaque architecture-dependent structure which holds
interrupt frame information. Use the functions below to get individual values:
* ``uintptr_t kvm_get_interrupt_ip(const struct kvm_interrupt_frame *ifrm)``
Gets instruction pointer value from the interrupt frame structure. This may be
the instruction which caused an interrupt or the one immediately after,
depending on the interrupt vector semantics.
* ``int (*tst_interrupt_callback)(void *userdata, struct kvm_interrupt_frame *ifrm, unsigned long errcode)``
Interrupt handler callback prototype. When an interrupt occurs, the assigned callback function
will be passed the ``userdata`` pointer that was given
to ``tst_set_interrupt_callback()``, interrupt frame ``ifrm`` and the error
code ``errcode`` defined by the interrupt vector semantics. If the interrupt
vector does not generate an error code, ``errcode`` will be set to zero.
The callback function must return 0 if the interrupt was successfully
handled and test execution should resume. A non-zero return value means that
the interrupt could not be handled and the test will terminate with an error.
* ``void tst_set_interrupt_callback(unsigned int vector, tst_interrupt_callback func, void *userdata)``
Registers a new interrupt handler callback function ``func`` for interrupt ``vector``. The ``userdata``
argument is an arbitrary pointer that will be passed to ``func()`` every time
it gets called. The previous interrupt handler callback will be removed.
Setting ``func`` to ``NULL`` will remove any existing interrupt handler
from ``vector``, and the interrupt will become a fatal error.
.. code-block:: c
struct page_table_entry_pae {
unsigned int present: 1;
unsigned int writable: 1;
unsigned int user_access: 1;
unsigned int write_through: 1;
unsigned int disable_cache: 1;
unsigned int accessed: 1;
unsigned int dirty: 1;
unsigned int page_type: 1;
unsigned int global: 1;
unsigned int padding: 3;
uint64_t address: 40;
unsigned int padding2: 7;
unsigned int prot_key: 4;
unsigned int noexec: 1;
} __attribute__((__packed__));
struct kvm_cpuid {
unsigned int eax, ebx, ecx, edx;
};
struct kvm_cregs {
unsigned long cr0, cr2, cr3, cr4;
};
struct kvm_sregs {
uint16_t cs, ds, es, fs, gs, ss;
};
``struct page_table_entry_pae`` is the page table entry structure for PAE and
64-bit paging modes. See Intel® 64 and IA-32 Architectures Software
Developer's Manual, Volume 3, Chapter 4 for an explanation of the fields.
* ``uintptr_t kvm_get_page_address_pae(const struct page_table_entry_pae *entry)``
Returns the physical address of the memory page referenced by the given
page table ``entry``. Depending on memory mapping changes done by the test,
the physical address may not be a valid pointer. The caller must determine
whether the address points to another page table entry or a data page, using
the known position in page table hierarchy and ``entry->page_type``. Returns
zero if the ``entry`` does not reference any memory page.
* ``void kvm_set_segment_descriptor(struct segment_descriptor *dst, uint64_t baseaddr, uint32_t limit, unsigned int flags)`` -
Fills the ``dst`` segment descriptor with given values. The maximum value
of ``limit`` is ``0xfffff`` (inclusive) regardless of ``flags``.
* ``void kvm_parse_segment_descriptor(struct segment_descriptor *src, uint64_t *baseaddr, uint32_t *limit, unsigned int *flags)`` -
Parses data in the ``src`` segment descriptor and copies them to variables
pointed to by the other arguments. Any parameter except the first one can
be ``NULL``.
* ``int kvm_find_free_descriptor(const struct segment_descriptor *table, size_t size)`` -
Finds the first segment descriptor in ``table`` which does not have
the ``SEGFLAG_PRESENT`` bit set. The function handles double-size descriptors
correctly. Returns the index of the first available descriptor or -1 if all
``size`` descriptors are taken.
* ``unsigned int kvm_create_stack_descriptor(struct segment_descriptor *table, size_t tabsize, void *stack_base)`` -
A convenience function for registering a stack segment descriptor. It will
automatically find a free slot in ``table`` and fill the necessary flags.
The ``stack_base`` pointer must point to the bottom of the stack.
* ``void kvm_get_cpuid(unsigned int eax, unsigned int ecx, struct kvm_cpuid *buf)``
Executes the CPUID instruction with the given
``eax`` and ``ecx`` arguments and stores the results in ``buf``.
* ``void kvm_read_cregs(struct kvm_cregs *buf)`` Copies the current values
of control registers to ``buf``.
* ``void kvm_read_sregs(struct kvm_sregs *buf)`` - Copies the current values
of segment registers to ``buf``.
* ``uint64_t kvm_rdmsr(unsigned int msr)`` Returns the current value
of model-specific register ``msr``.
* ``void kvm_wrmsr(unsigned int msr, uint64_t value)`` Stores ``value``
into model-specific register ``msr``.
* ``void kvm_exit(void) __attribute__((noreturn))`` Terminates the test.
Similar to calling ``exit(0)`` in a regular LTP test, although ``kvm_exit()``
will terminate only one iteration of the test, not the whole host process.
See Intel® 64 and IA-32 Architectures Software Developer's Manual
for documentation of standard and model-specific x86 registers.
AMD SVM Helper Functions
~~~~~~~~~~~~~~~~~~~~~~~~
``#include "kvm_test.h"``
``#include "kvm_x86.h"``
``#include "kvm_x86_svm.h"``
The KVM guest library provides basic helper functions for creating and running
nested virtual machines using the AMD SVM technology.
.. _example-code-to-execute-nested-vm:
.. rubric:: Example Code to Execute Nested VM
.. code-block:: c
int guest_main(void)
{
...
return 0;
}
void main(void)
{
struct kvm_svm_vcpu *vm;
kvm_init_svm();
vm = kvm_create_svm_vcpu(guest_main, 1);
kvm_svm_vmrun(vm);
}
* ``int kvm_is_svm_supported(void)`` - Returns a non-zero value if the CPU
supports AMD SVM; otherwise, returns 0.
* ``int kvm_get_svm_state(void)`` - Returns a non-zero value if SVM is currently
enabled; otherwise, returns 0.
* ``void kvm_set_svm_state(int enabled)`` - Enables or disables SVM according
to the argument. If SVM is disabled by the host or not supported, the test will exit
with ``TCONF``.
* ``void kvm_init_svm(void)`` - Enables and fully initializes SVM, including
allocating and setting up the host save area VMCB. If SVM is disabled by the host or
not supported, the test will exit with ``TCONF``.
* ``struct kvm_vmcb *kvm_alloc_vmcb(void)`` - Allocates a new VMCB structure
with correct memory alignment and fills it with zeroes.
* ``void kvm_vmcb_set_intercept(struct kvm_vmcb *vmcb, unsigned int id, unsigned int state)`` -
Sets SVM intercept bit ``id`` to the given ``state``.
* ``void kvm_init_guest_vmcb(struct kvm_vmcb *vmcb, uint32_t asid, uint16_t ss, void *rsp, int (*guest_main)(void))`` -
Initializes a new SVM virtual machine. The ``asid`` parameter is the nested
page table ID. The ``ss`` and ``rsp`` parameters set the stack segment and stack
pointer values, respectively. The ``guest_main`` parameter sets the code entry
point of the virtual machine. All control registers, segment registers
(except stack segment register), GDTR and IDTR will be copied
from the current CPU state.
* ``struct kvm_svm_vcpu *kvm_create_svm_vcpu(int (*guest_main)(void), int alloc_stack)`` -
A convenience function for allocating and initializing a new SVM virtual CPU.
The ``guest_main`` parameter is passed to ``kvm_init_guest_vmcb()``;
the ``alloc_stack`` parameter controls whether a new 8KB stack will be
allocated and registered in GDT. Interception will be enabled for ``VMSAVE``
and ``HLT`` instructions. If you set ``alloc_stack`` to zero, you must configure
the stack segment register and stack pointer manually.
* ``void kvm_svm_vmrun(struct kvm_svm_vcpu *cpu)`` - Starts or continues execution
of a nested virtual machine. Be aware that FPU state is not saved. Do not use
floating point types or values in nested guest code. Also, do not use
``tst_res()`` or ``tst_brk()`` functions in nested guest code.
See AMD64 Architecture Programmer's Manual Volume 2 for documentation
of the Secure Virtual Machine (SVM) technology.
KVM Guest Environment
---------------------
KVM guest payload execution begins with bootstrap code which will perform
the minimal guest environment setup required for running C code:
* Activates the appropriate CPU execution mode (IA-32 protected mode
on 32-bit x86 or the 64-bit mode on x86_64).
* Creates an identity mapping (virtual address = physical address) of the lower
2GB memory region, even if parts of the region are not backed by any host
memory buffers. The memory region above the 2GB threshold is left unmapped
except for one memory page reserved for the ``struct tst_kvm_result`` buffer.
* Initializes an 8KB stack.
* Installs default interrupt handlers for standard CPU exception vectors.
When the environment setup is complete, bootstrap will call the ``void main(void)``
function implemented by the test program. To finish execution of the guest payload,
the test can either return from the ``main()`` function or call ``kvm_exit()``
at any point.
+7
View File
@@ -0,0 +1,7 @@
.. SPDX-License-Identifier: GPL-2.0-or-later
.. Include headers in this file with:
.. .. kernel-doc:: ../../include/tst_test.h
Developing using network API
============================
+4
View File
@@ -0,0 +1,4 @@
.. SPDX-License-Identifier: GPL-2.0-or-later
LTP shell API
=============
+209
View File
@@ -0,0 +1,209 @@
.. SPDX-License-Identifier: GPL-2.0-or-later
Build system
============
The following document briefly describes the steps and methodologies used for
the new and improved Makefile system.
The Problem
-----------
The problem with the old Makefile system is that it was very difficult to
maintain and it lacked any sense of formal structure, thus developing for LTP
and including new targets was more difficult than it should have been
(maintenance). Furthermore, proper option-based cross-compilation was
impossible due to the fact that the Makefiles didn't support a prefixing
system, and the appropriate implicit / static rules hadn't been configured to
compile into multiple object directories for out-of-tree build support (ease of
use / functionality). Finally, there wasn't a means to setup dependencies
between components, such that if a component required ``libltp.a`` in order to
compile, it would go off and compile ``libltp.a`` first (ease of use).
These items needed to be fixed to reduce maintenance nightmares for the
development community contributing to LTP, and the project maintainers.
Design
------
The system was designed such that including a single GNU Makefile compatible
set in each new directory component is all that's essentially required to
build the system.
Say you had a directory like the following (with ``.c`` files in them which
directly tie into applications, e.g. baz.c -> baz):
.. code-block::
.../foo/
|--> Makefile
|
--> bar/
|
--> Makefile
|
--> baz.c
.. code-block:: make
:caption: .../foo/Makefile
# SPDX-License-Identifier: GPL-2.0-or-later
top_srcdir ?= ..
include $(top_srcdir)/include/mk/env_pre.mk
include $(top_srcdir)/include/mk/generic_trunk_target.mk
.. code-block:: make
:caption: .../foo/bar/Makefile
# SPDX-License-Identifier: GPL-2.0-or-later
top_srcdir ?= ../..
include $(top_srcdir)/include/mk/env_pre.mk
include $(top_srcdir)/include/mk/generic_leaf_target.mk
Kernel Modules
--------------
Some of the tests need to build kernel modules, happily LTP has
infrastructure for this.
.. code-block:: make
ifneq ($(KERNELRELEASE),)
obj-m := module01.o
else
top_srcdir ?= ../../../..
include $(top_srcdir)/include/mk/testcases.mk
REQ_VERSION_MAJOR := 2
REQ_VERSION_PATCH := 6
MAKE_TARGETS := test01 test02 module01.ko
include $(top_srcdir)/include/mk/module.mk
include $(top_srcdir)/include/mk/generic_leaf_target.mk
endif
This is a Makefile example that allows you to build kernel modules inside LTP.
The prerequisites for the build are detected by the ``configure`` script.
The ``REQ_VERSION_MAJOR`` and ``REQ_VERSION_PATCH`` describe minimal kernel
version for which the build system tries to build the module.
The build system is also forward compatible with changes in Linux kernel
internal API so that, if module fails to build, the failure is ignored both on
build and installation. If the userspace counterpart of the test fails to load
the module because the file does not exists, the test is skipped.
Note the ``ifneq($(KERNELRELEASE),)``. The reason it exists, it is that the
Makefile is executed twice: once by LTP build system and once by kernel kbuild,
see :kernel_doc:`kbuild/modules` in the Linux kernel documentation for details
on external module build.
Make Rules and Make Variables
-----------------------------
When using make rules, avoid writing ad hoc rules like:
.. code-block:: make
[prog]: [dependencies]
cc -I../../include $(CFLAGS) $(CPPFLAGS) $(LDFLAGS) $(LDLIBS) \
-o [prog] [dependencies]
This makes cross-compilation and determinism difficult, if not impossible.
Besides, implicit rules are your friends and as long as you use ``MAKEOPTS=;``
in the top-level caller (or do ``$(subst r,$(MAKEOPTS)``) to remove ``-r``),
the compile will complete successfully, assuming all other prerequisites have
been fulfilled (libraries, headers, etc).
.. list-table::
:header-rows: 1
* - Variable
- Explanation
* - $(AR)
- The library archiver
* - $(CC)
- The system C compiler
* - $(CCP)
- The system C preprocessor
* - $(CFLAGS)
- C compiler flags
* - $(CPPFLAGS)
- Preprocessor flags, e.g. ``-I`` arguments
* - $(DEBUG_CFLAGS)
- Debug flags to pass to ``$(CC)``, ``-g``, etc
* - $(KVM_LD)
- Special linker for wrapping KVM payload binaries into linkable object
files. Defaults to ``$(LD)``. Change this variable if the KVM Makefile
fails to build files named ``*-payload.o``
* - $(LD)
- The system linker (typically ``$(CC)``, but not necessarily)
* - $(LDFLAGS)
- What to pass in to the linker, including ``-L`` arguments and other ld
arguments, apart from ``-l`` library includes (see ``$(LDLIBS)``).
This should be done in the ``$(CC)`` args passing style when
``LD := $(CC)``, e.g. ``-Wl,-foo``, as opposed to ``-foo``
* - $(LDLIBS)
- Libraries to pass to the linker (e.g. ``-lltp``, etc)
* - $(LTPLDLIBS)
- LTP internal libraries i.e. these in libs/ directory
* - $(OPT_CFLAGS)
- Optimization flags to pass into the C compiler, ``-O2``, etc. If you
specify ``-O2`` or higher, you should also specify
``-fno-strict-aliasing``, because of gcc fstrict-aliasing optimization
bugs in the tree optimizer. Search for **fstrict-aliasing optimization
bug** with your favorite search engine.
Examples of more recent bugs: tree-optimization/17510
and tree-optimization/39100.
Various bugs have occurred in the past due to buggy logic in the
tree-optimization portion of the gcc compiler, from 3.3.x to 4.4.
* - $(RANLIB)
- What to run after archiving a library
* - $(WCFLAGS)
- Warning flags to pass to ``$(CC)``, e.g. ``-Werror``, ``-Wall``, etc.
Make System Variables
---------------------
A series of variables are used within the make system that direct what actions
need to be taken. Rather than listing the variables here, please refer to the
comments contained in :master:`include/mk/env_pre.mk`.
Guidelines and Recommendations
------------------------------
Of course, GNU Make manual is the key to understand the Make system, but
following manuals are probably the most important:
* `Implicit Rules <http://www.gnu.org/software/make/manual/make.html#Implicit-Rules>`_
* `Variables and Expansion <http://www.gnu.org/software/make/manual/make.html#Using-Variables>`_
* `Origin Use <http://www.gnu.org/software/make/manual/make.html#Origin-Function>`_
* `VPath Use <http://www.gnu.org/software/make/manual/make.html#Directory-Search>`_
.. warning::
Rebuild from scratch before committing anything in the build system.
+23
View File
@@ -0,0 +1,23 @@
.. SPDX-License-Identifier: GPL-2.0-or-later
Debugging
=========
This section explains some tricks which can be used to debug test binaries.
Debug messages
--------------
The LTP framework supports ``TDEBUG`` flag test debug messages. These
messages can be enabled using the ``-D`` parameter or setting ``LTP_ENABLE_DEBUG=1``
environment variable (see :doc:`../users/setup_tests`).
Tracing and debugging syscalls
------------------------------
The new test library runs the actual test (i.e. the ``test()`` function) in a
forked process. To get stack trace of a crashing test in ``gdb`` it's needed to
`set follow-fork-mode child <https://sourceware.org/gdb/current/onlinedocs/gdb.html/Forks.html>`_.
To trace the test, please use ``strace -f`` to enable tracing also for the
forked processes.
+55
View File
@@ -0,0 +1,55 @@
.. SPDX-License-Identifier: GPL-2.0-or-later
Documentation
=============
This section explains how to use and develop the LTP documentation. The current
documentation format is written using
`reStructedText <https://www.sphinx-doc.org/en/master/usage/restructuredtext/index.html>`_
and it's built on top of `Sphinx <https://www.sphinx-doc.org/en/master/>`_.
Building documentation
~~~~~~~~~~~~~~~~~~~~~~
Before building, make sure you have python3 ``virtualenv`` module installed.
.. code-block:: bash
# run configure to be able to compile doc dependencies in metadata/
make autotools
./configure
cd doc
# prepare virtual environment
python3 -m virtualenv .venv
. .venv/bin/activate
pip install -r requirements.txt
# build documentation
make
Once the procedure has been completed, documentation will be visible at
``doc/html/index.html``.
.. warning::
Documentation requires ``Python >= 3.6``.
The current :master:`.readthedocs.yml` workflow is using ``Python 3.12``,
it is tested in GitHub Actions :master:`.github/workflows/ci-sphinx-doc.yml`.
Validating spelling
~~~~~~~~~~~~~~~~~~~
To check documentation words spelling, we provide support for
`aspell <http://aspell.net/>`_, so make sure that it's installed. The
documentation can be tested via ``make spelling`` command. Output will be
visible in the ``doc/build`` folder and, if any error will be found, a warning
message will be shown.
C API documentation
~~~~~~~~~~~~~~~~~~~
The C API documentation is generated from headers using
`kernel-doc <https://return42.github.io/linuxdoc/linuxdoc-howto/kernel-doc-syntax.html>`_
syntax which is supported by Sphinx via
`linuxdoc <https://pypi.org/project/linuxdoc/>`_ extension.
+45
View File
@@ -0,0 +1,45 @@
.. SPDX-License-Identifier: GPL-2.0-or-later
LTP Library guidelines
======================
General Rules
-------------
For extending the LTP library API it applies the same general rules as
for :doc:`writing tests <../developers/writing_tests>`
(with strong focus on readability and simplicity), plus:
#. LTP library tests must go inside :master:`lib/newlib_tests` directory
#. LTP documentation has to be updated according to API changes
#. Do not add new API functions to the old API. Add new functions to
``tst_.[ch]`` files.
Shell API
---------
API source code is in :master:`testcases/lib/tst_test.sh`,
:master:`testcases/lib/tst_security.sh` and :master:`testcases/lib/tst_net.sh`.
Changes in the shell API should not introduce uncommon dependencies
(use basic commands installed everywhere by default).
Shell libraries
~~~~~~~~~~~~~~~
Aside from shell API libraries in :master:`testcases/lib` directory, it's
worth putting common code for a group of tests into a shell library.
The filename should end with ``_lib.sh`` and the library should load
``tst_test.sh`` or ``tst_net.sh``.
Shell libraries should have conditional expansion for ``TST_SETUP`` or
``TST_CLEANUP``, to avoid surprises when test specific setup/cleanup function is
redefined by shell library.
.. code-block:: bash
# ipsec_lib.sh
# SPDX-License-Identifier: GPL-2.0-or-later
TST_SETUP="${TST_SETUP:-ipsec_lib_setup}"
...
. tst_test.sh
+50
View File
@@ -0,0 +1,50 @@
.. SPDX-License-Identifier: GPL-2.0-or-later
Setting up the Mailing list
===========================
Before using ``git send-email``, you need to set up your email client to send
emails from the command line. This typically involves configuring an SMTP server
and authentication details.
Open a terminal and configure Git with your email settings using the following
commands:
.. code-block:: bash
git config --global sendemail.from "Your Name <your_email@example.com>"
git config --global sendemail.smtpserver "smtp.example.com"
git config --global sendemail.smtpuser "your_email@example.com"
git config --global sendemail.smtpserverport 587
git config --global sendemail.smtpencryption tls
Replace ``smtp.example.com`` with the SMTP server address provided by your email
provider. Replace ``your_email@example.com`` with your email address. Adjust the
SMTP port and encryption settings according to your email provider's
requirements.
To test the configuration you can use ``--dry-run`` parameter.
.. code-block:: bash
git send-email --dry-run --to "ltp@lists.linux.it" --subject "Test Email" --body "This is a test email." HEAD^
Depending on your SMTP server's configuration, you may need to authenticate
before sending emails. If required, configure authentication settings using:
.. code-block:: bash
git config --global sendemail.smtpuser "your_email@example.com"
git config --global sendemail.smtppass "your_password"
Replace ``your_email@example.com`` with your email address and ``your_password``
with your email account password.
For any corner case, please take a look at the
`email + git <https://git-send-email.io/>`_ documentation.
.. note::
This method still works in most of the cases, but nowadays we often
require to setup a two factor authentication. If this is the case, please
consider setting up Git accordingly.
File diff suppressed because it is too large Load Diff
+537
View File
@@ -0,0 +1,537 @@
.. SPDX-License-Identifier: GPL-2.0-or-later
Writing tests
=============
This document describes LTP guidelines and it's intended for anybody who wants
to write or to modify a LTP testcase. It's not a definitive guide and it's not,
by any means, a substitute for common sense.
Guide to clean and understandable code
--------------------------------------
Testcases require that the source code is easy to follow. When a test starts to
fail, the failure has to be analyzed and clean test codebase makes this task
much easier and quicker.
Keep things simple
~~~~~~~~~~~~~~~~~~
It's worth to keep testcases simple or, better, as simple as possible.
The kernel and libc are tricky beasts and the complexity imposed by their
interfaces is quite high. Concentrate on the interface you want to test and
follow the UNIX philosophy.
It's a good idea to make the test as self-contained as possible too, ideally
tests should not depend on tools or libraries that are not widely available.
Do not reinvent the wheel!
* Use LTP standard interface
* Do not add custom PASS/FAIL reporting functions
* Do not write Makefiles from scratch, use LTP build system instead
* Etc.
Keep functions and variable names short
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Choosing a good name for an API functions or even variables is a difficult
task do not underestimate it.
There are a couple of customary names for different things that help people to
understand code, for example:
* For loop variables are usually named with a single letter ``i``, ``j``, ...
* File descriptors ``fd`` or ``fd_foo``.
* Number of bytes stored in file are usually named as ``size`` or ``len``
* Etc.
Do not over-comment
~~~~~~~~~~~~~~~~~~~
Comments can sometimes save your day, but they can easily do more harm than
good. There has been several cases where comments and actual implementation
drifted slowly apart which yielded into API misuses and hard to find bugs.
Remember there is only one thing worse than no documentation: wrong
documentation.
Ideally, everybody should write code that is obvious, which unfortunately isn't
always possible. If there is a code that requires to be commented, keep it
short and to the point. These comments should explain *why* and not *how*
things are done.
Never ever comment the obvious.
In case of LTP testcases, it's customary to add an `RST
<https://www.sphinx-doc.org/en/master/usage/restructuredtext/basics.html>`_
formatted comment paragraph with high-level test description at the beginning
of the file right under the GPL SPDX header. This helps other people to
understand the overall goal of the test before they dive into the technical
details. It's also exported into generated documentation hence it should mostly
explain what is tested.
DRY (Code duplication)
~~~~~~~~~~~~~~~~~~~~~~
Copy & paste is a good servant but very poor master. If you are about to copy a
large part of the code from one testcase to another, think what would happen if
you find bug in the code that has been copied all around the tree. What about
moving it to a library instead?
The same goes for short but complicated parts, whenever you are about to copy &
paste a syscall wrapper that packs arguments accordingly to machine
architecture or similarly complicated code, put it into a header instead.
C coding style
--------------
LTP adopted `Linux kernel coding style <https://www.kernel.org/doc/html/latest/process/coding-style.html>`_.
Run ``make check`` in the test's directory and/or use ``make check-$TCID``, it
uses (among other checks) our vendoring version of
`checkpatch.pl <https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/plain/scripts/checkpatch.pl>`_
script from kernel git tree.
.. note::
If ``make check`` does not report any problems, the code still may be wrong
as all tools used for checking only look for common mistakes.
The following linting code can be found when we run ``make check``:
.. list-table::
:header-rows: 1
* - Linting code
- Message
- Explanation
* - LTP-001
- Library source files have ``tst_`` prefix
- API source code is inside headers in ``include/{empty}*.h``,
``include/lapi/{empty}*.h`` (backward compatibility for old kernel and
libc) and C sources in ``lib/{empty}*.c``. Files must have ``tst_``
prefix.
* - LTP-002
- ``TST_RET`` and ``TST_ERR`` are never modified by test library functions
- The test author is guaranteed that the test API will not modify these
variables. This prevents silent errors where the return value and
errno are overwritten before the test has chance to check them.
The macros which are clearly intended to update these variables. That
is ``TEST`` and those in :master:`include/tst_test_macros.h`. Are of
course allowed to update these variables.
* - LTP-003
- Externally visible library symbols have the ``tst_`` prefix
- Functions, types and variables in the public test API should have the
``tst_`` prefix. With some exceptions for symbols already prefixed with
``safe_`` or ``ltp_``.
Static (private) symbols should not have the prefix.
* - LTP-004
- Test executable symbols are marked ``static``
- Test executables should not export symbols unnecessarily. This means
that all top-level variables and functions should be marked with the
``static`` keyword. The only visible symbols should be those included
from shared object files.
* - LTP-005
- Array must terminate with a sentinel value (i.e. ``NULL`` or ``{}``)
- When defining arrays in the :ref:`struct tst_test` structure, we need to
end the array items with a sentinel ``NULL`` value.
Shell coding style
------------------
When writing testcases in shell, write in *portable shell* only, it's a good
idea to try to run the test using alternative shell (alternative to bash, for
example dash) too.
*Portable shell* means Shell Command Language as defined by POSIX with an
exception of few widely used extensions, namely **local** keyword used inside of
functions and ``-o`` and ``-a`` test parameters (that are marked as obsolete in
POSIX).
You can either try to run the testcases in Debian which has ``/bin/sh`` pointing
to ``dash`` by default, or to install ``dash`` on your favorite distribution,
then use it to run tests. If your distribution lacks ``dash`` package, you can
always compile it from `sources <http://gondor.apana.org.au/~herbert/dash/files/>`_.
Run ``make check`` in the test's directory and/or use ``make check-$TCID.sh``.
It uses (among other checks) our vendoring version of
`checkbashism.pl <https://salsa.debian.org/debian/devscripts/raw/master/scripts/checkbashisms.pl>`_
from Debian that is used to check for non-portable shell code.
.. note::
If ``make check`` does not report any problems the code still may be wrong,
as ``checkbashisms.pl`` is used for checking only common mistakes.
Here there are some common sense style rules for shell
* Keep lines under 80 chars
* Use tabs for indentation
* Keep things simple, avoid unnecessary subshells
* Don't do confusing things (i.e. don't name your functions like common shell
commands, etc.)
* Quote variables
* Be consistent
3 Backwards compatibility
~~~~~~~~~~~~~~~~~~~~~~~~~
LTP test should be as backward compatible as possible. Think of an enterprise
distributions with long term support (more than five years since the initial
release) or of an embedded platform that needs to use several years old
toolchain supplied by the manufacturer.
Therefore LTP test for more current features should be able to cope with older
systems. It should at least compile fine and if it's not appropriate for the
configuration it should return ``TCONF``.
There are several types of checks we use:
* The *configure script* is usually used to detect availability of a function
declarations in system headers. It's used to disable tests at compile time or
to enable fallback definitions.
* Checking the ``errno`` value is another type of runtime check. Most of the
syscalls returns either ``EINVAL`` or ``ENOSYS`` when syscall was not
implemented or was disabled upon kernel compilation.
* LTP has kernel version detection that can be used to disable tests at runtime.
Unfortunately, the kernel version does not always corresponds to a well
defined feature set, as distributions tend to backport hundreds of patches
while the kernel version stays the same. Use with caution.
* Lately, we added a kernel ``.config`` parser. A test can define a boolean
expression of kernel config variables that has to be satisfied in order to run
a test. At the moment, this is mostly used for kernel namespaces.
* Sometimes it makes sense to define a few macros instead of creating a
configure test. One example is Linux specific POSIX clock ids in
:master:`include/lapi/posix_clocks.h`.
Dealing with messed up legacy code
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
LTP still contains a lot of old and messy code and we are cleaning it up as
fast as we can but, despite the decade of efforts, there is still a lot of it.
If you start modifying old or a messy testcase and your changes are more
complicated than simple typo fixes, you should convert the test into a new
library first.
It's also much easier to review the changes if you split them into a smaller
logical groups. The same goes for moving files: if you need to rename or to move
files, do it in a separate patch.
License
~~~~~~~
Code contributed to LTP should be licensed under GPLv2+ (GNU GPL version 2 or
any later version).
Use ``SPDX-License-Identifier: GPL-2.0-or-later``
LTP Structure
-------------
The structure of LTP is quite simple. Each test is a binary written either in
portable shell or C. The test gets a configuration via environment variables
and/or command line parameters, it prints additional information into the
stdout and reports overall success/failure via the exit value.
Tests are generally placed under the :master:`testcases` directory. Everything that
is a syscall or (slightly confusingly) libc syscall wrapper, goes under
:master:`testcases/kernel/syscalls/`.
There is also :master:`testcases/open_posix_testsuite/` which is a well maintained
fork of the Open POSIX testsuite project, that has been dead since 2005.
We also have a number of directories with tests for more specific features, such
as containers, etc.
Runtest Files
~~~~~~~~~~~~~
The list of tests to be executed is stored in runtest files under the
:master:`runtest` directory. The default set of runtest files to be executed is
stored in :master:`scenario_groups/default`. When you add a test, you should add
corresponding entries into some runtest file(s) as well.
Each line of runtest file contains one test. The first item is the test name.
All other items, separated by space will be executed as a command.
.. code-block:: bash
shell_test01 echo "SUCCESS" | shell_pipe01.sh
splice02 splice02 -s 20
Blank lines and lines starting with a ``#`` (comments) are ignored.
Syscalls tests, placed under :master:`testcases/kernel/syscalls/`, use
:master:`runtest/syscalls` file. For kernel related tests for memory management we
have :master:`runtest/mm`, etc.
.. note::
runtest files should have one entry per a test. Creating a
wrapper that runs all your tests and adding it as a single test
into runtest file is strongly discouraged.
Datafiles
---------
If your test needs data files, these should be put into a subdirectory
named ``datafiles`` and installed into the ``testcases/data/$TCID`` directory.
This will require to add ``INSTALL_DIR := testcases/data/TCID`` into
correspondent ``datafiles/Makefile``.
You can obtain path to datafiles via ``$TST_DATAROOT`` provided by ``test.sh``
or via C function ``tst_dataroot()`` provided by libltp:
.. code-block:: c
const char *dataroot = tst_dataroot();
Datafiles can also be accessed as ``$LTPROOT/testcases/data/$TCID/...``,
but ``$TST_DATAROOT`` and ``tst_dataroot()`` are preferred, as these can be used
when running testcases directly in git tree as well as from install location.
Sub-executables
~~~~~~~~~~~~~~~
If your test needs to execute a binary, place it in the same directory of the
testcase and name the binary with ``$TESTNAME_`` prefix, where ``$TESTNAME`` is
the name of the test binary. Once the test is executed by the framework, the
path to the directory with all LTP binaries is added to the ``$PATH`` and you
can execute it via its name.
.. note::
If you need to execute a test from the LTP tree, you can add ``PATH`` to
the current directory with ``PATH="$PATH:$PWD" ./foo01``.
Test Contribution Checklist
---------------------------
#. Test compiles and it runs fine (check with ``-i 10`` and ``-i 0`` too)
#. ``make check`` should not emit any warnings for the test you are working on
(hint: run it in the test's directory and/or use ``make check-$TCID``)
#. The runtest entries are in place
#. New test binaries are added into the corresponding ``.gitignore`` files
#. Patches apply over the latest git
About .gitignore files
~~~~~~~~~~~~~~~~~~~~~~
There are numerous ``.gitignore`` files in the LTP tree. Usually, there is a
``.gitignore`` file for a group of tests. The reason of this setup is simple:
it's easier to maintain a ``.gitignore`` file per tests' directory, rather
than having a single file in the project root directory. In this way, we don't
have to update all the gitignore files when moving directories, and they get
deleted automatically when a directory with tests is removed.
Testing pre-release kernel features
-----------------------------------
Tests for features not yet in the mainline kernel release are accepted. However,
they must be added only to :master:`runtest/staging`. Once a feature is part
of the stable kernel ABI, the associated test must be moved out of staging.
Testing builds with GitHub Actions
----------------------------------
Master branch is tested in GitHub :repo:`actions`
to ensure LTP builds in various distributions, including old, current and
bleeding edge. ``gcc`` and ``clang`` toolchains are also tested for various
architectures using cross-compilation. For a full list of tested distros, please
check :master:`.github/workflows/ci-docker-build.yml`.
.. note::
Passing the GitHub Actions CI means that LTP compiles in a variety of
different distributions on their **newest releases**.
The CI also checks for code linting, running ``make check`` in the whole
LTP project.
LTP C And Shell Test API Comparison
-----------------------------------
.. list-table::
:header-rows: 1
* - C API :ref:`struct tst_test` members
- Shell API ``$TST_*`` variables
* - .all_filesystems
- TST_ALL_FILESYSTEMS
* - .bufs
- \-
* - .caps
- \-
* - .child_needs_reinit
- not applicable
* - .cleanup
- TST_CLEANUP
* - .dev_extra_opts
- TST_DEV_EXTRA_OPTS
* - .dev_fs_opts
- TST_DEV_FS_OPTS
* - .dev_fs_type
- TST_FS_TYPE
* - .dev_min_size
- TST_DEVICE_SIZE
* - .format_device
- TST_FORMAT_DEVICE
* - .max_runtime
- TST_TIMEOUT (not exactly the same, a real timeout based on old .timeout
concept. .max_runtime has also an extra 30 sec safety margin for
teardown of the test.)
* - .min_cpus
- not applicable
* - .min_kver
- TST_MIN_KVER
* - .min_mem_avail
- not applicable
* - .mnt_flags
- TST_MNT_PARAMS
* - .min_swap_avail
- not applicable
* - .mntpoint | .mnt_data
- TST_MNTPOINT
* - .mount_device
- TST_MOUNT_DEVICE
* - .needs_cgroup_ctrls
- \-
* - .needs_checkpoints
- TST_NEEDS_CHECKPOINTS
* - .needs_cmds
- TST_NEEDS_CMDS
* - .needs_devfs
- \-
* - .needs_device
- TST_NEEDS_DEVICE
* - .needs_drivers
- TST_NEEDS_DRIVERS
* - .needs_kconfigs
- TST_NEEDS_KCONFIGS
* - .needs_overlay
- \-
* - .needs_rofs
- \-
* - .needs_root
- TST_NEEDS_ROOT
* - .needs_tmpdir
- TST_NEEDS_TMPDIR
* - .options
- TST_PARSE_ARGS | TST_OPTS
* - .resource_files
- \-
* - .restore_wallclock
- not applicable
* - .sample
- \-
* - .save_restore
- \-
* - .scall
- not applicable
* - .setup
- TST_SETUP
* - .skip_filesystems
- TST_SKIP_FILESYSTEMS
* - .skip_in_compat
- \-
* - .skip_in_lockdown
- TST_SKIP_IN_LOCKDOWN
* - .skip_in_secureboot
- TST_SKIP_IN_SECUREBOOT
* - .supported_archs
- not applicable
* - .tags
- \-
* - .taint_check
- \-
* - .tcnt
- TST_CNT
* - .tconf_msg
- not applicable
* - .test | .test_all
- TST_TESTFUNC
* - .test_variants
- \-
* - .tst_hugepage
- not applicable
* - .ulimit
- not applicable
* - not applicable
- TST_NEEDS_KCONFIGS_IFS
* - not applicable
- TST_NEEDS_MODULE
* - not applicable
- TST_POS_ARGS
* - not applicable
- TST_USAGE
.. list-table::
:header-rows: 1
* - C API other structs
- Shell API ``$TST_*`` variables
* - :ref:`struct tst_device`
- TST_DEVICE
+112
View File
@@ -0,0 +1,112 @@
.. SPDX-License-Identifier: GPL-2.0-or-later
.. include:: ../README.rst
.. toctree::
:maxdepth: 3
:hidden:
:caption: For users
users/quick_start
users/setup_tests
users/testers_guide
users/supported_systems
users/stats
users/test_catalog
.. toctree::
:maxdepth: 3
:hidden:
:caption: For developers
developers/setup_mailinglist
developers/writing_tests
developers/test_case_tutorial
developers/api_c_tests
developers/api_shell_tests
developers/api_network_tests
developers/api_kvm_tests
developers/ltp_library
developers/build_system
developers/debugging
developers/documentation
.. toctree::
:maxdepth: 3
:hidden:
:caption: For maintainers
maintainers/patch_review
maintainers/ltp_release_procedure
For users
---------
.. descriptions here are active
:doc:`users/quick_start`
How to build and use LTP framework in few steps
:doc:`users/setup_tests`
How to setup tests execution
:doc:`users/supported_systems`
A list of supported technologies by the LTP framework
:doc:`users/stats`
Some LTP statistics
:doc:`users/test_catalog`
The LTP test catalog
For developers
--------------
.. descriptions here are active
:doc:`developers/setup_mailinglist`
How to configure git and to start sending patches via :git_man:`send-email`.
:doc:`developers/writing_tests`
Starting guide on writing tests
:doc:`developers/test_case_tutorial`
A tutorial showing how to write a test from scratch using C API
:doc:`developers/api_c_tests`
Walk through the C API features
:doc:`developers/api_shell_tests`
Walk through the Shell API features
:doc:`developers/api_network_tests`
Walk through the network API features
:doc:`developers/api_kvm_tests`
Walk through the KVM API features
:doc:`developers/ltp_library`
Developing new features in the LTP library
:doc:`developers/build_system`
Short introduction to the LTP build system
:doc:`developers/debugging`
How to debug LTP tests
:doc:`developers/documentation`
How to use and develop LTP documentation
For maintainers
---------------
:doc:`maintainers/patch_review`
Steps to follow when reviewing patches
:doc:`maintainers/ltp_release_procedure`
Steps to follow for a new LTP release
Getting help
------------
To report a problem or suggest any feature, please write at ltp@lists.linux.it
-96
View File
@@ -1,96 +0,0 @@
The runtest files contain a list of test cases to be executed.
File Format
-----------
Lines starting with a '#' are comments and blank lines are ignored.
Otherwise, lines start with a test name followed by white space, then some
shell script to be executed. For example
Test Name
| Delimiter Test case argument
| | |
v v v
splice02 seq 1 20000 | splice02 splice02-temp
^ ^ ^
| | |
| Test case executable |
-----------Shell script-------------
So the splice02 runtest entry pipes the output of seq into the splice02 test
executable. Most runtest entries are simpler than this, for example
splice03 splice03
Here the test name and executable have the same name and no arguments have
been supplied.
Run test files should start with a comment describing the tests they contain,
e.g.
#DESCRIPTION:Kernel system calls
Note that the LTP has absorbed a number of other projects. Some of these have
been fully converted to the LTP format, others have runtest files generated
for them during installation, while some use a shell script to integrate them
with the other tests.
Test suites
-----------
- syscalls (except epoll, see below)
- fs
- fsx
- dio
- mm
- ipc
- sched
- math
- pty
if run network tests flag is passed these additional tests are run
- tcp_cmds
- multicast
- rpc
- nfs
To test filesystem with LVM
- testscripts/lvmtest.sh
Device Mapper tests
- ltpdmmapper.sh
Network tests
- network.sh
- testcases/network/sockets/ltpSockets.sh
other filesystem or disk type tests
- autofs1.sh
- autofs4.sh
- diskio.sh
- isofs.sh
- sysfs.sh
AIO/DIO filesystem tests
- ltp-aiodio.sh
Device driver tests (may not run on all platforms)
- acpi
- agp
- base
- drm
- include
- nls
- pci
- tbio
- usb
Open_hpi_testsuite
- run_tests
Open_posix_testsuite
- run_tests
testcases/kernel/syscalls/epoll - The tests require additional installation files. See the README in the epoll directory.
+166
View File
@@ -0,0 +1,166 @@
.. SPDX-License-Identifier: GPL-2.0-or-later
Release process
===============
Preparations
------------
The release procedure generally takes a few weeks. In the first week or two,
patches that should go into the release are reviewed and possibly merged. These
patches are either fixes or patches pointed out by the community.
Patch review, when finished, is followed by a git freeze, which is a period
where only fixes are pushed to the git. During that period community is
expected to run a LTP pre-release tests, reports problems, and/or send fixes to
the mailing list. In this period we are especially making sure that there are
no regressions in the test results on a wide range of distributions and
architectures.
Once the stabilization period has ended the time has finally come to proceed
with the release.
Prepare the release notes
-------------------------
Part of the preparation is also to write the release notes, which are then
added to the GitHub release and also sent as announcement to various mailing
lists (see below).
Have a look at `this release letter <https://lore.kernel.org/ltp/ZGNiQ1sMGvPU_ETp@yuki/>`_
to get the idea how it should look.
Tag the git and push changes to github
--------------------------------------
.. code-block:: bash
cd ltp
echo YYYYMMDD > VERSION
git commit -S -s -m 'LTP YYYYMMDD' VERSION
git tag -s -a YYYYMMDD -m 'LTP YYYYMMDD'
git push origin master:master
git push origin YYYYMMDD
The string ``YYYYMMDD`` should be substituted to the current date.
You can use :master:`tools/tag-release.sh` script to have the above automated
process. It allows you to verify the tag before pushing it and does other
checks.
.. code-block:: bash
$ ./tools/tag-release.sh
===== git push =====
new tag: 'YYYYMMDD', previous tag: '20230127'
tag YYYYMMDD
Tagger: Person-who-released LTP <foo@example.com>
Date: ...
LTP YYYYMMDD
-----BEGIN PGP SIGNATURE-----
...
-----END PGP SIGNATURE-----
commit 3ebc2dfa85c2445bb68d8c0d66e33c4da1e1b3a7
gpg: using RSA key ...
...
Primary key fingerprint: ...
Author: Person-who-released LTP <foo@example.com>
Date: ...
LTP YYYYMMDD
Signed-off-by: Person-who-released LTP <foo@example.com>
diff --git a/VERSION b/VERSION
index af4c41fec..ae488c0e7 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-20230127
+YYYYMMDD
Please check tag and signature. Proceed? [N/y]: y
Pushing changes to upstream git. Proceed? [N/y]: y
...
To github.com:linux-test-project/ltp.git
* [new tag] YYYYMMDD -> YYYYMMDD
Prepare tarballs and metadata documentation
-------------------------------------------
The following procedure will show how to create the release archives and the
metadata documentation:
.. code-block:: bash
# clone already clonned git repository to new folder
cd ..
git clone ltp ltp-full-YYYYMMDD
cd ltp-full-YYYYMMDD
# update all submodules
git submodule update --init
# Generate configure script
make autotools
# Generate tarballs
cd ..
tar -cjf ltp-full-YYYYMMDD.tar.bz2 ltp-full-YYYYMMDD --exclude .git
tar -cJf ltp-full-YYYYMMDD.tar.xz ltp-full-YYYYMMDD --exclude .git
# Generate checksums
md5 ltp-full-YYYYMMDD.tar.xz > ltp-full-YYYYMMDD.tar.xz.md5
sha1 ltp-full-YYYYMMDD.tar.xz > ltp-full-YYYYMMDD.tar.xz.sha1
sha256sum ltp-full-YYYYMMDD.tar.xz > ltp-full-YYYYMMDD.tar.xz.sha256
You can use :master:`tools/create-tarballs-metadata.sh` script to have the above
procedure automated. All generated files are placed in the
``ltp-release-YYYYMMDD`` directory.
.. code-block:: bash
$ ./tools/create-tarballs-metadata.sh
===== git clone =====
Cloning into 'ltp-full-YYYYMMDD'...
done.
===== Update submodules =====
Submodule 'tools/kirk' (https://github.com/linux-test-project/kirk.git) registered for path 'tools/kirk'
...
===== Generate configure script =====
sed -n '1{s:LTP-:m4_define([LTP_VERSION],[:;s:$:]):;p;q}' VERSION > m4/ltp-version.m4
aclocal -I m4
...
===== Generate tarballs =====
===== Generate checksums =====
===== Generate metadata documentation =====
checking for a BSD-compatible install... /usr/bin/install -c
...
Generated files are in '/home/foo/ltp-release-YYYYMMDD', upload them to github
Upload the generated files to GitHub
------------------------------------
Go to :repo:`tags`. Click on ``Add release notes``.
There should be ``Attach binaries ...`` link at the bottom of the page.
Don't forget to upload checksums for the tarballs and metadata documentation
as well.
Send release announcement
-------------------------
The announcement is sent to:
* ltp at lists.linux.it (requires a subscription)
* linux-kernel at vger.kernel.org
* libc-alpha at sourceware.org (requires a subscription)
* valgrind-developers at lists.sourceforge.net (requires a subscription)
CCed to:
* lwn at lwn.net
* akpm at linux-foundation.org
* torvalds at linux-foundation.org
+167
View File
@@ -0,0 +1,167 @@
.. SPDX-License-Identifier: GPL-2.0-or-later
Patch review
============
Anyone can and should review patches. It's the only way to get good at patch
review and for the project to scale. For this reason, we have a short guide on
what to do during the review process.
Goals of patch review
---------------------
#. Prevent false positive test results
#. Prevent false negative test results
#. Keep the code as simple as possible, but no simpler
How to find clear errors
------------------------
A clear error is one where there is unlikely to be any argument if you
provide evidence of it. Evidence being an error trace or logical proof
that an error will occur in a common situation.
The following are examples and may not be appropriate for all tests.
* Merge the patch locally. It should apply cleanly to master.
* Compile the patch with default and non-default configurations.
* Use sanitizers e.g. undefined behavior, address.
* Compile on non-x86
* Compile on x86 with ``-m32``
* Compile testing patches with GitHub Actions in LTP repo fork can cover
various distros/architectures
* Use ``make check``
* Run effected tests in a VM
* Use single vCPU
* Use many vCPUs and enable NUMA
* Restrict RAM to < 1GB.
* Run effected tests on an embedded device
* Run effected tests on non-x86 machine in general
* Run reproducers on a kernel where the bug is present
* Run tests with ``-i0`` and ``-i2``
* Compare usage of system calls with man page descriptions
* Compare usage of system calls with kernel code
* Double check commit message
* Search the LTP library for existing helper functions
* Check doc formatting, see :doc:`../developers/documentation`.
How to find subtle errors
-------------------------
A subtle error is one where you can expect some argument because you
do not have clear evidence of an error. It is best to state these as
questions and not make assertions if possible.
Although if it is a matter of style or "taste" then senior maintainers
can assert what is correct to avoid bike shedding.
* Ask what happens if there is an error, could it be debugged just
with the test output?
* Are we testing undefined behavior?
* Could future kernel behavior change without "breaking userland"?
* Does the kernel behave differently depending on hardware?
* Does it behave differently depending on kernel configuration?
* Does it behave differently depending on the compiler?
* Would it behave differently if the order of checks on syscall parameters
changed in the kernel?
* Will it scale to tiny and huge systems?
* What happens if there are 100+ CPUs?
* What happens if each CPU core is very slow?
* What happens if there are 2TB of RAM?
* Are we repeating a pattern that can be turned into a library function?
* Is a single test trying to do too much?
* Could multiple similar tests be merged?
* Race conditions
* What happens if a process gets preempted?
* Could checkpoints or fuzzsync by used instead?
* Note, usually you can insert a sleep to prove a race condition
exists however finding them is hard
* Is there a simpler way to achieve the same kernel coverage?
How to get patches merged
-------------------------
Once you think a patch is good enough you should add your ``Reviewed-by``
and/or ``Tested-by`` tags. This means you will get some credit for getting
the patch merged. Also some blame if there are problems.
If you ran the test you can add the ``Tested-by`` tag. If you read the
code or used static analysis tools on it, you can add the Reviewed-by
tag.
In addition you can expect others to review your patches and add their
tags. This will speed up the process of getting your patches merged.
Maintainers Checklist
---------------------
Patchset should be tested locally and ideally also in maintainer's fork in
GitHub Actions on GitHub.
.. note::
GitHub Actions do only build testing, passing the CI means only that
the test compiles fine on variety of different distributions and releases.
The test should be executed at least once locally and should PASS as well.
Commit messages should have
* Author's ``Signed-off-by`` tag
* Committer's ``Reviewed-by`` or ``Signed-off-by`` tag
* Check also mailing lists for other reviewers / testers tags, notes and failure
reports
* ``Fixes: hash`` if it fixes particular LTP commit
* ``Fixes: #N`` if it fixes github issue number N, so it's automatically closed
* LTP documentation should be kept up to date.
After patch is accepted or rejected, set correct state and archive in the
`LTP patchwork instance <https://patchwork.ozlabs.org/project/ltp/list/>`_.
New tests
---------
New test should
* Have a record in runtest file
* Test should work fine with more than one iteration (e.g. run with ``-i 100``)
* Run with ``-i 0`` to check that setup and cleanup are coded properly
(no test is being run)
* Have a brief description
* License: the default license for new tests is GPL v2 or later, use
``GPL-2.0-or-later``; the license for test (e.g. GPL-2.0) should not change
unless test is completely rewritten
* Old copyrights should be kept unless test is completely rewritten
C tests
~~~~~~~
* Use :doc:`../developers/api_c_tests`, implementing :ref:`struct tst_test`
* Test binaries are added into corresponding ``.gitignore`` files
* Check coding style with ``make check``
* Metadata documentation
* If a test is a regression test it should include :ref:`.tags<struct tst_tag>` in the
:ref:`struct tst_test` definition
Shell tests
~~~~~~~~~~~
* Use :doc:`../developers/api_shell_tests`
* Check coding style with ``make check``
* If a test is a regression test it should include related kernel or glibc
commits as a comment
LTP library
~~~~~~~~~~~
For patchset touching the LTP library, follow :doc:`../developers/ltp_library`.
-27
View File
@@ -1,27 +0,0 @@
#
# man1 Makefile.
#
# Copyright (C) 2009, Cisco Systems Inc.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along
# with this program; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
#
# Ngie Cooper, July 2009
#
MANPREFIX := 1
top_srcdir ?= ../..
include $(top_srcdir)/include/mk/man.mk
-70
View File
@@ -1,70 +0,0 @@
.\"
.\" $Id: doio.1,v 1.1 2000/07/27 16:59:03 alaffin Exp $
.\"
.\" Copyright (c) 2000 Silicon Graphics, Inc. All Rights Reserved.
.\"
.\" This program is free software; you can redistribute it and/or modify it
.\" under the terms of version 2 of the GNU General Public License as
.\" published by the Free Software Foundation.
.\"
.\" This program is distributed in the hope that it would be useful, but
.\" WITHOUT ANY WARRANTY; without even the implied warranty of
.\" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
.\"
.\" Further, this software is distributed without any warranty that it is
.\" free of the rightful claim of any third person regarding infringement
.\" or the like. Any license provided herein, whether implied or
.\" otherwise, applies only to this software file. Patent licenses, if
.\" any, provided herein do not apply to combinations of this program with
.\" other software, or any other product whatsoever.
.\"
.\" You should have received a copy of the GNU General Public License along
.\" with this program; if not, write the Free Software Foundation, Inc.,
.\" 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
.\"
.\" Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
.\" Mountain View, CA 94043, or:
.\"
.\" http://www.sgi.com
.\"
.\" For further information regarding this notice, see:
.\"
.\" http://oss.sgi.com/projects/GenInfo/NoticeExplan/
.\"
.TH doio 1 10/13/93 "UNICOS Testing"
.SH NAME
\*Cdoio\fR - Executes I/O Requests
.SH IMPLEMENTATION
All Cray Research systems
.SH SYNOPSIS
\*Cdoio\fR
.SH DESCRIPTION
.QS
Doio is one of the device-beater tools.
.PP
Options:
.RS .5i
.IP "-a"
abort on data compare errors
.IP "-n opt"
.IP "-k opt"
lockd request pipe
.IP "-K opt"
use fcntl() file locking
.IP "-r opt"
resource release interval
.IP "-s opt"
syscall log file
.IP "-w opt"
file write log file
.IP "-v"
verify writes if set
.IP "-U opt"
upanic() on varios conditions
.RE
.SH AUTHOR
Mark Maule wrote the code.
.br
Glen Overby wrote the man page.
.SH BUGS
See "Features".
-78
View File
@@ -1,78 +0,0 @@
.\"
.\" $Id: iogen.1,v 1.1 2000/07/27 16:59:03 alaffin Exp $
.\"
.\" Copyright (c) 2000 Silicon Graphics, Inc. All Rights Reserved.
.\"
.\" This program is free software; you can redistribute it and/or modify it
.\" under the terms of version 2 of the GNU General Public License as
.\" published by the Free Software Foundation.
.\"
.\" This program is distributed in the hope that it would be useful, but
.\" WITHOUT ANY WARRANTY; without even the implied warranty of
.\" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
.\"
.\" Further, this software is distributed without any warranty that it is
.\" free of the rightful claim of any third person regarding infringement
.\" or the like. Any license provided herein, whether implied or
.\" otherwise, applies only to this software file. Patent licenses, if
.\" any, provided herein do not apply to combinations of this program with
.\" other software, or any other product whatsoever.
.\"
.\" You should have received a copy of the GNU General Public License along
.\" with this program; if not, write the Free Software Foundation, Inc.,
.\" 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
.\"
.\" Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
.\" Mountain View, CA 94043, or:
.\"
.\" http://www.sgi.com
.\"
.\" For further information regarding this notice, see:
.\"
.\" http://oss.sgi.com/projects/GenInfo/NoticeExplan/
.\"
.TH iogen 1 10/13/93 "UNICOS Testing"
.SH NAME
\*Ciogen\fR - Generate I/O Requests
.SH IMPLEMENTATION
All Cray Research systems
.SH SYNOPSIS
\*Ciogen\fR
.SH DESCRIPTION
.QS
Iogen is one of the device-beater tools.
.PP
Options:
.RS .5i
.IP "-f [opt]"
open flags:
raw, sync, ssd, ldraw, buffered
.IP "-i [opt]"
Number of iterations to run.
0 implies infinite.
.IP "-q"
.IP "-m [opt]"
Offset mode.
One of: random, sequential, reverse.
.IP "-o"
Overlap flag.
.IP "-p [opt]"
output pipe (default is stdout)
.IP "-r [opt]"
specify raw io multiple instead of getting it from the mounted on device.
Only applies to regular files.
.IP "-s [opt]"
System calls to use for I/O.
A list of:
read, write, reada, writea, ssread, sswrite
.IP "-t [opt]"
min transfer size
.IP "-T [opt]"
max transfer size
.RE
.SH AUTHOR
Mark Maule wrote the code.
.br
Glen Overby wrote the man page.
.SH BUGS
See "Features".
-80
View File
@@ -1,80 +0,0 @@
.\"
.\" $Id: ltp-bump.1,v 1.1 2009/05/19 09:39:11 subrata_modak Exp $
.\"
.\" Copyright (c) 2000 Silicon Graphics, Inc. All Rights Reserved.
.\"
.\" This program is free software; you can redistribute it and/or modify it
.\" under the terms of version 2 of the GNU General Public License as
.\" published by the Free Software Foundation.
.\"
.\" This program is distributed in the hope that it would be useful, but
.\" WITHOUT ANY WARRANTY; without even the implied warranty of
.\" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
.\"
.\" Further, this software is distributed without any warranty that it is
.\" free of the rightful claim of any third person regarding infringement
.\" or the like. Any license provided herein, whether implied or
.\" otherwise, applies only to this software file. Patent licenses, if
.\" any, provided herein do not apply to combinations of this program with
.\" other software, or any other product whatsoever.
.\"
.\" You should have received a copy of the GNU General Public License along
.\" with this program; if not, write the Free Software Foundation, Inc.,
.\" 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
.\"
.\" Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
.\" Mountain View, CA 94043, or:
.\"
.\" http://www.sgi.com
.\"
.\" For further information regarding this notice, see:
.\"
.\" http://oss.sgi.com/projects/GenInfo/NoticeExplan/
.\"
.TH BUMP 1 "14 Sep 2000" "LTP" "Linux Test Project"
.SH NAME
ltp-bump \- send signal to tags run by ltp-pan
.SH SYNOPSIS
\fBltp-bump [-1] [-s \fIsig\fB] [\fI-a active-file\fB] [tags...]
.SH DESCRIPTION
Bump will send a SIGINT signal to processes, given that each process has a
corresponding tag in an active-file. The active-file is the same one that is
used by the ltp-pan to start the processes.
If the active file has multiple occurrences of a single tag name then only the
first process will be signaled. You may specify the tag name multiple times
on the commandline if necessary.
.TP 1i
\fB-1\fP
Send a SIGUSR1 signal. By default a SIGINT will be sent.
.TP 1i
\fB-a \fIactive_file\fB
A file containing the tagnames, pids, and commands being run by a ltp-pan. If this
is not specified then the ZOO environment variable will be read for the name of
the directory where the active file can be found.
.TP 1i
\fB-s \fIsig\fB
Used to specify a signal number to send. By default a SIGINT will be sent.
.in -1i
.SH ENVIRONMENT
.TP
ZOO
If set, should name the directory where the active file can be found.
This is ignored if \fI-a\fP is specified.
.SH FILES
.TP
active
Default name of active file if \fI-a\fP is not specified. This is prefixed
by the directory name found in the ZOO environment variable.
.SH "SEE ALSO"
Zoo tools - ltp-pan(1)
.SH DIAGNOSTICS
Exits zero, unless it cannot find the active file or if there were no tags
listed on the commandline.
-262
View File
@@ -1,262 +0,0 @@
.\"
.\" $Id: ltp-pan.1,v 1.1 2009/05/19 09:39:11 subrata_modak Exp $
.\"
.\" Copyright (c) 2000 Silicon Graphics, Inc. All Rights Reserved.
.\"
.\" This program is free software; you can redistribute it and/or modify it
.\" under the terms of version 2 of the GNU General Public License as
.\" published by the Free Software Foundation.
.\"
.\" This program is distributed in the hope that it would be useful, but
.\" WITHOUT ANY WARRANTY; without even the implied warranty of
.\" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
.\"
.\" Further, this software is distributed without any warranty that it is
.\" free of the rightful claim of any third person regarding infringement
.\" or the like. Any license provided herein, whether implied or
.\" otherwise, applies only to this software file. Patent licenses, if
.\" any, provided herein do not apply to combinations of this program with
.\" other software, or any other product whatsoever.
.\"
.\" You should have received a copy of the GNU General Public License along
.\" with this program; if not, write the Free Software Foundation, Inc.,
.\" 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
.\"
.\" Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
.\" Mountain View, CA 94043, or:
.\"
.\" http://www.sgi.com
.\"
.\" For further information regarding this notice, see:
.\"
.\" http://oss.sgi.com/projects/GenInfo/NoticeExplan/
.TH PAN 1 "21 Jan 2011" "LTP" "Linux Test Project"
.SH NAME
ltp-pan \- A light-weight driver to run tests and clean up their pgrps
.SH SYNOPSIS
\fBltp-pan -n tagname [-SyAehp] [-t #s|m|h|d \fItime\fB] [-s \fIstarts\fB] [\fI-x nactive\fB] [\fI-l logfile\fB] [\fI-a active-file\fB] [\fI-f command-file\fB] [\fI-d debug-level\fB] [\fI-o output-file\fB] [\fI-O buffer_directory\fB] [\fI-r report_type\fB] [\fI-C fail-command-file\fB] [cmd]
.SH DESCRIPTION
Pan will run a command, as specified on the commandline, or collection of
commands from a command-file. By default ltp-pan runs one command, choosing it at
random from the whole set of commands available to it. The ltp-pan's name in the
active file is specified by the tagname. When a command terminates ltp-pan will
kill any orphans that may have been left behind in its pgrp. If ltp-pan is
signaled it will kill any active commands and, again, clean up any orphans.
Pan uses the signal ratchet found in other zoo tools. The first time ltp-pan is
signaled it sends a SIGTERM to the active pgrps; the second time it sends
SIGHUP; the third time a SIGINT; after that it always sends SIGKILL.
Pan will not terminate until all the active commands and everything in their
pgrps is dead. It will loop around at 5 second intervals, triggering its own
signal ratchet, until it succeeds in killing the pgrps.
When the ltp-pan starts up it places its own tagname and commandline in the active
file and begins scheduling commands. After a command is started ltp-pan puts an
entry for it into the active file with its indicated tagname. If the command
was specified on the command line, rather than in the command-file, then its
tagname will be "cmdln". When a process terminates ltp-pan frees the active file
entry. If a command terminates and leaves an orphaned pgrp then ltp-pan will put
an entry into the active file called "panorphan" which will be removed only
when the orphaned pgrp is cleaned up. Before ltp-pan exits it will ensure that
all orphaned pgrps are dead (see above) and then it will remove its own
tagname from the active file.
The command-file is a file containing tag/command pairs. Each line in the
file begins with a tag identifying the command, followed by white space, and
then the command and its arguments. A line beginning with the # character is
a comment. Pan recognizes the token "%f" in a command's arguments and
replaces it with a unique identifier--add this to filename arguments to
prevent two instances of the command from interfering with each other.
When ltp-pan receives a SIGUSR2 it stops scheduling new tests and waits for the
active tests to terminate. If the \fB-y\fP option was used then it will begin
scheduling again, otherwise it will exit. It does not propagate the SIGUSR2.
.TP 1i
\fB-A\fP
The all-stop flag. If any command exits non-zero ltp-pan will shutdown its
scheduler and signal any active pgrps. The ltp-pan will exit non-zero after
everything is shut down. By default ltp-pan ignores command exit statuses.
The \fI-e\fP option is implied when this option is used.
.TP 1i
\fB-a \fIactive_file\fB
A file containing the tagnames, pids, and commands being run. If this is
not specified then the ZOO environment variable will be read for the name
of a directory where the active file will be placed, and in this case the
active file's name will be "active". A single active file may be shared
by any number of Zoo tools.
.TP 1i
\fB-C \fIfail-command-file\fB
The file to which all failed test commands will be saved. You can use it later with \fI-f\fP option if you want to run only the failed test cases.
.TP 1i
\fB-d \fIdebug-level\fB
See the source for settings.
.TP 1i
\fB-e\fP
Pan will exit non-zero if any of its commands exited non-zero. By default
ltp-pan ignores command exit statuses.
.TP 1i
\fB-f \fIcommand-file\fB
The file that has a collection of commands that ltp-pan will execute.
.TP 1i
\fB-h\fP
Print some simple help.
.TP 1i
\fB-l \fIlogfile\fB
Name of a log file to be used to store exit information for each of the
commands (tags) that are run. This log file may not be shared with other Zoo
tools or other ltp-pan processes.
.TP 1i
\fB-n \fItagname\fB
The tagname by which this ltp-pan process will be known by the zoo tools. This
is a required argument.
.TP 1i
\fB-o \fIoutput_file\fB
The file to which all test output will be saved. Normally all test output is sent to standard output. This includes each test's standard output and standard error.
.TP 1i
\fB-O \fIbuffer_directory\fB
A directory where ltp-pan can place temporary files to capture test output. This will prevent output from several tests mixing together in the output file.
.TP 1i
\fB-p\fP
Enables printing results in human readable format.
.TP 1i
\fB-r \fIreport_type\fB
This controls the type of output that ltp-pan will produce. Supported formats are \fIrts\fP and \fInone\fP. The default is \fIrts\fP.
.TP 1i
\fB-S\fP
Causes ltp-pan to run commands (tags) sequentially, as they are listed in the
command-file. By default it chooses tags randomly. If a command is specified
on the commandline and a command-file is also specified, then the commandline
tag will be the last command. If this is specified and \fI-s\fP is not
specified then the default setting for \fI-s\fP is equal to the total number
of commands.
.TP 1i
\fB-s \fIstarts\fB
Indicates the number of commands (tags) that should be run before terminating.
Set this to zero to run forever. By default this is set to 1 (but see
\fI-S\fP for an exception). If this is specified and is less than the value
specified for \fI-x\fP then it is bumped up to be equal to the value of
\fI-x\fP (in other words, \fI-x\fP is always satisfied).
.TP 1i
\fB-t #s|m|h|d \fItime\fB
Indicates the length that ltp-pan should run tests. By default this is not set. If specified,
the \fI-s\fP flag is automatically set to 0 (infinite). Presumably, you want as many
tests ran during this timeframe. Duration is measured in \fIs\fPeconds, \fIm\fPinutes,
\fIh\fPours, or \fId\fPays.
.TP 1i
\fB-x \fInactive\fB
Indicates the number of commands (tags) that should be kept active at any one
time. If this is greater than 1 then it is possible to have multiple
instances of the same tag active at once. By default this is 1.
.TP 1i
\fB-y\fP
Causes the ltp-pan scheduler to go idle if a signal is received or if a command
exits non-zero. All active commands and their pgrps will be killed. After
everything is dead the scheduler will restart again where it left off. If the
signal is SIGUSR1 then ltp-pan will behave as if \fI-y\fP had not been specified.
.in -1i
.SH EXAMPLES
In practice, the ZOO environment variable is generally preferred over the
\fI-a\fP option. All examples assume this is being set.
The following creates a ltp-pan named "ex1" with an active file in /tmp/active.
It runs the command "echo hello", keeping 3 copies running at all times,
running 10 copies before terminating.
$ export ZOO=/tmp
.br
$ ltp-pan -n ex1 -s 10 -x 3 echo hello
The next example will use this command file. Call this /tmp/cmds1.
.br
----------cut------
.br
fido ls /bin
.br
rover echo hello wally
.br
gidget sleep 2
.br
lassie ls /etc
.br
----------cut------
.br
Using the above command file, /tmp/cmds1, run one command at a time,
sequentially, running each command only once. If one command should fail then
terminate immediately. An exit log is kept for all the commands.
$ ltp-pan -n ex3 -S -A -f /tmp/cmds1 -l ex3.log
Here is just a simple stress case. In this case the test will run for 24 hours,
printing the output as a human readable format, with the test output at /tmp/output-file
and all failed test commands (if you have any) at /tmp/fail-command-file.
$ ltp-pan -n stress -e -p -q -S -t 24h -a stress -l logfile -f command-file \
-o /tmp/output-file -C /tmp/fail-command-file
.SH LAYERING
Pan is often used in layers. This section extends the above examples to show
how this is done.
The next example will use this command file. Call this /tmp/cmds2. Note that
the embedded ltp-pans inside this file have exit logs, and that %f is used to give
each ltp-pan a unique log file name.
.br
----------cut------
.br
larry ltp-pan -n ex4b -s10 -A -l ex4_%f.log echo hello
.br
curly ltp-pan -n ex4c -S -A -f /tmp/cmds1 -l ex4_%f.log
.br
moe echo done here
.br
----------cut------
.br
The following will run commands from the command file, keeping two at a time
running, choosing them sequentially, and terminating if any of them exits
non-zero.
$ ltp-pan -n ex4 -x2 -A -S -f /tmp/cmds2
Now run the commands in /tmp/cmds2, but this time we want to recover if one of
the commands should exit non-zero. In this example it is possible for the
"larry" or "curly" tags to exit non-zero. When this happens the ltp-pan will kill
all active tags, making sure both larry and curly are dead, and then will
continue scheduling--ensuring that our "done here" message comes out no matter
what.
$ ltp-pan -n ex5 -x2 -A -S -y -f /tmp/cmds2
.SH ENVIRONMENT
.TP
ZOO
If set, should name the directory where the active file should be placed.
This is ignored if \fI-a\fP is specified.
.SH FILES
.TP
active
Default name of active file if \fI-a\fP is not specified. This is prefixed
by the directory name found in the ZOO environment variable.
.TP
PAN_STOP_FILE
The creation of this file in the defined \fITMP\fP directory will cause ltp-pan to
execute one more loop and stop. This is useful when testing needs to be stopped
before its scheduled stop time (\fI-t\fP). By doing a 'touch' on this file, testing
is ended, i.e. touch /tmp/runalltests-2345/PAN_STOP_FILE
.SH "SEE ALSO"
Zoo tools - ltp-bump(1)
.SH DIAGNOSTICS
By default it exits zero unless signaled, regardless of the exit status of any
of the commands it is running. If \fI-A\fP or \fI-e\fP are specified it exits non-zero if
it is signaled or if any of the commands it is running should exit non-zero.
-27
View File
@@ -1,27 +0,0 @@
#
# man3 Makefile.
#
# Copyright (C) 2009, Cisco Systems Inc.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along
# with this program; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
#
# Ngie Cooper, July 2009
#
MANPREFIX := 3
top_srcdir ?= ../..
include $(top_srcdir)/include/mk/man.mk
-179
View File
@@ -1,179 +0,0 @@
.\"
.\" $Id: parse_opts.3,v 1.3 2000/08/31 18:40:28 nstraz Exp $
.\"
.\" Copyright (c) 2000 Silicon Graphics, Inc. All Rights Reserved.
.\"
.\" This program is free software; you can redistribute it and/or modify it
.\" under the terms of version 2 of the GNU General Public License as
.\" published by the Free Software Foundation.
.\"
.\" This program is distributed in the hope that it would be useful, but
.\" WITHOUT ANY WARRANTY; without even the implied warranty of
.\" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
.\"
.\" Further, this software is distributed without any warranty that it is
.\" free of the rightful claim of any third person regarding infringement
.\" or the like. Any license provided herein, whether implied or
.\" otherwise, applies only to this software file. Patent licenses, if
.\" any, provided herein do not apply to combinations of this program with
.\" other software, or any other product whatsoever.
.\"
.\" You should have received a copy of the GNU General Public License along
.\" with this program; if not, write the Free Software Foundation, Inc.,
.\" 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
.\"
.\" Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
.\" Mountain View, CA 94043, or:
.\"
.\" http://www.sgi.com
.\"
.\" For further information regarding this notice, see:
.\"
.\" http://oss.sgi.com/projects/GenInfo/NoticeExplan/
.\"
.TH PARSE_OPTS 3 "21 Jan 2011" "LTP" "Linux Test Project"
.SH NAME
parse_opts \- parse standard and user options for LTP test programs
.SH SYNOPSIS
.nf
.B #include \(rqtest.h\(rq
.B #include \(rqusctest.h\(rq
.sp
.BI "char *parse_opts(int " argc ", char *" argv[] ", "
.BI " option_t " option_array[] ","
.BI " void (*" user_help_func ")());"
.fi
.SH DESCRIPTION
The \fBparse_opts()\fP routine parses options from the command line, looking
for user specified options or standard options (see below). Its arguments
\fIargc\fP and \fIargv\fP are the argument count and array as passed to the
main() function on program invocation. User options may be specified in the
\fIoption_array\fR argument. A help function may be specified in the
\fIuser_help_func\fP argument.
.sp
\fIoption_array\fP is a pointer to the first element of an array of
\fBoption_t\fP. If no additional options are needed, pass NULL.
\fBoption_t\fR is declared in \fBusctest.h\fP as
.nf
.sp
.in 10
typedef struct {
.in 14
char *option;
int *flag;
char **arg;
.in 10
} option_t;
.fi
.PP
The meanings of the different fields are:
.TP
.I option
is a valid option string to be given to getopt().
.TP
.I flag
is a pointer to an integer location to set true if option is given in
\fIargv\fR. This can be NULL if the option doesn't require an argument.
.TP
.I arg
is a pointer to a character pointer variable that will be set with the option
argument if the option is present in argv. This pointer MUST be provided if
the option can take an argument. Failure to provide a location will cause
\fBparse_opts()\fR to return an error.
.PP
.I user_help_func
is a pointer to a function that will be called when the \-h option is found.
This function should print help messages for the options in \fIoption_array\fR
to standard out. The standard help messages are formatted such that the option
designator starts in column 3 and the description starts in column 11.
.sp
.SH "STANDARD OPTIONS"
Below is a list of the standard options defined in \fBparse_opts()\fR:
.TP
.BI \-c " n"
Run \fIn\fR copies of the test in parallel. This is done by forking \fIn\fR
times and running the test as usual. If \-i or \-I are specified, each process
will run for that amount of time.
.TP
.B \-e
Turn on logging all errno's received. This option is to facilitate security
audit testing for MLS.
.TP
.B \-f
Suppresses functional testing messages.
.TP
.B \-h
Print help message. The standard options will be printed first, then a call to
.I user_help_func()
will be made.
.TP
.BI \-i " n"
Run for \fIn\fR iterations. A value of 0 makes the test loop infinitely.
(default 1)
.TP
.BI \-I " x"
The test will loop until \fIx\fR seconds have passed. (default 0.0)
.TP
.B \-p
Pause for SIGUSR1 before testing. The test will pause where you place
TEST_PAUSE. \fIWarning\fR: The test will also fork at this point if \-c is
used.
.TP
.BI \-P " x"
This option will do a delay of \fIx\fR seconds after each iteration. (default 0.0)
.TP
.B \-t
Produce timing statistics. *NOT IMPLEMENTED*
.PP
.sp
The STD_* flags are used by system call test macros defined in usctest.h
(see \fBusctest(3)\fR), or may be used in the user's code.
.SH "RETURN VALUE"
.B parse_opts()
returns a NULL pointer upon successful completion. If an error occurs a
pointer to an error message is returned.
.SH "EXAMPLE"
The following example defines two options, one with an argument, one without.
.sp
.nf
int fflag, Tflag; /* binary flags: opt or not */
char *Topt; /* option arguments */
option_t options[] = {
{ "F", &fflag, NULL }, /* No argument */
{ "T:", &Tflag, &Topt }, /* argument required */
{ NULL, NULL, NULL } /* NULL required to end array */
};
void help()
{
printf(" -F An option with no argument\\n");
printf(" -T opt An option that requires an argument\\n");
}
int main(int argc, char *argv[])
{
char *msg;
if ((msg = parse_opts(argc, argv, options, &help)) != NULL)
error_exit(msg);
return 0;
}
.fi
.sp
The following example shows how to use \fBparse_opts()\fR without defining new options.
.sp
.nf
int main(int argc, char *argv[])
{
char *msg;
if ((msg = parse_opts(argc, argv, NULL, NULL)) != NULL)
error_exit(msg);
return 0;
}
.fi
.SH "SEE ALSO"
usctest(3), getopt(3).
-169
View File
@@ -1,169 +0,0 @@
.\"
.\" $Id: parse_ranges.3,v 1.1 2000/07/27 16:59:03 alaffin Exp $
.\"
.\" Copyright (c) 2000 Silicon Graphics, Inc. All Rights Reserved.
.\"
.\" This program is free software; you can redistribute it and/or modify it
.\" under the terms of version 2 of the GNU General Public License as
.\" published by the Free Software Foundation.
.\"
.\" This program is distributed in the hope that it would be useful, but
.\" WITHOUT ANY WARRANTY; without even the implied warranty of
.\" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
.\"
.\" Further, this software is distributed without any warranty that it is
.\" free of the rightful claim of any third person regarding infringement
.\" or the like. Any license provided herein, whether implied or
.\" otherwise, applies only to this software file. Patent licenses, if
.\" any, provided herein do not apply to combinations of this program with
.\" other software, or any other product whatsoever.
.\"
.\" You should have received a copy of the GNU General Public License along
.\" with this program; if not, write the Free Software Foundation, Inc.,
.\" 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
.\"
.\" Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
.\" Mountain View, CA 94043, or:
.\"
.\" http://www.sgi.com
.\"
.\" For further information regarding this notice, see:
.\"
.\" http://oss.sgi.com/projects/GenInfo/NoticeExplan/
.\"
.TH PARSE_RANGES 3 07/25/2000 "Linux Test Project"
.SH NAME
parse_ranges \- function to parse a string formatted like 'min:max:mult,...'
.SH SYNOPSIS
.nf
int parse_ranges(char *str, int defmin, int defmax, int defmult, int (*parse_func)(), char **rangeptr, char **errptr);
int range_min(char *rbuf, int r);
int range_max(char *rbuf, int r);
int range_mult(char *rbuf, int r);
.fi
.SH DESCRIPTION
parse_ranges() is a function to parse a comma-separated list of range
tokens each having the following form:
.SP
.nf
num
or
min:max[:mult]
.fi
any of the values may be blank (ie. min::mult, :max, etc.) and default
values for missing arguments may be supplied by the caller.
The special first form is short hand for 'num:num'.
After parsing the string, the ranges are put into an array of integers,
which is malloc'd by the routine. The min, max, and mult entries of each
range can be extracted from the array using the range_min(), range_max(),
and range_mult() functions.
If \fIrange_ptr\fP is not NULL, and parse_ranges() successfully parses the
range string (ie. does not return -1), *range_ptr will point to space
malloc'd by parse_ranges(). The user may free this space by calling free().
parse_ranges() parameters are:
.SP
.TP 1i
\fIstr\fP
The string to parse - assumed to be a comma-separated
list of tokens having the above format.
.TP 1i
\fIdefmin\fP
default value to plug in for min, if it is missing
.TP 1i
\fIdefmax\fP
default value to plug in for max, if it is missing
.TP 1i
\fIdefmult\fP
default value to plug in for mult, if missing
.TP 1i
\fIparse_func\fP
A user-supplied function pointer, which parse_ranges()
can call to parse the min, max, and mult strings. This
allows for customized number formats. The function
MUST have the following prototype:
.SP
.nf
int parse_func(char *str, int *val)
.fi
.SP
The function should return -1 if str cannot be parsed
into an integer, or >= 0 if it was successfully
parsed. The resulting integer will be stored in
*val. If parse_func is NULL, parse_ranges will parse
the tokens in a manner consistent with the sscanf %i format.
.TP 1i
\fIrange_ptr\fP
A user-supplied char **, which will be set to point
at malloc'd space which holds the parsed range
values. If range_ptr is NULL, parse_ranges() just
parses the string. The data returned in range_ptr
should not be processed directly - use the functions
range_min(), range_max(), and range_mult() to access
data for a given range.
.TP 1i
\fIerrptr\fP
user-supplied char ** which can be set to point to a
static error string. If errptr is NULL, it is ignored.
.in -1i
.SP
range_min(), range_max(), and range_mult() parameters are:
.SP
.SP
.TP 1i
\fIrbuf\fP
An array of ranges set up by parse_ranges().
.TP 1i
\fIr\fP
The range number to extract information from. Must be an integer >= 0 and
< the number of ranges returned by parse_ranges().
.in -1i
.SH EXAMPLES
\fC
.ta .25i +.25i +.25i +.25i
.nf
/*
* simple example to take a list of ranges on the cmdline (in argv[1]), and
* print a random number from within that range.
*/
#include <stdio.h>
main()
{
extern int parse_ranges(), range_min(), range_max(), range_mult();
extern long random_range(), random_range_seed();
int min, max, mult, nranges;
char *ep, *rp;
random_range_seed(getpid());
if ((nranges = parse_ranges(argv[1], 0, INT_MAX, 1, NULL, &rp, &ep)) < 0) {
fprintf(stderr, "parse_ranges() failed: %s\n", ep);
exit(1);
}
range = random_range(0, nranges-1, 1);
min = range_min(rp, range);
max = range_max(rp, range);
mult = range_mult(rp, range);
fprintf("%d\\n", random_range(min, max-1, mult));
exit(0);
}
\fP
.DT
.SH "SEE ALSO"
random_range(3),
random_range_seed(3),
bytes_by_prefix(3).
.SH DIAGNOSTICS
parse_ranges() returns -1 on error or the number of ranges parsed. No space
will be malloc'd if parse_ranges() fails. Error
messages are passed back through the errptr parameter. There are no error
conditions for range_min(), range_max(), or range_mult().
-114
View File
@@ -1,114 +0,0 @@
.\"
.\" $Id: random_range.3,v 1.1 2000/07/27 16:59:03 alaffin Exp $
.\"
.\" Copyright (c) 2000 Silicon Graphics, Inc. All Rights Reserved.
.\"
.\" This program is free software; you can redistribute it and/or modify it
.\" under the terms of version 2 of the GNU General Public License as
.\" published by the Free Software Foundation.
.\"
.\" This program is distributed in the hope that it would be useful, but
.\" WITHOUT ANY WARRANTY; without even the implied warranty of
.\" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
.\"
.\" Further, this software is distributed without any warranty that it is
.\" free of the rightful claim of any third person regarding infringement
.\" or the like. Any license provided herein, whether implied or
.\" otherwise, applies only to this software file. Patent licenses, if
.\" any, provided herein do not apply to combinations of this program with
.\" other software, or any other product whatsoever.
.\"
.\" You should have received a copy of the GNU General Public License along
.\" with this program; if not, write the Free Software Foundation, Inc.,
.\" 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
.\"
.\" Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
.\" Mountain View, CA 94043, or:
.\"
.\" http://www.sgi.com
.\"
.\" For further information regarding this notice, see:
.\"
.\" http://oss.sgi.com/projects/GenInfo/NoticeExplan/
.\"
.TH random_range 3 07/25/2000 "Linux Test Project"
.SH NAME
random_range \- a set of routines for dealing with integer ranges, and random numbers in a range
.SH SYNOPSIS
.nf
void random_range_seed(int seed)
long random_range(int min, int max, int mult, char **errp)
long random_rangel(long min, long max, long mult, char **errp)
long long random_rangell(long long min, long long max,
long long mult, char **errp)
long random_bit(long mask)
.fi
.SH DESCRIPTION
This is a set of routines for parsing numeric ranges, and choosing random
numbers from a range.
random_range() chooses a random number in the range min-max (inclusive) which
is a multiple of mult. min and max may be any integer, but mult must be
a positive integer greater than 0. errp is a char ** which is used to detect
error conditions. If errp is not NULL, *errp will be set to point to an
error message. If errp is NULL, error conditions cannot be detected by the
caller. If mult is 1 (the most common case), there are no possible error
conditions, and the return value is guaranteed to be valid.
random_range_seed() sets the random number generator seed to the specified
value.
random_bit() will return a randomly selected single bit bitmask from the bits
set in mask. The bit is randomly chosen using random_range().
If mask is zero, zero is returned.
random_range() functions uses lrand48() internally. If the range is bigger
than will fit in a 32 bit long (2G), lrand48() with a
a internal recursive algorithm to produce a random number.
.SH EXAMPLES
\fC
.ta .25i +.25i +.25i +.25i
.nf
#include <stdio.h>
main(argc, argv)
int argc;
char **argv;
{
int r;
char *errp;
extern void random_range_seed();
extern long random_range();
random_range_seed(getpid());
r = random_range(atoi(argv[1]), atoi(argv[2]), atoi(argv[3]), &errp);
if (errp == NULL) {
fprintf(stderr, "random_range failed: %s\n", errp);
exit(1);
} else {
printf("%d\n", r);
}
exit(0);
}
\fP
.fi
.SH "SEE ALSO"
lrand48(3c)
.SH DIAGNOSTICS
If random_range() fails, errp will point to NULL, and the return value will be
undefined. If mult is 1, there are no possible error conditions, so the return
value is always valid in this case.
.SH BUGS
On CRAY systems, random_range(), random_rangel(), random_rangell()
all have the 64 bit limit since int, long and long long are always 64 bits.
On IRIX systems, random_range() can only produce a 32 number.
random_rangel() when compiled as a 32 bit object is still limited to 32 bit
number. random_rangell() can be used to return a value bigger than 32 bits
even when compiled as a 32 bit object.
-114
View File
@@ -1,114 +0,0 @@
.\"
.\" $Id: random_range_seed.3,v 1.1 2000/07/27 16:59:03 alaffin Exp $
.\"
.\" Copyright (c) 2000 Silicon Graphics, Inc. All Rights Reserved.
.\"
.\" This program is free software; you can redistribute it and/or modify it
.\" under the terms of version 2 of the GNU General Public License as
.\" published by the Free Software Foundation.
.\"
.\" This program is distributed in the hope that it would be useful, but
.\" WITHOUT ANY WARRANTY; without even the implied warranty of
.\" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
.\"
.\" Further, this software is distributed without any warranty that it is
.\" free of the rightful claim of any third person regarding infringement
.\" or the like. Any license provided herein, whether implied or
.\" otherwise, applies only to this software file. Patent licenses, if
.\" any, provided herein do not apply to combinations of this program with
.\" other software, or any other product whatsoever.
.\"
.\" You should have received a copy of the GNU General Public License along
.\" with this program; if not, write the Free Software Foundation, Inc.,
.\" 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
.\"
.\" Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
.\" Mountain View, CA 94043, or:
.\"
.\" http://www.sgi.com
.\"
.\" For further information regarding this notice, see:
.\"
.\" http://oss.sgi.com/projects/GenInfo/NoticeExplan/
.\"
.TH random_range 3 07/25/2000 "Linux Test Project"
.SH NAME
random_range \- a set of routines for dealing with integer ranges, and random numbers in a range
.SH SYNOPSIS
.nf
void random_range_seed(int seed)
long random_range(int min, int max, int mult, char **errp)
long random_rangel(long min, long max, long mult, char **errp)
long long random_rangell(long long min, long long max,
long long mult, char **errp)
long random_bit(long mask)
.fi
.SH DESCRIPTION
This is a set of routines for parsing numeric ranges, and choosing random
numbers from a range.
random_range() chooses a random number in the range min-max (inclusive) which
is a multiple of mult. min and max may be any integer, but mult must be
a positive integer greater than 0. errp is a char ** which is used to detect
error conditions. If errp is not NULL, *errp will be set to point to an
error message. If errp is NULL, error conditions cannot be detected by the
caller. If mult is 1 (the most common case), there are no possible error
conditions, and the return value is guaranteed to be valid.
random_range_seed() sets the random number generator seed to the specified
value.
random_bit() will return a randomly selected single bit bitmask from the bits
set in mask. The bit is randomly chosen using random_range().
If mask is zero, zero is returned.
random_range() functions uses lrand48() internally. If the range is bigger
than will fit in a 32 bit long (2G), lrand48() with a
a internal recursive algorithm to produce a random number.
.SH EXAMPLES
\fC
.ta .25i +.25i +.25i +.25i
.nf
#include <stdio.h>
main(argc, argv)
int argc;
char **argv;
{
int r;
char *errp;
extern void random_range_seed();
extern long random_range();
random_range_seed(getpid());
r = random_range(atoi(argv[1]), atoi(argv[2]), atoi(argv[3]), &errp);
if (errp == NULL) {
fprintf(stderr, "random_range failed: %s\n", errp);
exit(1);
} else {
printf("%d\n", r);
}
exit(0);
}
\fP
.fi
.SH "SEE ALSO"
lrand48(3c)
.SH DIAGNOSTICS
If random_range() fails, errp will point to NULL, and the return value will be
undefined. If mult is 1, there are no possible error conditions, so the return
value is always valid in this case.
.SH BUGS
On CRAY systems, random_range(), random_rangel(), random_rangell()
all have the 64 bit limit since int, long and long long are always 64 bits.
On IRIX systems, random_range() can only produce a 32 number.
random_rangel() when compiled as a 32 bit object is still limited to 32 bit
number. random_rangell() can be used to return a value bigger than 32 bits
even when compiled as a 32 bit object.
-313
View File
@@ -1,313 +0,0 @@
.\"
.\" $Id: tst_res.3,v 1.2 2008/06/10 05:52:02 subrata_modak Exp $
.\"
.\" Copyright (c) 2000 Silicon Graphics, Inc. All Rights Reserved.
.\"
.\" This program is free software; you can redistribute it and/or modify it
.\" under the terms of version 2 of the GNU General Public License as
.\" published by the Free Software Foundation.
.\"
.\" This program is distributed in the hope that it would be useful, but
.\" WITHOUT ANY WARRANTY; without even the implied warranty of
.\" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
.\"
.\" Further, this software is distributed without any warranty that it is
.\" free of the rightful claim of any third person regarding infringement
.\" or the like. Any license provided herein, whether implied or
.\" otherwise, applies only to this software file. Patent licenses, if
.\" any, provided herein do not apply to combinations of this program with
.\" other software, or any other product whatsoever.
.\"
.\" You should have received a copy of the GNU General Public License along
.\" with this program; if not, write the Free Software Foundation, Inc.,
.\" 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
.\"
.\" Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
.\" Mountain View, CA 94043, or:
.\"
.\" http://www.sgi.com
.\"
.\" For further information regarding this notice, see:
.\"
.\" http://oss.sgi.com/projects/GenInfo/NoticeExplan/
.\"
.TH TST_RES 3 01/21/2011 "Linux Test Project"
.SH NAME
tst_resm \- Print result message
.sp
tst_resm_hexd \- Print result message, including specified buffer in hexadecimal format
.sp
tst_brkm \- Print result message and break remaining test cases
.sp
tst_old_flush \- Print any messages pending because of CONDENSE mode, and flush output stream
.sp
tst_exit \- Exit test with a meaningful exit value
.sp
tst_environ \- Keep results coming to original stdout
.SH SYNOPSIS
\fB#include "test.h"\fR
.P
.P
\fBvoid tst_resm(int \fIttype\fB, char *\fItmesg, [arg ...]\fR)
.P
\fBvoid tst_resm_hexd(int \fIttype\fB, const void *\fIbuf\fB, size_t \fIsize\fB,
char *\fItmesg, [arg ...]\fR)
.P
\fBvoid tst_brkm(int \fIttype\fB, void (*\fIfunc\fB)(), char *\fItmesg,
[arg ...]\fR)
.P
\fBvoid tst_old_flush()
.P
\fBvoid tst_exit()
.P
\fBint tst_environ()
.P
\fBextern int tst_count;
.br
extern int tst_range;
.br
\fR
.SH DESCRIPTION
.SS Introduction
This library of functions are used by UNICOS tests to report results to
standard output in a consistent manner. It is assumed that tests using this
library have a distinct number of test cases, and that each test case is
distinct and uniquely identified by the test case number. It is also assumed
that test case results are printed in consecutive order, starting with 1.
The library maintains a set of global variables (\fBTCID\fR, \fBTST_TOTAL\fR,
\fBtst_count\fR), which are used by the various functions to format the
results and to keep track of the current result reporting state (i.e. how many
total test cases there are, and how many have been reported so far) for the
calling test.
.P
The \fBTCID\fR and \fBTST_TOTAL\fR global variables are externed in the
library, and MUST be defined/initialized by tests using the library.
\fBTCID\fR must be set to the \fBT\fRest \fBC\fRase \fBID\fRentifier, and
\fBTST_TOTAL\fR must be set to the total number of test cases that will be
reported.
.P
The other global variables are available as externs to tests linked with
tst_res.o. \fBtst_count\fR is the running count of the number of test
results that have been reported so far. The library initializes it to 0, and
it should not be modified by the test.
The details are described below under the appropriate functions.
.SS Arguments
.RS 5
.TP 10
.I ttype
test result type; one of \fBTPASS, TFAIL, TBROK, TCONF, TWARN\fR, or
\fBTINFO\fR (explained below).
.TP 10
.I fname
pointer to a character string holding the name of a file whose contents will
be printed on a new line following \fItmesg\fR. If this pointer is NULL, it
is ignored.
.TP 10
.I tmesg, [arg ...]
pointer to a character string containing a message explaining the test
result. This character string can contain percent-sign conversion
specifications as in \fBprintf\fR(3C) with corresponding \fIarg\fR arguments
following the \fItmesg\fR argument.
.br
\fBNOTE:\fR These routines use static space internally to hold the
expanded message. The maximum size allowed for an expanded message is
2048 bytes.
.TP 10
.I func
pointer to a function which performs either the cleanup necessary prior to
exiting the test or some function executed at the end of each iteration of a
loop.
.TP 10
.I buf
pointer to a buffer whose contents will be printed in hexadecimal format.
.TP 10
.I size
size of the buffer.
.RE
.SS Result Types
The possible test result types defined in \fBtest.h\fR are as follows:
.RS 5
.TP 10
.B TPASS
The test case produced expected results.
.TP 10
.B TFAIL
The test case produced unexpected results.
.TP 10
.B TBROK
A resource needed to execute the test case was not available (e.g. a
temporary file could not be opened).
.TP 10
.B TCONF
The test case was not appropriate for the current hardware or software
configuration (e.g. MLS was not enabled).
.TP 10
.B TWARN
The testing procedure caused undesirable side effects that did not affect
test results (e.g. a temporary file could not be removed after all test
results were recorded).
.TP 10
.B TINFO
An informative message about the execution of the test that does not
correspond to a test case result and does not indicate a problem.
.RE
.SS Function Descriptions
\fBtst_resm()\fR and \fBtst_resm_hexd()\fR are the basic
result reporting functions. They report 1 or more test case results of the
specified \fIttype\fR. All result types are valid for these functions. The
\fBtst_range\fR global variable indicates the number of results that will be
reported for each call to one of these functions. It is initialized by the
library to 1, but may be set to a value > 1 by the test. Each call to one of
these functions will result in \fBtst_range\fR test case results being
reported, each with an identical message (\fItmesg\fR). \fBtst_range\fR is
always reset to 1 by the library before returning to the caller.
.P
\fBtst_brk()\fR and \fBtst_brkm()\fR are used to report results for all test
cases remaining in the test, and then call a cleanup function. The only
result types that are valid for these functions are: \fBTFAIL, TBROK,
and TCONF\fR. When called with a \fIttype\fR of \fBTFAIL\fR or
\fBTBROK\fR, one result of the specified \fIttype\fR will be printed,
followed by results of type \fBTBROK\fR for the remaining test cases. When
called with a \fIttype\fR of \fBTCONF\fR, the specified
\fIttype\fR will be printed for all remaining test cases. If \fIfunc\fR is
not NULL, \fBtst_brk()\fR and \fBtst_brkm()\fR will call \fIfunc\fR after all
results have been printed. If the call to \fIfunc\fR returns,
\fBtst_brk()\fR and \fBtst_brkm()\fR will then call \fBtst_exit()\fR. If
\fIfunc\fR is NULL, \fBtst_brk()\fR and \fBtst_brkm()\fR return to the caller
after all results have been printed. If \fBtst_brk()\fR is called with a
\fIfname\fR argument, the contents of the file will only be printed for the
first reported result. \fBtst_brk()\fR takes the \fIfname\fR argument
whereas \fBtst_brkm()\fR does not.
.P
\fBtst_old_flush()\fR is used to print any results pending because of
\fBCONDENSE\fR or \fBNOPASS\fR modes (described below), and flushes the
output stream.
.P
\fBtst_exit()\fR is used to allow tests to exit with a meaningful exit
value. A bit is set in the exit value for each of the non passing test
case result types (TFAIL, TBROK, and TWARN) encountered by the library.
Thus any bit which is set in the exit value indicates that the
corresponding result flag was used at least once in the test run.
.P
The current bit fields for the result types are as follows:
.RS 5
.TP 10
TPASS
0000 /* .... .... */
.TP 10
TFAIL
0001 /* .... ...1 */
.TP 10
TBROK
0002 /* .... ..1. */
.TP 10
TWARN
0004 /* .... .1.. */
.TP 10
TINFO
0020 /* ...1 .... */
.TP 10
TCONF
0040 /* ..1. .... */
.RE
.P
NOTE: \fBTPASS and TINFO\fR do not have an effect
on the test program exit status.
.P
\fBtst_environ()\fR is used to ensure that results reported by this library
will go to the original stdout, even if the test changes the original stdout
to another file, or closes it. A test may want to do this in order to
redirect output that normally goes to stdout (e.g. printf() output) to a
file. \fBtst_environ()\fR returns 0 upon successful completion, and -1 if it
encountered any problems.
.SS Output Modes
Four output display modes are supported by the \fBtst_resm()\fR family of
functions to enhance output readability. The active mode is controlled via
the environment variable \fBTOUTPUT\fR, which must be set prior to the start
of the test in order to have any effect (see \fBksh\fR(1) for information on
environment variables). The supported modes are as follows:
.RS 5
.TP 15
.B VERBOSE
A test result output line is generated for each test result. This is the
default mode.
.TP 15
.B CONDENSE
Consecutive, identical PASS, FAIL, BROK, CONF, and RETR test results are
condensed into one output line. The test case number field contains the range
of results involved. WARN and INFO output lines are not condensed, but
printed as usual.
.TP 15
.B NOPASS
All PASS, CONF, INFO, and RETR output lines are discarded (i.e. not printed),
and consecutive, identical FAIL and BROK output lines are condensed as in
\fBCONDENSE\fR mode. WARN output lines are printed as usual.
.TP 15
.B DISCARD
All output lines are discarded.
.RE
.SH EXAMPLES
.nf
#include "test.h"
char *TCID = "tsttcs01"; /* set test case identifier */
int TST_TOTAL = 15; /* set total number of test results */
main()
{
.
.
/* a successful test result */
tst_resm(TPASS, "\fIwhat was tested\fR");
.
.
/* break all remaining test results */
tst_brkm(TBROK, cleanup, "\fIwhat didn't work\fR");
/* or */
tst_brk(TBROK, file, cleanup, "\fIwhat didn't work\fR");
.
.
/* exit after all test results have been passed to tst_res */
tst_exit();
}
.fi
.P
Sample output:
.RS 5
.nf
tsttcs01 1 PASS : Able to create MAXUP processes
tsttcs01 2 FAIL : Too many processes (MAXUP+1) created
tsttcs01 3 BROK : tabinfo(PROCTAB, &tbs) failed; errno = 13: Permission denied
.fi
.SH "SEE ALSO"
tst_setup(1),
printf(3C),
ksh(1).
.SH DIAGNOSTICS
.P
A WARN result message will be printed if any of the following occur:
.RS 5
.P
If an invalid test type is specified.
.P
If \fBtst_count\fR is negative.
.P
If one of the \fBtst_brk[m]()\fR routines is called with a test type
other than \fBTFAIL, TBROK, TCONF\fR.
.P
If there are any problems opening/reading/writing the contents of \fIfname\fR.
.RE
.SH LIMITATIONS
If \fIfname\fR is NULL and \fItmesg\fR is NULL or empty, the result message
will be empty. This allows a test to not print a message for a result, but
it is not advised.
.SH NOTES
In multithreaded environment, output of \fBtst_resm_hexd()\fR may be interleaved
with messages produced by other threads.
.SH BUGS
.P
The programmer is free to alter the value of \fBtst_count\fR causing possible
test result order problems.
-141
View File
@@ -1,141 +0,0 @@
.\"
.\" $Id: tst_sig.3,v 1.1 2000/07/27 16:59:03 alaffin Exp $
.\"
.\" Copyright (c) 2000 Silicon Graphics, Inc. All Rights Reserved.
.\"
.\" This program is free software; you can redistribute it and/or modify it
.\" under the terms of version 2 of the GNU General Public License as
.\" published by the Free Software Foundation.
.\"
.\" This program is distributed in the hope that it would be useful, but
.\" WITHOUT ANY WARRANTY; without even the implied warranty of
.\" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
.\"
.\" Further, this software is distributed without any warranty that it is
.\" free of the rightful claim of any third person regarding infringement
.\" or the like. Any license provided herein, whether implied or
.\" otherwise, applies only to this software file. Patent licenses, if
.\" any, provided herein do not apply to combinations of this program with
.\" other software, or any other product whatsoever.
.\"
.\" You should have received a copy of the GNU General Public License along
.\" with this program; if not, write the Free Software Foundation, Inc.,
.\" 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
.\"
.\" Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
.\" Mountain View, CA 94043, or:
.\"
.\" http://www.sgi.com
.\"
.\" For further information regarding this notice, see:
.\"
.\" http://oss.sgi.com/projects/GenInfo/NoticeExplan/
.\"
.TH TST_SIG 3 07/25/2000 "Linux Test Project"
.SH NAME
tst_sig \- set up for unexpected signals
.SH SYNOPSIS
.nf
\fB
#include "test.h"
void tst_sig(fork_flag, handler, cleanup)
char *fork_flag;
int (*handler)();
void (*cleanup)();
\fR
.fi
.SH DESCRIPTION
.P
\fItst_sig\fR is used by UNICOS test case programs
to set up signal handling functions for unexpected
signals. This provides test cases with a graceful means
of exiting following an unexpected interruption by a signal.
\fItst_sig\fR should be called only once by a test
program.
.P
The \fIfork_flag\fR parameter is used to tell \fItst_sig\fR
whether or not to ignore the SIGCHLD signal caused by the death of a
child process that had previously been created by the
\fIfork\fR(2) system call (see \fIsignal\fR(2) for more
information on the SIGCHLD signal).
.P
Setting \fIfork_flag\fR to FORK will cause \fItst_sig\fR to
ignore the SIGCHLD signal. This option should be set if the
test program directly (eg. call \fIfork\fR(2)) or indirectly
(eg. call \fIsystem\fR(3S)) creates a child process.
.P
Setting \fIfork_flag\fR to NOFORK will cause \fItst_sig\fR to
treat the SIGCHLD signal just as any other unexpected
signal (ie. the \fIhandler\fR will be called).
This option should be set by any test program which does not
directly or indirectly create any child processes.
.P
The \fIhandler\fR parameter is
a pointer to a function returning type int which is
executed upon the receipt of an unexpected signal.
The test program may pass a pointer to a signal handling
function or it may elect to use a \fIdefault handler\fR
supplied by \fItst_sig\fR.
The \fIdefault handler\fR is specified by passing DEF_HANDLER
as the \fIhandler\fR argument. Upon receipt of an unexpected
signal, the \fIdefault handler\fR will generate
\fItst_res\fR(3) messages for all test results that had
not been completed at the time of the signal, execute the
\fIcleanup\fR routine, if provided, and call \fItst_exit\fR.
Note: if the \fIdefault handler\fR is used, the variables
\fBTCID\fR and \fBtst_count\fR must be defined and available to
\fItst_sig\fR (see \fItst_res\fR(3)).
.P
The \fIcleanup\fR parameter is a pointer to a user-defined
function returning type void which is executed
by the \fIdefault handler\fR. The \fIcleanup\fR function
should remove any files, directories, processes, etc. created
by the test program.
If no cleanup is required, this parameter should be set to NULL.
.SH EXAMPLES
.nf
#include "test.h"
/*
* the TCID and TST_TOTAL variables must be available to tst_sig
* if the \fIdefault handler\fR is used. The \fIdefault handler\fR will call
* \fItst_res\fR(3) and will need this information.
*/
int TCID = "tsttcs01"; /* set test case identifier */
int TST_TOTAL = 5; /* set total number of test results */
void tst_sig();
/*
* set up for unexpected signals:
* no \fIfork\fR() system calls will be executed during the test run
* use the default signal handler provided by \fItst_sig\fR
* no cleanup is necessary
*/
tst_sig(NOFORK, DEF_HANDLER, NULL);
void tst_sig(), cleanup();
int handler();
/*
* set up for unexpected signals:
* \fIfork\fR() system calls will be executed during the test run
* use user-defined signal handler
* use cleanup
*/
tst_sig(FORK, handler, cleanup);
.fi
.SH "SEE ALSO"
signal(2),
tst_setup(1).
.SH DIAGNOSTICS
.P
\fItst_sig\fR will output warnings in standard \fItst_res\fR
format if it cannot set up the signal handlers.
-76
View File
@@ -1,76 +0,0 @@
.\"
.\" $Id: tst_tmpdir.3,v 1.1 2000/07/27 16:59:03 alaffin Exp $
.\"
.\" Copyright (c) 2000 Silicon Graphics, Inc. All Rights Reserved.
.\"
.\" This program is free software; you can redistribute it and/or modify it
.\" under the terms of version 2 of the GNU General Public License as
.\" published by the Free Software Foundation.
.\"
.\" This program is distributed in the hope that it would be useful, but
.\" WITHOUT ANY WARRANTY; without even the implied warranty of
.\" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
.\"
.\" Further, this software is distributed without any warranty that it is
.\" free of the rightful claim of any third person regarding infringement
.\" or the like. Any license provided herein, whether implied or
.\" otherwise, applies only to this software file. Patent licenses, if
.\" any, provided herein do not apply to combinations of this program with
.\" other software, or any other product whatsoever.
.\"
.\" You should have received a copy of the GNU General Public License along
.\" with this program; if not, write the Free Software Foundation, Inc.,
.\" 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
.\"
.\" Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
.\" Mountain View, CA 94043, or:
.\"
.\" http://www.sgi.com
.\"
.\" For further information regarding this notice, see:
.\"
.\" http://oss.sgi.com/projects/GenInfo/NoticeExplan/
.\"
.TH TST_TMPDIR 3 07/25/2000 "Linux Test Project"
.SH NAME
tst_tmpdir \- create a unique testing directory and make it current.
.br
tst_rmdir \- remove the directory created by \fBtst_tmpdir\fR.
.SH SYNOPSIS
\fBvoid tst_tmpdir()
.P
void tst_rmdir()
.P
extern char *TESTDIR;\fR
.SH DESCRIPTION
The \fBtst_tmpdir()\fR function uses the first three characters of the
\fBTCID\fR global variable as the prefix in forming a unique directory name
(via \fBtempnam\fR(3S)). The directory is then created and made the current
working directory.
.P
If \fBtst_tmpdir()\fR cannot form a unique directory name, create the
directory, or \fBchdir\fR to the directory, it uses \fBtst_brk()\fR to issue
"BROK" messages for all test cases. It then exits via \fBtst_exit()\fR.
Because \fBtst_tmpdir()\fR exits in the event of a problem, a test must call
it \fBbefore\fR performing any operations that would require running a
cleanup routine.
.P
The \fBtst_rmdir()\fR function recursively removes the directory created by
\fBtst_tmpdir()\fR. This function should be used \fBonly\fR as a companion
to \fBtst_tmpdir()\fR and should be called immediately prior to the test
exiting via \fBtst_exit()\fR.
.P
\fBtst_rmdir()\fR uses the \fBsystem\fR(3S) library routine (which in turn
calls \fBfork\fR(2)), so tests that use it \fBcannot\fR treat SIGCHLD as an
unexpected signal.
.P
Users may gain access to the name of the temporary directory by declaring the
external character pointer \fBTESTDIR\fR.
.SH DIAGNOSTICS
The \fBtst_rmdir()\fR function will check the \fBTESTDIR\fR global variable
to ensure that the user is not attempting to remove the root directory or
some unspecified directories with a "*" parameter. All error/warning
messages are delivered through \fBtst_resm()\fR.
.SH "SEE ALSO"
fork(2), system(3S), tst_res(3), tmpnam(3S).
-164
View File
@@ -1,164 +0,0 @@
.\" $Id: usctest.3,v 1.2 2000/08/31 18:40:28 nstraz Exp $
.\"
.\" Copyright (c) 2000 Silicon Graphics, Inc. All Rights Reserved.
.\"
.\" This program is free software; you can redistribute it and/or modify it
.\" under the terms of version 2 of the GNU General Public License as
.\" published by the Free Software Foundation.
.\"
.\" This program is distributed in the hope that it would be useful, but
.\" WITHOUT ANY WARRANTY; without even the implied warranty of
.\" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
.\"
.\" Further, this software is distributed without any warranty that it is
.\" free of the rightful claim of any third person regarding infringement
.\" or the like. Any license provided herein, whether implied or
.\" otherwise, applies only to this software file. Patent licenses, if
.\" any, provided herein do not apply to combinations of this program with
.\" other software, or any other product whatsoever.
.\"
.\" You should have received a copy of the GNU General Public License along
.\" with this program; if not, write the Free Software Foundation, Inc.,
.\" 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
.\"
.\" Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
.\" Mountain View, CA 94043, or:
.\"
.\" http://www.sgi.com
.\"
.\" For further information regarding this notice, see:
.\"
.\" http://oss.sgi.com/projects/GenInfo/NoticeExplan/
.\"
.TH USCTEST 3 01/21/2011 "Linux Test Project"
.SH NAME
usctest \- macros and libraries for common functions in system call tests
.SH SYNOPSIS
\fBRoutines:\fR
.br
.in +1
char *\fBparse_opts(\fI...\fB)\fR
.in -1
.sp
\fBMacros\fR
.in +1
.br
\fBTEST_PAUSE\fR
.br
\fBTEST(\fIsyscall\fB)\fR
.br
.\"\fBTEST_CALLER(\fIsyscall\fB, \fIpid\fB)\fR
.\".br
\fBTEST_VOID(\fIsyscall\fB)\fR
.br
\fBTEST_CLEANUP\fR
.br
\fBTEST_LOOPING(\fIcounter\fB)\fR
.br
\fBTEST_ERROR_LOG(\fIerrno\fB)\fR
.br
\fBTEST_EXP_ENOS(\fIarray\fB)\fR
.in -1
.sp
\fBGlobal Variable(s)\fR (see \fBparse_opts(3)\fR for complete list):
.br
.in +1
int \fBTEST_RETURN\fR; /* set by the \fBTEST\fR macro to the return code from \fIsyscall\fR */
.br
int \fBTEST_ERRNO\fR; /* set by the \fBTEST\fR macro to the value of \fBerrno\fR after \fIsyscall\fR returns */
.br
/* All STD_* variables referenced below are set by the \fBparse_opts(3)\fR routine. */
.in -1
.SH DESCRIPTION
The \fBTEST_PAUSE\fR macro checks if the global variable STD_PAUSE is set. If so, it
pauses for a SIGUSR1 before continuing execution. The signal handler used does nothing.
After the signal is processed, the previous action is replaced for SIGUSR1.
.sp
The \fBTEST(\fIsyscall\fB)\fR macro executes (\fIsyscall\fR) and times its execution.
It saves the max time, min time, accumulated time, and
execution count, if STD_TIMING_ON is set.
.sp
.\"The\fBTEST_CALLER(\fIsyscall\fB, \fIpid\fB)\fR macro executes (\fIsyscall\fR) and times its execution.
.\"It saves the max time, min time, accumulated time, and
.\"execution count, if STD_TIMING_ON is set and if \fIpid\fR is equal to the current pid.
.\".sp
The \fBTEST_VOID(\fIsyscall\fB)\fR macro works exactly the same as the \fBTEST()\fR
macro except that it does NOT set the global \fBTEST_RETURN\fR. It is intended
to be used with system calls that do not have a return value.
.sp
The \fBTEST_CLEANUP\fR macro prints timing statistics,
accumulated through the TEST macro, if STD_TIMING_ON is set. Also, prints the \fBerrno\fR return
counts as logged by the \fBTEST_ERROR_LOG\fR macro, if STD_ERR_LOG is set. \fBTEST_CLEANUP\fR uses
\fBtst_resm(3)\fR to output this information.
.sp
The \fBTEST_LOOPING(\fIcounter\fB)\fR macro checks \fIcounter\fR against
the global variable STD_LOOP_COUNTER. If \fIcounter\fR is less than STD_LOOP_COUNTER or STD_INFINITE
is set, it returns TRUE.
.sp
The \fBTEST_ERROR_LOG\fR macro records the return of \fIerrno\fR as unexpected, unless the option to
turn it off is specified on the command line.
.sp
The \fBTEST_EXP_ENOS(\fIarray\fB)\fR macro sets an internal flag for each errno in \fIarray\fR, indicating
that the errno is expected at some point in the test. This is used by the TEST_CLEANUP macro to determine
which errnos are expected when printing the log. The \fIarray\fR must be zero terminated.
.sp
The \fBparse_opts\fR routine parses the command line (see \fBparse_opts(3)\fR). All STD_* global
variables used are set by the \fBparse_opts(3)\fR routine.
.SH EXAMPLES
Below is a partial template of a system call test using these routines, macros, and global variables.
.nf
void setup(void)
{
TEST_PAUSE; /* Pause if option specified */
}
void cleanup(void)
{
TEST_CLEANUP;
}
int main(int argc, char *argv[])
{
int lc;
char *msg;
int exp_enos[]={EACCESS, 0};
TEST_EXP_ENOS(exp_enos); /* set expected errnos */
setup(); /* execute setup */
/* parse options */
msg = parse_opts(ac, av, NULL, NULL);
/* Check parse_opts return */
for (lc=0; TEST_LOOPING(lc); lc++) {
TEST(open("file", O_RDWR))
if (TEST_RETURN == -1) {
TEST_ERROR_LOG(TEST_ERRNO)
/* BREAK test case, or whatever... */
}
}
cleanup();
tst_exit();
}
.fi
.SH "SEE ALSO"
parse_opts(3).
.SH "RETURN VALUES"
The TEST_LOOPING macro evaluates to TRUE (1) or FALSE (0), and is intended for
use in while or for loops. The TEST macro places the return value from
\fIsyscall\fR in the global variable TEST_RETURN and the errno in the global
variable TEST_ERRNO. The \fBTEST_PAUSE\fR, \fBTEST_CLEANUP\fR,
\fBTEST_ERROR_LOG\fR, and \fBTEST_EXP_ENOS\fR macros do not have any return
values.
-171
View File
@@ -1,171 +0,0 @@
-------------
--- Intro ---
-------------
Linux running on processors without a memory management unit place certain
restrictions on the userspace programs. Here we will provide some guidelines
for people who are not familiar with such systems.
If you are not familiar with virtual memory, you might want to review some
background such as:
http://en.wikipedia.org/wiki/Virtual_Memory
/usr/src/linux/Documentation/nommu-mmap.txt
----------------------------
--- No memory protection ---
----------------------------
By virtue of every process getting its own virtual memory space, applications
are protected from each other. So a bad memory access in one will not affect
the memory of another. When processors forgo virtual memory, they typically
do not add memory protection back in to the hardware. There are one or two
exceptions to this rule, but for now, we'll assume no one supports it.
In practical terms, this means you cannot dereference bad pointers directly
and expect the kernel to catch and kill your application. However, you can
expect the kernel to catch some bad pointers when given to system calls.
For example, this will "work" in the sense that no signal will be sent:
char *foo = NULL;
foo[0] = 'a';
foo[1] = 'b';
However, the kernel should return errors when using "standard" bad pointers
with system calls. Such as:
char *foo = NULL;
write(1, foo, 10);
-> kernel will return EFAULT or similar
The other bad pointer you can rely on in your tests is -1:
char *foo = (void *)-1;
read(0, foo, 10);
-> kernel will return EFAULT or similar
Otherwise, no bad pointer may reliably be tested, either directly or
indirectly via the kernel. This tends to be a large part of the UCLINUX
ifdef code that shows up in LTP.
----------------
--- No forks ---
----------------
The ubiquitous fork() function relies completely on the Copy On Write (COW)
functionality provided by virtual memory to share pages between processes.
Since this isn't feasible without virtual memory, there is no fork() function.
You will either get a linker error (undefined reference to fork) or you will
get a runtime failure of ENOSYS.
Typically, fork() is used for very few programming paradigms:
- daemonization
- run a program
- parallelism
For the daemonization functionality, simply use the daemon() function. This
works under both MMU and NOMMU systems.
To run a program, simply use vfork() followed by an exec-style function.
And change the error handler in the child from exit() to _exit(). This too
works under both MMU and NOMMU systems. But be aware of vfork() semantics --
since the parent and child share the same memory process, the child has to be
careful in what it does. This is why the recommended construct is simply:
pid_t child = vfork();
if (vfork == 0)
_exit(execl(....));
For parallelism where processes use IPC to work together, you have to options,
neither of which are easy. You can rewrite to use threads, or you can re-exec
yourself with special flags to pass along updated runtime state. This is what
the self_exec() helper function in LTP is designed for.
-------------------------
--- No overcommitting ---
-------------------------
Virtual memory allows people to do malloc(128MiB) and get back a buffer that
big. But that buffer is only of virtual memory, not physical. On a NOMMU
system, the memory comes immediately from physical memory and takes it away
from anyone else.
Avoid large mallocs.
---------------------
--- Fragmentation ---
---------------------
On a MMU system, when physical memory gets fragmented, things slow down. But
they keep working. This is because every new process gets a clean virtual
memory address space. While processes can fragment their own virtual address
space, this usually takes quite a long time and a lot of effort, so generally
it is not a problem people hit.
On a NOMMU system, when physical memory gets fragmented, access to large
contiguous blocks becomes unavailable which means requests fail. Even if your
system has 40MiB _total_ free, the largest contiguous block might only be 1MiB
which means that allocations larger than that will always fail.
Break up your large memory allocations when possible. Generally speaking,
single allocations under 2MiB aren't a problem.
-----------------
--- No paging ---
-----------------
No virtual memory means you can't mmap() a file and only have the pages read in
(paged) on the fly. So if you use mmap() on a file, the kernel must allocate
memory for it and read in all the contents immediately.
---------------------
--- No swap space ---
---------------------
See the "No paging" section above. For the same reason, there is no support
for swap partitions. Plus, nommu typically means embedded which means flash
based storage which means limited storage space and limited number of times
you can write it.
-------------------------
--- No dynamic stacks ---
-------------------------
No virtual memory means that applications can't all have their stacks at the
top of memory and allowed to grown "indefinitely" downwards. Stack space is
fixed at process creation time (when it is first executed) and cannot grow.
While the fixed size may be increased, it's best to avoid stack pressure in
the first place.
Avoid the alloca() function and use malloc()/free() instead.
Avoid declaring large buffers on the stack. Some people like to do things
such as:
char buf[PATH_MAX];
This will most likely smash the stack on nommu systems ! Use global variables
(the bss), or use malloc()/free() type functions.
-------------------------------
--- No dynamic data segment ---
-------------------------------
No virtual memory means that mappings cannot arbitrarily be extended. Another
process might have its own mapping right after yours! This is where the brk()
and sbrk() functions come into play. These are most often used to dynamically
increase the heap space via the C library, but a few people use these manually.
Best if you simply avoid them, and if you're writing tests to exercise these
functions specifically, make them nops/XFAIL for nommu systems.
-------------------------------
--- Limited shared mappings ---
-------------------------------
No virtual memory means files cannot be mmapped in and have writes to it
written back out to disk on the fly. So you cannot use MAP_SHARED when
mmapping a file.
-------------------------
--- No fixed mappings ---
-------------------------
The MAP_FIXED option to mmap() is not supported. It doesn't even really work
all that well under MMU systems.
Best if you simply avoid it, and if you're writing tests to exercise this
option specifically, make them nops/XFAIL for nommu systems.
@@ -17,7 +17,6 @@ Let's start with an example, following code is a simple test for a 'getenv()'.
[source,c]
-------------------------------------------------------------------------------
/*\
* [Description]
* Tests basic functionality of getenv().
*
* - create an env variable and verify that getenv() can get it
@@ -94,26 +93,32 @@ in range of [0, '.tcnt' - 1].
IMPORTANT: Only one of '.test' and '.test_all' can be set at a time.
Each test has a limit on how long it can run and the limit composes of two
parts max_runtime and timeout. The max_runtime is a limit for how long can the
'.test_all' or a set of '.test' functions take and the timeout is static part
that should cover the duration of test setup and cleanup plus some safety.
Each test has a limit on how long it can run, composed of two parts: 'runtime'
and 'timeout'. The 'runtime' is the limit for how long the '.test_all' or a set
of '.test' main functions can execute. The 'timeout', on the other hand, applies
to the total time for setup, single test function invocation, cleanup, and some
additional safety margin. If test without an explicit 'runtime', the 'timeout'
governs the entire test duration.
The timeout timer is also reset on each subsequent iteration with the test -i
parameter, variants or .all_filesystems.
Any test that runs for more than a second or two has to make sure to:
- set the runtime either by setting the '.max_runtime' in tst_test or by
calling 'tst_set_max_runtime()' in the test setup
- set the runtime by setting '.runtime' in tst_test and calling 'tst_set_runtime()'
to monitor the remaining runtime and ensure the test exits when the runtime
limit is reached.
- monitor remaning runtime by regular calls to 'tst_remaining_runtime()' and
exit when runtime has been used up
- set the timeout by setting '.timeout' in tst_test to limit the whole test
run that does not use 'tst_remaining_runtime()'.
Test is free to exit before max_runtime has been used up for example when
Test is free to exit before runtime has been used up for example when
minimal number of iteration was finished.
The limit is applied to a single call of the '.test_all' function that means
that for example when '.test_variants' or '.all_filesystems' is set the whole
test will be limited by 'variants * (max_runtime + timeout)' seconds and the
test runtime will be likely close to 'variants * max_runtime' seconds.
test will be limited by 'variants * (runtime + timeout)' seconds and the
test runtime will be likely close to 'variants * runtime' seconds.
[source,c]
-------------------------------------------------------------------------------
@@ -224,10 +229,12 @@ void tst_res(int ttype, char *arg_fmt, ...);
Printf-like function to report test result, it's mostly used with ttype:
|==============================
| 'TPASS' | Test has passed.
| 'TFAIL' | Test has failed.
| 'TINFO' | General message.
| 'TWARN' | Something went wrong but we decided to continue. Mostly used in cleanup functions.
| 'TPASS' | Test has passed.
| 'TFAIL' | Test has failed.
| 'TINFO' | General message.
| 'TDEBUG' | Debug message (new C API only, printed with '-D' or via 'LTP_ENABLE_DEBUG=1' or 'y'
environment variable), only for messages which would be too verbose for normal run.
| 'TWARN' | Something went wrong but we decided to continue. Mostly used in cleanup functions.
|==============================
The 'ttype' can be combined bitwise with 'TERRNO' or 'TTERRNO' to print
@@ -238,13 +245,13 @@ The 'ttype' can be combined bitwise with 'TERRNO' or 'TTERRNO' to print
void tst_brk(int ttype, char *arg_fmt, ...);
-------------------------------------------------------------------------------
Printf-like function to report error and exit the test, it can be used with ttype:
Printf-like function to report result and exits current test. If test uses
'.all_filesystems', '.test_variants' etc. the 'tst_brk()' exits current test
iteration e.g. currently running filesystem test or a test variant unless
'ttype' is set to 'TBROK'.
|============================================================
| 'TBROK' | Something has failed in test preparation phase.
| 'TCONF' | Test is not appropriate for current configuration
(syscall not implemented, unsupported arch, ...)
|============================================================
If 'ttype' is set to 'TBROK' all test processes are killed and the test exits
immediately with an error.
The 'ttype' can be combined bitwise with 'TERRNO' or 'TTERRNO' to print
'errno', 'TST_ERR' respectively.
@@ -338,7 +345,7 @@ if (TST_RET > -1) {
-------------------------------------------------------------------------------
The +TEST+ macro sets +TST_RET+ to its argument's return value and +TST_ERR+ to
+errno+. The +TTERNO+ flag can be used to print the error number's symbolic
+errno+. The +TTERRNO+ flag can be used to print the error number's symbolic
value.
No LTP library function or macro, except those in 'tst_test_macros.h', will
@@ -399,13 +406,25 @@ WARNING: This function is not thread safe.
[source,c]
-------------------------------------------------------------------------------
void tst_set_max_runtime(int max_runtime);
void tst_set_timeout(int timeout);
-------------------------------------------------------------------------------
Allows for setting max_runtime per test iteration dynamically in the test 'setup()',
the timeout is specified in seconds. There are a few testcases whose runtime
can vary arbitrarily, these can disable timeouts by setting it to
TST_UNLIMITED_RUNTIME.
Allows for setting the entire timeout dynamically during the test setup(). The
timeout is specified in seconds and represents the total time allowed for a single
test iteration, including setup, runtime, and teardown phases.
[source,c]
-------------------------------------------------------------------------------
void tst_set_runtime(int runtime);
-------------------------------------------------------------------------------
Allows for setting the runtime per test iteration dynamically during the test 'setup()'.
The runtime is specified in seconds and represents the duration the test is allowed
to execute its main workload, excluding setup and teardown phases.
This function is useful for tests where the duration of the main workload can be
controlled or needs to be adjusted dynamically. For example, tests that loop until
the runtime expires can use this function to define how long they should run.
[source,c]
-------------------------------------------------------------------------------
@@ -628,15 +647,15 @@ IMPORTANT: You have to set the '.forks_child' flag in the test structure
Results reported by 'tst_res()' are propagated to the parent test process via
block of shared memory.
Calling 'tst_brk()' causes child process to exit with non-zero exit value.
Which means that it's safe to use 'SAFE_*()' macros in the child processes as
well.
Calling 'tst_brk()' causes child process to set the test library abort flag and
exits the test immediately. Which means that it's safe to use 'SAFE_*()' macros
in the child processes as well.
Children that outlive the 'test()' function execution are waited for in the
test library. Unclean child exit (killed by signal, non-zero exit value, etc.)
will cause the main test process to exit with 'tst_brk()', which especially
means that 'TBROK' propagated from a child process will cause the whole test
to exit with 'TBROK'.
will cause the main test process to exit with 'tst_brk()'. That means that all
test child processes are supposed to exit with success unless they are
explicitly waited for.
If a test needs a child that segfaults or does anything else that cause it to
exit uncleanly all you need to do is to wait for such children from the
@@ -1332,8 +1351,9 @@ return value is '255' if 'execvp()' failed with 'ENOENT' and '254' otherwise.
'stdout_path' and 'stderr_path' determine where to redirect the program
stdout and stderr I/O streams.
The 'SAFE_CMD()' macro can be used automatic handling non-zero exits (exits
with 'TBROK') and 'ENOENT' (exits with 'TCONF').
'SAFE_CMD()' is a wrapper for 'tst_cmd()' which can be used for automatic
handling non-zero exit (exits with 'TBROK') and 'ENOENT' (the program not in
'$PATH', exits with 'TCONF').
.Example
[source,c]
@@ -1631,7 +1651,7 @@ with 'TBROK'. This behavior can be changed using tst_path_val.flags:
* 'TST_SR_TBROK_RO' End test with 'TBROK' if the file is read-only
* 'TST_SR_TCONF_RO' End test with 'TCONF' if the file is read-only
* 'TST_SR_SKIP_RO' Continue without saving the file if it is read-only
* 'TST_SR_IGNORE_ERR' Ignore errors when writing new value into the file
* 'TST_SR_IGNORE_ERR' Ignore all errors during reading and writing the file
Common flag combinations also have shortcuts:
@@ -1812,7 +1832,7 @@ fault or EFAULT depending on if the access happened in userspace or the kernel
respectively. The canary before the buffer will also catch any write access
outside of the buffer.
The purpose of the patch is to catch off-by-one bugs which happens when
The purpose of this feature is to catch off-by-one bugs which happens when
buffers and structures are passed to syscalls. New tests should allocate
guarded buffers for all data passed to the tested syscall which are passed by
a pointer.
@@ -2016,9 +2036,8 @@ static struct tst_test test = {
--------------------------------------------------------------------------------
Above is a minimal template for a test using fuzzy-sync. In a simple case, you
just need to put the bits you want to race inbetween 'start_race' and
'end_race'. Meanwhile, any setup you need to do per-iteration goes outside the
windows.
just need to put the bits you want to race between 'start_race' and 'end_race'.
Meanwhile, any setup you need to do per-iteration goes outside the windows.
Fuzzy sync synchronises 'run_a' and 'run_b', which act as barriers, so that
neither thread can progress until the other has caught up with it. There is
@@ -2336,7 +2355,7 @@ Some tests require at least size(MB) of free RAM or Swap.
To make sure that test will run only on systems with more than minimal
required amount of RAM set `.min_mem_avail = N`.
Similarily for tests that require certain amount of free Swap use
Similarly for tests that require certain amount of free Swap use
`.min_swap_avail = N`.
1.40 Test tags
@@ -2424,6 +2443,25 @@ Test can be skipped on various conditions: on enabled SecureBoot
('.skip_in_secureboot = 1'), lockdown ('.skip_in_lockdown = 1') or in 32-bit
compat mode ('.skip_in_compat = 1').
1.43 Set resource limits
~~~~~~~~~~~~~~~~~~~~~~~~
'.ulimit' allows to set resource limits on particular resource. NOTE: It sets 'rlim_max'
only if it's higher than 'rlim_cur'.
[source,c]
-------------------------------------------------------------------------------
#include "tst_test.h"
static struct tst_test test = {
...
.ulimit = (const struct tst_ulimit_val[]) {
{RLIMIT_STACK, RLIM_INFINITY},
{}
},
};
-------------------------------------------------------------------------------
2. Common problems
------------------
@@ -143,7 +143,7 @@ static void setup(void)
When opening a localhost socket isn't enough and the test needs special device
or routing configuration, the netdevice library can create the required network
setup without calling external programs. Internally, the netdevice functions
use a rtnetlink socket to communicate with the kernel.
use a netlink socket to communicate with the kernel.
All of these functions will call +tst_brk()+ on failure, unless stated
otherwise. Error values described below are returned only during test cleanup
@@ -274,12 +274,12 @@ static void setup(void)
}
-------------------------------------------------------------------------------
3 rtnetlink API
---------------
3 Netlink API
-------------
+#include "tst_rtnetlink.h"+
+#include "tst_netlink.h"+
The rtnetlink library provides helper functions for constructing and sending
The netlink library provides helper functions for constructing and sending
arbitrary messages and parsing kernel responses.
All of the functions below will call +tst_brk()+ on failure, unless stated
@@ -291,16 +291,16 @@ stage.
[source,c]
-------------------------------------------------------------------------------
struct tst_rtnl_context;
struct tst_netlink_context;
struct tst_rtnl_attr_list {
struct tst_netlink_attr_list {
unsigned short type;
const void *data;
ssize_t len;
const struct tst_rtnl_attr_list *sublist;
const struct tst_netlink_attr_list *sublist;
};
struct tst_rtnl_message {
struct tst_netlink_message {
struct nlmsghdr *header;
struct nlmsgerr *err;
void *payload;
@@ -308,17 +308,18 @@ struct tst_rtnl_message {
};
-------------------------------------------------------------------------------
+struct tst_rtnl_context+ is an opaque rtnetlink socket with buffer for
+struct tst_netlink_context+ is an opaque netlink socket with buffer for
constructing and sending arbitrary messages using the functions described
below. Create a new context using +RTNL_CREATE_CONTEXT()+, then free it using
+RTNL_DESTROY_CONTEXT()+ when you're done with it.
below. Create a new context using +NETLINK_CREATE_CONTEXT()+, then free it
using +NETLINK_DESTROY_CONTEXT()+ when you're done with it.
+struct tst_rtnl_attr_list+ is a helper structure for defining complex
+struct tst_netlink_attr_list+ is a helper structure for defining complex
rtnetlink message attribute payloads, including nested attribute lists. Every
list and sublist defined using this structure is terminated by item with
negative +len+.
- +type+ is the attribute type that will be stored in +struct rtattr.rta_type+.
- +type+ is the attribute type that will be stored in +struct nlattr.nla_type+
or +struct rtattr.rta_type+.
- +data+ contains arbitrary attribute payload.
@@ -326,15 +327,15 @@ negative +len+.
set +len+ to 0. The last item in a list or sublist must have negative length.
- +sublist+ contains a nested attribute list which will be appended after
+data+ as part of the attribute payload. +struct rtattr.rta_len+ will be
calculated automatically with proper alignment, do _not_ add the sublist size
to the +len+ field. If you do not want to add nested attributes, set
+sublist+ to +NULL+.
+data+ as part of the attribute payload. +struct nlattr.nla_len+ or
+struct rtattr.rta_len+ will be calculated automatically with proper
alignment, do _not_ add the sublist size to the +len+ field. If you do not
want to add nested attributes, set +sublist+ to +NULL+.
+struct tst_rtnl_message+ is a structure holding partially parsed rtnetlink
messages received from the kernel. +RTNL_RECV()+ returns an array of these
+struct tst_netlink_message+ is a structure holding partially parsed netlink
messages received from the kernel. +NETLINK_RECV()+ returns an array of these
structures with the last item having +NULL+ in the +header+ field. Call
+RTNL_FREE_MESSAGE()+ to free a message list returned by +RTNL_RECV()+.
+NETLINK_FREE_MESSAGE()+ to free a message list returned by +NETLINK_RECV()+.
- +header+ is the netlink header structure of the message. +NULL+ in the header
field terminates a list of messages.
@@ -349,84 +350,110 @@ structures with the last item having +NULL+ in the +header+ field. Call
3.2 Sending and receiving messages
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- +struct tst_rtnl_context *RTNL_CREATE_CONTEXT(void)+ Creates a new
rtnetlink communication context for use with the functions described below.
Returns +NULL+ on error.
- +struct tst_netlink_context *NETLINK_CREATE_CONTEXT(int protocol)+ Creates
a new netlink communication context with given netlink protocol for use
with the functions described below. Returns +NULL+ on error.
- +void RTNL_FREE_MESSAGE(struct tst_rtnl_message *msg)+ Frees an array of
messages returned by +RTNL_RECV()+.
- +void NETLINK_FREE_MESSAGE(struct tst_netlink_message *msg)+ Frees
an array of messages returned by +NETLINK_RECV()+.
- +void RTNL_DESTROY_CONTEXT(struct tst_rtnl_context *ctx)+ Closes a
communication context created by +RTNL_CREATE_CONTEXT()+.
- +void NETLINK_DESTROY_CONTEXT(struct tst_netlink_context *ctx)+ Closes a
communication context created by +NETLINK_CREATE_CONTEXT()+.
- +int RTNL_SEND(struct tst_rtnl_context *ctx)+ Sends all messages waiting
in +ctx+ buffer to the kernel. If there are multiple messages to send, a new
+NLMSG_DONE+ message will be added automatically. Returns the number of
bytes sent on success. Return 0 or negative value on error.
- +int NETLINK_SEND(struct tst_netlink_context *ctx)+ Sends all messages
waiting in +ctx+ buffer to the kernel. If there are multiple messages
to send, a new +NLMSG_DONE+ message will be added automatically. Returns
the number of bytes sent on success. Return 0 or negative value on error.
- +int RTNL_SEND_VALIDATE(struct tst_rtnl_context *ctx)+ Sends all messages
just like +RTNL_SEND()+, then receives the response from the kernel and
validates results of requests sent with the +NLM_F_ACK+ flag. This function
calls +tst_brk()+ as usual if communication fails but it will return error
status without terminating the test if one of the received messages contains
error code. See +RTNL_CHECK_ACKS()+ below for explanation of the return
value.
- +int NETLINK_SEND_VALIDATE(struct tst_netlink_context *ctx)+ Sends all
messages just like +NETLINK_SEND()+, then receives the response from
the kernel and validates results of requests sent with the +NLM_F_ACK+ flag.
This function calls +tst_brk()+ as usual if communication fails but it will
return error status without terminating the test if one of the received
messages contains error code. See +NETLINK_CHECK_ACKS()+ below for
explanation of the return value.
- +int RTNL_WAIT(struct tst_rtnl_context *ctx)+ Waits until data becomes
available to read from the rtnetlink socket (timeout: 1 second). Returns 1
- +int NETLINK_WAIT(struct tst_netlink_context *ctx)+ Waits until data becomes
available to read from the netlink socket (timeout: 1 second). Returns 1
if there is data to read, 0 on timeout or -1 on error.
- +struct tst_rtnl_message *RTNL_RECV(struct tst_rtnl_context *ctx)+ Receives
rtnetlink messages from the kernel. The messages are received in non-blocking
mode so calling +RTNL_WAIT()+ first is recommended. Returns an array of
partially parsed messages terminated by an item with +NULL+ in the +header+
field. On error or when there are no messages to receive, returns +NULL+.
Call +RTNL_FREE_MESSAGE()+ to free the returned data.
- +struct tst_netlink_message *NETLINK_RECV(struct tst_netlink_context *ctx)+
Receives netlink messages from the kernel. The messages are received
in non-blocking mode so calling +NETLINK_WAIT()+ first is recommended.
Returns an array of partially parsed messages terminated by an item with
+NULL+ in the +header+ field. On error or when there are no messages
to receive, returns +NULL+. Call +NETLINK_FREE_MESSAGE()+ to free
the returned data.
- +int RTNL_CHECK_ACKS(struct tst_rtnl_context *ctx, struct tst_rtnl_message
*response)+ Validate results of requests sent with the +NLM_F_ACK+ flag.
Do not call +RTNL_ADD_MESSAGE()+ between +RTNL_SEND()+ and
+RTNL_CHECK_ACKS()+ because it will reset the state of +ctx+ and prevent
result validation. Returns 1 if all messages sent with the +NLM_F_ACK+ flag
have a corresponding message in +response+ and the error code is 0. If any
of the expected response messages is missing, this function will call
+tst_brk()+ (or return 0 during test cleanup phase). If any of the response
messages has non-zero error code, this function will return 0 and store the
first non-zero error code in global variable +tst_rtnl_errno+ (sign-flipped
just like regular libc +errno+).
- +int NETLINK_CHECK_ACKS(struct tst_netlink_context *ctx,
struct tst_netlink_message *response)+ Validate results of requests sent
with the +NLM_F_ACK+ flag. Do not call +NETLINK_ADD_MESSAGE()+ between
+NETLINK_SEND()+ and +NETLINK_CHECK_ACKS()+ because it will reset the state
of +ctx+ and prevent result validation. Returns 1 if all messages sent
with the +NLM_F_ACK+ flag have a corresponding message in +response+ and
the error code is 0. If any of the expected response messages is missing,
this function will call +tst_brk()+ (or return 0 during test cleanup phase).
If any of the response messages has non-zero error code, this function will
return 0 and store the first non-zero error code in global variable
+tst_netlink_errno+ (sign-flipped just like regular libc +errno+).
3.3 Creating messages
~~~~~~~~~~~~~~~~~~~~~
- +int RTNL_ADD_MESSAGE(struct tst_rtnl_context *ctx, const struct nlmsghdr
*header, const void *payload, size_t payload_size)+ Adds new rtnetlink
message to +ctx+ buffer. You need to provide message +header+ and optional
+payload+. +payload_size+ is the size of +payload+ data in bytes. If you
don't want to add any payload data, set +payload+ to +NULL+ and
- +int NETLINK_ADD_MESSAGE(struct tst_netlink_context *ctx, const struct
nlmsghdr *header, const void *payload, size_t payload_size)+ Adds new
netlink message to +ctx+ buffer. You need to provide message +header+ and
optional +payload+. +payload_size+ is the size of +payload+ data in bytes.
If you don't want to add any payload data, set +payload+ to +NULL+ and
+payload_size+ to 0. This function will automatically fill the +nlmsg_len+,
+nlmsg_seq+ and +nlmsg_pid+ fields of the new message header. You don't need
to set those. It'll also automatically add +NLM_F_MULTI+ flag when needed.
Returns 1 on success, 0 on error. Note that the first call of
+RTNL_ADD_MESSAGE()+ after +RTNL_SEND()+ will reset the state of +ctx+
and +RTNL_CHECK_ACKS()+ will not work correctly until the next +RTNL_SEND()+.
+NETLINK_ADD_MESSAGE()+ after +NETLINK_SEND()+ will reset the state of +ctx+
and +NETLINK_CHECK_ACKS()+ will not work correctly until the next
+NETLINK_SEND()+.
- +int RTNL_ADD_ATTR(struct tst_rtnl_context *ctx, unsigned short type, const
void *data, unsigned short len)+ Adds new attribute to the last message
in +ctx+ buffer. See +RTNL_ADD_MESSAGE()+. You need to provide attribute
+type+ which will be stored in +struct rtattr.rta_type+, optional payload
+data+ and payload size +len+ in bytes. If you don't want to add any payload,
set +data+ to +NULL+ and +len+ to 0. Returns 1 on success, 0 on error.
- +int NETLINK_ADD_ATTR(struct tst_netlink_context *ctx, unsigned short type,
const void *data, unsigned short len)+ Adds new +struct nlattr+ attribute
to the last message in +ctx+ buffer. See +NETLINK_ADD_MESSAGE()+. You need
to provide attribute +type+ which will be stored in +struct nlattr.nla_type+,
optional payload +data+ and payload size +len+ in bytes. If you don't want
to add any payload, set +data+ to +NULL+ and +len+ to 0. Returns 1 on
success, 0 on error.
- +int RTNL_ADD_ATTR_STRING(struct tst_rtnl_context *ctx, unsigned short type,
const char *data)+ Adds new string attribute to the last message in +ctx+
buffer. Parameters and return value are the same as for +RTNL_ADD_ATTR()+,
except the payload length is calculated using +strlen()+.
- +int NETLINK_ADD_ATTR_STRING(struct tst_netlink_context *ctx, unsigned short
type, const char *data)+ Adds new +struct nlattr+ string attribute to the
last message in +ctx+ buffer. Parameters and return value are the same as
for +NETLINK_ADD_ATTR()+, except the payload length is calculated using
+strlen()+.
- +int RTNL_ADD_ATTR_LIST(struct tst_rtnl_context *ctx, const struct
tst_rtnl_attr_list *list)+ Adds a list of attributes to the last message
in +ctx+ buffer. See description of +struct tst_rtnl_attr_list+ and
+RTNL_ADD_MESSAGE()+ above. Returns the number of added attributes on
success (nested attributes are not counted), -1 on error.
- +int NETLINK_ADD_ATTR_LIST(struct tst_netlink_context *ctx, const struct
tst_netlink_attr_list *list)+ Adds a list of +struct nlattr+ attributes
to the last message in +ctx+ buffer. See description of
+struct tst_netlink_attr_list+ and +NETLINK_ADD_MESSAGE()+ above. Returns
the number of added attributes on success (nested attributes are not
counted), -1 on error.
- +int RTNL_ADD_ATTR(struct tst_netlink_context *ctx, unsigned short type,
const void *data, unsigned short len)+ Adds new +struct rtattr+ attribute
to the last message in +ctx+ buffer. See +NETLINK_ADD_MESSAGE()+. You need
to provide attribute +type+ which will be stored in +struct rtattr.rta_type+,
optional payload +data+ and payload size +len+ in bytes. If you don't want
to add any payload, set +data+ to +NULL+ and +len+ to 0. Returns 1 on
success, 0 on error.
- +int RTNL_ADD_ATTR_STRING(struct tst_netlink_context *ctx, unsigned short
type, const char *data)+ Adds new +struct rtattr+ string attribute to the
last message in +ctx+ buffer. Parameters and return value are the same as
for +RTNL_ADD_ATTR()+, except the payload length is calculated using
+strlen()+.
- +int RTNL_ADD_ATTR_LIST(struct tst_netlink_context *ctx, const struct
tst_netlink_attr_list *list)+ Adds a list of +struct rtattr+ attributes
to the last message in +ctx+ buffer. See description of
+struct tst_netlink_attr_list+ and +NETLINK_ADD_MESSAGE()+ above. Returns
the number of added attributes on success (nested attributes are not
counted), -1 on error.
Example Usage
+++++++++++++
@@ -440,14 +467,14 @@ Example Usage
#include <arpa/inet.h>
#include "tst_test.h"
#include "tst_rtnetlink.h"
#include "tst_netlink.h"
#include "tst_netdevice.h"
...
void setup(void)
{
struct tst_rtnl_context *ctx;
struct tst_netlink_context *ctx;
int index, ret;
in_addr_t addr;
@@ -465,12 +492,12 @@ void setup(void)
index = NETDEV_INDEX_BY_NAME("ltp_veth1");
info.ifa_index = index;
ctx = RTNL_CREATE_CONTEXT();
RTNL_ADD_MESSAGE(ctx, &header, &info, sizeof(info));
ctx = NETLINK_CREATE_CONTEXT(NETLINK_ROUTE);
NETLINK_ADD_MESSAGE(ctx, &header, &info, sizeof(info));
addr = inet_addr("192.168.123.45");
RTNL_ADD_ATTR(ctx, IFA_LOCAL, &addr, sizeof(addr));
ret = RTNL_SEND_VALIDATE(ctx);
RTNL_DESTROY_CONTEXT(ctx);
ret = NETLINK_SEND_VALIDATE(ctx);
NETLINK_DESTROY_CONTEXT(ctx);
if (!ret) {
tst_brk(TBROK, "Failed to set ltp_veth1 address");
@@ -188,7 +188,7 @@ space as default value is used. Of course, it's possible to use separate functio
1.2 Library environment variables and functions for shell
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Similarily to the C library various checks and preparations can be requested
Similarly to the C library various checks and preparations can be requested
simply by setting right '$TST_FOO'.
[options="header"]
+7
View File
@@ -0,0 +1,7 @@
# Use the same sphinx as on readthedocs.org. When updated, make sure
# sphinx-rtd-theme is compatible with sphinx.
sphinx==7.2.6
sphinx-rtd-theme==2.0.0
linuxdoc==20231020
sphinxcontrib-spelling==7.7.0
-6
View File
@@ -1,6 +0,0 @@
ID DESCRIPTION
LTP-001 Library source files have tst_ prefix
LTP-002 TST_RET and TST_ERR are never modified by test library functions
LTP-003 Externally visible library symbols have the tst_ prefix
LTP-004 Test executable symbols are marked static
LTP-005 Array must terminate with a sentinel value (i.e. NULL or '{}')
1 ID DESCRIPTION
2 LTP-001 Library source files have tst_ prefix
3 LTP-002 TST_RET and TST_ERR are never modified by test library functions
4 LTP-003 Externally visible library symbols have the tst_ prefix
5 LTP-004 Test executable symbols are marked static
6 LTP-005 Array must terminate with a sentinel value (i.e. NULL or '{}')
+161
View File
@@ -0,0 +1,161 @@
aarch
akpm
amd
archiver
archs
args
asciidoc
autoconf
automake
backport
baz
btime
bufs
CCed
cgroup
cgroups
checksum
checksums
cmds
codebase
compat
config
cpus
ctrls
datafiles
dependants
dev
devfs
dio
distro
distros
docparse
doio
executables
fd
filesystem
filesystems
fixup
fs
fstrict
fuzzsync
gcc
gdb
github
gitignore
glibc
growfiles
hugepage
iogen
kbuild
kconfigs
kver
ld
le
libc
libltp
libs
linkable
linux
lockdown
ltp
lwn
Maipo
Makefile
Makefiles
mem
mnt
mntpoint
msg
namespace
namespaces
onwards
openSUSE
patchset
pkgconf
posix
ppc
pre
pre
preprocessor
rebase
reflog
reinit
repo
rofs
runtest
scall
secureboot
sourceware
statx
stdout
structs
stx
subdirectory
subshell
subshells
syscall
syscalls
tcnt
tconf
teardown
testcase
testcases
testsuite
testsuites
tmp
tmpdir
toolchain
toolchains
torvalds
tst
uClibc
ulimit
un
userland
userspace
vCPU
vCPUs
vendoring
vger
wallclock
pid
TBROK
mkfs
hugepages
hugetlbfs
printf
scanf
argv
argc
pthread
futex
hdr
brk
iovec
iov
strdup
aprintf
alloc
hexd
tcases
strsig
strstatus
strerrno
libcap
capset
capget
musl
setrlimit
rlim
optstr
tmpfs
nodev
sys
proc
arg
ver
bitwise
dereferenced
allocator
ptr
+127
View File
@@ -0,0 +1,127 @@
.. SPDX-License-Identifier: GPL-2.0-or-later
Installation and tests execution
================================
Basics requirements to build LTP are the following:
* git
* autoconf
* automake
* make
* gcc
* m4
* pkgconf / pkg-config
* libc headers
* linux headers
.. code-block:: console
$ git clone --recurse-submodules https://github.com/linux-test-project/ltp.git
$ cd ltp
$ make autotools
$ ./configure
.. note::
For optional library dependencies, take a look at the scripts inside :master:`ci/`
directory.
Running single tests
--------------------
LTP provides the possibility to build and run single tests:
.. code-block:: console
$ cd testcases/kernel/syscalls/foo
$ make
$ PATH=$PATH:$PWD ./foo01
Shell testcases are a bit more complicated, since they need to setup ``PATH``
as well as to compiled binary helpers:
.. code-block:: console
$ cd testcases/lib
$ make
$ cd ../commands/foo
$ PATH=$PATH:$PWD:$PWD/../../lib/ ./foo01.sh
Open Posix Testsuite has it's own build system which needs Makefiles to be
generated first:
.. code-block:: console
$ ./configure --with-open-posix-testsuite
$ cd testcases/open_posix_testsuite/
$ make generate-makefiles
$ cd conformance/interfaces/foo
$ make
$ ./foo_1-1.run-test
Compiling and installing all testcases
--------------------------------------
To compile all tests is really simple:
.. code-block:: console
$ make
$ # install LTP inside /opt/ltp by default
$ make install
.. note::
Some tests will be disabled if ``configure`` script won't find the build
dependencies.
Running tests
-------------
To run all the test suites
.. code-block:: console
$ cd /opt/ltp
$ # run syscalls testing suite
$ ./kirk -U ltp -f syscalls
.. note::
Many test cases have to be executed as root.
Test suites (e.g. syscalls) are defined in the ``runtest`` directory. Each file
contains a list of test cases in a simple format.
Each test case has its own executable or script that can directly executed:
.. code-block:: console
$ testcases/bin/abort01
$ # some tests have arguments
$ testcases/bin/mesgq_nstest -m none
$ # vast majority of tests have a help
$ testcases/bin/ioctl01 -h
$ # Many require certain environment variables to be set
$ LTPROOT=/opt/ltp PATH="$PATH:$LTPROOT/testcases/bin" testcases/bin/wc01.sh
Most commonly, the ``PATH`` variable needs to be set and also ``LTPROOT``, but
there are a number of other variables which usually ``kirk`` sets for you.
.. note::
All shell scripts need the ``PATH`` to be set. However, this is not limited
to shell scripts and some C based tests need environment variables as well.
They usually raise a configuration error when this is needed.
Network tests
-------------
Network tests usually require a certain setup that is described in
:master:`testcases/network/README.md`.
+120
View File
@@ -0,0 +1,120 @@
.. SPDX-License-Identifier: GPL-2.0-or-later
Tests setup
===========
The internal LTP library provides a set of features that permits to customize
tests behavior by setting environment variables and using specific tests
arguments.
Library environment variables
-----------------------------
Following environment variables are expected to be set by LTP users. Therefore,
with some exceptions, they have ``LTP_`` prefix. Environment variables with
``TST_`` prefix are used inside LTP shell API and should **not** be set by
users.
.. list-table::
:header-rows: 1
* - Variable
- Note
* - KCONFIG_PATH
- The path to the kernel config file, (if not set, it tries the usual paths
``/boot/config-RELEASE`` or ``/proc/config.gz``)
* - KCONFIG_SKIP_CHECK
- Skip kernel config check if variable set (not set by default)
* - LTPROOT
- Prefix for installed LTP. **Should be always set**, since some tests
need it to use data files (``LTP_DATAROOT``). LTP is by default installed
into ``/opt/ltp``
* - LTP_COLORIZE_OUTPUT
- By default LTP colorizes it's output unless it's redirected to a pipe or
file. Force colorized output behavior: ``y`` or ``1``: always colorize,
``n`` or ``0``: never colorize.
* - LTP_DEV
- Path to the block device to be used. C Language: ``.needs_device = 1``.
Shell language: ``TST_NEEDS_DEVICE=1``.
* - LTP_REPRODUCIBLE_OUTPUT
- When set to ``1`` or ``y`` discards the actual content of the messages
printed by the test (suitable for a reproducible output).
* - LTP_SINGLE_FS_TYPE
- Specifies single filesystem to run the test on instead all supported
(for tests with ``.all_filesystems``).
* - LTP_FORCE_SINGLE_FS_TYPE
- Testing only. Behaves like LTP_SINGLE_FS_TYPE but ignores test skiplists.
* - LTP_DEV_FS_TYPE
- Filesystem used for testing (default: ``ext2``).
* - LTP_TIMEOUT_MUL
- Multiplies timeout, must be number >= 0.1 (> 1 is useful for slow
machines to avoid unexpected timeout). It's mainly for shell API, which
does not have LTP_RUNTIME_MUL. In C API it scales the default 30 sec
safety margin, probably LTP_RUNTIME_MUL should be used instead.
* - LTP_RUNTIME_MUL
- Multiplies maximal test iteration runtime. Tests that run for more than a
second or two are capped on runtime. You can scale the default runtime
both up and down with this multiplier. This is not yet implemented in the
shell API.
* - LTP_IMA_LOAD_POLICY
- Load IMA example policy, see :master:`testcases/kernel/security/integrity/ima/README.md`.
* - LTP_VIRT_OVERRIDE
- Overrides virtual machine detection in the test library. Setting it to
empty string, tells the library that system is not a virtual machine.
Other possible values are ``kvm``, ``xen``, ``zvm`` and ``microsoft``
that describe different types supervisors.
* - PATH
- It's required to adjust path: ``PATH="$PATH:$LTPROOT/testcases/bin"``
* - TMPDIR
- Base directory for template directory (C language: ``.needs_tmpdir = 1``
and shell: ``TST_NEEDS_TMPDIR=1``). Must be an absolute path (default:
'/tmp').
* - LTP_NO_CLEANUP
- Disable running test cleanup (defined in ``TST_CLEANUP``).
Shell API only.
* - LTP_ENABLE_DEBUG
- Enable debug info (value ``1`` or ``y``). Equivalent of ``-D`` parameter.
Environment variables for network tests
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
See :master:`testcases/network/README.md`.
Test execution time and timeout
-------------------------------
The limit on how long a test can run does compose of two parts: ``runtime``
and ``timeout``. The limit does apply to a single test variant. That means, for
example, that tests which run for all available filesystems will apply this
limit for a single filesystem only.
The ``runtime`` is a cap on how long the ``run()`` function can take and for
most testcases this part is set to zero. For tests that do run for more than a
second or two the ``runtime`` has to be defined and the ``run()`` function
has to check actively how much runtime is left.
Test runtime can be scaled up and down with ``LTP_RUNTIME_MUL`` environment
variable or set on a command-line by the ``-I`` parameter. However,
setting the runtime too low will cause long running tests to exit prematurely,
possibly before having a chance to actually test anything.
The timeout is a limit for test setup and cleanup and it's also a safety
margin for the runtime accounting. It's currently set to 30 seconds but it may
change later. If your target machine is too slow, it can be scaled up with the
``LTP_TIMEOUT_MUL`` environment variable.
+9
View File
@@ -0,0 +1,9 @@
.. SPDX-License-Identifier: GPL-2.0-or-later
Statistics
==========
In this section we collect some statistics related to the current state of
LTP tests.
.. include:: ../_static/syscalls.rst
+114
View File
@@ -0,0 +1,114 @@
.. SPDX-License-Identifier: GPL-2.0-or-later
Supported systems
=================
LTP `master <https://github.com/linux-test-project/ltp/commits/master>`_
branch is build tested in
`GitHub Actions <https://github.com/linux-test-project/ltp/actions>`_.
.. note::
There is no CI for the actual test runs.
Kernel version
--------------
Minimal supported kernel version is **4.4**.
Oldest build tested distributions
---------------------------------
.. list-table::
:header-rows: 1
* - Distro
- Kernel
- glibc
- gcc
- clang
* - openSUSE Leap 42.2
- 4.4
- 2.22
- 4.8.5
- \-
* - Ubuntu 18.04 LTS bionic
- 4.15
- 2.27
- 7.3.0
- \-
* - Debian 11 (bullseye)
- 5.10
- 2.31
- 10.2.1
- 11.0.1
For a full list of build tested distros, please check :master:`.github/workflows/ci-docker-build.yml`.
Older distributions are not officially supported, which means that it
may or may not work. It all depends on your luck. It should be possible
to compile latest LTP even on slightly older distributions than we
support with a few manual tweaks, e.g. disabling manually tests for
newly added syscalls, etc. **Trivial fixes/workarounds may be accepted,
but users are encouraged to move to a newer distro.**
If latest LTP cannot be compiled even with some amount of workarounds,
you may result to older LTP releases, however these are **not** supported
in any way. Also if you are trying to run LTP on more than 10 years old
distribution you may as well reconsider you life choices.
Build tested architectures
--------------------------
.. list-table::
:header-rows: 1
* - Architecture
- Build
* - x86_64
- native
* - x86 emulation
- native
* - aarch64
- cross compilation
* - ppc64le
- cross compilation
* - s390x
- cross compilation
Supported C libraries
---------------------
.. list-table::
:header-rows: 1
* - C library
- Note
* - `glibc <https://www.gnu.org/software/libc/>`_
- Targeted libc, tested both compilation and actual test results.
* - `uClibc-ng <https://uclibc-ng.org/>`_
- Although not being tested, it should work as it attempt to maintain a glibc compatible interface.
* - `uClibc <https://www.uclibc.org/>`_
- Older uClibc might have problems.
* - `musl <https://musl.libc.org/>`_
- Not yet fully supported. Check :master:`ci/alpine.sh` script.
* - Android
- Please use `AOSP fork <https://android.googlesource.com/platform/external/ltp>`_.
C version
---------
LTP is compiled with ``-std=gnu99``.
+7
View File
@@ -0,0 +1,7 @@
.. SPDX-License-Identifier: GPL-2.0-or-later
Test catalog
============
.. include:: ../_static/tests.rst
+155
View File
@@ -0,0 +1,155 @@
.. SPDX-License-Identifier: GPL-2.0-or-later
Testers guide to the Linux test project
=======================================
While we try to make LTP work out of the box as much as possible there are
still many things that testers need to consider before the actual testing
starts. It's advisable to make a test plan in order to asses and formalize the
expected test coverage or even just sit down for a while and consider different
aspects of the problem at hand.
Is testing even required?
-------------------------
Some may argue that testing the Linux kernel locally is unnecessary because it
is already thoroughly tested upstream and considered stable. While it's true
that upstream releases generally go through extensive validation, including
test suites like LTP, stability is only guaranteed when you use the upstream
kernel sources and configuration exactly as released.
This assumption breaks down once you apply any changes: whether that's
modifying the source code, enabling/disabling different `.config` options, or
backporting patches. Such changes can introduce subtle bugs or unintended
behavior, even if the upstream kernel is stable.
For example, backporting patches without their full dependency chain can lead
to unexpected regressions. Therefore, its crucial to test your own kernel
builds in the environment where they will actually run, using tools like LTP to
catch issues that does not exists or are not triggered in the upstream
configuration.
Multi dimensionality
--------------------
First of all kernel testing is a multi dimensional problem, just compiling and
running LTP will give you some coverage but very likely not enough. There are
several big gaps that may be easily missed.
For example 64bit Linux kernel provides compatibility layer for 32bit
applications whose code quality is usually a bit worse than the 64bit ABI.
Hence recompiling LTP with `-m32` in compiler flags and running both 64bit and
32bit test binaries is a good start. If you try to make an argument that your
application does not need 32bit support it's better to disable the compat layer
completely since it's possible source of security bugs.
Another dimension is the number of architectures you need to test, for a
general distribution testing you may end up with a couple of them. Different
architectures have different platform code as well as differences in memory
orderings, etc. that all means that running tests on one architecture out of
several will give you incomplete coverage.
Since most of the POSIX API deals with files, the choice of filesystem for the
testing changes the focus and coverage too. LTP defaults to using `/tmp/` as a
temporary directory for the tests. If `/tmp/` is mounted as tmpfs subset of
tests will be skipped, if that is the case it's advisable to point environment
variable `TMPDIR` to a path with a different filesystem instead. Then there are
tests that format a device with a filesystem. LTP defaults to `ext2` and loop
devices for these testcases, that can be changed with environment variables as
well. Lastly but not least a few testcases repeat the test for all supported
filesystem, if you are interested in testing on a single filesystem only, you
can limit these tests to a single filesystem too. See the tests setup for a
comprehensive list of the `evironment variables
<setup_tests.html#library-environment-variables>`_.
Then you also have to decide if you are going to run tests in virtual machine
e.g. `qemu-kvm`, on bare metal or both. Testing in virtual machine will give you
about 90% of the coverage for bare metal and vice versa.
There are other options worth of consideration too, Linux kernel has many
debugging options that are usually disabled on runtime since they incur
significant performance penalty. Having a few more LTP test runs with different
debug options enabled e.g. `KASAN
<https://www.kernel.org/doc/html/latest/dev-tools/kasan.html>`_ or `KMEMLEAK
<https://www.kernel.org/doc/html/latest/dev-tools/kmemleak.html>`_ may help
catch bugs before they materialize in production.
In practice your test matrix may easily explode and you may end up with dozens
of differently configured testruns based on different considerations. The hard
task at hand is not to have too many since computing power is not an infinite
resource and does not scale that easily. If you managed to read up to this
point *"Don't Panic!"* things are almost never as bad as they may seem at first
glance.
It's a good idea to start small with an environment that models your
production. Once that works well you can try different configurations. Select
a few interesting ones and run them for some time in order to get an idea of
their usefulness. If you are feeling adventurous you may try to measure and
compare actual test coverage with one of the tools such as `gcov
<https://www.kernel.org/doc/html/latest/dev-tools/gcov.html>`_ and `lcov
<https://github.com/linux-test-project/lcov>`_. If you do so do not fall into a
trap of attempting to have 100% line coverage. Having 100% of lines executed
during the test does not mean that your test coverage is 100%. Good tests
validate much more than just how much code from the tested binary was executed.
You may need to sacrifice some coverage in order to match the tests runtime to
the available computing power. When doing so `Pareto principle
<https://en.wikipedia.org/wiki/Pareto_principle>`_ is your friend.
Test scope
----------
So far we were talking about a code coverage from a point of maximizing test
coverage while keeping our test matrix as small as possible. While that is a
noble goal it's not the universal holy grail of testing. Different use cases
have different considerations and scope. For a testing before a final release
such testing is very desirable, however for a continuous integration or smoke
testing the main requirement is that feedback loops are as short as possible.
When a developer changes the kernel and submits the changes to be merged it's
desirable to run some tests. Again the hard question is which tests. If we run
all possible tests in all possible combinations it may take a day or two and
the developer will move to a different tasks before the tests have a chance to
finish. If you multiply that by a number of developers in the team you may end
up in a situation where a developer will retire before tests for his patch may
have had a chance to finish.
In this case careful selection of tests is even more important. Having less is
more in this context. One of the first ideas for CI is to skip tests that run
for more than a second or so, happily this can be easily done with `kirk
<https://github.com/linux-test-project/kirk/>`_. In the future we may want to
explore some heuristics that would map the code changes in kernel into a subset
of tests, which would allow for a very quick feedback.
Debugging test failures
-----------------------
You may think that you will enjoy some rest once you have your test matrix
ready and your tests are running. Unfortunately that's where the actual work
starts. Debugging test failures is probably the hardest part of the testing
process. In some cases failures are easily reproducible and it's not that hard
to locate the bug, either in the test or in the kernel itself. There are
however, quite common, cases where the test failure reproduces only in 10% or
even 1% of the test runs. Sometimes tests are not failing in isolation, that is
because operating system has a huge internal state and a test failure manifests
only after running right sequence of tests. All of that does not mean that
there is no bug, that usually means that the bug depends on more prerequisites
that have to manifest at the right time in order to trigger the failure. Sadly
for modern systems that are asynchronous in nature such bugs are more and more
common.
The debugging process itself is not complicated by its nature. You have to
attempt to understand the failure by checking the logs, reading and
understanding the source code, debugging with strace, gdb, etc. Then form a
hypothesis and either prove or disprove it. Rinse and repeat until you end up
with a clear description of what went wrong. Hopefully you will manage to find
the root cause, but you should not be discouraged, if you do not. Debugging
kernel bugs takes a lot of experience and skill one can say as much as is
needed to write the kernel code.
Happy testing!
-5
View File
@@ -1,5 +0,0 @@
/*.txt
/docbook-xsl.css
/metadata.html
/metadata.pdf
/metadata.chunked/
-69
View File
@@ -1,69 +0,0 @@
# SPDX-License-Identifier: GPL-2.0-or-later
# Copyright (c) 2019 Cyril Hrubis <chrubis@suse.cz>
# Copyright (c) 2020 Petr Vorel <pvorel@suse.cz>
top_srcdir ?= ..
include $(top_srcdir)/include/mk/env_pre.mk
include $(top_srcdir)/include/mk/functions.mk
ifeq ($(METADATA_GENERATOR),asciidoctor)
METADATA_GENERATOR_CMD := asciidoctor
METADATA_GENERATOR_PARAMS := -d book metadata.txt
METADATA_GENERATOR_PARAMS_HTML := -b xhtml
METADATA_GENERATOR_PARAMS_PDF := -b pdf -r asciidoctor-pdf
else ifeq ($(METADATA_GENERATOR),asciidoc)
METADATA_GENERATOR_CMD := a2x
METADATA_GENERATOR_PARAMS := --xsltproc-opts "--stringparam toc.section.depth 1" -d book -L --resource="$(PWD)" metadata.txt
METADATA_GENERATOR_PARAMS_HTML := -f xhtml
METADATA_GENERATOR_PARAMS_PDF := -f pdf
METADATA_GENERATOR_PARAMS_HTML_CHUNKED := -f chunked
else ifeq ($(METADATA_GENERATOR),)
$(error 'METADATA_GENERATOR' not configured, run ./configure in the root directory)
else
$(error '$(METADATA_GENERATOR)' not supported, only asciidoctor and asciidoc are supported)
endif
ifdef VERBOSE
METADATA_GENERATOR_PARAMS += -v
endif
CLEAN_TARGETS := *.css *.js *.txt
ifeq ($(WITH_METADATA_HTML),yes)
MAKE_TARGETS += metadata.html
ifneq ($(METADATA_GENERATOR_PARAMS_HTML_CHUNKED),)
MAKE_TARGETS += metadata.chunked
endif
endif
ifeq ($(WITH_METADATA_PDF),yes)
MAKE_TARGETS += metadata.pdf
endif
INSTALL_DIR = metadata
INSTALL_TARGETS = *.css *.js
ifndef METADATA_GENERATOR
METADATA_GENERATOR := asciidoctor
endif
txt: ${abs_top_builddir}/metadata/ltp.json
$(abs_srcdir)/testinfo.pl $<
ifeq ($(WITH_METADATA_HTML),yes)
metadata.html: txt
$(METADATA_GENERATOR_CMD) $(METADATA_GENERATOR_PARAMS) $(METADATA_GENERATOR_PARAMS_HTML)
ifneq ($(METADATA_GENERATOR_PARAMS_HTML_CHUNKED),)
metadata.chunked: txt
$(METADATA_GENERATOR_CMD) $(METADATA_GENERATOR_PARAMS) $(METADATA_GENERATOR_PARAMS_HTML_CHUNKED)
endif
endif
ifeq ($(WITH_METADATA_PDF),yes)
metadata.pdf: txt
$(METADATA_GENERATOR_CMD) $(METADATA_GENERATOR_PARAMS) $(METADATA_GENERATOR_PARAMS_PDF)
endif
include $(top_srcdir)/include/mk/generic_leaf_target.mk
-522
View File
@@ -1,522 +0,0 @@
#!/usr/bin/perl
# SPDX-License-Identifier: GPL-2.0-or-later
# Copyright (c) 2019 Cyril Hrubis <chrubis@suse.cz>
# Copyright (c) 2020-2021 Petr Vorel <pvorel@suse.cz>
use strict;
use warnings;
use JSON qw(decode_json);
use Cwd qw(abs_path);
use File::Basename qw(dirname);
use constant OUTDIR => dirname(abs_path($0));
# tags which expect git tree, also need constant for URL
our @TAGS_GIT = ("linux-git", "linux-stable-git", "glibc-git", "musl-git");
# tags should map these in lib/tst_test.c
use constant LINUX_GIT_URL => "https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=";
use constant LINUX_STABLE_GIT_URL => "https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=";
use constant GLIBC_GIT_URL => "https://sourceware.org/git/?p=glibc.git;a=commit;h=";
use constant MUSL_GIT_URL => "https://git.musl-libc.org/cgit/musl/commit/src/linux/clone.c?id=";
use constant CVE_DB_URL => "https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-";
sub load_json
{
my ($fname, $mode) = @_;
local $/;
open(my $fh, '<', $fname) or die("Can't open $fname $!");
return <$fh>;
}
sub log_info
{
my $msg = shift;
print STDERR "INFO: $msg\n";
}
sub log_warn
{
my $msg = shift;
print STDERR "WARN: $msg\n";
}
sub print_asciidoc_page
{
my ($fh, $json, $title, $content) = @_;
print $fh <<EOL;
// -*- mode:doc; -*-
// vim: set syntax=asciidoc:
$title
$content
EOL
}
sub tag_url {
my ($tag, $value, $scm_url_base) = @_;
if ($tag eq "fname") {
return $scm_url_base . $value;
}
if ($tag eq "CVE") {
return CVE_DB_URL . $value;
}
# *_GIT_URL
my $key = tag2env($tag) . "_URL";
if (defined($constant::declared{"main::$key"})) {
return eval("main::$key") . $value;
}
if ('known-fail') {
return '';
}
die("unknown constant '$key' for tag $tag, define it!");
}
sub bold
{
return "*$_[0]*";
}
sub code
{
return "+$_[0]+";
}
sub hr
{
return "\n\n'''\n\n";
}
sub html_a
{
my ($url, $text) = @_;
# escape: ] |
$text =~ s/([]|])/\\$1/g;
return "$url\[$text\]";
}
sub h1
{
return "== $_[0]\n";
}
sub h2
{
return "=== $_[0]\n";
}
sub h3
{
return "==== $_[0]\n";
}
sub label
{
return "[[$_[0]]]\n";
}
sub paragraph
{
return "$_[0]\n\n";
}
sub reference
{
my ($link, %args) = @_;
$args{text} //= $link;
$args{delimiter} //= "";
return "xref:$link\[$args{text}\]$args{delimiter}\n";
}
sub table
{
return "|===\n";
}
sub table_escape
{
my $out = $_[0];
$out =~ s/\|/\\|/g;
return $out;
}
sub print_defined
{
my ($key, $val, $val2) = @_;
if (defined($val)) {
return paragraph(bold($key) . ": " . $val . (defined($val2) ? " $val2" : ""));
}
}
sub content_about
{
my $json = shift;
my $content;
$content .= print_defined("URL", $json->{'testsuite'}->{'url'});
$content .= print_defined("Version", $json->{'testsuite'}->{'version'});
$content .= print_defined("Default timeout", $json->{'defaults'}->{'timeout'}, "seconds");
return $content;
}
sub uniq {
my %seen;
grep !$seen{$_}++, @_;
}
sub get_test_names
{
my @names = @{$_[0]};
my ($letter, $prev_letter);
my $content;
for my $name (sort @names) {
$letter = substr($name, 0, 1);
if (defined($prev_letter) && $letter ne $prev_letter) {
$content .= "\n";
}
$content .= reference($name, delimiter => " ");
$prev_letter = $letter;
}
$content .= "\n";
return $content;
}
sub get_test_letters
{
my @names = @{$_[0]};
my $letter;
my $prev_letter = "";
my $content;
for (@names) {
$_ = substr($_, 0, 1);
}
@names = uniq(@names);
for my $letter (@names) {
$content .= reference($letter);
}
$content .= "\n";
return $content;
}
sub tag2title
{
my $tag = shift;
return code(".$tag");
}
sub get_filters
{
my $json = shift;
my %data;
while (my ($k, $v) = each %{$json->{'tests'}}) {
for my $j (keys %{$v}) {
next if ($j eq 'fname' || $j eq 'doc');
$data{$j} = () unless (defined($data{$j}));
if ($j eq 'tags') {
for my $tags (@{$v}{'tags'}) {
for my $tag (@$tags) {
my $k2 = $$tag[0];
my $v2 = $$tag[1];
$data{$j}{$k2} = () unless (defined($data{$j}{$k2}));
push @{$data{$j}{$k2}}, $k unless grep{$_ eq $k} @{$data{$j}{$k2}};
}
}
} else {
push @{$data{$j}}, $k unless grep{$_ eq $k} @{$data{$j}};
}
}
}
return \%data;
}
sub content_filter
{
my $k = $_[0];
my $title = $_[1];
my $desc = $_[2];
my $h = $_[3];
my ($letter, $prev_letter, $content);
$content = label($k);
$content .= $title;
$content .= paragraph("Tests containing $desc flag.");
$content .= get_test_names(\@{$h});
return $content;
}
sub content_filters
{
my $json = shift;
my $data = get_filters($json);
my %h = %$data;
my $content;
for my $k (sort keys %$data) {
my $title = tag2title($k);
if (ref($h{$k}) eq 'HASH') {
$content .= label($k);
$content .= h2($title);
for my $k2 (sort keys %{$h{$k}}) {
my $title2 = code($k2);
$content .= content_filter($k2, h3($title2), "$title $title2", $h{$k}{$k2});
}
} else {
$content .= content_filter($k, h2($title), $title, \@{$h{$k}});
}
}
return $content;
}
sub tag2env
{
my $tag = shift;
$tag =~ s/-/_/g;
return uc($tag);
}
sub detect_git
{
my %data;
for my $tag (@TAGS_GIT) {
my $env = tag2env($tag);
unless (defined $ENV{$env} && $ENV{$env}) {
log_warn("git repository $tag not defined. Define it in \$$env");
next;
}
unless (-d $ENV{$env}) {
log_warn("\$$env does not exit ('$ENV{$env}')");
next;
}
if (system("which git >/dev/null")) {
log_warn("git not in \$PATH ('$ENV{'PATH'}')");
next;
}
chdir($ENV{$env});
if (!system("git log -1 > /dev/null")) {
log_info("using '$ENV{$env}' as $env repository");
$data{$tag} = $ENV{$env};
} else {
log_warn("git failed, git not installed or \$$env is not a git repository? ('$ENV{$env}')");
}
chdir(OUTDIR);
}
return \%data;
}
sub content_all_tests
{
my $json = shift;
my @names = sort keys %{$json->{'tests'}};
my $letters = paragraph(get_test_letters(\@names));
my $git_url = detect_git();
my $tmp = undef;
my $printed = "";
my $content;
$content .= paragraph("Total $#names tests.");
$content .= $letters;
$content .= get_test_names(\@names);
for my $name (@names) {
my $letter = substr($name, 0, 1);
if ($printed ne $letter) {
$content .= label($letter);
$content .= h2($letter);
$printed = $letter;
}
$content .= hr() if (defined($tmp));
$content .= label($name);
$content .= h3($name);
$content .= $letters;
if (defined($json->{'testsuite'}->{'scm_url_base'}) &&
defined($json->{'tests'}{$name}{fname})) {
$content .= paragraph(html_a(tag_url("fname", $json->{'tests'}{$name}{fname},
$json->{'testsuite'}->{'scm_url_base'}), "source"));
}
if (defined $json->{'tests'}{$name}{doc}) {
for my $doc (@{$json->{'tests'}{$name}{doc}}) {
# fix formatting for asciidoc [DOCUMENTATION] => *Documentation*
if ($doc =~ s/^\[(.*)\]$/$1/) {
$doc = paragraph(bold(ucfirst(lc($doc))));
}
$content .= "$doc\n";
}
$content .= "\n";
}
if ($json->{'tests'}{$name}{timeout}) {
if ($json->{'tests'}{$name}{timeout} eq -1) {
$content .= paragraph("Test timeout is disabled");
} else {
$content .= paragraph("Test timeout is $json->{'tests'}{$name}{timeout} seconds");
}
} else {
$content .= paragraph("Test timeout defaults to $json->{'defaults'}->{'timeout'} seconds");
}
my $tmp2 = undef;
for my $k (sort keys %{$json->{'tests'}{$name}}) {
my $v = $json->{'tests'}{$name}{$k};
next if ($k eq "tags" || $k eq "fname" || $k eq "doc");
if (!defined($tmp2)) {
$content .= table . "|Key|Value\n\n"
}
$content .= "|" . reference($k, text => tag2title($k)) . "\n|";
if (ref($v) eq 'ARRAY') {
# two dimensional array
if (ref(@$v[0]) eq 'ARRAY') {
for my $v2 (@$v) {
$content .= paragraph(table_escape(join(' ', @$v2)));
}
} else {
# one dimensional array
$content .= table_escape(join(', ', @$v));
}
} else {
# plain content
$content .= table_escape($v);
}
$content .= "\n";
$tmp2 = 1;
}
if (defined($tmp2)) {
$content .= table . "\n";
}
$tmp2 = undef;
my %commits;
my @sorted_tags = sort { $a->[0] cmp $b->[0] } @{$json->{'tests'}{$name}{tags} // []};
for my $tag (@sorted_tags) {
if (!defined($tmp2)) {
$content .= table . "|Tag|Info\n"
}
my $k = @$tag[0];
my $v = @$tag[1];
my $url;
if (defined($$git_url{$k})) {
$commits{$k} = () unless (defined($commits{$k}));
unless (defined($commits{$k}{$v})) {
chdir($$git_url{$k});
$commits{$k}{$v} = `git log --pretty=format:'%s' -1 $v`;
chdir(OUTDIR);
}
$v .= ' ("' . $commits{$k}{$v} . '")';
}
$url = tag_url($k, @$tag[1]);
if ($url) {
$v = html_a($url, $v);
}
# tag value value can be split into more lines if too long
# i.e. URL in known-fail
for (@$tag[2 .. $#$tag]) {
$v .= " $_";
}
$content .= "\n|" . reference($k) . "\n|$v\n";
$tmp2 = 1;
}
if (defined($tmp2)) {
$content .= table . "\n";
}
$tmp = 1;
}
return $content;
}
my $json = decode_json(load_json($ARGV[0]));
my $config = [
{
file => "about.txt",
title => h2("About $json->{'testsuite'}->{'name'}"),
content => \&content_about,
},
{
file => "filters.txt",
title => h1("Test filtered by used flags"),
content => \&content_filters,
},
{
file => "all-tests.txt",
title => h1("All tests"),
content => \&content_all_tests,
},
];
sub print_asciidoc_main
{
my $config = shift;
my $file = "metadata.txt";
my $content;
open(my $fh, '>', $file) or die("Can't open $file $!");
$content = <<EOL;
:doctype: inline
:sectanchors:
:toc:
EOL
for my $c (@{$config}) {
$content .= "include::$c->{'file'}\[\]\n";
}
print_asciidoc_page($fh, $json, h1($json->{'testsuite'}->{'short_name'} . " test catalog"), $content);
}
for my $c (@{$config}) {
open(my $fh, '>', $c->{'file'}) or die("Can't open $c->{'file'} $!");
print_asciidoc_page($fh, $json, $c->{'title'}, $c->{'content'}->($json));
}
print_asciidoc_main($config);
+2 -2
View File
@@ -18,8 +18,8 @@ MAKE_TARGETS :=
distclean:: clean ac-distclean
maintainer-clean:: distclean ac-maintainer-clean
ac-clean ac-distclean::
$(RM) -f config.h
ac-maintainer-clean::
$(RM) -f config.h lapi/syscalls.h stamp-h1
ac-maintainer-clean:: ac-clean
$(RM) -f config.h.in
vpath %.h $(abs_srcdir)
+22
View File
@@ -0,0 +1,22 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Copyright (c) 2024 Cyril Hrubis <chrubis@suse.cz>
*/
#ifndef LAPI_ARCH_PRCTL_H__
#define LAPI_ARCH_PRCTL_H__
#include "config.h"
#ifdef HAVE_ASM_PRCTL_H
# include <asm/prctl.h>
#endif
#ifndef ARCH_GET_CPUID
# define ARCH_GET_CPUID 0x1011
#endif
#ifndef ARCH_SET_CPUID
# define ARCH_SET_CPUID 0x1012
#endif
#endif /* LAPI_ARCH_PRCTL_H__ */
+19
View File
@@ -0,0 +1,19 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Copyright (c) 2025 Linux Test Project
* Li Wang <liwang@redhat.com>
*/
#ifndef LAPI_BLKDEV_H__
#define LAPI_BLKDEV_H__
#ifdef HAVE_LINUX_BLKDEV_H
#include <linux/blkdev.h>
#endif
/* Define BLK_MAX_BLOCK_SIZE for older kernels */
#ifndef BLK_MAX_BLOCK_SIZE
#define BLK_MAX_BLOCK_SIZE 0x00010000 /* 64K */
#endif
#endif /* LAPI_BLKDEV_H */
+16 -12
View File
@@ -10,14 +10,10 @@
#ifdef HAVE_SYS_CAPABILITY_H
# include <sys/capability.h>
/**
* Some old libcap-devel(1.96~2.16) define _LINUX_TYPES_H in
* sys/capability.h that makes ltp-lib cann't include linux/types.h
* essentially. Here undefine it if include such old header-file.
*/
# ifndef HAVE_NEWER_LIBCAP
# undef _LINUX_TYPES_H
# endif
#endif
#ifndef CAP_NET_BIND_SERVICE
# define CAP_NET_BIND_SERVICE 10
#endif
#ifndef CAP_NET_RAW
@@ -36,18 +32,26 @@
# define CAP_SYS_ADMIN 21
#endif
#ifndef CAP_SYS_NICE
# define CAP_SYS_NICE 23
#endif
#ifndef CAP_SYS_TIME
# define CAP_SYS_TIME 25
#endif
#ifndef CAP_AUDIT_READ
# define CAP_AUDIT_READ 37
#endif
#ifndef CAP_SYS_RESOURCE
# define CAP_SYS_RESOURCE 24
#endif
#ifndef CAP_MKNOD
# define CAP_MKNOD 27
#endif
#ifndef CAP_AUDIT_READ
# define CAP_AUDIT_READ 37
#endif
#ifndef CAP_BPF
# define CAP_BPF 39
#endif
+3
View File
@@ -7,6 +7,7 @@
#ifndef LAPI_COMMON_TIMERS_H__
#define LAPI_COMMON_TIMERS_H__
#include <linux/version.h>
#include "config.h"
#include "lapi/syscalls.h"
#include "lapi/posix_clocks.h"
@@ -30,6 +31,8 @@ static const clock_t clock_list[] = {
/* MAX_CLOCKS is the maximum number of clock sources supported by kernel */
#define MAX_CLOCKS 16
#define MAX_AUX_CLOCKS 8
#define CLOCK_TO_STR(def_name) \
case def_name: \
return #def_name;
+36
View File
@@ -32,6 +32,10 @@
#define FAN_REPORT_DFID_NAME_TARGET (FAN_REPORT_DFID_NAME | \
FAN_REPORT_FID | FAN_REPORT_TARGET_FID)
#endif
#ifndef FAN_REPORT_FD_ERROR
#define FAN_REPORT_FD_ERROR 0x00002000
#endif
/* Non-uapi convenience macros */
#ifndef FAN_REPORT_DFID_NAME_FID
@@ -105,6 +109,9 @@
#ifndef FAN_FS_ERROR
#define FAN_FS_ERROR 0x00008000
#endif
#ifndef FAN_PRE_ACCESS
#define FAN_PRE_ACCESS 0x00100000
#endif
#ifndef FAN_RENAME
#define FAN_RENAME 0x10000000
#endif
@@ -117,6 +124,16 @@
#define FAN_EPIDFD -2
#endif
/* errno other than EPERM can specified in upper byte of deny response */
#ifndef FAN_DENY_ERRNO
#define FAN_ERRNO(err) (((((__u32)(err)) & 0xff) << 24))
#define FAN_DENY_ERRNO(err) (FAN_DENY | FAN_ERRNO(err))
#endif
#ifndef FAN_RESPONSE_ERRNO
#define FAN_RESPONSE_ERRNO(res) ((int)((res) >> 24))
#endif
/* Flags required for unprivileged user group */
#define FANOTIFY_REQUIRED_USER_INIT_FLAGS (FAN_REPORT_FID)
@@ -130,6 +147,8 @@
#define LTP_ALL_PERM_EVENTS (FAN_OPEN_PERM | FAN_OPEN_EXEC_PERM | \
FAN_ACCESS_PERM)
#define LTP_PRE_CONTENT_EVENTS (FAN_PRE_ACCESS)
struct fanotify_group_type {
unsigned int flag;
const char *name;
@@ -162,6 +181,9 @@ typedef struct {
#ifndef FAN_EVENT_INFO_TYPE_ERROR
#define FAN_EVENT_INFO_TYPE_ERROR 5
#endif
#ifndef FAN_EVENT_INFO_TYPE_RANGE
#define FAN_EVENT_INFO_TYPE_RANGE 6
#endif
#ifndef FAN_EVENT_INFO_TYPE_OLD_DFID_NAME
#define FAN_EVENT_INFO_TYPE_OLD_DFID_NAME 10
@@ -201,6 +223,15 @@ struct fanotify_event_info_error {
};
#endif /* HAVE_STRUCT_FANOTIFY_EVENT_INFO_ERROR */
#ifndef HAVE_STRUCT_FANOTIFY_EVENT_INFO_RANGE
struct fanotify_event_info_range {
struct fanotify_event_info_header hdr;
__u32 pad;
__u64 offset;
__u64 count;
};
#endif /* HAVE_STRUCT_FANOTIFY_EVENT_INFO_RANGE */
/* NOTE: only for struct fanotify_event_info_fid */
#ifdef HAVE_STRUCT_FANOTIFY_EVENT_INFO_FID_FSID___VAL
# define FSID_VAL_MEMBER(fsid, i) (fsid.__val[i])
@@ -208,4 +239,9 @@ struct fanotify_event_info_error {
# define FSID_VAL_MEMBER(fsid, i) (fsid.val[i])
#endif /* HAVE_STRUCT_FANOTIFY_EVENT_INFO_FID_FSID___VAL */
/* linux/exportfs.h */
#ifndef FILEID_INVALID
# define FILEID_INVALID 0xff
#endif
#endif /* LAPI_FANOTIFY_H__ */
+12
View File
@@ -94,6 +94,10 @@
# define AT_REMOVEDIR 0x200
#endif
#ifndef AT_HANDLE_FID
# define AT_HANDLE_FID AT_REMOVEDIR
#endif
#ifndef AT_SYMLINK_FOLLOW
# define AT_SYMLINK_FOLLOW 0x400
#endif
@@ -150,6 +154,14 @@
# define RENAME_WHITEOUT (1 << 2)
#endif
#ifndef F_LINUX_SPECIFIC_BASE
#define F_LINUX_SPECIFIC_BASE 1024
#endif
#ifndef F_CREATED_QUERY
#define F_CREATED_QUERY (F_LINUX_SPECIFIC_BASE + 4)
#endif
/* splice, vmsplice, tee */
#ifndef SPLICE_F_NONBLOCK
+31
View File
@@ -0,0 +1,31 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Copyright (C) 2024 Andrea Cervesato <andrea.cervesato@suse.com>
* Copyright (C) 2024 Cyril Hrubis <chrubis@suse.cz>
*/
#ifndef LAPI_FICLONE_H__
#define LAPI_FICLONE_H__
#include "config.h"
#include <linux/fs.h>
#include <stdint.h>
#ifndef HAVE_STRUCT_FILE_CLONE_RANGE
struct file_clone_range {
int64_t src_fd;
uint64_t src_offset;
uint64_t src_length;
uint64_t dest_offset;
};
#endif
#ifndef FICLONE
# define FICLONE _IOW(0x94, 9, int)
#endif
#ifndef FICLONERANGE
# define FICLONERANGE _IOW(0x94, 13, struct file_clone_range)
#endif
#endif /* LAPI_FICLONE_H__ */
+73 -7
View File
@@ -10,15 +10,28 @@
#define LAPI_FS_H__
#include "config.h"
#ifndef HAVE_MOUNT_SETATTR
# ifdef HAVE_LINUX_FS_H
# include <linux/fs.h>
# endif
#ifndef HAVE_LINUX_FS
# include <linux/fs.h>
#endif
#include <stddef.h>
#include <stdint.h>
#include <sys/user.h>
#include <limits.h>
#include "tst_test.h"
#include "lapi/abisize.h"
#include "lapi/syscalls.h"
#ifndef HAVE_STRUCT_FSXATTR
struct fsxattr {
uint32_t fsx_xflags; /* xflags field value (get/set) */
uint32_t fsx_extsize; /* extsize field value (get/set)*/
uint32_t fsx_nextents; /* nextents field value (get) */
uint32_t fsx_projid; /* project identifier (get/set) */
uint32_t fsx_cowextsize; /* CoW extsize field value (get/set)*/
unsigned char fsx_pad[8];
};
#endif
#ifndef FS_IOC_GETFLAGS
# define FS_IOC_GETFLAGS _IOR('f', 1, long)
@@ -28,6 +41,14 @@
# define FS_IOC_SETFLAGS _IOW('f', 2, long)
#endif
#ifndef FS_IOC_FSGETXATTR
# define FS_IOC_FSGETXATTR _IOR('X', 31, struct fsxattr)
#endif
#ifndef FS_IOC_FSSETXATTR
# define FS_IOC_FSSETXATTR _IOW('X', 32, struct fsxattr)
#endif
#ifndef FS_COMPR_FL
# define FS_COMPR_FL 0x00000004 /* Compress file */
#endif
@@ -48,6 +69,18 @@
# define FS_VERITY_FL 0x00100000 /* Verity protected inode */
#endif
#ifndef FS_XFLAG_APPEND
# define FS_XFLAG_APPEND 0x00000010 /* all writes append */
#endif
#ifndef FS_XFLAG_EXTSIZE
# define FS_XFLAG_EXTSIZE 0x00000800 /* extent size allocator hint */
#endif
#ifndef FS_XFLAG_COWEXTSIZE
# define FS_XFLAG_COWEXTSIZE 0x00010000 /* CoW extent size allocator hint */
#endif
/*
* Helper function to get MAX_LFS_FILESIZE.
* Missing PAGE_SHIFT on some libc prevents defining MAX_LFS_FILESIZE.
@@ -55,13 +88,13 @@
* 64 bit: macro taken from kernel from include/linux/fs.h
* 32 bit: own implementation
*/
static inline loff_t tst_max_lfs_filesize(void)
static inline long long tst_max_lfs_filesize(void)
{
#ifdef TST_ABI64
return (loff_t)LLONG_MAX;
return LLONG_MAX;
#else
long page_size = getpagesize();
loff_t ret = ULONG_MAX;
long long ret = ULONG_MAX;
while (page_size >>= 1)
ret <<= 1;
@@ -70,4 +103,37 @@ static inline loff_t tst_max_lfs_filesize(void)
#endif
}
#ifndef HAVE_STRUCT_FILE_ATTR
struct file_attr {
uint64_t fa_xflags; /* xflags field value (get/set) */
uint32_t fa_extsize; /* extsize field value (get/set)*/
uint32_t fa_nextents; /* nextents field value (get) */
uint32_t fa_projid; /* project identifier (get/set) */
uint32_t fa_cowextsize; /* CoW extsize field value (get/set) */
};
#endif
#define FILE_ATTR_SIZE_VER0 24
#define FILE_ATTR_SIZE_LATEST FILE_ATTR_SIZE_VER0
#ifndef HAVE_FILE_GETATTR
static inline int file_getattr(int dfd, const char *filename,
struct file_attr *ufattr, size_t usize,
unsigned int at_flags)
{
return tst_syscall(__NR_file_getattr, dfd, filename, ufattr, usize,
at_flags);
}
#endif
#ifndef HAVE_FILE_SETATTR
static inline int file_setattr(int dfd, const char *filename,
struct file_attr *ufattr, size_t usize,
unsigned int at_flags)
{
return tst_syscall(__NR_file_setattr, dfd, filename, ufattr, usize,
at_flags);
}
#endif
#endif /* LAPI_FS_H__ */
+9 -6
View File
@@ -11,12 +11,11 @@
#include "config.h"
#include <sys/syscall.h>
#include <sys/types.h>
#include <sys/mount.h>
#ifndef HAVE_FSOPEN
# ifdef HAVE_LINUX_MOUNT_H
# include <linux/mount.h>
# endif
#if !defined(HAVE_FSOPEN) && defined(HAVE_LINUX_MOUNT_H)
# include <linux/mount.h>
#else
# include <sys/mount.h>
#endif
#include "lapi/fcntl.h"
@@ -119,6 +118,10 @@ static inline int mount_setattr(int dirfd, const char *from_pathname, unsigned i
* New headers added in kernel after 5.2 release, create them for old userspace.
*/
#ifndef MOVE_MOUNT_BENEATH
# define MOVE_MOUNT_BENEATH 0x00000200
#endif
#ifndef OPEN_TREE_CLONE
/*
@@ -136,7 +139,7 @@ static inline int mount_setattr(int dirfd, const char *from_pathname, unsigned i
#define MOVE_MOUNT_T_SYMLINKS 0x00000010 /* Follow symlinks on to path */
#define MOVE_MOUNT_T_AUTOMOUNTS 0x00000020 /* Follow automounts on to path */
#define MOVE_MOUNT_T_EMPTY_PATH 0x00000040 /* Empty to path permitted */
#define MOVE_MOUNT__MASK 0x00000077
#define MOVE_MOUNT__MASK 0x00000377
/*
* fsopen() flags.
+13 -2
View File
@@ -8,10 +8,14 @@
#include "config.h"
#if HAVE_LINUX_RANDOM_H
#include <linux/random.h>
#ifdef HAVE_SYS_RANDOM_H
# include <sys/random.h>
#else
# include <linux/random.h>
#endif
#include "lapi/syscalls.h"
/*
* Flags for getrandom(2)
*
@@ -27,4 +31,11 @@
# define GRND_RANDOM 0x0002
#endif
#ifndef HAVE_SYS_RANDOM_H
static inline int getrandom(void *buf, size_t buflen, unsigned int flags)
{
return tst_syscall(SYS_getrandom, buf, buflen, flags);
}
#endif
#endif /* LAPI_GETRANDOM_H__ */
+1 -2
View File
@@ -11,10 +11,9 @@
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/uio.h>
#include <stdlib.h>
#include <linux/fs.h>
#include <linux/types.h>
#include "lapi/syscalls.h"
+133
View File
@@ -9,6 +9,7 @@
#include "config.h"
#include <sys/ioctl.h>
#include <stdint.h>
/* musl not including it in <sys/ioctl.h> */
#include <sys/ttydefaults.h>
@@ -37,4 +38,136 @@ struct termio
};
#endif /* HAVE_STRUCT_TERMIO */
#ifndef HAVE_STRUCT_PROCMAP_QUERY
#define PROCFS_IOCTL_MAGIC 'f'
#define PROCMAP_QUERY _IOWR(PROCFS_IOCTL_MAGIC, 17, struct procmap_query)
enum procmap_query_flags {
/*
* VMA permission flags.
*
* Can be used as part of procmap_query.query_flags field to look up
* only VMAs satisfying specified subset of permissions. E.g., specifying
* PROCMAP_QUERY_VMA_READABLE only will return both readable and read/write VMAs,
* while having PROCMAP_QUERY_VMA_READABLE | PROCMAP_QUERY_VMA_WRITABLE will only
* return read/write VMAs, though both executable/non-executable and
* private/shared will be ignored.
*
* PROCMAP_QUERY_VMA_* flags are also returned in procmap_query.vma_flags
* field to specify actual VMA permissions.
*/
PROCMAP_QUERY_VMA_READABLE = 0x01,
PROCMAP_QUERY_VMA_WRITABLE = 0x02,
PROCMAP_QUERY_VMA_EXECUTABLE = 0x04,
PROCMAP_QUERY_VMA_SHARED = 0x08,
/*
* Query modifier flags.
*
* By default VMA that covers provided address is returned, or -ENOENT
* is returned. With PROCMAP_QUERY_COVERING_OR_NEXT_VMA flag set, closest
* VMA with vma_start > addr will be returned if no covering VMA is
* found.
*
* PROCMAP_QUERY_FILE_BACKED_VMA instructs query to consider only VMAs that
* have file backing. Can be combined with PROCMAP_QUERY_COVERING_OR_NEXT_VMA
* to iterate all VMAs with file backing.
*/
PROCMAP_QUERY_COVERING_OR_NEXT_VMA = 0x10,
PROCMAP_QUERY_FILE_BACKED_VMA = 0x20,
};
struct procmap_query {
/* Query struct size, for backwards/forward compatibility */
uint64_t size;
/*
* Query flags, a combination of enum procmap_query_flags values.
* Defines query filtering and behavior, see enum procmap_query_flags.
*
* Input argument, provided by user. Kernel doesn't modify it.
*/
uint64_t query_flags; /* in */
/*
* Query address. By default, VMA that covers this address will
* be looked up. PROCMAP_QUERY_* flags above modify this default
* behavior further.
*
* Input argument, provided by user. Kernel doesn't modify it.
*/
uint64_t query_addr; /* in */
/* VMA starting (inclusive) and ending (exclusive) address, if VMA is found. */
uint64_t vma_start; /* out */
uint64_t vma_end; /* out */
/* VMA permissions flags. A combination of PROCMAP_QUERY_VMA_* flags. */
uint64_t vma_flags; /* out */
/* VMA backing page size granularity. */
uint64_t vma_page_size; /* out */
/*
* VMA file offset. If VMA has file backing, this specifies offset
* within the file that VMA's start address corresponds to.
* Is set to zero if VMA has no backing file.
*/
uint64_t vma_offset; /* out */
/* Backing file's inode number, or zero, if VMA has no backing file. */
uint64_t inode; /* out */
/* Backing file's device major/minor number, or zero, if VMA has no backing file. */
uint32_t dev_major; /* out */
uint32_t dev_minor; /* out */
/*
* If set to non-zero value, signals the request to return VMA name
* (i.e., VMA's backing file's absolute path, with " (deleted)" suffix
* appended, if file was unlinked from FS) for matched VMA. VMA name
* can also be some special name (e.g., "[heap]", "[stack]") or could
* be even user-supplied with prctl(PR_SET_VMA, PR_SET_VMA_ANON_NAME).
*
* Kernel will set this field to zero, if VMA has no associated name.
* Otherwise kernel will return actual amount of bytes filled in
* user-supplied buffer (see vma_name_addr field below), including the
* terminating zero.
*
* If VMA name is longer that user-supplied maximum buffer size,
* -E2BIG error is returned.
*
* If this field is set to non-zero value, vma_name_addr should point
* to valid user space memory buffer of at least vma_name_size bytes.
* If set to zero, vma_name_addr should be set to zero as well
*/
uint32_t vma_name_size; /* in/out */
/*
* If set to non-zero value, signals the request to extract and return
* VMA's backing file's build ID, if the backing file is an ELF file
* and it contains embedded build ID.
*
* Kernel will set this field to zero, if VMA has no backing file,
* backing file is not an ELF file, or ELF file has no build ID
* embedded.
*
* Build ID is a binary value (not a string). Kernel will set
* build_id_size field to exact number of bytes used for build ID.
* If build ID is requested and present, but needs more bytes than
* user-supplied maximum buffer size (see build_id_addr field below),
* -E2BIG error will be returned.
*
* If this field is set to non-zero value, build_id_addr should point
* to valid user space memory buffer of at least build_id_size bytes.
* If set to zero, build_id_addr should be set to zero as well
*/
uint32_t build_id_size; /* in/out */
/*
* User-supplied address of a buffer of at least vma_name_size bytes
* for kernel to fill with matched VMA's name (see vma_name_size field
* description above for details).
*
* Should be set to zero if VMA name should not be returned.
*/
uint64_t vma_name_addr; /* in */
/*
* User-supplied address of a buffer of at least build_id_size bytes
* for kernel to fill with matched VMA's ELF build ID, if available
* (see build_id_size field description above for details).
*
* Should be set to zero if build ID should not be returned.
*/
uint64_t build_id_addr; /* in */
};
#endif /* HAVE_STRUCT_PROCMAP_QUERY */
#endif /* LAPI_IOCTL_H__ */
+4 -1
View File
@@ -6,6 +6,7 @@
#ifndef LAPI_IOCTL_NS_H__
#define LAPI_IOCTL_NS_H__
#include <stdint.h>
#include <asm-generic/ioctl.h>
#ifndef NSIO
@@ -23,6 +24,8 @@
#ifndef NS_GET_NSTYPE
#define NS_GET_NSTYPE _IO(NSIO, 0x3)
#endif
#ifndef NS_GET_MNTNS_ID
#define NS_GET_MNTNS_ID _IOR(NSIO, 0x5, uint64_t)
#endif
#endif /* LAPI_IOCTL_NS_H__ */

Some files were not shown because too many files have changed in this diff Show More