mirror of
https://github.com/openharmony/third_party_ltp.git
synced 2026-07-01 12:25:45 -04:00
+2
-24
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
@@ -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
|
||||
|
||||
@@ -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
|
||||
-------------
|
||||
|
||||
|
||||
@@ -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
@@ -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."
|
||||
|
||||
@@ -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
-3
@@ -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,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 \
|
||||
|
||||
@@ -37,7 +37,6 @@ $apt \
|
||||
libjson-perl \
|
||||
libkeyutils-dev \
|
||||
libkeyutils1 \
|
||||
libmm-dev \
|
||||
libmnl-dev \
|
||||
libnuma-dev \
|
||||
libnuma1 \
|
||||
|
||||
+1
-1
@@ -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
@@ -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}
|
||||
|
||||
|
||||
@@ -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
@@ -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");
|
||||
}
|
||||
}
|
||||
-------------------------------------------------------------------------------
|
||||
@@ -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
|
||||
-------------------------------------------------------------------------------
|
||||
@@ -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].
|
||||
@@ -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'.
|
||||
@@ -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'
|
||||
|================================================================================
|
||||
@@ -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
@@ -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.
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
@@ -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
@@ -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:
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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__ */
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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__ */
|
||||
@@ -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 */
|
||||
@@ -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),
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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.
|
||||
*/
|
||||
|
||||
@@ -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
|
||||
@@ -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__ */
|
||||
|
||||
@@ -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
@@ -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?");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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__ */
|
||||
@@ -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__ */
|
||||
@@ -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__ */
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
@@ -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__ */
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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__ */
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
@@ -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__ */
|
||||
|
||||
@@ -24,4 +24,8 @@ union semun {
|
||||
# define SEM_STAT_ANY 20
|
||||
#endif
|
||||
|
||||
#ifndef SEMMSL
|
||||
# define SEMMSL 32000
|
||||
#endif
|
||||
|
||||
#endif /* LAPI_SEM_H__ */
|
||||
|
||||
+11
-41
@@ -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__ */
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
@@ -370,3 +370,4 @@ process_madvise 6440
|
||||
epoll_pwait2 6441
|
||||
mount_setattr 6442
|
||||
quotactl_fd 6443
|
||||
futex_waitv 6449
|
||||
|
||||
@@ -346,3 +346,4 @@ process_madvise 5440
|
||||
epoll_pwait2 5441
|
||||
mount_setattr 5442
|
||||
quotactl_fd 5443
|
||||
futex_waitv 5449
|
||||
|
||||
@@ -416,3 +416,4 @@ process_madvise 4440
|
||||
epoll_pwait2 4441
|
||||
mount_setattr 4442
|
||||
quotactl_fd 4443
|
||||
futex_waitv 4449
|
||||
|
||||
@@ -4,6 +4,7 @@ arm
|
||||
hppa
|
||||
i386
|
||||
ia64
|
||||
loongarch
|
||||
mips_n32
|
||||
mips_n64
|
||||
mips_o32
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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; \\
|
||||
})
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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__ */
|
||||
@@ -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
@@ -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() \
|
||||
|
||||
@@ -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 \
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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@
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
@@ -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, \
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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
Reference in New Issue
Block a user