ltp代码升级

Signed-off-by: gaoxue <gaoxue15@huawei.com>
This commit is contained in:
gaoxue
2024-02-05 10:59:52 +08:00
parent 81381d7816
commit 04dd74dfe9
1716 changed files with 49345 additions and 34600 deletions
+2 -24
View File
@@ -11,6 +11,8 @@ core
lib*.a
.cache.mk
*.dwo
*.mod
built-in.a
/aclocal.m4
autom4te.cache
@@ -31,19 +33,14 @@ autom4te.cache
/m4/Makefile
/m4/Makefile.in
/execltp
/ltp-devel.spec
/README.ltp-devel
/tags
/Version
/include/mk/config.mk
/include/mk/config-openposix.mk
/include/mk/features.mk
/m4/ltp-version.m4
/lib/ltp.pc
/pan/ltp-bump
/pan/ltp-pan
/pan/ltp-scanner
cscope.*
ncscope.*
@@ -61,24 +58,5 @@ patches/
*.run-test
*.test
logfile.*
*.logfile
logfile
/utils/benchmark/ebizzy-0.3/ebizzy
/lib/tests/tst_tmpdir_test
/lib/tests/tst_checkpoint
/lib/tests/tst_checkpoint_wait_timeout
/lib/tests/tst_checkpoint_wake_timeout
/lib/tests/tst_process_state
/lib/tests/tst_cleanup_once
/lib/tests/tst_safe_macros
/lib/tests/tst_strsig
/lib/tests/tst_strerrno
/lib/tests/tst_fs_fill_subdirs
/lib/tests/tst_fs_fill_hardlinks
/lib/tests/tst_device
/lib/tests/tst_record_childstatus
/lib/tests/trerrno
/lib/tests/tst_dataroot01
/lib/tests/tst_dataroot02
/lib/tests/tst_dataroot03
+9
View File
@@ -1,3 +1,12 @@
[submodule "testcases/kernel/mce-test"]
path = testcases/kernel/mce-test
url = git://git.kernel.org/pub/scm/linux/kernel/git/gong.chen/mce-test.git
[submodule "tools/sparse/sparse-src"]
path = tools/sparse/sparse-src
url = git://git.kernel.org/pub/scm/devel/sparse/sparse.git
[submodule "tools/kirk"]
path = tools/kirk
url = https://github.com/linux-test-project/kirk.git
[submodule "tools/ltx/ltx-src"]
path = tools/ltx/ltx-src
url = https://github.com/linux-test-project/ltx.git
+2
View File
@@ -0,0 +1,2 @@
Petr Vorel <pvorel@suse.cz> <petr.vorel@gmail.com>
Petr Vorel <pvorel@suse.cz> <pevik@users.noreply.github.com>
+9 -2
View File
@@ -26,9 +26,11 @@ echo "Checking for required user/group ids"
echo ""
# Check ids and create if needed.
NO_ROOT_ID=1
NO_NOBODY_ID=1
NO_BIN_ID=1
NO_DAEMON_ID=1
NO_ROOT_GRP=1
NO_NOBODY_GRP=1
NO_BIN_GRP=1
NO_DAEMON_GRP=1
@@ -49,7 +51,7 @@ fe() {
prompt_for_create() {
if [ -z "$CREATE_ENTRIES" ] ; then
if [ $NO_NOBODY_ID -ne 0 -o $NO_BIN_ID -ne 0 -o $NO_DAEMON_ID -ne 0 -o $NO_NOBODY_GRP -ne 0 -o $NO_BIN_GRP -ne 0 -o $NO_DAEMON_GRP -ne 0 -o $NO_USERS_GRP -ne 0 -o $NO_SYS_GRP -ne 0 ] ; then
if [ $NO_ROOT_ID -ne 0 -o $NO_NOBODY_ID -ne 0 -o $NO_BIN_ID -ne 0 -o $NO_DAEMON_ID -ne 0 -o $NO_ROOT_GRP -ne 0 -o $NO_NOBODY_GRP -ne 0 -o $NO_BIN_GRP -ne 0 -o $NO_DAEMON_GRP -ne 0 -o $NO_USERS_GRP -ne 0 -o $NO_SYS_GRP -ne 0 ] ; then
echo -n "If any required user ids and/or groups are missing, would you like these created? [y/N]"
read ans
case "$ans" in
@@ -74,10 +76,12 @@ for i in "$passwd" "$group"; do
fi
done
fe root "$passwd"; NO_ROOT_ID=$?
fe bin "$passwd"; NO_BIN_ID=$?
fe daemon "$passwd"; NO_DAEMON_ID=$?
fe nobody "$passwd"; NO_NOBODY_ID=$?
fe root "$group"; NO_ROOT_GRP=$?
fe bin "$group"; NO_BIN_GRP=$?
fe daemon "$group"; NO_DAEMON_GRP=$?
fe nobody "$group" || fe nogroup "$group"; NO_NOBODY_GRP=$?
@@ -91,9 +95,11 @@ debug_vals() {
echo "Missing the following group / user entries:"
echo "Group file: $group"
echo "Password file: $passwd"
echo "root $NO_ROOT_ID"
echo "nobody: $NO_NOBODY_ID"
echo "bin: $NO_BIN_ID"
echo "daemon: $NO_DAEMON_ID"
echo "root grp: $NO_ROOT_GRP"
echo "nobody[/nogroup] grp: $NO_NOBODY_GRP"
echo "bin grp: $NO_BIN_GRP"
echo "daemon grp: $NO_DAEMON_GRP"
@@ -130,6 +136,7 @@ make_user_group() {
fi
fi
}
make_user_group root 0 $NO_ROOT_ID $NO_ROOT_GRP
make_user_group nobody 65534 $NO_NOBODY_ID $NO_NOBODY_GRP
make_user_group bin 1 $NO_BIN_ID $NO_BIN_GRP
make_user_group daemon 2 $NO_DAEMON_ID $NO_DAEMON_GRP
@@ -149,7 +156,7 @@ fi
MISSING_ENTRY=0
# For entries that exist in both $group and $passwd.
for i in bin daemon; do
for i in root bin daemon; do
for file in "$group" "$passwd"; do
if ! fe "$i" "$file"; then
MISSING_ENTRY=1
-2
View File
@@ -27,8 +27,6 @@ configure file).
pkgconf is recommended also for compilation from tarball as it
does automatic detection of some library support.
GNU Bison / Berkeley Yacc is required for ltp-scanner.
Configuration
-------------
+9 -22
View File
@@ -1,25 +1,13 @@
#
# Top-level Makefile for LTP. See INSTALL for more info.
#
# Copyright (c) Linux Test Project, 2009-2020
# Copyright (c) Cisco Systems Inc., 2009-2010
#
# 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.
#
# SPDX-License-Identifier: GPL-2.0-or-later
# Copyright (c) Linux Test Project, 2009-2022
# Copyright (c) Cisco Systems Inc., 2009-2010
# Ngie Cooper, July 2009
#
# Avoid funny character set dependencies
unexport LC_ALL
LC_COLLATE=C
LC_NUMERIC=C
export LC_COLLATE LC_NUMERIC
top_srcdir ?= $(CURDIR)
@@ -158,7 +146,6 @@ clean:: $(CLEAN_TARGETS)
$(foreach tgt,$(MAKE_TARGETS) include-all lib-all $(filter-out clean_install_dir,$(CLEAN_TARGETS)) $(INSTALL_TARGETS) include-install lib-install,$(eval $(call target_to_dir_dep_mapping,$(tgt))))
BINDIR_INSTALL_SCRIPTS := execltp
SRCDIR_INSTALL_SCRIPTS := IDcheck.sh runltp ver_linux
SRCDIR_INSTALL_READONLY := Version
SRCDIR_INSTALL_TARGETS := $(SRCDIR_INSTALL_SCRIPTS) $(SRCDIR_INSTALL_READONLY)
+1 -1
View File
@@ -3,7 +3,7 @@
"Name" : "ltp",
"License" : "GPL V2.0",
"License File" : "COPYING",
"Version Number" : "20220121",
"Version Number" : "20230929",
"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."
+9 -5
View File
@@ -16,9 +16,14 @@ 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:
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
@@ -96,8 +101,7 @@ $ make install
```
This will install LTP to `/opt/ltp`.
* If you have a problem see `doc/mini-howto-building-ltp-from-git.txt`.
* If you still have a problem see `INSTALL` and `./configure --help`.
* 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
@@ -150,7 +154,7 @@ $ testcases/bin/abort01
Some have arguments
```
$ testcases/bin/fork13 -i 37
$ testcases/bin/mesgq\_nstest -m none
```
The vast majority of test cases accept the -h (help) switch
@@ -206,4 +210,4 @@ Although we accept GitHub pull requests, the preferred way is sending patches to
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 to push your changes to your own LTP fork on GitHub.
For testing you need to just push your changes to your own LTP fork on GitHub.
+1 -1
View File
@@ -1 +1 @@
20220121
20230929
+1 -3
View File
@@ -1,5 +1,5 @@
#!/bin/sh
# Copyright (c) 2019-2021 Petr Vorel <petr.vorel@gmail.com>
# Copyright (c) 2019-2022 Petr Vorel <petr.vorel@gmail.com>
set -ex
apk update
@@ -33,9 +33,7 @@ cat /etc/os-release
echo "WARNING: remove unsupported tests (until they're fixed)"
cd $(dirname $0)/..
rm -rfv \
testcases/kernel/syscalls/confstr/confstr01.c \
testcases/kernel/syscalls/fmtmsg/fmtmsg01.c \
testcases/kernel/syscalls/getcontext/getcontext01.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 -3
View File
@@ -1,5 +1,5 @@
#!/bin/sh
# Copyright (c) 2018-2020 Petr Vorel <pvorel@suse.cz>
# Copyright (c) 2018-2023 Petr Vorel <pvorel@suse.cz>
set -ex
apt="apt remove -y"
@@ -11,9 +11,7 @@ $apt \
libaio-dev \
libaio1 \
libcap-dev \
libcap2 \
libkeyutils-dev \
libmm-dev \
libnuma-dev \
libnuma1 \
libselinux1-dev \
-1
View File
@@ -37,7 +37,6 @@ $apt \
libjson-perl \
libkeyutils-dev \
libkeyutils1 \
libmm-dev \
libmnl-dev \
libnuma-dev \
libnuma1 \
+1 -1
View File
@@ -2,7 +2,7 @@
# Copyright (c) 2018-2021 Petr Vorel <pvorel@suse.cz>
set -ex
yum="yum -y install"
yum="yum -y install --skip-broken"
$yum \
asciidoc \
+69 -23
View File
@@ -1,4 +1,4 @@
AC_PREREQ(2.61)
AC_PREREQ(2.64)
AC_INIT([ltp], [LTP_VERSION], [ltp@lists.linux.it])
AC_CONFIG_AUX_DIR([.])
AM_INIT_AUTOMAKE
@@ -10,7 +10,6 @@ AC_CONFIG_FILES([ \
include/mk/features.mk \
lib/ltp.pc \
m4/Makefile \
execltp \
])
AC_ARG_VAR(HOSTCC, [The C compiler on the host])
@@ -24,7 +23,6 @@ AC_PROG_CC
# 2.62.
AC_DEFUN([AC_PROG_AR], [AC_CHECK_TOOL(AR, ar, :)])
AC_PROG_AR
AC_PROG_LEX
AC_PROG_RANLIB
AC_DEFUN([AC_PROG_STRIP], [AC_CHECK_TOOL(STRIP, strip, :)])
AC_PROG_STRIP
@@ -42,6 +40,7 @@ AC_CHECK_DECLS([SEM_STAT_ANY],,,[#include <sys/sem.h>])
AC_CHECK_HEADERS_ONCE([ \
asm/ldt.h \
cpuid.h \
emmintrin.h \
ifaddrs.h \
keyutils.h \
@@ -51,14 +50,17 @@ AC_CHECK_HEADERS_ONCE([ \
linux/close_range.h \
linux/dccp.h \
linux/fs.h \
linux/futex.h \
linux/genetlink.h \
linux/if_alg.h \
linux/if_ether.h \
linux/if_packet.h \
linux/io_uring.h \
linux/ioprio.h \
linux/keyctl.h \
linux/mempolicy.h \
linux/module.h \
linux/mount.h \
linux/netlink.h \
linux/seccomp.h \
linux/securebits.h \
@@ -70,6 +72,7 @@ AC_CHECK_HEADERS_ONCE([ \
sys/epoll.h \
sys/fanotify.h \
sys/inotify.h \
sys/pidfd.h
sys/prctl.h \
sys/shm.h \
sys/timerfd.h \
@@ -89,6 +92,7 @@ AC_CHECK_FUNCS_ONCE([ \
epoll_pwait \
epoll_pwait2 \
execveat \
faccessat2 \
fallocate \
fchownat \
fsconfig \
@@ -97,6 +101,8 @@ AC_CHECK_FUNCS_ONCE([ \
fspick \
fstatat \
getauxval \
getcontext \
getcpu \
getdents \
getdents64 \
io_pgetevents \
@@ -110,11 +116,13 @@ AC_CHECK_FUNCS_ONCE([ \
mkdirat \
mknodat \
modify_ldt \
mount_setattr \
move_mount \
name_to_handle_at \
open_tree \
openat \
openat2 \
pidfd_getfd \
pidfd_open \
pidfd_send_signal \
pkey_mprotect \
@@ -152,7 +160,7 @@ AC_CHECK_FUNCS(mkdtemp,[],AC_MSG_ERROR(mkdtemp() not found!))
AC_CHECK_MEMBERS([struct fanotify_event_info_fid.fsid.__val],,,[#include <sys/fanotify.h>])
AC_CHECK_MEMBERS([struct perf_event_mmap_page.aux_head],,,[#include <linux/perf_event.h>])
AC_CHECK_MEMBERS([struct sigaction.sa_sigaction],[],[],[#include <signal.h>])
AC_CHECK_MEMBERS([struct statx.stx_mnt_id],,,[
AC_CHECK_MEMBERS([struct statx.stx_mnt_id, struct statx.stx_dio_mem_align],,,[
#define _GNU_SOURCE
#include <sys/stat.h>
])
@@ -216,11 +224,20 @@ 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>])
AC_CHECK_TYPES([struct futex_waitv],,,[#include <linux/futex.h>])
AC_CHECK_TYPES([struct mount_attr],,,[
#ifdef HAVE_MOUNT_SETATTR
# include <sys/mount.h>
#elif HAVE_LINUX_MOUNT_H
# include <linux/mount.h>
#endif
])
# Tools knobs
# Bash
AC_ARG_WITH([bash],
[AC_HELP_STRING([--with-bash],
[AS_HELP_STRING([--with-bash],
[have the Bourne Again Shell interpreter])],
[with_bash=$withval],
[with_bash=no]
@@ -233,24 +250,24 @@ fi
# metadata
AC_ARG_ENABLE([metadata],
[AC_HELP_STRING([--disable-metadata],
[AS_HELP_STRING([--disable-metadata],
[Disable metadata generation (both HTML and PDF, default no)])],
[], [enable_metadata=yes]
)
AC_ARG_ENABLE([metadata_html],
[AC_HELP_STRING([--disable-metadata-html],
[AS_HELP_STRING([--disable-metadata-html],
[Disable metadata HTML generation (default no)])],
[], [enable_metadata_html=yes]
)
AC_ARG_ENABLE([metadata_pdf],
[AC_HELP_STRING([--enable-metadata-pdf],
[AS_HELP_STRING([--enable-metadata-pdf],
[Enable metadata PDF generation (default no)])],
[], [enable_metadata_pdf=no]
)
AC_ARG_WITH([metadata_generator],
[AC_HELP_STRING([--with-metadata-generator=asciidoc|asciidoctor],
[AS_HELP_STRING([--with-metadata-generator=asciidoc|asciidoctor],
[Specify metadata generator to use (default autodetect)])],
[with_metadata_generator=$withval],
[with_metadata_generator=detect]
@@ -260,7 +277,7 @@ LTP_DOCPARSE
# Expect
AC_ARG_WITH([expect],
[AC_HELP_STRING([--with-expect],
[AS_HELP_STRING([--with-expect],
[have the Tcl/expect library])],
[with_expect=$withval],
[with_expect=no]
@@ -273,7 +290,7 @@ fi
# Numa
AC_ARG_WITH([numa],
AC_HELP_STRING([--without-numa],
AS_HELP_STRING([--without-numa],
[without numa support]),
[with_numa=$withval],
[with_numa=yes]
@@ -281,7 +298,7 @@ AC_ARG_WITH([numa],
# Perl
AC_ARG_WITH([perl],
[AC_HELP_STRING([--with-perl],
[AS_HELP_STRING([--with-perl],
[have a perl interpreter])],
[with_perl=$withval],
[with_perl=no]
@@ -294,7 +311,7 @@ fi
# Python
AC_ARG_WITH([python],
[AC_HELP_STRING([--with-python],
[AS_HELP_STRING([--with-python],
[have a python interpreter])],
[with_python=$withval],
[with_python=no]
@@ -307,7 +324,7 @@ fi
# TI RPC
AC_ARG_WITH([tirpc],
AC_HELP_STRING([--without-tirpc],
AS_HELP_STRING([--without-tirpc],
[without libtirpc support]),
[with_tirpc=$withval],
[with_tirpc=yes]
@@ -317,20 +334,31 @@ AC_ARG_WITH([tirpc],
# Testsuites knobs
AC_ARG_WITH([open-posix-testsuite],
[AC_HELP_STRING([--with-open-posix-testsuite],
[AS_HELP_STRING([--with-open-posix-testsuite],
[compile and install the open posix testsuite])],
[with_open_posix_testsuite=$withval],
[with_open_posix_testsuite=no]
)
# Allow setting the directoy, where the open posix testsuite is installed to.
# If nothing is defined, we have to pass our default value to submake
AC_ARG_WITH([open-posix-testdir],
[AS_HELP_STRING([--with-open-posix-testdir=<dir>],
[set the directory, where the open posix testsuite will be installed under prefix])],
[],
[ac_configure_args="$ac_configure_args --with-open-posix-testdir=testcases/open_posix_testsuite"]
)
if test "x$with_open_posix_testsuite" = xyes; then
AC_SUBST([WITH_OPEN_POSIX_TESTSUITE],["yes"])
AC_CONFIG_SUBDIRS([testcases/open_posix_testsuite])
else
AC_SUBST([WITH_OPEN_POSIX_TESTSUITE],["no"])
fi
# TODO: testcases/realtime requires bash and python.
AC_ARG_WITH([realtime-testsuite],
[AC_HELP_STRING([--with-realtime-testsuite],
[AS_HELP_STRING([--with-realtime-testsuite],
[compile and install the realtime testsuite])],
[with_realtime_testsuite=$withval],
[with_realtime_testsuite=no]
@@ -353,7 +381,6 @@ LTP_CHECK_ATOMIC_MEMORY_MODEL
LTP_CHECK_BUILTIN_CLEAR_CACHE
LTP_CHECK_CAPABILITY_SUPPORT
LTP_CHECK_CC_WARN_OLDSTYLE
LTP_CHECK_CLONE_SUPPORTS_7_ARGS
LTP_CHECK_CRYPTO
LTP_CHECK_FORTIFY_SOURCE
LTP_CHECK_KERNEL_DEVEL
@@ -361,12 +388,15 @@ LTP_CHECK_KEYUTILS_SUPPORT
LTP_CHECK_LIBMNL
LTP_CHECK_LINUX_PTRACE
LTP_CHECK_LINUXRANDOM
LTP_CHECK_MREMAP_FIXED
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])
AC_SUBST([LTP_CFLAGS_NOPIE])
if test "x$with_numa" = xyes; then
LTP_CHECK_SYSCALL_NUMA
@@ -377,13 +407,29 @@ fi
AC_DEFINE_UNQUOTED(NUMA_ERROR_MSG, ["$numa_error_msg"], [Error message when no NUMA support])
LTP_CHECK_SYSCALL_PERF_EVENT_OPEN
LTP_CHECK_SYSCALL_SIGNALFD
LTP_CHECK_SYSCALL_UTIMENSAT
LTP_CHECK_TASKSTATS
test "x$with_tirpc" = xyes && LTP_CHECK_TIRPC
LTP_DETECT_HOST_CPU
AC_MSG_CHECKING([whether linker can handle KVM payloads])
ltp_backup_ldflags="$LDFLAGS"
ltp_backup_flags="$[]_AC_LANG_PREFIX[]FLAGS"
LDFLAGS="-T ${srcdir}/testcases/kernel/kvm/linker/${HOST_CPU}.lds"
_AC_LANG_PREFIX[]FLAGS=
AC_LINK_IFELSE([AC_LANG_PROGRAM()],
[
AC_MSG_RESULT([yes])
AC_SUBST([WITH_KVM_TESTSUITE],["yes"])
],
[
AC_MSG_RESULT([no])
AC_SUBST([WITH_KVM_TESTSUITE],["no"])
])
_AC_LANG_PREFIX[]FLAGS="$ltp_backup_flags"
LDFLAGS="$ltp_backup_ldflags"
AC_OUTPUT
cat << EOF
@@ -393,13 +439,13 @@ open posix testsuite: ${with_open_posix_testsuite:-no}
realtime testsuite: ${with_realtime_testsuite:-no}
LIBRARIES
keyutils: ${have_keyutils:-no}
keyutils: ${have_keyutils:-yes}
libacl: ${have_libacl:-no}
libaio: ${have_libaio:-no} (aio: ${have_aio:-no})
libcap: $cap_libs (newer: ${has_newer_libcap:-no})
libcrypto: $have_libcrypto (sha: ${have_sha:-no})
libmnl: ${have_libmnl:-no}
libnuma: ${have_libnuma:-no} (headers: ${have_numa_headers:-no}, v2 headers: ${have_numa_headers_v2:-no})
libcrypto: ${have_libcrypto:-no} (sha: ${have_sha:-no})
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}
+218
View File
@@ -0,0 +1,218 @@
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
File diff suppressed because it is too large Load Diff
+479
View File
@@ -0,0 +1,479 @@
LTP C Test Network API
======================
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],
https://github.com/linux-test-project/ltp/wiki/Shell-Test-API[Shell Test API].
LTP library includes helper functions for configuring sockets and setting up
network devices.
1 Configuring sockets
---------------------
1.1 Safe syscall variants
~~~~~~~~~~~~~~~~~~~~~~~~~
+#include "tst_safe_net.h"+
Most common standard syscalls and libc functions for configuring sockets have a
"safe" variant in LTP library which will call +tst_brk()+ if the underlying
system function fails. See
https://github.com/linux-test-project/ltp/wiki/C-Test-API[C Test API]. The
safe function names are in uppercase with the +SAFE_+ prefix (e.g. the safe
variant of +socket()+ is called +SAFE_SOCKET()+). For most safe functions, the
parameters and return type are identical to the standard system function:
- +SAFE_SOCKET()+
- +SAFE_SOCKETPAIR()+
- +SAFE_GETSOCKOPT()+
- +SAFE_SETSOCKOPT()+
- +SAFE_BIND()+
- +SAFE_LISTEN()+
- +SAFE_ACCEPT()+
- +SAFE_CONNECT()+
- +SAFE_GETSOCKNAME()+
- +SAFE_GETHOSTNAME()+
- +SAFE_GETADDRINFO()+
A few safe functions have extra parameters for quick return value validation.
The ellipsis (+...+) represents the standard parameters of the underlying system
function:
* +SAFE_SEND(char strict, ...)+
* +SAFE_SENDTO(char strict, ...)+
** If +strict+ is non-zero, the return value must be equal to the data length
argument. Otherwise the test will fail and exit.
* +SAFE_SENDMSG(size_t msg_len, ...)+
* +SAFE_RECV(size_t msg_len, ...)+
* +SAFE_RECVMSG(size_t msg_len, ...)+
** If +msg_len+ is non-zero, the return value must be equal to the +msg_len+
argument. Otherwise the test will fail and exit.
There are also some custom functions for simpler configuration and queries:
- +int SAFE_SETSOCKOPT_INT(int sockfd, int level, int optname, int value)+
Simple setsockopt() variant for passing integers by value.
- +int TST_GETSOCKPORT(int sockfd)+ Get port number (in host byte order) of a
bound socket.
- +unsigned short TST_GET_UNUSED_PORT(int family, int type)+ Get a random
port number (in network byte order) which is currently closed for the given
socket family and type. Note that another application may open the port while
the test is still running. The test user is responsible for setting up test
environment without such interference.
1.2 Address conversion functions
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+#include "tst_net.h"+
LTP library also provides helper functions for quick initialization of socket
address structures:
- +void tst_get_in_addr(const char *ip_str, struct in_addr *ip)+ Convert
human-readable IPv4 address string +ip_str+ to binary representation in
network byte order. The converted value will be stored in the second argument.
- +void tst_get_in6_addr(const char *ip_str, struct in6_addr *ip6)+ Convert
human-readable IPv6 address string +ip_str+ to binary representation in
network byte order. The converted value will be stored in the second argument.
- +socklen_t tst_get_connect_address(int sock, struct sockaddr_storage *addr)+
Find the address which can be used to send data to bound socket +sock+ from
another socket. The address will be stored in the second argument. This
function automatically converts wildcard bind address to localhost. Returns
size of the address in bytes.
- +void tst_init_sockaddr_inet(struct sockaddr_in *sa, const char *ip_str,
uint16_t port)+ Initialize socket address structure +sa+ using
human-readable IPv4 address +ip_str+ and port number +port+ in host byte
order.
- +void tst_init_sockaddr_inet_bin(struct sockaddr_in *sa, uint32_t ip_val,
uint16_t port)+ Initialize socket address structure +sa+ using binary IPv4
address +ip_val+ and port number +port+, both in host byte order.
- +void tst_init_sockaddr_inet6(struct sockaddr_in6 *sa, const char *ip_str,
uint16_t port)+ Initialize socket address structure +sa+ using
human-readable IPv6 address +ip_str+ and port number +port+ in host byte
order.
- +void tst_init_sockaddr_inet6_bin(struct sockaddr_in6 *sa, const struct
in6_addr *ip_val, uint16_t port)+ Initialize socket address structure +sa+
using binary IPv6 address +ip_val+ and port number +port+, both in host byte
order.
Example Usage
+++++++++++++
[source,c]
-------------------------------------------------------------------------------
#include <sys/socket.h>
#include <netinet/in.h>
#include "tst_test.h"
#include "tst_safe_net.h"
#include "tst_net.h"
static int sockfd = -1;
static void setup(void)
{
struct sockaddr_in addr;
tst_init_sockaddr_inet_bin(&addr, INADDR_ANY, 0);
sockfd = SAFE_SOCKET(AF_INET, SOCK_STREAM, 0);
SAFE_SETSOCKOPT_INT(sockfd, SOL_SOCKET, SO_SNDBUF, 4096);
SAFE_BIND(sockfd, (struct sockaddr *)&addr, sizeof(addr));
SAFE_LISTEN(sockfd, 8);
}
-------------------------------------------------------------------------------
2 Configuring network devices
-----------------------------
+#include "tst_netdevice.h"+
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.
All of these functions will call +tst_brk()+ on failure, unless stated
otherwise. Error values described below are returned only during test cleanup
stage.
2.1 Network device management
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- +int NETDEV_INDEX_BY_NAME(const char *ifname)+ Returns the device index for
the given device name, or -1 on error.
- +int NETDEV_SET_STATE(const char *ifname, int up)+ Enable or disable a
network device +ifname+. Returns 0 on success, -1 on error.
- +int CREATE_VETH_PAIR(const char *ifname1, const char *ifname2)+ Creates a
connected pair of virtual network devices with given device names. Returns 1
on success, 0 on error. Add +"CONFIG_VETH"+ to +test.needs_kconfigs+ if your
test calls this function.
- +int NETDEV_ADD_DEVICE(const char *ifname, const char *devtype)+ - Creates
a new network device named +ifname+ of specified device type. Returns 1 on
success, 0 on error.
- +int NETDEV_REMOVE_DEVICE(const char *ifname)+ Removes network device
+ifname+. Returns 1 on success, 0 on error.
2.2 Network address management
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- +int NETDEV_ADD_ADDRESS(const char \*ifname, unsigned int family, const void
*address, unsigned int prefix, size_t addrlen, unsigned int flags)+ Adds
new address to network device +ifname+. This is a low-level function which
allows setting any type of address. You must specify the protocol +family+,
address length in bytes (+addrlen+) and network prefix length (+prefix+). The
+address+ itself must be in binary representation in network byte order. You
can also pass rtnetlink flags from the +IFA_F_*+ group. Returns 1 on success,
0 on error.
- +int NETDEV_ADD_ADDRESS_INET(const char *ifname, in_addr_t address, unsigned
int prefix, unsigned int flags)+ Adds new IPv4 address to network device
+ifname+. Parameters have the same meaning as in +NETDEV_ADD_ADDRESS()+.
Returns 1 on success, 0 on error.
- +int NETDEV_REMOVE_ADDRESS(const char *ifname, unsigned int family, const
void *address, size_t addrlen)+ Removes the specified address from network
device +ifname+. Parameters have the same meaning as in
+NETDEV_ADD_ADDRESS()+. Returns 1 on success, 0 on error.
- +int NETDEV_REMOVE_ADDRESS_INET(const char *ifname, in_addr_t address)+
Removes specified IPv4 +address+ (in network byte order) from network device
+ifname+. Returns 1 on success, 0 on error.
2.3 Network namespace device assignment
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
WARNING: Moving a network device to another namespace will erase previous
configuration. Move the device to the correct namespace first, then
configure it.
- +int NETDEV_CHANGE_NS_FD(const char *ifname, int nsfd)+ Moves network
device +ifname+ to network namespace designated by open file descriptor
+nsfd+. Returns 1 on success, 0 on error.
- +int NETDEV_CHANGE_NS_PID(const char *ifname, pid_t nspid)+ Moves network
device +ifname+ to the network namespace currently used by process +nspid+.
Returns 1 on success, 0 on error.
2.4 Routing table management
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- +int NETDEV_ADD_ROUTE(const char *ifname, unsigned int family, const void
*srcaddr, unsigned int srcprefix, size_t srclen, const void *dstaddr,
unsigned int dstprefix, size_t dstlen, const void *gateway, size_t
gatewaylen)+ Adds new route to the main routing table. This is a low-level
function which allows creating routes for any protocol. You must specify the
protocol +family+ and either network device name +ifname+ or +gateway+
address. Both packet source address +srcaddr+ and destination address
+dstaddr+ are optional. You must also specify the corresponding length
and prefix argument for any address which is not +NULL+. All addresses must
be in binary representation in network byte order. Returns 1 on success,
0 on error.
- +int NETDEV_ADD_ROUTE_INET(const char *ifname, in_addr_t srcaddr, unsigned
int srcprefix, in_addr_t dstaddr, unsigned int dstprefix, in_addr_t
gateway)+ Adds new IPv4 route to the main routing table. Parameters have
the same meaning as in +NETDEV_ADD_ROUTE()+. If you do not want to set
explicit +gateway+ address, set it to 0. If the routing rule should ignore
the source or destination address, set the corresponding prefix argument
to 0. Returns 1 on success, 0 on error.
- +int NETDEV_REMOVE_ROUTE(const char *ifname, unsigned int family, const void
*srcaddr, unsigned int srcprefix, size_t srclen, const void *dstaddr,
unsigned int dstprefix, size_t dstlen, const void *gateway, size_t
gatewaylen)+ Removes a route from the main routing table. Parameters have
the same meaning as in +NETDEV_ADD_ROUTE()+. Returns 1 on success, 0 on
error.
- +int NETDEV_REMOVE_ROUTE_INET(const char *ifname, in_addr_t srcaddr,
unsigned int srcprefix, in_addr_t dstaddr, unsigned int dstprefix, in_addr_t
gateway)+ Removes IPv4 route from the main routing table. Parameters have
the same meaning as in +NETDEV_ADD_ROUTE_INET()+. Returns 1 on success,
0 on error.
Example Usage
+++++++++++++
[source,c]
-------------------------------------------------------------------------------
#include <arpa/inet.h>
#include <linux/if_addr.h>
#include "tst_test.h"
#include "tst_netdevice.h"
...
static void setup(void)
{
CREATE_VETH_PAIR("ltp_veth1", "ltp_veth2");
NETDEV_ADD_ADDRESS_INET("ltp_veth2", htonl(DSTADDR), NETMASK,
IFA_F_NOPREFIXROUTE);
NETDEV_SET_STATE("ltp_veth2", 1);
NETDEV_ADD_ROUTE_INET("ltp_veth2", 0, 0, htonl(SRCNET), NETMASK, 0);
NETDEV_ADD_ADDRESS_INET("ltp_veth1", htonl(SRCADDR), NETMASK,
IFA_F_NOPREFIXROUTE);
NETDEV_SET_STATE("ltp_veth1", 1);
NETDEV_ADD_ROUTE_INET("ltp_veth1", 0, 0, htonl(DSTNET), NETMASK, 0);
...
}
-------------------------------------------------------------------------------
3 rtnetlink API
---------------
+#include "tst_rtnetlink.h"+
The rtnetlink 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
otherwise. Error values described below are returned only during test cleanup
stage.
3.1 Data structures
~~~~~~~~~~~~~~~~~~~
[source,c]
-------------------------------------------------------------------------------
struct tst_rtnl_context;
struct tst_rtnl_attr_list {
unsigned short type;
const void *data;
ssize_t len;
const struct tst_rtnl_attr_list *sublist;
};
struct tst_rtnl_message {
struct nlmsghdr *header;
struct nlmsgerr *err;
void *payload;
size_t payload_size;
};
-------------------------------------------------------------------------------
+struct tst_rtnl_context+ is an opaque rtnetlink 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.
+struct tst_rtnl_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+.
- +data+ contains arbitrary attribute payload.
- +len+ contains length of the +data+ attribute in bytes. If +data+ is +NULL+,
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+.
+struct tst_rtnl_message+ is a structure holding partially parsed rtnetlink
messages received from the kernel. +RTNL_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()+.
- +header+ is the netlink header structure of the message. +NULL+ in the header
field terminates a list of messages.
- +err+ points to the payload of +NLMSG_ERROR+ messages. It is set to +NULL+
for all other message types.
- +payload+ is a pointer to message data.
- +payload_size+ is the length of +payload+ data in bytes.
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.
- +void RTNL_FREE_MESSAGE(struct tst_rtnl_message *msg)+ Frees an array of
messages returned by +RTNL_RECV()+.
- +void RTNL_DESTROY_CONTEXT(struct tst_rtnl_context *ctx)+ Closes a
communication context created by +RTNL_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 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 RTNL_WAIT(struct tst_rtnl_context *ctx)+ Waits until data becomes
available to read from the rtnetlink 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.
- +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+).
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
+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()+.
- +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 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 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.
Example Usage
+++++++++++++
[source,c]
-------------------------------------------------------------------------------
#include <asm/types.h>
#include <linux/netlink.h>
#include <linux/rtnetlink.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include "tst_test.h"
#include "tst_rtnetlink.h"
#include "tst_netdevice.h"
...
void setup(void)
{
struct tst_rtnl_context *ctx;
int index, ret;
in_addr_t addr;
struct nlmsghdr header = {
.nlmsg_type = RTM_NEWADDR,
.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK | NLM_F_CREATE |
NLM_F_EXCL
};
struct ifaddrmsg info = {
.ifa_family = AF_INET,
.ifa_prefixlen = 24
};
index = NETDEV_INDEX_BY_NAME("ltp_veth1");
info.ifa_index = index;
ctx = RTNL_CREATE_CONTEXT();
RTNL_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);
if (!ret) {
tst_brk(TBROK, "Failed to set ltp_veth1 address");
}
}
-------------------------------------------------------------------------------
+487
View File
@@ -0,0 +1,487 @@
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.
@@ -0,0 +1,84 @@
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
@@ -0,0 +1,170 @@
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
@@ -0,0 +1,141 @@
# 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].
+828
View File
@@ -0,0 +1,828 @@
LTP Shell Test API
==================
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].
1 Writing a testcase in shell
-----------------------------
LTP supports testcases to be written in a portable shell too.
There is a shell library modeled closely to the C interface at
'testcases/lib/tst_test.sh'.
WARNING: All identifiers starting with 'TST_' or 'tst_' are reserved for the
test library.
1.1 Basic test interface
~~~~~~~~~~~~~~~~~~~~~~~~
[source,sh]
-------------------------------------------------------------------------------
#!/bin/sh
# SPDX-License-Identifier: GPL-2.0-or-later
# This is a basic test for true shell builtin
TST_TESTFUNC=do_test
do_test()
{
true
ret=$?
if [ $ret -eq 0 ]; then
tst_res TPASS "true returned 0"
else
tst_res TFAIL "true returned $ret"
fi
}
. tst_test.sh
tst_run
-------------------------------------------------------------------------------
TIP: To execute this test the 'tst_test.sh' library must be in '$PATH'. If you
are executing the test from a git checkout you can run it as
'PATH="$PATH:../../lib" ./foo01.sh'
The shell library expects test setup, cleanup and the test function executing
the test in the '$TST_SETUP', '$TST_CLEANUP' and '$TST_TESTFUNC' variables.
Both '$TST_SETUP' and '$TST_CLEANUP' are optional.
The '$TST_TESTFUNC' may be called several times if more than one test
iteration was requested by passing right command line options to the test.
The '$TST_CLEANUP' may be called even in the middle of the setup and must be
able to clean up correctly even in this situation. The easiest solution for
this is to keep track of what was initialized and act accordingly in the
cleanup.
WARNING: Similar to the C library, calling 'tst_brk' in the $TST_CLEANUP does
not exit the test and 'TBROK' is converted to 'TWARN'.
Notice also the 'tst_run' shell API function called at the end of the test that
actually starts the test.
WARNING: cleanup function is called only after 'tst_run' has been started.
Calling 'tst_brk' in shell libraries, e.g. 'tst_test.sh' or 'tst_net.sh' does
not trigger calling it.
[source,sh]
-------------------------------------------------------------------------------
#!/bin/sh
# SPDX-License-Identifier: GPL-2.0-or-later
# Example test with tests in separate functions
TST_TESTFUNC=test
TST_CNT=2
test1()
{
tst_res TPASS "Test $1 passed"
}
test2()
{
tst_res TPASS "Test $1 passed"
}
. tst_test.sh
tst_run
# output:
# foo 1 TPASS: Test 1 passed
# foo 2 TPASS: Test 2 passed
-------------------------------------------------------------------------------
If '$TST_CNT' is set, the test library looks if there are functions named
'$\{TST_TESTFUNC\}1', ..., '$\{TST_TESTFUNC\}$\{TST_CNT\}' and if these are
found they are executed one by one. The test number is passed to it in the '$1'.
[source,sh]
-------------------------------------------------------------------------------
#!/bin/sh
# SPDX-License-Identifier: GPL-2.0-or-later
# Example test with tests in a single function
TST_TESTFUNC=do_test
TST_CNT=2
do_test()
{
case $1 in
1) tst_res TPASS "Test $1 passed";;
2) tst_res TPASS "Test $1 passed";;
esac
}
. tst_test.sh
tst_run
# output:
# foo 1 TPASS: Test 1 passed
# foo 2 TPASS: Test 2 passed
-------------------------------------------------------------------------------
Otherwise, if '$TST_CNT' is set but there is no '$\{TST_TESTFUNC\}1', etc.,
the '$TST_TESTFUNC' is executed '$TST_CNT' times and the test number is passed
to it in the '$1'.
[source,sh]
-------------------------------------------------------------------------------
#!/bin/sh
# SPDX-License-Identifier: GPL-2.0-or-later
# Example test with tests in a single function, using $TST_TEST_DATA and
# $TST_TEST_DATA_IFS
TST_TESTFUNC=do_test
TST_TEST_DATA="foo:bar:d dd"
TST_TEST_DATA_IFS=":"
do_test()
{
tst_res TPASS "Test $1 passed with data '$2'"
}
. tst_test.sh
tst_run
# output:
# foo 1 TPASS: Test 1 passed with data 'foo'
# foo 2 TPASS: Test 1 passed with data 'bar'
# foo 3 TPASS: Test 1 passed with data 'd dd'
-------------------------------------------------------------------------------
It's possible to pass data for function with '$TST_TEST_DATA'. Optional
'$TST_TEST_DATA_IFS' is used for splitting, default value is space.
[source,sh]
-------------------------------------------------------------------------------
#!/bin/sh
# SPDX-License-Identifier: GPL-2.0-or-later
# Example test with tests in a single function, using $TST_TEST_DATA and $TST_CNT
TST_TESTFUNC=do_test
TST_CNT=2
TST_TEST_DATA="foo bar"
do_test()
{
case $1 in
1) tst_res TPASS "Test $1 passed with data '$2'";;
2) tst_res TPASS "Test $1 passed with data '$2'";;
esac
}
. tst_test.sh
tst_run
# output:
# foo 1 TPASS: Test 1 passed with data 'foo'
# foo 2 TPASS: Test 2 passed with data 'foo'
# foo 3 TPASS: Test 1 passed with data 'bar'
# foo 4 TPASS: Test 2 passed with data 'bar'
-------------------------------------------------------------------------------
'$TST_TEST_DATA' can be used with '$TST_CNT'. If '$TST_TEST_DATA_IFS' not specified,
space as default value is used. Of course, it's possible to use separate functions.
1.2 Library environment variables and functions for shell
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Similarily to the C library various checks and preparations can be requested
simply by setting right '$TST_FOO'.
[options="header"]
|=============================================================================
| Variable name | Action done
| 'TST_ALL_FILESYSTEMS' | Testing on all available filesystems
('tst_test.all_filesystems' equivalent).
When 'TST_SKIP_FILESYSTEMS' any listed filesystem is not
included in the resulting list of supported filesystems.
| 'TST_DEV_EXTRA_OPTS' | Pass extra 'mkfs' options _after_ device name,
to 'tst_mkfs', use with 'TST_FORMAT_DEVICE=1'.
| 'TST_DEV_FS_OPTS' | Pass 'mkfs' options _before_ the device name,
to 'tst_mkfs', use with 'TST_FORMAT_DEVICE=1'.
| 'TST_FORMAT_DEVICE' | Format a block device with a filesystem, see
https://github.com/linux-test-project/ltp/wiki/Shell-Test-API#formatting-device-with-a-filesystem[Formatting device with a filesystem].
See also 'TST_DEV_EXTRA_OPTS', 'TST_DEV_FS_OPTS', 'TST_FS_TYPE'.
Implies 'TST_NEEDS_DEVICE=1' (no need to set it).
| 'TST_DEVICE' | Block device name for 'tst_mount' and 'tst_mkfs', see
https://github.com/linux-test-project/ltp/wiki/Shell-Test-API#formatting-device-with-a-filesystem[Formatting device with a filesystem].
| 'TST_FS_TYPE' | Override the default filesystem to be used. Also
contains currently used filesystem during looping
filesystems in 'TST_ALL_FILESYSTEMS=1'
('tst_device->fs_type' equivalent).
| 'TST_MNTPOINT' | Holds path to mountpoint used in 'tst_mount', see
https://github.com/linux-test-project/ltp/wiki/Shell-Test-API#formatting-device-with-a-filesystem[Formatting device with a filesystem].
| 'TST_MNT_PARAMS' | Extra mount params for 'tst_mount', see
https://github.com/linux-test-project/ltp/wiki/Shell-Test-API#formatting-device-with-a-filesystem[Formatting device with a filesystem].
| 'TST_MOUNT_DEVICE' | Mount device, see
https://github.com/linux-test-project/ltp/wiki/Shell-Test-API#mounting-and-unmounting-filesystems[Mounting and unmounting filesystems].
| 'TST_NEEDS_ROOT' | Exit the test with 'TCONF' unless executed under root.
Alternatively the 'tst_require_root' command can be used.
| 'TST_NEEDS_TMPDIR' | Create test temporary directory and cd into it.
| 'TST_NEEDS_DEVICE' | Prepare test temporary device, the path to testing
device is stored in '$TST_DEVICE' variable.
The option implies 'TST_NEEDS_TMPDIR'.
| 'TST_NEEDS_CMDS' | String with command names that has to be present for
the test (see below).
| 'TST_NEEDS_MODULE' | Test module name needed for the test (see below).
| 'TST_NEEDS_DRIVERS' | Checks kernel drivers support for the test.
| 'TST_NEEDS_KCONFIGS' | Checks kernel kconfigs support for the test (see below).
| 'TST_NEEDS_KCONFIGS_IFS' | Used for splitting '$TST_NEEDS_KCONFIGS' variable,
default value is comma, it only supports single character.
| 'TST_SKIP_FILESYSTEMS' | Comma separated list of filesystems on which test will be skipped
(tst_test.skip_filesystems equivalent).
| 'TST_TIMEOUT' | Maximum timeout set for the test in sec. Must be int >= 1,
or -1 (special value to disable timeout), default is 300.
Variable is meant be set in tests, not by user.
It's an equivalent of `tst_test.timeout` in C, can be set
via 'tst_set_timeout(timeout)' after test has started.
|=============================================================================
[options="header"]
|=============================================================================
| Function name | Action done
| 'tst_set_timeout(timeout)' | Maximum timeout set for the test in sec.
See 'TST_TIMEOUT' variable.
|=============================================================================
NOTE: Network tests (see testcases/network/README.md) use additional variables
and functions in 'tst_net.sh'.
Checking for presence of commands
+++++++++++++++++++++++++++++++++
[source,sh]
-------------------------------------------------------------------------------
#!/bin/sh
...
TST_NEEDS_CMDS="modinfo modprobe"
. tst_test.sh
...
-------------------------------------------------------------------------------
Setting '$TST_NEEDS_CMDS' to a string listing required commands will check for
existence each of them and exits the test with 'TCONF' on first missing.
Alternatively the 'tst_require_cmds()' function can be used to do the same on
runtime, since sometimes we need to the check at runtime too.
'tst_check_cmds()' can be used for requirements just for a particular test
as it doesn't exit (it issues 'tst_res TCONF'). Expected usage is:
[source,sh]
-------------------------------------------------------------------------------
#!/bin/sh
TST_TESTFUNC=do_test
do_test()
{
tst_check_cmds cmd || return
cmd --foo
...
}
. tst_test.sh
tst_run
-------------------------------------------------------------------------------
Locating kernel modules
+++++++++++++++++++++++
The LTP build system can build kernel modules as well, setting
'$TST_NEEDS_MODULE' to module name will cause the library to look for the
module in a few possible paths.
If module was found the path to it will be stored into '$TST_MODPATH'
variable, if module wasn't found the test will exit with 'TCONF'.
Alternatively the 'tst_require_module()' function can be used to do the same
at runtime.
1.3 Optional command line parameters
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
[source,sh]
-------------------------------------------------------------------------------
#!/bin/sh
# SPDX-License-Identifier: GPL-2.0-or-later
# Optional test command line parameters
TST_OPTS="af:"
TST_USAGE=usage
TST_PARSE_ARGS=parse_args
TST_TESTFUNC=do_test
ALTERNATIVE=0
MODE="foo"
usage()
{
cat << EOF
usage: $0 [-a] [-f <foo|bar>]
OPTIONS
-a Enable support for alternative foo
-f Specify foo or bar mode
EOF
}
parse_args()
{
case $1 in
a) ALTERNATIVE=1;;
f) MODE="$2";;
esac
}
do_test()
{
...
}
. tst_test.sh
tst_run
-------------------------------------------------------------------------------
The 'getopts' string for optional parameters is passed in the '$TST_OPTS'
variable. There are a few default parameters that cannot be used by a test,
these can be listed with passing help '-h' option to any test.
The function that prints the usage is passed in '$TST_USAGE', the help for
the options implemented in the library is appended when usage is printed.
Lastly the function '$PARSE_ARGS' is called with the option name in the '$1'
and, if option has argument, its value in the '$2'.
[source,sh]
-------------------------------------------------------------------------------
#!/bin/sh
# SPDX-License-Identifier: GPL-2.0-or-later
# Optional test positional parameters
TST_POS_ARGS=3
TST_USAGE=usage
TST_TESTFUNC=do_test
usage()
{
cat << EOF
usage: $0 [min] [max] [size]
EOF
}
min="$1"
max="$2"
size="$3"
do_test()
{
...
}
. tst_test.sh
tst_run
-------------------------------------------------------------------------------
You can also request a number of positional parameters by setting the
'$TST_POS_ARGS' variable. If you do, these will be available as they were
passed directly to the script in '$1', '$2', ..., '$n'.
1.4 Useful library functions
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Retrieving configuration variables
++++++++++++++++++++++++++++++++++
You may need to retrieve configuration values such as PAGESIZE, there is
'getconf' but as some system may not have it, you are advised to use
'tst_getconf' instead. Note that it implements subset of 'getconf'
system variables used by the testcases only.
[source,sh]
-------------------------------------------------------------------------------
# retrieve PAGESIZE
pagesize=`tst_getconf PAGESIZE`
-------------------------------------------------------------------------------
Sleeping for subsecond intervals
++++++++++++++++++++++++++++++++
Albeit there is a sleep command available basically everywhere not all
implementations can support sleeping for less than one second. And most of the
time sleeping for a second is too much. Therefore LTP includes 'tst_sleep'
that can sleep for defined amount of seconds, milliseconds or microseconds.
[source,sh]
-------------------------------------------------------------------------------
# sleep for 100 milliseconds
tst_sleep 100ms
-------------------------------------------------------------------------------
Retry a function call multiple times
++++++++++++++++++++++++++++++++++++
Sometimes an LTP test needs to retry a function call multiple times because
the system is not ready to process it successfully on the first try. The LTP
library has useful tools to handle the call retry automatically.
'TST_RETRY_FUNC()' will keep retrying for up to 1 second. If you want a custom
time limit use 'TST_RETRY_FN_EXP_BACKOFF()'. Both methods return the value
returned by the last 'FUNC' call.
The delay between retries starts at 1 microsecond and doubles after each call.
The retry loop ends when the function call succeeds or when the next delay
exceeds the specified time (1 second for 'TST_RETRY_FUNC()'). The maximum
delay is multiplied by TST_TIMEOUT_MUL. The total cumulative delay may be up
to twice as long as the adjusted maximum delay.
The C version of 'TST_RETRY_FUNC()' is a macro which takes two arguments:
* 'FUNC' is the complete function call with arguments which should be retried
multiple times.
* 'SUCCESS_CHECK' is a macro or function which will validate 'FUNC' return
value. 'FUNC' call was successful if 'SUCCESS_CHECK(ret)' evaluates to
non-zero.
Both retry methods clear 'errno' before every 'FUNC' call so your
'SUCCESS_CHECK' can look for specific error codes as well. The LTP library
also includes predefined 'SUCCESS_CHECK' macros for the most common call
conventions:
* 'TST_RETVAL_EQ0()' - The call was successful if 'FUNC' returned 0 or NULL
* 'TST_RETVAL_NOTNULL()' - The call was successful if 'FUNC' returned any
value other than 0 or NULL.
* 'TST_RETVAL_GE0()' - The call was successful if 'FUNC' returned value >= 0.
[source,c]
-------------------------------------------------------------------------------
/* Keep trying for 1 second */
TST_RETRY_FUNC(FUNC, SUCCESS_CHECK)
/* Keep trying for up to 2*N seconds */
TST_RETRY_FN_EXP_BACKOFF(FUNC, SUCCESS_CHECK, N)
-------------------------------------------------------------------------------
The shell version of 'TST_RETRY_FUNC()' is simpler and takes slightly
different arguments:
* 'FUNC' is a string containing the complete function or program call with
arguments.
* 'EXPECTED_RET' is a single expected return value. 'FUNC' call was successful
if the return value is equal to EXPECTED_RET.
[source,sh]
-------------------------------------------------------------------------------
# Keep trying for 1 second
TST_RETRY_FUNC "FUNC arg1 arg2 ..." "EXPECTED_RET"
# Keep trying for up to 2*N seconds
TST_RETRY_FN_EXP_BACKOFF "FUNC arg1 arg2 ..." "EXPECTED_RET" "N"
-------------------------------------------------------------------------------
Checking for integers
+++++++++++++++++++++
[source,sh]
-------------------------------------------------------------------------------
# returns zero if passed an integer parameter, non-zero otherwise
tst_is_int "$FOO"
-------------------------------------------------------------------------------
Checking for integers and floating point numbers
++++++++++++++++++++++++++++++++++++++++++++++++
[source,sh]
-------------------------------------------------------------------------------
# returns zero if passed an integer or floating point number parameter,
# non-zero otherwise
tst_is_num "$FOO"
-------------------------------------------------------------------------------
Obtaining random numbers
++++++++++++++++++++++++
There is no '$RANDOM' in portable shell, use 'tst_random' instead.
[source,sh]
-------------------------------------------------------------------------------
# get random integer between 0 and 1000 (including 0 and 1000)
tst_random 0 1000
-------------------------------------------------------------------------------
Formatting device with a filesystem
+++++++++++++++++++++++++++++++++++
'TST_FORMAT_DEVICE=1' can be used to format device before running the test.
Uses '$TST_FS_TYPE' (by default ext2), '$TST_DEVICE' a block device to be
formatted, usually prepared by the library (TST_NEEDS_DEVICE=1 must be set).
'$TST_DEV_FS_OPTS' a 'mkfs' options _before_ the device path and
'$TST_DEV_EXTRA_OPTS' extra 'mkfs'' options _after_ the device path.
[source,sh]
-------------------------------------------------------------------------------
TST_FORMAT_DEVICE=1
TST_DEV_FS_OPTS="-b 1024 -O quota"
TST_DEV_EXTRA_OPTS="5m"
TST_TESTFUNC=test
test()
{
tst_res TPASS "device formatted"
}
-------------------------------------------------------------------------------
[source,sh]
-------------------------------------------------------------------------------
# format test device with ext2
tst_mkfs ext2 $TST_DEVICE
# default params are $TST_FS_TYPE $TST_DEVICE
tst_mkfs
# optional parameters
tst_mkfs ext4 /dev/device -T largefile
-------------------------------------------------------------------------------
Mounting and unmounting filesystems
+++++++++++++++++++++++++++++++++++
The 'tst_mount' and 'tst_umount' helpers are a safe way to mount/umount
a filesystem.
The 'tst_mount' mounts '$TST_DEVICE' of '$TST_FS_TYPE' (optional) to
'$TST_MNTPOINT' (defaults to mntpoint), optionally using the
'$TST_MNT_PARAMS'. The '$TST_MNTPOINT' directory is created if it didn't
exist prior to the function call.
If the path passed (optional, must be absolute path, defaults to '$TST_MNTPOINT')
to the 'tst_umount' is not mounted (present in '/proc/mounts') it's noop.
Otherwise it retries to umount the filesystem a few times on failure.
This is a workaround since there are daemons dumb enough to probe all newly
mounted filesystems, and prevents them from being umounted shortly after they
were mounted.
ROD and ROD_SILENT
++++++++++++++++++
These functions supply the 'SAFE_MACROS' used in C although they work and are
named differently.
[source,sh]
-------------------------------------------------------------------------------
ROD_SILENT command arg1 arg2 ...
# is shorthand for:
command arg1 arg2 ... > /dev/null 2>&1
if [ $? -ne 0 ]; then
tst_brk TBROK "..."
fi
ROD command arg1 arg2 ...
# is shorthand for:
ROD arg1 arg2 ...
if [ $? -ne 0 ]; then
tst_brk TBROK "..."
fi
-------------------------------------------------------------------------------
WARNING: Keep in mind that output redirection (to a file) happens in the
caller rather than in the ROD function and cannot be checked for
write errors by the ROD function.
As a matter of a fact doing +ROD echo a > /proc/cpuinfo+ would work just fine
since the 'ROD' function will only get the +echo a+ part that will run just
fine.
[source,sh]
-------------------------------------------------------------------------------
# Redirect output to a file with ROD
ROD echo foo \> bar
-------------------------------------------------------------------------------
Note the '>' is escaped with '\', this causes that the '>' and filename are
passed to the 'ROD' function as parameters and the 'ROD' function contains
code to split '$@' on '>' and redirects the output to the file.
EXPECT_PASS{,_BRK} and EXPECT_FAIL{,_BRK}
+++++++++++++++++++++++++++++++++++++++++
[source,sh]
-------------------------------------------------------------------------------
EXPECT_PASS command arg1 arg2 ... [ \> file ]
EXPECT_FAIL command arg1 arg2 ... [ \> file ]
-------------------------------------------------------------------------------
'EXPECT_PASS' calls 'tst_res TPASS' if the command exited with 0 exit code,
and 'tst_res TFAIL' otherwise. 'EXPECT_FAIL' does vice versa.
Output redirection rules are the same as for the 'ROD' function. In addition
to that, 'EXPECT_FAIL' always redirects the command's stderr to '/dev/null'.
There are also 'EXPECT_PASS_BRK' and 'EXPECT_FAIL_BRK', which works the same way
except breaking a test when unexpected action happen.
It's possible to detect whether expected value happened:
[source,sh]
-------------------------------------------------------------------------------
if ! EXPECT_PASS command arg1 2\> /dev/null; then
continue
fi
-------------------------------------------------------------------------------
tst_kvcmp
+++++++++
This command compares the currently running kernel version given conditions
with syntax similar to the shell test command.
[source,sh]
-------------------------------------------------------------------------------
# Exit the test if kernel version is older or equal to 4.0.0
if tst_kvcmp -le 4.0.0; then
tst_brk TCONF "Kernel newer than 4.0.0 is needed"
fi
# Exit the test if kernel is newer than 3.16 and older than 4.0.1
if tst_kvcmp -gt 3.16 -a -lt 4.0.1; then
tst_brk TCONF "Kernel must be older than 3.16 or newer than 4.0.1"
fi
if tst_kvcmp -lt "6.1 RHEL9:5.14.0-191"; then
# code for kernel < 6.1 or RHEL9 kernel < 5.14.0-191
fi
-------------------------------------------------------------------------------
[options="header"]
|=======================================================================
| expression | description
| -eq kver | Returns true if kernel version is equal
| -ne kver | Returns true if kernel version is not equal
| -gt kver | Returns true if kernel version is greater
| -ge kver | Returns true if kernel version is greater or equal
| -lt kver | Returns true if kernel version is lesser
| -le kver | Returns true if kernel version is lesser or equal
| -a | Does logical and between two expressions
| -o | Does logical or between two expressions
|=======================================================================
The format for kernel version has to either be with one dot e.g. '2.6' or with
two dots e.g. '4.8.1'.
Kernel version can also be followed by a space separated list of extra versions
prefixed by distribution which when matched take precedence, e.g. '6.1 RHEL9:5.14.0-191'.
For more info see 'tst_kvercmp()' and 'tst_kvercmp2()' in
https://github.com/linux-test-project/ltp/wiki/C-Test-API#16-runtime-kernel-version-detection[C Test API].
NOTE: See also LTP
https://github.com/linux-test-project/ltp/wiki/Supported-kernel,-libc,-toolchain-versions#13-minimal-supported-kernel-version[minimal supported kernel version].
tst_fs_has_free
+++++++++++++++
[source,sh]
-------------------------------------------------------------------------------
#!/bin/sh
...
# whether current directory has 100MB free space at least.
if ! tst_fs_has_free . 100MB; then
tst_brkm TCONF "Not enough free space"
fi
...
-------------------------------------------------------------------------------
The 'tst_fs_has_free' shell interface returns 0 if the specified free space is
satisfied, 1 if not, and 2 on error.
The second argument supports suffixes kB, MB and GB, the default unit is Byte.
tst_retry
+++++++++
[source,sh]
-------------------------------------------------------------------------------
#!/bin/sh
...
# Retry ping command three times
tst_retry "ping -c 1 127.0.0.1"
if [ $? -ne 0 ]; then
tst_resm TFAIL "Failed to ping 127.0.0.1"
else
tst_resm TPASS "Successfully pinged 127.0.0.1"
fi
...
-------------------------------------------------------------------------------
The 'tst_retry' function allows you to retry a command after waiting small
amount of time until it succeeds or until given amount of retries has been
reached (default is three attempts).
1.5 Restarting daemons
~~~~~~~~~~~~~~~~~~~~~~
Restarting system daemons is a complicated task for two reasons.
* There are different init systems
(SysV init, systemd, etc...)
* Daemon names are not unified between distributions
(apache vs httpd, cron vs crond, various syslog variations)
To solve these problems LTP has 'testcases/lib/daemonlib.sh' library that
provides functions to start/stop/query daemons as well as variables that store
correct daemon name.
.Supported operations
|==============================================================================
| start_daemon() | Starts daemon, name is passed as first parameter.
| stop_daemon() | Stops daemon, name is passed as first parameter.
| restart_daemon() | Restarts daemon, name is passed as first parameter.
| status_daemon() | Detect daemon status (exit code: 0: running, 1: not running).
|==============================================================================
.Variables with detected names
|==============================================================================
| CROND_DAEMON | Cron daemon name (cron, crond).
| SYSLOG_DAEMON | Syslog daemon name (syslog, syslog-ng, rsyslog).
|==============================================================================
Cron daemon restart example
+++++++++++++++++++++++++++
[source,sh]
-------------------------------------------------------------------------------
#!/bin/sh
# SPDX-License-Identifier: GPL-2.0-or-later
# Cron daemon restart example
TCID=cron01
TST_COUNT=1
. test.sh
. daemonlib.sh
...
restart_daemon $CROND_DAEMON
...
tst_exit
-------------------------------------------------------------------------------
1.6 Access to the checkpoint interface
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The shell library provides an implementation of the checkpoint interface
compatible with the C version. All 'TST_CHECKPOINT_*' functions are available.
In order to initialize checkpoints '$TST_NEEDS_CHECKPOINTS' must be set to '1'
before the inclusion of 'tst_test.sh':
[source,sh]
-------------------------------------------------------------------------------
#!/bin/sh
TST_NEEDS_CHECKPOINTS=1
. tst_test.sh
-------------------------------------------------------------------------------
Since both the implementations are compatible, it's also possible to start
a child binary process from a shell test and synchronize with it. This process
must have checkpoints initialized by calling 'tst_reinit()'.
1.7 Parsing kernel .config
~~~~~~~~~~~~~~~~~~~~~~~~~~
The shell library provides an implementation of the kconfig parsing interface
compatible with the C version.
It's possible to pass kernel kconfig list for tst_require_kconfigs API with
'$TST_NEEDS_KCONFIGS'.
Optional '$TST_NEEDS_KCONFIGS_IFS' is used for splitting, default value is comma.
-------------------------------------------------------------------------------
#!/bin/sh
TST_NEEDS_KCONFIGS="CONFIG_EXT4_FS, CONFIG_QUOTACTL=y"
. tst_test.sh
-------------------------------------------------------------------------------
1.8 Skipping test based on system state
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Test can be skipped on various conditions: on enabled SecureBoot
('TST_SKIP_IN_SECUREBOOT=1'), lockdown ('TST_SKIP_IN_LOCKDOWN=1').
@@ -0,0 +1,77 @@
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
@@ -0,0 +1,412 @@
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
@@ -0,0 +1,68 @@
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.
+1 -1
View File
@@ -161,7 +161,7 @@ signal is SIGUSR1 then ltp-pan will behave as if \fI-y\fP had not been specified
.SH EXAMPLES
In practice, the ZOO environment variable is generally prefered over the
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.
+1 -1
View File
@@ -95,7 +95,7 @@ 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 the sscanf %i format.
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
+7 -9
View File
@@ -8,18 +8,16 @@ LTP namespaces helper tools
LTP provides helper tools for creating and working with namespaces. These are
located in ltp/testcases/kernel/containers/share directory and include:
* ns_create
* tst_ns_create
** creates a child process in the new specified namespace(s)
** child is then daemonized and is running in the background
** PID of the daemonized child process is printed on the stdout
** the new namespace(s) is(are) maintained by the daemonized child process
** namespace(s) can be removed by killing the daemonized process
* setns_check
** check for setns() availability, should be called before using ns_exec
* ns_exec
* tst_ns_exec
** enters the namespace(s) of a process specified by a PID
** then executes the indicated program inside that namespace(s)
* ns_ifmove
* tst_ns_ifmove
** moves a network interface to the namespace of a process specified by a PID
Purpose of these helper tools is the ability to execute test cases utilizing
@@ -36,18 +34,18 @@ The following code shows how test cases can use the namespaces helper tools:
-------------------------------------------------------------------------------
# Creates a new network and ipc namespace and stores the PID of the daemonized
# process inside that namespace into variable myns
myns=$(ns_create net,ipc)
myns=$(tst_ns_create net,ipc)
ip link add veth0 type veth peer name veth1
# Executes command 'ip a' inside the namespace specified by PID in myns variable
ns_exec $myns net,ipc ip a
tst_ns_exec $myns net,ipc ip a
1: lo: <LOOPBACK> mtu 65536 qdisc noop state DOWN
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
# Moves interface veth1 into the namespace specified by PID in myns variable
ns_ifmove veth1 $myns
ns_exec $myns net,ipc ip a
tst_ns_ifmove veth1 $myns
tst_ns_exec $myns net,ipc ip a
1: lo: <LOOPBACK> mtu 65536 qdisc noop state DOWN
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
6: veth1: <BROADCAST> mtu 1500 qdisc noop state DOWN qlen 1000
+1 -1
View File
@@ -19,7 +19,7 @@ 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 not configured, run ./configure in the root directory)
$(error 'METADATA_GENERATOR' not configured, run ./configure in the root directory)
else
$(error '$(METADATA_GENERATOR)' not supported, only asciidoctor and asciidoc are supported)
endif
+1 -1
View File
@@ -48,7 +48,7 @@ given test, as obviously we cannot run two tests that monopolize the same
resource. In some cases we would also need to partition the system resource
accordingly, e.g. if we have two memory stress tests running at the same time
we will need to cap each of these tests on half of the available memory, or
make sure that sum of the memory used by these two tests is not greater an
make sure that sum of the memory used by these two tests is not greater than
available memory.
Examples of such tests are:
+2 -1
View File
@@ -13,12 +13,13 @@ 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");
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
-2
View File
@@ -43,8 +43,6 @@ void setup(void);
#define NR_MSGQUEUES 16 /* MSGMNI as defined in linux/msg.h */
#define min(a, b) (((a) < (b)) ? (a) : (b))
typedef struct mbuf { /* a generic message structure */
long mtype;
char mtext[MSGSIZE + 1]; /* add 1 here so the message can be 1024 */
+34 -1
View File
@@ -38,6 +38,7 @@
#define BPF_OP(code) ((code) & 0xf0)
#define BPF_ADD 0x00
#define BPF_SUB 0x10
#define BPF_MUL 0x20
#define BPF_DIV 0x30
#define BPF_LSH 0x60
#define BPF_RSH 0x70
@@ -130,6 +131,12 @@ enum bpf_map_type {
BPF_MAP_TYPE_QUEUE,
BPF_MAP_TYPE_STACK,
BPF_MAP_TYPE_SK_STORAGE,
BPF_MAP_TYPE_DEVMAP_HASH,
BPF_MAP_TYPE_STRUCT_OPS,
BPF_MAP_TYPE_RINGBUF,
BPF_MAP_TYPE_INODE_STORAGE,
BPF_MAP_TYPE_TASK_STORAGE,
BPF_MAP_TYPE_BLOOM_FILTER,
};
enum bpf_prog_type {
@@ -428,7 +435,33 @@ union bpf_attr {
FN(strtoul), \
FN(sk_storage_get), \
FN(sk_storage_delete), \
FN(send_signal),
FN(send_signal), \
FN(tcp_gen_syncookie), \
FN(skb_output), \
FN(probe_read_user), \
FN(probe_read_kernel), \
FN(probe_read_user_str), \
FN(probe_read_kernel_str), \
FN(tcp_send_ack), \
FN(send_signal_thread), \
FN(jiffies64), \
FN(read_branch_records), \
FN(get_ns_current_pid_tgid), \
FN(xdp_output), \
FN(get_netns_cookie), \
FN(get_current_ancestor_cgroup_id), \
FN(sk_assign), \
FN(ktime_get_boot_ns), \
FN(seq_printf), \
FN(seq_write), \
FN(sk_cgroup_id), \
FN(sk_ancestor_cgroup_id), \
FN(ringbuf_output), \
FN(ringbuf_reserve), \
FN(ringbuf_submit), \
FN(ringbuf_discard), \
FN(ringbuf_query), \
FN(csum_level),
/* integer value in 'imm' field of BPF_CALL instruction selects which helper
* function eBPF program intends to call
+4
View File
@@ -24,6 +24,10 @@
# define CAP_NET_RAW 13
#endif
#ifndef CAP_IPC_LOCK
# define CAP_IPC_LOCK 14
#endif
#ifndef CAP_SYS_CHROOT
# define CAP_SYS_CHROOT 18
#endif
+13
View File
@@ -25,4 +25,17 @@ static inline int close_range(unsigned int fd, unsigned int max_fd,
return tst_syscall(__NR_close_range, fd, max_fd, flags);
}
# endif
static inline void close_range_supported_by_kernel(void)
{
long ret;
if ((tst_kvercmp(5, 9, 0)) < 0) {
/* Check if the syscall is backported on an older kernel */
ret = syscall(__NR_close_range, 1, 0, 0);
if (ret == -1 && errno == ENOSYS)
tst_brk(TCONF, "Test not supported on kernel version < v5.9");
}
}
#endif /* LAPI_CLOSE_RANGE_H__ */
-5
View File
@@ -63,11 +63,6 @@ static inline int possibly_unsupported(clock_t clock)
}
}
static inline int have_cputime_timers(void)
{
return tst_kvercmp(2, 6, 12) >= 0;
}
#include "lapi/syscalls.h"
#include <time.h>
+30
View File
@@ -0,0 +1,30 @@
// SPDX-License-Identifier: GPL-2.0-or-later
#if !(defined(__i386__) || defined(__x86_64__))
# error "cpuid.h should only be included on x86"
#endif
#ifdef HAVE_CPUID_H
# include <cpuid.h>
#endif
#ifndef LAPI_CPUID_H__
#define LAPI_CPUID_H__
/*
* gcc cpuid.h provides __cpuid_count() since v4.4.
* Clang/LLVM cpuid.h provides __cpuid_count() since v3.4.0.
*
* Provide local define for tests needing __cpuid_count() because
* ltp needs to work in older environments that do not yet
* have __cpuid_count().
*/
#ifndef __cpuid_count
#define __cpuid_count(level, count, a, b, c, d) ({ \
__asm__ __volatile__ ("cpuid\n\t" \
: "=a" (a), "=b" (b), "=c" (c), "=d" (d) \
: "0" (level), "2" (count)); \
})
#endif
#endif /* LAPI_CPUID_H__ */
+22
View File
@@ -0,0 +1,22 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Copyright (c) 2023 FUJITSU LIMITED. All rights reserved.
* Copyright (c) Linux Test Project, 2003-2023
* Author: Yang Xu <xuyang2018.jy@fujitsu.com>
*/
#ifndef FACCESSAT2_H
#define FACCESSAT2_H
#include "tst_test.h"
#include "config.h"
#include "lapi/syscalls.h"
#ifndef HAVE_FACCESSAT2
int faccessat2(int dirfd, const char *pathname, int mode, int flags)
{
return tst_syscall(__NR_faccessat2, dirfd, pathname, mode, flags);
}
#endif
#endif /* FACCESSAT2_H */
+2 -8
View File
@@ -36,19 +36,13 @@
#if !defined(HAVE_FALLOCATE)
# ifdef __TEST_H__
# define TST_SYSCALL_WRAPPER ltp_syscall
# else
# define TST_SYSCALL_WRAPPER tst_syscall
# endif /* __TEST_H__ */
static inline long fallocate(int fd, int mode, loff_t offset, loff_t len)
{
/* Deal with 32bit ABIs that have 64bit syscalls. */
# if LTP_USE_64_ABI
return TST_SYSCALL_WRAPPER(__NR_fallocate, fd, mode, offset, len);
return tst_syscall(__NR_fallocate, fd, mode, offset, len);
# else
return (long)TST_SYSCALL_WRAPPER(__NR_fallocate, fd, mode,
return (long)tst_syscall(__NR_fallocate, fd, mode,
__LONG_LONG_PAIR((off_t) (offset >> 32),
(off_t) offset),
__LONG_LONG_PAIR((off_t) (len >> 32),
+211
View File
@@ -0,0 +1,211 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
/*
* Copyright (c) 2012-2022 Linux Test Project. All Rights Reserved.
* Author: Jan Kara, November 2013
*/
#ifndef LAPI_FANOTIFY_H__
#define LAPI_FANOTIFY_H__
#include "config.h"
#include <sys/fanotify.h>
#include <linux/types.h>
#ifndef FAN_REPORT_TID
#define FAN_REPORT_TID 0x00000100
#endif
#ifndef FAN_REPORT_FID
#define FAN_REPORT_FID 0x00000200
#endif
#ifndef FAN_REPORT_DIR_FID
#define FAN_REPORT_DIR_FID 0x00000400
#endif
#ifndef FAN_REPORT_NAME
#define FAN_REPORT_NAME 0x00000800
#define FAN_REPORT_DFID_NAME (FAN_REPORT_DIR_FID | FAN_REPORT_NAME)
#endif
#ifndef FAN_REPORT_PIDFD
#define FAN_REPORT_PIDFD 0x00000080
#endif
#ifndef FAN_REPORT_TARGET_FID
#define FAN_REPORT_TARGET_FID 0x00001000
#define FAN_REPORT_DFID_NAME_TARGET (FAN_REPORT_DFID_NAME | \
FAN_REPORT_FID | FAN_REPORT_TARGET_FID)
#endif
/* Non-uapi convenience macros */
#ifndef FAN_REPORT_DFID_NAME_FID
#define FAN_REPORT_DFID_NAME_FID (FAN_REPORT_DFID_NAME | FAN_REPORT_FID)
#endif
#ifndef FAN_REPORT_DFID_FID
#define FAN_REPORT_DFID_FID (FAN_REPORT_DIR_FID | FAN_REPORT_FID)
#endif
#ifndef FAN_MARK_INODE
#define FAN_MARK_INODE 0
#endif
#ifndef FAN_MARK_FILESYSTEM
#define FAN_MARK_FILESYSTEM 0x00000100
#endif
#ifndef FAN_MARK_EVICTABLE
#define FAN_MARK_EVICTABLE 0x00000200
#endif
#ifndef FAN_MARK_IGNORE
#define FAN_MARK_IGNORE 0x00000400
#endif
#ifndef FAN_MARK_IGNORE_SURV
#define FAN_MARK_IGNORE_SURV (FAN_MARK_IGNORE | FAN_MARK_IGNORED_SURV_MODIFY)
#endif
/* Non-uapi convenience macros */
#ifndef FAN_MARK_IGNORED_SURV
#define FAN_MARK_IGNORED_SURV (FAN_MARK_IGNORED_MASK | \
FAN_MARK_IGNORED_SURV_MODIFY)
#endif
#ifndef FAN_MARK_PARENT
#define FAN_MARK_PARENT FAN_MARK_ONLYDIR
#endif
#ifndef FAN_MARK_SUBDIR
#define FAN_MARK_SUBDIR FAN_MARK_ONLYDIR
#endif
#ifndef FAN_MARK_TYPES
#define FAN_MARK_TYPES (FAN_MARK_INODE | FAN_MARK_MOUNT | FAN_MARK_FILESYSTEM)
#endif
/* New dirent event masks */
#ifndef FAN_ATTRIB
#define FAN_ATTRIB 0x00000004
#endif
#ifndef FAN_MOVED_FROM
#define FAN_MOVED_FROM 0x00000040
#endif
#ifndef FAN_MOVED_TO
#define FAN_MOVED_TO 0x00000080
#endif
#ifndef FAN_CREATE
#define FAN_CREATE 0x00000100
#endif
#ifndef FAN_DELETE
#define FAN_DELETE 0x00000200
#endif
#ifndef FAN_DELETE_SELF
#define FAN_DELETE_SELF 0x00000400
#endif
#ifndef FAN_MOVE_SELF
#define FAN_MOVE_SELF 0x00000800
#endif
#ifndef FAN_MOVE
#define FAN_MOVE (FAN_MOVED_FROM | FAN_MOVED_TO)
#endif
#ifndef FAN_OPEN_EXEC
#define FAN_OPEN_EXEC 0x00001000
#endif
#ifndef FAN_OPEN_EXEC_PERM
#define FAN_OPEN_EXEC_PERM 0x00040000
#endif
#ifndef FAN_FS_ERROR
#define FAN_FS_ERROR 0x00008000
#endif
#ifndef FAN_RENAME
#define FAN_RENAME 0x10000000
#endif
/* Additional error status codes that can be returned to userspace */
#ifndef FAN_NOPIDFD
#define FAN_NOPIDFD -1
#endif
#ifndef FAN_EPIDFD
#define FAN_EPIDFD -2
#endif
/* Flags required for unprivileged user group */
#define FANOTIFY_REQUIRED_USER_INIT_FLAGS (FAN_REPORT_FID)
/*
* FAN_ALL_PERM_EVENTS has been deprecated, so any new permission events
* are not to be added to it. To cover the instance where a new permission
* event is defined, we create a new macro that is to include all
* permission events. Any new permission events should be added to this
* macro.
*/
#define LTP_ALL_PERM_EVENTS (FAN_OPEN_PERM | FAN_OPEN_EXEC_PERM | \
FAN_ACCESS_PERM)
struct fanotify_group_type {
unsigned int flag;
const char *name;
};
struct fanotify_mark_type {
unsigned int flag;
const char *name;
};
#ifndef __kernel_fsid_t
typedef struct {
int val[2];
} lapi_fsid_t;
#define __kernel_fsid_t lapi_fsid_t
#endif /* __kernel_fsid_t */
#ifndef FAN_EVENT_INFO_TYPE_FID
#define FAN_EVENT_INFO_TYPE_FID 1
#endif
#ifndef FAN_EVENT_INFO_TYPE_DFID_NAME
#define FAN_EVENT_INFO_TYPE_DFID_NAME 2
#endif
#ifndef FAN_EVENT_INFO_TYPE_DFID
#define FAN_EVENT_INFO_TYPE_DFID 3
#endif
#ifndef FAN_EVENT_INFO_TYPE_PIDFD
#define FAN_EVENT_INFO_TYPE_PIDFD 4
#endif
#ifndef FAN_EVENT_INFO_TYPE_ERROR
#define FAN_EVENT_INFO_TYPE_ERROR 5
#endif
#ifndef FAN_EVENT_INFO_TYPE_OLD_DFID_NAME
#define FAN_EVENT_INFO_TYPE_OLD_DFID_NAME 10
#endif
#ifndef FAN_EVENT_INFO_TYPE_NEW_DFID_NAME
#define FAN_EVENT_INFO_TYPE_NEW_DFID_NAME 12
#endif
#ifndef HAVE_STRUCT_FANOTIFY_EVENT_INFO_HEADER
struct fanotify_event_info_header {
uint8_t info_type;
uint8_t pad;
uint16_t len;
};
#endif /* HAVE_STRUCT_FANOTIFY_EVENT_INFO_HEADER */
#ifndef HAVE_STRUCT_FANOTIFY_EVENT_INFO_FID
struct fanotify_event_info_fid {
struct fanotify_event_info_header hdr;
__kernel_fsid_t fsid;
unsigned char handle[0];
};
#endif /* HAVE_STRUCT_FANOTIFY_EVENT_INFO_FID */
#ifndef HAVE_STRUCT_FANOTIFY_EVENT_INFO_PIDFD
struct fanotify_event_info_pidfd {
struct fanotify_event_info_header hdr;
int32_t pidfd;
};
#endif /* HAVE_STRUCT_FANOTIFY_EVENT_INFO_PIDFD */
#ifndef HAVE_STRUCT_FANOTIFY_EVENT_INFO_ERROR
struct fanotify_event_info_error {
struct fanotify_event_info_header hdr;
__s32 error;
__u32 error_count;
};
#endif /* HAVE_STRUCT_FANOTIFY_EVENT_INFO_ERROR */
/* 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])
#else
# define FSID_VAL_MEMBER(fsid, i) (fsid.val[i])
#endif /* HAVE_STRUCT_FANOTIFY_EVENT_INFO_FID_FSID___VAL */
#endif /* LAPI_FANOTIFY_H__ */
+35 -13
View File
@@ -1,6 +1,7 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Copyright (c) 2014 Cyril Hrubis <chrubis@suse.cz>
* Copyright (c) Linux Test Project, 2014-2023
*/
#ifndef LAPI_FCNTL_H__
@@ -10,9 +11,7 @@
#include <fcntl.h>
#include <sys/socket.h>
#ifndef O_DIRECT
# define O_DIRECT 040000
#endif
/* NOTE: #define _GNU_SOURCE if you need O_DIRECT in tests */
#ifndef O_CLOEXEC
# define O_CLOEXEC 02000000
@@ -87,20 +86,40 @@
# define AT_FDCWD -100
#endif
#ifndef AT_SYMLINK_FOLLOW
# define AT_SYMLINK_FOLLOW 0x400
#endif
#ifndef AT_SYMLINK_NOFOLLOW
# define AT_SYMLINK_NOFOLLOW 0x100
#endif
#ifndef AT_EMPTY_PATH
# define AT_EMPTY_PATH 0x1000
# define AT_SYMLINK_NOFOLLOW 0x100
#endif
#ifndef AT_REMOVEDIR
# define AT_REMOVEDIR 0x200
# define AT_REMOVEDIR 0x200
#endif
#ifndef AT_SYMLINK_FOLLOW
# define AT_SYMLINK_FOLLOW 0x400
#endif
#ifndef AT_NO_AUTOMOUNT
# define AT_NO_AUTOMOUNT 0x800
#endif
#ifndef AT_EMPTY_PATH
# define AT_EMPTY_PATH 0x1000
#endif
#ifndef AT_STATX_SYNC_AS_STAT
# define AT_STATX_SYNC_AS_STAT 0x0000
#endif
#ifndef AT_STATX_FORCE_SYNC
# define AT_STATX_FORCE_SYNC 0x2000
#endif
#ifndef AT_STATX_DONT_SYNC
# define AT_STATX_DONT_SYNC 0x4000
#endif
#ifndef AT_STATX_SYNC_TYPE
# define AT_STATX_SYNC_TYPE 0x6000
#endif
#ifndef O_NOATIME
@@ -141,6 +160,9 @@
# define MAX_HANDLE_SZ 128
#endif
#define TST_OPEN_NEEDS_MODE(oflag) \
(((oflag) & O_CREAT) != 0 || ((oflag) & O_TMPFILE) == O_TMPFILE)
#ifndef HAVE_STRUCT_FILE_HANDLE
struct file_handle {
unsigned int handle_bytes;
+18 -11
View File
@@ -6,39 +6,46 @@
* Email: code@zilogic.com
*/
#ifdef HAVE_LINUX_FS_H
# include <linux/fs.h>
#ifndef LAPI_FS_H__
#define LAPI_FS_H__
#include "config.h"
#ifndef HAVE_MOUNT_SETATTR
# ifdef HAVE_LINUX_FS_H
# include <linux/fs.h>
# endif
#endif
#include <sys/user.h>
#include <limits.h>
#include "lapi/abisize.h"
#ifndef LAPI_FS_H__
#define LAPI_FS_H__
#ifndef FS_IOC_GETFLAGS
#define FS_IOC_GETFLAGS _IOR('f', 1, long)
# define FS_IOC_GETFLAGS _IOR('f', 1, long)
#endif
#ifndef FS_IOC_SETFLAGS
#define FS_IOC_SETFLAGS _IOW('f', 2, long)
# define FS_IOC_SETFLAGS _IOW('f', 2, long)
#endif
#ifndef FS_COMPR_FL
#define FS_COMPR_FL 0x00000004 /* Compress file */
# define FS_COMPR_FL 0x00000004 /* Compress file */
#endif
#ifndef FS_IMMUTABLE_FL
#define FS_IMMUTABLE_FL 0x00000010 /* Immutable file */
# define FS_IMMUTABLE_FL 0x00000010 /* Immutable file */
#endif
#ifndef FS_APPEND_FL
#define FS_APPEND_FL 0x00000020 /* writes to file may only append */
# define FS_APPEND_FL 0x00000020 /* writes to file may only append */
#endif
#ifndef FS_NODUMP_FL
#define FS_NODUMP_FL 0x00000040 /* do not dump file */
# define FS_NODUMP_FL 0x00000040 /* do not dump file */
#endif
#ifndef FS_VERITY_FL
# define FS_VERITY_FL 0x00100000 /* Verity protected inode */
#endif
/*
+56 -2
View File
@@ -1,5 +1,6 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Copyright (c) Linux Test Project, 2021-2022
* Copyright (c) 2020 Linaro Limited. All rights reserved.
* Author: Viresh Kumar <viresh.kumar@linaro.org>
*/
@@ -7,14 +8,58 @@
#ifndef LAPI_FSMOUNT_H__
#define LAPI_FSMOUNT_H__
#include <sys/mount.h>
#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
#endif
#include "config.h"
#include "lapi/fcntl.h"
#include "lapi/syscalls.h"
/*
* Mount attributes.
*/
#ifndef MOUNT_ATTR_RDONLY
# define MOUNT_ATTR_RDONLY 0x00000001 /* Mount read-only */
#endif
#ifndef MOUNT_ATTR_NOSUID
# define MOUNT_ATTR_NOSUID 0x00000002 /* Ignore suid and sgid bits */
#endif
#ifndef MOUNT_ATTR_NODEV
# define MOUNT_ATTR_NODEV 0x00000004 /* Disallow access to device special files */
#endif
#ifndef MOUNT_ATTR_NOEXEC
# define MOUNT_ATTR_NOEXEC 0x00000008 /* Disallow program execution */
#endif
#ifndef MOUNT_ATTR_NODIRATIME
# define MOUNT_ATTR_NODIRATIME 0x00000080 /* Do not update directory access times */
#endif
#ifndef MOUNT_ATTR_NOSYMFOLLOW
# define MOUNT_ATTR_NOSYMFOLLOW 0x00200000 /* Do not follow symlinks */
#endif
#ifndef ST_NOSYMFOLLOW
# define ST_NOSYMFOLLOW 0x2000 /* do not follow symlinks */
#endif
#ifndef HAVE_STRUCT_MOUNT_ATTR
/*
* mount_setattr()
*/
struct mount_attr {
uint64_t attr_set;
uint64_t attr_clr;
uint64_t propagation;
uint64_t userns_fd;
};
#endif
#ifndef HAVE_FSOPEN
static inline int fsopen(const char *fsname, unsigned int flags)
{
@@ -61,6 +106,15 @@ static inline int open_tree(int dirfd, const char *pathname, unsigned int flags)
}
#endif /* HAVE_OPEN_TREE */
#ifndef HAVE_MOUNT_SETATTR
static inline int mount_setattr(int dirfd, const char *from_pathname, unsigned int flags,
struct mount_attr *attr, size_t size)
{
return tst_syscall(__NR_mount_setattr, dirfd, from_pathname, flags,
attr, size);
}
#endif /* HAVE_MOUNT_SETATTR */
/*
* New headers added in kernel after 5.2 release, create them for old userspace.
*/
+39
View File
@@ -0,0 +1,39 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Copyright (c) 2022 FUJITSU LIMITED. All rights reserved.
* Author: Dai Shili <daisl.fnst@cn.fujitsu.com>
*/
#ifndef LAPI_FSVERITY_H__
#define LAPI_FSVERITY_H__
#include "config.h"
#include <stdint.h>
#include <sys/ioctl.h>
#ifdef HAVE_LINUX_FSVERITY_H
#include <linux/fsverity.h>
#endif
#ifndef FS_VERITY_HASH_ALG_SHA256
# define FS_VERITY_HASH_ALG_SHA256 1
#endif
#ifndef HAVE_STRUCT_FSVERITY_ENABLE_ARG
struct fsverity_enable_arg {
uint32_t version;
uint32_t hash_algorithm;
uint32_t block_size;
uint32_t salt_size;
uint64_t salt_ptr;
uint32_t sig_size;
uint32_t __reserved1;
uint64_t sig_ptr;
uint64_t __reserved2[11];
};
#endif
#ifndef FS_IOC_ENABLE_VERITY
# define FS_IOC_ENABLE_VERITY _IOW('f', 133, struct fsverity_enable_arg)
#endif
#endif
+180
View File
@@ -1,12 +1,14 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Copyright (c) 2015 Linux Test Project
* Copyright (C) 2021 SUSE LLC Andrea Cervesato <andrea.cervesato@suse.com>
*/
#ifndef LAPI_FUTEX_H__
#define LAPI_FUTEX_H__
#include <stdint.h>
#include "config.h"
typedef volatile uint32_t futex_t;
@@ -14,4 +16,182 @@ typedef volatile uint32_t futex_t;
#define SYS_futex SYS_futex_time64
#endif
#ifdef HAVE_LINUX_FUTEX_H
# include <linux/futex.h>
#else
#include <unistd.h>
#define FUTEX_WAIT 0
#define FUTEX_WAKE 1
#define FUTEX_FD 2
#define FUTEX_REQUEUE 3
#define FUTEX_CMP_REQUEUE 4
#define FUTEX_WAKE_OP 5
#define FUTEX_LOCK_PI 6
#define FUTEX_UNLOCK_PI 7
#define FUTEX_TRYLOCK_PI 8
#define FUTEX_WAIT_BITSET 9
#define FUTEX_WAKE_BITSET 10
#define FUTEX_WAIT_REQUEUE_PI 11
#define FUTEX_CMP_REQUEUE_PI 12
#define FUTEX_LOCK_PI2 13
#define FUTEX_PRIVATE_FLAG 128
#define FUTEX_CLOCK_REALTIME 256
#define FUTEX_CMD_MASK ~(FUTEX_PRIVATE_FLAG | FUTEX_CLOCK_REALTIME)
#define FUTEX_WAIT_PRIVATE (FUTEX_WAIT | FUTEX_PRIVATE_FLAG)
#define FUTEX_WAKE_PRIVATE (FUTEX_WAKE | FUTEX_PRIVATE_FLAG)
#define FUTEX_REQUEUE_PRIVATE (FUTEX_REQUEUE | FUTEX_PRIVATE_FLAG)
#define FUTEX_CMP_REQUEUE_PRIVATE (FUTEX_CMP_REQUEUE | FUTEX_PRIVATE_FLAG)
#define FUTEX_WAKE_OP_PRIVATE (FUTEX_WAKE_OP | FUTEX_PRIVATE_FLAG)
#define FUTEX_LOCK_PI_PRIVATE (FUTEX_LOCK_PI | FUTEX_PRIVATE_FLAG)
#define FUTEX_LOCK_PI2_PRIVATE (FUTEX_LOCK_PI2 | FUTEX_PRIVATE_FLAG)
#define FUTEX_UNLOCK_PI_PRIVATE (FUTEX_UNLOCK_PI | FUTEX_PRIVATE_FLAG)
#define FUTEX_TRYLOCK_PI_PRIVATE (FUTEX_TRYLOCK_PI | FUTEX_PRIVATE_FLAG)
#define FUTEX_WAIT_BITSET_PRIVATE (FUTEX_WAIT_BITSET | FUTEX_PRIVATE_FLAG)
#define FUTEX_WAKE_BITSET_PRIVATE (FUTEX_WAKE_BITSET | FUTEX_PRIVATE_FLAG)
#define FUTEX_WAIT_REQUEUE_PI_PRIVATE (FUTEX_WAIT_REQUEUE_PI | \
FUTEX_PRIVATE_FLAG)
#define FUTEX_CMP_REQUEUE_PI_PRIVATE (FUTEX_CMP_REQUEUE_PI | \
FUTEX_PRIVATE_FLAG)
/*
* Support for robust futexes: the kernel cleans up held futexes at
* thread exit time.
*/
/*
* Per-lock list entry - embedded in user-space locks, somewhere close
* to the futex field. (Note: user-space uses a double-linked list to
* achieve O(1) list add and remove, but the kernel only needs to know
* about the forward link)
*
* NOTE: this structure is part of the syscall ABI, and must not be
* changed.
*/
struct robust_list {
struct robust_list *next;
};
/*
* Per-thread list head:
*
* NOTE: this structure is part of the syscall ABI, and must only be
* changed if the change is first communicated with the glibc folks.
* (When an incompatible change is done, we'll increase the structure
* size, which glibc will detect)
*/
struct robust_list_head {
/*
* The head of the list. Points back to itself if empty:
*/
struct robust_list list;
/*
* This relative offset is set by user-space, it gives the kernel
* the relative position of the futex field to examine. This way
* we keep userspace flexible, to freely shape its data-structure,
* without hardcoding any particular offset into the kernel:
*/
long futex_offset;
/*
* The death of the thread may race with userspace setting
* up a lock's links. So to handle this race, userspace first
* sets this field to the address of the to-be-taken lock,
* then does the lock acquire, and then adds itself to the
* list, and then clears this field. Hence the kernel will
* always have full knowledge of all locks that the thread
* _might_ have taken. We check the owner TID in any case,
* so only truly owned locks will be handled.
*/
struct robust_list *list_op_pending;
};
/*
* Are there any waiters for this robust futex:
*/
#define FUTEX_WAITERS 0x80000000
/*
* The kernel signals via this bit that a thread holding a futex
* has exited without unlocking the futex. The kernel also does
* a FUTEX_WAKE on such futexes, after setting the bit, to wake
* up any possible waiters:
*/
#define FUTEX_OWNER_DIED 0x40000000
/*
* The rest of the robust-futex field is for the TID:
*/
#define FUTEX_TID_MASK 0x3fffffff
/*
* This limit protects against a deliberately circular list.
* (Not worth introducing an rlimit for it)
*/
#define ROBUST_LIST_LIMIT 2048
/*
* bitset with all bits set for the FUTEX_xxx_BITSET OPs to request a
* match of any bit.
*/
#define FUTEX_BITSET_MATCH_ANY 0xffffffff
#define FUTEX_OP_SET 0 /* *(int *)UADDR2 = OPARG; */
#define FUTEX_OP_ADD 1 /* *(int *)UADDR2 += OPARG; */
#define FUTEX_OP_OR 2 /* *(int *)UADDR2 |= OPARG; */
#define FUTEX_OP_ANDN 3 /* *(int *)UADDR2 &= ~OPARG; */
#define FUTEX_OP_XOR 4 /* *(int *)UADDR2 ^= OPARG; */
#define FUTEX_OP_OPARG_SHIFT 8 /* Use (1 << OPARG) instead of OPARG. */
#define FUTEX_OP_CMP_EQ 0 /* if (oldval == CMPARG) wake */
#define FUTEX_OP_CMP_NE 1 /* if (oldval != CMPARG) wake */
#define FUTEX_OP_CMP_LT 2 /* if (oldval < CMPARG) wake */
#define FUTEX_OP_CMP_LE 3 /* if (oldval <= CMPARG) wake */
#define FUTEX_OP_CMP_GT 4 /* if (oldval > CMPARG) wake */
#define FUTEX_OP_CMP_GE 5 /* if (oldval >= CMPARG) wake */
/* FUTEX_WAKE_OP will perform atomically
int oldval = *(int *)UADDR2;
*(int *)UADDR2 = oldval OP OPARG;
if (oldval CMP CMPARG)
wake UADDR2; */
#define FUTEX_OP(op, oparg, cmp, cmparg) \
(((op & 0xf) << 28) | ((cmp & 0xf) << 24) \
| ((oparg & 0xfff) << 12) | (cmparg & 0xfff))
#endif /* HAVE_LINUX_FUTEX_H */
#ifndef HAVE_STRUCT_FUTEX_WAITV
/*
* Flags to specify the bit length of the futex word for futex2 syscalls.
* Currently, only 32 is supported.
*/
#define FUTEX_32 2
/*
* Max numbers of elements in a futex_waitv array
*/
#define FUTEX_WAITV_MAX 128
/**
* struct futex_waitv - A waiter for vectorized wait
* @val: Expected value at uaddr
* @uaddr: User address to wait on
* @flags: Flags for this waiter
* @__reserved: Reserved member to preserve data alignment. Should be 0.
*/
struct futex_waitv {
uint64_t val;
uint64_t uaddr;
uint32_t flags;
uint32_t __reserved;
};
#endif /* HAVE_STRUCT_FUTEX_WAITV */
#endif /* LAPI_FUTEX_H__ */
+1 -13
View File
@@ -8,8 +8,8 @@
#define LAPI_INIT_MODULE_H__
#include "config.h"
#include "lapi/syscalls.h"
#include "tst_test.h"
#include "lapi/syscalls.h"
static inline int init_module(void *module_image, unsigned long len,
const char *param_values)
@@ -22,16 +22,4 @@ static inline int finit_module(int fd, const char *param_values, int flags)
return tst_syscall(__NR_finit_module, fd, param_values, flags);
}
static inline void finit_module_supported_by_kernel(void)
{
long ret;
if ((tst_kvercmp(3, 8, 0)) < 0) {
/* Check if the syscall is backported on an older kernel */
ret = syscall(__NR_finit_module, 0, "", 0);
if (ret == -1 && errno == ENOSYS)
tst_brk(TCONF, "Test not supported on kernel version < v3.8");
}
}
#endif /* LAPI_INIT_MODULE_H__ */
+10 -5
View File
@@ -297,13 +297,18 @@ static inline int io_uring_enter(int fd, unsigned int to_submit,
static inline void io_uring_setup_supported_by_kernel(void)
{
long ret;
if ((tst_kvercmp(5, 1, 0)) < 0) {
ret = syscall(__NR_io_uring_setup, NULL, 0);
if (ret != -1)
SAFE_CLOSE(ret);
else if (errno == ENOSYS)
ret = syscall(__NR_io_uring_setup, NULL, 0);
if (ret != -1) {
SAFE_CLOSE(ret);
return;
}
if (errno == ENOSYS) {
if ((tst_kvercmp(5, 1, 0)) < 0) {
tst_brk(TCONF,
"Test not supported on kernel version < v5.1");
}
tst_brk(TCONF, "CONFIG_IO_URING not set?");
}
}
+47
View File
@@ -0,0 +1,47 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
/*
* Copyright (c) 2019 Linus Walleij <linus.walleij@linaro.org>
*/
#ifndef LAPI_IOPRIO_H__
#define LAPI_IOPRIO_H__
#include "config.h"
#ifdef HAVE_LINUX_IOPRIO_H
# include <linux/ioprio.h>
#else
enum {
IOPRIO_CLASS_NONE = 0,
IOPRIO_CLASS_RT,
IOPRIO_CLASS_BE,
IOPRIO_CLASS_IDLE,
};
enum {
IOPRIO_WHO_PROCESS = 1,
IOPRIO_WHO_PGRP,
IOPRIO_WHO_USER,
};
# define IOPRIO_CLASS_SHIFT (13)
# define IOPRIO_PRIO_MASK ((1UL << IOPRIO_CLASS_SHIFT) - 1)
# define IOPRIO_PRIO_CLASS(data) ((data) >> IOPRIO_CLASS_SHIFT)
# define IOPRIO_PRIO_VALUE(class, data) (((class) << IOPRIO_CLASS_SHIFT) | data)
#endif
/* The RT and BE I/O priority classes have 8 priority levels 0..7 */
#ifdef IOPRIO_NR_LEVELS
# define IOPRIO_PRIO_NUM IOPRIO_NR_LEVELS
#else
# define IOPRIO_PRIO_NUM 8
#endif
#ifndef IOPRIO_PRIO_LEVEL
# define IOPRIO_PRIO_LEVEL(data) ((data) & IOPRIO_PRIO_MASK)
#endif
#endif /* LAPI_IOPRIO_H__ */
+14
View File
@@ -0,0 +1,14 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Copyright (c) 2022 Arm Ltd.
*/
#ifndef LAPI_IPC_H__
#define LAPI_IPC_H__
#include <sys/ipc.h>
#ifndef IPC_INFO
# define IPC_INFO 3
#endif
#endif /* LAPI_IPC_H__ */
+41
View File
@@ -0,0 +1,41 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Copyright (c) 2015 Cedric Hnyda <chnyda@suse.com>
*/
#ifndef LAPI_KCMP_H__
#define LAPI_KCMP_H__
#include <sys/types.h>
#include "config.h"
#include "lapi/syscalls.h"
#ifndef HAVE_ENUM_KCMP_TYPE
enum kcmp_type {
KCMP_FILE,
KCMP_VM,
KCMP_FILES,
KCMP_FS,
KCMP_SIGHAND,
KCMP_IO,
KCMP_SYSVSEM,
KCMP_TYPES,
};
#else
# include <linux/kcmp.h>
#endif
#ifndef HAVE_KCMP
static inline int kcmp(int pid1, int pid2, int type, int fd1, int fd2)
{
return tst_syscall(__NR_kcmp, pid1, pid2, type, fd1, fd2);
}
#endif
#endif /* LAPI_KCMP_H__ */
+4
View File
@@ -140,6 +140,10 @@ static inline key_serial_t keyctl_join_session_keyring(const char *name) {
# define KEYCTL_INVALIDATE 21
#endif
#ifndef KEYCTL_WATCH_KEY
# define KEYCTL_WATCH_KEY 32
#endif
/* key permissions */
#ifndef KEY_POS_VIEW
# define KEY_POS_VIEW 0x01000000
+1 -1
View File
@@ -13,7 +13,7 @@
#ifndef HAVE_MKDIRAT
static inline int mkdirat(int dirfd, const char *dirname, int mode)
{
return ltp_syscall(__NR_mkdirat, dirfd, dirname, mode);
return tst_syscall(__NR_mkdirat, dirfd, dirname, mode);
}
#endif
+13
View File
@@ -8,6 +8,11 @@
#define LAPI_MMAP_H__
#include "config.h"
#include <sys/mman.h>
#ifndef MAP_SHARED_VALIDATE
# define MAP_SHARED_VALIDATE 0x03
#endif
#ifndef MAP_HUGETLB
# define MAP_HUGETLB 0x40000
@@ -66,6 +71,14 @@
# define MADV_KEEPONFORK 19
#endif
#ifndef MADV_COLD
# define MADV_COLD 20
#endif
#ifndef MADV_PAGEOUT
# define MADV_PAGEOUT 21
#endif
#ifndef MAP_FIXED_NOREPLACE
#ifdef __alpha__
+13 -6
View File
@@ -1,33 +1,40 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Copyright (c) Linux Test Project, 2015-2022
* Copyright (c) 2015 Cui Bixuan <cuibixuan@huawei.com>
*/
#ifndef LAPI_MOUNT_H__
#define LAPI_MOUNT_H__
#include <sys/mount.h>
#ifndef MS_REC
#define MS_REC 16384
# define MS_REC 16384
#endif
#ifndef MS_PRIVATE
#define MS_PRIVATE (1<<18)
# define MS_PRIVATE (1<<18)
#endif
#ifndef MS_STRICTATIME
#define MS_STRICTATIME (1 << 24)
# define MS_STRICTATIME (1 << 24)
#endif
#ifndef MNT_DETACH
#define MNT_DETACH 2
# define MNT_DETACH 2
#endif
#ifndef MNT_EXPIRE
#define MNT_EXPIRE 4
# define MNT_EXPIRE 4
#endif
#ifndef UMOUNT_NOFOLLOW
#define UMOUNT_NOFOLLOW 8
# define UMOUNT_NOFOLLOW 8
#endif
#ifndef MS_NOSYMFOLLOW
# define MS_NOSYMFOLLOW 256
#endif
#endif /* LAPI_MOUNT_H__ */
+1 -1
View File
@@ -9,10 +9,10 @@
#include <sys/syscall.h>
#include "config.h"
#include "tst_test.h"
#include "lapi/syscalls.h"
#include "lapi/fcntl.h"
#include "tst_buffers.h"
#include "tst_test.h"
#ifndef HAVE_NAME_TO_HANDLE_AT
static inline int name_to_handle_at(int dfd, const char *pathname,
+61
View File
@@ -0,0 +1,61 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Copyright (c) 2022 FUJITSU LIMITED. All rights reserved.
* Author: Yang Xu <xuyang2018.jy@fujitsu.com>
*/
#ifndef LAPI_PIDFD_H__
#define LAPI_PIDFD_H__
#include <fcntl.h>
#ifdef HAVE_SYS_PIDFD_H
# include <sys/pidfd.h>
#endif
#include "config.h"
#include "lapi/syscalls.h"
#ifndef PIDFD_NONBLOCK
#define PIDFD_NONBLOCK O_NONBLOCK
#endif
static inline void pidfd_send_signal_supported(void)
{
/* allow the tests to fail early */
tst_syscall(__NR_pidfd_send_signal);
}
#ifndef HAVE_PIDFD_SEND_SIGNAL
static inline int pidfd_send_signal(int pidfd, int sig, siginfo_t *info,
unsigned int flags)
{
return tst_syscall(__NR_pidfd_send_signal, pidfd, sig, info, flags);
}
#endif
static inline void pidfd_open_supported(void)
{
/* allow the tests to fail early */
tst_syscall(__NR_pidfd_open);
}
#ifndef HAVE_PIDFD_OPEN
static inline int pidfd_open(pid_t pid, unsigned int flags)
{
return tst_syscall(__NR_pidfd_open, pid, flags);
}
#endif
static inline void pidfd_getfd_supported(void)
{
/* allow the tests to fail early */
tst_syscall(__NR_pidfd_getfd);
}
#ifndef HAVE_PIDFD_GETFD
static inline int pidfd_getfd(int pidfd, int targetfd, unsigned int flags)
{
return tst_syscall(__NR_pidfd_getfd, pidfd, targetfd, flags);
}
#endif
#endif /* LAPI_PIDFD_H__ */
+7
View File
@@ -19,6 +19,13 @@
# define PR_SET_SECCOMP 22
#endif
#ifndef PR_SET_TSC
# define PR_GET_TSC 25
# define PR_SET_TSC 26
# define PR_TSC_ENABLE 1
# define PR_TSC_SIGSEGV 2
#endif
#ifndef PR_SET_TIMERSLACK
# define PR_SET_TIMERSLACK 29
# define PR_GET_TIMERSLACK 30
+1 -1
View File
@@ -14,7 +14,7 @@
static inline int readlinkat(int dirfd, const char *pathname,
char *buf, size_t bufsiz)
{
return ltp_syscall(__NR_readlinkat, dirfd, pathname, buf, bufsiz);
return tst_syscall(__NR_readlinkat, dirfd, pathname, buf, bufsiz);
}
#endif
+1 -1
View File
@@ -15,7 +15,7 @@
static inline int renameat(int olddirfd, const char *oldpath, int newdirfd,
const char *newpath)
{
return ltp_syscall(__NR_renameat, olddirfd, oldpath, newdirfd,
return tst_syscall(__NR_renameat, olddirfd, oldpath, newdirfd,
newpath);
}
#endif
+2 -8
View File
@@ -157,12 +157,6 @@ __attribute__ ((optimize("Os"))) __attribute__((used)) restore_rt(void)
}
#endif
#ifdef TST_TEST_H__
# define TST_SYSCALL tst_syscall
#else
# define TST_SYSCALL ltp_syscall
#endif
/* This is a wrapper for __NR_rt_sigaction syscall.
* act/oact values of INVAL_SA_PTR is used to pass
* an invalid pointer to syscall(__NR_rt_sigaction)
@@ -218,11 +212,11 @@ static int ltp_rt_sigaction(int signum, const struct sigaction *act,
#ifdef __sparc__
ret = TST_SYSCALL(__NR_rt_sigaction, signum,
ret = tst_syscall(__NR_rt_sigaction, signum,
kact_p, koact_p,
stub, sigsetsize);
#else
ret = TST_SYSCALL(__NR_rt_sigaction, signum,
ret = tst_syscall(__NR_rt_sigaction, signum,
kact_p, koact_p,
sigsetsize);
#endif
+101 -5
View File
@@ -1,14 +1,19 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Copyright (c) 2015 Cui Bixuan <cuibixuan@huawei.com>
* Copyright (c) Linux Test Project, 2016-2022
*/
#ifndef LAPI_SCHED_H__
#define LAPI_SCHED_H__
#include "lapi/syscalls.h"
#include <sched.h>
#include <unistd.h>
#include <stdint.h>
#include <inttypes.h>
#include "config.h"
#include "lapi/syscalls.h"
#include "lapi/sched.h"
struct sched_attr {
uint32_t size;
@@ -40,20 +45,111 @@ static inline int sched_getattr(pid_t pid, struct sched_attr *attr,
return syscall(__NR_sched_getattr, pid, attr, size, flags);
}
#ifndef HAVE_CLONE3
struct clone_args {
uint64_t __attribute__((aligned(8))) flags;
uint64_t __attribute__((aligned(8))) pidfd;
uint64_t __attribute__((aligned(8))) child_tid;
uint64_t __attribute__((aligned(8))) parent_tid;
uint64_t __attribute__((aligned(8))) exit_signal;
uint64_t __attribute__((aligned(8))) stack;
uint64_t __attribute__((aligned(8))) stack_size;
uint64_t __attribute__((aligned(8))) tls;
uint64_t __attribute__((aligned(8))) set_tid;
uint64_t __attribute__((aligned(8))) set_tid_size;
uint64_t __attribute__((aligned(8))) cgroup;
};
struct clone_args_minimal {
uint64_t __attribute__((aligned(8))) flags;
uint64_t __attribute__((aligned(8))) pidfd;
uint64_t __attribute__((aligned(8))) child_tid;
uint64_t __attribute__((aligned(8))) parent_tid;
uint64_t __attribute__((aligned(8))) exit_signal;
uint64_t __attribute__((aligned(8))) stack;
uint64_t __attribute__((aligned(8))) stack_size;
uint64_t __attribute__((aligned(8))) tls;
};
static inline int clone3(struct clone_args *args, size_t size)
{
return tst_syscall(__NR_clone3, args, size);
}
#endif
static inline void clone3_supported_by_kernel(void)
{
if ((tst_kvercmp(5, 3, 0)) < 0) {
/* Check if the syscall is backported on an older kernel */
tst_syscall(__NR_clone3, NULL, 0);
}
}
#ifndef HAVE_GETCPU
static inline int getcpu(unsigned *cpu, unsigned *node)
{
return tst_syscall(__NR_getcpu, cpu, node, NULL);
}
#endif
#ifndef SCHED_DEADLINE
# define SCHED_DEADLINE 6
#endif
#ifndef CLONE_VM
#define CLONE_VM 0x00000100
# define CLONE_VM 0x00000100
#endif
#ifndef CLONE_FS
#define CLONE_FS 0x00000200
# define CLONE_FS 0x00000200
#endif
#ifndef CLONE_PIDFD
# define CLONE_PIDFD 0x00001000
#endif
#ifndef CLONE_NEWNS
# define CLONE_NEWNS 0x00020000
#endif
#ifndef CLONE_SYSVSEM
#define CLONE_SYSVSEM 0x00040000
# define CLONE_SYSVSEM 0x00040000
#endif
#ifndef CLONE_NEWCGROUP
# define CLONE_NEWCGROUP 0x02000000
#endif
#ifndef CLONE_NEWUTS
# define CLONE_NEWUTS 0x04000000
#endif
#ifndef CLONE_NEWIPC
# define CLONE_NEWIPC 0x08000000
#endif
#ifndef CLONE_NEWUSER
# define CLONE_NEWUSER 0x10000000
#endif
#ifndef CLONE_NEWPID
# define CLONE_NEWPID 0x20000000
#endif
#ifndef CLONE_NEWNET
# define CLONE_NEWNET 0x40000000
#endif
#ifndef CLONE_IO
#define CLONE_IO 0x80000000
# define CLONE_IO 0x80000000
#endif
#ifndef CLONE_NEWTIME
# define CLONE_NEWTIME 0x00000080
#endif
#ifndef CLONE_INTO_CGROUP
# define CLONE_INTO_CGROUP 0x200000000ULL
#endif
#endif /* LAPI_SCHED_H__ */
+4
View File
@@ -24,4 +24,8 @@ union semun {
# define SEM_STAT_ANY 20
#endif
#ifndef SEMMSL
# define SEMMSL 32000
#endif
#endif /* LAPI_SEM_H__ */
+11 -41
View File
@@ -10,7 +10,9 @@
#include <stdint.h>
#include <unistd.h>
#include <sys/stat.h>
#include "lapi/syscalls.h"
/*
* Timestamp structure for the timestamps in struct statx.
*
@@ -21,9 +23,7 @@
*
* __reserved is held in case we need a yet finer resolution.
*/
#if defined(HAVE_STRUCT_STATX_TIMESTAMP)
#include <sys/stat.h>
#else
#ifndef HAVE_STRUCT_STATX_TIMESTAMP
struct statx_timestamp {
int64_t tv_sec;
uint32_t tv_nsec;
@@ -67,9 +67,7 @@ struct statx_timestamp {
* will have values installed for compatibility purposes so that stat() and
* co. can be emulated in userspace.
*/
#if defined(HAVE_STRUCT_STATX)
#include <sys/stat.h>
#else
#ifndef HAVE_STRUCT_STATX
struct statx {
/* 0x00 */
uint32_t stx_mask;
@@ -102,7 +100,7 @@ struct statx {
};
#endif
#if !defined(HAVE_STATX)
#ifndef HAVE_STATX
/*
* statx: wrapper function of statx
@@ -180,8 +178,8 @@ static inline int statx(int dirfd, const char *pathname, unsigned int flags,
# define STATX_MNT_ID 0x00001000U
#endif
#ifndef STATX_ALL
# define STATX_ALL 0x00000fffU
#ifndef STATX_DIOALIGN
# define STATX_DIOALIGN 0x00002000U
#endif
#ifndef STATX__RESERVED
@@ -223,40 +221,12 @@ static inline int statx(int dirfd, const char *pathname, unsigned int flags,
# define STATX_ATTR_AUTOMOUNT 0x00001000
#endif
#ifndef AT_SYMLINK_NOFOLLOW
# define AT_SYMLINK_NOFOLLOW 0x100
#ifndef STATX_ATTR_MOUNT_ROOT
# define STATX_ATTR_MOUNT_ROOT 0x00002000
#endif
#ifndef AT_REMOVEDIR
# define AT_REMOVEDIR 0x200
#endif
#ifndef AT_SYMLINK_FOLLOW
# define AT_SYMLINK_FOLLOW 0x400
#endif
#ifndef AT_NO_AUTOMOUNT
# define AT_NO_AUTOMOUNT 0x800
#endif
#ifndef AT_EMPTY_PATH
# define AT_EMPTY_PATH 0x1000
#endif
#ifndef AT_STATX_SYNC_TYPE
# define AT_STATX_SYNC_TYPE 0x6000
#endif
#ifndef AT_STATX_SYNC_AS_STAT
# define AT_STATX_SYNC_AS_STAT 0x0000
#endif
#ifndef AT_STATX_FORCE_SYNC
# define AT_STATX_FORCE_SYNC 0x2000
#endif
#ifndef AT_STATX_DONT_SYNC
# define AT_STATX_DONT_SYNC 0x4000
#ifndef STATX_ATTR_VERITY
# define STATX_ATTR_VERITY 0x00100000
#endif
#endif /* LAPI_STAT_H__ */
+7 -13
View File
@@ -13,12 +13,6 @@
#if !defined(HAVE_SYNC_FILE_RANGE)
#ifdef TST_TEST_H__
# define TST_SYSCALL tst_syscall
#else
# define TST_SYSCALL ltp_syscall
#endif
/*****************************************************************************
* Wraper function to call sync_file_range system call
******************************************************************************/
@@ -28,29 +22,29 @@ static inline long sync_file_range(int fd, off64_t offset, off64_t nbytes,
#if (defined(__arm__) || defined(__powerpc__) || defined(__powerpc64__))
# ifdef TST_ABI32
# if __BYTE_ORDER == __BIG_ENDIAN
return TST_SYSCALL(__NR_sync_file_range2, fd, flags,
return tst_syscall(__NR_sync_file_range2, fd, flags,
(int)(offset >> 32), (int)offset, (int)(nbytes >> 32),
(int)nbytes);
# elif __BYTE_ORDER == __LITTLE_ENDIAN
return TST_SYSCALL(__NR_sync_file_range2, fd, flags, (int)offset,
return tst_syscall(__NR_sync_file_range2, fd, flags, (int)offset,
(int)(offset >> 32), nbytes, (int)(nbytes >> 32));
# endif
# else
return TST_SYSCALL(__NR_sync_file_range2, fd, flags, offset, nbytes);
return tst_syscall(__NR_sync_file_range2, fd, flags, offset, nbytes);
# endif
#elif (defined(__s390__) || defined(__s390x__)) && defined(TST_ABI32)
return TST_SYSCALL(__NR_sync_file_range, fd, (int)(offset >> 32),
return tst_syscall(__NR_sync_file_range, fd, (int)(offset >> 32),
(int)offset, (int)(nbytes >> 32), (int)nbytes, flags);
#elif defined(__mips__) && defined(TST_ABI32)
# if __BYTE_ORDER == __BIG_ENDIAN
return TST_SYSCALL(__NR_sync_file_range, fd, 0, (int)(offset >> 32),
return tst_syscall(__NR_sync_file_range, fd, 0, (int)(offset >> 32),
(int)offset, (int)(nbytes >> 32), (int)nbytes, flags);
# elif __BYTE_ORDER == __LITTLE_ENDIAN
return TST_SYSCALL(__NR_sync_file_range, fd, 0, (int)offset,
return tst_syscall(__NR_sync_file_range, fd, 0, (int)offset,
(int)(offset >> 32), (int)nbytes, (int)(nbytes >> 32), flags);
# endif
#else
return TST_SYSCALL(__NR_sync_file_range, fd, offset, nbytes, flags);
return tst_syscall(__NR_sync_file_range, fd, offset, nbytes, flags);
#endif
}
#endif
+2
View File
@@ -293,6 +293,8 @@ clone3 435
close_range 436
openat2 437
pidfd_getfd 438
faccessat2 439
epoll_pwait2 441
quotactl_fd 443
futex_waitv 449
_sysctl 1078
+2
View File
@@ -313,5 +313,7 @@ clone3 435
close_range 436
openat2 437
pidfd_getfd 438
faccessat2 439
epoll_pwait2 441
quotactl_fd 443
futex_waitv 449
+2
View File
@@ -391,5 +391,7 @@ clone3 (__NR_SYSCALL_BASE+435)
close_range (__NR_SYSCALL_BASE+436)
openat2 (__NR_SYSCALL_BASE+437)
pidfd_getfd (__NR_SYSCALL_BASE+438)
faccessat2 (__NR_SYSCALL_BASE+439)
epoll_pwait2 (__NR_SYSCALL_BASE+441)
quotactl_fd (__NR_SYSCALL_BASE+443)
futex_waitv (__NR_SYSCALL_BASE+449)
+2
View File
@@ -40,5 +40,7 @@ fsmount 432
fspick 433
pidfd_open 434
close_range 436
faccessat2 439
epoll_pwait2 441
quotactl_fd 443
futex_waitv 449
+2
View File
@@ -427,5 +427,7 @@ clone3 435
close_range 436
openat2 437
pidfd_getfd 438
faccessat2 439
epoll_pwait2 441
quotactl_fd 443
futex_waitv 449
+2
View File
@@ -340,5 +340,7 @@ pidfd_open 1458
close_range 1460
openat2 1461
pidfd_getfd 1462
faccessat2 1463
epoll_pwait2 1465
quotactl_fd 1467
futex_waitv 1473
+307
View File
@@ -0,0 +1,307 @@
io_setup 0
io_destroy 1
io_submit 2
io_cancel 3
io_getevents 4
setxattr 5
lsetxattr 6
fsetxattr 7
getxattr 8
lgetxattr 9
fgetxattr 10
listxattr 11
llistxattr 12
flistxattr 13
removexattr 14
lremovexattr 15
fremovexattr 16
getcwd 17
lookup_dcookie 18
eventfd2 19
epoll_create1 20
epoll_ctl 21
epoll_pwait 22
dup 23
dup3 24
fcntl 25
inotify_init1 26
inotify_add_watch 27
inotify_rm_watch 28
ioctl 29
ioprio_set 30
ioprio_get 31
flock 32
mknodat 33
mkdirat 34
unlinkat 35
symlinkat 36
linkat 37
renameat 38
umount2 39
mount 40
pivot_root 41
nfsservctl 42
statfs 43
fstatfs 44
truncate 45
ftruncate 46
fallocate 47
faccessat 48
chdir 49
fchdir 50
chroot 51
fchmod 52
fchmodat 53
fchownat 54
fchown 55
openat 56
close 57
vhangup 58
pipe2 59
quotactl 60
getdents64 61
lseek 62
read 63
write 64
readv 65
writev 66
pread64 67
pwrite64 68
preadv 69
pwritev 70
sendfile 71
pselect6 72
ppoll 73
signalfd4 74
vmsplice 75
splice 76
tee 77
readlinkat 78
fstatat 79
fstat 80
sync 81
fsync 82
fdatasync 83
sync_file_range2 84
sync_file_range 84
timerfd_create 85
timerfd_settime 86
timerfd_gettime 87
utimensat 88
acct 89
capget 90
capset 91
personality 92
exit 93
exit_group 94
waitid 95
set_tid_address 96
unshare 97
futex 98
set_robust_list 99
get_robust_list 100
nanosleep 101
getitimer 102
setitimer 103
kexec_load 104
init_module 105
delete_module 106
timer_create 107
timer_gettime 108
timer_getoverrun 109
timer_settime 110
timer_delete 111
clock_settime 112
clock_gettime 113
clock_getres 114
clock_nanosleep 115
syslog 116
ptrace 117
sched_setparam 118
sched_setscheduler 119
sched_getscheduler 120
sched_getparam 121
sched_setaffinity 122
sched_getaffinity 123
sched_yield 124
sched_get_priority_max 125
sched_get_priority_min 126
sched_rr_get_interval 127
restart_syscall 128
kill 129
tkill 130
tgkill 131
sigaltstack 132
rt_sigsuspend 133
rt_sigaction 134
rt_sigprocmask 135
rt_sigpending 136
rt_sigtimedwait 137
rt_sigqueueinfo 138
rt_sigreturn 139
setpriority 140
getpriority 141
reboot 142
setregid 143
setgid 144
setreuid 145
setuid 146
setresuid 147
getresuid 148
setresgid 149
getresgid 150
setfsuid 151
setfsgid 152
times 153
setpgid 154
getpgid 155
getsid 156
setsid 157
getgroups 158
setgroups 159
uname 160
sethostname 161
setdomainname 162
getrlimit 163
setrlimit 164
getrusage 165
umask 166
prctl 167
getcpu 168
gettimeofday 169
settimeofday 170
adjtimex 171
getpid 172
getppid 173
getuid 174
geteuid 175
getgid 176
getegid 177
gettid 178
sysinfo 179
mq_open 180
mq_unlink 181
mq_timedsend 182
mq_timedreceive 183
mq_notify 184
mq_getsetattr 185
msgget 186
msgctl 187
msgrcv 188
msgsnd 189
semget 190
semctl 191
semtimedop 192
semop 193
shmget 194
shmctl 195
shmat 196
shmdt 197
socket 198
socketpair 199
bind 200
listen 201
accept 202
connect 203
getsockname 204
getpeername 205
sendto 206
recvfrom 207
setsockopt 208
getsockopt 209
shutdown 210
sendmsg 211
recvmsg 212
readahead 213
brk 214
munmap 215
mremap 216
add_key 217
request_key 218
keyctl 219
clone 220
execve 221
mmap 222
fadvise64 223
swapon 224
swapoff 225
mprotect 226
msync 227
mlock 228
munlock 229
mlockall 230
munlockall 231
mincore 232
madvise 233
remap_file_pages 234
mbind 235
get_mempolicy 236
set_mempolicy 237
migrate_pages 238
move_pages 239
rt_tgsigqueueinfo 240
perf_event_open 241
accept4 242
recvmmsg 243
wait4 260
prlimit64 261
fanotify_init 262
fanotify_mark 263
name_to_handle_at 264
open_by_handle_at 265
clock_adjtime 266
syncfs 267
setns 268
sendmmsg 269
process_vm_readv 270
process_vm_writev 271
kcmp 272
finit_module 273
sched_setattr 274
sched_getattr 275
renameat2 276
seccomp 277
getrandom 278
memfd_create 279
bpf 280
execveat 281
userfaultfd 282
membarrier 283
mlock2 284
copy_file_range 285
preadv2 286
pwritev2 287
pkey_mprotect 288
pkey_alloc 289
pkey_free 290
statx 291
io_pgetevents 292
rseq 293
kexec_file_load 294
pidfd_send_signal 424
io_uring_setup 425
io_uring_enter 426
io_uring_register 427
open_tree 428
move_mount 429
fsopen 430
fsconfig 431
fsmount 432
fspick 433
pidfd_open 434
clone3 435
close_range 436
openat2 437
pidfd_getfd 438
faccessat2 439
process_madvise 440
epoll_pwait2 441
mount_setattr 442
quotactl_fd 443
landlock_create_ruleset 444
landlock_add_rule 445
landlock_restrict_self 446
memfd_secret 447
process_mrelease 448
futex_waitv 449
set_mempolicy_home_node 450
+1
View File
@@ -370,3 +370,4 @@ process_madvise 6440
epoll_pwait2 6441
mount_setattr 6442
quotactl_fd 6443
futex_waitv 6449
+1
View File
@@ -346,3 +346,4 @@ process_madvise 5440
epoll_pwait2 5441
mount_setattr 5442
quotactl_fd 5443
futex_waitv 5449
+1
View File
@@ -416,3 +416,4 @@ process_madvise 4440
epoll_pwait2 4441
mount_setattr 4442
quotactl_fd 4443
futex_waitv 4449
+1
View File
@@ -4,6 +4,7 @@ arm
hppa
i386
ia64
loongarch
mips_n32
mips_n64
mips_o32
+2
View File
@@ -420,5 +420,7 @@ clone3 435
close_range 436
openat2 437
pidfd_getfd 438
faccessat2 439
epoll_pwait2 441
quotactl_fd 443
futex_waitv 449
+2
View File
@@ -420,5 +420,7 @@ clone3 435
close_range 436
openat2 437
pidfd_getfd 438
faccessat2 439
epoll_pwait2 441
quotactl_fd 443
futex_waitv 449
+12 -16
View File
@@ -35,24 +35,20 @@ cat << EOF > "${output_pid}"
#include <asm/unistd.h>
#include "cleanup.c"
#define ltp_syscall(NR, ...) ({ \\
int __ret; \\
if (NR == __LTP__NR_INVALID_SYSCALL) { \\
errno = ENOSYS; \\
__ret = -1; \\
} else { \\
__ret = syscall(NR, ##__VA_ARGS__); \\
} \\
if (__ret == -1 && errno == ENOSYS) { \\
tst_brkm(TCONF, CLEANUP, \\
"syscall(%d) " #NR " not supported on your arch", \\
NR); \\
} \\
__ret; \\
#ifdef TST_TEST_H__
#define TST_SYSCALL_BRK__(NR, SNR) ({ \\
tst_brk(TCONF, \\
"syscall(%d) " SNR " not supported on your arch", NR); \\
})
#else
#define TST_SYSCALL_BRK__(NR, SNR) ({ \\
tst_brkm(TCONF, CLEANUP, \\
"syscall(%d) " SNR " not supported on your arch", NR); \\
})
#endif
#define tst_syscall(NR, ...) ({ \\
int tst_ret; \\
intptr_t tst_ret; \\
if (NR == __LTP__NR_INVALID_SYSCALL) { \\
errno = ENOSYS; \\
tst_ret = -1; \\
@@ -60,7 +56,7 @@ cat << EOF > "${output_pid}"
tst_ret = syscall(NR, ##__VA_ARGS__); \\
} \\
if (tst_ret == -1 && errno == ENOSYS) { \\
tst_brk(TCONF, "syscall(%d) " #NR " not supported", NR); \\
TST_SYSCALL_BRK__(NR, #NR); \\
} \\
tst_ret; \\
})
+2
View File
@@ -407,5 +407,7 @@ clone3 435
close_range 436
openat2 437
pidfd_getfd 438
faccessat2 439
epoll_pwait2 441
quotactl_fd 443
futex_waitv 449
+2
View File
@@ -355,5 +355,7 @@ clone3 435
close_range 436
openat2 437
pidfd_getfd 438
faccessat2 439
epoll_pwait2 441
quotactl_fd 443
futex_waitv 449
+2
View File
@@ -401,5 +401,7 @@ pidfd_open 434
close_range 436
openat2 437
pidfd_getfd 438
faccessat2 439
epoll_pwait2 441
quotactl_fd 443
futex_waitv 449
+2
View File
@@ -406,5 +406,7 @@ pidfd_open 434
close_range 436
openat2 437
pidfd_getfd 438
faccessat2 439
epoll_pwait2 441
quotactl_fd 443
futex_waitv 449
+2
View File
@@ -371,5 +371,7 @@ pidfd_open 434
close_range 436
openat2 437
pidfd_getfd 438
faccessat2 439
epoll_pwait2 441
quotactl_fd 443
futex_waitv 449
+2
View File
@@ -348,8 +348,10 @@ clone3 435
close_range 436
openat2 437
pidfd_getfd 438
faccessat2 439
epoll_pwait2 441
quotactl_fd 443
futex_waitv 449
rt_sigaction 512
rt_sigreturn 513
ioctl 514
+3 -3
View File
@@ -18,7 +18,7 @@
#if !defined(HAVE_TIMERFD_CREATE)
static inline int timerfd_create(int clockid, int flags)
{
return ltp_syscall(__NR_timerfd_create, clockid, flags);
return tst_syscall(__NR_timerfd_create, clockid, flags);
}
#endif
@@ -27,7 +27,7 @@ static inline int timerfd_settime(int fd, int flags,
const struct itimerspec *new_value,
struct itimerspec *old_value)
{
return ltp_syscall(__NR_timerfd_settime, fd, flags, new_value,
return tst_syscall(__NR_timerfd_settime, fd, flags, new_value,
old_value);
}
#endif
@@ -35,7 +35,7 @@ static inline int timerfd_settime(int fd, int flags,
#if !defined(HAVE_TIMERFD_SETTIME)
static inline int timerfd_gettime(int fd, struct itimerspec *curr_value)
{
return ltp_syscall(__NR_timerfd_gettime, fd, curr_value);
return tst_syscall(__NR_timerfd_gettime, fd, curr_value);
}
#endif
+190
View File
@@ -0,0 +1,190 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Copyright (C) 2007 Davide Libenzi <davidel@xmailserver.org>
* Copyright (C) 2015,2022 Red Hat, Inc.
*
* Mostly copied/adapted from <linux/userfaultfd.h>
*/
#ifndef LAPI_USERFAULTFD_H__
#define LAPI_USERFAULTFD_H__
#include <unistd.h>
#include <sys/types.h>
#include "lapi/syscalls.h"
#ifdef HAVE_LINUX_USERFAULTFD_H
#include <linux/userfaultfd.h>
#endif
/* userfaultfd support was added in v4.1 */
#ifndef UFFD_API
#define UFFD_API ((__u64)0xAA)
/*
* Valid ioctl command number range with this API is from 0x00 to
* 0x3F. UFFDIO_API is the fixed number, everything else can be
* changed by implementing a different UFFD_API. If sticking to the
* same UFFD_API more ioctl can be added and userland will be aware of
* which ioctl the running kernel implements through the ioctl command
* bitmask written by the UFFDIO_API.
*/
#define _UFFDIO_REGISTER (0x00)
#define _UFFDIO_UNREGISTER (0x01)
#define _UFFDIO_WAKE (0x02)
#define _UFFDIO_COPY (0x03)
#define _UFFDIO_ZEROPAGE (0x04)
#define _UFFDIO_API (0x3F)
/* userfaultfd ioctl ids */
#define UFFDIO 0xAA
#define UFFDIO_API _IOWR(UFFDIO, _UFFDIO_API, \
struct uffdio_api)
#define UFFDIO_REGISTER _IOWR(UFFDIO, _UFFDIO_REGISTER, \
struct uffdio_register)
#define UFFDIO_UNREGISTER _IOR(UFFDIO, _UFFDIO_UNREGISTER, \
struct uffdio_range)
#define UFFDIO_WAKE _IOR(UFFDIO, _UFFDIO_WAKE, \
struct uffdio_range)
#define UFFDIO_COPY _IOWR(UFFDIO, _UFFDIO_COPY, \
struct uffdio_copy)
#define UFFDIO_ZEROPAGE _IOWR(UFFDIO, _UFFDIO_ZEROPAGE, \
struct uffdio_zeropage)
/* read() structure */
struct uffd_msg {
__u8 event;
__u8 reserved1;
__u16 reserved2;
__u32 reserved3;
union {
struct {
__u64 flags;
__u64 address;
} pagefault;
struct {
/* unused reserved fields */
__u64 reserved1;
__u64 reserved2;
__u64 reserved3;
} reserved;
} arg;
} __packed;
/*
* Start at 0x12 and not at 0 to be more strict against bugs.
*/
#define UFFD_EVENT_PAGEFAULT 0x12
/* flags for UFFD_EVENT_PAGEFAULT */
#define UFFD_PAGEFAULT_FLAG_WRITE (1<<0) /* If this was a write fault */
#define UFFD_PAGEFAULT_FLAG_WP (1<<1) /* If reason is VM_UFFD_WP */
struct uffdio_api {
/* userland asks for an API number and the features to enable */
__u64 api;
/*
* Kernel answers below with the all available features for
* the API, this notifies userland of which events and/or
* which flags for each event are enabled in the current
* kernel.
*
* Note: UFFD_EVENT_PAGEFAULT and UFFD_PAGEFAULT_FLAG_WRITE
* are to be considered implicitly always enabled in all kernels as
* long as the uffdio_api.api requested matches UFFD_API.
*/
__u64 features;
__u64 ioctls;
};
struct uffdio_range {
__u64 start;
__u64 len;
};
struct uffdio_register {
struct uffdio_range range;
#define UFFDIO_REGISTER_MODE_MISSING ((__u64)1<<0)
#define UFFDIO_REGISTER_MODE_WP ((__u64)1<<1)
__u64 mode;
/*
* kernel answers which ioctl commands are available for the
* range, keep at the end as the last 8 bytes aren't read.
*/
__u64 ioctls;
};
struct uffdio_copy {
__u64 dst;
__u64 src;
__u64 len;
/*
* There will be a wrprotection flag later that allows to map
* pages wrprotected on the fly. And such a flag will be
* available if the wrprotection ioctl are implemented for the
* range according to the uffdio_register.ioctls.
*/
#define UFFDIO_COPY_MODE_DONTWAKE ((__u64)1<<0)
__u64 mode;
/*
* "copy" is written by the ioctl and must be at the end: the
* copy_from_user will not read the last 8 bytes.
*/
__s64 copy;
};
struct uffdio_zeropage {
struct uffdio_range range;
#define UFFDIO_ZEROPAGE_MODE_DONTWAKE ((__u64)1<<0)
__u64 mode;
/*
* "zeropage" is written by the ioctl and must be at the end:
* the copy_from_user will not read the last 8 bytes.
*/
__s64 zeropage;
};
#endif /* UFFD_API */
/* UFFD_USER_MODE_ONLY was added in v5.11 */
#ifndef UFFD_USER_MODE_ONLY
#define UFFD_USER_MODE_ONLY 1
#endif /* UFFD_USER_MODE_ONLY */
/* UFFD_PAGEFAULT_FLAG_MINOR and UFFDIO_CONTINUE were added in v5.13 */
#ifndef UFFD_PAGEFAULT_FLAG_MINOR
#define UFFD_FEATURE_MINOR_HUGETLBFS (1<<9)
#define UFFDIO_REGISTER_MODE_MINOR ((__u64)1<<2)
#define _UFFDIO_CONTINUE (0x07)
#define UFFDIO_CONTINUE _IOWR(UFFDIO, _UFFDIO_CONTINUE, \
struct uffdio_continue)
struct uffdio_continue {
struct uffdio_range range;
#define UFFDIO_CONTINUE_MODE_DONTWAKE ((__u64)1<<0)
__u64 mode;
/*
* Fields below here are written by the ioctl and must be at the end:
* the copy_from_user will not read past here.
*/
__s64 mapped;
};
#endif /* UFFD_PAGEFAULT_FLAG_MINOR */
/* UFFD_FEATURE_MINOR_SHMEM was added in v5.14 */
#ifndef UFFD_FEATURE_MINOR_SHMEM
#define UFFD_FEATURE_MINOR_SHMEM (1<<10)
#endif /* UFFD_FEATURE_MINOR_SHMEM */
#endif /* LAPI_USERFAULTFD_H__ */
+112
View File
@@ -0,0 +1,112 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Copyright (C) 2021 SUSE LLC Andrea Cervesato <andrea.cervesato@suse.com>
*
* This file is created to resolve conflicts between user space and kernel
* space fctnl.h declaration. linux/watch_queue.h is not handled, since
* user space fcntl.h redefines kernel space structures.
*/
#ifndef LAPI_WATCH_QUEUE_H__
#define LAPI_WATCH_QUEUE_H__
#include <stdint.h>
#include "lapi/ioctl.h"
#include "lapi/fcntl.h"
#define O_NOTIFICATION_PIPE O_EXCL /* Parameter to pipe2() selecting notification pipe */
#define IOC_WATCH_QUEUE_SET_SIZE _IO('W', 0x60) /* Set the size in pages */
#define IOC_WATCH_QUEUE_SET_FILTER _IO('W', 0x61) /* Set the filter */
enum watch_notification_type {
WATCH_TYPE_META = 0, /* Special record */
WATCH_TYPE_KEY_NOTIFY = 1, /* Key change event notification */
WATCH_TYPE__NR = 2
};
enum watch_meta_notification_subtype {
WATCH_META_REMOVAL_NOTIFICATION = 0, /* Watched object was removed */
WATCH_META_LOSS_NOTIFICATION = 1, /* Data loss occurred */
};
/*
* Notification record header. This is aligned to 64-bits so that subclasses
* can contain __u64 fields.
*/
struct watch_notification {
uint32_t type:24; /* enum watch_notification_type */
uint32_t subtype:8; /* Type-specific subtype (filterable) */
uint32_t info;
#define WATCH_INFO_LENGTH 0x0000007f /* Length of record */
#define WATCH_INFO_LENGTH__SHIFT 0
#define WATCH_INFO_ID 0x0000ff00 /* ID of watchpoint */
#define WATCH_INFO_ID__SHIFT 8
#define WATCH_INFO_TYPE_INFO 0xffff0000 /* Type-specific info */
#define WATCH_INFO_TYPE_INFO__SHIFT 16
#define WATCH_INFO_FLAG_0 0x00010000 /* Type-specific info, flag bit 0 */
#define WATCH_INFO_FLAG_1 0x00020000 /* ... */
#define WATCH_INFO_FLAG_2 0x00040000
#define WATCH_INFO_FLAG_3 0x00080000
#define WATCH_INFO_FLAG_4 0x00100000
#define WATCH_INFO_FLAG_5 0x00200000
#define WATCH_INFO_FLAG_6 0x00400000
#define WATCH_INFO_FLAG_7 0x00800000
};
/*
* Notification filtering rules (IOC_WATCH_QUEUE_SET_FILTER).
*/
struct watch_notification_type_filter {
uint32_t type; /* Type to apply filter to */
uint32_t info_filter; /* Filter on watch_notification::info */
uint32_t info_mask; /* Mask of relevant bits in info_filter */
uint32_t subtype_filter[8]; /* Bitmask of subtypes to filter on */
};
struct watch_notification_filter {
uint32_t nr_filters; /* Number of filters */
uint32_t __reserved; /* Must be 0 */
struct watch_notification_type_filter filters[];
};
/*
* Extended watch removal notification. This is used optionally if the type
* wants to indicate an identifier for the object being watched, if there is
* such. This can be distinguished by the length.
*
* type -> WATCH_TYPE_META
* subtype -> WATCH_META_REMOVAL_NOTIFICATION
*/
struct watch_notification_removal {
struct watch_notification watch;
uint64_t id; /* Type-dependent identifier */
};
/*
* Type of key/keyring change notification.
*/
enum key_notification_subtype {
NOTIFY_KEY_INSTANTIATED = 0, /* Key was instantiated (aux is error code) */
NOTIFY_KEY_UPDATED = 1, /* Key was updated */
NOTIFY_KEY_LINKED = 2, /* Key (aux) was added to watched keyring */
NOTIFY_KEY_UNLINKED = 3, /* Key (aux) was removed from watched keyring */
NOTIFY_KEY_CLEARED = 4, /* Keyring was cleared */
NOTIFY_KEY_REVOKED = 5, /* Key was revoked */
NOTIFY_KEY_INVALIDATED = 6, /* Key was invalidated */
NOTIFY_KEY_SETATTR = 7, /* Key's attributes got changed */
};
/*
* Key/keyring notification record.
* - watch.type = WATCH_TYPE_KEY_NOTIFY
* - watch.subtype = enum key_notification_type
*/
struct key_notification {
struct watch_notification watch;
uint32_t key_id; /* The key/keyring affected */
uint32_t aux; /* Per-type auxiliary data */
};
#endif /* LAPI_WATCH_QUEUE_H__ */
+2 -1
View File
@@ -31,7 +31,6 @@
#define MSGSIZE 1024
#define MSGTYPE 1
#define NR_MSGQUEUES 16
#define min(a, b) (((a) < (b)) ? (a) : (b))
#define SEM_RD 0400
#define SEM_ALT 0200
@@ -54,6 +53,8 @@ int get_used_sysvipc(const char *file, const int lineno, const char *sysvipc_fil
get_used_sysvipc(__FILE__, __LINE__, "/proc/sysvipc/msg")
#define GET_USED_SEGMENTS() \
get_used_sysvipc(__FILE__, __LINE__, "/proc/sysvipc/shm")
#define GET_USED_ARRAYS() \
get_used_sysvipc(__FILE__, __LINE__, "/proc/sysvipc/sem")
void *probe_free_addr(const char *file, const int lineno);
#define PROBE_FREE_ADDR() \
+7 -3
View File
@@ -27,7 +27,8 @@ AUTOHEADER ?= autoheader
AUTOMAKE ?= automake
AUTOCONFED_SUBDIRS = \
testcases/realtime
testcases/realtime \
testcases/open_posix_testsuite
# We want to run this every single time to ensure that all of the prereq files
# are there.
@@ -35,6 +36,10 @@ AUTOCONFED_SUBDIRS = \
testcases/realtime/configure:
$(MAKE) -C $(@D) autotools
.PHONY: testcases/open_posix_testsuite/configure
testcases/open_posix_testsuite/configure:
$(MAKE) -C $(@D) autotools
.PHONY: autotools
autotools: aclocal autoconf autoheader automake $(addsuffix /configure,$(AUTOCONFED_SUBDIRS))
@@ -94,8 +99,7 @@ AUTOGENERATED_FILES = \
include/mk/config.mk \
include/mk/features.mk \
lib/ltp.pc \
m4/Makefile \
execltp
m4/Makefile
distclean:: %: clean ac-distclean
for d in $(AUTOCONFED_SUBDIRS); do \
+5 -1
View File
@@ -80,8 +80,12 @@ OPT_CFLAGS ?= -O2 -fno-strict-aliasing -pipe
WCFLAGS ?= -Wall -W @GCC_WARN_OLDSTYLE@
STDCFLAGS ?= -std=gnu99
LDFLAGS += $(WLDFLAGS)
CFLAGS += $(DEBUG_CFLAGS) $(OPT_CFLAGS) $(WCFLAGS)
CFLAGS += $(DEBUG_CFLAGS) $(OPT_CFLAGS) $(WCFLAGS) $(STDCFLAGS)
LTP_CFLAGS_NOPIE := @LTP_CFLAGS_NOPIE@
ifeq ($(strip $(HOST_CFLAGS)),)
HOST_CFLAGS := $(CFLAGS)
+2
View File
@@ -32,6 +32,7 @@ ENV_POST_LOADED = 1
# poor software design if you need more than one search directory, and
# would suggest creating a general purpose static library to that end.
vpath %.c $(abs_srcdir)
vpath %.S $(abs_srcdir)
# For config.h, et all.
CPPFLAGS += -I$(top_srcdir)/include -I$(top_builddir)/include -I$(top_srcdir)/include/old/
@@ -91,6 +92,7 @@ endif
CHECK_TARGETS ?= $(addprefix check-,$(notdir $(patsubst %.c,%,$(sort $(wildcard $(abs_srcdir)/*.c)))))
CHECK_TARGETS := $(filter-out $(addprefix check-, $(FILTER_OUT_MAKE_TARGETS)), $(CHECK_TARGETS))
CHECK_HEADER_TARGETS ?= $(addprefix check-,$(notdir $(sort $(wildcard $(abs_srcdir)/*.h))))
CHECK ?= $(abs_top_srcdir)/tools/sparse/sparse-ltp
CHECK_NOFLAGS ?= $(abs_top_srcdir)/scripts/checkpatch.pl -f --no-tree --terse --no-summary --ignore CONST_STRUCT,VOLATILE,SPLIT_STRING
SHELL_CHECK ?= $(abs_top_srcdir)/scripts/checkbashisms.pl --force --extra
+3
View File
@@ -52,3 +52,6 @@ WITH_REALTIME_TESTSUITE := no
else
WITH_REALTIME_TESTSUITE := @WITH_REALTIME_TESTSUITE@
endif
# Enable testcases/kernel/kvm compile and install?
WITH_KVM_TESTSUITE := @WITH_KVM_TESTSUITE@
+1 -1
View File
@@ -110,6 +110,6 @@ $(INSTALL_FILES): | $(INSTALL_DEPS)
install: $(INSTALL_FILES)
$(CHECK_TARGETS): | $(CHECK_DEPS)
check: $(CHECK_TARGETS) $(SHELL_CHECK_TARGETS)
check: $(CHECK_HEADER_TARGETS) $(CHECK_TARGETS) $(SHELL_CHECK_TARGETS)
# vim: syntax=make
+17
View File
@@ -1,5 +1,13 @@
target_rel_dir := $(if $(cwd_rel_from_top),$(cwd_rel_from_top)/,)
%.o: %.S
ifdef VERBOSE
$(AS) $(ASFLAGS) -c -o $@ $<
else
@$(AS) $(ASFLAGS) -c -o $@ $<
@echo AS $(target_rel_dir)$@
endif
%.o: %.c
ifdef VERBOSE
$(CC) $(CPPFLAGS) $(CFLAGS) -c -o $@ $<
@@ -49,6 +57,15 @@ else
@-$(CHECK) $(CHECK_FLAGS) $(CPPFLAGS) $(CFLAGS) $<
endif
.PHONY: $(CHECK_HEADER_TARGETS)
$(CHECK_HEADER_TARGETS): check-%.h: %.h
ifdef VERBOSE
-$(CHECK_NOFLAGS) $<
else
@echo CHECK $(target_rel_dir)$<
@-$(CHECK_NOFLAGS) $<
endif
.PHONY: $(SHELL_CHECK_TARGETS)
$(SHELL_CHECK_TARGETS): check-%.sh: %.sh
ifdef VERBOSE
+5
View File
@@ -45,6 +45,11 @@ void tst_rmdir(void);
*/
char *tst_get_tmpdir(void);
/*
* Returns path to the test temporary directory root (TMPDIR).
*/
const char *tst_get_tmpdir_root(void);
/*
* Returns 1 if temp directory was created.
*/
+2 -1
View File
@@ -193,7 +193,8 @@ int self_exec(const char *argv0, const char *fmt, ...);
* @dev: path to a device
* @fs_type: filesystem type
* @fs_opts: NULL or NULL terminated array of mkfs options
* @extra_opt: extra mkfs option which is passed after the device name
* @extra_opts: NULL or NULL terminated array of extra mkfs options which are
* passed after the device name.
*/
#define tst_mkfs(cleanup, dev, fs_type, fs_opts, extra_opts) \
tst_mkfs_(__FILE__, __LINE__, cleanup, dev, fs_type, \
+17 -2
View File
@@ -24,6 +24,18 @@
#include <unistd.h>
#include <dirent.h>
/* supported values for safe_write() len_strict parameter */
enum safe_write_opts {
/* no length strictness, short writes are ok */
SAFE_WRITE_ANY = 0,
/* strict length, short writes raise TBROK */
SAFE_WRITE_ALL = 1,
/* retry/resume after short write */
SAFE_WRITE_RETRY = 2,
};
char* safe_basename(const char *file, const int lineno,
void (*cleanup_fn)(void), char *path);
@@ -111,8 +123,8 @@ int safe_symlink(const char *file, const int lineno,
const char *newpath);
ssize_t safe_write(const char *file, const int lineno,
void (cleanup_fn)(void), char len_strict, int fildes,
const void *buf, size_t nbyte);
void (cleanup_fn)(void), enum safe_write_opts len_strict,
int fildes, const void *buf, size_t nbyte);
long safe_strtol(const char *file, const int lineno,
void (cleanup_fn)(void), char *str, long min, long max);
@@ -121,6 +133,9 @@ unsigned long safe_strtoul(const char *file, const int lineno,
void (cleanup_fn)(void),
char *str, unsigned long min, unsigned long max);
float safe_strtof(const char *file, const int lineno,
void (cleanup_fn)(void), char *str, float min, float max);
long safe_sysconf(const char *file, const int lineno,
void (cleanup_fn)(void), int name);
+3
View File
@@ -73,6 +73,9 @@ int safe_getsockname(const char *file, const int lineno,
int safe_gethostname(const char *file, const int lineno,
char *name, size_t size);
int safe_sethostname(const char *file, const int lineno,
const char *name, size_t size);
int tst_getsockport(const char *file, const int lineno, int sockfd);
unsigned short tst_get_unused_port(const char *file, const int lineno,
+11
View File
@@ -25,6 +25,11 @@ struct tst_buffers {
* Array of iov buffer sizes terminated by -1.
*/
int *iov_sizes;
/*
* If size and iov_sizes is NULL this is the string we want to strdup()
* into the buffer.
*/
char *str;
};
/*
@@ -46,6 +51,12 @@ char *tst_strdup(const char *str);
*/
void *tst_alloc(size_t size);
/*
* Printf into a guarded buffer.
*/
char *tst_aprintf(const char *fmt, ...)
__attribute__((format (printf, 1, 2)));
/*
* Allocates iovec structure including the buffers.
*

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