aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEdward Liaw <edliaw@google.com>2024-02-16 18:21:39 +0000
committerEdward Liaw <edliaw@google.com>2024-02-29 00:08:11 +0000
commit1470d306139c8cef017d97095952c47c7b06c2a8 (patch)
treef74b010ad8edb89b855ae0e48ebdaa0a4a997fbd
parentb1db0711a7e2c2f97b6606f31bff0d3ae2182d97 (diff)
parent68737d20556d37364c95776044b1119c0912a36a (diff)
downloadltp-1470d306139c8cef017d97095952c47c7b06c2a8.tar.gz
Merge tag '20240129'
Update LTP to 20240129 release. Bug: 327505050 Test: N/A Change-Id: I119e0b87d1c07c98fe6e4f63c6afd8ba01ff8372 Signed-off-by: Edward Liaw <edliaw@google.com>
-rw-r--r--.dockerignore1
-rw-r--r--.github/workflows/ci.yml19
-rw-r--r--.github/workflows/wiki-mirror.yml2
-rw-r--r--Containerfile35
-rw-r--r--INSTALL2
-rw-r--r--README.md50
-rw-r--r--VERSION2
-rwxr-xr-xci/alpine-runtime.sh18
-rwxr-xr-xci/alpine.sh4
-rwxr-xr-xci/debian.cross-compile.sh4
-rwxr-xr-xci/debian.i386.sh4
-rwxr-xr-xci/debian.minimal.sh4
-rwxr-xr-xci/debian.sh4
-rwxr-xr-xci/fedora.sh4
l---------ci/quay.io.sh (renamed from ci/centos.sh)0
-rwxr-xr-xci/tumbleweed-runtime.sh15
-rwxr-xr-xci/tumbleweed.sh4
-rw-r--r--configure.ac8
-rw-r--r--doc/Build-System.asciidoc (renamed from doc/Build-System.rest)2
-rw-r--r--doc/C-Test-API.asciidoc10
-rw-r--r--doc/C-Test-Case-Tutorial.asciidoc2
-rw-r--r--doc/C-Test-Network-API.asciidoc207
-rw-r--r--doc/Contact-Info.asciidoc28
-rw-r--r--doc/LTP-Library-API-Writing-Guidelines.asciidoc2
-rw-r--r--doc/LTP-Release-Procedure.asciidoc13
-rw-r--r--doc/Maintainer-Patch-Review-Checklist.asciidoc5
-rw-r--r--doc/Supported-kernel,-libc,-toolchain-versions.asciidoc7
-rw-r--r--doc/Test-Writing-Guidelines.asciidoc12
-rw-r--r--doc/User-Guidelines.asciidoc9
-rw-r--r--doc/ltp-run-files.txt96
-rw-r--r--include/lapi/capability.h4
-rw-r--r--include/lapi/fanotify.h5
-rw-r--r--include/lapi/fcntl.h4
-rw-r--r--include/lapi/fsmount.h9
-rw-r--r--include/lapi/io_uring.h3
-rw-r--r--include/lapi/mkdirat.h20
-rw-r--r--include/lapi/nf_tables.h19
-rw-r--r--include/lapi/readlinkat.h21
-rw-r--r--include/lapi/renameat.h23
-rw-r--r--include/lapi/socket.h4
-rw-r--r--include/lapi/tcp.h4
-rw-r--r--include/lapi/uinput.h15
-rw-r--r--include/mk/config.mk.in2
-rw-r--r--include/old/usctest.h12
-rw-r--r--include/safe_file_ops_fn.h2
-rw-r--r--include/tst_ansi_color.h3
-rw-r--r--include/tst_clone.h4
-rw-r--r--include/tst_common.h2
-rw-r--r--include/tst_crypto.h69
-rw-r--r--include/tst_fd.h61
-rw-r--r--include/tst_fs.h10
-rw-r--r--include/tst_kconfig.h8
-rw-r--r--include/tst_memutils.h2
-rw-r--r--include/tst_netdevice.h8
-rw-r--r--include/tst_netlink.h195
-rw-r--r--include/tst_pid.h8
-rw-r--r--include/tst_res_flags.h1
-rw-r--r--include/tst_rtnetlink.h108
-rw-r--r--include/tst_safe_macros.h9
-rw-r--r--include/tst_test.h6
-rw-r--r--include/tst_test_macros.h81
-rw-r--r--lib/README.md28
-rw-r--r--lib/cloner.c39
-rw-r--r--lib/newlib_tests/.gitignore1
-rwxr-xr-xlib/newlib_tests/shell/tst_res_flags.sh24
-rw-r--r--lib/newlib_tests/test_macros02.c11
-rw-r--r--lib/newlib_tests/tst_res_flags.c44
-rw-r--r--lib/tlibio.c2
-rw-r--r--lib/tst_ansi_color.c3
-rw-r--r--lib/tst_cgroup.c1
-rw-r--r--lib/tst_crypto.c90
-rw-r--r--lib/tst_fd.c325
-rw-r--r--lib/tst_fill_file.c25
-rw-r--r--lib/tst_fill_fs.c4
-rw-r--r--lib/tst_fs_type.c2
-rw-r--r--lib/tst_ioctl.c23
-rw-r--r--lib/tst_kernel.c2
-rw-r--r--lib/tst_memutils.c2
-rw-r--r--lib/tst_netdevice.c115
-rw-r--r--lib/tst_netlink.c (renamed from lib/tst_rtnetlink.c)183
-rw-r--r--lib/tst_pid.c5
-rw-r--r--lib/tst_res.c5
-rw-r--r--lib/tst_safe_macros.c34
-rw-r--r--lib/tst_supported_fs_types.c12
-rw-r--r--lib/tst_test.c21
-rw-r--r--lib/tst_test_macros.c36
-rw-r--r--libs/libltpswap/libswap.c9
-rw-r--r--m4/ltp-ptrace.m426
-rwxr-xr-xrunltp13
-rw-r--r--runtest/connectors2
-rw-r--r--runtest/crashme3
-rw-r--r--runtest/cve2
-rw-r--r--runtest/fsx8
-rw-r--r--runtest/kernel_misc1
-rw-r--r--runtest/ltp-aiodio.part372
-rw-r--r--runtest/mm1
-rw-r--r--runtest/sched2
-rw-r--r--runtest/syscalls23
-rw-r--r--scenario_groups/default1
-rwxr-xr-xtestcases/commands/gzip/gzip_tests.sh3
-rwxr-xr-xtestcases/commands/mv/mv_tests.sh3
-rw-r--r--testcases/cve/Makefile2
-rw-r--r--testcases/cve/stack_clash.c4
-rw-r--r--testcases/cve/tcindex01.c37
-rw-r--r--testcases/kernel/containers/pidns/pidns05.c11
-rwxr-xr-xtestcases/kernel/controllers/cpuset/cpuset_funcs.sh3
-rwxr-xr-xtestcases/kernel/controllers/cpuset/cpuset_regression_test.sh18
-rw-r--r--testcases/kernel/controllers/freezer/vfork.c4
-rwxr-xr-xtestcases/kernel/controllers/memcg/functional/memcg_subgroup_charge.sh5
-rw-r--r--testcases/kernel/controllers/memcg/memcontrol02.c2
-rw-r--r--testcases/kernel/controllers/memcg/memcontrol03.c1
-rw-r--r--testcases/kernel/controllers/memcg/memcontrol04.c1
-rw-r--r--testcases/kernel/controllers/memcg/memcontrol_common.h5
-rw-r--r--testcases/kernel/controllers/memcg/regression/memcg_test_3.c6
-rw-r--r--testcases/kernel/crypto/crypto_user01.c58
-rw-r--r--testcases/kernel/crypto/crypto_user02.c17
-rw-r--r--testcases/kernel/crypto/pcrypt_aead01.c10
-rwxr-xr-xtestcases/kernel/device-drivers/zram/zram01.sh4
-rw-r--r--testcases/kernel/device-drivers/zram/zram03.c6
-rwxr-xr-xtestcases/kernel/device-drivers/zram/zram_lib.sh30
-rw-r--r--testcases/kernel/fs/doio/growfiles.c2
-rw-r--r--testcases/kernel/fs/doio/rwtest7
-rw-r--r--testcases/kernel/fs/fs_fill/fs_fill.c3
-rw-r--r--testcases/kernel/fs/fsx-linux/Makefile4
-rw-r--r--testcases/kernel/fs/fsx-linux/fsx-linux.c1501
-rwxr-xr-xtestcases/kernel/fs/fsx-linux/fsxtest50
-rwxr-xr-xtestcases/kernel/fs/fsx-linux/fsxtest0244
-rwxr-xr-xtestcases/kernel/fs/iso9660/isofs.sh49
-rw-r--r--testcases/kernel/fs/mongo/README37
-rw-r--r--testcases/kernel/fs/mongo/map5.c78
-rwxr-xr-xtestcases/kernel/fs/mongo/mongo.pl511
-rw-r--r--testcases/kernel/fs/mongo/mongo_compare.c224
-rw-r--r--testcases/kernel/fs/mongo/mongo_read.c57
-rw-r--r--testcases/kernel/fs/mongo/mongo_slinks.c98
-rw-r--r--testcases/kernel/fs/mongo/reiser_fract_tree.c502
-rwxr-xr-xtestcases/kernel/fs/mongo/run_mongo36
-rw-r--r--testcases/kernel/fs/mongo/summ.c27
-rwxr-xr-xtestcases/kernel/fs/mongo/test.sh109
-rwxr-xr-xtestcases/kernel/fs/quota_remount/quota_remount_test01.sh3
-rw-r--r--testcases/kernel/fs/scsi/ltpfs/Ltpfs.h71
-rw-r--r--testcases/kernel/fs/scsi/ltpfs/LtpfsCmds.c315
-rw-r--r--testcases/kernel/fs/scsi/ltpfs/Makefile30
-rw-r--r--testcases/kernel/fs/scsi/ltpfs/ltpfs.part14
-rw-r--r--testcases/kernel/fs/scsi/ltpfs/ltpfs.part23
-rw-r--r--testcases/kernel/fs/scsi/ltpfs/ltpfs.part33
-rw-r--r--testcases/kernel/fs/scsi/ltpfs/ltpfs.part43
-rw-r--r--testcases/kernel/fs/scsi/ltpfs/ltpfs.part53
-rw-r--r--testcases/kernel/fs/scsi/ltpfs/ltpfs.part63
-rw-r--r--testcases/kernel/fs/scsi/ltpfs/ltpfs.part73
-rwxr-xr-xtestcases/kernel/fs/scsi/ltpfs/ltpfsio.sh154
-rw-r--r--testcases/kernel/fs/scsi/ltpfs/main.c647
-rw-r--r--testcases/kernel/fs/scsi/ltpscsi/Makefile47
-rw-r--r--testcases/kernel/fs/scsi/ltpscsi/llseek.c123
-rw-r--r--testcases/kernel/fs/scsi/ltpscsi/llseek.h10
-rwxr-xr-xtestcases/kernel/fs/scsi/ltpscsi/ltpfsscsi.sh111
-rw-r--r--testcases/kernel/fs/scsi/ltpscsi/scsimain.c7651
-rw-r--r--testcases/kernel/fs/scsi/ltpscsi/sg_err.c1379
-rw-r--r--testcases/kernel/fs/scsi/ltpscsi/sg_err.h162
-rw-r--r--testcases/kernel/fs/scsi/ltpscsi/sg_include.h42
-rw-r--r--testcases/kernel/input/input_helper.c28
-rw-r--r--testcases/kernel/io/direct_io/diotest4.c2
-rw-r--r--testcases/kernel/irq/irqbalance01.c9
-rw-r--r--testcases/kernel/mem/.gitignore1
-rw-r--r--testcases/kernel/mem/hugetlb/hugemmap/hugemmap06.c43
-rw-r--r--testcases/kernel/mem/hugetlb/hugemmap/hugemmap13.c9
-rw-r--r--testcases/kernel/mem/hugetlb/hugemmap/hugemmap20.c9
-rw-r--r--testcases/kernel/mem/hugetlb/hugemmap/hugemmap21.c4
-rw-r--r--testcases/kernel/mem/hugetlb/hugemmap/hugemmap23.c26
-rw-r--r--testcases/kernel/mem/hugetlb/hugemmap/hugemmap24.c2
-rw-r--r--testcases/kernel/mem/hugetlb/hugeshmctl/hugeshmctl01.c35
-rw-r--r--testcases/kernel/mem/ksm/ksm01.c2
-rw-r--r--testcases/kernel/mem/ksm/ksm02.c2
-rw-r--r--testcases/kernel/mem/ksm/ksm03.c2
-rw-r--r--testcases/kernel/mem/ksm/ksm04.c37
-rw-r--r--testcases/kernel/mem/ksm/ksm05.c3
-rw-r--r--testcases/kernel/mem/ksm/ksm06.c2
-rw-r--r--testcases/kernel/mem/ksm/ksm07.c114
-rw-r--r--testcases/kernel/mem/ksm/ksm_common.h28
-rw-r--r--testcases/kernel/mem/mmapstress/mmapstress01.c6
-rw-r--r--testcases/kernel/mem/oom/oom01.c29
-rw-r--r--testcases/kernel/mem/oom/oom02.c31
-rw-r--r--testcases/kernel/mem/oom/oom03.c28
-rw-r--r--testcases/kernel/mem/oom/oom04.c28
-rw-r--r--testcases/kernel/mem/oom/oom05.c29
-rw-r--r--testcases/kernel/mem/swapping/swapping01.c17
-rw-r--r--testcases/kernel/mem/tunable/overcommit_memory.c8
-rwxr-xr-xtestcases/kernel/mem/vma/vma05.sh5
-rw-r--r--testcases/kernel/pty/pty04.c14
-rw-r--r--testcases/kernel/sched/sysctl/.gitignore1
-rw-r--r--testcases/kernel/sched/sysctl/Makefile (renamed from testcases/kernel/syscalls/getdtablesize/Makefile)1
-rw-r--r--testcases/kernel/sched/sysctl/proc_sched_rt01.c113
-rwxr-xr-xtestcases/kernel/security/integrity/ima/tests/ima_tpm.sh3
-rw-r--r--testcases/kernel/syscalls/accept/.gitignore1
-rw-r--r--testcases/kernel/syscalls/accept/accept01.c8
-rw-r--r--testcases/kernel/syscalls/accept/accept03.c60
-rw-r--r--testcases/kernel/syscalls/acct/acct01.c11
-rw-r--r--testcases/kernel/syscalls/acct/acct02.c16
-rw-r--r--testcases/kernel/syscalls/acct/acct02_helper.c4
-rw-r--r--testcases/kernel/syscalls/adjtimex/adjtimex03.c2
-rw-r--r--testcases/kernel/syscalls/clock_adjtime/clock_adjtime.h3
-rw-r--r--testcases/kernel/syscalls/dup/dup06.c145
-rw-r--r--testcases/kernel/syscalls/dup/dup07.c173
-rw-r--r--testcases/kernel/syscalls/eventfd2/eventfd2.h5
-rw-r--r--testcases/kernel/syscalls/execve/execve04.c4
-rw-r--r--testcases/kernel/syscalls/execve/execve05.c27
-rw-r--r--testcases/kernel/syscalls/exit_group/Makefile2
-rw-r--r--testcases/kernel/syscalls/exit_group/exit_group01.c161
-rw-r--r--testcases/kernel/syscalls/fallocate/fallocate06.c2
-rw-r--r--testcases/kernel/syscalls/fanotify/fanotify.h202
-rw-r--r--testcases/kernel/syscalls/fanotify/fanotify01.c16
-rw-r--r--testcases/kernel/syscalls/fanotify/fanotify03.c10
-rw-r--r--testcases/kernel/syscalls/fanotify/fanotify07.c3
-rw-r--r--testcases/kernel/syscalls/fanotify/fanotify09.c8
-rw-r--r--testcases/kernel/syscalls/fanotify/fanotify10.c18
-rw-r--r--testcases/kernel/syscalls/fanotify/fanotify11.c2
-rw-r--r--testcases/kernel/syscalls/fanotify/fanotify12.c5
-rw-r--r--testcases/kernel/syscalls/fanotify/fanotify13.c57
-rw-r--r--testcases/kernel/syscalls/fanotify/fanotify14.c22
-rw-r--r--testcases/kernel/syscalls/fanotify/fanotify15.c10
-rw-r--r--testcases/kernel/syscalls/fanotify/fanotify16.c27
-rw-r--r--testcases/kernel/syscalls/fanotify/fanotify20.c3
-rw-r--r--testcases/kernel/syscalls/fanotify/fanotify21.c3
-rw-r--r--testcases/kernel/syscalls/fanotify/fanotify23.c2
-rw-r--r--testcases/kernel/syscalls/fchmodat/.gitignore1
-rw-r--r--testcases/kernel/syscalls/fchmodat/fchmodat01.c108
-rw-r--r--testcases/kernel/syscalls/fchmodat/fchmodat02.c87
-rw-r--r--testcases/kernel/syscalls/fchownat/fchownat.h37
-rw-r--r--testcases/kernel/syscalls/fchownat/fchownat01.c1
-rw-r--r--testcases/kernel/syscalls/fchownat/fchownat02.c1
-rw-r--r--testcases/kernel/syscalls/fcntl/Makefile2
-rw-r--r--testcases/kernel/syscalls/fork/.gitignore4
-rw-r--r--testcases/kernel/syscalls/fork/fork04.c362
-rw-r--r--testcases/kernel/syscalls/fork/fork06.c106
-rw-r--r--testcases/kernel/syscalls/fork/fork10.c215
-rw-r--r--testcases/kernel/syscalls/fork/fork11.c97
-rw-r--r--testcases/kernel/syscalls/fork/fork12.c137
-rw-r--r--testcases/kernel/syscalls/fork/fork_procs.c55
-rw-r--r--testcases/kernel/syscalls/fsetxattr/fsetxattr01.c2
-rw-r--r--testcases/kernel/syscalls/fsetxattr/fsetxattr02.c34
-rw-r--r--testcases/kernel/syscalls/getcwd/getcwd01.c28
-rw-r--r--testcases/kernel/syscalls/getcwd/getcwd02.c12
-rw-r--r--testcases/kernel/syscalls/getcwd/getcwd03.c16
-rw-r--r--testcases/kernel/syscalls/getdtablesize/.gitignore1
-rw-r--r--testcases/kernel/syscalls/getdtablesize/getdtablesize01.c119
-rw-r--r--testcases/kernel/syscalls/getegid/getegid01.c95
-rw-r--r--testcases/kernel/syscalls/getegid/getegid02.c93
-rw-r--r--testcases/kernel/syscalls/getgroups/Makefile3
-rw-r--r--testcases/kernel/syscalls/getgroups/getgroups01.c5
-rw-r--r--testcases/kernel/syscalls/getgroups/getgroups03.c5
-rw-r--r--testcases/kernel/syscalls/getpid/getpid01.c16
-rw-r--r--testcases/kernel/syscalls/getppid/getppid01.c13
-rw-r--r--testcases/kernel/syscalls/getresgid/Makefile3
-rw-r--r--testcases/kernel/syscalls/getresgid/getresgid01.c5
-rw-r--r--testcases/kernel/syscalls/getresgid/getresgid02.c5
-rw-r--r--testcases/kernel/syscalls/getresgid/getresgid03.c5
-rw-r--r--testcases/kernel/syscalls/getresuid/Makefile3
-rw-r--r--testcases/kernel/syscalls/getresuid/getresuid01.c5
-rw-r--r--testcases/kernel/syscalls/getresuid/getresuid02.c5
-rw-r--r--testcases/kernel/syscalls/getresuid/getresuid03.c5
-rw-r--r--testcases/kernel/syscalls/getrlimit/getrlimit02.c13
-rw-r--r--testcases/kernel/syscalls/getsockopt/getsockopt02.c8
-rw-r--r--testcases/kernel/syscalls/gettid/.gitignore1
-rw-r--r--testcases/kernel/syscalls/gettid/Makefile4
-rw-r--r--testcases/kernel/syscalls/gettid/gettid01.c104
-rw-r--r--testcases/kernel/syscalls/gettid/gettid02.c66
-rw-r--r--testcases/kernel/syscalls/gettimeofday/gettimeofday01.c119
-rw-r--r--testcases/kernel/syscalls/gettimeofday/gettimeofday02.c12
-rw-r--r--testcases/kernel/syscalls/getxattr/getxattr02.c205
-rw-r--r--testcases/kernel/syscalls/getxattr/getxattr03.c133
-rw-r--r--testcases/kernel/syscalls/ioctl/ioctl02.c556
-rw-r--r--testcases/kernel/syscalls/ioctl/ioctl_loop06.c3
-rwxr-xr-xtestcases/kernel/syscalls/ioctl/test_ioctl2
-rw-r--r--testcases/kernel/syscalls/ipc/msgctl/msgctl06.c6
-rw-r--r--testcases/kernel/syscalls/ipc/shmget/shmget02.c7
-rw-r--r--testcases/kernel/syscalls/keyctl/keyctl01.c13
-rw-r--r--testcases/kernel/syscalls/keyctl/keyctl02.c40
-rw-r--r--testcases/kernel/syscalls/keyctl/keyctl03.c16
-rw-r--r--testcases/kernel/syscalls/keyctl/keyctl04.c5
-rw-r--r--testcases/kernel/syscalls/keyctl/keyctl05.c20
-rw-r--r--testcases/kernel/syscalls/keyctl/keyctl06.c14
-rw-r--r--testcases/kernel/syscalls/keyctl/keyctl07.c5
-rw-r--r--testcases/kernel/syscalls/keyctl/keyctl08.c10
-rw-r--r--testcases/kernel/syscalls/keyctl/keyctl09.c1
-rw-r--r--testcases/kernel/syscalls/lchown/Makefile3
-rw-r--r--testcases/kernel/syscalls/lchown/lchown01.c5
-rw-r--r--testcases/kernel/syscalls/lchown/lchown02.c5
-rw-r--r--testcases/kernel/syscalls/lchown/lchown03.c5
-rw-r--r--testcases/kernel/syscalls/link/.gitignore1
-rw-r--r--testcases/kernel/syscalls/link/link03.c167
-rw-r--r--testcases/kernel/syscalls/link/link05.c28
-rw-r--r--testcases/kernel/syscalls/link/link08.c31
-rw-r--r--testcases/kernel/syscalls/mkdirat/mkdirat01.c1
-rw-r--r--testcases/kernel/syscalls/mkdirat/mkdirat02.c1
-rw-r--r--testcases/kernel/syscalls/mknodat/mknodat.h35
-rw-r--r--testcases/kernel/syscalls/mknodat/mknodat01.c1
-rw-r--r--testcases/kernel/syscalls/mknodat/mknodat02.c2
-rw-r--r--testcases/kernel/syscalls/mmap/mmap04.c236
-rw-r--r--testcases/kernel/syscalls/mmap/mmap15.c123
-rw-r--r--testcases/kernel/syscalls/mount/mount04.c133
-rw-r--r--testcases/kernel/syscalls/mount/mount05.c159
-rw-r--r--testcases/kernel/syscalls/mount/mount06.c197
-rw-r--r--testcases/kernel/syscalls/mremap/mremap06.c27
-rw-r--r--testcases/kernel/syscalls/open/open11.c172
-rw-r--r--testcases/kernel/syscalls/pathconf/.gitignore1
-rw-r--r--testcases/kernel/syscalls/pathconf/pathconf01.c267
-rw-r--r--testcases/kernel/syscalls/pathconf/pathconf02.c98
-rw-r--r--testcases/kernel/syscalls/pipe/.gitignore1
-rw-r--r--testcases/kernel/syscalls/pipe/pipe15.c94
-rw-r--r--testcases/kernel/syscalls/preadv/preadv.h21
-rw-r--r--testcases/kernel/syscalls/preadv/preadv01.c31
-rw-r--r--testcases/kernel/syscalls/preadv/preadv02.c44
-rw-r--r--testcases/kernel/syscalls/preadv/preadv03.c7
-rw-r--r--testcases/kernel/syscalls/ptrace/.gitignore1
-rw-r--r--testcases/kernel/syscalls/ptrace/Makefile27
-rwxr-xr-xtestcases/kernel/syscalls/ptrace/make_syscall_list.sh7
-rw-r--r--testcases/kernel/syscalls/ptrace/ptrace.h35
-rw-r--r--testcases/kernel/syscalls/ptrace/ptrace01.c3
-rw-r--r--testcases/kernel/syscalls/ptrace/ptrace02.c3
-rw-r--r--testcases/kernel/syscalls/ptrace/ptrace03.c3
-rw-r--r--testcases/kernel/syscalls/ptrace/ptrace04.c6
-rw-r--r--testcases/kernel/syscalls/ptrace/ptrace05.c4
-rw-r--r--testcases/kernel/syscalls/ptrace/ptrace06.c5
-rw-r--r--testcases/kernel/syscalls/ptrace/ptrace07.c3
-rw-r--r--testcases/kernel/syscalls/ptrace/ptrace11.c3
-rw-r--r--testcases/kernel/syscalls/ptrace/simple_tracer.c144
-rw-r--r--testcases/kernel/syscalls/ptrace/syscalls.h17
-rw-r--r--testcases/kernel/syscalls/pwritev/pwritev.h21
-rw-r--r--testcases/kernel/syscalls/pwritev/pwritev01.c25
-rw-r--r--testcases/kernel/syscalls/pwritev/pwritev02.c41
-rw-r--r--testcases/kernel/syscalls/pwritev/pwritev03.c9
-rw-r--r--testcases/kernel/syscalls/readahead/readahead01.c53
-rw-r--r--testcases/kernel/syscalls/remap_file_pages/remap_file_pages01.c32
-rw-r--r--testcases/kernel/syscalls/rename/rename10.c10
-rw-r--r--testcases/kernel/syscalls/renameat/renameat01.c1
-rw-r--r--testcases/kernel/syscalls/sched_rr_get_interval/sched_rr_get_interval01.c10
-rw-r--r--testcases/kernel/syscalls/sched_rr_get_interval/sched_rr_get_interval02.c3
-rw-r--r--testcases/kernel/syscalls/sched_rr_get_interval/sched_rr_get_interval03.c20
-rw-r--r--testcases/kernel/syscalls/sched_setparam/sched_setparam03.c2
-rw-r--r--testcases/kernel/syscalls/sched_setparam/sched_setparam04.c11
-rw-r--r--testcases/kernel/syscalls/sched_setscheduler/.gitignore1
-rw-r--r--testcases/kernel/syscalls/sched_setscheduler/sched_setscheduler04.c78
-rw-r--r--testcases/kernel/syscalls/sendfile/sendfile09.c10
-rw-r--r--testcases/kernel/syscalls/sendmmsg/sendmmsg.h5
-rw-r--r--testcases/kernel/syscalls/setgroups/.gitignore2
-rw-r--r--testcases/kernel/syscalls/setgroups/Makefile3
-rw-r--r--testcases/kernel/syscalls/setgroups/setgroups04.c167
-rw-r--r--testcases/kernel/syscalls/setsockopt/.gitignore1
-rw-r--r--testcases/kernel/syscalls/setsockopt/setsockopt10.c205
-rw-r--r--testcases/kernel/syscalls/setuid/Makefile3
-rw-r--r--testcases/kernel/syscalls/setxattr/setxattr01.c2
-rw-r--r--testcases/kernel/syscalls/sighold/sighold02.c9
-rw-r--r--testcases/kernel/syscalls/splice/.gitignore2
-rw-r--r--testcases/kernel/syscalls/splice/splice06.c228
-rw-r--r--testcases/kernel/syscalls/splice/splice07.c72
-rw-r--r--testcases/kernel/syscalls/swapon/swapon01.c23
-rw-r--r--testcases/kernel/syscalls/swapon/swapon02.c60
-rw-r--r--testcases/kernel/syscalls/swapon/swaponoff.h10
-rw-r--r--testcases/kernel/syscalls/symlink/.gitignore1
-rw-r--r--testcases/kernel/syscalls/symlink/symlink02.c218
-rw-r--r--testcases/kernel/syscalls/symlink/symlink04.c213
-rw-r--r--testcases/kernel/syscalls/symlink/symlink05.c180
-rw-r--r--testcases/kernel/syscalls/timerfd/.gitignore1
-rw-r--r--testcases/kernel/syscalls/timerfd/timerfd02.c201
-rw-r--r--testcases/kernel/syscalls/timerfd/timerfd03.c170
-rw-r--r--testcases/kernel/syscalls/umount/umount01.c17
-rw-r--r--testcases/kernel/syscalls/umount/umount02.c34
-rw-r--r--testcases/kernel/syscalls/umount/umount03.c24
-rw-r--r--testcases/kernel/syscalls/utils/compat_16.mk2
-rw-r--r--testcases/kernel/syscalls/wait4/wait402.c105
-rw-r--r--testcases/kernel/syscalls/writev/writev07.c35
-rw-r--r--testcases/kernel/uevents/uevent01.c4
-rw-r--r--testcases/kernel/uevents/uevent02.c11
-rw-r--r--testcases/kernel/uevents/uevent03.c4
-rw-r--r--testcases/lib/test.sh2
-rw-r--r--testcases/lib/tst_net.sh31
-rw-r--r--testcases/lib/tst_test.sh16
-rw-r--r--testcases/network/README.md4
-rwxr-xr-xtestcases/network/busy_poll/busy_poll01.sh2
-rwxr-xr-xtestcases/network/busy_poll/busy_poll02.sh2
-rwxr-xr-xtestcases/network/busy_poll/busy_poll03.sh2
-rw-r--r--testcases/network/can/cve/can_bcm01.c11
-rw-r--r--testcases/network/can/filter-tests/can_filter.c2
-rw-r--r--testcases/network/can/filter-tests/can_rcv_own_msgs.c2
-rw-r--r--testcases/network/iptables/.gitignore1
-rw-r--r--testcases/network/iptables/Makefile2
-rw-r--r--testcases/network/iptables/nft02.c216
-rw-r--r--testcases/network/netstress/netstress.c5
-rwxr-xr-xtestcases/network/nfs/fsx-linux/fsx.sh3
-rw-r--r--testcases/network/nfs/nfs_stress/nfs05_make_tree.c1
-rwxr-xr-xtestcases/network/nfs/nfs_stress/nfs06.sh5
-rw-r--r--testcases/network/nfs/nfs_stress/nfs_lib.sh6
-rwxr-xr-xtestcases/network/nfs/nfslock01/nfslock01.sh3
-rw-r--r--testcases/network/stress/route/route-lib.sh8
-rwxr-xr-xtestcases/network/stress/ssh/ssh-stress.sh16
-rwxr-xr-xtestcases/network/tcp_cmds/host/host01.sh5
-rwxr-xr-xtestcases/network/tcp_cmds/ipneigh/ipneigh01.sh21
-rw-r--r--testcases/network/virt/virt_lib.sh10
-rwxr-xr-xtestcases/network/xinetd/xinetd_tests.sh7
-rw-r--r--testcases/open_posix_testsuite/conformance/interfaces/pthread_cond_timedwait/4-3.c5
-rw-r--r--testcases/open_posix_testsuite/conformance/interfaces/pthread_rwlock_unlock/4-1.c4
-rw-r--r--testcases/open_posix_testsuite/conformance/interfaces/sem_timedwait/3-1.c2
-rw-r--r--testcases/open_posix_testsuite/functional/mqueues/send_rev_2.c4
-rw-r--r--testcases/realtime/func/rt-migrate/rt-migrate.c25
-rwxr-xr-xtestscripts/autofs1.sh273
-rwxr-xr-xtestscripts/autofs4.sh259
-rwxr-xr-xtestscripts/load_stress_all_kernel_modules.sh35
-rwxr-xr-xtestscripts/ltp-scsi_debug.sh218
-rwxr-xr-xtestscripts/ltpdmmapper.sh204
-rwxr-xr-xtestscripts/sysfs.sh121
-rwxr-xr-xtools/create-tarballs-metadata.sh13
-rw-r--r--tools/create_dmesg_entries_for_each_test.awk1
m---------tools/kirk0
m---------tools/ltx/ltx-src0
-rwxr-xr-xtools/tag-release.sh12
414 files changed, 6091 insertions, 21532 deletions
diff --git a/.dockerignore b/.dockerignore
new file mode 100644
index 000000000..bbcd7072f
--- /dev/null
+++ b/.dockerignore
@@ -0,0 +1 @@
+Containerfile
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index d7e9f2dd0..a632ed96b 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -58,14 +58,12 @@ jobs:
TREE: out
VARIANT: minimal
- # other builds
- - container: "fedora:latest"
+ # oldest distros
+ - container: "opensuse/archive:42.2"
env:
- CC: clang
- MAKE_INSTALL: 1
- METADATA: asciidoctor-pdf
+ CC: gcc
- - container: "centos:7"
+ - container: "quay.io/centos/centos:stream9"
env:
CC: gcc
METADATA: asciidoc-pdf
@@ -80,7 +78,14 @@ jobs:
env:
CC: clang
- - container: "opensuse/leap"
+ # other builds
+ - container: "fedora:latest"
+ env:
+ CC: clang
+ MAKE_INSTALL: 1
+ METADATA: asciidoctor-pdf
+
+ - container: "opensuse/leap:latest"
env:
CC: gcc
METADATA: asciidoc-pdf
diff --git a/.github/workflows/wiki-mirror.yml b/.github/workflows/wiki-mirror.yml
index 2ac0caf74..a62ca676c 100644
--- a/.github/workflows/wiki-mirror.yml
+++ b/.github/workflows/wiki-mirror.yml
@@ -39,7 +39,7 @@ jobs:
cd $GITHUB_WORKSPACE/ltp.wiki
# don't forget to add new extensions
- cp -v $dir/*.asciidoc $dir/*.rest .
+ cp -v $dir/*.asciidoc .
git add .
# only commit if there are changes
diff --git a/Containerfile b/Containerfile
new file mode 100644
index 000000000..227c7d39d
--- /dev/null
+++ b/Containerfile
@@ -0,0 +1,35 @@
+# SPDX-License-Identifier: GPL-2.0-or-later
+# Copyright (c) 2023 SUSE LLC
+
+ARG PREFIX=docker.io/
+ARG DISTRO_NAME=alpine
+ARG DISTRO_RELEASE=3.18
+
+FROM $PREFIX$DISTRO_NAME:$DISTRO_RELEASE AS build
+ARG LTPROOT=/opt/ltp
+ARG DISTRO_NAME=alpine
+ARG DISTRO_RELEASE=3.18
+
+RUN mkdir /build
+WORKDIR /build
+COPY . /build
+RUN ./ci/${DISTRO_NAME}.sh
+RUN git clean -fdX
+RUN ./build.sh -p $LTPROOT -i
+
+FROM $PREFIX$DISTRO_NAME:$DISTRO_RELEASE
+ARG LTPROOT=/opt/ltp
+ARG KIRKROOT=/opt/kirk
+ARG DISTRO_NAME=alpine
+
+COPY --from=build /build/ci/${DISTRO_NAME}-runtime.sh $LTPROOT/runtime-deps.sh
+RUN $LTPROOT/runtime-deps.sh
+
+COPY --from=build $LTPROOT $LTPROOT
+ENV LTPROOT=$LTPROOT
+ENV PATH=$LTPROOT/testcases/bin:$LTPROOT/bin:$PATH
+
+RUN mkdir -p $KIRKROOT
+COPY --from=build /build/tools/kirk $KIRKROOT
+
+USER ltp
diff --git a/INSTALL b/INSTALL
index eb63539a8..99386bed8 100644
--- a/INSTALL
+++ b/INSTALL
@@ -202,7 +202,7 @@ LDLIBS - libraries listed after objects during link, e.g. -lc, -lpthread,
-lltp.
For other variables and more info about the build systems see
-doc/build-system-guide.txt.
+doc/Build-System.asciidoc.
Common Issues
-------------
diff --git a/README.md b/README.md
index 68f6ec897..6147c5f6f 100644
--- a/README.md
+++ b/README.md
@@ -154,7 +154,7 @@ $ testcases/bin/abort01
Some have arguments
```
-$ testcases/bin/mesgq\_nstest -m none
+$ testcases/bin/mesgq_nstest -m none
```
The vast majority of test cases accept the -h (help) switch
@@ -176,7 +176,7 @@ Note that all shell scripts need the `PATH` to be set. However this is not
limited to shell scripts, many C based tests need environment variables as
well.
-For more info see `doc/user-guide.txt` or online at
+For more info see `doc/User-Guidelines.asciidoc` or online at
https://github.com/linux-test-project/ltp/wiki/User-Guidelines.
Network tests
@@ -184,18 +184,56 @@ Network tests
Network tests require certain setup, described in `testcases/network/README.md`
(online at https://github.com/linux-test-project/ltp/tree/master/testcases/network).
+Containers
+----------
+
+*Presently running the LTP inside a container is not a shortcut. It
+will make things much harder for you.*
+
+There is a Containerfile which can be used with Docker or
+Podman. Currently it can build Alpine and OpenSUSE images.
+
+The container can be built with a command like:
+
+```
+$ podman build -t tumbleweed/ltp \
+ --build-arg PREFIX=registry.opensuse.org/opensuse/ \
+ --build-arg DISTRO_NAME=tumbleweed \
+ --build-arg DISTRO_RELEASE=20230925 .
+```
+
+Or just `podman build .` which will create an Alpine container.
+
+It contains Kirk in /opt/kirk. So the following will run some tests.
+
+```
+$ podman run -it --rm tumbleweed/ltp:latest
+$ cd /opt/kirk && ./kirk -f ltp -r syscalls
+```
+
+SUSE also publishes a
+[smaller LTP container](https://registry.opensuse.org/cgi-bin/cooverview?srch_term=project%3D%5Ebenchmark+container%3D.*)
+that is not based on the Containerfile.
+
+Debugging with gdb
+==================
+
+The new test library runs the actual test, i.e. the `test()` function in a
+forked process. To get stack trace of a crashing test in gdb it's needed to
+[`set follow-fork-mode child`](https://ftp.gnu.org/old-gnu/Manuals/gdb/html_node/gdb_25.html).
+
Developers corner
=================
Before you start you should read following documents:
-* `doc/test-writing-guidelines.txt`
-* `doc/build-system-guide.txt`
-* `doc/library-api-writing-guidelines.txt`
+* `doc/Test-Writing-Guidelines.asciidoc`
+* `doc/Build-System.asciidoc`
+* `doc/LTP-Library-API-Writing-Guidelines.asciidoc`
There is also a step-by-step tutorial:
-* `doc/c-test-tutorial-simple.txt`
+* `doc/C-Test-Case-Tutorial.asciidoc`
If something is not covered there don't hesitate to ask on the LTP mailing
list. Also note that these documents are available online at:
diff --git a/VERSION b/VERSION
index e851466ff..5c916bb2a 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-20230929
+20240129
diff --git a/ci/alpine-runtime.sh b/ci/alpine-runtime.sh
new file mode 100755
index 000000000..3bff42770
--- /dev/null
+++ b/ci/alpine-runtime.sh
@@ -0,0 +1,18 @@
+#!/bin/sh -eux
+# SPDX-License-Identifier: GPL-2.0-or-later
+# Copyright (c) 2023 SUSE LLC
+
+apk add \
+ acl \
+ keyutils \
+ libaio \
+ libacl \
+ libcap \
+ libselinux \
+ libsepol \
+ libtirpc \
+ numactl \
+ openssl \
+ py3-msgpack
+
+adduser -D -g "Unprivileged LTP user" ltp
diff --git a/ci/alpine.sh b/ci/alpine.sh
index 9ae5a8d07..d2495c389 100755
--- a/ci/alpine.sh
+++ b/ci/alpine.sh
@@ -1,6 +1,6 @@
-#!/bin/sh
+#!/bin/sh -eux
+# SPDX-License-Identifier: GPL-2.0-or-later
# Copyright (c) 2019-2022 Petr Vorel <petr.vorel@gmail.com>
-set -ex
apk update
diff --git a/ci/debian.cross-compile.sh b/ci/debian.cross-compile.sh
index 0a7ef7710..95cf11da2 100755
--- a/ci/debian.cross-compile.sh
+++ b/ci/debian.cross-compile.sh
@@ -1,6 +1,6 @@
-#!/bin/sh
+#!/bin/sh -eux
+# SPDX-License-Identifier: GPL-2.0-or-later
# Copyright (c) 2018-2020 Petr Vorel <pvorel@suse.cz>
-set -ex
if [ -z "$ARCH" ]; then
echo "missing \$ARCH!" >&2
diff --git a/ci/debian.i386.sh b/ci/debian.i386.sh
index 707a23ca6..d28e552ff 100755
--- a/ci/debian.i386.sh
+++ b/ci/debian.i386.sh
@@ -1,6 +1,6 @@
-#!/bin/sh
+#!/bin/sh -eux
+# SPDX-License-Identifier: GPL-2.0-or-later
# Copyright (c) 2018-2020 Petr Vorel <pvorel@suse.cz>
-set -ex
dpkg --add-architecture i386
apt update
diff --git a/ci/debian.minimal.sh b/ci/debian.minimal.sh
index b51154b05..568125555 100755
--- a/ci/debian.minimal.sh
+++ b/ci/debian.minimal.sh
@@ -1,6 +1,6 @@
-#!/bin/sh
+#!/bin/sh -eux
+# SPDX-License-Identifier: GPL-2.0-or-later
# Copyright (c) 2018-2023 Petr Vorel <pvorel@suse.cz>
-set -ex
apt="apt remove -y"
diff --git a/ci/debian.sh b/ci/debian.sh
index da92337fb..96b55a35b 100755
--- a/ci/debian.sh
+++ b/ci/debian.sh
@@ -1,6 +1,6 @@
-#!/bin/sh
+#!/bin/sh -eux
+# SPDX-License-Identifier: GPL-2.0-or-later
# Copyright (c) 2018-2021 Petr Vorel <pvorel@suse.cz>
-set -ex
# workaround for missing oldstable-updates repository
# W: Failed to fetch http://deb.debian.org/debian/dists/oldstable-updates/main/binary-amd64/Packages
diff --git a/ci/fedora.sh b/ci/fedora.sh
index a603bcbe3..623dbb5cb 100755
--- a/ci/fedora.sh
+++ b/ci/fedora.sh
@@ -1,6 +1,6 @@
-#!/bin/sh
+#!/bin/sh -eux
+# SPDX-License-Identifier: GPL-2.0-or-later
# Copyright (c) 2018-2021 Petr Vorel <pvorel@suse.cz>
-set -ex
yum="yum -y install --skip-broken"
diff --git a/ci/centos.sh b/ci/quay.io.sh
index 1479a43e0..1479a43e0 120000
--- a/ci/centos.sh
+++ b/ci/quay.io.sh
diff --git a/ci/tumbleweed-runtime.sh b/ci/tumbleweed-runtime.sh
new file mode 100755
index 000000000..3eea991aa
--- /dev/null
+++ b/ci/tumbleweed-runtime.sh
@@ -0,0 +1,15 @@
+#!/bin/sh -eux
+# SPDX-License-Identifier: GPL-2.0-or-later
+# Copyright (c) 2023 SUSE LLC
+
+zyp="zypper --non-interactive install --force-resolution --no-recommends"
+
+$zyp \
+ iproute2 \
+ keyutils \
+ libaio1 \
+ libmnl0 \
+ libnuma1 \
+ libtirpc3
+
+useradd ltp
diff --git a/ci/tumbleweed.sh b/ci/tumbleweed.sh
index f1e7252f2..42d62c0e0 100755
--- a/ci/tumbleweed.sh
+++ b/ci/tumbleweed.sh
@@ -1,6 +1,6 @@
-#!/bin/sh
+#!/bin/sh -eux
+# SPDX-License-Identifier: GPL-2.0-or-later
# Copyright (c) 2018-2021 Petr Vorel <pvorel@suse.cz>
-set -ex
zyp="zypper --non-interactive install --force-resolution --no-recommends"
diff --git a/configure.ac b/configure.ac
index 4ba57fca3..a676bc3f3 100644
--- a/configure.ac
+++ b/configure.ac
@@ -35,6 +35,7 @@ AC_PREFIX_DEFAULT(/opt/ltp)
AC_CHECK_DECLS([IFLA_NET_NS_PID],,,[#include <linux/if_link.h>])
AC_CHECK_DECLS([MADV_MERGEABLE],,,[#include <sys/mman.h>])
+AC_CHECK_DECLS([NFTA_CHAIN_ID, NFTA_VERDICT_CHAIN_ID],,,[#include <linux/netfilter/nf_tables.h>])
AC_CHECK_DECLS([PR_CAPBSET_DROP, PR_CAPBSET_READ],,,[#include <sys/prctl.h>])
AC_CHECK_DECLS([SEM_STAT_ANY],,,[#include <sys/sem.h>])
@@ -65,6 +66,7 @@ AC_CHECK_HEADERS_ONCE([ \
linux/openat2.h \
linux/seccomp.h \
linux/securebits.h \
+ linux/tls.h \
linux/tty.h \
linux/types.h \
linux/userfaultfd.h \
@@ -95,7 +97,6 @@ AC_CHECK_FUNCS_ONCE([ \
execveat \
faccessat2 \
fallocate \
- fchownat \
fsconfig \
fsmount \
fsopen \
@@ -114,8 +115,6 @@ AC_CHECK_FUNCS_ONCE([ \
mallinfo \
mallinfo2 \
mallopt \
- mkdirat \
- mknodat \
modify_ldt \
mount_setattr \
move_mount \
@@ -134,9 +133,7 @@ AC_CHECK_FUNCS_ONCE([ \
pwritev2 \
quotactl_fd \
rand_r \
- readlinkat \
recvmmsg \
- renameat \
renameat2 \
sched_getcpu \
sendmmsg \
@@ -397,7 +394,6 @@ LTP_CHECK_FORTIFY_SOURCE
LTP_CHECK_KERNEL_DEVEL
LTP_CHECK_KEYUTILS_SUPPORT
LTP_CHECK_LIBMNL
-LTP_CHECK_LINUX_PTRACE
LTP_CHECK_LINUXRANDOM
LTP_CHECK_NOMMU_LINUX
LTP_CHECK_SELINUX
diff --git a/doc/Build-System.rest b/doc/Build-System.asciidoc
index e078fa7f7..95ba3b70e 100644
--- a/doc/Build-System.rest
+++ b/doc/Build-System.asciidoc
@@ -112,7 +112,7 @@ 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
+kbuild, see 'Documentation/kbuild/modules.rst' in the Linux kernel tree for
details on external module build.
Make Rules and Make Variables
diff --git a/doc/C-Test-API.asciidoc b/doc/C-Test-API.asciidoc
index dab811564..db16be36e 100644
--- a/doc/C-Test-API.asciidoc
+++ b/doc/C-Test-API.asciidoc
@@ -224,10 +224,12 @@ void tst_res(int ttype, char *arg_fmt, ...);
Printf-like function to report test result, it's mostly used with ttype:
|==============================
-| 'TPASS' | Test has passed.
-| 'TFAIL' | Test has failed.
-| 'TINFO' | General message.
-| 'TWARN' | Something went wrong but we decided to continue. Mostly used in cleanup functions.
+| 'TPASS' | Test has passed.
+| 'TFAIL' | Test has failed.
+| 'TINFO' | General message.
+| 'TDEBUG' | Debug message (new C API only, printed with '-D' or via 'LTP_ENABLE_DEBUG=1' or 'y'
+ environment variable), only for messages which would be too verbose for normal run.
+| 'TWARN' | Something went wrong but we decided to continue. Mostly used in cleanup functions.
|==============================
The 'ttype' can be combined bitwise with 'TERRNO' or 'TTERRNO' to print
diff --git a/doc/C-Test-Case-Tutorial.asciidoc b/doc/C-Test-Case-Tutorial.asciidoc
index 07a61f4ec..6575781ab 100644
--- a/doc/C-Test-Case-Tutorial.asciidoc
+++ b/doc/C-Test-Case-Tutorial.asciidoc
@@ -298,7 +298,7 @@ the database into a branch.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Maybe the test should report "TCONF: Not implemented" instead or perhaps
-+TBROK+. Try changing it do so (see +doc/test-writing-guidelines.txt+ or
++TBROK+. Try changing it do so (see +doc/Test-Writing-Guidelines.asciidoc+ or
https://github.com/linux-test-project/ltp/wiki/Test-Writing-Guidelines[the
Wiki]).
diff --git a/doc/C-Test-Network-API.asciidoc b/doc/C-Test-Network-API.asciidoc
index 3bf2a1f8a..feedd5a95 100644
--- a/doc/C-Test-Network-API.asciidoc
+++ b/doc/C-Test-Network-API.asciidoc
@@ -143,7 +143,7 @@ static void setup(void)
When opening a localhost socket isn't enough and the test needs special device
or routing configuration, the netdevice library can create the required network
setup without calling external programs. Internally, the netdevice functions
-use a rtnetlink socket to communicate with the kernel.
+use a netlink socket to communicate with the kernel.
All of these functions will call +tst_brk()+ on failure, unless stated
otherwise. Error values described below are returned only during test cleanup
@@ -274,12 +274,12 @@ static void setup(void)
}
-------------------------------------------------------------------------------
-3 rtnetlink API
----------------
+3 Netlink API
+-------------
-+#include "tst_rtnetlink.h"+
++#include "tst_netlink.h"+
-The rtnetlink library provides helper functions for constructing and sending
+The netlink library provides helper functions for constructing and sending
arbitrary messages and parsing kernel responses.
All of the functions below will call +tst_brk()+ on failure, unless stated
@@ -291,16 +291,16 @@ stage.
[source,c]
-------------------------------------------------------------------------------
-struct tst_rtnl_context;
+struct tst_netlink_context;
-struct tst_rtnl_attr_list {
+struct tst_netlink_attr_list {
unsigned short type;
const void *data;
ssize_t len;
- const struct tst_rtnl_attr_list *sublist;
+ const struct tst_netlink_attr_list *sublist;
};
-struct tst_rtnl_message {
+struct tst_netlink_message {
struct nlmsghdr *header;
struct nlmsgerr *err;
void *payload;
@@ -308,17 +308,18 @@ struct tst_rtnl_message {
};
-------------------------------------------------------------------------------
-+struct tst_rtnl_context+ is an opaque rtnetlink socket with buffer for
++struct tst_netlink_context+ is an opaque netlink socket with buffer for
constructing and sending arbitrary messages using the functions described
-below. Create a new context using +RTNL_CREATE_CONTEXT()+, then free it using
-+RTNL_DESTROY_CONTEXT()+ when you're done with it.
+below. Create a new context using +NETLINK_CREATE_CONTEXT()+, then free it
+using +NETLINK_DESTROY_CONTEXT()+ when you're done with it.
-+struct tst_rtnl_attr_list+ is a helper structure for defining complex
++struct tst_netlink_attr_list+ is a helper structure for defining complex
rtnetlink message attribute payloads, including nested attribute lists. Every
list and sublist defined using this structure is terminated by item with
negative +len+.
-- +type+ is the attribute type that will be stored in +struct rtattr.rta_type+.
+- +type+ is the attribute type that will be stored in +struct nlattr.nla_type+
+ or +struct rtattr.rta_type+.
- +data+ contains arbitrary attribute payload.
@@ -326,15 +327,15 @@ negative +len+.
set +len+ to 0. The last item in a list or sublist must have negative length.
- +sublist+ contains a nested attribute list which will be appended after
- +data+ as part of the attribute payload. +struct rtattr.rta_len+ will be
- calculated automatically with proper alignment, do _not_ add the sublist size
- to the +len+ field. If you do not want to add nested attributes, set
- +sublist+ to +NULL+.
+ +data+ as part of the attribute payload. +struct nlattr.nla_len+ or
+ +struct rtattr.rta_len+ will be calculated automatically with proper
+ alignment, do _not_ add the sublist size to the +len+ field. If you do not
+ want to add nested attributes, set +sublist+ to +NULL+.
-+struct tst_rtnl_message+ is a structure holding partially parsed rtnetlink
-messages received from the kernel. +RTNL_RECV()+ returns an array of these
++struct tst_netlink_message+ is a structure holding partially parsed netlink
+messages received from the kernel. +NETLINK_RECV()+ returns an array of these
structures with the last item having +NULL+ in the +header+ field. Call
-+RTNL_FREE_MESSAGE()+ to free a message list returned by +RTNL_RECV()+.
++NETLINK_FREE_MESSAGE()+ to free a message list returned by +NETLINK_RECV()+.
- +header+ is the netlink header structure of the message. +NULL+ in the header
field terminates a list of messages.
@@ -349,84 +350,110 @@ structures with the last item having +NULL+ in the +header+ field. Call
3.2 Sending and receiving messages
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-- +struct tst_rtnl_context *RTNL_CREATE_CONTEXT(void)+ – Creates a new
- rtnetlink communication context for use with the functions described below.
- Returns +NULL+ on error.
+- +struct tst_netlink_context *NETLINK_CREATE_CONTEXT(int protocol)+ – Creates
+ a new netlink communication context with given netlink protocol for use
+ with the functions described below. Returns +NULL+ on error.
-- +void RTNL_FREE_MESSAGE(struct tst_rtnl_message *msg)+ – Frees an array of
- messages returned by +RTNL_RECV()+.
+- +void NETLINK_FREE_MESSAGE(struct tst_netlink_message *msg)+ – Frees
+ an array of messages returned by +NETLINK_RECV()+.
-- +void RTNL_DESTROY_CONTEXT(struct tst_rtnl_context *ctx)+ – Closes a
- communication context created by +RTNL_CREATE_CONTEXT()+.
+- +void NETLINK_DESTROY_CONTEXT(struct tst_netlink_context *ctx)+ – Closes a
+ communication context created by +NETLINK_CREATE_CONTEXT()+.
-- +int RTNL_SEND(struct tst_rtnl_context *ctx)+ – Sends all messages waiting
- in +ctx+ buffer to the kernel. If there are multiple messages to send, a new
- +NLMSG_DONE+ message will be added automatically. Returns the number of
- bytes sent on success. Return 0 or negative value on error.
+- +int NETLINK_SEND(struct tst_netlink_context *ctx)+ – Sends all messages
+ waiting in +ctx+ buffer to the kernel. If there are multiple messages
+ to send, a new +NLMSG_DONE+ message will be added automatically. Returns
+ the number of bytes sent on success. Return 0 or negative value on error.
-- +int RTNL_SEND_VALIDATE(struct tst_rtnl_context *ctx)+ – Sends all messages
- just like +RTNL_SEND()+, then receives the response from the kernel and
- validates results of requests sent with the +NLM_F_ACK+ flag. This function
- calls +tst_brk()+ as usual if communication fails but it will return error
- status without terminating the test if one of the received messages contains
- error code. See +RTNL_CHECK_ACKS()+ below for explanation of the return
- value.
+- +int NETLINK_SEND_VALIDATE(struct tst_netlink_context *ctx)+ – Sends all
+ messages just like +NETLINK_SEND()+, then receives the response from
+ the kernel and validates results of requests sent with the +NLM_F_ACK+ flag.
+ This function calls +tst_brk()+ as usual if communication fails but it will
+ return error status without terminating the test if one of the received
+ messages contains error code. See +NETLINK_CHECK_ACKS()+ below for
+ explanation of the return value.
-- +int RTNL_WAIT(struct tst_rtnl_context *ctx)+ – Waits until data becomes
- available to read from the rtnetlink socket (timeout: 1 second). Returns 1
+- +int NETLINK_WAIT(struct tst_netlink_context *ctx)+ – Waits until data becomes
+ available to read from the netlink socket (timeout: 1 second). Returns 1
if there is data to read, 0 on timeout or -1 on error.
-- +struct tst_rtnl_message *RTNL_RECV(struct tst_rtnl_context *ctx)+ – Receives
- rtnetlink messages from the kernel. The messages are received in non-blocking
- mode so calling +RTNL_WAIT()+ first is recommended. Returns an array of
- partially parsed messages terminated by an item with +NULL+ in the +header+
- field. On error or when there are no messages to receive, returns +NULL+.
- Call +RTNL_FREE_MESSAGE()+ to free the returned data.
-
-- +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+).
+- +struct tst_netlink_message *NETLINK_RECV(struct tst_netlink_context *ctx)+ –
+ Receives netlink messages from the kernel. The messages are received
+ in non-blocking mode so calling +NETLINK_WAIT()+ first is recommended.
+ Returns an array of partially parsed messages terminated by an item with
+ +NULL+ in the +header+ field. On error or when there are no messages
+ to receive, returns +NULL+. Call +NETLINK_FREE_MESSAGE()+ to free
+ the returned data.
+
+- +int NETLINK_CHECK_ACKS(struct tst_netlink_context *ctx,
+ struct tst_netlink_message *response)+ – Validate results of requests sent
+ with the +NLM_F_ACK+ flag. Do not call +NETLINK_ADD_MESSAGE()+ between
+ +NETLINK_SEND()+ and +NETLINK_CHECK_ACKS()+ because it will reset the state
+ of +ctx+ and prevent result validation. Returns 1 if all messages sent
+ with the +NLM_F_ACK+ flag have a corresponding message in +response+ and
+ the error code is 0. If any of the expected response messages is missing,
+ this function will call +tst_brk()+ (or return 0 during test cleanup phase).
+ If any of the response messages has non-zero error code, this function will
+ return 0 and store the first non-zero error code in global variable
+ +tst_netlink_errno+ (sign-flipped just like regular libc +errno+).
3.3 Creating messages
~~~~~~~~~~~~~~~~~~~~~
-- +int RTNL_ADD_MESSAGE(struct tst_rtnl_context *ctx, const struct nlmsghdr
- *header, const void *payload, size_t payload_size)+ – Adds new rtnetlink
- message to +ctx+ buffer. You need to provide message +header+ and optional
- +payload+. +payload_size+ is the size of +payload+ data in bytes. If you
- don't want to add any payload data, set +payload+ to +NULL+ and
+- +int NETLINK_ADD_MESSAGE(struct tst_netlink_context *ctx, const struct
+ nlmsghdr *header, const void *payload, size_t payload_size)+ – Adds new
+ netlink message to +ctx+ buffer. You need to provide message +header+ and
+ optional +payload+. +payload_size+ is the size of +payload+ data in bytes.
+ If you don't want to add any payload data, set +payload+ to +NULL+ and
+payload_size+ to 0. This function will automatically fill the +nlmsg_len+,
+nlmsg_seq+ and +nlmsg_pid+ fields of the new message header. You don't need
to set those. It'll also automatically add +NLM_F_MULTI+ flag when needed.
Returns 1 on success, 0 on error. Note that the first call of
- +RTNL_ADD_MESSAGE()+ after +RTNL_SEND()+ will reset the state of +ctx+
- and +RTNL_CHECK_ACKS()+ will not work correctly until the next +RTNL_SEND()+.
-
-- +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.
+ +NETLINK_ADD_MESSAGE()+ after +NETLINK_SEND()+ will reset the state of +ctx+
+ and +NETLINK_CHECK_ACKS()+ will not work correctly until the next
+ +NETLINK_SEND()+.
+
+- +int NETLINK_ADD_ATTR(struct tst_netlink_context *ctx, unsigned short type,
+ const void *data, unsigned short len)+ – Adds new +struct nlattr+ attribute
+ to the last message in +ctx+ buffer. See +NETLINK_ADD_MESSAGE()+. You need
+ to provide attribute +type+ which will be stored in +struct nlattr.nla_type+,
+ optional payload +data+ and payload size +len+ in bytes. If you don't want
+ to add any payload, set +data+ to +NULL+ and +len+ to 0. Returns 1 on
+ success, 0 on error.
+
+- +int NETLINK_ADD_ATTR_STRING(struct tst_netlink_context *ctx, unsigned short
+ type, const char *data)+ – Adds new +struct nlattr+ string attribute to the
+ last message in +ctx+ buffer. Parameters and return value are the same as
+ for +NETLINK_ADD_ATTR()+, except the payload length is calculated using
+ +strlen()+.
+
+- +int NETLINK_ADD_ATTR_LIST(struct tst_netlink_context *ctx, const struct
+ tst_netlink_attr_list *list)+ – Adds a list of +struct nlattr+ attributes
+ to the last message in +ctx+ buffer. See description of
+ +struct tst_netlink_attr_list+ and +NETLINK_ADD_MESSAGE()+ above. Returns
+ the number of added attributes on success (nested attributes are not
+ counted), -1 on error.
+
+- +int RTNL_ADD_ATTR(struct tst_netlink_context *ctx, unsigned short type,
+ const void *data, unsigned short len)+ – Adds new +struct rtattr+ attribute
+ to the last message in +ctx+ buffer. See +NETLINK_ADD_MESSAGE()+. You need
+ to provide attribute +type+ which will be stored in +struct rtattr.rta_type+,
+ optional payload +data+ and payload size +len+ in bytes. If you don't want
+ to add any payload, set +data+ to +NULL+ and +len+ to 0. Returns 1 on
+ success, 0 on error.
+
+- +int RTNL_ADD_ATTR_STRING(struct tst_netlink_context *ctx, unsigned short
+ type, const char *data)+ – Adds new +struct rtattr+ string attribute to the
+ last message in +ctx+ buffer. Parameters and return value are the same as
+ for +RTNL_ADD_ATTR()+, except the payload length is calculated using
+ +strlen()+.
+
+- +int RTNL_ADD_ATTR_LIST(struct tst_netlink_context *ctx, const struct
+ tst_netlink_attr_list *list)+ – Adds a list of +struct rtattr+ attributes
+ to the last message in +ctx+ buffer. See description of
+ +struct tst_netlink_attr_list+ and +NETLINK_ADD_MESSAGE()+ above. Returns
+ the number of added attributes on success (nested attributes are not
+ counted), -1 on error.
Example Usage
+++++++++++++
@@ -440,14 +467,14 @@ Example Usage
#include <arpa/inet.h>
#include "tst_test.h"
-#include "tst_rtnetlink.h"
+#include "tst_netlink.h"
#include "tst_netdevice.h"
...
void setup(void)
{
- struct tst_rtnl_context *ctx;
+ struct tst_netlink_context *ctx;
int index, ret;
in_addr_t addr;
@@ -465,12 +492,12 @@ void setup(void)
index = NETDEV_INDEX_BY_NAME("ltp_veth1");
info.ifa_index = index;
- ctx = RTNL_CREATE_CONTEXT();
- RTNL_ADD_MESSAGE(ctx, &header, &info, sizeof(info));
+ ctx = NETLINK_CREATE_CONTEXT(NETLINK_ROUTE);
+ NETLINK_ADD_MESSAGE(ctx, &header, &info, sizeof(info));
addr = inet_addr("192.168.123.45");
RTNL_ADD_ATTR(ctx, IFA_LOCAL, &addr, sizeof(addr));
- ret = RTNL_SEND_VALIDATE(ctx);
- RTNL_DESTROY_CONTEXT(ctx);
+ ret = NETLINK_SEND_VALIDATE(ctx);
+ NETLINK_DESTROY_CONTEXT(ctx);
if (!ret) {
tst_brk(TBROK, "Failed to set ltp_veth1 address");
diff --git a/doc/Contact-Info.asciidoc b/doc/Contact-Info.asciidoc
new file mode 100644
index 000000000..34d6fb770
--- /dev/null
+++ b/doc/Contact-Info.asciidoc
@@ -0,0 +1,28 @@
+Contact information
+===================
+
+Mailing lists
+-------------
+
+Current list
+~~~~~~~~~~~~
+
+- https://lists.linux.it/listinfo/ltp
+
+3rd-party mailing list archive sites
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+- *https://lore.kernel.org/ltp/*
+- http://marc.info/?l=ltp-list
+- http://www.mail-archive.com/ltp-list@lists.sourceforge.net/
+
+Old mailing list archive
+~~~~~~~~~~~~~~~~~~~~~~~~
+Archive of the old list, before we got new mailing list on linux.it.
+
+- http://sourceforge.net/mail/?group_id=3382
+
+IRC
+---
+
+- IRC channel: irc.freenode.net #ltp \ No newline at end of file
diff --git a/doc/LTP-Library-API-Writing-Guidelines.asciidoc b/doc/LTP-Library-API-Writing-Guidelines.asciidoc
index 3b8c1d97d..3b9a905f3 100644
--- a/doc/LTP-Library-API-Writing-Guidelines.asciidoc
+++ b/doc/LTP-Library-API-Writing-Guidelines.asciidoc
@@ -11,7 +11,7 @@ NOTE: See also
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'),
+offline: 'doc/Test-Writing-Guidelines.asciidoc'),
with strong focus on readability and simplicity.
Library tests are in 'lib/newlib_tests' directory.
diff --git a/doc/LTP-Release-Procedure.asciidoc b/doc/LTP-Release-Procedure.asciidoc
index 69c05071f..c2336e4a4 100644
--- a/doc/LTP-Release-Procedure.asciidoc
+++ b/doc/LTP-Release-Procedure.asciidoc
@@ -41,9 +41,10 @@ git push origin master:master
git push origin YYYYMMDD
--------------------------------------------------------------------
-NOTE: The string YYYYMMDD should be substituted to the current date.
+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.
+NOTE: You can use https://github.com/linux-test-project/ltp/blob/master/tools/tag-release.sh[`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]
@@ -118,9 +119,9 @@ 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.
+NOTE: You can use https://github.com/linux-test-project/ltp/blob/master/tools/create-tarballs-metadata.sh[`tools/create-tarballs-metadata.sh`]
+ script to have the above automated. All generated files are placed in
+ ltp-release-YYYYMMDD directory.
[source,sh]
--------------------------------------------------------------------
@@ -147,7 +148,7 @@ 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
+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.
diff --git a/doc/Maintainer-Patch-Review-Checklist.asciidoc b/doc/Maintainer-Patch-Review-Checklist.asciidoc
index cb9e00e8b..452de0d49 100644
--- a/doc/Maintainer-Patch-Review-Checklist.asciidoc
+++ b/doc/Maintainer-Patch-Review-Checklist.asciidoc
@@ -97,14 +97,11 @@ Commit messages should have
* Check also mailing lists for other reviewers / testers tags, notes and failure reports
* `Fixes: hash` if it fixes particular LTP commit
* `Fixes: #N` if it fixes github issue number N, so it's automatically closed
+* LTP WIKI (git: https://github.com/linux-test-project/ltp.wiki.git) should be kept up to date.
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
diff --git a/doc/Supported-kernel,-libc,-toolchain-versions.asciidoc b/doc/Supported-kernel,-libc,-toolchain-versions.asciidoc
index e3d9cd92f..bdb3e44f3 100644
--- a/doc/Supported-kernel,-libc,-toolchain-versions.asciidoc
+++ b/doc/Supported-kernel,-libc,-toolchain-versions.asciidoc
@@ -19,12 +19,11 @@ NOTE: GitHub Actions does only build testing, passing the CI means only that
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
[align="center",options="header"]
-|==============================================================
+|===============================================================
| Distro | kernel | glibc | gcc | clang
-| CentOS 7 | 3.10 | 2.17 | 4.8.5 | -
+| openSUSE Leap 42.2 | 4.4 | 2.22 | 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
diff --git a/doc/Test-Writing-Guidelines.asciidoc b/doc/Test-Writing-Guidelines.asciidoc
index 0db852ae6..a81404fa6 100644
--- a/doc/Test-Writing-Guidelines.asciidoc
+++ b/doc/Test-Writing-Guidelines.asciidoc
@@ -262,6 +262,18 @@ The list of tests to be executed is stored in runtest files under the
stored in 'scenario_groups/default'. When you add a test you should add
corresponding entries into some runtest file(s) as well.
+Each line of runtest file contain one test. First item is the test name
+('shell_test01', 'splice02'). All other items, separated by space will be
+executed ('echo "SUCCESS" | shell_pipe01.sh', 'splice02 -s 20').
+
+[source,sh]
+-------------------------------------------------------------------------------
+shell_test01 echo "SUCCESS" | shell_pipe01.sh
+splice02 splice02 -s 20
+-------------------------------------------------------------------------------
+
+Blank lines and lines starting with a '#' (comments) are ignored.
+
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.
diff --git a/doc/User-Guidelines.asciidoc b/doc/User-Guidelines.asciidoc
index 8f2418df0..9ff9a59e7 100644
--- a/doc/User-Guidelines.asciidoc
+++ b/doc/User-Guidelines.asciidoc
@@ -7,6 +7,10 @@ For running LTP network tests see `testcases/network/README.md`.
1. Library environment variables
--------------------------------
+Following environment variables are expected to be set by LTP users. Therefore,
+with some exceptions, they have 'LTP_' prefix. Environment variables with 'TST_'
+prefix are used inside LTP shell API and should *not* be set by users.
+
|==============================================================================
| 'KCONFIG_PATH' | The path to the kernel config file, (if not set, it tries
the usual paths '/boot/config-RELEASE' or '/proc/config.gz').
@@ -40,10 +44,11 @@ For running LTP network tests see `testcases/network/README.md`.
| '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').
+| 'LTP_NO_CLEANUP' | Disable running test cleanup (defined in 'TST_CLEANUP').
+ Shell API only.
+| 'LTP_ENABLE_DEBUG' | Enable debug info (value '1' or 'y').
|==============================================================================
-
2. Test execution time and timeout
----------------------------------
diff --git a/doc/ltp-run-files.txt b/doc/ltp-run-files.txt
deleted file mode 100644
index 3f405b387..000000000
--- a/doc/ltp-run-files.txt
+++ /dev/null
@@ -1,96 +0,0 @@
-The runtest files contain a list of test cases to be executed.
-
-File Format
------------
-
-Lines starting with a '#' are comments and blank lines are ignored.
-
-Otherwise, lines start with a test name followed by white space, then some
-shell script to be executed. For example
-
-Test Name
-| Delimiter Test case argument
-| | |
-v v v
-splice02 seq 1 20000 | splice02 splice02-temp
- ^ ^ ^
- | | |
- | Test case executable |
- -----------Shell script-------------
-
-So the splice02 runtest entry pipes the output of seq into the splice02 test
-executable. Most runtest entries are simpler than this, for example
-
-splice03 splice03
-
-Here the test name and executable have the same name and no arguments have
-been supplied.
-
-Run test files should start with a comment describing the tests they contain,
-e.g.
-
-#DESCRIPTION:Kernel system calls
-
-Note that the LTP has absorbed a number of other projects. Some of these have
-been fully converted to the LTP format, others have runtest files generated
-for them during installation, while some use a shell script to integrate them
-with the other tests.
-
-Test suites
------------
-
- - syscalls (except epoll, see below)
- - fs
- - fsx
- - dio
- - mm
- - ipc
- - sched
- - math
- - pty
-
-if run network tests flag is passed these additional tests are run
- - tcp_cmds
- - multicast
- - rpc
- - nfs
-
-To test filesystem with LVM
-- testscripts/lvmtest.sh
-
-Device Mapper tests
- - ltpdmmapper.sh
-
-Network tests
- - network.sh
- - testcases/network/sockets/ltpSockets.sh
-
-other filesystem or disk type tests
- - autofs1.sh
- - autofs4.sh
- - diskio.sh
- - isofs.sh
- - sysfs.sh
-
-AIO/DIO filesystem tests
- - ltp-aiodio.sh
-
-Device driver tests (may not run on all platforms)
- - acpi
- - agp
- - base
- - drm
- - include
- - nls
- - pci
- - tbio
- - usb
-
-Open_hpi_testsuite
- - run_tests
-
-Open_posix_testsuite
- - run_tests
-
-
-testcases/kernel/syscalls/epoll - The tests require additional installation files. See the README in the epoll directory.
diff --git a/include/lapi/capability.h b/include/lapi/capability.h
index 17ec107b1..2b593797c 100644
--- a/include/lapi/capability.h
+++ b/include/lapi/capability.h
@@ -36,6 +36,10 @@
# define CAP_SYS_ADMIN 21
#endif
+#ifndef CAP_SYS_NICE
+# define CAP_SYS_NICE 23
+#endif
+
#ifndef CAP_SYS_TIME
# define CAP_SYS_TIME 25
#endif
diff --git a/include/lapi/fanotify.h b/include/lapi/fanotify.h
index 4bd1a113c..424514625 100644
--- a/include/lapi/fanotify.h
+++ b/include/lapi/fanotify.h
@@ -208,4 +208,9 @@ struct fanotify_event_info_error {
# define FSID_VAL_MEMBER(fsid, i) (fsid.val[i])
#endif /* HAVE_STRUCT_FANOTIFY_EVENT_INFO_FID_FSID___VAL */
+/* linux/exportfs.h */
+#ifndef FILEID_INVALID
+# define FILEID_INVALID 0xff
+#endif
+
#endif /* LAPI_FANOTIFY_H__ */
diff --git a/include/lapi/fcntl.h b/include/lapi/fcntl.h
index cb216e2dc..761331798 100644
--- a/include/lapi/fcntl.h
+++ b/include/lapi/fcntl.h
@@ -94,6 +94,10 @@
# define AT_REMOVEDIR 0x200
#endif
+#ifndef AT_HANDLE_FID
+# define AT_HANDLE_FID AT_REMOVEDIR
+#endif
+
#ifndef AT_SYMLINK_FOLLOW
# define AT_SYMLINK_FOLLOW 0x400
#endif
diff --git a/include/lapi/fsmount.h b/include/lapi/fsmount.h
index 07eb42ffa..2ed4da86f 100644
--- a/include/lapi/fsmount.h
+++ b/include/lapi/fsmount.h
@@ -11,12 +11,11 @@
#include "config.h"
#include <sys/syscall.h>
#include <sys/types.h>
-#include <sys/mount.h>
-#ifndef HAVE_FSOPEN
-# ifdef HAVE_LINUX_MOUNT_H
-# include <linux/mount.h>
-# endif
+#if !defined(HAVE_FSOPEN) && defined(HAVE_LINUX_MOUNT_H)
+# include <linux/mount.h>
+#else
+# include <sys/mount.h>
#endif
#include "lapi/fcntl.h"
diff --git a/include/lapi/io_uring.h b/include/lapi/io_uring.h
index a63741a08..c05517595 100644
--- a/include/lapi/io_uring.h
+++ b/include/lapi/io_uring.h
@@ -11,10 +11,9 @@
#include <unistd.h>
#include <fcntl.h>
-#include <sys/types.h>
#include <sys/uio.h>
#include <stdlib.h>
-#include <linux/fs.h>
+#include <linux/types.h>
#include "lapi/syscalls.h"
diff --git a/include/lapi/mkdirat.h b/include/lapi/mkdirat.h
deleted file mode 100644
index 72eb7f647..000000000
--- a/include/lapi/mkdirat.h
+++ /dev/null
@@ -1,20 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
- * Copyright (c) 2014 Cyril Hrubis <chrubis@suse.cz>
- */
-
-#ifndef LAPI_MKDIRAT_H__
-#define LAPI_MKDIRAT_H__
-
-#include "config.h"
-#include "lapi/syscalls.h"
-#include "lapi/fcntl.h"
-
-#ifndef HAVE_MKDIRAT
-static inline int mkdirat(int dirfd, const char *dirname, int mode)
-{
- return tst_syscall(__NR_mkdirat, dirfd, dirname, mode);
-}
-#endif
-
-#endif /* LAPI_MKDIRAT_H__ */
diff --git a/include/lapi/nf_tables.h b/include/lapi/nf_tables.h
new file mode 100644
index 000000000..9feb3a60e
--- /dev/null
+++ b/include/lapi/nf_tables.h
@@ -0,0 +1,19 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Copyright (C) 2023 SUSE LLC <mdoucha@suse.cz>
+ */
+
+#ifndef LAPI_NF_TABLES_H__
+#define LAPI_NF_TABLES_H__
+
+#include <linux/netfilter/nf_tables.h>
+
+#ifndef HAVE_DECL_NFTA_CHAIN_ID
+# define NFTA_CHAIN_ID 11
+#endif
+
+#ifndef HAVE_DECL_NFTA_VERDICT_CHAIN_ID
+# define NFTA_VERDICT_CHAIN_ID 3
+#endif
+
+#endif /* LAPI_NF_TABLES_H__ */
diff --git a/include/lapi/readlinkat.h b/include/lapi/readlinkat.h
deleted file mode 100644
index a680deeec..000000000
--- a/include/lapi/readlinkat.h
+++ /dev/null
@@ -1,21 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
- * Copyright (c) 2014 Cyril Hrubis <chrubis@suse.cz>
- */
-
-#ifndef LAPI_READLINKAT_H__
-#define LAPI_READLINKAT_H__
-
-#include "config.h"
-#include "lapi/syscalls.h"
-#include "lapi/fcntl.h"
-
-#ifndef HAVE_READLINKAT
-static inline int readlinkat(int dirfd, const char *pathname,
- char *buf, size_t bufsiz)
-{
- return tst_syscall(__NR_readlinkat, dirfd, pathname, buf, bufsiz);
-}
-#endif
-
-#endif /* LAPI_READLINKAT_H__ */
diff --git a/include/lapi/renameat.h b/include/lapi/renameat.h
deleted file mode 100644
index abf4c1d6e..000000000
--- a/include/lapi/renameat.h
+++ /dev/null
@@ -1,23 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
- * Copyright (c) International Business Machines Corp., 2007
- * Copyright (c) 2014 Fujitsu Ltd.
- */
-
-#ifndef LAPI_RENAMEAT_H__
-#define LAPI_RENAMEAT_H__
-
-#include <sys/types.h>
-#include "config.h"
-#include "lapi/syscalls.h"
-
-#if !defined(HAVE_RENAMEAT)
-static inline int renameat(int olddirfd, const char *oldpath, int newdirfd,
- const char *newpath)
-{
- return tst_syscall(__NR_renameat, olddirfd, oldpath, newdirfd,
- newpath);
-}
-#endif
-
-#endif /* LAPI_RENAMEAT_H__ */
diff --git a/include/lapi/socket.h b/include/lapi/socket.h
index 794dee49f..23e7ba6cf 100644
--- a/include/lapi/socket.h
+++ b/include/lapi/socket.h
@@ -62,6 +62,10 @@
# define SOL_ALG 279
#endif
+#ifndef SOL_TLS
+# define SOL_TLS 282
+#endif
+
#ifndef HAVE_STRUCT_MMSGHDR
struct mmsghdr {
struct msghdr msg_hdr;
diff --git a/include/lapi/tcp.h b/include/lapi/tcp.h
index bb98f28f0..87c5636f6 100644
--- a/include/lapi/tcp.h
+++ b/include/lapi/tcp.h
@@ -12,6 +12,10 @@
# define TCP_FASTOPEN 23
#endif
+#ifndef TCP_ULP
+# define TCP_ULP 31
+#endif
+
#ifndef TCP_FASTOPEN_CONNECT
# define TCP_FASTOPEN_CONNECT 30 /* Attempt FastOpen with connect */
#endif
diff --git a/include/lapi/uinput.h b/include/lapi/uinput.h
new file mode 100644
index 000000000..bdd6f466f
--- /dev/null
+++ b/include/lapi/uinput.h
@@ -0,0 +1,15 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (c) 2023 Petr Vorel <pvorel@suse.cz>
+ */
+
+#ifndef LAPI_UINPUT_H__
+#define LAPI_UINPUT_H__
+
+#include <linux/uinput.h>
+
+#ifndef UI_GET_SYSNAME
+# define UI_GET_SYSNAME(len) _IOC(_IOC_READ, UINPUT_IOCTL_BASE, 44, len)
+#endif
+
+#endif /* LAPI_UINPUT_H__ */
diff --git a/include/mk/config.mk.in b/include/mk/config.mk.in
index 22301e126..145b887fa 100644
--- a/include/mk/config.mk.in
+++ b/include/mk/config.mk.in
@@ -75,7 +75,7 @@ LDFLAGS := @LDFLAGS@
DEBUG_CFLAGS ?= -g
-# for -fstrict-aliasing see doc/build-system-guide.txt
+# for -fstrict-aliasing see doc/Build-System.asciidoc
OPT_CFLAGS ?= -O2 -fno-strict-aliasing -pipe
WCFLAGS ?= -Wall -W @GCC_WARN_OLDSTYLE@
diff --git a/include/old/usctest.h b/include/old/usctest.h
index 9b9446d70..2d46c4045 100644
--- a/include/old/usctest.h
+++ b/include/old/usctest.h
@@ -34,16 +34,8 @@
#ifndef __USCTEST_H__
#define __USCTEST_H__
-/*
- * Ensure that PATH_MAX is defined
- */
-#ifndef PATH_MAX
-#ifdef MAXPATHLEN
-#define PATH_MAX MAXPATHLEN
-#else
-#define PATH_MAX 1024
-#endif
-#endif
+/* For PATH_MAX */
+#include <linux/limits.h>
/***********************************************************************
* The following globals are defined in parse_opts.c but must be
diff --git a/include/safe_file_ops_fn.h b/include/safe_file_ops_fn.h
index e8ed85382..aa6420d90 100644
--- a/include/safe_file_ops_fn.h
+++ b/include/safe_file_ops_fn.h
@@ -92,6 +92,6 @@ int safe_touch(const char *file, const int lineno,
/* helper functions to setup overlayfs mountpoint */
void create_overlay_dirs(void);
-int mount_overlay(const char *file, const int lineno, int skip);
+int mount_overlay(const char *file, const int lineno, int strict);
#endif /* SAFE_FILE_OPS_FN */
diff --git a/include/tst_ansi_color.h b/include/tst_ansi_color.h
index 770bf46d9..376d4ad63 100644
--- a/include/tst_ansi_color.h
+++ b/include/tst_ansi_color.h
@@ -4,14 +4,17 @@
#ifndef TST_ANSI_COLOR_H__
#define TST_ANSI_COLOR_H__
+
/*
* NOTE: these colors should match colors defined in tst_flag2color() in
* testcases/lib/tst_ansi_color.sh
*/
+
#define ANSI_COLOR_BLUE "\033[1;34m"
#define ANSI_COLOR_GREEN "\033[1;32m"
#define ANSI_COLOR_MAGENTA "\033[1;35m"
#define ANSI_COLOR_RED "\033[1;31m"
+#define ANSI_COLOR_WHITE "\033[1;37m"
#define ANSI_COLOR_YELLOW "\033[1;33m"
#define ANSI_COLOR_RESET "\033[0m"
diff --git a/include/tst_clone.h b/include/tst_clone.h
index 7b278dfa7..56f23142d 100644
--- a/include/tst_clone.h
+++ b/include/tst_clone.h
@@ -39,10 +39,6 @@ int ltp_clone(unsigned long flags, int (*fn)(void *arg), void *arg,
size_t stack_size, void *stack);
int ltp_clone7(unsigned long flags, int (*fn)(void *arg), void *arg,
size_t stack_size, void *stack, ...);
-int ltp_clone_alloc(unsigned long clone_flags, int (*fn)(void *arg),
- void *arg, size_t stacksize);
-int ltp_clone_quick(unsigned long clone_flags, int (*fn)(void *arg),
- void *arg);
void *ltp_alloc_stack(size_t size);
#define clone(...) (use_the_ltp_clone_functions__do_not_use_clone)
diff --git a/include/tst_common.h b/include/tst_common.h
index 520cca72c..b14bbae04 100644
--- a/include/tst_common.h
+++ b/include/tst_common.h
@@ -80,7 +80,7 @@
#define TST_BRK_SUPPORTS_ONLY_TCONF_TBROK(condition) \
TST_BUILD_BUG_ON(condition)
-#define TST_RES_SUPPORTS_TCONF_TFAIL_TINFO_TPASS_TWARN(condition) \
+#define TST_RES_SUPPORTS_TCONF_TDEBUG_TFAIL_TINFO_TPASS_TWARN(condition) \
TST_BUILD_BUG_ON(condition)
/* stringification */
diff --git a/include/tst_crypto.h b/include/tst_crypto.h
index ae406bd04..421e6b947 100644
--- a/include/tst_crypto.h
+++ b/include/tst_crypto.h
@@ -13,67 +13,12 @@
#define TST_CRYPTO_H
#include "lapi/cryptouser.h"
-
-/**
- * A reference to a crypto session and associated state.
- *
- * Holds state relevant to a netlink crypto connection. The seq_num is used
- * to tag each message sent to the netlink layer and is automatically
- * incremented by the tst_crypto_ functions. When the netlink layer sends a
- * response (ack) it will use the sequences number from the request.
- *
- * Some functions, such as delete ALG, may return EBUSY in which case it is
- * safe to retry them. The retries field allows you to set the number of
- * times this should be done. If set to zero the operation will only be tried
- * once. For operations which do not return EBUSY, the field is ignored.
- *
- * Use TST_CRYPTO_SESSION_INIT to statically initialize this struct with sane
- * defaults.
- */
-struct tst_crypto_session {
- /** File descriptor for the netlink socket */
- int fd;
- /** A sequence number used to identify responses from the kernel. */
- uint32_t seq_num;
- /** Number of times some operations will be retried. */
- uint32_t retries;
-};
-
-/**
- * Default static definition of tst_crypto_session.
- *
- * @relates tst_crypto_session
- */
-#define TST_CRYPTO_SESSION_INIT {\
- .fd = 0, \
- .seq_num = 0, \
- .retries = 1000 \
-}
-
-/**
- * Creates a crypto session.
- *
- * @relates tst_crypto_session
- * @param ses Session structure to use, it can be uninitialized.
- *
- * If some necessary feature is missing then it will call tst_brk() with
- * TCONF, for any other error it will use TBROK.
- */
-void tst_crypto_open(struct tst_crypto_session *ses);
-
-/**
- * Close a crypto session.
- *
- * @relates tst_crypto_session
- * @param ses The session to close.
- */
-void tst_crypto_close(struct tst_crypto_session *ses);
+#include "tst_netlink.h"
/**
* Add a crypto algorithm to a session.
*
- * @relates tst_crypto_session
- * @param ses An open session.
+ * @param ctx Initialized netlink context
* @param alg The crypto algorithm or module to add.
*
* This requests a new crypto algorithm/engine/module to be initialized by the
@@ -84,15 +29,15 @@ void tst_crypto_close(struct tst_crypto_session *ses);
* @return On success it will return 0 otherwise it will return an inverted
* error code from the crypto layer.
*/
-int tst_crypto_add_alg(struct tst_crypto_session *ses,
+int tst_crypto_add_alg(struct tst_netlink_context *ctx,
const struct crypto_user_alg *alg);
/**
* Delete a crypto algorithm from a session.
*
- * @relates tst_crypto_session
- * @param ses An open session.
+ * @param ctx Initialized netlink context
* @param alg The crypto algorithm to delete.
+ * @param retries Number of retries before giving up. Recommended value: 1000
*
* Request that the kernel remove an existing crypto algorithm. This behaves
* in a similar way to tst_crypto_add_alg() except that it is the inverse
@@ -106,7 +51,7 @@ int tst_crypto_add_alg(struct tst_crypto_session *ses,
* library, you don't need to log this error as it will already have
* been printed by tst_brk().
*/
-int tst_crypto_del_alg(struct tst_crypto_session *ses,
- const struct crypto_user_alg *alg);
+int tst_crypto_del_alg(struct tst_netlink_context *ctx,
+ const struct crypto_user_alg *alg, unsigned int retries);
#endif /* TST_CRYPTO_H */
diff --git a/include/tst_fd.h b/include/tst_fd.h
new file mode 100644
index 000000000..2183ea068
--- /dev/null
+++ b/include/tst_fd.h
@@ -0,0 +1,61 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+/*
+ * Copyright (C) 2023 Cyril Hrubis <chrubis@suse.cz>
+ */
+
+#ifndef TST_FD_H__
+#define TST_FD_H__
+
+enum tst_fd_type {
+ TST_FD_FILE,
+ TST_FD_PATH,
+ TST_FD_DIR,
+ TST_FD_DEV_ZERO,
+ TST_FD_PROC_MAPS,
+ TST_FD_PIPE_READ,
+ TST_FD_PIPE_WRITE,
+ TST_FD_UNIX_SOCK,
+ TST_FD_INET_SOCK,
+ TST_FD_EPOLL,
+ TST_FD_EVENTFD,
+ TST_FD_SIGNALFD,
+ TST_FD_TIMERFD,
+ TST_FD_PIDFD,
+ TST_FD_FANOTIFY,
+ TST_FD_INOTIFY,
+ TST_FD_USERFAULTFD,
+ TST_FD_PERF_EVENT,
+ TST_FD_IO_URING,
+ TST_FD_BPF_MAP,
+ TST_FD_FSOPEN,
+ TST_FD_FSPICK,
+ TST_FD_OPEN_TREE,
+ TST_FD_MEMFD,
+ TST_FD_MEMFD_SECRET,
+ TST_FD_MAX,
+};
+
+struct tst_fd {
+ enum tst_fd_type type;
+ int fd;
+ /* used by the library, do not touch! */
+ long priv;
+};
+
+#define TST_FD_INIT {.type = TST_FD_FILE, .fd = -1}
+
+/*
+ * Advances the iterator to the next fd type, returns zero at the end.
+ */
+int tst_fd_next(struct tst_fd *fd);
+
+#define TST_FD_FOREACH(fd) \
+ for (struct tst_fd fd = TST_FD_INIT; tst_fd_next(&fd); )
+
+/*
+ * Returns human readable name for the file descriptor type.
+ */
+const char *tst_fd_desc(struct tst_fd *fd);
+
+#endif /* TST_FD_H__ */
diff --git a/include/tst_fs.h b/include/tst_fs.h
index 769fac1e5..1dd7d32fc 100644
--- a/include/tst_fs.h
+++ b/include/tst_fs.h
@@ -6,7 +6,7 @@
#ifndef TST_FS_H__
#define TST_FS_H__
-/* man 2 statfs or kernel-source/include/linux/magic.h */
+/* man 2 statfs or kernel-source/include/uapi/linux/magic.h */
#define TST_BTRFS_MAGIC 0x9123683E
#define TST_NFS_MAGIC 0x6969
#define TST_RAMFS_MAGIC 0x858458f6
@@ -34,6 +34,9 @@
#define TST_VFAT_MAGIC 0x4d44 /* AKA MSDOS */
#define TST_EXFAT_MAGIC 0x2011BAB0UL
+/* fs/bcachefs/bcachefs_format.h */
+#define TST_BCACHE_MAGIC 0xca451a4e
+
enum tst_fill_access_pattern {
TST_FILL_BLOCKS,
TST_FILL_RANDOM
@@ -209,7 +212,10 @@ int tst_fs_in_skiplist(const char *fs_type, const char *const *skiplist);
void tst_fill_fs(const char *path, int verbose, enum tst_fill_access_pattern pattern);
/*
- * test if FIBMAP ioctl is supported
+ * Check if FIBMAP ioctl is supported.
+ * Tests needs to set .needs_root = 1 in order to avoid EPERM.
+ *
+ * @return 0: FIBMAP is supported, 1: FIBMAP is *not* supported.
*/
int tst_fibmap(const char *filename);
diff --git a/include/tst_kconfig.h b/include/tst_kconfig.h
index cc0908ea8..8b24a8380 100644
--- a/include/tst_kconfig.h
+++ b/include/tst_kconfig.h
@@ -6,6 +6,14 @@
#ifndef TST_KCONFIG_H__
#define TST_KCONFIG_H__
+/**
+ * Initialization helper macro for struct tst_kconfig_var. Requires <string.h>
+ */
+#define TST_KCONFIG_INIT(confname) { \
+ .id = confname, \
+ .id_len = strlen(confname) \
+}
+
struct tst_kconfig_var {
char id[64];
unsigned int id_len;
diff --git a/include/tst_memutils.h b/include/tst_memutils.h
index 19b593430..0dd941ced 100644
--- a/include/tst_memutils.h
+++ b/include/tst_memutils.h
@@ -58,4 +58,6 @@ void tst_enable_oom_protection(pid_t pid);
*/
void tst_disable_oom_protection(pid_t pid);
+#define TST_PRINT_MEMINFO() safe_print_file(__FILE__, __LINE__, "/proc/meminfo")
+
#endif /* TST_MEMUTILS_H__ */
diff --git a/include/tst_netdevice.h b/include/tst_netdevice.h
index 5e62ba065..8d40148a6 100644
--- a/include/tst_netdevice.h
+++ b/include/tst_netdevice.h
@@ -5,7 +5,7 @@
#ifndef TST_NETDEVICE_H
#define TST_NETDEVICE_H
-#include "tst_rtnetlink.h"
+#include "tst_netlink.h"
/* Find device index for given network interface name. */
int tst_netdev_index_by_name(const char *file, const int lineno,
@@ -132,7 +132,7 @@ int tst_netdev_remove_route_inet(const char *file, const int lineno,
int tst_netdev_add_qdisc(const char *file, const int lineno, int strict,
const char *ifname, unsigned int family, unsigned int parent,
unsigned int handle, const char *qd_kind,
- const struct tst_rtnl_attr_list *config);
+ const struct tst_netlink_attr_list *config);
#define NETDEV_ADD_QDISC(ifname, family, parent, handle, qd_kind, config) \
tst_netdev_add_qdisc(__FILE__, __LINE__, 1, (ifname), (family), \
(parent), (handle), (qd_kind), (config))
@@ -154,7 +154,7 @@ int tst_netdev_remove_qdisc(const char *file, const int lineno, int strict,
int tst_netdev_add_traffic_class(const char *file, const int lineno,
int strict, const char *ifname, unsigned int parent,
unsigned int handle, const char *qd_kind,
- const struct tst_rtnl_attr_list *config);
+ const struct tst_netlink_attr_list *config);
#define NETDEV_ADD_TRAFFIC_CLASS(ifname, parent, handle, qd_kind, config) \
tst_netdev_add_traffic_class(__FILE__, __LINE__, 1, (ifname), \
(parent), (handle), (qd_kind), (config))
@@ -173,7 +173,7 @@ int tst_netdev_remove_traffic_class(const char *file, const int lineno,
int tst_netdev_add_traffic_filter(const char *file, const int lineno,
int strict, const char *ifname, unsigned int parent,
unsigned int handle, unsigned int protocol, unsigned int priority,
- const char *f_kind, const struct tst_rtnl_attr_list *config);
+ const char *f_kind, const struct tst_netlink_attr_list *config);
#define NETDEV_ADD_TRAFFIC_FILTER(ifname, parent, handle, protocol, priority, \
f_kind, config) \
tst_netdev_add_traffic_filter(__FILE__, __LINE__, 1, (ifname), \
diff --git a/include/tst_netlink.h b/include/tst_netlink.h
index 2030ac30b..7d96fd711 100644
--- a/include/tst_netlink.h
+++ b/include/tst_netlink.h
@@ -1,11 +1,5 @@
/* SPDX-License-Identifier: GPL-2.0-or-later
- * Copyright (c) 2018 Richard Palethorpe <rpalethorpe@suse.com>
- */
-
-/**
- * @file tst_netlink.h
- *
- * Library for communicating with the kernel over the netlink interface.
+ * Copyright (c) 2021 Linux Test Project
*/
#ifndef TST_NETLINK_H
@@ -13,76 +7,129 @@
#include <linux/netlink.h>
-#ifndef NETLINK_CRYPTO
-/**
- * The netlink-crypto socket protocol.
+struct tst_netlink_context;
+
+struct tst_netlink_attr_list {
+ unsigned short type;
+ const void *data;
+ ssize_t len;
+ const struct tst_netlink_attr_list *sublist;
+};
+
+struct tst_netlink_message {
+ struct nlmsghdr *header;
+ struct nlmsgerr *err;
+ void *payload;
+ size_t payload_size;
+};
+
+extern int tst_netlink_errno;
+
+/* Open a netlink socket */
+struct tst_netlink_context *tst_netlink_create_context(const char *file,
+ const int lineno, int protocol);
+#define NETLINK_CREATE_CONTEXT(protocol) \
+ tst_netlink_create_context(__FILE__, __LINE__, (protocol))
+
+/* Free a tst_netlink_message array returned by tst_netlink_recv() */
+void tst_netlink_free_message(struct tst_netlink_message *msg);
+#define NETLINK_FREE_MESSAGE tst_netlink_free_message
+
+/* Close netlink socket */
+void tst_netlink_destroy_context(const char *file, const int lineno,
+ struct tst_netlink_context *ctx);
+#define NETLINK_DESTROY_CONTEXT(ctx) \
+ tst_netlink_destroy_context(__FILE__, __LINE__, (ctx))
+
+/* Send all messages in given buffer */
+int tst_netlink_send(const char *file, const int lineno,
+ struct tst_netlink_context *ctx);
+#define NETLINK_SEND(ctx) tst_netlink_send(__FILE__, __LINE__, (ctx))
+
+/* Send all messages in given buffer and validate kernel response */
+int tst_netlink_send_validate(const char *file, const int lineno,
+ struct tst_netlink_context *ctx);
+#define NETLINK_SEND_VALIDATE(ctx) \
+ tst_netlink_send_validate(__FILE__, __LINE__, (ctx))
+
+/* Wait until data is available for reading from the netlink socket */
+int tst_netlink_wait(struct tst_netlink_context *ctx);
+#define NETLINK_WAIT tst_netlink_wait
+
+/*
+ * Read from netlink socket and return an array of partially parsed messages.
+ * header == NULL indicates end of array.
*/
-#define NETLINK_CRYPTO 21
-#endif
-
-/** @private */
-static inline ssize_t safe_netlink_send(const char *file, const int lineno,
- int fd, const struct nlmsghdr *nh,
- const void *payload)
-{
- struct sockaddr_nl sa = { .nl_family = AF_NETLINK };
- struct iovec iov[2] = {
- {(struct nlmsghdr *)nh, sizeof(*nh)},
- {(void *)payload, nh->nlmsg_len - sizeof(*nh)}
- };
- struct msghdr msg = {
- .msg_name = &sa,
- .msg_namelen = sizeof(sa),
- .msg_iov = iov,
- .msg_iovlen = 2
- };
-
- return safe_sendmsg(file, lineno, nh->nlmsg_len, fd, &msg, 0);
-}
-
-/**
- * Sends a netlink message using safe_sendmsg().
- *
- * @param fd netlink socket file descriptor.
- * @param nl_header netlink header structure describing the message.
- * @param payload an opaque object containing the message data.
- *
- * You should set the message length, type and flags to appropriate values
- * within the nl_header object. See lib/tst_crypto.c for an example.
- *
- * @return The number of bytes sent.
+struct tst_netlink_message *tst_netlink_recv(const char *file, const int lineno,
+ struct tst_netlink_context *ctx);
+#define NETLINK_RECV(ctx) tst_netlink_recv(__FILE__, __LINE__, (ctx))
+
+/* Add new message to buffer */
+int tst_netlink_add_message(const char *file, const int lineno,
+ struct tst_netlink_context *ctx, const struct nlmsghdr *header,
+ const void *payload, size_t payload_size);
+#define NETLINK_ADD_MESSAGE(ctx, header, payload, psize) \
+ tst_netlink_add_message(__FILE__, __LINE__, (ctx), (header), \
+ (payload), (psize))
+
+/* Add arbitrary nlattr attribute to last message */
+int tst_netlink_add_attr(const char *file, const int lineno,
+ struct tst_netlink_context *ctx, unsigned short type, const void *data,
+ unsigned short len);
+#define NETLINK_ADD_ATTR(ctx, type, data, len) \
+ tst_netlink_add_attr(__FILE__, __LINE__, (ctx), (type), (data), (len))
+
+/* Add string nlattr attribute to last message */
+int tst_netlink_add_attr_string(const char *file, const int lineno,
+ struct tst_netlink_context *ctx, unsigned short type, const char *data);
+#define NETLINK_ADD_ATTR_STRING(ctx, type, data) \
+ tst_netlink_add_attr_string(__FILE__, __LINE__, (ctx), (type), (data))
+
+/*
+ * Add list of arbitrary nlattr attributes to last message. The list is
+ * terminated by attribute with negative length. Nested sublists are supported.
*/
-#define SAFE_NETLINK_SEND(fd, nl_header, payload) \
- safe_netlink_send(__FILE__, __LINE__, fd, nl_header, payload)
-
-/** @private */
-static inline ssize_t safe_netlink_recv(const char *file, const int lineno,
- int fd, char *nl_headers_buf,
- size_t buf_len)
-{
- struct iovec iov = { nl_headers_buf, buf_len };
- struct sockaddr_nl sa;
- struct msghdr msg = {
- .msg_name = &sa,
- .msg_namelen = sizeof(sa),
- .msg_iov = &iov,
- .msg_iovlen = 1
- };
-
- return safe_recvmsg(file, lineno, 0, fd, &msg, 0);
-}
-
-/**
- * Receives a netlink message using safe_recvmsg().
- *
- * @param fd netlink socket file descriptor.
- * @param nl_header_buf buffer to contain the received netlink header structure.
- * @param buf_len The length of the header buffer. Must be greater than the page
- * size.
+int tst_netlink_add_attr_list(const char *file, const int lineno,
+ struct tst_netlink_context *ctx,
+ const struct tst_netlink_attr_list *list);
+#define NETLINK_ADD_ATTR_LIST(ctx, list) \
+ tst_netlink_add_attr_list(__FILE__, __LINE__, (ctx), (list))
+
+/* Add arbitrary rtattr attribute to last message */
+int tst_rtnl_add_attr(const char *file, const int lineno,
+ struct tst_netlink_context *ctx, unsigned short type, const void *data,
+ unsigned short len);
+#define RTNL_ADD_ATTR(ctx, type, data, len) \
+ tst_rtnl_add_attr(__FILE__, __LINE__, (ctx), (type), (data), (len))
+
+/* Add string rtattr attribute to last message */
+int tst_rtnl_add_attr_string(const char *file, const int lineno,
+ struct tst_netlink_context *ctx, unsigned short type, const char *data);
+#define RTNL_ADD_ATTR_STRING(ctx, type, data) \
+ tst_rtnl_add_attr_string(__FILE__, __LINE__, (ctx), (type), (data))
+
+/*
+ * Add list of arbitrary rtattr attributes to last message. The list is
+ * terminated by attribute with negative length. Nested sublists are supported.
+ */
+int tst_rtnl_add_attr_list(const char *file, const int lineno,
+ struct tst_netlink_context *ctx,
+ const struct tst_netlink_attr_list *list);
+#define RTNL_ADD_ATTR_LIST(ctx, list) \
+ tst_rtnl_add_attr_list(__FILE__, __LINE__, (ctx), (list))
+
+/* Check that all sent messages with NLM_F_ACK flag have been acked without
+ * error. Usage:
*
- * @return The number of bytes received.
+ * tst_netlink_send(ctx);
+ * tst_netlink_wait(ctx);
+ * response = tst_netlink_recv(ctx);
+ * if (!tst_netlink_check_acks(ctx, response)) { ... }
+ * tst_netlink_free_message(response);
*/
-#define SAFE_NETLINK_RECV(fd, nl_header_buf, buf_len) \
- safe_netlink_recv(__FILE__, __LINE__, fd, nl_header_buf, buf_len)
+int tst_netlink_check_acks(const char *file, const int lineno,
+ struct tst_netlink_context *ctx, struct tst_netlink_message *response);
+#define NETLINK_CHECK_ACKS(ctx, response) \
+ tst_netlink_check_acks(__FILE__, __LINE__, (ctx), (response))
#endif /* TST_NETLINK_H */
diff --git a/include/tst_pid.h b/include/tst_pid.h
index 774c845ce..951138abc 100644
--- a/include/tst_pid.h
+++ b/include/tst_pid.h
@@ -50,4 +50,12 @@ static inline int tst_get_free_pids(void (*cleanup_fn)(void))
*/
pid_t tst_getpid(void);
+/*
+ * Direct gettid() syscall. Some glibc versions cache gettid() return value
+ * which can cause confusing issues for example in processes created by
+ * direct clone() syscall (without using the glibc wrapper). Use this function
+ * whenever the current process may be a thread of the main test process.
+ */
+pid_t tst_gettid(void);
+
#endif /* TST_PID_H__ */
diff --git a/include/tst_res_flags.h b/include/tst_res_flags.h
index 8eda2f8b8..872352144 100644
--- a/include/tst_res_flags.h
+++ b/include/tst_res_flags.h
@@ -11,6 +11,7 @@
#define TFAIL 1 /* Test failed flag */
#define TBROK 2 /* Test broken flag */
#define TWARN 4 /* Test warning flag */
+#define TDEBUG 8 /* Test debug information flag */
#define TINFO 16 /* Test information flag */
#define TCONF 32 /* Test not appropriate for configuration flag */
#define TTYPE_RESULT(ttype) ((ttype) & TTYPE_MASK)
diff --git a/include/tst_rtnetlink.h b/include/tst_rtnetlink.h
deleted file mode 100644
index 6a0c53df4..000000000
--- a/include/tst_rtnetlink.h
+++ /dev/null
@@ -1,108 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-or-later
- * Copyright (c) 2021 Linux Test Project
- */
-
-#ifndef TST_RTNETLINK_H
-#define TST_RTNETLINK_H
-
-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;
-};
-
-extern int tst_rtnl_errno;
-
-/* Open a netlink socket */
-struct tst_rtnl_context *tst_rtnl_create_context(const char *file,
- const int lineno);
-#define RTNL_CREATE_CONTEXT() tst_rtnl_create_context(__FILE__, __LINE__)
-
-/* Free a tst_rtnl_message array returned by tst_rtnl_recv() */
-void tst_rtnl_free_message(struct tst_rtnl_message *msg);
-#define RTNL_FREE_MESSAGE tst_rtnl_free_message
-
-/* Close netlink socket */
-void tst_rtnl_destroy_context(const char *file, const int lineno,
- struct tst_rtnl_context *ctx);
-#define RTNL_DESTROY_CONTEXT(ctx) \
- tst_rtnl_destroy_context(__FILE__, __LINE__, (ctx))
-
-/* Send all messages in given buffer */
-int tst_rtnl_send(const char *file, const int lineno,
- struct tst_rtnl_context *ctx);
-#define RTNL_SEND(ctx) tst_rtnl_send(__FILE__, __LINE__, (ctx))
-
-/* Send all messages in given buffer and validate kernel response */
-int tst_rtnl_send_validate(const char *file, const int lineno,
- struct tst_rtnl_context *ctx);
-#define RTNL_SEND_VALIDATE(ctx) \
- tst_rtnl_send_validate(__FILE__, __LINE__, (ctx))
-
-/* Wait until data is available for reading from the netlink socket */
-int tst_rtnl_wait(struct tst_rtnl_context *ctx);
-#define RTNL_WAIT tst_rtnl_wait
-
-/*
- * Read from netlink socket and return an array of partially parsed messages.
- * header == NULL indicates end of array.
- */
-struct tst_rtnl_message *tst_rtnl_recv(const char *file, const int lineno,
- struct tst_rtnl_context *ctx);
-#define RTNL_RECV(ctx) tst_rtnl_recv(__FILE__, __LINE__, (ctx))
-
-/* Add new message to buffer */
-int tst_rtnl_add_message(const char *file, const int lineno,
- struct tst_rtnl_context *ctx, const struct nlmsghdr *header,
- const void *payload, size_t payload_size);
-#define RTNL_ADD_MESSAGE(ctx, header, payload, psize) \
- tst_rtnl_add_message(__FILE__, __LINE__, (ctx), (header), (payload), \
- (psize))
-
-/* Add arbitrary attribute to last message */
-int tst_rtnl_add_attr(const char *file, const int lineno,
- struct tst_rtnl_context *ctx, unsigned short type, const void *data,
- unsigned short len);
-#define RTNL_ADD_ATTR(ctx, type, data, len) \
- tst_rtnl_add_attr(__FILE__, __LINE__, (ctx), (type), (data), (len))
-
-/* Add string attribute to last message */
-int tst_rtnl_add_attr_string(const char *file, const int lineno,
- struct tst_rtnl_context *ctx, unsigned short type, const char *data);
-#define RTNL_ADD_ATTR_STRING(ctx, type, data) \
- tst_rtnl_add_attr_string(__FILE__, __LINE__, (ctx), (type), (data))
-
-/*
- * Add list of arbitrary attributes to last message. The list is terminated
- * by attribute with negative length. Nested sublists are supported.
- */
-int tst_rtnl_add_attr_list(const char *file, const int lineno,
- struct tst_rtnl_context *ctx, const struct tst_rtnl_attr_list *list);
-#define RTNL_ADD_ATTR_LIST(ctx, list) \
- tst_rtnl_add_attr_list(__FILE__, __LINE__, (ctx), (list))
-
-/* Check that all sent messages with NLM_F_ACK flag have been acked without
- * error. Usage:
- *
- * tst_rtnl_send(ctx);
- * tst_rtnl_wait(ctx);
- * response = tst_rtnl_recv(ctx);
- * if (!tst_rtnl_check_acks(ctx, response)) { ... }
- * tst_rtnl_free_message(response);
- */
-int tst_rtnl_check_acks(const char *file, const int lineno,
- struct tst_rtnl_context *ctx, struct tst_rtnl_message *response);
-#define RTNL_CHECK_ACKS(ctx, response) \
- tst_rtnl_context(__FILE__, __LINE__, (ctx), (response))
-
-#endif /* TST_RTNETLINK_H */
diff --git a/include/tst_safe_macros.h b/include/tst_safe_macros.h
index 0cf3d7878..f2ce8919b 100644
--- a/include/tst_safe_macros.h
+++ b/include/tst_safe_macros.h
@@ -21,6 +21,7 @@
#include <dirent.h>
#include <grp.h>
+#include "safe_stdio_fn.h"
#include "safe_macros_fn.h"
#include "tst_cmd.h"
@@ -86,6 +87,12 @@ void *safe_realloc(const char *file, const int lineno, void *ptr, size_t size);
#define SAFE_MUNMAP(addr, length) \
safe_munmap(__FILE__, __LINE__, NULL, (addr), (length))
+int safe_msync(const char *file, const int lineno, void *addr,
+ size_t length, int flags);
+
+#define SAFE_MSYNC(addr, length, flags) \
+ safe_msync(__FILE__, __LINE__, (addr), (length), (flags))
+
#define SAFE_OPEN(pathname, oflags, ...) \
safe_open(__FILE__, __LINE__, NULL, (pathname), (oflags), \
##__VA_ARGS__)
@@ -665,4 +672,6 @@ int safe_sysinfo(const char *file, const int lineno, struct sysinfo *info);
#define SAFE_SYSINFO(info) \
safe_sysinfo(__FILE__, __LINE__, (info))
+void safe_print_file(const char *file, const int lineno, char *path);
+
#endif /* SAFE_MACROS_H__ */
diff --git a/include/tst_test.h b/include/tst_test.h
index 75c2109b9..fda696eeb 100644
--- a/include/tst_test.h
+++ b/include/tst_test.h
@@ -44,6 +44,7 @@
#include "tst_taint.h"
#include "tst_memutils.h"
#include "tst_arch.h"
+#include "tst_fd.h"
/*
* Reports testcase result.
@@ -54,8 +55,9 @@ void tst_res_(const char *file, const int lineno, int ttype,
#define tst_res(ttype, arg_fmt, ...) \
({ \
- TST_RES_SUPPORTS_TCONF_TFAIL_TINFO_TPASS_TWARN(!((TTYPE_RESULT(ttype) ?: TCONF) & \
- (TCONF | TFAIL | TINFO | TPASS | TWARN))); \
+ TST_RES_SUPPORTS_TCONF_TDEBUG_TFAIL_TINFO_TPASS_TWARN(\
+ !((TTYPE_RESULT(ttype) ?: TCONF) & \
+ (TCONF | TDEBUG | TFAIL | TINFO | TPASS | TWARN))); \
tst_res_(__FILE__, __LINE__, (ttype), (arg_fmt), ##__VA_ARGS__);\
})
diff --git a/include/tst_test_macros.h b/include/tst_test_macros.h
index bd0c491c1..d2e50a219 100644
--- a/include/tst_test_macros.h
+++ b/include/tst_test_macros.h
@@ -1,12 +1,14 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/*
- * Copyright (c) 2015-2020 Cyril Hrubis <chrubis@suse.cz>
+ * Copyright (c) 2015-2024 Cyril Hrubis <chrubis@suse.cz>
* Copyright (c) Linux Test Project, 2021-2022
*/
#ifndef TST_TEST_MACROS_H__
#define TST_TEST_MACROS_H__
+#include <stdbool.h>
+
#define TEST(SCALL) \
do { \
errno = 0; \
@@ -73,9 +75,9 @@ extern void *TST_RET_PTR;
\
} while (0)
-#define TST_EXP_POSITIVE_(SCALL, ...) \
+#define TST_EXP_POSITIVE_(SCALL, SSCALL, ...) \
({ \
- TST_EXP_POSITIVE__(SCALL, #SCALL, ##__VA_ARGS__); \
+ TST_EXP_POSITIVE__(SCALL, SSCALL, ##__VA_ARGS__); \
TST_RET; \
})
@@ -186,7 +188,18 @@ extern void *TST_RET_PTR;
TST_MSG_(TPASS, " passed", #SCALL, ##__VA_ARGS__); \
} while (0) \
-#define TST_EXP_FAIL_SILENT_(PASS_COND, SCALL, SSCALL, ERRNO, ...) \
+/*
+ * Returns true if err is in the exp_err array.
+ */
+bool tst_errno_in_set(int err, const int *exp_errs, int exp_errs_cnt);
+
+/*
+ * Fills in the buf with the errno names in the exp_err set. The buf must be at
+ * least 20 * exp_errs_cnt bytes long.
+ */
+const char *tst_errno_names(char *buf, const int *exp_errs, int exp_errs_cnt);
+
+#define TST_EXP_FAIL_SILENT_(PASS_COND, SCALL, SSCALL, ERRNOS, ERRNOS_CNT, ...)\
do { \
TEST(SCALL); \
\
@@ -203,36 +216,68 @@ extern void *TST_RET_PTR;
break; \
} \
\
- if (TST_ERR == (ERRNO)) { \
+ if (tst_errno_in_set(TST_ERR, ERRNOS, ERRNOS_CNT)) { \
TST_PASS = 1; \
} else { \
+ char tst_str_buf__[ERRNOS_CNT * 20]; \
TST_MSGP_(TFAIL | TTERRNO, " expected %s", \
- tst_strerrno(ERRNO), \
+ tst_errno_names(tst_str_buf__, \
+ ERRNOS, ERRNOS_CNT), \
SSCALL, ##__VA_ARGS__); \
} \
} while (0)
-#define TST_EXP_FAIL(SCALL, ERRNO, ...) \
+#define TST_EXP_FAIL_ARR_(SCALL, SSCALL, EXP_ERRS, EXP_ERRS_CNT, ...) \
do { \
- TST_EXP_FAIL_SILENT_(TST_RET == 0, SCALL, #SCALL, \
- ERRNO, ##__VA_ARGS__); \
+ TST_EXP_FAIL_SILENT_(TST_RET == 0, SCALL, SSCALL, \
+ EXP_ERRS, EXP_ERRS_CNT, ##__VA_ARGS__); \
if (TST_PASS) \
- TST_MSG_(TPASS | TTERRNO, " ", #SCALL, ##__VA_ARGS__); \
+ TST_MSG_(TPASS | TTERRNO, " ", SSCALL, ##__VA_ARGS__); \
} while (0)
-#define TST_EXP_FAIL2(SCALL, ERRNO, ...) \
+#define TST_EXP_FAIL(SCALL, EXP_ERR, ...) \
do { \
- TST_EXP_FAIL_SILENT_(TST_RET >= 0, SCALL, #SCALL, \
- ERRNO, ##__VA_ARGS__); \
+ int tst_exp_err__ = EXP_ERR; \
+ TST_EXP_FAIL_ARR_(SCALL, #SCALL, &tst_exp_err__, 1, \
+ ##__VA_ARGS__); \
+ } while (0)
+
+#define TST_EXP_FAIL_ARR(SCALL, EXP_ERRS, ...) \
+ TST_EXP_FAIL_ARR_(SCALL, #SCALL, EXP_ERRS, \
+ ARRAY_SIZE(EXP_ERRS), ##__VA_ARGS__);
+
+#define TST_EXP_FAIL2_ARR_(SCALL, SSCALL, EXP_ERRS, EXP_ERRS_CNT, ...) \
+ do { \
+ TST_EXP_FAIL_SILENT_(TST_RET >= 0, SCALL, SSCALL, \
+ EXP_ERRS, EXP_ERRS_CNT, ##__VA_ARGS__); \
if (TST_PASS) \
- TST_MSG_(TPASS | TTERRNO, " ", #SCALL, ##__VA_ARGS__); \
+ TST_MSG_(TPASS | TTERRNO, " ", SSCALL, ##__VA_ARGS__); \
+ } while (0)
+
+#define TST_EXP_FAIL2_ARR(SCALL, EXP_ERRS, ...) \
+ TST_EXP_FAIL2_ARR_(SCALL, #SCALL, EXP_ERRS, \
+ ARRAY_SIZE(EXP_ERRS), ##__VA_ARGS__);
+
+#define TST_EXP_FAIL2(SCALL, EXP_ERR, ...) \
+ do { \
+ int tst_exp_err__ = EXP_ERR; \
+ TST_EXP_FAIL2_ARR_(SCALL, #SCALL, &tst_exp_err__, 1, \
+ ##__VA_ARGS__); \
} while (0)
-#define TST_EXP_FAIL_SILENT(SCALL, ERRNO, ...) \
- TST_EXP_FAIL_SILENT_(TST_RET == 0, SCALL, #SCALL, ERRNO, ##__VA_ARGS__)
+#define TST_EXP_FAIL_SILENT(SCALL, EXP_ERR, ...) \
+ do { \
+ int tst_exp_err__ = EXP_ERR; \
+ TST_EXP_FAIL_SILENT_(TST_RET == 0, SCALL, #SCALL, \
+ &tst_exp_err__, 1, ##__VA_ARGS__); \
+ } while (0)
-#define TST_EXP_FAIL2_SILENT(SCALL, ERRNO, ...) \
- TST_EXP_FAIL_SILENT_(TST_RET >= 0, SCALL, #SCALL, ERRNO, ##__VA_ARGS__)
+#define TST_EXP_FAIL2_SILENT(SCALL, EXP_ERR, ...) \
+ do { \
+ int tst_exp_err__ = EXP_ERR; \
+ TST_EXP_FAIL_SILENT_(TST_RET >= 0, SCALL, #SCALL, \
+ &tst_exp_err__, 1, ##__VA_ARGS__); \
+ } while (0)
#define TST_EXP_EXPR(EXPR, FMT, ...) \
tst_res_(__FILE__, __LINE__, (EXPR) ? TPASS : TFAIL, "Expect: " FMT, ##__VA_ARGS__);
diff --git a/lib/README.md b/lib/README.md
index ccb1cf1da..8340de0dd 100644
--- a/lib/README.md
+++ b/lib/README.md
@@ -27,16 +27,16 @@
When a test is executed the very first thing to happen is that we check for
various test prerequisites. These are described in the tst\_test structure and
-range from simple '.require\_root' to a more complicated kernel .config boolean
+range from simple '.needs\_root' to a more complicated kernel .config boolean
expressions such as: "CONFIG\_X86\_INTEL\_UMIP=y | CONFIG\_X86\_UMIP=y".
-If all checks are passed the process carries on with setting up the test
+If all checks are passed, the process continues with setting up the test
environment as requested in the tst\_test structure. There are many different
setup steps that have been put into the test library again ranging from rather
simple creation of a unique test temporary directory to a bit more complicated
ones such as preparing, formatting, and mounting a block device.
-The test library also intializes shrared memory used for IPC at this step.
+The test library also initializes shared memory used for IPC at this step.
Once all the prerequisites are checked and test environment has been prepared
we can move on executing the testcase itself. The actual test is executed in a
@@ -62,9 +62,9 @@ for test_variants:
fork_testrun()
```
-Before we fork() the test process the test library sets up a timeout alarm and
-also a heartbeat signal handlers and also sets up an alarm(2) accordingly to
-the test timeout. When a test times out the test library gets SIGALRM and the
+Before we fork the test process, the test library sets up a timeout alarm and
+a heartbeat signal handler and it also sets up an alarm(2) accordingly to
+the test timeout. When a test times out, the test library gets SIGALRM and the
alarm handler mercilessly kills all forked children by sending SIGKILL to the
whole process group. The heartbeat handler is used by the test process to reset
this timer for example when the test functions run in a loop.
@@ -97,14 +97,14 @@ usually better option than exiting it in the middle.
The test cleanup() is also called by the tst\_brk() handler in order to cleanup
before exiting the test process, hence it must be able to cope even with
partial test setup. Usually it suffices to make sure to clean up only
-resources that already have been set up and to do that in an inverse order that
-we did in setup().
+resources that already have been set up and to do that in the reverse order
+that we did in setup().
Once the test process exits or leaves the run() or run\_all() function the test
library wakes up from the waitpid() call, and checks if the test process
exited normally.
-Once the testrun is finished the test library does a cleanup() as well to clean
+Once the testrun is finished, the test library does a cleanup() as well to clean
up resources set up in the test library setup(), reports test results and
finally exits the process.
@@ -126,8 +126,8 @@ This especially means that:
- While the test results are, by the design, propagated to the test library
we may still miss a child that gets killed by a signal or exits unexpectedly.
-The test writer should, because of this, take care for reaping these proceses
-properly, in most cases this could be simply done by calling
+The test writer should, because of this, take care of reaping these
+processes properly, in most cases this could be simply done by calling
tst\_reap\_children() to collect and dissect deceased.
Also note that tst\_brk() does exit only the current process, so if a child
@@ -136,9 +136,9 @@ exits.
### Test library and exec()
-The piece of mapped memory to store the results to is not preserved over
+The piece of mapped memory to store the results is not preserved over
exec(2), hence to use the test library from a binary started by an exec() it
-has to be remaped. In this case the process must to call tst\_reinit() before
+has to be remapped. In this case, the process must call tst\_reinit() before
calling any other library functions. In order to make this happen the program
environment carries LTP\_IPC\_PATH variable with a path to the backing file on
tmpfs. This also allows us to use the test library from shell testcases.
@@ -148,5 +148,5 @@ tmpfs. This also allows us to use the test library from shell testcases.
The piece of mapped memory is also used as a base for a futex-based
synchronization primitives called checkpoints. And as said previously the
memory can be mapped to any process by calling the tst\_reinit() function. As a
-matter of a fact there is even a tst\_checkpoint binary that allows us to use
+matter of a fact, there is even a tst\_checkpoint binary that allows us to use
the checkpoints from shell code as well.
diff --git a/lib/cloner.c b/lib/cloner.c
index 95954f6df..00cbb8987 100644
--- a/lib/cloner.c
+++ b/lib/cloner.c
@@ -124,42 +124,3 @@ void *ltp_alloc_stack(size_t size)
return ret;
}
-
-/*
- * ltp_clone_alloc: also does the memory allocation for clone with a
- * caller-specified size.
- */
-int
-ltp_clone_alloc(unsigned long clone_flags, int (*fn) (void *arg), void *arg,
- size_t stack_size)
-{
- void *stack;
- int ret;
- int saved_errno;
-
- stack = ltp_alloc_stack(stack_size);
- if (stack == NULL)
- return -1;
-
- ret = ltp_clone(clone_flags, fn, arg, stack_size, stack);
-
- if (ret == -1) {
- saved_errno = errno;
- free(stack);
- errno = saved_errno;
- }
-
- return ret;
-}
-
-/*
- * ltp_clone_quick: calls ltp_clone_alloc with predetermined stack size.
- * Experience thus far suggests that one page is often insufficient,
- * while 6*getpagesize() seems adequate.
- */
-int ltp_clone_quick(unsigned long clone_flags, int (*fn) (void *arg), void *arg)
-{
- size_t stack_size = getpagesize() * 6;
-
- return ltp_clone_alloc(clone_flags, fn, arg, stack_size);
-}
diff --git a/lib/newlib_tests/.gitignore b/lib/newlib_tests/.gitignore
index 0256bef76..a69b29e24 100644
--- a/lib/newlib_tests/.gitignore
+++ b/lib/newlib_tests/.gitignore
@@ -56,3 +56,4 @@ tst_needs_cmds08
test_runtime01
test_runtime02
test_children_cleanup
+tst_res_flags
diff --git a/lib/newlib_tests/shell/tst_res_flags.sh b/lib/newlib_tests/shell/tst_res_flags.sh
new file mode 100755
index 000000000..bca3d26c0
--- /dev/null
+++ b/lib/newlib_tests/shell/tst_res_flags.sh
@@ -0,0 +1,24 @@
+#!/bin/sh
+# SPDX-License-Identifier: GPL-2.0-or-later
+# Copyright (c) 2023 Petr Vorel <pvorel@suse.cz>
+
+TST_TESTFUNC=test
+TST_CLEANUP=cleanup
+
+test()
+{
+ tst_res TPASS "TPASS message"
+ tst_res TFAIL "TFAIL message"
+ tst_res TBROK "TBROK message"
+ tst_res TCONF "TCONF message"
+ tst_res TWARN "TWARN message"
+ tst_res TINFO "TINFO message"
+}
+
+cleanup()
+{
+ tst_brk TBROK "TBROK message should be TWARN in cleanup"
+}
+
+. tst_test.sh
+tst_run
diff --git a/lib/newlib_tests/test_macros02.c b/lib/newlib_tests/test_macros02.c
index 647f73682..6c1ca7a8a 100644
--- a/lib/newlib_tests/test_macros02.c
+++ b/lib/newlib_tests/test_macros02.c
@@ -27,6 +27,9 @@ static int inval_ret_fn(void)
static void do_test(void)
{
+ const int exp_errs_pass[] = {ENOTTY, EINVAL};
+ const int exp_errs_fail[] = {ENOTTY, EISDIR};
+
tst_res(TINFO, "Testing TST_EXP_FAIL macro");
TST_EXP_FAIL(fail_fn(), EINVAL, "fail_fn()");
tst_res(TINFO, "TST_PASS = %i", TST_PASS);
@@ -36,6 +39,10 @@ static void do_test(void)
tst_res(TINFO, "TST_PASS = %i", TST_PASS);
TST_EXP_FAIL(inval_ret_fn(), ENOTTY, "inval_ret_fn()");
tst_res(TINFO, "TST_PASS = %i", TST_PASS);
+ TST_EXP_FAIL_ARR(fail_fn(), exp_errs_pass, "fail_fn()");
+ tst_res(TINFO, "TST_PASS = %i", TST_PASS);
+ TST_EXP_FAIL_ARR(fail_fn(), exp_errs_fail, "fail_fn()");
+ tst_res(TINFO, "TST_PASS = %i", TST_PASS);
tst_res(TINFO, "Testing TST_EXP_FAIL2 macro");
TST_EXP_FAIL2(fail_fn(), EINVAL, "fail_fn()");
@@ -46,6 +53,10 @@ static void do_test(void)
tst_res(TINFO, "TST_PASS = %i", TST_PASS);
TST_EXP_FAIL2(inval_ret_fn(), ENOTTY, "inval_ret_fn()");
tst_res(TINFO, "TST_PASS = %i", TST_PASS);
+ TST_EXP_FAIL2_ARR(fail_fn(), exp_errs_pass, "fail_fn()");
+ tst_res(TINFO, "TST_PASS = %i", TST_PASS);
+ TST_EXP_FAIL2_ARR(fail_fn(), exp_errs_fail, "fail_fn()");
+ tst_res(TINFO, "TST_PASS = %i", TST_PASS);
}
static struct tst_test test = {
diff --git a/lib/newlib_tests/tst_res_flags.c b/lib/newlib_tests/tst_res_flags.c
new file mode 100644
index 000000000..a14f0df2c
--- /dev/null
+++ b/lib/newlib_tests/tst_res_flags.c
@@ -0,0 +1,44 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (c) 2023 Petr Vorel <pvorel@suse.cz>
+ */
+
+/*
+ * Test tst_res() flags.
+ */
+
+#include "tst_test.h"
+
+#define FLAG(x) .flag = x, .str = #x
+static struct tcase {
+ int flag;
+ const char *str;
+ const char *note;
+} tcases[] = {
+ {FLAG(TPASS)},
+ {FLAG(TFAIL)},
+ {FLAG(TBROK)},
+ {FLAG(TCONF)},
+ {FLAG(TWARN)},
+ {FLAG(TINFO)},
+ {FLAG(TDEBUG), " (printed only with -D or LTP_ENABLE_DEBUG=1)"},
+};
+
+static void do_cleanup(void)
+{
+ tst_brk(TBROK, "TBROK message should be TWARN in cleanup");
+}
+
+static void do_test(void)
+{
+ size_t i;
+
+ for (i = 0; i < ARRAY_SIZE(tcases); i++)
+ tst_res(tcases[i].flag, "%s message%s", tcases[i].str,
+ tcases[i].note ?: "");
+}
+
+static struct tst_test test = {
+ .test_all = do_test,
+ .cleanup = do_cleanup,
+};
diff --git a/lib/tlibio.c b/lib/tlibio.c
index 2ecdbb42a..bfb4ea023 100644
--- a/lib/tlibio.c
+++ b/lib/tlibio.c
@@ -114,7 +114,7 @@
#endif
#include <stdlib.h> /* atoi, abs */
-#include "tlibio.h" /* defines LIO* marcos */
+#include "tlibio.h" /* defines LIO* macros */
#include "random_range.h"
#ifndef PATH_MAX
diff --git a/lib/tst_ansi_color.c b/lib/tst_ansi_color.c
index 1c29268f2..98041c0af 100644
--- a/lib/tst_ansi_color.c
+++ b/lib/tst_ansi_color.c
@@ -31,6 +31,9 @@ char* tst_ttype2color(int ttype)
case TINFO:
return ANSI_COLOR_BLUE;
break;
+ case TDEBUG:
+ return ANSI_COLOR_WHITE;
+ break;
default:
return "";
}
diff --git a/lib/tst_cgroup.c b/lib/tst_cgroup.c
index 6e9ab372d..a8a598e0e 100644
--- a/lib/tst_cgroup.c
+++ b/lib/tst_cgroup.c
@@ -15,7 +15,6 @@
#include "tst_test.h"
#include "lapi/fcntl.h"
#include "lapi/mount.h"
-#include "lapi/mkdirat.h"
#include "tst_safe_file_at.h"
struct cgroup_root;
diff --git a/lib/tst_crypto.c b/lib/tst_crypto.c
index c01632c2a..4495d0baa 100644
--- a/lib/tst_crypto.c
+++ b/lib/tst_crypto.c
@@ -10,102 +10,42 @@
#define TST_NO_DEFAULT_MAIN
#include "tst_test.h"
#include "tst_crypto.h"
-#include "tst_netlink.h"
-void tst_crypto_open(struct tst_crypto_session *ses)
-{
- const long ret = socket(AF_NETLINK, SOCK_DGRAM, NETLINK_CRYPTO);
-
- if (ret < 0 && errno == EPROTONOSUPPORT)
- tst_brk(TCONF | TERRNO, "NETLINK_CRYPTO is probably disabled");
-
- if (ret < 0) {
- tst_brk(TBROK | TERRNO,
- "socket(AF_NETLINK, SOCK_DGRAM, NETLINK_CRYPTO)");
- }
-
- ses->fd = ret;
- ses->seq_num = 0;
-}
-
-void tst_crypto_close(struct tst_crypto_session *ses)
-{
- SAFE_CLOSE(ses->fd);
-}
-
-static int tst_crypto_recv_ack(struct tst_crypto_session *ses)
-{
- uint32_t len;
- char buf[BUFSIZ];
- struct nlmsghdr *nh;
-
- len = SAFE_NETLINK_RECV(ses->fd, buf, sizeof(buf));
-
- for (nh = (struct nlmsghdr *) buf;
- NLMSG_OK(nh, len);
- nh = NLMSG_NEXT(nh, len)) {
- if (nh->nlmsg_seq != ses->seq_num) {
- tst_brk(TBROK,
- "Message out of sequence; type=0%hx, seq_num=%u (not %u)",
- nh->nlmsg_type, nh->nlmsg_seq, ses->seq_num);
- }
-
- /* Acks use the error message type with error number set to
- * zero. Ofcourse we could also receive an actual error.
- */
- if (nh->nlmsg_type == NLMSG_ERROR)
- return ((struct nlmsgerr *)NLMSG_DATA(nh))->error;
-
- tst_brk(TBROK, "Unexpected message type; type=0x%hx, seq_num=%u",
- nh->nlmsg_type, nh->nlmsg_seq);
- }
-
- tst_brk(TBROK, "Empty message from netlink socket?");
-
- return ENODATA;
-}
-
-int tst_crypto_add_alg(struct tst_crypto_session *ses,
+int tst_crypto_add_alg(struct tst_netlink_context *ctx,
const struct crypto_user_alg *alg)
{
struct nlmsghdr nh = {
- .nlmsg_len = sizeof(struct nlmsghdr) + sizeof(*alg),
.nlmsg_type = CRYPTO_MSG_NEWALG,
.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK,
- .nlmsg_seq = ++(ses->seq_num),
- .nlmsg_pid = 0,
};
- SAFE_NETLINK_SEND(ses->fd, &nh, alg);
-
- return tst_crypto_recv_ack(ses);
+ NETLINK_ADD_MESSAGE(ctx, &nh, alg, sizeof(struct crypto_user_alg));
+ return NETLINK_SEND_VALIDATE(ctx) ? 0 : -tst_netlink_errno;
}
-int tst_crypto_del_alg(struct tst_crypto_session *ses,
- const struct crypto_user_alg *alg)
+int tst_crypto_del_alg(struct tst_netlink_context *ctx,
+ const struct crypto_user_alg *alg, unsigned int retries)
{
- long ret;
+ int ret;
unsigned int i = 0;
struct nlmsghdr nh = {
- .nlmsg_len = sizeof(struct nlmsghdr) + sizeof(*alg),
.nlmsg_type = CRYPTO_MSG_DELALG,
.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK,
- .nlmsg_pid = 0,
};
- while (1) {
- nh.nlmsg_seq = ++(ses->seq_num),
+ for (i = 0; i < retries; i++) {
+ NETLINK_ADD_MESSAGE(ctx, &nh, alg,
+ sizeof(struct crypto_user_alg));
- SAFE_NETLINK_SEND(ses->fd, &nh, alg);
+ if (NETLINK_SEND_VALIDATE(ctx))
+ return 0;
- ret = tst_crypto_recv_ack(ses);
- if (ret != -EBUSY || i >= ses->retries)
- break;
+ ret = -tst_netlink_errno;
- if (usleep(1) && errno != EINTR)
- tst_brk(TBROK | TERRNO, "usleep(1)");
+ if (ret != -EBUSY)
+ break;
- ++i;
+ usleep(1);
}
return ret;
diff --git a/lib/tst_fd.c b/lib/tst_fd.c
new file mode 100644
index 000000000..b3d43a7c3
--- /dev/null
+++ b/lib/tst_fd.c
@@ -0,0 +1,325 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+/*
+ * Copyright (C) 2023 Cyril Hrubis <chrubis@suse.cz>
+ */
+
+#define TST_NO_DEFAULT_MAIN
+
+#include <sys/epoll.h>
+#include <sys/eventfd.h>
+#include <sys/signalfd.h>
+#include <sys/timerfd.h>
+#include <sys/fanotify.h>
+#include <sys/inotify.h>
+#include <linux/perf_event.h>
+
+#include "tst_test.h"
+#include "tst_safe_macros.h"
+
+#include "lapi/pidfd.h"
+#include "lapi/io_uring.h"
+#include "lapi/bpf.h"
+#include "lapi/fsmount.h"
+
+#include "tst_fd.h"
+
+struct tst_fd_desc {
+ void (*open_fd)(struct tst_fd *fd);
+ void (*destroy)(struct tst_fd *fd);
+ const char *desc;
+};
+
+static void open_file(struct tst_fd *fd)
+{
+ fd->fd = SAFE_OPEN("fd_file", O_RDWR | O_CREAT, 0666);
+ SAFE_UNLINK("fd_file");
+}
+
+static void open_path(struct tst_fd *fd)
+{
+ int tfd;
+
+ tfd = SAFE_CREAT("fd_file", 0666);
+ SAFE_CLOSE(tfd);
+
+ fd->fd = SAFE_OPEN("fd_file", O_PATH);
+
+ SAFE_UNLINK("fd_file");
+}
+
+static void open_dir(struct tst_fd *fd)
+{
+ SAFE_MKDIR("fd_dir", 0700);
+ fd->fd = SAFE_OPEN("fd_dir", O_DIRECTORY);
+ SAFE_RMDIR("fd_dir");
+}
+
+static void open_dev_zero(struct tst_fd *fd)
+{
+ fd->fd = SAFE_OPEN("/dev/zero", O_RDONLY);
+}
+
+static void open_proc_self_maps(struct tst_fd *fd)
+{
+ fd->fd = SAFE_OPEN("/proc/self/maps", O_RDONLY);
+}
+
+static void open_pipe_read(struct tst_fd *fd)
+{
+ int pipe[2];
+
+ SAFE_PIPE(pipe);
+ fd->fd = pipe[0];
+ fd->priv = pipe[1];
+}
+
+static void open_pipe_write(struct tst_fd *fd)
+{
+ int pipe[2];
+
+ SAFE_PIPE(pipe);
+ fd->fd = pipe[1];
+ fd->priv = pipe[0];
+}
+
+static void destroy_pipe(struct tst_fd *fd)
+{
+ SAFE_CLOSE(fd->priv);
+}
+
+static void open_unix_sock(struct tst_fd *fd)
+{
+ fd->fd = SAFE_SOCKET(AF_UNIX, SOCK_STREAM, 0);
+}
+
+static void open_inet_sock(struct tst_fd *fd)
+{
+ fd->fd = SAFE_SOCKET(AF_INET, SOCK_STREAM, 0);
+}
+
+static void open_epoll(struct tst_fd *fd)
+{
+ fd->fd = epoll_create(1);
+
+ if (fd->fd < 0)
+ tst_res(TCONF | TERRNO, "epoll_create()");
+}
+
+static void open_eventfd(struct tst_fd *fd)
+{
+ fd->fd = eventfd(0, 0);
+
+ if (fd->fd < 0)
+ tst_res(TCONF | TERRNO, "Skipping %s", tst_fd_desc(fd));
+}
+
+static void open_signalfd(struct tst_fd *fd)
+{
+ sigset_t sfd_mask;
+
+ sigemptyset(&sfd_mask);
+
+ fd->fd = signalfd(-1, &sfd_mask, 0);
+ if (fd->fd < 0) {
+ tst_res(TCONF | TERRNO,
+ "Skipping %s", tst_fd_desc(fd));
+ }
+}
+
+static void open_timerfd(struct tst_fd *fd)
+{
+ fd->fd = timerfd_create(CLOCK_REALTIME, 0);
+
+ if (fd->fd < 0) {
+ tst_res(TCONF | TERRNO,
+ "Skipping %s", tst_fd_desc(fd));
+ }
+}
+
+static void open_pidfd(struct tst_fd *fd)
+{
+ fd->fd = syscall(__NR_pidfd_open, getpid(), 0);
+ if (fd->fd < 0)
+ tst_res(TCONF | TERRNO, "pidfd_open()");
+}
+
+static void open_fanotify(struct tst_fd *fd)
+{
+ fd->fd = fanotify_init(FAN_CLASS_NOTIF, O_RDONLY);
+ if (fd->fd < 0) {
+ tst_res(TCONF | TERRNO,
+ "Skipping %s", tst_fd_desc(fd));
+ }
+}
+
+static void open_inotify(struct tst_fd *fd)
+{
+ fd->fd = inotify_init();
+ if (fd->fd < 0) {
+ tst_res(TCONF | TERRNO,
+ "Skipping %s", tst_fd_desc(fd));
+ }
+}
+
+static void open_userfaultfd(struct tst_fd *fd)
+{
+ fd->fd = syscall(__NR_userfaultfd, 0);
+
+ if (fd->fd < 0) {
+ tst_res(TCONF | TERRNO,
+ "Skipping %s", tst_fd_desc(fd));
+ }
+}
+
+static void open_perf_event(struct tst_fd *fd)
+{
+ struct perf_event_attr pe_attr = {
+ .type = PERF_TYPE_SOFTWARE,
+ .size = sizeof(struct perf_event_attr),
+ .config = PERF_COUNT_SW_CPU_CLOCK,
+ .disabled = 1,
+ .exclude_kernel = 1,
+ .exclude_hv = 1,
+ };
+
+ fd->fd = syscall(__NR_perf_event_open, &pe_attr, 0, -1, -1, 0);
+ if (fd->fd < 0) {
+ tst_res(TCONF | TERRNO,
+ "Skipping %s", tst_fd_desc(fd));
+ }
+}
+
+static void open_io_uring(struct tst_fd *fd)
+{
+ struct io_uring_params uring_params = {};
+
+ fd->fd = syscall(__NR_io_uring_setup, 1, &uring_params);
+ if (fd->fd < 0) {
+ tst_res(TCONF | TERRNO,
+ "Skipping %s", tst_fd_desc(fd));
+ }
+}
+
+static void open_bpf_map(struct tst_fd *fd)
+{
+ union bpf_attr array_attr = {
+ .map_type = BPF_MAP_TYPE_ARRAY,
+ .key_size = 4,
+ .value_size = 8,
+ .max_entries = 1,
+ };
+
+ fd->fd = syscall(__NR_bpf, BPF_MAP_CREATE, &array_attr, sizeof(array_attr));
+ if (fd->fd < 0) {
+ tst_res(TCONF | TERRNO,
+ "Skipping %s", tst_fd_desc(fd));
+ }
+}
+
+static void open_fsopen(struct tst_fd *fd)
+{
+ fd->fd = syscall(__NR_fsopen, "ext2", 0);
+ if (fd->fd < 0) {
+ tst_res(TCONF | TERRNO,
+ "Skipping %s", tst_fd_desc(fd));
+ }
+}
+
+static void open_fspick(struct tst_fd *fd)
+{
+ fd->fd = syscall(__NR_fspick, AT_FDCWD, "/", 0);
+ if (fd->fd < 0) {
+ tst_res(TCONF | TERRNO,
+ "Skipping %s", tst_fd_desc(fd));
+ }
+}
+
+static void open_open_tree(struct tst_fd *fd)
+{
+ fd->fd = syscall(__NR_open_tree, AT_FDCWD, "/", 0);
+ if (fd->fd < 0) {
+ tst_res(TCONF | TERRNO,
+ "Skipping %s", tst_fd_desc(fd));
+ }
+}
+
+static void open_memfd(struct tst_fd *fd)
+{
+ fd->fd = syscall(__NR_memfd_create, "ltp_memfd", 0);
+ if (fd->fd < 0) {
+ tst_res(TCONF | TERRNO,
+ "Skipping %s", tst_fd_desc(fd));
+ }
+}
+
+static void open_memfd_secret(struct tst_fd *fd)
+{
+ fd->fd = syscall(__NR_memfd_secret, 0);
+ if (fd->fd < 0) {
+ tst_res(TCONF | TERRNO,
+ "Skipping %s", tst_fd_desc(fd));
+ }
+}
+
+static struct tst_fd_desc fd_desc[] = {
+ [TST_FD_FILE] = {.open_fd = open_file, .desc = "file"},
+ [TST_FD_PATH] = {.open_fd = open_path, .desc = "O_PATH file"},
+ [TST_FD_DIR] = {.open_fd = open_dir, .desc = "directory"},
+ [TST_FD_DEV_ZERO] = {.open_fd = open_dev_zero, .desc = "/dev/zero"},
+ [TST_FD_PROC_MAPS] = {.open_fd = open_proc_self_maps, .desc = "/proc/self/maps"},
+ [TST_FD_PIPE_READ] = {.open_fd = open_pipe_read, .desc = "pipe read end", .destroy = destroy_pipe},
+ [TST_FD_PIPE_WRITE] = {.open_fd = open_pipe_write, .desc = "pipe write end", .destroy = destroy_pipe},
+ [TST_FD_UNIX_SOCK] = {.open_fd = open_unix_sock, .desc = "unix socket"},
+ [TST_FD_INET_SOCK] = {.open_fd = open_inet_sock, .desc = "inet socket"},
+ [TST_FD_EPOLL] = {.open_fd = open_epoll, .desc = "epoll"},
+ [TST_FD_EVENTFD] = {.open_fd = open_eventfd, .desc = "eventfd"},
+ [TST_FD_SIGNALFD] = {.open_fd = open_signalfd, .desc = "signalfd"},
+ [TST_FD_TIMERFD] = {.open_fd = open_timerfd, .desc = "timerfd"},
+ [TST_FD_PIDFD] = {.open_fd = open_pidfd, .desc = "pidfd"},
+ [TST_FD_FANOTIFY] = {.open_fd = open_fanotify, .desc = "fanotify"},
+ [TST_FD_INOTIFY] = {.open_fd = open_inotify, .desc = "inotify"},
+ [TST_FD_USERFAULTFD] = {.open_fd = open_userfaultfd, .desc = "userfaultfd"},
+ [TST_FD_PERF_EVENT] = {.open_fd = open_perf_event, .desc = "perf event"},
+ [TST_FD_IO_URING] = {.open_fd = open_io_uring, .desc = "io uring"},
+ [TST_FD_BPF_MAP] = {.open_fd = open_bpf_map, .desc = "bpf map"},
+ [TST_FD_FSOPEN] = {.open_fd = open_fsopen, .desc = "fsopen"},
+ [TST_FD_FSPICK] = {.open_fd = open_fspick, .desc = "fspick"},
+ [TST_FD_OPEN_TREE] = {.open_fd = open_open_tree, .desc = "open_tree"},
+ [TST_FD_MEMFD] = {.open_fd = open_memfd, .desc = "memfd"},
+ [TST_FD_MEMFD_SECRET] = {.open_fd = open_memfd_secret, .desc = "memfd secret"},
+};
+
+const char *tst_fd_desc(struct tst_fd *fd)
+{
+ if (fd->type >= ARRAY_SIZE(fd_desc))
+ return "invalid";
+
+ return fd_desc[fd->type].desc;
+}
+
+int tst_fd_next(struct tst_fd *fd)
+{
+ size_t len = ARRAY_SIZE(fd_desc);
+
+ if (fd->fd >= 0) {
+ SAFE_CLOSE(fd->fd);
+
+ if (fd_desc[fd->type].destroy)
+ fd_desc[fd->type].destroy(fd);
+
+ fd->type++;
+ }
+
+ for (;;) {
+ if (fd->type >= len)
+ return 0;
+
+ fd_desc[fd->type].open_fd(fd);
+
+ if (fd->fd >= 0)
+ return 1;
+
+ fd->type++;
+ }
+}
diff --git a/lib/tst_fill_file.c b/lib/tst_fill_file.c
index 80472007f..6cedde73d 100644
--- a/lib/tst_fill_file.c
+++ b/lib/tst_fill_file.c
@@ -1,34 +1,15 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
/*
+ * Copyright (c) Linux Test Project, 2014-2024
* Copyright (c) 2013 Oracle and/or its affiliates. All Rights Reserved.
- *
- * 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 would 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 the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- *
* Author: Stanislav Kholmanskikh <stanislav.kholmanskikh@oracle.com>
- *
*/
#define _GNU_SOURCE
-#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <unistd.h>
#include "lapi/fallocate.h"
-
-#include "test.h"
+#include "tst_fs.h"
int tst_fill_fd(int fd, char pattern, size_t bs, size_t bcount)
{
diff --git a/lib/tst_fill_fs.c b/lib/tst_fill_fs.c
index 5e8cf9197..c62d48e28 100644
--- a/lib/tst_fill_fs.c
+++ b/lib/tst_fill_fs.c
@@ -16,7 +16,7 @@
#include "tst_rand_data.h"
#include "tst_safe_file_at.h"
-void fill_random(const char *path, int verbose)
+static void fill_random(const char *path, int verbose)
{
int i = 0;
char file[PATH_MAX];
@@ -71,7 +71,7 @@ void fill_random(const char *path, int verbose)
}
}
-void fill_flat_vec(const char *path, int verbose)
+static void fill_flat_vec(const char *path, int verbose)
{
int dir, fd;
struct iovec iov[512];
diff --git a/lib/tst_fs_type.c b/lib/tst_fs_type.c
index d9c9c0817..7f0d61a8e 100644
--- a/lib/tst_fs_type.c
+++ b/lib/tst_fs_type.c
@@ -36,6 +36,8 @@ const char *tst_fs_type_name(long f_type)
return "9p";
case TST_RAMFS_MAGIC:
return "ramfs";
+ case TST_BCACHE_MAGIC:
+ return "bcachefs";
case TST_BTRFS_MAGIC:
return "btrfs";
case TST_XFS_MAGIC:
diff --git a/lib/tst_ioctl.c b/lib/tst_ioctl.c
index 364220bcd..985cd5329 100644
--- a/lib/tst_ioctl.c
+++ b/lib/tst_ioctl.c
@@ -1,37 +1,30 @@
// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (c) Linux Test Project, 2019-2023
+ */
-#include <errno.h>
-#include <stdio.h>
-#include <stdlib.h>
#include <sys/ioctl.h>
#include <linux/fs.h>
#define TST_NO_DEFAULT_MAIN
#include "tst_test.h"
+#include "tst_fs.h"
int tst_fibmap(const char *filename)
{
- /* test if FIBMAP ioctl is supported */
int fd, block = 0;
- fd = open(filename, O_RDWR | O_CREAT, 0666);
- if (fd < 0) {
- tst_res(TWARN | TERRNO,
- "open(%s, O_RDWR | O_CREAT, 0666) failed", filename);
- return -1;
- }
+ fd = SAFE_OPEN(filename, O_RDWR | O_CREAT, 0666);
if (ioctl(fd, FIBMAP, &block)) {
tst_res(TINFO | TERRNO, "FIBMAP ioctl is NOT supported");
- close(fd);
+ SAFE_CLOSE(fd);
return 1;
}
+
tst_res(TINFO, "FIBMAP ioctl is supported");
+ SAFE_CLOSE(fd);
- if (close(fd)) {
- tst_res(TWARN | TERRNO, "close(fd) failed");
- return -1;
- }
return 0;
}
diff --git a/lib/tst_kernel.c b/lib/tst_kernel.c
index 4b75ceadb..51e4daa09 100644
--- a/lib/tst_kernel.c
+++ b/lib/tst_kernel.c
@@ -193,7 +193,7 @@ int tst_check_builtin_driver(const char *driver)
int tst_check_driver(const char *driver)
{
if (!tst_search_driver(driver, "modules.dep") ||
- !tst_search_driver(driver, "modules.builtin"))
+ !tst_check_builtin_driver(driver))
return 0;
return -1;
diff --git a/lib/tst_memutils.c b/lib/tst_memutils.c
index c5382ff10..e33f19d29 100644
--- a/lib/tst_memutils.c
+++ b/lib/tst_memutils.c
@@ -1,6 +1,7 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Copyright (c) 2020 SUSE LLC <mdoucha@suse.cz>
+ * Copyright (c) Linux Test Project, 2021-2023
*/
#include <stdio.h>
@@ -11,6 +12,7 @@
#define TST_NO_DEFAULT_MAIN
#include "tst_test.h"
+#include "tst_memutils.h"
#include "tst_capability.h"
#include "lapi/syscalls.h"
diff --git a/lib/tst_netdevice.c b/lib/tst_netdevice.c
index dba44c623..1042466bf 100644
--- a/lib/tst_netdevice.c
+++ b/lib/tst_netdevice.c
@@ -12,26 +12,27 @@
#define TST_NO_DEFAULT_MAIN
#include "tst_test.h"
-#include "tst_rtnetlink.h"
+#include "tst_netlink.h"
#include "tst_netdevice.h"
-static struct tst_rtnl_context *create_request(const char *file,
+static struct tst_netlink_context *create_request(const char *file,
const int lineno, unsigned int type, unsigned int flags,
const void *payload, size_t psize)
{
- struct tst_rtnl_context *ctx;
+ struct tst_netlink_context *ctx;
struct nlmsghdr header = {
.nlmsg_type = type,
.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK | flags,
};
- ctx = tst_rtnl_create_context(file, lineno);
+ ctx = tst_netlink_create_context(file, lineno, NETLINK_ROUTE);
if (!ctx)
return NULL;
- if (!tst_rtnl_add_message(file, lineno, ctx, &header, payload, psize)) {
- tst_rtnl_destroy_context(file, lineno, ctx);
+ if (!tst_netlink_add_message(file, lineno, ctx, &header, payload,
+ psize)) {
+ tst_netlink_destroy_context(file, lineno, ctx);
return NULL;
}
@@ -103,18 +104,18 @@ int tst_create_veth_pair(const char *file, const int lineno, int strict,
{
int ret;
struct ifinfomsg info = { .ifi_family = AF_UNSPEC };
- struct tst_rtnl_context *ctx;
- struct tst_rtnl_attr_list peerinfo[] = {
+ struct tst_netlink_context *ctx;
+ struct tst_netlink_attr_list peerinfo[] = {
{IFLA_IFNAME, ifname2, strlen(ifname2) + 1, NULL},
{0, NULL, -1, NULL}
};
- struct tst_rtnl_attr_list peerdata[] = {
+ struct tst_netlink_attr_list peerdata[] = {
{VETH_INFO_PEER, &info, sizeof(info), peerinfo},
{0, NULL, -1, NULL}
};
- struct tst_rtnl_attr_list attrs[] = {
+ struct tst_netlink_attr_list attrs[] = {
{IFLA_IFNAME, ifname1, strlen(ifname1) + 1, NULL},
- {IFLA_LINKINFO, NULL, 0, (const struct tst_rtnl_attr_list[]){
+ {IFLA_LINKINFO, NULL, 0, (const struct tst_netlink_attr_list[]){
{IFLA_INFO_KIND, "veth", 4, NULL},
{IFLA_INFO_DATA, NULL, 0, peerdata},
{0, NULL, -1, NULL}
@@ -141,17 +142,17 @@ int tst_create_veth_pair(const char *file, const int lineno, int strict,
return 0;
if (tst_rtnl_add_attr_list(file, lineno, ctx, attrs) != 2) {
- tst_rtnl_destroy_context(file, lineno, ctx);
+ tst_netlink_destroy_context(file, lineno, ctx);
return 0;
}
- ret = tst_rtnl_send_validate(file, lineno, ctx);
- tst_rtnl_destroy_context(file, lineno, ctx);
+ ret = tst_netlink_send_validate(file, lineno, ctx);
+ tst_netlink_destroy_context(file, lineno, ctx);
if (strict && !ret) {
tst_brk_(file, lineno, TBROK,
"Failed to create veth interfaces %s+%s: %s", ifname1,
- ifname2, tst_strerrno(tst_rtnl_errno));
+ ifname2, tst_strerrno(tst_netlink_errno));
}
return ret;
@@ -162,10 +163,10 @@ int tst_netdev_add_device(const char *file, const int lineno, int strict,
{
int ret;
struct ifinfomsg info = { .ifi_family = AF_UNSPEC };
- struct tst_rtnl_context *ctx;
- struct tst_rtnl_attr_list attrs[] = {
+ struct tst_netlink_context *ctx;
+ struct tst_netlink_attr_list attrs[] = {
{IFLA_IFNAME, ifname, strlen(ifname) + 1, NULL},
- {IFLA_LINKINFO, NULL, 0, (const struct tst_rtnl_attr_list[]){
+ {IFLA_LINKINFO, NULL, 0, (const struct tst_netlink_attr_list[]){
{IFLA_INFO_KIND, devtype, strlen(devtype), NULL},
{0, NULL, -1, NULL}
}},
@@ -185,17 +186,17 @@ int tst_netdev_add_device(const char *file, const int lineno, int strict,
return 0;
if (tst_rtnl_add_attr_list(file, lineno, ctx, attrs) != 2) {
- tst_rtnl_destroy_context(file, lineno, ctx);
+ tst_netlink_destroy_context(file, lineno, ctx);
return 0;
}
- ret = tst_rtnl_send_validate(file, lineno, ctx);
- tst_rtnl_destroy_context(file, lineno, ctx);
+ ret = tst_netlink_send_validate(file, lineno, ctx);
+ tst_netlink_destroy_context(file, lineno, ctx);
if (strict && !ret) {
tst_brk_(file, lineno, TBROK,
"Failed to create %s device %s: %s", devtype, ifname,
- tst_strerrno(tst_rtnl_errno));
+ tst_strerrno(tst_netlink_errno));
}
return ret;
@@ -205,7 +206,7 @@ int tst_netdev_remove_device(const char *file, const int lineno, int strict,
const char *ifname)
{
struct ifinfomsg info = { .ifi_family = AF_UNSPEC };
- struct tst_rtnl_context *ctx;
+ struct tst_netlink_context *ctx;
int ret;
if (strlen(ifname) >= IFNAMSIZ) {
@@ -220,17 +221,17 @@ int tst_netdev_remove_device(const char *file, const int lineno, int strict,
return 0;
if (!tst_rtnl_add_attr_string(file, lineno, ctx, IFLA_IFNAME, ifname)) {
- tst_rtnl_destroy_context(file, lineno, ctx);
+ tst_netlink_destroy_context(file, lineno, ctx);
return 0;
}
- ret = tst_rtnl_send_validate(file, lineno, ctx);
- tst_rtnl_destroy_context(file, lineno, ctx);
+ ret = tst_netlink_send_validate(file, lineno, ctx);
+ tst_netlink_destroy_context(file, lineno, ctx);
if (strict && !ret) {
tst_brk_(file, lineno, TBROK,
"Failed to remove netdevice %s: %s", ifname,
- tst_strerrno(tst_rtnl_errno));
+ tst_strerrno(tst_netlink_errno));
}
return ret;
@@ -241,7 +242,7 @@ static int modify_address(const char *file, const int lineno, int strict,
unsigned int family, const void *address, unsigned int prefix,
size_t addrlen, uint32_t addr_flags)
{
- struct tst_rtnl_context *ctx;
+ struct tst_netlink_context *ctx;
int index, ret;
struct ifaddrmsg info = {
.ifa_family = family,
@@ -264,23 +265,23 @@ static int modify_address(const char *file, const int lineno, int strict,
if (!tst_rtnl_add_attr(file, lineno, ctx, IFA_FLAGS, &addr_flags,
sizeof(uint32_t))) {
- tst_rtnl_destroy_context(file, lineno, ctx);
+ tst_netlink_destroy_context(file, lineno, ctx);
return 0;
}
if (!tst_rtnl_add_attr(file, lineno, ctx, IFA_LOCAL, address,
addrlen)) {
- tst_rtnl_destroy_context(file, lineno, ctx);
+ tst_netlink_destroy_context(file, lineno, ctx);
return 0;
}
- ret = tst_rtnl_send_validate(file, lineno, ctx);
- tst_rtnl_destroy_context(file, lineno, ctx);
+ ret = tst_netlink_send_validate(file, lineno, ctx);
+ tst_netlink_destroy_context(file, lineno, ctx);
if (strict && !ret) {
tst_brk_(file, lineno, TBROK,
"Failed to modify %s network address: %s", ifname,
- tst_strerrno(tst_rtnl_errno));
+ tst_strerrno(tst_netlink_errno));
}
return ret;
@@ -322,7 +323,7 @@ static int change_ns(const char *file, const int lineno, int strict,
const char *ifname, unsigned short attr, uint32_t value)
{
struct ifinfomsg info = { .ifi_family = AF_UNSPEC };
- struct tst_rtnl_context *ctx;
+ struct tst_netlink_context *ctx;
int ret;
if (strlen(ifname) >= IFNAMSIZ) {
@@ -337,23 +338,23 @@ static int change_ns(const char *file, const int lineno, int strict,
return 0;
if (!tst_rtnl_add_attr_string(file, lineno, ctx, IFLA_IFNAME, ifname)) {
- tst_rtnl_destroy_context(file, lineno, ctx);
+ tst_netlink_destroy_context(file, lineno, ctx);
return 0;
}
if (!tst_rtnl_add_attr(file, lineno, ctx, attr, &value,
sizeof(uint32_t))) {
- tst_rtnl_destroy_context(file, lineno, ctx);
+ tst_netlink_destroy_context(file, lineno, ctx);
return 0;
}
- ret = tst_rtnl_send_validate(file, lineno, ctx);
- tst_rtnl_destroy_context(file, lineno, ctx);
+ ret = tst_netlink_send_validate(file, lineno, ctx);
+ tst_netlink_destroy_context(file, lineno, ctx);
if (strict && !ret) {
tst_brk_(file, lineno, TBROK,
"Failed to move %s to another namespace: %s", ifname,
- tst_strerrno(tst_rtnl_errno));
+ tst_strerrno(tst_netlink_errno));
}
return ret;
@@ -377,7 +378,7 @@ static int modify_route(const char *file, const int lineno, int strict,
size_t srclen, const void *dstaddr, unsigned int dstprefix,
size_t dstlen, const void *gateway, size_t gatewaylen)
{
- struct tst_rtnl_context *ctx;
+ struct tst_netlink_context *ctx;
int ret;
int32_t index;
struct rtmsg info = {
@@ -420,35 +421,35 @@ static int modify_route(const char *file, const int lineno, int strict,
if (srcaddr && !tst_rtnl_add_attr(file, lineno, ctx, RTA_SRC, srcaddr,
srclen)) {
- tst_rtnl_destroy_context(file, lineno, ctx);
+ tst_netlink_destroy_context(file, lineno, ctx);
return 0;
}
if (dstaddr && !tst_rtnl_add_attr(file, lineno, ctx, RTA_DST, dstaddr,
dstlen)) {
- tst_rtnl_destroy_context(file, lineno, ctx);
+ tst_netlink_destroy_context(file, lineno, ctx);
return 0;
}
if (gateway && !tst_rtnl_add_attr(file, lineno, ctx, RTA_GATEWAY,
gateway, gatewaylen)) {
- tst_rtnl_destroy_context(file, lineno, ctx);
+ tst_netlink_destroy_context(file, lineno, ctx);
return 0;
}
if (ifname && !tst_rtnl_add_attr(file, lineno, ctx, RTA_OIF, &index,
sizeof(index))) {
- tst_rtnl_destroy_context(file, lineno, ctx);
+ tst_netlink_destroy_context(file, lineno, ctx);
return 0;
}
- ret = tst_rtnl_send_validate(file, lineno, ctx);
- tst_rtnl_destroy_context(file, lineno, ctx);
+ ret = tst_netlink_send_validate(file, lineno, ctx);
+ tst_netlink_destroy_context(file, lineno, ctx);
if (strict && !ret) {
tst_brk_(file, lineno, TBROK,
"Failed to modify network route: %s",
- tst_strerrno(tst_rtnl_errno));
+ tst_strerrno(tst_netlink_errno));
}
return ret;
@@ -526,9 +527,9 @@ static int modify_qdisc(const char *file, const int lineno, int strict,
const char *object, unsigned int action, unsigned int nl_flags,
const char *ifname, unsigned int family, unsigned int parent,
unsigned int handle, unsigned int info, const char *qd_kind,
- const struct tst_rtnl_attr_list *config)
+ const struct tst_netlink_attr_list *config)
{
- struct tst_rtnl_context *ctx;
+ struct tst_netlink_context *ctx;
int ret;
struct tcmsg msg = {
.tcm_family = family,
@@ -560,22 +561,22 @@ static int modify_qdisc(const char *file, const int lineno, int strict,
return 0;
if (!tst_rtnl_add_attr_string(file, lineno, ctx, TCA_KIND, qd_kind)) {
- tst_rtnl_destroy_context(file, lineno, ctx);
+ tst_netlink_destroy_context(file, lineno, ctx);
return 0;
}
if (config && !tst_rtnl_add_attr_list(file, lineno, ctx, config)) {
- tst_rtnl_destroy_context(file, lineno, ctx);
+ tst_netlink_destroy_context(file, lineno, ctx);
return 0;
}
- ret = tst_rtnl_send_validate(file, lineno, ctx);
- tst_rtnl_destroy_context(file, lineno, ctx);
+ ret = tst_netlink_send_validate(file, lineno, ctx);
+ tst_netlink_destroy_context(file, lineno, ctx);
if (strict && !ret) {
tst_brk_(file, lineno, TBROK,
"Failed to modify %s: %s", object,
- tst_strerrno(tst_rtnl_errno));
+ tst_strerrno(tst_netlink_errno));
}
return ret;
@@ -584,7 +585,7 @@ static int modify_qdisc(const char *file, const int lineno, int strict,
int tst_netdev_add_qdisc(const char *file, const int lineno, int strict,
const char *ifname, unsigned int family, unsigned int parent,
unsigned int handle, const char *qd_kind,
- const struct tst_rtnl_attr_list *config)
+ const struct tst_netlink_attr_list *config)
{
return modify_qdisc(file, lineno, strict, "queueing discipline",
RTM_NEWQDISC, NLM_F_CREATE | NLM_F_EXCL, ifname, family,
@@ -603,7 +604,7 @@ int tst_netdev_remove_qdisc(const char *file, const int lineno, int strict,
int tst_netdev_add_traffic_class(const char *file, const int lineno,
int strict, const char *ifname, unsigned int parent,
unsigned int handle, const char *qd_kind,
- const struct tst_rtnl_attr_list *config)
+ const struct tst_netlink_attr_list *config)
{
return modify_qdisc(file, lineno, strict, "traffic class",
RTM_NEWTCLASS, NLM_F_CREATE | NLM_F_EXCL, ifname, AF_UNSPEC,
@@ -622,7 +623,7 @@ int tst_netdev_remove_traffic_class(const char *file, const int lineno,
int tst_netdev_add_traffic_filter(const char *file, const int lineno,
int strict, const char *ifname, unsigned int parent,
unsigned int handle, unsigned int protocol, unsigned int priority,
- const char *f_kind, const struct tst_rtnl_attr_list *config)
+ const char *f_kind, const struct tst_netlink_attr_list *config)
{
return modify_qdisc(file, lineno, strict, "traffic filter",
RTM_NEWTFILTER, NLM_F_CREATE | NLM_F_EXCL, ifname, AF_UNSPEC,
diff --git a/lib/tst_rtnetlink.c b/lib/tst_netlink.c
index a2411dfde..d61cc8b88 100644
--- a/lib/tst_rtnetlink.c
+++ b/lib/tst_netlink.c
@@ -13,9 +13,9 @@
#include <sys/poll.h>
#define TST_NO_DEFAULT_MAIN
#include "tst_test.h"
-#include "tst_rtnetlink.h"
+#include "tst_netlink.h"
-struct tst_rtnl_context {
+struct tst_netlink_context {
int socket;
pid_t pid;
uint32_t seq;
@@ -24,10 +24,10 @@ struct tst_rtnl_context {
struct nlmsghdr *curmsg;
};
-int tst_rtnl_errno;
+int tst_netlink_errno;
-static int tst_rtnl_grow_buffer(const char *file, const int lineno,
- struct tst_rtnl_context *ctx, size_t size)
+static int netlink_grow_buffer(const char *file, const int lineno,
+ struct tst_netlink_context *ctx, size_t size)
{
size_t needed, offset, curlen = NLMSG_ALIGN(ctx->datalen);
char *buf;
@@ -52,21 +52,25 @@ static int tst_rtnl_grow_buffer(const char *file, const int lineno,
return 1;
}
-void tst_rtnl_destroy_context(const char *file, const int lineno,
- struct tst_rtnl_context *ctx)
+void tst_netlink_destroy_context(const char *file, const int lineno,
+ struct tst_netlink_context *ctx)
{
+ if (!ctx)
+ return;
+
safe_close(file, lineno, NULL, ctx->socket);
free(ctx->buffer);
free(ctx);
}
-struct tst_rtnl_context *tst_rtnl_create_context(const char *file,
- const int lineno)
+struct tst_netlink_context *tst_netlink_create_context(const char *file,
+ const int lineno, int protocol)
{
- struct tst_rtnl_context *ctx;
+ struct tst_netlink_context *ctx;
struct sockaddr_nl addr = { .nl_family = AF_NETLINK };
- ctx = safe_malloc(file, lineno, NULL, sizeof(struct tst_rtnl_context));
+ ctx = safe_malloc(file, lineno, NULL,
+ sizeof(struct tst_netlink_context));
if (!ctx)
return NULL;
@@ -78,7 +82,7 @@ struct tst_rtnl_context *tst_rtnl_create_context(const char *file,
ctx->datalen = 0;
ctx->curmsg = NULL;
ctx->socket = safe_socket(file, lineno, NULL, AF_NETLINK,
- SOCK_DGRAM | SOCK_CLOEXEC, NETLINK_ROUTE);
+ SOCK_DGRAM | SOCK_CLOEXEC, protocol);
if (ctx->socket < 0) {
free(ctx);
@@ -87,14 +91,14 @@ struct tst_rtnl_context *tst_rtnl_create_context(const char *file,
if (safe_bind(file, lineno, NULL, ctx->socket, (struct sockaddr *)&addr,
sizeof(addr))) {
- tst_rtnl_destroy_context(file, lineno, ctx);
+ tst_netlink_destroy_context(file, lineno, ctx);
return NULL;
}
ctx->buffer = safe_malloc(file, lineno, NULL, ctx->bufsize);
if (!ctx->buffer) {
- tst_rtnl_destroy_context(file, lineno, ctx);
+ tst_netlink_destroy_context(file, lineno, ctx);
return NULL;
}
@@ -103,7 +107,7 @@ struct tst_rtnl_context *tst_rtnl_create_context(const char *file,
return ctx;
}
-void tst_rtnl_free_message(struct tst_rtnl_message *msg)
+void tst_netlink_free_message(struct tst_netlink_message *msg)
{
if (!msg)
return;
@@ -114,8 +118,8 @@ void tst_rtnl_free_message(struct tst_rtnl_message *msg)
free(msg);
}
-int tst_rtnl_send(const char *file, const int lineno,
- struct tst_rtnl_context *ctx)
+int tst_netlink_send(const char *file, const int lineno,
+ struct tst_netlink_context *ctx)
{
int ret;
struct sockaddr_nl addr = { .nl_family = AF_NETLINK };
@@ -136,7 +140,7 @@ int tst_rtnl_send(const char *file, const int lineno,
if (ctx->curmsg->nlmsg_flags & NLM_F_MULTI) {
struct nlmsghdr eom = { .nlmsg_type = NLMSG_DONE };
- if (!tst_rtnl_add_message(file, lineno, ctx, &eom, NULL, 0))
+ if (!tst_netlink_add_message(file, lineno, ctx, &eom, NULL, 0))
return 0;
/* NLMSG_DONE message must not have NLM_F_MULTI flag */
@@ -153,7 +157,7 @@ int tst_rtnl_send(const char *file, const int lineno,
return ret;
}
-int tst_rtnl_wait(struct tst_rtnl_context *ctx)
+int tst_netlink_wait(struct tst_netlink_context *ctx)
{
struct pollfd fdinfo = {
.fd = ctx->socket,
@@ -163,11 +167,11 @@ int tst_rtnl_wait(struct tst_rtnl_context *ctx)
return poll(&fdinfo, 1, 1000);
}
-struct tst_rtnl_message *tst_rtnl_recv(const char *file, const int lineno,
- struct tst_rtnl_context *ctx)
+struct tst_netlink_message *tst_netlink_recv(const char *file,
+ const int lineno, struct tst_netlink_context *ctx)
{
char tmp, *tmpbuf, *buffer = NULL;
- struct tst_rtnl_message *ret;
+ struct tst_netlink_message *ret;
struct nlmsghdr *ptr;
size_t retsize, bufsize = 0;
ssize_t size;
@@ -215,7 +219,7 @@ struct tst_rtnl_message *tst_rtnl_recv(const char *file, const int lineno,
for (; size_left > 0 && NLMSG_OK(ptr, size_left); msgcount++)
ptr = NLMSG_NEXT(ptr, size_left);
- retsize = (msgcount + 1) * sizeof(struct tst_rtnl_message);
+ retsize = (msgcount + 1) * sizeof(struct tst_netlink_message);
ret = safe_malloc(file, lineno, NULL, retsize);
if (!ret) {
@@ -239,14 +243,14 @@ struct tst_rtnl_message *tst_rtnl_recv(const char *file, const int lineno,
return ret;
}
-int tst_rtnl_add_message(const char *file, const int lineno,
- struct tst_rtnl_context *ctx, const struct nlmsghdr *header,
+int tst_netlink_add_message(const char *file, const int lineno,
+ struct tst_netlink_context *ctx, const struct nlmsghdr *header,
const void *payload, size_t payload_size)
{
size_t size;
unsigned int extra_flags = 0;
- if (!tst_rtnl_grow_buffer(file, lineno, ctx, NLMSG_SPACE(payload_size)))
+ if (!netlink_grow_buffer(file, lineno, ctx, NLMSG_SPACE(payload_size)))
return 0;
if (!ctx->curmsg) {
@@ -279,8 +283,88 @@ int tst_rtnl_add_message(const char *file, const int lineno,
return 1;
}
+int tst_netlink_add_attr(const char *file, const int lineno,
+ struct tst_netlink_context *ctx, unsigned short type,
+ const void *data, unsigned short len)
+{
+ size_t size = NLA_HDRLEN + NLA_ALIGN(len);
+ struct nlattr *attr;
+
+ if (!ctx->curmsg) {
+ tst_brk_(file, lineno, TBROK,
+ "%s(): No message to add attributes to", __func__);
+ return 0;
+ }
+
+ if (!netlink_grow_buffer(file, lineno, ctx, size))
+ return 0;
+
+ size = NLMSG_ALIGN(ctx->curmsg->nlmsg_len);
+ attr = (struct nlattr *)(((char *)ctx->curmsg) + size);
+ attr->nla_type = type;
+ attr->nla_len = NLA_HDRLEN + len;
+ memcpy(((char *)attr) + NLA_HDRLEN, data, len);
+ ctx->curmsg->nlmsg_len = size + attr->nla_len;
+ ctx->datalen = NLMSG_ALIGN(ctx->datalen) + attr->nla_len;
+
+ return 1;
+}
+
+int tst_netlink_add_attr_string(const char *file, const int lineno,
+ struct tst_netlink_context *ctx, unsigned short type,
+ const char *data)
+{
+ return tst_netlink_add_attr(file, lineno, ctx, type, data,
+ strlen(data) + 1);
+}
+
+int tst_netlink_add_attr_list(const char *file, const int lineno,
+ struct tst_netlink_context *ctx,
+ const struct tst_netlink_attr_list *list)
+{
+ int i, ret;
+ size_t offset;
+
+ for (i = 0; list[i].len >= 0; i++) {
+ if (list[i].len > USHRT_MAX) {
+ tst_brk_(file, lineno, TBROK,
+ "%s(): Attribute value too long", __func__);
+ return -1;
+ }
+
+ offset = NLMSG_ALIGN(ctx->datalen);
+ ret = tst_netlink_add_attr(file, lineno, ctx, list[i].type,
+ list[i].data, list[i].len);
+
+ if (!ret)
+ return -1;
+
+ if (list[i].sublist) {
+ struct rtattr *attr;
+
+ ret = tst_netlink_add_attr_list(file, lineno, ctx,
+ list[i].sublist);
+
+ if (ret < 0)
+ return ret;
+
+ attr = (struct rtattr *)(ctx->buffer + offset);
+
+ if (ctx->datalen - offset > USHRT_MAX) {
+ tst_brk_(file, lineno, TBROK,
+ "%s(): Sublist too long", __func__);
+ return -1;
+ }
+
+ attr->rta_len = ctx->datalen - offset;
+ }
+ }
+
+ return i;
+}
+
int tst_rtnl_add_attr(const char *file, const int lineno,
- struct tst_rtnl_context *ctx, unsigned short type,
+ struct tst_netlink_context *ctx, unsigned short type,
const void *data, unsigned short len)
{
size_t size;
@@ -292,7 +376,7 @@ int tst_rtnl_add_attr(const char *file, const int lineno,
return 0;
}
- if (!tst_rtnl_grow_buffer(file, lineno, ctx, RTA_SPACE(len)))
+ if (!netlink_grow_buffer(file, lineno, ctx, RTA_SPACE(len)))
return 0;
size = NLMSG_ALIGN(ctx->curmsg->nlmsg_len);
@@ -307,7 +391,7 @@ int tst_rtnl_add_attr(const char *file, const int lineno,
}
int tst_rtnl_add_attr_string(const char *file, const int lineno,
- struct tst_rtnl_context *ctx, unsigned short type,
+ struct tst_netlink_context *ctx, unsigned short type,
const char *data)
{
return tst_rtnl_add_attr(file, lineno, ctx, type, data,
@@ -315,8 +399,8 @@ int tst_rtnl_add_attr_string(const char *file, const int lineno,
}
int tst_rtnl_add_attr_list(const char *file, const int lineno,
- struct tst_rtnl_context *ctx,
- const struct tst_rtnl_attr_list *list)
+ struct tst_netlink_context *ctx,
+ const struct tst_netlink_attr_list *list)
{
int i, ret;
size_t offset;
@@ -359,8 +443,8 @@ int tst_rtnl_add_attr_list(const char *file, const int lineno,
return i;
}
-int tst_rtnl_check_acks(const char *file, const int lineno,
- struct tst_rtnl_context *ctx, struct tst_rtnl_message *res)
+int tst_netlink_check_acks(const char *file, const int lineno,
+ struct tst_netlink_context *ctx, struct tst_netlink_message *res)
{
struct nlmsghdr *msg = (struct nlmsghdr *)ctx->buffer;
int size_left = ctx->datalen;
@@ -371,18 +455,19 @@ int tst_rtnl_check_acks(const char *file, const int lineno,
if (!(msg->nlmsg_flags & NLM_F_ACK))
continue;
- while (res->header && res->header->nlmsg_seq != msg->nlmsg_seq)
+ while (res->header && !(res->err && res->err->error) &&
+ res->header->nlmsg_seq != msg->nlmsg_seq)
res++;
- if (!res->err || res->header->nlmsg_seq != msg->nlmsg_seq) {
- tst_brk_(file, lineno, TBROK,
- "No ACK found for Netlink message %u",
- msg->nlmsg_seq);
+ if (res->err && res->err->error) {
+ tst_netlink_errno = -res->err->error;
return 0;
}
- if (res->err->error) {
- tst_rtnl_errno = -res->err->error;
+ if (!res->header || res->header->nlmsg_seq != msg->nlmsg_seq) {
+ tst_brk_(file, lineno, TBROK,
+ "No ACK found for Netlink message %u",
+ msg->nlmsg_seq);
return 0;
}
}
@@ -390,25 +475,25 @@ int tst_rtnl_check_acks(const char *file, const int lineno,
return 1;
}
-int tst_rtnl_send_validate(const char *file, const int lineno,
- struct tst_rtnl_context *ctx)
+int tst_netlink_send_validate(const char *file, const int lineno,
+ struct tst_netlink_context *ctx)
{
- struct tst_rtnl_message *response;
+ struct tst_netlink_message *response;
int ret;
- tst_rtnl_errno = 0;
+ tst_netlink_errno = 0;
- if (tst_rtnl_send(file, lineno, ctx) <= 0)
+ if (tst_netlink_send(file, lineno, ctx) <= 0)
return 0;
- tst_rtnl_wait(ctx);
- response = tst_rtnl_recv(file, lineno, ctx);
+ tst_netlink_wait(ctx);
+ response = tst_netlink_recv(file, lineno, ctx);
if (!response)
return 0;
- ret = tst_rtnl_check_acks(file, lineno, ctx, response);
- tst_rtnl_free_message(response);
+ ret = tst_netlink_check_acks(file, lineno, ctx, response);
+ tst_netlink_free_message(response);
return ret;
}
diff --git a/lib/tst_pid.c b/lib/tst_pid.c
index cfaa5db36..4e9dc7a52 100644
--- a/lib/tst_pid.c
+++ b/lib/tst_pid.c
@@ -166,3 +166,8 @@ pid_t tst_getpid(void)
{
return syscall(SYS_getpid);
}
+
+pid_t tst_gettid(void)
+{
+ return syscall(SYS_gettid);
+}
diff --git a/lib/tst_res.c b/lib/tst_res.c
index e0896eb05..e87918ed1 100644
--- a/lib/tst_res.c
+++ b/lib/tst_res.c
@@ -174,6 +174,11 @@ static void tst_res__(const char *file, const int lineno, int ttype,
int len = 0;
int ttype_result = TTYPE_RESULT(ttype);
+ if (ttype_result == TDEBUG) {
+ printf("%s: %i: TDEBUG is not supported\n", __func__, __LINE__);
+ abort();
+ }
+
if (file && (ttype_result != TPASS && ttype_result != TINFO))
len = sprintf(tmesg, "%s:%d: ", file, lineno);
EXPAND_VAR_ARGS(tmesg + len, arg_fmt, USERMESG - len);
diff --git a/lib/tst_safe_macros.c b/lib/tst_safe_macros.c
index c4cdc87e7..a178a13e7 100644
--- a/lib/tst_safe_macros.c
+++ b/lib/tst_safe_macros.c
@@ -591,3 +591,37 @@ void safe_cmd(const char *file, const int lineno, const char *const argv[],
tst_brk_(file, lineno, TBROK, "%s failed (%d)", argv[0], rval);
}
}
+
+int safe_msync(const char *file, const int lineno, void *addr,
+ size_t length, int flags)
+{
+ int rval;
+
+ rval = msync(addr, length, flags);
+
+ if (rval == -1) {
+ tst_brk_(file, lineno, TBROK | TERRNO,
+ "msync(%p, %zu, %d) failed", addr, length, flags);
+ } else if (rval) {
+ tst_brk_(file, lineno, TBROK | TERRNO,
+ "Invalid msync(%p, %zu, %d) return value %d",
+ addr, length, flags, rval);
+ }
+
+ return rval;
+}
+
+void safe_print_file(const char *file, const int lineno, char *path)
+{
+ FILE *pfile;
+ char line[PATH_MAX];
+
+ tst_res(TINFO, "=== %s ===", path);
+
+ pfile = safe_fopen(file, lineno, NULL, path, "r");
+
+ while (fgets(line, sizeof(line), pfile))
+ fprintf(stderr, "%s", line);
+
+ safe_fclose(file, lineno, NULL, pfile);
+}
diff --git a/lib/tst_supported_fs_types.c b/lib/tst_supported_fs_types.c
index d4911fa3b..bbbb8df19 100644
--- a/lib/tst_supported_fs_types.c
+++ b/lib/tst_supported_fs_types.c
@@ -1,6 +1,7 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Copyright (c) 2017 Cyril Hrubis <chrubis@suse.cz>
+ * Copyright (c) Linux Test Project, 2018-2023
*/
#include <stdio.h>
@@ -24,6 +25,7 @@ static const char *const fs_type_whitelist[] = {
"ext4",
"xfs",
"btrfs",
+ "bcachefs",
"vfat",
"exfat",
"ntfs",
@@ -31,6 +33,11 @@ static const char *const fs_type_whitelist[] = {
NULL
};
+static const char *const fs_type_fuse_blacklist[] = {
+ "bcachefs",
+ NULL,
+};
+
static const char *fs_types[ARRAY_SIZE(fs_type_whitelist)];
static int has_mkfs(const char *fs_type)
@@ -94,6 +101,11 @@ static enum tst_fs_impl has_kernel_support(const char *fs_type)
SAFE_RMDIR(template);
+ if (tst_fs_in_skiplist(fs_type, fs_type_fuse_blacklist)) {
+ tst_res(TINFO, "Skipping %s because of FUSE blacklist", fs_type);
+ return TST_FS_UNSUPPORTED;
+ }
+
/* Is FUSE supported by kernel? */
if (fuse_supported == -1) {
ret = open("/dev/fuse", O_RDWR);
diff --git a/lib/tst_test.c b/lib/tst_test.c
index 0dec00be4..bcf2c4555 100644
--- a/lib/tst_test.c
+++ b/lib/tst_test.c
@@ -60,6 +60,7 @@ static pid_t main_pid, lib_pid;
static int mntpoint_mounted;
static int ovl_mounted;
static struct timespec tst_start_time; /* valid only for test pid */
+static int tdebug;
struct results {
int passed;
@@ -224,6 +225,9 @@ static void print_result(const char *file, const int lineno, int ttype,
case TINFO:
res = "TINFO";
break;
+ case TDEBUG:
+ res = "TDEBUG";
+ break;
default:
tst_brk(TBROK, "Invalid ttype value %i", ttype);
abort();
@@ -352,6 +356,9 @@ void tst_res_(const char *file, const int lineno, int ttype,
{
va_list va;
+ if (ttype == TDEBUG && !tdebug)
+ return;
+
va_start(va, fmt);
tst_vres_(file, lineno, ttype, fmt, va);
va_end(va);
@@ -511,6 +518,7 @@ static struct option {
{"h", "-h Prints this help"},
{"i:", "-i n Execute test n times"},
{"I:", "-I x Execute test for n seconds"},
+ {"D", "-D Prints debug information"},
{"V", "-V Prints LTP version"},
{"C:", "-C ARG Run child process with ARG arguments (used internally)"},
};
@@ -520,7 +528,7 @@ static void print_help(void)
unsigned int i;
int timeout, runtime;
- /* see doc/user-guide.txt, which lists also shell API variables */
+ /* see doc/User-Guidelines.asciidoc, which lists also shell API variables */
fprintf(stderr, "Environment Variables\n");
fprintf(stderr, "---------------------\n");
fprintf(stderr, "KCONFIG_PATH Specify kernel config file\n");
@@ -679,6 +687,10 @@ static void parse_opts(int argc, char *argv[])
print_help();
tst_brk(TBROK, "Invalid option");
break;
+ case 'D':
+ tst_res(TINFO, "Enabling debug info");
+ tdebug = 1;
+ break;
case 'h':
print_help();
print_test_tags();
@@ -1137,6 +1149,8 @@ static void do_cgroup_requires(void)
static void do_setup(int argc, char *argv[])
{
+ char *tdebug_env = getenv("LTP_ENABLE_DEBUG");
+
if (!tst_test)
tst_brk(TBROK, "No tests to run");
@@ -1157,6 +1171,11 @@ static void do_setup(int argc, char *argv[])
parse_opts(argc, argv);
+ if (tdebug_env && (!strcmp(tdebug_env, "1") || !strcmp(tdebug_env, "y"))) {
+ tst_res(TINFO, "Enabling debug info");
+ tdebug = 1;
+ }
+
if (tst_test->needs_kconfigs && tst_kconfig_check(tst_test->needs_kconfigs))
tst_brk(TCONF, "Aborting due to unsuitable kernel config, see above!");
diff --git a/lib/tst_test_macros.c b/lib/tst_test_macros.c
new file mode 100644
index 000000000..79d670af6
--- /dev/null
+++ b/lib/tst_test_macros.c
@@ -0,0 +1,36 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (c) 2024 Cyril Hrubis <chrubis@suse.cz>
+ */
+
+#include <stdio.h>
+#define TST_NO_DEFAULT_MAIN
+#include "tst_test.h"
+#include "tst_test_macros.h"
+
+bool tst_errno_in_set(int err, const int *exp_errs, int exp_errs_cnt)
+{
+ int i;
+
+ for (i = 0; i < exp_errs_cnt; i++) {
+ if (err == exp_errs[i])
+ return 1;
+ }
+
+ return 0;
+}
+
+const char *tst_errno_names(char *buf, const int *exp_errs, int exp_errs_cnt)
+{
+ int i;
+ char *cb = buf;
+
+ for (i = 0; i < exp_errs_cnt-1; i++)
+ cb += sprintf(cb, "%s, ", tst_strerrno(exp_errs[i]));
+
+ cb += sprintf(cb, "%s", tst_strerrno(exp_errs[i]));
+
+ *cb = '\0';
+
+ return buf;
+}
diff --git a/libs/libltpswap/libswap.c b/libs/libltpswap/libswap.c
index a4427736f..13610709e 100644
--- a/libs/libltpswap/libswap.c
+++ b/libs/libltpswap/libswap.c
@@ -30,7 +30,8 @@ int make_swapfile(const char *swapfile, int safe)
argv[1] = swapfile;
argv[2] = NULL;
- return tst_cmd(argv, "/dev/null", "/dev/null", safe);
+ return tst_cmd(argv, "/dev/null", "/dev/null", safe ?
+ TST_CMD_PASS_RETVAL | TST_CMD_TCONF_ON_MISSING : 0);
}
/*
@@ -53,10 +54,12 @@ void is_swap_supported(const char *filename)
TEST(tst_syscall(__NR_swapon, filename, 0));
if (TST_RET == -1) {
- if (fibmap == 1 && errno == EINVAL)
+ if (errno == EPERM)
+ tst_brk(TCONF, "Permission denied for swapon()");
+ else if (fibmap == 1 && errno == EINVAL)
tst_brk(TCONF, "Swapfile on %s not implemented", fstype);
else
- tst_brk(TFAIL | TTERRNO, "swapon on %s failed", fstype);
+ tst_brk(TFAIL | TTERRNO, "swapon() on %s failed", fstype);
}
TEST(tst_syscall(__NR_swapoff, filename, 0));
diff --git a/m4/ltp-ptrace.m4 b/m4/ltp-ptrace.m4
deleted file mode 100644
index 6f03fa57e..000000000
--- a/m4/ltp-ptrace.m4
+++ /dev/null
@@ -1,26 +0,0 @@
-dnl SPDX-License-Identifier: GPL-2.0-or-later
-dnl Copyright (c) Jiri Palecek 2009
-
-AC_DEFUN([LTP_CHECK_LINUX_PTRACE],
-_LTP_CHECK_LINUX_PTRACE
-)
-
-dnl Check for ptrace support
-dnl in commit 016ae219 in July 2008
-AC_DEFUN([_LTP_CHECK_LINUX_PTRACE],[
-dnl order of headers checked here is significant
-AC_CHECK_HEADERS([ \
- sys/ptrace.h \
- sys/reg.h \
- asm/ptrace.h \
- linux/ptrace.h \
-])
-save_CPPFLAGS=$CPPFLAGS
-CPPFLAGS="$CPPFLAGS -I$srcdir/testcases/kernel/syscalls/ptrace"
-AC_CHECK_TYPES([struct user_regs_struct, struct pt_regs],,,[#include "ptrace.h"])
-AC_CHECK_DECLS([PTRACE_GETSIGINFO, PTRACE_O_TRACEVFORKDONE, PTRACE_SETOPTIONS],,,[#include "ptrace.h"])
-dnl glibc-2.18 defines ptrace_peeksiginfo_args in sys/ptrace.h which
-dnl conflicts with the one from linux kernel in linux/ptrace.h
-AC_CHECK_TYPES([struct ptrace_peeksiginfo_args],,,[#include <sys/ptrace.h>])
-CPPFLAGS=$save_CPPFLAGS
-])
diff --git a/runltp b/runltp
index 94c4c9b57..62ab66871 100755
--- a/runltp
+++ b/runltp
@@ -629,19 +629,6 @@ EOF
}
}
- # The fsx-linux tests use the SCRATCHDEV environment variable as a location
- # that can be reformatted and run on. Set SCRATCHDEV if you want to run
- # these tests. As a safeguard, this is disabled.
- unset SCRATCHDEV
- [ -n "$SCRATCHDEV" ] && \
- {
- cat ${LTPROOT}/runtest/fsx >> ${TMP}/alltests ||
- {
- echo "FATAL: unable to create fsx-linux tests command file"
- exit 1
- }
- }
-
# If enabled, execute only test cases that match the PATTERN
if [ -n "$TAG_RESTRICT_STRING" ]
then
diff --git a/runtest/connectors b/runtest/connectors
deleted file mode 100644
index 2c7aed474..000000000
--- a/runtest/connectors
+++ /dev/null
@@ -1,2 +0,0 @@
-#DESCRIPTION:Netlink Connector tests
-cn_pec_sh cn_pec.sh
diff --git a/runtest/crashme b/runtest/crashme
index 47f5f93b4..7a630916b 100644
--- a/runtest/crashme
+++ b/runtest/crashme
@@ -8,8 +8,5 @@ crash01 crash01
# Generate random code and execute it. Read f00f comment,
# this test lockup SunOS,WindowsNT,etc. in seconds..
crash02 crash02 -v 2
-# Generate random syscalls and execute them, less probability
-# to hose your system, but still.
-fork12 fork12
# Fork as many children as possible. On systems with lots of memory
# and kernels prior to 2.4.19, this can hang the system by using up all pids
diff --git a/runtest/cve b/runtest/cve
index f9b36a182..1d1d87597 100644
--- a/runtest/cve
+++ b/runtest/cve
@@ -85,6 +85,8 @@ cve-2022-0847 dirtypipe
cve-2022-2590 dirtyc0w_shmem
cve-2022-23222 bpf_prog07
cve-2023-1829 tcindex01
+cve-2023-0461 setsockopt10
+cve-2023-31248 nft02
# Tests below may cause kernel memory leak
cve-2020-25704 perf_event_open03
cve-2022-0185 fsconfig03
diff --git a/runtest/fsx b/runtest/fsx
deleted file mode 100644
index b09e5c2af..000000000
--- a/runtest/fsx
+++ /dev/null
@@ -1,8 +0,0 @@
-#DESCRIPTION:fsx filesystem stress tests
-fsx-linux export TCbin=$LTPROOT/testcases/bin;fsxtest02 10000
-#fsx-ext2 fsxtest $SCRATCHDEV ext2 10000
-#fsx-ext3 fsxtest $SCRATCHDEV ext3 10000
-#fsx-jfs fsxtest $SCRATCHDEV jfs 10000
-#fsx-xfs fsxtest $SCRATCHDEV xfs 10000
-#fsx-reiserfs fsxtest $SCRATCHDEV reiserfs 10000
-
diff --git a/runtest/kernel_misc b/runtest/kernel_misc
index abb75ebaf..02b0ddd1a 100644
--- a/runtest/kernel_misc
+++ b/runtest/kernel_misc
@@ -1,3 +1,4 @@
+cn_pec_sh cn_pec.sh
kmsg01 kmsg01
fw_load fw_load
rtc01 rtc01
diff --git a/runtest/ltp-aiodio.part3 b/runtest/ltp-aiodio.part3
index d53e836b9..decf2f6ea 100644
--- a/runtest/ltp-aiodio.part3
+++ b/runtest/ltp-aiodio.part3
@@ -1,51 +1,21 @@
-# fname: this filename is Required (no default)
-#
-#
-FSX032 fsx-linux -l 500000 -r 4096 -t 4096 -w 4096 -N 10000 $TMPDIR/aiodio.$$/junkfile
-FSX033 fsx-linux -l 500000 -r 4096 -t 2048 -w 2048 -N 10000 $TMPDIR/aiodio.$$/junkfile
-FSX034 fsx-linux -l 500000 -r 4096 -N 10000 $TMPDIR/aiodio.$$/junkfile
-FSX035 fsx-linux -N 10000 $TMPDIR/aiodio.$$/junkfile
-FSX036 fsx-linux -N 10000 $TMPDIR/aiodio.$$/junkfile
-FSX037 fsx-linux -N 10000 $TMPDIR/aiodio.$$/junkfile
-FSX038 fsx-linux -N 10000 $TMPDIR/aiodio.$$/junkfile
-FSX039 fsx-linux -N 10000 $TMPDIR/aiodio.$$/junkfile
-FSX040 fsx-linux -N 10000 -o 1024 $TMPDIR/aiodio.$$/junkfile
-FSX041 fsx-linux -N 10000 -o 2048 $TMPDIR/aiodio.$$/junkfile
-FSX042 fsx-linux -N 10000 -o 4096 $TMPDIR/aiodio.$$/junkfile
-FSX043 fsx-linux -N 10000 -o 8192 $TMPDIR/aiodio.$$/junkfile
-FSX044 fsx-linux -N 10000 -o 16384 $TMPDIR/aiodio.$$/junkfile
-FSX045 fsx-linux -N 10000 -o 32768 $TMPDIR/aiodio.$$/junkfile
-FSX046 fsx-linux -N 10000 -o 128000 $TMPDIR/aiodio.$$/junkfile
-FSX047 fsx-linux -N 10000 -o 1024 $TMPDIR/aiodio.$$/junkfile
-FSX048 fsx-linux -N 10000 -o 2048 $TMPDIR/aiodio.$$/junkfile
-FSX049 fsx-linux -N 10000 -o 4096 $TMPDIR/aiodio.$$/junkfile
-FSX050 fsx-linux -N 10000 -o 8192 $TMPDIR/aiodio.$$/junkfile
-FSX051 fsx-linux -N 10000 -o 16384 $TMPDIR/aiodio.$$/junkfile
-FSX052 fsx-linux -N 10000 -o 32768 $TMPDIR/aiodio.$$/junkfile
-FSX053 fsx-linux -N 10000 -o 128000 $TMPDIR/aiodio.$$/junkfile
-FSX054 fsx-linux -N 10000 -o 1024 -l 500000 -r 4096 -t 4096 -w 4096 $TMPDIR/aiodio.$$/junkfile
-FSX055 fsx-linux -N 10000 -o 2048 -l 500000 -r 4096 -t 2048 -w 2048 $TMPDIR/aiodio.$$/junkfile
-FSX056 fsx-linux -N 10000 -o 4096 -l 500000 -r 4096 -t 4096 -w 4096 $TMPDIR/aiodio.$$/junkfile
-FSX057 fsx-linux -N 10000 -o 8192 -l 500000 -r 4096 -t 2048 -w 2048 $TMPDIR/aiodio.$$/junkfile
-FSX058 fsx-linux -N 10000 -o 16384 -l 500000 -r 4096 -t 4096 -w 4096 $TMPDIR/aiodio.$$/junkfile
-FSX059 fsx-linux -N 10000 -o 32768 -l 500000 -r 4096 -t 2048 -w 2048 $TMPDIR/aiodio.$$/junkfile
-FSX060 fsx-linux -N 10000 -o 128000 -l 500000 -r 4096 -t 4096 -w 4096 $TMPDIR/aiodio.$$/junkfile
-FSX061 fsx-linux -N 10000 -o 32768 $TMPDIR/aiodio.$$/junkfile
-FSX062 fsx-linux -N 10000 -o 128000 $TMPDIR/aiodio.$$/junkfile
-FSX063 fsx-linux -N 10000 -o 1024 -l 500000 -r 4096 -t 4096 -w 4096 $TMPDIR/aiodio.$$/junkfile
-FSX064 fsx-linux -N 10000 -o 2048 -l 500000 -r 4096 -t 2048 -w 2048 $TMPDIR/aiodio.$$/junkfile
-FSX065 fsx-linux -N 10000 -o 4096 -l 500000 -r 4096 -t 4096 -w 4096 $TMPDIR/aiodio.$$/junkfile
-FSX066 fsx-linux -N 10000 -o 8192 -l 500000 -r 4096 -t 2048 -w 2048 $TMPDIR/aiodio.$$/junkfile
-FSX067 fsx-linux -N 10000 -o 16384 -l 500000 -r 4096 -t 4096 -w 4096 $TMPDIR/aiodio.$$/junkfile
-FSX068 fsx-linux -N 10000 -o 32768 -l 500000 -r 4096 -t 2048 -w 2048 $TMPDIR/aiodio.$$/junkfile
-FSX069 fsx-linux -N 10000 -o 128000 -l 500000 -r 4096 -t 4096 -w 4096 $TMPDIR/aiodio.$$/junkfile
-FSX070 fsx-linux -N 10000 -o 128000 -l 500000 -r 4096 -t 4096 -w 4096 $TMPDIR/aiodio.$$/junkfile
-FSX071 fsx-linux -N 10000 -o 16384 -l 500000 -r 4096 -t 4096 -w 4096 $TMPDIR/aiodio.$$/junkfile1
-FSX072 fsx-linux -N 10000 -o 32768 -l 500000 -r 4096 -t 2048 -w 2048 $TMPDIR/aiodio.$$/junkfile2
-FSX073 fsx-linux -N 10000 -o 128000 -l 500000 -r 4096 -t 4096 -w 4096 $TMPDIR/aiodio.$$/junkfile3
-FSX074 fsx-linux -N 10000 -o 16384 -l 500000 -r 4096 -t 4096 -w 4096 $TMPDIR/aiodio.$$/junkfile4
-FSX075 fsx-linux -N 10000 -o 32768 -l 500000 -r 4096 -t 2048 -w 2048 $TMPDIR/aiodio.$$/junkfile5
-FSX076 fsx-linux -N 10000 -o 128000 -l 500000 -r 4096 -t 4096 -w 4096 $TMPDIR/aiodio.$$/junkfile6
-FSX077 fsx-linux -N 10000 $TMPDIR/aiodio.$$/junkfile7
-FSX078 fsx-linux -N 100000 $TMPDIR/aiodio.$$/junkfile8
-FSX079 fsx-linux -N 100000 $TMPDIR/aiodio.$$/junkfile9
+fsx01 fsx-linux -l 500000 -r 4096 -t 4096 -w 4096 -N 10000
+fsx02 fsx-linux -l 500000 -r 4096 -t 2048 -w 2048 -N 10000
+fsx03 fsx-linux -l 500000 -r 4096 -N 10000
+fsx04 fsx-linux -N 10000
+fsx05 fsx-linux -N 10000 -o 1024
+fsx06 fsx-linux -N 10000 -o 2048
+fsx07 fsx-linux -N 10000 -o 4096
+fsx08 fsx-linux -N 10000 -o 8192
+fsx09 fsx-linux -N 10000 -o 16384
+fsx10 fsx-linux -N 10000 -o 32768
+fsx12 fsx-linux -N 10000 -o 128000
+fsx13 fsx-linux -N 10000 -o 1024 -l 500000 -r 4096 -t 4096 -w 4096
+fsx14 fsx-linux -N 10000 -o 2048 -l 500000 -r 4096 -t 2048 -w 2048
+fsx15 fsx-linux -N 10000 -o 4096 -l 500000 -r 4096 -t 4096 -w 4096
+fsx16 fsx-linux -N 10000 -o 8192 -l 500000 -r 4096 -t 2048 -w 2048
+fsx17 fsx-linux -N 10000 -o 16384 -l 500000 -r 4096 -t 4096 -w 4096
+fsx18 fsx-linux -N 10000 -o 32768 -l 500000 -r 4096 -t 2048 -w 2048
+fsx19 fsx-linux -N 10000 -o 128000 -l 500000 -r 4096 -t 4096 -w 4096
+fsx20 fsx-linux -N 10000 -o 128000 -l 500000 -r 4096 -t 4096 -w 40963
+fsx21 fsx-linux -N 10000 -o 128000 -l 500000 -r 4096 -t 4096 -w 40966
+fsx22 fsx-linux -N 100000
diff --git a/runtest/mm b/runtest/mm
index f288fed36..d859b331c 100644
--- a/runtest/mm
+++ b/runtest/mm
@@ -70,6 +70,7 @@ ksm05 ksm05 -I 10
ksm06 ksm06
ksm06_1 ksm06 -n 10
ksm06_2 ksm06 -n 8000
+ksm07 ksm07
cpuset01 cpuset01
diff --git a/runtest/sched b/runtest/sched
index 172fe4174..5dab7a4c2 100644
--- a/runtest/sched
+++ b/runtest/sched
@@ -11,6 +11,8 @@ hackbench01 hackbench 50 process 1000
hackbench02 hackbench 20 thread 1000
starvation starvation
+proc_sched_rt01 proc_sched_rt01
+
sched_cli_serv run_sched_cliserv.sh
# Run this stress test for 2 minutes
sched_stress sched_stress.sh
diff --git a/runtest/syscalls b/runtest/syscalls
index 906753578..db5648ee3 100644
--- a/runtest/syscalls
+++ b/runtest/syscalls
@@ -3,6 +3,7 @@ abort01 abort01
accept01 accept01
accept02 accept02
+accept03 accept03
accept4_01 accept4_01
@@ -259,6 +260,7 @@ fchmod06 fchmod06
#fchmodat test cases
fchmodat01 fchmodat01
+fchmodat02 fchmodat02
fchown01 fchown01
fchown01_16 fchown01_16
@@ -379,12 +381,12 @@ fork01 fork01
fork03 fork03
fork04 fork04
fork05 fork05
-fork06 fork06
+fork06 fork_procs -n 1000
fork07 fork07
fork08 fork08
fork09 fork09
fork10 fork10
-fork11 fork11
+fork11 fork_procs -n 100
fork13 fork13
fork14 fork14
@@ -448,8 +450,6 @@ getdents02 getdents02
getdomainname01 getdomainname01
-getdtablesize01 getdtablesize01
-
getegid01 getegid01
getegid01_16 getegid01_16
getegid02 getegid02
@@ -538,6 +538,7 @@ getsockopt01 getsockopt01
getsockopt02 getsockopt02
gettid01 gettid01
+gettid02 gettid02
gettimeofday01 gettimeofday01
gettimeofday02 gettimeofday02
@@ -557,7 +558,7 @@ init_module01 init_module01
init_module02 init_module02
#Needs tty device.
-#ioctl02 ioctl02 -D /dev/tty0
+#ioctl02 ioctl02 -d /dev/tty0
# Introducing ioctl tests for all /dev/tty* devices
ioctl01 ioctl01
@@ -693,7 +694,6 @@ lgetxattr02 lgetxattr02
link01 symlink01 -T link01
link02 link02
-link03 link03
link04 link04
link05 link05
link08 link08
@@ -970,6 +970,7 @@ madvise11 madvise11
newuname01 newuname01
pathconf01 pathconf01
+pathconf02 pathconf02
pause01 pause01
pause02 pause02
@@ -1004,6 +1005,7 @@ pipe11 pipe11
pipe12 pipe12
pipe13 pipe13
pipe14 pipe14
+pipe15 pipe15
pipe2_01 pipe2_01
pipe2_02 pipe2_02
@@ -1073,8 +1075,7 @@ ptrace02 ptrace02
ptrace03 ptrace03
ptrace04 ptrace04
ptrace05 ptrace05
-# Broken test; See: testcases/kernel/syscalls/ptrace/Makefile for more details.
-#ptrace06 ptrace06
+ptrace06 ptrace06
ptrace07 ptrace07
ptrace08 ptrace08
ptrace09 ptrace09
@@ -1228,6 +1229,7 @@ sched_getscheduler02 sched_getscheduler02
sched_setscheduler01 sched_setscheduler01
sched_setscheduler02 sched_setscheduler02
sched_setscheduler03 sched_setscheduler03
+sched_setscheduler04 sched_setscheduler04
sched_yield01 sched_yield01
@@ -1437,6 +1439,7 @@ setsockopt06 setsockopt06
setsockopt07 setsockopt07
setsockopt08 setsockopt08
setsockopt09 setsockopt09
+setsockopt10 setsockopt10
settimeofday01 settimeofday01
settimeofday02 settimeofday02
@@ -1525,6 +1528,8 @@ splice02 splice02
splice03 splice03
splice04 splice04
splice05 splice05
+splice06 splice06
+splice07 splice07
tee01 tee01
tee02 tee02
@@ -1569,7 +1574,6 @@ symlink01 symlink01
symlink02 symlink02
symlink03 symlink03
symlink04 symlink04
-symlink05 symlink05
#symlinkat test cases
symlinkat01 symlinkat01
@@ -1618,7 +1622,6 @@ times03 times03
timerfd01 timerfd01
timerfd02 timerfd02
-timerfd03 timerfd03
timerfd04 timerfd04
timerfd_create01 timerfd_create01
timerfd_gettime01 timerfd_gettime01
diff --git a/scenario_groups/default b/scenario_groups/default
index 68bd5300d..f17b2061a 100644
--- a/scenario_groups/default
+++ b/scenario_groups/default
@@ -1,7 +1,6 @@
syscalls
fs
fs_perms_simple
-fsx
dio
io
mm
diff --git a/testcases/commands/gzip/gzip_tests.sh b/testcases/commands/gzip/gzip_tests.sh
index fdc933ea2..3262c555b 100755
--- a/testcases/commands/gzip/gzip_tests.sh
+++ b/testcases/commands/gzip/gzip_tests.sh
@@ -82,7 +82,8 @@ test1()
gzip -r tst_gzip.tmp > tst_gzip.err 2>&1
if [ $? -ne 0 ]; then
cat tst_gzip.err
- tst_brk TFAIL "Test #1: gzip -r failed"
+ tst_res TFAIL "Test #1: gzip -r failed"
+ return
fi
tst_res TINFO "Test #1: creating output file"
diff --git a/testcases/commands/mv/mv_tests.sh b/testcases/commands/mv/mv_tests.sh
index 91648dd8f..ae8b8701d 100755
--- a/testcases/commands/mv/mv_tests.sh
+++ b/testcases/commands/mv/mv_tests.sh
@@ -88,7 +88,8 @@ test1()
mv tst_mv.old tst_mv.new > tst_mv.err 2>&1
if [ $? -ne 0 ]; then
cat tst_mv.err
- tst_brk TFAIL "Test #1: 'mv tst_mv.old tst_mv.new' failed"
+ tst_res TFAIL "Test #1: 'mv tst_mv.old tst_mv.new' failed"
+ return
fi
tst_res TINFO "Test #1: creating output file"
diff --git a/testcases/cve/Makefile b/testcases/cve/Makefile
index c5308794d..01b9b9ccb 100644
--- a/testcases/cve/Makefile
+++ b/testcases/cve/Makefile
@@ -7,7 +7,7 @@ include $(top_srcdir)/include/mk/testcases.mk
CFLAGS += -D_GNU_SOURCE
-stack_clash: CFLAGS += -fno-optimize-sibling-calls
+stack_clash: CFLAGS += -fno-optimize-sibling-calls -Wno-infinite-recursion
cve-2016-7042: LDLIBS += $(KEYUTILS_LIBS)
diff --git a/testcases/cve/stack_clash.c b/testcases/cve/stack_clash.c
index 3a99c49bb..56b970a1b 100644
--- a/testcases/cve/stack_clash.c
+++ b/testcases/cve/stack_clash.c
@@ -92,6 +92,7 @@ void segv_handler(int sig, siginfo_t *info, void *data LTP_ATTRIBUTE_UNUSED)
_exit(EXIT_SUCCESS);
}
+#ifdef __x86_64__
static void force_bottom_up(void)
{
FILE *fh;
@@ -134,6 +135,7 @@ static void force_bottom_up(void)
out:
SAFE_FCLOSE(fh);
}
+#endif
unsigned long read_stack_addr_from_proc(unsigned long *stack_size)
{
@@ -187,6 +189,7 @@ void __attribute__((noinline)) preallocate_stack(unsigned long required)
garbage[0] = garbage[required - 1] = '\0';
}
+#ifdef __x86_64__
static void do_mmap_placement_test(unsigned long stack_addr, unsigned long gap)
{
void *map_test_gap;
@@ -208,6 +211,7 @@ static void do_mmap_placement_test(unsigned long stack_addr, unsigned long gap)
SAFE_MUNMAP(map_test_gap, MAPPED_LEN);
}
}
+#endif
void do_child(void)
{
diff --git a/testcases/cve/tcindex01.c b/testcases/cve/tcindex01.c
index 91bfafb53..70e5639f1 100644
--- a/testcases/cve/tcindex01.c
+++ b/testcases/cve/tcindex01.c
@@ -24,7 +24,7 @@
#include <linux/pkt_sched.h>
#include <linux/pkt_cls.h>
#include "tst_test.h"
-#include "tst_rtnetlink.h"
+#include "tst_netlink.h"
#include "tst_netdevice.h"
#include "lapi/sched.h"
#include "lapi/if_ether.h"
@@ -32,6 +32,23 @@
#define DEVNAME "ltp_dummy1"
+#ifndef TCA_TCINDEX_MAX
+enum {
+ TCA_TCINDEX_UNSPEC,
+ TCA_TCINDEX_HASH,
+ TCA_TCINDEX_MASK,
+ TCA_TCINDEX_SHIFT,
+ TCA_TCINDEX_FALL_THROUGH,
+ TCA_TCINDEX_CLASSID,
+ TCA_TCINDEX_POLICE,
+ TCA_TCINDEX_ACT,
+ __TCA_TCINDEX_MAX
+};
+
+#define TCA_TCINDEX_MAX (__TCA_TCINDEX_MAX - 1)
+#endif
+
+
static const uint32_t qd_handle = TC_H_MAKE(1 << 16, 0);
static const uint32_t clsid = TC_H_MAKE(1 << 16, 1);
static const uint32_t shift = 10;
@@ -46,15 +63,15 @@ static const struct tc_htb_glob qd_opt = {
static struct tc_htb_opt cls_opt = {};
/* htb qdisc and class options */
-static const struct tst_rtnl_attr_list qd_config[] = {
- {TCA_OPTIONS, NULL, 0, (const struct tst_rtnl_attr_list[]){
+static const struct tst_netlink_attr_list qd_config[] = {
+ {TCA_OPTIONS, NULL, 0, (const struct tst_netlink_attr_list[]){
{TCA_HTB_INIT, &qd_opt, sizeof(qd_opt), NULL},
{0, NULL, -1, NULL}
}},
{0, NULL, -1, NULL}
};
-static const struct tst_rtnl_attr_list cls_config[] = {
- {TCA_OPTIONS, NULL, 0, (const struct tst_rtnl_attr_list[]){
+static const struct tst_netlink_attr_list cls_config[] = {
+ {TCA_OPTIONS, NULL, 0, (const struct tst_netlink_attr_list[]){
{TCA_HTB_PARMS, &cls_opt, sizeof(cls_opt), NULL},
{0, NULL, -1, NULL}
}},
@@ -62,8 +79,8 @@ static const struct tst_rtnl_attr_list cls_config[] = {
};
/* tcindex filter options */
-static const struct tst_rtnl_attr_list f_config[] = {
- {TCA_OPTIONS, NULL, 0, (const struct tst_rtnl_attr_list[]){
+static const struct tst_netlink_attr_list f_config[] = {
+ {TCA_OPTIONS, NULL, 0, (const struct tst_netlink_attr_list[]){
{TCA_TCINDEX_MASK, &mask, sizeof(mask), NULL},
{TCA_TCINDEX_SHIFT, &shift, sizeof(shift), NULL},
{TCA_TCINDEX_CLASSID, &clsid, sizeof(clsid), NULL},
@@ -95,7 +112,7 @@ static void run(void)
1, "tcindex");
ret = tst_netdev_add_traffic_filter(__FILE__, __LINE__, 0, DEVNAME,
qd_handle, 10, ETH_P_IP, 1, "tcindex", f_config);
- TST_ERR = tst_rtnl_errno;
+ TST_ERR = tst_netlink_errno;
NETDEV_REMOVE_QDISC(DEVNAME, AF_UNSPEC, TC_H_ROOT, qd_handle, "htb");
if (ret)
@@ -128,6 +145,10 @@ static struct tst_test test = {
{"/proc/sys/user/max_user_namespaces", "1024", TST_SR_SKIP},
{}
},
+ .needs_drivers = (const char *const []) {
+ "dummy",
+ NULL
+ },
.tags = (const struct tst_tag[]) {
{"linux-git", "8c710f75256b"},
{"CVE", "2023-1829"},
diff --git a/testcases/kernel/containers/pidns/pidns05.c b/testcases/kernel/containers/pidns/pidns05.c
index 0e7739aaa..7843fe7a9 100644
--- a/testcases/kernel/containers/pidns/pidns05.c
+++ b/testcases/kernel/containers/pidns/pidns05.c
@@ -24,7 +24,7 @@ static struct tst_clone_args clone_args = {
};
static pid_t pid_max;
-static void child_func(int *level)
+static void child_func(const int level)
{
pid_t cpid, ppid;
@@ -34,15 +34,13 @@ static void child_func(int *level)
TST_EXP_EQ_LI(cpid, 1);
TST_EXP_EQ_LI(ppid, 0);
- if (*level >= MAX_DEPTH) {
+ if (level >= MAX_DEPTH - 1) {
TST_CHECKPOINT_WAKE(0);
return;
}
- (*level)++;
-
if (!SAFE_CLONE(&clone_args)) {
- child_func(level);
+ child_func(level + 1);
return;
}
@@ -81,14 +79,13 @@ static void setup(void)
static void run(void)
{
int i, status, children;
- int level = 0;
pid_t pids_new[MAX_DEPTH];
pid_t pids[MAX_DEPTH];
pid_t pid;
pid = SAFE_CLONE(&clone_args);
if (!pid) {
- child_func(&level);
+ child_func(0);
return;
}
diff --git a/testcases/kernel/controllers/cpuset/cpuset_funcs.sh b/testcases/kernel/controllers/cpuset/cpuset_funcs.sh
index 0cfa0c17e..567178e3f 100755
--- a/testcases/kernel/controllers/cpuset/cpuset_funcs.sh
+++ b/testcases/kernel/controllers/cpuset/cpuset_funcs.sh
@@ -165,8 +165,7 @@ setup()
mount -t cgroup -o cpuset cpuset "$CPUSET" 2> /dev/null
if [ $? -ne 0 ]; then
cleanup
- tst_brkm TFAIL "Could not mount cgroup filesystem with"\
- " cpuset on $CPUSET..Exiting test"
+ tst_brkm TCONF "Could not mount cgroup filesystem with cpuset on $CPUSET"
fi
CHILDREN_VALUE="`cat $CLONE_CHILDREN`"
diff --git a/testcases/kernel/controllers/cpuset/cpuset_regression_test.sh b/testcases/kernel/controllers/cpuset/cpuset_regression_test.sh
index a5757309f..bedc48110 100755
--- a/testcases/kernel/controllers/cpuset/cpuset_regression_test.sh
+++ b/testcases/kernel/controllers/cpuset/cpuset_regression_test.sh
@@ -190,21 +190,27 @@ do_test()
ROD_SILENT mkdir ${root_cpuset_dir}/testdir
# Creat an exclusive cpuset.
- echo 1 > ${root_cpuset_dir}/testdir/${cpu_exclusive}
- [ $? -ne 0 ] && tst_brk TFAIL "'echo 1 > ${root_cpuset_dir}/testdir/${cpu_exclusive}' failed"
+ if ! echo 1 > ${root_cpuset_dir}/testdir/${cpu_exclusive}; then
+ tst_res TFAIL "'echo 1 > ${root_cpuset_dir}/testdir/${cpu_exclusive}' failed"
+ return
+ fi
cpu_exclusive_tmp=$(cat ${root_cpuset_dir}/testdir/${cpu_exclusive})
if [ "${cpu_exclusive_tmp}" != "1" ]; then
- tst_brk TFAIL "${cpu_exclusive} is '${cpu_exclusive_tmp}', expected '1'"
+ tst_res TFAIL "${cpu_exclusive} is '${cpu_exclusive_tmp}', expected '1'"
+ return
fi
# This may trigger the kernel crash
- echo 0 > ${root_cpuset_dir}/testdir/${cpus}
- [ $? -ne 0 ] && tst_brk TFAIL "'echo 0 > ${root_cpuset_dir}/testdir/${cpus}' failed"
+ if ! echo 0 > ${root_cpuset_dir}/testdir/${cpus}; then
+ tst_res TFAIL "'echo 0 > ${root_cpuset_dir}/testdir/${cpus}' failed"
+ return
+ fi
cpus_value=$(cat ${root_cpuset_dir}/testdir/${cpus})
if [ "${cpus_value}" != "0" ]; then
- tst_brk TFAIL "${cpus} is '${cpus_value}', expected '0'"
+ tst_res TFAIL "${cpus} is '${cpus_value}', expected '0'"
+ return
fi
tst_res TPASS "Bug is not reproducible"
diff --git a/testcases/kernel/controllers/freezer/vfork.c b/testcases/kernel/controllers/freezer/vfork.c
index 0b25e90c2..9f4359bf8 100644
--- a/testcases/kernel/controllers/freezer/vfork.c
+++ b/testcases/kernel/controllers/freezer/vfork.c
@@ -29,6 +29,7 @@
* until vfork returns. This can delay delivery of signals to the parent
* process, even delay or stop system suspend.
*/
+
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -39,9 +40,8 @@
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/socket.h>
+#include <sys/ptrace.h>
#include "test.h"
-#include "config.h"
-#include "../../syscalls/ptrace/ptrace.h"
#define str_expand(s) str(s)
#define str(s) #s
diff --git a/testcases/kernel/controllers/memcg/functional/memcg_subgroup_charge.sh b/testcases/kernel/controllers/memcg/functional/memcg_subgroup_charge.sh
index 9bcc01258..3b7311422 100755
--- a/testcases/kernel/controllers/memcg/functional/memcg_subgroup_charge.sh
+++ b/testcases/kernel/controllers/memcg/functional/memcg_subgroup_charge.sh
@@ -33,8 +33,8 @@ test_subgroup()
fi
echo $MEMCG_PROCESS_PID > tasks
- signal_memcg_process $MEM_TO_ALLOC
- check_mem_stat "rss" $MEM_TO_ALLOC
+ signal_memcg_process $MIN_CHARGED
+ check_mem_stat "rss" $MIN_CHARGED $MEM_TO_ALLOC
cd subgroup
echo $MEMCG_PROCESS_PID > tasks
@@ -66,5 +66,6 @@ test3()
# Allocate memory bigger than per-cpu kernel memory
MEM_TO_ALLOC=$((PAGESIZES * 2))
+MIN_CHARGED=$((2 * (PAGESIZES - 1)))
tst_run
diff --git a/testcases/kernel/controllers/memcg/memcontrol02.c b/testcases/kernel/controllers/memcg/memcontrol02.c
index 1656176b6..0d93abd9e 100644
--- a/testcases/kernel/controllers/memcg/memcontrol02.c
+++ b/testcases/kernel/controllers/memcg/memcontrol02.c
@@ -134,7 +134,7 @@ static struct tst_test test = {
.tcnt = 2,
.test = test_memcg_current,
.mount_device = 1,
- .dev_min_size = 256,
+ .dev_min_size = 300,
.mntpoint = TMPDIR,
.all_filesystems = 1,
.forks_child = 1,
diff --git a/testcases/kernel/controllers/memcg/memcontrol03.c b/testcases/kernel/controllers/memcg/memcontrol03.c
index bc726f395..9c6c808e0 100644
--- a/testcases/kernel/controllers/memcg/memcontrol03.c
+++ b/testcases/kernel/controllers/memcg/memcontrol03.c
@@ -239,7 +239,6 @@ static struct tst_test test = {
.cleanup = cleanup,
.test_all = test_memcg_min,
.mount_device = 1,
- .dev_min_size = 256,
.mntpoint = TMPDIR,
.all_filesystems = 1,
.skip_filesystems = (const char *const[]){
diff --git a/testcases/kernel/controllers/memcg/memcontrol04.c b/testcases/kernel/controllers/memcg/memcontrol04.c
index c963a1cd8..32a0b9fd4 100644
--- a/testcases/kernel/controllers/memcg/memcontrol04.c
+++ b/testcases/kernel/controllers/memcg/memcontrol04.c
@@ -232,7 +232,6 @@ static struct tst_test test = {
.cleanup = cleanup,
.test_all = test_memcg_low,
.mount_device = 1,
- .dev_min_size = 256,
.mntpoint = TMPDIR,
.all_filesystems = 1,
.skip_filesystems = (const char *const[]){
diff --git a/testcases/kernel/controllers/memcg/memcontrol_common.h b/testcases/kernel/controllers/memcg/memcontrol_common.h
index adb6fafb3..a3bd243f5 100644
--- a/testcases/kernel/controllers/memcg/memcontrol_common.h
+++ b/testcases/kernel/controllers/memcg/memcontrol_common.h
@@ -1,5 +1,8 @@
// SPDX-License-Identifier: GPL-2.0
+#ifndef MEMCONTROL_COMMON_H__
+#define MEMCONTROL_COMMON_H__
+
#include <stdlib.h>
#include <stdio.h>
@@ -45,3 +48,5 @@ static inline void alloc_anon(const size_t size)
free(buf);
}
+
+#endif /* MEMCONTROL_COMMON_H__ */
diff --git a/testcases/kernel/controllers/memcg/regression/memcg_test_3.c b/testcases/kernel/controllers/memcg/regression/memcg_test_3.c
index f29c2bea5..31b1b5a83 100644
--- a/testcases/kernel/controllers/memcg/regression/memcg_test_3.c
+++ b/testcases/kernel/controllers/memcg/regression/memcg_test_3.c
@@ -21,6 +21,7 @@
static volatile int sigcounter;
static struct tst_cg_group *test_cg;
+static pid_t ppid;
static void sighandler(int sig LTP_ATTRIBUTE_UNUSED)
{
@@ -29,8 +30,8 @@ static void sighandler(int sig LTP_ATTRIBUTE_UNUSED)
static void do_child(void)
{
- while (1)
- SAFE_KILL(getppid(), SIGUSR1);
+ while (getppid() == ppid)
+ SAFE_KILL(ppid, SIGUSR1);
exit(0);
}
@@ -40,6 +41,7 @@ static void do_test(void)
pid_t cpid;
SAFE_SIGNAL(SIGUSR1, sighandler);
+ ppid = getpid();
cpid = SAFE_FORK();
if (cpid == 0)
diff --git a/testcases/kernel/crypto/crypto_user01.c b/testcases/kernel/crypto/crypto_user01.c
index 47bf9f0d2..6f6036aed 100644
--- a/testcases/kernel/crypto/crypto_user01.c
+++ b/testcases/kernel/crypto/crypto_user01.c
@@ -17,7 +17,6 @@
#include "tst_test.h"
#include "tst_crypto.h"
-#include "tst_netlink.h"
/*
* include after <sys/socket.h> (via tst_test.h), to work around dependency bug
@@ -25,11 +24,11 @@
*/
#include <linux/rtnetlink.h>
-static struct tst_crypto_session ses = TST_CRYPTO_SESSION_INIT;
+static struct tst_netlink_context *ctx;
static void setup(void)
{
- tst_crypto_open(&ses);
+ ctx = NETLINK_CREATE_CONTEXT(NETLINK_CRYPTO);
}
static void do_check_for_leaks(const char *name, const char *value, size_t vlen)
@@ -131,25 +130,20 @@ static void validate_one_alg(const struct nlmsghdr *nh)
}
}
-static void validate_alg_list(const void *buf, size_t remaining)
+static void validate_alg_list(const struct tst_netlink_message *msg)
{
- const struct nlmsghdr *nh;
-
- for (nh = buf; NLMSG_OK(nh, remaining);
- nh = NLMSG_NEXT(nh, remaining)) {
- if (nh->nlmsg_seq != ses.seq_num) {
- tst_brk(TBROK,
- "Message out of sequence; type=0%hx, seq_num=%u (not %u)",
- nh->nlmsg_type, nh->nlmsg_seq, ses.seq_num);
- }
- if (nh->nlmsg_type == NLMSG_DONE)
+ for (; msg->header; msg++) {
+ if (msg->header->nlmsg_type == NLMSG_DONE)
return;
- if (nh->nlmsg_type != CRYPTO_MSG_GETALG) {
+
+ if (msg->header->nlmsg_type != CRYPTO_MSG_GETALG) {
tst_brk(TBROK,
"Unexpected message type; type=0x%hx, seq_num=%u",
- nh->nlmsg_type, nh->nlmsg_seq);
+ msg->header->nlmsg_type,
+ msg->header->nlmsg_seq);
}
- validate_one_alg(nh);
+
+ validate_one_alg(msg->header);
}
}
@@ -157,35 +151,23 @@ static void run(void)
{
struct crypto_user_alg payload = { 0 };
struct nlmsghdr nh = {
- .nlmsg_len = sizeof(payload),
.nlmsg_type = CRYPTO_MSG_GETALG,
.nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP,
- .nlmsg_seq = ++(ses.seq_num),
- .nlmsg_pid = 0,
};
- /*
- * Due to an apparent kernel bug, this API cannot be used incrementally,
- * so we just use a large recvmsg() buffer. This is good enough since
- * we don't necessarily have to check every algorithm for this test to
- * be effective...
- */
- const size_t bufsize = 1048576;
- void *buf = SAFE_MALLOC(bufsize);
- size_t res;
-
- SAFE_NETLINK_SEND(ses.fd, &nh, &payload);
-
- res = SAFE_NETLINK_RECV(ses.fd, buf, bufsize);
-
- validate_alg_list(buf, res);
-
- free(buf);
+ struct tst_netlink_message *msg;
+
+ NETLINK_ADD_MESSAGE(ctx, &nh, &payload, sizeof(payload));
+ NETLINK_SEND(ctx);
+ NETLINK_WAIT(ctx);
+ msg = NETLINK_RECV(ctx);
+ validate_alg_list(msg);
+ NETLINK_FREE_MESSAGE(msg);
tst_res(TPASS, "No information leaks found");
}
static void cleanup(void)
{
- tst_crypto_close(&ses);
+ NETLINK_DESTROY_CONTEXT(ctx);
}
static struct tst_test test = {
diff --git a/testcases/kernel/crypto/crypto_user02.c b/testcases/kernel/crypto/crypto_user02.c
index afaff5d18..89cbb9bc5 100644
--- a/testcases/kernel/crypto/crypto_user02.c
+++ b/testcases/kernel/crypto/crypto_user02.c
@@ -52,7 +52,7 @@ static const char * const ALGORITHM_CANDIDATES[] = {
};
static const char* algorithm = NULL;
-static struct tst_crypto_session ses = TST_CRYPTO_SESSION_INIT;
+static struct tst_netlink_context *ctx;
static void setup(void)
@@ -60,7 +60,8 @@ static void setup(void)
int rc;
unsigned i;
struct crypto_user_alg alg;
- tst_crypto_open(&ses);
+
+ ctx = NETLINK_CREATE_CONTEXT(NETLINK_CRYPTO);
/* find an algorithm, that is not in use */
for (i = 0; i < ARRAY_SIZE(ALGORITHM_CANDIDATES); ++i) {
@@ -68,12 +69,12 @@ static void setup(void)
strcpy(alg.cru_driver_name, ALGORITHM_CANDIDATES[i]);
/* try to add it, to see if it is valid */
- rc = tst_crypto_add_alg(&ses, &alg);
+ rc = tst_crypto_add_alg(ctx, &alg);
if (rc != 0)
continue;
/* it also has to be deletable */
- rc = tst_crypto_del_alg(&ses, &alg);
+ rc = tst_crypto_del_alg(ctx, &alg, 1000);
if (rc == 0) {
algorithm = ALGORITHM_CANDIDATES[i];
break;
@@ -103,9 +104,9 @@ static void run(void)
if (pid == 0) {
/* Child process: execute CRYPTO_MSG_NEWALG. */
- tst_crypto_open(&ses);
+ ctx = NETLINK_CREATE_CONTEXT(NETLINK_CRYPTO);
for (;;) {
- TEST(tst_crypto_add_alg(&ses, &alg));
+ TEST(tst_crypto_add_alg(ctx, &alg));
if (TST_RET && TST_RET != -EEXIST)
tst_brk(TBROK | TRERRNO,
"unexpected error from tst_crypto_add_alg()");
@@ -123,7 +124,7 @@ static void run(void)
SAFE_WAIT(&status);
if (!WIFSIGNALED(status) || WTERMSIG(status) != SIGKILL)
tst_brk(TBROK, "child %s", tst_strstatus(status));
- TEST(tst_crypto_del_alg(&ses, &alg));
+ TEST(tst_crypto_del_alg(ctx, &alg, 1000));
if (TST_RET && TST_RET != -ENOENT)
tst_brk(TBROK | TRERRNO,
"unexpected error from tst_crypto_del_alg()");
@@ -134,7 +135,7 @@ static void run(void)
static void cleanup(void)
{
- tst_crypto_close(&ses);
+ NETLINK_DESTROY_CONTEXT(ctx);
}
static struct tst_test test = {
diff --git a/testcases/kernel/crypto/pcrypt_aead01.c b/testcases/kernel/crypto/pcrypt_aead01.c
index 3b4f5d8d1..3979f317a 100644
--- a/testcases/kernel/crypto/pcrypt_aead01.c
+++ b/testcases/kernel/crypto/pcrypt_aead01.c
@@ -26,11 +26,11 @@
#define ATTEMPTS 10000
-static struct tst_crypto_session ses = TST_CRYPTO_SESSION_INIT;
+static struct tst_netlink_context *ctx;
void setup(void)
{
- tst_crypto_open(&ses);
+ ctx = NETLINK_CREATE_CONTEXT(NETLINK_CRYPTO);
}
void run(void)
@@ -43,7 +43,7 @@ void run(void)
};
for (i = 0; i < ATTEMPTS; ++i) {
- TEST(tst_crypto_add_alg(&ses, &a));
+ TEST(tst_crypto_add_alg(ctx, &a));
if (TST_RET && TST_RET == -ENOENT) {
tst_brk(TCONF | TRERRNO,
"pcrypt, hmac, sha256, cbc or aes not supported");
@@ -51,7 +51,7 @@ void run(void)
if (TST_RET && TST_RET != -EEXIST)
tst_brk(TBROK | TRERRNO, "add_alg");
- TEST(tst_crypto_del_alg(&ses, &a));
+ TEST(tst_crypto_del_alg(ctx, &a, 1000));
if (TST_RET)
tst_brk(TBROK | TRERRNO, "del_alg");
@@ -67,7 +67,7 @@ void run(void)
void cleanup(void)
{
- tst_crypto_close(&ses);
+ NETLINK_DESTROY_CONTEXT(ctx);
}
static struct tst_test test = {
diff --git a/testcases/kernel/device-drivers/zram/zram01.sh b/testcases/kernel/device-drivers/zram/zram01.sh
index 6bc305f2c..0c100b706 100755
--- a/testcases/kernel/device-drivers/zram/zram01.sh
+++ b/testcases/kernel/device-drivers/zram/zram01.sh
@@ -82,7 +82,9 @@ zram_makefs()
mkfs.$fs /dev/zram$i > err.log 2>&1
if [ $? -ne 0 ]; then
cat err.log
- tst_brk TFAIL "failed to make $fs on /dev/zram$i"
+ tst_res TFAIL "Failed to make $fs on /dev/zram$i"
+ tst_brk TBROK "Can't continue with mounting the FS"
+ return
fi
i=$(($i + 1))
diff --git a/testcases/kernel/device-drivers/zram/zram03.c b/testcases/kernel/device-drivers/zram/zram03.c
index 98eb61e1c..1df3325ec 100644
--- a/testcases/kernel/device-drivers/zram/zram03.c
+++ b/testcases/kernel/device-drivers/zram/zram03.c
@@ -89,7 +89,7 @@ static void verify_device(void)
SAFE_CLOSE(fd);
}
-static void reset(void)
+static void reset_zram(void)
{
char reset_path[200];
@@ -163,7 +163,7 @@ static void run(void)
dump_info();
verify_device();
- reset();
+ reset_zram();
dump_info();
}
@@ -181,7 +181,7 @@ static void setup(void)
tst_res(TINFO,
"zram module already loaded, kernel supports zram-control interface");
SAFE_FILE_SCANF(HOT_ADD_PATH, "%d", &dev_num);
- hot_add_flag =1;
+ hot_add_flag = 1;
goto fill_path;
}
diff --git a/testcases/kernel/device-drivers/zram/zram_lib.sh b/testcases/kernel/device-drivers/zram/zram_lib.sh
index e94d7db11..e94f9244d 100755
--- a/testcases/kernel/device-drivers/zram/zram_lib.sh
+++ b/testcases/kernel/device-drivers/zram/zram_lib.sh
@@ -108,12 +108,16 @@ zram_max_streams()
for max_s in $zram_max_streams; do
local sys_path="/sys/block/zram${i}/max_comp_streams"
- echo $max_s > $sys_path || \
- tst_brk TFAIL "failed to set '$max_s' to $sys_path"
+ if ! echo $max_s > $sys_path; then
+ tst_res TFAIL "failed to set '$max_s' to $sys_path"
+ return
+ fi
local max_streams=$(cat $sys_path)
- [ "$max_s" -ne "$max_streams" ] && \
- tst_brk TFAIL "can't set max_streams '$max_s', get $max_stream"
+ if [ "$max_s" -ne "$max_streams" ]; then
+ tst_res TFAIL "can't set max_streams '$max_s', get $max_stream"
+ return
+ fi
i=$(($i + 1))
tst_res TINFO "$sys_path = '$max_streams'"
@@ -140,8 +144,10 @@ zram_compress_alg()
for i in $(seq $dev_start $dev_end); do
for alg in $algs; do
local sys_path="/sys/block/zram${i}/comp_algorithm"
- echo "$alg" > $sys_path || \
- tst_brk TFAIL "can't set '$alg' to $sys_path"
+ if ! echo "$alg" > $sys_path; then
+ tst_res TFAIL "can't set '$alg' to $sys_path"
+ return
+ fi
tst_res TINFO "$sys_path = '$alg'"
done
done
@@ -157,8 +163,10 @@ zram_set_disksizes()
tst_res TINFO "set disk size to zram device(s)"
for ds in $zram_sizes; do
local sys_path="/sys/block/zram${i}/disksize"
- echo "$ds" > $sys_path || \
- tst_brk TFAIL "can't set '$ds' to $sys_path"
+ if ! echo "$ds" > $sys_path; then
+ tst_res TFAIL "can't set '$ds' to $sys_path"
+ return
+ fi
i=$(($i + 1))
tst_res TINFO "$sys_path = '$ds'"
@@ -183,8 +191,10 @@ zram_set_memlimit()
for ds in $zram_mem_limits; do
local sys_path="/sys/block/zram${i}/mem_limit"
- echo "$ds" > $sys_path || \
- tst_brk TFAIL "can't set '$ds' to $sys_path"
+ if ! echo "$ds" > $sys_path; then
+ tst_res TFAIL "can't set '$ds' to $sys_path"
+ return
+ fi
i=$(($i + 1))
tst_res TINFO "$sys_path = '$ds'"
diff --git a/testcases/kernel/fs/doio/growfiles.c b/testcases/kernel/fs/doio/growfiles.c
index eb58ce0cd..7bf51fb9c 100644
--- a/testcases/kernel/fs/doio/growfiles.c
+++ b/testcases/kernel/fs/doio/growfiles.c
@@ -328,7 +328,7 @@ int Open_flags[] = {
#define USECS_PER_SEC 1000000 /* microseconds per second */
/*
- * Define marcos used when dealing with file locks.
+ * Define macros used when dealing with file locks.
*/
#define LKLVL0 1 /* file lock around write/read/trunc */
#define LKLVL1 2 /* file lock after open to before close */
diff --git a/testcases/kernel/fs/doio/rwtest b/testcases/kernel/fs/doio/rwtest
index 6725e1426..3fbdf7f96 100644
--- a/testcases/kernel/fs/doio/rwtest
+++ b/testcases/kernel/fs/doio/rwtest
@@ -327,13 +327,6 @@ do
then
blks=${szblks[$n]}
else
- # If df is a symlink (to busybox) then do not pass the $dir and $dfOpts
- # parameters because they don't work as expected
- if test -h $(which df)
- then
- dir=""; dfOpts="";
- fi
-
blks=$(df $dfOpts $dir |
(while read fs blks used avail cap mountpoint
do
diff --git a/testcases/kernel/fs/fs_fill/fs_fill.c b/testcases/kernel/fs/fs_fill/fs_fill.c
index 2ecd8e2ad..3b4ee1ae9 100644
--- a/testcases/kernel/fs/fs_fill/fs_fill.c
+++ b/testcases/kernel/fs/fs_fill/fs_fill.c
@@ -121,8 +121,9 @@ static void cleanup(void)
}
static struct tst_test test = {
- .max_runtime = 60,
+ .max_runtime = 300,
.needs_root = 1,
+ .dev_min_size = 1024,
.mount_device = 1,
.mntpoint = MNTPOINT,
.all_filesystems = 1,
diff --git a/testcases/kernel/fs/fsx-linux/Makefile b/testcases/kernel/fs/fsx-linux/Makefile
index 956486b8a..5d04d81bc 100644
--- a/testcases/kernel/fs/fsx-linux/Makefile
+++ b/testcases/kernel/fs/fsx-linux/Makefile
@@ -22,13 +22,11 @@
top_srcdir ?= ../../../..
-include $(top_srcdir)/include/mk/env_pre.mk
+include $(top_srcdir)/include/mk/testcases.mk
CPPFLAGS += -DNO_XFS -I$(abs_srcdir) \
-D_LARGEFILE64_SOURCE -D_GNU_SOURCE
WCFLAGS += -w
-INSTALL_TARGETS := fsxtest*
-
include $(top_srcdir)/include/mk/generic_leaf_target.mk
diff --git a/testcases/kernel/fs/fsx-linux/fsx-linux.c b/testcases/kernel/fs/fsx-linux/fsx-linux.c
index 64c27a0f5..ba1e21bbc 100644
--- a/testcases/kernel/fs/fsx-linux/fsx-linux.c
+++ b/testcases/kernel/fs/fsx-linux/fsx-linux.c
@@ -1,1353 +1,380 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Copyright (C) 1991, NeXT Computer, Inc. All Rights Reserverd.
- * Copyright (c) 1998-2001 Apple Computer, Inc. All rights reserved.
- *
- * @APPLE_LICENSE_HEADER_START@
- *
- * The contents of this file constitute Original Code as defined in and
- * are subject to the Apple Public Source License Version 1.1 (the
- * "License"). You may not use this file except in compliance with the
- * License. Please obtain a copy of the License at
- * http://www.apple.com/publicsource and read it before using this file.
- *
- * This Original Code and all software distributed under the License are
- * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
- * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
- * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
- * License for the specific language governing rights and limitations
- * under the License.
- *
- * @APPLE_LICENSE_HEADER_END@
- *
- * File: fsx.c
* Author: Avadis Tevanian, Jr.
*
- * File system exerciser.
- *
- * Rewrite and enhancements 1998-2001 Conrad Minshall -- conrad@mac.com
- *
- * Various features from Joe Sokol, Pat Dirks, and Clark Warner.
- *
- * Small changes to work under Linux -- davej@suse.de
- *
- * Sundry porting patches from Guy Harris 12/2001
- * $FreeBSD: src/tools/regression/fsx/fsx.c,v 1.1 2001/12/20 04:15:57 jkh Exp $
+ * Copyright (c) 1998-2001 Apple Computer, Inc. All rights reserved.
+ * Conrad Minshall <conrad@mac.com>
+ * Dave Jones <davej@suse.de>
+ * Zach Brown <zab@clusterfs.com>
+ * Joe Sokol, Pat Dirks, Clark Warner, Guy Harris
*
- * Add multi-file testing feature -- Zach Brown <zab@clusterfs.com>
+ * Copyright (C) 2023 SUSE LLC Andrea Cervesato <andrea.cervesato@suse.com>
*/
-#include <sys/types.h>
-#include <sys/stat.h>
-#if defined(_UWIN) || defined(__linux__)
-#include <sys/param.h>
-#include <limits.h>
-#include <time.h>
-#include <string.h>
-#include <sys/time.h>
-#endif
-#include <fcntl.h>
-#include <sys/mman.h>
-#ifndef MAP_FILE
-#define MAP_FILE 0
-#endif
-#include <limits.h>
-#include <signal.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-#include <stdarg.h>
-#include <errno.h>
-
-/*
- * A log entry is an operation and a bunch of arguments.
+/*\
+ * [Description]
+ *
+ * This is a complete rewrite of the old fsx-linux tool, created by
+ * NeXT Computer, Inc. and Apple Computer, Inc. between 1991 and 2001,
+ * then adapted for LTP. Test is actually a file system exerciser: we bring a
+ * file and randomly write operations like read/write/map read/map write and
+ * truncate, according with input parameters. Then we check if all of them
+ * have been completed.
*/
-struct log_entry {
- int operation;
- struct timeval tv;
- int args[3];
+#include <stdlib.h>
+#include "tst_test.h"
+
+#define FNAME "ltp-file.bin"
+
+enum {
+ OP_READ = 0,
+ OP_WRITE,
+ OP_TRUNCATE,
+ OP_MAPREAD,
+ OP_MAPWRITE,
+ /* keep counter here */
+ OP_TOTAL,
};
-#define LOGSIZE 1000
+static char *str_file_max_size;
+static char *str_op_max_size;
+static char *str_op_nums;
+static char *str_op_write_align;
+static char *str_op_read_align;
+static char *str_op_trunc_align;
+
+static int file_desc;
+static long long file_max_size = 256 * 1024;
+static long long op_max_size = 64 * 1024;
+static long long file_size;
+static int op_write_align = 1;
+static int op_read_align = 1;
+static int op_trunc_align = 1;
+static int op_nums = 1000;
+static int page_size;
+
+static char *file_buff;
+static char *temp_buff;
+
+struct file_pos_t {
+ long long offset;
+ long long size;
+};
-struct log_entry oplog[LOGSIZE]; /* the log */
-int logptr = 0; /* current position in log */
-int logcount = 0; /* total ops */
+static void op_align_pages(struct file_pos_t *pos)
+{
+ long long pg_offset;
-/*
- * Define operations
- */
+ pg_offset = pos->offset % page_size;
-#define OP_READ 1
-#define OP_WRITE 2
-#define OP_TRUNCATE 3
-#define OP_CLOSEOPEN 4
-#define OP_MAPREAD 5
-#define OP_MAPWRITE 6
-#define OP_SKIPPED 7
-
-int page_size;
-int page_mask;
-
-char *original_buf; /* a pointer to the original data */
-char *good_buf; /* a pointer to the correct data */
-char *temp_buf; /* a pointer to the current data */
-char *fname; /* name of our test file */
-char logfile[1024]; /* name of our log file */
-char goodfile[1024]; /* name of our test file */
-
-off_t file_size = 0;
-off_t biggest = 0;
-char state[256];
-unsigned long testcalls = 0; /* calls to function "test" */
-
-unsigned long simulatedopcount = 0; /* -b flag */
-int closeprob = 0; /* -c flag */
-int debug = 0; /* -d flag */
-unsigned long debugstart = 0; /* -D flag */
-unsigned long maxfilelen = 256 * 1024; /* -l flag */
-int sizechecks = 1; /* -n flag disables them */
-int maxoplen = 64 * 1024; /* -o flag */
-int quiet = 0; /* -q flag */
-unsigned long progressinterval = 0; /* -p flag */
-int readbdy = 1; /* -r flag */
-int style = 0; /* -s flag */
-int truncbdy = 1; /* -t flag */
-int writebdy = 1; /* -w flag */
-long monitorstart = -1; /* -m flag */
-long monitorend = -1; /* -m flag */
-int lite = 0; /* -L flag */
-long numops = -1; /* -N flag */
-int randomoplen = 1; /* -O flag disables it */
-int seed = 1; /* -S flag */
-int mapped_writes = 1; /* -W flag disables */
-int mapped_reads = 1; /* -R flag disables it */
-int fsxgoodfd = 0;
-FILE *fsxlogf = NULL;
-int badoff = -1;
-
-void vwarnc(int code,const char *fmt, va_list ap)
-{
- fprintf(stderr, "fsx: ");
- if (fmt != NULL) {
- vfprintf(stderr, fmt, ap);
- fprintf(stderr, ": ");
- }
- fprintf(stderr, "%s\n", strerror(code));
+ pos->offset -= pg_offset;
+ pos->size += pg_offset;
}
-void warn(const char *fmt, ...)
+static void op_file_position(
+ const long long fsize,
+ const int align,
+ struct file_pos_t *pos)
{
- va_list ap;
- va_start(ap, fmt);
- vwarnc(errno, fmt, ap);
- va_end(ap);
-}
+ long long diff;
-void
- __attribute__ ((format(printf, 1, 2)))
- prt(char *fmt, ...)
-{
- va_list args;
+ pos->offset = random() % fsize;
+ pos->size = random() % (fsize - pos->offset);
- va_start(args, fmt);
- vfprintf(stdout, fmt, args);
- va_end(args);
+ diff = pos->offset % align;
- if (fsxlogf) {
- va_start(args, fmt);
- vfprintf(fsxlogf, fmt, args);
- va_end(args);
+ if (diff) {
+ pos->offset -= diff;
+ pos->size += diff;
}
-}
-void prterr(char *prefix)
-{
- prt("%s%s%s\n", prefix, prefix ? ": " : "", strerror(errno));
+ if (!pos->size)
+ pos->size = 1;
}
-void log4(int operation, int arg0, int arg1, int arg2, struct timeval *tv)
+static void update_file_size(struct file_pos_t const *pos)
{
- struct log_entry *le;
-
- le = &oplog[logptr];
- le->tv = *tv;
- le->operation = operation;
- le->args[0] = arg0;
- le->args[1] = arg1;
- le->args[2] = arg2;
- logptr++;
- logcount++;
- if (logptr >= LOGSIZE)
- logptr = 0;
+ if (pos->offset + pos->size > file_size) {
+ file_size = pos->offset + pos->size;
+ tst_res(TDEBUG, "File size changed: %llu", file_size);
+ }
}
-void logdump(void)
+static int memory_compare(
+ const char *a,
+ const char *b,
+ const long long offset,
+ const long long size)
{
- int i, count, down;
- struct log_entry *lp;
-
- prt("LOG DUMP (%d total operations):\n", logcount);
- if (logcount < LOGSIZE) {
- i = 0;
- count = logcount;
- } else {
- i = logptr;
- count = LOGSIZE;
- }
- for (; count > 0; count--) {
- int opnum;
+ int diff;
- opnum = i + 1 + (logcount / LOGSIZE) * LOGSIZE;
- lp = &oplog[i];
- prt("%d: %lu.%06lu ", opnum, lp->tv.tv_sec, lp->tv.tv_usec);
-
- switch (lp->operation) {
- case OP_MAPREAD:
- prt("MAPREAD 0x%x thru 0x%x (0x%x bytes)",
- lp->args[0], lp->args[0] + lp->args[1] - 1,
- lp->args[1]);
- if (badoff >= lp->args[0] && badoff <
- lp->args[0] + lp->args[1])
- prt("\t***RRRR***");
- break;
- case OP_MAPWRITE:
- prt("MAPWRITE 0x%x thru 0x%x (0x%x bytes)",
- lp->args[0], lp->args[0] + lp->args[1] - 1,
- lp->args[1]);
- if (badoff >= lp->args[0] && badoff <
- lp->args[0] + lp->args[1])
- prt("\t******WWWW");
- break;
- case OP_READ:
- prt("READ 0x%x thru 0x%x (0x%x bytes)",
- lp->args[0], lp->args[0] + lp->args[1] - 1,
- lp->args[1]);
- if (badoff >= lp->args[0] &&
- badoff < lp->args[0] + lp->args[1])
- prt("\t***RRRR***");
- break;
- case OP_WRITE:
- prt("WRITE 0x%x thru 0x%x (0x%x bytes)",
- lp->args[0], lp->args[0] + lp->args[1] - 1,
- lp->args[1]);
- if (lp->args[0] > lp->args[2])
- prt(" HOLE");
- else if (lp->args[0] + lp->args[1] > lp->args[2])
- prt(" EXTEND");
- if ((badoff >= lp->args[0] || badoff >= lp->args[2]) &&
- badoff < lp->args[0] + lp->args[1])
- prt("\t***WWWW");
- break;
- case OP_TRUNCATE:
- down = lp->args[0] < lp->args[1];
- prt("TRUNCATE %s\tfrom 0x%x to 0x%x",
- down ? "DOWN" : "UP", lp->args[1], lp->args[0]);
- if (badoff >= lp->args[!down] &&
- badoff < lp->args[! !down])
- prt("\t******WWWW");
- break;
- case OP_CLOSEOPEN:
- prt("CLOSE/OPEN");
+ for (long long i = 0; i < size; i++) {
+ diff = a[i] - b[i];
+ if (diff) {
+ tst_res(TDEBUG, "File memory differs at offset=%llu ('%c' != '%c')",
+ offset + i, a[i], b[i]);
break;
- case OP_SKIPPED:
- prt("SKIPPED (no operation)");
- break;
- default:
- prt("BOGUS LOG ENTRY (operation code = %d)!",
- lp->operation);
}
- prt("\n");
- i++;
- if (i == LOGSIZE)
- i = 0;
}
+
+ return diff;
}
-void save_buffer(char *buffer, off_t bufferlength, int fd)
+static int op_read(void)
{
- off_t ret;
- ssize_t byteswritten;
-
- if (fd <= 0 || bufferlength == 0)
- return;
-
- if (bufferlength > INT_MAX) {
- prt("fsx flaw: overflow in save_buffer\n");
- exit(67);
- }
- if (lite) {
- off_t size_by_seek = lseek(fd, (off_t) 0, SEEK_END);
- if (size_by_seek == (off_t) - 1)
- prterr("save_buffer: lseek eof");
- else if (bufferlength > size_by_seek) {
- warn("save_buffer: .fsxgood file too short... will "
- "save 0x%llx bytes instead of 0x%llx\n",
- (unsigned long long)size_by_seek,
- (unsigned long long)bufferlength);
- bufferlength = size_by_seek;
- }
+ if (!file_size) {
+ tst_res(TINFO, "Skipping zero size read");
+ return 0;
}
- ret = lseek(fd, (off_t) 0, SEEK_SET);
- if (ret == (off_t) - 1)
- prterr("save_buffer: lseek 0");
-
- byteswritten = write(fd, buffer, (size_t) bufferlength);
- if (byteswritten != bufferlength) {
- if (byteswritten == -1)
- prterr("save_buffer write");
- else
- warn("save_buffer: short write, 0x%x bytes instead "
- "of 0x%llx\n",
- (unsigned)byteswritten,
- (unsigned long long)bufferlength);
- }
-}
+ struct file_pos_t pos;
-void report_failure(int status)
-{
- logdump();
-
- if (fsxgoodfd) {
- if (good_buf) {
- save_buffer(good_buf, file_size, fsxgoodfd);
- prt("Correct content saved for comparison\n");
- prt("(maybe hexdump \"%s\" vs \"%s\")\n",
- fname, goodfile);
- }
- close(fsxgoodfd);
- }
- exit(status);
-}
+ op_file_position(file_size, op_read_align, &pos);
-#define short_at(cp) ((unsigned short)((*((unsigned char *)(cp)) << 8) | \
- *(((unsigned char *)(cp)) + 1)))
+ tst_res(TDEBUG, "Reading at offset=%llu, size=%llu",
+ pos.offset, pos.size);
-void check_buffers(unsigned offset, unsigned size)
-{
- unsigned char c, t;
- unsigned i = 0;
- unsigned n = 0;
- unsigned op = 0;
- unsigned bad = 0;
-
- if (memcmp(good_buf + offset, temp_buf, size) != 0) {
- prt("READ BAD DATA: offset = 0x%x, size = 0x%x\n",
- offset, size);
- prt("OFFSET\tGOOD\tBAD\tRANGE\n");
- while (size > 0) {
- c = good_buf[offset];
- t = temp_buf[i];
- if (c != t) {
- if (n == 0) {
- bad = short_at(&temp_buf[i]);
- prt("%#07x\t%#06x\t%#06x", offset,
- short_at(&good_buf[offset]), bad);
- op = temp_buf[offset & 1 ? i + 1 : i];
- }
- n++;
- badoff = offset;
- }
- offset++;
- i++;
- size--;
- }
- if (n) {
- prt("\t%#7x\n", n);
- if (bad)
- prt("operation# (mod 256) for the bad data "
- "may be %u\n", ((unsigned)op & 0xff));
- else
- prt("operation# (mod 256) for the bad data "
- "unknown, check HOLE and EXTEND ops\n");
- } else
- prt("????????????????\n");
- report_failure(110);
- }
-}
+ memset(temp_buff, 0, file_max_size);
-struct test_file {
- char *path;
- int fd;
-} *test_files = NULL;
+ SAFE_LSEEK(file_desc, (off_t)pos.offset, SEEK_SET);
+ SAFE_READ(0, file_desc, temp_buff, pos.size);
-int num_test_files = 0;
-enum fd_iteration_policy {
- FD_SINGLE,
- FD_ROTATE,
- FD_RANDOM,
-};
-int fd_policy = FD_RANDOM;
-int fd_last = 0;
+ int ret = memory_compare(
+ file_buff + pos.offset,
+ temp_buff,
+ pos.offset,
+ pos.size);
-struct test_file *get_tf(void)
-{
- unsigned index = 0;
-
- switch (fd_policy) {
- case FD_ROTATE:
- index = fd_last++;
- break;
- case FD_RANDOM:
- index = random();
- break;
- case FD_SINGLE:
- index = 0;
- break;
- default:
- prt("unknown policy");
- exit(1);
- break;
- }
- return &test_files[index % num_test_files];
+ if (ret)
+ return -1;
+
+ return 1;
}
-void assign_fd_policy(char *policy)
+static int op_write(void)
{
- if (!strcmp(policy, "random"))
- fd_policy = FD_RANDOM;
- else if (!strcmp(policy, "rotate"))
- fd_policy = FD_ROTATE;
- else {
- prt("unknown -I policy: '%s'\n", policy);
- exit(1);
+ if (file_size >= file_max_size) {
+ tst_res(TINFO, "Skipping max size write");
+ return 0;
}
-}
-int get_fd(void)
-{
- struct test_file *tf = get_tf();
- return tf->fd;
-}
+ struct file_pos_t pos;
+ char data;
-void open_test_files(char **argv, int argc)
-{
- struct test_file *tf;
- int i;
+ op_file_position(file_max_size, op_write_align, &pos);
- num_test_files = argc;
- if (num_test_files == 1)
- fd_policy = FD_SINGLE;
+ for (long long i = 0; i < pos.size; i++) {
+ data = random() % 10 + 'a';
- test_files = calloc(num_test_files, sizeof(*test_files));
- if (test_files == NULL) {
- prterr("reallocating space for test files");
- exit(1);
+ file_buff[pos.offset + i] = data;
+ temp_buff[i] = data;
}
- for (i = 0, tf = test_files; i < num_test_files; i++, tf++) {
+ tst_res(TDEBUG, "Writing at offset=%llu, size=%llu",
+ pos.offset, pos.size);
- tf->path = argv[i];
- tf->fd = open(tf->path, O_RDWR | (lite ? 0 : O_CREAT | O_TRUNC),
- 0666);
- if (tf->fd < 0) {
- prterr(tf->path);
- exit(91);
- }
- }
+ SAFE_LSEEK(file_desc, (off_t)pos.offset, SEEK_SET);
+ SAFE_WRITE(SAFE_WRITE_ALL, file_desc, temp_buff, pos.size);
- if (quiet || fd_policy == FD_SINGLE)
- return;
+ update_file_size(&pos);
- for (i = 0, tf = test_files; i < num_test_files; i++, tf++)
- prt("fd %d: %s\n", i, tf->path);
+ return 1;
}
-void close_test_files(void)
+static int op_truncate(void)
{
- int i;
- struct test_file *tf;
+ struct file_pos_t pos;
- for (i = 0, tf = test_files; i < num_test_files; i++, tf++) {
- if (close(tf->fd)) {
- prterr("close");
- report_failure(99);
- }
- }
-}
+ op_file_position(file_max_size, op_trunc_align, &pos);
+ file_size = pos.offset + pos.size;
-void check_size(void)
-{
- struct stat statbuf;
- off_t size_by_seek;
- int fd = get_fd();
+ tst_res(TDEBUG, "Truncating to %llu", file_size);
- if (fstat(fd, &statbuf)) {
- prterr("check_size: fstat");
- statbuf.st_size = -1;
- }
- size_by_seek = lseek(fd, (off_t) 0, SEEK_END);
- if (file_size != statbuf.st_size || file_size != size_by_seek) {
- prt("Size error: expected 0x%llx stat 0x%llx seek 0x%llx\n",
- (unsigned long long)file_size,
- (unsigned long long)statbuf.st_size,
- (unsigned long long)size_by_seek);
- report_failure(120);
- }
-}
+ SAFE_FTRUNCATE(file_desc, file_size);
+ memset(file_buff + file_size, 0, file_max_size - file_size);
-void check_trunc_hack(void)
-{
- struct stat statbuf;
- int fd = get_fd();
-
- ftruncate(fd, (off_t) 0);
- ftruncate(fd, (off_t) 100000);
- if (fstat(fd, &statbuf)) {
- prterr("trunc_hack: fstat");
- statbuf.st_size = -1;
- }
- if (statbuf.st_size != (off_t) 100000) {
- prt("no extend on truncate! not posix!\n");
- exit(130);
- }
- ftruncate(fd, 0);
+ return 1;
}
-static char *tf_buf = NULL;
-static int max_tf_len = 0;
-
-void alloc_tf_buf(void)
+static int op_map_read(void)
{
- char dummy = '\0';
- int highest = num_test_files - 1;
- int len;
-
- len = snprintf(&dummy, 0, "%u ", highest);
- if (len < 1) {
- prterr("finding max tf_buf");
- exit(1);
- }
- len++;
- tf_buf = malloc(len);
- if (tf_buf == NULL) {
- prterr("allocating tf_buf");
- exit(1);
+ if (!file_size) {
+ tst_res(TINFO, "Skipping zero size read");
+ return 0;
}
- max_tf_len = snprintf(tf_buf, len, "%u ", highest);
- if (max_tf_len < 1) {
- prterr("fiding max_tv_len\n");
- exit(1);
- }
- if (max_tf_len != len - 1) {
- warn("snprintf() gave %d instead of %d?\n",
- max_tf_len, len - 1);
- exit(1);
- }
-}
-char *fill_tf_buf(struct test_file *tf)
-{
- if (tf_buf == NULL)
- alloc_tf_buf();
+ struct file_pos_t pos;
+ char *addr;
- sprintf(tf_buf, "%lu ", (unsigned long)(tf - test_files));
- return tf_buf;
-}
+ op_file_position(file_size, op_read_align, &pos);
+ op_align_pages(&pos);
-void
-output_line(struct test_file *tf, int op, unsigned offset,
- unsigned size, struct timeval *tv)
-{
- char *tf_num = "";
-
- char *ops[] = {
- [OP_READ] = "read",
- [OP_WRITE] = "write",
- [OP_TRUNCATE] = "trunc from",
- [OP_MAPREAD] = "mapread",
- [OP_MAPWRITE] = "mapwrite",
- };
-
- /* W. */
- if (!(!quiet && ((progressinterval &&
- testcalls % progressinterval == 0) ||
- (debug &&
- (monitorstart == -1 ||
- (offset + size > monitorstart &&
- (monitorend == -1 || offset <= monitorend)))))))
- return;
-
- if (fd_policy != FD_SINGLE)
- tf_num = fill_tf_buf(tf);
-
- prt("%06lu %lu.%06lu %.*s%-10s %#08x %s %#08x\t(0x%x bytes)\n",
- testcalls, tv->tv_sec, tv->tv_usec, max_tf_len,
- tf_num, ops[op],
- offset, op == OP_TRUNCATE ? " to " : "thru",
- offset + size - 1, size);
-}
+ tst_res(TDEBUG, "Map reading at offset=%llu, size=%llu",
+ pos.offset, pos.size);
-void doread(unsigned offset, unsigned size)
-{
- struct timeval t;
- off_t ret;
- unsigned iret;
- struct test_file *tf = get_tf();
- int fd = tf->fd;
-
- offset -= offset % readbdy;
- gettimeofday(&t, NULL);
- if (size == 0) {
- if (!quiet && testcalls > simulatedopcount)
- prt("skipping zero size read\n");
- log4(OP_SKIPPED, OP_READ, offset, size, &t);
- return;
- }
- if (size + offset > file_size) {
- if (!quiet && testcalls > simulatedopcount)
- prt("skipping seek/read past end of file\n");
- log4(OP_SKIPPED, OP_READ, offset, size, &t);
- return;
- }
+ addr = SAFE_MMAP(
+ 0, pos.size,
+ PROT_READ,
+ MAP_FILE | MAP_SHARED,
+ file_desc,
+ (off_t)pos.offset);
- log4(OP_READ, offset, size, 0, &t);
+ memcpy(file_buff + pos.offset, addr, pos.size);
- if (testcalls <= simulatedopcount)
- return;
+ int ret = memory_compare(
+ addr,
+ file_buff + pos.offset,
+ pos.offset,
+ pos.size);
- output_line(tf, OP_READ, offset, size, &t);
+ SAFE_MUNMAP(addr, pos.size);
+ if (ret)
+ return -1;
- ret = lseek(fd, (off_t) offset, SEEK_SET);
- if (ret == (off_t) - 1) {
- prterr("doread: lseek");
- report_failure(140);
- }
- iret = read(fd, temp_buf, size);
- if (!quiet && (debug > 1 &&
- (monitorstart == -1 ||
- (offset + size > monitorstart &&
- (monitorend == -1 || offset <= monitorend))))) {
- gettimeofday(&t, NULL);
- prt(" %lu.%06lu read done\n", t.tv_sec, t.tv_usec);
- }
- if (iret != size) {
- if (iret == -1)
- prterr("doread: read");
- else
- prt("short read: 0x%x bytes instead of 0x%x\n",
- iret, size);
- report_failure(141);
- }
- check_buffers(offset, size);
+ return 1;
}
-void domapread(unsigned offset, unsigned size)
+static int op_map_write(void)
{
- struct timeval t;
- unsigned pg_offset;
- unsigned map_size;
- char *p;
- struct test_file *tf = get_tf();
- int fd = tf->fd;
-
- offset -= offset % readbdy;
- gettimeofday(&t, NULL);
- if (size == 0) {
- if (!quiet && testcalls > simulatedopcount)
- prt("skipping zero size read\n");
- log4(OP_SKIPPED, OP_MAPREAD, offset, size, &t);
- return;
- }
- if (size + offset > file_size) {
- if (!quiet && testcalls > simulatedopcount)
- prt("skipping seek/read past end of file\n");
- log4(OP_SKIPPED, OP_MAPREAD, offset, size, &t);
- return;
+ if (file_size >= file_max_size) {
+ tst_res(TINFO, "Skipping max size write");
+ return 0;
}
- log4(OP_MAPREAD, offset, size, 0, &t);
+ struct file_pos_t pos;
+ char *addr;
- if (testcalls <= simulatedopcount)
- return;
+ op_file_position(file_max_size, op_write_align, &pos);
+ op_align_pages(&pos);
- output_line(tf, OP_MAPREAD, offset, size, &t);
+ if (file_size < pos.offset + pos.size)
+ SAFE_FTRUNCATE(file_desc, pos.offset + pos.size);
- pg_offset = offset & page_mask;
- map_size = pg_offset + size;
+ tst_res(TDEBUG, "Map writing at offset=%llu, size=%llu",
+ pos.offset, pos.size);
- if ((p = mmap(0, map_size, PROT_READ, MAP_FILE | MAP_SHARED, fd,
- (off_t) (offset - pg_offset))) == MAP_FAILED) {
- prterr("domapread: mmap");
- report_failure(190);
- }
- if (!quiet && (debug > 1 &&
- (monitorstart == -1 ||
- (offset + size > monitorstart &&
- (monitorend == -1 || offset <= monitorend))))) {
- gettimeofday(&t, NULL);
- prt(" %lu.%06lu mmap done\n", t.tv_sec, t.tv_usec);
- }
- memcpy(temp_buf, p + pg_offset, size);
- if (!quiet && (debug > 1 &&
- (monitorstart == -1 ||
- (offset + size > monitorstart &&
- (monitorend == -1 || offset <= monitorend))))) {
- gettimeofday(&t, NULL);
- prt(" %lu.%06lu memcpy done\n", t.tv_sec, t.tv_usec);
- }
- if (munmap(p, map_size) != 0) {
- prterr("domapread: munmap");
- report_failure(191);
- }
- if (!quiet && (debug > 1 &&
- (monitorstart == -1 ||
- (offset + size > monitorstart &&
- (monitorend == -1 || offset <= monitorend))))) {
- gettimeofday(&t, NULL);
- prt(" %lu.%06lu munmap done\n", t.tv_sec, t.tv_usec);
- }
+ for (long long i = 0; i < pos.size; i++)
+ file_buff[pos.offset + i] = random() % 10 + 'l';
- check_buffers(offset, size);
-}
+ addr = SAFE_MMAP(
+ 0, pos.size,
+ PROT_READ | PROT_WRITE,
+ MAP_FILE | MAP_SHARED,
+ file_desc,
+ (off_t)pos.offset);
-void gendata(char *original_buf, char *good_buf, unsigned offset, unsigned size)
-{
- while (size--) {
- good_buf[offset] = testcalls % 256;
- if (offset % 2)
- good_buf[offset] += original_buf[offset];
- offset++;
- }
-}
+ memcpy(addr, file_buff + pos.offset, pos.size);
+ SAFE_MSYNC(addr, pos.size, MS_SYNC);
+ SAFE_MUNMAP(addr, pos.size);
+ update_file_size(&pos);
-void dowrite(unsigned offset, unsigned size)
-{
- struct timeval t;
- off_t ret;
- unsigned iret;
- struct test_file *tf = get_tf();
- int fd = tf->fd;
-
- offset -= offset % writebdy;
- gettimeofday(&t, NULL);
- if (size == 0) {
- if (!quiet && testcalls > simulatedopcount)
- prt("skipping zero size write\n");
- log4(OP_SKIPPED, OP_WRITE, offset, size, &t);
- return;
- }
-
- log4(OP_WRITE, offset, size, file_size, &t);
-
- gendata(original_buf, good_buf, offset, size);
- if (file_size < offset + size) {
- if (file_size < offset)
- memset(good_buf + file_size, '\0', offset - file_size);
- file_size = offset + size;
- if (lite) {
- warn("Lite file size bug in fsx!");
- report_failure(149);
- }
- }
-
- if (testcalls <= simulatedopcount)
- return;
-
- output_line(tf, OP_WRITE, offset, size, &t);
-
- ret = lseek(fd, (off_t) offset, SEEK_SET);
- if (ret == (off_t) - 1) {
- prterr("dowrite: lseek");
- report_failure(150);
- }
- iret = write(fd, good_buf + offset, size);
- if (!quiet && (debug > 1 &&
- (monitorstart == -1 ||
- (offset + size > monitorstart &&
- (monitorend == -1 || offset <= monitorend))))) {
- gettimeofday(&t, NULL);
- prt(" %lu.%06lu write done\n", t.tv_sec, t.tv_usec);
- }
- if (iret != size) {
- if (iret == -1)
- prterr("dowrite: write");
- else
- prt("short write: 0x%x bytes instead of 0x%x\n",
- iret, size);
- report_failure(151);
- }
+ return 1;
}
-void domapwrite(unsigned offset, unsigned size)
+static void run(void)
{
- struct timeval t;
- unsigned pg_offset;
- unsigned map_size;
- off_t cur_filesize;
- char *p;
- struct test_file *tf = get_tf();
- int fd = tf->fd;
-
- offset -= offset % writebdy;
- gettimeofday(&t, NULL);
- if (size == 0) {
- if (!quiet && testcalls > simulatedopcount)
- prt("skipping zero size write\n");
- log4(OP_SKIPPED, OP_MAPWRITE, offset, size, &t);
- return;
- }
- cur_filesize = file_size;
-
- log4(OP_MAPWRITE, offset, size, 0, &t);
-
- gendata(original_buf, good_buf, offset, size);
- if (file_size < offset + size) {
- if (file_size < offset)
- memset(good_buf + file_size, '\0', offset - file_size);
- file_size = offset + size;
- if (lite) {
- warn("Lite file size bug in fsx!");
- report_failure(200);
- }
- }
+ int op;
+ int ret;
+ int counter = 0;
- if (testcalls <= simulatedopcount)
- return;
+ file_size = 0;
- output_line(tf, OP_MAPWRITE, offset, size, &t);
+ memset(file_buff, 0, file_max_size);
+ memset(temp_buff, 0, file_max_size);
- if (file_size > cur_filesize) {
- if (ftruncate(fd, file_size) == -1) {
- prterr("domapwrite: ftruncate");
- exit(201);
- }
- if (!quiet && (debug > 1 &&
- (monitorstart == -1 ||
- (offset + size > monitorstart &&
- (monitorend == -1
- || offset <= monitorend))))) {
- gettimeofday(&t, NULL);
- prt(" %lu.%06lu truncate done\n", t.tv_sec,
- t.tv_usec);
- }
- }
- pg_offset = offset & page_mask;
- map_size = pg_offset + size;
-
- if ((p =
- mmap(0, map_size, PROT_READ | PROT_WRITE, MAP_FILE | MAP_SHARED,
- fd, (off_t) (offset - pg_offset))) == MAP_FAILED) {
- prterr("domapwrite: mmap");
- report_failure(202);
- }
- if (!quiet && (debug > 1 &&
- (monitorstart == -1 ||
- (offset + size > monitorstart &&
- (monitorend == -1 || offset <= monitorend))))) {
- gettimeofday(&t, NULL);
- prt(" %lu.%06lu mmap done\n", t.tv_sec, t.tv_usec);
- }
- memcpy(p + pg_offset, good_buf + offset, size);
- if (!quiet && (debug > 1 &&
- (monitorstart == -1 ||
- (offset + size > monitorstart &&
- (monitorend == -1 || offset <= monitorend))))) {
- gettimeofday(&t, NULL);
- prt(" %lu.%06lu memcpy done\n", t.tv_sec, t.tv_usec);
- }
- if (msync(p, map_size, 0) != 0) {
- prterr("domapwrite: msync");
- report_failure(203);
- }
- if (!quiet && (debug > 1 &&
- (monitorstart == -1 ||
- (offset + size > monitorstart &&
- (monitorend == -1 || offset <= monitorend))))) {
- gettimeofday(&t, NULL);
- prt(" %lu.%06lu msync done\n", t.tv_sec, t.tv_usec);
- }
- if (munmap(p, map_size) != 0) {
- prterr("domapwrite: munmap");
- report_failure(204);
- }
- if (!quiet && (debug > 1 &&
- (monitorstart == -1 ||
- (offset + size > monitorstart &&
- (monitorend == -1 || offset <= monitorend))))) {
- gettimeofday(&t, NULL);
- prt(" %lu.%06lu munmap done\n", t.tv_sec, t.tv_usec);
- }
-}
+ SAFE_FTRUNCATE(file_desc, 0);
-void dotruncate(unsigned size)
-{
- struct timeval t;
- int oldsize = file_size;
- struct test_file *tf = get_tf();
- int fd = tf->fd;
-
- size -= size % truncbdy;
- gettimeofday(&t, NULL);
- if (size > biggest) {
- biggest = size;
- if (!quiet && testcalls > simulatedopcount)
- prt("truncating to largest ever: 0x%x\n", size);
- }
+ while (counter < op_nums) {
+ op = random() % OP_TOTAL;
- log4(OP_TRUNCATE, size, (unsigned)file_size, 0, &t);
-
- if (size > file_size)
- memset(good_buf + file_size, '\0', size - file_size);
- file_size = size;
-
- if (testcalls <= simulatedopcount)
- return;
+ switch (op) {
+ case OP_WRITE:
+ ret = op_write();
+ break;
+ case OP_MAPREAD:
+ ret = op_map_read();
+ break;
+ case OP_MAPWRITE:
+ ret = op_map_write();
+ break;
+ case OP_TRUNCATE:
+ ret = op_truncate();
+ break;
+ case OP_READ:
+ default:
+ ret = op_read();
+ break;
+ };
- output_line(tf, OP_TRUNCATE, oldsize, size, &t);
+ if (ret == -1)
+ break;
- if (ftruncate(fd, (off_t) size) == -1) {
- prt("ftruncate1: %x\n", size);
- prterr("dotruncate: ftruncate");
- report_failure(160);
- }
- if (!quiet && debug > 1) {
- gettimeofday(&t, NULL);
- prt(" %lu.%06lu trunc done\n", t.tv_sec, t.tv_usec);
+ counter += ret;
}
+
+ if (counter != op_nums)
+ tst_brk(TFAIL, "Some file operations failed");
+ else
+ tst_res(TPASS, "All file operations succeed");
}
-void writefileimage(void)
+static void setup(void)
{
- ssize_t iret;
- int fd = get_fd();
+ if (tst_parse_filesize(str_file_max_size, &file_max_size, 1, LLONG_MAX))
+ tst_brk(TBROK, "Invalid file size '%s'", str_file_max_size);
- if (lseek(fd, (off_t) 0, SEEK_SET) == (off_t) - 1) {
- prterr("writefileimage: lseek");
- report_failure(171);
- }
- iret = write(fd, good_buf, file_size);
- if ((off_t) iret != file_size) {
- if (iret == -1)
- prterr("writefileimage: write");
- else
- prt("short write: 0x%lx bytes instead of 0x%llx\n",
- (unsigned long)iret, (unsigned long long)file_size);
- report_failure(172);
- }
- if (lite ? 0 : ftruncate(fd, file_size) == -1) {
- prt("ftruncate2: %llx\n", (unsigned long long)file_size);
- prterr("writefileimage: ftruncate");
- report_failure(173);
- }
-}
+ if (tst_parse_filesize(str_op_max_size, &op_max_size, 1, LLONG_MAX))
+ tst_brk(TBROK, "Invalid maximum size for single operation '%s'", str_op_max_size);
-void docloseopen(void)
-{
- struct timeval t;
- struct test_file *tf = get_tf();
+ if (tst_parse_int(str_op_nums, &op_nums, 1, INT_MAX))
+ tst_brk(TBROK, "Invalid number of operations '%s'", str_op_nums);
- if (testcalls <= simulatedopcount)
- return;
+ if (tst_parse_int(str_op_write_align, &op_write_align, 1, INT_MAX))
+ tst_brk(TBROK, "Invalid memory write alignment factor '%s'", str_op_write_align);
- gettimeofday(&t, NULL);
- log4(OP_CLOSEOPEN, file_size, (unsigned)file_size, 0, &t);
+ if (tst_parse_int(str_op_read_align, &op_read_align, 1, INT_MAX))
+ tst_brk(TBROK, "Invalid memory read alignment factor '%s'", str_op_read_align);
- if (debug)
- prt("%06lu %lu.%06lu close/open\n", testcalls, t.tv_sec,
- t.tv_usec);
- if (close(tf->fd)) {
- prterr("docloseopen: close");
- report_failure(180);
- }
- if (!quiet && debug > 1) {
- gettimeofday(&t, NULL);
- prt(" %lu.%06lu close done\n", t.tv_sec, t.tv_usec);
- }
- tf->fd = open(tf->path, O_RDWR, 0);
- if (tf->fd < 0) {
- prterr("docloseopen: open");
- report_failure(181);
- }
- if (!quiet && debug > 1) {
- gettimeofday(&t, NULL);
- prt(" %lu.%06lu open done\n", t.tv_sec, t.tv_usec);
- }
-}
+ if (tst_parse_int(str_op_trunc_align, &op_trunc_align, 1, INT_MAX))
+ tst_brk(TBROK, "Invalid memory truncate alignment factor '%s'", str_op_trunc_align);
-void test(void)
-{
- unsigned long offset;
- unsigned long size = maxoplen;
- unsigned long rv = random();
- unsigned long op = rv % (3 + !lite + mapped_writes);
-
- /* turn off the map read if necessary */
-
- if (op == 2 && !mapped_reads)
- op = 0;
-
- if (simulatedopcount > 0 && testcalls == simulatedopcount)
- writefileimage();
-
- testcalls++;
-
- if (debugstart > 0 && testcalls >= debugstart)
- debug = 1;
-
- if (!quiet && testcalls < simulatedopcount && testcalls % 100000 == 0)
- prt("%lu...\n", testcalls);
-
- /*
- * READ: op = 0
- * WRITE: op = 1
- * MAPREAD: op = 2
- * TRUNCATE: op = 3
- * MAPWRITE: op = 3 or 4
- */
- if (lite ? 0 : op == 3 && (style & 1) == 0) /* vanilla truncate? */
- dotruncate(random() % maxfilelen);
- else {
- if (randomoplen)
- size = random() % (maxoplen + 1);
- if (lite ? 0 : op == 3)
- dotruncate(size);
- else {
- offset = random();
- if (op == 1 || op == (lite ? 3 : 4)) {
- offset %= maxfilelen;
- if (offset + size > maxfilelen)
- size = maxfilelen - offset;
- if (op != 1)
- domapwrite(offset, size);
- else
- dowrite(offset, size);
- } else {
- if (file_size)
- offset %= file_size;
- else
- offset = 0;
- if (offset + size > file_size)
- size = file_size - offset;
- if (op != 0)
- domapread(offset, size);
- else
- doread(offset, size);
- }
- }
- }
- if (sizechecks && testcalls > simulatedopcount)
- check_size();
- if (closeprob && (rv >> 3) < (1 << 28) / closeprob)
- docloseopen();
-}
+ page_size = (int)sysconf(_SC_PAGESIZE);
-void cleanup(int sig)
-{
- if (sig)
- prt("signal %d\n", sig);
- prt("testcalls = %lu\n", testcalls);
- exit(sig);
-}
+ srandom(time(NULL));
-void usage(void)
-{
- fprintf(stdout, "usage: %s",
- "fsx [-dnqLOW] [-b opnum] [-c Prob] [-l flen] [-m "
- "start:end] [-o oplen] [-p progressinterval] [-r readbdy] [-s style] [-t "
- "truncbdy] [-w writebdy] [-D startingop] [-N numops] [-P dirpath] [-S seed] "
- "[ -I random|rotate ] fname [additional paths to fname..]\n"
- " -b opnum: beginning operation number (default 1)\n"
- " -c P: 1 in P chance of file close+open at each op (default infinity)\n"
- " -d: debug output for all operations [-d -d = more debugging]\n"
- " -l flen: the upper bound on file size (default 262144)\n"
- " -m start:end: monitor (print debug) specified byte range (default 0:infinity)\n"
- " -n: no verifications of file size\n"
- " -o oplen: the upper bound on operation size (default 65536)\n"
- " -p progressinterval: debug output at specified operation interval\n"
- " -q: quieter operation\n"
- " -r readbdy: 4096 would make reads page aligned (default 1)\n"
- " -s style: 1 gives smaller truncates (default 0)\n"
- " -t truncbdy: 4096 would make truncates page aligned (default 1)\n"
- " -w writebdy: 4096 would make writes page aligned (default 1)\n"
- " -D startingop: debug output starting at specified operation\n"
- " -L: fsxLite - no file creations & no file size changes\n"
- " -N numops: total # operations to do (default infinity)\n"
- " -O: use oplen (see -o flag) for every op (default random)\n"
- " -P: save .fsxlog and .fsxgood files in dirpath (default ./)\n"
- " -S seed: for random # generator (default 1) 0 gets timestamp\n"
- " -W: mapped write operations DISabled\n"
- " -R: read() system calls only (mapped reads disabled)\n"
- " -I: When multiple paths to the file are given each operation uses\n"
- " a different path. Iterate through them in order with 'rotate'\n"
- " or chose then at 'random'. (defaults to random)\n"
- " fname: this filename is REQUIRED (no default)\n");
- exit(90);
-}
+ file_desc = SAFE_OPEN(FNAME, O_RDWR | O_CREAT, 0666);
-int getnum(char *s, char **e)
-{
- int ret = -1;
-
- *e = NULL;
- ret = strtol(s, e, 0);
- if (*e)
- switch (**e) {
- case 'b':
- case 'B':
- ret *= 512;
- *e = *e + 1;
- break;
- case 'k':
- case 'K':
- ret *= 1024;
- *e = *e + 1;
- break;
- case 'm':
- case 'M':
- ret *= 1024 * 1024;
- *e = *e + 1;
- break;
- case 'w':
- case 'W':
- ret *= 4;
- *e = *e + 1;
- break;
- }
- return (ret);
+ file_buff = SAFE_MALLOC(file_max_size);
+ temp_buff = SAFE_MALLOC(file_max_size);
}
-int main(int argc, char **argv)
+static void cleanup(void)
{
- int i, style, ch;
- char *endp;
- int dirpath = 0;
-
- goodfile[0] = 0;
- logfile[0] = 0;
-
- page_size = getpagesize();
- page_mask = page_size - 1;
-
- setvbuf(stdout, NULL, _IOLBF, 0); /* line buffered stdout */
-
- while ((ch = getopt(argc, argv,
- "b:c:dl:m:no:p:qr:s:t:w:D:I:LN:OP:RS:W"))
- != EOF)
- switch (ch) {
- case 'b':
- simulatedopcount = getnum(optarg, &endp);
- if (!quiet)
- fprintf(stdout, "Will begin at operation"
- "%ld\n", simulatedopcount);
- if (simulatedopcount == 0)
- usage();
- simulatedopcount -= 1;
- break;
- case 'c':
- closeprob = getnum(optarg, &endp);
- if (!quiet)
- fprintf(stdout,
- "Chance of close/open is 1 in %d\n",
- closeprob);
- if (closeprob <= 0)
- usage();
- break;
- case 'd':
- debug++;
- break;
- case 'l':
- maxfilelen = getnum(optarg, &endp);
- if (maxfilelen <= 0)
- usage();
- break;
- case 'm':
- monitorstart = getnum(optarg, &endp);
- if (monitorstart < 0)
- usage();
- if (!endp || *endp++ != ':')
- usage();
- monitorend = getnum(endp, &endp);
- if (monitorend < 0)
- usage();
- if (monitorend == 0)
- monitorend = -1; /* aka infinity */
- debug = 1;
- case 'n':
- sizechecks = 0;
- break;
- case 'o':
- maxoplen = getnum(optarg, &endp);
- if (maxoplen <= 0)
- usage();
- break;
- case 'p':
- progressinterval = getnum(optarg, &endp);
- if (progressinterval < 0)
- usage();
- break;
- case 'q':
- quiet = 1;
- break;
- case 'r':
- readbdy = getnum(optarg, &endp);
- if (readbdy <= 0)
- usage();
- break;
- case 's':
- style = getnum(optarg, &endp);
- if (style < 0 || style > 1)
- usage();
- break;
- case 't':
- truncbdy = getnum(optarg, &endp);
- if (truncbdy <= 0)
- usage();
- break;
- case 'w':
- writebdy = getnum(optarg, &endp);
- if (writebdy <= 0)
- usage();
- break;
- case 'D':
- debugstart = getnum(optarg, &endp);
- if (debugstart < 1)
- usage();
- break;
- case 'I':
- assign_fd_policy(optarg);
- break;
- case 'L':
- lite = 1;
- break;
- case 'N':
- numops = getnum(optarg, &endp);
- if (numops < 0)
- usage();
- break;
- case 'O':
- randomoplen = 0;
- break;
- case 'P':
- strncpy(goodfile, optarg, sizeof(goodfile));
- strcat(goodfile, "/");
- strncpy(logfile, optarg, sizeof(logfile));
- strcat(logfile, "/");
- dirpath = 1;
- break;
- case 'R':
- mapped_reads = 0;
- break;
- case 'S':
- seed = getnum(optarg, &endp);
- if (seed == 0)
- seed = time(0) % 10000;
- if (!quiet)
- fprintf(stdout, "Seed set to %d\n", seed);
- if (seed < 0)
- usage();
- break;
- case 'W':
- mapped_writes = 0;
- if (!quiet)
- fprintf(stdout, "mapped writes DISABLED\n");
- break;
+ if (file_buff)
+ free(file_buff);
- default:
- usage();
+ if (temp_buff)
+ free(temp_buff);
- }
- argc -= optind;
- argv += optind;
- if (argc < 1)
- usage();
- fname = argv[0];
-
- signal(SIGHUP, cleanup);
- signal(SIGINT, cleanup);
- signal(SIGPIPE, cleanup);
- signal(SIGALRM, cleanup);
- signal(SIGTERM, cleanup);
- signal(SIGXCPU, cleanup);
- signal(SIGXFSZ, cleanup);
- signal(SIGVTALRM, cleanup);
- signal(SIGUSR1, cleanup);
- signal(SIGUSR2, cleanup);
-
- initstate(seed, state, 256);
- setstate(state);
-
- open_test_files(argv, argc);
-
- strncat(goodfile, dirpath ? basename(fname) : fname, 256);
- strcat(goodfile, ".fsxgood");
- fsxgoodfd = open(goodfile, O_RDWR | O_CREAT | O_TRUNC, 0666);
- if (fsxgoodfd < 0) {
- prterr(goodfile);
- exit(92);
- }
- strncat(logfile, dirpath ? basename(fname) : fname, 256);
- strcat(logfile, ".fsxlog");
- fsxlogf = fopen(logfile, "w");
- if (fsxlogf == NULL) {
- prterr(logfile);
- exit(93);
- }
- if (lite) {
- off_t ret;
- int fd = get_fd();
- file_size = maxfilelen = lseek(fd, (off_t) 0, SEEK_END);
- if (file_size == (off_t) - 1) {
- prterr(fname);
- warn("main: lseek eof");
- exit(94);
- }
- ret = lseek(fd, (off_t) 0, SEEK_SET);
- if (ret == (off_t) - 1) {
- prterr(fname);
- warn("main: lseek 0");
- exit(95);
- }
- }
- original_buf = malloc(maxfilelen);
- if (original_buf == NULL)
- exit(96);
- for (i = 0; i < maxfilelen; i++)
- original_buf[i] = random() % 256;
-
- good_buf = malloc(maxfilelen);
- if (good_buf == NULL)
- exit(97);
- memset(good_buf, '\0', maxfilelen);
-
- temp_buf = malloc(maxoplen);
- if (temp_buf == NULL)
- exit(99);
- memset(temp_buf, '\0', maxoplen);
-
- if (lite) { /* zero entire existing file */
- ssize_t written;
- int fd = get_fd();
-
- written = write(fd, good_buf, (size_t) maxfilelen);
- if (written != maxfilelen) {
- if (written == -1) {
- prterr(fname);
- warn("main: error on write");
- } else
- warn("main: short write, 0x%x bytes instead "
- "of 0x%x\n",
- (unsigned)written, maxfilelen);
- exit(98);
- }
- } else
- check_trunc_hack();
-
- while (numops == -1 || numops--)
- test();
-
- close_test_files();
- prt("All operations completed A-OK!\n");
-
- if (tf_buf)
- free(tf_buf);
-
- free(original_buf);
- free(good_buf);
- free(temp_buf);
-
- return 0;
+ if (file_desc)
+ SAFE_CLOSE(file_desc);
}
+
+static struct tst_test test = {
+ .needs_tmpdir = 1,
+ .setup = setup,
+ .cleanup = cleanup,
+ .test_all = run,
+ .max_runtime = 1800,
+ .options = (struct tst_option[]) {
+ { "l:", &str_file_max_size, "Maximum size in MB of the test file(s) (default 262144)" },
+ { "o:", &str_op_max_size, "Maximum size for single operation (default 65536)" },
+ { "N:", &str_op_nums, "Total # operations to do (default 1000)" },
+ { "w:", &str_op_write_align, "Write memory page alignment (default 1)" },
+ { "r:", &str_op_read_align, "Read memory page alignment (default 1)" },
+ { "t:", &str_op_trunc_align, "Truncate memory page alignment (default 1)" },
+ {},
+ },
+};
diff --git a/testcases/kernel/fs/fsx-linux/fsxtest b/testcases/kernel/fs/fsx-linux/fsxtest
deleted file mode 100755
index 61835437d..000000000
--- a/testcases/kernel/fs/fsx-linux/fsxtest
+++ /dev/null
@@ -1,50 +0,0 @@
-#!/bin/sh
-#
-# Copyright (c) 2001 Silicon Graphics, Inc. All Rights Reserved.
-# Copyright (c) International Business Machines Corp., 2001
-#
-# 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
-#
-#
-#
-# Proper error checking and result reporting still needed
-#
-# usage: fsxtest $1 $2 $3
-# $1 scratch device to use for testing
-# $2 optional file system type
-# $3 number of operations to perform
-
-#Uncomment line below for debugging
-#set -x
-if [ $2 = "jfs" ]; then
- mkfs -t $2 -q $1
-else
- mkfs -t $2 $1
-fi
-mkdir /testmount
-mount -t $2 $1 /testmount
-touch /testmount/testfile
-fsx-linux -N $3 /testmount/testfile
-RESULT=$?
-# report the results
-if [ $RESULT -eq "0" ]; then
- echo "PASS: fsxtest $1 $2 $3"
-else
- echo "FAIL: fsxtest $1 $2 $3"
-fi
-umount /testmount
-rm -rf /testmount
-fsck -a -t $2 $1 # report the results
-exit $RESULT
diff --git a/testcases/kernel/fs/fsx-linux/fsxtest02 b/testcases/kernel/fs/fsx-linux/fsxtest02
deleted file mode 100755
index fe014abdd..000000000
--- a/testcases/kernel/fs/fsx-linux/fsxtest02
+++ /dev/null
@@ -1,44 +0,0 @@
-#!/bin/sh
-#
-# Copyright (c) 2001 Silicon Graphics, Inc. All Rights Reserved.
-# Copyright (c) International Business Machines Corp., 2001
-#
-# 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
-#
-#
-#
-# Proper error checking and result reporting still needed
-#
-# usage: fsxtest02 $1
-# $1 number of operations to perform
-
-#Uncomment line below for debugging
-#set -x
-
-TCbin=${TCbin:-`pwd`}
-TCtmp=${TCtmp:-/tmp/fsxtest2.$$}
-
-mkdir -p $TCtmp 2>/dev/null
-touch $TCtmp/testfile
-$TCbin/fsx-linux -N $1 $TCtmp/testfile
-RESULT=$?
-# report the results
-if [ $RESULT -eq "0" ]; then
- echo "PASS: fsxtest02 $1 $2 $3"
-else
- echo "FAIL: fsxtest02 $1 $2 $3"
-fi
-rm -rf $TCtmp
-exit $RESULT
diff --git a/testcases/kernel/fs/iso9660/isofs.sh b/testcases/kernel/fs/iso9660/isofs.sh
index dfa4ac73d..d1a362d97 100755
--- a/testcases/kernel/fs/iso9660/isofs.sh
+++ b/testcases/kernel/fs/iso9660/isofs.sh
@@ -1,7 +1,7 @@
#!/bin/sh
# SPDX-License-Identifier: GPL-2.0-or-later
# Copyright (c) International Business Machines Corp., 2003
-# Copyright (c) Linux Test Project, 2016-2021
+# Copyright (c) Linux Test Project, 2016-2024
# Written by Prakash Narayana (prakashn@us.ibm.com)
# and Michael Reed (mreed10@us.ibm.com)
#
@@ -11,23 +11,12 @@
TST_NEEDS_CMDS="mount umount"
TST_NEEDS_TMPDIR=1
-TST_SETUP=setup
TST_TESTFUNC=do_test
+TST_CNT=3
MAX_DEPTH=3
MAX_DIRS=4
-setup()
-{
- if tst_cmd_available mkisofs; then
- MKISOFS_CMD="mkisofs"
- elif tst_cmd_available genisoimage; then
- MKISOFS_CMD="genisoimage"
- else
- tst_brk TCONF "please install mkisofs or genisoimage"
- fi
-}
-
gen_fs_tree()
{
local cur_path="$1"
@@ -50,10 +39,33 @@ do_test()
local make_file_sys_dir="$PWD/files"
local mkisofs_opt mount_opt
+ case $1 in
+ 1) MKISOFS_CMD="mkisofs"
+ HFSOPT="-hfs -D"
+ GREPOPT="mkisofs";;
+ 2) MKISOFS_CMD="genisoimage"
+ HFSOPT="-hfsplus -D -hfs -D"
+ GREPOPT="genisoimage";;
+ 3) MKISOFS_CMD="xorrisofs"
+ HFSOPT="-hfsplus -D"
+ GREPOPT="xorriso";;
+ esac
+
+ if ! tst_cmd_available $MKISOFS_CMD; then
+ tst_res TCONF "Missing '$MKISOFS_CMD'"
+ return
+ fi
+
+ if ! $MKISOFS_CMD 2>&1 | head -n 2 | grep -q "$GREPOPT"; then
+ tst_res TCONF "'$MKISOFS_CMD' is a symlink to another tool"
+ return
+ fi
+
+ tst_res TINFO "Testing $MKISOFS_CMD"
+
mkdir -p -m 777 $mnt_point
mkdir -p $make_file_sys_dir
- # Generated directories and files
mkdir -p $make_file_sys_dir
gen_fs_tree "$make_file_sys_dir" 1
@@ -62,15 +74,16 @@ do_test()
for mkisofs_opt in \
" " \
"-J" \
- "-hfs -D" \
+ "$HFSOPT" \
" -R " \
"-R -J" \
"-f -l -D -J -allow-leading-dots -R" \
- "-allow-lowercase -allow-multidot -iso-level 3 -f -l -D -J -allow-leading-dots -R"
+ "-allow-lowercase -allow-multidot -iso-level 3 -f -l -D -J \
+ -allow-leading-dots -R"
do
rm -f isofs.iso
- EXPECT_PASS $MKISOFS_CMD -o isofs.iso -quiet $mkisofs_opt $make_file_sys_dir 2\> /dev/null \
- || continue
+ EXPECT_PASS $MKISOFS_CMD -o isofs.iso -quiet $mkisofs_opt \
+ $make_file_sys_dir 2\> /dev/null || continue
for mount_opt in \
"loop" \
diff --git a/testcases/kernel/fs/mongo/README b/testcases/kernel/fs/mongo/README
deleted file mode 100644
index a134305b6..000000000
--- a/testcases/kernel/fs/mongo/README
+++ /dev/null
@@ -1,37 +0,0 @@
-
- MONGO.PL BENCHMARK.
-
-To run mongo benchmark please use the next :
-
-# run_mongo <device> <processes>
-
-Where :
-<device> - test device
-<processes> - number of processes
-
-The benchmark will be performed on given device with
-reiserfs and ext2. Then results will be compared.
-
-The results directory : ./results
-The comparision *.html and *.txt files in ./results/html
-
-Warning : All info will be erased on device.
-
-------------------------------------------------------
-
-Mongo.pl description :
-
- mongo.pl <filesystem> <device> <test_dir> <log> <processes>
-
- for example :
- mongo.pl reiserfs /dev/hda5 /testfs log 1
-
-Be careful :
- /dev/hda5 - test device and all info on it will be erased.
- It should be at least 500 Mb in size.
-
- /testfs - mount-point directory
-
- log - name prefix for results file.
-
-
diff --git a/testcases/kernel/fs/mongo/map5.c b/testcases/kernel/fs/mongo/map5.c
deleted file mode 100644
index 7cd700e98..000000000
--- a/testcases/kernel/fs/mongo/map5.c
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
- * Copyright 2000 by Hans Reiser, licensing governed by reiserfs/README
- */
-
-#include <stdio.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <linux/fs.h>
-#include <errno.h>
-
-int main(int argc, char **argv)
-{
- int fd;
- int block;
- int first_block;
- int last_block;
- int totals_block;
- int fragments;
- int i;
- int n;
-
- for (n = 1; n < argc; n++) {
- if (argc < 2) {
- printf
- ("Used to see file maps \nUsage: %s filename1 [[..[filename2]...filename(N-1)] filenameN]\n",
- argv[0]);
- return 0;
- }
- fd = open(argv[n], O_RDONLY);
- if (fd == -1) {
- perror("open failed");
- continue;
- }
- // printf ("file %s occupies blocks: \n", argv[1]);
- // printf ("START\tEND\tCOUNT\n");
- i = 0;
- block = 0;
- first_block = 0;
- last_block = 0;
- fragments = 0;
- totals_block = 0;
-
- while (ioctl(fd, FIBMAP, &block) == 0) {
- if (first_block == 0) {
- last_block = block - 1;
- first_block = block;
- }
- if (block != last_block + 1) {
- // printf ("%d\t%d\t%d\n",first_block,last_block,last_block-first_block+1);
- totals_block += last_block - first_block + 1;
- fragments++;
- first_block = block;
- last_block = block;
- } else {
- last_block++;
- }
-
- if (!block) {
- //printf ("Fragments: %d\tBlocks: %d\n",fragments,totals_block);
- //printf ("%d:%d\t",fragments,totals_block);
- //if (fragments == 1) printf(".",totals_block);
- //else printf("%d_",fragments,totals_block);
- printf("%d\n", fragments);
- break;
- }
-
- i++;
- block = i;
- }
- if (errno) {
- perror("FIBMAP failed");
- }
- close(fd);
- // printf ("\n");
- }
- return 0;
-}
diff --git a/testcases/kernel/fs/mongo/mongo.pl b/testcases/kernel/fs/mongo/mongo.pl
deleted file mode 100755
index 5d47d8746..000000000
--- a/testcases/kernel/fs/mongo/mongo.pl
+++ /dev/null
@@ -1,511 +0,0 @@
-#!/usr/bin/perl
-#
-# Copyright 2000 by Hans Reiser, licensing governed by reiserfs/README
-#
-
-#
-# Mongo.pl is reiserfs benchmark.
-#
-# To run please use run_mongo script or :
-#
-# # ./mongo.pl reiserfs /dev/xxxx /testfs log1 5
-# or
-# # ./mongo.pl ext2 /dev/xxxx /testfs log2 5
-#
-# 5 - number of processes, you can set any number here
-#
-# Test will format partition /dev/xxxx by 'mkreiserfs' or 'mke2fs'
-# mount it and run given number of processes during each phase :
-# Create, Copy, Symlinks, Read, Stats, Rename and Delete.
-#
-# Also, the program calc fragmentations after Create and Copy phases:
-# Fragm = number_of_fragments / number_of_files
-# (Current version use the files more than 16KB to calc Fragm.)
-#
-# You can find the same results in files : log, log.tbl, log_table
-#
-# log - raw results
-# log.tbl - results for compare program
-# log_table - results in table form
-#
-
-$EXTENDED_STATISTICS = 1;
-
-
-use POSIX;
-use File::stat;
-
-sub print_usage {
-
- print "\nUsage: mongo.pl <filesystem> <device>";
- print " <mount_point> <log> <processes>\n";
-
- print "<filesystem> - the name of filesystem [reiserfs|ext2]\n";
- print "<device> - the device for benchmark (e.g. /dev/hda9)\n";
- print "<mount_point> - mount-point for the filesystem";
- print " (e.g. /mnt/testfs)\n";
- print "<log> - the name prefix for benchmark results\n";
- print "<processes> - the number of benchmark processes\n";
-
- print "\nexamples:\n";
- print "mongo.pl reiserfs /dev/hda9 /testfs reiserfs_results 1\n";
- print "mongo.pl ext2 /dev/hda9 /testfs ext2_results 1\n";
-
- print "\nThe results will be put in ./results directory\n";
-}
-
-
-#------- Subroutines declaration --------
-sub make_fsys;
-sub mongo_x_process;
-sub mongo_launcher;
-sub set_params;
-
-#------- main() -------------------------
-
-if ( $#{ARGV} != 4 ) {
- print_usage;
- exit(0);
- }
-
-#--------------------------------------------
-# Set working directories
-#--------------------------------------------
-$TOPDIR = "$ENV{PWD}";
-
-$RESDIR = "${TOPDIR}/results";
-$HTMLDIR = "${RESDIR}/html";
-
-$FILESYSTEM = $ARGV[0];
-$DEVICE = $ARGV[1];
-$TESTDIR = $ARGV[2];
-$PROCESSES = $ARGV[4];
-
-$LOGFILE = "${RESDIR}/${ARGV[3]}";
-$LOGFILE2 = "${LOGFILE}_table";
-$LOGFILE3 = "${LOGFILE}.tbl";
-
-$TMPFILE = "${RESDIR}/mongo_tmp";
-$nproc = $PROCESSES;
-$READIT = "${TOPDIR}/mongo_read";
-$SLINKS = "${TOPDIR}/mongo_slinks";
-
-#-------- reiser_fract_tree parameters----------------
-$x1mb = 1024 * 1024;
-$x2mb = 2 * $x1mb;
-$x3mb = 3 * $x1mb;
-
-$x5mb = 5 * $x1mb;
-$x50mb = 50 * $x1mb;
-$x100mb = 100 * $x1mb;
-
-# Total amount of bytes in all files on test partition
-#-----------------------------------------------------
-
-$small_bytes = $x50mb;
-$medium_bytes = $x100mb;
-$big_bytes = $x100mb;
-$large_bytes = $x100mb;
-
-# Median size of files in bytes for first tree to create
-#-------------------------------------------------------
-$small_size = 100;
-$medium_size = 1000;
-$big_size = 10000;
-$large_size = 100000;
-
-# Keep the largest file to one fifth (100 million bytes)
-# of the total tree size.
-#-------------------------------------------------------
-$max_file_size = 100000000;
-
-# Yuri Shevchuk says that 0 is the median size
-# in real life, so I believe him.
-#----------------------------------------------
-$median_dir_nr_files = 0;
-
-# This should be larger, change once done testing.
-#-------------------------------------------------
-$bytes_to_consume = 10000000;
-
-$median_file_size = 100;
-$max_file_size = 1000000;
-
-$median_dir_nr_files = 100;
-$max_directory_nr_files = 10000;
-
-$median_dir_branching = 0;
-$max_dir_branching = 1;
-
-# This should be varying, someday....
-#------------------------------------
-$write_buffer_size = 4096;
-
-@numb_of_bytes = ($small_bytes, $medium_bytes, $big_bytes, $large_bytes);
-@size_of_files = ($small_size, $medium_size, $big_size, $large_size);
-
-$reiser_fract_tree_rep_counter = 3;
-
-$total_params = $#{numb_of_bytes};
-
-#... Make directories for results
-#--------------------------------
-unless (-e $RESDIR) {
- print "Creating dir: ${RESDIR} \n";
- system("mkdir $RESDIR");
-}
-
-unless ( -e $HTMLDIR ) {
- print "Creating dir: ${HTMLDIR} \n";
- system("mkdir $HTMLDIR");
-}
-
-#... Compile *.c files if it is necessary
-#----------------------------------------
-sub compile
-{
- my $file = shift @_;
- my $opt = shift @_ if @_ ;
- my $cfile = $file . ".c";
- die "source file \"${cfile}\" does not exist" unless (-e "$cfile");
- if ( -e "$file" && (stat("$file")->mtime >= stat("$cfile")->mtime)) {
- print "$file is up to date ...\n";
- } else {
- print "Compiling ${cfile} ...\n";
- system ("gcc $cfile -o $file $opt");
- }
-}
-
-compile("reiser_fract_tree", "-lm");
-compile("mongo_slinks");
-compile("mongo_read");
-compile("map5");
-compile("summ");
-compile("mongo_compare");
-
-#... Check the command string parameters
-#---------------------------------------
-unless ( ($FILESYSTEM eq "reiserfs") or ($FILESYSTEM eq "ext2") ) {
- print "mongo.pl: not valid filesystem name: ${FILESYSTEM} \n";
- print "Usage: mongo.pl <filesystem> <device> <mount_point> <log> <repeat>\n";
- exit(0);
-}
-
-unless ( -b $DEVICE ) {
- print "mongo.pl: not valid device: ${DEVICE} \n";
- print "Usage: mongo.pl <filesystem> <device> <mount_point> <log> <repeat>\n";
- exit(0);
-}
-
-
-#------- Subroutines --------------------------------------
-#----------------------------------------------------------
-sub get_blocks_usage ($) {
- my ($mp) = @_;
- my $df = `df -k $mp | tail -n 1`;
- chomp $df;
- my @items = split / +/, $df;
- return $items[2];
-}
-
-sub make_fsys {
-
- system ("umount $TESTDIR") ;
-
- if ( $FILESYSTEM eq "reiserfs" ) {
- system("echo y | mkreiserfs $DEVICE") ;
- system("mount -t reiserfs $DEVICE $TESTDIR") ;
- }
-
- if ( $FILESYSTEM eq "ext2" ) {
- system("mke2fs $DEVICE") ;
- system("mount $DEVICE $TESTDIR") ;
- }
-}
-
-
-#------------------------------------------------------------------
-# Mongo Launcher
-#------------------------------------------------------------------
-sub mongo_launcher {
-
- my ($phase_num, $phase_name, $cmd, $dir1, $dir2, $flag, $processes) = @_ ;
-
-
- print "$phase_num.$phase_name files of median size $median_file_size bytes ($p processes)...\n";
- print LOG "********* Phase $phase_num: $phase_name files of median size $median_file_size bytes ($p processes) *********\n";
- $i=0;
- $total=0;
-
-# eliminate the rep counter and the while
- while ( $i < $reiser_fract_tree_rep_counter ) {
- print "$phase_name : ";
- print LOG "$phase_name : ";
- $com = "";
- $pp=$processes;
-
- $j=0;
- while ($pp > 0) {
- $pp--;
-
-# the fact that this if statement was necessary indicated you
-# attempted excessive generalization and abstraction where it was not
-# natural to the task that makes the code harder to understand. put
-# every command on one line to execute. I like it when I can read a
-# one line command and see what that phase of the test does instead of
-# looking in many places throughout the code.
-
- if ($phase_num == 1) {
- $com .= "$cmd $dir1-$i-$j $flag";
- }
- elsif ($phase_num == 2) {
- $com .= "$cmd $dir1-$i-$j $dir2-$i-$j";
- }
- elsif ($phase_num == 3) {
- $com .= "$cmd $dir1-$i-$j "."-type f | while read X; do echo \$X \$X.lnk ; done | $TOPDIR/mongo_slinks ";
- }
- elsif ($phase_num == 4) {
- $com .= "$cmd";
- }
- elsif ($phase_num == 5) {
- $com .= "$cmd";
- }
- elsif ($phase_num == 6) {
- $com .= "$cmd $dir1-$i-$j -type f | perl -e 'while (<>) { chomp; rename (\$_, \"\$_.r\"); };'";
- #$com .= " & $cmd $dir2-$i-$j "."-type d -exec mv {} {}.r ';'";
- }
- elsif ($phase_num == 7) {
- if ($processes > 1) {
- $com .= "$cmd $dir1-$i-$j & $cmd $dir2-$i-$j";
- }
- else {
- $com .= "$cmd $dir1-$i-$j ; $cmd $dir2-$i-$j";
- }
- }
- $com .= " & ";
- $j++;
- }
-
- $com .= " wait";
- #print $com, "\n";
-
- @t=`(time -p $com) 2>&1`;
-
- @tt = split ' ', $t[0];
- $res = $tt[1];
- unless ( $res =~ /\s*\d+/) {
- print @t , "\n";
- print LOG @t, "\n";
- } else {
- print LOG "$res sec.\n";
- print "$res sec.\n";
- }
-
- $total += $res;
- $i++;
- }
-
- print "total $phase_name time: $total sec.\n";
- print LOG "total $phase_name time: $total sec.\n";
-
- $ares[$phase_num]=$total; # ser array of results
-
- if ($EXTENDED_STATISTICS) {
- if( $phase_num < 3) {
- $used = get_blocks_usage($TESTDIR) - $used0;
- if ($phase_num == 1) {
- $used1=$used;
- }elsif($phase_num == 2){
- $used2=$used;
- }
- print "Used disk space (df) : $used KB\n";
- print LOG "Used disk space (df) : $used KB\n";
-
- open (FIND_PIPE, "find $TESTDIR|") || die "cannnot open pipe from \"find\": $!\n";
- $dirs = 0;
- $files = 0;
- $files16 = 0;
-
- while(<FIND_PIPE>) {
- chomp;
- $st = lstat ($_);
- if (S_ISDIR($st->mode)) {
- $dirs ++;
- } elsif (S_ISREG($st->mode)) {
- $files ++;
- $files16 ++ if ($st->size > 16384);
- }
- }
-
- close (FIND_PIPE);
-
- print "Total dirs: $dirs\n";
- print "Total files: $files\n";
- print LOG "Total dirs: $dirs\n";
- print LOG "Total files: $files\n";
-
- #$f=$frag;
- $f16 = $files16;
- $fr16 =`find $TESTDIR -type f -size +16k | xargs $TOPDIR/map5 | $TOPDIR/summ | tail -n 1 2>&1`;
- @ff16= split ' ', $f16;
- @ffr16= split ' ', $fr16;
- $files16 = $ff16[0];
- $frag = $ffr16[0];
- $procent = $frag / $files16;
- print "Total fragments : $frag \n";
- print LOG "Total fragments : $frag \n";
-
- printf "Fragments / files :%.3f\n", $procent;
- printf LOG "Fragments / files :%.3f\n", $procent;
- $frag_res[$phase_num]=$procent; # ser array of results
- }
- }
-
- system("sync");
- print "\n";
- print LOG "\n";
-
-}
-
-# and what is an x process?
-
-#------------------------------------------------------------------
-# MONGO_X_PROCESS ( x is number of processes to run )
-#------------------------------------------------------------------
-sub mongo_x_process {
-
- my ($processes) = @_ ;
- $p = $processes;
-
- make_fsys; # make and mount the file system
- $used0 = get_blocks_usage($TESTDIR);
-
- open LOG, ">>$LOGFILE" or die "Can not open log file $LOGFILE\n";
- open LOG2, ">>$LOGFILE2" or die "Can not open log file $LOGFILE2\n";
- open LOG3, ">>$LOGFILE3" or die "Can not open log file $LOGFILE2\n";
-
- print LOG "FILESYSTEM=$FILESYSTEM \n";
-
- print "\n";
- if($p == 1) {
- print "mongo_single_process, the_set_of_param.N=$par_set_n of $total_params \n";
- print LOG "mongo_single_process, the_set_of_paramN=$par_set_n of $total_params \n";
- } elsif ($p > 1) {
- print "mongo_multi_process ($p processes), the_set_of_param.N=$par_set_n of $total_params \n";
- print LOG "mongo_multi_process ($p processes), the_set_of_paramN=$par_set_n of $total_params \n";
- }
-
- print "Results in file : $LOGFILE \n";
- print "\n";
-
- $dir1 = "$TESTDIR/testdir1";
- $dir2 = "$TESTDIR/testdir2";
- $flag = 0;
-
- $cmd_1 = "$TOPDIR/reiser_fract_tree $bytes_to_consume $median_file_size $max_file_size $median_dir_nr_files $max_directory_nr_files $median_dir_branching $max_dir_branching $write_buffer_size";
- $cmd_2 = "cp -r";
- $cmd_3 = "find";
- $cmd_4 = "find $TESTDIR -type f | xargs $TOPDIR/mongo_read";
- $cmd_5 = "find $TESTDIR -type f > /dev/null"; # it should be enough for stat all files. -zam
- $cmd_6 = "find"; #" $TESTDIR -type f -exec mv {} {}.r ';'";
- $cmd_7 = "rm -r";
-
- system("sync");
- $frag = 0;
- mongo_launcher ( 1, "Create", $cmd_1, $dir1, $dir2, $flag, $p); # phase 1
- mongo_launcher ( 2, "Copy ", $cmd_2, $dir1, $dir2, $flag, $p); # phase 2
- mongo_launcher ( 3, "Slinks", $cmd_3, $dir1, $dir2, $flag, $p); # phase 3
- mongo_launcher ( 4, "Read ", $cmd_4, $dir1, $dir2, $flag, $p); # phase 4
- mongo_launcher ( 5, "Stats ", $cmd_5, $dir1, $dir2, $flag, $p); # phase 5
- mongo_launcher ( 6, "Rename", $cmd_6, $dir1, $dir2, $flag, $p); # phase 6
- mongo_launcher ( 7, "Delete", $cmd_7, $dir1, $dir2, $flag, $p); # phase 7
-
- print LOG2 "\n";
- if ($processes > 1) {
- print LOG2 "MONGO_MULTI_PROCESS ($processes processes) BENCHMARK RESULTS (time in sec.)\n";
- }else {
- print LOG2 "MONGO_SINGLE_PROCESS BENCHMARK RESULTS (time in sec.)\n";
- }
- print LOG2 " FILESYSTEM=$FILESYSTEM\n";
- print LOG2 " parameters: files=$files, base_size=$median_file_size bytes, dirs=$dirs\n";
- print LOG2 "--------------------------------------------------------------\n";
- print LOG2 "Create\tCopy\tSlink\tRead\tStats\tRename\tDelete\n";
- print LOG2 " time \ttime\ttime\ttime\ttime \t time \t time\n";
- print LOG2 "--------------------------------------------------------------\n";
- print LOG2 "$ares[1]\t$ares[2]\t$ares[3]\t$ares[4]\t$ares[5]\t$ares[6]\t$ares[7]\n";
- print LOG2 "--------------------------------------------------------------\n";
- print LOG2 "The size of files tree : \n";
- print LOG2 " after create = $used1 kb\n";
- print LOG2 " after copy = $used2 kb\n";
- print LOG2 "\n";
-
-
- print LOG3 "\n";
- if ($processes > 1) {
- print LOG3 "MONGO_MULTI_PROCESS ($processes) \n";
- }else {
- print LOG3 "MONGO_SINGLE_PROCESS \n";
- }
- print LOG3 "parameters: \n";
- print LOG3 "files=$files \n";
- print LOG3 "base_size=$median_file_size bytes \n";
- print LOG3 "dirs=$dirs \n";
- print LOG3 "\n";
-
- print LOG3 "FSYS=$FILESYSTEM \n";
- print LOG3 "(time in sec.) \n";
- print LOG3 "Create : $ares[1]\n";
- print LOG3 "Fragm. : $frag_res[1]\n";
- print LOG3 "df : $used1\n\n";
- print LOG3 "Copy : $ares[2] \n";
- print LOG3 "Fragm. : $frag_res[2]\n";
- print LOG3 "df : $used2\n\n";
- print LOG3 "Slinks : $ares[3]\n";
- print LOG3 "Read : $ares[4]\n";
- print LOG3 "Stats : $ares[5]\n";
- print LOG3 "Rename : $ares[6] \n";
- print LOG3 "Delete : $ares[7]\n";
-
- print LOG3 "\n";
-
-
- if($processes > 1) {
- print LOG "******* The end of mongo_multi_process *******";
- }else {
- print LOG "******* The end of mongo_single_process *******";
- }
-}
-
-#---------------------------------------------------
-# Set parameters
-#---------------------------------------------------
-sub set_params {
- my ($n) = @_ ;
-
- $bytes_to_consume = $numb_of_bytes[$n];
- $median_file_size = $size_of_files[$n];
-
- #$max_file_size = 1000000;
-
- #$median_dir_nr_files = 100;
- #$max_directory_nr_files = 10000;
-
- #$median_dir_branching = 0;
- #$max_dir_branching = 1;
-
-}
-
-#----------------------------------------------------------
-# TEST START
-#----------------------------------------------------------
-
- $par_set_n = 0;
- foreach $fsize (@size_of_files) {
- set_params ($par_set_n);
- mongo_x_process( $nproc ); # run n processes
- $par_set_n++;
- }
- system("umount $TESTDIR");
- exit;
-
-
diff --git a/testcases/kernel/fs/mongo/mongo_compare.c b/testcases/kernel/fs/mongo/mongo_compare.c
deleted file mode 100644
index 6dba95347..000000000
--- a/testcases/kernel/fs/mongo/mongo_compare.c
+++ /dev/null
@@ -1,224 +0,0 @@
-/*
- * Copyright 2000 by Hans Reiser, licensing governed by reiserfs/README
- */
-
-#include <stdio.h>
-#include <ctype.h>
-#include <string.h>
-
-char time_str1[50];
-char time_str2[50];
-char name_str1[50];
-char tmp_str[20][100];
-
-char out1[256];
-char out2[256];
-
-FILE *f1;
-FILE *f2;
-FILE *f3;
-FILE *f4;
-
-void write_html_head(FILE * fp);
-void write_html_end(FILE * fp);
-
-char head_str[] = "\n \
-<!doctype html public \"-//w3c//dtd html 4.0 transitional//en\">\n \
-<html>\n \
-<head>\n \
- <meta http-equiv=\"Content-Type\" content=\"text/html; charset=iso-8859-1\">\n \
- <meta name=\"GENERATOR\" content=\"Mozilla/4.5 [en] (X11; I; Linux 2.2.7 i586) [Netscape]\">\n \
-</head>\n \
-<body>\n \
-";
-/*
-<tt></tt>&nbsp;\n \
-<table BORDER NOSAVE >\n \
-<tr BGCOLOR=\"#CCFFFF\" NOSAVE>\n \
-<td NOSAVE> \n \
-";
-*/
-
-char end_str[] = "\n \
-</table> \n \
-<tt></tt> \n \
-</body> \n \
-</html> \n \
-";
-
-main(int argc, char **argv)
-{
- float n1, n2, ratio;
- char *p, *p1, *p2;
- char line0[100];
- char line1[100];
- char line2[100];
- char line3[100];
- char out_line[100];
- char html_line[500];
- int i, k;
-
- if (argc < 3) {
- printf("\nUsage: mongo_compare file1 file2 res_file\n\n");
- printf
- ("\t<file1> should contain reiserfs or ext2 results of mogo benchmark\n");
- printf
- ("\t<file2> should contain reiserfs or ext2 results of mogo benchmark\n");
- printf("\tMongo results will be compared\n");
- printf
- ("\t<res_file.txt> will be contain results in the text form\n");
- printf
- ("\t<res_file.html> will be contain results in the html form\n");
- exit(0);
- }
-
- strcpy(out1, argv[3]);
- strcat(out1, ".txt");
-
- strcpy(out2, argv[3]);
- strcat(out2, ".html");
-
- if ((f1 = fopen(argv[1], "r")) == NULL) {
- fprintf(stderr, "%s: can't open %s\n", argv[0], argv[1]);
- return 1;
- }
-
- if ((f2 = fopen(argv[2], "r")) == NULL) {
- fprintf(stderr, "%s: can't open %s\n", argv[0], argv[2]);
- return 1;
- }
-
- if ((f3 = fopen(out1, "wr")) == NULL) {
- fprintf(stderr, "%s: can't open %s\n", argv[0], out1);
- return 1;
- }
-
- if ((f4 = fopen(out2, "wr")) == NULL) {
- fprintf(stderr, "%s: can't open %s\n", argv[0], out2);
- return 1;
- }
-
- write_html_head(f4);
- i = 0;
- while (fgets(line1, 100, f1)) {
- fgets(line2, 100, f2);
-
- if (p = strstr(line1, "\n"))
- *(p + 1) = 0;
- if (p = strstr(line2, "\n"))
- *(p + 1) = 0;
-
- strcpy(line3, line1);
- line3[strlen(line3) - 1] = 0;
-
- while (strlen(line3) < 40) {
- strcat(line3, " ");
- }
-
- if (strstr(line3, "MONGO_")) {
- fprintf(f4, "</table>\n<table BORDER NOSAVE >\n");
- fprintf(f4, "<tr BGCOLOR=\"#CCFFFF\" NOSAVE>");
- fprintf(f4, "<td NOSAVE>\n");
- i = 0;
- }
- if (i < 20)
- strcpy(tmp_str[i], line2);
-
- if (strstr(line3, "FSYS=")) {
- fprintf(f4, "</td><td>\n");
- for (k = 0; k < i; k++) {
- fprintf(f4, "<tt>%s</tt><br>\n", tmp_str[k]);
- }
- fprintf(f4,
- "</td>\n <tr BGCOLOR=\"#CCFFFF\" NOSAVE><td COLSPAN=\"2\"><tt><B> %s %s </B></tt>\n",
- line3, line2);
- i = 20;
- } else if (NULL == strstr(line3, " :")) {
-
- if (strstr(line3, "(time"))
- fprintf(f4,
- "<br><tt><center>%s</center></tt>\n",
- line3);
- else {
- k = 0;
- p = line3;
- while (*p++ != 0) {
- if (*p != ' ' && *p != '\n')
- k++;
- }
- if (k > 0) {
- fprintf(f4, "<tt>%s</tt><br>\n", line3);
- if (i < 20)
- i++;
- }
- }
- }
-
- else if (strstr(line3, "Create"))
- fprintf(f4, "</td>\n");
-
- line2[strlen(line2) - 1] = 0;
- while (strlen(line2) < 40) {
- strcat(line2, " ");
- }
-
- strcat(line3, line2);
-
- strcpy(out_line, line3);
- strcat(out_line, "\n");
- name_str1[0] = 0;
-
- if (p1 = strstr(line1, " :")) {
- strcpy(time_str1, p1 + 2);
- strncpy(name_str1, line1, p1 - line1);
-
- if (p2 = strstr(line2, " :")) {
- strcpy(time_str2, p2 + 2);
-
- time_str1[strlen(time_str1) - 1] = 0;
- time_str2[strlen(time_str2) - 1] = 0;
-
- sscanf(time_str1, "%f", &n1);
- sscanf(time_str2, "%f", &n2);
-
- ratio = n1 / n2;
- sprintf(out_line, "%s : %6.2f / %6.2f = %.2f\n",
- name_str1, n1, n2, ratio);
-
- fprintf(f4,
- "<tr><td><tt> %s &nbsp </tt></td> <td><div align=right><tt> %6.2f / %6.2f = %.2f &nbsp </tt></div></td></tr>\n",
- name_str1, n1, n2, ratio);
-
- }
- }
-
- fprintf(f3, "%s", out_line);
- line1[0] = 0;
- line2[0] = 0;
- line3[0] = 0;
- out_line[0] = 0;
- }
-
- write_html_end(f4);
-
- fclose(f1);
- fclose(f2);
-
- fclose(f3);
- fclose(f4);
-
- fflush(f3);
- fflush(f4);
-}
-
-/*******************************************/
-void write_html_head(FILE * fp)
-{
- fprintf(fp, "%s", head_str);
-}
-
-/*******************************************/
-void write_html_end(FILE * fp)
-{
- fprintf(fp, "%s", end_str);
-}
diff --git a/testcases/kernel/fs/mongo/mongo_read.c b/testcases/kernel/fs/mongo/mongo_read.c
deleted file mode 100644
index 927b92a13..000000000
--- a/testcases/kernel/fs/mongo/mongo_read.c
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Copyright 2000 by Hans Reiser, licensing governed by reiserfs/README
- */
-
-/*
- * MONGO READ - simple possible program to read a number of given files
- * suitable for benchmarking FS read performance
- */
-
-#include <stdio.h>
-#include <errno.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <stdlib.h>
-#include <unistd.h>
-
-int main(int argc, char **argv)
-{
- int fd, rd, i;
- char *buf;
- int bufsize = 4096;
-
- if (argc < 2) {
- printf("\nUsage: %s filename [,filename2 [,...] ] ]\n\n",
- argv[0]);
- return 0;
- }
-
- buf = malloc(bufsize);
- if (buf == 0) {
- printf("Malloc failed on %d\n", bufsize);
- return 0;
- }
-
- /* Read all given files */
- for (i = 1; i < argc; i++) {
-
- /* open the file */
- fd = open(argv[i], O_RDONLY);
- if (fd == -1) {
- printf("Open failed (%s)\n", strerror(errno));
- return 0;
- }
-
- /* read the file */
- while ((rd = read(fd, buf, bufsize)) == bufsize) ;
- if (rd == -1) {
- printf("Read failed (%s)\n", strerror(errno));
- return 0;
- }
- close(fd);
- }
-
- free(buf);
- return 0;
-}
diff --git a/testcases/kernel/fs/mongo/mongo_slinks.c b/testcases/kernel/fs/mongo/mongo_slinks.c
deleted file mode 100644
index 6bd1e2b69..000000000
--- a/testcases/kernel/fs/mongo/mongo_slinks.c
+++ /dev/null
@@ -1,98 +0,0 @@
-//
-// A simple symlink test
-//
-
-#define _GNU_SOURCE
-
-#include <sys/stat.h>
-#include <unistd.h>
-#include <stdlib.h>
-#include <errno.h>
-#include <stdio.h>
-#include <string.h>
-
-//
-// Creates symlink [new-path] to [old-path], checks it,
-// returnes 0 - if everything looks fine and
-// 1 - otherwise.
-// mongo_slinks reads arguments from stdin.
-
-int main(int argc, char *argv[])
-{
- char *old_path;
- char *new_path;
-
- struct stat statbuf;
-
- int num;
- char *buffer = NULL;
- char *line_buffer = NULL;
- size_t line_buffer_size = 0;
- int size = 1;
-
- if ((buffer = malloc(size + 1)) == NULL) {
- perror("checklink: malloc failed");
- return 1;
- }
-
- while (getline(&line_buffer, &line_buffer_size, stdin) != -1) {
-
- old_path = strtok(line_buffer, "\t ");
- new_path = strtok(NULL, "\t\n ");
-
- if (!old_path || !new_path) /* empty lines at the end of file */
- break;
-
- // Create symlink
- if (symlink(old_path, new_path) != 0) {
- perror("checklink : symlink failed ");
- return 1;
- }
- // stat data of symlink itself
- if (lstat(new_path, &statbuf) == -1) {
- perror("checklink: lstat failed");
- return 1;
- }
-
- if (!(S_ISLNK(statbuf.st_mode))) {
- printf("checklink : file %s is not a symbol link\n",
- new_path);
- return 1;
- }
- // Test readlink
- //
- // Increase size of buffer to readlink untile whole symlink body will be read.
- // Check readlink result on every iteration.
-
- while (1) {
- memset(buffer, 0, size + 1);
- num = readlink(new_path, buffer, size);
- if (num < 1 || num > size) {
- perror("checklink: readlink failed");
- free(buffer);
- return 1;
- }
- // Make sure that readlink did not break things
- if (buffer[num] != 0) {
- printf
- ("checklink : readlink corrupts memory\n");
- free(buffer);
- return 1;
- }
- // Whole expected symlink body is read
- if (num < size)
- break;
-
- // Only part of symlink body was read. So we make a bigger buffer
- // and call `readlink' again.
- size *= 2;
- if ((buffer = realloc(buffer, size + 1)) == NULL) {
- perror("checklink: realloc failed");
- return 1;
- }
- }
- }
- free(buffer);
- free(line_buffer);
- return 0;
-}
diff --git a/testcases/kernel/fs/mongo/reiser_fract_tree.c b/testcases/kernel/fs/mongo/reiser_fract_tree.c
deleted file mode 100644
index af2fa46a7..000000000
--- a/testcases/kernel/fs/mongo/reiser_fract_tree.c
+++ /dev/null
@@ -1,502 +0,0 @@
-/*
- * Copyright 2000 by Hans Reiser, licensing governed by reiserfs/README
- */
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include <math.h>
-#include <sys/types.h>
-#include <unistd.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <errno.h>
-char tdir[256];
-char path[256];
-long stats = 0;
-
-void print_usage()
-{
- printf("
-This program creates files in a tree of random depth and branching. Files vary
-in size randomly according to a distribution function which seems to model real
-file systems. This distribution function has a median size of median_file_size
-(Median file size is hypothesized to be proportional to the average per file
-space wastage. Notice how that implies that with a more efficient file system
-file size usage patterns will in the long term move to a lower median file
-size), and a maximum size of max_file_size. Directories vary in size according
-to the same distribution function but with separate parameters to control median
-and maximum size for the number of files within them, and the number of
-subdirectories within them. This program prunes some empty subdirectories in a
-way that causes parents of leaf directories to branch less than
-median_dir_branching.
-
- To avoid having one large file distort the results such that you have
-to benchmark many times set max_file_size to not more than
-bytes_to_consume/10. If maximum/median is a small integer, then
-randomness is very poor. This is a bug, Nikita, please find some
-clever way to fix it. If it is 0, then the program crashes....
-
-For isolating performance consequences of design variations on
-particular file or directory size ranges, try setting their median size and
-max_size to both equal the max size of the file size range you want
-to test.
-
-To avoid having one large file distort the results set max_file_size to
-not more than bytes_to_consume/10. Using a distribution function for
-the sizes of writes would be a natural next step in developing this program.\n\n");
-
- printf
- ("Usage: reiser_fract_tree bytes_to_consume median_file_size max_file_size median_dir_nr_files max_directory_nr_files median_dir_branching max_dir_branching write_buffer_size /testfs_mount_point print_stats_flag\n\n");
-}
-
-/* #define DEBUG */
-
-char *write_buffer; /* buffer from which we write */
-int write_buffer_size = 0; /* gets reset to an argv */
-static int already_whined = 0; /* keep out of disk space errors from being
- endless by tracking whether we already
- printed the message */
-long bytes_to_consume = 0; /* create files until their total number of
- bytes exceeds this number, but not by more
- than 1/10th */
-long byte_total = 0; /* bytes created so far */
-
-/* statistics on sizes of files we attempted to create */
-int fsz_0_100 = 0;
-int fsz_100_1k = 0;
-int fsz_1k_10k = 0;
-int fsz_10k_100k = 0;
-int fsz_100k_1m = 0;
-int fsz_1m_10m = 0;
-int fsz_10m_larger = 0;
-
-void chngdir(char *name)
-{
- int i;
-
- if (name[0] == '.' && name[1] == '.') {
- for (i = strlen(path); i > 0; i--) {
- if (path[i] == '/') {
- path[i] = 0;
- break;
- }
- }
- } else {
- strcat(path, "/");
- strcat(path, name);
- }
-}
-
-/* this is the core statistical distribution function, and it is used for file
- sizes, directory sizes, etc. */
-int determine_size(double median_size,
- double max_size /* The maximal value of size */ )
-{
- /* when x is half of its random range (max_size/median_size), result is
- median_size */
- int nr_random, granularity_reducer;
- double size, double_nr_random;
-
- /* it is a feature for us that this repeats identically every time it is run,
- as otherwise meaningless variances would affect our results and require us
- to use a higher number of benchmarks to achieve low noise results. */
- nr_random = rand();
- median_size++; /* avoids divide by zero errors */
-
- /* this code does poorly when max_size is not a lot more than median size,
- and that needs fixing */
-
- /* THE NEXT 2 LINES ARE THE HEART OF THE PROGRAM */
-
- /* keep x below the value that when multiplied by median size on the next
- line will equal max_size */
- /* the granularity_reducer is to handle the case where max_size is near
- median_size, since '%' can only take ints, we need this complicated what
- of handling that for small values of max_size/median_size by making
- large ints out of small ints temporarily. */
- if (max_size / median_size < 1024)
- granularity_reducer = 1024 * 1024;
- else
- granularity_reducer = 1;
- nr_random =
- nr_random %
- ((int)
- (granularity_reducer *
- (((double)max_size) / ((double)median_size))));
- double_nr_random = ((double)nr_random) / (granularity_reducer);
- size =
- median_size * (1 /
- (1 -
- (double_nr_random) / (((double)max_size) /
- ((double)median_size))) - 1);
- return ((int)size);
-}
-
-/* generate a unique filename */
-void get_name_by_number(long this_files_number, char *str)
-{
- sprintf(str, "%lu", this_files_number);
-}
-
-/* make a file of a specified size */
-void make_file(int size)
-{
- char string[128] = { 0 };
- char *str = string;
- char fname[256];
- int fd = 0;
- int error;
- static long this_files_number = 1;
-
- /* collect statistics about the size of files created, or more precisely, the
- size of files that we will attempt to create. */
- if (size <= 100)
- fsz_0_100++;
- else if (size <= 1000)
- fsz_100_1k++;
- else if (size <= 10 * 1000)
- fsz_1k_10k++;
- else if (size <= 100 * 1000)
- fsz_10k_100k++;
- else if (size <= 1000 * 1000)
- fsz_100k_1m++;
- else if (size <= 10 * 1000 * 1000)
- fsz_1m_10m++;
- else
- fsz_10m_larger++;
-
- /* construct a name for the file */
- get_name_by_number(this_files_number++, str);
- strcpy(fname, path);
- strcat(fname, "/");
- strcat(fname, str);
-
- /* open the file, and deal with the various errors that can occur */
-
- if ((fd = open(fname, O_CREAT | O_EXCL | O_RDWR, 0777)) == -1) {
- if (errno == ENOSPC) {
- if (!already_whined) {
- printf
- ("reiser-2021A: out of disk (or inodes) space, will keep trying\n");
- already_whined = 1; /* we continue other file creation in out of
- space conditions */
- }
- return;
- }
- /* it is sometimes useful to be able to run this program more than once
- inside the same directory, and that means skipping over filenames that
- already exist. Thus we ignore EEXIST, and pay attention to all
- else. */
- if (errno == EEXIST) { /* just skip existing file */
- return;
- }
- perror("open");
- exit(errno);
- }
- /* write to the file until it is the right size, handling the various error
- conditions appropriately */
-
- while (size > 0) {
- size -= (error =
- write(fd, write_buffer,
- (size <
- write_buffer_size -
- 1) ? size : (write_buffer_size - 1)));
- if (error == -1) {
- if (errno == ENOSPC) {
- if (!already_whined) {
- printf
- ("reiser-2022: out of disk space, will keep trying\n");
- already_whined = 1;
- }
- close(fd);
- return;
- }
- perror("write() failed");
- exit(errno);
- }
- }
-
- /* close the file */
- if (close(fd)) {
- perror("close() failed");
- exit(errno);
- }
-}
-
-/* print the statistics on how many files were created of what size */
-
-void print_stats()
-{
- if (!stats)
- return;
-
- printf("\n");
- printf("File stats: Units are decimal (1k = 1000)\n");
- printf("files 0-100 : %i\n", fsz_0_100);
- printf("files 100-1K : %i\n", fsz_100_1k);
- printf("files 1K-10K : %i\n", fsz_1k_10k);
- printf("files 10K-100K : %i\n", fsz_10k_100k);
- printf("files 100K-1M : %i\n", fsz_100k_1m);
- printf("files 1M-10M : %i\n", fsz_1m_10m);
- printf("files 10M-larger : %i\n", fsz_10m_larger);
- printf("total bytes written : %lu\n", byte_total);
-
-}
-
-/* predict the number of files that will be created before max_bytes total
- length of files is reached */
-long determine_nr_of_files(int median_file_size, double max_file_size,
- long bytes_to_consume)
-{
- long nr_of_files = 0, byte_total = 0;
-
- /* the next line is not necessary as 1 is the default, it is just cautious
- coding */
- srand(1);
- while (byte_total < bytes_to_consume) {
- byte_total += determine_size(median_file_size, max_file_size);
- nr_of_files++;
- }
- /* reset the random number generator so that when we determine_size() of the
- files later they will be created with the same "random" sequence used in
- this calculation */
- srand(1);
-#ifdef DEBUG
- printf("number of files is %d\n", (int)nr_of_files);
-#endif /* DEBUG */
- fflush(NULL);
- return nr_of_files;
-}
-
-/* fill the current working directory with nr_files_this_directory number of
- files*/
-
-void fill_this_directory(long nr_files_this_directory, long median_file_size,
- long maximum_size)
-{
- long size;
-
-#ifdef DEBUG
- printf("filling with %lu files, ", nr_files_this_directory);
-#endif
- while (nr_files_this_directory--) {
- size = determine_size(median_file_size, maximum_size);
- byte_total += size;
- make_file(size);
- }
-}
-
-/* this will unfortunately handle out of disk space by forever trying */
-/* What we should do in out of space situaltion ? I think we must skip this
- directory and continue files/dirs creation process. Error value (!= 0)
- indicates that we can't go to this directory. -zam */
-int make_directory(char *dirname)
-{
- static long this_directory_number = 0;
-
- strcpy(tdir, path);
- strcat(tdir, "/");
- strcat(tdir, dirname);
-
- if (mkdir(tdir, 0755) == -1) {
- if (errno == ENOSPC) {
- if (!already_whined) {
- printf("reiser-2021: out of disk space, ");
- already_whined = 1;
- }
- return errno;
- }
- /* it is sometimes useful to be able to run this program more than once
- inside the same directory, and that means skipping over filenames that
- already exist. Thus we ignore EEXIST, and pay attention to all else. */
- if (errno != EEXIST) {
- perror("mkdir");
- exit(errno);
- }
- }
- sprintf(dirname, "d%lu", this_directory_number++);
- strcpy(tdir, path);
- strcat(tdir, "/");
- strcat(tdir, dirname);
-
- return 0;
-}
-
-/* assumes we are already chdir'd into a directory that the subtree is rooted
- at. Fills the directory with files and subdirectories, cd's into those
- subdirectories, and recurses upon itself */
-
-void do_subtree(
- /* the start and end of the portion of the directory sizes
- array which corresponds to the sizes of the directories
- composing this subtree */
- /* sizes_end minus sizes_start is equal to the number of
- directories in this subtree */
- long *sizes_start, long *sizes_end,
- long median_file_size, long maximum_file_size,
- long median_dir_branching, long max_dir_branching)
-{
- long *p;
- long *sub_start;
- long *sub_end;
- int index_subdirectory_to_add_directory_to;
- long *dirs_in_subtrees;
- char *subtree_name;
- long *sizes_index = sizes_start;
- char subtree_name_array[128];
- long this_directory_branching;
- static long this_directorys_number;
-
- subtree_name = subtree_name_array;
- /* fill this directory with its number of files */
- fill_this_directory(*sizes_index, median_file_size, maximum_file_size);
- sizes_index++;
- /* ok, now randomly assign directories (and their number of files) among the
- subdirectories that will be created if at least one directory is assigned
- to it */
-
- /* this will cause the random number sequence to not match the one used in
- determine_nr_files() I need to accumulate my values in an array
- beforehand. I'll code that later. */
- /* worry about whether 0 or 1 is a problem value */
- this_directory_branching =
- determine_size(median_dir_branching, max_dir_branching) + 1;
-
- /* create an array holding the number of directories assigned to each
- potential subdirectory */
- dirs_in_subtrees = calloc(this_directory_branching, sizeof(long));
- while (sizes_index <= sizes_end) {
- index_subdirectory_to_add_directory_to =
- (rand() % this_directory_branching);
- (*
- (dirs_in_subtrees + index_subdirectory_to_add_directory_to))++;
- sizes_index++;
- }
- /* the +1 is for the fill_directory() we did above */
- sizes_index = sizes_start + 1;
-
- /* go through each potential subdirectory, and if at least one directory has
- been assigned to it, create it and recurse */
- for (p = dirs_in_subtrees;
- p < (dirs_in_subtrees + this_directory_branching); p++) {
- if (*p) {
- int nocd;
- sprintf(subtree_name, "d%lu", this_directorys_number++);
- nocd = make_directory(subtree_name);
- /* if make_dir.. may fails (in out of space situation), we continue
- creation process in same dir */
- if (!nocd)
- chngdir(subtree_name);
- sub_start = sizes_index;
- /* the minus one is because *p is the number of elements and arrays start at 0 */
- sub_end = (sizes_index + (*p - 1));
-
-#ifdef DEBUG
- /* comment this back in if the array logic has you going cross-eyed */
- /* printf ("sizes_start is %p, sizes_index is %p, sizes_index+p is %p, sizes_end is %p\n", sizes_start, sub_start, sub_end, sizes_end); */
-#endif
- do_subtree(sub_start, sub_end, median_file_size,
- maximum_file_size, median_dir_branching,
- max_dir_branching);
- if (!nocd)
- chngdir("..");
- }
- sizes_index += *p;
- }
-}
-
-/* We have already determined that nr_files can fit in bytes_to_consume space.
- Fill the sizes array with the number of files to be in each directory, and
- then call do_subtree to fill the tree with files and directories. */
-
-void make_fractal_tree(long median_file_size, long maximum_file_size,
- long median_dir_nr_files, long max_dir_nr_files,
- long median_dir_branching, long max_dir_branching,
- long nr_files)
-{
- long *sizes_start;
- long *sizes_end;
- long *sizes_index;
- long remaining_files = nr_files;
-
- /* collect together array of directory sizes for whole filesystem. This
- cannot easily be done recursively without distorting the directory sizes
- and making deeper directories smaller. Send me the code if you
- disagree.:-) */
- /* we almost certainly don't need this much space, but so what.... */
- sizes_index = sizes_start = malloc(nr_files * sizeof(long));
- for (; remaining_files > 0;) {
- *sizes_index =
- determine_size(median_dir_nr_files, max_dir_nr_files);
- // we alloc space for nr_files, so we should avoid
- // number of files in directory = 0 -grev.
- if (*sizes_index == 0)
- *sizes_index = 1;
- *sizes_index =
- (*sizes_index <
- remaining_files) ? *sizes_index : remaining_files;
-
-#ifdef DEBUG
- printf("*sizes_index == %lu, ", *sizes_index);
-#endif
- remaining_files -= *sizes_index;
- sizes_index++;
- }
- /* don't decrement below sizes_start if nr_files is 0 */
- sizes_end = (sizes_index-- > sizes_start) ? sizes_index : sizes_start;
-
- sizes_index = sizes_start;
- srand(1);
- do_subtree(sizes_start, sizes_end, median_file_size, maximum_file_size,
- median_dir_branching, max_dir_branching);
-
-}
-
-int main(int argc, char *argv[])
-{
- /* initialized from argv[] */
- long median_file_size,
- median_dir_branching,
- median_dir_nr_files,
- max_dir_nr_files, max_dir_branching, max_file_size;
- long nr_of_files = 0; /* files to be created */
-
- if (argc != 11) {
- print_usage();
- exit(1);
- }
-
- write_buffer_size = atoi(argv[8]);
- write_buffer = malloc(write_buffer_size);
- memset(write_buffer, 'a', write_buffer_size);
-
- /* the number of bytes that we desire this tree to consume. It will actually
- consume more, because the last file will overshoot by a random amount, and
- because the directories and metadata will consume space. */
- bytes_to_consume = atol(argv[1]);
- max_file_size = atol(argv[3]);
- median_file_size = atol(argv[2]);
- /* Figure out how many random files will fit into bytes_to_consume bytes. We
- depend on resetting rand() to get the same result later. */
- nr_of_files =
- determine_nr_of_files(median_file_size, max_file_size,
- bytes_to_consume);
-
- strcpy(path, argv[9]);
- mkdir(path, 0755);
- stats = atol(argv[10]);
- median_dir_branching = atol(argv[6]);
- max_dir_branching = atol(argv[7]);
- median_dir_nr_files = atol(argv[4]);
- max_dir_nr_files = atol(argv[5]);
- make_fractal_tree(median_file_size, max_file_size, median_dir_nr_files,
- max_dir_nr_files, median_dir_branching,
- max_dir_branching, nr_of_files);
- print_stats();
- if (stats)
- printf("\nreiser_fract_tree finished\n");
-
- return 0;
-}
diff --git a/testcases/kernel/fs/mongo/run_mongo b/testcases/kernel/fs/mongo/run_mongo
deleted file mode 100755
index e22e2b9a8..000000000
--- a/testcases/kernel/fs/mongo/run_mongo
+++ /dev/null
@@ -1,36 +0,0 @@
-#!/bin/bash
-#
-# Copyright 2000 by Hans Reiser, licensing governed by reiserfs/README
-#
-if [ $# -lt 2 ]
-then
- echo
- echo "Usage : run_mogo <device> <processes>"
- echo
- echo "Example :"
- echo "# run_mogo /dev/hdx1 2"
- echo
- exit
-fi
-
-DEVICE=$1
-NPROC=$2
-
-y="Yes"
-echo "WARNING : All data will be erased on device=$DEVICE "
-echo "Run ? (Yes | no)"
-read x
-
-if [ -z $x ]
-then
- exit
-fi
-
-if ! [ $x = $y ]
-then
- exit
-fi
-
-./mongo.pl reiserfs $DEVICE /testfs reiserfs $NPROC
-./mongo.pl ext2 $DEVICE /testfs ext2 $NPROC
-./mongo_compare ./results/ext2.tbl ./results/reiserfs.tbl ./results/html/ext2_vs_reiserfs
diff --git a/testcases/kernel/fs/mongo/summ.c b/testcases/kernel/fs/mongo/summ.c
deleted file mode 100644
index c5712a4e3..000000000
--- a/testcases/kernel/fs/mongo/summ.c
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * Copyright 2000 by Hans Reiser, licensing governed by reiserfs/README
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-char str[100];
-
-int main(int argc, char **argv)
-{
- char c, *p;
- int sum = 0, n = 0;
-
- p = str;
- while ((c = getchar()) != EOF) {
- if (c != '\n') {
- *p++ = c;
- } else {
- *p = '\0';
- n = atol(str);
- sum += n;
- printf("%i\n", sum);
- p = str;
- *p = '\0';
- }
- }
-}
diff --git a/testcases/kernel/fs/mongo/test.sh b/testcases/kernel/fs/mongo/test.sh
deleted file mode 100755
index 5ec4e3139..000000000
--- a/testcases/kernel/fs/mongo/test.sh
+++ /dev/null
@@ -1,109 +0,0 @@
-#!/bin/sh
-#To exectute this you need mongo filesystem utility.
-#Run this inside the mongo directory.
-#mongo utility can be found in www.namesys.com/benchmarks/mongo-xxx.tgz
-#Description-this script tests the mongo utility which actulally give the time ie cpu time
-#Real time etc on reiserfile system and jfs filesystem.
-#created by prakash.banu@wipro.com
-#
-# 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
-#
-
-LOG_DIR=$PWD
-TEST_DIR=testdir
-
-
- #should be root to execute this script .
- if [ $(id -ru) -ne 0 ]; then
- echo "This script must be run as root"
- exit
- fi
- #set the PATH variable if its not done .
-export PATH=$PATH:/sbin
-lsmod |grep reiserfs
-
- if [ $? -ne 0 ]; then
- echo "inserting reiserfs and its dependencies"
- fi
-modprobe reiserfs
- if [ $? -ne 0 ]; then
- echo "check wheather reiserfs is been compiled in the kernel"
- fi
-
-lsmod |grep loop
- if [ $? -ne 0 ]; then
- echo "inserting loopback device module"
- fi
-modprobe loop
- if [ $? -ne 0 ]; then
- echo "check wheather loopback device option is been compiled in the kernel"
- fi
-
- #run the mongo test on reiserfs file system type
-reiserfs()
-{
-cat > fs.sh <<EOF
-echo "performing mongo on reiserfs"
-dd if=/dev/zero of=reiserfs bs=8k count=10240 > /dev/null 2>&1
-losetup /dev/loop0 reiserfs
-mkdir -p $TEST_DIR
-./mongo.pl LOG=/tmp/logfile1 file_size=10000 bytes=100000 fstype=reiserfs dev=/dev/loop0 dir=$TEST_DIR RUN log=$LOG_DIR/reiserlog > /dev/null 2>&1
-
-echo "RESULTS LOGGED IN $LOG_DIR/reiserlog"
-export PATH=$PATH:/sbin
-losetup -d /dev/loop0
-
-EOF
-}
-
-
-#To run on jfs file system type
-JFS()
-{
-cat >> fs.sh <<EOF
-echo "performing mongo on jfs file system"
-mkdir -p $TEST_DIR
-dd if=/dev/zero of=jfs bs=8k count=10240 > /dev/null 2>&1
-losetup /dev/loop0 jfs
-./mongo.pl LOG=/tmp/logfile1 file_size=10000 bytes=100000 fstype=jfs dev=/dev/loop0 dir=$TEST_DIR RUN log=$LOG_DIR/jfslog
-
-echo "RESULTS LOGGED IN $LOG_DIR/jfslog"
-export PATH=$PATH:/sbin
-losetup -d /dev/loop0
-echo "rm -rf ./fs.sh" >> ./fs.sh 2>&1
-EOF
-}
-
-
-echo -ne "TEST ON REISERFS?[y/N]:"
-read ker
-
-case $ker in
-y|Y) reiserfs
-esac
-
-echo -ne "TEST ON JFS[y/N]: "
-read ker
-
-case $ker in
-y|Y) JFS
-esac
-
-echo "THIS MAY TAKE SOME MINUTES"
-sh fs.sh
-
-#performing cleanup
-#losetup -d /dev/loop0
-rm -rf $TEST_DIR
diff --git a/testcases/kernel/fs/quota_remount/quota_remount_test01.sh b/testcases/kernel/fs/quota_remount/quota_remount_test01.sh
index 25d9f8fcc..7e20b3608 100755
--- a/testcases/kernel/fs/quota_remount/quota_remount_test01.sh
+++ b/testcases/kernel/fs/quota_remount/quota_remount_test01.sh
@@ -67,7 +67,8 @@ do_test()
newblocks=$(get_blocks)
if [ $blocks -eq $newblocks ]; then
- tst_brk TFAIL "usage did not change after remount"
+ tst_res TFAIL "usage did not change after remount"
+ return
fi
tst_res TPASS "quota on remount passed"
diff --git a/testcases/kernel/fs/scsi/ltpfs/Ltpfs.h b/testcases/kernel/fs/scsi/ltpfs/Ltpfs.h
deleted file mode 100644
index 24a85c95c..000000000
--- a/testcases/kernel/fs/scsi/ltpfs/Ltpfs.h
+++ /dev/null
@@ -1,71 +0,0 @@
-
-#define FS_LTP_TEST_COMPONENT 0x00020999
-#define FS_LTP_TEST_CLASS "ltp_test"
-#define FS_LTP_TEST_HID "FS0999"
-#define FS_LTP_TEST_DRIVER_NAME "FS LTP Test Driver"
-#define FS_LTP_TEST_DEVICE_NAME "LTP Test"
-#define FS_LTP_TEST_FILE_STATE "state"
-#define FS_LTP_TEST_NOTIFY_STATUS 0x80
-#define FS_LTP_TEST_STATUS_OFFLINE 0x00
-#define FS_LTP_TEST_STATUS_ONLINE 0x01
-#define FS_LTP_TEST_STATUS_UNKNOWN 0xFF
-#define _COMPONENT FS_LTP_TEST_COMPONENT
-#define FS_TLP_TEST_MODULE_NAME ("fs_ltp_test")
-#define FS_NS_SYSTEM_BUS "_SB_"
-#define FS_BATTERY_FORMAT_BIF "NNNNNNNNNSSSS"
-#define FS_BATTERY_FORMAT_BST "NNNN"
-
-
-#define FS_TYPE_ANY 0x00
-#define FS_TYPE_INTEGER 0x01 /* Byte/Word/Dword/Zero/One/Ones */
-#define FS_TYPE_STRING 0x02
-#define FS_TYPE_BUFFER 0x03
-#define FS_TYPE_PACKAGE 0x04 /* byte_const, multiple data_term/Constant/super_name */
-#define FS_TYPE_FIELD_UNIT 0x05
-#define FS_TYPE_DEVICE 0x06 /* Name, multiple Node */
-#define FS_TYPE_EVENT 0x07
-#define FS_TYPE_METHOD 0x08 /* Name, byte_const, multiple Code */
-#define FS_TYPE_MUTEX 0x09
-#define FS_TYPE_REGION 0x0A
-#define FS_TYPE_POWER 0x0B /* Name,byte_const,word_const,multi Node */
-#define FS_TYPE_PROCESSOR 0x0C /* Name,byte_const,Dword_const,byte_const,multi nm_o */
-#define FS_TYPE_THERMAL 0x0D /* Name, multiple Node */
-#define FS_TYPE_BUFFER_FIELD 0x0E
-#define FS_TYPE_DDB_HANDLE 0x0F
-#define FS_TYPE_DEBUG_OBJECT 0x10
-
-#define FS_TYPE_EXTERNAL_MAX 0x10
-#define LTPMAJOR 256
-
-/* Use 'k' as magic number */
-#define LTPFS_IOC_MAGIC 'k'
-#define TOMINOR(x) ((x & 3) | ((x & 4) << 5))
-
-
-#define DEV_PATH "/dev"
-#define LTP_FS_DIR_NAME ""
-#define LTP_FS_DEV_NAME "LTPFS"
-#define LTP_FS_DEV_NODE_PATH DEV_PATH "/"
-#define LTP_FS_DEVICE_NAME DEV_PATH "/" LTP_FS_DEV_NAME
-#define MINOR_SHIFT_BITS 3
-#define MAX_PARTITIONS 8 /* partition 0 + 7 more possible due to 3 bit partition number field */
-#define MAX_NUM_DISKS 3 /* number of real devices */
-
-#define MPDEV_FLAG_CLEAR 0
-#define MPDEV_FLAG_SET 1
-
-typedef struct _ltpdev_cmd {
- u_int32_t cmd; // input - 0==recover, 1==fail
- u_int32_t status; // ouput - 0==success
-} ltpdev_cmd_t;
-
-typedef enum ltpdev_ioctl_cmds_s {
- /* version commands */
- LTP_AIO_IOCTL_NUMBER = 0x5500,
- LTP_BIO_IOCTL_NUMBER = 0x5501
-} ltpdev_ioctl_cmds_t;
-
-// define the ioctl cmds
-#define LTPAIODEV_CMD _IOR( LTPMAJOR, LTP_AIO_IOCTL_NUMBER, ltpdev_cmd_t **)
-#define LTPBIODEV_CMD _IOR( LTPMAJOR, LTP_BIO_IOCTL_NUMBER, ltpdev_cmd_t **)
-
diff --git a/testcases/kernel/fs/scsi/ltpfs/LtpfsCmds.c b/testcases/kernel/fs/scsi/ltpfs/LtpfsCmds.c
deleted file mode 100644
index 0b561702e..000000000
--- a/testcases/kernel/fs/scsi/ltpfs/LtpfsCmds.c
+++ /dev/null
@@ -1,315 +0,0 @@
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/types.h>
-#include <linux/fs.h>
-#include <linux/ioctl.h>
-#include <linux/pm.h>
-#include <linux/genhd.h>
-#include <linux/bio.h>
-#include <linux/mm.h>
-#include <linux/swap.h>
-#include <linux/bio.h>
-#include <linux/blk.h>
-#include <linux/slab.h>
-#include <linux/mempool.h>
-#include <linux/workqueue.h>
-#include <linux/namei.h>
-#include <linux/mount.h>
-#include <linux/quotaops.h>
-#include <linux/pagemap.h>
-#include <linux/dnotify.h>
-#include <linux/smp_lock.h>
-#include <linux/personality.h>
-#include <linux/security.h>
-#include <linux/buffer_head.h>
-#include <asm/namei.h>
-#include <asm/uaccess.h>
-
-#define ACC_MODE(x) ("\000\004\002\006"[(x)&O_ACCMODE])
-#define IS_POSIX(fl) (fl->fl_flags & FL_POSIX)
-#define TEST_MEM_SIZE 4096
-#define FALSE 0
-#include "Ltpfs.h"
-
-static int ltpdev_open(struct inode *inode, struct file *pfile);
-static int ltpdev_release(struct inode *inode, struct file *pfile);
-static int ltpdev_ioctl(struct inode *pinode, struct file *pfile,
- unsigned int cmd, unsigned long arg);
-static int do_buffer_c_tests(void);
-
-static struct block_device_operations blkops = {
-open: ltpdev_open,
-release:ltpdev_release,
-ioctl: ltpdev_ioctl,
-};
-
-int ltp_fs_major = LTPMAJOR;
-int test_iteration = 0;
-
-static char genhd_flags = 0;
-static struct gendisk *gd_ptr;
-static spinlock_t bdev_lock __cacheline_aligned_in_smp = SPIN_LOCK_UNLOCKED;
-
-MODULE_AUTHOR("Martin Ridgeway <mridge@us.ibm.com>");
-MODULE_DESCRIPTION(FS_LTP_TEST_DRIVER_NAME);
-MODULE_LICENSE("GPL");
-
-/*
- * Device operations for the virtual FS devices
- */
-
-static struct pm_dev *ltp_pm_dev = NULL;
-struct block_device *ltplookup_bdev(const char *path);
-int path_lookup(const char *name, unsigned int flags, struct nameidata *nd);
-//static int __emul_lookup_dentry(const char *name, struct nameidata *nd);
-void path_release(struct nameidata *nd);
-
-static int ltpdev_open(struct inode *pinode, struct file *pfile)
-{
- printk(KERN_ALERT "ltpdev_open \n");
- return 0;
-}
-
-static int ltpdev_release(struct inode *pinode, struct file *pfile)
-{
-
- printk(KERN_ALERT "ltpdev_release \n");
- return 0;
-}
-
-static int ltpdev_ioctl(struct inode *pinode, struct file *pfile,
- unsigned int cmd, unsigned long arg)
-{
-
- struct bio *my_bio = NULL;
- struct bio *my_bio_copy = NULL;
- request_queue_t *q = NULL;
- struct block_device *bdev = NULL;
- unsigned long uaddr;
-
- unsigned int bytes_done = 100;
-
- int error = 0;
- int rc = 0;
-
- /*****************************************************************************/
-
- printk(KERN_ALERT "ltpdev_ioctl fs tests\n");
-
- switch (cmd) {
-
- case LTPAIODEV_CMD:
- printk(KERN_ALERT "Running AIO FS tests \n");
- printk(KERN_ALERT "AIO FS tests complete\n");
- break;
-
- case LTPBIODEV_CMD:
-
- printk(KERN_ALERT "Running BIO FS tests \n");
-
- my_bio = bio_alloc(GFP_KERNEL, 0);
- if (!my_bio) {
- printk(KERN_ALERT
- "Error getting kernel slab memory !!\n");
- } else {
- printk(KERN_ALERT "kernel slab memory alloc OK\n");
- }
-
- bio_endio(my_bio, bytes_done, error);
-
- printk(KERN_ALERT "Return from bio_endio = %d \n", error);
-
- my_bio_copy = bio_clone(my_bio, GFP_ATOMIC);
-
- if (!my_bio_copy) {
- printk(KERN_ALERT
- "Error getting kernel bio clone !!\n");
- } else {
- printk(KERN_ALERT "kernel bio clone OK\n");
- }
-
- my_bio_copy = bio_clone(my_bio, GFP_NOIO);
-
- if (!my_bio_copy) {
- printk(KERN_ALERT
- "Error getting kernel bio clone !!\n");
- } else {
- printk(KERN_ALERT "kernel bio clone OK\n");
- }
-
-// q = bdev_get_queue(my_bio->bi_bdev);
-
-// rc = bio_phys_segments(q, my_bio);
-
-// rc = bio_hw_segments(q, my_bio);
-
- bdev = lookup_bdev(LTP_FS_DEVICE_NAME);
-
- printk(KERN_ALERT "return from bdev size %d\n",
- bdev->bd_block_size);
-
- printk(KERN_ALERT "Return from phys_segments = %d \n", rc);
-
-// Don't use this API, causes system to hang and corrupts FS
-// bio_put(my_bio);
-
- (char *)uaddr = kmalloc(TEST_MEM_SIZE, GFP_KERNEL);
-
- my_bio_copy = bio_map_user(bdev, uaddr, TEST_MEM_SIZE, FALSE);
-
- printk(KERN_ALERT "Return from bio_map_user %p\n", my_bio_copy);
-
- do_buffer_c_tests();
-
- printk(KERN_ALERT "BIO FS tests complete\n");
-
- break;
- }
-
- return 0;
-}
-
-static int ltp_pm_callback(struct pm_dev *dev, pm_request_t rqst, void *data)
-{
- return 0;
-}
-
-int init_module(void)
-{
- int result;
-
- printk(KERN_ALERT "ltpdev_init_module \n");
-
- ltp_pm_dev = pm_register(PM_UNKNOWN_DEV, 0, ltp_pm_callback);
-
- result = register_blkdev(ltp_fs_major, LTP_FS_DEV_NAME);
-
- printk(KERN_ALERT "LTP FS: register_blkdev result=%d major %d\n",
- result, ltp_fs_major);
-
- if (result < 0) {
- printk(KERN_ALERT "LTP FS: can't get major %d\n", ltp_fs_major);
- return result;
- }
-
- gd_ptr = kmalloc(sizeof(struct gendisk *), GFP_KERNEL);
-
- if (!gd_ptr) {
- printk(KERN_ALERT "ERROR getting memory !!!\n");
- return 0;
- }
-
- gd_ptr = alloc_disk(1);
-
- printk(KERN_ALERT "gd_ptr after alloc = %p \n", gd_ptr);
-
- gd_ptr->major = ltp_fs_major;
- gd_ptr->first_minor = 0;
- gd_ptr->fops = &blkops;
- gd_ptr->driverfs_dev = NULL;
- gd_ptr->capacity = MAX_NUM_DISKS;
- gd_ptr->flags = genhd_flags;
-
- sprintf(gd_ptr->disk_name, LTP_FS_DEV_NAME);
-
- add_disk(gd_ptr);
-
- return 0;
-}
-
-void cleanup_module(void)
-{
-
- printk(KERN_ALERT "Exiting module and cleaning up \n");
-
- pm_unregister(ltp_pm_dev);
-
- put_disk(gd_ptr);
-
- del_gendisk(gd_ptr);
-
- unregister_blkdev(ltp_fs_major, LTP_FS_DEV_NAME);
-
-}
-
-static int do_buffer_c_tests()
-{
- int line_no = 0;
-
- printk(KERN_ALERT "Starting buffer.c coverage tests... \n");
-
- __buffer_error("Test file", line_no);
-
- printk(KERN_ALERT "buffer.c coverage tests complete...\n");
-
- return 0;
-}
-
-/**
- * lookup_bdev - lookup a struct block_device by name
- *
- * @path: special file representing the block device
- *
- * Get a reference to the blockdevice at @path in the current
- * namespace if possible and return it. Return ERR_PTR(error)
- * otherwise.
- */
-struct block_device *lookup_bdev(const char *path)
-{
- struct block_device *bdev;
- struct inode *inode;
- struct nameidata nd;
- int error;
-
- if (!path || !*path)
- return ERR_PTR(-EINVAL);
-
- error = path_lookup(path, LOOKUP_FOLLOW, &nd);
- if (error)
- return ERR_PTR(error);
-
- inode = nd.dentry->d_inode;
- error = -ENOTBLK;
- if (!S_ISBLK(inode->i_mode))
- goto fail;
- error = -EACCES;
- if (nd.mnt->mnt_flags & MNT_NODEV)
- goto fail;
- error = bd_acquire(inode);
- if (error)
- goto fail;
- bdev = inode->i_bdev;
-
-out:
- path_release(&nd);
- return bdev;
-fail:
- bdev = ERR_PTR(error);
- goto out;
-}
-
-int bd_acquire(struct inode *inode)
-{
- struct block_device *bdev;
- spin_lock(&bdev_lock);
- if (inode->i_bdev) {
- atomic_inc(&inode->i_bdev->bd_count);
- spin_unlock(&bdev_lock);
- return 0;
- }
- spin_unlock(&bdev_lock);
- bdev = bdget(kdev_t_to_nr(inode->i_rdev));
- if (!bdev)
- return -ENOMEM;
- spin_lock(&bdev_lock);
- if (!inode->i_bdev) {
- inode->i_bdev = bdev;
- inode->i_mapping = bdev->bd_inode->i_mapping;
- list_add(&inode->i_devices, &bdev->bd_inodes);
- } else if (inode->i_bdev != bdev)
- BUG();
- spin_unlock(&bdev_lock);
- return 0;
-}
diff --git a/testcases/kernel/fs/scsi/ltpfs/Makefile b/testcases/kernel/fs/scsi/ltpfs/Makefile
deleted file mode 100644
index 5f4030661..000000000
--- a/testcases/kernel/fs/scsi/ltpfs/Makefile
+++ /dev/null
@@ -1,30 +0,0 @@
-#
-# Makefile for GCOV profiling kernel module
-#
-
-#KERNELDIR := ../linux-2.5.73
-CFLAGS := $(CFLAGS) -Wall -g
-
-ifneq ($(KERNELRELEASE),)
-
-obj-m := LtpfsCmds.o
-obj-p := ltpfstest
-else
-KDIR := /lib/modules/$(shell uname -r)/build
-PWD := $(shell pwd)
-
-default:
- $(MAKE) -C $(KDIR) M=$(PWD) modules
- ${CC} $(CFLAGS) -o ltpfstest -lm main.c
-# $(MAKE) -C $(KERNELDIR) M=$(PWD) modules
-endif
-
-clean:
- rm -f LtpfsCmds.o
- rm -f LtpfsCmds.ko
- rm -f LtpfsCmds.bb
- rm -f LtpfsCmds.bbg
- rm -f LtpfsCmds.mod.c
- rm -f LtpfsCmds.mod.o
- rm -f .*.mod*
- rm -f .*.cmd
diff --git a/testcases/kernel/fs/scsi/ltpfs/ltpfs.part1 b/testcases/kernel/fs/scsi/ltpfs/ltpfs.part1
deleted file mode 100644
index 65086d536..000000000
--- a/testcases/kernel/fs/scsi/ltpfs/ltpfs.part1
+++ /dev/null
@@ -1,4 +0,0 @@
-#DESCRIPTION:filesystem tests
-# Check the EXT2 & NFS filesystems
-bfs101 ltpfstest /test/growfiles/ext2
-bfs102 ltpfstest /test/growfiles/nfs
diff --git a/testcases/kernel/fs/scsi/ltpfs/ltpfs.part2 b/testcases/kernel/fs/scsi/ltpfs/ltpfs.part2
deleted file mode 100644
index 86514908e..000000000
--- a/testcases/kernel/fs/scsi/ltpfs/ltpfs.part2
+++ /dev/null
@@ -1,3 +0,0 @@
-#DESCRIPTION:filesystem tests
-# Check the XFS filesystems
-bfs201 ltpfstest /test/growfiles/xfs
diff --git a/testcases/kernel/fs/scsi/ltpfs/ltpfs.part3 b/testcases/kernel/fs/scsi/ltpfs/ltpfs.part3
deleted file mode 100644
index 4f2ee5f21..000000000
--- a/testcases/kernel/fs/scsi/ltpfs/ltpfs.part3
+++ /dev/null
@@ -1,3 +0,0 @@
-#DESCRIPTION:filesystem tests
-# Check the MSDOS filesystems
-bfs101 ltpfstest /test/growfiles/msdos
diff --git a/testcases/kernel/fs/scsi/ltpfs/ltpfs.part4 b/testcases/kernel/fs/scsi/ltpfs/ltpfs.part4
deleted file mode 100644
index 84519512c..000000000
--- a/testcases/kernel/fs/scsi/ltpfs/ltpfs.part4
+++ /dev/null
@@ -1,3 +0,0 @@
-#DESCRIPTION:filesystem tests
-# Check the Reiser filesystems
-bfs401 ltpfstest /test/growfiles/reiser
diff --git a/testcases/kernel/fs/scsi/ltpfs/ltpfs.part5 b/testcases/kernel/fs/scsi/ltpfs/ltpfs.part5
deleted file mode 100644
index c3fa4d7aa..000000000
--- a/testcases/kernel/fs/scsi/ltpfs/ltpfs.part5
+++ /dev/null
@@ -1,3 +0,0 @@
-#DESCRIPTION:filesystem tests
-# Check the Minix filesystems
-bfs501 ltpfstest /test/growfiles/minix
diff --git a/testcases/kernel/fs/scsi/ltpfs/ltpfs.part6 b/testcases/kernel/fs/scsi/ltpfs/ltpfs.part6
deleted file mode 100644
index 0d600fe8e..000000000
--- a/testcases/kernel/fs/scsi/ltpfs/ltpfs.part6
+++ /dev/null
@@ -1,3 +0,0 @@
-#DESCRIPTION:filesystem tests
-# Check the EXT3 filesystems
-bfs601 ltpfstest /test/growfiles/ext3
diff --git a/testcases/kernel/fs/scsi/ltpfs/ltpfs.part7 b/testcases/kernel/fs/scsi/ltpfs/ltpfs.part7
deleted file mode 100644
index c9904d6be..000000000
--- a/testcases/kernel/fs/scsi/ltpfs/ltpfs.part7
+++ /dev/null
@@ -1,3 +0,0 @@
-#DESCRIPTION:filesystem tests
-# Check the JFS filesystems
-bfs701 ltpfstest /test/growfiles/jfs
diff --git a/testcases/kernel/fs/scsi/ltpfs/ltpfsio.sh b/testcases/kernel/fs/scsi/ltpfs/ltpfsio.sh
deleted file mode 100755
index ed3d8e2ab..000000000
--- a/testcases/kernel/fs/scsi/ltpfs/ltpfsio.sh
+++ /dev/null
@@ -1,154 +0,0 @@
--#!/bin/sh
-# This script should be run prior to running executing the filesystem tests.
-# valid devices need to be passed for the test to work correctly
-# 10/06/03 mridge@us.ibm.com added instance and time command line options
-#
-#
-
-cd `dirname $0`
-export LTPROOT=${PWD}
-echo $LTPROOT | grep testscripts > /dev/null 2>&1
-if [ $? -eq 0 ]; then
- cd ..
- export LTPROOT=${PWD}
-fi
-
-export TMPBASE="/tmp"
-
-
-usage()
-{
- cat <<-END >&2
- usage: ${0##*/} [ -a part1 ] [ -n nfsmount ]
- defaults:
- part1=$part1
- nfsmount=$nfsmount
- ltproot=$TPROOT
- tmpdir=$TMPBASE
-
- example: ${0##*/} -a hdc1 -b hdc2 -c hdc3 -d hdc4 -n mytesthost:/testmountdir
-
- - This test will ONLY run on a 2.5.66 or higher kernel system.
-
- - These operations are destructive so do NOT point the tests to partitions where the data shouldn't be overwritten.
- Once these tests are started all data in the partitions you point to will be destroyed.
-
- END
-exit
-}
-
-while getopts :a:n:v: arg
-do case $arg in
- a) part1=$OPTARG;;
- n) nfsmount=$OPTARG;;
- v) verb=$OPTARG;;
-
- \?) echo "************** Help Info: ********************"
- usage;;
- esac
-done
-
-if [ ! -n "$part1" ]; then
- echo "Missing 1st partition. You must pass 4 partitions for testing"
- usage;
- exit
-fi
-
-if [ ! -n "$nfsmount" ]; then
- echo "Missing NFS partition. You must pass an NFS mount point for testing"
- usage;
- exit
-fi
-
-export PATH="${PATH}:${LTPROOT}/testcases/bin"
-
-
-mkdir /test >/dev/null 2>&1
-mkdir /test/growfiles >/dev/null 2>&1
-mkdir /test/growfiles/ext2 >/dev/null 2>&1
-mkdir /test/growfiles/msdos >/dev/null 2>&1
-mkdir /test/growfiles/reiser >/dev/null 2>&1
-mkdir /test/growfiles/minix >/dev/null 2>&1
-mkdir /test/growfiles/xfs >/dev/null 2>&1
-mkdir /test/growfiles/nfs >/dev/null 2>&1
-mkdir /test/growfiles/jfs >/dev/null 2>&1
-mkdir /test/growfiles/ext3 >/dev/null 2>&1
-
-
-mkfs -V -t ext2 /dev/$part1
-
-
-mount -v -t nfs $nfsmount /test/growfiles/nfs
-mount -v /dev/$part1 /test/growfiles/ext2
-
-
-echo "************ Running tests "
-sort -R ${LTPROOT}/runtest/ltpfs.part1 -o ${TMPBASE}/ltpfs.part1
-
-${LTPROOT}/pan/pan -e -S -a ltpfspart1 -n ltpfspart1 -l lvmlogfile -f ${TMPBASE}/ltpfs.part1 &
-
-wait $!
-
-umount -v -t nfs $nfsmount
-umount -v /dev/$part1
-mkfs.xfs -f /dev/$part1
-mount -v /dev/$part1 /test/growfiles/xfs
-
-
-sort -R ${LTPROOT}/runtest/ltpfs.part2 -o ${TMPBASE}/ltpfs.part2
-
-${LTPROOT}/pan/pan -e -S -a ltpfspart2 -n ltpfspart2 -l lvmlogfile -f ${TMPBASE}/ltpfs.part2 &
-
-wait $!
-
-mkfs -V -t msdos /dev/$part1
-umount -v /dev/$part1
-mount -v /dev/$part1 /test/growfiles/msdos
-
-sort -R ${LTPROOT}/runtest/ltpfs.part3 -o ${TMPBASE}/ltpfs.part3
-
-${LTPROOT}/pan/pan -e -S -a ltpfspart3 -n ltpfspart3 -l lvmlogfile -f ${TMPBASE}/ltpfs.part3 &
-
-wait $!
-
-umount -v /dev/$part1
-mkreiserfs /dev/$part1 <yesenter.txt
-mount -v /dev/$part1 /test/growfiles/reiser
-
-sort -R ${LTPROOT}/runtest/ltpfs.part4 -o ${TMPBASE}/ltpfs.part4
-
-${LTPROOT}/pan/pan -e -S -a ltpfspart4 -n ltpfspart4 -l lvmlogfile -f ${TMPBASE}/ltpfs.part4 &
-
-wait $!
-
-umount -v /dev/$part1
-mkfs -V -t minix /dev/$part1
-mount -v /dev/$part1 /test/growfiles/minix
-
-sort -R ${LTPROOT}/runtest/ltpfs.part5 -o ${TMPBASE}/ltpfs.part5
-
-${LTPROOT}/pan/pan -e -S -a ltpfspart5 -n ltpfspart5 -l lvmlogfile -f ${TMPBASE}/ltpfs.part5 &
-
-wait $!
-
-umount -v /dev/$part1
-mkfs -V -t ext3 /dev/$part1
-mount -v /dev/$part1 /test/growfiles/ext3
-
-sort -R ${LTPROOT}/runtest/ltpfs.part6 -o ${TMPBASE}/ltpfs.part6
-
-${LTPROOT}/pan/pan -e -S -a ltpfspart6 -n ltpfspart6 -l lvmlogfile -f ${TMPBASE}/ltpfs.part6 &
-
-wait $!
-
-umount -v /dev/$part1
-mkfs -V -t jfs /dev/$part1 <yesenter.txt
-mount -v -t jfs /dev/$part1 /test/growfiles/jfs
-
-sort -R ${LTPROOT}/runtest/ltpfs.part7 -o ${TMPBASE}/ltpfs.part7
-
-${LTPROOT}/pan/pan -e -S -a ltpfspart7 -n ltpfspart7 -l lvmlogfile -f ${TMPBASE}/ltpfs.part7 &
-
-wait $!
-
-
diff --git a/testcases/kernel/fs/scsi/ltpfs/main.c b/testcases/kernel/fs/scsi/ltpfs/main.c
deleted file mode 100644
index 90a5531ac..000000000
--- a/testcases/kernel/fs/scsi/ltpfs/main.c
+++ /dev/null
@@ -1,647 +0,0 @@
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <string.h>
-#include <ctype.h>
-#include <errno.h>
-#include <math.h>
-#include <time.h>
-#include <ftw.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <sys/ioctl.h>
-#include <linux/kd.h>
-#include <linux/errno.h>
-
-#include "Ltpfs.h"
-
-#define M_2PI (M_PI*2)
-#define MAXN 4096
-#define MAXFSIZE 1024 * 192
-#define FILE_CREATE_COUNT 256
-#define FAIL 0
-#define SUCCESS 1
-#define MAXNUM 5000
-#define BUFFSIZE 8192
-#define AVEFSIZE (MAXFSIZE/2)
-#define POOLDISKSPACE (AVEFSIZE*128)
-#define MAXERROR 1024
-#define FILES_ONLY 0x01
-#define ALL 0x00
-
-// Globals
-
-char wbuf[MAXFSIZE];
-int startc = 0;
-int showchar[] = { 124, 47, 45, 92, 124, 47, 45, 92 };
-
-int nullFileHandle;
-static int openlog[2] = { 0, 0 };
-
-int cFileCount, dFileCount, errorCount;
-static int disk_space_pool = 0;
-char rootPath[BUFFSIZE];
-
-int LTP_fs_open_block_device(void);
-int do_fs_thump_tests(char *path);
-int do_create_file_test(char *path);
-int makedir(char *dir1);
-int changedir(char *dir);
-int do_random_access_test(int maxNum);
-int do_random_create_delete(int maxNum);
-int create_file(char *filename);
-int delete_file(char *filename);
-int gen_random_file_size(int min, int max);
-int open_read_close(char *fname);
-int create_or_delete(char *fname);
-int do_tree_cleanup(char *path, int flag);
-int cleanup_files(char *file, struct stat *statBuff, int flag);
-int cleanup_dirs(char *file, struct stat *statBuff, int flag);
-
-int ltp_block_dev_handle = 0; /* handle to LTP Test block device */
-int ltp_fileHandle = 0;
-char *fileBuf;
-
-int main(int argc, char **argv)
-{
-
- ltpdev_cmd_t cmd = { 0, 0 };
- int rc, i, tmpHandle;
- struct stat statBuf;
-
- printf("[%s] - Running test program\n", argv[0]);
-
- rc = LTP_fs_open_block_device();
-
- if (!rc) {
-
- ltp_block_dev_handle = open(LTP_FS_DEVICE_NAME, O_RDWR);
-
- if (ltp_block_dev_handle < 0) {
- printf
- ("ERROR: Open of device %s failed %d errno = %d\n",
- LTP_FS_DEVICE_NAME, ltp_block_dev_handle, errno);
- } else {
- rc = ioctl(ltp_block_dev_handle, LTPAIODEV_CMD, &cmd);
-
- printf("return from AIO ioctl %d \n", rc);
-
- rc = ioctl(ltp_block_dev_handle, LTPBIODEV_CMD, &cmd);
-
- printf("return from BIO ioctl %d \n", rc);
- }
-
- } else {
- printf("ERROR: Create/open block device failed\n");
- }
-
- ltp_fileHandle =
- open("/tmp/testfile", O_CREAT | O_RDWR | O_SYNC | FASYNC,
- S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
-
- if (ltp_fileHandle > 0) {
-
- tmpHandle = open("/usr/include/ctype.h", O_RDONLY);
-
- if (tmpHandle > 0) {
-
- rc = fstat(tmpHandle, &statBuf);
-
- if (!rc) {
- fileBuf = malloc(statBuf.st_size);
-
- if (fileBuf) {
-
- read(tmpHandle, fileBuf,
- statBuf.st_size);
- close(tmpHandle);
- write(ltp_fileHandle, fileBuf,
- statBuf.st_size);
-
- for (i = 0; i < 100; i++) {
- read(ltp_fileHandle, fileBuf,
- statBuf.st_size * i);
- write(ltp_fileHandle, fileBuf,
- statBuf.st_size * i);
- }
- }
-
- }
-
- } else {
- printf("ERROR: Create/open file failed\n");
- }
- }
-
- printf("*** Starting FileSystem thump tests....****\n");
- printf("*** Please be patient, this may take a little while... ***\n");
-
- for (i = 1; i < argc; i++) {
- printf("Running test %d of %d on FileSystem %s \n", i, argc - 1,
- argv[i]);
- if (strcmp(argv[i], "|") != 0) {
- strcpy(rootPath, argv[i]);
- rc = do_fs_thump_tests(argv[i]);
- if (rc != 0 && rc != ENOSPC) {
- printf
- ("ERROR: Failed on FileSystem %s with errno %d \n",
- argv[i], rc);
- }
- } else {
- printf("Test Program complete..\n");
- break;
- }
-
- }
-
- printf("Test Program complete..\n");
-
- return 0;
-}
-
-int do_fs_thump_tests(char *path)
-{
- int rc = 0;
-
- printf("Changing to directory %s \n", path);
-
- changedir(path);
-
- cFileCount = 0;
- dFileCount = 0;
-
- rc |= do_create_file_test(path);
- rc |= do_random_access_test(MAXNUM);
- rc |= do_tree_cleanup(path, FILES_ONLY);
- rc |= do_random_create_delete(MAXNUM);
- rc |= do_tree_cleanup(path, ALL);
-
- return rc;
-
-}
-
-int do_tree_cleanup(char *path, int flag)
-{
-
- if (flag == FILES_ONLY) {
- printf("Cleaning up test files...\n");
- ftw(path, (void *)cleanup_files, MAXNUM);
- } else {
- printf("Cleaning up everything in the test directory...\n");
- ftw(path, (void *)cleanup_files, MAXNUM);
- ftw(path, (void *)cleanup_dirs, MAXNUM);
- }
-
- return 0;
-}
-
-int cleanup_files(char *file, struct stat *statBuff, int flag)
-{
- int rc = 0;
-
- if (flag == FTW_F) {
- if (unlink(file)) {
- printf("ERROR:%d removing file %s\n", errno, file);
- }
- }
-
- return rc;
-}
-
-int cleanup_dirs(char *file, struct stat *statBuff, int flag)
-{
- int rc = 0;
-
- //printf("%s:Cleaning up directory %s \n", __FUNCTION__, file);
-
- if (strcmp(rootPath, file) == 0) {
- return 0;
- }
-
- if (flag == FTW_F) {
- if (unlink(file)) {
- printf("ERROR:%d removing file %s\n", errno, file);
- }
- } else if (flag == FTW_D) {
- changedir(file);
- ftw(file, (void *)cleanup_dirs, MAXNUM);
- rmdir(file);
-
- } else {
- printf("No idea what we found here\n");
- }
-
- return rc;
-}
-
-int do_create_file_test(char *path)
-{
- int i = 0;
- int j = 0;
- int k = 0;
- int l = 0;
- int rc = 0;
-
- char dir1[MAXN];
- char dir2[MAXN];
- char dir3[MAXN];
- char filename[MAXN];
-
- time_t t;
-
- int maxfiles = 0xFFFFFF;
-
- time(&t);
-
- srandom((unsigned int)getpid() ^
- (((unsigned int)t << 16) | (unsigned int)t >> 16));
-
- printf("Creating files...\n");
-
- for (i = 0; i < FILE_CREATE_COUNT; i++) {
-
- sprintf(dir1, "%2.2x", i);
-
- makedir(dir1);
-
- changedir(dir1);
-
- for (j = 0; j < FILE_CREATE_COUNT; j++) {
-
- sprintf(dir2, "%2.2x", j);
-
- makedir(dir2);
-
- changedir(dir2);
-
- for (k = 0; k < FILE_CREATE_COUNT; k++) {
-
- sprintf(dir3, "%2.2x", k);
- makedir(dir3);
- changedir(dir3);
-
- for (l = 0; l < FILE_CREATE_COUNT; l++) {
- sprintf(filename, "%s%s%s%2.2x", dir1,
- dir2, dir3, l);
- rc = create_file(filename);
- if (rc != 0 || maxfiles < dFileCount++) {
- if (rc != ENOSPC) {
- printf
- ("ERROR: failed error:%d creating all the test files ! \n",
- errno);
- printf
- ("ERROR2: rc:%d -- dFileCount:%d \n",
- rc, dFileCount);
- }
- goto end;
- }
- }
- changedir("../");
- }
- changedir("../");
- }
- changedir("../");
- }
-end:
- fprintf(stderr, "\nTotal create files: %d\n", cFileCount);
- printf("Done\n");
- return rc;
-}
-
-int makedir(char *dir1)
-{
- if (mkdir(dir1, S_IRWXU) < 0) {
- perror(dir1);
- return (errno);
- }
- return 0;
-}
-
-int changedir(char *dir)
-{
- if (chdir(dir) < 0) {
- perror(dir);
- return (errno);
- }
-
- return 0;
-}
-
-int create_file(char *filename)
-{
- int fileHandle;
- int randomsize;
-
- if ((fileHandle = creat(filename, S_IRWXU)) < 0) {
-
- fprintf(stderr, "\nERROR line %d: Total create files: %d\n",
- __LINE__, cFileCount);
- perror(filename);
- return (errno);
- }
-
- if ((randomsize = gen_random_file_size(0, MAXFSIZE)) < 0) {
- randomsize = MAXFSIZE;
- }
- if (write(fileHandle, wbuf, randomsize) < 0) {
-
- fprintf(stderr, "\nERROR:%d line%d: Total create files: %d\n",
- errno, __LINE__, cFileCount);
- close(fileHandle);
-
- perror(filename);
- return (errno);
- }
-
- cFileCount++;
- close(fileHandle);
- return 0;
-}
-
-int delete_file(char *filename)
-{
- struct stat buf;
- int st;
-
- st = stat(filename, &buf);
-
- if (st < 0) {
- errorCount++;
- printf("ERROR line %d: Getting file stats %s \n", __LINE__,
- filename);
- return (-1);
- }
-
- disk_space_pool += buf.st_size;
-
- if (unlink(filename) < 0) {
- errorCount++;
- printf("ERROR line %d: Removing file %s \n", __LINE__,
- filename);
- return (-1);
- }
-
- dFileCount++;
- return 0;
-}
-
-int LTP_fs_open_block_device()
-{
- dev_t devt;
- struct stat statbuf;
- int rc = 0;
-
- if (ltp_block_dev_handle == 0) {
-
- /* check for the /dev/LTPFSTest subdir, and create if it does not exist.
- *
- * If devfs is running and mounted on /dev, these checks will all pass,
- * so a new node will not be created.
- */
- devt = makedev(LTPMAJOR, 0);
-
- rc = stat(LTP_FS_DEV_NODE_PATH, &statbuf);
-
- if (rc) {
- if (errno == ENOENT) {
- /* dev node does not exist. */
- rc = mkdir(LTP_FS_DEV_NODE_PATH,
- (S_IFDIR | S_IRWXU | S_IRGRP |
- S_IXGRP | S_IROTH | S_IXOTH));
- } else {
- printf
- ("ERROR: Problem with LTP FS dev directory. Error code from stat() is %d\n\n",
- errno);
- }
-
- } else {
- if (!(statbuf.st_mode & S_IFDIR)) {
- rc = unlink(LTP_FS_DEV_NODE_PATH);
- if (!rc) {
- rc = mkdir(LTP_FS_DEV_NODE_PATH,
- (S_IFDIR | S_IRWXU | S_IRGRP
- | S_IXGRP | S_IROTH |
- S_IXOTH));
- }
- }
- }
-
- /*
- * Check for the /dev/ltp-fs/block_device node, and create if it does not
- * exist.
- */
- rc = stat(LTP_FS_DEVICE_NAME, &statbuf);
- if (rc) {
- if (errno == ENOENT) {
- /* dev node does not exist */
- rc = mknod(LTP_FS_DEVICE_NAME,
- (S_IFBLK | S_IRUSR | S_IWUSR |
- S_IRGRP | S_IWGRP), devt);
- } else {
- printf
- ("ERROR:Problem with LTP FS block device node directory. Error code form stat() is %d\n\n",
- errno);
- }
-
- } else {
- /*
- * /dev/ltp-fs/block_device exists. Check to make sure it is for a
- * block device and that it has the right major and minor.
- */
- if ((!(statbuf.st_mode & S_IFBLK)) ||
- (statbuf.st_rdev != devt)) {
-
- /* Recreate the dev node. */
- rc = unlink(LTP_FS_DEVICE_NAME);
- if (!rc) {
- rc = mknod(LTP_FS_DEVICE_NAME,
- (S_IFBLK | S_IRUSR | S_IWUSR
- | S_IRGRP | S_IWGRP), devt);
- }
- }
- }
-
- }
-
- return rc;
-}
-
-int gen_random_file_size(int min, int max)
-{
- double u1, u2, z;
- int i;
- int ave;
- int range;
- int ZZ;
- if (min >= max) {
- return (-1);
- }
- range = max - min;
- ave = range / 2;
- for (i = 0; i < 10; i++) {
- u1 = ((double)(random() % 1000000)) / 1000000;
- u2 = ((double)(random() % 1000000)) / 1000000;
- z = sqrt(-2.0 * log(u1)) * cos(M_2PI * u2);
- ZZ = min + (ave + (z * (ave / 4)));
- if (ZZ >= min && ZZ < max) {
- return (ZZ);
- }
- }
- return (-1);
-}
-
-int do_random_access_test(int maxNum)
-{
- int r;
- char fname[1024];
- time_t t;
- int i;
-
- printf("Running random access test...\n");
- changedir(rootPath);
-
- if (maxNum < 1 || maxNum > MAXNUM) {
- printf("out of size %d\n", maxNum);
- return 1;
- }
-
- time(&t);
- srandom((unsigned int)getpid() ^
- (((unsigned int)t << 16) | (unsigned int)t >> 16));
-
- if ((nullFileHandle = open("/dev/null", O_WRONLY)) < 0) {
- perror("/dev/null");
- return (errno);
- }
-
- /* 00/00/00/00 */
- for (i = 0; i < maxNum; i++) {
-
- r = random() % maxNum;
-
- sprintf(fname, "00/%2.2x/%2.2x/00%2.2x%2.2x%2.2x",
- ((r >> 16) & 0xFF),
- ((r >> 8) & 0xFF),
- ((r >> 16) & 0xFF), ((r >> 8) & 0xFF), (r & 0xFF));
-
- open_read_close(fname);
- }
- close(nullFileHandle);
- printf("Success:\t%d\nFail:\t%d\n", openlog[SUCCESS], openlog[FAIL]);
- return 0;
-}
-
-int open_read_close(char *fname)
-{
- int fileHandle, fileHandle2;
- char buffer[BUFFSIZE];
- int c;
-
- if ((fileHandle = open(fname, O_RDONLY | O_SYNC | O_ASYNC)) < 0) {
- openlog[FAIL]++;
- printf("ERROR:opening file %s failed %d \n", fname, errno);
- return (errno);
- }
-
- if ((fileHandle2 = open(fname, O_RDONLY | O_SYNC | O_ASYNC)) < 0) {
- openlog[FAIL]++;
- printf("ERROR:2nd opening file %s failed %d \n", fname, errno);
- return (errno);
- }
-
- openlog[SUCCESS]++;
-
- while ((c = read(fileHandle, buffer, BUFFSIZE)) > 0) {
- if (write(nullFileHandle, buffer, c) < 0) {
- perror("/dev/null");
- printf("Opened\t %d\nUnopend:\t%d\n", openlog[SUCCESS],
- openlog[FAIL]);
- close(fileHandle2);
- close(fileHandle);
- return (errno);
- }
- if ((c = read(fileHandle2, buffer, BUFFSIZE)) > 0) {
- if (write(nullFileHandle, buffer, c) < 0) {
- perror("/dev/null");
- printf("Opened\t %d\nUnopend:\t%d\n",
- openlog[SUCCESS], openlog[FAIL]);
- close(fileHandle2);
- close(fileHandle);
- return (errno);
- }
- }
- }
-
- if (c < 0) {
- perror(fname);
- printf("Opened\t %d\nUnopend:\t%d\n", openlog[SUCCESS],
- openlog[FAIL]);
- return (errno);
- }
-
- close(fileHandle2);
- close(fileHandle);
- return 0;
-}
-
-int create_or_delete(char *fname)
-{
- int r, rc;
-
- r = (random() & 1);
-
- /* create */
- if ((create_file(fname) == 0)) {
- rc = delete_file(fname);
- } else {
- printf("Error: %d creating random file \n", errno);
- }
-
- if ((errorCount > dFileCount || errorCount > cFileCount)
- && (errorCount > MAXERROR)) {
- fprintf(stderr, "Too many errors -- Aborting test\n");
- fprintf(stderr, "Total create files: %d\n", cFileCount);
- fprintf(stderr, "Total delete files: %d\n", dFileCount);
- fprintf(stderr, "Total error : %d\n", errorCount);
- return (MAXERROR);
- }
-
- return 0;
-}
-
-int do_random_create_delete(int maxNum)
-{
- int r, rc = 0;
- char fname[1024];
- time_t t;
- int i;
-
- printf("Running random create/delete test...\n");
-
- if (maxNum < 1 || maxNum > MAXNUM) {
- printf("MAX out of size %d\n", maxNum);
- return (maxNum);
- }
-
- time(&t);
- srandom((unsigned int)getpid() ^
- (((unsigned int)t << 16) | (unsigned int)t >> 16));
-
- /* 00/00/00/00 */
- for (i = 0; i < maxNum && rc != MAXERROR; i++) {
- r = random() % maxNum;
- sprintf(fname, "00/%2.2x/%2.2x/00%2.2x%2.2x%2.2x",
- ((r >> 16) & 0xFF),
- ((r >> 8) & 0xFF),
- ((r >> 16) & 0xFF), ((r >> 8) & 0xFF), (r & 0xFF));
-
- rc = create_or_delete(fname);
- }
-
- fprintf(stderr, "Total create files: %d\n", cFileCount);
- fprintf(stderr, "Total delete files: %d\n", dFileCount);
- fprintf(stderr, "Total error : %d\n", errorCount);
- return (rc);
-}
diff --git a/testcases/kernel/fs/scsi/ltpscsi/Makefile b/testcases/kernel/fs/scsi/ltpscsi/Makefile
deleted file mode 100644
index e404ce074..000000000
--- a/testcases/kernel/fs/scsi/ltpscsi/Makefile
+++ /dev/null
@@ -1,47 +0,0 @@
-SHELL = /bin/sh
-
-EXECS = scsimain
-
-LARGE_FILE_FLAGS = -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64
-
-CFLAGS = -g -O2 -Wall -D_REENTRANT $(LARGE_FILE_FLAGS)
-# CFLAGS = -g -O2 -Wall -D_REENTRANT -DSG_KERNEL_INCLUDES $(LARGE_FILE_FLAGS)
-# CFLAGS = -g -O2 -Wall -pedantic -D_REENTRANT $(LARGE_FILE_FLAGS)
-
-LDFLAGS =
-
-all: $(EXECS)
-
-depend dep:
- @set -e; for i in *.c; do $(CC) $(INCLUDES) $(CFLAGS) -M $$i; \
- done > .depend
-
-clean:
- /bin/rm -f *.o $(EXECS) core .depend
-
-scsimain: scsimain.o sg_err.o llseek.o
- $(LD) -o $@ $(LDFLAGS) $^ -lpthread
-
-install: $(EXECS)
- install -d $(INSTDIR)
- @set -e; for name in $^; \
- do install -s -o root -g root -m 755 $$name $(INSTDIR); \
- done
- install -d $(MANDIR)/$(MAN_PREF)
- @set -e; for mp in $(MAN_PGS); \
- do install -o root -g root -m 644 $$mp $(MANDIR)/$(MAN_PREF); \
- gzip -9f $(MANDIR)/$(MAN_PREF)/$$mp; \
- done
-
-uninstall:
- dists="$(EXECS)"; \
- @set -e; for name in $$dists; do \
- rm -f $(INSTDIR)/$$name; \
- done
- @set -e; for mp in $(MAN_PGS); do \
- rm -f $(MANDIR)/$(MAN_PREF)/$$mp.gz; \
- done
-
-ifeq (.depend,$(wildcard .depend))
-include .depend
-endif
diff --git a/testcases/kernel/fs/scsi/ltpscsi/llseek.c b/testcases/kernel/fs/scsi/ltpscsi/llseek.c
deleted file mode 100644
index 25b77620c..000000000
--- a/testcases/kernel/fs/scsi/ltpscsi/llseek.c
+++ /dev/null
@@ -1,123 +0,0 @@
-/*
- * llseek.c -- stub calling the llseek system call
- *
- * Copyright (C) 1994 Remy Card. This file may be redistributed
- * under the terms of the GNU Public License.
- *
- * This file is borrowed from the util-linux-2.10q tarball's implementation
- * of fdisk. It allows seeks to 64 bit offsets, if supported.
- * Changed "ext2_" prefix to "llse".
- */
-
-#include <sys/types.h>
-
-#include <errno.h>
-#include <unistd.h>
-#include <sys/syscall.h>
-#include <linux/unistd.h> /* for __NR_llseek */
-
-#if defined(__GNUC__) || defined(HAS_LONG_LONG)
-typedef long long llse_loff_t;
-#else
-typedef long llse_loff_t;
-#endif
-
-extern llse_loff_t llse_llseek(unsigned int, llse_loff_t, unsigned int);
-
-#ifdef __linux__
-
-#if defined(__alpha__) || defined(__ia64__)
-
-#ifdef __NR_lseek
-static off_t my_lseek(int fd, off_t off, int whence)
-{
- return syscall(__NR_lseek, fd, off, whence);
-}
-#else /* undefined __NR_lseek */
-static off_t my_lseek(int fd, off_t off, int whence)
-{
- errno = ENOSYS;
- return -1;
-}
-#endif /* __NR_lseek */
-
-#define my_llseek my_lseek
-
-#else /* !__alpha__ && !__ia64__ */
-
-static int _llseek(unsigned int, unsigned long,
- unsigned long, llse_loff_t *, unsigned int);
-
-#ifndef __NR_llseek
-/* no __NR_llseek on compilation machine - might give it explicitly */
-static int _llseek(unsigned int fd, unsigned long oh,
- unsigned long ol, llse_loff_t * result, unsigned int origin)
-{
- errno = ENOSYS;
- return -1;
-}
-#else
-static int _llseek(unsigned int fd, unsigned long oh,
- unsigned long ol, llse_loff_t * result, unsigned int origin)
-{
- return syscall(__NR_llseek, fd, oh, ol, result, origin);
-}
-#endif
-
-static llse_loff_t my_llseek(unsigned int fd, llse_loff_t offset,
- unsigned int origin)
-{
- llse_loff_t result;
- int retval;
-
- retval = _llseek(fd, ((unsigned long long)offset) >> 32,
- ((unsigned long long)offset) & 0xffffffff,
- &result, origin);
- return (retval == -1 ? (llse_loff_t) retval : result);
-}
-
-#endif /* __alpha__ */
-
-llse_loff_t llse_llseek(unsigned int fd, llse_loff_t offset,
- unsigned int origin)
-{
- llse_loff_t result;
- static int do_compat = 0;
-
- if (!do_compat) {
- result = my_llseek(fd, offset, origin);
- if (!(result == -1 && errno == ENOSYS))
- return result;
-
- /*
- * Just in case this code runs on top of an old kernel
- * which does not support the llseek system call
- */
- do_compat = 1;
- /*
- * Now try ordinary lseek.
- */
- }
-
- if ((sizeof(off_t) >= sizeof(llse_loff_t)) ||
- (offset < ((llse_loff_t) 1 << ((sizeof(off_t) * 8) - 1))))
- return lseek(fd, (off_t) offset, origin);
-
- errno = EINVAL;
- return -1;
-}
-
-#else /* !linux */
-
-llse_loff_t llse_llseek(unsigned int fd, llse_loff_t offset,
- unsigned int origin)
-{
- if ((sizeof(off_t) < sizeof(llse_loff_t)) &&
- (offset >= ((llse_loff_t) 1 << ((sizeof(off_t) * 8) - 1)))) {
- errno = EINVAL;
- return -1;
- }
- return lseek(fd, (off_t) offset, origin);
-}
-
-#endif /* linux */
diff --git a/testcases/kernel/fs/scsi/ltpscsi/llseek.h b/testcases/kernel/fs/scsi/ltpscsi/llseek.h
deleted file mode 100644
index cdf6fceae..000000000
--- a/testcases/kernel/fs/scsi/ltpscsi/llseek.h
+++ /dev/null
@@ -1,10 +0,0 @@
-
-#if defined(__GNUC__) || defined(HAS_LONG_LONG)
-typedef long long llse_loff_t;
-#else
-typedef long llse_loff_t;
-#endif
-
-extern llse_loff_t llse_llseek(unsigned int fd,
- llse_loff_t offset,
- unsigned int origin);
diff --git a/testcases/kernel/fs/scsi/ltpscsi/ltpfsscsi.sh b/testcases/kernel/fs/scsi/ltpscsi/ltpfsscsi.sh
deleted file mode 100755
index 29648d9e7..000000000
--- a/testcases/kernel/fs/scsi/ltpscsi/ltpfsscsi.sh
+++ /dev/null
@@ -1,111 +0,0 @@
-#!/bin/sh
-# This script should be run to execute the filesystem tests on SCSI vitual devices.
-# 10/21/03 mridge@us.ibm.com Initial creation of testcases
-#
-#
-
-cd `dirname $0`
-export LTPROOT=${PWD}
-echo $LTPROOT | grep testscripts > /dev/null 2>&1
-if [ $? -eq 0 ]; then
- cd ..
- export LTPROOT=${PWD}
-fi
-
-export TMPBASE="/tmp"
-
-
-usage()
-{
- cat <<-END >&2
- usage: ${0##*/} [ -a part1 ] [ -b part2 ] [ -k Kernel Path - fully qualified kernel path ]
- defaults:
-
- There are no defaults, all items MUST be passed
-
- example: ${0##*/} -a sda -b sdb -k /usr/src/linux
-
- - These tests must be run after ssi_debug has been configured and built as a module so it can be loaded with
- the correct parameters.
-
- - These operations are destructive so do NOT point the tests to partitions where the data shouldn't be overwritten.
- Once these tests are started all data in the partitions you point to will be destroyed.
-
- END
-exit
-}
-
-while getopts :a:b:c:k: arg
-do case $arg in
- a) part1=$OPTARG;;
- b) part2=$OPTARG;;
- c) part3=$OPTARG;;
- k) kernpath=$OPTARG;;
-
- \?) echo "************** Help Info: ********************"
- usage;;
- esac
-done
-
-if [ ! -n "$part1" ]; then
- echo "Missing 1st partition. You must pass 2 partitions for testing"
- usage;
- exit
-fi
-
-if [ ! -n "$part2" ]; then
- echo "Missing 2nd partition. You must pass 2 partitions for testing"
- usage;
- exit
-fi
-
-if [ ! -n "$part3" ]; then
- echo "Missing 3rd partition. You must pass 3 partitions for testing"
- usage;
- exit
-fi
-
-if [ ! -n "$kernpath" ]; then
- echo "Missing kernel path. You must pass kernel path for testing"
- usage;
- exit
-fi
-
-export PATH="${PATH}:${LTPROOT}/testcases/bin"
-
-
-mkdir /test >/dev/null 2>&1
-mkdir /test/growfiles >/dev/null 2>&1
-mkdir /test/growfiles/scsi >/dev/null 2>&1
-mkdir /test/growfiles/scsi/ext2 >/dev/null 2>&1
-mkdir /test/growfiles/scsi/ext3 >/dev/null 2>&1
-mkdir /test/growfiles/scsi/reiser >/dev/null 2>&1
-
-
-mkfs -V -t ext2 /dev/$part1 <yesenter.txt
-mkfs -V -t ext3 /dev/$part2 <yesenter.txt
-mkreiserfs -f /dev/$part3 <yesenter.txt
-
-
-mount -v -t ext2 /dev/$part1 /test/growfiles/scsi/ext2
-mount -v -t ext3 /dev/$part2 /test/growfiles/scsi/ext3
-mount -v /dev/$part3 /test/growfiles/scsi/reiser
-
-cd $kernpath/drivers/scsi
-modprobe scsi_debug max_luns=2 num_tgts=7 add_host=10
-cd ${LTPROOT}
-
-echo "************ Running tests "
-sort -R ${LTPROOT}/runtest/scsi.part1 -o ${TMPBASE}/scsi.part1
-
-${LTPROOT}/pan/pan -e -S -a scsipart1 -n scsipart1 -l scsilogfile -f ${TMPBASE}/scsi.part1 &
-
-wait $!
-
-umount -v /dev/$part1
-umount -v /dev/$part2
-umount -v /dev/$part3
-rmmod scsi_debug
-
-
-
diff --git a/testcases/kernel/fs/scsi/ltpscsi/scsimain.c b/testcases/kernel/fs/scsi/ltpscsi/scsimain.c
deleted file mode 100644
index ce23ae1e7..000000000
--- a/testcases/kernel/fs/scsi/ltpscsi/scsimain.c
+++ /dev/null
@@ -1,7651 +0,0 @@
-/* Test code for D. Gilbert's extensions to the Linux OS SCSI generic ("sg")
- device driver.
-* Copyright (C) 1999 - 2002 D. Gilbert
-* 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, or (at your option)
-* any later version.
-
- This program scans the "sg" device space (ie actual + simulated SCSI
- generic devices).
- Options: -w open writable (new driver opens readable unless -i)
- -n numeric scan: scan /dev/sg0,1,2, ....
- -a alpha scan: scan /dev/sga,b,c, ....
- -i do SCSI inquiry on device (implies -w)
- -x extra information output
-
- By default this program will look for /dev/sg0 first (i.e. numeric scan)
-
- Note: This program is written to work under both the original and
- the new sg driver.
-
- Version 1.00 20031022
-
- F. Jansen - modification to extend beyond 26 sg devices.
- M. Ridgeway - Roll code together for SCSI testing with one command line
-
-6 byte INQUIRY command:
-[0x12][ |lu][pg cde][res ][al len][cntrl ]
-*/
-
-#define _GNU_SOURCE
-#include <unistd.h>
-#include <fcntl.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <errno.h>
-#include <dirent.h>
-#include <limits.h>
-#include <time.h>
-#include <sys/ioctl.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <signal.h>
-#include <ctype.h>
-#include <pthread.h>
-#include <sys/sysmacros.h>
-#include <sys/time.h>
-#include <sys/mman.h>
-#include <linux/major.h>
-#include "sg_include.h"
-#include "sg_err.h"
-#include "llseek.h"
-
-#define ME "scsimain: "
-
-#define NUMERIC_SCAN_DEF 1 /* change to 0 to make alpha scan default */
-//static char * version_str = "0.21 20030513";
-
-#define BPI (signed)(sizeof(int))
-#define READWRITE_BASE_NUM 0x12345678
-#define DEF_BLOCK_SIZE 512
-#define DEF_NUM_THREADS 16
-#define MAX_NUM_THREADS SG_MAX_QUEUE
-#define DEF_BLOCKS_PER_TRANSFER 128
-#define DEF_SCSI_CDBSZ 10
-#define MAX_SCSI_CDBSZ 16
-#define TUR_CMD_LEN 6
-#define DEVNAME_SZ 256
-#define MAX_HOLES 4
-
-#define OFF sizeof(struct sg_header)
-#define INQ_REPLY_LEN 96 /* logic assumes >= sizeof(inqCmdBlk) */
-#define INQUIRY_CMDLEN 6
-#define INQUIRY_CMD 0x12
-#define SENSE_BUFF_LEN 32 /* Arbitrary, could be larger */
-#define DEF_TIMEOUT 60000 /* 60,000 millisecs == 60 seconds */
-#define REASON_SZ 128
-
-#define SENSE_BUFF_SZ 64
-#define RCAP_REPLY_LEN 8
-#define LOG_SENSE_CMD 0x4d
-#define LOG_SENSE_CMDLEN 10
-#define MX_ALLOC_LEN (1024 * 17)
-#define D_ROOT_SZ 512
-#define STR_SZ 1024
-#define INOUTF_SZ 512
-#define EBUFF_SZ 512
-#define MDEV_NAME_SZ 256
-
-#define PG_CODE_ALL 0x00
-
-#define TRUE 1
-#define FALSE 0
-#define MAX_DEVICES 50
-
-#define NAME_LEN_MAX 256
-#define LEVELS 4
-
-#define SENSE_BUFF_LEN 32 /* Arbitrary, could be larger */
-#define INQ_ALLOC_LEN 255
-
-#ifndef SCSI_IOCTL_GET_PCI
-#define SCSI_IOCTL_GET_PCI 0x5387
-#endif
-
-#define READ_CAP_REPLY_LEN 8
-
-#ifndef RAW_MAJOR
-#define RAW_MAJOR 255 /*unlikey value */
-#endif
-
-#define FT_OTHER 1 /* filetype is probably normal */
-#define FT_SG 2 /* filetype is sg char device or supports
- SG_IO ioctl */
-#define FT_RAW 4 /* filetype is raw char device */
-#define FT_DEV_NULL 8 /* either "/dev/null" or "." as filename */
-#define FT_ST 16 /* filetype is st char device (tape) */
-#define FT_BLOCK 32 /* filetype is block device */
-
-#define DEV_NULL_MINOR_NUM 3
-
-#ifdef SG_GET_RESERVED_SIZE
-#define OPEN_FLAG O_RDONLY
-#else
-#define OPEN_FLAG O_RDWR
-#endif
-
-#ifndef SG_MAX_SENSE
-#define SG_MAX_SENSE 16
-#endif
-
-#define TEST_START 0
-#define TEST_BREAK 1
-#define TEST_STOP 2
-#define MAX_SG_DEVS 128
-#define MAX_SD_DEVS 128
-#define MAX_SR_DEVS 128
-#define MAX_ST_DEVS 128
-#define MAX_OSST_DEVS 128
-#define MAX_ERRORS 5
-
-#define LIN_DEV_TYPE_UNKNOWN 0
-#define LIN_DEV_TYPE_SD 1
-#define LIN_DEV_TYPE_SR 2
-#define LIN_DEV_TYPE_ST 3
-#define LIN_DEV_TYPE_SCD 4
-#define LIN_DEV_TYPE_OSST 5
-
-#define MODE_SENSE6_CMD 0x1a
-#define MODE_SENSE6_CMDLEN 6
-#define MODE_SENSE10_CMD 0x5a
-#define MODE_SENSE10_CMDLEN 10
-#define INQUIRY_CMD 0x12
-#define INQUIRY_CMDLEN 6
-#define MODE_ALLOC_LEN (1024 * 4)
-
-#define MODE_CODE_ALL 0x3f
-
-#define RB_MODE_DESC 3
-#define RB_MODE_DATA 2
-#define RB_DESC_LEN 4
-#define RB_MB_TO_READ 200
-#define RB_OPCODE 0x3C
-#define RB_CMD_LEN 10
-
-/* #define SG_DEBUG */
-
-#ifndef SG_FLAG_MMAP_IO
-#define SG_FLAG_MMAP_IO 4
-#endif
-#ifndef SG_SCSI_RESET
-#define SG_SCSI_RESET 0x2284
-#endif
-
-#ifndef SG_SCSI_RESET_NOTHING
-#define SG_SCSI_RESET_NOTHING 0
-#define SG_SCSI_RESET_DEVICE 1
-#define SG_SCSI_RESET_BUS 2
-#define SG_SCSI_RESET_HOST 3
-#endif
-#define LONG_TIMEOUT 2400000 /* 2,400,000 millisecs == 40 minutes */
-
-#define SEND_DIAGNOSTIC_CMD 0x1d
-#define SEND_DIAGNOSTIC_CMDLEN 6
-#define RECEIVE_DIAGNOSTIC_CMD 0x1c
-#define RECEIVE_DIAGNOSTIC_CMDLEN 6
-
-#define START_STOP 0x1b
-#define SYNCHRONIZE_CACHE 0x35
-
-#define DEF_START_TIMEOUT 120000 /* 120,000 millisecs == 2 minutes */
-
-#define DEVICE_RESET 0
-#define HOST_RESET 1
-#define BUS_RESET 2
-#define SG_HSZ sizeof(struct sg_header)
-#define OFFSET_HEADER (SG_HSZ - (2 * sizeof(int)))
-#define SIZEOF_BUFFER (256*1024)
-#define SIZEOF_BUFFER1 (16*1024)
-#define MAXPARM 32
-
-#define SETUP_MODE_PAGE(NPAGE, NPARAM) \
- status = get_mode_page(NPAGE, page_code); \
- if (status) { printf("\n"); return status; } \
- bdlen = buffer[11]; \
- pagestart = buffer + 12 + bdlen;
-
-typedef struct request_collection { /* one instance visible to all threads */
- int infd;
- int skip;
- int in_type;
- int in_scsi_type;
- int in_blk; /* -\ next block address to read */
- int in_count; /* | blocks remaining for next read */
- int in_done_count; /* | count of completed in blocks */
- int in_partial; /* | */
- int in_stop; /* | */
- pthread_mutex_t in_mutex; /* -/ */
- int outfd;
- int seek;
- int out_type;
- int out_scsi_type;
- int out_blk; /* -\ next block address to write */
- int out_count; /* | blocks remaining for next write */
- int out_done_count; /* | count of completed out blocks */
- int out_partial; /* | */
- int out_stop; /* | */
- pthread_mutex_t out_mutex; /* | */
- pthread_cond_t out_sync_cv; /* -/ hold writes until "in order" */
- int bs;
- int bpt;
- int fua_mode;
- int dio;
- int dio_incomplete; /* -\ */
- int sum_of_resids; /* | */
- pthread_mutex_t aux_mutex; /* -/ (also serializes some printf()s */
- int coe;
- int cdbsz;
- int debug;
-} Rq_coll;
-
-typedef struct request_element { /* one instance per worker thread */
- int infd;
- int outfd;
- int wr;
- int blk;
- int num_blks;
- unsigned char *buffp;
- unsigned char *alloc_bp;
- sg_io_hdr_t io_hdr;
- unsigned char cmd[MAX_SCSI_CDBSZ];
- unsigned char sb[SENSE_BUFF_LEN];
- int bs;
- int fua_mode;
- int dio;
- int dio_incomplete;
- int resid;
- int in_scsi_type;
- int out_scsi_type;
- int cdbsz;
- int debug;
-} Rq_elem;
-
-typedef struct my_map_info {
- int active;
- int lin_dev_type;
- int oth_dev_num;
- struct sg_scsi_id sg_dat;
- char vendor[8];
- char product[16];
- char revision[4];
-} my_map_info_t;
-
-typedef struct sg_map {
- int bus;
- int channel;
- int target_id;
- int lun;
- char *dev_name;
-} Sg_map;
-
-typedef struct my_scsi_idlun {
-/* why can't userland see this structure ??? */
- int dev_id;
- int host_unique_id;
-} My_scsi_idlun;
-
-struct page_code_desc {
- int page_code;
- const char *desc;
-};
-
-static const char *pg_control_str_arr[] = {
- "current",
- "changeable",
- "default",
- "saved"
-};
-
-char *devices[] =
- { "/dev/sda", "/dev/sdb", "/dev/sdc", "/dev/sdd", "/dev/sde", "/dev/sdf",
- "/dev/sdg", "/dev/sdh", "/dev/sdi", "/dev/sdj", "/dev/sdk", "/dev/sdl",
- "/dev/sdm", "/dev/sdn", "/dev/sdo", "/dev/sdp", "/dev/sdq", "/dev/sdr",
- "/dev/sds", "/dev/sdt", "/dev/sdu", "/dev/sdv", "/dev/sdw", "/dev/sdx",
- "/dev/sdy", "/dev/sdz", "/dev/sdaa", "/dev/sdab", "/dev/sdac",
- "/dev/sdad",
- "/dev/scd0", "/dev/scd1", "/dev/scd2", "/dev/scd3", "/dev/scd4",
- "/dev/scd5",
- "/dev/scd6", "/dev/scd7", "/dev/scd8", "/dev/scd9", "/dev/scd10",
- "/dev/scd11",
- "/dev/sr0", "/dev/sr1", "/dev/sr2", "/dev/sr3", "/dev/sr4", "/dev/sr5",
- "/dev/sr6", "/dev/sr7", "/dev/sr8", "/dev/sr9", "/dev/sr10",
- "/dev/sr11",
- "/dev/nst0", "/dev/nst1", "/dev/nst2", "/dev/nst3", "/dev/nst4",
- "/dev/nst5",
- "/dev/nosst0", "/dev/nosst1", "/dev/nosst2", "/dev/nosst3",
- "/dev/nosst4"
-};
-
-static char *page_names[] = {
- NULL,
- "Read-Write Error Recovery",
- "Disconnect-Reconnect",
- "Format Device",
- "Rigid Disk Geometry",
- /* "Flexible Disk" */ NULL,
- NULL,
- "Verify Error Recovery",
- "Caching",
- "Peripheral Device",
- "Control Mode",
- /* "Medium Types Supported" */ NULL,
- "Notch and Partition",
- /* "CD-ROM" */ NULL,
- /* "CD-ROM Audio Control" */ NULL,
- NULL,
- /* "Medium Partition (1)" */ NULL,
- /* "Medium Partition (2)" */ NULL,
- /* "Medium Partition (3)" */ NULL,
- /* "Medium Partition (4)" */ NULL
-};
-
-#define MAX_PAGENO (sizeof(page_names)/sizeof(char *))
-
-/* Following 2 macros from D.R. Butenhof's POSIX threads book:
- ISBN 0-201-63392-2 . [Highly recommended book.] */
-#define err_exit(code,text) do { \
- fprintf(stderr, "%s at \"%s\":%d: %s\n", \
- text, __FILE__, __LINE__, strerror(code)); \
- exit(1); \
- } while (0)
-
-static Sg_map sg_map_arr[(sizeof(devices) / sizeof(char *)) + 1];
-
-static const unsigned char scsi_command_size[8] = { 6, 10, 10, 12,
- 12, 12, 10, 10
-};
-const unsigned char rbCmdBlk[10] = { READ_BUFFER, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
-static const char *level_arr[LEVELS] = { "host", "bus", "target", "lun" };
-
-static const char *proc_allow_dio = "/proc/scsi/sg/allow_dio";
-static const char *devfs_id = "/dev/.devfsd";
-static my_map_info_t map_arr[MAX_SG_DEVS];
-static char ebuff[EBUFF_SZ];
-static int glob_fd;
-static char defectformat = 0x4;
-static sigset_t signal_set;
-static pthread_t sig_listen_thread_id;
-
-static int do_ide = 0;
-static int do_inq = 1;
-static int do_leaf = 1;
-static int do_extra = 1;
-static int do_quiet = 0;
-static int checked_sg = 1;
-static int sum_of_resids = 0;
-
-static int dd_count = -1;
-static int in_full = 0;
-static int in_partial = 0;
-static int out_full = 0;
-static int out_partial = 0;
-static int do_coe = 0;
-int base = READWRITE_BASE_NUM;
-unsigned char *cmpbuf = 0;
-static unsigned char buff_a[SIZEOF_BUFFER + SG_HSZ + 12];
-static unsigned char *buffer = buff_a + OFFSET_HEADER;
-
-typedef struct my_sg_scsi_id {
- int host_no; /* as in "scsi<n>" where 'n' is one of 0, 1, 2 etc */
- int channel;
- int scsi_id; /* scsi id of target device */
- int lun;
- int scsi_type; /* TYPE_... defined in scsi/scsi.h */
- short h_cmd_per_lun; /* host (adapter) maximum commands per lun */
- short d_queue_depth; /* device (or adapter) maximum queue length */
- int unused1; /* probably find a good use, set 0 for now */
- int unused2; /* ditto */
-} My_sg_scsi_id;
-
-// Prototypes
-int do_scsi_sgp_read_write(char *device);
-int do_scsi_sgm_read_write(char *device);
-void sg_in_operation(Rq_coll * clp, Rq_elem * rep);
-void sg_out_operation(Rq_coll * clp, Rq_elem * rep);
-int normal_in_operation(Rq_coll * clp, Rq_elem * rep, int blocks);
-void normal_out_operation(Rq_coll * clp, Rq_elem * rep, int blocks);
-int sg_start_io(Rq_elem * rep);
-int sg_finish_io(int wr, Rq_elem * rep, pthread_mutex_t * a_mutp);
-int run_sg_scan_tests(void);
-int show_scsi_logs(char *device);
-int validate_device(char *device);
-int show_devfs_devices(void);
-void usage(void);
-int do_scsi_device_read_write(char *device);
-int do_scsi_inquiry(char *device, int hex_flag);
-int show_scsi_maps(void);
-int show_scsi_modes(char *device);
-int do_scsi_read_buffer(char *device);
-int show_scsi_read_capacity(char *device);
-int do_scsi_reset_devices(char *device, int reset_opts);
-int do_scsi_send_diagnostics(char *device);
-int do_scsi_start_stop(char *device, int startstop);
-int do_scsi_read_write_buffer(char *device);
-int do_scsi_test_unit_ready(char *device);
-int show_scsi_info(char *device);
-void print_msg(int msg_num, const char *msg);
-static void scan_dev_type(const char *leadin, int max_dev, int do_numeric,
- int lin_dev_type, int last_sg_ind);
-
-#ifdef SG_IO
-int sg3_inq(int sg_fd, unsigned char *inqBuff, int do_extra);
-#endif
-
-static unsigned char inqCmdBlk[INQUIRY_CMDLEN] =
- { 0x12, 0, 0, 0, INQ_REPLY_LEN, 0 };
-
-void print_msg(int msg_num, const char *msg)
-{
- switch (msg_num) {
- case TEST_START:
- printf
- ("\n****************** Starting Tests ***************************\n");
- break;
- case TEST_STOP:
- printf
- ("\n****************** Tests Complete ***************************\n");
- break;
- case TEST_BREAK:
- printf("\n------------------ %s Test ------------------\n\n",
- msg);
- break;
- }
-}
-
-int main(int argc, char *argv[])
-{
- int rc = 0;
-
- if (argc < 2) {
- printf("\n\nERROR:No device passed to test\n\n");
- usage();
- return 1;
- }
-
- rc = validate_device(argv[1]);
- if (rc == 0) {
-
- print_msg(TEST_START, NULL);
-
- rc = run_sg_scan_tests();
- if (rc != 0) {
- printf("ERROR: run_sg_scan_tests failed %d\n", rc);
- }
-
- rc = show_scsi_logs(argv[1]);
- if (rc != 0) {
- printf("ERROR: show_scsi_logs failed %d\n", rc);
- }
-
- rc = show_devfs_devices();
- if (rc != 0) {
- printf("ERROR: show_devfs_devices failed %d\n", rc);
- }
-
- rc = do_scsi_device_read_write(argv[1]);
- if (rc != 0) {
- printf("ERROR: do_scsi_devices_read_write failed %d\n",
- rc);
- }
-
- rc = do_scsi_inquiry(argv[1], TRUE);
- if (rc != 0) {
- printf("ERROR: do_scsi_inquiry HEX failed %d\n", rc);
- } else {
- rc = do_scsi_inquiry(argv[1], FALSE);
- if (rc != 0) {
- printf("ERROR: do_scsi_inquiry PCI failed %d\n",
- rc);
- }
- }
-
- rc = show_scsi_maps();
- if (rc != 0) {
- printf("ERROR: show_scsi_maps failed %d\n", rc);
- }
-
- rc = show_scsi_modes(argv[1]);
- if (rc != 0) {
- printf("ERROR: show_scsi_modes failed %d\n", rc);
- }
-
- rc = do_scsi_read_buffer(argv[1]);
- if (rc != 0 && rc != 1) {
- printf("ERROR: do_scsi_read_buffer failed %d\n", rc);
- }
-
- rc = show_scsi_read_capacity(argv[1]);
- if (rc != 0) {
- printf("ERROR: show_scsi_read_capacity failed %d\n",
- rc);
- }
-
- rc |= do_scsi_reset_devices(argv[1], DEVICE_RESET);
- rc |= do_scsi_reset_devices(argv[1], BUS_RESET);
- rc |= do_scsi_reset_devices(argv[1], HOST_RESET);
- if (rc != 0) {
- printf("ERROR: do_scsi_reset_devices failed %d\n", rc);
- }
-
- rc = do_scsi_send_diagnostics(argv[1]);
- if (rc != 0) {
- printf("ERROR: do_scsi_send_diagnostics failed %d\n",
- rc);
- }
-
- rc |= do_scsi_start_stop(argv[1], FALSE);
- rc |= do_scsi_start_stop(argv[1], TRUE);
- if (rc != 0) {
- printf("ERROR: do_scsi_start_top failed %d\n", rc);
- }
-
- rc = do_scsi_read_write_buffer(argv[1]);
- if (rc != 0 && rc != 1) {
- printf("ERROR: do_scsi_read_write_buffer failed %d\n",
- rc);
- }
-
- rc = do_scsi_test_unit_ready(argv[1]);
- if (rc != 0) {
- printf("ERROR: do_scsi_test_unit_ready failed %d\n",
- rc);
- }
-
- rc = show_scsi_info(argv[1]);
- if (rc != 0) {
- printf("ERROR: show_scsi_info failed %d\n", rc);
- }
-
- rc = do_scsi_sgp_read_write(argv[1]);
- if (rc != 0) {
- printf("ERROR: do_scsi_sgp_read_write failed %d\n", rc);
- }
-
- rc = do_scsi_sgm_read_write(argv[1]);
- if (rc != 0) {
- printf("ERROR: do_scsi_sgm_read_write failed %d\n", rc);
- }
-
- print_msg(TEST_STOP, NULL);
- } else {
- printf("\nERROR: Invalid device passed to test\n\n\n");
- usage();
-
- }
-
- return 0;
-}
-
-int validate_device(char *device)
-{
- int rc = 0;
- int i, found = FALSE;
- char device_string[25];
-
- for (i = 0; i < MAX_DEVICES && !found; i++) {
- sprintf(device_string, "/dev/sg%d", i);
- //printf("checking %s \n", device_string);
- if (strcmp(device, device_string) == 0) {
- found = TRUE;
- }
- }
-
- return rc;
-}
-
-void usage()
-{
- printf("Usage: 'sg_scan [-a] [-n] [-w] [-i] [-x]'\n");
- printf(" where: -a do alpha scan (ie sga, sgb, sgc)\n");
- printf(" -n do numeric scan (ie sg0, sg1...) [default]\n");
- printf(" -w force open with read/write flag\n");
- printf(" -i do SCSI INQUIRY, output results\n");
- printf(" -x extra information output about queuing\n\n\n");
-}
-
-void make_dev_name(char *fname, const char *leadin, int k, int do_numeric)
-{
- char buff[64];
- int big, little;
-
- strcpy(fname, leadin ? leadin : "/dev/sg");
- if (do_numeric) {
- sprintf(buff, "%d", k);
- strcat(fname, buff);
- } else {
- if (k < 26) {
- buff[0] = 'a' + (char)k;
- buff[1] = '\0';
- strcat(fname, buff);
- } else if (k <= 255) { /* assumes sequence goes x,y,z,aa,ab,ac etc */
- big = k / 26;
- little = k - (26 * big);
- big = big - 1;
-
- buff[0] = 'a' + (char)big;
- buff[1] = 'a' + (char)little;
- buff[2] = '\0';
- strcat(fname, buff);
- } else
- strcat(fname, "xxxx");
- }
-}
-
-int run_sg_scan_tests()
-{
- int sg_fd, res, k, f;
- unsigned char inqBuff[OFF + INQ_REPLY_LEN];
- int inqInLen = OFF + sizeof(inqCmdBlk);
- int inqOutLen = OFF + INQ_REPLY_LEN;
- unsigned char *buffp = inqBuff + OFF;
- struct sg_header *isghp = (struct sg_header *)inqBuff;
- int do_numeric = NUMERIC_SCAN_DEF;
- int do_inquiry = 0;
- int do_extra = 1;
- int writeable = 0;
- int num_errors = 0;
- int num_silent = 0;
- int eacces_err = 0;
- char fname[64];
- My_scsi_idlun my_idlun;
- int host_no;
- int flags;
- int emul;
-
- print_msg(TEST_BREAK, __FUNCTION__);
-
- flags = writeable ? O_RDWR : OPEN_FLAG;
-
- do_numeric = 1;
- writeable = O_RDONLY;
- do_inquiry = 1;
- do_extra = 1;
-
- for (k = 0, res = 0; (k < 1000) && (num_errors < MAX_ERRORS);
- ++k, res = (sg_fd >= 0) ? close(sg_fd) : 0) {
- if (res < 0) {
- snprintf(ebuff, EBUFF_SZ, ME "Error closing %s ",
- fname);
- perror(ME "close error");
- return 1;
- }
- make_dev_name(fname, NULL, k, do_numeric);
-
- sg_fd = open(fname, flags | O_NONBLOCK);
- if (sg_fd < 0) {
- if (EBUSY == errno) {
- printf
- ("%s: device busy (O_EXCL lock), skipping\n",
- fname);
- continue;
- } else if ((ENODEV == errno) || (ENOENT == errno) ||
- (ENXIO == errno)) {
- ++num_errors;
- ++num_silent;
- continue;
- } else {
- if (EACCES == errno)
- eacces_err = 1;
- snprintf(ebuff, EBUFF_SZ,
- ME "Error opening %s ", fname);
- perror(ebuff);
- ++num_errors;
- continue;
- }
- }
- res = ioctl(sg_fd, SCSI_IOCTL_GET_IDLUN, &my_idlun);
- if (res < 0) {
- snprintf(ebuff, EBUFF_SZ,
- ME "device %s failed on scsi ioctl, skip",
- fname);
- perror(ebuff);
- ++num_errors;
- continue;
- }
- res = ioctl(sg_fd, SCSI_IOCTL_GET_BUS_NUMBER, &host_no);
- if (res < 0) {
- snprintf(ebuff, EBUFF_SZ, ME "device %s failed on scsi "
- "ioctl(2), skip", fname);
- perror(ebuff);
- ++num_errors;
- continue;
- }
-#ifdef SG_EMULATED_HOST
- res = ioctl(sg_fd, SG_EMULATED_HOST, &emul);
- if (res < 0) {
- snprintf(ebuff, EBUFF_SZ,
- ME "device %s failed on sg ioctl(3), skip",
- fname);
- perror(ebuff);
- ++num_errors;
- continue;
- }
-#else
- emul = 0;
-#endif
- printf("%s: scsi%d channel=%d id=%d lun=%d", fname, host_no,
- (my_idlun.dev_id >> 16) & 0xff, my_idlun.dev_id & 0xff,
- (my_idlun.dev_id >> 8) & 0xff);
- if (emul)
- printf(" [em]");
-#if 0
- printf(", huid=%d", my_idlun.host_unique_id);
-#endif
-#ifdef SG_GET_RESERVED_SIZE
- {
- My_sg_scsi_id m_id; /* compatible with sg_scsi_id_t in sg.h */
-
- res = ioctl(sg_fd, SG_GET_SCSI_ID, &m_id);
- if (res < 0) {
- snprintf(ebuff, EBUFF_SZ,
- ME "device %s ioctls(4), skip", fname);
- perror(ebuff);
- ++num_errors;
- continue;
- }
- printf(" type=%d", m_id.scsi_type);
- if (do_extra)
- printf(" cmd_per_lun=%hd queue_depth=%hd\n",
- m_id.h_cmd_per_lun, m_id.d_queue_depth);
- else
- printf("\n");
- }
-#else
- printf("\n");
-#endif
- if (!do_inquiry)
- continue;
-
-#ifdef SG_IO
- if ((ioctl(sg_fd, SG_GET_VERSION_NUM, &f) >= 0) && (f >= 30000)) {
- res = sg3_inq(sg_fd, inqBuff, do_extra);
- continue;
- }
-#endif
- memset(isghp, 0, sizeof(struct sg_header));
- isghp->reply_len = inqOutLen;
- memcpy(inqBuff + OFF, inqCmdBlk, INQUIRY_CMDLEN);
-
- if (O_RDWR == (flags & O_ACCMODE)) { /* turn on blocking */
- f = fcntl(sg_fd, F_GETFL);
- fcntl(sg_fd, F_SETFL, f & (~O_NONBLOCK));
- } else {
- close(sg_fd);
- sg_fd = open(fname, O_RDWR);
- }
-
- res = write(sg_fd, inqBuff, inqInLen);
- if (res < 0) {
- snprintf(ebuff, EBUFF_SZ, ME "device %s writing, skip",
- fname);
- perror(ebuff);
- ++num_errors;
- continue;
- }
- res = read(sg_fd, inqBuff, inqOutLen);
- if (res < 0) {
- snprintf(ebuff, EBUFF_SZ, ME "device %s reading, skip",
- fname);
- perror(ebuff);
- ++num_errors;
- continue;
- }
-#ifdef SG_GET_RESERVED_SIZE
- if (!sg_chk_n_print("Error from Inquiry", isghp->target_status,
- isghp->host_status, isghp->driver_status,
- isghp->sense_buffer, SG_MAX_SENSE))
- continue;
-#else
- if ((isghp->result != 0) || (0 != isghp->sense_buffer[0])) {
- printf("Error from Inquiry: result=%d\n",
- isghp->result);
- if (0 != isghp->sense_buffer[0])
- sg_print_sense("Error from Inquiry",
- isghp->sense_buffer,
- SG_MAX_SENSE);
- continue;
- }
-#endif
- f = (int)*(buffp + 7);
- printf(" %.8s %.16s %.4s ", buffp + 8, buffp + 16,
- buffp + 32);
- printf("[wide=%d sync=%d cmdq=%d sftre=%d pq=0x%x]\n",
- ! !(f & 0x20), ! !(f & 0x10), ! !(f & 2), ! !(f & 1),
- (*buffp & 0xe0) >> 5);
- }
- if ((num_errors >= MAX_ERRORS) && (num_silent < num_errors)) {
- printf("Stopping because there are too many error\n");
- if (eacces_err)
- printf(" root access may be required\n");
- }
- return 0;
-}
-
-#ifdef SG_IO
-int sg3_inq(int sg_fd, unsigned char *inqBuff, int do_extra)
-{
- sg_io_hdr_t io_hdr;
- unsigned char sense_buffer[32];
- int ok;
-
- memset(&io_hdr, 0, sizeof(sg_io_hdr_t));
- io_hdr.interface_id = 'S';
- io_hdr.cmd_len = sizeof(inqCmdBlk);
- io_hdr.mx_sb_len = sizeof(sense_buffer);
- io_hdr.dxfer_direction = SG_DXFER_FROM_DEV;
- io_hdr.dxfer_len = INQ_REPLY_LEN;
- io_hdr.dxferp = inqBuff;
- io_hdr.cmdp = inqCmdBlk;
- io_hdr.sbp = sense_buffer;
- io_hdr.timeout = 20000; /* 20000 millisecs == 20 seconds */
-
- if (ioctl(sg_fd, SG_IO, &io_hdr) < 0) {
- perror(ME "Inquiry SG_IO ioctl error");
- return 1;
- }
-
- /* now for the error processing */
- ok = 0;
- switch (sg_err_category3(&io_hdr)) {
- case SG_ERR_CAT_CLEAN:
- case SG_ERR_CAT_RECOVERED:
- ok = 1;
- break;
- default: /* won't bother decoding other categories */
- sg_chk_n_print3("INQUIRY command error", &io_hdr);
- break;
- }
-
- if (ok) { /* output result if it is available */
- char *p = (char *)inqBuff;
- int f = (int)*(p + 7);
- printf(" %.8s %.16s %.4s ", p + 8, p + 16, p + 32);
- printf("[wide=%d sync=%d cmdq=%d sftre=%d pq=0x%x] ",
- ! !(f & 0x20), ! !(f & 0x10), ! !(f & 2), ! !(f & 1),
- (*p & 0xe0) >> 5);
- if (do_extra)
- printf("dur=%ums\n", io_hdr.duration);
- else
- printf("\n");
- }
- return 0;
-}
-#endif
-
-static int do_logs(int sg_fd, int ppc, int sp, int pc, int pg_code,
- int paramp, void *resp, int mx_resp_len, int noisy)
-{
- int res;
- unsigned char logsCmdBlk[LOG_SENSE_CMDLEN] =
- { LOG_SENSE_CMD, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
- unsigned char sense_b[SENSE_BUFF_LEN];
- sg_io_hdr_t io_hdr;
-
- logsCmdBlk[1] = (unsigned char)((ppc ? 2 : 0) | (sp ? 1 : 0));
- logsCmdBlk[2] = (unsigned char)(((pc << 6) & 0xc0) | (pg_code & 0x3f));
- logsCmdBlk[5] = (unsigned char)((paramp >> 8) & 0xff);
- logsCmdBlk[6] = (unsigned char)(paramp & 0xff);
- if (mx_resp_len > 0xffff) {
- printf(ME "mx_resp_len too big\n");
- return -1;
- }
- logsCmdBlk[7] = (unsigned char)((mx_resp_len >> 8) & 0xff);
- logsCmdBlk[8] = (unsigned char)(mx_resp_len & 0xff);
-
- memset(&io_hdr, 0, sizeof(sg_io_hdr_t));
- io_hdr.interface_id = 'S';
- io_hdr.cmd_len = sizeof(logsCmdBlk);
- io_hdr.mx_sb_len = sizeof(sense_b);
- io_hdr.dxfer_direction = SG_DXFER_FROM_DEV;
- io_hdr.dxfer_len = mx_resp_len;
- io_hdr.dxferp = resp;
- io_hdr.cmdp = logsCmdBlk;
- io_hdr.sbp = sense_b;
- io_hdr.timeout = DEF_TIMEOUT;
-
- if (ioctl(sg_fd, SG_IO, &io_hdr) < 0) {
- perror("SG_IO (log sense) error");
- return -1;
- }
-#if 0
- printf("SG_IO ioctl: status=%d, info=%d, sb_len_wr=%d\n",
- io_hdr.status, io_hdr.info, io_hdr.sb_len_wr);
-#endif
- res = sg_err_category3(&io_hdr);
- switch (res) {
- case SG_ERR_CAT_CLEAN:
- case SG_ERR_CAT_RECOVERED:
- return 0;
- default:
- if (noisy) {
- char ebuff[EBUFF_SZ];
- snprintf(ebuff, EBUFF_SZ, ME "ppc=%d, sp=%d, "
- "pc=%d, page_code=%x, paramp=%x\n ", ppc,
- sp, pc, pg_code, paramp);
- sg_chk_n_print3(ebuff, &io_hdr);
- }
- return -1;
- }
-}
-
-static void dStrHex(const char *str, int len, int no_ascii)
-{
- const char *p = str;
- unsigned char c;
- char buff[82];
- int a = 0;
- const int bpstart = 5;
- const int cpstart = 60;
- int cpos = cpstart;
- int bpos = bpstart;
- int i, k;
-
- if (len <= 0)
- return;
- memset(buff, ' ', 80);
- buff[80] = '\0';
- k = sprintf(buff + 1, "%.2x", a);
- buff[k + 1] = ' ';
- if (bpos >= ((bpstart + (9 * 3))))
- bpos++;
-
- for (i = 0; i < len; i++) {
- c = *p++;
- bpos += 3;
- if (bpos == (bpstart + (9 * 3)))
- bpos++;
- sprintf(&buff[bpos], "%.2x", (int)(unsigned char)c);
- buff[bpos + 2] = ' ';
- if (no_ascii)
- buff[cpos++] = ' ';
- else {
- if ((c < ' ') || (c >= 0x7f))
- c = '.';
- buff[cpos++] = c;
- }
- if (cpos > (cpstart + 15)) {
- printf("%s\n", buff);
- bpos = bpstart;
- cpos = cpstart;
- a += 16;
- memset(buff, ' ', 80);
- k = sprintf(buff + 1, "%.2x", a);
- buff[k + 1] = ' ';
- }
- }
- if (cpos > cpstart) {
- printf("%s\n", buff);
- }
-}
-
-static void show_page_name(int page_no)
-{
- switch (page_no) {
- case 0x0:
- printf(" 0x00 Supported log pages\n");
- break;
- case 0x1:
- printf(" 0x01 Buffer over-run/under-run\n");
- break;
- case 0x2:
- printf(" 0x02 Error counters (write)\n");
- break;
- case 0x3:
- printf(" 0x03 Error counters (read)\n");
- break;
- case 0x4:
- printf(" 0x04 Error counters (read reverse)\n");
- break;
- case 0x5:
- printf(" 0x05 Error counters (verify)\n");
- break;
- case 0x6:
- printf(" 0x06 Non-medium errors\n");
- break;
- case 0x7:
- printf(" 0x07 Last n error events\n");
- break;
- case 0x8:
- printf(" 0x08 Format status (sbc2)\n");
- break;
- case 0xb:
- printf(" 0x0b Last n deferred errors of "
- "asynchronous events\n");
- break;
- case 0xc:
- printf(" 0x0c Sequential Access (ssc-2)\n");
- break;
- case 0xd:
- printf(" 0x0d Temperature\n");
- break;
- case 0xe:
- printf(" 0x0e Start-stop cycle counter\n");
- break;
- case 0xf:
- printf(" 0x0f Application client\n");
- break;
- case 0x10:
- printf(" 0x10 Self-test results\n");
- break;
- case 0x18:
- printf(" 0x18 Protocol specific port\n");
- break;
- case 0x2e:
- printf(" 0x2e Tape alerts (ssc-2)\n");
- break;
- case 0x2f:
- printf(" 0x2f Informational exceptions (SMART)\n");
- break;
- default:
- printf(" 0x%.2x\n", page_no);
- break;
- }
-}
-
-static void show_buffer_under_overrun_page(unsigned char *resp, int len)
-{
- int k, j, num, pl, count_basis, cause;
- unsigned char *ucp;
- unsigned char *xp;
- unsigned long long ull;
-
- printf("Buffer over-run/under-run page\n");
- num = len - 4;
- ucp = &resp[0] + 4;
- while (num > 3) {
- pl = ucp[3] + 4;
- count_basis = (ucp[1] >> 5) & 0x7;
- printf(" Count basis: ");
- switch (count_basis) {
- case 0:
- printf("undefined");
- break;
- case 1:
- printf("per command");
- break;
- case 2:
- printf("per failed reconnect");
- break;
- case 3:
- printf("per unit of time");
- break;
- default:
- printf("reserved [0x%x]", count_basis);
- break;
- }
- cause = (ucp[1] >> 1) & 0xf;
- printf(", Cause: ");
- switch (cause) {
- case 0:
- printf("bus busy");
- break;
- case 1:
- printf("transfer rate too slow");
- break;
- default:
- printf("reserved [0x%x]", cause);
- break;
- }
- printf(", Type: ");
- if (ucp[1] & 1)
- printf("over-run");
- else
- printf("under-run");
- printf(", count");
- k = pl - 4;
- xp = ucp + 4;
- if (k > sizeof(ull)) {
- xp += (k - sizeof(ull));
- k = sizeof(ull);
- }
- ull = 0;
- for (j = 0; j < k; ++j) {
- if (j > 0)
- ull <<= 8;
- ull |= xp[j];
- }
- printf(" = %llu\n", ull);
- num -= pl;
- ucp += pl;
- }
-}
-
-static void show_error_counter_page(unsigned char *resp, int len)
-{
- int k, j, num, pl, pc;
- unsigned char *ucp;
- unsigned char *xp;
- unsigned long long ull;
-
- switch (resp[0]) {
- case 2:
- printf("Write error counter page\n");
- break;
- case 3:
- printf("Read error counter page\n");
- break;
- case 4:
- printf("Read Reverse error counter page\n");
- break;
- case 5:
- printf("Verify error counter page\n");
- break;
- default:
- printf("expecting error counter page, got page=0x%x\n",
- resp[0]);
- return;
- }
- num = len - 4;
- ucp = &resp[0] + 4;
- while (num > 3) {
- pc = (ucp[0] << 8) | ucp[1];
- pl = ucp[3] + 4;
- switch (pc) {
- case 0:
- printf(" Errors corrected without substantion delay");
- break;
- case 1:
- printf(" Errors corrected with possible delays");
- break;
- case 2:
- printf(" Total operations");
- break;
- case 3:
- printf(" Total errors corrected");
- break;
- case 4:
- printf(" Total times correction algorithm processed");
- break;
- case 5:
- printf(" Total bytes processed");
- break;
- case 6:
- printf(" Total uncorrected errors");
- break;
- default:
- printf(" Reserved or vendor specific [0x%x]", pc);
- break;
- }
- k = pl - 4;
- xp = ucp + 4;
- if (k > sizeof(ull)) {
- xp += (k - sizeof(ull));
- k = sizeof(ull);
- }
- ull = 0;
- for (j = 0; j < k; ++j) {
- if (j > 0)
- ull <<= 8;
- ull |= xp[j];
- }
- printf(" = %llu\n", ull);
- num -= pl;
- ucp += pl;
- }
-}
-
-static void show_non_medium_error_page(unsigned char *resp, int len)
-{
- int k, j, num, pl, pc;
- unsigned char *ucp;
- unsigned char *xp;
- unsigned long long ull;
-
- printf("Non-medium error page\n");
- num = len - 4;
- ucp = &resp[0] + 4;
- while (num > 3) {
- pc = (ucp[0] << 8) | ucp[1];
- pl = ucp[3] + 4;
- switch (pc) {
- case 0:
- printf(" Non-medium error count");
- break;
- default:
- if (pc <= 0x7fff)
- printf(" Reserved [0x%x]", pc);
- else
- printf(" Vendor specific [0x%x]", pc);
- break;
- }
- k = pl - 4;
- xp = ucp + 4;
- if (k > sizeof(ull)) {
- xp += (k - sizeof(ull));
- k = sizeof(ull);
- }
- ull = 0;
- for (j = 0; j < k; ++j) {
- if (j > 0)
- ull <<= 8;
- ull |= xp[j];
- }
- printf(" = %llu\n", ull);
- num -= pl;
- ucp += pl;
- }
-}
-
-const char *self_test_code[] = {
- "default", "background short", "background extended", "reserved",
- "aborted background", "foreground short", "foreground extended",
- "reserved"
-};
-
-const char *self_test_result[] = {
- "completed without error",
- "aborted by SEND DIAGNOSTIC",
- "aborted other than by SEND DIAGNOSTIC",
- "unknown error, unable to complete",
- "self test completed with failure in test segment (which one unkown)",
- "first segment in self test failed",
- "second segment in self test failed",
- "another segment in self test failed",
- "reserved", "reserved", "reserved", "reserved", "reserved", "reserved",
- "reserved",
- "self test in progress"
-};
-
-static void show_self_test_page(unsigned char *resp, int len)
-{
- int k, num, n, res;
- unsigned char *ucp;
- unsigned long long ull;
-
- num = len - 4;
- if (num < 0x190) {
- printf("badly formed self-test results page\n");
- return;
- }
- printf("Self-test results page\n");
- for (k = 0, ucp = resp + 4; k < 20; ++k, ucp += 20) {
- n = (ucp[6] << 8) | ucp[7];
- if ((0 == n) && (0 == ucp[4]))
- break;
- printf(" Parameter code=%d, accumulated power-on hours=%d\n",
- (ucp[0] << 8) | ucp[1], n);
- printf(" self test code: %s [%d]\n",
- self_test_code[(ucp[4] >> 5) & 0x7],
- (ucp[4] >> 5) & 0x7);
- res = ucp[4] & 0xf;
- printf(" self test result: %s [%d]\n",
- self_test_result[res], res);
- if (ucp[5])
- printf(" self-test number=%d\n", (int)ucp[5]);
- ull = ucp[8];
- ull <<= 8;
- ull |= ucp[9];
- ull <<= 8;
- ull |= ucp[10];
- ull <<= 8;
- ull |= ucp[11];
- ull <<= 8;
- ull |= ucp[12];
- ull <<= 8;
- ull |= ucp[13];
- ull <<= 8;
- ull |= ucp[14];
- ull <<= 8;
- ull |= ucp[14];
- ull <<= 8;
- ull |= ucp[15];
- if ((0xffffffffffffffffULL != ull) && (res > 0) && (res < 0xf))
- printf(" address of first error=0x%llx\n", ull);
- if (ucp[16] & 0xf)
- printf(" sense key=0x%x, asc=0x%x, asq=0x%x\n",
- ucp[16] & 0xf, ucp[17], ucp[18]);
- }
-}
-
-static void show_Temperature_page(unsigned char *resp, int len, int hdr)
-{
- int k, num, extra, pc;
- unsigned char *ucp;
-
- num = len - 4;
- ucp = &resp[0] + 4;
- if (num < 4) {
- printf("badly formed Temperature log page\n");
- return;
- }
- if (hdr)
- printf("Temperature log page\n");
- for (k = num; k > 0; k -= extra, ucp += extra) {
- if (k < 3) {
- printf("short Temperature log page\n");
- return;
- }
- extra = ucp[3] + 4;
- pc = ((ucp[0] << 8) & 0xff) + ucp[1];
- if (0 == pc) {
- if (extra > 5) {
- if (ucp[5] < 0xff)
- printf(" Current temperature= %d C\n",
- ucp[5]);
- else
- printf
- (" Current temperature=<not available>\n");
- }
- } else if (1 == pc) {
- if (extra > 5) {
- if (ucp[5] < 0xff)
- printf
- (" Reference temperature= %d C\n",
- ucp[5]);
- else
- printf
- (" Reference temperature=<not available>\n");
- }
-
- } else {
- printf(" parameter code=0x%x, contents in hex:\n", pc);
- dStrHex((const char *)ucp, extra, 1);
- }
- }
-}
-
-static void show_IE_page(unsigned char *resp, int len, int full)
-{
- int k, num, extra, pc;
- unsigned char *ucp;
-
- num = len - 4;
- ucp = &resp[0] + 4;
- if (num < 4) {
- printf("badly formed Informational Exceptions log page\n");
- return;
- }
- if (full)
- printf("Informational Exceptions log page\n");
- for (k = num; k > 0; k -= extra, ucp += extra) {
- if (k < 3) {
- printf("short Informational Exceptions log page\n");
- return;
- }
- extra = ucp[3] + 4;
- pc = ((ucp[0] << 8) & 0xff) + ucp[1];
- if (0 == pc) {
- if (extra > 5) {
- if (full)
- printf(" IE asc=0x%x, ascq=0x%x",
- ucp[4], ucp[5]);
- if (extra > 6) {
- if (full)
- printf(",");
- if (ucp[6] < 0xff)
- printf
- (" Current temperature=%d C",
- ucp[6]);
- else
- printf
- (" Current temperature=<not available>");
- }
- printf("\n");
- }
- } else if (full) {
- printf(" parameter code=0x%x, contents in hex:\n", pc);
- dStrHex((const char *)ucp, extra, 1);
- }
- }
-}
-
-static void show_ascii_page(unsigned char *resp, int len)
-{
- int k, n, num;
-
- if (len < 0) {
- printf("response has bad length\n");
- return;
- }
- num = len - 4;
- switch (resp[0]) {
- case 0:
- printf("Supported pages:\n");
- for (k = 0; k < num; ++k)
- show_page_name((int)resp[4 + k]);
- break;
- case 0x1:
- show_buffer_under_overrun_page(resp, len);
- break;
- case 0x2:
- case 0x3:
- case 0x4:
- case 0x5:
- show_error_counter_page(resp, len);
- break;
- case 0x6:
- show_non_medium_error_page(resp, len);
- break;
- case 0xd:
- show_Temperature_page(resp, len, 1);
- break;
- case 0xe:
- if (len < 40) {
- printf("badly formed start-stop cycle counter page\n");
- break;
- }
- printf("Start-stop cycle counter page\n");
- printf(" Date of manufacture, year: %.4s, week: %.2s\n",
- &resp[8], &resp[12]);
- printf(" Accounting date, year: %.4s, week: %.2s\n",
- &resp[18], &resp[22]);
- n = (resp[28] << 24) | (resp[29] << 16) | (resp[30] << 8) |
- resp[31];
- printf(" Specified cycle count over device lifetime=%d\n", n);
- n = (resp[36] << 24) | (resp[37] << 16) | (resp[38] << 8) |
- resp[39];
- printf(" Accumulated start-stop cycles=%d\n", n);
- break;
- case 0x10:
- show_self_test_page(resp, len);
- break;
- case 0x2f:
- show_IE_page(resp, len, 1);
- break;
- default:
- printf("No ascii information for page=0x%x, here is hex:\n",
- resp[0]);
- dStrHex((const char *)resp, len, 1);
- break;
- }
-}
-
-static int fetchTemperature(int sg_fd, int do_hex, unsigned char *resp,
- int max_len)
-{
- int res = 0;
-
- if (0 == do_logs(sg_fd, 0, 0, 1, 0xd, 0, resp, max_len, 0))
- show_Temperature_page(resp, (resp[2] << 8) + resp[3] + 4, 0);
- else if (0 == do_logs(sg_fd, 0, 0, 1, 0x2f, 0, resp, max_len, 0))
- show_IE_page(resp, (resp[2] << 8) + resp[3] + 4, 0);
- else {
- printf
- ("Unable to find temperature in either log page (temperature "
- "or IE)\n");
- res = 1;
- }
- close(sg_fd);
- return res;
-}
-
-int show_scsi_logs(char *device)
-{
- int sg_fd, k, pg_len;
- char *file_name = 0;
- unsigned char rsp_buff[MX_ALLOC_LEN];
- int pg_code = 0;
- int pc = 1; /* N.B. some disks only give data for current cumulative */
- int paramp = 0;
- int do_list = 0;
- int do_ppc = 0;
- int do_sp = 0;
- int do_hex = 0;
- int do_all = 1;
- int do_temp = 0;
- int oflags = O_RDWR | O_NONBLOCK;
-
- file_name = device;
- print_msg(TEST_BREAK, __FUNCTION__);
-
- if ((sg_fd = open(file_name, oflags)) < 0) {
- snprintf(ebuff, EBUFF_SZ, ME "error opening file: %s",
- file_name);
- perror(ebuff);
- return 1;
- }
- /* Just to be safe, check we have a new sg device by trying an ioctl */
- if ((ioctl(sg_fd, SG_GET_VERSION_NUM, &k) < 0) || (k < 30000)) {
- printf(ME "%s doesn't seem to be a version 3 sg device\n",
- file_name);
- close(sg_fd);
- return 1;
- }
- if (do_list || do_all)
- pg_code = PG_CODE_ALL;
- pg_len = 0;
- if (1 == do_temp)
- return fetchTemperature(sg_fd, do_hex, rsp_buff, MX_ALLOC_LEN);
-
- if (0 == do_logs(sg_fd, do_ppc, do_sp, pc, pg_code, paramp,
- rsp_buff, MX_ALLOC_LEN, 1)) {
- pg_len = (rsp_buff[2] << 8) + rsp_buff[3];
- if ((pg_len + 4) > MX_ALLOC_LEN) {
- printf
- ("Only fetched %d bytes of response, truncate output\n",
- MX_ALLOC_LEN);
- pg_len = MX_ALLOC_LEN - 4;
- }
- if (do_hex) {
- printf("Returned log page code=0x%x, page len=0x%x\n",
- rsp_buff[0], pg_len);
- dStrHex((const char *)rsp_buff, pg_len + 4, 1);
- } else
- show_ascii_page(rsp_buff, pg_len + 4);
- }
- if (do_all && (pg_len > 1)) {
- int my_len = pg_len - 1;
- unsigned char parr[256];
-
- memcpy(parr, rsp_buff + 5, my_len);
- for (k = 0; k < my_len; ++k) {
- printf("\n");
- pg_code = parr[k];
- if (0 ==
- do_logs(sg_fd, do_ppc, do_sp, pc, pg_code, paramp,
- rsp_buff, MX_ALLOC_LEN, 1)) {
- pg_len = (rsp_buff[2] << 8) + rsp_buff[3];
- if ((pg_len + 4) > MX_ALLOC_LEN) {
- printf
- ("Only fetched %d bytes of response, truncate "
- "output\n", MX_ALLOC_LEN);
- pg_len = MX_ALLOC_LEN - 4;
- }
- if (do_hex) {
- printf
- ("Returned log page code=0x%x, page len=0x%x\n",
- rsp_buff[0], pg_len);
- dStrHex((const char *)rsp_buff,
- pg_len + 4, 1);
- } else
- show_ascii_page(rsp_buff, pg_len + 4);
- }
- }
- }
- close(sg_fd);
- return 0;
-}
-
-static int do_inquiry(int sg_fd, void *resp, int mx_resp_len)
-{
- int res;
- unsigned char inqCmdBlk[INQUIRY_CMDLEN] =
- { INQUIRY_CMD, 0, 0, 0, 0, 0 };
- unsigned char sense_b[SENSE_BUFF_LEN];
- sg_io_hdr_t io_hdr;
-
- inqCmdBlk[4] = (unsigned char)mx_resp_len;
- memset(&io_hdr, 0, sizeof(sg_io_hdr_t));
- io_hdr.interface_id = 'S';
- io_hdr.cmd_len = sizeof(inqCmdBlk);
- io_hdr.mx_sb_len = sizeof(sense_b);
- io_hdr.dxfer_direction = SG_DXFER_TO_FROM_DEV;
- io_hdr.dxfer_len = mx_resp_len;
- io_hdr.dxferp = resp;
- io_hdr.cmdp = inqCmdBlk;
- io_hdr.timeout = DEF_TIMEOUT;
-
- if (ioctl(sg_fd, SG_IO, &io_hdr) < 0) {
- perror("SG_IO (inquiry) error");
- return -1;
- }
- res = sg_err_category3(&io_hdr);
- switch (res) {
- case SG_ERR_CAT_CLEAN:
- case SG_ERR_CAT_RECOVERED:
- return 0;
- default:
- sg_chk_n_print3("Failed INQUIRY", &io_hdr);
- return -1;
- }
-}
-
-void leaf_dir(const char *lf, unsigned int *larr)
-{
- char name[NAME_LEN_MAX * 2];
- int res;
-
- if (do_quiet) {
- printf("%u\t%u\t%u\t%u\n", larr[0], larr[1], larr[2], larr[3]);
- return;
- }
- printf("%u\t%u\t%u\t%u\t%s\n", larr[0], larr[1], larr[2], larr[3], lf);
- if (do_leaf) {
- struct dirent *de_entry;
- struct dirent *de_result;
- DIR *sdir;
- int outpos;
-
- if (NULL == (sdir = opendir(lf))) {
- fprintf(stderr, "leaf_dir: opendir of %s: failed\n",
- lf);
- return;
- }
- de_entry = malloc(sizeof(struct dirent) + NAME_LEN_MAX);
- if (NULL == de_entry)
- return;
- res = 0;
- printf("\t");
- outpos = 8;
- while (1) {
- res = readdir_r(sdir, de_entry, &de_result);
- if (0 != res) {
- fprintf(stderr,
- "leaf_dir: readdir_r of %s: %s\n", lf,
- strerror(res));
- res = -2;
- break;
- }
- if (de_result == NULL)
- break;
- strncpy(name, de_entry->d_name, NAME_LEN_MAX * 2);
- if ((0 == strcmp("..", name))
- || (0 == strcmp(".", name)))
- continue;
- if (do_extra) {
- struct stat st;
- char devname[NAME_LEN_MAX * 2];
-
- strncpy(devname, lf, NAME_LEN_MAX * 2);
- strcat(devname, "/");
- strcat(devname, name);
- if (stat(devname, &st) < 0)
- return;
- if (S_ISCHR(st.st_mode)) {
- strcat(name, "(c ");
- sprintf(name + strlen(name), "%d %d)",
- major(st.st_rdev),
- minor(st.st_rdev));
- } else if (S_ISBLK(st.st_mode)) {
- strcat(name, "(b ");
- sprintf(name + strlen(name), "%d %d)",
- major(st.st_rdev),
- minor(st.st_rdev));
- }
- }
- res = strlen(name);
- if ((outpos + res + 2) > 80) {
- printf("\n\t");
- outpos = 8;
- }
- printf("%s ", name);
- outpos += res + 2;
- }
- printf("\n");
- }
- if (do_inq) {
- int sg_fd;
- char buff[64];
-
- memset(buff, 0, sizeof(buff));
- strncpy(name, lf, NAME_LEN_MAX * 2);
- strcat(name, "/generic");
- if ((sg_fd = open(name, O_RDONLY)) < 0) {
- if (!checked_sg) {
- checked_sg = 1;
- if ((sg_fd = open("/dev/sg0", O_RDONLY)) >= 0)
- close(sg_fd); /* try and get sg module loaded */
- sg_fd = open(name, O_RDONLY);
- }
- if (sg_fd < 0) {
- printf("Unable to open sg device: %s, %s\n",
- name, strerror(errno));
- return;
- }
- }
- if (0 != do_inquiry(sg_fd, buff, 64))
- return;
- close(sg_fd);
- dStrHex(buff, 64, 0);
- }
-}
-
-/* Return 0 -> ok, -1 -> opendir() error, -2 -> readdir_r error,
- -3 -> malloc error */
-int hbtl_scan(const char *path, int level, unsigned int *larr)
-{
- struct dirent *de_entry;
- struct dirent *de_result;
- char new_path[NAME_LEN_MAX * 2];
- DIR *sdir;
- int res;
- size_t level_slen;
-
- level_slen = strlen(level_arr[level]);
- if (NULL == (sdir = opendir(path))) {
- fprintf(stderr, "hbtl_scan: opendir of %s: failed\n", path);
- return -1;
- }
- de_entry = malloc(sizeof(struct dirent) + NAME_LEN_MAX);
- if (NULL == de_entry)
- return -3;
- res = 0;
- while (1) {
- res = readdir_r(sdir, de_entry, &de_result);
- if (0 != res) {
- fprintf(stderr, "hbtl_scan: readdir_r of %s: %s\n",
- path, strerror(res));
- res = -2;
- break;
- }
- if (de_result == NULL)
- break;
- if (0 ==
- strncmp(level_arr[level], de_entry->d_name, level_slen)) {
- if (1 !=
- sscanf(de_entry->d_name + level_slen, "%u",
- larr + level))
- larr[level] = UINT_MAX;
- strncpy(new_path, path, NAME_LEN_MAX * 2);
- strcat(new_path, "/");
- strcat(new_path, de_entry->d_name);
- if ((level + 1) < LEVELS) {
- res = hbtl_scan(new_path, level + 1, larr);
- if (res < 0)
- break;
- } else
- leaf_dir(new_path, larr);
- }
- }
- free(de_entry);
- closedir(sdir);
- return res;
-}
-
-int show_devfs_devices()
-{
- int res;
- char ds_root[D_ROOT_SZ];
- char di_root[D_ROOT_SZ];
- unsigned int larr[LEVELS];
- struct stat st;
-
- print_msg(TEST_BREAK, __FUNCTION__);
- strncpy(ds_root, "/dev", D_ROOT_SZ);
-
- strncpy(di_root, ds_root, D_ROOT_SZ);
-
- strcat(di_root, "/.devfsd");
-
- if (stat(di_root, &st) < 0) {
- printf("Didn't find %s so perhaps devfs is not present,"
- " attempting to continue ...\n", di_root);
- }
-
- strncpy(di_root, ds_root, D_ROOT_SZ);
- strcat(ds_root, "/scsi");
- strcat(di_root, "/ide");
-
- if (!do_ide)
- printf("SCSI scan:\n");
-
- res = hbtl_scan(ds_root, 0, larr);
-
- if (res < 0)
- printf("main: scsi hbtl_scan res=%d\n", res);
-
- do_ide = TRUE;
- do_inq = 0; /* won't try SCSI INQUIRY on IDE devices */
-
- if (do_ide) {
- printf("\nIDE scan:\n");
- res = hbtl_scan(di_root, 0, larr);
-
- if (res < 0)
- printf("main: ide hbtl_scan res=%d\n", res);
- }
- return 0;
-}
-
-static void install_handler(int sig_num, void (*sig_handler) (int sig))
-{
- struct sigaction sigact;
- sigaction(sig_num, NULL, &sigact);
- if (sigact.sa_handler != SIG_IGN) {
- sigact.sa_handler = sig_handler;
- sigemptyset(&sigact.sa_mask);
- sigact.sa_flags = 0;
- sigaction(sig_num, &sigact, NULL);
- }
-}
-
-void print_stats()
-{
- if (0 != dd_count)
- fprintf(stderr, " remaining block count=%d\n", dd_count);
- fprintf(stderr, "%d+%d records in\n", in_full - in_partial, in_partial);
- fprintf(stderr, "%d+%d records out\n", out_full - out_partial,
- out_partial);
-}
-
-static void interrupt_handler(int sig)
-{
- struct sigaction sigact;
-
- sigact.sa_handler = SIG_DFL;
- sigemptyset(&sigact.sa_mask);
- sigact.sa_flags = 0;
- sigaction(sig, &sigact, NULL);
- fprintf(stderr, "Interrupted by signal,");
- print_stats();
- kill(getpid(), sig);
-}
-
-static void siginfo_handler(int sig)
-{
- fprintf(stderr, "Progress report, continuing ...\n");
- print_stats();
-}
-
-int dd_filetype(const char *filename)
-{
- struct stat st;
- size_t len = strlen(filename);
-
- if ((1 == len) && ('.' == filename[0]))
- return FT_DEV_NULL;
- if (stat(filename, &st) < 0)
- return FT_OTHER;
- if (S_ISCHR(st.st_mode)) {
- if ((MEM_MAJOR == major(st.st_rdev)) &&
- (DEV_NULL_MINOR_NUM == minor(st.st_rdev)))
- return FT_DEV_NULL;
- if (RAW_MAJOR == major(st.st_rdev))
- return FT_RAW;
- if (SCSI_GENERIC_MAJOR == major(st.st_rdev))
- return FT_SG;
- if (SCSI_TAPE_MAJOR == major(st.st_rdev))
- return FT_ST;
- } else if (S_ISBLK(st.st_mode))
- return FT_BLOCK;
- return FT_OTHER;
-}
-
-int read_capacity(int sg_fd, int *num_sect, int *sect_sz)
-{
- int res;
- unsigned char rcCmdBlk[10] =
- { READ_CAPACITY, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
- unsigned char rcBuff[READ_CAP_REPLY_LEN];
- unsigned char sense_b[64];
- sg_io_hdr_t io_hdr;
-
- memset(&io_hdr, 0, sizeof(sg_io_hdr_t));
- io_hdr.interface_id = 'S';
- io_hdr.cmd_len = sizeof(rcCmdBlk);
- io_hdr.mx_sb_len = sizeof(sense_b);
- io_hdr.dxfer_direction = SG_DXFER_FROM_DEV;
- io_hdr.dxfer_len = sizeof(rcBuff);
- io_hdr.dxferp = rcBuff;
- io_hdr.cmdp = rcCmdBlk;
- io_hdr.sbp = sense_b;
- io_hdr.timeout = DEF_TIMEOUT;
-
- if (ioctl(sg_fd, SG_IO, &io_hdr) < 0) {
- perror("read_capacity (SG_IO) error");
- return -1;
- }
- res = sg_err_category3(&io_hdr);
- if (SG_ERR_CAT_MEDIA_CHANGED == res)
- return 2; /* probably have another go ... */
- else if (SG_ERR_CAT_CLEAN != res) {
- sg_chk_n_print3("read capacity", &io_hdr);
- return -1;
- }
- *num_sect = 1 + ((rcBuff[0] << 24) | (rcBuff[1] << 16) |
- (rcBuff[2] << 8) | rcBuff[3]);
- *sect_sz = (rcBuff[4] << 24) | (rcBuff[5] << 16) |
- (rcBuff[6] << 8) | rcBuff[7];
- return 0;
-}
-
-/* Return of 0 -> success, -1 -> failure, 2 -> try again */
-int sync_cache(int sg_fd)
-{
- int res;
- unsigned char scCmdBlk[10] = { SYNCHRONIZE_CACHE, 0, 0, 0, 0, 0, 0,
- 0, 0, 0
- };
- unsigned char sense_b[64];
- sg_io_hdr_t io_hdr;
-
- memset(&io_hdr, 0, sizeof(sg_io_hdr_t));
- io_hdr.interface_id = 'S';
- io_hdr.cmd_len = sizeof(scCmdBlk);
- io_hdr.mx_sb_len = sizeof(sense_b);
- io_hdr.dxfer_direction = SG_DXFER_NONE;
- io_hdr.dxfer_len = 0;
- io_hdr.dxferp = NULL;
- io_hdr.cmdp = scCmdBlk;
- io_hdr.sbp = sense_b;
- io_hdr.timeout = DEF_TIMEOUT;
-
- if (ioctl(sg_fd, SG_IO, &io_hdr) < 0) {
- perror("synchronize_cache (SG_IO) error");
- return -1;
- }
- res = sg_err_category3(&io_hdr);
- if (SG_ERR_CAT_MEDIA_CHANGED == res)
- return 2; /* probably have another go ... */
- else if (SG_ERR_CAT_CLEAN != res) {
- sg_chk_n_print3("synchronize cache", &io_hdr);
- return -1;
- }
- return 0;
-}
-
-int sg_build_scsi_cdb(unsigned char *cdbp, int cdb_sz, unsigned int blocks,
- unsigned int start_block, int write_true, int fua,
- int dpo)
-{
- int rd_opcode[] = { 0x8, 0x28, 0xa8, 0x88 };
- int wr_opcode[] = { 0xa, 0x2a, 0xaa, 0x8a };
- int sz_ind;
-
- memset(cdbp, 0, cdb_sz);
- if (dpo)
- cdbp[1] |= 0x10;
- if (fua)
- cdbp[1] |= 0x8;
- switch (cdb_sz) {
- case 6:
- sz_ind = 0;
- cdbp[0] = (unsigned char)(write_true ? wr_opcode[sz_ind] :
- rd_opcode[sz_ind]);
- cdbp[1] = (unsigned char)((start_block >> 16) & 0x1f);
- cdbp[2] = (unsigned char)((start_block >> 8) & 0xff);
- cdbp[3] = (unsigned char)(start_block & 0xff);
- cdbp[4] = (256 == blocks) ? 0 : (unsigned char)blocks;
- if (blocks > 256) {
- fprintf(stderr,
- ME "for 6 byte commands, maximum number of "
- "blocks is 256\n");
- return 1;
- }
- if ((start_block + blocks - 1) & (~0x1fffff)) {
- fprintf(stderr,
- ME "for 6 byte commands, can't address blocks"
- " beyond %d\n", 0x1fffff);
- return 1;
- }
- if (dpo || fua) {
- fprintf(stderr,
- ME "for 6 byte commands, neither dpo nor fua"
- " bits supported\n");
- return 1;
- }
- break;
- case 10:
- sz_ind = 1;
- cdbp[0] = (unsigned char)(write_true ? wr_opcode[sz_ind] :
- rd_opcode[sz_ind]);
- cdbp[2] = (unsigned char)((start_block >> 24) & 0xff);
- cdbp[3] = (unsigned char)((start_block >> 16) & 0xff);
- cdbp[4] = (unsigned char)((start_block >> 8) & 0xff);
- cdbp[5] = (unsigned char)(start_block & 0xff);
- cdbp[7] = (unsigned char)((blocks >> 8) & 0xff);
- cdbp[8] = (unsigned char)(blocks & 0xff);
- if (blocks & (~0xffff)) {
- fprintf(stderr,
- ME "for 10 byte commands, maximum number of "
- "blocks is %d\n", 0xffff);
- return 1;
- }
- break;
- case 12:
- sz_ind = 2;
- cdbp[0] = (unsigned char)(write_true ? wr_opcode[sz_ind] :
- rd_opcode[sz_ind]);
- cdbp[2] = (unsigned char)((start_block >> 24) & 0xff);
- cdbp[3] = (unsigned char)((start_block >> 16) & 0xff);
- cdbp[4] = (unsigned char)((start_block >> 8) & 0xff);
- cdbp[5] = (unsigned char)(start_block & 0xff);
- cdbp[6] = (unsigned char)((blocks >> 24) & 0xff);
- cdbp[7] = (unsigned char)((blocks >> 16) & 0xff);
- cdbp[8] = (unsigned char)((blocks >> 8) & 0xff);
- cdbp[9] = (unsigned char)(blocks & 0xff);
- break;
- case 16:
- sz_ind = 3;
- cdbp[0] = (unsigned char)(write_true ? wr_opcode[sz_ind] :
- rd_opcode[sz_ind]);
- /* can't cope with block number > 32 bits (yet) */
- cdbp[6] = (unsigned char)((start_block >> 24) & 0xff);
- cdbp[7] = (unsigned char)((start_block >> 16) & 0xff);
- cdbp[8] = (unsigned char)((start_block >> 8) & 0xff);
- cdbp[9] = (unsigned char)(start_block & 0xff);
- cdbp[10] = (unsigned char)((blocks >> 24) & 0xff);
- cdbp[11] = (unsigned char)((blocks >> 16) & 0xff);
- cdbp[12] = (unsigned char)((blocks >> 8) & 0xff);
- cdbp[13] = (unsigned char)(blocks & 0xff);
- break;
- default:
- fprintf(stderr,
- ME "expected cdb size of 6, 10, 12, or 16 but got"
- "=%d\n", cdb_sz);
- return 1;
- }
- return 0;
-}
-
-/* -1 -> unrecoverable error, 0 -> successful, 1 -> recoverable (ENOMEM),
- 2 -> try again */
-int sg_read(int sg_fd, unsigned char *buff, int blocks, int from_block,
- int bs, int cdbsz, int fua, int *diop)
-{
- unsigned char rdCmd[MAX_SCSI_CDBSZ];
- unsigned char senseBuff[SENSE_BUFF_LEN];
- sg_io_hdr_t io_hdr;
-
- if (sg_build_scsi_cdb(rdCmd, cdbsz, blocks, from_block, 0, fua, 0)) {
- fprintf(stderr,
- ME "bad rd cdb build, from_block=%d, blocks=%d\n",
- from_block, blocks);
- return -1;
- }
-
- memset(&io_hdr, 0, sizeof(sg_io_hdr_t));
- io_hdr.interface_id = 'S';
- io_hdr.cmd_len = cdbsz;
- io_hdr.cmdp = rdCmd;
- io_hdr.dxfer_direction = SG_DXFER_FROM_DEV;
- io_hdr.dxfer_len = bs * blocks;
- io_hdr.dxferp = buff;
- io_hdr.mx_sb_len = SENSE_BUFF_LEN;
- io_hdr.sbp = senseBuff;
- io_hdr.timeout = DEF_TIMEOUT;
- io_hdr.pack_id = from_block;
- if (diop && *diop)
- io_hdr.flags |= SG_FLAG_DIRECT_IO;
-
- if (ioctl(sg_fd, SG_IO, &io_hdr)) {
- if (ENOMEM == errno)
- return 1;
- perror("reading (SG_IO) on sg device, error");
- return -1;
- }
- switch (sg_err_category3(&io_hdr)) {
- case SG_ERR_CAT_CLEAN:
- break;
- case SG_ERR_CAT_RECOVERED:
- fprintf(stderr,
- "Recovered error while reading block=%d, num=%d\n",
- from_block, blocks);
- break;
- case SG_ERR_CAT_MEDIA_CHANGED:
- return 2;
- default:
- sg_chk_n_print3("reading", &io_hdr);
- if (do_coe) {
- memset(buff, 0, bs * blocks);
- fprintf(stderr, ">> unable to read at blk=%d for "
- "%d bytes, use zeros\n", from_block,
- bs * blocks);
- return 0; /* fudge success */
- } else
- return -1;
- }
- if (diop && *diop &&
- ((io_hdr.info & SG_INFO_DIRECT_IO_MASK) != SG_INFO_DIRECT_IO))
- *diop = 0; /* flag that dio not done (completely) */
- sum_of_resids += io_hdr.resid;
-#if SG_DEBUG
- fprintf(stderr, "duration=%u ms\n", io_hdr.duration);
-#endif
- return 0;
-}
-
-/* -1 -> unrecoverable error, 0 -> successful, 1 -> recoverable (ENOMEM),
- 2 -> try again */
-int sg_write(int sg_fd, unsigned char *buff, int blocks, int to_block,
- int bs, int cdbsz, int fua, int *diop)
-{
- unsigned char wrCmd[MAX_SCSI_CDBSZ];
- unsigned char senseBuff[SENSE_BUFF_LEN];
- sg_io_hdr_t io_hdr;
-
- if (sg_build_scsi_cdb(wrCmd, cdbsz, blocks, to_block, 1, fua, 0)) {
- fprintf(stderr, ME "bad wr cdb build, to_block=%d, blocks=%d\n",
- to_block, blocks);
- return -1;
- }
-
- memset(&io_hdr, 0, sizeof(sg_io_hdr_t));
- io_hdr.interface_id = 'S';
- io_hdr.cmd_len = cdbsz;
- io_hdr.cmdp = wrCmd;
- io_hdr.dxfer_direction = SG_DXFER_TO_DEV;
- io_hdr.dxfer_len = bs * blocks;
- io_hdr.dxferp = buff;
- io_hdr.mx_sb_len = SENSE_BUFF_LEN;
- io_hdr.sbp = senseBuff;
- io_hdr.timeout = DEF_TIMEOUT;
- io_hdr.pack_id = to_block;
- if (diop && *diop)
- io_hdr.flags |= SG_FLAG_DIRECT_IO;
-
- if (ioctl(sg_fd, SG_IO, &io_hdr)) {
- if (ENOMEM == errno)
- return 1;
- perror("writing (SG_IO) on sg device, error");
- return -1;
- }
- switch (sg_err_category3(&io_hdr)) {
- case SG_ERR_CAT_CLEAN:
- break;
- case SG_ERR_CAT_RECOVERED:
- fprintf(stderr,
- "Recovered error while writing block=%d, num=%d\n",
- to_block, blocks);
- break;
- case SG_ERR_CAT_MEDIA_CHANGED:
- return 2;
- default:
- sg_chk_n_print3("writing", &io_hdr);
- if (do_coe) {
- fprintf(stderr, ">> ignored errors for out blk=%d for "
- "%d bytes\n", to_block, bs * blocks);
- return 0; /* fudge success */
- } else
- return -1;
- }
- if (diop && *diop &&
- ((io_hdr.info & SG_INFO_DIRECT_IO_MASK) != SG_INFO_DIRECT_IO))
- *diop = 0; /* flag that dio not done (completely) */
- return 0;
-}
-
-int get_num(char *buf)
-{
- int res, num;
- char c;
-
- res = sscanf(buf, "%d%c", &num, &c);
- if (0 == res)
- return -1;
- else if (1 == res)
- return num;
- else {
- switch (c) {
- case 'c':
- case 'C':
- return num;
- case 'b':
- case 'B':
- return num * 512;
- case 'k':
- return num * 1024;
- case 'K':
- return num * 1000;
- case 'm':
- return num * 1024 * 1024;
- case 'M':
- return num * 1000000;
- case 'g':
- return num * 1024 * 1024 * 1024;
- case 'G':
- return num * 1000000000;
- default:
- fprintf(stderr, "unrecognized multiplier\n");
- return -1;
- }
- }
-}
-
-int do_scsi_device_read_write(char *device)
-{
- int skip = 0;
- int seek = 0;
- int bs = 0;
- int ibs = 0;
- int obs = 0;
- int bpt = DEF_BLOCKS_PER_TRANSFER;
- char inf[INOUTF_SZ];
- int in_type = FT_OTHER;
- char outf[INOUTF_SZ];
- int out_type = FT_OTHER;
- int dio = 0;
- int dio_incomplete = 0;
- int do_time = 1;
- int do_odir = 1;
- int scsi_cdbsz = DEF_SCSI_CDBSZ;
- int fua_mode = 0;
- int do_sync = 1;
- int do_blk_sgio = 1;
- int do_append = 1;
- int res, t, buf_sz, dio_tmp;
- int infd, outfd, blocks;
- unsigned char *wrkBuff;
- unsigned char *wrkPos;
- int in_num_sect = 0;
- int out_num_sect = 0;
- int in_sect_sz, out_sect_sz;
- char ebuff[EBUFF_SZ];
- int blocks_per;
- int req_count;
- struct timeval start_tm, end_tm;
-
- print_msg(TEST_BREAK, __FUNCTION__);
- strcpy(inf, "/dev/zero");
- strcpy(outf, device);
-
- if (bs <= 0) {
- bs = DEF_BLOCK_SIZE;
- fprintf(stderr,
- "Assume default 'bs' (block size) of %d bytes\n", bs);
- }
- if ((ibs && (ibs != bs)) || (obs && (obs != bs))) {
- fprintf(stderr,
- "If 'ibs' or 'obs' given must be same as 'bs'\n");
- usage();
- return 1;
- }
- if ((skip < 0) || (seek < 0)) {
- fprintf(stderr, "skip and seek cannot be negative\n");
- return 1;
- }
- if ((do_append > 0) && (seek > 0)) {
- fprintf(stderr, "Can't use both append and seek switches\n");
- return 1;
- }
-#ifdef SG_DEBUG
- fprintf(stderr, ME "if=%s skip=%d of=%s seek=%d count=%d\n",
- inf, skip, outf, seek, dd_count);
-#endif
- install_handler(SIGINT, interrupt_handler);
- install_handler(SIGQUIT, interrupt_handler);
- install_handler(SIGPIPE, interrupt_handler);
- install_handler(SIGUSR1, siginfo_handler);
-
- infd = STDIN_FILENO;
- outfd = STDOUT_FILENO;
- if (inf[0] && ('-' != inf[0])) {
- in_type = dd_filetype(inf);
-
- if ((FT_BLOCK & in_type) && do_blk_sgio)
- in_type |= FT_SG;
-
- if (FT_ST == in_type) {
- fprintf(stderr,
- ME "unable to use scsi tape device %s\n", inf);
- return 1;
- } else if (FT_SG & in_type) {
- if ((infd = open(inf, O_RDWR)) < 0) {
- snprintf(ebuff, EBUFF_SZ,
- ME "could not open %s for sg reading",
- inf);
- perror(ebuff);
- return 1;
- }
- t = bs * bpt;
- res = ioctl(infd, SG_SET_RESERVED_SIZE, &t);
- if (res < 0)
- perror(ME "SG_SET_RESERVED_SIZE error");
- res = ioctl(infd, SG_GET_VERSION_NUM, &t);
- if ((res < 0) || (t < 30000)) {
- if (FT_BLOCK & in_type)
- fprintf(stderr,
- ME
- "SG_IO unsupported on this block"
- " device\n");
- else
- fprintf(stderr,
- ME
- "sg driver prior to 3.x.y\n");
- return 1;
- }
- } else {
- if (do_odir && (FT_BLOCK == in_type))
- infd = open(inf, O_RDONLY | O_DIRECT);
- else
- infd = open(inf, O_RDONLY);
- if (infd < 0) {
- snprintf(ebuff, EBUFF_SZ,
- ME "could not open %s for reading",
- inf);
- perror(ebuff);
- return 1;
- } else if (skip > 0) {
- llse_loff_t offset = skip;
-
- offset *= bs; /* could exceed 32 bits here! */
- if (llse_llseek(infd, offset, SEEK_SET) < 0) {
- snprintf(ebuff, EBUFF_SZ,
- ME
- "couldn't skip to required position on %s",
- inf);
- perror(ebuff);
- return 1;
- }
- }
- }
- }
-
- if (outf[0] && ('-' != outf[0])) {
- out_type = dd_filetype(outf);
-
- if ((FT_BLOCK & out_type) && do_blk_sgio)
- out_type |= FT_SG;
-
- if (FT_ST == out_type) {
- fprintf(stderr,
- ME "unable to use scsi tape device %s\n", outf);
- return 1;
- } else if (FT_SG & out_type) {
- if ((outfd = open(outf, O_RDWR)) < 0) {
- snprintf(ebuff, EBUFF_SZ,
- ME "could not open %s for sg writing",
- outf);
- perror(ebuff);
- return 1;
- }
- t = bs * bpt;
- res = ioctl(outfd, SG_SET_RESERVED_SIZE, &t);
- if (res < 0)
- perror(ME "SG_SET_RESERVED_SIZE error");
- res = ioctl(outfd, SG_GET_VERSION_NUM, &t);
- if ((res < 0) || (t < 30000)) {
- fprintf(stderr,
- ME "sg driver prior to 3.x.y\n");
- return 1;
- }
- } else if (FT_DEV_NULL & out_type)
- outfd = -1; /* don't bother opening */
- else {
- if (FT_RAW != out_type) {
- int flags = O_WRONLY | O_CREAT;
-
- if (do_odir && (FT_BLOCK == out_type))
- flags |= O_DIRECT;
- else if (do_append)
- flags |= O_APPEND;
- if ((outfd = open(outf, flags, 0666)) < 0) {
- snprintf(ebuff, EBUFF_SZ,
- ME
- "could not open %s for writing",
- outf);
- perror(ebuff);
- return 1;
- }
- } else {
- if ((outfd = open(outf, O_WRONLY)) < 0) {
- snprintf(ebuff, EBUFF_SZ,
- ME
- "could not open %s for raw writing",
- outf);
- perror(ebuff);
- return 1;
- }
- }
- if (seek > 0) {
- llse_loff_t offset = seek;
-
- offset *= bs; /* could exceed 32 bits here! */
- if (llse_llseek(outfd, offset, SEEK_SET) < 0) {
- snprintf(ebuff, EBUFF_SZ,
- ME
- "couldn't seek to required position on %s",
- outf);
- perror(ebuff);
- return 1;
- }
- }
- }
- }
- if ((STDIN_FILENO == infd) && (STDOUT_FILENO == outfd)) {
- fprintf(stderr,
- "Can't have both 'if' as stdin _and_ 'of' as stdout\n");
- return 1;
- }
-
- if (dd_count < 0) {
- if (FT_SG & in_type) {
- res = read_capacity(infd, &in_num_sect, &in_sect_sz);
- if (2 == res) {
- fprintf(stderr,
- "Unit attention, media changed(in), continuing\n");
- res =
- read_capacity(infd, &in_num_sect,
- &in_sect_sz);
- }
- if (0 != res) {
- fprintf(stderr,
- "Unable to read capacity on %s\n", inf);
- in_num_sect = -1;
- } else {
- if (in_num_sect > skip)
- in_num_sect -= skip;
- }
- }
- if (FT_SG & out_type) {
- res = read_capacity(outfd, &out_num_sect, &out_sect_sz);
- if (2 == res) {
- fprintf(stderr,
- "Unit attention, media changed(out), continuing\n");
- res =
- read_capacity(outfd, &out_num_sect,
- &out_sect_sz);
- }
- if (0 != res) {
- fprintf(stderr,
- "Unable to read capacity on %s\n",
- outf);
- out_num_sect = -1;
- } else {
- if (out_num_sect > seek)
- out_num_sect -= seek;
- }
- }
-#ifdef SG_DEBUG
- fprintf(stderr,
- "Start of loop, count=%d, in_num_sect=%d, out_num_sect=%d\n",
- dd_count, in_num_sect, out_num_sect);
-#endif
- if (in_num_sect > 0) {
- if (out_num_sect > 0)
- dd_count =
- (in_num_sect >
- out_num_sect) ? out_num_sect : in_num_sect;
- else
- dd_count = in_num_sect;
- } else
- dd_count = out_num_sect;
- }
- if (dd_count < 0) {
- fprintf(stderr, "Couldn't calculate count, please give one\n");
- return 1;
- }
-
- if (dio || do_odir || (FT_RAW == in_type) || (FT_RAW == out_type)) {
- size_t psz = getpagesize();
- wrkBuff = malloc(bs * bpt + psz);
- if (0 == wrkBuff) {
- fprintf(stderr, "Not enough user memory for raw\n");
- return 1;
- }
- wrkPos = (unsigned char *)(((unsigned long)wrkBuff + psz - 1) &
- (~(psz - 1)));
- } else {
- wrkBuff = malloc(bs * bpt);
- if (0 == wrkBuff) {
- fprintf(stderr, "Not enough user memory\n");
- return 1;
- }
- wrkPos = wrkBuff;
- }
-
- blocks_per = bpt;
-#ifdef SG_DEBUG
- fprintf(stderr, "Start of loop, count=%d, blocks_per=%d\n",
- dd_count, blocks_per);
-#endif
- if (do_time) {
- start_tm.tv_sec = 0;
- start_tm.tv_usec = 0;
- gettimeofday(&start_tm, NULL);
- }
- req_count = dd_count;
-
- while (dd_count > 0) {
- blocks = (dd_count > blocks_per) ? blocks_per : dd_count;
- if (FT_SG & in_type) {
- int fua = fua_mode & 2;
-
- dio_tmp = dio;
- res =
- sg_read(infd, wrkPos, blocks, skip, bs, scsi_cdbsz,
- fua, &dio_tmp);
- if (1 == res) { /* ENOMEM, find what's available+try that */
- if (ioctl(infd, SG_GET_RESERVED_SIZE, &buf_sz) <
- 0) {
- perror("RESERVED_SIZE ioctls failed");
- break;
- }
- blocks_per = (buf_sz + bs - 1) / bs;
- blocks = blocks_per;
- fprintf(stderr,
- "Reducing read to %d blocks per loop\n",
- blocks_per);
- res =
- sg_read(infd, wrkPos, blocks, skip, bs,
- scsi_cdbsz, fua, &dio_tmp);
- } else if (2 == res) {
- fprintf(stderr,
- "Unit attention, media changed, continuing (r)\n");
- res =
- sg_read(infd, wrkPos, blocks, skip, bs,
- scsi_cdbsz, fua, &dio_tmp);
- }
- if (0 != res) {
- fprintf(stderr, "sg_read failed, skip=%d\n",
- skip);
- break;
- } else {
- in_full += blocks;
- if (dio && (0 == dio_tmp))
- dio_incomplete++;
- }
- } else {
- while (((res = read(infd, wrkPos, blocks * bs)) < 0) &&
- (EINTR == errno)) ;
- if (res < 0) {
- snprintf(ebuff, EBUFF_SZ,
- ME "reading, skip=%d ", skip);
- perror(ebuff);
- break;
- } else if (res < blocks * bs) {
- dd_count = 0;
- blocks = res / bs;
- if ((res % bs) > 0) {
- blocks++;
- in_partial++;
- }
- }
- in_full += blocks;
- }
-
- if (FT_SG & out_type) {
- int fua = fua_mode & 1;
-
- dio_tmp = dio;
- res =
- sg_write(outfd, wrkPos, blocks, seek, bs,
- scsi_cdbsz, fua, &dio_tmp);
- if (1 == res) { /* ENOMEM, find what's available+try that */
- if (ioctl(outfd, SG_GET_RESERVED_SIZE, &buf_sz)
- < 0) {
- perror("RESERVED_SIZE ioctls failed");
- break;
- }
- blocks_per = (buf_sz + bs - 1) / bs;
- blocks = blocks_per;
- fprintf(stderr,
- "Reducing write to %d blocks per loop\n",
- blocks);
- res =
- sg_write(outfd, wrkPos, blocks, seek, bs,
- scsi_cdbsz, fua, &dio_tmp);
- } else if (2 == res) {
- fprintf(stderr,
- "Unit attention, media changed, continuing (w)\n");
- res =
- sg_write(outfd, wrkPos, blocks, seek, bs,
- scsi_cdbsz, fua, &dio_tmp);
- } else if (0 != res) {
- fprintf(stderr, "sg_write failed, seek=%d\n",
- seek);
- break;
- } else {
- out_full += blocks;
- if (dio && (0 == dio_tmp))
- dio_incomplete++;
- }
- } else if (FT_DEV_NULL & out_type)
- out_full += blocks; /* act as if written out without error */
- else {
- while (((res = write(outfd, wrkPos, blocks * bs)) < 0)
- && (EINTR == errno)) ;
- if (res < 0) {
- snprintf(ebuff, EBUFF_SZ,
- ME "writing, seek=%d ", seek);
- perror(ebuff);
- break;
- } else if (res < blocks * bs) {
- fprintf(stderr,
- "output file probably full, seek=%d ",
- seek);
- blocks = res / bs;
- out_full += blocks;
- if ((res % bs) > 0)
- out_partial++;
- break;
- } else
- out_full += blocks;
- }
- if (dd_count > 0)
- dd_count -= blocks;
- skip += blocks;
- seek += blocks;
- }
- if ((do_time) && (start_tm.tv_sec || start_tm.tv_usec)) {
- struct timeval res_tm;
- double a, b;
-
- gettimeofday(&end_tm, NULL);
- res_tm.tv_sec = end_tm.tv_sec - start_tm.tv_sec;
- res_tm.tv_usec = end_tm.tv_usec - start_tm.tv_usec;
- if (res_tm.tv_usec < 0) {
- --res_tm.tv_sec;
- res_tm.tv_usec += 1000000;
- }
- a = res_tm.tv_sec;
- a += (0.000001 * res_tm.tv_usec);
- b = (double)bs *(req_count - dd_count);
- printf("time to transfer data was %d.%06d secs",
- (int)res_tm.tv_sec, (int)res_tm.tv_usec);
- if ((a > 0.00001) && (b > 511))
- printf(", %.2f MB/sec\n", b / (a * 1000000.0));
- else
- printf("\n");
- }
- if (do_sync) {
- if (FT_SG & out_type) {
- fprintf(stderr, ">> Synchronizing cache on %s\n", outf);
- res = sync_cache(outfd);
- if (2 == res) {
- fprintf(stderr,
- "Unit attention, media changed(in), continuing\n");
- res = sync_cache(outfd);
- }
- if (0 != res)
- fprintf(stderr,
- "Unable to synchronize cache\n");
- }
- }
- free(wrkBuff);
- if (STDIN_FILENO != infd)
- close(infd);
- if ((STDOUT_FILENO != outfd) && (FT_DEV_NULL != out_type))
- close(outfd);
- res = 0;
- if (0 != dd_count) {
- fprintf(stderr, "Some error occurred,");
- res = 2;
- }
- print_stats();
- if (dio_incomplete) {
- int fd;
- char c;
-
- fprintf(stderr,
- ">> Direct IO requested but incomplete %d times\n",
- dio_incomplete);
- if ((fd = open(proc_allow_dio, O_RDONLY)) >= 0) {
- if (1 == read(fd, &c, 1)) {
- if ('0' == c)
- fprintf(stderr,
- ">>> %s set to '0' but should be set "
- "to '1' for direct IO\n",
- proc_allow_dio);
- }
- close(fd);
- }
- }
- if (sum_of_resids)
- fprintf(stderr, ">> Non-zero sum of residual counts=%d\n",
- sum_of_resids);
- return res;
-}
-
-/* Returns 0 when successful, else -1 */
-static int do_scsi_inq(int sg_fd, int cmddt, int evpd, unsigned int pg_op,
- void *resp, int mx_resp_len, int noisy)
-{
- int res;
- unsigned char inqCmdBlk[INQUIRY_CMDLEN] =
- { INQUIRY_CMD, 0, 0, 0, 0, 0 };
- unsigned char sense_b[SENSE_BUFF_LEN];
- sg_io_hdr_t io_hdr;
-
- if (cmddt)
- inqCmdBlk[1] |= 2;
- if (evpd)
- inqCmdBlk[1] |= 1;
- inqCmdBlk[2] = (unsigned char)pg_op;
- inqCmdBlk[4] = (unsigned char)mx_resp_len;
- memset(&io_hdr, 0, sizeof(sg_io_hdr_t));
- io_hdr.interface_id = 'S';
- io_hdr.cmd_len = sizeof(inqCmdBlk);
- io_hdr.mx_sb_len = sizeof(sense_b);
- io_hdr.dxfer_direction = SG_DXFER_FROM_DEV;
- io_hdr.dxfer_len = mx_resp_len;
- io_hdr.dxferp = resp;
- io_hdr.cmdp = inqCmdBlk;
- io_hdr.sbp = sense_b;
- io_hdr.timeout = DEF_TIMEOUT;
-
- if (ioctl(sg_fd, SG_IO, &io_hdr) < 0) {
- perror("SG_IO (inquiry) error");
- return -1;
- }
- res = sg_err_category3(&io_hdr);
- switch (res) {
- case SG_ERR_CAT_CLEAN:
- case SG_ERR_CAT_RECOVERED:
- return 0;
- default:
- if (noisy) {
- char ebuff[EBUFF_SZ];
- snprintf(ebuff, EBUFF_SZ, "Inquiry error, CmdDt=%d, "
- "EVPD=%d, page_opcode=%x ", cmddt, evpd,
- pg_op);
- sg_chk_n_print3(ebuff, &io_hdr);
- }
- return -1;
- }
-}
-
-int do_scsi_inquiry(char *device, int hex_flag)
-{
- int sg_fd, k, j, num, len, act_len;
- int support_num;
- char *file_name = 0;
- char buff[MX_ALLOC_LEN + 1];
- unsigned char rsp_buff[MX_ALLOC_LEN + 1];
- unsigned int num_opcode = 0;
- int do_evpd = 0;
- int do_cmddt = 0;
- int do_cmdlst = 0;
- int do_hex = 0;
- int do_raw = 0;
- int do_pci = 0;
- int do_36 = 0;
- int oflags = O_RDONLY | O_NONBLOCK;
- int ansi_version = 0;
- int ret = 0;
-
- file_name = device;
-
- if (hex_flag) {
- do_hex = TRUE;
- print_msg(TEST_BREAK, __FUNCTION__);
- } else {
- do_pci = TRUE;
- }
-
- if (do_pci)
- oflags = O_RDWR | O_NONBLOCK;
- if ((sg_fd = open(file_name, oflags)) < 0) {
- snprintf(ebuff, EBUFF_SZ, "sg_inq: error opening file: %s",
- file_name);
- perror(ebuff);
- return 1;
- }
- /* Just to be safe, check we have a new sg device by trying an ioctl */
- if ((ioctl(sg_fd, SG_GET_VERSION_NUM, &k) < 0) || (k < 30000)) {
- fprintf(stderr,
- "sg_inq: %s doesn't seem to be a version 3 sg device\n",
- file_name);
- close(sg_fd);
- return 1;
- }
- memset(rsp_buff, 0, MX_ALLOC_LEN + 1);
-
- if (!(do_cmddt || do_evpd)) {
- if (!do_raw)
- printf("standard INQUIRY:\n");
- if (num_opcode > 0)
- printf
- (" <<given opcode or page_code is being ignored>>\n");
-
- if (0 == do_scsi_inq(sg_fd, 0, 0, 0, rsp_buff, 36, 1)) {
- len = rsp_buff[4] + 5;
- ansi_version = rsp_buff[2] & 0x7;
- if ((len > 36) && (len < 256) && (!do_36)) {
- if (do_scsi_inq
- (sg_fd, 0, 0, 0, rsp_buff, len, 1)) {
- fprintf(stderr,
- "second INQUIRY (%d byte) failed\n",
- len);
- return 1;
- }
- if (len != (rsp_buff[4] + 5)) {
- fprintf(stderr,
- "strange, twin INQUIRYs yield different "
- "'additional length'\n");
- ret = 2;
- }
- }
- if (do_36) {
- act_len = len;
- len = 36;
- } else
- act_len = len;
- if (do_hex)
- dStrHex((const char *)rsp_buff, len, 0);
- else {
- printf
- (" PQual=%d, Device type=%d, RMB=%d, ANSI version=%d, ",
- (rsp_buff[0] & 0xe0) >> 5,
- rsp_buff[0] & 0x1f,
- ! !(rsp_buff[1] & 0x80), ansi_version);
- printf("[full version=0x%02x]\n",
- (unsigned int)rsp_buff[2]);
- printf
- (" AERC=%d, TrmTsk=%d, NormACA=%d, HiSUP=%d, "
- "Resp data format=%d, SCCS=%d\n",
- ! !(rsp_buff[3] & 0x80),
- ! !(rsp_buff[3] & 0x40),
- ! !(rsp_buff[3] & 0x20),
- ! !(rsp_buff[3] & 0x10),
- rsp_buff[3] & 0x0f,
- ! !(rsp_buff[5] & 0x80));
- printf
- (" BQue=%d, EncServ=%d, MultiP=%d, MChngr=%d, "
- "ACKREQQ=%d, ", ! !(rsp_buff[6] & 0x80),
- ! !(rsp_buff[6] & 0x40),
- ! !(rsp_buff[6] & 0x10),
- ! !(rsp_buff[6] & 0x08),
- ! !(rsp_buff[6] & 0x04));
- printf("Addr16=%d\n RelAdr=%d, ",
- ! !(rsp_buff[6] & 0x01),
- ! !(rsp_buff[7] & 0x80));
- printf
- ("WBus16=%d, Sync=%d, Linked=%d, TranDis=%d, ",
- ! !(rsp_buff[7] & 0x20),
- ! !(rsp_buff[7] & 0x10),
- ! !(rsp_buff[7] & 0x08),
- ! !(rsp_buff[7] & 0x04));
- printf("CmdQue=%d\n", ! !(rsp_buff[7] & 0x02));
- if (len > 56)
- printf
- (" Clocking=0x%x, QAS=%d, IUS=%d\n",
- (rsp_buff[56] & 0x0c) >> 2,
- ! !(rsp_buff[56] & 0x2),
- ! !(rsp_buff[56] & 0x1));
- if (act_len == len)
- printf(" length=%d (0x%x)", len,
- len);
- else
- printf
- (" length=%d (0x%x), but only read 36 bytes",
- len, len);
- if ((ansi_version >= 2) && (len < 36))
- printf
- (" [for SCSI>=2, len>=36 is expected]\n");
- else
- printf("\n");
-
- if (len <= 8)
- printf
- (" Inquiry response length=%d\n, no vendor, "
- "product or revision data\n", len);
- else {
- if (len < 36)
- rsp_buff[len] = '\0';
- memcpy(buff, &rsp_buff[8], 8);
- buff[8] = '\0';
- printf(" Vendor identification: %s\n",
- buff);
- if (len <= 16)
- printf
- (" Product identification: <none>\n");
- else {
- memcpy(buff, &rsp_buff[16], 16);
- buff[16] = '\0';
- printf
- (" Product identification: %s\n",
- buff);
- }
- if (len <= 32)
- printf
- (" Product revision level: <none>\n");
- else {
- memcpy(buff, &rsp_buff[32], 4);
- buff[4] = '\0';
- printf
- (" Product revision level: %s\n",
- buff);
- }
- }
- }
- if (!do_raw &&
- (0 ==
- do_scsi_inq(sg_fd, 0, 1, 0x80, rsp_buff,
- MX_ALLOC_LEN, 0))) {
- len = rsp_buff[3];
- if (len > 0) {
- memcpy(buff, rsp_buff + 4, len);
- buff[len] = '\0';
- printf(" Product serial number: %s\n",
- buff);
- }
- }
- } else {
- printf("36 byte INQUIRY failed\n");
- return 1;
- }
- } else if (do_cmddt) {
- int reserved_cmddt;
- char op_name[128];
-
- if (do_cmdlst) {
- printf("Supported command list:\n");
- for (k = 0; k < 256; ++k) {
- if (0 ==
- do_scsi_inq(sg_fd, 1, 0, k, rsp_buff,
- MX_ALLOC_LEN, 1)) {
- support_num = rsp_buff[1] & 7;
- reserved_cmddt = rsp_buff[4];
- if ((3 == support_num)
- || (5 == support_num)) {
- num = rsp_buff[5];
- for (j = 0; j < num; ++j)
- printf(" %.2x",
- (int)rsp_buff[6 +
- j]);
- if (5 == support_num)
- printf
- (" [vendor specific manner (5)]");
- sg_get_command_name((unsigned
- char)k,
- sizeof
- (op_name) -
- 1, op_name);
- op_name[sizeof(op_name) - 1] =
- '\0';
- printf(" %s\n", op_name);
- } else if ((4 == support_num)
- || (6 == support_num))
- printf
- (" opcode=0x%.2x vendor specific (%d)\n",
- k, support_num);
- else if ((0 == support_num)
- && (reserved_cmddt > 0)) {
- printf
- (" opcode=0x%.2x ignored cmddt bit, "
- "given standard INQUIRY response, stop\n",
- k);
- break;
- }
- } else {
- fprintf(stderr,
- "CmdDt INQUIRY on opcode=0x%.2x: failed\n",
- k);
- break;
- }
- }
- } else {
- if (!do_raw) {
- printf("CmdDt INQUIRY, opcode=0x%.2x: [",
- num_opcode);
- sg_get_command_name((unsigned char)num_opcode,
- sizeof(op_name) - 1,
- op_name);
- op_name[sizeof(op_name) - 1] = '\0';
- printf("%s]\n", op_name);
- }
- if (0 == do_scsi_inq(sg_fd, 1, 0, num_opcode, rsp_buff,
- MX_ALLOC_LEN, 1)) {
- len = rsp_buff[5] + 6;
- reserved_cmddt = rsp_buff[4];
- if (do_hex)
- dStrHex((const char *)rsp_buff, len, 0);
- else {
- const char *desc_p;
- int prnt_cmd = 0;
-
- support_num = rsp_buff[1] & 7;
- num = rsp_buff[5];
- switch (support_num) {
- case 0:
- if (0 == reserved_cmddt)
- desc_p =
- "no data available";
- else
- desc_p =
- "ignored cmddt bit, standard INQUIRY "
- "response";
- break;
- case 1:
- desc_p = "not supported";
- break;
- case 2:
- desc_p = "reserved (2)";
- break;
- case 3:
- desc_p =
- "supported as per standard";
- prnt_cmd = 1;
- break;
- case 4:
- desc_p = "vendor specific (4)";
- break;
- case 5:
- desc_p =
- "supported in vendor specific way";
- prnt_cmd = 1;
- break;
- case 6:
- desc_p = "vendor specific (6)";
- break;
- case 7:
- desc_p = "reserved (7)";
- break;
- default:
- desc_p = "impossible value > 7";
- break;
- }
- if (prnt_cmd) {
- printf(" Support field: %s [",
- desc_p);
- for (j = 0; j < num; ++j)
- printf(" %.2x",
- (int)rsp_buff[6 +
- j]);
- printf(" ]\n");
- } else
- printf(" Support field: %s\n",
- desc_p);
- }
- } else {
- fprintf(stderr,
- "CmdDt INQUIRY on opcode=0x%.2x: failed\n",
- num_opcode);
- return 1;
- }
-
- }
- } else if (do_evpd) {
- if (!do_raw)
- printf("EVPD INQUIRY, page code=0x%.2x:\n", num_opcode);
- if (0 ==
- do_scsi_inq(sg_fd, 0, 1, num_opcode, rsp_buff, MX_ALLOC_LEN,
- 1)) {
- len = rsp_buff[3] + 4;
- if (num_opcode != rsp_buff[1])
- printf
- ("non evpd respone; probably a STANDARD INQUIRY "
- "response\n");
- else {
- if (!do_hex)
- printf(" Only hex output supported\n");
- dStrHex((const char *)rsp_buff, len, 0);
- }
- } else {
- fprintf(stderr,
- "EVPD INQUIRY, page code=0x%.2x: failed\n",
- num_opcode);
- return 1;
- }
- }
-
- if (do_pci) {
- unsigned char slot_name[16];
-
- printf("\n");
- memset(slot_name, '\0', sizeof(slot_name));
- if (ioctl(sg_fd, SCSI_IOCTL_GET_PCI, slot_name) < 0) {
- if (EINVAL == errno)
- printf
- ("ioctl(SCSI_IOCTL_GET_PCI) not supported by this "
- "kernel\n");
- else if (ENXIO == errno)
- printf
- ("associated adapter not a PCI device?\n");
- else
- perror("ioctl(SCSI_IOCTL_GET_PCI) failed");
- } else
- printf("PCI:slot_name: %s\n", slot_name);
- }
-
- close(sg_fd);
- return ret;
-}
-
-int show_scsi_maps()
-{
- int sg_fd, res, k;
- int do_numeric = NUMERIC_SCAN_DEF;
- int do_all_s = 1;
- int do_sd = 0;
- int do_st = 0;
- int do_osst = 0;
- int do_sr = 0;
- int do_scd = 0;
- int do_extra = 1;
- int do_inquiry = 0;
- char fname[64];
- int num_errors = 0;
- int num_silent = 0;
- int eacces_err = 0;
- int last_sg_ind = -1;
- struct stat stat_buf;
-
- print_msg(TEST_BREAK, __FUNCTION__);
-
- if (stat(devfs_id, &stat_buf) == 0)
- printf("# Note: the devfs pseudo file system is present\n");
-
- for (k = 0, res = 0; (k < MAX_SG_DEVS) && (num_errors < MAX_ERRORS);
- ++k, res = (sg_fd >= 0) ? close(sg_fd) : 0) {
- if (res < 0) {
- snprintf(ebuff, EBUFF_SZ, "Error closing %s ", fname);
- perror("sg_map: close error");
- return 1;
- }
- make_dev_name(fname, "/dev/sg", k, do_numeric);
-
- sg_fd = open(fname, O_RDONLY | O_NONBLOCK);
- if (sg_fd < 0) {
- if (EBUSY == errno) {
- map_arr[k].active = -2;
- continue;
- } else if ((ENODEV == errno) || (ENOENT == errno) ||
- (ENXIO == errno)) {
- ++num_errors;
- ++num_silent;
- map_arr[k].active = -1;
- continue;
- } else {
- if (EACCES == errno)
- eacces_err = 1;
- snprintf(ebuff, EBUFF_SZ, "Error opening %s ",
- fname);
- perror(ebuff);
- ++num_errors;
- continue;
- }
- }
- res = ioctl(sg_fd, SG_GET_SCSI_ID, &map_arr[k].sg_dat);
- if (res < 0) {
- snprintf(ebuff, EBUFF_SZ,
- "device %s failed on sg ioctl, skip", fname);
- perror(ebuff);
- ++num_errors;
- continue;
- }
- if (do_inquiry) {
- char buff[36];
-
- if (0 ==
- do_scsi_inq(sg_fd, 0, 0, 0, buff, sizeof(buff),
- 1)) {
- memcpy(map_arr[k].vendor, &buff[8], 8);
- memcpy(map_arr[k].product, &buff[16], 16);
- memcpy(map_arr[k].revision, &buff[32], 4);
- }
- }
- map_arr[k].active = 1;
- map_arr[k].oth_dev_num = -1;
- last_sg_ind = k;
- }
- if ((num_errors >= MAX_ERRORS) && (num_silent < num_errors)) {
- printf("Stopping because there are too many error\n");
- if (eacces_err)
- printf(" root access may be required\n");
- return 1;
- }
- if (last_sg_ind < 0) {
- printf("Stopping because no sg devices found\n");
- }
-
- if (do_all_s || do_sd)
- scan_dev_type("/dev/sd", MAX_SD_DEVS, 0, LIN_DEV_TYPE_SD,
- last_sg_ind);
- if (do_all_s || do_sr)
- scan_dev_type("/dev/sr", MAX_SR_DEVS, 1, LIN_DEV_TYPE_SR,
- last_sg_ind);
- if (do_all_s || do_scd)
- scan_dev_type("/dev/scd", MAX_SR_DEVS, 1, LIN_DEV_TYPE_SCD,
- last_sg_ind);
- if (do_all_s || do_st)
- scan_dev_type("/dev/st", MAX_ST_DEVS, 1, LIN_DEV_TYPE_ST,
- last_sg_ind);
- if (do_all_s || do_osst)
- scan_dev_type("/dev/osst", MAX_OSST_DEVS, 1, LIN_DEV_TYPE_OSST,
- last_sg_ind);
-
- for (k = 0; k <= last_sg_ind; ++k) {
- make_dev_name(fname, "/dev/sg", k, do_numeric);
- printf("%s", fname);
- switch (map_arr[k].active) {
- case -2:
- printf(do_extra ? " -2 -2 -2 -2 -2" : " busy");
- break;
- case -1:
- printf(do_extra ? " -1 -1 -1 -1 -1" :
- " not present");
- break;
- case 0:
- printf(do_extra ? " -3 -3 -3 -3 -3" :
- " some error\n");
- break;
- case 1:
- if (do_extra)
- printf(" %d %d %d %d %d",
- map_arr[k].sg_dat.host_no,
- map_arr[k].sg_dat.channel,
- map_arr[k].sg_dat.scsi_id,
- map_arr[k].sg_dat.lun,
- map_arr[k].sg_dat.scsi_type);
- switch (map_arr[k].lin_dev_type) {
- case LIN_DEV_TYPE_SD:
- make_dev_name(fname, "/dev/sd",
- map_arr[k].oth_dev_num, 0);
- printf(" %s", fname);
- break;
- case LIN_DEV_TYPE_ST:
- make_dev_name(fname, "/dev/st",
- map_arr[k].oth_dev_num, 1);
- printf(" %s", fname);
- break;
- case LIN_DEV_TYPE_OSST:
- make_dev_name(fname, "/dev/osst",
- map_arr[k].oth_dev_num, 1);
- printf(" %s", fname);
- break;
- case LIN_DEV_TYPE_SR:
- make_dev_name(fname, "/dev/sr",
- map_arr[k].oth_dev_num, 1);
- printf(" %s", fname);
- break;
- case LIN_DEV_TYPE_SCD:
- make_dev_name(fname, "/dev/scd",
- map_arr[k].oth_dev_num, 1);
- printf(" %s", fname);
- break;
- default:
- break;
- }
- if (do_inquiry)
- printf(" %.8s %.16s %.4s", map_arr[k].vendor,
- map_arr[k].product, map_arr[k].revision);
- break;
- default:
- printf(" bad logic\n");
- break;
- }
- printf("\n");
- }
- return 0;
-}
-
-static int find_dev_in_sg_arr(My_scsi_idlun * my_idlun, int host_no,
- int last_sg_ind)
-{
- int k;
- struct sg_scsi_id *sidp;
-
- for (k = 0; k <= last_sg_ind; ++k) {
- sidp = &(map_arr[k].sg_dat);
- if ((host_no == sidp->host_no) &&
- ((my_idlun->dev_id & 0xff) == sidp->scsi_id) &&
- (((my_idlun->dev_id >> 8) & 0xff) == sidp->lun) &&
- (((my_idlun->dev_id >> 16) & 0xff) == sidp->channel))
- return k;
- }
- return -1;
-}
-
-static void scan_dev_type(const char *leadin, int max_dev, int do_numeric,
- int lin_dev_type, int last_sg_ind)
-{
- int k, res, ind, sg_fd = 0;
- int num_errors = 0;
- int num_silent = 0;
- int host_no = -1;
- int nonMappedDevicesPresent = FALSE;
- My_scsi_idlun my_idlun;
- char fname[64];
-
- for (k = 0, res = 0; (k < max_dev) && (num_errors < MAX_ERRORS);
- ++k, res = (sg_fd >= 0) ? close(sg_fd) : 0) {
-
-/* ignore close() errors */
-#if 0
- if (res < 0) {
- snprintf(ebuff, EBUFF_SZ, "Error closing %s ", fname);
- perror("sg_map: close error");
-#ifndef IGN_CLOSE_ERR
- return;
-#else
- ++num_errors;
- sg_fd = 0;
-#endif
- }
-#endif
- make_dev_name(fname, leadin, k, do_numeric);
-#ifdef DEBUG
- printf("Trying %s: ", fname);
-#endif
-
- sg_fd = open(fname, O_RDONLY | O_NONBLOCK);
- if (sg_fd < 0) {
-#ifdef DEBUG
- printf("ERROR %i\n", errno);
-#endif
- if (EBUSY == errno) {
- printf("Device %s is busy\n", fname);
- ++num_errors;
- continue;
- } else if ((ENODEV == errno) || (ENOENT == errno) ||
- (ENXIO == errno)) {
- ++num_errors;
- ++num_silent;
- continue;
- } else {
- snprintf(ebuff, EBUFF_SZ, "Error opening %s ",
- fname);
- perror(ebuff);
- ++num_errors;
- continue;
- }
- }
-
- res = ioctl(sg_fd, SCSI_IOCTL_GET_IDLUN, &my_idlun);
- if (res < 0) {
- snprintf(ebuff, EBUFF_SZ,
- "device %s failed on scsi ioctl(idlun), skip",
- fname);
- perror(ebuff);
- ++num_errors;
-#ifdef DEBUG
- printf("Couldn't get IDLUN!\n");
-#endif
- continue;
- }
- res = ioctl(sg_fd, SCSI_IOCTL_GET_BUS_NUMBER, &host_no);
- if (res < 0) {
- snprintf(ebuff, EBUFF_SZ,
- "device %s failed on scsi ioctl(bus_number), skip",
- fname);
- perror(ebuff);
- ++num_errors;
-#ifdef DEBUG
- printf("Couldn't get BUS!\n");
-#endif
- continue;
- }
-#ifdef DEBUG
- printf("%i(%x) %i %i %i %i\n", host_no, my_idlun.host_unique_id,
- (my_idlun.dev_id >> 24) & 0xff,
- (my_idlun.dev_id >> 16) & 0xff,
- (my_idlun.dev_id >> 8) & 0xff, my_idlun.dev_id & 0xff);
-#endif
- ind = find_dev_in_sg_arr(&my_idlun, host_no, last_sg_ind);
- if (ind >= 0) {
- map_arr[ind].oth_dev_num = k;
- map_arr[ind].lin_dev_type = lin_dev_type;
- } else if (ind != -1) {
- printf
- ("Strange, could not find device %s mapped to sg device error %d??\n",
- fname, ind);
- } else {
- nonMappedDevicesPresent = TRUE;
- }
- }
- if (nonMappedDevicesPresent) {
- printf("Unmapped Devices found...\n\n");
- }
-}
-
-/* Returns 0 when successful, else -1 */
-static int do_simple_inq(int sg_fd, void *resp, int mx_resp_len, int noisy)
-{
- int res;
- unsigned char inqCmdBlk[INQUIRY_CMDLEN] =
- { INQUIRY_CMD, 0, 0, 0, 0, 0 };
- unsigned char sense_b[SENSE_BUFF_LEN];
- sg_io_hdr_t io_hdr;
-
- inqCmdBlk[4] = (unsigned char)mx_resp_len;
- memset(&io_hdr, 0, sizeof(sg_io_hdr_t));
- io_hdr.interface_id = 'S';
- io_hdr.cmd_len = sizeof(inqCmdBlk);
- io_hdr.mx_sb_len = sizeof(sense_b);
- io_hdr.dxfer_direction = SG_DXFER_FROM_DEV;
- io_hdr.dxfer_len = mx_resp_len;
- io_hdr.dxferp = resp;
- io_hdr.cmdp = inqCmdBlk;
- io_hdr.sbp = sense_b;
- io_hdr.timeout = DEF_TIMEOUT;
-
- if (ioctl(sg_fd, SG_IO, &io_hdr) < 0) {
- perror("SG_IO (inquiry) error");
- return -1;
- }
- res = sg_err_category3(&io_hdr);
- switch (res) {
- case SG_ERR_CAT_CLEAN:
- case SG_ERR_CAT_RECOVERED:
- return 0;
- default:
- if (noisy) {
- char ebuff[EBUFF_SZ];
- snprintf(ebuff, EBUFF_SZ, "Inquiry error ");
- sg_chk_n_print3(ebuff, &io_hdr);
- }
- return -1;
- }
-}
-
-static int do_modes(int sg_fd, int dbd, int pc, int pg_code, int sub_pg_code,
- void *resp, int mx_resp_len, int noisy, int mode6)
-{
- int res;
- unsigned char modesCmdBlk[MODE_SENSE10_CMDLEN] =
- { MODE_SENSE10_CMD, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
- unsigned char sense_b[SENSE_BUFF_LEN];
- sg_io_hdr_t io_hdr;
-
- modesCmdBlk[1] = (unsigned char)(dbd ? 0x8 : 0);
- modesCmdBlk[2] = (unsigned char)(((pc << 6) & 0xc0) | (pg_code & 0x3f));
- modesCmdBlk[3] = (unsigned char)(sub_pg_code & 0xff);
- if (mx_resp_len > (mode6 ? 0xff : 0xffff)) {
- printf(ME "mx_resp_len too big\n");
- return -1;
- }
- if (mode6) {
- modesCmdBlk[0] = MODE_SENSE6_CMD;
- modesCmdBlk[4] = (unsigned char)(mx_resp_len & 0xff);
- } else {
- modesCmdBlk[7] = (unsigned char)((mx_resp_len >> 8) & 0xff);
- modesCmdBlk[8] = (unsigned char)(mx_resp_len & 0xff);
- }
-
- memset(&io_hdr, 0, sizeof(sg_io_hdr_t));
- memset(sense_b, 0, sizeof(sense_b));
- io_hdr.interface_id = 'S';
- io_hdr.cmd_len = mode6 ? MODE_SENSE6_CMDLEN : MODE_SENSE10_CMDLEN;
- io_hdr.mx_sb_len = sizeof(sense_b);
- io_hdr.dxfer_direction = SG_DXFER_FROM_DEV;
- io_hdr.dxfer_len = mx_resp_len;
- io_hdr.dxferp = resp;
- io_hdr.cmdp = modesCmdBlk;
- io_hdr.sbp = sense_b;
- io_hdr.timeout = DEF_TIMEOUT;
-
- if (ioctl(sg_fd, SG_IO, &io_hdr) < 0) {
- perror("SG_IO (mode sense) error");
- return -1;
- }
- res = sg_err_category3(&io_hdr);
- switch (res) {
- case SG_ERR_CAT_CLEAN:
- case SG_ERR_CAT_RECOVERED:
- return 0;
- default:
- if (noisy) {
- char ebuff[EBUFF_SZ];
- snprintf(ebuff, EBUFF_SZ, "Mode sense error, dbd=%d "
- "pc=%d page_code=%x sub_page_code=%x\n ",
- dbd, pc, pg_code, sub_pg_code);
- sg_chk_n_print3(ebuff, &io_hdr);
- }
- if ((0x70 == (0x7f & sense_b[0])) && (0x20 == sense_b[12]) &&
- (0x0 == sense_b[13])) {
- if (mode6)
- fprintf(stderr,
- ">>>>>> drop '-6' switch and try again with "
- "a 10 byte MODE SENSE\n");
- else
- fprintf(stderr,
- ">>>>>> add '-6' switch and try again with "
- "a 6 byte MODE SENSE\n");
- }
- return -1;
- }
-}
-
-const char *scsi_ptype_strs[] = {
- "disk",
- "tape",
- "printer",
- "processor",
- "write once optical disk",
- "cd/dvd",
- "scanner",
- "optical memory device",
- "medium changer",
- "communications",
- "graphics",
- "graphics",
- "storage array controller",
- "enclosure services device",
- "simplified direct access device",
- "optical card reader/writer device",
-};
-
-const char *get_ptype_str(int scsi_ptype)
-{
- int num = sizeof(scsi_ptype_strs) / sizeof(scsi_ptype_strs[0]);
-
- return (scsi_ptype < num) ? scsi_ptype_strs[scsi_ptype] : "";
-}
-
-static struct page_code_desc pc_desc_all[] = {
- {0x0, "Unit Attention condition [vendor: page format not required]"},
- {0x2, "Disconnect-Reconnect"},
- {0xa, "Control"},
- {0x15, "Extended"},
- {0x16, "Extended device-type specific"},
- {0x18, "Protocol specific LUN"},
- {0x19, "Protocol specific port"},
- {0x1a, "Power condition"},
- {0x1c, "Informational exceptions control"},
- {0x3f, "[yields all supported pages]"},
-};
-
-static struct page_code_desc pc_desc_disk[] = {
- {0x1, "Read-Write error recovery"},
- {0x3, "Format"},
- {0x4, "Rigid disk geometry"},
- {0x5, "Flexible geometry"},
- {0x7, "Verify error recovery"},
- {0x8, "Caching"},
- {0x9, "Peripheral device (spc-2 ?)"},
- {0xb, "Medium types supported"},
- {0xc, "Notch and partition"},
- {0xd, "Power condition (obsolete)"},
- {0x10, "XOR control"},
-};
-
-static struct page_code_desc pc_desc_tape[] = {
- {0xf, "Data Compression"},
- {0x10, "Device config"},
- {0x11, "Medium Partition [1]"},
- {0x12, "Medium Partition [2]"},
- {0x13, "Medium Partition [3]"},
- {0x14, "Medium Partition [4]"},
- {0x1c, "Informational exceptions control (tape version)"},
-};
-
-static struct page_code_desc pc_desc_cddvd[] = {
- {0x1, "Read-Write error recovery"},
- {0x3, "MRW"},
- {0x5, "Write parameters"},
- {0xd, "CD device parameters (obsolete)"},
- {0xe, "CD audio"},
- {0x1a, "Power condition"},
- {0x1c, "Fault/failure reporting control"},
- {0x1d, "Timeout and protect"},
- {0x2a, "MM capabilities and mechanical status (obsolete)"},
-};
-
-static struct page_code_desc pc_desc_smc[] = {
- {0x1d, "Element address assignment"},
- {0x1e, "Transport geometry parameters"},
- {0x1f, "Device capabilities"},
-};
-
-static struct page_code_desc pc_desc_scc[] = {
- {0x1b, "LUN mapping"},
-};
-
-static struct page_code_desc pc_desc_ses[] = {
- {0x14, "Enclosure services management"},
-};
-
-struct page_code_desc *find_mode_page_table(int scsi_ptype, int *size)
-{
- switch (scsi_ptype) {
- case 0: /* disk (direct access) type devices */
- case 4:
- case 7:
- case 0xe:
- *size = sizeof(pc_desc_disk) / sizeof(pc_desc_disk[0]);
- return &pc_desc_disk[0];
- case 1: /* tape devices */
- case 2:
- *size = sizeof(pc_desc_tape) / sizeof(pc_desc_tape[0]);
- return &pc_desc_tape[0];
- case 5: /* cd/dvd devices */
- *size = sizeof(pc_desc_cddvd) / sizeof(pc_desc_cddvd[0]);
- return &pc_desc_cddvd[0];
- case 8: /* medium changer devices */
- *size = sizeof(pc_desc_smc) / sizeof(pc_desc_smc[0]);
- return &pc_desc_smc[0];
- case 0xc: /* storage array devices */
- *size = sizeof(pc_desc_scc) / sizeof(pc_desc_scc[0]);
- return &pc_desc_scc[0];
- case 0xd: /* enclosure services devices */
- *size = sizeof(pc_desc_ses) / sizeof(pc_desc_ses[0]);
- return &pc_desc_ses[0];
- }
- *size = 0;
- return NULL;
-}
-
-const char *find_page_code_desc(int page_num, int scsi_ptype)
-{
- int k;
- int num;
- const struct page_code_desc *pcdp;
-
- pcdp = find_mode_page_table(scsi_ptype, &num);
- if (pcdp) {
- for (k = 0; k < num; ++k, ++pcdp) {
- if (page_num == pcdp->page_code)
- return pcdp->desc;
- else if (page_num < pcdp->page_code)
- break;
- }
- }
- pcdp = &pc_desc_all[0];
- num = sizeof(pc_desc_all) / sizeof(pc_desc_all[0]);
- for (k = 0; k < num; ++k, ++pcdp) {
- if (page_num == pcdp->page_code)
- return pcdp->desc;
- else if (page_num < pcdp->page_code)
- break;
- }
- return NULL;
-}
-
-static void list_page_codes(int scsi_ptype)
-{
- int k;
- int num = sizeof(pc_desc_all) / sizeof(pc_desc_all[0]);
- const struct page_code_desc *pcdp = &pc_desc_all[0];
- int num_ptype;
- const struct page_code_desc *pcd_ptypep;
-
- pcd_ptypep = find_mode_page_table(scsi_ptype, &num_ptype);
- printf("Page_Code Description\n");
- for (k = 0; k < 0x3f; ++k) {
- if (pcd_ptypep && (num_ptype > 0)) {
- if (k == pcd_ptypep->page_code) {
- printf(" 0x%02x %s\n",
- pcd_ptypep->page_code, pcd_ptypep->desc);
- ++pcd_ptypep;
- --num_ptype;
- continue;
- } else if (k > pcd_ptypep->page_code) {
- pcd_ptypep++;
- --num_ptype;
- }
- }
- if (pcdp && (num > 0)) {
- if (k == pcdp->page_code) {
- printf(" 0x%02x %s\n", pcdp->page_code,
- pcdp->desc);
- ++pcdp;
- --num;
- continue;
- } else if (k > pcdp->page_code) {
- pcdp++;
- --num;
- }
- }
- }
-}
-
-int show_scsi_modes(char *device)
-{
- int sg_fd, k, num, len, md_len, bd_len, longlba, page_num;
- char *file_name = 0;
- char ebuff[EBUFF_SZ];
- const char *descp;
- unsigned char rsp_buff[MODE_ALLOC_LEN];
- int rsp_buff_size = MODE_ALLOC_LEN;
- int pg_code = 0;
- int sub_pg_code = 0;
- int pc = 0;
- int do_all = 1;
- int do_dbd = 0;
- int do_hex = 0;
- int do_mode6 = 0; /* Use MODE SENSE(6) instead of MODE SENSE(10) */
- int oflags = O_RDONLY | O_NONBLOCK;
- struct sg_scsi_id a_sid;
- int scsi_ptype, density_code_off;
- unsigned char *ucp;
- unsigned char uc;
-
- print_msg(TEST_BREAK, __FUNCTION__);
-
- file_name = device;
-
- list_page_codes(0);
-
- /* The 6 bytes command only allows up to 255 bytes of response data */
- if (do_mode6)
- rsp_buff_size = 255;
-
- if ((sg_fd = open(file_name, oflags)) < 0) {
- snprintf(ebuff, EBUFF_SZ, ME "error opening file: %s",
- file_name);
- perror(ebuff);
- return 1;
- }
- /* Just to be safe, check we have a new sg device by trying an ioctl */
- if ((ioctl(sg_fd, SG_GET_VERSION_NUM, &k) < 0) || (k < 30000)) {
- printf(ME "%s doesn't seem to be a version 3 sg device\n",
- file_name);
- close(sg_fd);
- return 1;
- }
- if (ioctl(sg_fd, SG_GET_SCSI_ID, &a_sid) < 0) {
- unsigned char inqBuff[36];
-
- if (do_simple_inq(sg_fd, inqBuff, sizeof(inqBuff), 1)) {
- printf(ME "%s doesn't respond to a SCSI INQUIRY\n",
- file_name);
- close(sg_fd);
- return 1;
- }
- scsi_ptype = inqBuff[0] & 0x1f; /* fetch peripheral device type */
- } else
- scsi_ptype = a_sid.scsi_type;
- printf(" SCSI peripheral type: %s [0x%x] (from INQUIRY)\n",
- get_ptype_str(scsi_ptype), scsi_ptype);
-
- if (do_all)
- pg_code = MODE_CODE_ALL;
-
- if (0 == do_modes(sg_fd, do_dbd, pc, pg_code, sub_pg_code,
- rsp_buff, rsp_buff_size, 1, do_mode6)) {
- int medium_type, specific, headerlen;
-
- printf("Mode parameter header from %s byte MODE SENSE:\n",
- (do_mode6 ? "6" : "10"));
- if (do_mode6) {
- headerlen = 4;
- if (do_hex)
- dStrHex((const char *)rsp_buff, headerlen, 1);
- md_len = rsp_buff[0] + 1;
- bd_len = rsp_buff[3];
- medium_type = rsp_buff[1];
- specific = rsp_buff[2];
- longlba = 0; /* what is this field? */
- } else {
- headerlen = 8;
- md_len = (rsp_buff[0] << 8) + rsp_buff[1] + 2;
- bd_len = (rsp_buff[6] << 8) + rsp_buff[7];
- medium_type = rsp_buff[2];
- specific = rsp_buff[3];
- longlba = rsp_buff[4] & 1;
- }
- if (do_hex)
- dStrHex((const char *)rsp_buff, headerlen, 1);
- printf(" Mode data length=%d, medium type=0x%.2x, specific"
- " param=0x%.2x, longlba=%d\n", md_len, medium_type,
- specific, longlba);
- if (md_len > rsp_buff_size) {
- printf
- ("Only fetched %d bytes of response, truncate output\n",
- rsp_buff_size);
- md_len = rsp_buff_size;
- if (bd_len + headerlen > rsp_buff_size)
- bd_len = rsp_buff_size - headerlen;
- }
- printf(" Block descriptor length=%d\n", bd_len);
- if (bd_len > 0) {
- len = 8;
- density_code_off = 0;
- num = bd_len;
- if (longlba) {
- printf("> longlba block descriptors:\n");
- len = 16;
- density_code_off = 8;
- } else if (0 == scsi_ptype) {
- printf
- ("> Direct access device block descriptors:\n");
- density_code_off = 4;
- } else
- printf
- ("> General mode parameter block descriptors:\n");
-
- ucp = rsp_buff + headerlen;
- while (num > 0) {
- printf(" Density code=0x%x\n",
- *(ucp + density_code_off));
- dStrHex((const char *)ucp, len, 1);
- ucp += len;
- num -= len;
- }
- printf("\n");
- }
- ucp = rsp_buff + bd_len + headerlen; /* start of mode page(s) */
- md_len -= bd_len + headerlen; /* length of mode page(s) */
- while (md_len > 0) { /* got mode page(s) */
- uc = *ucp;
- page_num = ucp[0] & 0x3f;
- if (do_hex)
- descp = NULL;
- else {
- descp =
- find_page_code_desc(page_num, scsi_ptype);
- if (NULL == descp)
- snprintf(ebuff, EBUFF_SZ,
- "vendor[0x%x]", page_num);
- }
- if (uc & 0x40) {
- len = (ucp[2] << 8) + ucp[3] + 4;
- if (do_hex)
- printf
- (">> page_code=0x%x, subpage_code=0x%x, "
- "page_control=%d\n", page_num,
- ucp[1], pc);
- else
- printf
- (">> page_code: %s, subpage_code=0x%x, "
- "page_control: %s\n",
- (descp ? descp : ebuff), ucp[1],
- pg_control_str_arr[pc]);
- } else {
- len = ucp[1] + 2;
- if (do_hex)
- printf
- (">> page_code=0x%x, page_control=%d\n",
- page_num, pc);
- else
- printf
- (">> page_code: %s, page_control: %s\n",
- (descp ? descp : ebuff),
- pg_control_str_arr[pc]);
- }
- dStrHex((const char *)ucp, len, 1);
- ucp += len;
- md_len -= len;
- }
- }
-
- close(sg_fd);
- return 0;
-}
-
-int do_scsi_read_buffer(char *device)
-{
- int sg_fd, res;
- unsigned int k, num;
- unsigned char rbCmdBlk[RB_CMD_LEN];
- unsigned char *rbBuff = NULL;
- void *rawp = NULL;
- unsigned char sense_buffer[32];
- int buf_capacity = 0;
- int do_quick = 0;
- int do_dio = 0;
- int do_mmap = 1;
- int do_time = 0;
- int buf_size = 0;
- unsigned int total_size_mb = RB_MB_TO_READ;
- char *file_name = 0;
- size_t psz = getpagesize();
- int dio_incomplete = 0;
- sg_io_hdr_t io_hdr;
- struct timeval start_tm, end_tm;
-#ifdef SG_DEBUG
- int clear = 1;
-#endif
-
- print_msg(TEST_BREAK, __FUNCTION__);
-
- file_name = device;
-
- sg_fd = open(file_name, O_RDONLY);
- if (sg_fd < 0) {
- perror(ME "open error");
- return 1;
- }
- /* Don't worry, being very careful not to write to a none-sg file ... */
- res = ioctl(sg_fd, SG_GET_VERSION_NUM, &k);
- if ((res < 0) || (k < 30000)) {
- printf(ME "not a sg device, or driver prior to 3.x\n");
- return 1;
- }
- if (do_mmap) {
- do_dio = 0;
- do_quick = 0;
- }
- if (NULL == (rawp = malloc(512))) {
- printf(ME "out of memory (query)\n");
- return 1;
- }
- rbBuff = rawp;
-
- memset(rbCmdBlk, 0, RB_CMD_LEN);
- rbCmdBlk[0] = RB_OPCODE;
- rbCmdBlk[1] = RB_MODE_DESC;
- rbCmdBlk[8] = RB_DESC_LEN;
- memset(&io_hdr, 0, sizeof(sg_io_hdr_t));
- io_hdr.interface_id = 'S';
- io_hdr.cmd_len = sizeof(rbCmdBlk);
- io_hdr.mx_sb_len = sizeof(sense_buffer);
- io_hdr.dxfer_direction = SG_DXFER_FROM_DEV;
- io_hdr.dxfer_len = RB_DESC_LEN;
- io_hdr.dxferp = rbBuff;
- io_hdr.cmdp = rbCmdBlk;
- io_hdr.sbp = sense_buffer;
- io_hdr.timeout = 60000; /* 60000 millisecs == 60 seconds */
- /* do normal IO to find RB size (not dio or mmap-ed at this stage) */
-
- if (ioctl(sg_fd, SG_IO, &io_hdr) < 0) {
- perror(ME "SG_IO READ BUFFER descriptor error");
- if (rawp)
- free(rawp);
- return 1;
- }
-
- /* now for the error processing */
- switch (sg_err_category3(&io_hdr)) {
- case SG_ERR_CAT_CLEAN:
- break;
- case SG_ERR_CAT_RECOVERED:
- printf
- ("Recovered error on READ BUFFER descriptor, continuing\n");
- break;
- default: /* won't bother decoding other categories */
- sg_chk_n_print3("READ BUFFER descriptor error", &io_hdr);
- if (rawp)
- free(rawp);
- return 1;
- }
-
- buf_capacity = ((rbBuff[1] << 16) | (rbBuff[2] << 8) | rbBuff[3]);
- printf("READ BUFFER reports: buffer capacity=%d, offset boundary=%d\n",
- buf_capacity, (int)rbBuff[0]);
-
- if (0 == buf_size)
- buf_size = buf_capacity;
- else if (buf_size > buf_capacity) {
- printf
- ("Requested buffer size=%d exceeds reported capacity=%d\n",
- buf_size, buf_capacity);
- if (rawp)
- free(rawp);
- return 1;
- }
- if (rawp) {
- free(rawp);
- rawp = NULL;
- }
-
- if (!do_dio) {
- k = buf_size;
- if (do_mmap && (0 != (k % psz)))
- k = ((k / psz) + 1) * psz; /* round up to page size */
- res = ioctl(sg_fd, SG_SET_RESERVED_SIZE, &k);
- if (res < 0)
- perror(ME "SG_SET_RESERVED_SIZE error");
- }
-
- if (do_mmap) {
- rbBuff = mmap(NULL, buf_size, PROT_READ, MAP_SHARED, sg_fd, 0);
- if (MAP_FAILED == rbBuff) {
- if (ENOMEM == errno)
- printf(ME "mmap() out of memory, try a smaller "
- "buffer size than %d KB\n",
- buf_size / 1024);
- else
- perror(ME "error using mmap()");
- return 1;
- }
- } else { /* non mmap-ed IO */
- rawp = malloc(buf_size + (do_dio ? psz : 0));
- if (NULL == rawp) {
- printf(ME "out of memory (data)\n");
- return 1;
- }
- if (do_dio) /* align to page boundary */
- rbBuff =
- (unsigned char *)(((unsigned long)rawp + psz - 1) &
- (~(psz - 1)));
- else
- rbBuff = rawp;
- }
-
- num = (total_size_mb * 1024U * 1024U) / (unsigned int)buf_size;
- if (do_time) {
- start_tm.tv_sec = 0;
- start_tm.tv_usec = 0;
- gettimeofday(&start_tm, NULL);
- }
- /* main data reading loop */
- for (k = 0; k < num; ++k) {
- memset(rbCmdBlk, 0, RB_CMD_LEN);
- rbCmdBlk[0] = RB_OPCODE;
- rbCmdBlk[1] = RB_MODE_DATA;
- rbCmdBlk[6] = 0xff & (buf_size >> 16);
- rbCmdBlk[7] = 0xff & (buf_size >> 8);
- rbCmdBlk[8] = 0xff & buf_size;
-#ifdef SG_DEBUG
- memset(rbBuff, 0, buf_size);
-#endif
-
- memset(&io_hdr, 0, sizeof(sg_io_hdr_t));
- io_hdr.interface_id = 'S';
- io_hdr.cmd_len = sizeof(rbCmdBlk);
- io_hdr.mx_sb_len = sizeof(sense_buffer);
- io_hdr.dxfer_direction = SG_DXFER_FROM_DEV;
- io_hdr.dxfer_len = buf_size;
- if (!do_mmap)
- io_hdr.dxferp = rbBuff;
- io_hdr.cmdp = rbCmdBlk;
- io_hdr.sbp = sense_buffer;
- io_hdr.timeout = 20000; /* 20000 millisecs == 20 seconds */
- io_hdr.pack_id = k;
- if (do_mmap)
- io_hdr.flags |= SG_FLAG_MMAP_IO;
- else if (do_dio)
- io_hdr.flags |= SG_FLAG_DIRECT_IO;
- else if (do_quick)
- io_hdr.flags |= SG_FLAG_NO_DXFER;
-
- if (ioctl(sg_fd, SG_IO, &io_hdr) < 0) {
- if (ENOMEM == errno)
- printf(ME
- "SG_IO data; out of memory, try a smaller "
- "buffer size than %d KB\n",
- buf_size / 1024);
- else
- perror(ME "SG_IO READ BUFFER data error");
- if (rawp)
- free(rawp);
- return 1;
- }
-
- /* now for the error processing */
- switch (sg_err_category3(&io_hdr)) {
- case SG_ERR_CAT_CLEAN:
- break;
- case SG_ERR_CAT_RECOVERED:
- printf
- ("Recovered error on READ BUFFER data, continuing\n");
- break;
- default: /* won't bother decoding other categories */
- sg_chk_n_print3("READ BUFFER data error", &io_hdr);
- if (rawp)
- free(rawp);
- return 1;
- }
- if (do_dio &&
- ((io_hdr.info & SG_INFO_DIRECT_IO_MASK) !=
- SG_INFO_DIRECT_IO))
- dio_incomplete = 1; /* flag that dio not done (completely) */
-
-#ifdef SG_DEBUG
- if (clear) {
- for (j = 0; j < buf_size; ++j) {
- if (rbBuff[j] != 0) {
- clear = 0;
- break;
- }
- }
- }
-#endif
- }
- if ((do_time) && (start_tm.tv_sec || start_tm.tv_usec)) {
- struct timeval res_tm;
- double a, b;
-
- gettimeofday(&end_tm, NULL);
- res_tm.tv_sec = end_tm.tv_sec - start_tm.tv_sec;
- res_tm.tv_usec = end_tm.tv_usec - start_tm.tv_usec;
- if (res_tm.tv_usec < 0) {
- --res_tm.tv_sec;
- res_tm.tv_usec += 1000000;
- }
- a = res_tm.tv_sec;
- a += (0.000001 * res_tm.tv_usec);
- b = (double)buf_size *num;
- printf("time to read data from buffer was %d.%06d secs",
- (int)res_tm.tv_sec, (int)res_tm.tv_usec);
- if ((a > 0.00001) && (b > 511))
- printf(", %.2f MB/sec\n", b / (a * 1000000.0));
- else
- printf("\n");
- }
- if (dio_incomplete)
- printf(">> direct IO requested but not done\n");
- printf
- ("Read %u MBytes (actual %u MB, %u bytes), buffer size=%d KBytes\n",
- total_size_mb, (num * buf_size) / 1048576, num * buf_size,
- buf_size / 1024);
-
- if (rawp)
- free(rawp);
- res = close(sg_fd);
- if (res < 0) {
- perror(ME "close error");
- return 0;
- }
-#ifdef SG_DEBUG
- if (clear)
- printf("read buffer always zero\n");
- else
- printf("read buffer non-zero\n");
-#endif
- return 0;
-}
-
-/* Performs a 10 byte READ CAPACITY command and fetches response. There is
- * evidently a 16 byte READ CAPACITY command coming.
- * Return of 0 -> success, -1 -> failure */
-int do_readcap_10(int sg_fd, int pmi, unsigned int lba,
- unsigned int *last_sect, unsigned int *sect_sz)
-{
- int res;
- unsigned char rcCmdBlk[10] = { 0x25, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
- unsigned char rcBuff[RCAP_REPLY_LEN];
- unsigned char sense_b[SENSE_BUFF_SZ];
- sg_io_hdr_t io_hdr;
-
- if (pmi) { /* lbs only valid when pmi set */
- rcCmdBlk[8] |= 1;
- rcCmdBlk[2] = (lba >> 24) & 0xff;
- rcCmdBlk[3] = (lba >> 16) & 0xff;
- rcCmdBlk[4] = (lba >> 8) & 0xff;
- rcCmdBlk[5] = lba & 0xff;
- }
- memset(&io_hdr, 0, sizeof(sg_io_hdr_t));
- io_hdr.interface_id = 'S';
- io_hdr.cmd_len = sizeof(rcCmdBlk);
- io_hdr.mx_sb_len = sizeof(sense_b);
- io_hdr.dxfer_direction = SG_DXFER_FROM_DEV;
- io_hdr.dxfer_len = sizeof(rcBuff);
- io_hdr.dxferp = rcBuff;
- io_hdr.cmdp = rcCmdBlk;
- io_hdr.sbp = sense_b;
- io_hdr.timeout = 60000;
-
- while (1) {
- if (ioctl(sg_fd, SG_IO, &io_hdr) < 0) {
- perror("read_capacity (SG_IO) error");
- return -1;
- }
- res = sg_err_category3(&io_hdr);
- if (SG_ERR_CAT_MEDIA_CHANGED == res)
- continue;
- else if (SG_ERR_CAT_CLEAN != res) {
- sg_chk_n_print3("READ CAPACITY command error", &io_hdr);
- return -1;
- } else
- break;
- }
- *last_sect = ((rcBuff[0] << 24) | (rcBuff[1] << 16) |
- (rcBuff[2] << 8) | rcBuff[3]);
- *sect_sz = (rcBuff[4] << 24) | (rcBuff[5] << 16) |
- (rcBuff[6] << 8) | rcBuff[7];
- return 0;
-}
-
-int show_scsi_read_capacity(char *device)
-{
- int sg_fd, k, res;
- unsigned int lba = 0;
- int pmi = 1;
- unsigned int last_blk_addr, block_size;
- char ebuff[EBUFF_SZ];
- const char *file_name = 0;
-
- print_msg(TEST_BREAK, __FUNCTION__);
-
- file_name = device;
-
- if ((0 == pmi) && (lba > 0)) {
- fprintf(stderr,
- ME "lba can only be non-zero when pmi is set\n");
- usage();
- return 1;
- }
- if ((sg_fd = open(file_name, O_RDONLY)) < 0) {
- snprintf(ebuff, EBUFF_SZ, ME "error opening file: %s",
- file_name);
- perror(ebuff);
- return 1;
- }
- /* Just to be safe, check we have a new sg device by trying an ioctl */
- if ((ioctl(sg_fd, SG_GET_VERSION_NUM, &k) < 0) || (k < 30000)) {
- printf(ME "%s doesn't seem to be a version 3 sg device\n",
- file_name);
- close(sg_fd);
- return 1;
- }
- res = do_readcap_10(sg_fd, pmi, lba, &last_blk_addr, &block_size);
-
- if (0 == res) {
- printf("Read Capacity results:\n");
- if (pmi)
- printf(" PMI mode: given lba=0x%x, last block before "
- "delay=0x%x\n", lba, last_blk_addr);
- else
- printf
- (" Last block address=%u (0x%x), Number of blocks=%u\n",
- last_blk_addr, last_blk_addr, last_blk_addr + 1);
- printf(" Block size = %u bytes\n", block_size);
- }
- close(sg_fd);
- return 0;
-}
-
-int do_scsi_reset_devices(char *device, int reset_opt)
-{
- int sg_fd, res, k;
- int do_device_reset = 0;
- int do_bus_reset = 0;
- int do_host_reset = 0;
- char *file_name = 0;
-
- switch (reset_opt) {
- case DEVICE_RESET:
- print_msg(TEST_BREAK, __FUNCTION__);
- do_device_reset = 1;
- break;
- case HOST_RESET:
- do_host_reset = 1;
- break;
- case BUS_RESET:
- do_bus_reset = 1;
- break;
- }
-
- file_name = device;
-
- sg_fd = open(file_name, O_RDWR | O_NONBLOCK);
- if (sg_fd < 0) {
- perror("sg_reset: open error");
- return 1;
- }
-
- k = SG_SCSI_RESET_NOTHING;
- if (do_device_reset) {
- printf("sg_reset: starting device reset\n");
- k = SG_SCSI_RESET_DEVICE;
- } else if (do_bus_reset) {
- printf("sg_reset: starting bus reset\n");
- k = SG_SCSI_RESET_BUS;
- } else if (do_host_reset) {
- printf("sg_reset: starting host reset\n");
- k = SG_SCSI_RESET_HOST;
- }
-
- res = ioctl(sg_fd, SG_SCSI_RESET, &k);
- if (res < 0) {
- if (EBUSY == errno)
- printf("sg_reset: BUSY, may be resetting now\n");
- else if (EIO == errno)
- printf
- ("sg_reset: requested type of reset may not be available\n");
- else if (EACCES == errno)
- printf("sg_reset: reset requires CAP_SYS_ADMIN (root) "
- "permission\n");
- else if (EINVAL == errno)
- printf("sg_reset: SG_SCSI_RESET not supported\n");
- else if (EIO == errno)
- printf("sg_reset: scsi_reset_provider() call failed\n");
- else
- perror("sg_reset: SG_SCSI_RESET failed");
- return 1;
- }
- if (SG_SCSI_RESET_NOTHING == k)
- printf("sg_reset: did nothing, device is normal mode\n");
- else if (SG_SCSI_RESET_DEVICE == k)
- printf("sg_reset: completed device reset\n");
- else if (SG_SCSI_RESET_BUS == k)
- printf("sg_reset: completed bus reset\n");
- else if (SG_SCSI_RESET_HOST == k)
- printf("sg_reset: completed host reset\n");
-
- if (close(sg_fd) < 0) {
- perror("sg_reset: close error");
- return 1;
- }
- return 0;
-}
-
-static int do_senddiag(int sg_fd, int sf_code, int pf_bit, int sf_bit,
- int devofl_bit, int unitofl_bit, void *outgoing_pg,
- int outgoing_len, int noisy)
-{
- int res;
- unsigned char senddiagCmdBlk[SEND_DIAGNOSTIC_CMDLEN] =
- { SEND_DIAGNOSTIC_CMD, 0, 0, 0, 0, 0 };
- unsigned char sense_b[SENSE_BUFF_LEN];
- sg_io_hdr_t io_hdr;
-
- senddiagCmdBlk[1] = (unsigned char)((sf_code << 5) | (pf_bit << 4) |
- (sf_bit << 2) | (devofl_bit << 1) |
- unitofl_bit);
- senddiagCmdBlk[3] = (unsigned char)((outgoing_len >> 8) & 0xff);
- senddiagCmdBlk[4] = (unsigned char)(outgoing_len & 0xff);
-
- memset(&io_hdr, 0, sizeof(sg_io_hdr_t));
- io_hdr.interface_id = 'S';
- io_hdr.cmd_len = SEND_DIAGNOSTIC_CMDLEN;
- io_hdr.mx_sb_len = sizeof(sense_b);
- io_hdr.dxfer_direction = outgoing_len ? SG_DXFER_TO_DEV : SG_DXFER_NONE;
- io_hdr.dxfer_len = outgoing_len;
- io_hdr.dxferp = outgoing_pg;
- io_hdr.cmdp = senddiagCmdBlk;
- io_hdr.sbp = sense_b;
- io_hdr.timeout = LONG_TIMEOUT;
-
- if (ioctl(sg_fd, SG_IO, &io_hdr) < 0) {
- perror("SG_IO (send diagnostic) error");
- return -1;
- }
- res = sg_err_category3(&io_hdr);
- switch (res) {
- case SG_ERR_CAT_CLEAN:
- case SG_ERR_CAT_RECOVERED:
- return 0;
- default:
- if (noisy) {
- char ebuff[EBUFF_SZ];
- snprintf(ebuff, EBUFF_SZ,
- "Send diagnostic error, sf_code=0x%x, "
- "pf_bit=%d, sf_bit=%d ", sf_code, pf_bit,
- sf_bit);
- sg_chk_n_print3(ebuff, &io_hdr);
- }
- return -1;
- }
-}
-
-static int do_rcvdiag(int sg_fd, int pcv, int pg_code, void *resp,
- int mx_resp_len, int noisy)
-{
- int res;
- unsigned char rcvdiagCmdBlk[RECEIVE_DIAGNOSTIC_CMDLEN] =
- { RECEIVE_DIAGNOSTIC_CMD, 0, 0, 0, 0, 0 };
- unsigned char sense_b[SENSE_BUFF_LEN];
- sg_io_hdr_t io_hdr;
-
- rcvdiagCmdBlk[1] = (unsigned char)(pcv ? 0x1 : 0);
- rcvdiagCmdBlk[2] = (unsigned char)(pg_code);
- rcvdiagCmdBlk[3] = (unsigned char)((mx_resp_len >> 8) & 0xff);
- rcvdiagCmdBlk[4] = (unsigned char)(mx_resp_len & 0xff);
-
- memset(&io_hdr, 0, sizeof(sg_io_hdr_t));
- io_hdr.interface_id = 'S';
- io_hdr.cmd_len = RECEIVE_DIAGNOSTIC_CMDLEN;
- io_hdr.mx_sb_len = sizeof(sense_b);
- io_hdr.dxfer_direction = SG_DXFER_FROM_DEV;
- io_hdr.dxfer_len = mx_resp_len;
- io_hdr.dxferp = resp;
- io_hdr.cmdp = rcvdiagCmdBlk;
- io_hdr.sbp = sense_b;
- io_hdr.timeout = DEF_TIMEOUT;
-
- if (ioctl(sg_fd, SG_IO, &io_hdr) < 0) {
- perror("SG_IO (receive diagnostic) error");
- return -1;
- }
- res = sg_err_category3(&io_hdr);
- switch (res) {
- case SG_ERR_CAT_CLEAN:
- case SG_ERR_CAT_RECOVERED:
- return 0;
- default:
- if (noisy) {
- char ebuff[EBUFF_SZ];
- snprintf(ebuff, EBUFF_SZ,
- "Receive diagnostic error, pcv=%d, "
- "page_code=%x ", pcv, pg_code);
- sg_chk_n_print3(ebuff, &io_hdr);
- }
- return -1;
- }
-}
-
-/* Get last extended self-test time from mode page 0xa (for '-e' option) */
-static int do_modes_0a(int sg_fd, void *resp, int mx_resp_len, int noisy,
- int mode6)
-{
- int res;
- unsigned char modesCmdBlk[MODE_SENSE10_CMDLEN] =
- { MODE_SENSE10_CMD, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
- unsigned char sense_b[SENSE_BUFF_LEN];
- sg_io_hdr_t io_hdr;
- int dbd = 1;
- int pc = 0;
- int pg_code = 0xa;
-
- modesCmdBlk[1] = (unsigned char)(dbd ? 0x8 : 0);
- modesCmdBlk[2] = (unsigned char)(((pc << 6) & 0xc0) | (pg_code & 0x3f));
- if (mx_resp_len > (mode6 ? 0xff : 0xffff)) {
- printf(ME "mx_resp_len too big\n");
- return -1;
- }
- if (mode6) {
- modesCmdBlk[0] = MODE_SENSE6_CMD;
- modesCmdBlk[4] = (unsigned char)(mx_resp_len & 0xff);
- } else {
- modesCmdBlk[7] = (unsigned char)((mx_resp_len >> 8) & 0xff);
- modesCmdBlk[8] = (unsigned char)(mx_resp_len & 0xff);
- }
-
- memset(&io_hdr, 0, sizeof(sg_io_hdr_t));
- io_hdr.interface_id = 'S';
- io_hdr.cmd_len = mode6 ? MODE_SENSE6_CMDLEN : MODE_SENSE10_CMDLEN;
- io_hdr.mx_sb_len = sizeof(sense_b);
- io_hdr.dxfer_direction = SG_DXFER_FROM_DEV;
- io_hdr.dxfer_len = mx_resp_len;
- io_hdr.dxferp = resp;
- io_hdr.cmdp = modesCmdBlk;
- io_hdr.sbp = sense_b;
- io_hdr.timeout = DEF_TIMEOUT;
-
- if (ioctl(sg_fd, SG_IO, &io_hdr) < 0) {
- perror("SG_IO (mode sense) error");
- return -1;
- }
- res = sg_err_category3(&io_hdr);
- switch (res) {
- case SG_ERR_CAT_CLEAN:
- case SG_ERR_CAT_RECOVERED:
- return 0;
- default:
- if (noisy) {
- char ebuff[EBUFF_SZ];
- snprintf(ebuff, EBUFF_SZ, "Mode sense error, dbd=%d, "
- "pc=%d, page_code=%x ", dbd, pc, pg_code);
- sg_chk_n_print3(ebuff, &io_hdr);
- }
- return -1;
- }
-}
-
-int do_scsi_send_diagnostics(char *device)
-{
- int sg_fd, k, num, rsp_len;
- char *file_name = 0;
- unsigned char rsp_buff[MODE_ALLOC_LEN];
- int rsp_buff_size = MODE_ALLOC_LEN;
- int self_test_code = 6;
- int do_pf = 0;
- int do_doff = 0;
- int do_def_test = 0;
- int do_uoff = 0;
- int oflags = O_RDWR;
-
- print_msg(TEST_BREAK, __FUNCTION__);
-
- file_name = device;
-
- if ((sg_fd = open(file_name, oflags)) < 0) {
- snprintf(ebuff, EBUFF_SZ, ME "error opening file: %s",
- file_name);
- perror(ebuff);
- return 1;
- }
- /* Just to be safe, check we have a new sg device by trying an ioctl */
- if ((ioctl(sg_fd, SG_GET_VERSION_NUM, &k) < 0) || (k < 30000)) {
- printf(ME "%s doesn't seem to be a version 3 sg device\n",
- file_name);
- close(sg_fd);
- return 1;
- }
-
- if (0 == do_modes_0a(sg_fd, rsp_buff, 32, 1, 0)) {
- /* Assume mode sense(10) response without block descriptors */
- num = (rsp_buff[0] << 8) + rsp_buff[1] - 6;
- if (num >= 0xc) {
- int secs;
-
- secs = (rsp_buff[18] << 8) + rsp_buff[19];
- printf
- ("Previous extended self-test duration=%d seconds "
- "(%.2f minutes)\n", secs, secs / 60.0);
- } else
- printf("Extended self-test duration not available\n");
- } else
- printf("Extended self-test duration (mode page 0xa) failed\n");
-
- memset(rsp_buff, 0, sizeof(rsp_buff));
- if (0 == do_senddiag(sg_fd, 0, do_pf, 0, 0, 0, rsp_buff, 4, 1)) {
- if (0 == do_rcvdiag(sg_fd, 0, 0, rsp_buff, rsp_buff_size, 1)) {
- printf("Supported diagnostic pages response:\n");
- rsp_len = (rsp_buff[2] << 8) + rsp_buff[3] + 4;
- for (k = 0; k < (rsp_len - 4); ++k)
- printf(" %s\n",
- find_page_code_desc(rsp_buff[k + 4], 0));
- }
- }
-
- if (0 == do_senddiag(sg_fd, self_test_code, do_pf, do_def_test,
- do_doff, do_uoff, NULL, 0, 1)) {
- if ((5 == self_test_code) || (6 == self_test_code))
- printf("Foreground self test returned GOOD status\n");
- else if (do_def_test && (!do_doff) && (!do_uoff))
- printf("Default self test returned GOOD status\n");
- }
- close(sg_fd);
- return 0;
-}
-
-static void do_start_stop(int fd, int start, int immed, int loej,
- int power_conditions)
-{
- unsigned char cmdblk[6] = {
- START_STOP, /* Command */
- 0, /* Resvd/Immed */
- 0, /* Reserved */
- 0, /* Reserved */
- 0, /* PowCond/Resvd/LoEj/Start */
- 0
- }; /* Reserved/Flag/Link */
- unsigned char sense_b[32];
- sg_io_hdr_t io_hdr;
- int k, res, debug = 1;
-
- memset(&io_hdr, 0, sizeof(sg_io_hdr_t));
- cmdblk[1] = immed & 1;
- cmdblk[4] = ((power_conditions & 0xf) << 4) |
- ((loej & 1) << 1) | (start & 1);
- io_hdr.interface_id = 'S';
- io_hdr.cmd_len = sizeof(cmdblk);
- io_hdr.mx_sb_len = sizeof(sense_b);
- io_hdr.dxfer_direction = SG_DXFER_NONE;
- io_hdr.dxfer_len = 0;
- io_hdr.dxferp = NULL;
- io_hdr.cmdp = cmdblk;
- io_hdr.sbp = sense_b;
- io_hdr.timeout = DEF_START_TIMEOUT;
-
- if (debug) {
- printf(" Start/Stop command:");
- for (k = 0; k < 6; ++k)
- printf(" %02x", cmdblk[k]);
- printf("\n");
- }
-
- if (ioctl(fd, SG_IO, &io_hdr) < 0) {
- perror("start_stop (SG_IO) error");
- return;
- }
- res = sg_err_category3(&io_hdr);
- if (SG_ERR_CAT_MEDIA_CHANGED == res) {
- fprintf(stderr, "media change report, try start_stop again\n");
- if (ioctl(fd, SG_IO, &io_hdr) < 0) {
- perror("start_stop (SG_IO) error");
- return;
- }
- }
- if (SG_ERR_CAT_CLEAN != res) {
- sg_chk_n_print3("start_stop", &io_hdr);
- return;
- }
- if (debug)
- fprintf(stderr, "start_stop [%s] successful\n",
- start ? "start" : "stop");
-}
-
-static void do_sync_cache(int fd)
-{
- unsigned char cmdblk[10] = {
- SYNCHRONIZE_CACHE, /* Command */
- 0, /* Immed (2) */
- 0, 0, 0, 0, /* LBA */
- 0, /* Reserved */
- 0, 0, /* No of blocks */
- 0
- }; /* Reserved/Flag/Link */
- unsigned char sense_b[32];
- sg_io_hdr_t io_hdr;
- int res, debug = 1;
-
- memset(&io_hdr, 0, sizeof(sg_io_hdr_t));
- io_hdr.interface_id = 'S';
- io_hdr.cmd_len = sizeof(cmdblk);
- io_hdr.mx_sb_len = sizeof(sense_b);
- io_hdr.dxfer_direction = SG_DXFER_NONE;
- io_hdr.dxfer_len = 0;
- io_hdr.dxferp = NULL;
- io_hdr.cmdp = cmdblk;
- io_hdr.sbp = sense_b;
- io_hdr.timeout = DEF_START_TIMEOUT;
-
- if (ioctl(fd, SG_IO, &io_hdr) < 0) {
- perror("sync_cache (SG_IO) error");
- return;
- }
- res = sg_err_category3(&io_hdr);
- if (SG_ERR_CAT_MEDIA_CHANGED == res) {
- fprintf(stderr, "media change report, try sync_cache again\n");
- if (ioctl(fd, SG_IO, &io_hdr) < 0) {
- perror("sync_cache (SG_IO) error");
- return;
- }
- }
- if (SG_ERR_CAT_CLEAN != res) {
- sg_chk_n_print3("sync_cache", &io_hdr);
- return;
- }
- if (debug)
- fprintf(stderr, "synchronize cache successful\n");
-}
-
-int do_scsi_start_stop(char *device, int startstop)
-{
- int synccache = 1;
- char *file_name = 0;
- int fd;
- int immed = 1;
- int loej = 0;
- int power_conds = 0;
-
- print_msg(TEST_BREAK, __FUNCTION__);
-
- file_name = device;
-
- fd = open(file_name, O_RDWR | O_NONBLOCK);
- if (fd < 0) {
- fprintf(stderr, "Error trying to open %s\n", file_name);
- perror("");
- usage();
- return 2;
- }
- if (ioctl(fd, SG_GET_TIMEOUT, 0) < 0) {
- fprintf(stderr, "Given file not block or SCSI "
- "generic device\n");
- close(fd);
- return 3;
- }
-
- if (synccache)
- do_sync_cache(fd);
-
- if (power_conds > 0)
- do_start_stop(fd, 0, immed, 0, power_conds);
- else if (startstop != -1)
- do_start_stop(fd, startstop, immed, loej, 0);
-
- close(fd);
- return 0;
-}
-
-int find_out_about_buffer(int sg_fd, int *buf_capacity, char *file_name)
-{
- int res, buf_granul = 255;
- unsigned char *rbBuff = malloc(OFF + sizeof(rbCmdBlk) + 512);
- struct sg_header *rsghp = (struct sg_header *)rbBuff;
- int rbInLen = OFF + RB_DESC_LEN;
- int rbOutLen = OFF + sizeof(rbCmdBlk);
- unsigned char *buffp = rbBuff + OFF;
- rsghp->pack_len = 0; /* don't care */
- rsghp->pack_id = 0;
- rsghp->reply_len = rbInLen;
- rsghp->twelve_byte = 0;
- rsghp->result = 0;
-#ifndef SG_GET_RESERVED_SIZE
- rsghp->sense_buffer[0] = 0;
-#endif
- memcpy(rbBuff + OFF, rbCmdBlk, sizeof(rbCmdBlk));
- rbBuff[OFF + 1] = RB_MODE_DESC;
- rbBuff[OFF + 8] = RB_DESC_LEN;
-
- res = write(sg_fd, rbBuff, rbOutLen);
- if (res < 0) {
- perror("sg_test_rwbuf: write (desc) error");
- if (rbBuff)
- free(rbBuff);
- return 1;
- }
- if (res < rbOutLen) {
- printf("sg_test_rwbuf: wrote less (desc), ask=%d, got=%d\n",
- rbOutLen, res);
- if (rbBuff)
- free(rbBuff);
- return 1;
- }
-
- memset(rbBuff + OFF, 0, RB_DESC_LEN);
- res = read(sg_fd, rbBuff, rbInLen);
- if (res < 0) {
- perror("sg_test_rwbuf: read (desc) error");
- if (rbBuff)
- free(rbBuff);
- return 1;
- }
- if (res < rbInLen) {
- printf("sg_test_rwbuf: read less (desc), ask=%d, got=%d\n",
- rbInLen, res);
- if (rbBuff)
- free(rbBuff);
- return 1;
- }
-#ifdef SG_GET_RESERVED_SIZE
- if (!sg_chk_n_print("sg_test_rwbuf: desc", rsghp->target_status,
- rsghp->host_status, rsghp->driver_status,
- rsghp->sense_buffer, SG_MAX_SENSE)) {
- printf
- ("sg_test_rwbuf: perhaps %s doesn't support READ BUFFER\n",
- file_name);
- if (rbBuff)
- free(rbBuff);
- return 1;
- }
-#else
- if ((rsghp->result != 0) || (0 != rsghp->sense_buffer[0])) {
- printf("sg_test_rwbuf: read(desc) result=%d\n", rsghp->result);
- if (0 != rsghp->sense_buffer[0])
- sg_print_sense("sg_test_rwbuf: desc",
- rsghp->sense_buffer, SG_MAX_SENSE);
- printf
- ("sg_test_rwbuf: perhaps %s doesn't support READ BUFFER\n",
- file_name);
- if (rbBuff)
- free(rbBuff);
- return 1;
- }
-#endif
- *(buf_capacity) = ((buffp[1] << 16) | (buffp[2] << 8) | buffp[3]);
- buf_granul = (unsigned char)buffp[0];
-
- printf("READ BUFFER reports: %02x %02x %02x %02x %02x %02x %02x %02x\n",
- buffp[0], buffp[1], buffp[2], buffp[3],
- buffp[4], buffp[5], buffp[6], buffp[7]);
-
- printf("READ BUFFER reports: buffer capacity=%d, offset boundary=%d\n",
- *(buf_capacity), buf_granul);
-#ifdef SG_DEF_RESERVED_SIZE
- res = ioctl(sg_fd, SG_SET_RESERVED_SIZE, buf_capacity);
- if (res < 0)
- perror("sg_test_rwbuf: SG_SET_RESERVED_SIZE error");
-#endif
- return 0;
-}
-
-int mymemcmp(unsigned char *bf1, unsigned char *bf2, int len)
-{
- int df;
- for (df = 0; df < len; df++)
- if (bf1[df] != bf2[df])
- return df;
- return 0;
-}
-
-int do_checksum(int *buf, int len, int quiet)
-{
- int sum = base;
- int i;
- int rln = len;
- for (i = 0; i < len / BPI; i++)
- sum += buf[i];
- while (rln % BPI)
- sum += ((char *)buf)[--rln];
- if (sum != READWRITE_BASE_NUM) {
- if (!quiet)
- printf("sg_test_rwbuf: Checksum error (sz=%i): %08x\n",
- len, sum);
- if (cmpbuf && !quiet) {
- int diff = mymemcmp(cmpbuf, (unsigned char *)buf, len);
- printf("Differ at pos %i/%i:\n", diff, len);
- for (i = 0; i < 24 && i + diff < len; i++)
- printf(" %02x", cmpbuf[i + diff]);
- printf("\n");
- for (i = 0; i < 24 && i + diff < len; i++)
- printf(" %02x",
- ((unsigned char *)buf)[i + diff]);
- printf("\n");
- }
- return 2;
- } else
- return 0;
-}
-
-void do_fill_buffer(int *buf, int len)
-{
- int sum;
- int i;
- int rln = len;
- srand(time(0));
-retry:
- if (len >= BPI)
- base = READWRITE_BASE_NUM + rand();
- else
- base = READWRITE_BASE_NUM + (char)rand();
- sum = base;
- for (i = 0; i < len / BPI - 1; i++) {
- /* we rely on rand() giving full range of int */
- buf[i] = rand();
- sum += buf[i];
- }
- while (rln % BPI) {
- ((char *)buf)[--rln] = rand();
- sum += ((char *)buf)[rln];
- }
- if (len >= BPI)
- buf[len / BPI - 1] = READWRITE_BASE_NUM - sum;
- else
- ((char *)buf)[0] = READWRITE_BASE_NUM + ((char *)buf)[0] - sum;
- if (do_checksum(buf, len, 1)) {
- if (len < BPI)
- goto retry;
- printf("sg_test_rwbuf: Memory corruption?\n");
- exit(1);
- }
- if (cmpbuf)
- memcpy(cmpbuf, (char *)buf, len);
-}
-
-int read_buffer(int sg_fd, unsigned size)
-{
- int res;
- unsigned char *rbBuff = malloc(OFF + sizeof(rbCmdBlk) + size);
- struct sg_header *rsghp = (struct sg_header *)rbBuff;
-
- int rbInLen = OFF + size;
- int rbOutLen = OFF + sizeof(rbCmdBlk);
- memset(rbBuff, 0, OFF + sizeof(rbCmdBlk) + size);
- rsghp->pack_len = 0; /* don't care */
- rsghp->reply_len = rbInLen;
- rsghp->twelve_byte = 0;
- rsghp->result = 0;
- memcpy(rbBuff + OFF, rbCmdBlk, sizeof(rbCmdBlk));
- rbBuff[OFF + 1] = RB_MODE_DATA;
- rbBuff[OFF + 6] = 0xff & ((size) >> 16);
- rbBuff[OFF + 7] = 0xff & ((size) >> 8);
- rbBuff[OFF + 8] = 0xff & (size);
-
- rsghp->pack_id = 2;
- res = write(sg_fd, rbBuff, rbOutLen);
- if (res < 0) {
- perror("sg_test_rwbuf: write (data) error");
- if (rbBuff)
- free(rbBuff);
- return 1;
- }
- if (res < rbOutLen) {
- printf("sg_test_rwbuf: wrote less (data), ask=%d, got=%d\n",
- rbOutLen, res);
- if (rbBuff)
- free(rbBuff);
- return 1;
- }
-
- res = read(sg_fd, rbBuff, rbInLen);
- if (res < 0) {
- perror("sg_test_rwbuf: read (data) error");
- if (rbBuff)
- free(rbBuff);
- return 1;
- }
- if (res < rbInLen) {
- printf("sg_test_rwbuf: read less (data), ask=%d, got=%d\n",
- rbInLen, res);
- if (rbBuff)
- free(rbBuff);
- return 1;
- }
- res = do_checksum((int *)(rbBuff + OFF), size, 0);
- if (rbBuff)
- free(rbBuff);
- return res;
-}
-
-int write_buffer(int sg_fd, unsigned size)
-{
- int res;
- unsigned char *rbBuff = malloc(OFF + sizeof(rbCmdBlk) + size);
- struct sg_header *rsghp = (struct sg_header *)rbBuff;
- //unsigned char * buffp = rbBuff + OFF;
-
- int rbInLen = OFF;
- int rbOutLen = OFF + sizeof(rbCmdBlk) + size;
-
- do_fill_buffer((int *)(rbBuff + OFF + sizeof(rbCmdBlk)), size);
- rsghp->pack_len = 0; /* don't care */
- rsghp->reply_len = rbInLen;
- rsghp->twelve_byte = 0;
- rsghp->result = 0;
- memcpy(rbBuff + OFF, rbCmdBlk, sizeof(rbCmdBlk));
- rbBuff[OFF + 0] = WRITE_BUFFER;
- rbBuff[OFF + 1] = RB_MODE_DATA;
- rbBuff[OFF + 6] = 0xff & ((size) >> 16);
- rbBuff[OFF + 7] = 0xff & ((size) >> 8);
- rbBuff[OFF + 8] = 0xff & (size);
-
- rsghp->pack_id = 1;
- res = write(sg_fd, rbBuff, rbOutLen);
- if (res < 0) {
- perror("sg_test_rwbuf: write (data) error");
- if (rbBuff)
- free(rbBuff);
- return 1;
- }
- if (res < rbOutLen) {
- printf("sg_test_rwbuf: wrote less (data), ask=%d, got=%d\n",
- rbOutLen, res);
- if (rbBuff)
- free(rbBuff);
- return 1;
- }
-
- res = read(sg_fd, rbBuff, rbInLen);
- if (res < 0) {
- perror("sg_test_rwbuf: read (status) error");
- if (rbBuff)
- free(rbBuff);
- return 1;
- }
- if (rbBuff)
- free(rbBuff);
- return 0;
-}
-
-int do_scsi_read_write_buffer(char *device)
-{
- int sg_fd;
- int res, buf_capacity;
- char *file_name = device;
- struct stat a_st;
- int block_dev = 0;
-
- print_msg(TEST_BREAK, __FUNCTION__);
-
- sg_fd = open(file_name, O_RDWR);
- if (sg_fd < 0) {
- perror("sg_test_rwbuf: open error");
- return 1;
- }
- if (fstat(sg_fd, &a_st) < 0) {
- fprintf(stderr, "could do fstat() on fd ??\n");
- close(sg_fd);
- return 1;
- }
- if (S_ISBLK(a_st.st_mode))
- block_dev = 1;
- /* Don't worry, being very careful not to write to a none-sg file ... */
- if (block_dev || (ioctl(sg_fd, SG_GET_TIMEOUT, 0) < 0)) {
- /* perror("ioctl on generic device, error"); */
- printf("sg_test_rwbuf: not a sg device, or wrong driver\n");
- return 1;
- }
- if (find_out_about_buffer(sg_fd, &buf_capacity, file_name))
- return 1;
-
- cmpbuf = malloc(buf_capacity);
- if (write_buffer(sg_fd, buf_capacity))
- return 3;
- res = read_buffer(sg_fd, buf_capacity);
- if (res)
- return (res + 4);
-
- res = close(sg_fd);
- if (res < 0) {
- perror("sg_test_rwbuf: close error");
- return 6;
- }
- printf("Success\n");
- return 0;
-}
-
-int do_scsi_test_unit_ready(char *device)
-{
- int sg_fd, k;
- unsigned char turCmdBlk[TUR_CMD_LEN] = { 0x00, 0, 0, 0, 0, 0 };
- sg_io_hdr_t io_hdr;
- char *file_name = device;
- char ebuff[EBUFF_SZ];
- unsigned char sense_buffer[32];
- int num_turs = 10240;
- int num_errs = 0;
- int do_time = 1;
- struct timeval start_tm, end_tm;
-
- print_msg(TEST_BREAK, __FUNCTION__);
-
- if ((sg_fd = open(file_name, O_RDONLY)) < 0) {
- snprintf(ebuff, EBUFF_SZ,
- "sg_turs: error opening file: %s", file_name);
- perror(ebuff);
- return 1;
- }
- /* Just to be safe, check we have a new sg driver by trying an ioctl */
- if ((ioctl(sg_fd, SG_GET_VERSION_NUM, &k) < 0) || (k < 30000)) {
- printf
- ("sg_turs: %s isn't an sg device (or the sg driver is old)\n",
- file_name);
- close(sg_fd);
- return 1;
- }
- /* Prepare TEST UNIT READY command */
- memset(&io_hdr, 0, sizeof(sg_io_hdr_t));
- io_hdr.interface_id = 'S';
- io_hdr.cmd_len = sizeof(turCmdBlk);
- io_hdr.mx_sb_len = sizeof(sense_buffer);
- io_hdr.dxfer_direction = SG_DXFER_NONE;
- io_hdr.cmdp = turCmdBlk;
- io_hdr.sbp = sense_buffer;
- io_hdr.timeout = 20000; /* 20000 millisecs == 20 seconds */
- if (do_time) {
- start_tm.tv_sec = 0;
- start_tm.tv_usec = 0;
- gettimeofday(&start_tm, NULL);
- }
- for (k = 0; k < num_turs; ++k) {
- io_hdr.pack_id = k;
- if (ioctl(sg_fd, SG_IO, &io_hdr) < 0) {
- perror("sg_turs: Test Unit Ready SG_IO ioctl error");
- close(sg_fd);
- return 1;
- }
- if (io_hdr.info & SG_INFO_OK_MASK) {
- ++num_errs;
- if (1 == num_turs) { /* then print out the error message */
- if (SG_ERR_CAT_CLEAN !=
- sg_err_category3(&io_hdr))
- sg_chk_n_print3("tur", &io_hdr);
- }
- }
- }
- if ((do_time) && (start_tm.tv_sec || start_tm.tv_usec)) {
- struct timeval res_tm;
- double a, b;
-
- gettimeofday(&end_tm, NULL);
- res_tm.tv_sec = end_tm.tv_sec - start_tm.tv_sec;
- res_tm.tv_usec = end_tm.tv_usec - start_tm.tv_usec;
- if (res_tm.tv_usec < 0) {
- --res_tm.tv_sec;
- res_tm.tv_usec += 1000000;
- }
- a = res_tm.tv_sec;
- a += (0.000001 * res_tm.tv_usec);
- b = (double)num_turs;
- printf("time to perform commands was %d.%06d secs",
- (int)res_tm.tv_sec, (int)res_tm.tv_usec);
- if (a > 0.00001)
- printf("; %.2f operations/sec\n", b / a);
- else
- printf("\n");
- }
-
- printf("Completed %d Test Unit Ready commands with %d errors\n",
- num_turs, num_errs);
- close(sg_fd);
- return 0;
-}
-
-/* Returns 0 -> ok, 1 -> err, 2 -> recovered error */
-static int do_sg_io(int sg_fd, unsigned char *buff)
-{
-/* N.B. Assuming buff contains pointer 'buffer' or 'buffer1' */
- struct sg_header *sghp = (struct sg_header *)(buff - OFF);
- int res;
-
- sghp->pack_len = 0;
- sghp->reply_len = SG_HSZ + *(((int *)buff) + 1);
- sghp->pack_id = 0;
- sghp->twelve_byte = 0;
- sghp->other_flags = 0;
-#ifndef SG_GET_RESERVED_SIZE
- sghp->sense_buffer[0] = 0;
-#endif
-#if 0
- sg_print_command(buff + 8);
- printf(" write_len=%d, read_len=%d\n",
- SG_HSZ + sg_get_command_size(buff[8]) + *((int *)buff),
- sghp->reply_len);
-#endif
- res = write(sg_fd, (const void *)sghp,
- SG_HSZ + sg_get_command_size(buff[8]) + *((int *)buff));
- if (res < 0) {
-#ifdef SG_IO_DEBUG
- perror("write to sg failed");
-#endif
- return 1;
- }
- res = read(sg_fd, (void *)sghp, sghp->reply_len);
- if (res < 0) {
-#ifdef SG_IO_DEBUG
- perror("read from sg failed");
-#endif
- return 1;
- }
-#ifdef SG_GET_RESERVED_SIZE
- res = sg_err_category(sghp->target_status, sghp->host_status,
- sghp->driver_status, sghp->sense_buffer,
- SG_MAX_SENSE);
- switch (res) {
- case SG_ERR_CAT_CLEAN:
- return 0;
- case SG_ERR_CAT_RECOVERED:
- return 2;
- default:
-#ifdef SG_IO_DEBUG
- sg_chk_n_print("read from sg", sghp->target_status,
- sghp->host_status, sghp->driver_status,
- sghp->sense_buffer, SG_MAX_SENSE);
-#endif
- return 1;
- }
-#else
- if (0 != sghp->sense_buffer[0]) {
-#ifdef SG_IO_DEBUG
- int k;
- printf("read from sg, sense buffer (in hex):\n ");
- for (k = 0; k < 16; ++k)
- printf("%02x ", (int)sghp->sense_buffer[k]);
- printf("\n");
-#endif
- return 1;
- } else if (0 != sghp->result) {
-#ifdef SG_IO_DEBUG
- printf("read from sg, bad result=%d\n", sghp->result);
-#endif
- return 1;
- } else
- return 0;
-#endif
-}
-
-static char *get_page_name(int pageno)
-{
- if ((pageno <= 0) || (pageno >= MAX_PAGENO) || (!page_names[pageno]))
- return "Mode";
- return page_names[pageno];
-}
-
-static int getnbyte(unsigned char *pnt, int nbyte)
-{
- unsigned int result;
- int i;
- result = 0;
- for (i = 0; i < nbyte; i++)
- result = (result << 8) | (pnt[i] & 0xff);
- return result;
-}
-
-static void bitfield(unsigned char *pageaddr, char *text, int mask, int shift)
-{
- printf("%-35s%d\n", text, (*pageaddr >> shift) & mask);
-}
-
-static void notbitfield(unsigned char *pageaddr, char *text, int mask,
- int shift)
-{
- printf("%-35s%d\n", text, !((*pageaddr >> shift) & mask));
-}
-
-static void intfield(unsigned char *pageaddr, int nbytes, char *text)
-{
- printf("%-35s%d\n", text, getnbyte(pageaddr, nbytes));
-}
-
-static void hexfield(unsigned char *pageaddr, int nbytes, char *text)
-{
- printf("%-35s0x%x\n", text, getnbyte(pageaddr, nbytes));
-}
-
-static void hexdatafield(unsigned char *pageaddr, int nbytes, char *text)
-{
- printf("%-35s0x", text);
- while (nbytes-- > 0)
- printf("%02x", *pageaddr++);
- putchar('\n');
-}
-
-static int get_mode_page(int page, int page_code)
-{
- int status, quiet;
- unsigned char *cmd;
-
- memset(buffer, 0, SIZEOF_BUFFER);
-
- quiet = page_code & ~3;
- page_code &= 3;
-
- *((int *)buffer) = 0; /* length of input data */
- *(((int *)buffer) + 1) = 0xff; /* length of output data */
-
- cmd = (unsigned char *)(((int *)buffer) + 2);
-
- cmd[0] = MODE_SENSE; /* MODE SENSE (6) */
- cmd[1] = 0x00; /* lun = 0, inhibitting BD makes this fail
- for me */
- cmd[2] = (page_code << 6) | page;
- cmd[3] = 0x00; /* (reserved) */
- cmd[4] = (unsigned char)0xff; /* allocation length */
- cmd[5] = 0x00; /* control */
-
- status = do_sg_io(glob_fd, buffer);
- if (status && (!quiet))
- fprintf(stdout, ">>> Unable to read %s Page %02xh\n",
- get_page_name(page), page);
- //dump (buffer+2, 46);
- return status;
-}
-
-/* Same as above, but this time with MODE_SENSE_10 */
-static int get_mode_page10(int page, int page_code)
-{
- int status, quiet;
- unsigned char *cmd;
-
- memset(buffer, 0, SIZEOF_BUFFER);
-
- quiet = page_code & ~3;
- page_code &= 3;
-
- *((int *)buffer) = 0; /* length of input data */
- *(((int *)buffer) + 1) = 0xffff; /* length of output buffer */
-
- cmd = (unsigned char *)(((int *)buffer) + 2);
-
- cmd[0] = MODE_SENSE_10; /* MODE SENSE (10) */
- cmd[1] = 0x00; /* lun = 0, inhibitting BD makes this fail
- for me */
- cmd[2] = (page_code << 6) | page;
- cmd[3] = 0x00; /* (reserved) */
- cmd[4] = 0x00; /* (reserved) */
- cmd[5] = 0x00; /* (reserved) */
- cmd[6] = 0x00; /* (reserved) */
- cmd[7] = 0xff; /* allocation length hi */
- cmd[8] = 0xff; /* allocation length lo */
- cmd[9] = 0x00; /* control */
-
- status = do_sg_io(glob_fd, buffer);
- if (status && (!quiet))
- fprintf(stdout,
- ">>> Unable to read %s Page %02xh with MODESENSE(10)\n",
- get_page_name(page), page);
- return status;
-}
-
-/* Contents should point to the mode parameter header that we obtained
- in a prior read operation. This way we do not have to work out the
- format of the beast */
-
-static int read_geometry(int page_code)
-{
- int status;
- int bdlen;
- unsigned char *pagestart;
-
- SETUP_MODE_PAGE(4, 9);
-
- printf("Data from Rigid Disk Drive Geometry Page\n");
- printf("----------------------------------------\n");
- intfield(pagestart + 2, 3, "Number of cylinders");
- intfield(pagestart + 5, 1, "Number of heads");
- intfield(pagestart + 6, 3, "Starting write precomp");
- intfield(pagestart + 9, 3, "Starting reduced current");
- intfield(pagestart + 12, 2, "Drive step rate");
- intfield(pagestart + 14, 3, "Landing Zone Cylinder");
- bitfield(pagestart + 17, "RPL", 3, 0);
- intfield(pagestart + 18, 1, "Rotational Offset");
- intfield(pagestart + 20, 2, "Rotational Rate");
- printf("\n");
- return 0;
-
-}
-
-static int read_disconnect_reconnect_data(int page_code)
-{
- int status;
- int bdlen;
- unsigned char *pagestart;
-
- SETUP_MODE_PAGE(2, 7);
-
- printf("Data from Disconnect-Reconnect Page\n");
- printf("-----------------------------------\n");
- intfield(pagestart + 2, 1, "Buffer full ratio");
- intfield(pagestart + 3, 1, "Buffer empty ratio");
- intfield(pagestart + 4, 2, "Bus Inactivity Limit");
- intfield(pagestart + 6, 2, "Disconnect Time Limit");
- intfield(pagestart + 8, 2, "Connect Time Limit");
- intfield(pagestart + 10, 2, "Maximum Burst Size");
- hexfield(pagestart + 12, 1, "DTDC");
- printf("\n");
- return 0;
-
-}
-
-static int read_control_page(int page_code)
-{
- int status;
- int bdlen;
- unsigned char *pagestart;
-
- SETUP_MODE_PAGE(10, 9);
-
- printf("Data from Control Page\n");
- printf("----------------------\n");
- bitfield(pagestart + 2, "RLEC", 1, 0);
- bitfield(pagestart + 3, "QErr", 1, 1);
- bitfield(pagestart + 3, "DQue", 1, 0);
- bitfield(pagestart + 4, "EECA", 1, 7);
- bitfield(pagestart + 4, "RAENP", 1, 2);
- bitfield(pagestart + 4, "UUAENP", 1, 1);
- bitfield(pagestart + 4, "EAENP", 1, 0);
- bitfield(pagestart + 3, "Queue Algorithm Modifier", 0xf, 4);
- intfield(pagestart + 6, 2, "Ready AEN Holdoff Period");
- printf("\n");
- return 0;
-
-}
-
-static int error_recovery_page(int page_code)
-{
- int status;
- int bdlen;
- unsigned char *pagestart;
-
- SETUP_MODE_PAGE(1, 14);
- printf("Data from Error Recovery Page\n");
- printf("-----------------------------\n");
- bitfield(pagestart + 2, "AWRE", 1, 7);
- bitfield(pagestart + 2, "ARRE", 1, 6);
- bitfield(pagestart + 2, "TB", 1, 5);
- bitfield(pagestart + 2, "RC", 1, 4);
- bitfield(pagestart + 2, "EER", 1, 3);
- bitfield(pagestart + 2, "PER", 1, 2);
- bitfield(pagestart + 2, "DTE", 1, 1);
- bitfield(pagestart + 2, "DCR", 1, 0);
- intfield(pagestart + 3, 1, "Read Retry Count");
- intfield(pagestart + 4, 1, "Correction Span");
- intfield(pagestart + 5, 1, "Head Offset Count");
- intfield(pagestart + 6, 1, "Data Strobe Offset Count");
- intfield(pagestart + 8, 1, "Write Retry Count");
- intfield(pagestart + 10, 2, "Recovery Time Limit");
- printf("\n");
- return 0;
-}
-
-static int notch_parameters_page(int page_code)
-{
- int status;
- int bdlen;
- unsigned char *pagestart;
-
- SETUP_MODE_PAGE(0xc, 7);
-
- printf("Data from Notch Parameters Page\n");
- printf("-------------------------------\n");
- bitfield(pagestart + 2, "Notched Drive", 1, 7);
- bitfield(pagestart + 2, "Logical or Physical Notch", 1, 6);
- intfield(pagestart + 4, 2, "Max # of notches");
- intfield(pagestart + 6, 2, "Active Notch");
- if (pagestart[2] & 0x40) {
- intfield(pagestart + 8, 4, "Starting Boundary");
- intfield(pagestart + 12, 4, "Ending Boundary");
- } else { /* Hex is more meaningful for physical notches */
- hexfield(pagestart + 8, 4, "Starting Boundary");
- hexfield(pagestart + 12, 4, "Ending Boundary");
- }
-
- printf("0x%8.8x%8.8x", getnbyte(pagestart + 16, 4),
- getnbyte(pagestart + 20, 4));
-
- printf("\n");
- return 0;
-}
-
-static char *formatname(int format)
-{
- switch (format) {
- case 0x0:
- return "logical blocks";
- case 0x4:
- return "bytes from index [Cyl:Head:Off]\n"
- "Offset -1 marks whole track as bad.\n";
- case 0x5:
- return "physical blocks [Cyl:Head:Sect]\n"
- "Sector -1 marks whole track as bad.\n";
- }
- return "Weird, unknown format";
-}
-
-static int read_defect_list(int page_code)
-{
- int status = 0, i, len, reallen, table, k;
- unsigned char *cmd, *df = 0;
- int trunc;
-
- printf("Data from Defect Lists\n" "----------------------\n");
- for (table = 0; table < 2; table++) {
- memset(buffer, 0, SIZEOF_BUFFER);
- trunc = 0;
-
- *((int *)buffer) = 0; /* length of input data */
- *(((int *)buffer) + 1) = 4; /* length of output buffer */
-
- cmd = (unsigned char *)(((int *)buffer) + 2);
-
- cmd[0] = 0x37; /* READ DEFECT DATA */
- cmd[1] = 0x00; /* lun=0 */
- cmd[2] = (table ? 0x08 : 0x10) | defectformat; /* List, Format */
- cmd[3] = 0x00; /* (reserved) */
- cmd[4] = 0x00; /* (reserved) */
- cmd[5] = 0x00; /* (reserved) */
- cmd[6] = 0x00; /* (reserved) */
- cmd[7] = 0x00; /* Alloc len */
- cmd[8] = 0x04; /* Alloc len */
- cmd[9] = 0x00; /* control */
-
- i = do_sg_io(glob_fd, buffer);
- if (2 == i)
- i = 0; /* Recovered error, probably returned a different
- format */
- if (i) {
- fprintf(stdout, ">>> Unable to read %s defect data.\n",
- (table ? "grown" : "manufacturer"));
- status |= i;
- continue;
- }
- len = (buffer[10] << 8) | buffer[11];
- reallen = len;
- if (len > 0) {
- if (len >= 0xfff8) {
- len = SIZEOF_BUFFER - 8;
- k = len + 8; /* length of defect list */
- *((int *)buffer) = 0; /* length of input data */
- *(((int *)buffer) + 1) = k; /* length of output buffer */
- ((struct sg_header *)buffer)->twelve_byte = 1;
- cmd[0] = 0xB7; /* READ DEFECT DATA */
- cmd[1] = (table ? 0x08 : 0x10) | defectformat; /* List, Format */
- cmd[2] = 0x00; /* (reserved) */
- cmd[3] = 0x00; /* (reserved) */
- cmd[4] = 0x00; /* (reserved) */
- cmd[5] = 0x00; /* (reserved) */
- cmd[6] = 0x00; /* Alloc len */
- cmd[7] = (k >> 16); /* Alloc len */
- cmd[8] = (k >> 8); /* Alloc len */
- cmd[9] = (k & 0xff); /* Alloc len */
- cmd[10] = 0x00; /* reserved */
- cmd[11] = 0x00; /* control */
- i = do_sg_io(glob_fd, buffer);
- if (i == 2)
- i = 0;
- if (i)
- goto trytenbyte;
- reallen =
- (buffer[12] << 24 | buffer[13] << 16 |
- buffer[14] << 8 | buffer[15]);
- len = reallen;
- if (len > SIZEOF_BUFFER - 8) {
- len = SIZEOF_BUFFER - 8;
- trunc = 1;
- }
- df = (unsigned char *)(buffer + 16);
- } else {
-trytenbyte:
- if (len > 0xfff8) {
- len = 0xfff8;
- trunc = 1;
- }
- k = len + 4; /* length of defect list */
- *((int *)buffer) = 0; /* length of input data */
- *(((int *)buffer) + 1) = k; /* length of output buffer */
- cmd[0] = 0x37; /* READ DEFECT DATA */
- cmd[1] = 0x00; /* lun=0 */
- cmd[2] = (table ? 0x08 : 0x10) | defectformat; /* List, Format */
- cmd[3] = 0x00; /* (reserved) */
- cmd[4] = 0x00; /* (reserved) */
- cmd[5] = 0x00; /* (reserved) */
- cmd[6] = 0x00; /* (reserved) */
- cmd[7] = (k >> 8); /* Alloc len */
- cmd[8] = (k & 0xff); /* Alloc len */
- cmd[9] = 0x00; /* control */
- i = do_sg_io(glob_fd, buffer);
- df = (unsigned char *)(buffer + 12);
- }
- }
- if (2 == i)
- i = 0; /* Recovered error, probably returned a different
- format */
- if (i) {
- fprintf(stdout, ">>> Unable to read %s defect data.\n",
- (table ? "grown" : "manufacturer"));
- status |= i;
- continue;
- } else {
- if (table && !status)
- printf("\n");
- printf("%d entries (%d bytes) in %s table.\n"
- "Format (%x) is: %s\n",
- reallen / ((buffer[9] & 7) ? 8 : 4), reallen,
- (table ? "grown" : "manufacturer"),
- buffer[9] & 7, formatname(buffer[9] & 7));
- i = 0;
- if ((buffer[9] & 7) == 4) {
- while (len > 0) {
- snprintf((char *)buffer, 40,
- "%6d:%3u:%8d", getnbyte(df, 3),
- df[3], getnbyte(df + 4, 4));
- printf("%19s", (char *)buffer);
- len -= 8;
- df += 8;
- i++;
- if (i >= 4) {
- printf("\n");
- i = 0;
- } else
- printf("|");
- }
- } else if ((buffer[9] & 7) == 5) {
- while (len > 0) {
- snprintf((char *)buffer, 40,
- "%6d:%2u:%5d", getnbyte(df, 3),
- df[3], getnbyte(df + 4, 4));
- printf("%15s", (char *)buffer);
- len -= 8;
- df += 8;
- i++;
- if (i >= 5) {
- printf("\n");
- i = 0;
- } else
- printf("|");
- }
- } else {
- while (len > 0) {
- printf("%10d", getnbyte(df, 4));
- len -= 4;
- df += 4;
- i++;
- if (i >= 7) {
- printf("\n");
- i = 0;
- } else
- printf("|");
- }
- }
- if (i)
- printf("\n");
- }
- if (trunc)
- printf("[truncated]\n");
- }
- printf("\n");
- return status;
-}
-
-static int read_cache(int page_code)
-{
- int status;
- int bdlen;
- unsigned char *pagestart;
-
- SETUP_MODE_PAGE(8, 9);
-
- printf("Data from Caching Page\n");
- printf("----------------------\n");
- bitfield(pagestart + 2, "Write Cache", 1, 2);
- notbitfield(pagestart + 2, "Read Cache", 1, 0);
- bitfield(pagestart + 2, "Prefetch units", 1, 1);
- bitfield(pagestart + 3, "Demand Read Retention Priority", 0xf, 4);
- bitfield(pagestart + 3, "Demand Write Retention Priority", 0xf, 0);
- intfield(pagestart + 4, 2, "Disable Pre-fetch Transfer Length");
- intfield(pagestart + 6, 2, "Minimum Pre-fetch");
- intfield(pagestart + 8, 2, "Maximum Pre-fetch");
- intfield(pagestart + 10, 2, "Maximum Pre-fetch Ceiling");
- printf("\n");
- return 0;
-}
-
-static int read_format_info(int page_code)
-{
- int status;
- int bdlen;
- unsigned char *pagestart;
-
- SETUP_MODE_PAGE(3, 13);
-
- printf("Data from Format Device Page\n");
- printf("----------------------------\n");
- bitfield(pagestart + 20, "Removable Medium", 1, 5);
- bitfield(pagestart + 20, "Supports Hard Sectoring", 1, 6);
- bitfield(pagestart + 20, "Supports Soft Sectoring", 1, 7);
- bitfield(pagestart + 20, "Addresses assigned by surface", 1, 4);
- intfield(pagestart + 2, 2, "Tracks per Zone");
- intfield(pagestart + 4, 2, "Alternate sectors per zone");
- intfield(pagestart + 6, 2, "Alternate tracks per zone");
- intfield(pagestart + 8, 2, "Alternate tracks per lun");
- intfield(pagestart + 10, 2, "Sectors per track");
- intfield(pagestart + 12, 2, "Bytes per sector");
- intfield(pagestart + 14, 2, "Interleave");
- intfield(pagestart + 16, 2, "Track skew factor");
- intfield(pagestart + 18, 2, "Cylinder skew factor");
- printf("\n");
- return 0;
-
-}
-
-static int verify_error_recovery(int page_code)
-{
- int status;
- int bdlen;
- unsigned char *pagestart;
-
- SETUP_MODE_PAGE(7, 7);
-
- printf("Data from Verify Error Recovery Page\n");
- printf("------------------------------------\n");
- bitfield(pagestart + 2, "EER", 1, 3);
- bitfield(pagestart + 2, "PER", 1, 2);
- bitfield(pagestart + 2, "DTE", 1, 1);
- bitfield(pagestart + 2, "DCR", 1, 0);
- intfield(pagestart + 3, 1, "Verify Retry Count");
- intfield(pagestart + 4, 1, "Verify Correction Span (bits)");
- intfield(pagestart + 10, 2, "Verify Recovery Time Limit (ms)");
-
- printf("\n");
- return 0;
-}
-
-static int peripheral_device_page(int page_code)
-{
- static char *idents[] = {
- "X3.131: Small Computer System Interface",
- "X3.91M-1987: Storage Module Interface",
- "X3.170: Enhanced Small Device Interface",
- "X3.130-1986; X3T9.3/87-002: IPI-2",
- "X3.132-1987; X3.147-1988: IPI-3"
- };
- int status;
- int bdlen;
- unsigned ident;
- unsigned char *pagestart;
- char *name;
-
- SETUP_MODE_PAGE(9, 2);
-
- printf("Data from Peripheral Device Page\n");
- printf("--------------------------------\n");
-
- ident = getnbyte(pagestart + 2, 2);
- if (ident < (sizeof(idents) / sizeof(char *)))
- name = idents[ident];
- else if (ident < 0x8000)
- name = "Reserved";
- else
- name = "Vendor Specific";
-
- bdlen = pagestart[1] - 6;
- if (bdlen < 0)
- bdlen = 0;
- else
- SETUP_MODE_PAGE(9, 2);
-
- hexfield(pagestart + 2, 2, "Interface Identifier");
- for (ident = 0; ident < 35; ident++)
- putchar(' ');
- puts(name);
-
- hexdatafield(pagestart + 8, bdlen, "Vendor Specific Data");
-
- printf("\n");
- return 0;
-}
-
-/* end */
-
-static int do_user_page(int page_code, int page_no)
-{
- int status;
- int bdlen;
- int i;
- //unsigned ident;
- unsigned char *pagestart;
- char *name;
-
- SETUP_MODE_PAGE(page_no, 0);
- //printf ("Page 0x%02x len: %i\n", page_code, pagestart[1]);
-
- name = "Vendor specific";
- for (i = 2; i < pagestart[1] + 2; i++) {
- char nm[8];
- snprintf(nm, 8, "%02x", i);
- hexdatafield(pagestart + i, 1, nm);
- }
-
- printf("\n");
- puts(name);
- return 0;
-}
-
-/* end */
-
-static int do_scsi_info_inquiry(int page_code)
-{
- int status, i, x_interface = 0;
- unsigned char *cmd;
- unsigned char *pagestart;
- unsigned char tmp;
-
- for (i = 0; i < 1024; i++) {
- buffer[i] = 0;
- }
-
- *((int *)buffer) = 0; /* length of input data */
- *(((int *)buffer) + 1) = 36; /* length of output buffer */
-
- cmd = (unsigned char *)(((int *)buffer) + 2);
-
- cmd[0] = 0x12; /* INQUIRY */
- cmd[1] = 0x00; /* lun=0, evpd=0 */
- cmd[2] = 0x00; /* page code = 0 */
- cmd[3] = 0x00; /* (reserved) */
- cmd[4] = 0x24; /* allocation length */
- cmd[5] = 0x00; /* control */
-
- status = do_sg_io(glob_fd, buffer);
- if (status) {
- printf("Error doing INQUIRY (1)");
- return status;
- }
-
- pagestart = buffer + 8;
-
- printf("Inquiry command\n");
- printf("---------------\n");
- bitfield(pagestart + 7, "Relative Address", 1, 7);
- bitfield(pagestart + 7, "Wide bus 32", 1, 6);
- bitfield(pagestart + 7, "Wide bus 16", 1, 5);
- bitfield(pagestart + 7, "Synchronous neg.", 1, 4);
- bitfield(pagestart + 7, "Linked Commands", 1, 3);
- bitfield(pagestart + 7, "Command Queueing", 1, 1);
- bitfield(pagestart + 7, "SftRe", 1, 0);
- bitfield(pagestart + 0, "Device Type", 0x1f, 0);
- bitfield(pagestart + 0, "Peripheral Qualifier", 0x7, 5);
- bitfield(pagestart + 1, "Removable?", 1, 7);
- bitfield(pagestart + 1, "Device Type Modifier", 0x7f, 0);
- bitfield(pagestart + 2, "ISO Version", 3, 6);
- bitfield(pagestart + 2, "ECMA Version", 7, 3);
- bitfield(pagestart + 2, "ANSI Version", 7, 0);
- bitfield(pagestart + 3, "AENC", 1, 7);
- bitfield(pagestart + 3, "TrmIOP", 1, 6);
- bitfield(pagestart + 3, "Response Data Format", 0xf, 0);
- tmp = pagestart[16];
- pagestart[16] = 0;
- printf("%s%s\n", (!x_interface ? "Vendor: " : ""),
- pagestart + 8);
- pagestart[16] = tmp;
-
- tmp = pagestart[32];
- pagestart[32] = 0;
- printf("%s%s\n", (!x_interface ? "Product: " : ""),
- pagestart + 16);
- pagestart[32] = tmp;
-
- printf("%s%s\n", (!x_interface ? "Revision level: " : ""),
- pagestart + 32);
-
- printf("\n");
- return status;
-
-}
-
-static int do_serial_number(int page_code)
-{
- int status, i, pagelen;
- unsigned char *cmd;
- unsigned char *pagestart;
-
- for (i = 0; i < 1024; i++) {
- buffer[i] = 0;
- }
-
- *((int *)buffer) = 0; /* length of input data */
- *(((int *)buffer) + 1) = 4; /* length of output buffer */
-
- cmd = (unsigned char *)(((int *)buffer) + 2);
-
- cmd[0] = 0x12; /* INQUIRY */
- cmd[1] = 0x01; /* lun=0, evpd=1 */
- cmd[2] = 0x80; /* page code = 0x80, serial number */
- cmd[3] = 0x00; /* (reserved) */
- cmd[4] = 0x04; /* allocation length */
- cmd[5] = 0x00; /* control */
-
- status = do_sg_io(glob_fd, buffer);
- if (status) {
- printf("Error doing INQUIRY (evpd=1, serial number)\n");
- return status;
- }
-
- pagestart = buffer + 8;
-
- pagelen = 4 + pagestart[3];
- *((int *)buffer) = 0; /* length of input data */
- *(((int *)buffer) + 1) = pagelen; /* length of output buffer */
-
- cmd[0] = 0x12; /* INQUIRY */
- cmd[1] = 0x01; /* lun=0, evpd=1 */
- cmd[2] = 0x80; /* page code = 0x80, serial number */
- cmd[3] = 0x00; /* (reserved) */
- cmd[4] = (unsigned char)pagelen; /* allocation length */
- cmd[5] = 0x00; /* control */
-
- status = do_sg_io(glob_fd, buffer);
- if (status) {
- printf("Error doing INQUIRY (evpd=1, serial number, len)\n");
- return status;
- }
-
- printf("Serial Number '");
- for (i = 0; i < pagestart[3]; i++)
- printf("%c", pagestart[4 + i]);
- printf("'\n");
- printf("\n");
-
- return status;
-}
-
-/* Print out a list of the known devices on the system */
-static void show_devices()
-{
- int k, j, fd, err, bus;
- My_scsi_idlun m_idlun;
- char name[MDEV_NAME_SZ];
- char ebuff[EBUFF_SZ];
- int do_numeric = 1;
- int max_holes = MAX_HOLES;
-
- for (k = 0, j = 0; k < sizeof(devices) / sizeof(char *); k++) {
- fd = open(devices[k], O_RDONLY | O_NONBLOCK);
- if (fd < 0)
- continue;
- err =
- ioctl(fd, SCSI_IOCTL_GET_BUS_NUMBER, &(sg_map_arr[j].bus));
- if (err < 0) {
- snprintf(ebuff, EBUFF_SZ,
- "SCSI(1) ioctl on %s failed", devices[k]);
- perror(ebuff);
- close(fd);
- continue;
- }
- err = ioctl(fd, SCSI_IOCTL_GET_IDLUN, &m_idlun);
- if (err < 0) {
- snprintf(ebuff, EBUFF_SZ,
- "SCSI(2) ioctl on %s failed", devices[k]);
- perror(ebuff);
- close(fd);
- continue;
- }
- sg_map_arr[j].channel = (m_idlun.dev_id >> 16) & 0xff;
- sg_map_arr[j].lun = (m_idlun.dev_id >> 8) & 0xff;
- sg_map_arr[j].target_id = m_idlun.dev_id & 0xff;
- sg_map_arr[j].dev_name = devices[k];
-
- printf("[scsi%d ch=%d id=%d lun=%d %s] ", sg_map_arr[j].bus,
- sg_map_arr[j].channel, sg_map_arr[j].target_id,
- sg_map_arr[j].lun, sg_map_arr[j].dev_name);
-
- ++j;
- printf("%s ", devices[k]);
- close(fd);
- };
- printf("\n");
- for (k = 0; k < MAX_SG_DEVS; k++) {
- make_dev_name(name, NULL, k, do_numeric);
- fd = open(name, O_RDWR | O_NONBLOCK);
- if (fd < 0) {
- if ((ENOENT == errno) && (0 == k)) {
- do_numeric = 0;
- make_dev_name(name, NULL, k, do_numeric);
- fd = open(name, O_RDWR | O_NONBLOCK);
- }
- if (fd < 0) {
- if (EBUSY == errno)
- continue; /* step over if O_EXCL already on it */
- else {
-#if 0
- snprintf(ebuff, EBUFF_SZ,
- "open on %s failed (%d)", name,
- errno);
- perror(ebuff);
-#endif
- if (max_holes-- > 0)
- continue;
- else
- break;
- }
- }
- }
- max_holes = MAX_HOLES;
- err = ioctl(fd, SCSI_IOCTL_GET_BUS_NUMBER, &bus);
- if (err < 0) {
- snprintf(ebuff, EBUFF_SZ, "SCSI(3) ioctl on %s failed",
- name);
- perror(ebuff);
- close(fd);
- continue;
- }
- err = ioctl(fd, SCSI_IOCTL_GET_IDLUN, &m_idlun);
- if (err < 0) {
- snprintf(ebuff, EBUFF_SZ, "SCSI(3) ioctl on %s failed",
- name);
- perror(ebuff);
- close(fd);
- continue;
- }
-
- printf("[scsi%d ch=%d id=%d lun=%d %s]", bus,
- (m_idlun.dev_id >> 16) & 0xff, m_idlun.dev_id & 0xff,
- (m_idlun.dev_id >> 8) & 0xff, name);
-
- for (j = 0; sg_map_arr[j].dev_name; ++j) {
- if ((bus == sg_map_arr[j].bus) &&
- ((m_idlun.dev_id & 0xff) == sg_map_arr[j].target_id)
- && (((m_idlun.dev_id >> 16) & 0xff) ==
- sg_map_arr[j].channel)
- && (((m_idlun.dev_id >> 8) & 0xff) ==
- sg_map_arr[j].lun)) {
- printf("%s [=%s scsi%d ch=%d id=%d lun=%d]\n",
- name, sg_map_arr[j].dev_name, bus,
- ((m_idlun.dev_id >> 16) & 0xff),
- m_idlun.dev_id & 0xff,
- ((m_idlun.dev_id >> 8) & 0xff));
- break;
- }
- }
- if (NULL == sg_map_arr[j].dev_name)
- printf("%s [scsi%d ch=%d id=%d lun=%d]\n", name, bus,
- ((m_idlun.dev_id >> 16) & 0xff),
- m_idlun.dev_id & 0xff,
- ((m_idlun.dev_id >> 8) & 0xff));
- close(fd);
- }
- printf("\n");
-}
-
-static int show_pages(int page_code)
-{
- int offset;
- int length;
- int i;
- unsigned long long pages_sup = 0;
- unsigned long long pages_mask = 0;
-
- if (!get_mode_page10(0x3f, page_code | 0x10)) {
- length = 9 + getnbyte(buffer + 8, 2);
- offset = 16 + getnbyte(buffer + 14, 2);
- } else if (!get_mode_page(0x3f, page_code | 0x10)) {
- length = 9 + buffer[8];
- offset = 12 + buffer[11];
- } else { /* Assume SCSI-1 and fake settings to report NO pages */
- offset = 10;
- length = 0;
- }
-
- /* Get mask of pages supported by prog: */
- for (i = 0; i < MAX_PAGENO; i++)
- if (page_names[i])
- pages_mask |= (1LL << i);
-
- /* Get pages listed in mode_pages */
- while (offset < length) {
- pages_sup |= (1LL << (buffer[offset] & 0x3f));
- offset += 2 + buffer[offset + 1];
- }
-
- /* Mask out pages unsupported by this binary */
- pages_sup &= pages_mask;
-
- /* Notch page supported? */
- if (pages_sup & (1LL << 12)) {
- if (get_mode_page(12, 0))
- return 2;
- offset = 12 + buffer[11];
- } else { /* Fake empty notch page */
- memset(buffer, 0, SIZEOF_BUFFER);
- offset = 0;
- }
-
- pages_mask = getnbyte(buffer + offset + 16, 4);
- pages_mask <<= 32;
- pages_mask += getnbyte(buffer + offset + 20, 4);
-
- puts("Mode Pages supported by this binary and target:");
- puts("-----------------------------------------------");
- for (i = 0; i < MAX_PAGENO; i++)
- if (pages_sup & (1LL << i))
- printf("%02xh: %s Page%s\n", i, get_page_name(i),
- (pages_mask & (1LL << i)) ? " (notched)" : "");
- if (pages_sup & (1LL << 12)) {
- printf("\nCurrent notch is %d.\n",
- getnbyte(buffer + offset + 6, 2));
- }
- if (!pages_sup)
- puts("No mode pages supported (SCSI-1?).");
-
- return 0;
-}
-
-static int open_sg_dev(char *devname)
-{
- int fd, err, bus, bbus, k;
- My_scsi_idlun m_idlun, mm_idlun;
- int do_numeric = 1;
- char name[DEVNAME_SZ];
- struct stat a_st;
- int block_dev = 0;
-
- strncpy(name, devname, DEVNAME_SZ);
- name[DEVNAME_SZ - 1] = '\0';
- fd = open(name, O_RDONLY);
- if (fd < 0)
- return fd;
- if (fstat(fd, &a_st) < 0) {
- fprintf(stderr, "could do fstat() on fd ??\n");
- close(fd);
- return -9999;
- }
- if (S_ISBLK(a_st.st_mode))
- block_dev = 1;
- if (block_dev || (ioctl(fd, SG_GET_TIMEOUT, 0) < 0)) {
- err = ioctl(fd, SCSI_IOCTL_GET_BUS_NUMBER, &bus);
- if (err < 0) {
- perror("A SCSI device name is required\n");
- close(fd);
- return -9999;
- }
- err = ioctl(fd, SCSI_IOCTL_GET_IDLUN, &m_idlun);
- if (err < 0) {
- perror("A SCSI device name is required\n");
- close(fd);
- return -9999;
- }
- close(fd);
-
- for (k = 0; k < MAX_SG_DEVS; k++) {
- make_dev_name(name, NULL, k, do_numeric);
- fd = open(name, O_RDWR | O_NONBLOCK);
- if (fd < 0) {
- if ((ENOENT == errno) && (0 == k)) {
- do_numeric = 0;
- make_dev_name(name, NULL, k,
- do_numeric);
- fd = open(name, O_RDWR | O_NONBLOCK);
- }
- if (fd < 0) {
- if (EBUSY == errno)
- continue; /* step over if O_EXCL already on it */
- else
- break;
- }
- }
- err = ioctl(fd, SCSI_IOCTL_GET_BUS_NUMBER, &bbus);
- if (err < 0) {
- perror("sg ioctl failed");
- close(fd);
- fd = -9999;
- }
- err = ioctl(fd, SCSI_IOCTL_GET_IDLUN, &mm_idlun);
- if (err < 0) {
- perror("sg ioctl failed");
- close(fd);
- fd = -9999;
- }
- if ((bus == bbus) &&
- ((m_idlun.dev_id & 0xff) ==
- (mm_idlun.dev_id & 0xff))
- && (((m_idlun.dev_id >> 8) & 0xff) ==
- ((mm_idlun.dev_id >> 8) & 0xff))
- && (((m_idlun.dev_id >> 16) & 0xff) ==
- ((mm_idlun.dev_id >> 16) & 0xff)))
- break;
- else {
- close(fd);
- fd = -9999;
- }
- }
- }
- if (fd >= 0) {
-#ifdef SG_GET_RESERVED_SIZE
- int size;
-
- if (ioctl(fd, SG_GET_RESERVED_SIZE, &size) < 0) {
- fprintf(stderr,
- "Compiled with new driver, running on old!!\n");
- close(fd);
- return -9999;
- }
-#endif
- close(fd);
- return open(name, O_RDWR);
- } else
- return fd;
-}
-
-int show_scsi_info(char *device)
-{
- int page_code = 0;
- int status = 0;
-
- print_msg(TEST_BREAK, __FUNCTION__);
-
- show_devices();
-
- glob_fd = open_sg_dev(device);
- if (glob_fd < 0) {
- if (-9999 == glob_fd)
- fprintf(stderr,
- "Couldn't find sg device corresponding to %s\n",
- device);
- else {
- perror("sginfo(open)");
- fprintf(stderr,
- "file=%s, or no corresponding sg device found\n",
- device);
- fprintf(stderr, "Is sg driver loaded?\n");
- }
- return 1;
- }
-
- status |= do_scsi_info_inquiry(page_code);
-
- status |= do_serial_number(page_code);
-
- status |= read_geometry(page_code);
-
- status |= read_cache(page_code);
-
- status |= read_format_info(page_code);
-
- status |= error_recovery_page(page_code);
-
- status |= read_control_page(page_code);
-
- status |= read_disconnect_reconnect_data(page_code);
-
- status |= read_defect_list(page_code);
-
- status |= notch_parameters_page(page_code);
-
- status |= verify_error_recovery(page_code);
-
- status |= peripheral_device_page(page_code);
-
- status |= do_user_page(page_code, 0);
-
- status |= show_pages(page_code);
-
- return status;
-}
-
-/* -1 -> unrecoverable error, 0 -> successful, 1 -> recoverable (ENOMEM),
- 2 -> try again */
-int sg_read2(int sg_fd, unsigned char *buff, int blocks, int from_block,
- int bs, int cdbsz, int fua, int do_mmap)
-{
- unsigned char rdCmd[MAX_SCSI_CDBSZ];
- unsigned char senseBuff[SENSE_BUFF_LEN];
- sg_io_hdr_t io_hdr;
- int res;
-
- if (sg_build_scsi_cdb(rdCmd, cdbsz, blocks, from_block, 0, fua, 0)) {
- fprintf(stderr,
- ME "bad rd cdb build, from_block=%d, blocks=%d\n",
- from_block, blocks);
- return -1;
- }
- memset(&io_hdr, 0, sizeof(sg_io_hdr_t));
- io_hdr.interface_id = 'S';
- io_hdr.cmd_len = cdbsz;
- io_hdr.cmdp = rdCmd;
- io_hdr.dxfer_direction = SG_DXFER_FROM_DEV;
- io_hdr.dxfer_len = bs * blocks;
- if (!do_mmap)
- io_hdr.dxferp = buff;
- io_hdr.mx_sb_len = SENSE_BUFF_LEN;
- io_hdr.sbp = senseBuff;
- io_hdr.timeout = DEF_TIMEOUT;
- io_hdr.pack_id = from_block;
- if (do_mmap)
- io_hdr.flags |= SG_FLAG_MMAP_IO;
-
- while (((res = write(sg_fd, &io_hdr, sizeof(io_hdr))) < 0) &&
- (EINTR == errno)) ;
- if (res < 0) {
- if (ENOMEM == errno)
- return 1;
- perror("reading (wr) on sg device, error");
- return -1;
- }
-
- while (((res = read(sg_fd, &io_hdr, sizeof(io_hdr))) < 0) &&
- (EINTR == errno)) ;
- if (res < 0) {
- perror("reading (rd) on sg device, error");
- return -1;
- }
- switch (sg_err_category3(&io_hdr)) {
- case SG_ERR_CAT_CLEAN:
- break;
- case SG_ERR_CAT_RECOVERED:
- fprintf(stderr,
- "Recovered error while reading block=%d, num=%d\n",
- from_block, blocks);
- break;
- case SG_ERR_CAT_MEDIA_CHANGED:
- return 2;
- default:
- sg_chk_n_print3("reading", &io_hdr);
- return -1;
- }
- sum_of_resids += io_hdr.resid;
-#if SG_DEBUG
- fprintf(stderr, "duration=%u ms\n", io_hdr.duration);
-#endif
- return 0;
-}
-
-/* -1 -> unrecoverable error, 0 -> successful, 1 -> recoverable (ENOMEM),
- 2 -> try again */
-int sg_write2(int sg_fd, unsigned char *buff, int blocks, int to_block,
- int bs, int cdbsz, int fua, int do_mmap, int *diop)
-{
- unsigned char wrCmd[MAX_SCSI_CDBSZ];
- unsigned char senseBuff[SENSE_BUFF_LEN];
- sg_io_hdr_t io_hdr;
- int res;
-
- if (sg_build_scsi_cdb(wrCmd, cdbsz, blocks, to_block, 1, fua, 0)) {
- fprintf(stderr, ME "bad wr cdb build, to_block=%d, blocks=%d\n",
- to_block, blocks);
- return -1;
- }
-
- memset(&io_hdr, 0, sizeof(sg_io_hdr_t));
- io_hdr.interface_id = 'S';
- io_hdr.cmd_len = cdbsz;
- io_hdr.cmdp = wrCmd;
- io_hdr.dxfer_direction = SG_DXFER_TO_DEV;
- io_hdr.dxfer_len = bs * blocks;
- if (!do_mmap)
- io_hdr.dxferp = buff;
- io_hdr.mx_sb_len = SENSE_BUFF_LEN;
- io_hdr.sbp = senseBuff;
- io_hdr.timeout = DEF_TIMEOUT;
- io_hdr.pack_id = to_block;
- if (do_mmap)
- io_hdr.flags |= SG_FLAG_MMAP_IO;
- if (diop && *diop)
- io_hdr.flags |= SG_FLAG_DIRECT_IO;
-
- while (((res = write(sg_fd, &io_hdr, sizeof(io_hdr))) < 0) &&
- (EINTR == errno)) ;
- if (res < 0) {
- if (ENOMEM == errno)
- return 1;
- perror("writing (wr) on sg device, error");
- return -1;
- }
-
- while (((res = read(sg_fd, &io_hdr, sizeof(io_hdr))) < 0) &&
- (EINTR == errno)) ;
- if (res < 0) {
- perror("writing (rd) on sg device, error");
- return -1;
- }
- switch (sg_err_category3(&io_hdr)) {
- case SG_ERR_CAT_CLEAN:
- break;
- case SG_ERR_CAT_RECOVERED:
- fprintf(stderr,
- "Recovered error while writing block=%d, num=%d\n",
- to_block, blocks);
- break;
- case SG_ERR_CAT_MEDIA_CHANGED:
- return 2;
- default:
- sg_chk_n_print3("writing", &io_hdr);
- return -1;
- }
- if (diop && *diop &&
- ((io_hdr.info & SG_INFO_DIRECT_IO_MASK) != SG_INFO_DIRECT_IO))
- *diop = 0; /* flag that dio not done (completely) */
- return 0;
-}
-
-int do_scsi_sgm_read_write(char *device)
-{
- int skip = 0;
- int seek = 0;
- int bs = 0;
- int bpt = DEF_BLOCKS_PER_TRANSFER;
- char inf[INOUTF_SZ];
- int in_type = FT_OTHER;
- char outf[INOUTF_SZ];
- int out_type = FT_OTHER;
- int res, t;
- int infd, outfd, blocks;
- unsigned char *wrkPos;
- unsigned char *wrkBuff = NULL;
- unsigned char *wrkMmap = NULL;
- int in_num_sect = 0;
- int in_res_sz = 0;
- int out_num_sect = 0;
- int out_res_sz = 0;
- int do_time = 1;
- int scsi_cdbsz = DEF_SCSI_CDBSZ;
- int do_sync = 1;
- int do_dio = 0;
- int num_dio_not_done = 0;
- int fua_mode = 0;
- int in_sect_sz, out_sect_sz;
- char ebuff[EBUFF_SZ];
- int blocks_per;
- int req_count;
- size_t psz = getpagesize();
- struct timeval start_tm, end_tm;
-
- print_msg(TEST_BREAK, __FUNCTION__);
-
- strcpy(inf, "/dev/zero");
- strcpy(outf, device);
-
- install_handler(SIGINT, interrupt_handler);
- install_handler(SIGQUIT, interrupt_handler);
- install_handler(SIGPIPE, interrupt_handler);
- install_handler(SIGUSR1, siginfo_handler);
-
- infd = STDIN_FILENO;
- outfd = STDOUT_FILENO;
-
- in_type = dd_filetype(inf);
-
- if (FT_ST == in_type) {
- fprintf(stderr, ME "unable to use scsi tape device %s\n", inf);
- return 1;
- } else if (FT_SG == in_type) {
- if ((infd = open(inf, O_RDWR)) < 0) {
- snprintf(ebuff, EBUFF_SZ,
- ME "could not open %s for sg reading", inf);
- perror(ebuff);
- return 1;
- }
- res = ioctl(infd, SG_GET_VERSION_NUM, &t);
- if ((res < 0) || (t < 30122)) {
- fprintf(stderr, ME "sg driver prior to 3.1.22\n");
- return 1;
- }
- in_res_sz = bs * bpt;
- if (0 != (in_res_sz % psz)) /* round up to next page */
- in_res_sz = ((in_res_sz / psz) + 1) * psz;
- if (ioctl(infd, SG_GET_RESERVED_SIZE, &t) < 0) {
- perror(ME "SG_GET_RESERVED_SIZE error");
- return 1;
- }
- if (in_res_sz > t) {
- if (ioctl(infd, SG_SET_RESERVED_SIZE, &in_res_sz) < 0) {
- perror(ME "SG_SET_RESERVED_SIZE error");
- return 1;
- }
- }
- wrkMmap = mmap(NULL, in_res_sz, PROT_READ | PROT_WRITE,
- MAP_SHARED, infd, 0);
- if (MAP_FAILED == wrkMmap) {
- snprintf(ebuff, EBUFF_SZ,
- ME "error using mmap() on file: %s", inf);
- perror(ebuff);
- return 1;
- }
- } else {
- if ((infd = open(inf, O_RDONLY)) < 0) {
- snprintf(ebuff, EBUFF_SZ,
- ME "could not open %s for reading", inf);
- perror(ebuff);
- return 1;
- } else if (skip > 0) {
- llse_loff_t offset = skip;
-
- offset *= bs; /* could exceed 32 bits here! */
- if (llse_llseek(infd, offset, SEEK_SET) < 0) {
- snprintf(ebuff, EBUFF_SZ, ME "couldn't skip to "
- "required position on %s", inf);
- perror(ebuff);
- return 1;
- }
- }
- }
-
- if (outf[0] && ('-' != outf[0])) {
- out_type = dd_filetype(outf);
-
- if (FT_ST == out_type) {
- fprintf(stderr,
- ME "unable to use scsi tape device %s\n", outf);
- return 1;
- } else if (FT_SG == out_type) {
- if ((outfd = open(outf, O_RDWR)) < 0) {
- snprintf(ebuff, EBUFF_SZ,
- ME "could not open %s for "
- "sg writing", outf);
- perror(ebuff);
- return 1;
- }
- res = ioctl(outfd, SG_GET_VERSION_NUM, &t);
- if ((res < 0) || (t < 30122)) {
- fprintf(stderr,
- ME "sg driver prior to 3.1.22\n");
- return 1;
- }
- if (ioctl(outfd, SG_GET_RESERVED_SIZE, &t) < 0) {
- perror(ME "SG_GET_RESERVED_SIZE error");
- return 1;
- }
- out_res_sz = bs * bpt;
- if (out_res_sz > t) {
- if (ioctl
- (outfd, SG_SET_RESERVED_SIZE,
- &out_res_sz) < 0) {
- perror(ME "SG_SET_RESERVED_SIZE error");
- return 1;
- }
- }
- if (NULL == wrkMmap) {
- wrkMmap =
- mmap(NULL, out_res_sz,
- PROT_READ | PROT_WRITE, MAP_SHARED,
- outfd, 0);
- if (MAP_FAILED == wrkMmap) {
- snprintf(ebuff, EBUFF_SZ,
- ME
- "error using mmap() on file: %s",
- outf);
- perror(ebuff);
- return 1;
- }
- }
- } else if (FT_DEV_NULL == out_type)
- outfd = -1; /* don't bother opening */
- else {
- if (FT_RAW != out_type) {
- if ((outfd =
- open(outf, O_WRONLY | O_CREAT,
- 0666)) < 0) {
- snprintf(ebuff, EBUFF_SZ,
- ME
- "could not open %s for writing",
- outf);
- perror(ebuff);
- return 1;
- }
- } else {
- if ((outfd = open(outf, O_WRONLY)) < 0) {
- snprintf(ebuff, EBUFF_SZ,
- ME "could not open %s "
- "for raw writing", outf);
- perror(ebuff);
- return 1;
- }
- }
- if (seek > 0) {
- llse_loff_t offset = seek;
-
- offset *= bs; /* could exceed 32 bits here! */
- if (llse_llseek(outfd, offset, SEEK_SET) < 0) {
- snprintf(ebuff, EBUFF_SZ,
- ME "couldn't seek to "
- "required position on %s",
- outf);
- perror(ebuff);
- return 1;
- }
- }
- }
- }
- if ((STDIN_FILENO == infd) && (STDOUT_FILENO == outfd)) {
- fprintf(stderr,
- "Can't have both 'if' as stdin _and_ 'of' as stdout\n");
- return 1;
- }
-#if 0
- if ((FT_OTHER == in_type) && (FT_OTHER == out_type)) {
- fprintf(stderr, "Both 'if' and 'of' can't be ordinary files\n");
- return 1;
- }
-#endif
- if (dd_count < 0) {
- if (FT_SG == in_type) {
- res = read_capacity(infd, &in_num_sect, &in_sect_sz);
- if (2 == res) {
- fprintf(stderr,
- "Unit attention, media changed(in), continuing\n");
- res =
- read_capacity(infd, &in_num_sect,
- &in_sect_sz);
- }
- if (0 != res) {
- fprintf(stderr,
- "Unable to read capacity on %s\n", inf);
- in_num_sect = -1;
- } else {
-#if 0
- if (0 == in_sect_sz)
- in_sect_sz = bs;
- else if (in_sect_sz > bs)
- in_num_sect *= (in_sect_sz / bs);
- else if (in_sect_sz < bs)
- in_num_sect /= (bs / in_sect_sz);
-#endif
- if (in_num_sect > skip)
- in_num_sect -= skip;
- }
- }
- if (FT_SG == out_type) {
- res = read_capacity(outfd, &out_num_sect, &out_sect_sz);
- if (2 == res) {
- fprintf(stderr,
- "Unit attention, media changed(out), continuing\n");
- res =
- read_capacity(outfd, &out_num_sect,
- &out_sect_sz);
- }
- if (0 != res) {
- fprintf(stderr,
- "Unable to read capacity on %s\n",
- outf);
- out_num_sect = -1;
- } else {
- if (out_num_sect > seek)
- out_num_sect -= seek;
- }
- }
-#ifdef SG_DEBUG
- fprintf(stderr,
- "Start of loop, count=%d, in_num_sect=%d, out_num_sect=%d\n",
- dd_count, in_num_sect, out_num_sect);
-#endif
- if (in_num_sect > 0) {
- if (out_num_sect > 0)
- dd_count =
- (in_num_sect >
- out_num_sect) ? out_num_sect : in_num_sect;
- else
- dd_count = in_num_sect;
- } else
- dd_count = out_num_sect;
- }
- if (dd_count < 0) {
- fprintf(stderr, "Couldn't calculate count, please give one\n");
- return 1;
- }
- if (do_dio && (FT_SG != in_type)) {
- do_dio = 0;
- fprintf(stderr,
- ">>> dio only performed on 'of' side when 'if' is"
- " an sg device\n");
- }
- if (do_dio) {
- int fd;
- char c;
-
- if ((fd = open(proc_allow_dio, O_RDONLY)) >= 0) {
- if (1 == read(fd, &c, 1)) {
- if ('0' == c)
- fprintf(stderr,
- ">>> %s set to '0' but should be set "
- "to '1' for direct IO\n",
- proc_allow_dio);
- }
- close(fd);
- }
- }
-
- if (wrkMmap)
- wrkPos = wrkMmap;
- else {
- if ((FT_RAW == in_type) || (FT_RAW == out_type)) {
- wrkBuff = malloc(bs * bpt + psz);
- if (0 == wrkBuff) {
- fprintf(stderr,
- "Not enough user memory for raw\n");
- return 1;
- }
- wrkPos =
- (unsigned char *)(((unsigned long)wrkBuff + psz - 1)
- & (~(psz - 1)));
- } else {
- wrkBuff = malloc(bs * bpt);
- if (0 == wrkBuff) {
- fprintf(stderr, "Not enough user memory\n");
- return 1;
- }
- wrkPos = wrkBuff;
- }
- }
-
- blocks_per = bpt;
-#ifdef SG_DEBUG
- fprintf(stderr, "Start of loop, count=%d, blocks_per=%d\n",
- dd_count, blocks_per);
-#endif
- if (do_time) {
- start_tm.tv_sec = 0;
- start_tm.tv_usec = 0;
- gettimeofday(&start_tm, NULL);
- }
- req_count = dd_count;
-
- while (dd_count > 0) {
- blocks = (dd_count > blocks_per) ? blocks_per : dd_count;
- if (FT_SG == in_type) {
- int fua = fua_mode & 2;
-
- res =
- sg_read2(infd, wrkPos, blocks, skip, bs, scsi_cdbsz,
- fua, 1);
- if (2 == res) {
- fprintf(stderr,
- "Unit attention, media changed, continuing (r)\n");
- res =
- sg_read2(infd, wrkPos, blocks, skip, bs,
- scsi_cdbsz, fua, 1);
- }
- if (0 != res) {
- fprintf(stderr, "sg_read2 failed, skip=%d\n",
- skip);
- break;
- } else
- in_full += blocks;
- } else {
- while (((res = read(infd, wrkPos, blocks * bs)) < 0) &&
- (EINTR == errno)) ;
- if (res < 0) {
- snprintf(ebuff, EBUFF_SZ,
- ME "reading, skip=%d ", skip);
- perror(ebuff);
- break;
- } else if (res < blocks * bs) {
- dd_count = 0;
- blocks = res / bs;
- if ((res % bs) > 0) {
- blocks++;
- in_partial++;
- }
- }
- in_full += blocks;
- }
-
- if (FT_SG == out_type) {
- int do_mmap = (FT_SG == in_type) ? 0 : 1;
- int fua = fua_mode & 1;
- int dio_res = do_dio;
-
- res =
- sg_write2(outfd, wrkPos, blocks, seek, bs,
- scsi_cdbsz, fua, do_mmap, &dio_res);
- if (2 == res) {
- fprintf(stderr,
- "Unit attention, media changed, continuing (w)\n");
- res =
- sg_write2(outfd, wrkPos, blocks, seek, bs,
- scsi_cdbsz, fua, do_mmap,
- &dio_res);
- } else if (0 != res) {
- fprintf(stderr, "sg_write2 failed, seek=%d\n",
- seek);
- break;
- } else {
- out_full += blocks;
- if (do_dio && (0 == dio_res))
- num_dio_not_done++;
- }
- } else if (FT_DEV_NULL == out_type)
- out_full += blocks; /* act as if written out without error */
- else {
- while (((res = write(outfd, wrkPos, blocks * bs)) < 0)
- && (EINTR == errno)) ;
- if (res < 0) {
- snprintf(ebuff, EBUFF_SZ,
- ME "writing, seek=%d ", seek);
- perror(ebuff);
- break;
- } else if (res < blocks * bs) {
- fprintf(stderr,
- "output file probably full, seek=%d ",
- seek);
- blocks = res / bs;
- out_full += blocks;
- if ((res % bs) > 0)
- out_partial++;
- break;
- } else
- out_full += blocks;
- }
- if (dd_count > 0)
- dd_count -= blocks;
- skip += blocks;
- seek += blocks;
- }
- if ((do_time) && (start_tm.tv_sec || start_tm.tv_usec)) {
- struct timeval res_tm;
- double a, b;
-
- gettimeofday(&end_tm, NULL);
- res_tm.tv_sec = end_tm.tv_sec - start_tm.tv_sec;
- res_tm.tv_usec = end_tm.tv_usec - start_tm.tv_usec;
- if (res_tm.tv_usec < 0) {
- --res_tm.tv_sec;
- res_tm.tv_usec += 1000000;
- }
- a = res_tm.tv_sec;
- a += (0.000001 * res_tm.tv_usec);
- b = (double)bs *(req_count - dd_count);
- printf("time to transfer data was %d.%06d secs",
- (int)res_tm.tv_sec, (int)res_tm.tv_usec);
- if ((a > 0.00001) && (b > 511))
- printf(", %.2f MB/sec\n", b / (a * 1000000.0));
- else
- printf("\n");
- }
- if (do_sync) {
- if (FT_SG == out_type) {
- fprintf(stderr, ">> Synchronizing cache on %s\n", outf);
- res = sync_cache(outfd);
- if (2 == res) {
- fprintf(stderr,
- "Unit attention, media changed(in), continuing\n");
- res = sync_cache(outfd);
- }
- if (0 != res)
- fprintf(stderr,
- "Unable to synchronize cache\n");
- }
- }
-
- if (wrkBuff)
- free(wrkBuff);
- if (STDIN_FILENO != infd)
- close(infd);
- if ((STDOUT_FILENO != outfd) && (FT_DEV_NULL != out_type))
- close(outfd);
- res = 0;
- if (0 != dd_count) {
- fprintf(stderr, "Some error occurred,");
- res = 2;
- }
- print_stats();
- if (sum_of_resids)
- fprintf(stderr, ">> Non-zero sum of residual counts=%d\n",
- sum_of_resids);
- if (num_dio_not_done)
- fprintf(stderr, ">> dio requested but _not done %d times\n",
- num_dio_not_done);
- return res;
-}
-
-static void guarded_stop_in(Rq_coll * clp)
-{
- pthread_mutex_lock(&clp->in_mutex);
- clp->in_stop = 1;
- pthread_mutex_unlock(&clp->in_mutex);
-}
-
-static void guarded_stop_out(Rq_coll * clp)
-{
- pthread_mutex_lock(&clp->out_mutex);
- clp->out_stop = 1;
- pthread_mutex_unlock(&clp->out_mutex);
-}
-
-static void guarded_stop_both(Rq_coll * clp)
-{
- guarded_stop_in(clp);
- guarded_stop_out(clp);
-}
-
-void *sig_listen_thread(void *v_clp)
-{
- Rq_coll *clp = (Rq_coll *) v_clp;
- int sig_number;
-
- while (1) {
- sigwait(&signal_set, &sig_number);
- if (SIGINT == sig_number) {
- fprintf(stderr, ME "interrupted by SIGINT\n");
- guarded_stop_both(clp);
- pthread_cond_broadcast(&clp->out_sync_cv);
- }
- }
- return NULL;
-}
-
-void cleanup_in(void *v_clp)
-{
- Rq_coll *clp = (Rq_coll *) v_clp;
-
- fprintf(stderr, "thread cancelled while in mutex held\n");
- clp->in_stop = 1;
- pthread_mutex_unlock(&clp->in_mutex);
- guarded_stop_out(clp);
- pthread_cond_broadcast(&clp->out_sync_cv);
-}
-
-void cleanup_out(void *v_clp)
-{
- Rq_coll *clp = (Rq_coll *) v_clp;
-
- fprintf(stderr, "thread cancelled while out mutex held\n");
- clp->out_stop = 1;
- pthread_mutex_unlock(&clp->out_mutex);
- guarded_stop_in(clp);
- pthread_cond_broadcast(&clp->out_sync_cv);
-}
-
-void *read_write_thread(void *v_clp)
-{
- Rq_coll *clp = (Rq_coll *) v_clp;
- Rq_elem rel;
- Rq_elem *rep = &rel;
- size_t psz = 0;
- int sz = clp->bpt * clp->bs;
- int stop_after_write = 0;
- int seek_skip = clp->seek - clp->skip;
- int blocks, status;
-
- memset(rep, 0, sizeof(Rq_elem));
- psz = getpagesize();
- if (NULL == (rep->alloc_bp = malloc(sz + psz)))
- err_exit(ENOMEM, "out of memory creating user buffers\n");
- rep->buffp =
- (unsigned char *)(((unsigned long)rep->alloc_bp + psz - 1) &
- (~(psz - 1)));
- /* Follow clp members are constant during lifetime of thread */
- rep->bs = clp->bs;
- rep->fua_mode = clp->fua_mode;
- rep->dio = clp->dio;
- rep->infd = clp->infd;
- rep->outfd = clp->outfd;
- rep->debug = clp->debug;
- rep->in_scsi_type = clp->in_scsi_type;
- rep->out_scsi_type = clp->out_scsi_type;
- rep->cdbsz = clp->cdbsz;
-
- while (1) {
- status = pthread_mutex_lock(&clp->in_mutex);
- if (0 != status)
- err_exit(status, "lock in_mutex");
- if (clp->in_stop || (clp->in_count <= 0)) {
- /* no more to do, exit loop then thread */
- status = pthread_mutex_unlock(&clp->in_mutex);
- if (0 != status)
- err_exit(status, "unlock in_mutex");
- break;
- }
- blocks = (clp->in_count > clp->bpt) ? clp->bpt : clp->in_count;
- rep->wr = 0;
- rep->blk = clp->in_blk;
- rep->num_blks = blocks;
- clp->in_blk += blocks;
- clp->in_count -= blocks;
-
- pthread_cleanup_push(cleanup_in, (void *)clp);
- if (FT_SG == clp->in_type)
- sg_in_operation(clp, rep); /* lets go of in_mutex mid operation */
- else {
- stop_after_write =
- normal_in_operation(clp, rep, blocks);
- status = pthread_mutex_unlock(&clp->in_mutex);
- if (0 != status)
- err_exit(status, "unlock in_mutex");
- }
- pthread_cleanup_pop(0);
-
- status = pthread_mutex_lock(&clp->out_mutex);
- if (0 != status)
- err_exit(status, "lock out_mutex");
- if (FT_DEV_NULL != clp->out_type) {
- while ((!clp->out_stop) &&
- ((rep->blk + seek_skip) != clp->out_blk)) {
- /* if write would be out of sequence then wait */
- pthread_cleanup_push(cleanup_out, (void *)clp);
- status =
- pthread_cond_wait(&clp->out_sync_cv,
- &clp->out_mutex);
- if (0 != status)
- err_exit(status, "cond out_sync_cv");
- pthread_cleanup_pop(0);
- }
- }
-
- if (clp->out_stop || (clp->out_count <= 0)) {
- if (!clp->out_stop)
- clp->out_stop = 1;
- status = pthread_mutex_unlock(&clp->out_mutex);
- if (0 != status)
- err_exit(status, "unlock out_mutex");
- break;
- }
- if (stop_after_write)
- clp->out_stop = 1;
- rep->wr = 1;
- rep->blk = clp->out_blk;
- /* rep->num_blks = blocks; */
- clp->out_blk += blocks;
- clp->out_count -= blocks;
-
- pthread_cleanup_push(cleanup_out, (void *)clp);
- if (FT_SG == clp->out_type)
- sg_out_operation(clp, rep); /* releases out_mutex mid operation */
- else if (FT_DEV_NULL == clp->out_type) {
- /* skip actual write operation */
- clp->out_done_count -= blocks;
- status = pthread_mutex_unlock(&clp->out_mutex);
- if (0 != status)
- err_exit(status, "unlock out_mutex");
- } else {
- normal_out_operation(clp, rep, blocks);
- status = pthread_mutex_unlock(&clp->out_mutex);
- if (0 != status)
- err_exit(status, "unlock out_mutex");
- }
- pthread_cleanup_pop(0);
-
- if (stop_after_write)
- break;
- pthread_cond_broadcast(&clp->out_sync_cv);
- } /* end of while loop */
- if (rep->alloc_bp)
- free(rep->alloc_bp);
- status = pthread_mutex_lock(&clp->in_mutex);
- if (0 != status)
- err_exit(status, "lock in_mutex");
- if (!clp->in_stop)
- clp->in_stop = 1; /* flag other workers to stop */
- status = pthread_mutex_unlock(&clp->in_mutex);
- if (0 != status)
- err_exit(status, "unlock in_mutex");
- pthread_cond_broadcast(&clp->out_sync_cv);
- return stop_after_write ? NULL : v_clp;
-}
-
-int normal_in_operation(Rq_coll * clp, Rq_elem * rep, int blocks)
-{
- int res;
- int stop_after_write = 0;
-
- /* enters holding in_mutex */
- while (((res = read(clp->infd, rep->buffp,
- blocks * clp->bs)) < 0) && (EINTR == errno)) ;
- if (res < 0) {
- if (clp->coe) {
- memset(rep->buffp, 0, rep->num_blks * rep->bs);
- fprintf(stderr,
- ">> substituted zeros for in blk=%d for "
- "%d bytes, %s\n", rep->blk,
- rep->num_blks * rep->bs, strerror(errno));
- res = rep->num_blks * clp->bs;
- } else {
- fprintf(stderr, "error in normal read, %s\n",
- strerror(errno));
- clp->in_stop = 1;
- guarded_stop_out(clp);
- return 1;
- }
- }
- if (res < blocks * clp->bs) {
- int o_blocks = blocks;
- stop_after_write = 1;
- blocks = res / clp->bs;
- if ((res % clp->bs) > 0) {
- blocks++;
- clp->in_partial++;
- }
- /* Reverse out + re-apply blocks on clp */
- clp->in_blk -= o_blocks;
- clp->in_count += o_blocks;
- rep->num_blks = blocks;
- clp->in_blk += blocks;
- clp->in_count -= blocks;
- }
- clp->in_done_count -= blocks;
- return stop_after_write;
-}
-
-void normal_out_operation(Rq_coll * clp, Rq_elem * rep, int blocks)
-{
- int res;
-
- /* enters holding out_mutex */
- while (((res = write(clp->outfd, rep->buffp,
- rep->num_blks * clp->bs)) < 0)
- && (EINTR == errno)) ;
- if (res < 0) {
- if (clp->coe) {
- fprintf(stderr, ">> ignored error for out blk=%d for "
- "%d bytes, %s\n", rep->blk,
- rep->num_blks * rep->bs, strerror(errno));
- res = rep->num_blks * clp->bs;
- } else {
- fprintf(stderr, "error normal write, %s\n",
- strerror(errno));
- guarded_stop_in(clp);
- clp->out_stop = 1;
- return;
- }
- }
- if (res < blocks * clp->bs) {
- blocks = res / clp->bs;
- if ((res % clp->bs) > 0) {
- blocks++;
- clp->out_partial++;
- }
- rep->num_blks = blocks;
- }
- clp->out_done_count -= blocks;
-}
-
-void sg_in_operation(Rq_coll * clp, Rq_elem * rep)
-{
- int res;
- int status;
-
- /* enters holding in_mutex */
- while (1) {
- res = sg_start_io(rep);
- if (1 == res)
- err_exit(ENOMEM, "sg starting in command");
- else if (res < 0) {
- fprintf(stderr, ME "inputting to sg failed, blk=%d\n",
- rep->blk);
- status = pthread_mutex_unlock(&clp->in_mutex);
- if (0 != status)
- err_exit(status, "unlock in_mutex");
- guarded_stop_both(clp);
- return;
- }
- /* Now release in mutex to let other reads run in parallel */
- status = pthread_mutex_unlock(&clp->in_mutex);
- if (0 != status)
- err_exit(status, "unlock in_mutex");
-
- res = sg_finish_io(rep->wr, rep, &clp->aux_mutex);
- if (res < 0) {
- if (clp->coe) {
- memset(rep->buffp, 0, rep->num_blks * rep->bs);
- fprintf(stderr,
- ">> substituted zeros for in blk=%d for "
- "%d bytes\n", rep->blk,
- rep->num_blks * rep->bs);
- } else {
- fprintf(stderr,
- "error finishing sg in command\n");
- guarded_stop_both(clp);
- return;
- }
- }
- if (res <= 0) { /* looks good, going to return */
- if (rep->dio_incomplete || rep->resid) {
- status = pthread_mutex_lock(&clp->aux_mutex);
- if (0 != status)
- err_exit(status, "lock aux_mutex");
- clp->dio_incomplete += rep->dio_incomplete;
- clp->sum_of_resids += rep->resid;
- status = pthread_mutex_unlock(&clp->aux_mutex);
- if (0 != status)
- err_exit(status, "unlock aux_mutex");
- }
- status = pthread_mutex_lock(&clp->in_mutex);
- if (0 != status)
- err_exit(status, "lock in_mutex");
- clp->in_done_count -= rep->num_blks;
- status = pthread_mutex_unlock(&clp->in_mutex);
- if (0 != status)
- err_exit(status, "unlock in_mutex");
- return;
- }
- /* else assume 1 == res so try again with same addr, count info */
- /* now re-acquire read mutex for balance */
- /* N.B. This re-read could now be out of read sequence */
- status = pthread_mutex_lock(&clp->in_mutex);
- if (0 != status)
- err_exit(status, "lock in_mutex");
- }
-}
-
-void sg_out_operation(Rq_coll * clp, Rq_elem * rep)
-{
- int res;
- int status;
-
- /* enters holding out_mutex */
- while (1) {
- res = sg_start_io(rep);
- if (1 == res)
- err_exit(ENOMEM, "sg starting out command");
- else if (res < 0) {
- fprintf(stderr,
- ME "outputting from sg failed, blk=%d\n",
- rep->blk);
- status = pthread_mutex_unlock(&clp->out_mutex);
- if (0 != status)
- err_exit(status, "unlock out_mutex");
- guarded_stop_both(clp);
- return;
- }
- /* Now release in mutex to let other reads run in parallel */
- status = pthread_mutex_unlock(&clp->out_mutex);
- if (0 != status)
- err_exit(status, "unlock out_mutex");
-
- res = sg_finish_io(rep->wr, rep, &clp->aux_mutex);
- if (res < 0) {
- if (clp->coe)
- fprintf(stderr,
- ">> ignored error for out blk=%d for "
- "%d bytes\n", rep->blk,
- rep->num_blks * rep->bs);
- else {
- fprintf(stderr,
- "error finishing sg out command\n");
- guarded_stop_both(clp);
- return;
- }
- }
- if (res <= 0) {
- if (rep->dio_incomplete || rep->resid) {
- status = pthread_mutex_lock(&clp->aux_mutex);
- if (0 != status)
- err_exit(status, "lock aux_mutex");
- clp->dio_incomplete += rep->dio_incomplete;
- clp->sum_of_resids += rep->resid;
- status = pthread_mutex_unlock(&clp->aux_mutex);
- if (0 != status)
- err_exit(status, "unlock aux_mutex");
- }
- status = pthread_mutex_lock(&clp->out_mutex);
- if (0 != status)
- err_exit(status, "lock out_mutex");
- clp->out_done_count -= rep->num_blks;
- status = pthread_mutex_unlock(&clp->out_mutex);
- if (0 != status)
- err_exit(status, "unlock out_mutex");
- return;
- }
- /* else assume 1 == res so try again with same addr, count info */
- /* now re-acquire out mutex for balance */
- /* N.B. This re-write could now be out of write sequence */
- status = pthread_mutex_lock(&clp->out_mutex);
- if (0 != status)
- err_exit(status, "lock out_mutex");
- }
-}
-
-int sg_start_io(Rq_elem * rep)
-{
- sg_io_hdr_t *hp = &rep->io_hdr;
- int fua = rep->wr ? (rep->fua_mode & 1) : (rep->fua_mode & 2);
- int res;
-
- if (sg_build_scsi_cdb(rep->cmd, rep->cdbsz, rep->num_blks, rep->blk,
- rep->wr, fua, 0)) {
- fprintf(stderr, ME "bad cdb build, start_blk=%d, blocks=%d\n",
- rep->blk, rep->num_blks);
- return -1;
- }
- memset(hp, 0, sizeof(sg_io_hdr_t));
- hp->interface_id = 'S';
- hp->cmd_len = rep->cdbsz;
- hp->cmdp = rep->cmd;
- hp->dxfer_direction = rep->wr ? SG_DXFER_TO_DEV : SG_DXFER_FROM_DEV;
- hp->dxfer_len = rep->bs * rep->num_blks;
- hp->dxferp = rep->buffp;
- hp->mx_sb_len = sizeof(rep->sb);
- hp->sbp = rep->sb;
- hp->timeout = DEF_TIMEOUT;
- hp->usr_ptr = rep;
- hp->pack_id = rep->blk;
- if (rep->dio)
- hp->flags |= SG_FLAG_DIRECT_IO;
- if (rep->debug > 8) {
- fprintf(stderr, "sg_start_io: SCSI %s, blk=%d num_blks=%d\n",
- rep->wr ? "WRITE" : "READ", rep->blk, rep->num_blks);
- sg_print_command(hp->cmdp);
- fprintf(stderr, "dir=%d, len=%d, dxfrp=%p, cmd_len=%d\n",
- hp->dxfer_direction, hp->dxfer_len, hp->dxferp,
- hp->cmd_len);
- }
-
- while (((res = write(rep->wr ? rep->outfd : rep->infd, hp,
- sizeof(sg_io_hdr_t))) < 0) && (EINTR == errno)) ;
- if (res < 0) {
- if (ENOMEM == errno)
- return 1;
- perror("starting io on sg device, error");
- return -1;
- }
- return 0;
-}
-
-/* -1 -> unrecoverable error, 0 -> successful, 1 -> try again */
-int sg_finish_io(int wr, Rq_elem * rep, pthread_mutex_t * a_mutp)
-{
- int res, status;
- sg_io_hdr_t io_hdr;
- sg_io_hdr_t *hp;
-#if 0
- static int testing = 0; /* thread dubious! */
-#endif
-
- memset(&io_hdr, 0, sizeof(sg_io_hdr_t));
- /* FORCE_PACK_ID active set only read packet with matching pack_id */
- io_hdr.interface_id = 'S';
- io_hdr.dxfer_direction = rep->wr ? SG_DXFER_TO_DEV : SG_DXFER_FROM_DEV;
- io_hdr.pack_id = rep->blk;
-
- while (((res = read(wr ? rep->outfd : rep->infd, &io_hdr,
- sizeof(sg_io_hdr_t))) < 0) && (EINTR == errno)) ;
- if (res < 0) {
- perror("finishing io on sg device, error");
- return -1;
- }
- if (rep != (Rq_elem *) io_hdr.usr_ptr)
- err_exit(0,
- "sg_finish_io: bad usr_ptr, request-response mismatch\n");
- memcpy(&rep->io_hdr, &io_hdr, sizeof(sg_io_hdr_t));
- hp = &rep->io_hdr;
-
- switch (sg_err_category3(hp)) {
- case SG_ERR_CAT_CLEAN:
- break;
- case SG_ERR_CAT_RECOVERED:
- fprintf(stderr, "Recovered error on block=%d, num=%d\n",
- rep->blk, rep->num_blks);
- break;
- case SG_ERR_CAT_MEDIA_CHANGED:
- return 1;
- default:
- {
- char ebuff[EBUFF_SZ];
-
- snprintf(ebuff, EBUFF_SZ,
- "%s blk=%d", rep->wr ? "writing" : "reading",
- rep->blk);
- status = pthread_mutex_lock(a_mutp);
- if (0 != status)
- err_exit(status, "lock aux_mutex");
- sg_chk_n_print3(ebuff, hp);
- status = pthread_mutex_unlock(a_mutp);
- if (0 != status)
- err_exit(status, "unlock aux_mutex");
- return -1;
- }
- }
-#if 0
- if (0 == (++testing % 100))
- return -1;
-#endif
- if (rep->dio &&
- ((hp->info & SG_INFO_DIRECT_IO_MASK) != SG_INFO_DIRECT_IO))
- rep->dio_incomplete = 1; /* count dios done as indirect IO */
- else
- rep->dio_incomplete = 0;
- rep->resid = hp->resid;
- if (rep->debug > 8)
- fprintf(stderr, "sg_finish_io: completed %s\n",
- wr ? "WRITE" : "READ");
- return 0;
-}
-
-int sg_prepare(int fd, int bs, int bpt, int *scsi_typep)
-{
- int res, t;
-
- res = ioctl(fd, SG_GET_VERSION_NUM, &t);
- if ((res < 0) || (t < 30000)) {
- fprintf(stderr, ME "sg driver prior to 3.x.y\n");
- return 1;
- }
- res = 0;
- t = bs * bpt;
- res = ioctl(fd, SG_SET_RESERVED_SIZE, &t);
- if (res < 0)
- perror(ME "SG_SET_RESERVED_SIZE error");
- t = 1;
- res = ioctl(fd, SG_SET_FORCE_PACK_ID, &t);
- if (res < 0)
- perror(ME "SG_SET_FORCE_PACK_ID error");
- if (scsi_typep) {
- struct sg_scsi_id info;
-
- res = ioctl(fd, SG_GET_SCSI_ID, &info);
- if (res < 0)
- perror(ME "SG_SET_SCSI_ID error");
- *scsi_typep = info.scsi_type;
- }
- return 0;
-}
-
-int do_scsi_sgp_read_write(char *device)
-{
- int skip = 0;
- int seek = 0;
- int count = -1;
- char inf[INOUTF_SZ];
- char outf[INOUTF_SZ];
- int res, k;
- int in_num_sect = 0;
- int out_num_sect = 0;
- int num_threads = DEF_NUM_THREADS;
- pthread_t threads[MAX_NUM_THREADS];
- int do_time = 1;
- int do_sync = 1;
- int in_sect_sz, out_sect_sz, status, infull, outfull;
- void *vp;
- char ebuff[EBUFF_SZ];
- struct timeval start_tm, end_tm;
- Rq_coll rcoll;
-
- print_msg(TEST_BREAK, __FUNCTION__);
-
- memset(&rcoll, 0, sizeof(Rq_coll));
- rcoll.bpt = DEF_BLOCKS_PER_TRANSFER;
- rcoll.in_type = FT_OTHER;
- rcoll.out_type = FT_OTHER;
- rcoll.cdbsz = DEF_SCSI_CDBSZ;
-
- strcpy(inf, "/dev/zero");
- strcpy(outf, device);
-
- if (rcoll.bs <= 0) {
- rcoll.bs = DEF_BLOCK_SIZE;
- fprintf(stderr,
- "Assume default 'bs' (block size) of %d bytes\n",
- rcoll.bs);
- }
-
- if (rcoll.debug)
- fprintf(stderr, ME "if=%s skip=%d of=%s seek=%d count=%d\n",
- inf, skip, outf, seek, count);
-
- rcoll.infd = STDIN_FILENO;
- rcoll.outfd = STDOUT_FILENO;
- if (inf[0] && ('-' != inf[0])) {
- rcoll.in_type = dd_filetype(inf);
-
- if (FT_ST == rcoll.in_type) {
- fprintf(stderr,
- ME "unable to use scsi tape device %s\n", inf);
- return 1;
- } else if (FT_SG == rcoll.in_type) {
- if ((rcoll.infd = open(inf, O_RDWR)) < 0) {
- snprintf(ebuff, EBUFF_SZ,
- ME "could not open %s for sg reading",
- inf);
- perror(ebuff);
- return 1;
- }
- if (sg_prepare(rcoll.infd, rcoll.bs, rcoll.bpt,
- &rcoll.in_scsi_type))
- return 1;
- } else {
- if ((rcoll.infd = open(inf, O_RDONLY)) < 0) {
- snprintf(ebuff, EBUFF_SZ,
- ME "could not open %s for reading",
- inf);
- perror(ebuff);
- return 1;
- } else if (skip > 0) {
- llse_loff_t offset = skip;
-
- offset *= rcoll.bs; /* could exceed 32 here! */
- if (llse_llseek(rcoll.infd, offset, SEEK_SET) <
- 0) {
- snprintf(ebuff, EBUFF_SZ,
- ME
- "couldn't skip to required position on %s",
- inf);
- perror(ebuff);
- return 1;
- }
- }
- }
- }
- if (outf[0] && ('-' != outf[0])) {
- rcoll.out_type = dd_filetype(outf);
-
- if (FT_ST == rcoll.out_type) {
- fprintf(stderr,
- ME "unable to use scsi tape device %s\n", outf);
- return 1;
- } else if (FT_SG == rcoll.out_type) {
- if ((rcoll.outfd = open(outf, O_RDWR)) < 0) {
- snprintf(ebuff, EBUFF_SZ,
- ME "could not open %s for sg writing",
- outf);
- perror(ebuff);
- return 1;
- }
-
- if (sg_prepare(rcoll.outfd, rcoll.bs, rcoll.bpt,
- &rcoll.out_scsi_type))
- return 1;
- } else if (FT_DEV_NULL == rcoll.out_type)
- rcoll.outfd = -1; /* don't bother opening */
- else {
- if (FT_RAW != rcoll.out_type) {
- if ((rcoll.outfd =
- open(outf, O_WRONLY | O_CREAT,
- 0666)) < 0) {
- snprintf(ebuff, EBUFF_SZ,
- ME
- "could not open %s for writing",
- outf);
- perror(ebuff);
- return 1;
- }
- } else {
- if ((rcoll.outfd = open(outf, O_WRONLY)) < 0) {
- snprintf(ebuff, EBUFF_SZ,
- ME
- "could not open %s for raw writing",
- outf);
- perror(ebuff);
- return 1;
- }
- }
- if (seek > 0) {
- llse_loff_t offset = seek;
-
- offset *= rcoll.bs; /* could exceed 32 bits here! */
- if (llse_llseek(rcoll.outfd, offset, SEEK_SET) <
- 0) {
- snprintf(ebuff, EBUFF_SZ,
- ME
- "couldn't seek to required position on %s",
- outf);
- perror(ebuff);
- return 1;
- }
- }
- }
- }
- if ((STDIN_FILENO == rcoll.infd) && (STDOUT_FILENO == rcoll.outfd)) {
- fprintf(stderr,
- "Disallow both if and of to be stdin and stdout");
- return 1;
- }
- if (count < 0) {
- if (FT_SG == rcoll.in_type) {
- res =
- read_capacity(rcoll.infd, &in_num_sect,
- &in_sect_sz);
- if (2 == res) {
- fprintf(stderr,
- "Unit attention, media changed(in), continuing\n");
- res =
- read_capacity(rcoll.infd, &in_num_sect,
- &in_sect_sz);
- }
- if (0 != res) {
- fprintf(stderr,
- "Unable to read capacity on %s\n", inf);
- in_num_sect = -1;
- } else {
- if (in_num_sect > skip)
- in_num_sect -= skip;
- }
- }
- if (FT_SG == rcoll.out_type) {
- res =
- read_capacity(rcoll.outfd, &out_num_sect,
- &out_sect_sz);
- if (2 == res) {
- fprintf(stderr,
- "Unit attention, media changed(out), continuing\n");
- res =
- read_capacity(rcoll.outfd, &out_num_sect,
- &out_sect_sz);
- }
- if (0 != res) {
- fprintf(stderr,
- "Unable to read capacity on %s\n",
- outf);
- out_num_sect = -1;
- } else {
- if (out_num_sect > seek)
- out_num_sect -= seek;
- }
- }
- if (in_num_sect > 0) {
- if (out_num_sect > 0)
- count =
- (in_num_sect >
- out_num_sect) ? out_num_sect : in_num_sect;
- else
- count = in_num_sect;
- } else
- count = out_num_sect;
- }
- if (rcoll.debug > 1)
- fprintf(stderr, "Start of loop, count=%d, in_num_sect=%d, "
- "out_num_sect=%d\n", count, in_num_sect, out_num_sect);
- if (count < 0) {
- fprintf(stderr, "Couldn't calculate count, please give one\n");
- return 1;
- }
-
- rcoll.in_count = count;
- rcoll.in_done_count = count;
- rcoll.skip = skip;
- rcoll.in_blk = skip;
- rcoll.out_count = count;
- rcoll.out_done_count = count;
- rcoll.seek = seek;
- rcoll.out_blk = seek;
- status = pthread_mutex_init(&rcoll.in_mutex, NULL);
- if (0 != status)
- err_exit(status, "init in_mutex");
- status = pthread_mutex_init(&rcoll.out_mutex, NULL);
- if (0 != status)
- err_exit(status, "init out_mutex");
- status = pthread_mutex_init(&rcoll.aux_mutex, NULL);
- if (0 != status)
- err_exit(status, "init aux_mutex");
- status = pthread_cond_init(&rcoll.out_sync_cv, NULL);
- if (0 != status)
- err_exit(status, "init out_sync_cv");
-
- sigemptyset(&signal_set);
- sigaddset(&signal_set, SIGINT);
- status = pthread_sigmask(SIG_BLOCK, &signal_set, NULL);
- if (0 != status)
- err_exit(status, "pthread_sigmask");
- status = pthread_create(&sig_listen_thread_id, NULL,
- sig_listen_thread, (void *)&rcoll);
- if (0 != status)
- err_exit(status, "pthread_create, sig...");
-
- if (do_time) {
- start_tm.tv_sec = 0;
- start_tm.tv_usec = 0;
- gettimeofday(&start_tm, NULL);
- }
-
-/* vvvvvvvvvvv Start worker threads vvvvvvvvvvvvvvvvvvvvvvvv */
- if ((rcoll.out_done_count > 0) && (num_threads > 0)) {
- /* Run 1 work thread to shake down infant retryable stuff */
- status = pthread_mutex_lock(&rcoll.out_mutex);
- if (0 != status)
- err_exit(status, "lock out_mutex");
- status = pthread_create(&threads[0], NULL, read_write_thread,
- (void *)&rcoll);
- if (0 != status)
- err_exit(status, "pthread_create");
- if (rcoll.debug)
- fprintf(stderr, "Starting worker thread k=0\n");
-
- /* wait for any broadcast */
- pthread_cleanup_push(cleanup_out, (void *)&rcoll);
- status =
- pthread_cond_wait(&rcoll.out_sync_cv, &rcoll.out_mutex);
- if (0 != status)
- err_exit(status, "cond out_sync_cv");
- pthread_cleanup_pop(0);
- status = pthread_mutex_unlock(&rcoll.out_mutex);
- if (0 != status)
- err_exit(status, "unlock out_mutex");
-
- /* now start the rest of the threads */
- for (k = 1; k < num_threads; ++k) {
- status =
- pthread_create(&threads[k], NULL, read_write_thread,
- (void *)&rcoll);
- if (0 != status)
- err_exit(status, "pthread_create");
- if (rcoll.debug)
- fprintf(stderr, "Starting worker thread k=%d\n",
- k);
- }
-
- /* now wait for worker threads to finish */
- for (k = 0; k < num_threads; ++k) {
- status = pthread_join(threads[k], &vp);
- if (0 != status)
- err_exit(status, "pthread_join");
- if (rcoll.debug)
- fprintf(stderr,
- "Worker thread k=%d terminated\n", k);
- }
- }
-
- if ((do_time) && (start_tm.tv_sec || start_tm.tv_usec)) {
- struct timeval res_tm;
- double a, b;
-
- gettimeofday(&end_tm, NULL);
- res_tm.tv_sec = end_tm.tv_sec - start_tm.tv_sec;
- res_tm.tv_usec = end_tm.tv_usec - start_tm.tv_usec;
- if (res_tm.tv_usec < 0) {
- --res_tm.tv_sec;
- res_tm.tv_usec += 1000000;
- }
- a = res_tm.tv_sec;
- a += (0.000001 * res_tm.tv_usec);
- b = (double)rcoll.bs * (count - rcoll.out_done_count);
- printf("time to transfer data was %d.%06d secs",
- (int)res_tm.tv_sec, (int)res_tm.tv_usec);
- if ((a > 0.00001) && (b > 511))
- printf(", %.2f MB/sec\n", b / (a * 1000000.0));
- else
- printf("\n");
- }
- if (do_sync) {
- if (FT_SG == rcoll.out_type) {
- fprintf(stderr, ">> Synchronizing cache on %s\n", outf);
- res = sync_cache(rcoll.outfd);
- if (2 == res) {
- fprintf(stderr,
- "Unit attention, media changed(in), continuing\n");
- res = sync_cache(rcoll.outfd);
- }
- if (0 != res)
- fprintf(stderr,
- "Unable to synchronize cache\n");
- }
- }
-
- status = pthread_cancel(sig_listen_thread_id);
- if (0 != status)
- err_exit(status, "pthread_cancel");
- if (STDIN_FILENO != rcoll.infd)
- close(rcoll.infd);
- if ((STDOUT_FILENO != rcoll.outfd) && (FT_DEV_NULL != rcoll.out_type))
- close(rcoll.outfd);
- res = 0;
- if (0 != rcoll.out_count) {
- fprintf(stderr,
- ">>>> Some error occurred, remaining blocks=%d\n",
- rcoll.out_count);
- res = 2;
- }
- infull = count - rcoll.in_done_count - rcoll.in_partial;
- fprintf(stderr, "%d+%d records in\n", infull, rcoll.in_partial);
- outfull = count - rcoll.out_done_count - rcoll.out_partial;
- fprintf(stderr, "%d+%d records out\n", outfull, rcoll.out_partial);
- if (rcoll.dio_incomplete) {
- int fd;
- char c;
-
- fprintf(stderr,
- ">> Direct IO requested but incomplete %d times\n",
- rcoll.dio_incomplete);
- if ((fd = open(proc_allow_dio, O_RDONLY)) >= 0) {
- if (1 == read(fd, &c, 1)) {
- if ('0' == c)
- fprintf(stderr,
- ">>> %s set to '0' but should be set "
- "to '1' for direct IO\n",
- proc_allow_dio);
- }
- close(fd);
- }
- }
- if (rcoll.sum_of_resids)
- fprintf(stderr, ">> Non-zero sum of residual counts=%d\n",
- rcoll.sum_of_resids);
- return res;
-}
diff --git a/testcases/kernel/fs/scsi/ltpscsi/sg_err.c b/testcases/kernel/fs/scsi/ltpscsi/sg_err.c
deleted file mode 100644
index 08eba2cf3..000000000
--- a/testcases/kernel/fs/scsi/ltpscsi/sg_err.c
+++ /dev/null
@@ -1,1379 +0,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include "sg_include.h"
-#include "sg_err.h"
-
-/* This file is a huge cut, paste and hack from linux/drivers/scsi/constant.c
-* which I guess was written by:
-* Copyright (C) 1993, 1994, 1995 Eric Youngdale
-
-* The rest of this is:
-* Copyright (C) 1999 - 2003 D. Gilbert
-*
-* 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, or (at your option)
-* any later version.
-*
-* ASCII values for a number of symbolic constants, printing functions, etc.
-*
-* Some of the tables have been updated for SCSI 2.
-* Additions for SCSI 3+ (SPC-3 T10/1416-D Rev 07 3 May 2002)
-*
-* Version 0.89 (20030313)
-* sense key specific field (bytes 15-17) decoding [Trent Piepho]
-*/
-
-#define OUTP stderr
-
-static const unsigned char scsi_command_size[8] = { 6, 10, 10, 12,
- 16, 12, 10, 10
-};
-
-#define COMMAND_SIZE(opcode) scsi_command_size[((opcode) >> 5) & 7]
-
-static const char unknown[] = "UNKNOWN";
-
-static const char *group_0_commands[] = {
-/* 00-03 */ "Test Unit Ready", "Rezero Unit", unknown, "Request Sense",
-/* 04-07 */ "Format Unit", "Read Block Limits", unknown,
- "Reasssign Blocks",
-/* 08-0d */ "Read (6)", unknown, "Write (6)", "Seek (6)", unknown,
- unknown,
-/* 0e-12 */ unknown, "Read Reverse", "Write Filemarks", "Space",
- "Inquiry",
-/* 13-16 */ "Verify", "Recover Buffered Data", "Mode Select", "Reserve",
-/* 17-1b */ "Release", "Copy", "Erase", "Mode Sense", "Start/Stop Unit",
-/* 1c-1d */ "Receive Diagnostic", "Send Diagnostic",
-/* 1e-1f */ "Prevent/Allow Medium Removal", unknown,
-};
-
-static const char *group_1_commands[] = {
-/* 20-23 */ unknown, unknown, unknown, "Read Format capacities",
-/* 24-28 */ "Set window", "Read Capacity",
- unknown, unknown, "Read (10)",
-/* 29-2d */ "Read Generation", "Write (10)", "Seek (10)", "Erase",
- "Read updated block",
-/* 2e-31 */ "Write Verify", "Verify", "Search High", "Search Equal",
-/* 32-34 */ "Search Low", "Set Limits", "Prefetch or Read Position",
-/* 35-37 */ "Synchronize Cache", "Lock/Unlock Cache",
- "Read Defect Data",
-/* 38-3c */ "Medium Scan", "Compare", "Copy Verify", "Write Buffer",
- "Read Buffer",
-/* 3d-3f */ "Update Block", "Read Long", "Write Long",
-};
-
-static const char *group_2_commands[] = {
-/* 40-41 */ "Change Definition", "Write Same",
-/* 42-48 */ "Read sub-channel", "Read TOC", "Read header",
- "Play audio (10)", "Get configuration", "Play audio msf",
- "Play audio track/index",
-/* 49-4f */ "Play track relative (10)", "Get event status notification",
- "Pause/resume", "Log Select", "Log Sense", "Stop play/scan",
- unknown,
-/* 50-55 */ "Xdwrite", "Xpwrite, Read disk info",
- "Xdread, Read track info",
- "Reserve track", "Send OPC onfo", "Mode Select (10)",
-/* 56-5b */ "Reserve (10)", "Release (10)", "Repair track",
- "Read master cue",
- "Mode Sense (10)", "Close track/session",
-/* 5c-5f */ "Read buffer capacity", "Send cue sheet",
- "Persistent reserve in",
- "Persistent reserve out",
-};
-
-/* The following are 16 byte commands in group 4 */
-static const char *group_4_commands[] = {
-/* 80-84 */ "Xdwrite (16)", "Rebuild (16)", "Regenerate (16)",
- "Extended copy",
- "Receive copy results",
-/* 85-89 */ "Memory Export In (16)", "Access control in",
- "Access control out",
- "Read (16)", "Memory Export Out (16)",
-/* 8a-8f */ "Write (16)", unknown, "Read attributes",
- "Write attributes",
- "Write and verify (16)", "Verify (16)",
-/* 90-94 */ "Pre-fetch (16)", "Synchronize cache (16)",
- "Lock/unlock cache (16)", "Write same (16)", unknown,
-/* 95-99 */ unknown, unknown, unknown, unknown, unknown,
-/* 9a-9f */ unknown, unknown, unknown, unknown, "Service action in",
- "Service action out",
-};
-
-/* The following are 12 byte commands in group 5 */
-static const char *group_5_commands[] = {
-/* a0-a5 */ "Report luns", "Blank", "Send event", "Maintenance (in)",
- "Maintenance (out)", "Move medium/play audio(12)",
-/* a6-a9 */ "Exchange medium", "Move medium attached", "Read(12)",
- "Play track relative(12)",
-/* aa-ae */ "Write(12)", unknown, "Erase(12), Get Performance",
- "Read DVD structure", "Write and verify(12)",
-/* af-b1 */ "Verify(12)", "Search data high(12)",
- "Search data equal(12)",
-/* b2-b4 */ "Search data low(12)", "Set limits(12)",
- "Read element status attached",
-/* b5-b6 */ "Request volume element address",
- "Send volume tag, set streaming",
-/* b7-b9 */ "Read defect data(12)", "Read element status",
- "Read CD msf",
-/* ba-bc */ "Redundancy group (in), Scan",
- "Redundancy group (out), Set cd-rom speed", "Spare (in), Play cd",
-/* bd-bf */ "Spare (out), Mechanism status", "Volume set (in), Read cd",
- "Volume set (out), Send DVD structure",
-};
-
-#define group(opcode) (((opcode) >> 5) & 7)
-
-#define RESERVED_GROUP 0
-#define VENDOR_GROUP 1
-
-static const char **commands[] = {
- group_0_commands, group_1_commands, group_2_commands,
- (const char **)RESERVED_GROUP, group_4_commands,
- group_5_commands, (const char **)VENDOR_GROUP,
- (const char **)VENDOR_GROUP
-};
-
-static const char reserved[] = "RESERVED";
-static const char vendor[] = "VENDOR SPECIFIC";
-
-static void print_opcode(int opcode)
-{
- const char **table = commands[group(opcode)];
-
- switch ((unsigned long)table) {
- case RESERVED_GROUP:
- fprintf(OUTP, "%s(0x%02x)", reserved, opcode);
- break;
- case VENDOR_GROUP:
- fprintf(OUTP, "%s(0x%02x)", vendor, opcode);
- break;
- default:
- fprintf(OUTP, "%s", table[opcode & 0x1f]);
- break;
- }
-}
-
-void sg_print_command(const unsigned char *command)
-{
- int k, s;
- print_opcode(command[0]);
- fprintf(OUTP, " [");
- for (k = 0, s = COMMAND_SIZE(command[0]); k < s; ++k)
- fprintf(OUTP, "%02x ", command[k]);
- fprintf(OUTP, "]\n");
-}
-
-void sg_print_status(int masked_status)
-{
- int scsi_status = (masked_status << 1) & 0x7e;
-
- sg_print_scsi_status(scsi_status);
-}
-
-void sg_print_scsi_status(int scsi_status)
-{
- const char *ccp;
-
- scsi_status &= 0x7e; /* sanitize as much as possible */
- switch (scsi_status) {
- case 0:
- ccp = "Good";
- break;
- case 0x2:
- ccp = "Check Condition";
- break;
- case 0x4:
- ccp = "Condition Met";
- break;
- case 0x8:
- ccp = "Busy";
- break;
- case 0x10:
- ccp = "Intermediate";
- break;
- case 0x14:
- ccp = "Intermediate-Condition Met";
- break;
- case 0x18:
- ccp = "Reservation Conflict";
- break;
- case 0x22:
- ccp = "Command Terminated (obsolete)";
- break;
- case 0x28:
- ccp = "Task set Full";
- break;
- case 0x30:
- ccp = "ACA Active";
- break;
- case 0x40:
- ccp = "Task Aborted";
- break;
- default:
- ccp = "Unknown status";
- break;
- }
- fprintf(OUTP, "%s ", ccp);
-}
-
-/* In brackets is the related SCSI document (see www.t10.org) with the */
-/* peripheral device type after the colon */
-/* No programmatic use is made of these flags currently */
-#define D 0x0001 /* DIRECT ACCESS DEVICE (disk) [SBC-2: 0] */
-#define T 0x0002 /* SEQUENTIAL ACCESS DEVICE (tape) [SSC: 1] */
-#define L 0x0004 /* PRINTER DEVICE [SSC: 2] */
-#define P 0x0008 /* PROCESSOR DEVICE [SPC-2: 3] */
-#define W 0x0010 /* WRITE ONCE READ MULTIPLE DEVICE [SBC-2: 4] */
-#define R 0x0020 /* CD/DVD DEVICE [MMC-2: 5] */
-#define S 0x0040 /* SCANNER DEVICE [SCSI-2 (obsolete): 6] */
-#define O 0x0080 /* OPTICAL MEMORY DEVICE [SBC-2: 7] */
-#define M 0x0100 /* MEDIA CHANGER DEVICE [SMC-2: 8] */
-#define C 0x0200 /* COMMUNICATION DEVICE [SCSI-2 (obsolete): 9] */
-#define A 0x0400 /* ARRAY STORAGE [SCC-2: 12] */
-#define E 0x0800 /* ENCLOSURE SERVICES DEVICE [SES: 13] */
-#define B 0x1000 /* SIMPLIFIED DIRECT ACCESS DEVICE [RBC: 14] */
-#define K 0x2000 /* OPTICAL CARD READER/WRITER DEVICE [OCRW: 15] */
-
-#define SC_ALL_DEVS ( D|T|L|P|W|R|S|O|M|C|A|E|B|K )
-
-/* oft used strings are encoded using ASCII codes 0x1 to 0x1f . */
-/* This is to save space. This encoding should be UTF-8 and */
-/* UTF-16 friendly. */
-#define SC_AUDIO_PLAY_OPERATION "\x1"
-#define SC_LOGICAL_UNIT "\x2"
-#define SC_NOT_READY "\x3"
-#define SC_OPERATION "\x4"
-#define SC_IN_PROGRESS "\x5"
-#define SC_HARDWARE_IF "\x6"
-#define SC_CONTROLLER_IF "\x7"
-#define SC_DATA_CHANNEL_IF "\x8"
-#define SC_SERVO_IF "\x9"
-#define SC_SPINDLE_IF "\xa"
-#define SC_FIRMWARE_IF "\xb"
-#define SC_RECOVERED_DATA "\xc"
-#define SC_ERROR_RATE_TOO_HIGH "\xd"
-#define SC_TIMES_TOO_HIGH "\xe"
-
-struct error_info {
- unsigned char code1, code2;
- unsigned short int devices;
- const char *text;
-};
-
-struct error_info2 {
- unsigned char code1, code2_min, code2_max;
- unsigned short int devices;
- const char *text;
-};
-
-static struct error_info2 additional2[] = {
- {0x40, 0x00, 0x7f, D, "Ram failure (%x)"},
- {0x40, 0x80, 0xff, D | T | L | P | W | R | S | O | M | C,
- "Diagnostic failure on component (%x)"},
- {0x41, 0x00, 0xff, D, "Data path failure (%x)"},
- {0x42, 0x00, 0xff, D, "Power-on or self-test failure (%x)"},
- {0, 0, 0, 0, NULL}
-};
-
-static struct error_info additional[] = {
- {0x00, 0x00, SC_ALL_DEVS, "No additional sense information"},
- {0x00, 0x01, T, "Filemark detected"},
- {0x00, 0x02, T | S, "End-of-partition/medium detected"},
- {0x00, 0x03, T, "Setmark detected"},
- {0x00, 0x04, T | S, "Beginning-of-partition/medium detected"},
- {0x00, 0x05, T | L | S, "End-of-data detected"},
- {0x00, 0x06, SC_ALL_DEVS, "I/O process terminated"},
- {0x00, 0x11, R, SC_AUDIO_PLAY_OPERATION SC_IN_PROGRESS},
- {0x00, 0x12, R, SC_AUDIO_PLAY_OPERATION "paused"},
- {0x00, 0x13, R, SC_AUDIO_PLAY_OPERATION "successfully completed"},
- {0x00, 0x14, R, SC_AUDIO_PLAY_OPERATION "stopped due to error"},
- {0x00, 0x15, R, "No current audio status to return"},
- {0x00, 0x16, SC_ALL_DEVS, SC_OPERATION SC_IN_PROGRESS},
- {0x00, 0x17, D | T | L | W | R | S | O | M | A | E | B | K,
- "Cleaning requested"},
- {0x00, 0x18, T, "Erase" SC_OPERATION SC_IN_PROGRESS},
- {0x00, 0x19, T, "Locate" SC_OPERATION SC_IN_PROGRESS},
- {0x00, 0x1a, T, "Rewind" SC_OPERATION SC_IN_PROGRESS},
- {0x00, 0x1b, T, "Set capacity" SC_OPERATION SC_IN_PROGRESS},
- {0x00, 0x1c, T, "Verify" SC_OPERATION SC_IN_PROGRESS},
- {0x01, 0x00, D | W | O | B | K, "No index/sector signal"},
- {0x02, 0x00, D | W | R | O | M | B | K, "No seek complete"},
- {0x03, 0x00, D | T | L | W | S | O | B | K,
- "Peripheral device write fault"},
- {0x03, 0x01, T, "No write current"},
- {0x03, 0x02, T, "Excessive write errors"},
- {0x04, 0x00, SC_ALL_DEVS,
- SC_LOGICAL_UNIT SC_NOT_READY "cause not reportable"},
- {0x04, 0x01, SC_ALL_DEVS,
- SC_LOGICAL_UNIT "is" SC_IN_PROGRESS "of becoming ready"},
- {0x04, 0x02, SC_ALL_DEVS,
- SC_LOGICAL_UNIT SC_NOT_READY "initializing cmd. required"},
- {0x04, 0x03, SC_ALL_DEVS,
- SC_LOGICAL_UNIT SC_NOT_READY "manual intervention required"},
- {0x04, 0x04, D | T | L | R | O | B,
- SC_LOGICAL_UNIT SC_NOT_READY "format" SC_IN_PROGRESS},
- {0x04, 0x05, D | T | W | O | M | C | A | B | K,
- SC_LOGICAL_UNIT SC_NOT_READY "rebuild" SC_IN_PROGRESS},
- {0x04, 0x06, D | T | W | O | M | C | A | B | K,
- SC_LOGICAL_UNIT SC_NOT_READY "recalculation" SC_IN_PROGRESS},
- {0x04, 0x07, SC_ALL_DEVS,
- SC_LOGICAL_UNIT SC_NOT_READY SC_OPERATION SC_IN_PROGRESS},
- {0x04, 0x08, R,
- SC_LOGICAL_UNIT SC_NOT_READY "long write" SC_IN_PROGRESS},
- {0x04, 0x09, SC_ALL_DEVS,
- SC_LOGICAL_UNIT SC_NOT_READY "self-test" SC_IN_PROGRESS},
- {0x04, 0x0a, SC_ALL_DEVS,
- SC_LOGICAL_UNIT "not accessible, asymmetric access state transition"},
- {0x04, 0x0b, SC_ALL_DEVS,
- SC_LOGICAL_UNIT "not accessible, target port in standby state"},
- {0x04, 0x0c, SC_ALL_DEVS,
- SC_LOGICAL_UNIT "not accessible, target port in unavailable state"},
- {0x04, 0x10, SC_ALL_DEVS,
- SC_LOGICAL_UNIT SC_NOT_READY "auxiliary memory not accessible"},
- {0x05, 0x00, D | T | L | W | R | S | O | M | C | A | E | B | K,
- SC_LOGICAL_UNIT "does not respond to selection"},
- {0x06, 0x00, D | W | R | O | M | B | K, "No reference position found"},
- {0x07, 0x00, D | T | L | W | R | S | O | M | B | K,
- "Multiple peripheral devices selected"},
- {0x08, 0x00, D | T | L | W | R | S | O | M | C | A | E | B | K,
- SC_LOGICAL_UNIT "communication failure"},
- {0x08, 0x01, D | T | L | W | R | S | O | M | C | A | E | B | K,
- SC_LOGICAL_UNIT "communication time-out"},
- {0x08, 0x02, D | T | L | W | R | S | O | M | C | A | E | B | K,
- SC_LOGICAL_UNIT "communication parity error"},
- {0x08, 0x03, D | T | R | O | M | B | K,
- SC_LOGICAL_UNIT "communication CRC error (Ultra-DMA/32)"},
- {0x08, 0x04, D | T | L | P | W | R | S | O | C | K,
- "Unreachable copy target"},
- {0x09, 0x00, D | T | W | R | O | B, "Track following error"},
- {0x09, 0x01, W | R | O | K, "Tracking servo failure"},
- {0x09, 0x02, W | R | O | K, "Focus servo failure"},
- {0x09, 0x03, W | R | O, "Spindle servo failure"},
- {0x09, 0x04, D | T | W | R | O | B, "Head select fault"},
- {0x0A, 0x00, SC_ALL_DEVS, "Error log overflow"},
- {0x0B, 0x00, SC_ALL_DEVS, "Warning"},
- {0x0B, 0x01, SC_ALL_DEVS, "Warning - specified temperature exceeded"},
- {0x0B, 0x02, SC_ALL_DEVS, "Warning - enclosure degraded"},
- {0x0C, 0x00, T | R | S, "Write error"},
- {0x0C, 0x01, K, "Write error - recovered with auto reallocation"},
- {0x0C, 0x02, D | W | O | B | K,
- "Write error - auto reallocation failed"},
- {0x0C, 0x03, D | W | O | B | K, "Write error - recommend reassignment"},
- {0x0C, 0x04, D | T | W | O | B, "Compression check miscompare error"},
- {0x0C, 0x05, D | T | W | O | B,
- "Data expansion occurred during compression"},
- {0x0C, 0x06, D | T | W | O | B, "Block not compressible"},
- {0x0C, 0x07, R, "Write error - recovery needed"},
- {0x0C, 0x08, R, "Write error - recovery failed"},
- {0x0C, 0x09, R, "Write error - loss of streaming"},
- {0x0C, 0x0A, R, "Write error - padding blocks added"},
- {0x0C, 0x0B, D | T | W | R | O | M | B, "Auxiliary memory write error"},
- {0x0C, 0x0C, SC_ALL_DEVS, "Write error - unexpected unsolicited data"},
- {0x0C, 0x0D, SC_ALL_DEVS, "Write error - not enough unsolicited data"},
- {0x0D, 0x00, D | T | L | P | W | R | S | O | C | A | K,
- "Error detected by third party temporary initiator"},
- {0x0D, 0x01, D | T | L | P | W | R | S | O | C | A | K,
- "Third party device failure"},
- {0x0D, 0x02, D | T | L | P | W | R | S | O | C | A | K,
- "Copy target device not reachable"},
- {0x0D, 0x03, D | T | L | P | W | R | S | O | C | A | K,
- "Incorrect copy target device"},
- {0x0D, 0x04, D | T | L | P | W | R | S | O | C | A | K,
- "Copy target device underrun"},
- {0x0D, 0x05, D | T | L | P | W | R | S | O | C | A | K,
- "Copy target device overrun"},
- {0x10, 0x00, D | W | O | B | K, "Id CRC or ECC error"},
- {0x11, 0x00, D | T | W | R | S | O | B | K, "Unrecovered read error"},
- {0x11, 0x01, D | T | W | R | S | O | B | K, "Read retries exhausted"},
- {0x11, 0x02, D | T | W | R | S | O | B | K,
- "Error too long to correct"},
- {0x11, 0x03, D | T | W | S | O | B | K, "Multiple read errors"},
- {0x11, 0x04, D | W | O | B | K,
- "Unrecovered read error - auto reallocate failed"},
- {0x11, 0x05, W | R | O | B, "L-EC uncorrectable error"},
- {0x11, 0x06, W | R | O | B, "CIRC unrecovered error"},
- {0x11, 0x07, W | O | B, "Data re-synchronization error"},
- {0x11, 0x08, T, "Incomplete block read"},
- {0x11, 0x09, T, "No gap found"},
- {0x11, 0x0A, D | T | O | B | K, "Miscorrected error"},
- {0x11, 0x0B, D | W | O | B | K,
- "Unrecovered read error - recommend reassignment"},
- {0x11, 0x0C, D | W | O | B | K,
- "Unrecovered read error - recommend rewrite the data"},
- {0x11, 0x0D, D | T | W | R | O | B, "De-compression CRC error"},
- {0x11, 0x0E, D | T | W | R | O | B,
- "Cannot decompress using declared algorithm"},
- {0x11, 0x0F, R, "Error reading UPC/EAN number"},
- {0x11, 0x10, R, "Error reading ISRC number"},
- {0x11, 0x11, R, "Read error - loss of streaming"},
- {0x11, 0x12, D | T | W | R | O | M | B, "Auxiliary memory read error"},
- {0x11, 0x13, SC_ALL_DEVS, "Read error - failed retransmission request"},
- {0x12, 0x00, D | W | O | B | K, "Address mark not found for id field"},
- {0x13, 0x00, D | W | O | B | K,
- "Address mark not found for data field"},
- {0x14, 0x00, D | T | L | W | R | S | O | B | K,
- "Recorded entity not found"},
- {0x14, 0x01, D | T | W | R | O | B | K, "Record not found"},
- {0x14, 0x02, T, "Filemark or setmark not found"},
- {0x14, 0x03, T, "End-of-data not found"},
- {0x14, 0x04, T, "Block sequence error"},
- {0x14, 0x05, D | T | W | O | B | K,
- "Record not found - recommend reassignment"},
- {0x14, 0x06, D | T | W | O | B | K,
- "Record not found - data auto-reallocated"},
- {0x14, 0x07, T, "Locate" SC_OPERATION " failure"},
- {0x15, 0x00, D | T | L | W | R | S | O | M | B | K,
- "Random positioning error"},
- {0x15, 0x01, D | T | L | W | R | S | O | M | B | K,
- "Mechanical positioning error"},
- {0x15, 0x02, D | T | W | R | O | B | K,
- "Positioning error detected by read of medium"},
- {0x16, 0x00, D | W | O | B | K, "Data synchronization mark error"},
- {0x16, 0x01, D | W | O | B | K, "Data sync error - data rewritten"},
- {0x16, 0x02, D | W | O | B | K, "Data sync error - recommend rewrite"},
- {0x16, 0x03, D | W | O | B | K,
- "Data sync error - data auto-reallocated"},
- {0x16, 0x04, D | W | O | B | K,
- "Data sync error - recommend reassignment"},
- {0x17, 0x00, D | T | W | R | S | O | B | K,
- SC_RECOVERED_DATA "with no error correction applied"},
- {0x17, 0x01, D | T | W | R | S | O | B | K,
- SC_RECOVERED_DATA "with retries"},
- {0x17, 0x02, D | T | W | R | O | B | K,
- SC_RECOVERED_DATA "with positive head offset"},
- {0x17, 0x03, D | T | W | R | O | B | K,
- SC_RECOVERED_DATA "with negative head offset"},
- {0x17, 0x04, W | R | O | B,
- SC_RECOVERED_DATA "with retries and/or circ applied"},
- {0x17, 0x05, D | W | R | O | B | K,
- SC_RECOVERED_DATA "using previous sector id"},
- {0x17, 0x06, D | W | O | B | K,
- SC_RECOVERED_DATA "without ecc - data auto-reallocated"},
- {0x17, 0x07, D | W | R | O | B | K,
- SC_RECOVERED_DATA "without ecc - recommend reassignment"},
- {0x17, 0x08, D | W | R | O | B | K,
- SC_RECOVERED_DATA "without ecc - recommend rewrite"},
- {0x17, 0x09, D | W | R | O | B | K,
- SC_RECOVERED_DATA "without ecc - data rewritten"},
- {0x18, 0x00, D | T | W | R | O | B | K,
- SC_RECOVERED_DATA "with error correction applied"},
- {0x18, 0x01, D | W | R | O | B | K,
- SC_RECOVERED_DATA "with error corr. & retries applied"},
- {0x18, 0x02, D | W | R | O | B | K,
- SC_RECOVERED_DATA "- data auto-reallocated"},
- {0x18, 0x03, R, SC_RECOVERED_DATA "with CIRC"},
- {0x18, 0x04, R, SC_RECOVERED_DATA "with L-EC"},
- {0x18, 0x05, D | W | R | O | B | K,
- SC_RECOVERED_DATA "- recommend reassignment"},
- {0x18, 0x06, D | W | R | O | B | K,
- SC_RECOVERED_DATA "- recommend rewrite"},
- {0x18, 0x07, D | W | O | B | K,
- SC_RECOVERED_DATA "with ecc - data rewritten"},
- {0x18, 0x08, R, SC_RECOVERED_DATA "with linking"},
- {0x19, 0x00, D | O | K, "Defect list error"},
- {0x19, 0x01, D | O | K, "Defect list not available"},
- {0x19, 0x02, D | O | K, "Defect list error in primary list"},
- {0x19, 0x03, D | O | K, "Defect list error in grown list"},
- {0x1A, 0x00, SC_ALL_DEVS, "Parameter list length error"},
- {0x1B, 0x00, SC_ALL_DEVS, "Synchronous data transfer error"},
- {0x1C, 0x00, D | O | B | K, "Defect list not found"},
- {0x1C, 0x01, D | O | B | K, "Primary defect list not found"},
- {0x1C, 0x02, D | O | B | K, "Grown defect list not found"},
- {0x1D, 0x00, D | T | W | R | O | B | K,
- "Miscompare during verify" SC_OPERATION},
- {0x1E, 0x00, D | W | O | B | K, "Recovered id with ecc correction"},
- {0x1F, 0x00, D | O | K, "Partial defect list transfer"},
- {0x20, 0x00, SC_ALL_DEVS, "Invalid command" SC_OPERATION " code"},
- {0x20, 0x01, D | T | P | W | R | O | M | A | E | B | K,
- "Access denied - initiator pending-enrolled"},
- {0x20, 0x02, D | T | P | W | R | O | M | A | E | B | K,
- "Access denied - no access rights"},
- {0x20, 0x03, D | T | P | W | R | O | M | A | E | B | K,
- "Access denied - no mgmt id key"},
- {0x20, 0x04, T, "Illegal command while in write capable state"},
- {0x20, 0x05, T, "Obsolete"},
- {0x20, 0x06, T, "Illegal command while in explicit address mode"},
- {0x20, 0x07, T, "Illegal command while in implicit address mode"},
- {0x20, 0x08, D | T | P | W | R | O | M | A | E | B | K,
- "Access denied - enrollment conflict"},
- {0x20, 0x09, D | T | P | W | R | O | M | A | E | B | K,
- "Access denied - invalid LU identifier"},
- {0x20, 0x0A, D | T | P | W | R | O | M | A | E | B | K,
- "Access denied - invalid proxy token"},
- {0x20, 0x0B, D | T | P | W | R | O | M | A | E | B | K,
- "Access denied - ACL LUN conflict"},
- {0x21, 0x00, D | T | W | R | O | M | B | K,
- "Logical block address out of range"},
- {0x21, 0x01, D | T | W | R | O | M | B | K, "Invalid element address"},
- {0x21, 0x02, R, "Invalid address for write"},
- {0x22, 0x00, D, "Illegal function (use 20 00,24 00,or 26 00)"},
- {0x24, 0x00, SC_ALL_DEVS, "Invalid field in cdb"},
- {0x24, 0x01, SC_ALL_DEVS, "CDB decryption error"},
- {0x25, 0x00, SC_ALL_DEVS, SC_LOGICAL_UNIT "not supported"},
- {0x26, 0x00, SC_ALL_DEVS, "Invalid field in parameter list"},
- {0x26, 0x01, SC_ALL_DEVS, "Parameter not supported"},
- {0x26, 0x02, SC_ALL_DEVS, "Parameter value invalid"},
- {0x26, 0x03, D | T | L | P | W | R | S | O | M | C | A | E | K,
- "Threshold parameters not supported"},
- {0x26, 0x04, SC_ALL_DEVS, "Invalid release of persistent reservation"},
- {0x26, 0x05, D | T | L | P | W | R | S | O | M | C | A | B | K,
- "Data decryption error"},
- {0x26, 0x06, D | T | L | P | W | R | S | O | C | K,
- "Too many target descriptors"},
- {0x26, 0x07, D | T | L | P | W | R | S | O | C | K,
- "Unsupported target descriptor type code"},
- {0x26, 0x08, D | T | L | P | W | R | S | O | C | K,
- "Too many segment descriptors"},
- {0x26, 0x09, D | T | L | P | W | R | S | O | C | K,
- "Unsupported segment descriptor type code"},
- {0x26, 0x0A, D | T | L | P | W | R | S | O | C | K,
- "Unexpected inexact segment"},
- {0x26, 0x0B, D | T | L | P | W | R | S | O | C | K,
- "Inline data length exceeded"},
- {0x26, 0x0C, D | T | L | P | W | R | S | O | C | K,
- "Invalid" SC_OPERATION " for copy source or destination"},
- {0x26, 0x0D, D | T | L | P | W | R | S | O | C | K,
- "Copy segment granularity violation"},
- {0x27, 0x00, D | T | W | R | O | B | K, "Write protected"},
- {0x27, 0x01, D | T | W | R | O | B | K, "Hardware write protected"},
- {0x27, 0x02, D | T | W | R | O | B | K,
- SC_LOGICAL_UNIT "software write protected"},
- {0x27, 0x03, T | R, "Associated write protect"},
- {0x27, 0x04, T | R, "Persistent write protect"},
- {0x27, 0x05, T | R, "Permanent write protect"},
- {0x27, 0x06, R, "Conditional write protect"},
- {0x28, 0x00, SC_ALL_DEVS,
- "Not ready to ready change, medium may have changed"},
- {0x28, 0x01, D | T | W | R | O | M | B,
- "Import or export element accessed"},
- {0x29, 0x00, SC_ALL_DEVS,
- "Power on,reset,or bus device reset occurred"},
- {0x29, 0x01, SC_ALL_DEVS, "Power on occurred"},
- {0x29, 0x02, SC_ALL_DEVS, "Scsi bus reset occurred"},
- {0x29, 0x03, SC_ALL_DEVS, "Bus device reset function occurred"},
- {0x29, 0x04, SC_ALL_DEVS, "Device internal reset"},
- {0x29, 0x05, SC_ALL_DEVS, "Transceiver mode changed to single-ended"},
- {0x29, 0x06, SC_ALL_DEVS, "Transceiver mode changed to lvd"},
- {0x29, 0x07, SC_ALL_DEVS, "I_T nexus loss occurred"},
- {0x2A, 0x00, D | T | L | W | R | S | O | M | C | A | E | B | K,
- "Parameters changed"},
- {0x2A, 0x01, D | T | L | W | R | S | O | M | C | A | E | B | K,
- "Mode parameters changed"},
- {0x2A, 0x02, D | T | L | W | R | S | O | M | C | A | E | K,
- "Log parameters changed"},
- {0x2A, 0x03, D | T | L | P | W | R | S | O | M | C | A | E | K,
- "Reservations preempted"},
- {0x2A, 0x04, D | T | L | P | W | R | S | O | M | C | A | E,
- "Reservations released"},
- {0x2A, 0x05, D | T | L | P | W | R | S | O | M | C | A | E,
- "Registrations preempted"},
- {0x2A, 0x06, SC_ALL_DEVS, "Asymmetric access state changed"},
- {0x2A, 0x07, SC_ALL_DEVS,
- "Implicit asymmetric access state transition failed"},
- {0x2B, 0x00, D | T | L | P | W | R | S | O | C | K,
- "Copy cannot execute since host cannot disconnect"},
- {0x2C, 0x00, SC_ALL_DEVS, "Command sequence error"},
- {0x2C, 0x01, S, "Too many windows specified"},
- {0x2C, 0x02, S, "Invalid combination of windows specified"},
- {0x2C, 0x03, R, "Current program area is not empty"},
- {0x2C, 0x04, R, "Current program area is empty"},
- {0x2C, 0x05, B, "Illegal power condition request"},
- {0x2C, 0x06, R, "Persistent prevent conflict"},
- {0x2C, 0x07, SC_ALL_DEVS, "Previous busy status"},
- {0x2C, 0x08, SC_ALL_DEVS, "Previous task set full status"},
- {0x2C, 0x09, D | T | L | P | W | R | S | O | M | E | B | K,
- "Previous reservation conflict status"},
- {0x2D, 0x00, T, "Overwrite error on update in place"},
- {0x2F, 0x00, SC_ALL_DEVS, "Commands cleared by another initiator"},
- {0x30, 0x00, D | T | W | R | O | M | B | K,
- "Incompatible medium installed"},
- {0x30, 0x01, D | T | W | R | O | B | K,
- "Cannot read medium - unknown format"},
- {0x30, 0x02, D | T | W | R | O | B | K,
- "Cannot read medium - incompatible format"},
- {0x30, 0x03, D | T | R | K, "Cleaning cartridge installed"},
- {0x30, 0x04, D | T | W | R | O | B | K,
- "Cannot write medium - unknown format"},
- {0x30, 0x05, D | T | W | R | O | B | K,
- "Cannot write medium - incompatible format"},
- {0x30, 0x06, D | T | W | R | O | B,
- "Cannot format medium - incompatible medium"},
- {0x30, 0x07, D | T | L | W | R | S | O | M | A | E | B | K,
- "Cleaning failure"},
- {0x30, 0x08, R, "Cannot write - application code mismatch"},
- {0x30, 0x09, R, "Current session not fixated for append"},
- {0x30, 0x10, R, "Medium not formatted"}, /* should ascq be 0xa ?? */
- {0x31, 0x00, D | T | W | R | O | B | K, "Medium format corrupted"},
- {0x31, 0x01, D | L | R | O | B, "Format command failed"},
- {0x31, 0x02, R, "Zoned formatting failed due to spare linking"},
- {0x32, 0x00, D | W | O | B | K, "No defect spare location available"},
- {0x32, 0x01, D | W | O | B | K, "Defect list update failure"},
- {0x33, 0x00, T, "Tape length error"},
- {0x34, 0x00, SC_ALL_DEVS, "Enclosure failure"},
- {0x35, 0x00, SC_ALL_DEVS, "Enclosure services failure"},
- {0x35, 0x01, SC_ALL_DEVS, "Unsupported enclosure function"},
- {0x35, 0x02, SC_ALL_DEVS, "Enclosure services unavailable"},
- {0x35, 0x03, SC_ALL_DEVS, "Enclosure services transfer failure"},
- {0x35, 0x04, SC_ALL_DEVS, "Enclosure services transfer refused"},
- {0x36, 0x00, L, "Ribbon,ink,or toner failure"},
- {0x37, 0x00, D | T | L | W | R | S | O | M | C | A | E | B | K,
- "Rounded parameter"},
- {0x38, 0x00, B, "Event status notification"},
- {0x38, 0x02, B, "Esn - power management class event"},
- {0x38, 0x04, B, "Esn - media class event"},
- {0x38, 0x06, B, "Esn - device busy class event"},
- {0x39, 0x00, D | T | L | W | R | S | O | M | C | A | E | K,
- "Saving parameters not supported"},
- {0x3A, 0x00, D | T | L | W | R | S | O | M | B | K,
- "Medium not present"},
- {0x3A, 0x01, D | T | W | R | O | M | B | K,
- "Medium not present - tray closed"},
- {0x3A, 0x02, D | T | W | R | O | M | B | K,
- "Medium not present - tray open"},
- {0x3A, 0x03, D | T | W | R | O | M | B,
- "Medium not present - loadable"},
- {0x3A, 0x04, D | T | W | R | O | M | B,
- "Medium not present - medium auxiliary memory accessible"},
- {0x3B, 0x00, T | L, "Sequential positioning error"},
- {0x3B, 0x01, T, "Tape position error at beginning-of-medium"},
- {0x3B, 0x02, T, "Tape position error at end-of-medium"},
- {0x3B, 0x03, L, "Tape or electronic vertical forms unit " SC_NOT_READY},
- {0x3B, 0x04, L, "Slew failure"},
- {0x3B, 0x05, L, "Paper jam"},
- {0x3B, 0x06, L, "Failed to sense top-of-form"},
- {0x3B, 0x07, L, "Failed to sense bottom-of-form"},
- {0x3B, 0x08, T, "Reposition error"},
- {0x3B, 0x09, S, "Read past end of medium"},
- {0x3B, 0x0A, S, "Read past beginning of medium"},
- {0x3B, 0x0B, S, "Position past end of medium"},
- {0x3B, 0x0C, T | S, "Position past beginning of medium"},
- {0x3B, 0x0D, D | T | W | R | O | M | B | K,
- "Medium destination element full"},
- {0x3B, 0x0E, D | T | W | R | O | M | B | K,
- "Medium source element empty"},
- {0x3B, 0x0F, R, "End of medium reached"},
- {0x3B, 0x11, D | T | W | R | O | M | B | K,
- "Medium magazine not accessible"},
- {0x3B, 0x12, D | T | W | R | O | M | B | K, "Medium magazine removed"},
- {0x3B, 0x13, D | T | W | R | O | M | B | K, "Medium magazine inserted"},
- {0x3B, 0x14, D | T | W | R | O | M | B | K, "Medium magazine locked"},
- {0x3B, 0x15, D | T | W | R | O | M | B | K, "Medium magazine unlocked"},
- {0x3B, 0x16, R, "Mechanical positioning or changer error"},
- {0x3D, 0x00, D | T | L | P | W | R | S | O | M | C | A | E | K,
- "Invalid bits in identify message"},
- {0x3E, 0x00, SC_ALL_DEVS,
- SC_LOGICAL_UNIT "has not self-configured yet"},
- {0x3E, 0x01, SC_ALL_DEVS, SC_LOGICAL_UNIT "failure"},
- {0x3E, 0x02, SC_ALL_DEVS, "Timeout on logical unit"},
- {0x3E, 0x03, SC_ALL_DEVS, SC_LOGICAL_UNIT "failed self-test"},
- {0x3E, 0x04, SC_ALL_DEVS,
- SC_LOGICAL_UNIT "unable to update self-test log"},
- {0x3F, 0x00, SC_ALL_DEVS, "Target operating conditions have changed"},
- {0x3F, 0x01, SC_ALL_DEVS, "Microcode has been changed"},
- {0x3F, 0x02, D | T | L | P | W | R | S | O | M | C | B | K,
- "Changed operating definition"},
- {0x3F, 0x03, SC_ALL_DEVS, "Inquiry data has changed"},
- {0x3F, 0x04, D | T | W | R | O | M | C | A | E | B | K,
- "Component device attached"},
- {0x3F, 0x05, D | T | W | R | O | M | C | A | E | B | K,
- "Device identifier changed"},
- {0x3F, 0x06, D | T | W | R | O | M | C | A | E | B,
- "Redundancy group created or modified"},
- {0x3F, 0x07, D | T | W | R | O | M | C | A | E | B,
- "Redundancy group deleted"},
- {0x3F, 0x08, D | T | W | R | O | M | C | A | E | B,
- "Spare created or modified"},
- {0x3F, 0x09, D | T | W | R | O | M | C | A | E | B, "Spare deleted"},
- {0x3F, 0x0A, D | T | W | R | O | M | C | A | E | B | K,
- "Volume set created or modified"},
- {0x3F, 0x0B, D | T | W | R | O | M | C | A | E | B | K,
- "Volume set deleted"},
- {0x3F, 0x0C, D | T | W | R | O | M | C | A | E | B | K,
- "Volume set deassigned"},
- {0x3F, 0x0D, D | T | W | R | O | M | C | A | E | B | K,
- "Volume set reassigned"},
- {0x3F, 0x0E, D | T | L | P | W | R | S | O | M | C | A | E,
- "Reported luns data has changed"},
- {0x3F, 0x10, D | T | W | R | O | M | B, "Medium loadable"},
- {0x3F, 0x11, D | T | W | R | O | M | B,
- "Medium auxiliary memory accessible"},
- {0x40, 0x00, D, "Ram failure (should use 40 nn)"},
- /*
- * FIXME(eric) - need a way to represent wildcards here.
- */
- {0x40, 0x00, SC_ALL_DEVS,
- "Diagnostic failure on component nn (80h-ffh)"},
- {0x41, 0x00, D, "Data path failure (should use 40 nn)"},
- {0x42, 0x00, D, "Power-on or self-test failure (should use 40 nn)"},
- {0x43, 0x00, SC_ALL_DEVS, "Message error"},
- {0x44, 0x00, SC_ALL_DEVS, "Internal target failure"},
- {0x45, 0x00, SC_ALL_DEVS, "Select or reselect failure"},
- {0x46, 0x00, D | T | L | P | W | R | S | O | M | C | B | K,
- "Unsuccessful soft reset"},
- {0x47, 0x00, SC_ALL_DEVS, "Scsi parity error"},
- {0x47, 0x01, SC_ALL_DEVS, "Data phase CRC error detected"},
- {0x47, 0x02, SC_ALL_DEVS,
- "Scsi parity error detected during st data phase"},
- {0x47, 0x03, SC_ALL_DEVS, "Information unit CRC error detected"},
- {0x47, 0x04, SC_ALL_DEVS,
- "Asynchronous information protection error detected"},
- {0x47, 0x05, SC_ALL_DEVS, "Protocol service CRC error"},
- {0x48, 0x00, SC_ALL_DEVS, "Initiator detected error message received"},
- {0x49, 0x00, SC_ALL_DEVS, "Invalid message error"},
- {0x4A, 0x00, SC_ALL_DEVS, "Command phase error"},
- {0x4B, 0x00, SC_ALL_DEVS, "Data phase error"},
- {0x4C, 0x00, SC_ALL_DEVS, SC_LOGICAL_UNIT "failed self-configuration"},
- /*
- * FIXME(eric) - need a way to represent wildcards here.
- */
- {0x4D, 0x00, SC_ALL_DEVS,
- "Tagged overlapped commands (nn = queue tag)"},
- {0x4E, 0x00, SC_ALL_DEVS, "Overlapped commands attempted"},
- {0x50, 0x00, T, "Write append error"},
- {0x50, 0x01, T, "Write append position error"},
- {0x50, 0x02, T, "Position error related to timing"},
- {0x51, 0x00, T | R | O, "Erase failure"},
- {0x52, 0x00, T, "Cartridge fault"},
- {0x53, 0x00, D | T | L | W | R | S | O | M | B | K,
- "Media load or eject failed"},
- {0x53, 0x01, T, "Unload tape failure"},
- {0x53, 0x02, D | T | W | R | O | M | B | K, "Medium removal prevented"},
- {0x54, 0x00, P, "Scsi to host system interface failure"},
- {0x55, 0x00, P, "System resource failure"},
- {0x55, 0x01, D | O | B | K, "System buffer full"},
- {0x55, 0x02, D | T | L | P | W | R | S | O | M | A | E | K,
- "Insufficient reservation resources"},
- {0x55, 0x03, D | T | L | P | W | R | S | O | M | C | A | E,
- "Insufficient resources"},
- {0x55, 0x04, D | T | L | P | W | R | S | O | M | A | E,
- "Insufficient registration resources"},
- {0x55, 0x05, D | T | P | W | R | O | M | A | E | B | K,
- "Insufficient access control resources"},
- {0x55, 0x06, D | T | W | R | O | M | B,
- "Auxiliary memory out of space"},
- {0x57, 0x00, R, "Unable to recover table-of-contents"},
- {0x58, 0x00, O, "Generation does not exist"},
- {0x59, 0x00, O, "Updated block read"},
- {0x5A, 0x00, D | T | L | P | W | R | S | O | M | B | K,
- "Operator request or state change input"},
- {0x5A, 0x01, D | T | W | R | O | M | B | K,
- "Operator medium removal request"},
- {0x5A, 0x02, D | T | W | R | O | A | B | K,
- "Operator selected write protect"},
- {0x5A, 0x03, D | T | W | R | O | A | B | K,
- "Operator selected write permit"},
- {0x5B, 0x00, D | T | L | P | W | R | S | O | M | K, "Log exception"},
- {0x5B, 0x01, D | T | L | P | W | R | S | O | M | K,
- "Threshold condition met"},
- {0x5B, 0x02, D | T | L | P | W | R | S | O | M | K,
- "Log counter at maximum"},
- {0x5B, 0x03, D | T | L | P | W | R | S | O | M | K,
- "Log list codes exhausted"},
- {0x5C, 0x00, D | O, "Rpl status change"},
- {0x5C, 0x01, D | O, "Spindles synchronized"},
- {0x5C, 0x02, D | O, "Spindles not synchronized"},
- {0x5D, 0x00, SC_ALL_DEVS, "Failure prediction threshold exceeded"},
- {0x5D, 0x01, R | B, "Media failure prediction threshold exceeded"},
- {0x5D, 0x02, R,
- SC_LOGICAL_UNIT "failure prediction threshold exceeded"},
- {0x5D, 0x03, R, "spare area exhaustion prediction threshold exceeded"},
- /* large series of "impending failure" messages */
- {0x5D, 0x10, D | B, SC_HARDWARE_IF "general hard drive failure"},
- {0x5D, 0x11, D | B, SC_HARDWARE_IF "drive" SC_ERROR_RATE_TOO_HIGH},
- {0x5D, 0x12, D | B, SC_HARDWARE_IF "data" SC_ERROR_RATE_TOO_HIGH},
- {0x5D, 0x13, D | B, SC_HARDWARE_IF "seek" SC_ERROR_RATE_TOO_HIGH},
- {0x5D, 0x14, D | B, SC_HARDWARE_IF "too many block reassigns"},
- {0x5D, 0x15, D | B, SC_HARDWARE_IF "access" SC_TIMES_TOO_HIGH},
- {0x5D, 0x16, D | B, SC_HARDWARE_IF "start unit" SC_TIMES_TOO_HIGH},
- {0x5D, 0x17, D | B, SC_HARDWARE_IF "channel parametrics"},
- {0x5D, 0x18, D | B, SC_HARDWARE_IF "controller detected"},
- {0x5D, 0x19, D | B, SC_HARDWARE_IF "throughput performance"},
- {0x5D, 0x1A, D | B, SC_HARDWARE_IF "seek time performance"},
- {0x5D, 0x1B, D | B, SC_HARDWARE_IF "spin-up retry count"},
- {0x5D, 0x1C, D | B, SC_HARDWARE_IF "drive calibration retry count"},
- {0x5D, 0x20, D | B, SC_CONTROLLER_IF "general hard drive failure"},
- {0x5D, 0x21, D | B, SC_CONTROLLER_IF "drive" SC_ERROR_RATE_TOO_HIGH},
- {0x5D, 0x22, D | B, SC_CONTROLLER_IF "data" SC_ERROR_RATE_TOO_HIGH},
- {0x5D, 0x23, D | B, SC_CONTROLLER_IF "seek" SC_ERROR_RATE_TOO_HIGH},
- {0x5D, 0x24, D | B, SC_CONTROLLER_IF "too many block reassigns"},
- {0x5D, 0x25, D | B, SC_CONTROLLER_IF "access" SC_TIMES_TOO_HIGH},
- {0x5D, 0x26, D | B, SC_CONTROLLER_IF "start unit" SC_TIMES_TOO_HIGH},
- {0x5D, 0x27, D | B, SC_CONTROLLER_IF "channel parametrics"},
- {0x5D, 0x28, D | B, SC_CONTROLLER_IF "controller detected"},
- {0x5D, 0x29, D | B, SC_CONTROLLER_IF "throughput performance"},
- {0x5D, 0x2A, D | B, SC_CONTROLLER_IF "seek time performance"},
- {0x5D, 0x2B, D | B, SC_CONTROLLER_IF "spin-up retry count"},
- {0x5D, 0x2C, D | B, SC_CONTROLLER_IF "drive calibration retry count"},
- {0x5D, 0x30, D | B, SC_DATA_CHANNEL_IF "general hard drive failure"},
- {0x5D, 0x31, D | B, SC_DATA_CHANNEL_IF "drive" SC_ERROR_RATE_TOO_HIGH},
- {0x5D, 0x32, D | B, SC_DATA_CHANNEL_IF "data" SC_ERROR_RATE_TOO_HIGH},
- {0x5D, 0x33, D | B, SC_DATA_CHANNEL_IF "seek" SC_ERROR_RATE_TOO_HIGH},
- {0x5D, 0x34, D | B, SC_DATA_CHANNEL_IF "too many block reassigns"},
- {0x5D, 0x35, D | B, SC_DATA_CHANNEL_IF "access" SC_TIMES_TOO_HIGH},
- {0x5D, 0x36, D | B, SC_DATA_CHANNEL_IF "start unit" SC_TIMES_TOO_HIGH},
- {0x5D, 0x37, D | B, SC_DATA_CHANNEL_IF "channel parametrics"},
- {0x5D, 0x38, D | B, SC_DATA_CHANNEL_IF "controller detected"},
- {0x5D, 0x39, D | B, SC_DATA_CHANNEL_IF "throughput performance"},
- {0x5D, 0x3A, D | B, SC_DATA_CHANNEL_IF "seek time performance"},
- {0x5D, 0x3B, D | B, SC_DATA_CHANNEL_IF "spin-up retry count"},
- {0x5D, 0x3C, D | B, SC_DATA_CHANNEL_IF "drive calibration retry count"},
- {0x5D, 0x40, D | B, SC_SERVO_IF "general hard drive failure"},
- {0x5D, 0x41, D | B, SC_SERVO_IF "drive" SC_ERROR_RATE_TOO_HIGH},
- {0x5D, 0x42, D | B, SC_SERVO_IF "data" SC_ERROR_RATE_TOO_HIGH},
- {0x5D, 0x43, D | B, SC_SERVO_IF "seek" SC_ERROR_RATE_TOO_HIGH},
- {0x5D, 0x44, D | B, SC_SERVO_IF "too many block reassigns"},
- {0x5D, 0x45, D | B, SC_SERVO_IF "access" SC_TIMES_TOO_HIGH},
- {0x5D, 0x46, D | B, SC_SERVO_IF "start unit" SC_TIMES_TOO_HIGH},
- {0x5D, 0x47, D | B, SC_SERVO_IF "channel parametrics"},
- {0x5D, 0x48, D | B, SC_SERVO_IF "controller detected"},
- {0x5D, 0x49, D | B, SC_SERVO_IF "throughput performance"},
- {0x5D, 0x4A, D | B, SC_SERVO_IF "seek time performance"},
- {0x5D, 0x4B, D | B, SC_SERVO_IF "spin-up retry count"},
- {0x5D, 0x4C, D | B, SC_SERVO_IF "drive calibration retry count"},
- {0x5D, 0x50, D | B, SC_SPINDLE_IF "general hard drive failure"},
- {0x5D, 0x51, D | B, SC_SPINDLE_IF "drive" SC_ERROR_RATE_TOO_HIGH},
- {0x5D, 0x52, D | B, SC_SPINDLE_IF "data" SC_ERROR_RATE_TOO_HIGH},
- {0x5D, 0x53, D | B, SC_SPINDLE_IF "seek" SC_ERROR_RATE_TOO_HIGH},
- {0x5D, 0x54, D | B, SC_SPINDLE_IF "too many block reassigns"},
- {0x5D, 0x55, D | B, SC_SPINDLE_IF "access" SC_TIMES_TOO_HIGH},
- {0x5D, 0x56, D | B, SC_SPINDLE_IF "start unit" SC_TIMES_TOO_HIGH},
- {0x5D, 0x57, D | B, SC_SPINDLE_IF "channel parametrics"},
- {0x5D, 0x58, D | B, SC_SPINDLE_IF "controller detected"},
- {0x5D, 0x59, D | B, SC_SPINDLE_IF "throughput performance"},
- {0x5D, 0x5A, D | B, SC_SPINDLE_IF "seek time performance"},
- {0x5D, 0x5B, D | B, SC_SPINDLE_IF "spin-up retry count"},
- {0x5D, 0x5C, D | B, SC_SPINDLE_IF "drive calibration retry count"},
- {0x5D, 0x60, D | B, SC_FIRMWARE_IF "general hard drive failure"},
- {0x5D, 0x61, D | B, SC_FIRMWARE_IF "drive" SC_ERROR_RATE_TOO_HIGH},
- {0x5D, 0x62, D | B, SC_FIRMWARE_IF "data" SC_ERROR_RATE_TOO_HIGH},
- {0x5D, 0x63, D | B, SC_FIRMWARE_IF "seek" SC_ERROR_RATE_TOO_HIGH},
- {0x5D, 0x64, D | B, SC_FIRMWARE_IF "too many block reassigns"},
- {0x5D, 0x65, D | B, SC_FIRMWARE_IF "access" SC_TIMES_TOO_HIGH},
- {0x5D, 0x66, D | B, SC_FIRMWARE_IF "start unit" SC_TIMES_TOO_HIGH},
- {0x5D, 0x67, D | B, SC_FIRMWARE_IF "channel parametrics"},
- {0x5D, 0x68, D | B, SC_FIRMWARE_IF "controller detected"},
- {0x5D, 0x69, D | B, SC_FIRMWARE_IF "throughput performance"},
- {0x5D, 0x6A, D | B, SC_FIRMWARE_IF "seek time performance"},
- {0x5D, 0x6B, D | B, SC_FIRMWARE_IF "spin-up retry count"},
- {0x5D, 0x6C, D | B, SC_FIRMWARE_IF "drive calibration retry count"},
- {0x5D, 0xFF, SC_ALL_DEVS,
- "Failure prediction threshold exceeded (false)"},
- {0x5E, 0x00, D | T | L | P | W | R | S | O | C | A | K,
- "Low power condition on"},
- {0x5E, 0x01, D | T | L | P | W | R | S | O | C | A | K,
- "Idle condition activated by timer"},
- {0x5E, 0x02, D | T | L | P | W | R | S | O | C | A | K,
- "Standby condition activated by timer"},
- {0x5E, 0x03, D | T | L | P | W | R | S | O | C | A | K,
- "Idle condition activated by command"},
- {0x5E, 0x04, D | T | L | P | W | R | S | O | C | A | K,
- "Standby condition activated by command"},
- {0x5E, 0x41, B, "Power state change to active"},
- {0x5E, 0x42, B, "Power state change to idle"},
- {0x5E, 0x43, B, "Power state change to standby"},
- {0x5E, 0x45, B, "Power state change to sleep"},
- {0x5E, 0x47, B | K, "Power state change to device control"},
- {0x60, 0x00, S, "Lamp failure"},
- {0x61, 0x00, S, "Video acquisition error"},
- {0x61, 0x01, S, "Unable to acquire video"},
- {0x61, 0x02, S, "Out of focus"},
- {0x62, 0x00, S, "Scan head positioning error"},
- {0x63, 0x00, R, "End of user area encountered on this track"},
- {0x63, 0x01, R, "Packet does not fit in available space"},
- {0x64, 0x00, R, "Illegal mode for this track"},
- {0x64, 0x01, R, "Invalid packet size"},
- {0x65, 0x00, SC_ALL_DEVS, "Voltage fault"},
- {0x66, 0x00, S, "Automatic document feeder cover up"},
- {0x66, 0x01, S, "Automatic document feeder lift up"},
- {0x66, 0x02, S, "Document jam in automatic document feeder"},
- {0x66, 0x03, S, "Document miss feed automatic in document feeder"},
- {0x67, 0x00, A, "Configuration failure"},
- {0x67, 0x01, A, "Configuration of incapable logical units failed"},
- {0x67, 0x02, A, "Add logical unit failed"},
- {0x67, 0x03, A, "Modification of logical unit failed"},
- {0x67, 0x04, A, "Exchange of logical unit failed"},
- {0x67, 0x05, A, "Remove of logical unit failed"},
- {0x67, 0x06, A, "Attachment of logical unit failed"},
- {0x67, 0x07, A, "Creation of logical unit failed"},
- {0x67, 0x08, A, "Assign failure occurred"},
- {0x67, 0x09, A, "Multiply assigned logical unit"},
- {0x67, 0x0A, SC_ALL_DEVS, "Set target port groups command failed"},
- {0x68, 0x00, A, SC_LOGICAL_UNIT "not configured"},
- {0x69, 0x00, A, "Data loss on logical unit"},
- {0x69, 0x01, A, "Multiple logical unit failures"},
- {0x69, 0x02, A, "Parity/data mismatch"},
- {0x6A, 0x00, A, "Informational,refer to log"},
- {0x6B, 0x00, A, "State change has occurred"},
- {0x6B, 0x01, A, "Redundancy level got better"},
- {0x6B, 0x02, A, "Redundancy level got worse"},
- {0x6C, 0x00, A, "Rebuild failure occurred"},
- {0x6D, 0x00, A, "Recalculate failure occurred"},
- {0x6E, 0x00, A, "Command to logical unit failed"},
- {0x6F, 0x00, R,
- "Copy protection key exchange failure - authentication failure"},
- {0x6F, 0x01, R,
- "Copy protection key exchange failure - key not present"},
- {0x6F, 0x02, R,
- "Copy protection key exchange failure - key not established"},
- {0x6F, 0x03, R, "Read of scrambled sector without authentication"},
- {0x6F, 0x04, R,
- "Media region code is mismatched to logical unit region"},
- {0x6F, 0x05, R,
- "Drive region must be permanent/region reset count error"},
- /*
- * FIXME(eric) - need a way to represent wildcards here.
- */
- {0x70, 0x00, T, "Decompression exception short algorithm id of nn"},
- {0x71, 0x00, T, "Decompression exception long algorithm id"},
- {0x72, 0x00, R, "Session fixation error"},
- {0x72, 0x01, R, "Session fixation error writing lead-in"},
- {0x72, 0x02, R, "Session fixation error writing lead-out"},
- {0x72, 0x03, R, "Session fixation error - incomplete track in session"},
- {0x72, 0x04, R, "Empty or partially written reserved track"},
- {0x72, 0x05, R, "No more track reservations allowed"},
- {0x73, 0x00, R, "Cd control error"},
- {0x73, 0x01, R, "Power calibration area almost full"},
- {0x73, 0x02, R, "Power calibration area is full"},
- {0x73, 0x03, R, "Power calibration area error"},
- {0x73, 0x04, R, "Program memory area update failure"},
- {0x73, 0x05, R, "Program memory area is full"},
- {0x73, 0x06, R, "RMA/PMA is full"},
- {0, 0, 0, NULL}
-};
-
-static const char *sc_oft_used[0x1f] = {
- "umulig", /* index 0x0 should be impossible */
- "Audio play operation ",
- "Logical unit ",
- "not ready, ",
- " operation",
- " in progress ",
- "Hardware impending failure ",
- "Controller impending failure ",
- "Data channel impending failure ", /* index 0x8 */
- "Servo impending failure ",
- "Spindle impending failure ",
- "Firmware impending failure ",
- "Recovered data ",
- " error rate too high",
- " times too high",
-};
-
-static const char *snstext[] = {
- "No Sense", /* There is no sense information */
- "Recovered Error", /* The last command completed successfully
- but used error correction */
- "Not Ready", /* The addressed target is not ready */
- "Medium Error", /* Data error detected on the medium */
- "Hardware Error", /* Controller or device failure */
- "Illegal Request",
- "Unit Attention", /* Removable medium was changed, or
- the target has been reset */
- "Data Protect", /* Access to the data is blocked */
- "Blank Check", /* Reached unexpected written or unwritten
- region of the medium */
- "Key=9", /* Vendor specific */
- "Copy Aborted", /* COPY or COMPARE was aborted */
- "Aborted Command", /* The target aborted the command */
- "Equal", /* SEARCH DATA found data equal (obsolete) */
- "Volume Overflow", /* Medium full with still data to be written */
- "Miscompare", /* Source data and data on the medium
- do not agree */
- "Key=15" /* Reserved */
-};
-
-static
-void sg_print_asc_ascq(unsigned char asc, unsigned char ascq)
-{
- int k, j;
- char obuff[256];
- const char *ccp;
- const char *oup;
- char c;
- int found = 0;
-
- for (k = 0; additional[k].text; k++) {
- if (additional[k].code1 == asc && additional[k].code2 == ascq) {
- found = 1;
- ccp = additional[k].text;
- for (j = 0; *ccp && (j < sizeof(obuff)); ++ccp) {
- c = *ccp;
- if ((c < 0x20) && (c > 0)) {
- oup = sc_oft_used[(int)c];
- if (oup) {
- strcpy(obuff + j, oup);
- j += strlen(oup);
- } else {
- strcpy(obuff + j, "???");
- j += 3;
- }
- } else
- obuff[j++] = c;
- }
- if (j < sizeof(obuff))
- obuff[j] = '\0';
- else
- obuff[sizeof(obuff) - 1] = '\0';
- fprintf(OUTP, "Additional sense: %s\n", obuff);
- }
- }
- if (found)
- return;
-
- for (k = 0; additional2[k].text; k++) {
- if ((additional2[k].code1 == asc) &&
- (ascq >= additional2[k].code2_min) &&
- (ascq <= additional2[k].code2_max)) {
- found = 1;
- fprintf(OUTP, "Additional sense: ");
- fprintf(OUTP, additional2[k].text, ascq);
- fprintf(OUTP, "\n");
- }
- }
- if (!found)
- fprintf(OUTP, "ASC=%2x ASCQ=%2x\n", asc, ascq);
-}
-
-/* Print sense information */
-void sg_print_sense(const char *leadin, const unsigned char *sense_buffer,
- int sb_len)
-{
- int k, s;
- int sense_key, sense_class, valid, code;
- int descriptor_format = 0;
- const char *error = NULL;
-
- if (sb_len < 1) {
- fprintf(OUTP, "sense buffer empty\n");
- return;
- }
- sense_class = (sense_buffer[0] >> 4) & 0x07;
- code = sense_buffer[0] & 0xf;
- valid = sense_buffer[0] & 0x80;
- if (leadin)
- fprintf(OUTP, "%s: ", leadin);
-
- if (sense_class == 7) { /* extended sense data */
- s = sense_buffer[7] + 8;
- if (s > sb_len) {
- fprintf(OUTP,
- "Sense buffer too small (at %d bytes), %d bytes "
- "truncated\n", sb_len, s - sb_len);
- s = sb_len;
- }
-
- switch (code) {
- case 0x0:
- error = "Current"; /* error concerns current command */
- break;
- case 0x1:
- error = "Deferred"; /* error concerns some earlier command */
- /* e.g., an earlier write to disk cache succeeded, but
- now the disk discovers that it cannot write the data */
- break;
- case 0x2:
- descriptor_format = 1;
- error = "Descriptor current";
- /* new descriptor sense format */
- break;
- case 0x3:
- descriptor_format = 1;
- error = "Descriptor deferred";
- /* new descriptor sense format (deferred report) */
- break;
- default:
- error = "Invalid";
- }
- sense_key = sense_buffer[descriptor_format ? 1 : 2] & 0xf;
- fprintf(OUTP, "%s, Sense key: %s\n", error, snstext[sense_key]);
-
- if (descriptor_format)
- sg_print_asc_ascq(sense_buffer[2], sense_buffer[3]);
- else {
- if (!valid)
- fprintf(OUTP, "[valid=0] ");
- fprintf(OUTP, "Info fld=0x%x, ",
- (int)((sense_buffer[3] << 24) |
- (sense_buffer[4] << 16) | (sense_buffer[5]
- << 8) |
- sense_buffer[6]));
-
- if (sense_buffer[2] & 0x80)
- fprintf(OUTP, "FMK "); /* current command has read a filemark */
- if (sense_buffer[2] & 0x40)
- fprintf(OUTP, "EOM "); /* end-of-medium condition exists */
- if (sense_buffer[2] & 0x20)
- fprintf(OUTP, "ILI "); /* incorrect block length requested */
-
- if (s > 13) {
- if (sense_buffer[12] || sense_buffer[13])
- sg_print_asc_ascq(sense_buffer[12],
- sense_buffer[13]);
- }
- if (sense_key == 5 && s >= 18
- && (sense_buffer[15] & 0x80)) {
- fprintf(OUTP,
- "Sense Key Specific: Error in %s byte %d",
- (sense_buffer[15] & 0x40) ? "Command" :
- "Data",
- (sense_buffer[16] << 8) |
- sense_buffer[17]);
- if (sense_buffer[15] & 0x08) {
- fprintf(OUTP, " bit %d\n",
- sense_buffer[15] & 0x07);
- } else {
- fprintf(OUTP, "\n");
- }
- }
- }
-
- } else { /* non-extended sense data */
-
- /*
- * Standard says:
- * sense_buffer[0] & 0200 : address valid
- * sense_buffer[0] & 0177 : vendor-specific error code
- * sense_buffer[1] & 0340 : vendor-specific
- * sense_buffer[1..3] : 21-bit logical block address
- */
-
- if (sb_len < 4) {
- fprintf(OUTP,
- "sense buffer too short (4 byte minimum)\n");
- return;
- }
- if (leadin)
- fprintf(OUTP, "%s: ", leadin);
- if (sense_buffer[0] < 15)
- fprintf(OUTP,
- "old sense: key %s\n",
- snstext[sense_buffer[0] & 0x0f]);
- else
- fprintf(OUTP, "sns = %2x %2x\n", sense_buffer[0],
- sense_buffer[2]);
-
- fprintf(OUTP, "Non-extended sense class %d code 0x%0x ",
- sense_class, code);
- s = 4;
- }
-
- fprintf(OUTP, "Raw sense data (in hex):\n ");
- for (k = 0; k < s; ++k) {
- if ((k > 0) && (0 == (k % 24)))
- fprintf(OUTP, "\n ");
- fprintf(OUTP, "%02x ", sense_buffer[k]);
- }
- fprintf(OUTP, "\n");
-}
-
-static const char *hostbyte_table[] = {
- "DID_OK", "DID_NO_CONNECT", "DID_BUS_BUSY", "DID_TIME_OUT",
- "DID_BAD_TARGET",
- "DID_ABORT", "DID_PARITY", "DID_ERROR", "DID_RESET", "DID_BAD_INTR",
- "DID_PASSTHROUGH", "DID_SOFT_ERROR", NULL
-};
-
-void sg_print_host_status(int host_status)
-{
- static int maxcode = 0;
- int i;
-
- if (!maxcode) {
- for (i = 0; hostbyte_table[i]; i++) ;
- maxcode = i - 1;
- }
- fprintf(OUTP, "Host_status=0x%02x", host_status);
- if (host_status > maxcode) {
- fprintf(OUTP, "is invalid ");
- return;
- }
- fprintf(OUTP, "(%s) ", hostbyte_table[host_status]);
-}
-
-static const char *driverbyte_table[] = {
- "DRIVER_OK", "DRIVER_BUSY", "DRIVER_SOFT", "DRIVER_MEDIA",
- "DRIVER_ERROR",
- "DRIVER_INVALID", "DRIVER_TIMEOUT", "DRIVER_HARD", "DRIVER_SENSE", NULL
-};
-
-static const char *driversuggest_table[] = { "SUGGEST_OK",
- "SUGGEST_RETRY", "SUGGEST_ABORT", "SUGGEST_REMAP", "SUGGEST_DIE",
- unknown, unknown, unknown, "SUGGEST_SENSE", NULL
-};
-
-void sg_print_driver_status(int driver_status)
-{
- static int driver_max = 0, suggest_max = 0;
- int i;
- int dr = driver_status & SG_ERR_DRIVER_MASK;
- int su = (driver_status & SG_ERR_SUGGEST_MASK) >> 4;
-
- if (!driver_max) {
- for (i = 0; driverbyte_table[i]; i++) ;
- driver_max = i;
- for (i = 0; driversuggest_table[i]; i++) ;
- suggest_max = i;
- }
- fprintf(OUTP, "Driver_status=0x%02x", driver_status);
- fprintf(OUTP, " (%s,%s) ",
- dr < driver_max ? driverbyte_table[dr] : "invalid",
- su < suggest_max ? driversuggest_table[su] : "invalid");
-}
-
-static int sg_sense_print(const char *leadin, int scsi_status,
- int host_status, int driver_status,
- const unsigned char *sense_buffer, int sb_len)
-{
- int done_leadin = 0;
- int done_sense = 0;
-
- scsi_status &= 0x7e; /*sanity */
- if ((0 == scsi_status) && (0 == host_status) && (0 == driver_status))
- return 1; /* No problems */
- if (0 != scsi_status) {
- if (leadin)
- fprintf(OUTP, "%s: ", leadin);
- done_leadin = 1;
- fprintf(OUTP, "scsi status: ");
- sg_print_scsi_status(scsi_status);
- fprintf(OUTP, "\n");
- if (sense_buffer && ((scsi_status == SCSI_CHECK_CONDITION) ||
- (scsi_status ==
- SCSI_COMMAND_TERMINATED))) {
- sg_print_sense(0, sense_buffer, sb_len);
- done_sense = 1;
- }
- }
- if (0 != host_status) {
- if (leadin && (!done_leadin))
- fprintf(OUTP, "%s: ", leadin);
- if (done_leadin)
- fprintf(OUTP, "plus...: ");
- else
- done_leadin = 1;
- sg_print_host_status(host_status);
- fprintf(OUTP, "\n");
- }
- if (0 != driver_status) {
- if (leadin && (!done_leadin))
- fprintf(OUTP, "%s: ", leadin);
- if (done_leadin)
- fprintf(OUTP, "plus...: ");
- else
- done_leadin = 1;
- sg_print_driver_status(driver_status);
- fprintf(OUTP, "\n");
- if (sense_buffer && (!done_sense) &&
- (SG_ERR_DRIVER_SENSE == (0xf & driver_status)))
- sg_print_sense(0, sense_buffer, sb_len);
- }
- return 0;
-}
-
-#ifdef SG_IO
-int sg_chk_n_print3(const char *leadin, struct sg_io_hdr *hp)
-{
- return sg_sense_print(leadin, hp->status, hp->host_status,
- hp->driver_status, hp->sbp, hp->sb_len_wr);
-}
-#endif
-
-int sg_chk_n_print(const char *leadin, int masked_status,
- int host_status, int driver_status,
- const unsigned char *sense_buffer, int sb_len)
-{
- int scsi_status = (masked_status << 1) & 0x7e;
-
- return sg_sense_print(leadin, scsi_status, host_status, driver_status,
- sense_buffer, sb_len);
-}
-
-#ifdef SG_IO
-int sg_err_category3(struct sg_io_hdr *hp)
-{
- return sg_err_category_new(hp->status, hp->host_status,
- hp->driver_status, hp->sbp, hp->sb_len_wr);
-}
-#endif
-
-int sg_err_category(int masked_status, int host_status,
- int driver_status, const unsigned char *sense_buffer,
- int sb_len)
-{
- int scsi_status = (masked_status << 1) & 0x7e;
-
- return sg_err_category_new(scsi_status, host_status, driver_status,
- sense_buffer, sb_len);
-}
-
-int sg_err_category_new(int scsi_status, int host_status, int driver_status,
- const unsigned char *sense_buffer, int sb_len)
-{
- scsi_status &= 0x7e;
- if ((0 == scsi_status) && (0 == host_status) && (0 == driver_status))
- return SG_ERR_CAT_CLEAN;
- if ((SCSI_CHECK_CONDITION == scsi_status) ||
- (SCSI_COMMAND_TERMINATED == scsi_status) ||
- (SG_ERR_DRIVER_SENSE == (0xf & driver_status))) {
- if (sense_buffer && (sb_len > 2)) {
- int sense_key;
- unsigned char asc;
-
- if (sense_buffer[0] & 0x2) {
- sense_key = sense_buffer[1] & 0xf;
- asc = sense_buffer[2];
- } else {
- sense_key = sense_buffer[2] & 0xf;
- asc = (sb_len > 12) ? sense_buffer[12] : 0;
- }
-
- if (RECOVERED_ERROR == sense_key)
- return SG_ERR_CAT_RECOVERED;
- else if (UNIT_ATTENTION == sense_key) {
- if (0x28 == asc)
- return SG_ERR_CAT_MEDIA_CHANGED;
- if (0x29 == asc)
- return SG_ERR_CAT_RESET;
- }
- }
- return SG_ERR_CAT_SENSE;
- }
- if (0 != host_status) {
- if ((SG_ERR_DID_NO_CONNECT == host_status) ||
- (SG_ERR_DID_BUS_BUSY == host_status) ||
- (SG_ERR_DID_TIME_OUT == host_status))
- return SG_ERR_CAT_TIMEOUT;
- }
- if (0 != driver_status) {
- if (SG_ERR_DRIVER_TIMEOUT == driver_status)
- return SG_ERR_CAT_TIMEOUT;
- }
- return SG_ERR_CAT_OTHER;
-}
-
-int sg_get_command_size(unsigned char opcode)
-{
- return COMMAND_SIZE(opcode);
-}
-
-void sg_get_command_name(unsigned char opcode, int buff_len, char *buff)
-{
- const char **table = commands[group(opcode)];
-
- if ((NULL == buff) || (buff_len < 1))
- return;
-
- switch ((unsigned long)table) {
- case RESERVED_GROUP:
- strncpy(buff, reserved, buff_len);
- break;
- case VENDOR_GROUP:
- strncpy(buff, vendor, buff_len);
- break;
- default:
- strncpy(buff, table[opcode & 0x1f], buff_len);
- break;
- }
-}
diff --git a/testcases/kernel/fs/scsi/ltpscsi/sg_err.h b/testcases/kernel/fs/scsi/ltpscsi/sg_err.h
deleted file mode 100644
index 735f8a940..000000000
--- a/testcases/kernel/fs/scsi/ltpscsi/sg_err.h
+++ /dev/null
@@ -1,162 +0,0 @@
-#ifndef SG_ERR_H
-#define SG_ERR_H
-
-/* Feel free to copy and modify this GPL-ed code into your applications. */
-
-/* Version 0.89 (20030313)
-*/
-
-
-/* Some of the following error/status codes are exchanged between the
- various layers of the SCSI sub-system in Linux and should never
- reach the user. They are placed here for completeness. What appears
- here is copied from drivers/scsi/scsi.h which is not visible in
- the user space. */
-
-#ifndef SCSI_CHECK_CONDITION
-/* Following are the "true" SCSI status codes. Linux has traditionally
- used a 1 bit right and masked version of these. So now CHECK_CONDITION
- and friends (in <scsi/scsi.h>) are deprecated. */
-#define SCSI_CHECK_CONDITION 0x2
-#define SCSI_CONDITION_MET 0x4
-#define SCSI_BUSY 0x8
-#define SCSI_IMMEDIATE 0x10
-#define SCSI_IMMEDIATE_CONDITION_MET 0x14
-#define SCSI_RESERVATION_CONFLICT 0x18
-#define SCSI_COMMAND_TERMINATED 0x22
-#define SCSI_TASK_SET_FULL 0x28
-#define SCSI_ACA_ACTIVE 0x30
-#define SCSI_TASK_ABORTED 0x40
-#endif
-
-/* The following are 'host_status' codes */
-#ifndef DID_OK
-#define DID_OK 0x00
-#endif
-#ifndef DID_NO_CONNECT
-#define DID_NO_CONNECT 0x01 /* Unable to connect before timeout */
-#define DID_BUS_BUSY 0x02 /* Bus remain busy until timeout */
-#define DID_TIME_OUT 0x03 /* Timed out for some other reason */
-#define DID_BAD_TARGET 0x04 /* Bad target (id?) */
-#define DID_ABORT 0x05 /* Told to abort for some other reason */
-#define DID_PARITY 0x06 /* Parity error (on SCSI bus) */
-#define DID_ERROR 0x07 /* Internal error */
-#define DID_RESET 0x08 /* Reset by somebody */
-#define DID_BAD_INTR 0x09 /* Received an unexpected interrupt */
-#define DID_PASSTHROUGH 0x0a /* Force command past mid-level */
-#define DID_SOFT_ERROR 0x0b /* The low-level driver wants a retry */
-#endif
-
-/* These defines are to isolate applictaions from kernel define changes */
-#define SG_ERR_DID_OK DID_OK
-#define SG_ERR_DID_NO_CONNECT DID_NO_CONNECT
-#define SG_ERR_DID_BUS_BUSY DID_BUS_BUSY
-#define SG_ERR_DID_TIME_OUT DID_TIME_OUT
-#define SG_ERR_DID_BAD_TARGET DID_BAD_TARGET
-#define SG_ERR_DID_ABORT DID_ABORT
-#define SG_ERR_DID_PARITY DID_PARITY
-#define SG_ERR_DID_ERROR DID_ERROR
-#define SG_ERR_DID_RESET DID_RESET
-#define SG_ERR_DID_BAD_INTR DID_BAD_INTR
-#define SG_ERR_DID_PASSTHROUGH DID_PASSTHROUGH
-#define SG_ERR_DID_SOFT_ERROR DID_SOFT_ERROR
-
-/* The following are 'driver_status' codes */
-#ifndef DRIVER_OK
-#define DRIVER_OK 0x00
-#endif
-#ifndef DRIVER_BUSY
-#define DRIVER_BUSY 0x01
-#define DRIVER_SOFT 0x02
-#define DRIVER_MEDIA 0x03
-#define DRIVER_ERROR 0x04
-#define DRIVER_INVALID 0x05
-#define DRIVER_TIMEOUT 0x06
-#define DRIVER_HARD 0x07
-#define DRIVER_SENSE 0x08 /* Sense_buffer has been set */
-
-/* Following "suggests" are "or-ed" with one of previous 8 entries */
-#define SUGGEST_RETRY 0x10
-#define SUGGEST_ABORT 0x20
-#define SUGGEST_REMAP 0x30
-#define SUGGEST_DIE 0x40
-#define SUGGEST_SENSE 0x80
-#define SUGGEST_IS_OK 0xff
-#endif
-#ifndef DRIVER_MASK
-#define DRIVER_MASK 0x0f
-#endif
-#ifndef SUGGEST_MASK
-#define SUGGEST_MASK 0xf0
-#endif
-
-/* These defines are to isolate applictaions from kernel define changes */
-#define SG_ERR_DRIVER_OK DRIVER_OK
-#define SG_ERR_DRIVER_BUSY DRIVER_BUSY
-#define SG_ERR_DRIVER_SOFT DRIVER_SOFT
-#define SG_ERR_DRIVER_MEDIA DRIVER_MEDIA
-#define SG_ERR_DRIVER_ERROR DRIVER_ERROR
-#define SG_ERR_DRIVER_INVALID DRIVER_INVALID
-#define SG_ERR_DRIVER_TIMEOUT DRIVER_TIMEOUT
-#define SG_ERR_DRIVER_HARD DRIVER_HARD
-#define SG_ERR_DRIVER_SENSE DRIVER_SENSE
-#define SG_ERR_SUGGEST_RETRY SUGGEST_RETRY
-#define SG_ERR_SUGGEST_ABORT SUGGEST_ABORT
-#define SG_ERR_SUGGEST_REMAP SUGGEST_REMAP
-#define SG_ERR_SUGGEST_DIE SUGGEST_DIE
-#define SG_ERR_SUGGEST_SENSE SUGGEST_SENSE
-#define SG_ERR_SUGGEST_IS_OK SUGGEST_IS_OK
-#define SG_ERR_DRIVER_MASK DRIVER_MASK
-#define SG_ERR_SUGGEST_MASK SUGGEST_MASK
-
-
-
-/* The following "print" functions send ACSII to stdout */
-extern void sg_print_command(const unsigned char * command);
-extern void sg_print_sense(const char * leadin,
- const unsigned char * sense_buffer, int sb_len);
-extern void sg_print_status(int masked_status);
-extern void sg_print_scsi_status(int scsi_status);
-extern void sg_print_host_status(int host_status);
-extern void sg_print_driver_status(int driver_status);
-
-/* sg_chk_n_print() returns 1 quietly if there are no errors/warnings
- else it prints to standard output and returns 0. */
-extern int sg_chk_n_print(const char * leadin, int masked_status,
- int host_status, int driver_status,
- const unsigned char * sense_buffer, int sb_len);
-
-/* The following function declaration is for the sg version 3 driver.
- Only version 3 sg_err.c defines it. */
-struct sg_io_hdr;
-extern int sg_chk_n_print3(const char * leadin, struct sg_io_hdr * hp);
-
-
-/* The following "category" function returns one of the following */
-#define SG_ERR_CAT_CLEAN 0 /* No errors or other information */
-#define SG_ERR_CAT_MEDIA_CHANGED 1 /* interpreted from sense buffer */
-#define SG_ERR_CAT_RESET 2 /* interpreted from sense buffer */
-#define SG_ERR_CAT_TIMEOUT 3
-#define SG_ERR_CAT_RECOVERED 4 /* Successful command after recovered err */
-#define SG_ERR_CAT_SENSE 98 /* Something else is in the sense buffer */
-#define SG_ERR_CAT_OTHER 99 /* Some other error/warning has occurred */
-
-extern int sg_err_category(int masked_status, int host_status,
- int driver_status, const unsigned char * sense_buffer,
- int sb_len);
-
-extern int sg_err_category_new(int scsi_status, int host_status,
- int driver_status, const unsigned char * sense_buffer,
- int sb_len);
-
-/* The following function declaration is for the sg version 3 driver.
- Only version 3 sg_err.c defines it. */
-extern int sg_err_category3(struct sg_io_hdr * hp);
-
-/* Returns length of SCSI command given the opcode (first byte) */
-extern int sg_get_command_size(unsigned char opcode);
-
-extern void sg_get_command_name(unsigned char opcode, int buff_len,
- char * buff);
-
-#endif
diff --git a/testcases/kernel/fs/scsi/ltpscsi/sg_include.h b/testcases/kernel/fs/scsi/ltpscsi/sg_include.h
deleted file mode 100644
index 5baca3cc8..000000000
--- a/testcases/kernel/fs/scsi/ltpscsi/sg_include.h
+++ /dev/null
@@ -1,42 +0,0 @@
-#ifdef SG_KERNEL_INCLUDES
- #include "/usr/src/linux/include/scsi/sg.h"
- #include "/usr/src/linux/include/scsi/scsi.h"
-#else
- #ifdef SG_TRICK_GNU_INCLUDES
- #include <linux/../scsi/sg.h>
- #include <linux/../scsi/scsi.h>
- #else
- #include <scsi/sg.h>
- #include <scsi/scsi.h>
- #endif
-#endif
-
-/*
- Getting the correct include files for the sg interface can be an ordeal.
- In a perfect world, one would just write:
- #include <scsi/sg.h>
- #include <scsi/scsi.h>
- This would include the files found in the /usr/include/scsi directory.
- Those files are maintained with the GNU library which may or may not
- agree with the kernel and version of sg driver that is running. Any
- many cases this will not matter. However in some it might, for example
- glibc 2.1's include files match the sg driver found in the lk 2.2
- series. Hence if glibc 2.1 is used with lk 2.4 then the additional
- sg v3 interface will not be visible.
- If this is a problem then defining SG_KERNEL_INCLUDES will access the
- kernel supplied header files (assuming they are in the normal place).
- The GNU library maintainers and various kernel people don't like
- this approach (but it does work).
- The technique selected by defining SG_TRICK_GNU_INCLUDES worked (and
- was used) prior to glibc 2.2 . Prior to that version /usr/include/linux
- was a symbolic link to /usr/src/linux/include/linux .
-
- There are other approaches if this include "mixup" causes pain. These
- would involve include files being copied or symbolic links being
- introduced.
-
- Sorry about the inconvenience. Typically neither SG_KERNEL_INCLUDES
- nor SG_TRICK_GNU_INCLUDES is defined.
-
- dpg 20010415
-*/
diff --git a/testcases/kernel/input/input_helper.c b/testcases/kernel/input/input_helper.c
index 09530fb4d..c929de6ba 100644
--- a/testcases/kernel/input/input_helper.c
+++ b/testcases/kernel/input/input_helper.c
@@ -25,6 +25,7 @@
#include "test.h"
#include "safe_macros.h"
#include "input_helper.h"
+#include "lapi/uinput.h"
#define VIRTUAL_DEVICE "virtual-device-ltp"
@@ -185,6 +186,29 @@ void send_rel_move(int fd, int x, int y)
send_event(fd, EV_SYN, 0, 0);
}
+static void check_ui_get_sysname_ioctl(int fd)
+{
+ char sys_name[256];
+ char dev_name[256];
+ char *path;
+
+ SAFE_IOCTL(NULL, fd, UI_GET_SYSNAME(sizeof(sys_name)), sys_name, NULL);
+ SAFE_ASPRINTF(NULL, &path, "/sys/devices/virtual/input/%s/name", sys_name);
+
+ if (FILE_SCANF(path, "%s", dev_name)) {
+ tst_resm(TFAIL|TERRNO, "Failed to read '%s'", path);
+ free(path);
+ return;
+ }
+
+ if (!strcmp(VIRTUAL_DEVICE, dev_name))
+ tst_resm(TPASS, "ioctl UI_GET_SYSNAME returned correct name");
+ else
+ tst_resm(TFAIL, "ioctl UI_GET_SYSNAME returned wrong name");
+
+ free(path);
+}
+
void create_device(int fd)
{
int nb;
@@ -202,8 +226,10 @@ void create_device(int fd)
SAFE_IOCTL(NULL, fd, UI_DEV_CREATE, NULL);
for (nb = 100; nb > 0; nb--) {
- if (check_device())
+ if (check_device()) {
+ check_ui_get_sysname_ioctl(fd);
return;
+ }
usleep(10000);
}
diff --git a/testcases/kernel/io/direct_io/diotest4.c b/testcases/kernel/io/direct_io/diotest4.c
index 45c677b5b..ad00fa3e0 100644
--- a/testcases/kernel/io/direct_io/diotest4.c
+++ b/testcases/kernel/io/direct_io/diotest4.c
@@ -270,6 +270,7 @@ int main(int argc, char *argv[])
case TST_NFS_MAGIC:
case TST_BTRFS_MAGIC:
case TST_FUSE_MAGIC:
+ case TST_TMPFS_MAGIC:
tst_resm(TCONF, "%s supports odd count IO",
tst_fs_type_name(fs_type));
break;
@@ -443,6 +444,7 @@ int main(int argc, char *argv[])
case TST_NFS_MAGIC:
case TST_BTRFS_MAGIC:
case TST_FUSE_MAGIC:
+ case TST_TMPFS_MAGIC:
tst_resm(TCONF, "%s supports non-aligned buffer",
tst_fs_type_name(fs_type));
break;
diff --git a/testcases/kernel/irq/irqbalance01.c b/testcases/kernel/irq/irqbalance01.c
index a3d29aec2..96bbec6a8 100644
--- a/testcases/kernel/irq/irqbalance01.c
+++ b/testcases/kernel/irq/irqbalance01.c
@@ -93,7 +93,7 @@ static void collect_irq_info(void)
char path[PATH_MAX];
size_t row, col, len;
long acc;
- unsigned int cpu_total, bit;
+ unsigned int cpu_total, bit, row_parsed;
nr_cpus = 0;
nr_irqs = 0;
@@ -136,7 +136,7 @@ static void collect_irq_info(void)
c = first_row;
acc = -1;
- row = col = 0;
+ row = col = row_parsed = 0;
/* Parse columns containing IRQ counts and IRQ IDs into acc. Ignore
* everything else.
*/
@@ -154,7 +154,9 @@ static void collect_irq_info(void)
if (acc != -1)
tst_brk(TBROK, "Unexpected EOL");
col = 0;
- row++;
+ if (row_parsed)
+ row++;
+ row_parsed = 0;
break;
case '0' ... '9':
if (acc == -1)
@@ -168,6 +170,7 @@ static void collect_irq_info(void)
tst_brk(TBROK, "Unexpected ':'");
irq_ids[row] = acc;
acc = -1;
+ row_parsed = 1;
break;
default:
acc = -1;
diff --git a/testcases/kernel/mem/.gitignore b/testcases/kernel/mem/.gitignore
index 7258489ed..c96fe8bfc 100644
--- a/testcases/kernel/mem/.gitignore
+++ b/testcases/kernel/mem/.gitignore
@@ -53,6 +53,7 @@
/ksm/ksm04
/ksm/ksm05
/ksm/ksm06
+/ksm/ksm07
/mem/mem02
/mmapstress/mmap-corruption01
/mmapstress/mmapstress01
diff --git a/testcases/kernel/mem/hugetlb/hugemmap/hugemmap06.c b/testcases/kernel/mem/hugetlb/hugemmap/hugemmap06.c
index 79bea8e8b..5032e05ec 100644
--- a/testcases/kernel/mem/hugetlb/hugemmap/hugemmap06.c
+++ b/testcases/kernel/mem/hugetlb/hugemmap/hugemmap06.c
@@ -1,24 +1,28 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Copyright (c) 2015-2017 Red Hat, Inc.
+ * Copyright (c) Linux Test Project, 2018-2023
*
- * DESCRIPTION
+ * Authors:
+ * Herton R. Krzesinski <herton@redhat.com>
+ * Li Wang <liwang@redhat.com>
+ */
+
+/*\
+ * [Description]
*
- * There is a race condition if we map a same file on different processes.
- * Region tracking is protected by mmap_sem and hugetlb_instantiation_mutex.
- * When we do mmap, we don't grab a hugetlb_instantiation_mutex, but only
- * mmap_sem (exclusively). This doesn't prevent other tasks from modifying
- * the region structure, so it can be modified by two processes concurrently.
+ * There is a race condition if we map a same file on different processes.
+ * Region tracking is protected by mmap_sem and hugetlb_instantiation_mutex.
+ * When we do mmap, we don't grab a hugetlb_instantiation_mutex, but only
+ * mmap_sem (exclusively). This doesn't prevent other tasks from modifying
+ * the region structure, so it can be modified by two processes concurrently.
*
- * This bug was fixed on stable kernel by commits:
- * f522c3ac00a4(mm, hugetlb: change variable name reservations to resv)
- * 9119a41e9091(mm, hugetlb: unify region structure handling)
- * 7b24d8616be3(mm, hugetlb: fix race in region tracking)
- * 1406ec9ba6c6(mm, hugetlb: improve, cleanup resv_map parameters)
+ * This bug was fixed on stable kernel by commits:
*
- * AUTHOR:
- * Herton R. Krzesinski <herton@redhat.com>
- * Li Wang <liwang@redhat.com>
+ * f522c3ac00a4 (mm, hugetlb: change variable name reservations to resv)
+ * 9119a41e9091 (mm, hugetlb: unify region structure handling)
+ * 7b24d8616be3 (mm, hugetlb: fix race in region tracking)
+ * 1406ec9ba6c6 (mm, hugetlb: improve, cleanup resv_map parameters)
*/
#define _GNU_SOURCE
@@ -73,8 +77,7 @@ static void do_mmap(unsigned int j LTP_ATTRIBUTE_UNUSED)
if (addr == MAP_FAILED) {
if (errno == ENOMEM) {
- tst_brk(TCONF,
- "Cannot allocate hugepage, memory too fragmented?");
+ tst_brk(TCONF, "Cannot allocate hugepage, memory too fragmented?");
}
tst_brk(TBROK | TERRNO, "Cannot allocate hugepage");
@@ -86,8 +89,7 @@ static void do_mmap(unsigned int j LTP_ATTRIBUTE_UNUSED)
TEST(pthread_create(&tid[i], NULL, thr, &mmap_sz[i]));
if (TST_RET)
- tst_brk(TBROK | TRERRNO,
- "pthread_create failed");
+ tst_brk(TBROK | TRERRNO, "pthread_create failed");
new_addr = mmap(addr, (sz - 1) * hpage_size,
PROT_READ | PROT_WRITE,
@@ -103,14 +105,13 @@ static void do_mmap(unsigned int j LTP_ATTRIBUTE_UNUSED)
for (i = 0; i < ARSZ; ++i) {
TEST(pthread_join(tid[i], NULL));
if (TST_RET)
- tst_brk(TBROK | TRERRNO,
- "pthread_join failed");
+ tst_brk(TBROK | TRERRNO, "pthread_join failed");
}
if (munmap(addr, sz * hpage_size) == -1)
tst_brk(TFAIL | TERRNO, "huge munmap failed");
- tst_res(TPASS, "No regression found.");
+ tst_res(TPASS, "No regression found");
}
static struct tst_test test = {
diff --git a/testcases/kernel/mem/hugetlb/hugemmap/hugemmap13.c b/testcases/kernel/mem/hugetlb/hugemmap/hugemmap13.c
index f8c36640d..42b80064e 100644
--- a/testcases/kernel/mem/hugetlb/hugemmap/hugemmap13.c
+++ b/testcases/kernel/mem/hugetlb/hugemmap/hugemmap13.c
@@ -21,6 +21,7 @@
#include <limits.h>
#include <sys/param.h>
#include <sys/types.h>
+#include <lapi/mmap.h>
#include "hugetlb.h"
@@ -62,15 +63,15 @@ static void run_test(void)
memset(p, 0, hpage_size);
/* Test just below 4GB to check for off-by-one errors */
- lowaddr = FOURGB - page_size;
- q = mmap((void *)lowaddr, page_size, PROT_READ|PROT_WRITE,
+ lowaddr = FOURGB - MMAP_GRANULARITY;
+ q = mmap((void *)lowaddr, MMAP_GRANULARITY, PROT_READ|PROT_WRITE,
MAP_SHARED|MAP_FIXED|MAP_ANONYMOUS, 0, 0);
if (q == MAP_FAILED) {
- below_start = FOURGB - page_size;
+ below_start = FOURGB - MMAP_GRANULARITY;
above_end = FOURGB;
if (range_is_mapped(below_start, above_end) == 1) {
- tst_res(TINFO|TERRNO, "region (4G-page)-4G is not free & "
+ tst_res(TINFO|TERRNO, "region (4G-MMAP_GRANULARITY)-4G is not free & "
"mmap() failed expected");
tst_res(TPASS, "Successful but inconclusive");
} else
diff --git a/testcases/kernel/mem/hugetlb/hugemmap/hugemmap20.c b/testcases/kernel/mem/hugetlb/hugemmap/hugemmap20.c
index 6bc367f96..e6b6bda76 100644
--- a/testcases/kernel/mem/hugetlb/hugemmap/hugemmap20.c
+++ b/testcases/kernel/mem/hugetlb/hugemmap/hugemmap20.c
@@ -14,6 +14,7 @@
#include "hugetlb.h"
#define MNTPOINT "hugetlbfs/"
+#define FLAGS_DESC(x) .flags = x, .flags_str = #x
static int fd = -1;
static unsigned long hpage_size;
@@ -22,10 +23,10 @@ static struct tcase {
int flags;
char *flags_str;
} tcases[] = {
- {MAP_PRIVATE, "MAP_PRIVATE"},
- {MAP_SHARED, "MAP_SHARED"},
- {MAP_PRIVATE | MAP_LOCKED, "MAP_PRIVATE | MAP_LOCKED"},
- {MAP_SHARED | MAP_LOCKED, "MAP_SHARED | MAP_LOCKED"},
+ { FLAGS_DESC(MAP_PRIVATE) },
+ { FLAGS_DESC(MAP_SHARED) },
+ { FLAGS_DESC(MAP_PRIVATE | MAP_LOCKED) },
+ { FLAGS_DESC(MAP_SHARED | MAP_LOCKED) },
};
static void run_test(unsigned int i)
diff --git a/testcases/kernel/mem/hugetlb/hugemmap/hugemmap21.c b/testcases/kernel/mem/hugetlb/hugemmap/hugemmap21.c
index a8e332ebd..7abfda92d 100644
--- a/testcases/kernel/mem/hugetlb/hugemmap/hugemmap21.c
+++ b/testcases/kernel/mem/hugetlb/hugemmap/hugemmap21.c
@@ -36,9 +36,7 @@ static void do_work(int thread, size_t size, int fd)
for (i = 0; i < size; i++)
memcpy((char *)addr+i, &pattern, 1);
- if (msync(addr, size, MS_SYNC))
- tst_brk(TBROK | TERRNO, "Thread %d (pid %d): msync() failed",
- thread, getpid());
+ SAFE_MSYNC(addr, size, MS_SYNC);
for (i = 0; i < size; i++) {
if (addr[i] != pattern) {
diff --git a/testcases/kernel/mem/hugetlb/hugemmap/hugemmap23.c b/testcases/kernel/mem/hugetlb/hugemmap/hugemmap23.c
index 4c1cff325..d755161c9 100644
--- a/testcases/kernel/mem/hugetlb/hugemmap/hugemmap23.c
+++ b/testcases/kernel/mem/hugetlb/hugemmap/hugemmap23.c
@@ -1,6 +1,7 @@
// SPDX-License-Identifier: LGPL-2.1-or-later
/*
* Copyright (C) 2005-2006 IBM Corporation.
+ * Copyright (c) Linux Test Project, 2023
* Author: David Gibson & Adam Litke
*/
@@ -11,11 +12,13 @@
* perform read/write operation. It checks if the operation results in
* expected behaviour as per the protection.
*/
+
#include <setjmp.h>
#include "hugetlb.h"
#define MNTPOINT "hugetlbfs/"
#define RANDOM_CONSTANT 0x1234ABCD
+#define FLAGS_DESC(x) x, #x
static int fd = -1;
static sigjmp_buf sig_escape;
@@ -32,23 +35,12 @@ static struct tcase {
int prot2;
char *prot2_str;
} tcases[] = {
- {"R->RW", 1, PROT_READ, "PROT_READ",
- 1, PROT_READ|PROT_WRITE, "PROT_READ|PROT_WRITE"},
-
- {"RW->R", 1, PROT_READ|PROT_WRITE, "PROT_READ|PROT_WRITE",
- 1, PROT_READ, "PROT_READ"},
-
- {"R->RW 1/2", 2, PROT_READ, "PROT_READ",
- 1, PROT_READ|PROT_WRITE, "PROT_READ|PROT_WRITE"},
-
- {"RW->R 1/2", 2, PROT_READ|PROT_WRITE, "PROT_READ|PROT_WRITE",
- 1, PROT_READ, "PROT_READ"},
-
- {"NONE->R", 1, PROT_NONE, "PROT_NONE",
- 1, PROT_READ, "PROT_READ"},
-
- {"NONE->RW", 1, PROT_NONE, "PROT_NONE",
- 1, PROT_READ|PROT_WRITE, "PROT_READ|PROT_WRITE"},
+ {"R->RW", 1, FLAGS_DESC(PROT_READ), 1, FLAGS_DESC(PROT_READ|PROT_WRITE)},
+ {"RW->R", 1, FLAGS_DESC(PROT_READ | PROT_WRITE), 1, FLAGS_DESC(PROT_READ)},
+ {"R->RW 1/2", 2, FLAGS_DESC(PROT_READ), 1, FLAGS_DESC(PROT_READ | PROT_WRITE)},
+ {"RW->R 1/2", 2, FLAGS_DESC(PROT_READ | PROT_WRITE), 1, FLAGS_DESC(PROT_READ)},
+ {"NONE->R", 1, FLAGS_DESC(PROT_NONE), 1, FLAGS_DESC(PROT_READ)},
+ {"NONE->RW", 1, FLAGS_DESC(PROT_NONE), 1, FLAGS_DESC(PROT_READ | PROT_WRITE)},
};
static void sig_handler(int signum, siginfo_t *si, void *uc)
diff --git a/testcases/kernel/mem/hugetlb/hugemmap/hugemmap24.c b/testcases/kernel/mem/hugetlb/hugemmap/hugemmap24.c
index 158a03010..431dc1bbf 100644
--- a/testcases/kernel/mem/hugetlb/hugemmap/hugemmap24.c
+++ b/testcases/kernel/mem/hugetlb/hugemmap/hugemmap24.c
@@ -30,7 +30,7 @@ static int init_slice_boundary(int fd)
unsigned long slice_size;
void *p, *heap;
int i;
-#if defined(__LP64__) && !defined(__aarch64__)
+#if defined(__LP64__) && !defined(__aarch64__) && !defined(__loongarch__)
/* powerpc: 1TB slices starting at 1 TB */
slice_boundary = 0x10000000000;
slice_size = 0x10000000000;
diff --git a/testcases/kernel/mem/hugetlb/hugeshmctl/hugeshmctl01.c b/testcases/kernel/mem/hugetlb/hugeshmctl/hugeshmctl01.c
index a68b0da75..04325ce10 100644
--- a/testcases/kernel/mem/hugetlb/hugeshmctl/hugeshmctl01.c
+++ b/testcases/kernel/mem/hugetlb/hugeshmctl/hugeshmctl01.c
@@ -1,35 +1,14 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Copyright (c) International Business Machines Corp., 2004
- * Copyright (c) Linux Test Project, 2004-2020
+ * Copyright (c) Linux Test Project, 2004-2023
+ * Original author: Wayne Boyer, modified by Robbie Williamson
*/
-/*
- * DESCRIPTION
- * hugeshmctl01 - test the IPC_STAT, IPC_SET and IPC_RMID commands as
- * they are used with shmctl()
- *
- * ALGORITHM
- * loop if that option was specified
- * create a large shared memory segment with read and write permission
- * set up any test case specific conditions
- * call shmctl() using the TEST macro
- * check the return code
- * if failure, issue a FAIL message.
- * otherwise,
- * if doing functionality testing
- * call the correct test function
- * if the conditions are correct,
- * issue a PASS message
- * otherwise
- * issue a FAIL message
- * otherwise
- * issue a PASS message
- * call cleanup
+/*\
+ * [Description]
*
- * HISTORY
- * 03/2001 - Written by Wayne Boyer
- * 04/2004 - Updated by Robbie Williamson
+ * Test the IPC_STAT, IPC_SET and IPC_RMID commands used by shmctl().
*/
#include <limits.h>
@@ -71,9 +50,11 @@ static void test_hugeshmctl(unsigned int i)
* permissions. Do this here instead of in setup()
* so that looping (-i) will work correctly.
*/
- if (i == 0)
+ if (i == 0) {
shm_id_1 = shmget(shmkey, shm_size,
SHM_HUGETLB | IPC_CREAT | IPC_EXCL | SHM_RW);
+ }
+
if (shm_id_1 == -1)
tst_brk(TBROK | TERRNO, "shmget #main");
diff --git a/testcases/kernel/mem/ksm/ksm01.c b/testcases/kernel/mem/ksm/ksm01.c
index bcd095865..e2d3d9e00 100644
--- a/testcases/kernel/mem/ksm/ksm01.c
+++ b/testcases/kernel/mem/ksm/ksm01.c
@@ -86,6 +86,8 @@ static struct tst_test test = {
TST_SR_SKIP_MISSING | TST_SR_TCONF_RO},
{"/sys/kernel/mm/ksm/merge_across_nodes", "1",
TST_SR_SKIP_MISSING | TST_SR_TCONF_RO},
+ {"/sys/kernel/mm/ksm/smart_scan", "0",
+ TST_SR_SKIP_MISSING | TST_SR_TBROK_RO},
{}
},
.needs_kconfigs = (const char *const[]){
diff --git a/testcases/kernel/mem/ksm/ksm02.c b/testcases/kernel/mem/ksm/ksm02.c
index bce639dce..3707de95d 100644
--- a/testcases/kernel/mem/ksm/ksm02.c
+++ b/testcases/kernel/mem/ksm/ksm02.c
@@ -107,6 +107,8 @@ static struct tst_test test = {
TST_SR_SKIP_MISSING | TST_SR_TCONF_RO},
{"/sys/kernel/mm/ksm/merge_across_nodes", "1",
TST_SR_SKIP_MISSING | TST_SR_TCONF_RO},
+ {"/sys/kernel/mm/ksm/smart_scan", "0",
+ TST_SR_SKIP_MISSING | TST_SR_TBROK_RO},
{}
},
.needs_kconfigs = (const char *const[]){
diff --git a/testcases/kernel/mem/ksm/ksm03.c b/testcases/kernel/mem/ksm/ksm03.c
index 4a733269f..cff74700d 100644
--- a/testcases/kernel/mem/ksm/ksm03.c
+++ b/testcases/kernel/mem/ksm/ksm03.c
@@ -89,6 +89,8 @@ static struct tst_test test = {
TST_SR_SKIP_MISSING | TST_SR_TCONF_RO},
{"/sys/kernel/mm/ksm/merge_across_nodes", "1",
TST_SR_SKIP_MISSING | TST_SR_TCONF_RO},
+ {"/sys/kernel/mm/ksm/smart_scan", "0",
+ TST_SR_SKIP_MISSING | TST_SR_TBROK_RO},
{}
},
.needs_kconfigs = (const char *const[]){
diff --git a/testcases/kernel/mem/ksm/ksm04.c b/testcases/kernel/mem/ksm/ksm04.c
index 4f1f2f721..f558b23be 100644
--- a/testcases/kernel/mem/ksm/ksm04.c
+++ b/testcases/kernel/mem/ksm/ksm04.c
@@ -1,34 +1,19 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Copyright (C) 2010-2017 Red Hat, Inc.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
- * the GNU General Public License for more details.
- *
- * Kernel Samepage Merging (KSM) for Memory Resource Controller and NUMA
- *
- * Basic tests were to start several programs with same and different
- * memory contents and ensure only to merge the ones with the same
- * contents. When changed the content of one of merged pages in a
- * process and to the mode "unmerging", it should discard all merged
- * pages there. Also tested it is possible to disable KSM. There are
- * also command-line options to specify the memory allocation size, and
- * number of processes have same memory contents so it is possible to
- * test more advanced things like KSM + OOM etc.
+ */
+
+/*\
+ * [Description]
*
* Prerequisites:
*
- * 1) ksm and ksmtuned daemons need to be disabled. Otherwise, it could
- * distrub the testing as they also change some ksm tunables depends
- * on current workloads.
+ * ksm and ksmtuned daemons need to be disabled. Otherwise, it could
+ * distrub the testing as they also change some ksm tunables depends
+ * on current workloads.
+ *
+ * [Algorithm]
*
- * The test steps are:
* - Check ksm feature and backup current run setting.
* - Change run setting to 1 - merging.
* - 3 memory allocation programs have the memory contents that 2 of
@@ -109,6 +94,8 @@ static struct tst_test test = {
TST_SR_SKIP_MISSING | TST_SR_TCONF_RO},
{"/sys/kernel/mm/ksm/merge_across_nodes", "1",
TST_SR_SKIP_MISSING | TST_SR_TCONF_RO},
+ {"/sys/kernel/mm/ksm/smart_scan", "0",
+ TST_SR_SKIP_MISSING | TST_SR_TBROK_RO},
{}
},
.needs_kconfigs = (const char *const[]){
diff --git a/testcases/kernel/mem/ksm/ksm05.c b/testcases/kernel/mem/ksm/ksm05.c
index 1f58c8325..1d9d9699a 100644
--- a/testcases/kernel/mem/ksm/ksm05.c
+++ b/testcases/kernel/mem/ksm/ksm05.c
@@ -43,7 +43,6 @@
#ifdef HAVE_DECL_MADV_MERGEABLE
-static int ksm_run_orig = -1;
static void sighandler(int sig);
static void test_ksm(void)
@@ -89,6 +88,8 @@ static struct tst_test test = {
.test_all = test_ksm,
.save_restore = (const struct tst_path_val[]) {
{"/sys/kernel/mm/ksm/run", "1", TST_SR_TBROK},
+ {"/sys/kernel/mm/ksm/smart_scan", "0",
+ TST_SR_SKIP_MISSING | TST_SR_TBROK_RO},
{}
},
.needs_kconfigs = (const char *const[]){
diff --git a/testcases/kernel/mem/ksm/ksm06.c b/testcases/kernel/mem/ksm/ksm06.c
index 0b159e5c7..80fdf1e47 100644
--- a/testcases/kernel/mem/ksm/ksm06.c
+++ b/testcases/kernel/mem/ksm/ksm06.c
@@ -142,6 +142,8 @@ static struct tst_test test = {
{"/sys/kernel/mm/ksm/run", NULL, TST_SR_TBROK},
{"/sys/kernel/mm/ksm/sleep_millisecs", NULL, TST_SR_TBROK},
{"/sys/kernel/mm/ksm/merge_across_nodes", NULL, TST_SR_TCONF},
+ {"/sys/kernel/mm/ksm/smart_scan", "0",
+ TST_SR_SKIP_MISSING | TST_SR_TBROK_RO},
{}
},
.needs_kconfigs = (const char *const[]){
diff --git a/testcases/kernel/mem/ksm/ksm07.c b/testcases/kernel/mem/ksm/ksm07.c
new file mode 100644
index 000000000..619bd7b55
--- /dev/null
+++ b/testcases/kernel/mem/ksm/ksm07.c
@@ -0,0 +1,114 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (C) 2023 Red Hat, Inc.
+ */
+/*\
+ * [Description]
+ *
+ * Kernel Samepage Merging (KSM) for smart scan feature
+ *
+ * Test allocates a page and fills it with 'a' characters. It captures the
+ * pages_skipped counter, waits for a few iterations and captures the
+ * pages_skipped counter again. The expectation is that over 50% of the page
+ * scans are skipped. (There is only one page that has KSM enabled and it gets
+ * scanned during each iteration and it cannot be de-duplicated.)
+ *
+ * Smart scan feature was added in kernel v6.7.
+ *
+ * [Prerequisites]
+ *
+ * ksm and ksmtuned daemons need to be disabled. Otherwise, it could
+ * distrub the testing as they also change some ksm tunables depends
+ * on current workloads.
+ */
+
+#include <sys/wait.h>
+#include "mem.h"
+
+/* This test allocates one page, fills the page with a's, captures the
+ * full_scan and pages_skipped counters. Then it makes sure at least 3
+ * full scans have been performed and measures the above counters again.
+ * The expectation is that at least 50% of the pages are skipped.
+ *
+ * To wait for at least 3 scans it uses the wait_ksmd_full_scan() function. In
+ * reality, it will be a lot more scans as the wait_ksmd_full_scan() function
+ * sleeps for one second.
+ */
+static void verify_ksm(void)
+{
+ int full_scans_begin;
+ int full_scans_end;
+ int pages_skipped_begin;
+ int pages_skipped_end;
+ int diff_pages;
+ int diff_scans;
+ unsigned long page_size;
+ char *memory;
+
+ /* Apply for the space for memory. */
+ page_size = sysconf(_SC_PAGE_SIZE);
+ memory = SAFE_MALLOC(page_size);
+ memory = SAFE_MMAP(NULL, page_size, PROT_READ|PROT_WRITE,
+ MAP_ANONYMOUS|MAP_PRIVATE, -1, 0);
+#ifdef HAVE_DECL_MADV_MERGEABLE
+ if (madvise(memory, page_size, MADV_MERGEABLE) == -1)
+ tst_brk(TBROK|TERRNO, "madvise");
+#endif
+ memset(memory, 'a', page_size);
+
+ tst_res(TINFO, "KSM merging");
+
+ if (access(PATH_KSM "max_page_sharing", F_OK) == 0)
+ SAFE_FILE_PRINTF(PATH_KSM "run", "2");
+
+ /* Set defalut ksm scan values. */
+ SAFE_FILE_PRINTF(PATH_KSM "run", "1");
+ SAFE_FILE_PRINTF(PATH_KSM "pages_to_scan", "%ld", 100l);
+ SAFE_FILE_PRINTF(PATH_KSM "sleep_millisecs", "0");
+
+ /* Measure pages skipped aka "smart scan". */
+ SAFE_FILE_SCANF(PATH_KSM "full_scans", "%d", &full_scans_begin);
+ SAFE_FILE_SCANF(PATH_KSM "pages_skipped", "%d", &pages_skipped_begin);
+ wait_ksmd_full_scan();
+
+ tst_res(TINFO, "stop KSM");
+ SAFE_FILE_PRINTF(PATH_KSM "run", "0");
+
+ SAFE_FILE_SCANF(PATH_KSM "full_scans", "%d", &full_scans_end);
+ SAFE_FILE_SCANF(PATH_KSM "pages_skipped", "%d", &pages_skipped_end);
+ diff_pages = pages_skipped_end - pages_skipped_begin;
+ diff_scans = full_scans_end - full_scans_begin;
+
+ if (diff_pages < diff_scans * 50 / 100) {
+ tst_res(TINFO, "number of pages %d", diff_pages);
+ tst_res(TINFO, "number of scans %d", diff_scans);
+ tst_res(TFAIL, "not enough pages have been skipped by smart_scan");
+ } else {
+ tst_res(TPASS, "smart_scan skipped more than 50%% of the pages");
+ }
+
+#ifdef HAVE_DECL_MADV_MERGEABLE
+ if (madvise(memory, page_size, MADV_UNMERGEABLE) == -1)
+ tst_brk(TBROK|TERRNO, "madvise");
+#endif
+}
+
+static struct tst_test test = {
+ .needs_root = 1,
+ .options = (struct tst_option[]) {
+ {}
+ },
+ .save_restore = (const struct tst_path_val[]) {
+ {PATH_KSM "pages_skipped", NULL, TST_SR_TCONF},
+ {PATH_KSM "run", NULL, TST_SR_TCONF},
+ {PATH_KSM "sleep_millisecs", NULL, TST_SR_TCONF},
+ {PATH_KSM "smart_scan", "1",
+ TST_SR_SKIP_MISSING | TST_SR_TCONF},
+ {}
+ },
+ .needs_kconfigs = (const char *const[]){
+ "CONFIG_KSM=y",
+ NULL
+ },
+ .test_all = verify_ksm,
+};
diff --git a/testcases/kernel/mem/ksm/ksm_common.h b/testcases/kernel/mem/ksm/ksm_common.h
index a582891c6..489d34ae0 100644
--- a/testcases/kernel/mem/ksm/ksm_common.h
+++ b/testcases/kernel/mem/ksm/ksm_common.h
@@ -1,32 +1,36 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
+/* SPDX-License-Identifier: GPL-2.0-or-later */
/*
* Copyright (C) 2017 Red Hat, Inc.
*/
- /*
- * Parse the ksm0* test options in funcion parse_ksm_options().
- */
+/*
+ * Parse the ksm0* test options in funcion parse_ksm_options().
+ */
+
+#ifndef KSM_COMMON_H__
+#define KSM_COMMON_H__
#include "tst_test.h"
#define DEFAULT_MEMSIZE 128
-int size = DEFAULT_MEMSIZE, num = 3, unit = 1;
-char *opt_sizestr, *opt_numstr, *opt_unitstr;
+static int size = DEFAULT_MEMSIZE, num = 3, unit = 1;
+static char *opt_sizestr, *opt_numstr, *opt_unitstr;
static inline void parse_ksm_options(char *str_size, int *size,
char *str_num, int *num, char *str_unit, int *unit)
{
- if(tst_parse_int(str_size, size, 1, INT_MAX))
+ if (tst_parse_int(str_size, size, 1, INT_MAX))
tst_brk(TBROK, "Invalid size '%s'", str_size);
- if(tst_parse_int(str_num, num, 3, INT_MAX))
+ if (tst_parse_int(str_num, num, 3, INT_MAX))
tst_brk(TBROK, "Invalid num '%s'", str_num);
- if(tst_parse_int(str_unit, unit, 1, *size))
+ if (tst_parse_int(str_unit, unit, 1, *size))
tst_brk(TBROK, "Invalid unit '%s'", str_unit);
+
if (*size % *unit != 0)
- tst_brk(TBROK,
- "the remainder of division of size by unit is "
- "not zero.");
+ tst_brk(TBROK, "the remainder of division of size by unit is not zero.");
}
+
+#endif /* KSM_COMMON_H__ */
diff --git a/testcases/kernel/mem/mmapstress/mmapstress01.c b/testcases/kernel/mem/mmapstress/mmapstress01.c
index 6209c1bc3..9189f113e 100644
--- a/testcases/kernel/mem/mmapstress/mmapstress01.c
+++ b/testcases/kernel/mem/mmapstress/mmapstress01.c
@@ -187,13 +187,13 @@ static void child_mapper(char *file, unsigned int procno, unsigned int nprocs)
*(paddr + i) = (procno + pattern) & 0xff;
}
}
+
if (do_sync) {
randpage = lrand48() % mappages;
paddr = maddr + (randpage * pagesize); /* page address */
- if (msync(paddr, (mappages - randpage) * pagesize,
- MS_SYNC) == -1)
- tst_brk(TBROK | TERRNO, "msync failed");
+ SAFE_MSYNC(paddr, (mappages - randpage) * pagesize, MS_SYNC);
}
+
SAFE_MUNMAP(maddr, mapsize);
exit(0);
}
diff --git a/testcases/kernel/mem/oom/oom01.c b/testcases/kernel/mem/oom/oom01.c
index b13699898..903785f93 100644
--- a/testcases/kernel/mem/oom/oom01.c
+++ b/testcases/kernel/mem/oom/oom01.c
@@ -1,23 +1,12 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
/*
- * Out Of Memory (OOM)
- *
- * The program is designed to cope with unpredictable like amount and
- * system physical memory, swap size and other VMM technology like KSM,
- * memcg, memory hotplug and so on which may affect the OOM
- * behaviours. It simply increase the memory consumption 3G each time
- * until all the available memory is consumed and OOM is triggered.
- *
* Copyright (C) 2010-2017 Red Hat, Inc.
+ * Copyright (c) Linux Test Project, 2011-2023
+ */
+/*\
+ * [Description]
*
- * 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.
+ * Out Of Memory (OOM) test
*/
#include <sys/types.h>
@@ -27,15 +16,10 @@
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
-#include "lapi/abisize.h"
#include "mem.h"
static void verify_oom(void)
{
-#ifdef TST_ABI32
- tst_brk(TCONF, "test is not designed for 32-bit system.");
-#endif
-
/* we expect mmap to fail before OOM is hit */
set_sys_tune("overcommit_memory", 2, 1);
oom(NORMAL, 0, ENOMEM, 0);
@@ -54,6 +38,7 @@ static struct tst_test test = {
.forks_child = 1,
.max_runtime = TST_UNLIMITED_RUNTIME,
.test_all = verify_oom,
+ .skip_in_compat = 1,
.save_restore = (const struct tst_path_val[]) {
{"/proc/sys/vm/overcommit_memory", NULL, TST_SR_TBROK},
{}
diff --git a/testcases/kernel/mem/oom/oom02.c b/testcases/kernel/mem/oom/oom02.c
index 8d565d12a..087d61abe 100644
--- a/testcases/kernel/mem/oom/oom02.c
+++ b/testcases/kernel/mem/oom/oom02.c
@@ -1,23 +1,12 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
/*
- * Out Of Memory (OOM) for mempolicy - need NUMA system support
- *
- * The program is designed to cope with unpredictable like amount and
- * system physical memory, swap size and other VMM technology like KSM,
- * memcg, memory hotplug and so on which may affect the OOM
- * behaviours. It simply increase the memory consumption 3G each time
- * until all the available memory is consumed and OOM is triggered.
- *
* Copyright (C) 2010-2017 Red Hat, Inc.
+ * Copyright (c) Linux Test Project, 2011-2023
+ */
+/*\
+ * [Description]
*
- * 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.
+ * Out Of Memory (OOM) test for mempolicy - need NUMA system support
*/
#include "config.h"
@@ -30,7 +19,6 @@
#include <numa.h>
#endif
-#include "lapi/abisize.h"
#include "numa_helper.h"
#include "mem.h"
@@ -38,10 +26,6 @@
static void verify_oom(void)
{
-#ifdef TST_ABI32
- tst_brk(TCONF, "test is not designed for 32-bit system.");
-#endif
-
tst_res(TINFO, "OOM on MPOL_BIND mempolicy...");
testoom(MPOL_BIND, 0, ENOMEM, 1);
@@ -61,9 +45,10 @@ static void setup(void)
static struct tst_test test = {
.needs_root = 1,
.forks_child = 1,
- .max_runtime = TST_UNLIMITED_RUNTIME,
+ .max_runtime = TST_UNLIMITED_RUNTIME,
.setup = setup,
.test_all = verify_oom,
+ .skip_in_compat = 1,
.save_restore = (const struct tst_path_val[]) {
{"/proc/sys/vm/overcommit_memory", "1", TST_SR_TBROK},
{}
diff --git a/testcases/kernel/mem/oom/oom03.c b/testcases/kernel/mem/oom/oom03.c
index 778055d03..1041a6a1d 100644
--- a/testcases/kernel/mem/oom/oom03.c
+++ b/testcases/kernel/mem/oom/oom03.c
@@ -1,23 +1,12 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
/*
- * Out Of Memory (OOM) for Memory Resource Controller
- *
- * The program is designed to cope with unpredictable like amount and
- * system physical memory, swap size and other VMM technology like KSM,
- * memcg, memory hotplug and so on which may affect the OOM
- * behaviours. It simply increase the memory consumption 3G each time
- * until all the available memory is consumed and OOM is triggered.
- *
* Copyright (C) 2010-2017 Red Hat, Inc.
+ * Copyright (c) Linux Test Project, 2011-2023
+ */
+/*\
+ * [Description]
*
- * 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.
+ * Out Of Memory (OOM) test for Memory Resource Controller
*/
#include "config.h"
@@ -30,7 +19,6 @@
#include <numa.h>
#endif
-#include "lapi/abisize.h"
#include "numa_helper.h"
#include "mem.h"
@@ -38,9 +26,6 @@
static void verify_oom(void)
{
-#ifdef TST_ABI32
- tst_brk(TCONF, "test is not designed for 32-bit system.");
-#endif
testoom(0, 0, ENOMEM, 1);
if (SAFE_CG_HAS(tst_cg, "memory.swap.max")) {
@@ -90,6 +75,7 @@ static struct tst_test test = {
.setup = setup,
.test_all = verify_oom,
.needs_cgroup_ctrls = (const char *const []){ "memory", NULL },
+ .skip_in_compat = 1,
.save_restore = (const struct tst_path_val[]) {
{"/proc/sys/vm/overcommit_memory", "1", TST_SR_TBROK},
{}
diff --git a/testcases/kernel/mem/oom/oom04.c b/testcases/kernel/mem/oom/oom04.c
index d27d9d9e7..3f0bcf7e2 100644
--- a/testcases/kernel/mem/oom/oom04.c
+++ b/testcases/kernel/mem/oom/oom04.c
@@ -1,23 +1,12 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
/*
- * Out Of Memory (OOM) for CPUSET
- *
- * The program is designed to cope with unpredictable like amount and
- * system physical memory, swap size and other VMM technology like KSM,
- * memcg, memory hotplug and so on which may affect the OOM
- * behaviours. It simply increase the memory consumption 3G each time
- * until all the available memory is consumed and OOM is triggered.
- *
* Copyright (C) 2010-2017 Red Hat, Inc.
+ * Copyright (c) Linux Test Project, 2011-2023
+ */
+/*\
+ * [Description]
*
- * 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.
+ * Out Of Memory (OOM) test for CPUSET
*/
#include "config.h"
@@ -30,7 +19,6 @@
#include <numa.h>
#endif
-#include "lapi/abisize.h"
#include "numa_helper.h"
#include "mem.h"
@@ -38,9 +26,6 @@
static void verify_oom(void)
{
-#ifdef TST_ABI32
- tst_brk(TCONF, "test is not designed for 32-bit system.");
-#endif
tst_res(TINFO, "OOM on CPUSET...");
testoom(0, 0, ENOMEM, 1);
@@ -86,6 +71,7 @@ static struct tst_test test = {
.setup = setup,
.test_all = verify_oom,
.needs_cgroup_ctrls = (const char *const []){ "cpuset", NULL },
+ .skip_in_compat = 1,
.save_restore = (const struct tst_path_val[]) {
{"/proc/sys/vm/overcommit_memory", "1", TST_SR_TBROK},
{}
diff --git a/testcases/kernel/mem/oom/oom05.c b/testcases/kernel/mem/oom/oom05.c
index eb1a64267..74f0f78b3 100644
--- a/testcases/kernel/mem/oom/oom05.c
+++ b/testcases/kernel/mem/oom/oom05.c
@@ -1,23 +1,12 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
/*
- * Out Of Memory (OOM) for MEMCG and CPUSET
- *
- * The program is designed to cope with unpredictable like amount and
- * system physical memory, swap size and other VMM technology like KSM,
- * memcg, memory hotplug and so on which may affect the OOM
- * behaviours. It simply increase the memory consumption 3G each time
- * until all the available memory is consumed and OOM is triggered.
- *
* Copyright (C) 2013-2017 Red Hat, Inc.
+ * Copyright (c) Linux Test Project, 2014-2023
+ */
+/*\
+ * [Description]
*
- * 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.
+ * Out Of Memory (OOM) test for MEMCG and CPUSET
*/
#include "config.h"
@@ -30,7 +19,6 @@
#include <numa.h>
#endif
-#include "lapi/abisize.h"
#include "numa_helper.h"
#include "mem.h"
@@ -38,10 +26,6 @@
static void verify_oom(void)
{
-#ifdef TST_ABI32
- tst_brk(TCONF, "test is not designed for 32-bit system.");
-#endif
-
tst_res(TINFO, "OOM on CPUSET & MEMCG...");
testoom(0, 0, ENOMEM, 1);
@@ -110,6 +94,7 @@ static struct tst_test test = {
.needs_cgroup_ctrls = (const char *const []){
"memory", "cpuset", NULL
},
+ .skip_in_compat = 1,
.save_restore = (const struct tst_path_val[]) {
{"/proc/sys/vm/overcommit_memory", "1", TST_SR_TBROK},
{}
diff --git a/testcases/kernel/mem/swapping/swapping01.c b/testcases/kernel/mem/swapping/swapping01.c
index fc225e4a6..a0030a75f 100644
--- a/testcases/kernel/mem/swapping/swapping01.c
+++ b/testcases/kernel/mem/swapping/swapping01.c
@@ -41,7 +41,6 @@
#include <string.h>
#include <unistd.h>
#include "tst_safe_stdio.h"
-#include "lapi/abisize.h"
#include "mem.h"
/* allow swapping 1 * phy_mem in maximum */
@@ -62,9 +61,6 @@ static unsigned int start_runtime;
static void test_swapping(void)
{
-#ifdef TST_ABI32
- tst_brk(TCONF, "test is not designed for 32-bit system.");
-#endif
FILE *file;
char line[PATH_MAX];
@@ -83,7 +79,9 @@ static void test_swapping(void)
switch (pid = SAFE_FORK()) {
case 0:
+ TST_PRINT_MEMINFO();
do_alloc(0);
+ TST_PRINT_MEMINFO();
do_alloc(1);
exit(0);
default:
@@ -111,15 +109,19 @@ static void do_alloc(int allow_raise)
if (allow_raise == 1)
tst_res(TINFO, "available physical memory: %ld MB",
mem_available_init / 1024);
+
mem_count = mem_available_init + mem_over;
+
if (allow_raise == 1)
tst_res(TINFO, "try to allocate: %ld MB", mem_count / 1024);
s = SAFE_MALLOC(mem_count * 1024);
memset(s, 1, mem_count * 1024);
+
if ((allow_raise == 1) && (raise(SIGSTOP) == -1)) {
tst_res(TINFO, "memory allocated: %ld MB", mem_count / 1024);
tst_brk(TBROK | TERRNO, "kill");
}
+
free(s);
}
@@ -138,6 +140,7 @@ static void check_swapping(void)
swap_free_now = SAFE_READ_MEMINFO("SwapFree:");
sleep(1);
long diff = labs(swap_free_now - SAFE_READ_MEMINFO("SwapFree:"));
+
if (diff < 10)
break;
@@ -146,9 +149,10 @@ static void check_swapping(void)
swapped = SAFE_READ_PROC_STATUS(pid, "VmSwap:");
if (swapped > mem_over_max) {
+ TST_PRINT_MEMINFO();
kill(pid, SIGCONT);
- tst_brk(TFAIL, "heavy swapping detected: "
- "%ld MB swapped.", swapped / 1024);
+ tst_brk(TFAIL, "heavy swapping detected: %ld MB swapped",
+ swapped / 1024);
}
tst_res(TPASS, "no heavy swapping detected, %ld MB swapped.",
@@ -164,6 +168,7 @@ static struct tst_test test = {
.min_mem_avail = 10,
.max_runtime = 600,
.test_all = test_swapping,
+ .skip_in_compat = 1,
.needs_kconfigs = (const char *[]) {
"CONFIG_SWAP=y",
NULL
diff --git a/testcases/kernel/mem/tunable/overcommit_memory.c b/testcases/kernel/mem/tunable/overcommit_memory.c
index ffb7a6d9d..d055dd18f 100644
--- a/testcases/kernel/mem/tunable/overcommit_memory.c
+++ b/testcases/kernel/mem/tunable/overcommit_memory.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/*
- * Copyright (c) 2012-2020 Linux Test Project
+ * Copyright (c) 2012-2023 Linux Test Project
* Copyright (c) 2012-2017 Red Hat, Inc.
*
* There are two tunables overcommit_memory and overcommit_ratio under
@@ -62,7 +62,6 @@
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
-#include "lapi/abisize.h"
#include "mem.h"
#define DEFAULT_OVER_RATIO 50L
@@ -124,10 +123,6 @@ static void setup(void)
static void overcommit_memory_test(void)
{
-
-#ifdef TST_ABI32
- tst_brk(TCONF, "test is not designed for 32-bit system.");
-#endif
/* start to test overcommit_memory=2 */
set_sys_tune("overcommit_memory", 2, 1);
@@ -256,6 +251,7 @@ static struct tst_test test = {
},
.setup = setup,
.test_all = overcommit_memory_test,
+ .skip_in_compat = 1,
.save_restore = (const struct tst_path_val[]) {
{"/proc/sys/vm/overcommit_memory", NULL, TST_SR_TBROK},
{"/proc/sys/vm/overcommit_ratio", NULL, TST_SR_TBROK},
diff --git a/testcases/kernel/mem/vma/vma05.sh b/testcases/kernel/mem/vma/vma05.sh
index c9e4becdb..e1ef1014e 100755
--- a/testcases/kernel/mem/vma/vma05.sh
+++ b/testcases/kernel/mem/vma/vma05.sh
@@ -25,11 +25,13 @@ TST_NEEDS_CMDS="gdb"
CORE_LIMIT=$(ulimit -c)
CORE_PATTERN=$(cat /proc/sys/kernel/core_pattern)
+CORE_USES_PID=$(cat /proc/sys/kernel/core_uses_pid)
setup()
{
ulimit -c unlimited
echo "core" > /proc/sys/kernel/core_pattern
+ echo 0 > /proc/sys/kernel/core_uses_pid
unset DEBUGINFOD_URLS
}
@@ -37,6 +39,7 @@ cleanup()
{
ulimit -c "$CORE_LIMIT"
echo "$CORE_PATTERN" > /proc/sys/kernel/core_pattern
+ echo $CORE_USES_PID > /proc/sys/kernel/core_uses_pid
}
vma_report_check()
@@ -54,6 +57,8 @@ vma_report_check()
rm -rf core*
{ vma05_vdso; } > /dev/null 2>&1
+ [ -f core ] || tst_brk TBROK "missing core file"
+
TRACE=$(gdb -silent -ex="thread apply all backtrace" -ex="quit"\
vma05_vdso ./core* 2> /dev/null)
if echo "$TRACE" | grep -qF "??"; then
diff --git a/testcases/kernel/pty/pty04.c b/testcases/kernel/pty/pty04.c
index 8c7b1bf92..204703253 100644
--- a/testcases/kernel/pty/pty04.c
+++ b/testcases/kernel/pty/pty04.c
@@ -93,6 +93,19 @@ static struct ldisc_info ldiscs[] = {
static int ptmx = -1, pts = -1, sk = -1, mtu, no_check;
+static void setup(void)
+{
+ int fd = SAFE_OPEN("/dev/ptmx", O_RDWR);
+
+ TEST(ioctl(fd, TIOCVHANGUP));
+ SAFE_CLOSE(fd);
+
+ if (TST_RET && TST_ERR == ENOTTY)
+ tst_brk(TCONF | TTERRNO, "ioctl(TIOCVHANGUP) not supported");
+ else if (TST_RET)
+ tst_brk(TBROK | TTERRNO, "ioctl(TIOCVHANGUP) failed");
+}
+
static int set_ldisc(int tty, const struct ldisc_info *ldisc)
{
TEST(ioctl(tty, TIOCSETD, &ldisc->n));
@@ -467,6 +480,7 @@ static void cleanup(void)
}
static struct tst_test test = {
+ .setup = setup,
.test = do_test,
.cleanup = cleanup,
.tcnt = 2,
diff --git a/testcases/kernel/sched/sysctl/.gitignore b/testcases/kernel/sched/sysctl/.gitignore
new file mode 100644
index 000000000..29b859b81
--- /dev/null
+++ b/testcases/kernel/sched/sysctl/.gitignore
@@ -0,0 +1 @@
+proc_sched_rt01
diff --git a/testcases/kernel/syscalls/getdtablesize/Makefile b/testcases/kernel/sched/sysctl/Makefile
index 044619fb8..18896b6f2 100644
--- a/testcases/kernel/syscalls/getdtablesize/Makefile
+++ b/testcases/kernel/sched/sysctl/Makefile
@@ -1,5 +1,4 @@
# SPDX-License-Identifier: GPL-2.0-or-later
-# Copyright (c) International Business Machines Corp., 2001
top_srcdir ?= ../../../..
diff --git a/testcases/kernel/sched/sysctl/proc_sched_rt01.c b/testcases/kernel/sched/sysctl/proc_sched_rt01.c
new file mode 100644
index 000000000..7c1aaccd9
--- /dev/null
+++ b/testcases/kernel/sched/sysctl/proc_sched_rt01.c
@@ -0,0 +1,113 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (C) 2023 Cyril Hrubis <chrubis@suse.cz>
+ */
+
+/*\
+ * [Description]
+ *
+ * Sanity tests for the /proc/sys/kernel/sched_r* files.
+ *
+ * - The sched_rt_period_us range is 1 to INT_MAX
+ * try invalid values and check for EINVAL
+ *
+ * - The sched_rt_runtime_us range is -1 to INT_MAX
+ * try invalid values and check for EINVAL
+ *
+ * - The sched_rt_runtime_us must be less or equal to sched_rt_period_us
+ *
+ * - Reset sched_rr_timeslice_ms to default value by writing -1 and check that
+ * we get the default value on next read.
+ *
+ * This is a regression test for a commits:
+ *
+ * - c1fc6484e1fb ("sched/rt: sysctl_sched_rr_timeslice show default timeslice after reset")
+ * - 079be8fc6309 ("sched/rt: Disallow writing invalid values to sched_rt_period_us")
+ */
+
+#include <stdio.h>
+#include "tst_test.h"
+
+#define RT_PERIOD_US "/proc/sys/kernel/sched_rt_period_us"
+#define RT_RUNTIME_US "/proc/sys/kernel/sched_rt_runtime_us"
+#define RR_TIMESLICE_MS "/proc/sys/kernel/sched_rr_timeslice_ms"
+
+static int period_fd;
+static int runtime_fd;
+
+static void rr_timeslice_ms_reset(void)
+{
+ long timeslice_ms;
+
+ SAFE_FILE_PRINTF(RR_TIMESLICE_MS, "-1");
+ SAFE_FILE_SCANF(RR_TIMESLICE_MS, "%li", &timeslice_ms);
+
+ TST_EXP_EXPR(timeslice_ms > 0,
+ "timeslice_ms > 0 after reset to default");
+}
+
+static void rt_period_us_einval(void)
+{
+ TST_EXP_FAIL(write(period_fd, "0", 2), EINVAL,
+ "echo 0 > "RT_PERIOD_US);
+ TST_EXP_FAIL(write(period_fd, "-1", 2), EINVAL,
+ "echo -1 > "RT_PERIOD_US);
+}
+
+static void rt_runtime_us_einval(void)
+{
+ TST_EXP_FAIL(write(runtime_fd, "-2", 2), EINVAL,
+ "echo -2 > "RT_RUNTIME_US);
+}
+
+static void rt_runtime_us_le_period_us(void)
+{
+ int period_us;
+ char buf[32];
+
+ SAFE_FILE_SCANF(RT_PERIOD_US, "%i", &period_us);
+
+ sprintf(buf, "%i", period_us+1);
+
+ TST_EXP_FAIL(write(runtime_fd, buf, strlen(buf)), EINVAL,
+ "echo rt_period_us+1 > "RT_RUNTIME_US);
+}
+
+static void verify_sched_proc(void)
+{
+ rr_timeslice_ms_reset();
+ rt_period_us_einval();
+ rt_runtime_us_einval();
+ rt_runtime_us_le_period_us();
+}
+
+static void setup(void)
+{
+ period_fd = open(RT_PERIOD_US, O_RDWR);
+ runtime_fd = open(RT_RUNTIME_US, O_RDWR);
+}
+
+static void cleanup(void)
+{
+ if (period_fd > 0)
+ SAFE_CLOSE(period_fd);
+
+ if (runtime_fd > 0)
+ SAFE_CLOSE(runtime_fd);
+}
+
+static struct tst_test test = {
+ .needs_root = 1,
+ .setup = setup,
+ .cleanup = cleanup,
+ .test_all = verify_sched_proc,
+ .tags = (struct tst_tag []) {
+ {"linux-git", "c1fc6484e1fb"},
+ {"linux-git", "079be8fc6309"},
+ {}
+ },
+ .needs_kconfigs = (const char *[]) {
+ "CONFIG_SYSCTL",
+ NULL
+ },
+};
diff --git a/testcases/kernel/security/integrity/ima/tests/ima_tpm.sh b/testcases/kernel/security/integrity/ima/tests/ima_tpm.sh
index b675a20a1..2a28562e6 100755
--- a/testcases/kernel/security/integrity/ima/tests/ima_tpm.sh
+++ b/testcases/kernel/security/integrity/ima/tests/ima_tpm.sh
@@ -159,7 +159,8 @@ get_pcr10_aggregate()
$cmd > hash.txt 2>&1
ret=$?
elif [ $ret -ne 0 -a "$MISSING_EVMCTL" = 1 ]; then
- tst_brk TFAIL "evmctl failed $msg"
+ tst_res TFAIL "evmctl failed $msg"
+ return
fi
[ $ret -ne 0 ] && tst_res TWARN "evmctl failed, trying to continue $msg"
diff --git a/testcases/kernel/syscalls/accept/.gitignore b/testcases/kernel/syscalls/accept/.gitignore
index 5b1462699..f81d4bec9 100644
--- a/testcases/kernel/syscalls/accept/.gitignore
+++ b/testcases/kernel/syscalls/accept/.gitignore
@@ -1,2 +1,3 @@
/accept01
/accept02
+/accept03
diff --git a/testcases/kernel/syscalls/accept/accept01.c b/testcases/kernel/syscalls/accept/accept01.c
index 85af0f8af..e5db1dfec 100644
--- a/testcases/kernel/syscalls/accept/accept01.c
+++ b/testcases/kernel/syscalls/accept/accept01.c
@@ -26,7 +26,6 @@
struct sockaddr_in sin0, sin1, fsin1;
int invalid_socketfd = 400; /* anything that is not an open file */
-int devnull_fd;
int socket_fd;
int udp_fd;
@@ -46,10 +45,6 @@ static struct test_case {
"bad file descriptor"
},
{
- PF_INET, SOCK_STREAM, 0, &devnull_fd, (struct sockaddr *)&fsin1,
- sizeof(fsin1), ENOTSOCK, "fd is not socket"
- },
- {
PF_INET, SOCK_STREAM, 0, &socket_fd, (struct sockaddr *)3,
sizeof(fsin1), EINVAL, "invalid socket buffer"
},
@@ -73,8 +68,6 @@ static void test_setup(void)
sin0.sin_port = 0;
sin0.sin_addr.s_addr = INADDR_ANY;
- devnull_fd = SAFE_OPEN("/dev/null", O_WRONLY);
-
socket_fd = SAFE_SOCKET(PF_INET, SOCK_STREAM, 0);
SAFE_BIND(socket_fd, (struct sockaddr *)&sin0, sizeof(sin0));
@@ -88,7 +81,6 @@ static void test_setup(void)
static void test_cleanup(void)
{
- SAFE_CLOSE(devnull_fd);
SAFE_CLOSE(socket_fd);
SAFE_CLOSE(udp_fd);
}
diff --git a/testcases/kernel/syscalls/accept/accept03.c b/testcases/kernel/syscalls/accept/accept03.c
new file mode 100644
index 000000000..b85ec0d9b
--- /dev/null
+++ b/testcases/kernel/syscalls/accept/accept03.c
@@ -0,0 +1,60 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+/*
+ * Copyright (C) 2023-2024 Cyril Hrubis <chrubis@suse.cz>
+ */
+
+/*\
+ * [Description]
+ *
+ * Verify that accept() returns ENOTSOCK or EBADF for non-socket file
+ * descriptors. The EBADF is returned in the case that the file descriptor has
+ * not a file associated with it, which is for example in the case of O_PATH
+ * opened file.
+ */
+
+#include <sys/socket.h>
+#include <netinet/in.h>
+
+#include "tst_test.h"
+
+void check_accept(struct tst_fd *fd)
+{
+ struct sockaddr_in addr = {
+ .sin_family = AF_INET,
+ .sin_port = 0,
+ .sin_addr = {.s_addr = INADDR_ANY},
+ };
+
+ socklen_t size = sizeof(addr);
+
+ int exp_errno = ENOTSOCK;
+
+ switch (fd->type) {
+ case TST_FD_UNIX_SOCK:
+ case TST_FD_INET_SOCK:
+ return;
+ /*
+ * With these two we fail even before we get to the do_accept() because
+ * the fd does not have a struct file associated.
+ */
+ case TST_FD_OPEN_TREE:
+ case TST_FD_PATH:
+ exp_errno = EBADF;
+ default:
+ break;
+ }
+
+ TST_EXP_FAIL2(accept(fd->fd, (void*)&addr, &size),
+ exp_errno, "accept() on %s", tst_fd_desc(fd));
+}
+
+static void verify_accept(void)
+{
+ TST_FD_FOREACH(fd)
+ check_accept(&fd);
+}
+
+static struct tst_test test = {
+ .test_all = verify_accept,
+};
diff --git a/testcases/kernel/syscalls/acct/acct01.c b/testcases/kernel/syscalls/acct/acct01.c
index 52c4d41da..a05ed2ea9 100644
--- a/testcases/kernel/syscalls/acct/acct01.c
+++ b/testcases/kernel/syscalls/acct/acct01.c
@@ -1,14 +1,15 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/*
- * Copyright (c) International Business Machines Corp., 2002
+ * Copyright (c) International Business Machines Corp., 2002
+ * Copyright (c) Linux Test Project, 2003-2023
+ * 12/03/2002 Port to LTP robbiew@us.ibm.com
+ * 06/30/2001 Port to Linux nsharoff@us.ibm.com
*/
-/* 12/03/2002 Port to LTP robbiew@us.ibm.com */
-/* 06/30/2001 Port to Linux nsharoff@us.ibm.com */
-
/*\
- * [DOCUMENTATION]
+ * [Description]
+ *
* Verify that acct() returns proper errno on failure.
*/
diff --git a/testcases/kernel/syscalls/acct/acct02.c b/testcases/kernel/syscalls/acct/acct02.c
index b8eb1aad4..d3f3d9d04 100644
--- a/testcases/kernel/syscalls/acct/acct02.c
+++ b/testcases/kernel/syscalls/acct/acct02.c
@@ -1,10 +1,11 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/*
- * Copyright (c) SUSE LLC, 2019
- * Author: Christian Amann <camann@suse.com>
+ * Copyright (c) SUSE LLC, 2019
+ * Copyright (c) Linux Test Project, 2019-2023
+ * Author: Christian Amann <camann@suse.com>
*/
/*\
- * [DOCUMENTATION]
+ * [Description]
*
* This tests if the kernel writes correct data to the
* process accounting file.
@@ -19,8 +20,8 @@
* file, the contents get parsed until the correct entry is found, or EOF
* is reached.
*
- * This is also accidental regression test for:
- * 4d9570158b626 kernel/acct.c: fix the acct->needcheck check in check_free_space()
+ * This is also regression test for commit:
+ * 4d9570158b62 ("kernel/acct.c: fix the acct->needcheck check in check_free_space()")
*/
#include <sys/stat.h>
@@ -55,10 +56,7 @@ static union acct_union {
static int acct_version_is_3(void)
{
- struct tst_kconfig_var kconfig = {
- .id = ACCT_V3,
- .id_len = sizeof(ACCT_V3)-1,
- };
+ struct tst_kconfig_var kconfig = TST_KCONFIG_INIT(ACCT_V3);
tst_kconfig_read(&kconfig, 1);
diff --git a/testcases/kernel/syscalls/acct/acct02_helper.c b/testcases/kernel/syscalls/acct/acct02_helper.c
index 66017cb9b..0f55a6ae6 100644
--- a/testcases/kernel/syscalls/acct/acct02_helper.c
+++ b/testcases/kernel/syscalls/acct/acct02_helper.c
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/*
- * Copyright (c) SUSE LLC, 2019
- * Author: Christian Amann <camann@suse.com>
+ * Copyright (c) SUSE LLC, 2019
+ * Author: Christian Amann <camann@suse.com>
*/
/*
* Dummy program used in acct02
diff --git a/testcases/kernel/syscalls/adjtimex/adjtimex03.c b/testcases/kernel/syscalls/adjtimex/adjtimex03.c
index 7056973cc..9d34235e4 100644
--- a/testcases/kernel/syscalls/adjtimex/adjtimex03.c
+++ b/testcases/kernel/syscalls/adjtimex/adjtimex03.c
@@ -23,7 +23,7 @@
* To test that, Pass struct timex buffer filled with zero with
* some INVALID mode to the system call adjtimex. Passing an invalid
* parameters will not call do_adjtimex() and before that, it shall throw
- * an error(On error test shall not break). Therefore, none of the parameters
+ * an error (on error test shall not break). Therefore, none of the parameters
* will get initialized.
*
* On reading the last attribute tai of the struct, if the attribute is non-
diff --git a/testcases/kernel/syscalls/clock_adjtime/clock_adjtime.h b/testcases/kernel/syscalls/clock_adjtime/clock_adjtime.h
index 7577ab24d..63ebf5295 100644
--- a/testcases/kernel/syscalls/clock_adjtime/clock_adjtime.h
+++ b/testcases/kernel/syscalls/clock_adjtime/clock_adjtime.h
@@ -251,4 +251,5 @@ TIMEX_GET_SET_FIELD_TYPE(uint, uint);
TIMEX_GET_SET_FIELD_TYPE(long, long long);
#undef TIMEX_GET_SET_FIELD_TYPE
-#endif
+
+#endif /* CLOCK_ADJTIME_H__ */
diff --git a/testcases/kernel/syscalls/dup/dup06.c b/testcases/kernel/syscalls/dup/dup06.c
index e3f8070bf..cd4cb3513 100644
--- a/testcases/kernel/syscalls/dup/dup06.c
+++ b/testcases/kernel/syscalls/dup/dup06.c
@@ -1,41 +1,23 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
/*
- * Copyright (c) International Business Machines Corp., 2002
- * ported from SPIE, section2/iosuite/dup1.c, by Airong Zhang
- * Copyright (c) 2013 Cyril Hrubis <chrubis@suse.cz>
- *
- * 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
+ * Copyright (c) International Business Machines Corp., 2002
+ * Ported from SPIE, section2/iosuite/dup1.c, by Airong Zhang
+ * Copyright (c) 2013 Cyril Hrubis <chrubis@suse.cz>
+ * Copyright (c) Linux Test Project, 2003-2024
*/
-/*
- WHAT: Does dup return -1 on the 21st file?
- HOW: Create up to _NFILE (20) files and check for -1 return on the
- next attempt
- Should check NOFILE as well as _NFILE. 19-Jun-84 Dale.
-*/
+/*\
+ * [Description]
+ *
+ * Test for dup(2) syscall with max open file descriptors.
+ */
-#include <stdio.h>
-#include <fcntl.h>
-#include <errno.h>
-#include <unistd.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <sys/param.h>
-#include "test.h"
+#include <stdlib.h>
+#include "tst_test.h"
-char *TCID = "dup06";
-int TST_TOTAL = 1;
+static int *pfildes;
+static int minfd, maxfd, freefds;
+static char pfilname[40];
static int cnt_free_fds(int maxfd)
{
@@ -45,70 +27,53 @@ static int cnt_free_fds(int maxfd)
if (fcntl(maxfd, F_GETFD) == -1 && errno == EBADF)
freefds++;
- return (freefds);
+ return freefds;
}
-static void setup(void);
-static void cleanup(void);
-
-int main(int ac, char **av)
+static void setup(void)
{
- int *fildes, i;
- int min;
- int freefds;
- int lc;
- const char *pfilname = "dup06";
-
- tst_parse_opts(ac, av, NULL, NULL);
-
- setup();
-
- min = getdtablesize();
- freefds = cnt_free_fds(min);
- fildes = malloc((min + 5) * sizeof(int));
-
- for (i = 0; i < min + 5; i++)
- fildes[i] = 0;
-
- for (lc = 0; TEST_LOOPING(lc); lc++) {
- unlink(pfilname);
-
- if ((fildes[0] = creat(pfilname, 0666)) == -1) {
- tst_resm(TFAIL, "Cannot open first file");
- } else {
- for (i = 1; i < min + 5; i++) {
- if ((fildes[i] = dup(fildes[i - 1])) == -1)
- break;
- }
- if (i < freefds) {
- tst_resm(TFAIL, "Not enough files duped");
- } else if (i > freefds) {
- tst_resm(TFAIL, "Too many files duped");
- } else {
- tst_resm(TPASS, "Test passed.");
- }
- }
-
- unlink(pfilname);
-
- for (i = 0; i < min + 5; i++) {
- if (fildes[i] != 0 && fildes[i] != -1)
- close(fildes[i]);
-
- fildes[i] = 0;
- }
- }
-
- cleanup();
- tst_exit();
+ minfd = getdtablesize(); /* get number of files allowed open */
+ maxfd = minfd + 5;
+ freefds = cnt_free_fds(minfd);
+ pfildes = SAFE_MALLOC(maxfd * sizeof(int));
+ memset(pfildes, -1, maxfd * sizeof(int));
+ sprintf(pfilname, "./dup06.%d\n", getpid());
}
-static void setup(void)
+static void cleanup(void)
{
- tst_tmpdir();
+ if (pfildes != NULL)
+ free(pfildes);
}
-static void cleanup(void)
+static void run(void)
{
- tst_rmdir();
+ int i;
+
+ pfildes[0] = SAFE_CREAT(pfilname, 0666);
+ for (i = 1; i < maxfd; i++) {
+ pfildes[i] = dup(pfildes[i - 1]);
+ if (pfildes[i] == -1)
+ break;
+ }
+ if (i < freefds)
+ tst_res(TFAIL, "Not enough files duped");
+ else if (i > freefds)
+ tst_res(TFAIL, "Too many files duped");
+ else
+ tst_res(TPASS, "Test passed");
+
+ SAFE_UNLINK(pfilname);
+
+ for (i = 0; i < maxfd; i++) {
+ if (pfildes[i] != 0 && pfildes[i] != -1)
+ SAFE_CLOSE(pfildes[i]);
+ }
}
+
+static struct tst_test test = {
+ .needs_tmpdir = 1,
+ .test_all = run,
+ .setup = setup,
+ .cleanup = cleanup,
+};
diff --git a/testcases/kernel/syscalls/dup/dup07.c b/testcases/kernel/syscalls/dup/dup07.c
index a100f5d58..688ee1989 100644
--- a/testcases/kernel/syscalls/dup/dup07.c
+++ b/testcases/kernel/syscalls/dup/dup07.c
@@ -1,142 +1,57 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
/*
- *
- * Copyright (c) International Business Machines Corp., 2002
- * ported from SPIE, section2/iosuite/dup3.c, by Airong Zhang
- * Copyright (c) 2013 Cyril Hrubis <chrubis@suse.cz>
- *
- * 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
+ * Copyright (c) International Business Machines Corp., 2002
+ * Ported from SPIE, section2/iosuite/dup3.c, by Airong Zhang
+ * Copyright (c) 2013 Cyril Hrubis <chrubis@suse.cz>
+ * Copyright (c) Linux Test Project, 2006-2024
*/
-/*
- WHAT: Is the access mode the same for both file descriptors?
- 0: read only?
- 1: write only?
- 2: read/write?
- HOW: Creat a file with each access mode; dup each file descriptor;
- stat each file descriptor and compare mode of each pair
-*/
-
-#include <stdio.h>
-#include <fcntl.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include "test.h"
+/*\
+ * [Description]
+ *
+ * Verify that the file descriptor created by dup(2) syscall has the same
+ * access mode as the old one.
+ */
-char *TCID = "dup07";
-int TST_TOTAL = 3;
+#include "tst_test.h"
static const char *testfile = "dup07";
-static void setup(void);
-static void cleanup(void);
+static struct tcase {
+ char *mode_desc;
+ int mode;
+} tcases[] = {
+ {"read only", 0444},
+ {"write only", 0222},
+ {"read/write", 0666},
+};
-int main(int ac, char **av)
+static void run(unsigned int n)
{
- struct stat retbuf;
- struct stat dupbuf;
- int rdoret, wroret, rdwret;
- int duprdo, dupwro, duprdwr;
-
- int lc;
-
- tst_parse_opts(ac, av, NULL, NULL);
-
- setup();
-
- for (lc = 0; TEST_LOOPING(lc); lc++) {
-
- if ((rdoret = creat(testfile, 0444)) == -1) {
- tst_resm(TFAIL, "Unable to creat file '%s'", testfile);
- } else {
- if ((duprdo = dup(rdoret)) == -1) {
- tst_resm(TFAIL, "Unable to dup '%s'", testfile);
- } else {
- fstat(rdoret, &retbuf);
- fstat(duprdo, &dupbuf);
- if (retbuf.st_mode != dupbuf.st_mode) {
- tst_resm(TFAIL,
- "rdonly and dup do not match");
- } else {
- tst_resm(TPASS,
- "Passed in read mode.");
- }
- close(duprdo);
- }
- close(rdoret);
- }
-
- unlink(testfile);
-
- if ((wroret = creat(testfile, 0222)) == -1) {
- tst_resm(TFAIL, "Unable to creat file '%s'", testfile);
- } else {
- if ((dupwro = dup(wroret)) == -1) {
- tst_resm(TFAIL, "Unable to dup '%s'", testfile);
- } else {
- fstat(wroret, &retbuf);
- fstat(dupwro, &dupbuf);
- if (retbuf.st_mode != dupbuf.st_mode) {
- tst_resm(TFAIL,
- "wronly and dup do not match");
- } else {
- tst_resm(TPASS,
- "Passed in write mode.");
- }
- close(dupwro);
- }
- close(wroret);
-
- }
-
- unlink(testfile);
-
- if ((rdwret = creat(testfile, 0666)) == -1) {
- tst_resm(TFAIL, "Unable to creat file '%s'", testfile);
- } else {
- if ((duprdwr = dup(rdwret)) == -1) {
- tst_resm(TFAIL, "Unable to dup '%s'", testfile);
- } else {
- fstat(rdwret, &retbuf);
- fstat(duprdwr, &dupbuf);
- if (retbuf.st_mode != dupbuf.st_mode) {
- tst_resm(TFAIL,
- "rdwr and dup do not match");
- } else {
- tst_resm(TPASS,
- "Passed in read/write mode.");
- }
- close(duprdwr);
- }
- close(rdwret);
- }
-
- unlink(testfile);
+ int oldfd, dupfd;
+ struct stat oldbuf, dupbuf;
+ struct tcase *tc = &tcases[n];
+
+ oldfd = SAFE_CREAT(testfile, tc->mode);
+ dupfd = TST_EXP_FD_SILENT(dup(oldfd), "dup() %s file", tc->mode_desc);
+ if (TST_PASS) {
+ SAFE_FSTAT(oldfd, &oldbuf);
+ SAFE_FSTAT(dupfd, &dupbuf);
+
+ if (oldbuf.st_mode != dupbuf.st_mode)
+ tst_res(TFAIL, "%s and dup do not match", tc->mode_desc);
+ else
+ tst_res(TPASS, "Passed in %s mode", tc->mode_desc);
+
+ SAFE_CLOSE(dupfd);
}
- cleanup();
- tst_exit();
+ SAFE_CLOSE(oldfd);
+ SAFE_UNLINK(testfile);
}
-static void setup(void)
-{
- tst_tmpdir();
-}
-
-static void cleanup(void)
-{
- tst_rmdir();
-}
+static struct tst_test test = {
+ .needs_tmpdir = 1,
+ .test = run,
+ .tcnt = ARRAY_SIZE(tcases),
+};
diff --git a/testcases/kernel/syscalls/eventfd2/eventfd2.h b/testcases/kernel/syscalls/eventfd2/eventfd2.h
index 5350820b8..2333d1e53 100644
--- a/testcases/kernel/syscalls/eventfd2/eventfd2.h
+++ b/testcases/kernel/syscalls/eventfd2/eventfd2.h
@@ -3,6 +3,9 @@
* Copyright (C) 2023 SUSE LLC Andrea Cervesato <andrea.cervesato@suse.com>
*/
+#ifndef EVENTFD2_H__
+#define EVENTFD2_H__
+
#include "tst_test.h"
#include "lapi/syscalls.h"
@@ -16,3 +19,5 @@ static inline int eventfd2(unsigned int count, unsigned int flags)
return ret;
}
+
+#endif /* EVENTFD2_H__ */
diff --git a/testcases/kernel/syscalls/execve/execve04.c b/testcases/kernel/syscalls/execve/execve04.c
index 18e883ab3..3bac642e5 100644
--- a/testcases/kernel/syscalls/execve/execve04.c
+++ b/testcases/kernel/syscalls/execve/execve04.c
@@ -8,7 +8,9 @@
* 04/2008 Roy Lee <roylee@andestech.com>
*/
-/*
+/*\
+ * [Description]
+ *
* Attempt to execve(2) a file which is being opened by another process for
* writing fails with ETXTBSY.
*/
diff --git a/testcases/kernel/syscalls/execve/execve05.c b/testcases/kernel/syscalls/execve/execve05.c
index 87565d994..d87d7446d 100644
--- a/testcases/kernel/syscalls/execve/execve05.c
+++ b/testcases/kernel/syscalls/execve/execve05.c
@@ -1,32 +1,21 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/*
- * Copyright (c) 2018 Linux Test Project
+ * Copyright (c) 2001-2023 Linux Test Project
* Copyright (c) International Business Machines Corp., 2001
- *
+ * Copyright (c) 2008 Renaud Lottiaux <Renaud.Lottiaux@kerlabs.com>
* Ported to LTP: Wayne Boyer
- * 21/04/2008 Renaud Lottiaux (Renaud.Lottiaux@kerlabs.com)
*/
-/*
- * NAME
- * execve05.c
- *
- * DESCRIPTION
- * This testcase tests the basic functionality of the execve(2) system
- * call.
+/*\
+ * [Description]
*
- * ALGORITHM
- * This tests the functionality of the execve(2) system call by spawning
- * a few children, each of which would execute "execve_child" simultaneously,
- * and finally the parent ensures that they terminated correctly.
- *
- * USAGE
- * execve05 -i 5 -n 20
+ * This tests the functionality of the execve(2) system call by spawning
+ * a few children, each of which would execute "execve_child" simultaneously,
+ * and finally the parent ensures that they terminated correctly.
*/
-#ifndef _GNU_SOURCE
#define _GNU_SOURCE
-#endif
+
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
diff --git a/testcases/kernel/syscalls/exit_group/Makefile b/testcases/kernel/syscalls/exit_group/Makefile
index 1273a4e9c..adbac3c51 100644
--- a/testcases/kernel/syscalls/exit_group/Makefile
+++ b/testcases/kernel/syscalls/exit_group/Makefile
@@ -3,6 +3,8 @@
top_srcdir ?= ../../../..
+exit_group01: CFLAGS+=-pthread
+
include $(top_srcdir)/include/mk/testcases.mk
include $(top_srcdir)/include/mk/generic_leaf_target.mk
diff --git a/testcases/kernel/syscalls/exit_group/exit_group01.c b/testcases/kernel/syscalls/exit_group/exit_group01.c
index 5bf5b0218..6407a20e8 100644
--- a/testcases/kernel/syscalls/exit_group/exit_group01.c
+++ b/testcases/kernel/syscalls/exit_group/exit_group01.c
@@ -1,68 +1,127 @@
-/******************************************************************************
- * Copyright (c) Crackerjack Project., 2007 *
- * Ported to LTP by Manas Kumar Nayak <maknayak@in.ibm.com> *
- * Copyright (C) 2015 Cyril Hrubis <chrubis@suse.cz> *
- * *
- * 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) Crackerjack Project., 2007
+ * Ported to LTP by Manas Kumar Nayak <maknayak@in.ibm.com>
+ * Copyright (c) 2015 Linux Test Project
+ * Copyright (C) 2015 Cyril Hrubis <chrubis@suse.cz>
+ * Copyright (C) 2023 SUSE LLC Andrea Cervesato <andrea.cervesato@suse.com>
+ */
-#include <stdio.h>
-#include <errno.h>
-#include <linux/unistd.h>
-#include <sys/wait.h>
+/*\
+ * [Description]
+ *
+ * This test checks if exit_group() correctly ends a spawned child and all its
+ * running threads.
+ */
-#include "test.h"
-#include "safe_macros.h"
+#include <sched.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include "tst_test.h"
#include "lapi/syscalls.h"
+#include "tst_safe_pthread.h"
+
+static int cpu_count;
-char *TCID = "exit_group01";
-int testno;
-int TST_TOTAL = 1;
+static struct worker_data {
+ pid_t tid;
+ int counter;
+} *workers_data;
-static void verify_exit_group(void)
+static void *worker(void *arg)
{
- pid_t cpid, w;
- int status;
+ struct worker_data *data;
- cpid = fork();
- if (cpid == -1)
- tst_brkm(TFAIL | TERRNO, NULL, "fork failed");
+ data = (struct worker_data *)arg;
+ data->tid = tst_gettid();
- if (cpid == 0) {
- TEST(tst_syscall(__NR_exit_group, 4));
- } else {
- w = SAFE_WAIT(NULL, &status);
-
- if (WIFEXITED(status) && (WEXITSTATUS(status) == 4)) {
- tst_resm(TPASS, "exit_group() succeeded");
- } else {
- tst_resm(TFAIL | TERRNO,
- "exit_group() failed (wait status = %d)", w);
+ while (1) {
+ tst_atomic_inc(&data->counter);
+ sched_yield();
+ }
+
+ return arg;
+}
+
+static void spawn_threads(void)
+{
+ pthread_t threads[cpu_count];
+
+ for (int i = 0; i < cpu_count; i++)
+ SAFE_PTHREAD_CREATE(&threads[i], NULL, worker, (void *)(workers_data + i));
+}
+
+static void check_counters(void)
+{
+ struct worker_data data_copy[cpu_count];
+
+ memset(data_copy, 0, sizeof(struct worker_data) * cpu_count);
+ memcpy(data_copy, workers_data, sizeof(struct worker_data) * cpu_count);
+
+ tst_res(TINFO, "Checking if threads are still running");
+ usleep(100000);
+
+ struct worker_data *old_data;
+ struct worker_data *new_data;
+
+ for (int i = 0; i < cpu_count; i++) {
+ old_data = data_copy + i;
+ new_data = workers_data + i;
+
+ if (old_data->counter != new_data->counter) {
+ tst_res(TFAIL, "Counter value has changed for thread[%d]", i);
+ return;
}
}
+
+ tst_res(TINFO, "Threads counters value didn't change");
}
-int main(int ac, char **av)
+static void run(void)
{
- int lc;
+ pid_t pid;
+ int status;
+
+ pid = SAFE_FORK();
+ if (!pid) {
+ spawn_threads();
+
+ TEST(tst_syscall(__NR_exit_group, 4));
+ if (TST_RET == -1)
+ tst_brk(TBROK | TERRNO, "exit_group() error");
+
+ return;
+ }
- tst_parse_opts(ac, av, NULL, NULL);
+ SAFE_WAITPID(pid, &status, 0);
- for (lc = 0; TEST_LOOPING(lc); lc++)
- verify_exit_group();
+ TST_EXP_EXPR(WIFEXITED(status) && WEXITSTATUS(status) == 4,
+ "exit_group() succeeded");
- tst_exit();
+ check_counters();
}
+
+static void setup(void)
+{
+ cpu_count = MAX(2, tst_ncpus());
+
+ workers_data = SAFE_MMAP(
+ NULL,
+ sizeof(struct worker_data) * cpu_count,
+ PROT_READ | PROT_WRITE,
+ MAP_SHARED | MAP_ANONYMOUS,
+ -1, 0);
+}
+
+static void cleanup(void)
+{
+ SAFE_MUNMAP(workers_data, sizeof(struct worker_data) * cpu_count);
+}
+
+static struct tst_test test = {
+ .setup = setup,
+ .cleanup = cleanup,
+ .test_all = run,
+ .forks_child = 1,
+ .needs_checkpoints = 1,
+};
diff --git a/testcases/kernel/syscalls/fallocate/fallocate06.c b/testcases/kernel/syscalls/fallocate/fallocate06.c
index 124fb7eae..24f98e271 100644
--- a/testcases/kernel/syscalls/fallocate/fallocate06.c
+++ b/testcases/kernel/syscalls/fallocate/fallocate06.c
@@ -260,6 +260,8 @@ static struct tst_test test = {
.test = run,
.tcnt = ARRAY_SIZE(testcase_list),
.needs_root = 1,
+ .dev_min_size = 1024,
+ .max_runtime = 120,
.mount_device = 1,
.mntpoint = MNTPOINT,
.all_filesystems = 1,
diff --git a/testcases/kernel/syscalls/fanotify/fanotify.h b/testcases/kernel/syscalls/fanotify/fanotify.h
index 75a081dc9..e0d178bcc 100644
--- a/testcases/kernel/syscalls/fanotify/fanotify.h
+++ b/testcases/kernel/syscalls/fanotify/fanotify.h
@@ -68,19 +68,14 @@ static inline int safe_fanotify_mark(const char *file, const int lineno,
#ifdef HAVE_NAME_TO_HANDLE_AT
-#ifndef MAX_HANDLE_SZ
-#define MAX_HANDLE_SZ 128
-#endif
-
-#ifndef AT_HANDLE_FID
-#define AT_HANDLE_FID 0x200
-#endif
-
/*
* Helper function used to obtain fsid and file_handle for a given path.
* Used by test files correlated to FAN_REPORT_FID functionality.
+ *
+ * Returns 0 if normal NFS file handles are supported.
+ * Returns AT_HANDLE_FID, if only non-decodeable file handles are supported.
*/
-static inline void fanotify_get_fid(const char *path, __kernel_fsid_t *fsid,
+static inline int fanotify_get_fid(const char *path, __kernel_fsid_t *fsid,
struct file_handle *handle)
{
int mount_id;
@@ -93,6 +88,11 @@ static inline void fanotify_get_fid(const char *path, __kernel_fsid_t *fsid,
if (name_to_handle_at(AT_FDCWD, path, handle, &mount_id, 0) == -1) {
if (errno == EOPNOTSUPP) {
+ /* Try to request non-decodeable fid instead */
+ if (name_to_handle_at(AT_FDCWD, path, handle, &mount_id,
+ AT_HANDLE_FID) == 0)
+ return AT_HANDLE_FID;
+
tst_brk(TCONF,
"filesystem %s does not support file handles",
tst_device->fs_type);
@@ -100,30 +100,30 @@ static inline void fanotify_get_fid(const char *path, __kernel_fsid_t *fsid,
tst_brk(TBROK | TERRNO,
"name_to_handle_at(AT_FDCWD, %s, ...) failed", path);
}
+ return 0;
}
-#ifndef FILEID_INVALID
-#define FILEID_INVALID 0xff
-#endif
-
struct fanotify_fid_t {
__kernel_fsid_t fsid;
struct file_handle handle;
char buf[MAX_HANDLE_SZ];
};
-static inline void fanotify_save_fid(const char *path,
+static inline int fanotify_save_fid(const char *path,
struct fanotify_fid_t *fid)
{
int *fh = (int *)(fid->handle.f_handle);
+ int ret;
fh[0] = fh[1] = fh[2] = 0;
fid->handle.handle_bytes = MAX_HANDLE_SZ;
- fanotify_get_fid(path, &fid->fsid, &fid->handle);
+ ret = fanotify_get_fid(path, &fid->fsid, &fid->handle);
tst_res(TINFO,
"fid(%s) = %x.%x.%x.%x.%x...", path, fid->fsid.val[0],
fid->fsid.val[1], fh[0], fh[1], fh[2]);
+
+ return ret;
}
#endif /* HAVE_NAME_TO_HANDLE_AT */
@@ -133,13 +133,14 @@ static inline void fanotify_save_fid(const char *path,
#define INIT_FANOTIFY_MARK_TYPE(t) \
{ FAN_MARK_ ## t, "FAN_MARK_" #t }
-static inline void require_fanotify_access_permissions_supported_by_kernel(void)
+static inline void require_fanotify_access_permissions_supported_on_fs(
+ const char *fname)
{
int fd;
fd = SAFE_FANOTIFY_INIT(FAN_CLASS_CONTENT, O_RDONLY);
- if (fanotify_mark(fd, FAN_MARK_ADD, FAN_ACCESS_PERM, AT_FDCWD, ".") < 0) {
+ if (fanotify_mark(fd, FAN_MARK_ADD, FAN_ACCESS_PERM, AT_FDCWD, fname) < 0) {
if (errno == EINVAL) {
tst_brk(TCONF | TERRNO,
"CONFIG_FANOTIFY_ACCESS_PERMISSIONS not configured in kernel?");
@@ -152,21 +153,42 @@ static inline void require_fanotify_access_permissions_supported_by_kernel(void)
SAFE_CLOSE(fd);
}
-static inline int fanotify_events_supported_by_kernel(uint64_t mask,
- unsigned int init_flags,
- unsigned int mark_flags)
+/*
+ * @return 0: fanotify flags supported both in kernel and on tested filesystem
+ * @return -1: @init_flags not supported in kernel
+ * @return -2: @mark_flags not supported on tested filesystem (tested if @fname is not NULL)
+ * @return -3: @mark_flags not supported on overlayfs (tested if @fname == OVL_MNT)
+ */
+static inline int fanotify_flags_supported_on_fs(unsigned int init_flags,
+ unsigned int mark_flags,
+ uint64_t event_flags,
+ const char *fname)
{
int fd;
int rval = 0;
- fd = SAFE_FANOTIFY_INIT(init_flags, O_RDONLY);
+ fd = fanotify_init(init_flags, O_RDONLY);
- if (fanotify_mark(fd, FAN_MARK_ADD | mark_flags, mask, AT_FDCWD, ".") < 0) {
- if (errno == EINVAL) {
- rval = -1;
- } else {
+ if (fd < 0) {
+ if (errno == ENOSYS)
+ tst_brk(TCONF, "fanotify not configured in kernel");
+ if (errno != EINVAL)
+ tst_brk(TBROK | TERRNO,
+ "fanotify_init(%x, O_RDONLY) failed",
+ init_flags);
+ return -1;
+ }
+
+ if (fname && fanotify_mark(fd, FAN_MARK_ADD | mark_flags, event_flags, AT_FDCWD, fname) < 0) {
+ if (errno == ENODEV || errno == EOPNOTSUPP || errno == EXDEV) {
+ rval = strcmp(fname, OVL_MNT) ? -2 : -3;
+ } else if (errno != EINVAL) {
tst_brk(TBROK | TERRNO,
- "fanotify_mark (%d, FAN_MARK_ADD, ..., AT_FDCWD, \".\") failed", fd);
+ "fanotify_mark (%d, FAN_MARK_ADD | %x, %llx, AT_FDCWD, %s) failed",
+ fd, mark_flags, (unsigned long long)event_flags,
+ fname);
+ } else {
+ rval = -1;
}
}
@@ -175,95 +197,85 @@ static inline int fanotify_events_supported_by_kernel(uint64_t mask,
return rval;
}
-/*
- * @return 0: fanotify supported both in kernel and on tested filesystem
- * @return -1: @flags not supported in kernel
- * @return -2: @flags not supported on tested filesystem (tested if @fname is not NULL)
- */
static inline int fanotify_init_flags_supported_on_fs(unsigned int flags, const char *fname)
{
- int fd;
- int rval = 0;
-
- fd = fanotify_init(flags, O_RDONLY);
+ return fanotify_flags_supported_on_fs(flags, FAN_MARK_INODE, FAN_ACCESS, fname);
+}
- if (fd < 0) {
- if (errno == ENOSYS)
- tst_brk(TCONF, "fanotify not configured in kernel");
+static inline int fanotify_mark_supported_on_fs(uint64_t flag, const char *fname)
+{
+ return fanotify_flags_supported_on_fs(FAN_CLASS_NOTIF, flag, FAN_ACCESS, fname);
+}
- if (errno == EINVAL)
- return -1;
+#define TST_FANOTIFY_INIT_KNOWN_FLAGS \
+ (FAN_REPORT_DFID_NAME_TARGET | FAN_REPORT_TID | FAN_REPORT_PIDFD | \
+ FAN_CLASS_NOTIF | FAN_CLASS_CONTENT | FAN_CLASS_PRE_CONTENT)
- tst_brk(TBROK | TERRNO, "fanotify_init() failed");
+/*
+ * Check support of given init flags one by one and return those which are
+ * supported.
+ */
+static inline unsigned int fanotify_get_supported_init_flags(unsigned int flags,
+ const char *fname)
+{
+ unsigned int i, flg, arg, ret = 0;
+ static const struct { unsigned int flag, deps; } deplist[] = {
+ {FAN_REPORT_NAME, FAN_REPORT_DIR_FID},
+ {FAN_REPORT_TARGET_FID, FAN_REPORT_DFID_NAME_FID},
+ {0, 0}
+ };
+
+ if (flags & ~TST_FANOTIFY_INIT_KNOWN_FLAGS) {
+ tst_brk(TBROK, "fanotify_init() feature check called with unknown flags %x, please update flag dependency table if needed",
+ flags & ~TST_FANOTIFY_INIT_KNOWN_FLAGS);
}
- if (fname && fanotify_mark(fd, FAN_MARK_ADD, FAN_ACCESS, AT_FDCWD, fname) < 0) {
- if (errno == ENODEV || errno == EOPNOTSUPP || errno == EXDEV) {
- rval = -2;
- } else {
- tst_brk(TBROK | TERRNO,
- "fanotify_mark (%d, FAN_MARK_ADD, ..., AT_FDCWD, %s) failed",
- fd, fname);
- }
- }
+ for (flg = 1; flg; flg <<= 1) {
+ if (!(flags & flg))
+ continue;
- SAFE_CLOSE(fd);
+ arg = flg;
- return rval;
-}
+ for (i = 0; deplist[i].flag; i++) {
+ if (deplist[i].flag == flg) {
+ arg |= deplist[i].deps;
+ break;
+ }
+ }
-static inline int fanotify_init_flags_supported_by_kernel(unsigned int flags)
-{
- return fanotify_init_flags_supported_on_fs(flags, NULL);
+ if (!fanotify_init_flags_supported_on_fs(arg, fname))
+ ret |= flg;
+ }
+
+ return ret;
}
typedef void (*tst_res_func_t)(const char *file, const int lineno,
int ttype, const char *fmt, ...);
-static inline void fanotify_init_flags_err_msg(const char *flags_str,
+static inline void fanotify_flags_err_msg(const char *flags_str,
const char *file, const int lineno, tst_res_func_t res_func, int fail)
{
if (fail == -1)
res_func(file, lineno, TCONF,
"%s not supported in kernel?", flags_str);
- if (fail == -2)
+ if (fail == -2 || fail == -3)
res_func(file, lineno, TCONF,
- "%s not supported on %s filesystem",
- flags_str, tst_device->fs_type);
+ "%s not supported on %s%s filesystem",
+ flags_str, fail == -3 ? "overlayfs over " : "",
+ tst_device->fs_type);
}
#define FANOTIFY_INIT_FLAGS_ERR_MSG(flags, fail) \
- fanotify_init_flags_err_msg(#flags, __FILE__, __LINE__, tst_res_, (fail))
+ fanotify_flags_err_msg(#flags, __FILE__, __LINE__, tst_res_, (fail))
+
+#define FANOTIFY_MARK_FLAGS_ERR_MSG(mark, fail) \
+ fanotify_flags_err_msg((mark)->name, __FILE__, __LINE__, tst_res_, (fail))
#define REQUIRE_FANOTIFY_INIT_FLAGS_SUPPORTED_ON_FS(flags, fname) \
- fanotify_init_flags_err_msg(#flags, __FILE__, __LINE__, tst_brk_, \
+ fanotify_flags_err_msg(#flags, __FILE__, __LINE__, tst_brk_, \
fanotify_init_flags_supported_on_fs(flags, fname))
-#define REQUIRE_FANOTIFY_INIT_FLAGS_SUPPORTED_BY_KERNEL(flags) \
- fanotify_init_flags_err_msg(#flags, __FILE__, __LINE__, tst_brk_, \
- fanotify_init_flags_supported_by_kernel(flags))
-
-static inline int fanotify_mark_supported_by_kernel(uint64_t flag)
-{
- int fd;
- int rval = 0;
-
- fd = SAFE_FANOTIFY_INIT(FAN_CLASS_CONTENT, O_RDONLY);
-
- if (fanotify_mark(fd, FAN_MARK_ADD | flag, FAN_ACCESS, AT_FDCWD, ".") < 0) {
- if (errno == EINVAL) {
- rval = -1;
- } else {
- tst_brk(TBROK | TERRNO,
- "fanotify_mark (%d, FAN_MARK_ADD, ..., FAN_ACCESS, AT_FDCWD, \".\") failed", fd);
- }
- }
-
- SAFE_CLOSE(fd);
-
- return rval;
-}
-
static inline int fanotify_handle_supported_by_kernel(int flag)
{
/*
@@ -277,21 +289,21 @@ static inline int fanotify_handle_supported_by_kernel(int flag)
return 0;
}
-#define REQUIRE_MARK_TYPE_SUPPORTED_BY_KERNEL(mark_type) \
- fanotify_init_flags_err_msg(#mark_type, __FILE__, __LINE__, tst_brk_, \
- fanotify_mark_supported_by_kernel(mark_type))
+#define REQUIRE_MARK_TYPE_SUPPORTED_ON_FS(mark_type, fname) \
+ fanotify_flags_err_msg(#mark_type, __FILE__, __LINE__, tst_brk_, \
+ fanotify_mark_supported_on_fs(mark_type, fname))
#define REQUIRE_HANDLE_TYPE_SUPPORTED_BY_KERNEL(handle_type) \
- fanotify_init_flags_err_msg(#handle_type, __FILE__, __LINE__, tst_brk_, \
- fanotify_handle_supported_by_kernel(handle_type))
+ fanotify_flags_err_msg(#handle_type, __FILE__, __LINE__, tst_brk_, \
+ fanotify_handle_supported_by_kernel(handle_type))
#define REQUIRE_FANOTIFY_EVENTS_SUPPORTED_ON_FS(init_flags, mark_type, mask, fname) do { \
if (mark_type) \
- REQUIRE_MARK_TYPE_SUPPORTED_BY_KERNEL(mark_type); \
+ REQUIRE_MARK_TYPE_SUPPORTED_ON_FS(mark_type, fname); \
if (init_flags) \
REQUIRE_FANOTIFY_INIT_FLAGS_SUPPORTED_ON_FS(init_flags, fname); \
- fanotify_init_flags_err_msg(#mask, __FILE__, __LINE__, tst_brk_, \
- fanotify_events_supported_by_kernel(mask, init_flags, mark_type)); \
+ fanotify_flags_err_msg(#mask, __FILE__, __LINE__, tst_brk_, \
+ fanotify_flags_supported_on_fs(init_flags, mark_type, mask, fname)); \
} while (0)
static inline struct fanotify_event_info_header *get_event_info(
diff --git a/testcases/kernel/syscalls/fanotify/fanotify01.c b/testcases/kernel/syscalls/fanotify/fanotify01.c
index 3538335c9..e4398f236 100644
--- a/testcases/kernel/syscalls/fanotify/fanotify01.c
+++ b/testcases/kernel/syscalls/fanotify/fanotify01.c
@@ -76,6 +76,7 @@ static char fname[BUF_SIZE];
static char buf[BUF_SIZE];
static int fd_notify;
static int fan_report_fid_unsupported;
+static int mount_mark_fid_unsupported;
static int filesystem_mark_unsupported;
static unsigned long long event_set[EVENT_MAX];
@@ -88,16 +89,22 @@ static void test_fanotify(unsigned int n)
struct fanotify_mark_type *mark = &tc->mark;
int fd, ret, len, i = 0, test_num = 0;
int tst_count = 0;
+ int report_fid = (tc->init_flags & FAN_REPORT_FID);
tst_res(TINFO, "Test #%d: %s", n, tc->tname);
- if (fan_report_fid_unsupported && (tc->init_flags & FAN_REPORT_FID)) {
+ if (fan_report_fid_unsupported && report_fid) {
FANOTIFY_INIT_FLAGS_ERR_MSG(FAN_REPORT_FID, fan_report_fid_unsupported);
return;
}
if (filesystem_mark_unsupported && mark->flag == FAN_MARK_FILESYSTEM) {
- tst_res(TCONF, "FAN_MARK_FILESYSTEM not supported in kernel?");
+ FANOTIFY_MARK_FLAGS_ERR_MSG(mark, filesystem_mark_unsupported);
+ return;
+ }
+
+ if (mount_mark_fid_unsupported && report_fid && mark->flag != FAN_MARK_INODE) {
+ FANOTIFY_MARK_FLAGS_ERR_MSG(mark, mount_mark_fid_unsupported);
return;
}
@@ -341,7 +348,10 @@ static void setup(void)
SAFE_FILE_PRINTF(fname, "1");
fan_report_fid_unsupported = fanotify_init_flags_supported_on_fs(FAN_REPORT_FID, fname);
- filesystem_mark_unsupported = fanotify_mark_supported_by_kernel(FAN_MARK_FILESYSTEM);
+ filesystem_mark_unsupported = fanotify_mark_supported_on_fs(FAN_MARK_FILESYSTEM, fname);
+ mount_mark_fid_unsupported = fanotify_flags_supported_on_fs(FAN_REPORT_FID,
+ FAN_MARK_MOUNT,
+ FAN_OPEN, fname);
}
static void cleanup(void)
diff --git a/testcases/kernel/syscalls/fanotify/fanotify03.c b/testcases/kernel/syscalls/fanotify/fanotify03.c
index 0bd61587a..028da742c 100644
--- a/testcases/kernel/syscalls/fanotify/fanotify03.c
+++ b/testcases/kernel/syscalls/fanotify/fanotify03.c
@@ -320,14 +320,14 @@ static void test_fanotify(unsigned int n)
static void setup(void)
{
- require_fanotify_access_permissions_supported_by_kernel();
-
- filesystem_mark_unsupported = fanotify_mark_supported_by_kernel(FAN_MARK_FILESYSTEM);
- exec_events_unsupported = fanotify_events_supported_by_kernel(FAN_OPEN_EXEC_PERM,
- FAN_CLASS_CONTENT, 0);
sprintf(fname, MOUNT_PATH"/fname_%d", getpid());
SAFE_FILE_PRINTF(fname, "1");
+ require_fanotify_access_permissions_supported_on_fs(fname);
+ filesystem_mark_unsupported = fanotify_mark_supported_on_fs(FAN_MARK_FILESYSTEM, fname);
+ exec_events_unsupported = fanotify_flags_supported_on_fs(FAN_CLASS_CONTENT,
+ 0, FAN_OPEN_EXEC_PERM, fname);
+
SAFE_CP(TEST_APP, FILE_EXEC_PATH);
}
diff --git a/testcases/kernel/syscalls/fanotify/fanotify07.c b/testcases/kernel/syscalls/fanotify/fanotify07.c
index 396c8490e..34aa810c7 100644
--- a/testcases/kernel/syscalls/fanotify/fanotify07.c
+++ b/testcases/kernel/syscalls/fanotify/fanotify07.c
@@ -189,10 +189,9 @@ static void test_fanotify(void)
static void setup(void)
{
- require_fanotify_access_permissions_supported_by_kernel();
-
sprintf(fname, "fname_%d", getpid());
SAFE_FILE_PRINTF(fname, "%s", fname);
+ require_fanotify_access_permissions_supported_on_fs(fname);
}
static void cleanup(void)
diff --git a/testcases/kernel/syscalls/fanotify/fanotify09.c b/testcases/kernel/syscalls/fanotify/fanotify09.c
index 3f2db4709..f61c4e45a 100644
--- a/testcases/kernel/syscalls/fanotify/fanotify09.c
+++ b/testcases/kernel/syscalls/fanotify/fanotify09.c
@@ -480,9 +480,11 @@ static void test_fanotify(unsigned int n)
static void setup(void)
{
- fan_report_dfid_unsupported = fanotify_init_flags_supported_on_fs(FAN_REPORT_DFID_NAME,
- MOUNT_PATH);
- ignore_mark_unsupported = fanotify_mark_supported_by_kernel(FAN_MARK_IGNORE_SURV);
+ fan_report_dfid_unsupported = fanotify_flags_supported_on_fs(FAN_REPORT_DFID_NAME,
+ FAN_MARK_MOUNT,
+ FAN_OPEN, MOUNT_PATH);
+ ignore_mark_unsupported = fanotify_mark_supported_on_fs(FAN_MARK_IGNORE_SURV,
+ MOUNT_PATH);
SAFE_MKDIR(MOUNT_NAME, 0755);
SAFE_MOUNT(MOUNT_PATH, MOUNT_NAME, "none", MS_BIND, NULL);
diff --git a/testcases/kernel/syscalls/fanotify/fanotify10.c b/testcases/kernel/syscalls/fanotify/fanotify10.c
index d0e9194e7..6c89ca1d0 100644
--- a/testcases/kernel/syscalls/fanotify/fanotify10.c
+++ b/testcases/kernel/syscalls/fanotify/fanotify10.c
@@ -874,13 +874,17 @@ static void setup(void)
{
int i;
- exec_events_unsupported = fanotify_events_supported_by_kernel(FAN_OPEN_EXEC,
- FAN_CLASS_CONTENT, 0);
- filesystem_mark_unsupported = fanotify_mark_supported_by_kernel(FAN_MARK_FILESYSTEM);
- evictable_mark_unsupported = fanotify_mark_supported_by_kernel(FAN_MARK_EVICTABLE);
- ignore_mark_unsupported = fanotify_mark_supported_by_kernel(FAN_MARK_IGNORE_SURV);
- fan_report_dfid_unsupported = fanotify_init_flags_supported_on_fs(FAN_REPORT_DFID_NAME,
- MOUNT_PATH);
+ exec_events_unsupported = fanotify_flags_supported_on_fs(FAN_CLASS_CONTENT,
+ 0, FAN_OPEN_EXEC, MOUNT_PATH);
+ filesystem_mark_unsupported = fanotify_mark_supported_on_fs(FAN_MARK_FILESYSTEM,
+ MOUNT_PATH);
+ evictable_mark_unsupported = fanotify_mark_supported_on_fs(FAN_MARK_EVICTABLE,
+ MOUNT_PATH);
+ ignore_mark_unsupported = fanotify_mark_supported_on_fs(FAN_MARK_IGNORE_SURV,
+ MOUNT_PATH);
+ fan_report_dfid_unsupported = fanotify_flags_supported_on_fs(FAN_REPORT_DFID_NAME,
+ FAN_MARK_MOUNT,
+ FAN_OPEN, MOUNT_PATH);
if (fan_report_dfid_unsupported) {
FANOTIFY_INIT_FLAGS_ERR_MSG(FAN_REPORT_DFID_NAME, fan_report_dfid_unsupported);
/* Limit tests to legacy priority classes */
diff --git a/testcases/kernel/syscalls/fanotify/fanotify11.c b/testcases/kernel/syscalls/fanotify/fanotify11.c
index 03583d84b..ce46913b1 100644
--- a/testcases/kernel/syscalls/fanotify/fanotify11.c
+++ b/testcases/kernel/syscalls/fanotify/fanotify11.c
@@ -94,7 +94,7 @@ static void test01(unsigned int i)
static void setup(void)
{
- fan_report_tid_unsupported = fanotify_init_flags_supported_by_kernel(FAN_REPORT_TID);
+ fan_report_tid_unsupported = fanotify_init_flags_supported_on_fs(FAN_REPORT_TID, ".");
}
static struct tst_test test = {
diff --git a/testcases/kernel/syscalls/fanotify/fanotify12.c b/testcases/kernel/syscalls/fanotify/fanotify12.c
index 7f8e97b17..42ba08800 100644
--- a/testcases/kernel/syscalls/fanotify/fanotify12.c
+++ b/testcases/kernel/syscalls/fanotify/fanotify12.c
@@ -222,11 +222,10 @@ cleanup:
static void do_setup(void)
{
- exec_events_unsupported = fanotify_events_supported_by_kernel(FAN_OPEN_EXEC,
- FAN_CLASS_NOTIF, 0);
-
sprintf(fname, "fname_%d", getpid());
SAFE_FILE_PRINTF(fname, "1");
+ exec_events_unsupported = fanotify_flags_supported_on_fs(FAN_CLASS_NOTIF,
+ 0, FAN_OPEN_EXEC, fname);
}
static void do_cleanup(void)
diff --git a/testcases/kernel/syscalls/fanotify/fanotify13.c b/testcases/kernel/syscalls/fanotify/fanotify13.c
index a25a360fd..6086a81fc 100644
--- a/testcases/kernel/syscalls/fanotify/fanotify13.c
+++ b/testcases/kernel/syscalls/fanotify/fanotify13.c
@@ -91,8 +91,10 @@ static struct test_case_t {
static int ovl_mounted;
static int bind_mounted;
+static int ovl_bind_mounted;
static int nofid_fd;
static int fanotify_fd;
+static int at_handle_fid;
static int filesystem_mark_unsupported;
static char events_buf[BUF_SIZE];
static struct event_t event_set[EVENT_MAX];
@@ -113,8 +115,10 @@ static void get_object_stats(void)
{
unsigned int i;
- for (i = 0; i < ARRAY_SIZE(objects); i++)
- fanotify_save_fid(objects[i].path, &objects[i].fid);
+ for (i = 0; i < ARRAY_SIZE(objects); i++) {
+ at_handle_fid |=
+ fanotify_save_fid(objects[i].path, &objects[i].fid);
+ }
}
static int setup_marks(unsigned int fd, struct test_case_t *tc)
@@ -154,8 +158,8 @@ static void do_test(unsigned int number)
return;
}
- if (filesystem_mark_unsupported && mark->flag & FAN_MARK_FILESYSTEM) {
- tst_res(TCONF, "FAN_MARK_FILESYSTEM not supported in kernel?");
+ if (filesystem_mark_unsupported && mark->flag != FAN_MARK_INODE) {
+ FANOTIFY_MARK_FLAGS_ERR_MSG(mark, filesystem_mark_unsupported);
return;
}
@@ -168,10 +172,10 @@ static void do_test(unsigned int number)
if (setup_marks(fanotify_fd, tc) != 0)
goto out;
- /* Variant #1: watching upper fs - open files on overlayfs */
- if (tst_variant == 1) {
+ /* Watching base fs - open files on overlayfs */
+ if (tst_variant && !ovl_bind_mounted) {
if (mark->flag & FAN_MARK_MOUNT) {
- tst_res(TCONF, "overlayfs upper fs cannot be watched with mount mark");
+ tst_res(TCONF, "overlayfs base fs cannot be watched with mount mark");
goto out;
}
SAFE_MOUNT(OVL_MNT, MOUNT_PATH, "none", MS_BIND, NULL);
@@ -191,7 +195,7 @@ static void do_test(unsigned int number)
SAFE_CLOSE(fds[i]);
}
- if (tst_variant == 1)
+ if (tst_variant && !ovl_bind_mounted)
SAFE_UMOUNT(MOUNT_PATH);
/* Read events from event queue */
@@ -286,19 +290,27 @@ static void do_setup(void)
/*
* Bind mount to either base fs or to overlayfs over base fs:
* Variant #0: watch base fs - open files on base fs
- * Variant #1: watch upper fs - open files on overlayfs
+ * Variant #1: watch lower fs - open lower files on overlayfs
+ * Variant #2: watch upper fs - open upper files on overlayfs
+ * Variant #3: watch overlayfs - open lower files on overlayfs
+ * Variant #4: watch overlayfs - open upper files on overlayfs
*
- * Variant #1 tests a bug whose fix bc2473c90fca ("ovl: enable fsnotify
+ * Variants 1,2 test a bug whose fix bc2473c90fca ("ovl: enable fsnotify
* events on underlying real files") in kernel 6.5 is not likely to be
* backported to older kernels.
* To avoid waiting for events that won't arrive when testing old kernels,
- * require that kernel supports encoding fid with new flag AT_HADNLE_FID,
+ * require that kernel supports encoding fid with new flag AT_HANDLE_FID,
* also merged to 6.5 and not likely to be backported to older kernels.
+ * Variants 3,4 test overlayfs watch with FAN_REPORT_FID, which also
+ * requires kernel with support for AT_HANDLE_FID.
*/
if (tst_variant) {
REQUIRE_HANDLE_TYPE_SUPPORTED_BY_KERNEL(AT_HANDLE_FID);
ovl_mounted = TST_MOUNT_OVERLAY();
- mnt = OVL_UPPER;
+ if (!ovl_mounted)
+ return;
+
+ mnt = tst_variant & 1 ? OVL_LOWER : OVL_UPPER;
} else {
mnt = OVL_BASE_MNTPOINT;
@@ -308,13 +320,21 @@ static void do_setup(void)
SAFE_MOUNT(mnt, MOUNT_PATH, "none", MS_BIND, NULL);
bind_mounted = 1;
- filesystem_mark_unsupported = fanotify_mark_supported_by_kernel(FAN_MARK_FILESYSTEM);
-
nofid_fd = SAFE_FANOTIFY_INIT(FAN_CLASS_NOTIF, O_RDONLY);
- /* Create file and directory objects for testing */
+ /* Create file and directory objects for testing on base fs */
create_objects();
+ if (tst_variant > 2) {
+ /* Setup watches on overlayfs */
+ SAFE_MOUNT(OVL_MNT, MOUNT_PATH, "none", MS_BIND, NULL);
+ ovl_bind_mounted = 1;
+ }
+
+ filesystem_mark_unsupported =
+ fanotify_flags_supported_on_fs(FAN_REPORT_FID, FAN_MARK_FILESYSTEM, FAN_OPEN,
+ ovl_bind_mounted ? OVL_MNT : MOUNT_PATH);
+
/*
* Create a mark on first inode without FAN_REPORT_FID, to test
* uninitialized connector->fsid cache. This mark remains for all test
@@ -329,9 +349,12 @@ static void do_setup(void)
static void do_cleanup(void)
{
- SAFE_CLOSE(nofid_fd);
+ if (nofid_fd > 0)
+ SAFE_CLOSE(nofid_fd);
if (fanotify_fd > 0)
SAFE_CLOSE(fanotify_fd);
+ if (ovl_bind_mounted)
+ SAFE_UMOUNT(MOUNT_PATH);
if (bind_mounted) {
SAFE_UMOUNT(MOUNT_PATH);
SAFE_RMDIR(MOUNT_PATH);
@@ -343,7 +366,7 @@ static void do_cleanup(void)
static struct tst_test test = {
.test = do_test,
.tcnt = ARRAY_SIZE(test_cases),
- .test_variants = 2,
+ .test_variants = 5,
.setup = do_setup,
.cleanup = do_cleanup,
.needs_root = 1,
diff --git a/testcases/kernel/syscalls/fanotify/fanotify14.c b/testcases/kernel/syscalls/fanotify/fanotify14.c
index 4596511f0..0b0da89ca 100644
--- a/testcases/kernel/syscalls/fanotify/fanotify14.c
+++ b/testcases/kernel/syscalls/fanotify/fanotify14.c
@@ -45,8 +45,9 @@
static int pipes[2] = {-1, -1};
static int fanotify_fd;
-static int fan_report_target_fid_unsupported;
static int ignore_mark_unsupported;
+static int filesystem_mark_unsupported;
+static unsigned int supported_init_flags;
struct test_case_flags_t {
unsigned long long flags;
@@ -246,9 +247,8 @@ static void do_test(unsigned int number)
tst_res(TINFO, "Test case %d: fanotify_init(%s, O_RDONLY)", number,
tc->init.desc);
- if (fan_report_target_fid_unsupported && tc->init.flags & FAN_REPORT_TARGET_FID) {
- FANOTIFY_INIT_FLAGS_ERR_MSG(FAN_REPORT_TARGET_FID,
- fan_report_target_fid_unsupported);
+ if (tc->init.flags & ~supported_init_flags) {
+ tst_res(TCONF, "Unsupported init flags");
return;
}
@@ -300,7 +300,7 @@ static void do_test(unsigned int number)
"Adding an inode mark on directory did not fail with "
"ENOTDIR error as on non-dir inode");
- if (!(tc->mark.flags & FAN_MARK_ONLYDIR)) {
+ if (!(tc->mark.flags & FAN_MARK_ONLYDIR) && !filesystem_mark_unsupported) {
SAFE_FANOTIFY_MARK(fanotify_fd, FAN_MARK_ADD | tc->mark.flags |
FAN_MARK_FILESYSTEM, tc->mask.flags,
AT_FDCWD, FILE1);
@@ -317,12 +317,18 @@ out:
static void do_setup(void)
{
+ unsigned int all_init_flags = FAN_REPORT_DFID_NAME_TARGET |
+ FAN_CLASS_NOTIF | FAN_CLASS_CONTENT | FAN_CLASS_PRE_CONTENT;
+
/* Require FAN_REPORT_FID support for all tests to simplify per test case requirements */
REQUIRE_FANOTIFY_INIT_FLAGS_SUPPORTED_ON_FS(FAN_REPORT_FID, MNTPOINT);
+ supported_init_flags = fanotify_get_supported_init_flags(all_init_flags, MNTPOINT);
- fan_report_target_fid_unsupported =
- fanotify_init_flags_supported_on_fs(FAN_REPORT_DFID_NAME_TARGET, MNTPOINT);
- ignore_mark_unsupported = fanotify_mark_supported_by_kernel(FAN_MARK_IGNORE_SURV);
+ ignore_mark_unsupported = fanotify_mark_supported_on_fs(FAN_MARK_IGNORE_SURV,
+ MNTPOINT);
+ filesystem_mark_unsupported =
+ fanotify_flags_supported_on_fs(FAN_REPORT_FID, FAN_MARK_FILESYSTEM, FAN_OPEN,
+ MNTPOINT);
/* Create temporary test file to place marks on */
SAFE_FILE_PRINTF(FILE1, "0");
diff --git a/testcases/kernel/syscalls/fanotify/fanotify15.c b/testcases/kernel/syscalls/fanotify/fanotify15.c
index 6109d32cd..bacf05049 100644
--- a/testcases/kernel/syscalls/fanotify/fanotify15.c
+++ b/testcases/kernel/syscalls/fanotify/fanotify15.c
@@ -52,6 +52,7 @@ struct event_t {
};
static int fanotify_fd;
+static int filesystem_mark_unsupported;
static char events_buf[EVENT_BUF_LEN];
static struct event_t event_set[EVENT_MAX];
@@ -85,6 +86,11 @@ static void do_test(unsigned int number)
tst_res(TINFO, "Test #%d: %s", number, tc->tname);
+ if (filesystem_mark_unsupported && mark->flag != FAN_MARK_INODE) {
+ FANOTIFY_MARK_FLAGS_ERR_MSG(mark, filesystem_mark_unsupported);
+ return;
+ }
+
SAFE_FANOTIFY_MARK(fanotify_fd, FAN_MARK_ADD | mark->flag, tc->mask |
FAN_CREATE | FAN_DELETE | FAN_MOVE |
FAN_MODIFY | FAN_ONDIR,
@@ -274,6 +280,10 @@ static void do_setup(void)
{
SAFE_MKDIR(TEST_DIR, 0755);
REQUIRE_FANOTIFY_INIT_FLAGS_SUPPORTED_ON_FS(FAN_REPORT_FID, TEST_DIR);
+ filesystem_mark_unsupported =
+ fanotify_flags_supported_on_fs(FAN_REPORT_FID, FAN_MARK_FILESYSTEM, FAN_OPEN,
+ MOUNT_POINT);
+
fanotify_fd = SAFE_FANOTIFY_INIT(FAN_REPORT_FID, O_RDONLY);
}
diff --git a/testcases/kernel/syscalls/fanotify/fanotify16.c b/testcases/kernel/syscalls/fanotify/fanotify16.c
index d45270a9a..6ab360984 100644
--- a/testcases/kernel/syscalls/fanotify/fanotify16.c
+++ b/testcases/kernel/syscalls/fanotify/fanotify16.c
@@ -70,6 +70,7 @@ static char event_buf[EVENT_BUF_LEN];
#define TEMP_DIR MOUNT_PATH "/temp_dir"
static int fan_report_target_fid_unsupported;
+static int filesystem_mark_unsupported;
static int rename_events_unsupported;
static struct test_case_t {
@@ -281,6 +282,16 @@ static void do_test(unsigned int number)
return;
}
+ if (filesystem_mark_unsupported) {
+ if (sub_mark && sub_mark->flag != FAN_MARK_INODE)
+ mark = sub_mark;
+
+ if (mark->flag != FAN_MARK_INODE) {
+ FANOTIFY_MARK_FLAGS_ERR_MSG(mark, filesystem_mark_unsupported);
+ return;
+ }
+ }
+
fd_notify = SAFE_FANOTIFY_INIT(group->flag, 0);
/*
@@ -328,7 +339,15 @@ static void do_test(unsigned int number)
tst_count++;
/* Generate modify events "on child" */
- fd = SAFE_CREAT(fname1, 0755);
+
+ /*
+ * Split SAFE_CREAT() into explicit SAFE_MKNOD() and SAFE_OPEN(),
+ * because with atomic open (e.g. fuse), SAFE_CREAT() generates
+ * FAN_OPEN before FAN_CREATE and it is inconsistent with the order
+ * of events expectated from other filesystems.
+ */
+ SAFE_MKNOD(fname1, S_IFREG | 0644, 0);
+ fd = SAFE_OPEN(fname1, O_WRONLY);
/* Save the file fid */
fanotify_save_fid(fname1, &file_fid);
@@ -765,8 +784,12 @@ static void setup(void)
REQUIRE_FANOTIFY_INIT_FLAGS_SUPPORTED_ON_FS(FAN_REPORT_DIR_FID, MOUNT_PATH);
fan_report_target_fid_unsupported =
fanotify_init_flags_supported_on_fs(FAN_REPORT_DFID_NAME_TARGET, MOUNT_PATH);
+ filesystem_mark_unsupported =
+ fanotify_flags_supported_on_fs(FAN_REPORT_FID, FAN_MARK_FILESYSTEM, FAN_OPEN,
+ MOUNT_PATH);
rename_events_unsupported =
- fanotify_events_supported_by_kernel(FAN_RENAME, FAN_REPORT_DFID_NAME, 0);
+ fanotify_flags_supported_on_fs(FAN_REPORT_DFID_NAME, 0,
+ FAN_RENAME, MOUNT_PATH);
SAFE_MKDIR(TEMP_DIR, 0755);
sprintf(dname1, "%s/%s", MOUNT_PATH, DIR_NAME1);
diff --git a/testcases/kernel/syscalls/fanotify/fanotify20.c b/testcases/kernel/syscalls/fanotify/fanotify20.c
index 71310fb86..1d249ac9c 100644
--- a/testcases/kernel/syscalls/fanotify/fanotify20.c
+++ b/testcases/kernel/syscalls/fanotify/fanotify20.c
@@ -50,7 +50,8 @@ static void do_setup(void)
* An explicit check for FAN_REPORT_PIDFD is performed early on in the
* test initialization as it's a prerequisite for all test cases.
*/
- REQUIRE_FANOTIFY_INIT_FLAGS_SUPPORTED_BY_KERNEL(FAN_REPORT_PIDFD);
+ REQUIRE_FANOTIFY_INIT_FLAGS_SUPPORTED_ON_FS(FAN_REPORT_PIDFD,
+ MOUNT_PATH);
}
static void do_test(unsigned int i)
diff --git a/testcases/kernel/syscalls/fanotify/fanotify21.c b/testcases/kernel/syscalls/fanotify/fanotify21.c
index 2b7202b8a..90a797fce 100644
--- a/testcases/kernel/syscalls/fanotify/fanotify21.c
+++ b/testcases/kernel/syscalls/fanotify/fanotify21.c
@@ -119,7 +119,8 @@ static void do_setup(void)
* on in the test initialization as it's a prerequisite for
* all test cases.
*/
- REQUIRE_FANOTIFY_INIT_FLAGS_SUPPORTED_BY_KERNEL(FAN_REPORT_PIDFD);
+ REQUIRE_FANOTIFY_INIT_FLAGS_SUPPORTED_ON_FS(FAN_REPORT_PIDFD,
+ TEST_FILE);
fanotify_fd = SAFE_FANOTIFY_INIT(FAN_REPORT_PIDFD, O_RDONLY);
SAFE_FANOTIFY_MARK(fanotify_fd, FAN_MARK_ADD, FAN_OPEN, AT_FDCWD,
diff --git a/testcases/kernel/syscalls/fanotify/fanotify23.c b/testcases/kernel/syscalls/fanotify/fanotify23.c
index fb812c51e..5a03503e9 100644
--- a/testcases/kernel/syscalls/fanotify/fanotify23.c
+++ b/testcases/kernel/syscalls/fanotify/fanotify23.c
@@ -230,7 +230,7 @@ static void setup(void)
{
SAFE_TOUCH(TEST_FILE, 0666, NULL);
- REQUIRE_MARK_TYPE_SUPPORTED_BY_KERNEL(FAN_MARK_EVICTABLE);
+ REQUIRE_MARK_TYPE_SUPPORTED_ON_FS(FAN_MARK_EVICTABLE, ".");
REQUIRE_FANOTIFY_EVENTS_SUPPORTED_ON_FS(FAN_CLASS_NOTIF|FAN_REPORT_FID,
FAN_MARK_FILESYSTEM,
FAN_ATTRIB, ".");
diff --git a/testcases/kernel/syscalls/fchmodat/.gitignore b/testcases/kernel/syscalls/fchmodat/.gitignore
index a9508bc5a..09d5c47d5 100644
--- a/testcases/kernel/syscalls/fchmodat/.gitignore
+++ b/testcases/kernel/syscalls/fchmodat/.gitignore
@@ -1 +1,2 @@
/fchmodat01
+/fchmodat02
diff --git a/testcases/kernel/syscalls/fchmodat/fchmodat01.c b/testcases/kernel/syscalls/fchmodat/fchmodat01.c
index 3deff0ebe..bf3812738 100644
--- a/testcases/kernel/syscalls/fchmodat/fchmodat01.c
+++ b/testcases/kernel/syscalls/fchmodat/fchmodat01.c
@@ -1,99 +1,82 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Copyright (c) International Business Machines Corp., 2006
- *
+ * Copyright (c) Linux Test Project, 2003-2023
* 08/28/2006 AUTHOR: Yi Yang <yyangcdl@cn.ibm.com>
*/
/*\
* [Description]
*
- * This test case will verify basic function of fchmodat.
+ * Check the basic functionality of the fchmodat() system call.
+ *
+ * - fchmodat() passes if dir_fd is file descriptor to the directory
+ * where the file is located and pathname is relative path of the file.
+ * - fchmodat() passes if pathname is absolute, then dirfd is ignored.
+ * - fchmodat() passes if dir_fd is AT_FDCWD and pathname is interpreted
+ * relative to the current working directory of the calling process.
*/
-#define _GNU_SOURCE
-
-#include <unistd.h>
-#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include "tst_test.h"
-#include "lapi/syscalls.h"
-#ifndef AT_FDCWD
-#define AT_FDCWD -100
-#endif
+#define TESTDIR "fchmodatdir"
+#define TESTFILE "fchmodatfile"
+#define FILEPATH "fchmodatdir/fchmodatfile"
-static char pathname[256];
-static char testfile[256];
-static char testfile2[256];
-static char testfile3[256];
+static int dir_fd, file_fd;
+static int atcwd_fd = AT_FDCWD;
+static char *abs_path;
+static char *test_file;
+static char *file_path;
static struct tcase {
- int exp_errno;
- char *exp_errval;
+ int *fd;
+ char **filenames;
+ char **full_path;
} tcases[] = {
- { 0, NULL},
- { 0, NULL},
- { ENOTDIR, "ENOTDIR"},
- { EBADF, "EBADF"},
- { 0, NULL},
- { 0, NULL},
+ {&dir_fd, &test_file, &file_path},
+ {&file_fd, &abs_path, &abs_path},
+ {&atcwd_fd, &file_path, &file_path},
};
-static int fds[ARRAY_SIZE(tcases)];
-static char *filenames[ARRAY_SIZE(tcases)];
static void verify_fchmodat(unsigned int i)
{
struct tcase *tc = &tcases[i];
+ struct stat st;
- if (tc->exp_errno == 0)
- TST_EXP_PASS(tst_syscall(__NR_fchmodat, fds[i], filenames[i], 0600),
- "fchmodat() returned the expected errno %d: %s",
- TST_ERR, strerror(TST_ERR));
+ TST_EXP_PASS(fchmodat(*tc->fd, *tc->filenames, 0600, 0),
+ "fchmodat(%d, %s, 0600, 0)",
+ *tc->fd, *tc->filenames);
+
+ SAFE_LSTAT(*tc->full_path, &st);
+
+ if ((st.st_mode & ~S_IFREG) == 0600)
+ tst_res(TPASS, "File permission changed correctly");
else
- TST_EXP_FAIL(tst_syscall(__NR_fchmodat, fds[i], filenames[i], 0600),
- tc->exp_errno,
- "fchmodat() returned the expected errno %d: %s",
- TST_ERR, strerror(TST_ERR));
+ tst_res(TFAIL, "File permission not changed correctly");
}
static void setup(void)
{
- /* Initialize test dir and file names */
- char *abs_path = tst_get_tmpdir();
- int p = getpid();
-
- sprintf(pathname, "fchmodattestdir%d", p);
- sprintf(testfile, "fchmodattest%d.txt", p);
- sprintf(testfile2, "%s/fchmodattest%d.txt", abs_path, p);
- sprintf(testfile3, "fchmodattestdir%d/fchmodattest%d.txt", p, p);
+ char *tmpdir_path = tst_get_tmpdir();
- free(abs_path);
+ abs_path = tst_aprintf("%s/%s", tmpdir_path, FILEPATH);
+ free(tmpdir_path);
- SAFE_MKDIR(pathname, 0700);
-
- fds[0] = SAFE_OPEN(pathname, O_DIRECTORY);
- fds[1] = fds[4] = fds[0];
-
- SAFE_FILE_PRINTF(testfile, "%s", testfile);
- SAFE_FILE_PRINTF(testfile2, "%s", testfile2);
-
- fds[2] = SAFE_OPEN(testfile3, O_CREAT | O_RDWR, 0600);
- fds[3] = 100;
- fds[5] = AT_FDCWD;
-
- filenames[0] = filenames[2] = filenames[3] = filenames[4] = testfile;
- filenames[1] = testfile2;
- filenames[5] = testfile3;
+ SAFE_MKDIR(TESTDIR, 0700);
+ dir_fd = SAFE_OPEN(TESTDIR, O_DIRECTORY);
+ file_fd = SAFE_OPEN(FILEPATH, O_CREAT | O_RDWR, 0600);
}
static void cleanup(void)
{
- if (fds[0] > 0)
- close(fds[0]);
- if (fds[2] > 0)
- close(fds[2]);
+ if (dir_fd > -1)
+ SAFE_CLOSE(dir_fd);
+
+ if (file_fd > -1)
+ SAFE_CLOSE(file_fd);
}
static struct tst_test test = {
@@ -101,5 +84,10 @@ static struct tst_test test = {
.test = verify_fchmodat,
.setup = setup,
.cleanup = cleanup,
+ .bufs = (struct tst_buffers []) {
+ {&test_file, .str = TESTFILE},
+ {&file_path, .str = FILEPATH},
+ {},
+ },
.needs_tmpdir = 1,
};
diff --git a/testcases/kernel/syscalls/fchmodat/fchmodat02.c b/testcases/kernel/syscalls/fchmodat/fchmodat02.c
new file mode 100644
index 000000000..117865a8f
--- /dev/null
+++ b/testcases/kernel/syscalls/fchmodat/fchmodat02.c
@@ -0,0 +1,87 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (c) International Business Machines Corp., 2006
+ * Copyright (c) Linux Test Project, 2003-2023
+ * Author: Yi Yang <yyangcdl@cn.ibm.com>
+ */
+
+/*\
+ * [Description]
+ *
+ * Tests basic error handling of the fchmodat() syscall.
+ *
+ * - fchmodat() fails with ENOTDIR if dir_fd is file descriptor
+ * to the file and pathname is relative path of the file.
+ * - fchmodat() fails with EBADF if dir_fd is invalid.
+ * - fchmodat() fails with EFAULT if pathname points outside
+ * the accessible address space.
+ * - fchmodat() fails with ENAMETOOLONG if path is too long.
+ * - fchmodat() fails with ENOENT if pathname does not exist.
+ * - fchmodat() fails with EINVAL if flag is invalid.
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include "tst_test.h"
+
+#define TESTFILE "fchmodatfile"
+
+static int file_fd;
+static int bad_fd = -1;
+static char path[PATH_MAX + 2];
+static char *long_path = path;
+static int fd_atcwd = AT_FDCWD;
+static char *bad_path;
+static char *test_path;
+static char *empty_path;
+
+static struct tcase {
+ int *fd;
+ char **filenames;
+ int flag;
+ int exp_errno;
+ const char *desc;
+} tcases[] = {
+ {&file_fd, &test_path, 0, ENOTDIR, "fd pointing to file"},
+ {&bad_fd, &test_path, 0, EBADF, "invalid fd"},
+ {&file_fd, &bad_path, 0, EFAULT, "invalid address"},
+ {&file_fd, &long_path, 0, ENAMETOOLONG, "pathname too long"},
+ {&file_fd, &empty_path, 0, ENOENT, "path is empty"},
+ {&fd_atcwd, &test_path, -1, EINVAL, "invalid flag"},
+};
+
+static void verify_fchmodat(unsigned int i)
+{
+ struct tcase *tc = &tcases[i];
+
+ TST_EXP_FAIL(fchmodat(*tc->fd, *tc->filenames, 0600, tc->flag),
+ tc->exp_errno, "fchmodat() with %s", tc->desc);
+}
+
+static void setup(void)
+{
+ file_fd = SAFE_OPEN(TESTFILE, O_CREAT | O_RDWR, 0600);
+
+ bad_path = tst_get_bad_addr(NULL);
+
+ memset(path, 'a', PATH_MAX + 2);
+}
+
+static void cleanup(void)
+{
+ if (file_fd > -1)
+ SAFE_CLOSE(file_fd);
+}
+
+static struct tst_test test = {
+ .test = verify_fchmodat,
+ .tcnt = ARRAY_SIZE(tcases),
+ .setup = setup,
+ .cleanup = cleanup,
+ .bufs = (struct tst_buffers []) {
+ {&test_path, .str = TESTFILE},
+ {&empty_path, .str = ""},
+ {},
+ },
+ .needs_tmpdir = 1,
+};
diff --git a/testcases/kernel/syscalls/fchownat/fchownat.h b/testcases/kernel/syscalls/fchownat/fchownat.h
deleted file mode 100644
index 927cf929a..000000000
--- a/testcases/kernel/syscalls/fchownat/fchownat.h
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright (c) 2014 Fujitsu Ltd.
- *
- * 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 Library 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- *
- */
-
-#ifndef FCHOWNAT_H
-#define FCHOWNAT_H
-
-#include <sys/types.h>
-#include "config.h"
-#include "lapi/syscalls.h"
-
-
-#if !defined(HAVE_FCHOWNAT)
-static inline int fchownat(int dirfd, const char *filename, uid_t owner,
- gid_t group, int flags)
-{
- return tst_syscall(__NR_fchownat, dirfd, filename, owner, group, flags);
-}
-#endif
-
-
-#endif /* FCHOWNAT_H */
diff --git a/testcases/kernel/syscalls/fchownat/fchownat01.c b/testcases/kernel/syscalls/fchownat/fchownat01.c
index 3b29f1e75..7771c111a 100644
--- a/testcases/kernel/syscalls/fchownat/fchownat01.c
+++ b/testcases/kernel/syscalls/fchownat/fchownat01.c
@@ -34,7 +34,6 @@
#include "test.h"
#include "safe_macros.h"
-#include "fchownat.h"
#include "lapi/fcntl.h"
#define TESTFILE "testfile"
diff --git a/testcases/kernel/syscalls/fchownat/fchownat02.c b/testcases/kernel/syscalls/fchownat/fchownat02.c
index c39b0a919..6dd1e024e 100644
--- a/testcases/kernel/syscalls/fchownat/fchownat02.c
+++ b/testcases/kernel/syscalls/fchownat/fchownat02.c
@@ -31,7 +31,6 @@
#include <signal.h>
#include "test.h"
#include "safe_macros.h"
-#include "fchownat.h"
#include "lapi/fcntl.h"
#define TESTFILE "testfile"
diff --git a/testcases/kernel/syscalls/fcntl/Makefile b/testcases/kernel/syscalls/fcntl/Makefile
index df663a50a..aac774111 100644
--- a/testcases/kernel/syscalls/fcntl/Makefile
+++ b/testcases/kernel/syscalls/fcntl/Makefile
@@ -17,6 +17,6 @@ include $(abs_srcdir)/../utils/newer_64.mk
%_64: CPPFLAGS += -D_FILE_OFFSET_BITS=64
-CPPFLAGS += -D_GNU_SOURCE
+CPPFLAGS += -D_GNU_SOURCE -D_LARGEFILE64_SOURCE
include $(top_srcdir)/include/mk/generic_leaf_target.mk
diff --git a/testcases/kernel/syscalls/fork/.gitignore b/testcases/kernel/syscalls/fork/.gitignore
index b817e9c05..acab5f768 100644
--- a/testcases/kernel/syscalls/fork/.gitignore
+++ b/testcases/kernel/syscalls/fork/.gitignore
@@ -2,12 +2,10 @@
/fork03
/fork04
/fork05
-/fork06
/fork07
/fork08
/fork09
/fork10
-/fork11
-/fork12
/fork13
/fork14
+/fork_procs
diff --git a/testcases/kernel/syscalls/fork/fork04.c b/testcases/kernel/syscalls/fork/fork04.c
index 5e5e42c4e..1a515987e 100644
--- a/testcases/kernel/syscalls/fork/fork04.c
+++ b/testcases/kernel/syscalls/fork/fork04.c
@@ -1,328 +1,96 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2000 Silicon Graphics, Inc. All Rights Reserved.
+ * Copyright (c) Linux Test Project, 2001-2023
+ * Copyright (C) 2023 SUSE LLC Andrea Cervesato <andrea.cervesato@suse.com>
+ */
+
+/*\
+ *[Description]
*
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of version 2 of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- *
- * Further, this software is distributed without any warranty that it is
- * free of the rightful claim of any third person regarding infringement
- * or the like. Any license provided herein, whether implied or
- * otherwise, applies only to this software file. Patent licenses, if
- * any, provided herein do not apply to combinations of this program with
- * other software, or any other product whatsoever.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
- * Mountain View, CA 94043, or:
- *
- * http://www.sgi.com
- *
- * For further information regarding this notice, see:
- *
- * http://oss.sgi.com/projects/GenInfo/NoticeExplan/
- *
- *
- * OS Test - Silicon Graphics, Inc.
- * TEST IDENTIFIER : fork04
- * TEST TITLE : Child inheritance of Environment Variables after fork()
- * PARENT DOCUMENT : frktds01
- * TEST CASE TOTAL : 3
- * WALL CLOCK TIME : 1
- * CPU TYPES : ALL
- * AUTHOR : Kathy Olmsted
- * CO-PILOT : Steve Shaw
- * DATE STARTED : 06/17/92
- * INITIAL RELEASE : UNICOS 7.0
- *
- * TEST CASES
- * Test these environment variables correctly inherited by child:
- * 1. TERM
- * 2. NoTSetzWq
- * 3. TESTPROG
- *
- * INPUT SPECIFICATIONS
- * The standard options for system call tests are accepted.
- * (See the parse_opts(3) man page).
- *
- * DURATION
- * Terminates - with frequency and infinite modes.
- *
- * SIGNALS
- * Uses SIGUSR1 to pause before test if option set.
- * (See the parse_opts(3) man page).
- *
- * ENVIRONMENTAL NEEDS
- * No run-time environmental needs.
- *
- * DETAILED DESCRIPTION
- *
- * Setup:
- * Setup signal handling.
- * Make and change to a temporary directory.
- * Pause for SIGUSR1 if option specified.
- * Add TESTPROG variable to the environment
- *
- * Test:
- * Loop if the proper options are given.
- * fork()
- * Check return code, if system call failed (return=-1)
- * Log the errno
- * CHILD:
- * open a temp file
- * Determine environment values and write to file
- * close file containing test values.
- * exit.
- * PARENT:
- * Wait for child to exit.
- * Verify exit status
- * Open file containing test values.
- * For each test case:
- * Read the value from the file.
- * Determine and report PASS/FAIL result.
- *
- * Cleanup:
- * Print errno log and/or timing stats if options given
- * Remove the temporary directory and exit.
+ * This test verifies that parent process shares environ variables with the
+ * child and that child doesn't change parent's environ variables.
*/
#include <stdlib.h>
-#include <sys/types.h>
-#include <sys/wait.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <string.h>
-#include <sys/param.h>
-#include <signal.h>
-#include <errno.h>
-#include "test.h"
-#include "safe_macros.h"
-
-char *TCID = "fork04";
-
-#define KIDEXIT 42
-#define MAX_LINE_LENGTH 256
-#define OUTPUT_FILE "env.out"
-#define ENV_NOT_SET "getenv() does not find variable set"
+#include "tst_test.h"
-/* list of environment variables to test */
-char *environ_list[] = { "TERM", "NoTSetzWq", "TESTPROG" };
+#define ENV_KEY "LTP_FORK04"
+#define ENV_VAL0 "PASS"
+#define ENV_VAL1 "FAIL"
-#define NUMBER_OF_ENVIRON (sizeof(environ_list)/sizeof(char *))
-int TST_TOTAL = NUMBER_OF_ENVIRON;
-
-static void cleanup(void)
+static void run_child(void)
{
- tst_rmdir();
-}
+ const char *val;
-static void setup(void)
-{
+ val = getenv(ENV_KEY);
+ if (!val)
+ tst_brk(TBROK, "Can't find %s environ variable", ENV_KEY);
- tst_sig(FORK, DEF_HANDLER, cleanup);
- TEST_PAUSE;
- tst_tmpdir();
+ TST_EXP_EXPR(strcmp(ENV_VAL0, val) == 0,
+ "%s environ variable has been inherited by the child",
+ ENV_KEY)
- /* add a variable to the environment */
- putenv("TESTPROG=FRKTCS04");
-}
+ tst_res(TINFO, "Unset %s environ variable inside child", ENV_KEY);
-static void child_environment(void)
-{
-
- int fildes;
- int index;
- char msg[MAX_LINE_LENGTH];
- char *var;
+ if (unsetenv(ENV_KEY) == -1)
+ tst_brk(TBROK, "Can't unset %s environ variable", ENV_KEY);
- fildes = creat(OUTPUT_FILE, 0700);
+ TST_CHECKPOINT_WAKE_AND_WAIT(0);
- for (index = 0; index < (int)NUMBER_OF_ENVIRON; index++) {
- memset(msg, 0, MAX_LINE_LENGTH);
+ tst_res(TINFO, "Set %s=%s environ variable inside child", ENV_KEY, ENV_VAL1);
- var = getenv(environ_list[index]);
- if (var == NULL)
- (void)sprintf(msg, "%s:%s", environ_list[index],
- ENV_NOT_SET);
- else
- (void)sprintf(msg, "%s:%s", environ_list[index], var);
- /* includes extra null chars */
- write(fildes, msg, sizeof(msg));
- }
+ SAFE_SETENV(ENV_KEY, ENV_VAL1, 0);
- close(fildes);
+ TST_CHECKPOINT_WAKE(0);
}
-/*
- * Compare parent env string to child's string.
- * Each string is in the format: <env var>:<value>
- */
-static int cmp_env_strings(char *pstring, char *cstring)
+static void run(void)
{
- char *penv, *cenv, *pvalue, *cvalue;
+ const char *val;
- /*
- * Break pstring into env and value
- */
- penv = pstring;
- pvalue = strchr(pstring, ':');
- if (pvalue == NULL) {
- tst_resm(TBROK,
- "internal error - parent's env string not in correct format:'%s'",
- pstring);
- return -1;
- } else {
- *pvalue = '\0';
- pvalue++;
- if (*pvalue == '\0') {
- tst_resm(TBROK,
- "internal error - missing parent's env value");
- return -1;
- }
- }
+ tst_res(TINFO,
+ "Set %s=%s environ variable inside parent",
+ ENV_KEY, ENV_VAL0);
- /*
- * Break cstring into env and value
- */
- cenv = cstring;
- cvalue = strchr(cstring, ':');
- if (cvalue == NULL) {
- tst_resm(TBROK,
- "internal error - parent's env string not in correct format:'%s'",
- cstring);
- return -1;
- } else {
- *cvalue = '\0';
- cvalue++;
- if (*cvalue == '\0') {
- tst_resm(TBROK,
- "internal error - missing child's env value");
- return -1;
- }
- }
+ SAFE_SETENV(ENV_KEY, ENV_VAL0, 0);
- if (strcmp(penv, cenv) != 0) {
- tst_resm(TBROK, "internal error - parent(%s) != child (%s) env",
- penv, cenv);
- return -1;
- }
+ tst_res(TINFO, "Spawning child");
- if (strcmp(pvalue, cvalue) != 0) {
- tst_resm(TFAIL,
- "Env var %s changed after fork(), parent's %s, child's %s",
- penv, pvalue, cvalue);
- } else {
- tst_resm(TPASS, "Env var %s unchanged after fork(): %s",
- penv, cvalue);
+ if (!SAFE_FORK()) {
+ run_child();
+ exit(0);
}
- return 0;
-
-}
-
-/***************************************************************
- * parent_environment - the parent side of the environment tests
- * determine values for the variables
- * read the values determined by the child
- * compare values
- ***************************************************************/
-void parent_environment(void)
-{
-
- int fildes;
- char tmp_line[MAX_LINE_LENGTH];
- char parent_value[MAX_LINE_LENGTH];
- unsigned int index;
- int ret;
- char *var;
-
- fildes = SAFE_OPEN(cleanup, OUTPUT_FILE, O_RDWR);
- for (index = 0; index < NUMBER_OF_ENVIRON; index++) {
- ret = read(fildes, tmp_line, MAX_LINE_LENGTH);
- if (ret == 0) {
- tst_resm(TBROK,
- "fork() test. parent_environment: failed to read from file with %d (%s)",
- errno, strerror(errno));
- } else {
- var = getenv(environ_list[index]);
- if (var == NULL)
- sprintf(parent_value, "%s:%s",
- environ_list[index], ENV_NOT_SET);
- else
- sprintf(parent_value, "%s:%s",
- environ_list[index], var);
+ TST_CHECKPOINT_WAIT(0);
- cmp_env_strings(parent_value, tmp_line);
-
- }
+ val = getenv(ENV_KEY);
+ if (!val) {
+ tst_res(TFAIL,
+ "%s environ variable has been unset inside parent",
+ ENV_KEY);
+ } else {
+ TST_EXP_EXPR(strcmp(ENV_VAL0, val) == 0,
+ "%s environ variable is still present inside parent",
+ ENV_KEY)
}
- close(fildes);
-}
-
-int main(int ac, char **av)
-{
- int lc;
- int kid_status;
- int wait_status;
- int fails;
-
- tst_parse_opts(ac, av, NULL, NULL);
-
- setup();
-
- for (lc = 0; TEST_LOOPING(lc); lc++) {
- tst_count = 0;
- fails = 0;
-
- TEST(fork());
-
- if (TEST_RETURN == -1) {
- /* fork failed */
- tst_brkm(TFAIL, cleanup,
- "fork() failed with %d (%s)",
- TEST_ERRNO, strerror(TEST_ERRNO));
- } else if (TEST_RETURN == 0) {
- /* child */
- /* determine environment variables */
- child_environment();
- /* exit with known value */
- exit(KIDEXIT);
- } else {
- /* parent of successful fork */
- /* wait for the child to complete */
- wait_status = waitpid(TEST_RETURN, &kid_status, 0);
- /* validate the child exit status */
- if (wait_status == TEST_RETURN) {
- if (kid_status != KIDEXIT << 8) {
- tst_brkm(TBROK, cleanup,
- "fork(): Incorrect child status returned on wait(): %d",
- kid_status);
- fails++;
- }
- } else {
- tst_brkm(TBROK, cleanup,
- "fork(): wait() for child status failed with %d errno: %d : %s",
- wait_status, errno,
- strerror(errno));
- fails++;
- }
-
- if (fails == 0) {
- /* verification tests */
- parent_environment();
- }
- }
-
+ TST_CHECKPOINT_WAKE_AND_WAIT(0);
+
+ val = getenv(ENV_KEY);
+ if (!val)
+ tst_res(TFAIL,
+ "%s environ variable has been unset inside parent",
+ ENV_KEY);
+ else {
+ TST_EXP_EXPR(strcmp(ENV_VAL0, val) == 0,
+ "%s environ variable didn't change inside parent",
+ ENV_KEY)
}
-
- cleanup();
- tst_exit();
}
+
+static struct tst_test test = {
+ .test_all = run,
+ .forks_child = 1,
+ .needs_checkpoints = 1,
+};
diff --git a/testcases/kernel/syscalls/fork/fork06.c b/testcases/kernel/syscalls/fork/fork06.c
deleted file mode 100644
index 3bc11b14b..000000000
--- a/testcases/kernel/syscalls/fork/fork06.c
+++ /dev/null
@@ -1,106 +0,0 @@
-/*
- * Copyright (c) International Business Machines Corp., 2001
- *
- * 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
- *
- * NAME
- * fork06.c
- *
- * DESCRIPTION
- * Test that a process can fork children a large number of
- * times in succession
- *
- * ALGORITHM
- * Attempt to fork a child that exits immediately
- * Repeat it many times(1000), counting the number of successes and
- * failures
- *
- * USAGE
- * fork06
- *
- * HISTORY
- * 07/2001 Ported by Wayne Boyer
- *
- * RESTRICTIONS
- * None
- */
-
-#include <sys/types.h>
-#include <sys/wait.h>
-#include <stdio.h>
-#include "test.h"
-
-char *TCID = "fork06";
-int TST_TOTAL = 1;
-
-static void setup(void);
-static void cleanup(void);
-
-#define NUMFORKS 1000
-
-int main(int ac, char **av)
-{
- int i, pid, status, childpid, succeed, fail;
-
- int lc;
-
- tst_parse_opts(ac, av, NULL, NULL);
-
- setup();
-
- for (lc = 0; TEST_LOOPING(lc); lc++) {
- tst_count = 0;
- succeed = 0;
- fail = 0;
-
- for (i = 0; i < NUMFORKS; i++) {
- pid = fork();
- if (pid == -1) {
- fail++;
- continue;
- }
-
- if (pid == 0)
- _exit(0);
-
- childpid = wait(&status);
- if (pid != childpid)
- tst_resm(TFAIL, "pid from wait %d", childpid);
- succeed++;
- }
-
- tst_resm(TINFO, "tries %d", i);
- tst_resm(TINFO, "successes %d", succeed);
- tst_resm(TINFO, "failures %d", fail);
-
- if ((wait(&status)) == -1)
- tst_resm(TINFO, "There were no children to wait for");
- else
- tst_resm(TINFO, "There were children left");
- }
-
- cleanup();
- tst_exit();
-}
-
-static void setup(void)
-{
- tst_sig(FORK, DEF_HANDLER, cleanup);
- TEST_PAUSE;
-}
-
-static void cleanup(void)
-{
-}
diff --git a/testcases/kernel/syscalls/fork/fork10.c b/testcases/kernel/syscalls/fork/fork10.c
index 815eee1f6..790e7b386 100644
--- a/testcases/kernel/syscalls/fork/fork10.c
+++ b/testcases/kernel/syscalls/fork/fork10.c
@@ -1,159 +1,100 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
/*
- * Copyright (c) International Business Machines Corp., 2001
- *
- * 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
- *
- *
- * NAME
- * fork10.c
- *
- * DESCRIPTION
- * Check inheritance of file descriptor by children, they
- * should all be refering to the same file.
+ * Copyright (c) International Business Machines Corp., 2001
+ * 07/2001 Ported by Wayne Boyer
+ * Copyright (C) 2023 SUSE LLC Andrea Cervesato <andrea.cervesato@suse.com>
+ */
+
+/*\
+ * [Description]
*
- * ALGORITHM
- * Child reads several chars and exits.
- * Parent forks another child, have the child and parent attempt to use
- * that location
+ * This test verifies inheritance of file descriptors from parent to child
+ * process. We open a file from parent, then we check if file offset changes
+ * accordingly with file descriptor usage.
*
- * USAGE
- * fork10
+ * [Algorithm]
*
- * HISTORY
- * 07/2001 Ported by Wayne Boyer
+ * Test steps are the following:
+ * - create a file made in three parts -> | aa..a | bb..b | cc..c |
+ * - from parent, open the file
+ * - from child, move file offset after the first part
+ * - from parent, read second part and check if it's | bb..b |
+ * - from child, read third part and check if it's | cc..c |
*
- * RESTRICTIONS
- * None
+ * Test passes if we were able to read the correct file parts from parent and
+ * child.
*/
-#include <sys/types.h>
-#include <sys/wait.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <stdio.h>
-#include <errno.h>
-#include "test.h"
-#include "safe_macros.h"
-
-char *TCID = "fork10";
-int TST_TOTAL = 1;
+#include <stdlib.h>
+#include "tst_test.h"
-static void setup(void);
-static void cleanup(void);
+#define FILENAME "file.txt"
+#define DATASIZE 1024
-static char pidbuf[10];
-static char fnamebuf[40];
+static int fd = -1;
-int main(int ac, char **av)
+static void run(void)
{
- int status, pid, fildes;
- char parchar[2];
- char chilchar[2];
-
- int lc;
-
- fildes = -1;
-
- tst_parse_opts(ac, av, NULL, NULL);
-
- setup();
-
- for (lc = 0; TEST_LOOPING(lc); lc++) {
- tst_count = 0;
-
- fildes = SAFE_CREAT(cleanup, fnamebuf, 0600);
- write(fildes, "ABCDEFGHIJKLMNOPQRSTUVWXYZ\n", 27);
- close(fildes);
-
- fildes = SAFE_OPEN(cleanup, fnamebuf, 0);
-
- pid = fork();
- if (pid == -1)
- tst_brkm(TBROK, cleanup, "fork() #1 failed");
-
- if (pid == 0) { /* child */
- tst_resm(TINFO, "fork child A");
- if (lseek(fildes, 10L, 0) == -1L) {
- tst_resm(TFAIL, "bad lseek by child");
- exit(1);
- }
- exit(0);
- } else { /* parent */
- wait(&status);
-
- /* parent starts second child */
- pid = fork();
- if (pid == -1)
- tst_brkm(TBROK, cleanup, "fork() #2 failed");
-
- if (pid == 0) { /* child */
- if (read(fildes, chilchar, 1) <= 0) {
- tst_resm(TFAIL, "Child can't read "
- "file");
- exit(1);
- } else {
- if (chilchar[0] != 'K') {
- chilchar[1] = '\n';
- exit(1);
- } else {
- exit(0);
- }
- }
- } else { /* parent */
- (void)wait(&status);
- if (status >> 8 != 0) {
- tst_resm(TFAIL, "Bad return from "
- "second child");
- continue;
- }
- /* parent reads */
- if (read(fildes, parchar, 1) <= 0) {
- tst_resm(TFAIL, "Parent cannot read "
- "file");
- continue;
- } else {
- write(fildes, parchar, 1);
- if (parchar[0] != 'L') {
- parchar[1] = '\n';
- tst_resm(TFAIL, "Test failed");
- continue;
- }
- }
- }
- }
- tst_resm(TPASS, "test 1 PASSED");
+ int status;
+ char buff[DATASIZE];
+ char data[DATASIZE];
+
+ fd = SAFE_OPEN(FILENAME, 0);
+
+ if (!SAFE_FORK()) {
+ SAFE_LSEEK(fd, DATASIZE, SEEK_SET);
+ exit(0);
+ }
+
+ SAFE_WAIT(&status);
+
+ memset(buff, 'b', DATASIZE);
+ SAFE_READ(1, fd, data, DATASIZE);
+
+ TST_EXP_EXPR(strncmp(buff, data, DATASIZE) == 0,
+ "read first part of data from parent process");
+
+ if (!SAFE_FORK()) {
+ memset(buff, 'c', DATASIZE);
+ SAFE_READ(1, fd, data, DATASIZE);
+
+ TST_EXP_EXPR(strncmp(buff, data, DATASIZE) == 0,
+ "read second part of data from child process");
+
+ exit(0);
}
- close(fildes);
- cleanup();
- tst_exit();
+ SAFE_CLOSE(fd);
}
static void setup(void)
{
- tst_sig(FORK, DEF_HANDLER, cleanup);
- umask(0);
- TEST_PAUSE;
- tst_tmpdir();
-
- strcpy(fnamebuf, "fork10.");
- sprintf(pidbuf, "%d", getpid());
- strcat(fnamebuf, pidbuf);
+ char buff[DATASIZE];
+
+ fd = SAFE_CREAT(FILENAME, 0600);
+
+ memset(buff, 'a', DATASIZE);
+ SAFE_WRITE(SAFE_WRITE_ALL, fd, buff, DATASIZE);
+
+ memset(buff, 'b', DATASIZE);
+ SAFE_WRITE(SAFE_WRITE_ALL, fd, buff, DATASIZE);
+
+ memset(buff, 'c', DATASIZE);
+ SAFE_WRITE(SAFE_WRITE_ALL, fd, buff, DATASIZE);
+
+ SAFE_CLOSE(fd);
}
static void cleanup(void)
{
- tst_rmdir();
+ if (fd >= 0)
+ SAFE_CLOSE(fd);
}
+
+static struct tst_test test = {
+ .forks_child = 1,
+ .needs_tmpdir = 1,
+ .test_all = run,
+ .setup = setup,
+ .cleanup = cleanup,
+};
diff --git a/testcases/kernel/syscalls/fork/fork11.c b/testcases/kernel/syscalls/fork/fork11.c
deleted file mode 100644
index 6afda3a33..000000000
--- a/testcases/kernel/syscalls/fork/fork11.c
+++ /dev/null
@@ -1,97 +0,0 @@
-/*
- * Copyright (c) International Business Machines Corp., 2001
- *
- * 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
- *
- *
- * NAME
- * fork11.c
- *
- * DESCRIPTION
- * Test that parent gets a pid from each child when doing wait
- *
- * ALGORITHM
- * Fork NUMFORKS children that do nothing.
- *
- * USAGE
- * fork11
- *
- * HISTORY
- * 07/2001 Ported by Wayne Boyer
- *
- * RESTRICTIONS
- * None
- */
-
-#include <sys/types.h>
-#include <sys/wait.h>
-#include <stdio.h>
-#include <errno.h>
-#include "test.h"
-
-char *TCID = "fork11";
-int TST_TOTAL = 1;
-
-static void setup(void);
-static void cleanup(void);
-
-#define NUMFORKS 100
-
-int main(int ac, char **av)
-{
- int i, pid, cpid, status;
- int fail = 0;
- int lc;
-
- tst_parse_opts(ac, av, NULL, NULL);
-
- setup();
-
- for (lc = 0; TEST_LOOPING(lc); lc++) {
- tst_count = 0;
-
- for (i = 0; i < NUMFORKS; i++) {
- pid = fork();
- if (pid == 0)
- exit(0);
-
- if (pid > 0) { /* parent */
- cpid = wait(&status);
- if (cpid != pid)
- fail++;
- } else {
- fail++;
- break;
- }
- }
- if (fail)
- tst_resm(TFAIL, "fork failed %d times", fail);
- else
- tst_resm(TPASS, "fork test passed, %d processes", i);
- }
-
- cleanup();
- tst_exit();
-}
-
-static void setup(void)
-{
- tst_sig(FORK, DEF_HANDLER, cleanup);
- TEST_PAUSE;
-}
-
-static void cleanup(void)
-{
-}
diff --git a/testcases/kernel/syscalls/fork/fork12.c b/testcases/kernel/syscalls/fork/fork12.c
deleted file mode 100644
index 1c55c0c30..000000000
--- a/testcases/kernel/syscalls/fork/fork12.c
+++ /dev/null
@@ -1,137 +0,0 @@
-/*
- * Copyright (c) International Business Machines Corp., 2001
- *
- * 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
- *
- *
- * NAME
- * fork12.c
- *
- * DESCRIPTION
- * Check that all children inherit parent's file descriptor
- *
- * ALGORITHM
- * Parent forks processes until -1 is returned.$
- *
- * USAGE
- * fork12
- * ** CAUTION ** Can hang your machine, esp prior to 2.4.19
- *
- * HISTORY
- * 07/2001 Ported by Wayne Boyer
- * 07/2002 Split from fork07 as a test case to exhaust available pids.
- *
- * RESTRICTIONS
- * Should be run as root to avoid resource limits.$
- * Should not be run with other test programs because it tries to
- * use all available pids.
- */
-
-#include <stdio.h>
-#include <sys/wait.h>
-#include <errno.h>
-#include <string.h>
-#include "test.h"
-#include "safe_macros.h"
-
-char *TCID = "fork12";
-int TST_TOTAL = 1;
-
-static void setup(void);
-static void cleanup(void);
-static void fork12_sigs(int signum);
-
-int main(int ac, char **av)
-{
- int forks, pid1, fork_errno, waitstatus;
- int ret, status;
- int lc;
-
- tst_parse_opts(ac, av, NULL, NULL);
-
- setup();
-
- for (lc = 0; TEST_LOOPING(lc); lc++) {
- tst_count = 0;
-
- tst_resm(TINFO, "Forking as many kids as possible");
- forks = 0;
- while ((pid1 = fork()) != -1) {
- if (pid1 == 0) { /* child */
- /*
- * Taunt the OOM killer so that it doesn't
- * kill system processes
- */
- SAFE_FILE_PRINTF(NULL,
- "/proc/self/oom_score_adj", "500");
- pause();
- exit(0);
- }
- forks++;
- ret = SAFE_WAITPID(cleanup, -1, &status, WNOHANG);
- if (ret > 0) {
- /* a child may be killed by OOM killer */
- if (WTERMSIG(status) == SIGKILL)
- break;
- tst_brkm(TBROK, cleanup,
- "child exit with error code %d or signal %d",
- WEXITSTATUS(status), WTERMSIG(status));
- }
- }
- fork_errno = errno;
-
- /* parent */
- tst_resm(TINFO, "Number of processes forked is %d", forks);
- tst_resm(TPASS, "fork() eventually failed with %d: %s",
- fork_errno, strerror(fork_errno));
- /* collect our kids */
- /*
- * Introducing a sleep(3) to make sure all children are
- * at pause() when SIGQUIT is sent to them
- */
- sleep(3);
- kill(0, SIGQUIT);
- while (wait(&waitstatus) > 0) ;
-
- }
-
- cleanup();
- tst_exit();
-}
-
-static void setup(void)
-{
- tst_sig(FORK, fork12_sigs, cleanup);
- TEST_PAUSE;
-}
-
-static void cleanup(void)
-{
- int waitstatus;
-
- /* collect our kids */
- kill(0, SIGQUIT);
- while (wait(&waitstatus) > 0) ;
-}
-
-static void fork12_sigs(int signum)
-{
- if (signum == SIGQUIT) {
- /* Children will continue, parent will ignore */
- } else {
- tst_brkm(TBROK, cleanup,
- "Unexpected signal %d received.", signum);
- }
-}
diff --git a/testcases/kernel/syscalls/fork/fork_procs.c b/testcases/kernel/syscalls/fork/fork_procs.c
new file mode 100644
index 000000000..c35bb480c
--- /dev/null
+++ b/testcases/kernel/syscalls/fork/fork_procs.c
@@ -0,0 +1,55 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (C) 2023 SUSE LLC Andrea Cervesato <andrea.cervesato@suse.com>
+ */
+
+/*\
+ *[Description]
+ *
+ * This test spawns multiple processes using fork() and it checks if wait()
+ * returns the right PID once they end up.
+ */
+
+#include <stdlib.h>
+#include "tst_test.h"
+
+static char *str_numforks;
+static int numforks = 1000;
+
+static void run(void)
+{
+ pid_t pid;
+ int status;
+ int counter = 0;
+
+ tst_res(TINFO, "Forking %d processes", numforks);
+
+ for (int i = 0; i < numforks; i++) {
+ pid = SAFE_FORK();
+ if (!pid)
+ exit(0);
+
+ if (SAFE_WAIT(&status) == pid)
+ counter++;
+ }
+
+ TST_EXP_EXPR(numforks == counter,
+ "%d processes ended successfully",
+ counter);
+}
+
+static void setup(void)
+{
+ if (tst_parse_int(str_numforks, &numforks, 1, INT_MAX))
+ tst_brk(TBROK, "wrong number of forks '%s'", str_numforks);
+}
+
+static struct tst_test test = {
+ .test_all = run,
+ .setup = setup,
+ .forks_child = 1,
+ .options = (struct tst_option[]) {
+ { "n:", &str_numforks, "Number of processes to spawn" },
+ {},
+ },
+};
diff --git a/testcases/kernel/syscalls/fsetxattr/fsetxattr01.c b/testcases/kernel/syscalls/fsetxattr/fsetxattr01.c
index d799e477f..b65b27bdf 100644
--- a/testcases/kernel/syscalls/fsetxattr/fsetxattr01.c
+++ b/testcases/kernel/syscalls/fsetxattr/fsetxattr01.c
@@ -140,7 +140,7 @@ static void verify_fsetxattr(unsigned int i)
{
/* some tests might require existing keys for each iteration */
if (tc[i].keyneeded) {
- SAFE_FSETXATTR(fd, tc[i].key, tc[i].value, tc[i].size,
+ SAFE_FSETXATTR(fd, tc[i].key, *tc[i].value, tc[i].size,
XATTR_CREATE);
}
diff --git a/testcases/kernel/syscalls/fsetxattr/fsetxattr02.c b/testcases/kernel/syscalls/fsetxattr/fsetxattr02.c
index 0336c964a..39265af36 100644
--- a/testcases/kernel/syscalls/fsetxattr/fsetxattr02.c
+++ b/testcases/kernel/syscalls/fsetxattr/fsetxattr02.c
@@ -1,27 +1,33 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Copyright (c) 2018 Linaro Limited. All rights reserved.
+ * Copyright (c) Linux Test Project, 2018-2023
* Author: Rafael David Tinoco <rafael.tinoco@linaro.org>
*/
+/*\
+ * [Description]
+ *
+ * Verify basic fsetxattr(2) syscall functionality:
+ *
+ * - Set attribute to a regular file, fsetxattr(2) should succeed.
+ * - Set attribute to a directory, fsetxattr(2) should succeed.
+ * - Set attribute to a symlink which points to the regular file,
+ * fsetxattr(2) should return -1 and set errno to EEXIST.
+ * - Set attribute to a FIFO, fsetxattr(2) should return -1 and set
+ * errno to EPERM.
+ * - Set attribute to a char special file, fsetxattr(2) should
+ * return -1 and set errno to EPERM.
+ * - Set attribute to a block special file, fsetxattr(2) should
+ * return -1 and set errno to EPERM.
+ * - Set attribute to a UNIX domain socket, fsetxattr(2) should
+ * return -1 and set errno to EPERM.
+ */
+
/*
* In the user.* namespace, only regular files and directories can
* have extended attributes. Otherwise fsetxattr(2) will return -1
* and set errno to EPERM.
- *
- * There are 7 test cases:
- * 1. Set attribute to a regular file, fsetxattr(2) should succeed
- * 2. Set attribute to a directory, fsetxattr(2) should succeed
- * 3. Set attribute to a symlink which points to the regular file,
- * fsetxattr(2) should return -1 and set errno to EEXIST
- * 4. Set attribute to a FIFO, fsetxattr(2) should return -1 and set
- * errno to EPERM
- * 5. Set attribute to a char special file, fsetxattr(2) should
- * return -1 and set errno to EPERM
- * 6. Set attribute to a block special file, fsetxattr(2) should
- * return -1 and set errno to EPERM
- * 7. Set attribute to a UNIX domain socket, fsetxattr(2) should
- * return -1 and set errno to EPERM
*/
#include "config.h"
diff --git a/testcases/kernel/syscalls/getcwd/getcwd01.c b/testcases/kernel/syscalls/getcwd/getcwd01.c
index 65d827873..218bf4ef2 100644
--- a/testcases/kernel/syscalls/getcwd/getcwd01.c
+++ b/testcases/kernel/syscalls/getcwd/getcwd01.c
@@ -14,17 +14,17 @@
*
* Expected Result:
* 1) getcwd(2) should return NULL and set errno to EFAULT.
- * 2) getcwd(2) should return NULL and set errno to ENOMEM.
- * 3) getcwd(2) should return NULL and set errno to EINVAL.
+ * 2) getcwd(2) should return NULL and set errno to EFAULT.
+ * 3) getcwd(2) should return NULL and set errno to ERANGE.
* 4) getcwd(2) should return NULL and set errno to ERANGE.
* 5) getcwd(2) should return NULL and set errno to ERANGE.
- *
*/
#include <errno.h>
#include <unistd.h>
#include <limits.h>
#include "tst_test.h"
+#include "lapi/syscalls.h"
static char buffer[5];
@@ -34,32 +34,18 @@ static struct t_case {
int exp_err;
} tcases[] = {
{(void *)-1, PATH_MAX, EFAULT},
- {NULL, (size_t)-1, ENOMEM},
- {buffer, 0, EINVAL},
+ {NULL, (size_t)-1, EFAULT},
+ {buffer, 0, ERANGE},
{buffer, 1, ERANGE},
{NULL, 1, ERANGE}
};
+
static void verify_getcwd(unsigned int n)
{
struct t_case *tc = &tcases[n];
- char *res;
-
- errno = 0;
- res = getcwd(tc->buf, tc->size);
- TST_ERR = errno;
- if (res) {
- tst_res(TFAIL, "getcwd() succeeded unexpectedly");
- return;
- }
-
- if (TST_ERR != tc->exp_err) {
- tst_res(TFAIL | TTERRNO, "getcwd() failed unexpectedly, expected %s",
- tst_strerrno(tc->exp_err));
- return;
- }
- tst_res(TPASS | TTERRNO, "getcwd() failed as expected");
+ TST_EXP_FAIL2(tst_syscall(__NR_getcwd, tc->buf, tc->size), tc->exp_err);
}
static struct tst_test test = {
diff --git a/testcases/kernel/syscalls/getcwd/getcwd02.c b/testcases/kernel/syscalls/getcwd/getcwd02.c
index cb111a698..e3df22ceb 100644
--- a/testcases/kernel/syscalls/getcwd/getcwd02.c
+++ b/testcases/kernel/syscalls/getcwd/getcwd02.c
@@ -3,12 +3,14 @@
* Copyright (c) International Business Machines Corp., 2001
*/
-/*
- * DESCRIPTION
+/*\
+ * [Description]
+ *
* Testcase to check the basic functionality of the getcwd(2) system call.
- * 1) getcwd(2) works fine if buf and size are valid.
- * 2) getcwd(2) works fine if buf points to NULL and size is set to 0.
- * 3) getcwd(2) works fine if buf points to NULL and size is greater than strlen(path).
+ *
+ * 1. getcwd(2) works fine if buf and size are valid.
+ * 2. getcwd(2) works fine if buf points to NULL and size is set to 0.
+ * 3. getcwd(2) works fine if buf points to NULL and size is greater than strlen(path).
*/
#include <errno.h>
diff --git a/testcases/kernel/syscalls/getcwd/getcwd03.c b/testcases/kernel/syscalls/getcwd/getcwd03.c
index 97f4f3a33..9e3828a93 100644
--- a/testcases/kernel/syscalls/getcwd/getcwd03.c
+++ b/testcases/kernel/syscalls/getcwd/getcwd03.c
@@ -3,18 +3,20 @@
* Copyright (c) International Business Machines Corp., 2001
*/
-/*
- * DESCRIPTION
+/*\
+ * [Description]
+ *
* Testcase to check the basic functionality of the getcwd(2)
* system call on a symbolic link.
*
- * ALGORITHM
- * 1) create a directory, and create a symbolic link to it at the
+ * [Algorithm]
+ *
+ * 1. create a directory, and create a symbolic link to it at the
* same directory level.
- * 2) get the working directory of a directory, and its pathname.
- * 3) get the working directory of a symbolic link, and its pathname,
+ * 2. get the working directory of a directory, and its pathname.
+ * 3. get the working directory of a symbolic link, and its pathname,
* and its readlink info.
- * 4) compare the working directories and link information.
+ * 4. compare the working directories and link information.
*/
#define _GNU_SOURCE 1
diff --git a/testcases/kernel/syscalls/getdtablesize/.gitignore b/testcases/kernel/syscalls/getdtablesize/.gitignore
deleted file mode 100644
index 67a71b5e2..000000000
--- a/testcases/kernel/syscalls/getdtablesize/.gitignore
+++ /dev/null
@@ -1 +0,0 @@
-/getdtablesize01
diff --git a/testcases/kernel/syscalls/getdtablesize/getdtablesize01.c b/testcases/kernel/syscalls/getdtablesize/getdtablesize01.c
deleted file mode 100644
index d25cac261..000000000
--- a/testcases/kernel/syscalls/getdtablesize/getdtablesize01.c
+++ /dev/null
@@ -1,119 +0,0 @@
-/*
- * Copyright (c) International Business Machines Corp., 2005
- * Copyright (c) Wipro Technologies Ltd, 2005. All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of version 2 of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- */
-/**********************************************************
- *
- * TEST IDENTIFIER : getdtablesize01
- *
- * EXECUTED BY : root / superuser
- *
- * TEST TITLE : Basic tests for getdtablesize01(2)
- *
- * TEST CASE TOTAL : 1
- *
- * AUTHOR : Prashant P Yendigeri
- * <prashant.yendigeri@wipro.com>
- * Robbie Williamson
- * <robbiew@us.ibm.com>
- *
- * DESCRIPTION
- * This is a Phase I test for the getdtablesize01(2) system call.
- * It is intended to provide a limited exposure of the system call.
- *
- **********************************************************/
-
-#include <stdio.h>
-#include <errno.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <sys/time.h>
-#include <sys/resource.h>
-#include <unistd.h>
-#include "test.h"
-
-void setup();
-void cleanup();
-
-char *TCID = "getdtablesize01";
-int TST_TOTAL = 1;
-
-int main(void)
-{
- int table_size, fd = 0, count = 0;
- int max_val_opfiles;
- struct rlimit rlp;
-
- setup();
- table_size = getdtablesize();
- getrlimit(RLIMIT_NOFILE, &rlp);
- max_val_opfiles = (rlim_t) rlp.rlim_cur;
-
- tst_resm(TINFO,
- "Maximum number of files a process can have opened is %d",
- table_size);
- tst_resm(TINFO,
- "Checking with the value returned by getrlimit...RLIMIT_NOFILE");
-
- if (table_size == max_val_opfiles)
- tst_resm(TPASS, "got correct dtablesize, value is %d",
- max_val_opfiles);
- else {
- tst_resm(TFAIL, "got incorrect table size, value is %d",
- max_val_opfiles);
- cleanup();
- }
-
- tst_resm(TINFO,
- "Checking Max num of files that can be opened by a process.Should be: RLIMIT_NOFILE - 1");
- for (;;) {
- fd = open("/etc/hosts", O_RDONLY);
-
- if (fd == -1)
- break;
- count = fd;
-
-#ifdef DEBUG
- printf("Opened file num %d\n", fd);
-#endif
- }
-
-//Now the max files opened should be RLIMIT_NOFILE - 1 , why ? read getdtablesize man page
-
- if (count > 0)
- close(count);
- if (count == (max_val_opfiles - 1))
- tst_resm(TPASS, "%d = %d", count, (max_val_opfiles - 1));
- else if (fd < 0 && errno == ENFILE)
- tst_brkm(TCONF, cleanup, "Reached maximum number of open files for the system");
- else
- tst_resm(TFAIL, "%d != %d", count, (max_val_opfiles - 1));
-
- cleanup();
- tst_exit();
-}
-
-void setup(void)
-{
- tst_sig(NOFORK, DEF_HANDLER, cleanup);
-
- TEST_PAUSE;
-}
-
-void cleanup(void)
-{
-}
diff --git a/testcases/kernel/syscalls/getegid/getegid01.c b/testcases/kernel/syscalls/getegid/getegid01.c
index 271fbb6b6..46cdc680b 100644
--- a/testcases/kernel/syscalls/getegid/getegid01.c
+++ b/testcases/kernel/syscalls/getegid/getegid01.c
@@ -1,87 +1,32 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Copyright (c) 2000 Silicon Graphics, Inc. All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of version 2 of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- *
- * Further, this software is distributed without any warranty that it is
- * free of the rightful claim of any third person regarding infringement
- * or the like. Any license provided herein, whether implied or
- * otherwise, applies only to this software file. Patent licenses, if
- * any, provided herein do not apply to combinations of this program with
- * other software, or any other product whatsoever.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
- * Mountain View, CA 94043, or:
- *
- * http://www.sgi.com
- *
- * For further information regarding this notice, see:
- *
- * http://oss.sgi.com/projects/GenInfo/NoticeExplan/
- *
+ * William Roske, Dave Fenner
+ * Copyright (C) 2023 SUSE LLC Andrea Cervesato <andrea.cervesato@suse.com>
*/
-/*
- * AUTHOR : William Roske
- * CO-PILOT : Dave Fenner
+/*\
+ * [Description]
+ *
+ * This test checks if getegid() returns the effective group id.
*/
-#include <sys/types.h>
-#include <errno.h>
-#include <string.h>
-#include <signal.h>
-
-#include "test.h"
-#include "compat_16.h"
-
-static void setup();
-static void cleanup();
+#include "tst_test.h"
+#include "compat_tst_16.h"
-TCID_DEFINE(getegid01);
-int TST_TOTAL = 1;
-
-int main(int ac, char **av)
+static void run(void)
{
- int lc;
-
- tst_parse_opts(ac, av, NULL, NULL);
-
- setup();
-
- for (lc = 0; TEST_LOOPING(lc); lc++) {
-
- tst_count = 0;
-
- TEST(GETEGID(cleanup));
+ gid_t gid, st_egid;
- if (TEST_RETURN == -1) {
- tst_resm(TFAIL | TTERRNO, "getegid failed");
- continue; /* next loop for MTKERNEL */
- }
+ SAFE_FILE_LINES_SCANF("/proc/self/status", "Gid: %*d %d", &st_egid);
+ gid = getegid();
- tst_resm(TPASS, "getegid returned %ld", TEST_RETURN);
- }
-
- cleanup();
- tst_exit();
-}
-
-static void setup(void)
-{
- tst_sig(NOFORK, DEF_HANDLER, cleanup);
- TEST_PAUSE;
+ if (GID_SIZE_CHECK(st_egid))
+ TST_EXP_EQ_LI(gid, st_egid);
+ else
+ tst_res(TPASS, "getegid() passed");
}
-static void cleanup(void)
-{
-}
+static struct tst_test test = {
+ .test_all = run,
+};
diff --git a/testcases/kernel/syscalls/getegid/getegid02.c b/testcases/kernel/syscalls/getegid/getegid02.c
index 60f09501e..2f64bd869 100644
--- a/testcases/kernel/syscalls/getegid/getegid02.c
+++ b/testcases/kernel/syscalls/getegid/getegid02.c
@@ -1,90 +1,39 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
/*
- * Copyright (c) International Business Machines Corp., 2001
- * Ported by Wayne Boyer
- *
- * 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
+ * Copyright (c) 2000 Silicon Graphics, Inc. All Rights Reserved.
+ * William Roske, Dave Fenner
+ * Copyright (C) 2023 SUSE LLC Andrea Cervesato <andrea.cervesato@suse.com>
*/
-/*
- * Testcase to check the basic functionality of getegid().
+/*\
+ * [Description]
*
- * For functionality test the return value from getegid() is compared to passwd
- * entry.
+ * This test checks if getegid() returns the same effective group given by
+ * passwd entry via getpwuid().
*/
#include <pwd.h>
-#include <errno.h>
-
-#include "test.h"
-#include "compat_16.h"
-static void cleanup(void);
-static void setup(void);
+#include "tst_test.h"
+#include "compat_tst_16.h"
-TCID_DEFINE(getegid02);
-int TST_TOTAL = 1;
-
-int main(int ac, char **av)
+static void run(void)
{
- int lc;
uid_t euid;
+ gid_t egid;
struct passwd *pwent;
- tst_parse_opts(ac, av, NULL, NULL);
-
- setup();
-
- for (lc = 0; TEST_LOOPING(lc); lc++) {
- tst_count = 0;
-
- TEST(GETEGID(cleanup));
+ UID16_CHECK((euid = geteuid()), "geteuid");
- if (TEST_RETURN < 0) {
- tst_brkm(TBROK, cleanup, "This should never happen");
- }
+ pwent = getpwuid(euid);
+ if (!pwent)
+ tst_brk(TBROK | TERRNO, "getpwuid() error");
- euid = geteuid();
- pwent = getpwuid(euid);
+ GID16_CHECK((egid = getegid()), "getegid");
- if (pwent == NULL)
- tst_brkm(TBROK, cleanup, "geteuid() returned "
- "unexpected value %d", euid);
-
- GID16_CHECK(pwent->pw_gid, getegid, cleanup);
-
- if (pwent->pw_gid != TEST_RETURN) {
- tst_resm(TFAIL, "getegid() return value"
- " %ld unexpected - expected %d",
- TEST_RETURN, pwent->pw_gid);
- } else {
- tst_resm(TPASS,
- "effective group id %ld "
- "is correct", TEST_RETURN);
- }
- }
-
- cleanup();
- tst_exit();
-}
-
-static void setup(void)
-{
- tst_sig(NOFORK, DEF_HANDLER, cleanup);
- TEST_PAUSE;
+ TST_EXP_EQ_LI(pwent->pw_gid, egid);
}
-static void cleanup(void)
-{
-}
+static struct tst_test test = {
+ .test_all = run,
+};
diff --git a/testcases/kernel/syscalls/getgroups/Makefile b/testcases/kernel/syscalls/getgroups/Makefile
index b2bb1e005..a319acf85 100644
--- a/testcases/kernel/syscalls/getgroups/Makefile
+++ b/testcases/kernel/syscalls/getgroups/Makefile
@@ -3,6 +3,9 @@
top_srcdir ?= ../../../..
+# Remove after rewriting all tests to the new API.
+USE_LEGACY_COMPAT_16_H := 1
+
include $(top_srcdir)/include/mk/testcases.mk
include $(abs_srcdir)/../utils/compat_16.mk
include $(top_srcdir)/include/mk/generic_leaf_target.mk
diff --git a/testcases/kernel/syscalls/getgroups/getgroups01.c b/testcases/kernel/syscalls/getgroups/getgroups01.c
index cfddeb408..c253e487f 100644
--- a/testcases/kernel/syscalls/getgroups/getgroups01.c
+++ b/testcases/kernel/syscalls/getgroups/getgroups01.c
@@ -54,6 +54,11 @@
#include <sys/types.h>
#include "test.h"
+
+/*
+ * Don't forget to remove USE_LEGACY_COMPAT_16_H from Makefile after
+ * rewriting all tests to the new API.
+ */
#include "compat_16.h"
static void setup(void);
diff --git a/testcases/kernel/syscalls/getgroups/getgroups03.c b/testcases/kernel/syscalls/getgroups/getgroups03.c
index 5ba20ef82..fc94f0b8e 100644
--- a/testcases/kernel/syscalls/getgroups/getgroups03.c
+++ b/testcases/kernel/syscalls/getgroups/getgroups03.c
@@ -40,6 +40,11 @@
#include <pwd.h>
#include "test.h"
+
+/*
+ * Don't forget to remove USE_LEGACY_COMPAT_16_H from Makefile after
+ * rewriting all tests to the new API.
+ */
#include "compat_16.h"
#define TESTUSER "root"
diff --git a/testcases/kernel/syscalls/getpid/getpid01.c b/testcases/kernel/syscalls/getpid/getpid01.c
index ec18b67d5..495002037 100644
--- a/testcases/kernel/syscalls/getpid/getpid01.c
+++ b/testcases/kernel/syscalls/getpid/getpid01.c
@@ -6,26 +6,31 @@
/*\
* [Description]
*
- * Verify that getpid() system call returns process ID in range 2 ... PID_MAX
+ * Verify that getpid() system call returns process ID in range <2, PID_MAX>.
*/
#include <stdlib.h>
#include "tst_test.h"
+static pid_t pid_max;
+
+static void setup(void)
+{
+ SAFE_FILE_SCANF("/proc/sys/kernel/pid_max", "%d\n", &pid_max);
+}
+
static void verify_getpid(void)
{
- pid_t pid_max, pid;
+ pid_t pid;
int i;
- SAFE_FILE_SCANF("/proc/sys/kernel/pid_max", "%d\n", &pid_max);
-
for (i = 0; i < 100; i++) {
pid = SAFE_FORK();
if (pid == 0) {
pid = getpid();
/* pid should not be 1 or out of maximum */
- if (1 < pid && pid <= pid_max)
+ if (pid > 1 && pid <= pid_max)
tst_res(TPASS, "getpid() returns %d", pid);
else
tst_res(TFAIL,
@@ -38,6 +43,7 @@ static void verify_getpid(void)
}
static struct tst_test test = {
+ .setup = setup,
.forks_child = 1,
.test_all = verify_getpid,
};
diff --git a/testcases/kernel/syscalls/getppid/getppid01.c b/testcases/kernel/syscalls/getppid/getppid01.c
index f37948dd4..57efe1c1f 100644
--- a/testcases/kernel/syscalls/getppid/getppid01.c
+++ b/testcases/kernel/syscalls/getppid/getppid01.c
@@ -1,6 +1,7 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2000 Silicon Graphics, Inc. All Rights Reserved.
+ * Copyright (c) Linux Test Project, 2006-2023
*/
/*\
@@ -12,11 +13,16 @@
#include <errno.h>
#include "tst_test.h"
-static void verify_getppid(void)
-{
- pid_t ppid, pid_max;
+static pid_t pid_max;
+static void setup(void)
+{
SAFE_FILE_SCANF("/proc/sys/kernel/pid_max", "%d\n", &pid_max);
+}
+
+static void verify_getppid(void)
+{
+ pid_t ppid;
ppid = getppid();
if (ppid > pid_max)
@@ -26,5 +32,6 @@ static void verify_getppid(void)
}
static struct tst_test test = {
+ .setup = setup,
.test_all = verify_getppid,
};
diff --git a/testcases/kernel/syscalls/getresgid/Makefile b/testcases/kernel/syscalls/getresgid/Makefile
index b2bb1e005..a319acf85 100644
--- a/testcases/kernel/syscalls/getresgid/Makefile
+++ b/testcases/kernel/syscalls/getresgid/Makefile
@@ -3,6 +3,9 @@
top_srcdir ?= ../../../..
+# Remove after rewriting all tests to the new API.
+USE_LEGACY_COMPAT_16_H := 1
+
include $(top_srcdir)/include/mk/testcases.mk
include $(abs_srcdir)/../utils/compat_16.mk
include $(top_srcdir)/include/mk/generic_leaf_target.mk
diff --git a/testcases/kernel/syscalls/getresgid/getresgid01.c b/testcases/kernel/syscalls/getresgid/getresgid01.c
index b5fb804ee..8000200e1 100644
--- a/testcases/kernel/syscalls/getresgid/getresgid01.c
+++ b/testcases/kernel/syscalls/getresgid/getresgid01.c
@@ -73,6 +73,11 @@
#include <signal.h>
#include "test.h"
+
+/*
+ * Don't forget to remove USE_LEGACY_COMPAT_16_H from Makefile after
+ * rewriting all tests to the new API.
+ */
#include "compat_16.h"
char *TCID = "getresgid01";
diff --git a/testcases/kernel/syscalls/getresgid/getresgid02.c b/testcases/kernel/syscalls/getresgid/getresgid02.c
index 8bddf9824..ca4502aac 100644
--- a/testcases/kernel/syscalls/getresgid/getresgid02.c
+++ b/testcases/kernel/syscalls/getresgid/getresgid02.c
@@ -75,6 +75,11 @@
#include <pwd.h>
#include "test.h"
+
+/*
+ * Don't forget to remove USE_LEGACY_COMPAT_16_H from Makefile after
+ * rewriting all tests to the new API.
+ */
#include "compat_16.h"
#define LTPUSER "nobody"
diff --git a/testcases/kernel/syscalls/getresgid/getresgid03.c b/testcases/kernel/syscalls/getresgid/getresgid03.c
index 0785359e0..1d7bcabd2 100644
--- a/testcases/kernel/syscalls/getresgid/getresgid03.c
+++ b/testcases/kernel/syscalls/getresgid/getresgid03.c
@@ -77,6 +77,11 @@
#include <pwd.h>
#include "test.h"
+
+/*
+ * Don't forget to remove USE_LEGACY_COMPAT_16_H from Makefile after
+ * rewriting all tests to the new API.
+ */
#include "compat_16.h"
char *TCID = "getresgid03";
diff --git a/testcases/kernel/syscalls/getresuid/Makefile b/testcases/kernel/syscalls/getresuid/Makefile
index b2bb1e005..a319acf85 100644
--- a/testcases/kernel/syscalls/getresuid/Makefile
+++ b/testcases/kernel/syscalls/getresuid/Makefile
@@ -3,6 +3,9 @@
top_srcdir ?= ../../../..
+# Remove after rewriting all tests to the new API.
+USE_LEGACY_COMPAT_16_H := 1
+
include $(top_srcdir)/include/mk/testcases.mk
include $(abs_srcdir)/../utils/compat_16.mk
include $(top_srcdir)/include/mk/generic_leaf_target.mk
diff --git a/testcases/kernel/syscalls/getresuid/getresuid01.c b/testcases/kernel/syscalls/getresuid/getresuid01.c
index 07fed9c13..a04918d6f 100644
--- a/testcases/kernel/syscalls/getresuid/getresuid01.c
+++ b/testcases/kernel/syscalls/getresuid/getresuid01.c
@@ -72,6 +72,11 @@
#include <signal.h>
#include "test.h"
+
+/*
+ * Don't forget to remove USE_LEGACY_COMPAT_16_H from Makefile after
+ * rewriting all tests to the new API.
+ */
#include "compat_16.h"
char *TCID = "getresuid01";
diff --git a/testcases/kernel/syscalls/getresuid/getresuid02.c b/testcases/kernel/syscalls/getresuid/getresuid02.c
index 23f7944dd..77896a8a3 100644
--- a/testcases/kernel/syscalls/getresuid/getresuid02.c
+++ b/testcases/kernel/syscalls/getresuid/getresuid02.c
@@ -75,6 +75,11 @@
#include <pwd.h>
#include "test.h"
+
+/*
+ * Don't forget to remove USE_LEGACY_COMPAT_16_H from Makefile after
+ * rewriting all tests to the new API.
+ */
#include "compat_16.h"
#define LTPUSER "nobody"
diff --git a/testcases/kernel/syscalls/getresuid/getresuid03.c b/testcases/kernel/syscalls/getresuid/getresuid03.c
index bf117038b..34e40c45d 100644
--- a/testcases/kernel/syscalls/getresuid/getresuid03.c
+++ b/testcases/kernel/syscalls/getresuid/getresuid03.c
@@ -76,6 +76,11 @@
#include <pwd.h>
#include "test.h"
+
+/*
+ * Don't forget to remove USE_LEGACY_COMPAT_16_H from Makefile after
+ * rewriting all tests to the new API.
+ */
#include "compat_16.h"
char *TCID = "getresuid03";
diff --git a/testcases/kernel/syscalls/getrlimit/getrlimit02.c b/testcases/kernel/syscalls/getrlimit/getrlimit02.c
index 9b68ce20b..9f5b2bf9c 100644
--- a/testcases/kernel/syscalls/getrlimit/getrlimit02.c
+++ b/testcases/kernel/syscalls/getrlimit/getrlimit02.c
@@ -7,12 +7,13 @@
/*\
* [Description]
*
- * Test for checking error conditions for getrlimit(2)
- * 1) getrlimit(2) returns -1 and sets errno to EFAULT if an invalid
- * address is given for address parameter.
- * 2) getrlimit(2) returns -1 and sets errno to EINVAL if an invalid
- * resource type (RLIM_NLIMITS is a out of range resource type) is
- * passed.
+ * Test for checking error conditions for getrlimit(2):
+ *
+ * 1. getrlimit(2) returns -1 and sets errno to EFAULT if an invalid
+ * address is given for address parameter.
+ * 2. getrlimit(2) returns -1 and sets errno to EINVAL if an invalid
+ * resource type (RLIM_NLIMITS is a out of range resource type) is
+ * passed.
*/
#include <sys/resource.h>
diff --git a/testcases/kernel/syscalls/getsockopt/getsockopt02.c b/testcases/kernel/syscalls/getsockopt/getsockopt02.c
index 47aef32af..d24e9b693 100644
--- a/testcases/kernel/syscalls/getsockopt/getsockopt02.c
+++ b/testcases/kernel/syscalls/getsockopt/getsockopt02.c
@@ -3,9 +3,10 @@
* Copyright (C) 2017 Red Hat, Inc.
*/
-/*
- * Test description: Test retrieving of peer credentials (SO_PEERCRED)
+/*\
+ * [Description]
*
+ * Test getsockopt(2) for retrieving peer credentials (SO_PEERCRED).
*/
#define _GNU_SOURCE
@@ -53,6 +54,7 @@ static void test_function(void)
tst_res(TFAIL | TERRNO, "Error with accepting connection");
goto clean;
}
+
if (getsockopt(accepted, SOL_SOCKET,
SO_PEERCRED, &cred, &cred_len) < 0) {
tst_res(TFAIL | TERRNO, "Error while getting socket option");
@@ -67,6 +69,7 @@ static void test_function(void)
clean:
if (accepted >= 0)
SAFE_CLOSE(accepted);
+
TST_CHECKPOINT_WAKE(0);
}
@@ -74,6 +77,7 @@ static void cleanup(void)
{
if (accepted >= 0)
SAFE_CLOSE(accepted);
+
if (socket_fd >= 0)
SAFE_CLOSE(socket_fd);
}
diff --git a/testcases/kernel/syscalls/gettid/.gitignore b/testcases/kernel/syscalls/gettid/.gitignore
index 78dce3499..9014f7c3a 100644
--- a/testcases/kernel/syscalls/gettid/.gitignore
+++ b/testcases/kernel/syscalls/gettid/.gitignore
@@ -1 +1,2 @@
/gettid01
+/gettid02
diff --git a/testcases/kernel/syscalls/gettid/Makefile b/testcases/kernel/syscalls/gettid/Makefile
index 4e9982f76..5345eb0f5 100644
--- a/testcases/kernel/syscalls/gettid/Makefile
+++ b/testcases/kernel/syscalls/gettid/Makefile
@@ -10,7 +10,9 @@ top_srcdir ?= ../../../..
include $(top_srcdir)/include/mk/testcases.mk
ifeq ($(ANDROID), 1)
-FILTER_OUT_MAKE_TARGETS += gettid01
+FILTER_OUT_MAKE_TARGETS += gettid01 gettid02
endif
+gettid02: LDLIBS += -lpthread
+
include $(top_srcdir)/include/mk/generic_leaf_target.mk
diff --git a/testcases/kernel/syscalls/gettid/gettid01.c b/testcases/kernel/syscalls/gettid/gettid01.c
index 7e5b6b175..22ba15016 100644
--- a/testcases/kernel/syscalls/gettid/gettid01.c
+++ b/testcases/kernel/syscalls/gettid/gettid01.c
@@ -1,96 +1,32 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
/*
- * Crackerjack Project
- *
* Copyright (C) 2007-2008, Hitachi, Ltd.
- * Author(s): Takahiro Yasui <takahiro.yasui.mp@hitachi.com>,
- * Yumiko Sugita <yumiko.sugita.yf@hitachi.com>,
- * Satoshi Fujiwara <sa-fuji@sdl.hitachi.co.jp>
- *
- * 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.
- *
- * $Id: gettid01.c,v 1.5 2009/10/26 14:55:47 subrata_modak Exp $
+ * Copyright (C) 2023 SUSE LLC Andrea Cervesato <andrea.cervesato@suse.com>
+ */
+/*\
+ * [Description]
*
+ * This test checks if parent pid is equal to tid in single-threaded
+ * application.
*/
-/* Porting from Crackerjack to LTP is done
- by Masatake YAMATO <yamato@redhat.com> */
-
-#include <sys/types.h>
-#include <linux/unistd.h>
-#include <errno.h>
-
-#include "test.h"
-
-void setup();
-void cleanup();
-
-char *TCID = "gettid01";
-
-int TST_TOTAL = 1;
-
-pid_t my_gettid(void)
-{
- return (pid_t) syscall(__NR_gettid);
-}
-
-int main(int ac, char **av)
-{
- int lc;
-
- tst_parse_opts(ac, av, NULL, NULL);
-
- setup();
-
- /*
- * The following loop checks looping state if -c option given
- */
- for (lc = 0; TEST_LOOPING(lc); lc++) {
+#include "tst_test.h"
+#include "lapi/syscalls.h"
- tst_count = 0;
-
- TEST(my_gettid());
-
- if (TEST_RETURN == -1) {
- tst_resm(TFAIL, "gettid() Failed, errno=%d: %s",
- TEST_ERRNO, strerror(TEST_ERRNO));
- } else {
- tst_resm(TPASS, "gettid() returned %ld",
- TEST_RETURN);
- }
- }
-
- cleanup();
- tst_exit();
-}
-
-/*
- * setup() - performs all ONE TIME setup for this test.
- */
-void setup(void)
+static void run(void)
{
+ long pid, tid;
- tst_sig(NOFORK, DEF_HANDLER, cleanup);
+ SAFE_FILE_LINES_SCANF("/proc/self/status", "Pid: %ld", &pid);
+ SAFE_FILE_LINES_SCANF("/proc/self/status", "Tgid: %ld", &tid);
- TEST_PAUSE;
+ if (pid != tid)
+ tst_brk(TBROK, "Test function has been moved inside a thread?");
+ TST_EXP_EQ_LI(tst_syscall(__NR_gettid), tst_syscall(__NR_getpid));
+ TST_EXP_EQ_LI(tst_syscall(__NR_gettid), pid);
}
-/*
- * cleanup() - performs all ONE TIME cleanup for this test at
- * completion or premature exit.
- */
-void cleanup(void)
-{
-}
+static struct tst_test test = {
+ .test_all = run,
+};
diff --git a/testcases/kernel/syscalls/gettid/gettid02.c b/testcases/kernel/syscalls/gettid/gettid02.c
new file mode 100644
index 000000000..ef44761c4
--- /dev/null
+++ b/testcases/kernel/syscalls/gettid/gettid02.c
@@ -0,0 +1,66 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (C) 2023 SUSE LLC Andrea Cervesato <andrea.cervesato@suse.com>
+ */
+/*\
+ * [Description]
+ *
+ * This test spawns multiple threads, then check for each one of them if the
+ * parent ID is different AND if the thread ID is different from all the other
+ * spwaned threads.
+ */
+
+#include "tst_test.h"
+#include "lapi/syscalls.h"
+#include "tst_safe_pthread.h"
+
+#define THREADS_NUM 10
+
+static volatile pid_t tids[THREADS_NUM];
+
+static void *threaded(void *arg)
+{
+ int i = *(int *)arg;
+ pid_t pid, tid;
+
+ pid = tst_syscall(__NR_getpid);
+ tid = tst_syscall(__NR_gettid);
+
+ TST_EXP_EXPR(pid != tid,
+ "parent ID (%d) differs from thread[%d] ID (%d)",
+ pid, i, tid);
+ tids[i] = tid;
+ return NULL;
+}
+
+static void run(void)
+{
+ pthread_t thread[THREADS_NUM];
+ int args[THREADS_NUM];
+ int error = 0;
+
+ for (int i = 0; i < THREADS_NUM; i++) {
+ args[i] = i;
+ SAFE_PTHREAD_CREATE(&thread[i], NULL, threaded, &args[i]);
+ }
+ for (int i = 0; i < THREADS_NUM; i++)
+ SAFE_PTHREAD_JOIN(thread[i], NULL);
+
+ for (int i = 0; i < THREADS_NUM; i++) {
+ for (int j = i + 1; j < THREADS_NUM; j++) {
+ if (tids[i] == tids[j]) {
+ tst_res(TINFO, "thread[%d] and thread[%d] have the same ID %d", i, j, tids[i]);
+ error = 1;
+ }
+ }
+ }
+
+ if (error)
+ tst_res(TFAIL, "Some threads have the same TID");
+ else
+ tst_res(TPASS, "All threads have a different TID");
+}
+
+static struct tst_test test = {
+ .test_all = run,
+};
diff --git a/testcases/kernel/syscalls/gettimeofday/gettimeofday01.c b/testcases/kernel/syscalls/gettimeofday/gettimeofday01.c
index f9acb9665..887a36688 100644
--- a/testcases/kernel/syscalls/gettimeofday/gettimeofday01.c
+++ b/testcases/kernel/syscalls/gettimeofday/gettimeofday01.c
@@ -1,107 +1,42 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
/*
- *
- * Copyright (c) International Business Machines Corp., 2001
- *
- * 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
+ * Copyright (c) International Business Machines Corp., 2001
+ * Copyright (c) Linux Test Project, 2001-2023
*/
-/*
- * NAME
- * gettimeofday01.c
- *
- * DESCRIPTION
- * Testcase to check that gettimeofday(2) sets errno to EFAULT.
- *
- * ALGORITHM
- * Call gettimeofday() with an invalid buffer, and expect EFAULT to be
- * set in errno.
+/*\
+ * [Description]
*
- * HISTORY
- * 07/2001 Ported by Wayne Boyer
+ * Test for gettimeofday error.
*
- * RESTRICTIONS
- * NONE
+ * - EFAULT: tv pointed outside the accessible address space
+ * - EFAULT: tz pointed outside the accessible address space
+ * - EFAULT: both tv and tz pointed outside the accessible address space
*/
-#include <sys/time.h>
-#include <errno.h>
-#include "test.h"
-#include <unistd.h>
+#include "tst_test.h"
#include "lapi/syscalls.h"
-char *TCID = "gettimeofday01";
-int TST_TOTAL = 1;
+static struct timeval tv1;
-#if !defined UCLINUX
+static struct tcase {
+ void *tv;
+ void *tz;
+} tcases[] = {
+ /* timezone structure is obsolete, tz should be treated as null */
+ {(void *)-1, NULL},
+ {&tv1, (void *)-1},
+ {(void *)-1, (void *)-1},
+};
-void cleanup(void);
-void setup(void);
-
-int main(int ac, char **av)
+static void verify_gettimeofday(unsigned int n)
{
- int lc;
- int ret;
-
- tst_parse_opts(ac, av, NULL, NULL);
-
- setup();
-
- for (lc = 0; TEST_LOOPING(lc); lc++) {
- tst_count = 0;
-
- TEST(tst_syscall(__NR_gettimeofday, (void *)-1, (void *)-1));
-
- /* gettimeofday returns an int, so we need to turn the long
- * TEST_RETURN into an int to test with */
- ret = TEST_RETURN;
- if (ret != -1) {
- tst_resm(TFAIL,
- "call succeeded unexpectedly (got back %i, wanted -1)",
- ret);
- continue;
- }
+ struct tcase *tc = &tcases[n];
- if (TEST_ERRNO == EFAULT)
- tst_resm(TPASS,
- "gettimeofday(2) set the errno EFAULT correctly");
- else
- tst_resm(TFAIL,
- "gettimeofday(2) didn't set errno to EFAULT, errno=%i (%s)",
- errno, strerror(errno));
- }
-
- cleanup();
- tst_exit();
-}
-
-void setup(void)
-{
-
- tst_sig(NOFORK, DEF_HANDLER, cleanup);
-
- TEST_PAUSE;
-}
-
-void cleanup(void)
-{
-}
-#else
-
-int main(void)
-{
- tst_brkm(TCONF, "gettimeofday EFAULT check disabled on uClinux");
+ TST_EXP_FAIL(tst_syscall(__NR_gettimeofday, tc->tv, tc->tz), EFAULT);
}
-#endif
+static struct tst_test test = {
+ .tcnt = ARRAY_SIZE(tcases),
+ .test = verify_gettimeofday,
+};
diff --git a/testcases/kernel/syscalls/gettimeofday/gettimeofday02.c b/testcases/kernel/syscalls/gettimeofday/gettimeofday02.c
index 7c462cc29..84bf1f773 100644
--- a/testcases/kernel/syscalls/gettimeofday/gettimeofday02.c
+++ b/testcases/kernel/syscalls/gettimeofday/gettimeofday02.c
@@ -4,13 +4,13 @@
* Copyright (C) 2017 Cyril Hrubis <chrubis@suse.cz>
*/
-/*
- * DESCRIPTION
- * Check if gettimeofday is monotonous
+/*\
+ * [Description]
+ *
+ * Check if gettimeofday() is monotonous during 10s:
*
- * ALGORITHM
- * Call gettimeofday() to get a t1 (fist value)
- * call it again to get t2, see if t2 < t1, set t2 = t1, repeat for 10 sec
+ * - Call gettimeofday() to get a t1 (fist value)
+ * - Call it again to get t2, see if t2 < t1, set t2 = t1, repeat for 10 sec
*/
#include <stdint.h>
diff --git a/testcases/kernel/syscalls/getxattr/getxattr02.c b/testcases/kernel/syscalls/getxattr/getxattr02.c
index a42057d0a..5a84d876c 100644
--- a/testcases/kernel/syscalls/getxattr/getxattr02.c
+++ b/testcases/kernel/syscalls/getxattr/getxattr02.c
@@ -1,64 +1,41 @@
+// SPDX-License-Identifier: GPL-2.0-only
/*
- * Copyright (C) 2011 Red Hat, Inc.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU General Public
- * License as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- *
- * Further, this software is distributed without any warranty that it
- * is free of the rightful claim of any third person regarding
- * infringement or the like. Any license provided herein, whether
- * implied or otherwise, applies only to this software file. Patent
- * licenses, if any, provided herein do not apply to combinations of
- * this program with other software, or any other product whatsoever.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA.
+ * Copyright (C) 2011 Red Hat, Inc.
+ * Copyright (c) Linux Test Project, 2012-2022
+ * Copyright (c) 2023 Marius Kittler <mkittler@suse.de>
*/
-/*
+/*\
+ * [Description]
+ *
* In the user.* namespace, only regular files and directories can
* have extended attributes. Otherwise getxattr(2) will return -1
* and set errno to ENODATA.
*
* There are 4 test cases:
- * 1. Get attribute from a FIFO, setxattr(2) should return -1 and
+ *
+ * - Get attribute from a FIFO, setxattr(2) should return -1 and
* set errno to ENODATA
- * 2. Get attribute from a char special file, setxattr(2) should
+ * - Get attribute from a char special file, setxattr(2) should
* return -1 and set errno to ENODATA
- * 3. Get attribute from a block special file, setxattr(2) should
+ * - Get attribute from a block special file, setxattr(2) should
* return -1 and set errno to ENODATA
- * 4. Get attribute from a UNIX domain socket, setxattr(2) should
+ * - Get attribute from a UNIX domain socket, setxattr(2) should
* return -1 and set errno to ENODATA
*/
-#include "config.h"
#include <sys/types.h>
-#include <sys/stat.h>
#include <sys/sysmacros.h>
-#include <sys/wait.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <signal.h>
+#include <sys/xattr.h>
#include <stdio.h>
#include <stdlib.h>
-#include <string.h>
-#ifdef HAVE_SYS_XATTR_H
-# include <sys/xattr.h>
-#endif
-#include "test.h"
-#include "safe_macros.h"
-char *TCID = "getxattr02";
+#include "tst_res_flags.h"
+#include "tst_test.h"
+#include "tst_test_macros.h"
-#ifdef HAVE_SYS_XATTR_H
+#define MNTPOINT "mntpoint"
+#define FNAME MNTPOINT"/getxattr02"
#define XATTR_TEST_KEY "user.testkey"
#define FIFO "getxattr02fifo"
@@ -66,94 +43,78 @@ char *TCID = "getxattr02";
#define BLK "getxattr02blk"
#define SOCK "getxattr02sock"
-static void setup(void);
-static void cleanup(void);
-
-static char *tc[] = {
- FIFO, /* case 00, get attr from fifo */
- CHR, /* case 01, get attr from char special */
- BLK, /* case 02, get attr from block special */
- SOCK, /* case 03, get attr from UNIX domain socket */
+static struct test_case {
+ const char *desc;
+ char *fname;
+ int mode;
+} tcases[] = {
+ {
+ .desc = "get attr from fifo",
+ .fname = FNAME FIFO,
+ .mode = S_IFIFO,
+ },
+ {
+ .desc = "get attr from char special",
+ .fname = FNAME CHR,
+ .mode = S_IFCHR,
+ },
+ {
+ .desc = "get attr from block special",
+ .fname = FNAME BLK,
+ .mode = S_IFBLK,
+ },
+ {
+ .desc = "get attr from UNIX domain socket",
+ .fname = FNAME SOCK,
+ .mode = S_IFSOCK,
+ },
};
-int TST_TOTAL = sizeof(tc) / sizeof(tc[0]);
-
-int main(int argc, char *argv[])
+static void run(unsigned int i)
{
- int lc;
- int i;
- int exp_eno;
char buf[BUFSIZ];
-
- tst_parse_opts(argc, argv, NULL, NULL);
-
- setup();
-
- for (lc = 0; TEST_LOOPING(lc); lc++) {
- tst_count = 0;
- exp_eno = ENODATA;
-
- for (i = 0; i < TST_TOTAL; i++) {
- TEST(getxattr(tc[0], XATTR_TEST_KEY, buf, BUFSIZ));
-
- if (TEST_RETURN == -1 && TEST_ERRNO == exp_eno)
- tst_resm(TPASS | TTERRNO, "expected behavior");
- else
- tst_resm(TFAIL | TTERRNO, "unexpected behavior"
- " - expected errno %d - Got", exp_eno);
- }
- }
-
- cleanup();
- tst_exit();
+ struct test_case *tc = &tcases[i];
+ dev_t dev = tc->mode == S_IFCHR ? makedev(1, 3) : 0u;
+
+ if (mknod(tc->fname, tc->mode | 0777, dev) < 0)
+ tst_brk(TBROK | TERRNO, "create %s (mode %i) failed (%s)",
+ tc->fname, tc->mode, tc->desc);
+
+ TEST(getxattr(tc->fname, XATTR_TEST_KEY, buf, BUFSIZ));
+ if (TST_RET == -1 && TST_ERR == ENODATA)
+ tst_res(TPASS | TTERRNO, "%s: expected return value",
+ tc->desc);
+ else
+ tst_res(TFAIL | TTERRNO,
+ "%s: unexpected return value - expected errno %d - got",
+ tc->desc, ENODATA);
+
+ unlink(tc->fname);
}
static void setup(void)
{
- int fd;
- dev_t dev;
-
- tst_require_root();
-
- tst_tmpdir();
-
- /* Test for xattr support */
- fd = SAFE_CREAT(cleanup, "testfile", 0644);
- close(fd);
- if (setxattr("testfile", "user.test", "test", 4, XATTR_CREATE) == -1)
- if (errno == ENOTSUP)
- tst_brkm(TCONF, cleanup, "No xattr support in fs or "
- "mount without user_xattr option");
- unlink("testfile");
-
- /* Create test files */
- if (mknod(FIFO, S_IFIFO | 0777, 0) == -1)
- tst_brkm(TBROK | TERRNO, cleanup, "Create FIFO(%s) failed",
- FIFO);
-
- dev = makedev(1, 3);
- if (mknod(CHR, S_IFCHR | 0777, dev) == -1)
- tst_brkm(TBROK | TERRNO, cleanup, "Create char special(%s)"
- " failed", CHR);
-
- if (mknod(BLK, S_IFBLK | 0777, 0) == -1)
- tst_brkm(TBROK | TERRNO, cleanup, "Create block special(%s)"
- " failed", BLK);
-
- if (mknod(SOCK, S_IFSOCK | 0777, 0) == -1)
- tst_brkm(TBROK | TERRNO, cleanup, "Create socket(%s) failed",
- SOCK);
-
- TEST_PAUSE;
+ /* assert xattr support in the current filesystem */
+ SAFE_TOUCH(FNAME, 0644, NULL);
+ TEST(setxattr(FNAME, "user.test", "test", 4, XATTR_CREATE));
+ if (TST_ERR == ENOTSUP)
+ tst_brk(TCONF,
+ "No xattr support in fs or mount without user_xattr option");
+ else if (TST_RET != 0)
+ tst_brk(TBROK | TTERRNO, "setxattr failed");
}
-static void cleanup(void)
-{
- tst_rmdir();
-}
-#else /* HAVE_SYS_XATTR_H */
-int main(int argc, char *argv[])
-{
- tst_brkm(TCONF, NULL, "<sys/xattr.h> does not exist.");
-}
-#endif
+static struct tst_test test = {
+ .all_filesystems = 1,
+ .needs_root = 1,
+ .mntpoint = MNTPOINT,
+ .mount_device = 1,
+ .skip_filesystems = (const char *const []) {
+ "ramfs",
+ "nfs",
+ NULL
+ },
+ .setup = setup,
+ .test = run,
+ .tcnt = ARRAY_SIZE(tcases)
+};
diff --git a/testcases/kernel/syscalls/getxattr/getxattr03.c b/testcases/kernel/syscalls/getxattr/getxattr03.c
index b6ea14287..1fe4ba48f 100644
--- a/testcases/kernel/syscalls/getxattr/getxattr03.c
+++ b/testcases/kernel/syscalls/getxattr/getxattr03.c
@@ -1,117 +1,54 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
/*
- * Copyright (C) 2012 Red Hat, Inc.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU General Public
- * License as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- *
- * Further, this software is distributed without any warranty that it
- * is free of the rightful claim of any third person regarding
- * infringement or the like. Any license provided herein, whether
- * implied or otherwise, applies only to this software file. Patent
- * licenses, if any, provided herein do not apply to combinations of
- * this program with other software, or any other product whatsoever.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA.
+ * Copyright (C) 2012 Red Hat, Inc.
+ * Copyright (c) 2023 Marius Kittler <mkittler@suse.de>
*/
-/*
- * An empty buffer of size zero can be passed into getxattr(2) to return
- * the current size of the named extended attribute.
+/*\
+ * [Description]
+ *
+ * An empty buffer of size zero can be passed into getxattr(2) to
+ * return the current size of the named extended attribute.
*/
#include "config.h"
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <sys/wait.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <signal.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#ifdef HAVE_SYS_XATTR_H
-# include <sys/xattr.h>
-#endif
-#include "test.h"
-#include "safe_macros.h"
+#include "tst_test.h"
-char *TCID = "getxattr03";
+#include <sys/xattr.h>
+#include "tst_safe_macros.h"
-#ifdef HAVE_SYS_XATTR_H
+#define MNTPOINT "mntpoint"
+#define FNAME MNTPOINT"/getxattr03testfile"
#define XATTR_TEST_KEY "user.testkey"
#define XATTR_TEST_VALUE "test value"
#define XATTR_TEST_VALUE_SIZE (sizeof(XATTR_TEST_VALUE) - 1)
-#define TESTFILE "getxattr03testfile"
-static void setup(void);
-static void cleanup(void);
-
-int TST_TOTAL = 1;
-
-int main(int argc, char *argv[])
+static void run(void)
{
- int lc;
-
- tst_parse_opts(argc, argv, NULL, NULL);
-
- setup();
-
- for (lc = 0; TEST_LOOPING(lc); lc++) {
- tst_count = 0;
-
- TEST(getxattr(TESTFILE, XATTR_TEST_KEY, NULL, 0));
-
- if (TEST_RETURN == XATTR_TEST_VALUE_SIZE)
- tst_resm(TPASS, "getxattr(2) returned correct value");
- else
- tst_resm(TFAIL | TTERRNO, "getxattr(2) failed");
- }
-
- cleanup();
- tst_exit();
+ TST_EXP_VAL(getxattr(FNAME, XATTR_TEST_KEY, NULL, 0),
+ XATTR_TEST_VALUE_SIZE);
}
static void setup(void)
{
- int fd;
-
- tst_require_root();
-
- tst_tmpdir();
-
- /* Test for xattr support and set attr value */
- fd = SAFE_CREAT(cleanup, TESTFILE, 0644);
- close(fd);
-
- if (setxattr(TESTFILE, XATTR_TEST_KEY, XATTR_TEST_VALUE,
- XATTR_TEST_VALUE_SIZE, XATTR_CREATE) == -1) {
- if (errno == ENOTSUP)
- tst_brkm(TCONF, cleanup, "No xattr support in fs or "
- "fs mounted without user_xattr option");
- else
- tst_brkm(TBROK | TERRNO, cleanup, "setxattr %s failed",
- TESTFILE);
- }
-
- TEST_PAUSE;
+ SAFE_TOUCH(FNAME, 0644, NULL);
+ SAFE_SETXATTR(FNAME, XATTR_TEST_KEY, XATTR_TEST_VALUE,
+ XATTR_TEST_VALUE_SIZE, XATTR_CREATE);
}
-static void cleanup(void)
-{
- tst_rmdir();
-}
-#else /* HAVE_SYS_XATTR_H */
-int main(int argc, char *argv[])
-{
- tst_brkm(TCONF, NULL, "<sys/xattr.h> does not exist.");
-}
-#endif
+static struct tst_test test = {
+ .all_filesystems = 1,
+ .needs_root = 1,
+ .mntpoint = MNTPOINT,
+ .mount_device = 1,
+ .skip_filesystems = (const char *const []) {
+ "exfat",
+ "tmpfs",
+ "ramfs",
+ "nfs",
+ "vfat",
+ NULL
+ },
+ .setup = setup,
+ .test_all = run,
+};
diff --git a/testcases/kernel/syscalls/ioctl/ioctl02.c b/testcases/kernel/syscalls/ioctl/ioctl02.c
index b4d4a3594..aab80b251 100644
--- a/testcases/kernel/syscalls/ioctl/ioctl02.c
+++ b/testcases/kernel/syscalls/ioctl/ioctl02.c
@@ -1,468 +1,256 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
/*
- * Copyright (c) International Business Machines Corp., 2001
- * Copyright (c) 2020 Petr Vorel <pvorel@suse.cz>
- *
- * 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
+ * Copyright (c) International Business Machines Corp., 2001
+ * Copyright (c) 2020 Petr Vorel <pvorel@suse.cz>
+ * Copyright (c) 2023 Marius Kittler <mkittler@suse.de>
*/
-/*
- * NAME
- * ioctl02.c
- *
- * DESCRIPTION
- * Testcase to test the TCGETA, and TCSETA ioctl implementations for
- * the tty driver
+/*\
+ * [Description]
*
- * ALGORITHM
- * In this test, the parent and child open the parentty and the childtty
- * respectively. After opening the childtty the child flushes the stream
- * and sends a SIGUSR1 to the parent (thereby asking it to continue its
- * testing). The parent, which was waiting for this signal to arrive, now
- * starts the testing. It issues a TCGETA ioctl to get all the tty
- * parameters. It then changes them to known values by issuing a TCSETA
- * ioctl. Then the parent issues a TCGETA ioctl again and compares the
- * received values with what it had set earlier. The test fails if TCGETA
- * or TCSETA fails, or if the received values don't match those that were
- * set. The parent does all the testing, the requirement of the child
- * process is to moniter the testing done by the parent, and hence the
- * child just waits for the parent.
+ * Test TCGETA/TCGETS and TCSETA/TCSETS ioctl implementations for tty driver.
*
- * USAGE: <for command-line>
- * ioctl02 -D /dev/tty[0-9] [-c n] [-f] [-i n] [-I x] [-P x] [-t]
- * where, -c n : Run n copies concurrently.
- * -f : Turn off functionality Testing.
- * -i n : Execute test n times.
- * -I x : Execute test for x seconds.
- * -P x : Pause for x seconds between iterations.
- * -t : Turn on syscall timing.
- *
- * HISTORY
- * 07/2001 Ported by Wayne Boyer
- *
- * RESTRICTIONS
- * test must be run with the -D option
- * test may have to be run as root depending on the tty permissions
+ * In this test, the parent and child open the parentty and the childtty
+ * respectively. After opening the childtty the child flushes the stream
+ * and wakes the parent (thereby asking it to continue its testing). The
+ * parent, then starts the testing. It issues a TCGETA/TCGETS ioctl to
+ * get all the tty parameters. It then changes them to known values by
+ * issuing a TCSETA/TCSETS ioctl. Then the parent issues a TCSETA/TCGETS
+ * ioctl again and compares the received values with what it had set
+ * earlier. The test fails if TCGETA/TCGETS or TCSETA/TCSETS fails, or if
+ * the received values don't match those that were set. The parent does
+ * all the testing, the requirement of the child process is to moniter
+ * the testing done by the parent, and hence the child just waits for the
+ * parent.
*/
#include <stdio.h>
-#include <fcntl.h>
-#include <signal.h>
-#include <errno.h>
-#include <sys/wait.h>
-#include <sys/types.h>
-#include <sys/stat.h>
+#include <stdlib.h>
#include <termios.h>
-#include "test.h"
-#include "safe_macros.h"
-#include "lapi/ioctl.h"
-#define CNUL 0
-
-char *TCID = "ioctl02";
-int TST_TOTAL = 1;
+#include "lapi/ioctl.h"
+#include "tst_test.h"
-static struct termio termio, save_io;
+static struct termio termio, termio_exp;
+static struct termios termios, termios_exp, termios_bak;
static char *parenttty, *childtty;
-static int parentfd, childfd;
+static int parentfd = -1;
static int parentpid, childpid;
-static volatile int sigterm, sigusr1, sigusr2;
-static int closed = 1;
-
-static int do_child_setup(void);
-static int do_parent_setup(void);
-static int run_ptest(void);
-static int run_ctest(void);
-static int chk_tty_parms();
+
+static void do_child(void);
+static void prepare_termio(void);
+static void run_ptest(void);
+static void chk_tty_parms_termio(void);
+static void chk_tty_parms_termios(void);
static void setup(void);
static void cleanup(void);
-static void help(void);
-static void do_child(void);
-void do_child_uclinux(void);
-static void sigterm_handler(void);
-static int Devflag;
-static char *devname;
-
-static option_t options[] = {
- {"D:", &Devflag, &devname},
- {NULL, NULL, NULL}
+static char *device;
+
+static struct variant {
+ const char *name;
+ void *termio, *termio_exp, *termio_bak;
+ size_t termio_size;
+ void (*check)(void);
+ int tcget, tcset;
+} variants[] = {
+ {
+ .name = "termio",
+ .termio = &termio,
+ .termio_exp = &termio_exp,
+ .termio_size = sizeof(termio),
+ .check = &chk_tty_parms_termio,
+ .tcget = TCGETA,
+ .tcset = TCSETA,
+ },
+ {
+ .name = "termios",
+ .termio = &termios,
+ .termio_exp = &termios_exp,
+ .termio_size = sizeof(termios),
+ .check = &chk_tty_parms_termios,
+ .tcget = TCGETS,
+ .tcset = TCSETS,
+ },
};
-int main(int ac, char **av)
+static void verify_ioctl(void)
{
- int lc;
- int rval;
-
- tst_parse_opts(ac, av, options, &help);
-
-#ifdef UCLINUX
- maybe_run_child(&do_child_uclinux, "dS", &parentpid, &childtty);
-#endif
-
- if (!Devflag)
- tst_brkm(TBROK, NULL, "You must specify a tty device with "
- "the -D option.");
-
- tst_require_root();
-
- setup();
-
- for (lc = 0; TEST_LOOPING(lc); lc++) {
-
- tst_count = 0;
-
- parenttty = devname;
- childtty = devname;
-
- parentpid = getpid();
-
- childpid = FORK_OR_VFORK();
- if (childpid < 0)
- tst_brkm(TBROK, cleanup, "fork failed");
-
- if (childpid == 0) { /* child */
-#ifdef UCLINUX
- if (self_exec(av[0], "dS", parentpid, childtty) < 0)
- tst_brkm(TBROK, cleanup, "self_exec failed");
-#else
- do_child();
-#endif
- }
-
- while (!sigusr1)
- sleep(1);
-
- sigusr1 = 0;
-
- parentfd = do_parent_setup();
- if (parentfd < 0) {
- kill(childpid, SIGTERM);
- waitpid(childpid, NULL, 0);
- cleanup();
- }
-
- /* run the parent test */
- rval = run_ptest();
- if (rval == -1) {
- /*
- * Parent cannot set/get ioctl parameters.
- * SIGTERM the child and cleanup.
- */
- kill(childpid, SIGTERM);
- waitpid(childpid, NULL, 0);
- cleanup();
- }
-
- if (rval != 0)
- tst_resm(TFAIL, "TCGETA/TCSETA tests FAILED with "
- "%d %s", rval, rval > 1 ? "errors" : "error");
- else
- tst_resm(TPASS, "TCGETA/TCSETA tests SUCCEEDED");
-
- /* FIXME: check return codes. */
- (void)kill(childpid, SIGTERM);
- (void)waitpid(childpid, NULL, 0);
-
- /*
- * Clean up things from the parent by restoring the
- * tty device information that was saved in setup()
- * and closing the tty file descriptor.
- */
- if (ioctl(parentfd, TCSETA, &save_io) == -1)
- tst_resm(TINFO, "ioctl restore failed in main");
- SAFE_CLOSE(cleanup, parentfd);
-
- closed = 1;
- }
- cleanup();
+ tst_res(TINFO, "Testing %s variant", variants[tst_variant].name);
- tst_exit();
-}
+ parenttty = device;
+ childtty = device;
-static void do_child(void)
-{
- childfd = do_child_setup();
- if (childfd < 0)
- _exit(1);
- run_ctest();
- _exit(0);
-}
+ parentpid = getpid();
+ childpid = SAFE_FORK();
+ if (!childpid) {
+ do_child();
+ exit(EXIT_SUCCESS);
+ }
-void do_child_uclinux(void)
-{
- struct sigaction act;
+ TST_CHECKPOINT_WAIT(0);
+
+ parentfd = SAFE_OPEN(parenttty, O_RDWR, 0777);
+ SAFE_IOCTL(parentfd, TCFLSH, TCIOFLUSH);
- /* Set up the signal handlers again */
- act.sa_handler = (void *)sigterm_handler;
- act.sa_flags = 0;
- sigemptyset(&act.sa_mask);
- (void)sigaction(SIGTERM, &act, 0);
+ run_ptest();
- /* Run the normal child */
- do_child();
+ TST_CHECKPOINT_WAKE(0);
+ SAFE_CLOSE(parentfd);
}
-/*
- * run_ptest() - setup the various termio structure values and issue
- * the TCSETA ioctl call with the TEST macro.
- */
-static int run_ptest(void)
+static void prepare_termio(void)
{
- int i, rval;
-
/* Use "old" line discipline */
- termio.c_line = 0;
+ termios_exp.c_line = termio_exp.c_line = 0;
/* Set control modes */
- termio.c_cflag = B50 | CS7 | CREAD | PARENB | PARODD | CLOCAL;
+ termios_exp.c_cflag = termio_exp.c_cflag = B50 | CS7 | CREAD | PARENB | PARODD | CLOCAL;
/* Set control chars. */
- for (i = 0; i < NCC; i++) {
- if (i == VEOL2)
- continue;
- termio.c_cc[i] = CSTART;
- }
+ for (int i = 0; i < NCC; i++)
+ termio_exp.c_cc[i] = CSTART;
+ for (int i = 0; i < VEOL2; i++)
+ termios_exp.c_cc[i] = CSTART;
/* Set local modes. */
- termio.c_lflag =
+ termios_exp.c_lflag = termio_exp.c_lflag =
((unsigned short)(ISIG | ICANON | XCASE | ECHO | ECHOE | NOFLSH));
/* Set input modes. */
- termio.c_iflag =
+ termios_exp.c_iflag = termio_exp.c_iflag =
BRKINT | IGNPAR | INPCK | ISTRIP | ICRNL | IUCLC | IXON | IXANY |
IXOFF;
/* Set output modes. */
- termio.c_oflag = OPOST | OLCUC | ONLCR | ONOCR;
-
- TEST(ioctl(parentfd, TCSETA, &termio));
-
- if (TEST_RETURN < 0) {
- tst_resm(TFAIL, "ioctl TCSETA failed : "
- "errno = %d", TEST_ERRNO);
- return -1;
- }
-
- /* Get termio and see if all parameters actually got set */
- rval = ioctl(parentfd, TCGETA, &termio);
- if (rval < 0) {
- tst_resm(TFAIL, "ioctl TCGETA failed. Ending test.");
- return -1;
- }
-
- return chk_tty_parms();
+ termios_exp.c_oflag = termio_exp.c_oflag = OPOST | OLCUC | ONLCR | ONOCR;
}
-static int run_ctest(void)
+/*
+ * run_ptest() - setup the various termio/termios structure values and issue
+ * the TCSETA/TCSETS ioctl call with the TEST macro.
+ */
+static void run_ptest(void)
{
- /*
- * Wait till the parent has finished testing.
- */
- while (!sigterm)
- sleep(1);
+ struct variant *v = &variants[tst_variant];
- sigterm = 0;
+ /* Init termio/termios structures used to check if all params got set */
+ memset(v->termio, 0, v->termio_size);
- tst_resm(TINFO, "child: Got SIGTERM from parent.");
+ SAFE_IOCTL(parentfd, v->tcset, v->termio_exp);
- if (close(childfd) == -1)
- tst_resm(TINFO, "close() in run_ctest() failed");
- return 0;
+ /* Get termio and see if all parameters actually got set */
+ SAFE_IOCTL(parentfd, v->tcget, v->termio);
+ v->check();
}
-static int chk_tty_parms(void)
+static int cmp_attr(unsigned long long exp, unsigned long long act, const char *attr)
{
- int i, flag = 0;
-
- if (termio.c_line != 0) {
- tst_resm(TINFO, "line discipline has incorrect value %o",
- termio.c_line);
- flag++;
- }
- /*
- * The following Code Sniffet is disabled to check the value of c_cflag
- * as it seems that due to some changes from 2.6.24 onwards, this
- * setting is not done properly for either of (B50|CS7|CREAD|PARENB|
- * PARODD|CLOCAL|(CREAD|HUPCL|CLOCAL).
- * However, it has been observed that other flags are properly set.
- */
-#if 0
- if (termio.c_cflag != (B50 | CS7 | CREAD | PARENB | PARODD | CLOCAL)) {
- tst_resm(TINFO, "cflag has incorrect value. %o",
- termio.c_cflag);
- flag++;
- }
-#endif
-
- for (i = 0; i < NCC; i++) {
- if (i == VEOL2) {
- if (termio.c_cc[VEOL2] == CNUL) {
- continue;
- } else {
- tst_resm(TINFO, "control char %d has "
- "incorrect value %d %d", i,
- termio.c_cc[i], CNUL);
- flag++;
- continue;
- }
- }
-
- if (termio.c_cc[i] != CSTART) {
- tst_resm(TINFO, "control char %d has incorrect "
- "value %d.", i, termio.c_cc[i]);
- flag++;
- }
- }
+ if (act == exp)
+ return 0;
+ tst_res(TFAIL, "%s has incorrect value %llu, expected %llu",
+ attr, act, exp);
+ return 1;
+}
- if (!
- (termio.c_lflag
- && (ISIG | ICANON | XCASE | ECHO | ECHOE | NOFLSH))) {
- tst_resm(TINFO, "lflag has incorrect value. %o",
- termio.c_lflag);
- flag++;
- }
+static int cmp_c_cc(unsigned char *exp_c_cc, unsigned char *act_c_cc, int ncc)
+{
+ int i, fails = 0;
+ char what[32];
- if (!
- (termio.c_iflag
- && (BRKINT | IGNPAR | INPCK | ISTRIP | ICRNL | IUCLC | IXON | IXANY
- | IXOFF))) {
- tst_resm(TINFO, "iflag has incorrect value. %o",
- termio.c_iflag);
- flag++;
+ for (i = 0; i < ncc; ++i) {
+ sprintf(what, "control char %d", i);
+ fails += cmp_attr(exp_c_cc[i], act_c_cc[i], what);
}
+ return fails;
+}
- if (!(termio.c_oflag && (OPOST | OLCUC | ONLCR | ONOCR))) {
- tst_resm(TINFO, "oflag has incorrect value. %o",
- termio.c_oflag);
- flag++;
- }
+#define CMP_ATTR(term_exp, term, attr, flag) \
+({ \
+ flag += cmp_attr((term_exp).attr, (term).attr, #attr); \
+ flag; \
+})
- if (!flag)
- tst_resm(TINFO, "termio values are set as expected");
+#define CMP_C_CC(term_exp, term, flag) \
+({ \
+ flag += cmp_c_cc(term_exp.c_cc, term.c_cc, sizeof(term.c_cc)); \
+ flag; \
+})
- return flag;
-}
-
-static int do_parent_setup(void)
+static void chk_tty_parms_termio(void)
{
- int pfd;
-
- pfd = SAFE_OPEN(cleanup, parenttty, O_RDWR, 0777);
+ int flag = 0;
- /* unset the closed flag */
- closed = 0;
+ flag = CMP_ATTR(termio_exp, termio, c_line, flag);
+ flag = CMP_C_CC(termio_exp, termio, flag);
+ flag = CMP_ATTR(termio_exp, termio, c_lflag, flag);
+ flag = CMP_ATTR(termio_exp, termio, c_iflag, flag);
+ flag = CMP_ATTR(termio_exp, termio, c_oflag, flag);
- /* flush tty queues to remove old output */
- SAFE_IOCTL(cleanup, pfd, TCFLSH, 2);
- return pfd;
+ if (!flag)
+ tst_res(TPASS, "TCGETA/TCSETA tests");
}
-static int do_child_setup(void)
+static void chk_tty_parms_termios(void)
{
- int cfd;
-
- cfd = open(childtty, O_RDWR, 0777);
- if (cfd < 0) {
- tst_resm(TINFO, "Could not open %s in do_child_setup(), errno "
- "= %d", childtty, errno);
- /* signal the parent so we don't hang the test */
- kill(parentpid, SIGUSR1);
- return -1;
- }
+ int flag = 0;
- /* flush tty queues to remove old output */
- if (ioctl(cfd, TCFLSH, 2) < 0) {
- tst_resm(TINFO, "ioctl TCFLSH failed. : errno = %d", errno);
- /* signal the parent so we don't hang the test */
- kill(parentpid, SIGUSR1);
- return -1;
- }
+ flag = CMP_ATTR(termios_exp, termios, c_line, flag);
+ flag = CMP_C_CC(termios_exp, termios, flag);
+ flag = CMP_ATTR(termios_exp, termios, c_lflag, flag);
+ flag = CMP_ATTR(termios_exp, termios, c_iflag, flag);
+ flag = CMP_ATTR(termios_exp, termios, c_oflag, flag);
- /* tell the parent that we're done */
- kill(parentpid, SIGUSR1);
-
- return cfd;
+ if (!flag)
+ tst_res(TPASS, "TCGETS/TCSETS tests");
}
-/*
- * Define the signals handlers here.
- */
-static void sigterm_handler(void)
+static void do_child(void)
{
- sigterm = 1;
-}
+ int cfd = SAFE_OPEN(childtty, O_RDWR, 0777);
-static void sigusr1_handler(void)
-{
- sigusr1 = 1;
-}
+ SAFE_IOCTL(cfd, TCFLSH, TCIOFLUSH);
-static void sigusr2_handler(void)
-{
- sigusr2 = 1;
-}
+ /* tell the parent that we're done */
+ TST_CHECKPOINT_WAKE(0);
-static void help(void)
-{
- printf(" -D <tty device> : for example, /dev/tty[0-9]\n");
+ TST_CHECKPOINT_WAIT(0);
+ tst_res(TINFO, "child: parent has finished testing");
+ SAFE_CLOSE(cfd);
}
static void setup(void)
{
- int fd;
- struct sigaction act;
+ if (!device)
+ tst_brk(TBROK, "You must specify a tty device with -d option");
- /* XXX: TERRNO required all over the place */
- fd = SAFE_OPEN(NULL, devname, O_RDWR, 0777);
+ int fd = SAFE_OPEN(device, O_RDWR, 0777);
- /* Save the current device information - to be restored in cleanup() */
- SAFE_IOCTL(cleanup, fd, TCGETA, &save_io);
+ SAFE_IOCTL(fd, TCGETS, &termios_bak);
+ SAFE_CLOSE(fd);
- /* Close the device */
- SAFE_CLOSE(cleanup, fd);
-
- /* Set up the signal handlers */
- act.sa_handler = (void *)sigterm_handler;
- act.sa_flags = 0;
- sigemptyset(&act.sa_mask);
- (void)sigaction(SIGTERM, &act, 0);
-
- act.sa_handler = (void *)sigusr1_handler;
- act.sa_flags = 0;
- (void)sigaction(SIGUSR1, &act, 0);
-
- act.sa_handler = (void *)sigusr2_handler;
- act.sa_flags = 0;
- (void)sigaction(SIGUSR2, &act, 0);
-
- act.sa_handler = SIG_IGN;
- act.sa_flags = 0;
- (void)sigaction(SIGTTOU, &act, 0);
-
- sigterm = sigusr1 = sigusr2 = 0;
-
- TEST_PAUSE;
+ prepare_termio();
}
static void cleanup(void)
{
- if (!closed) {
- if (ioctl(parentfd, TCSETA, &save_io) == -1)
- tst_resm(TINFO, "ioctl restore failed in cleanup()");
- if (close(parentfd) == -1)
- tst_resm(TINFO, "close() failed in cleanup()");
+ if (parentfd >= 0) {
+ SAFE_IOCTL(parentfd, TCSETS, &termios_bak);
+ SAFE_CLOSE(parentfd);
}
}
+
+static struct tst_test test = {
+ .needs_root = 1,
+ .needs_checkpoints = 1,
+ .forks_child = 1,
+ .setup = setup,
+ .cleanup = cleanup,
+ .test_all = verify_ioctl,
+ .test_variants = 2,
+ .options = (struct tst_option[]) {
+ {"d:", &device, "Tty device. For example, /dev/tty[0-9]"},
+ {}
+ }
+};
diff --git a/testcases/kernel/syscalls/ioctl/ioctl_loop06.c b/testcases/kernel/syscalls/ioctl/ioctl_loop06.c
index 6d009af6a..64800b4ee 100644
--- a/testcases/kernel/syscalls/ioctl/ioctl_loop06.c
+++ b/testcases/kernel/syscalls/ioctl/ioctl_loop06.c
@@ -109,8 +109,9 @@ static void setup(void)
unalign_value = pg_size - 1;
dev_fd = SAFE_OPEN(dev_path, O_RDWR);
+ ret = ioctl(dev_fd, LOOP_SET_BLOCK_SIZE, 512);
- if (ioctl(dev_fd, LOOP_SET_BLOCK_SIZE, 512) && errno == EINVAL)
+ if (ret && (errno == EINVAL || errno == ENOTTY))
tst_brk(TCONF, "LOOP_SET_BLOCK_SIZE is not supported");
file_fd = SAFE_OPEN("test.img", O_RDWR);
diff --git a/testcases/kernel/syscalls/ioctl/test_ioctl b/testcases/kernel/syscalls/ioctl/test_ioctl
index 43836a229..8549e5608 100755
--- a/testcases/kernel/syscalls/ioctl/test_ioctl
+++ b/testcases/kernel/syscalls/ioctl/test_ioctl
@@ -45,7 +45,7 @@ case "$device_no" in
continue
fi
tst_resm TINFO "Testing ioctl02 with $tttype"
- ioctl02 -D $tttype
+ ioctl02 -d $tttype
RC=$?
if [ $RC -eq 0 ]
then
diff --git a/testcases/kernel/syscalls/ipc/msgctl/msgctl06.c b/testcases/kernel/syscalls/ipc/msgctl/msgctl06.c
index 6f5476383..c1264b71e 100644
--- a/testcases/kernel/syscalls/ipc/msgctl/msgctl06.c
+++ b/testcases/kernel/syscalls/ipc/msgctl/msgctl06.c
@@ -139,12 +139,16 @@ static void verify_msgctl(unsigned int n)
static void setup(void)
{
struct msqid_ds temp_buf;
+ struct buf {
+ long type;
+ char text[5];
+ } msgbuf = {MSGTYPE, "abcd"};
ltpuser = SAFE_GETPWNAM("nobody");
nobody_uid = ltpuser->pw_uid;
root_uid = 0;
msg_id = SAFE_MSGGET(IPC_PRIVATE, IPC_CREAT | MSG_RW);
- SAFE_MSGSND(msg_id, "abcd", 4, 0);
+ SAFE_MSGSND(msg_id, &msgbuf, sizeof(msgbuf.text), 0);
TEST(msgctl(msg_id, MSG_STAT_ANY, &temp_buf));
if (TST_RET == -1) {
diff --git a/testcases/kernel/syscalls/ipc/shmget/shmget02.c b/testcases/kernel/syscalls/ipc/shmget/shmget02.c
index 8168803a5..10b8c9292 100644
--- a/testcases/kernel/syscalls/ipc/shmget/shmget02.c
+++ b/testcases/kernel/syscalls/ipc/shmget/shmget02.c
@@ -37,8 +37,6 @@
#include "libnewipc.h"
#include "lapi/shm.h"
-#define CONFIG_HUGETLBFS "CONFIG_HUGETLBFS"
-
static int shm_id = -1;
static key_t shmkey, shmkey1;
static struct passwd *pw;
@@ -66,10 +64,7 @@ static struct tcase {
static int get_hugetlb_exp_error(void)
{
long tmp;
- struct tst_kconfig_var kconfig = {
- .id = CONFIG_HUGETLBFS,
- .id_len = sizeof(CONFIG_HUGETLBFS)-1,
- };
+ struct tst_kconfig_var kconfig = TST_KCONFIG_INIT("CONFIG_HUGETLBFS");
tst_kconfig_read(&kconfig, 1);
diff --git a/testcases/kernel/syscalls/keyctl/keyctl01.c b/testcases/kernel/syscalls/keyctl/keyctl01.c
index 55e069c68..674094eec 100644
--- a/testcases/kernel/syscalls/keyctl/keyctl01.c
+++ b/testcases/kernel/syscalls/keyctl/keyctl01.c
@@ -2,14 +2,17 @@
/*
* Copyright (c) Crackerjack Project., 2007
* Copyright (c) 2017 Fujitsu Ltd.
+ * Copyright (c) Linux Test Project, 2009-2024
+ * Ported by Manas Kumar Nayak maknayak@in.ibm.com>
+ * Modified by Guangwen Feng <fenggw-fnst@cn.fujitsu.com>
*/
-/*
- * Description: This tests the keyctl() syscall
- * Manipulate the kernel's key management facility
+/*\
+ * [Description]
*
- * Ported by Manas Kumar Nayak maknayak@in.ibm.com>
- * Modified by Guangwen Feng <fenggw-fnst@cn.fujitsu.com>
+ * Tests the keyctl(2) syscall.
+ *
+ * Manipulate the kernel's key management facility.
*/
#include <errno.h>
diff --git a/testcases/kernel/syscalls/keyctl/keyctl02.c b/testcases/kernel/syscalls/keyctl/keyctl02.c
index 35cc2838d..fd3f86bbc 100644
--- a/testcases/kernel/syscalls/keyctl/keyctl02.c
+++ b/testcases/kernel/syscalls/keyctl/keyctl02.c
@@ -1,11 +1,14 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Copyright (c) 2017 Fujitsu Ltd.
- * Ported: Guangwen Feng <fenggw-fnst@cn.fujitsu.com>
+ * Copyright (c) Linux Test Project, 2017-2024
+ * Ported: Guangwen Feng <fenggw-fnst@cn.fujitsu.com>
*/
-/*
- * This is a regression test for the race between keyctl_read() and
+/*\
+ * [Description]
+ *
+ * Regression test for the race between keyctl_read() and
* keyctl_revoke(), if the revoke happens between keyctl_read()
* checking the validity of a key and the key's semaphore being taken,
* then the key type read method will see a revoked key.
@@ -14,13 +17,8 @@
* assumes in its read method that there will always be a payload
* in a non-revoked key and doesn't check for a NULL pointer.
*
- * This test can crash the buggy kernel, and the bug was fixed in:
- *
- * commit b4a1b4f5047e4f54e194681125c74c0aa64d637d
- * Author: David Howells <dhowells@redhat.com>
- * Date: Fri Dec 18 01:34:26 2015 +0000
- *
- * KEYS: Fix race between read and revoke
+ * Bug was fixed in commit
+ * b4a1b4f5047e ("KEYS: Fix race between read and revoke")
*/
#include <errno.h>
@@ -29,6 +27,7 @@
#include "tst_safe_pthread.h"
#include "tst_test.h"
+#include "tst_kconfig.h"
#include "lapi/keyctl.h"
#define LOOPS 20000
@@ -36,6 +35,7 @@
#define PATH_KEY_COUNT_QUOTA "/proc/sys/kernel/keys/root_maxkeys"
static int orig_maxkeys;
+static int realtime_kernel;
static void *do_read(void *arg)
{
@@ -86,6 +86,15 @@ static void do_test(void)
tst_res(TINFO, "Runtime exhausted, exiting after %d loops", i);
break;
}
+
+ /*
+ * Realtime kernel has deferred post-join thread cleanup which
+ * may result in exhaustion of cgroup thread limit. Add delay
+ * to limit the maximum number of stale threads to 4000
+ * even with CONFIG_HZ=100.
+ */
+ if (realtime_kernel)
+ usleep(100);
}
/*
@@ -126,8 +135,19 @@ static void do_test(void)
static void setup(void)
{
+ unsigned int i;
+ struct tst_kconfig_var rt_kconfigs[] = {
+ TST_KCONFIG_INIT("CONFIG_PREEMPT_RT"),
+ TST_KCONFIG_INIT("CONFIG_PREEMPT_RT_FULL")
+ };
+
SAFE_FILE_SCANF(PATH_KEY_COUNT_QUOTA, "%d", &orig_maxkeys);
SAFE_FILE_PRINTF(PATH_KEY_COUNT_QUOTA, "%d", orig_maxkeys + LOOPS + 1);
+
+ tst_kconfig_read(rt_kconfigs, ARRAY_SIZE(rt_kconfigs));
+
+ for (i = 0; i < ARRAY_SIZE(rt_kconfigs); i++)
+ realtime_kernel |= rt_kconfigs[i].choice == 'y';
}
static void cleanup(void)
diff --git a/testcases/kernel/syscalls/keyctl/keyctl03.c b/testcases/kernel/syscalls/keyctl/keyctl03.c
index 9d7b9a0b5..563ee96a9 100644
--- a/testcases/kernel/syscalls/keyctl/keyctl03.c
+++ b/testcases/kernel/syscalls/keyctl/keyctl03.c
@@ -1,19 +1,15 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Copyright (c) 2017 Fujitsu Ltd.
- * Ported: Guangwen Feng <fenggw-fnst@cn.fujitsu.com>
+ * Copyright (c) Linux Test Project, 2017-2024
+ * Ported: Guangwen Feng <fenggw-fnst@cn.fujitsu.com>
*/
-/*
- * This regression test can crash the buggy kernel,
- * and the bug was fixed in:
- *
- * commit f05819df10d7b09f6d1eb6f8534a8f68e5a4fe61
- * Author: David Howells <dhowells@redhat.com>
- * Date: Thu Oct 15 17:21:37 2015 +0100
+/*\
+ * [Description]
*
- * KEYS: Fix crash when attempt to garbage collect
- * an uninstantiated keyring
+ * Regression test for commit
+ * f05819df10d7 ("KEYS: Fix crash when attempt to garbage collect an uninstantiated keyring")
*/
#include <errno.h>
diff --git a/testcases/kernel/syscalls/keyctl/keyctl04.c b/testcases/kernel/syscalls/keyctl/keyctl04.c
index 1fed23ca6..50c9244de 100644
--- a/testcases/kernel/syscalls/keyctl/keyctl04.c
+++ b/testcases/kernel/syscalls/keyctl/keyctl04.c
@@ -1,9 +1,12 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Copyright (c) 2017 Google, Inc.
+ * Copyright (c) Linux Test Project, 2017-2024
*/
-/*
+/*\
+ * [Description]
+ *
* Regression test for commit c9f838d104fe ("KEYS: fix
* keyctl_set_reqkey_keyring() to not leak thread keyrings"), a.k.a.
* CVE-2017-7472. This bug could be used to exhaust kernel memory, though it
diff --git a/testcases/kernel/syscalls/keyctl/keyctl05.c b/testcases/kernel/syscalls/keyctl/keyctl05.c
index 7d7c076c0..0ad106774 100644
--- a/testcases/kernel/syscalls/keyctl/keyctl05.c
+++ b/testcases/kernel/syscalls/keyctl/keyctl05.c
@@ -1,9 +1,12 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Copyright (c) 2017 Google, Inc.
+ * Copyright (c) Linux Test Project, 2017-2024
*/
-/*
+/*\
+ * [Description]
+ *
* Regression test for commit 63a0b0509e70 ("KEYS: fix freeing uninitialized
* memory in key_update()"). Try to reproduce the crash in two different ways:
*
@@ -31,6 +34,8 @@
#include "tst_test.h"
#include "lapi/keyctl.h"
+#define MODULE "dns_resolver"
+
/*
* A valid payload for the "asymmetric" key type. This is an x509 certificate
* in DER format, generated using:
@@ -190,6 +195,9 @@ static void test_update_setperm_race(void)
static void setup(void)
{
+ /* There is no way to trigger automatic dns_resolver module loading. */
+ tst_cmd((const char*[]){"modprobe", MODULE, NULL}, NULL, NULL, 0);
+
fips_enabled = tst_fips_enabled();
}
@@ -198,8 +206,12 @@ static void do_test(unsigned int i)
/*
* We need to pass check in dns_resolver_preparse(),
* give it dummy server list request.
+ * From v6.8-rc1 commit acc657692aed438e9931438f8c923b2b107aebf9:
+ * the incoming data for add_key() sysdall should be not less than 6
+ * bytes, because struct dns_server_list_v1_header is 6 bytes.
+ * The minimum payload will be tested here for boundary testing.
*/
- static char dns_res_payload[] = { 0x00, 0x00, 0x01, 0xff, 0x00 };
+ static char dns_res_payload[] = { 0x00, 0x00, 0x01, 0xff, 0x00, 0x00 };
switch (i) {
case 0:
@@ -207,7 +219,7 @@ static void do_test(unsigned int i)
x509_cert, sizeof(x509_cert));
break;
case 1:
- test_update_nonupdatable("dns_resolver", dns_res_payload,
+ test_update_nonupdatable(MODULE, dns_res_payload,
sizeof(dns_res_payload));
break;
case 2:
@@ -217,12 +229,14 @@ static void do_test(unsigned int i)
}
static struct tst_test test = {
+ .needs_root = 1,
.tcnt = 3,
.setup = setup,
.test = do_test,
.forks_child = 1,
.tags = (const struct tst_tag[]) {
{"linux-git", "63a0b0509e70"},
+ {"linux-git", "acc657692aed"},
{}
}
};
diff --git a/testcases/kernel/syscalls/keyctl/keyctl06.c b/testcases/kernel/syscalls/keyctl/keyctl06.c
index f76a85ff2..4564601d1 100644
--- a/testcases/kernel/syscalls/keyctl/keyctl06.c
+++ b/testcases/kernel/syscalls/keyctl/keyctl06.c
@@ -1,19 +1,19 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Copyright (c) 2017 Google, Inc.
+ * Copyright (c) Linux Test Project, 2017-2024
*/
-/*
- * Regression test for:
+/*\
+ * [Description]
*
- * commit e645016abc80 ("KEYS: fix writing past end of user-supplied buffer
- * in keyring_read()").
+ * Regression test for commit:
*
- * as well as its follow-on fix:
+ * e645016abc80 ("KEYS: fix writing past end of user-supplied buffer in keyring_read()")
*
- * commit 3239b6f29bdf ("KEYS: return full count in keyring_read() if
- * buffer is too small")
+ * as well as its follow-on fix:
*
+ * commit 3239b6f29bdf ("KEYS: return full count in keyring_read() if buffer is too small")
*/
#include <errno.h>
diff --git a/testcases/kernel/syscalls/keyctl/keyctl07.c b/testcases/kernel/syscalls/keyctl/keyctl07.c
index d9e20db5f..8b10ee803 100644
--- a/testcases/kernel/syscalls/keyctl/keyctl07.c
+++ b/testcases/kernel/syscalls/keyctl/keyctl07.c
@@ -1,9 +1,12 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Copyright (c) 2017 Google, Inc.
+ * Copyright (c) Linux Test Project, 2018-2024
*/
-/*
+/*\
+ * [Description]
+ *
* Regression test for commit 37863c43b2c6 ("KEYS: prevent KEYCTL_READ on
* negative key"). This is CVE-2017-12192.
*/
diff --git a/testcases/kernel/syscalls/keyctl/keyctl08.c b/testcases/kernel/syscalls/keyctl/keyctl08.c
index be4b23b14..30e077c50 100644
--- a/testcases/kernel/syscalls/keyctl/keyctl08.c
+++ b/testcases/kernel/syscalls/keyctl/keyctl08.c
@@ -1,10 +1,16 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Copyright (c) 2017 Richard Palethorpe <rpalethorpe@suse.com>
+ * Copyright (c) Linux Test Project, 2019-2024
*/
-/* Check for CVE-2016-9604; that keys beginning with "." are disallowed.
+
+/*\
+ * [Description]
+ *
+ * Test for CVE-2016-9604, checks that keys beginning with "." are disallowed.
*
- * See commit ee8f844e3c5a73b999edf733df1c529d6503ec2f
+ * See commit
+ * ee8f844e3c5a ("KEYS: Disallow keyrings beginning with '.' to be joined as session keyrings")
*/
#include <errno.h>
diff --git a/testcases/kernel/syscalls/keyctl/keyctl09.c b/testcases/kernel/syscalls/keyctl/keyctl09.c
index cfd5f7e5f..1f24f804a 100644
--- a/testcases/kernel/syscalls/keyctl/keyctl09.c
+++ b/testcases/kernel/syscalls/keyctl/keyctl09.c
@@ -1,6 +1,7 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Copyright (c) 2022 Google, Inc.
+ * Copyright (c) Linux Test Project, 2023
*/
/*\
diff --git a/testcases/kernel/syscalls/lchown/Makefile b/testcases/kernel/syscalls/lchown/Makefile
index 305fee281..7c76afea5 100644
--- a/testcases/kernel/syscalls/lchown/Makefile
+++ b/testcases/kernel/syscalls/lchown/Makefile
@@ -3,6 +3,9 @@
top_srcdir ?= ../../../..
+# Remove after rewriting all tests to the new API.
+USE_LEGACY_COMPAT_16_H := 1
+
include $(top_srcdir)/include/mk/testcases.mk
SRCS := $(sort $(wildcard $(abs_srcdir)/lchown*.c))
diff --git a/testcases/kernel/syscalls/lchown/lchown01.c b/testcases/kernel/syscalls/lchown/lchown01.c
index 4e6076e1f..aaa0ef403 100644
--- a/testcases/kernel/syscalls/lchown/lchown01.c
+++ b/testcases/kernel/syscalls/lchown/lchown01.c
@@ -41,6 +41,11 @@
#include "test.h"
#include "safe_macros.h"
+
+/*
+ * Don't forget to remove USE_LEGACY_COMPAT_16_H from Makefile after
+ * rewriting all tests to the new API.
+ */
#include "compat_16.h"
#define FILE_MODE (S_IFREG|S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH)
diff --git a/testcases/kernel/syscalls/lchown/lchown02.c b/testcases/kernel/syscalls/lchown/lchown02.c
index 97966f6be..c0932fb7a 100644
--- a/testcases/kernel/syscalls/lchown/lchown02.c
+++ b/testcases/kernel/syscalls/lchown/lchown02.c
@@ -58,6 +58,11 @@
#include "test.h"
#include "safe_macros.h"
+
+/*
+ * Don't forget to remove USE_LEGACY_COMPAT_16_H from Makefile after
+ * rewriting all tests to the new API.
+ */
#include "compat_16.h"
#define TEST_USER "nobody"
diff --git a/testcases/kernel/syscalls/lchown/lchown03.c b/testcases/kernel/syscalls/lchown/lchown03.c
index c26f54c21..ecb6ed64d 100644
--- a/testcases/kernel/syscalls/lchown/lchown03.c
+++ b/testcases/kernel/syscalls/lchown/lchown03.c
@@ -39,6 +39,11 @@
#include "test.h"
#include "safe_macros.h"
+
+/*
+ * Don't forget to remove USE_LEGACY_COMPAT_16_H from Makefile after
+ * rewriting all tests to the new API.
+ */
#include "compat_16.h"
#define DIR_MODE (S_IRUSR|S_IWUSR|S_IXUSR|S_IRGRP| \
diff --git a/testcases/kernel/syscalls/link/.gitignore b/testcases/kernel/syscalls/link/.gitignore
index e5d7f1bbc..b2b9db632 100644
--- a/testcases/kernel/syscalls/link/.gitignore
+++ b/testcases/kernel/syscalls/link/.gitignore
@@ -1,5 +1,4 @@
/link02
-/link03
/link04
/link05
/link08
diff --git a/testcases/kernel/syscalls/link/link03.c b/testcases/kernel/syscalls/link/link03.c
deleted file mode 100644
index 1f45240ae..000000000
--- a/testcases/kernel/syscalls/link/link03.c
+++ /dev/null
@@ -1,167 +0,0 @@
-/*
- * Copyright (c) 2000 Silicon Graphics, Inc. All Rights Reserved.
- * AUTHOR : Richard Logan
- * CO-PILOT : William Roske
- * Copyright (c) 2014 Cyril Hrubis <chrubis@suse.cz>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of version 2 of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- *
- * Further, this software is distributed without any warranty that it is
- * free of the rightful claim of any third person regarding infringement
- * or the like. Any license provided herein, whether implied or
- * otherwise, applies only to this software file. Patent licenses, if
- * any, provided herein do not apply to combinations of this program with
- * other software, or any other product whatsoever.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
- * Mountain View, CA 94043, or:
- *
- * http://www.sgi.com
- *
- * For further information regarding this notice, see:
- *
- * http://oss.sgi.com/projects/GenInfo/NoticeExplan/
- *
- */
-
- /*
- * Tests that link(2) succeds with creating n links.
- */
-
-#include <sys/types.h>
-#include <fcntl.h>
-#include <sys/stat.h>
-#include <errno.h>
-#include <string.h>
-#include <signal.h>
-#include "test.h"
-#include "safe_macros.h"
-
-static void setup(void);
-static void help(void);
-static void cleanup(void);
-
-char *TCID = "link03";
-int TST_TOTAL = 2;
-
-#define BASENAME "lkfile"
-
-static char fname[255];
-static int nlinks = 0;
-static char *links_arg;
-
-option_t options[] = {
- {"N:", NULL, &links_arg},
- {NULL, NULL, NULL}
-};
-
-int main(int ac, char **av)
-{
- int lc;
- struct stat buf;
- int i, links;
- char lname[255];
-
- tst_parse_opts(ac, av, options, &help);
-
- if (links_arg) {
- nlinks = atoi(links_arg);
-
- if (nlinks == 0) {
- tst_brkm(TBROK, NULL,
- "nlinks is not a positive number");
- }
-
- if (nlinks > 1000) {
- tst_resm(TINFO,
- "nlinks > 1000 - may get errno:%d (EMLINK)",
- EMLINK);
- }
- }
-
- setup();
-
- for (lc = 0; TEST_LOOPING(lc); lc++) {
- tst_count = 0;
-
- if (nlinks)
- links = nlinks;
- else
- links = (lc % 90) + 10;
-
- /* Create links - 1 hardlinks so that the st_nlink == links */
- for (i = 1; i < links; i++) {
- sprintf(lname, "%s%d", fname, i);
- TEST(link(fname, lname));
-
- if (TEST_RETURN == -1) {
- tst_brkm(TFAIL | TTERRNO, cleanup,
- "link(%s, %s) Failed", fname, lname);
- }
- }
-
- SAFE_STAT(cleanup, fname, &buf);
-
- if (buf.st_nlink != (nlink_t)links) {
- tst_resm(TFAIL, "Wrong number of links for "
- "'%s' have %i, should be %i",
- fname, (int)buf.st_nlink, links);
- goto unlink;
- }
-
- for (i = 1; i < links; i++) {
- sprintf(lname, "%s%d", fname, i);
- SAFE_STAT(cleanup, lname, &buf);
- if (buf.st_nlink != (nlink_t)links) {
- tst_resm(TFAIL,
- "Wrong number of links for "
- "'%s' have %i, should be %i",
- lname, (int)buf.st_nlink, links);
- goto unlink;
- }
- }
-
- tst_resm(TPASS, "link() passed and linkcounts=%d match", links);
-
-unlink:
- for (i = 1; i < links; i++) {
- sprintf(lname, "%s%d", fname, i);
- SAFE_UNLINK(cleanup, lname);
- }
- }
-
- cleanup();
- tst_exit();
-}
-
-static void help(void)
-{
- printf(" -N #links : create #links hard links every iteration\n");
-}
-
-static void setup(void)
-{
- tst_sig(NOFORK, DEF_HANDLER, cleanup);
-
- TEST_PAUSE;
-
- tst_tmpdir();
-
- sprintf(fname, "%s_%d", BASENAME, getpid());
- SAFE_TOUCH(cleanup, fname, 0700, NULL);
-}
-
-static void cleanup(void)
-{
- tst_rmdir();
-}
diff --git a/testcases/kernel/syscalls/link/link05.c b/testcases/kernel/syscalls/link/link05.c
index 95787ec24..dfef3d458 100644
--- a/testcases/kernel/syscalls/link/link05.c
+++ b/testcases/kernel/syscalls/link/link05.c
@@ -1,13 +1,15 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Copyright (c) 2000 Silicon Graphics, Inc. All Rights Reserved.
- * AUTHOR : Richard Logan
- * CO-PILOT : William Roske
+ * Authors: Richard Logan, William Roske
* Copyright (c) 2014 Cyril Hrubis <chrubis@suse.cz>
+ * Copyright (c) Linux Test Project, 2001-2023
*/
-/*
- * Test if link(2) fails with EMLINK.
+/*\
+ * [Description]
+ *
+ * Tests that link(2) succeeds with creating 1000 links.
*/
#include <stdio.h>
@@ -41,10 +43,8 @@ static void verify_link(void)
(fbuf.st_nlink != lbuf.st_nlink)) {
tst_res(TFAIL,
- "link(%s, %s[1-%d]) ret %ld for %d "
- "files, stat values do not match %d %d",
- fname, fname, nlinks,
- TST_RET, nlinks,
+ "link(%s, %s[1-%d]) ret %ld for %d files, stat values do not match %d %d",
+ fname, fname, nlinks, TST_RET, nlinks,
(int)fbuf.st_nlink, (int)lbuf.st_nlink);
break;
}
@@ -52,10 +52,8 @@ static void verify_link(void)
if (cnt >= nlinks) {
tst_res(TPASS,
- "link(%s, %s[1-%d]) ret %ld for %d files, "
- "stat linkcounts match %d",
- fname, fname, nlinks, TST_RET,
- nlinks, (int)fbuf.st_nlink);
+ "link(%s, %s[1-%d]) ret %ld for %d files, stat linkcounts match %d",
+ fname, fname, nlinks, TST_RET, nlinks, (int)fbuf.st_nlink);
}
for (cnt = 1; cnt < nlinks; cnt++) {
@@ -71,7 +69,7 @@ static void setup(void)
}
static struct tst_test test = {
- .test_all = verify_link,
- .setup = setup,
- .needs_tmpdir = 1,
+ .test_all = verify_link,
+ .setup = setup,
+ .needs_tmpdir = 1,
};
diff --git a/testcases/kernel/syscalls/link/link08.c b/testcases/kernel/syscalls/link/link08.c
index d3e33d077..92d507489 100644
--- a/testcases/kernel/syscalls/link/link08.c
+++ b/testcases/kernel/syscalls/link/link08.c
@@ -1,23 +1,26 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Copyright (c) 2014 Fujitsu Ltd.
+ * Copyright (c) Linux Test Project, 2014-2023
* Author: Zeng Linggang <zenglg.jy@cn.fujitsu.com>
*/
-/*
- * Test Description:
- * Verify that,
- * 1. link() fails with -1 return value and sets errno to EPERM
- * if oldpath is a directory.
- * 2. link() fails with -1 return value and sets errno to EXDEV
- * if oldpath and newpath are not on the same mounted file system( Linux
- * permits a file system to be mounted at multiple points, but link()
- * does not work across different mount points, even if the same
- * file system is mounted on both. ).
- * 3. link() fails with -1 return value and sets errno to EROFS
- * if the file is on a read-only file system.
- * 4. link() fails with -1 return value and sets errno to ELOOP
- * if too many symbolic links were encountered in resolving path.
+
+/*\
+ * [Description]
+ *
+ * Verify that:
+ *
+ * - link() fails with EPERM if the old path is a directory.
+ * - link() fails with EXDEV if the old path and the new path
+ * are not on the same mounted file system(Linux permits
+ * a file system to be mounted at multiple points, but link()
+ * does not work across different mount points, even if the same
+ * file system is mounted on both).
+ * - link() fails with EROFS if the file is on a read-only file system.
+ * - link() fails with ELOOP if too many symbolic links were encountered
+ * in resolving path.
*/
+
#include <errno.h>
#include "tst_test.h"
diff --git a/testcases/kernel/syscalls/mkdirat/mkdirat01.c b/testcases/kernel/syscalls/mkdirat/mkdirat01.c
index a323ed5b3..ca536bdab 100644
--- a/testcases/kernel/syscalls/mkdirat/mkdirat01.c
+++ b/testcases/kernel/syscalls/mkdirat/mkdirat01.c
@@ -35,7 +35,6 @@
#include <string.h>
#include <signal.h>
#include "test.h"
-#include "lapi/mkdirat.h"
#include "safe_macros.h"
static void setup(void);
diff --git a/testcases/kernel/syscalls/mkdirat/mkdirat02.c b/testcases/kernel/syscalls/mkdirat/mkdirat02.c
index ebc0ed16b..2bd8fe9c0 100644
--- a/testcases/kernel/syscalls/mkdirat/mkdirat02.c
+++ b/testcases/kernel/syscalls/mkdirat/mkdirat02.c
@@ -11,7 +11,6 @@
#define _GNU_SOURCE
#include "tst_test.h"
-#include "lapi/mkdirat.h"
#define MNT_POINT "mntpoint"
#define TEST_DIR "mntpoint/test_dir"
diff --git a/testcases/kernel/syscalls/mknodat/mknodat.h b/testcases/kernel/syscalls/mknodat/mknodat.h
deleted file mode 100644
index 8f3a1f007..000000000
--- a/testcases/kernel/syscalls/mknodat/mknodat.h
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright (c) International Business Machines Corp., 2007
- * Copyright (c) 2014 Fujitsu Ltd.
- *
- * 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 Library 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- *
- */
-
-#ifndef MKNODAT_H
-#define MKNODAT_H
-
-#include <sys/types.h>
-#include "config.h"
-#include "lapi/syscalls.h"
-
-#if !defined(HAVE_MKNODAT)
-int mknodat(int dirfd, const char *filename, mode_t mode, dev_t dev)
-{
- return tst_syscall(__NR_mknodat, dirfd, filename, mode, dev);
-}
-#endif
-
-#endif /* MKNODAT_H */
diff --git a/testcases/kernel/syscalls/mknodat/mknodat01.c b/testcases/kernel/syscalls/mknodat/mknodat01.c
index 6500ca362..3be0a4f87 100644
--- a/testcases/kernel/syscalls/mknodat/mknodat01.c
+++ b/testcases/kernel/syscalls/mknodat/mknodat01.c
@@ -35,7 +35,6 @@
#include "test.h"
#include "safe_macros.h"
#include "lapi/fcntl.h"
-#include "mknodat.h"
#define PATHNAME "mknodattestdir"
diff --git a/testcases/kernel/syscalls/mknodat/mknodat02.c b/testcases/kernel/syscalls/mknodat/mknodat02.c
index eda247fda..fdac5db15 100644
--- a/testcases/kernel/syscalls/mknodat/mknodat02.c
+++ b/testcases/kernel/syscalls/mknodat/mknodat02.c
@@ -37,7 +37,7 @@
#include "test.h"
#include "safe_macros.h"
#include "lapi/fcntl.h"
-#include "mknodat.h"
+#include "lapi/syscalls.h"
static void setup(void);
static void cleanup(void);
diff --git a/testcases/kernel/syscalls/mmap/mmap04.c b/testcases/kernel/syscalls/mmap/mmap04.c
index 43f7b7525..fa85deed1 100644
--- a/testcases/kernel/syscalls/mmap/mmap04.c
+++ b/testcases/kernel/syscalls/mmap/mmap04.c
@@ -1,185 +1,79 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Copyright (c) International Business Machines Corp., 2001
- *
- * 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
+ * 07/2001 Ported by Wayne Boyer
+ * Copyright (c) 2023 SUSE LLC Avinesh Kumar <avinesh.kumar@suse.com>
*/
-/*
- * Test Description:
- * Call mmap() to map a file creating a mapped region with read/exec access
- * under the following conditions -
- * - The prot parameter is set to PROT_READ|PROT_EXEC
- * - The file descriptor is open for read
- * - The file being mapped has read and execute permission bit set.
- * - The minimum file permissions should be 0555.
- *
- * The call should succeed to map the file creating mapped memory with the
- * required attributes.
- *
- * Expected Result:
- * mmap() should succeed returning the address of the mapped region,
- * and the mapped region should contain the contents of the mapped file.
+/*\
+ * [Description]
*
- * HISTORY
- * 07/2001 Ported by Wayne Boyer
+ * Verify that, after a successful mmap() call, permission bits of the new
+ * mapping in /proc/pid/maps file matches the prot and flags arguments in
+ * mmap() call.
*/
+#include <inttypes.h>
+#include "tst_test.h"
#include <stdio.h>
-#include <stdlib.h>
-#include <sys/types.h>
-#include <errno.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <string.h>
-#include <signal.h>
-#include <sys/stat.h>
-#include <sys/mman.h>
-#include "test.h"
-
-#define TEMPFILE "mmapfile"
-
-char *TCID = "mmap04";
-int TST_TOTAL = 1;
-
-static size_t page_sz;
-static char *addr;
-static char *dummy;
-static int fildes;
-
-static void setup(void);
-static void cleanup(void);
-
-int main(int ac, char **av)
+static char *addr1;
+static char *addr2;
+
+static struct tcase {
+ int prot;
+ int flags;
+ char *exp_perms;
+} tcases[] = {
+ {PROT_NONE, MAP_ANONYMOUS | MAP_PRIVATE, "---p"},
+ {PROT_NONE, MAP_ANONYMOUS | MAP_SHARED, "---s"},
+ {PROT_READ, MAP_ANONYMOUS | MAP_PRIVATE, "r--p"},
+ {PROT_READ, MAP_ANONYMOUS | MAP_SHARED, "r--s"},
+ {PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, "-w-p"},
+ {PROT_WRITE, MAP_ANONYMOUS | MAP_SHARED, "-w-s"},
+ {PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, "rw-p"},
+ {PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_SHARED, "rw-s"},
+ {PROT_READ | PROT_EXEC, MAP_ANONYMOUS | MAP_PRIVATE, "r-xp"},
+ {PROT_READ | PROT_EXEC, MAP_ANONYMOUS | MAP_SHARED, "r-xs"},
+ {PROT_WRITE | PROT_EXEC, MAP_ANONYMOUS | MAP_PRIVATE, "-wxp"},
+ {PROT_WRITE | PROT_EXEC, MAP_ANONYMOUS | MAP_SHARED, "-wxs"},
+ {PROT_READ | PROT_WRITE | PROT_EXEC, MAP_ANONYMOUS | MAP_PRIVATE, "rwxp"},
+ {PROT_READ | PROT_WRITE | PROT_EXEC, MAP_ANONYMOUS | MAP_SHARED, "rwxs"}
+};
+
+static void run(unsigned int i)
{
- int lc;
-
- tst_parse_opts(ac, av, NULL, NULL);
-
- setup();
-
- for (lc = 0; TEST_LOOPING(lc); lc++) {
-
- tst_count = 0;
-
- /*
- * Call mmap to map the temporary file 'TEMPFILE'
- * with read and execute access.
- */
- errno = 0;
- addr = mmap(0, page_sz, PROT_READ | PROT_EXEC,
- MAP_FILE | MAP_SHARED, fildes, 0);
-
- /* Check for the return value of mmap() */
- if (addr == MAP_FAILED) {
- tst_resm(TFAIL | TERRNO, "mmap of %s failed", TEMPFILE);
- continue;
- }
-
- /*
- * Read the file contents into the dummy
- * variable.
- */
- if (read(fildes, dummy, page_sz) < 0) {
- tst_brkm(TFAIL, cleanup, "reading %s failed",
- TEMPFILE);
- }
-
- /*
- * Check whether the mapped memory region
- * has the file contents.
- */
- if (memcmp(dummy, addr, page_sz)) {
- tst_resm(TFAIL,
- "mapped memory region contains invalid "
- "data");
- } else {
- tst_resm(TPASS,
- "Functionality of mmap() successful");
- }
-
- /* Clean up things in case we are looping. */
- /* Unmap the mapped memory */
- if (munmap(addr, page_sz) != 0) {
- tst_brkm(TFAIL, cleanup, "munmapping failed");
- }
+ struct tcase *tc = &tcases[i];
+ char perms[8];
+ char fmt[1024];
+ unsigned int pagesize;
+ int flag;
+
+ pagesize = SAFE_SYSCONF(_SC_PAGESIZE);
+
+ /* To avoid new mapping getting merged with existing mappings, we first
+ * create a 2-page mapping with the different permissions, and then remap
+ * the 2nd page with the perms being tested.
+ */
+ flag = (tc->flags & MAP_PRIVATE) ? MAP_SHARED : MAP_PRIVATE;
+ addr1 = SAFE_MMAP(NULL, pagesize * 2, PROT_NONE, MAP_ANONYMOUS | flag, -1, 0);
+
+ addr2 = SAFE_MMAP(addr1 + pagesize, pagesize, tc->prot, tc->flags | MAP_FIXED, -1, 0);
+
+ sprintf(fmt, "%" PRIxPTR "-%%*x %%s", (uintptr_t)addr2);
+ SAFE_FILE_LINES_SCANF("/proc/self/maps", fmt, perms);
+
+ if (!strcmp(perms, tc->exp_perms)) {
+ tst_res(TPASS, "mapping permissions in /proc matched: %s", perms);
+ } else {
+ tst_res(TFAIL, "mapping permissions in /proc mismatched, expected: %s, found: %s",
+ tc->exp_perms, perms);
}
- cleanup();
- tst_exit();
+ SAFE_MUNMAP(addr1, pagesize * 2);
}
-static void setup(void)
-{
- char *tst_buff;
-
- tst_sig(NOFORK, DEF_HANDLER, cleanup);
-
- TEST_PAUSE;
-
- page_sz = getpagesize();
-
- if ((tst_buff = calloc(page_sz, sizeof(char))) == NULL) {
- tst_brkm(TFAIL, NULL, "calloc failed (tst_buff)");
- }
-
- /* Fill the test buffer with the known data */
- memset(tst_buff, 'A', page_sz);
-
- tst_tmpdir();
-
- /* Creat a temporary file used for mapping */
- if ((fildes = open(TEMPFILE, O_WRONLY | O_CREAT, 0666)) < 0) {
- free(tst_buff);
- tst_brkm(TFAIL, cleanup, "opening %s failed", TEMPFILE);
- }
-
- /* Write test buffer contents into temporary file */
- if (write(fildes, tst_buff, page_sz) < (ssize_t)page_sz) {
- free(tst_buff);
- tst_brkm(TFAIL, cleanup, "writing to %s failed", TEMPFILE);
- }
-
- /* Free the memory allocated for test buffer */
- free(tst_buff);
-
- /* Make sure proper permissions set on file */
- if (fchmod(fildes, 0555) < 0) {
- tst_brkm(TFAIL, cleanup, "fchmod of %s failed", TEMPFILE);
- }
-
- /* Close the temporary file opened for write */
- if (close(fildes) < 0) {
- tst_brkm(TFAIL, cleanup, "closing %s failed", TEMPFILE);
- }
-
- /* Allocate and initialize dummy string of system page size bytes */
- if ((dummy = calloc(page_sz, sizeof(char))) == NULL) {
- tst_brkm(TFAIL, cleanup, "calloc failed (dummy)");
- }
-
- /* Open the temporary file again for reading */
- if ((fildes = open(TEMPFILE, O_RDONLY)) < 0) {
- tst_brkm(TFAIL, cleanup,
- "opening %s read-only failed", TEMPFILE);
- }
-}
-
-static void cleanup(void)
-{
- close(fildes);
- free(dummy);
- tst_rmdir();
-}
+static struct tst_test test = {
+ .test = run,
+ .tcnt = ARRAY_SIZE(tcases),
+};
diff --git a/testcases/kernel/syscalls/mmap/mmap15.c b/testcases/kernel/syscalls/mmap/mmap15.c
index 443a37eb8..71c18a10a 100644
--- a/testcases/kernel/syscalls/mmap/mmap15.c
+++ b/testcases/kernel/syscalls/mmap/mmap15.c
@@ -1,113 +1,66 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Copyright (c) International Business Machines Corp., 2004
- * Written by Robbie Williamson
- *
- * 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
+ * Written by Robbie Williamson
+ * Copyright (c) 2023 SUSE LLC Avinesh Kumar <avinesh.kumar@suse.com>
+ * Copyright (c) Linux Test Project, 2014-2023
*/
-/*
- * Test Description: Test that a normal page cannot be mapped into a high
- * memory region.
+/*\
+ * [Description]
+ *
+ * Verify that, a normal page cannot be mapped into a high memory region,
+ * and mmap() call fails with either ENOMEM or EINVAL errno.
*/
-#include <sys/types.h>
-#include <sys/mman.h>
-#include <sys/mount.h>
-#include <sys/stat.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <signal.h>
-#include <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-#include "test.h"
-#include "safe_macros.h"
-#include "lapi/abisize.h"
-
-char *TCID = "mmap15";
-int TST_TOTAL = 1;
+#include "tst_test.h"
#ifdef __ia64__
-# define HIGH_ADDR (void *)(0xa000000000000000UL)
+# define HIGH_ADDR ((void *)(0xa000000000000000UL))
#else
-# define HIGH_ADDR (void *)(-page_size)
+# define HIGH_ADDR ((void *)(-page_size))
#endif
-static long page_size;
+#define TEMPFILE "mmapfile"
-static void setup(void);
-static void cleanup(void);
+static long page_size;
+static int fd;
-int main(int ac, char **av)
+static void run(void)
{
- int lc, fd;
- void *addr;
-
-#ifdef TST_ABI32
- tst_brkm(TCONF, NULL, "This test is only for 64bit");
-#endif
+ fd = SAFE_OPEN(TEMPFILE, O_RDWR | O_CREAT, 0666);
- tst_parse_opts(ac, av, NULL, NULL);
+ TESTPTR(mmap(HIGH_ADDR, page_size, PROT_READ, MAP_SHARED | MAP_FIXED, fd, 0));
- setup();
-
- for (lc = 0; TEST_LOOPING(lc); lc++) {
- tst_count = 0;
-
- fd = SAFE_OPEN(cleanup, "testfile", O_RDWR | O_CREAT, 0666);
-
- /* Attempt to mmap into highmem addr, should get ENOMEM */
- addr = mmap(HIGH_ADDR, page_size, PROT_READ,
- MAP_SHARED | MAP_FIXED, fd, 0);
- if (addr != MAP_FAILED) {
- tst_resm(TFAIL, "mmap into high region "
- "succeeded unexpectedly");
- munmap(addr, page_size);
- close(fd);
- continue;
- }
-
- if (errno != ENOMEM && errno != EINVAL) {
- tst_resm(TFAIL | TERRNO, "mmap into high region "
- "failed unexpectedly");
- } else {
- tst_resm(TPASS | TERRNO, "mmap into high region "
- "failed as expected");
- }
-
- SAFE_CLOSE(cleanup, fd);
+ if (TST_RET_PTR != MAP_FAILED) {
+ tst_res(TFAIL, "mmap() into high mem region succeeded unexpectedly");
+ SAFE_MUNMAP(TST_RET_PTR, page_size);
+ return;
}
- cleanup();
- tst_exit();
+ if (TST_ERR == ENOMEM || TST_ERR == EINVAL)
+ tst_res(TPASS | TERRNO, "mmap() failed with expected errno");
+ else
+ tst_res(TFAIL | TERRNO, "mmap() failed with unexpected errno");
+
+ SAFE_CLOSE(fd);
}
static void setup(void)
{
- tst_require_root();
-
- tst_tmpdir();
-
page_size = getpagesize();
-
- TEST_PAUSE;
}
static void cleanup(void)
{
- tst_rmdir();
+ if (fd > 0)
+ SAFE_CLOSE(fd);
}
+
+static struct tst_test test = {
+ .setup = setup,
+ .cleanup = cleanup,
+ .test_all = run,
+ .skip_in_compat = 1,
+ .needs_tmpdir = 1
+};
diff --git a/testcases/kernel/syscalls/mount/mount04.c b/testcases/kernel/syscalls/mount/mount04.c
index 5969fbacb..5eb5ee11b 100644
--- a/testcases/kernel/syscalls/mount/mount04.c
+++ b/testcases/kernel/syscalls/mount/mount04.c
@@ -1,119 +1,50 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Copyright (c) Wipro Technologies Ltd, 2002. All Rights Reserved.
+ * Nirmala Devi Dhanasekar <nirmala.devi@wipro.com>
+ * Copyright (C) 2023 SUSE LLC Andrea Cervesato <andrea.cervesato@suse.com>
+ */
+
+/*\
+ * [Description]
*
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of version 2 of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * DESCRIPTION
- * Verify that mount(2) returns -1 and sets errno to EPERM if the user
- * is not the super-user.
+ * Verify that mount(2) returns -1 and sets errno to EPERM if the user
+ * is not root.
*/
-#include <errno.h>
-#include <sys/mount.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
+#include "tst_test.h"
#include <pwd.h>
-#include "test.h"
-#include "safe_macros.h"
-
-static void setup(void);
-static void cleanup(void);
-
-char *TCID = "mount04";
-
-#define DIR_MODE S_IRWXU | S_IRUSR | S_IXUSR | S_IRGRP | S_IXGRP
-
-static char *mntpoint = "mntpoint";
-static const char *fs_type;
-static const char *device;
-
-int TST_TOTAL = 1;
-
-static void verify_mount(void)
-{
-
- TEST(mount(device, mntpoint, fs_type, 0, NULL));
-
- if (TEST_RETURN == -1) {
- if (TEST_ERRNO == EPERM)
- tst_resm(TPASS | TTERRNO, "mount() failed expectedly");
- else
- tst_resm(TFAIL | TTERRNO,
- "mount() was expected to fail with EPERM");
- return;
- }
+#include <sys/mount.h>
- if (TEST_RETURN == 0) {
- tst_resm(TFAIL, "mount() succeeded unexpectedly");
- if (tst_umount(mntpoint))
- tst_brkm(TBROK, cleanup, "umount() failed");
- return;
- }
+#define MNTPOINT "mntpoint"
- tst_resm(TFAIL | TTERRNO, "mount() returned %li", TEST_RETURN);
-}
-
-int main(int ac, char **av)
+static void cleanup(void)
{
- int lc;
-
- tst_parse_opts(ac, av, NULL, NULL);
-
- setup();
-
- for (lc = 0; TEST_LOOPING(lc); lc++) {
- tst_count = 0;
- verify_mount();
- }
-
- cleanup();
- tst_exit();
+ if (tst_is_mounted(MNTPOINT))
+ SAFE_UMOUNT(MNTPOINT);
}
-static void setup(void)
+static void run(void)
{
- char nobody_uid[] = "nobody";
struct passwd *ltpuser;
- tst_sig(FORK, DEF_HANDLER, cleanup);
-
- tst_require_root();
-
- tst_tmpdir();
+ ltpuser = SAFE_GETPWNAM("nobody");
+ SAFE_SETEUID(ltpuser->pw_uid);
- fs_type = tst_dev_fs_type();
- device = tst_acquire_device(cleanup);
+ TST_EXP_FAIL(
+ mount(tst_device->dev, MNTPOINT, tst_device->fs_type, 0, NULL),
+ EPERM,
+ "mount() failed expectedly for normal user"
+ );
- if (!device)
- tst_brkm(TCONF, cleanup, "Failed to obtain block device");
-
- tst_mkfs(cleanup, device, fs_type, NULL, NULL);
-
- ltpuser = SAFE_GETPWNAM(cleanup, nobody_uid);
- SAFE_SETEUID(cleanup, ltpuser->pw_uid);
- SAFE_MKDIR(cleanup, mntpoint, DIR_MODE);
-
- TEST_PAUSE;
+ if (tst_is_mounted(MNTPOINT))
+ SAFE_UMOUNT(MNTPOINT);
}
-static void cleanup(void)
-{
- if (seteuid(0))
- tst_resm(TWARN | TERRNO, "seteuid(0) failed");
-
- if (device)
- tst_release_device(device);
-
- tst_rmdir();
-}
+static struct tst_test test = {
+ .cleanup = cleanup,
+ .test_all = run,
+ .needs_root = 1,
+ .format_device = 1,
+ .mntpoint = MNTPOINT,
+};
diff --git a/testcases/kernel/syscalls/mount/mount05.c b/testcases/kernel/syscalls/mount/mount05.c
index ca26f9738..616eeee79 100644
--- a/testcases/kernel/syscalls/mount/mount05.c
+++ b/testcases/kernel/syscalls/mount/mount05.c
@@ -1,131 +1,72 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
/*
- * Copyright (c) 2013 Fujitsu Ltd.
- * Author: DAN LI <li.dan@cn.fujitsu.com>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of version 2 of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ * Copyright (c) 2013 Fujitsu Ltd. Dan Li <li.dan@cn.fujitsu.com>
+ * Copyright (C) 2023 SUSE LLC Andrea Cervesato <andrea.cervesato@suse.com>
*/
-/*
- * DESCRIPTION
- * Test for feature MS_BIND of mount.
- * "Perform a bind mount, making a file or a directory subtree visible
- * at another point within a file system."
+/*\
+ * [Description]
+ *
+ * Test for feature MS_BIND of mount, which performs a bind mount, making a file
+ * or a directory subtree visible at another point within a file system.
*/
-#include <errno.h>
+#include "tst_test.h"
#include <sys/mount.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <unistd.h>
-#include <fcntl.h>
-
-#include "test.h"
-#include "safe_macros.h"
-
-static void help(void);
-static void setup(void);
-static void cleanup(void);
-char *TCID = "mount05";
-int TST_TOTAL = 1;
+#define MNTPOINT1 "mntpoint1"
+#define TESTFILE1 MNTPOINT1 "/testfile"
+#define TESTDIR1 MNTPOINT1 "/testdir"
-#define DIR_MODE (S_IRWXU | S_IRUSR | S_IXUSR | S_IRGRP | S_IXGRP)
+#define MNTPOINT2 "mntpoint2"
+#define TESTFILE2 MNTPOINT2 "/testfile"
+#define TESTDIR2 MNTPOINT2 "/testdir"
-static int dflag;
-static char *fstype = "ext2";
-static char *device;
-static const char file_src[] = "mnt_src/tstfile";
-static const char file_des[] = "mnt_des/tstfile";
-static const char mntpoint_src[] = "mnt_src";
-static const char mntpoint_des[] = "mnt_des";
-
-static option_t options[] = {
- {"T:", NULL, &fstype},
- {"D:", &dflag, &device},
- {NULL, NULL, NULL},
-};
-
-int main(int argc, char *argv[])
+static void setup(void)
{
- int lc;
-
- tst_parse_opts(argc, argv, options, &help);
-
- setup();
-
- for (lc = 0; TEST_LOOPING(lc); lc++) {
-
- tst_count = 0;
+ SAFE_MOUNT(tst_device->dev, MNTPOINT1, tst_device->fs_type, 0, NULL);
- TEST(mount(mntpoint_src, mntpoint_des, fstype, MS_BIND, NULL));
+ tst_res(TINFO, "Creating file in '%s'", TESTFILE1);
- if (TEST_RETURN != 0) {
- tst_resm(TFAIL | TTERRNO, "mount(2) failed");
- } else {
-
- if (open(file_des, O_CREAT | O_EXCL, S_IRWXU) == -1 &&
- errno == EEXIST)
- tst_resm(TPASS, "bind mount is ok");
- else
- tst_resm(TFAIL, "file %s is not available",
- file_des);
-
- TEST(tst_umount(mntpoint_des));
- if (TEST_RETURN != 0)
- tst_brkm(TBROK | TTERRNO, cleanup,
- "umount(2) failed");
- }
- }
-
- cleanup();
- tst_exit();
+ SAFE_FILE_PRINTF(TESTFILE1, "LTP TEST FILE");
+ SAFE_MKDIR(TESTDIR1, 0750);
}
-void setup(void)
+static void cleanup(void)
{
- tst_require_root();
-
- tst_sig(NOFORK, DEF_HANDLER, cleanup);
-
- tst_tmpdir();
-
- SAFE_MKDIR(cleanup, mntpoint_src, DIR_MODE);
- SAFE_MKDIR(cleanup, mntpoint_des, DIR_MODE);
-
- if (dflag) {
- tst_mkfs(NULL, device, fstype, NULL, NULL);
+ if (tst_is_mounted(MNTPOINT1))
+ SAFE_UMOUNT(MNTPOINT1);
- SAFE_MOUNT(cleanup, device, mntpoint_src, fstype, 0, NULL);
- }
-
- SAFE_FILE_PRINTF(cleanup, file_src, "TEST FILE");
-
- TEST_PAUSE;
+ if (tst_is_mounted(MNTPOINT2))
+ SAFE_UMOUNT(MNTPOINT2);
}
-void cleanup(void)
+static void run(void)
{
- if (dflag)
- if (tst_umount(mntpoint_src) != 0)
- tst_brkm(TBROK | TTERRNO, NULL, "umount(2) failed");
+ SAFE_MKDIR(MNTPOINT2, 0750);
+ SAFE_MOUNT(MNTPOINT1, MNTPOINT2, tst_device->fs_type, MS_BIND, NULL);
- tst_rmdir();
-}
+ TST_EXP_PASS(access(TESTFILE2, F_OK), "Accessing to '%s'", TESTFILE2);
+ TST_EXP_PASS(access(TESTDIR2, F_OK), "Accessing to '%s'", TESTDIR2);
-void help(void)
-{
- printf("-T type : specifies the type of filesystem to be mounted. "
- "Default ext2.\n");
- printf("-D device : device used for mounting.\n");
+ if (tst_is_mounted(MNTPOINT2))
+ SAFE_UMOUNT(MNTPOINT2);
+
+ SAFE_RMDIR(MNTPOINT2);
}
+
+static struct tst_test test = {
+ .setup = setup,
+ .cleanup = cleanup,
+ .test_all = run,
+ .needs_root = 1,
+ .format_device = 1,
+ .mntpoint = MNTPOINT1,
+ .all_filesystems = 1,
+ .skip_filesystems = (const char *const []){
+ "exfat",
+ "vfat",
+ "ntfs",
+ NULL
+ },
+};
diff --git a/testcases/kernel/syscalls/mount/mount06.c b/testcases/kernel/syscalls/mount/mount06.c
index 857f5f905..2376deab3 100644
--- a/testcases/kernel/syscalls/mount/mount06.c
+++ b/testcases/kernel/syscalls/mount/mount06.c
@@ -1,34 +1,19 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
/*
- * Copyright (c) 2013 Fujitsu Ltd.
- * Author: DAN LI <li.dan@cn.fujitsu.com>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of version 2 of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ * Copyright (c) 2013 Fujitsu Ltd. Dan Li <li.dan@cn.fujitsu.com>
+ * Copyright (C) 2023 SUSE LLC Andrea Cervesato <andrea.cervesato@suse.com>
*/
-/*
- * DESCRIPTION
- * Test for feature MS_MOVE of mount(2).
- * "Move an existing mount point to the new location."
+/*\
+ * [Description]
+ *
+ * Test for feature MS_MOVE of mount, which moves an existing mount point to
+ * a new location.
*/
-#include <errno.h>
+#include "tst_test.h"
+#include <stdio.h>
#include <sys/mount.h>
-#include <unistd.h>
-#include <fcntl.h>
-
-#include "test.h"
-#include "safe_macros.h"
#ifndef MS_MOVE
#define MS_MOVE 8192
@@ -38,126 +23,86 @@
#define MS_PRIVATE (1 << 18)
#endif
-#define MNTPOINT_SRC "mnt_src"
-#define MNTPOINT_DES "mnt_des"
-#define LINELENGTH 256
-#define DIR_MODE (S_IRWXU | S_IRUSR | S_IXUSR | S_IRGRP | S_IXGRP)
-
-static int ismount(char *mntpoint);
-static void setup(void);
-static void cleanup(void);
+#define MNTPOINT_SRC "mntpoint1"
+#define MNTPOINT_DST "mntpoint2"
-char *TCID = "mount06";
-int TST_TOTAL = 1;
-
-static const char *fs_type;
-static const char *device;
-static char path_name[PATH_MAX];
+static char *tmppath;
static char mntpoint_src[PATH_MAX];
-static char mntpoint_des[PATH_MAX];
-static int mount_flag;
+static char mntpoint_dst[PATH_MAX];
+static char tstfiles_src[PATH_MAX];
+static char tstfiles_dst[PATH_MAX];
-int main(int argc, char *argv[])
+static void setup(void)
{
- int lc;
+ tmppath = tst_get_tmpdir();
- tst_parse_opts(argc, argv, NULL, NULL);
-
- setup();
-
- for (lc = 0; TEST_LOOPING(lc); lc++) {
-
- tst_count = 0;
-
- SAFE_MOUNT(cleanup, device, mntpoint_src, fs_type, 0, NULL);
-
- TEST(mount(mntpoint_src, mntpoint_des, fs_type, MS_MOVE, NULL));
-
- if (TEST_RETURN != 0) {
- tst_resm(TFAIL | TTERRNO, "mount(2) failed");
- } else {
-
- if (!ismount(mntpoint_src) && ismount(mntpoint_des))
- tst_resm(TPASS, "move mount is ok");
- else
- tst_resm(TFAIL, "move mount does not work");
+ /*
+ * Turn current dir into a private mount point being a parent
+ * mount which is required by move mount.
+ */
+ SAFE_MOUNT(tmppath, tmppath, "none", MS_BIND, NULL);
+ SAFE_MOUNT("none", tmppath, "none", MS_PRIVATE, NULL);
- TEST(tst_umount(mntpoint_des));
- if (TEST_RETURN != 0)
- tst_brkm(TBROK | TTERRNO, cleanup,
- "umount(2) failed");
- }
- }
+ snprintf(mntpoint_src, PATH_MAX, "%s/%s", tmppath, MNTPOINT_SRC);
+ snprintf(mntpoint_dst, PATH_MAX, "%s/%s", tmppath, MNTPOINT_DST);
- cleanup();
- tst_exit();
-}
+ snprintf(tstfiles_src, PATH_MAX, "%s/%s/testfile", tmppath, MNTPOINT_SRC);
+ snprintf(tstfiles_dst, PATH_MAX, "%s/%s/testfile", tmppath, MNTPOINT_DST);
-int ismount(char *mntpoint)
-{
- int ret = 0;
- FILE *file;
- char line[LINELENGTH];
-
- file = fopen("/proc/mounts", "r");
- if (file == NULL)
- tst_brkm(TFAIL | TERRNO, NULL, "Open /proc/mounts failed");
-
- while (fgets(line, LINELENGTH, file) != NULL) {
- if (strstr(line, mntpoint) != NULL) {
- ret = 1;
- break;
- }
- }
- fclose(file);
- return ret;
+ SAFE_MKDIR(mntpoint_dst, 0750);
}
-static void setup(void)
+static void cleanup(void)
{
- tst_require_root();
+ if (tst_is_mounted(mntpoint_src))
+ SAFE_UMOUNT(mntpoint_src);
- tst_sig(NOFORK, DEF_HANDLER, cleanup);
+ if (tst_is_mounted(mntpoint_dst))
+ SAFE_UMOUNT(mntpoint_dst);
- tst_tmpdir();
+ if (tst_is_mounted(tmppath))
+ SAFE_UMOUNT(tmppath);
- fs_type = tst_dev_fs_type();
- device = tst_acquire_device(cleanup);
-
- if (!device)
- tst_brkm(TCONF, cleanup, "Failed to obtain block device");
-
- tst_mkfs(cleanup, device, fs_type, NULL, NULL);
-
- if (getcwd(path_name, sizeof(path_name)) == NULL)
- tst_brkm(TBROK, cleanup, "getcwd failed");
+ SAFE_RMDIR(mntpoint_dst);
+}
- /*
- * Turn current dir into a private mount point being a parent
- * mount which is required by move mount.
- */
- SAFE_MOUNT(cleanup, path_name, path_name, "none", MS_BIND, NULL);
+static void run(void)
+{
+ SAFE_MOUNT(tst_device->dev, mntpoint_src, tst_device->fs_type, 0, NULL);
+ SAFE_FILE_PRINTF(tstfiles_src, "LTP TEST FILE");
- mount_flag = 1;
+ SAFE_MOUNT(mntpoint_src, mntpoint_dst, tst_device->fs_type, MS_MOVE, NULL);
- SAFE_MOUNT(cleanup, "none", path_name, "none", MS_PRIVATE, NULL);
+ TST_EXP_FAIL(
+ access(tstfiles_src, F_OK),
+ ENOENT,
+ "File %s doesn't exist",
+ tstfiles_src);
- snprintf(mntpoint_src, PATH_MAX, "%s/%s", path_name, MNTPOINT_SRC);
- snprintf(mntpoint_des, PATH_MAX, "%s/%s", path_name, MNTPOINT_DES);
+ TST_EXP_PASS(
+ access(tstfiles_dst, F_OK),
+ "File %s exists :",
+ tstfiles_dst);
- SAFE_MKDIR(cleanup, mntpoint_src, DIR_MODE);
- SAFE_MKDIR(cleanup, mntpoint_des, DIR_MODE);
+ if (tst_is_mounted(mntpoint_src))
+ SAFE_UMOUNT(mntpoint_src);
- TEST_PAUSE;
+ if (tst_is_mounted(mntpoint_dst))
+ SAFE_UMOUNT(mntpoint_dst);
}
-static void cleanup(void)
-{
- if (mount_flag && tst_umount(path_name) != 0)
- tst_resm(TWARN | TERRNO, "umount(2) %s failed", path_name);
-
- if (device)
- tst_release_device(device);
-
- tst_rmdir();
-}
+static struct tst_test test = {
+ .setup = setup,
+ .cleanup = cleanup,
+ .test_all = run,
+ .needs_root = 1,
+ .format_device = 1,
+ .mntpoint = MNTPOINT_SRC,
+ .all_filesystems = 1,
+ .skip_filesystems = (const char *const []){
+ "exfat",
+ "vfat",
+ "ntfs",
+ NULL
+ },
+};
diff --git a/testcases/kernel/syscalls/mremap/mremap06.c b/testcases/kernel/syscalls/mremap/mremap06.c
index a19262750..3bbaf441a 100644
--- a/testcases/kernel/syscalls/mremap/mremap06.c
+++ b/testcases/kernel/syscalls/mremap/mremap06.c
@@ -18,15 +18,16 @@
#include <stdio.h>
#include <fcntl.h>
#include <sys/mman.h>
+#include <lapi/mmap.h>
#include "tst_test.h"
#include "tst_safe_macros.h"
-#define NUM_PAGES 3
+#define NUM_GRANULARITYS 3
static int fd;
static char *buf, *buf2;
-static int page_size, mmap_size, mremap_size;
+static int mmap_size, mremap_size;
static struct tcase {
size_t incompatible;
@@ -37,11 +38,11 @@ static struct tcase {
},
{
.incompatible = 3,
- .desc = "third page's mapping incompatible",
+ .desc = "third MMAP_GRANULARITY's mapping incompatible",
},
{
.incompatible = 1,
- .desc = "first page's mapping incompatible",
+ .desc = "first MMAP_GRANULARITY's mapping incompatible",
},
};
@@ -51,7 +52,7 @@ static int check_pages(void)
char val;
for (i = 0; i < (int)ARRAY_SIZE(tcases); i++) {
- val = buf[i * page_size];
+ val = buf[i * MMAP_GRANULARITY];
if (val != 0x30 + i) {
tst_res(TFAIL, "page %d wrong value %d (0x%x)", i, val - 0x30, val);
fail = 1;
@@ -70,19 +71,20 @@ static void do_test(unsigned int n)
buf = SAFE_MMAP(0, mmap_size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
- buf2 = mremap(buf + page_size, page_size, page_size,
+ buf2 = mremap(buf + MMAP_GRANULARITY, MMAP_GRANULARITY, MMAP_GRANULARITY,
MREMAP_MAYMOVE|MREMAP_FIXED, buf + mremap_size);
if (buf2 == MAP_FAILED)
tst_brk(TBROK, "mremap() failed");
if (tc->incompatible) {
- ret = mprotect(buf + (tc->incompatible-1)*page_size, page_size, PROT_READ);
+ ret = mprotect(buf + (tc->incompatible-1)*MMAP_GRANULARITY,
+ MMAP_GRANULARITY, PROT_READ);
if (ret == -1)
tst_brk(TBROK, "mprotect() failed");
}
- buf2 = mremap(buf + mremap_size, page_size, page_size,
- MREMAP_MAYMOVE|MREMAP_FIXED, buf + page_size);
+ buf2 = mremap(buf + mremap_size, MMAP_GRANULARITY, MMAP_GRANULARITY,
+ MREMAP_MAYMOVE|MREMAP_FIXED, buf + MMAP_GRANULARITY);
if (buf2 == MAP_FAILED)
tst_brk(TBROK, "mremap() failed");
@@ -96,9 +98,8 @@ static void setup(void)
{
int ret, i;
- page_size = getpagesize();
- mmap_size = (NUM_PAGES+1) * page_size;
- mremap_size = NUM_PAGES * page_size;
+ mmap_size = (NUM_GRANULARITYS+1) * MMAP_GRANULARITY;
+ mremap_size = NUM_GRANULARITYS * MMAP_GRANULARITY;
fd = SAFE_OPEN("testfile", O_CREAT | O_RDWR | O_TRUNC, 0600);
@@ -109,7 +110,7 @@ static void setup(void)
buf = SAFE_MMAP(0, mmap_size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
for (i = 0; i < (int)ARRAY_SIZE(tcases)+1; i++)
- buf[i*page_size] = 0x30 + i;
+ buf[i*MMAP_GRANULARITY] = 0x30 + i;
/* clear the page tables */
SAFE_MUNMAP(buf, mmap_size);
diff --git a/testcases/kernel/syscalls/open/open11.c b/testcases/kernel/syscalls/open/open11.c
index 3c3c11b84..3431efc2c 100644
--- a/testcases/kernel/syscalls/open/open11.c
+++ b/testcases/kernel/syscalls/open/open11.c
@@ -1,28 +1,34 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Copyright (C) 2013 Red Hat, Inc.
+ * Copyright (c) Linux Test Project, 2013-2022
+ */
+
+/*\
+ * [Description]
*
* Basic tests for open(2) and make sure open(2) works and handles error
* conditions correctly.
*
* There are 28 test cases:
+ *
* 1. Open regular file O_RDONLY
* 2. Open regular file O_WRONLY
* 3. Open regular file O_RDWR
* 4. Open regular file O_RDWR | O_SYNC
* 5. Open regular file O_RDWR | O_TRUNC
- * 6. Open dir O_RDONLY
- * 7. Open dir O_RDWR, expect EISDIR
+ * 6. Open directory O_RDONLY
+ * 7. Open directory O_RDWR, expect EISDIR
* 8. Open regular file O_DIRECTORY, expect ENOTDIR
* 9. Open hard link file O_RDONLY
* 10. Open hard link file O_WRONLY
* 11. Open hard link file O_RDWR
- * 12. Open sym link file O_RDONLY
- * 13. Open sym link file O_WRONLY
- * 14. Open sym link file O_RDWR
- * 15. Open sym link dir O_RDONLY
- * 16. Open sym link dir O_WRONLY, expect EISDIR
- * 17. Open sym link dir O_RDWR, expect EISDIR
+ * 12. Open symlink file O_RDONLY
+ * 13. Open symlink file O_WRONLY
+ * 14. Open symlink file O_RDWR
+ * 15. Open symlink directory O_RDONLY
+ * 16. Open symlink directory O_WRONLY, expect EISDIR
+ * 17. Open symlink directory O_RDWR, expect EISDIR
* 18. Open device special file O_RDONLY
* 19. Open device special file O_WRONLY
* 20. Open device special file O_RDWR
@@ -30,8 +36,8 @@
* 22. Open link file O_RDONLY | O_CREAT
* 23. Open symlink file O_RDONLY | O_CREAT
* 24. Open regular file O_RDONLY | O_CREAT
- * 25. Open symlink dir O_RDONLY | O_CREAT, expect EISDIR
- * 26. Open dir O_RDONLY | O_CREAT, expect EISDIR
+ * 25. Open symlink directory O_RDONLY | O_CREAT, expect EISDIR
+ * 26. Open directory O_RDONLY | O_CREAT, expect EISDIR
* 27. Open regular file O_RDONLY | O_TRUNC, behaviour is undefined but should
* not oops or hang
* 28. Open regular file(non-empty) O_RDONLY | O_TRUNC, behaviour is undefined
@@ -54,7 +60,7 @@
#define T_LINK_REG "t_link_reg" /* hard link to T_REG */
#define T_NEW_REG "t_new_reg" /* new regular file to be created */
#define T_SYMLINK_REG "t_symlink_reg" /* symlink to T_REG */
-#define T_DIR "t_dir" /* test dir */
+#define T_DIR "t_dir" /* test directory */
#define T_SYMLINK_DIR "t_symlink_dir" /* symlink to T_DIR */
#define T_DEV MNTPOINT"/t_dev" /* test device special file */
@@ -68,205 +74,191 @@ static struct test_case {
int err;
} tc[] = {
/* Test open(2) regular file */
- { /* open regular file O_RDONLY */
- .desc = "Open regular file O_RDONLY",
+ {
+ .desc = "open regular file O_RDONLY",
.path = T_REG_EMPTY,
.flags = O_RDONLY,
.mode = 0644,
- .err = 0,
},
- { /* open regular file O_WRONLY */
- .desc = "Open regular file O_WRONLY",
+ {
+ .desc = "open regular file O_WRONLY",
.path = T_REG_EMPTY,
.flags = O_WRONLY,
.mode = 0644,
- .err = 0,
},
- { /* open regular file O_RDWR */
- .desc = "Open regular file O_RDWR",
+ {
+ .desc = "open regular file O_RDWR",
.path = T_REG_EMPTY,
.flags = O_RDWR,
.mode = 0644,
- .err = 0,
},
- { /* open regular file O_RDWR | O_SYNC*/
- .desc = "Open regular file O_RDWR | O_SYNC",
+ {
+ .desc = "open regular file O_RDWR | O_SYNC",
.path = T_REG_EMPTY,
.flags = O_RDWR | O_SYNC,
.mode = 0644,
- .err = 0,
},
- { /* open regular file O_RDWR | O_TRUNC */
- .desc = "Open regular file O_RDWR | O_TRUNC",
+ {
+ .desc = "open regular file O_RDWR | O_TRUNC",
.path = T_REG_EMPTY,
.flags = O_RDWR | O_TRUNC,
.mode = 0644,
- .err = 0,
},
+
/* Test open(2) directory */
- { /* open dir O_RDONLY */
- .desc = "Open dir O_RDONLY",
+ {
+ .desc = "open directory O_RDONLY",
.path = T_DIR,
.flags = O_RDONLY,
.mode = 0755,
- .err = 0,
},
- { /* open dir O_RDWR */
- .desc = "Open dir O_RDWR, expect EISDIR",
+ {
+ .desc = "open directory O_RDWR",
.path = T_DIR,
.flags = O_RDWR,
.mode = 0755,
.err = EISDIR,
},
- { /* open regular file O_DIRECTORY */
- .desc = "Open regular file O_DIRECTORY, expect ENOTDIR",
+ {
+ .desc = "open regular file O_DIRECTORY",
.path = T_REG_EMPTY,
.flags = O_RDONLY | O_DIRECTORY,
.mode = 0644,
.err = ENOTDIR,
},
/* Test open(2) hard link */
- { /* open hard link file O_RDONLY */
- .desc = "Open hard link file O_RDONLY",
+ {
+ .desc = "open hard link file O_RDONLY",
.path = T_LINK_REG,
.flags = O_RDONLY,
.mode = 0644,
- .err = 0,
},
- { /* open hard link file O_WRONLY */
- .desc = "Open hard link file O_WRONLY",
+ {
+ .desc = "open hard link file O_WRONLY",
.path = T_LINK_REG,
.flags = O_WRONLY,
.mode = 0644,
- .err = 0,
},
- { /* open hard link file O_RDWR */
- .desc = "Open hard link file O_RDWR",
+ {
+ .desc = "open hard link file O_RDWR",
.path = T_LINK_REG,
.flags = O_RDWR,
.mode = 0644,
- .err = 0,
},
- /* Test open(2) sym link */
- { /* open sym link file O_RDONLY */
- .desc = "Open sym link file O_RDONLY",
+
+ /* Test open(2) symlink */
+ {
+ .desc = "open symlink file O_RDONLY",
.path = T_SYMLINK_REG,
.flags = O_RDONLY,
.mode = 0644,
- .err = 0,
},
- { /* open sym link file O_WRONLY */
- .desc = "Open sym link file O_WRONLY",
+ {
+ .desc = "open symlink file O_WRONLY",
.path = T_SYMLINK_REG,
.flags = O_WRONLY,
.mode = 0644,
- .err = 0,
},
- { /* open sym link file O_RDWR */
- .desc = "Open sym link file O_RDWR",
+ {
+ .desc = "open symlink file O_RDWR",
.path = T_SYMLINK_REG,
.flags = O_RDWR,
.mode = 0644,
- .err = 0,
},
- { /* open sym link dir O_RDONLY */
- .desc = "Open sym link dir O_RDONLY",
+ {
+ .desc = "open symlink directory O_RDONLY",
.path = T_SYMLINK_DIR,
.flags = O_RDONLY,
.mode = 0644,
- .err = 0,
},
- { /* open sym link dir O_WRONLY */
- .desc = "Open sym link dir O_WRONLY, expect EISDIR",
+ {
+ .desc = "open symlink directory O_WRONLY",
.path = T_SYMLINK_DIR,
.flags = O_WRONLY,
.mode = 0644,
.err = EISDIR,
},
- { /* open sym link dir O_RDWR */
- .desc = "Open sym link dir O_RDWR, expect EISDIR",
+ {
+ .desc = "open symlink directory O_RDWR",
.path = T_SYMLINK_DIR,
.flags = O_RDWR,
.mode = 0644,
.err = EISDIR,
},
- /* * Test open(2) device special */
- { /* open device special file O_RDONLY */
- .desc = "Open device special file O_RDONLY",
+
+ /* Test open(2) device special */
+ {
+ .desc = "open device special file O_RDONLY",
.path = T_DEV,
.flags = O_RDONLY,
.mode = 0644,
- .err = 0,
},
- { /* open device special file O_WRONLY */
- .desc = "Open device special file O_WRONLY",
+ {
+ .desc = "open device special file O_WRONLY",
.path = T_DEV,
.flags = O_WRONLY,
.mode = 0644,
- .err = 0,
},
- { /* open device special file O_RDWR */
- .desc = "Open device special file O_RDWR",
+ {
+ .desc = "open device special file O_RDWR",
.path = T_DEV,
.flags = O_RDWR,
.mode = 0644,
- .err = 0,
},
- /* * Test open(2) non-existing file */
- { /* open non-existing regular file in existing dir */
- .desc = "Open non-existing regular file in existing dir",
+
+ /* Test open(2) non-existing file */
+ {
+ .desc = "open non-existing regular file in existing dir",
.path = T_DIR"/"T_NEW_REG,
.flags = O_RDWR | O_CREAT,
.mode = 0644,
- .err = 0,
},
+
/* test open(2) with O_CREAT */
- { /* open hard link file O_RDONLY | O_CREAT */
- .desc = "Open link file O_RDONLY | O_CREAT",
+ {
+ .desc = "open link file O_RDONLY | O_CREAT",
.path = T_LINK_REG,
.flags = O_RDONLY | O_CREAT,
.mode = 0644,
- .err = 0,
},
- { /* open sym link file O_RDONLY | O_CREAT */
- .desc = "Open symlink file O_RDONLY | O_CREAT",
+ {
+ .desc = "open symlink file O_RDONLY | O_CREAT",
.path = T_SYMLINK_REG,
.flags = O_RDONLY | O_CREAT,
.mode = 0644,
- .err = 0,
},
- { /* open regular file O_RDONLY | O_CREAT */
- .desc = "Open regular file O_RDONLY | O_CREAT",
+ {
+ .desc = "open regular file O_RDONLY | O_CREAT",
.path = T_REG_EMPTY,
.flags = O_RDONLY | O_CREAT,
.mode = 0644,
- .err = 0,
},
- { /* open symlink dir O_RDONLY | O_CREAT */
- .desc = "Open symlink dir O_RDONLY | O_CREAT, expect EISDIR",
+ {
+ .desc = "open symlink directory O_RDONLY | O_CREAT",
.path = T_SYMLINK_DIR,
.flags = O_RDONLY | O_CREAT,
.mode = 0644,
.err = EISDIR,
},
- { /* open dir O_RDONLY | O_CREAT */
- .desc = "Open dir O_RDONLY | O_CREAT, expect EISDIR",
+ {
+ .desc = "open directory O_RDONLY | O_CREAT",
.path = T_DIR,
.flags = O_RDONLY | O_CREAT,
.mode = 0644,
.err = EISDIR,
},
+
/* Other random open(2) tests */
- { /* open regular file O_RDONLY | O_TRUNC */
- .desc = "Open regular file O_RDONLY | O_TRUNC, "
+ {
+ .desc = "open regular file O_RDONLY | O_TRUNC, "
"behaviour is undefined but should not oops or hang",
.path = T_REG_EMPTY,
.flags = O_RDONLY | O_TRUNC,
.mode = 0644,
.err = -1,
},
- { /* open regular(non-empty) file O_RDONLY | O_TRUNC */
- .desc = "Open regular file(non-empty) O_RDONLY | O_TRUNC, "
+ {
+ .desc = "open regular file(non-empty) O_RDONLY | O_TRUNC, "
"behaviour is undefined but should not oops or hang",
.path = T_REG,
.flags = O_RDONLY | O_TRUNC,
diff --git a/testcases/kernel/syscalls/pathconf/.gitignore b/testcases/kernel/syscalls/pathconf/.gitignore
index 31abe8a28..82e38b253 100644
--- a/testcases/kernel/syscalls/pathconf/.gitignore
+++ b/testcases/kernel/syscalls/pathconf/.gitignore
@@ -1 +1,2 @@
/pathconf01
+/pathconf02
diff --git a/testcases/kernel/syscalls/pathconf/pathconf01.c b/testcases/kernel/syscalls/pathconf/pathconf01.c
index 362bae94f..66b8d1fc1 100644
--- a/testcases/kernel/syscalls/pathconf/pathconf01.c
+++ b/testcases/kernel/syscalls/pathconf/pathconf01.c
@@ -1,237 +1,68 @@
+// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (c) 2000 Silicon Graphics, Inc. All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of version 2 of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- *
- * Further, this software is distributed without any warranty that it is
- * free of the rightful claim of any third person regarding infringement
- * or the like. Any license provided herein, whether implied or
- * otherwise, applies only to this software file. Patent licenses, if
- * any, provided herein do not apply to combinations of this program with
- * other software, or any other product whatsoever.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
- * Mountain View, CA 94043, or:
- *
- * http://www.sgi.com
- *
- * For further information regarding this notice, see:
- *
- * http://oss.sgi.com/projects/GenInfo/NoticeExplan/
- *
+ * Copyright (c) Linux Test Project, 2000-2023
+ * Authors: William Roske, Dave Fenner
*/
-/* $Id: pathconf01.c,v 1.5 2009/11/02 13:57:17 subrata_modak Exp $ */
-/**********************************************************
- *
- * OS Test - Silicon Graphics, Inc.
- *
- * TEST IDENTIFIER : pathconf01
- *
- * EXECUTED BY : anyone
- *
- * TEST TITLE : Basic test for pathconf(2)
- *
- * PARENT DOCUMENT : usctpl01
- *
- * TEST CASE TOTAL : 6
- *
- * WALL CLOCK TIME : 1
- *
- * CPU TYPES : ALL
- *
- * AUTHOR : William Roske
- *
- * CO-PILOT : Dave Fenner
- *
- * DATE STARTED : 03/30/92
- *
- * INITIAL RELEASE : UNICOS 7.0
- *
- * TEST CASES
- *
- * 1.) pathconf(2) returns...(See Description)
- *
- * INPUT SPECIFICATIONS
- * The standard options for system call tests are accepted.
- * (See the parse_opts(3) man page).
- *
- * OUTPUT SPECIFICATIONS
- *
- * DURATION
- * Terminates - with frequency and infinite modes.
- *
- * SIGNALS
- * Uses SIGUSR1 to pause before test if option set.
- * (See the parse_opts(3) man page).
- *
- * RESOURCES
- * None
- *
- * ENVIRONMENTAL NEEDS
- * No run-time environmental needs.
- *
- * SPECIAL PROCEDURAL REQUIREMENTS
- * None
- *
- * INTERCASE DEPENDENCIES
- * None
- *
- * DETAILED DESCRIPTION
- * This is a Phase I test for the pathconf(2) system call. It is intended
- * to provide a limited exposure of the system call, for now. It
- * should/will be extended when full functional tests are written for
- * pathconf(2).
- *
- * Setup:
- * Setup signal handling.
- * Pause for SIGUSR1 if option specified.
- *
- * Test:
- * Loop if the proper options are given.
- * Execute system call
- * Check return code, if system call failed (return=-1)
- * Log the errno and Issue a FAIL message.
- * Otherwise, Issue a PASS message.
- *
- * Cleanup:
- * Print errno log and/or timing stats if options given
- *
- *
- *#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#**/
-
-#include <unistd.h>
-#include <errno.h>
-#include <string.h>
-#include <signal.h>
-#include "test.h"
-void setup();
-void cleanup();
-void help();
-
-struct pathconf_args {
- char *define_tag;
- int value;
-} args[] = {
- {
- "_PC_LINK_MAX", _PC_LINK_MAX}, {
- "_PC_NAME_MAX", _PC_NAME_MAX}, {
- "_PC_PATH_MAX", _PC_PATH_MAX}, {
- "_PC_PIPE_BUF", _PC_PIPE_BUF}, {
- "_PC_CHOWN_RESTRICTED", _PC_CHOWN_RESTRICTED}, {
- "_PC_NO_TRUNC", _PC_NO_TRUNC}, {
- NULL, 0}
-};
-
-char *TCID = "pathconf01";
-int TST_TOTAL = ARRAY_SIZE(args);
+/*\
+ * [Description]
+ *
+ * Check the basic functionality of the pathconf(2) system call.
+ */
-int i;
+#include <stdlib.h>
+#include "tst_test.h"
+#define NAME_DESC(x) .value = x, .name = #x
-int lflag;
-char *path;
+static char *path;
-option_t options[] = {
- {"l:", &lflag, &path}, /* -l <path to test> */
- {NULL, NULL, NULL}
+static struct tcase {
+ int value;
+ char *name;
+} tcases[] = {
+ {NAME_DESC(_PC_LINK_MAX)},
+ {NAME_DESC(_PC_MAX_CANON)},
+ {NAME_DESC(_PC_MAX_INPUT)},
+ {NAME_DESC(_PC_NAME_MAX)},
+ {NAME_DESC(_PC_PATH_MAX)},
+ {NAME_DESC(_PC_PIPE_BUF)},
+ {NAME_DESC(_PC_CHOWN_RESTRICTED)},
+ {NAME_DESC(_PC_NO_TRUNC)},
+ {NAME_DESC(_PC_VDISABLE)},
+ {NAME_DESC(_PC_SYNC_IO)},
+ {NAME_DESC(_PC_ASYNC_IO)},
+ {NAME_DESC(_PC_PRIO_IO)},
+ {NAME_DESC(_PC_FILESIZEBITS)},
+ {NAME_DESC(_PC_REC_INCR_XFER_SIZE)},
+ {NAME_DESC(_PC_REC_MAX_XFER_SIZE)},
+ {NAME_DESC(_PC_REC_MIN_XFER_SIZE)},
+ {NAME_DESC(_PC_REC_XFER_ALIGN)},
};
-int main(int ac, char **av)
+static void verify_pathconf(unsigned int i)
{
- int lc;
+ struct tcase *tc = &tcases[i];
- tst_parse_opts(ac, av, options, &help);
+ path = tst_get_tmpdir();
- if (!lflag) {
- tst_tmpdir();
- path = tst_get_tmpdir();
- }
- /***************************************************************
- * perform global setup for test
- ***************************************************************/
- setup();
+ TEST(pathconf(path, tc->value));
- /***************************************************************
- * check looping state if -c option given
- ***************************************************************/
- for (lc = 0; TEST_LOOPING(lc); lc++) {
-
- tst_count = 0;
-
- for (i = 0; i < TST_TOTAL; i++) {
-
- errno = -4;
-
- /*
- * Call pathconf(2)
- */
- TEST(pathconf(path, args[i].value));
-
- /*
- * A test case can only fail if -1 is returned and the errno
- * was set. If the errno remains unchanged, the
- * system call did not fail.
- */
- if (TEST_RETURN == -1 && errno != -4) {
- tst_resm(TFAIL,
- "pathconf(%s, %s) Failed, errno=%d : %s",
- path, args[i].define_tag, TEST_ERRNO,
- strerror(TEST_ERRNO));
- } else {
- tst_resm(TPASS,
- "pathconf(%s, %s) returned %ld",
- path, args[i].define_tag,
- TEST_RETURN);
- }
- }
- }
-
- /***************************************************************
- * cleanup and exit
- ***************************************************************/
- cleanup();
-
- tst_exit();
+ if (TST_RET == -1 && errno != 0)
+ tst_res(TFAIL, "pathconf Failed, errno = %d", TST_ERR);
+ else
+ tst_res(TPASS, "pathconf(%s, %s)", path, tc->name);
}
-/***************************************************************
- * setup() - performs all ONE TIME setup for this test.
- ***************************************************************/
-void setup(void)
+static void cleanup(void)
{
-
- tst_sig(NOFORK, DEF_HANDLER, cleanup);
-
- TEST_PAUSE;
-}
-
-/***************************************************************
- * cleanup() - performs all ONE TIME cleanup for this test at
- * completion or premature exit.
- ***************************************************************/
-void cleanup(void)
-{
- if (!lflag) {
- tst_rmdir();
- free(path);
- }
+ free(path);
}
-/***************************************************************
- * help
- ***************************************************************/
-void help(void)
-{
- printf(" -l path a path to test with pathconf(2) (def: /tmp)\n");
-}
+static struct tst_test test = {
+ .needs_tmpdir = 1,
+ .test = verify_pathconf,
+ .tcnt = ARRAY_SIZE(tcases),
+ .cleanup = cleanup,
+};
diff --git a/testcases/kernel/syscalls/pathconf/pathconf02.c b/testcases/kernel/syscalls/pathconf/pathconf02.c
new file mode 100644
index 000000000..3fb2cdbe8
--- /dev/null
+++ b/testcases/kernel/syscalls/pathconf/pathconf02.c
@@ -0,0 +1,98 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (c) 2023 FUJITSU LIMITED. All rights reserved.
+ * Author: Yang Xu <xuyang2018.jy@cn.fujitsu.com>
+ */
+
+/*\
+ * [Description]
+ *
+ * Verify that,
+ *
+ * - pathconf() fails with ENOTDIR if a component used as a directory
+ * in path is not in fact a directory.
+ * - pathconf() fails with ENOENT if path is an empty string.
+ * - pathconf() fails with ENAMETOOLONG if path is too long.
+ * - pathconf() fails with EINVA if name is invalid.
+ * - pathconf() fails with EACCES if search permission is denied for
+ * one of the directories in the path prefix of path.
+ * - pathconf() fails with ELOOP if too many symbolic links were
+ * encountered while resolving path.
+ */
+
+#define FILEPATH "testfile/testfile_1"
+#define TESTELOOP "test_eloop1"
+#define PATH_LEN (PATH_MAX + 2)
+
+#include <stdlib.h>
+#include <pwd.h>
+#include "tst_test.h"
+
+static char *fpath;
+static char *emptypath;
+static char path[PATH_LEN];
+static char *long_path = path;
+static char *abs_path;
+static char *testeloop;
+static struct passwd *user;
+
+static struct tcase {
+ char **path;
+ int name;
+ int exp_errno;
+ char *desc;
+} tcases[] = {
+ {&fpath, 0, ENOTDIR, "path prefix is not a directory"},
+ {&emptypath, 0, ENOENT, "path is an empty string"},
+ {&long_path, 0, ENAMETOOLONG, "path is too long"},
+ {&abs_path, -1, EINVAL, "name is invalid"},
+ {&abs_path, 0, EACCES, "without full permissions of the path prefix"},
+ {&testeloop, 0, ELOOP, "too many symbolic links"},
+};
+
+static void verify_fpathconf(unsigned int i)
+{
+ struct tcase *tc = &tcases[i];
+
+ if (tc->exp_errno == EACCES)
+ SAFE_SETEUID(user->pw_uid);
+
+ TST_EXP_FAIL(pathconf(*tc->path, tc->name), tc->exp_errno,
+ "pathconf() fail with %s", tc->desc);
+
+ if (tc->exp_errno == EACCES)
+ SAFE_SETEUID(0);
+}
+
+static void setup(void)
+{
+ user = SAFE_GETPWNAM("nobody");
+
+ SAFE_TOUCH("testfile", 0777, NULL);
+
+ char *tmpdir = tst_get_tmpdir();
+
+ abs_path = tst_aprintf("%s/%s", tmpdir, FILEPATH);
+
+ SAFE_CHMOD(tmpdir, 0);
+ free(tmpdir);
+
+ memset(path, 'a', PATH_LEN);
+
+ SAFE_SYMLINK("test_eloop1", "test_eloop2");
+ SAFE_SYMLINK("test_eloop2", "test_eloop1");
+}
+
+static struct tst_test test = {
+ .tcnt = ARRAY_SIZE(tcases),
+ .test = verify_fpathconf,
+ .setup = setup,
+ .needs_tmpdir = 1,
+ .bufs = (struct tst_buffers []) {
+ {&fpath, .str = FILEPATH},
+ {&emptypath, .str = ""},
+ {&testeloop, .str = TESTELOOP},
+ {},
+ },
+ .needs_root = 1,
+};
diff --git a/testcases/kernel/syscalls/pipe/.gitignore b/testcases/kernel/syscalls/pipe/.gitignore
index 774d73205..581a68b78 100644
--- a/testcases/kernel/syscalls/pipe/.gitignore
+++ b/testcases/kernel/syscalls/pipe/.gitignore
@@ -12,3 +12,4 @@
/pipe12
/pipe13
/pipe14
+/pipe15
diff --git a/testcases/kernel/syscalls/pipe/pipe15.c b/testcases/kernel/syscalls/pipe/pipe15.c
new file mode 100644
index 000000000..c85ad1820
--- /dev/null
+++ b/testcases/kernel/syscalls/pipe/pipe15.c
@@ -0,0 +1,94 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (c) 2023 SUSE LLC Marius Kittler <mkittler@suse.de>
+ */
+
+/*\
+ * [Description]
+ *
+ * This is a regression test for hangup on pipe operations. See
+ * https://www.spinics.net/lists/linux-api/msg49762.html for
+ * additional context. It tests that pipe operations do not block
+ * indefinitely when going to the soft limit on the total size of
+ * all pipes created by a single user.
+ */
+
+#define _GNU_SOURCE
+#include <fcntl.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include "tst_test.h"
+#include "tst_safe_stdio.h"
+#include "tst_safe_macros.h"
+
+static int pipe_count;
+static int *pipes;
+static char *buffer;
+
+static void run(void)
+{
+ const int *const pipe = pipes + 2 * (pipe_count - 1);
+ const int buffer_size = SAFE_FCNTL(pipe[1], F_GETPIPE_SZ);
+
+ tst_res(TINFO, "Soft-limited buffer size: %d bytes", buffer_size);
+ SAFE_WRITE(1, pipe[1], buffer, buffer_size);
+ SAFE_READ(1, pipe[0], buffer, buffer_size - 1);
+ SAFE_WRITE(1, pipe[1], buffer, 1);
+ tst_res(TPASS, "Pipe operation did not block");
+
+ SAFE_READ(1, pipe[0], buffer, 2);
+}
+
+static void setup(void)
+{
+ int pipe[2];
+ int page_size = getpagesize(), soft_limit;
+ struct rlimit nfd;
+
+ SAFE_PIPE(pipe);
+ const int buffer_size = SAFE_FCNTL(pipe[1], F_GETPIPE_SZ);
+ SAFE_CLOSE(pipe[0]);
+ SAFE_CLOSE(pipe[1]);
+
+ SAFE_FILE_SCANF("/proc/sys/fs/pipe-user-pages-soft", "%i", &soft_limit);
+ pipe_count = soft_limit * page_size / buffer_size;
+
+ tst_res(TINFO, "Soft limit for pipes: %i pages", soft_limit);
+ tst_res(TINFO, "Buffer size: %d byte", buffer_size);
+ tst_res(TINFO, "Creating %i pipes", pipe_count);
+
+ SAFE_GETRLIMIT(RLIMIT_NOFILE, &nfd);
+ if (nfd.rlim_max < (unsigned long)pipe_count)
+ tst_brk(TCONF, "NOFILE limit max too low: %lu < %i", nfd.rlim_max, pipe_count);
+ if (nfd.rlim_cur < nfd.rlim_max) {
+ nfd.rlim_cur = nfd.rlim_max;
+ SAFE_SETRLIMIT(RLIMIT_NOFILE, &nfd);
+ }
+
+ buffer = SAFE_MALLOC(buffer_size);
+ pipes = SAFE_MALLOC(pipe_count * 2 * sizeof(int));
+ for (int i = 0; i < pipe_count; ++i)
+ SAFE_PIPE(pipes + i * 2);
+
+}
+
+static void cleanup(void)
+{
+ for (int i = 0; i < pipe_count * 2; i++)
+ if (pipes[i] > 0)
+ SAFE_CLOSE(pipes[i]);
+ if (pipes)
+ free(pipes);
+ if (buffer)
+ free(buffer);
+}
+
+static struct tst_test test = {
+ .setup = setup,
+ .test_all = run,
+ .cleanup = cleanup,
+ .tags = (const struct tst_tag[]){
+ {"linux-git", "46c4c9d1beb7"},
+ },
+};
diff --git a/testcases/kernel/syscalls/preadv/preadv.h b/testcases/kernel/syscalls/preadv/preadv.h
index 73466a9aa..c715715b1 100644
--- a/testcases/kernel/syscalls/preadv/preadv.h
+++ b/testcases/kernel/syscalls/preadv/preadv.h
@@ -1,18 +1,9 @@
-/*
-* Copyright (c) 2015 Fujitsu Ltd.
-* Author: Xiao Yang <yangx.jy@cn.fujitsu.com>
-*
-* This program is free software; you can redistribute it and/or modify it
-* under the terms of version 2 of the GNU General Public License as
-* published by the Free Software Foundation.
-*
-* This program is distributed in the hope that it would be useful, but
-* WITHOUT ANY WARRANTY; without even the implied warranty of
-* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
-*
-* You should have received a copy of the GNU General Public License
-* alone with this program.
-*/
+/* SPDX-License-Identifier: GPL-2.0-or-later
+ *
+ * Copyright (c) 2015 Fujitsu Ltd.
+ * Author: Xiao Yang <yangx.jy@cn.fujitsu.com>
+ * Copyright (c) Linux Test Project, 2016-2023
+ */
#ifndef PREADV_H
#define PREADV_H
diff --git a/testcases/kernel/syscalls/preadv/preadv01.c b/testcases/kernel/syscalls/preadv/preadv01.c
index 62f9296f2..871b3ab42 100644
--- a/testcases/kernel/syscalls/preadv/preadv01.c
+++ b/testcases/kernel/syscalls/preadv/preadv01.c
@@ -1,17 +1,18 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/*
-* Copyright (c) 2015 Fujitsu Ltd.
-* Author: Xiao Yang <yangx.jy@cn.fujitsu.com>
-*/
-
-/*
-* Test Name: preadv01
-*
-* Test Description:
-* Testcase to check the basic functionality of the preadv(2).
-* Preadv(2) should succeed to read the expected content of data
-* and after reading the file, the file offset is not changed.
-*/
+ * Copyright (c) 2015 Fujitsu Ltd.
+ * Author: Xiao Yang <yangx.jy@cn.fujitsu.com>
+ * Copyright (c) Linux Test Project, 2016-2023
+ */
+
+/*\
+ * [Description]
+ *
+ * Testcase to check the basic functionality of the preadv(2).
+ *
+ * Preadv(2) should succeed to read the expected content of data
+ * and after reading the file, the file offset is not changed.
+ */
#define _GNU_SOURCE
@@ -38,7 +39,7 @@ static struct tcase {
{1, CHUNK*3/2, CHUNK/2, 'b'}
};
-void verify_preadv(unsigned int n)
+static void verify_preadv(unsigned int n)
{
int i;
char *vec;
@@ -81,7 +82,7 @@ void verify_preadv(unsigned int n)
"with content '%c' expectedly", tc->size, tc->content);
}
-void setup(void)
+static void setup(void)
{
char buf[CHUNK];
@@ -94,7 +95,7 @@ void setup(void)
SAFE_WRITE(SAFE_WRITE_ALL, fd, buf, sizeof(buf));
}
-void cleanup(void)
+static void cleanup(void)
{
if (fd > 0)
SAFE_CLOSE(fd);
diff --git a/testcases/kernel/syscalls/preadv/preadv02.c b/testcases/kernel/syscalls/preadv/preadv02.c
index 500059e42..9977a4f48 100644
--- a/testcases/kernel/syscalls/preadv/preadv02.c
+++ b/testcases/kernel/syscalls/preadv/preadv02.c
@@ -1,32 +1,22 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/*
-* Copyright (c) 2015-2016 Fujitsu Ltd.
-* Author: Xiao Yang <yangx.jy@cn.fujitsu.com>
-*/
-
-/*
-* Test Name: preadv02
-*
-* Description:
-* 1) preadv(2) fails if iov_len is invalid.
-* 2) preadv(2) fails if the vector count iovcnt is less than zero.
-* 3) preadv(2) fails if offset is negative.
-* 4) preadv(2) fails when attempts to read into a invalid address.
-* 5) preadv(2) fails if file descriptor is invalid.
-* 6) preadv(2) fails if file descriptor is not open for reading.
-* 7) preadv(2) fails when fd refers to a directory.
-* 8) preadv(2) fails if fd is associated with a pipe.
-*
-* Expected Result:
-* 1) preadv(2) should return -1 and set errno to EINVAL.
-* 2) preadv(2) should return -1 and set errno to EINVAL.
-* 3) preadv(2) should return -1 and set errno to EINVAL.
-* 4) preadv(2) should return -1 and set errno to EFAULT.
-* 5) preadv(2) should return -1 and set errno to EBADF.
-* 6) preadv(2) should return -1 and set errno to EBADF.
-* 7) preadv(2) should return -1 and set errno to EISDIR.
-* 8) preadv(2) should return -1 and set errno to ESPIPE.
-*/
+ * Copyright (c) 2015-2016 Fujitsu Ltd.
+ * Author: Xiao Yang <yangx.jy@cn.fujitsu.com>
+ * Copyright (c) Linux Test Project, 2017-2023
+ */
+
+/*\
+ * [Description]
+ *
+ * - EINVAL when iov_len is invalid.
+ * - EINVAL when the vector count iovcnt is less than zero.
+ * - EINVAL when offset is negative.
+ * - EFAULT when attempts to read into a invalid address.
+ * - EBADF when file descriptor is invalid.
+ * - EBADF when file descriptor is not open for reading.
+ * - EISDIR when fd refers to a directory.
+ * - ESPIPE when fd is associated with a pipe.
+ */
#define _GNU_SOURCE
diff --git a/testcases/kernel/syscalls/preadv/preadv03.c b/testcases/kernel/syscalls/preadv/preadv03.c
index d4595dda6..558d85050 100644
--- a/testcases/kernel/syscalls/preadv/preadv03.c
+++ b/testcases/kernel/syscalls/preadv/preadv03.c
@@ -2,12 +2,15 @@
/*
* Copyright (c) 2018 FUJITSU LIMITED. All rights reserved.
* Author: Xiao Yang <yangx.jy@cn.fujitsu.com>
+ * Copyright (c) Linux Test Project, 2019-2023
*/
-/*
- * Description:
+/*\
+ * [Description]
+ *
* Check the basic functionality of the preadv(2) for the file
* opened with O_DIRECT in all filesystem.
+ *
* preadv(2) should succeed to read the expected content of data
* and after reading the file, the file offset is not changed.
*/
diff --git a/testcases/kernel/syscalls/ptrace/.gitignore b/testcases/kernel/syscalls/ptrace/.gitignore
index 01cbc6072..1ee6117e9 100644
--- a/testcases/kernel/syscalls/ptrace/.gitignore
+++ b/testcases/kernel/syscalls/ptrace/.gitignore
@@ -3,6 +3,7 @@
/ptrace03
/ptrace04
/ptrace05
+/ptrace06
/ptrace07
/ptrace08
/ptrace09
diff --git a/testcases/kernel/syscalls/ptrace/Makefile b/testcases/kernel/syscalls/ptrace/Makefile
index 9ee7b8374..d7eca6837 100644
--- a/testcases/kernel/syscalls/ptrace/Makefile
+++ b/testcases/kernel/syscalls/ptrace/Makefile
@@ -1,34 +1,9 @@
# SPDX-License-Identifier: GPL-2.0-or-later
+# Copyright (c) Linux Test Project, 2002-2023
# Copyright (c) International Business Machines Corp., 2001
top_srcdir ?= ../../../..
include $(top_srcdir)/include/mk/testcases.mk
-# - ptrace06 is a broken test ; it hangs the target consistently, chewing up
-# CPU. See: `Issue 3 - ptrace06 hung for 7 hours' --
-# http://sourceforge.net/mailarchive/forum.php?thread_name=364299f40910062300s65c43c93w9cccdfe8835c2334%40mail.gmail.com&forum_name=ltp-list
-# - simple_tracer is a utility that Mike Frysinger added that shouldn't be
-# compiled by default:
-#
-# gcc -g -O2 -g -O2 -fno-strict-aliasing -pipe -Wall
-# -I//scratch/ltp-install6/include -I../../../../include
-# -L//scratch/ltp-install6/lib simple_tracer.c -laio -lltp -o
-# simple_tracer
-# In file included from simple_tracer.c:25:
-# syscalls.h:6:23: error: _syscalls.h: No such file or directory
-# make[4]: *** [simple_tracer] Error 1
-# make[4]: Leaving directory
-# `/scratch/ltp-dev2/ltp/testcases/kernel/syscalls/ptrace'
-# make[3]: *** [all] Error 2
-# make[3]: Leaving directory `/scratch/ltp-dev2/ltp/testcases/kernel/syscalls'
-# make[2]: *** [all] Error 2
-# make[2]: Leaving directory `/scratch/ltp-dev2/ltp/testcases/kernel'
-# make[1]: *** [all] Error 2
-# make[1]: Leaving directory `/scratch/ltp-dev2/ltp/testcases'
-# make: *** [testcases-all] Error 2
-#
-
-FILTER_OUT_MAKE_TARGETS := ptrace06 simple_tracer
-
include $(top_srcdir)/include/mk/generic_leaf_target.mk
diff --git a/testcases/kernel/syscalls/ptrace/make_syscall_list.sh b/testcases/kernel/syscalls/ptrace/make_syscall_list.sh
deleted file mode 100755
index e5d6d2765..000000000
--- a/testcases/kernel/syscalls/ptrace/make_syscall_list.sh
+++ /dev/null
@@ -1,7 +0,0 @@
-#!/bin/sh
-set -- $( \
- printf '#include <sys/syscall.h>' | \
- ${CC:-gcc} -E -dD - | \
- awk '$2 ~ /^SYS_/ { sub(/SYS_/,"",$2); print $2; }'
-)
-printf 'P(%s)\n' "$@"
diff --git a/testcases/kernel/syscalls/ptrace/ptrace.h b/testcases/kernel/syscalls/ptrace/ptrace.h
deleted file mode 100644
index 4a43f01ef..000000000
--- a/testcases/kernel/syscalls/ptrace/ptrace.h
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * ptrace is a fickle beast and each arch sucks in a different way
- */
-
-#ifndef __LTP_PTRACE_H__
-#define __LTP_PTRACE_H__
-
-#ifdef HAVE_SYS_PTRACE_H
-# include <sys/ptrace.h>
-#endif
-#ifdef HAVE_SYS_REG_H
-# include <sys/reg.h>
-#endif
-#ifdef __ia64__ /* what a pos */
-# define ia64_fpreg FU_ia64_fpreg
-# define pt_all_user_regs FU_pt_all_user_regs
-#endif
-#ifdef HAVE_ASM_PTRACE_H
-# include <asm/ptrace.h>
-#endif
-#ifdef HAVE_LINUX_PTRACE_H
-# ifndef HAVE_STRUCT_PTRACE_PEEKSIGINFO_ARGS
-# include <linux/ptrace.h>
-# endif
-#endif
-#undef FU_ia64_fpreg
-#undef FU_pt_all_user_regs
-
-#if defined(HAVE_STRUCT_PT_REGS)
-typedef struct pt_regs ptrace_regs;
-#elif defined(HAVE_STRUCT_USER_REGS_STRUCT)
-typedef struct user_regs_struct ptrace_regs;
-#endif
-
-#endif
diff --git a/testcases/kernel/syscalls/ptrace/ptrace01.c b/testcases/kernel/syscalls/ptrace/ptrace01.c
index 9071bbaba..53ddfb393 100644
--- a/testcases/kernel/syscalls/ptrace/ptrace01.c
+++ b/testcases/kernel/syscalls/ptrace/ptrace01.c
@@ -26,8 +26,7 @@
#include <errno.h>
#include <signal.h>
#include <sys/wait.h>
-#include <config.h>
-#include "ptrace.h"
+#include <sys/ptrace.h>
#include "tst_test.h"
static struct tcase {
diff --git a/testcases/kernel/syscalls/ptrace/ptrace02.c b/testcases/kernel/syscalls/ptrace/ptrace02.c
index e330f459e..a48ef58a5 100644
--- a/testcases/kernel/syscalls/ptrace/ptrace02.c
+++ b/testcases/kernel/syscalls/ptrace/ptrace02.c
@@ -11,9 +11,8 @@
#include <signal.h>
#include <sys/wait.h>
#include <pwd.h>
-#include <config.h>
#include <stdlib.h>
-#include "ptrace.h"
+#include <sys/ptrace.h>
#include "tst_test.h"
uid_t uid;
diff --git a/testcases/kernel/syscalls/ptrace/ptrace03.c b/testcases/kernel/syscalls/ptrace/ptrace03.c
index b2b3fb49d..42ac3e7cf 100644
--- a/testcases/kernel/syscalls/ptrace/ptrace03.c
+++ b/testcases/kernel/syscalls/ptrace/ptrace03.c
@@ -14,9 +14,8 @@
#include <signal.h>
#include <sys/wait.h>
#include <pwd.h>
-#include <config.h>
#include <stdlib.h>
-#include "ptrace.h"
+#include <sys/ptrace.h>
#include "tst_test.h"
static pid_t unused_pid;
diff --git a/testcases/kernel/syscalls/ptrace/ptrace04.c b/testcases/kernel/syscalls/ptrace/ptrace04.c
index af35fb3a2..8f1b5c6cc 100644
--- a/testcases/kernel/syscalls/ptrace/ptrace04.c
+++ b/testcases/kernel/syscalls/ptrace/ptrace04.c
@@ -13,9 +13,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
-
-#include <config.h>
-#include "ptrace.h"
+#include <sys/ptrace.h>
#include "test.h"
#include "spawn_ptrace_child.h"
@@ -49,7 +47,7 @@ int TST_TOTAL = 2;
void compare_registers(unsigned char poison)
{
-#ifdef HAVE_STRUCT_PTRACE_REGS
+#if defined(HAVE_STRUCT_PTRACE_REGS) && defined(PTRACE_GETREGS)
ptrace_regs _pt_regs;
size_t i;
long ret;
diff --git a/testcases/kernel/syscalls/ptrace/ptrace05.c b/testcases/kernel/syscalls/ptrace/ptrace05.c
index 54cfa4d7b..541018393 100644
--- a/testcases/kernel/syscalls/ptrace/ptrace05.c
+++ b/testcases/kernel/syscalls/ptrace/ptrace05.c
@@ -33,9 +33,7 @@
#include <stdio.h>
#include <string.h>
#include <unistd.h>
-
-#include <config.h>
-#include "ptrace.h"
+#include <sys/ptrace.h>
#include "test.h"
#include "lapi/signal.h"
diff --git a/testcases/kernel/syscalls/ptrace/ptrace06.c b/testcases/kernel/syscalls/ptrace/ptrace06.c
index c0cb3b9bd..a1db3bab8 100644
--- a/testcases/kernel/syscalls/ptrace/ptrace06.c
+++ b/testcases/kernel/syscalls/ptrace/ptrace06.c
@@ -16,13 +16,10 @@
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
-
-#include <config.h>
-#include "ptrace.h"
+#include <sys/ptrace.h>
#include "test.h"
#include "spawn_ptrace_child.h"
-#include "config.h"
/* this should be sizeof(struct user), but that info is only found
* in the kernel asm/user.h which is not exported to userspace.
diff --git a/testcases/kernel/syscalls/ptrace/ptrace07.c b/testcases/kernel/syscalls/ptrace/ptrace07.c
index 362cee543..a78243671 100644
--- a/testcases/kernel/syscalls/ptrace/ptrace07.c
+++ b/testcases/kernel/syscalls/ptrace/ptrace07.c
@@ -35,9 +35,8 @@
#include <stdlib.h>
#include <sys/uio.h>
#include <sys/wait.h>
+#include <sys/ptrace.h>
-#include "config.h"
-#include "ptrace.h"
#include "tst_safe_macros.h"
#include "lapi/cpuid.h"
diff --git a/testcases/kernel/syscalls/ptrace/ptrace11.c b/testcases/kernel/syscalls/ptrace/ptrace11.c
index c54441671..90154852f 100644
--- a/testcases/kernel/syscalls/ptrace/ptrace11.c
+++ b/testcases/kernel/syscalls/ptrace/ptrace11.c
@@ -16,9 +16,8 @@
#include <signal.h>
#include <sys/wait.h>
#include <pwd.h>
-#include <config.h>
#include <stdlib.h>
-#include "ptrace.h"
+#include <sys/ptrace.h>
#include "tst_test.h"
static void verify_ptrace(void)
diff --git a/testcases/kernel/syscalls/ptrace/simple_tracer.c b/testcases/kernel/syscalls/ptrace/simple_tracer.c
deleted file mode 100644
index ae1af7c2f..000000000
--- a/testcases/kernel/syscalls/ptrace/simple_tracer.c
+++ /dev/null
@@ -1,144 +0,0 @@
-/*
- * simple example ptrace() code to help build basis for other tests
- *
- * Copyright (c) 2009 Analog Devices Inc.
- *
- * Licensed under the GPL-2 or later
- */
-
-#define _GNU_SOURCE
-
-#include <config.h>
-
-#include <errno.h>
-#include <stdbool.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <sys/ptrace.h>
-#include <sys/syscall.h>
-#include "ptrace.h"
-
-#include "test.h"
-#include "spawn_ptrace_child.h"
-
-#include "syscalls.h"
-
-char *TCID = "simple_tracer";
-int TST_TOTAL = 0;
-
-#define _decode(name, val) \
-({ \
- if (sizeof(long) == 4) \
- printf(name ":%08lx ", val); \
- else if (sizeof(long) == 8) \
- printf(name ":%016lx ", val); \
- else \
- printf(name ":%lx ", val); \
- val; \
-})
-#define decode(reg) _decode(#reg, pt->reg)
-#define decode_user(name, offset) \
- _decode(name, vptrace(PTRACE_PEEKUSER, pid, offset, NULL));
-#define decode_sysnum(nr) printf("%s ", get_sysnum(nr))
-static void decode_regs(struct pt_regs *pt)
-{
-#if defined(__bfin__)
- long nr = decode_user("orig_p0", PT_ORIG_P0);
- decode(p0);
- decode(r0);
- decode(r1);
- decode(r2);
- decode(r3);
- decode(r4);
- decode(r5);
- decode_sysnum(nr);
- puts("");
-#elif defined(__i386__)
- long nr = decode_user("orig_eax", 4 * ORIG_EAX);
- decode(eax);
- decode(ebx);
- decode(ecx);
- decode(edx);
- decode(esi);
- decode(edi);
- decode(ebp);
- decode_sysnum(nr);
- puts("");
-#elif defined(__x86_64__)
- long nr = decode_user("orig_rax", 8 * ORIG_RAX);
- decode(rax);
- decode(rbx);
- decode(rcx);
- decode(rdx);
- decode(rsi);
- decode(rdi);
- decode(rbp);
- decode_sysnum(nr);
- puts("");
-#elif defined(__sparc__)
-#define G1 u_regs[0]
-#define G2 u_regs[1]
-#define G3 u_regs[2]
-#define G4 u_regs[3]
-#define G5 u_regs[4]
-#define G6 u_regs[5]
-#define G7 u_regs[6]
-#define O0 u_regs[7]
-#define O1 u_regs[8]
-#define O2 u_regs[9]
-#define O3 u_regs[10]
-#define O4 u_regs[11]
-#define O5 u_regs[12]
-#define O6 u_regs[13]
-#define O7 u_regs[14]
- decode(G1);
- decode(G2);
- decode(G3);
- decode(G4);
- decode(G5);
- decode(G6);
- decode(G7);
- decode(O0);
- decode(O1);
- decode(O2);
- decode(O3);
- decode(O4);
- decode(O5);
- decode(O6);
- decode(O7);
- decode_sysnum(pt->G1);
- puts("");
-#else
-#warning "no idea how to decode your arch"
- puts("no idea how to decode your arch");
-#endif
-}
-
-int main(int argc, char *argv[])
-{
- struct pt_regs pt_regs;
- long ret;
- int status;
-
- make_a_baby(argc, argv);
-
- while (1) {
- ret = vptrace(PTRACE_GETREGS, pid, NULL, &pt_regs);
- if (ret)
- break;
- decode_regs(&pt_regs);
-
- ret = vptrace(PTRACE_SYSCALL, pid, NULL, NULL);
- if (ret)
- break;
-
- if (waitpid(pid, &status, 0) == -1)
- break;
- }
-
- /* hopefully this worked */
- vptrace(PTRACE_KILL, pid, NULL, NULL);
-
- tst_exit();
-}
diff --git a/testcases/kernel/syscalls/ptrace/syscalls.h b/testcases/kernel/syscalls/ptrace/syscalls.h
deleted file mode 100644
index 2d9c5ceb6..000000000
--- a/testcases/kernel/syscalls/ptrace/syscalls.h
+++ /dev/null
@@ -1,17 +0,0 @@
-const struct sysnums {
- long nr;
- const char *snr;
-} sysnums[] = {
-#define P(NR) { .nr = SYS_##NR, .snr = #NR, },
-#include "_syscalls.h"
-#undef P
-};
-
-const char *get_sysnum(long nr)
-{
- int i;
- for (i = 0; i < ARRAY_SIZE(sysnums); ++i)
- if (sysnums[i].nr == nr)
- break;
- return i == ARRAY_SIZE(sysnums) ? "???" : sysnums[i].snr;
-}
diff --git a/testcases/kernel/syscalls/pwritev/pwritev.h b/testcases/kernel/syscalls/pwritev/pwritev.h
index 833160ddb..e657dc7e6 100644
--- a/testcases/kernel/syscalls/pwritev/pwritev.h
+++ b/testcases/kernel/syscalls/pwritev/pwritev.h
@@ -1,18 +1,9 @@
-/*
-* Copyright (c) 2015 Fujitsu Ltd.
-* Author: Xiao Yang <yangx.jy@cn.fujitsu.com>
-*
-* This program is free software; you can redistribute it and/or modify it
-* under the terms of version 2 of the GNU General Public License as
-* published by the Free Software Foundation.
-*
-* This program is distributed in the hope that it would be useful, but
-* WITHOUT ANY WARRANTY; without even the implied warranty of
-* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
-*
-* You should have received a copy of the GNU General Public License
-* alone with this program.
-*/
+/* SPDX-License-Identifier: GPL-2.0-or-later
+ *
+ * Copyright (c) 2015 Fujitsu Ltd.
+ * Author: Xiao Yang <yangx.jy@cn.fujitsu.com>
+ * Copyright (c) Linux Test Project, 2016-2023
+ */
#ifndef PWRITEV_H
#define PWRITEV_H
diff --git a/testcases/kernel/syscalls/pwritev/pwritev01.c b/testcases/kernel/syscalls/pwritev/pwritev01.c
index 66358f7c4..f5fce81f2 100644
--- a/testcases/kernel/syscalls/pwritev/pwritev01.c
+++ b/testcases/kernel/syscalls/pwritev/pwritev01.c
@@ -1,17 +1,18 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/*
-* Copyright (c) 2015 Fujitsu Ltd.
-* Author: Xiao Yang <yangx.jy@cn.fujitsu.com>
-*/
-
-/*
-* Test Name: pwritev01
-*
-* Test Description:
-* Testcase to check the basic functionality of the pwritev(2).
-* pwritev(2) should succeed to write the expected content of data
-* and after writing the file, the file offset is not changed.
-*/
+ * Copyright (c) 2015 Fujitsu Ltd.
+ * Author: Xiao Yang <yangx.jy@cn.fujitsu.com>
+ * Copyright (c) Linux Test Project, 2016-2023
+ */
+
+/*\
+ * [Description]
+ *
+ * Testcase to check the basic functionality of the pwritev(2).
+ *
+ * pwritev(2) should succeed to write the expected content of data
+ * and after writing the file, the file offset is not changed.
+ */
#define _GNU_SOURCE
#include <string.h>
diff --git a/testcases/kernel/syscalls/pwritev/pwritev02.c b/testcases/kernel/syscalls/pwritev/pwritev02.c
index 0881b7566..59a286847 100644
--- a/testcases/kernel/syscalls/pwritev/pwritev02.c
+++ b/testcases/kernel/syscalls/pwritev/pwritev02.c
@@ -1,30 +1,21 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/*
-* Copyright (c) 2015-2016 Fujitsu Ltd.
-* Author: Xiao Yang <yangx.jy@cn.fujitsu.com>
-*/
-
-/*
-* Test Name: pwritev02
-*
-* Description:
-* 1) pwritev(2) fails if iov_len is invalid.
-* 2) pwritev(2) fails if the vector count iovcnt is less than zero.
-* 3) pwritev(2) fails if offset is negative.
-* 4) pwritev(2) fails when attempts to write from a invalid address
-* 5) pwritev(2) fails if file descriptor is invalid.
-* 6) pwritev(2) fails if file descriptor is not open for writing.
-* 7) pwritev(2) fails if fd is associated with a pipe.
-*
-* Expected Result:
-* 1) pwritev(2) should return -1 and set errno to EINVAL.
-* 2) pwritev(2) should return -1 and set errno to EINVAL.
-* 3) pwritev(2) should return -1 and set errno to EINVAL.
-* 4) pwritev(2) should return -1 and set errno to EFAULT.
-* 5) pwritev(2) should return -1 and set errno to EBADF.
-* 6) pwritev(2) should return -1 and set errno to EBADF.
-* 7) pwritev(2) should return -1 and set errno to ESPIPE.
-*/
+ * Copyright (c) 2015-2016 Fujitsu Ltd.
+ * Author: Xiao Yang <yangx.jy@cn.fujitsu.com>
+ * Copyright (c) Linux Test Project, 2017-2023
+ */
+
+/*\
+ * [Description]
+ *
+ * - EINVAL when iov_len is invalid.
+ * - EINVAL when the vector count iovcnt is less than zero.
+ * - EINVAL when offset is negative.
+ * - EFAULT when attempts to write from a invalid address
+ * - EBADF when file descriptor is invalid.
+ * - EBADF when file descriptor is not open for writing.
+ * - ESPIPE when fd is associated with a pipe.
+ */
#define _GNU_SOURCE
diff --git a/testcases/kernel/syscalls/pwritev/pwritev03.c b/testcases/kernel/syscalls/pwritev/pwritev03.c
index 8b91de336..1bf9d5731 100644
--- a/testcases/kernel/syscalls/pwritev/pwritev03.c
+++ b/testcases/kernel/syscalls/pwritev/pwritev03.c
@@ -2,12 +2,15 @@
/*
* Copyright (c) 2018 FUJITSU LIMITED. All rights reserved.
* Author: Xiao Yang <yangx.jy@cn.fujitsu.com>
+ * Copyright (c) Linux Test Project, 2019-2023
*/
-/*
- * Description:
+/*\
+ * [Description]
+ *
* Check the basic functionality of the pwritev(2) for the file
* opened with O_DIRECT in all filesystem.
+ *
* pwritev(2) should succeed to write the expected content of data
* and after writing the file, the file offset is not changed.
*/
@@ -90,7 +93,7 @@ static void verify_direct_pwritev(unsigned int n)
static void setup(void)
{
int dev_fd, ret;
-
+
dev_fd = SAFE_OPEN(tst_device->dev, O_RDWR);
SAFE_IOCTL(dev_fd, BLKSSZGET, &ret);
SAFE_CLOSE(dev_fd);
diff --git a/testcases/kernel/syscalls/readahead/readahead01.c b/testcases/kernel/syscalls/readahead/readahead01.c
index bdef7945d..a1f313605 100644
--- a/testcases/kernel/syscalls/readahead/readahead01.c
+++ b/testcases/kernel/syscalls/readahead/readahead01.c
@@ -1,6 +1,7 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (C) 2012 Linux Test Project, Inc.
+ * Copyright (C) 2023-2024 Cyril Hrubis <chrubis@suse.cz>
*/
/*\
@@ -30,43 +31,45 @@
static void test_bad_fd(void)
{
- char tempname[PATH_MAX] = "readahead01_XXXXXX";
- int fd;
+ int fd[2];
+
+ TST_EXP_FAIL(readahead(-1, 0, getpagesize()), EBADF,
+ "readahead() with fd = -1");
- tst_res(TINFO, "%s -1", __func__);
- TST_EXP_FAIL(readahead(-1, 0, getpagesize()), EBADF);
+ SAFE_PIPE(fd);
+ SAFE_CLOSE(fd[0]);
+ SAFE_CLOSE(fd[1]);
- tst_res(TINFO, "%s O_WRONLY", __func__);
- fd = mkstemp(tempname);
- if (fd == -1)
- tst_res(TFAIL | TERRNO, "mkstemp failed");
- SAFE_CLOSE(fd);
- fd = SAFE_OPEN(tempname, O_WRONLY);
- TST_EXP_FAIL(readahead(fd, 0, getpagesize()), EBADF);
- SAFE_CLOSE(fd);
- unlink(tempname);
+ TST_EXP_FAIL(readahead(fd[0], 0, getpagesize()), EBADF,
+ "readahead() with invalid fd");
}
-static void test_invalid_fd(void)
+static void test_invalid_fd(struct tst_fd *fd)
{
- int fd[2];
- tst_res(TINFO, "%s pipe", __func__);
- SAFE_PIPE(fd);
- TST_EXP_FAIL(readahead(fd[0], 0, getpagesize()), EINVAL);
- SAFE_CLOSE(fd[0]);
- SAFE_CLOSE(fd[1]);
+ switch (fd->type) {
+ /* These succeed */
+ case TST_FD_FILE:
+ case TST_FD_MEMFD:
+ case TST_FD_MEMFD_SECRET:
+ case TST_FD_PROC_MAPS:
+ return;
+ default:
+ break;
+ }
- tst_res(TINFO, "%s socket", __func__);
- fd[0] = SAFE_SOCKET(AF_INET, SOCK_STREAM, 0);
- TST_EXP_FAIL(readahead(fd[0], 0, getpagesize()), EINVAL);
- SAFE_CLOSE(fd[0]);
+ int exp_errnos[] = {EBADF, EINVAL, ESPIPE};
+
+ TST_EXP_FAIL_ARR(readahead(fd->fd, 0, getpagesize()), exp_errnos,
+ "readahead() on %s", tst_fd_desc(fd));
}
static void test_readahead(void)
{
test_bad_fd();
- test_invalid_fd();
+
+ TST_FD_FOREACH(fd)
+ test_invalid_fd(&fd);
}
static void setup(void)
diff --git a/testcases/kernel/syscalls/remap_file_pages/remap_file_pages01.c b/testcases/kernel/syscalls/remap_file_pages/remap_file_pages01.c
index 09143a2d0..8a401fe0a 100644
--- a/testcases/kernel/syscalls/remap_file_pages/remap_file_pages01.c
+++ b/testcases/kernel/syscalls/remap_file_pages/remap_file_pages01.c
@@ -85,6 +85,7 @@
#include <sys/ioctl.h>
#include <sys/syscall.h>
#include <linux/unistd.h>
+#include <lapi/mmap.h>
#include "test.h" /*LTP Specific Include File */
@@ -92,6 +93,7 @@
#define WINDOW_START 0x48000000
static int page_sz;
+static int granula;
size_t page_words;
size_t cache_pages;
size_t cache_sz;
@@ -140,10 +142,10 @@ static void test_nonlinear(int fd)
char *data = NULL;
int i, j, repeat = 2;
- for (i = 0; i < (int)cache_pages; i++) {
+ for (i = 0; i < (int)cache_pages; i += granula) {
char *page = cache_contents + i * page_sz;
- for (j = 0; j < (int)page_words; j++)
+ for (j = 0; j < (int)page_words * granula; j++)
page[j] = i;
}
@@ -164,24 +166,24 @@ static void test_nonlinear(int fd)
}
again:
- for (i = 0; i < (int)window_pages; i += 2) {
+ for (i = 0; i < (int)window_pages; i += 2 * granula) {
char *page = data + i * page_sz;
- if (remap_file_pages(page, page_sz * 2, 0,
- (window_pages - i - 2), 0) == -1) {
+ if (remap_file_pages(page, 2 * MMAP_GRANULARITY, 0,
+ (window_pages - i - 2 * granula), 0) == -1) {
tst_resm(TFAIL | TERRNO,
"remap_file_pages error for page=%p, "
- "page_sz=%d, window_pages=%zu",
- page, (page_sz * 2), (window_pages - i - 2));
+ "remap_sz=%d, window_pages=%zu",
+ page, 2 * MMAP_GRANULARITY, (window_pages - i - 2 * granula));
cleanup(data);
}
}
- for (i = 0; i < (int)window_pages; i++) {
+ for (i = 0, j = 0; i < (int)window_pages; i += granula, j++) {
/*
* Double-check the correctness of the mapping:
*/
- if (i & 1) {
+ if (j & 1) {
if (data[i * page_sz] != ((int)window_pages) - i) {
tst_resm(TFAIL,
"hm, mapped incorrect data, "
@@ -191,12 +193,12 @@ again:
cleanup(data);
}
} else {
- if (data[i * page_sz] != ((int)window_pages) - i - 2) {
+ if (data[i * page_sz] != ((int)window_pages) - i - 2 * granula) {
tst_resm(TFAIL,
"hm, mapped incorrect data, "
- "data[%d]=%d, (window_pages-%d-2)=%zu",
+ "data[%d]=%d, (window_pages-%d-2 * min_pages)=%zu",
(i * page_sz), data[i * page_sz], i,
- (window_pages - i - 2));
+ (window_pages - i - 2 * granula));
cleanup(data);
}
}
@@ -223,13 +225,15 @@ void setup(void)
page_words = page_sz;
+ granula = MMAP_GRANULARITY / page_sz;
+
/* Set the cache size */
- cache_pages = 1024;
+ cache_pages = 1024 * granula;
cache_sz = cache_pages * page_sz;
cache_contents = malloc(cache_sz * sizeof(char));
/* Set the window size */
- window_pages = 16;
+ window_pages = 16 * granula;
window_sz = window_pages * page_sz;
sprintf(fname, "/dev/shm/cache_%d", getpid());
diff --git a/testcases/kernel/syscalls/rename/rename10.c b/testcases/kernel/syscalls/rename/rename10.c
index 444f65366..5b5f79073 100644
--- a/testcases/kernel/syscalls/rename/rename10.c
+++ b/testcases/kernel/syscalls/rename/rename10.c
@@ -18,7 +18,13 @@
#define MNT_POINT "mntpoint"
#define TEMP_FILE "tmpfile"
-static char long_path[NAME_MAX + 1] = {[0 ... NAME_MAX] = 'a'};
+/* Path longer than PATH_MAX: fails the syscall right away (getname() fails) */
+static char long_path[PATH_MAX + 1] = {[0 ... PATH_MAX] = 'a'};
+/*
+ * Path fitting in PATH_MAX, but with an excessively long file name: rejected
+ * by the underlying filesystem
+ */
+static char long_name[PATH_MAX] = {[0 ... PATH_MAX - 2] = 'a', [PATH_MAX - 1] = '\0'};
static void setup(void)
{
@@ -30,6 +36,8 @@ static void run(void)
{
TST_EXP_FAIL(rename(TEMP_FILE, long_path),
ENAMETOOLONG);
+ TST_EXP_FAIL(rename(TEMP_FILE, long_name),
+ ENAMETOOLONG);
}
static struct tst_test test = {
diff --git a/testcases/kernel/syscalls/renameat/renameat01.c b/testcases/kernel/syscalls/renameat/renameat01.c
index 3de103563..c318a7971 100644
--- a/testcases/kernel/syscalls/renameat/renameat01.c
+++ b/testcases/kernel/syscalls/renameat/renameat01.c
@@ -50,7 +50,6 @@
#include "test.h"
#include "safe_macros.h"
#include "lapi/fcntl.h"
-#include "lapi/renameat.h"
#define MNTPOINT "mntpoint"
#define TESTDIR "testdir"
diff --git a/testcases/kernel/syscalls/sched_rr_get_interval/sched_rr_get_interval01.c b/testcases/kernel/syscalls/sched_rr_get_interval/sched_rr_get_interval01.c
index 597de4665..40ff6e988 100644
--- a/testcases/kernel/syscalls/sched_rr_get_interval/sched_rr_get_interval01.c
+++ b/testcases/kernel/syscalls/sched_rr_get_interval/sched_rr_get_interval01.c
@@ -2,13 +2,17 @@
/*
* Copyright (c) Wipro Technologies Ltd, 2002. All Rights Reserved.
* AUTHOR : Saji Kumar.V.R <saji.kumar@wipro.com>
+ */
+/*\
+ * [Description]
*
* Gets round-robin time quantum by calling sched_rr_get_interval() and
* checks that the value is sane.
*
- * It is also a regression test for kernel
- * commit 975e155ed873 ("sched/rt: Show the 'sched_rr_timeslice' SCHED_RR
- * timeslice tuning knob in milliseconds").
+ * It is also a regression test for:
+ *
+ * - 975e155ed873 (sched/rt: Show the 'sched_rr_timeslice' SCHED_RR timeslice tuning knob in milliseconds)
+ * - c7fcb99877f9 ( sched/rt: Fix sysctl_sched_rr_timeslice intial value)
*/
#include "time64_variants.h"
diff --git a/testcases/kernel/syscalls/sched_rr_get_interval/sched_rr_get_interval02.c b/testcases/kernel/syscalls/sched_rr_get_interval/sched_rr_get_interval02.c
index 15e4a3053..a61e2969b 100644
--- a/testcases/kernel/syscalls/sched_rr_get_interval/sched_rr_get_interval02.c
+++ b/testcases/kernel/syscalls/sched_rr_get_interval/sched_rr_get_interval02.c
@@ -2,6 +2,9 @@
/*
* Copyright (c) Wipro Technologies Ltd, 2002. All Rights Reserved.
* AUTHOR : Saji Kumar.V.R <saji.kumar@wipro.com>
+ */
+/*\
+ * [Description]
*
* Verify that for a process with scheduling policy SCHED_FIFO,
* sched_rr_get_interval() writes zero into timespec structure
diff --git a/testcases/kernel/syscalls/sched_rr_get_interval/sched_rr_get_interval03.c b/testcases/kernel/syscalls/sched_rr_get_interval/sched_rr_get_interval03.c
index f5a88f084..731c50082 100644
--- a/testcases/kernel/syscalls/sched_rr_get_interval/sched_rr_get_interval03.c
+++ b/testcases/kernel/syscalls/sched_rr_get_interval/sched_rr_get_interval03.c
@@ -2,14 +2,20 @@
/*
* Copyright (c) Wipro Technologies Ltd, 2002. All Rights Reserved.
* AUTHOR : Saji Kumar.V.R <saji.kumar@wipro.com>
+ */
+/*\
+ * [Description]
+ *
+ * Verify that:
+ *
+ * - sched_rr_get_interval() fails with errno set to EINVAL for an
+ * invalid pid
+ *
+ * - sched_rr_get_interval() fails with errno set to ESRCH if the
+ * process with specified pid does not exists
*
- * Verify that
- * 1) sched_rr_get_interval() fails with errno set to EINVAL for an
- * invalid pid
- * 2) sched_rr_get_interval() fails with errno set to ESRCH if the
- * process with specified pid does not exists
- * 3) sched_rr_get_interval() fails with errno set to EFAULT if the
- * address specified as &tp is invalid
+ * - sched_rr_get_interval() fails with errno set to EFAULT if the
+ * address specified as &tp is invalid
*/
#include "time64_variants.h"
diff --git a/testcases/kernel/syscalls/sched_setparam/sched_setparam03.c b/testcases/kernel/syscalls/sched_setparam/sched_setparam03.c
index 759b790b6..ffa92a3bf 100644
--- a/testcases/kernel/syscalls/sched_setparam/sched_setparam03.c
+++ b/testcases/kernel/syscalls/sched_setparam/sched_setparam03.c
@@ -49,7 +49,7 @@ void setup(void)
tst_res(TINFO, "Testing %s variant", tv->desc);
if (tv->sched_setscheduler(0, SCHED_FIFO, &p))
- tst_brk(TBROK | TERRNO, "sched_setcheduler(0, SCHED_FIFO, 1)");
+ tst_brk(TBROK | TERRNO, "sched_setscheduler(0, SCHED_FIFO, 1)");
}
static struct tst_test test = {
diff --git a/testcases/kernel/syscalls/sched_setparam/sched_setparam04.c b/testcases/kernel/syscalls/sched_setparam/sched_setparam04.c
index dbcb3c55c..26477e455 100644
--- a/testcases/kernel/syscalls/sched_setparam/sched_setparam04.c
+++ b/testcases/kernel/syscalls/sched_setparam/sched_setparam04.c
@@ -2,22 +2,23 @@
/*
* Copyright (c) 2021, BELLSOFT. All rights reserved.
* Copyright (c) Wipro Technologies Ltd, 2002. All Rights Reserved.
- * AUTHOR: Saji Kumar.V.R <saji.kumar@wipro.com>
+ * Author: Saji Kumar.V.R <saji.kumar@wipro.com>
*/
/*\
* [Description]
*
* Verify that:
+ *
* 1. sched_setparam(2) returns -1 and sets errno to ESRCH if the
- * process with specified pid could not be found
+ * process with specified pid could not be found.
* 2. sched_setparam(2) returns -1 and sets errno to EINVAL if
- * the parameter pid is an invalid value (-1)
+ * the parameter pid is an invalid value (-1).
* 3. sched_setparam(2) returns -1 and sets errno to EINVAL if the
- * parameter p is an invalid address
+ * parameter p is an invalid address.
* 4. sched_setparam(2) returns -1 sets errno to EINVAL if the
* value for p.sched_priority is other than 0 for scheduling
- * policy, SCHED_OTHER
+ * policy, SCHED_OTHER.
*/
#include "tst_test.h"
diff --git a/testcases/kernel/syscalls/sched_setscheduler/.gitignore b/testcases/kernel/syscalls/sched_setscheduler/.gitignore
index aa8ad9695..1b8860d2c 100644
--- a/testcases/kernel/syscalls/sched_setscheduler/.gitignore
+++ b/testcases/kernel/syscalls/sched_setscheduler/.gitignore
@@ -1,3 +1,4 @@
/sched_setscheduler01
/sched_setscheduler02
/sched_setscheduler03
+/sched_setscheduler04
diff --git a/testcases/kernel/syscalls/sched_setscheduler/sched_setscheduler04.c b/testcases/kernel/syscalls/sched_setscheduler/sched_setscheduler04.c
new file mode 100644
index 000000000..828d1ec09
--- /dev/null
+++ b/testcases/kernel/syscalls/sched_setscheduler/sched_setscheduler04.c
@@ -0,0 +1,78 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (c) 2022 Federico Bonfiglio <federico.bonfiglio@protonmail.ch>
+ */
+
+/*
+ * [Description]
+ *
+ * Testcases that test if sched_setscheduler with flag
+ * SCHED_RESET_ON_FORK restores children policy to
+ * SCHED_NORMAL.
+ *
+ */
+
+#define _GNU_SOURCE
+#include <stdio.h>
+#include <stdlib.h>
+#include <sched.h>
+#include <linux/sched.h>
+
+#include "tst_test.h"
+#include "tst_sched.h"
+
+struct test_case_t {
+ int policy;
+ char *desc;
+};
+
+static struct test_case_t cases[] = {
+ {
+ .policy = SCHED_FIFO,
+ .desc = "SCHED_FIFO"
+ },
+ {
+ .policy = SCHED_RR,
+ .desc = "SCHED_RR"
+ }
+};
+
+static void test_reset_on_fork(unsigned int i)
+{
+ struct sched_variant *tv = &sched_variants[tst_variant];
+ struct test_case_t *tc = &cases[i];
+
+ tst_res(TINFO, "Testing %s variant %s policy", tv->desc, tc->desc);
+
+ struct sched_param param = { .sched_priority = 10 };
+
+ tv->sched_setscheduler(getpid(), tc->policy | SCHED_RESET_ON_FORK, &param);
+
+ pid_t pid = SAFE_FORK();
+
+ if (pid) {
+ if (sched_getscheduler(pid) == SCHED_NORMAL)
+ tst_res(TPASS, "Policy reset to SCHED_NORMAL");
+ else
+ tst_res(TFAIL, "Policy NOT reset to SCHED_NORMAL");
+
+ sched_getparam(pid, &param);
+
+ /* kernel will return sched_priority 0 if task is not RT Policy */
+ if (param.sched_priority == 0)
+ tst_res(TPASS, "Priority set to 0");
+ else
+ tst_res(TFAIL, "Priority not set to 0");
+ }
+}
+
+static struct tst_test test = {
+ .forks_child = 1,
+ .caps = (struct tst_cap[]) {
+ TST_CAP(TST_CAP_REQ, CAP_SYS_NICE),
+ {}
+ },
+ .test_variants = ARRAY_SIZE(sched_variants),
+ .tcnt = ARRAY_SIZE(cases),
+ .test = test_reset_on_fork,
+};
diff --git a/testcases/kernel/syscalls/sendfile/sendfile09.c b/testcases/kernel/syscalls/sendfile/sendfile09.c
index 4a2d2083f..6cb3cd593 100644
--- a/testcases/kernel/syscalls/sendfile/sendfile09.c
+++ b/testcases/kernel/syscalls/sendfile/sendfile09.c
@@ -1,6 +1,7 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Copyright (c) International Business Machines Corp., 2014
+ * Copyright (c) Linux Test Project, 2013-2023
*/
/*\
@@ -20,11 +21,7 @@
#include <inttypes.h>
#include <sys/sendfile.h>
-
#include "tst_test.h"
-#include "lapi/abisize.h"
-
-#ifndef TST_ABI32
#define ONE_GB (INT64_C(1) << 30)
#define IN_FILE "in_file"
@@ -97,12 +94,9 @@ static struct tst_test test = {
.test = run,
.tcnt = ARRAY_SIZE(tc),
.max_runtime = 120,
+ .skip_in_compat = 1,
.tags = (const struct tst_tag[]) {
{"linux-git", "5d73320a96fcc"},
{}
}
};
-
-#else
-TST_TEST_TCONF("This test is only for 64bit");
-#endif
diff --git a/testcases/kernel/syscalls/sendmmsg/sendmmsg.h b/testcases/kernel/syscalls/sendmmsg/sendmmsg.h
index 65d5b680f..69ed80d44 100644
--- a/testcases/kernel/syscalls/sendmmsg/sendmmsg.h
+++ b/testcases/kernel/syscalls/sendmmsg/sendmmsg.h
@@ -1,5 +1,8 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
+#ifndef SENDMMSG_H__
+#define SENDMMSG_H__
+
#include <netinet/ip.h>
#include <stdio.h>
#include <stdlib.h>
@@ -25,3 +28,5 @@ static struct time64_variants variants[] = {
{ .recvmmsg = sys_recvmmsg64, .sendmmsg = sys_sendmmsg, .ts_type = TST_KERN_TIMESPEC, .desc = "syscall time64 with kernel spec"},
#endif
};
+
+#endif /* SENDMMSG_H__ */
diff --git a/testcases/kernel/syscalls/setgroups/.gitignore b/testcases/kernel/syscalls/setgroups/.gitignore
index 9de928241..0649a3425 100644
--- a/testcases/kernel/syscalls/setgroups/.gitignore
+++ b/testcases/kernel/syscalls/setgroups/.gitignore
@@ -4,3 +4,5 @@
/setgroups02_16
/setgroups03
/setgroups03_16
+/setgroups04
+/setgroups04_16
diff --git a/testcases/kernel/syscalls/setgroups/Makefile b/testcases/kernel/syscalls/setgroups/Makefile
index b2bb1e005..41160978e 100644
--- a/testcases/kernel/syscalls/setgroups/Makefile
+++ b/testcases/kernel/syscalls/setgroups/Makefile
@@ -3,6 +3,9 @@
top_srcdir ?= ../../../..
+# Remove after rewriting setgroups04.c to the new API.
+USE_LEGACY_COMPAT_16_H := 1
+
include $(top_srcdir)/include/mk/testcases.mk
include $(abs_srcdir)/../utils/compat_16.mk
include $(top_srcdir)/include/mk/generic_leaf_target.mk
diff --git a/testcases/kernel/syscalls/setgroups/setgroups04.c b/testcases/kernel/syscalls/setgroups/setgroups04.c
new file mode 100644
index 000000000..93a064cda
--- /dev/null
+++ b/testcases/kernel/syscalls/setgroups/setgroups04.c
@@ -0,0 +1,167 @@
+/*
+ * Copyright (C) Bull S.A. 2001
+ * Copyright (c) International Business Machines Corp., 2001
+ *
+ * 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
+ */
+
+/*
+ * Test Name: setgroups04
+ *
+ * Test Description:
+ * Verify that, setgroups() fails with -1 and sets errno to EFAULT if the list has an invalid address.
+ *
+ * Expected Result:
+ * setgroups() should fail with return value -1 and set expected errno.
+ *
+ * Algorithm:
+ * Setup:
+ * Setup signal handling.
+ * Pause for SIGUSR1 if option specified.
+ *
+ * Test:
+ * Loop if the proper options are given.
+ * Execute system call
+ * Check return code, if system call failed (return=-1)
+ * if errno set == expected errno
+ * Issue sys call fails with expected return value and errno.
+ * Otherwise,
+ * Issue sys call fails with unexpected errno.
+ * Otherwise,
+ * Issue sys call returns unexpected value.
+ *
+ * Cleanup:
+ * Print errno log and/or timing stats if options given
+ *
+ * Usage: <for command-line>
+ * setgroups04 [-c n] [-e] [-i n] [-I x] [-P x] [-t]
+ * where, -c n : Run n copies concurrently.
+ * -f : Turn off functionality Testing.
+ * -i n : Execute test n times.
+ * -I x : Execute test for x seconds.
+ * -P x : Pause for x seconds between iterations.
+ * -t : Turn on syscall timing.
+ *
+ * HISTORY
+ * 05/2002 Ported by André Merlier
+ *
+ * RESTRICTIONS:
+ * none.
+ *
+ */
+#include <sys/types.h>
+#include <sys/param.h>
+#include <unistd.h>
+#include <errno.h>
+#include <pwd.h>
+#include <grp.h>
+
+#include "test.h"
+
+/*
+ * Don't forget to remove USE_LEGACY_COMPAT_16_H from Makefile after
+ * rewriting this test to the new API.
+ */
+#include "compat_16.h"
+
+TCID_DEFINE(setgroups04);
+int TST_TOTAL = 1;
+
+GID_T groups_list[NGROUPS];
+
+void setup(); /* setup function for the test */
+void cleanup(); /* cleanup function for the test */
+
+#if !defined(UCLINUX)
+
+int main(int ac, char **av)
+{
+ int lc;
+ int gidsetsize; /* total no. of groups */
+ char *test_desc; /* test specific error message */
+
+ tst_parse_opts(ac, av, NULL, NULL);
+
+ /* Perform setup for test */
+ setup();
+
+ for (lc = 0; TEST_LOOPING(lc); lc++) {
+
+ tst_count = 0;
+
+ gidsetsize = NGROUPS;
+ test_desc = "EFAULT";
+
+ /*
+ * Call setgroups() to test condition
+ * verify that it fails with -1 return value and
+ * sets appropriate errno.
+ */
+ TEST(SETGROUPS(cleanup, gidsetsize, sbrk(0)));
+
+ if (TEST_RETURN != -1) {
+ tst_resm(TFAIL, "setgroups() returned %ld, "
+ "expected -1, errno=%d", TEST_RETURN,
+ EFAULT);
+ } else {
+
+ if (TEST_ERRNO == EFAULT) {
+ tst_resm(TPASS,
+ "setgroups() fails with expected "
+ "error EFAULT errno:%d", TEST_ERRNO);
+ } else {
+ tst_resm(TFAIL, "setgroups() fails, %s, "
+ "errno=%d, expected errno=%d",
+ test_desc, TEST_ERRNO, EFAULT);
+ }
+ }
+
+ }
+
+ cleanup();
+ tst_exit();
+
+}
+
+#else
+
+int main(void)
+{
+ tst_resm(TINFO, "test is not available on uClinux");
+ tst_exit();
+}
+
+#endif /* if !defined(UCLINUX) */
+
+/*
+ * setup()
+ */
+void setup(void)
+{
+ tst_require_root();
+
+ tst_sig(NOFORK, DEF_HANDLER, cleanup);
+
+ TEST_PAUSE;
+
+}
+
+/*
+ * cleanup()
+ */
+void cleanup(void)
+{
+
+}
diff --git a/testcases/kernel/syscalls/setsockopt/.gitignore b/testcases/kernel/syscalls/setsockopt/.gitignore
index fd3235bb3..5c05290a5 100644
--- a/testcases/kernel/syscalls/setsockopt/.gitignore
+++ b/testcases/kernel/syscalls/setsockopt/.gitignore
@@ -7,3 +7,4 @@
/setsockopt07
/setsockopt08
/setsockopt09
+/setsockopt10
diff --git a/testcases/kernel/syscalls/setsockopt/setsockopt10.c b/testcases/kernel/syscalls/setsockopt/setsockopt10.c
new file mode 100644
index 000000000..4e7e44938
--- /dev/null
+++ b/testcases/kernel/syscalls/setsockopt/setsockopt10.c
@@ -0,0 +1,205 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (C) 2023 SUSE LLC Richard Palethorpe <rpalethorpe@suse.com>
+ */
+/*\
+ * [Description]
+ *
+ * Reproducer for CVE-2023-0461 which is an exploitable use-after-free
+ * in a TLS socket. In fact it is exploitable in any User Level
+ * Protocol (ULP) which does not clone its context when accepting a
+ * connection.
+ *
+ * Because it does not clone the context, the child socket which is
+ * created on accept has a pointer to the listening socket's
+ * context. When the child is closed the parent's context is freed
+ * while it still has a reference to it.
+ *
+ * TLS can only be added to a socket which is connected. Not listening
+ * or disconnected, and a connected socket can not be set to
+ * listening. So we have to connect the socket, add TLS, then
+ * disconnect, then set it to listening.
+ *
+ * To my knowledge, setting a socket from open to disconnected
+ * requires a trick; we have to "connect" to an unspecified
+ * address. This could explain why the bug was not found earlier.
+ *
+ * The accepted fix was to disallow listening on sockets with a ULP
+ * set which does not have a clone function.
+ *
+ * The test uses two processes, first the child acts as a server so
+ * that the parent can create the TLS socket. Then the child connects
+ * to the parent's TLS socket.
+ *
+ * When we try to listen on the parent, the current kernel should
+ * return EINVAL. However if clone is implemented then this could
+ * become a valid operation. It is also quite easy to crash the kernel
+ * if we set some TLS options before doing a double free.
+ *
+ * commit 2c02d41d71f90a5168391b6a5f2954112ba2307c
+ * Author: Paolo Abeni <pabeni@redhat.com>
+ * Date: Tue Jan 3 12:19:17 2023 +0100
+ *
+ * net/ulp: prevent ULP without clone op from entering the LISTEN status
+ */
+
+#include "sched.h"
+#include "tst_test.h"
+
+#ifdef HAVE_LINUX_TLS_H
+
+#include <linux/tls.h>
+#include <netinet/in.h>
+
+#include "lapi/sched.h"
+#include "lapi/socket.h"
+#include "lapi/tcp.h"
+#include "tst_checkpoint.h"
+#include "tst_net.h"
+#include "tst_safe_net.h"
+#include "tst_taint.h"
+
+static struct tls12_crypto_info_aes_gcm_128 opts = {
+ .info = {
+ .version = TLS_1_2_VERSION,
+ .cipher_type = TLS_CIPHER_AES_GCM_128,
+ },
+ .iv = { 'i', 'v' },
+ .key = { 'k', 'e', 'y' },
+ .salt = { 's', 'a', 'l', 't' },
+ .rec_seq = { 'r', 'e', 'c', 's' },
+};
+
+static struct sockaddr_in tcp0_addr, tcp1_addr;
+static const struct sockaddr unspec_addr = {
+ .sa_family = AF_UNSPEC
+};
+
+static int tcp0_sk, tcp1_sk, tcp2_sk, tcp3_sk;
+
+static void setup(void)
+{
+ tst_init_sockaddr_inet(&tcp0_addr, "127.0.0.1", 0x7c90);
+ tst_init_sockaddr_inet(&tcp1_addr, "127.0.0.1", 0x7c91);
+}
+
+static void cleanup(void)
+{
+ if (tcp0_sk > 0)
+ SAFE_CLOSE(tcp0_sk);
+ if (tcp1_sk > 0)
+ SAFE_CLOSE(tcp1_sk);
+ if (tcp2_sk > 0)
+ SAFE_CLOSE(tcp2_sk);
+ if (tcp3_sk > 0)
+ SAFE_CLOSE(tcp3_sk);
+}
+
+static void child(void)
+{
+ tst_res(TINFO, "child: Listen for tcp1 connection");
+ tcp0_sk = SAFE_SOCKET(AF_INET, SOCK_STREAM, 0);
+ SAFE_BIND(tcp0_sk, (struct sockaddr *)&tcp0_addr, sizeof(tcp0_addr));
+ SAFE_LISTEN(tcp0_sk, 1);
+ TST_CHECKPOINT_WAKE(0);
+
+ tcp3_sk = SAFE_ACCEPT(tcp0_sk, NULL, 0);
+ TST_CHECKPOINT_WAIT(1);
+ SAFE_CLOSE(tcp3_sk);
+ SAFE_CLOSE(tcp0_sk);
+
+ tcp3_sk = SAFE_SOCKET(AF_INET, SOCK_STREAM, 0);
+ TST_CHECKPOINT_WAIT(2);
+
+ tst_res(TINFO, "child: connect for tcp2 connection");
+ TEST(connect(tcp3_sk, (struct sockaddr *)&tcp1_addr, sizeof(tcp1_addr)));
+
+ if (TST_RET == -1) {
+ tst_res(TINFO | TTERRNO, "child: could not connect to tcp1");
+ return;
+ }
+
+ TST_CHECKPOINT_WAIT(3);
+}
+
+static void run(void)
+{
+ const pid_t child_pid = SAFE_FORK();
+
+ if (child_pid == 0) {
+ child();
+ return;
+ }
+
+ tcp1_sk = SAFE_SOCKET(AF_INET, SOCK_STREAM, 0);
+ TST_CHECKPOINT_WAIT(0);
+
+ tst_res(TINFO, "parent: Connect for tcp0 connection");
+ SAFE_CONNECT(tcp1_sk, (struct sockaddr *)&tcp0_addr, sizeof(tcp0_addr));
+ TEST(setsockopt(tcp1_sk, SOL_TCP, TCP_ULP, "tls", 3));
+
+ if (TST_RET == -1 && TST_ERR == ENOENT)
+ tst_brk(TCONF | TTERRNO, "parent: setsockopt failed: The TLS module is probably not loaded");
+ else if (TST_RET == -1)
+ tst_brk(TBROK | TTERRNO, "parent: setsockopt failed");
+
+ SAFE_SETSOCKOPT(tcp1_sk, SOL_TLS, TLS_TX, &opts, sizeof(opts));
+ TST_CHECKPOINT_WAKE(1);
+
+ tst_res(TINFO, "parent: Disconnect by setting unspec address");
+ SAFE_CONNECT(tcp1_sk, &unspec_addr, sizeof(unspec_addr));
+ SAFE_BIND(tcp1_sk, (struct sockaddr *)&tcp1_addr, sizeof(tcp1_addr));
+
+ TEST(listen(tcp1_sk, 1));
+
+ if (TST_RET == -1) {
+ if (TST_ERR == EINVAL)
+ tst_res(TPASS | TTERRNO, "parent: Can't listen on disconnected TLS socket");
+ else
+ tst_res(TCONF | TTERRNO, "parent: Can't listen on disconnected TLS socket, but the errno is not EINVAL as expected");
+
+ TST_CHECKPOINT_WAKE(2);
+ tst_reap_children();
+ return;
+ }
+
+ tst_res(TINFO, "parent: Can listen on disconnected TLS socket");
+ TST_CHECKPOINT_WAKE(2);
+
+ tcp2_sk = SAFE_ACCEPT(tcp1_sk, NULL, 0);
+ SAFE_CLOSE(tcp2_sk);
+
+ tst_res(TINFO, "parent: Attempting double free, because we set cipher options this should result in an crash");
+ tst_flush();
+ SAFE_CLOSE(tcp1_sk);
+
+ TST_CHECKPOINT_WAKE(3);
+ tst_reap_children();
+ sched_yield();
+
+ tst_res(TCONF, "parent: We're still here, maybe the kernel can clone the TLS-ULP context now?");
+}
+
+static struct tst_test test = {
+ .setup = setup,
+ .cleanup = cleanup,
+ .test_all = run,
+ .forks_child = 1,
+ .needs_checkpoints = 1,
+ .taint_check = TST_TAINT_W | TST_TAINT_D,
+ .needs_kconfigs = (const char *[]) {
+ "CONFIG_TLS",
+ NULL
+ },
+ .tags = (const struct tst_tag[]) {
+ {"linux-git", "2c02d41d71f90"},
+ {"CVE", "2023-0461"},
+ {}
+ }
+};
+
+#else
+
+TST_TEST_TCONF("linux/tls.h missing, we assume your system is too old");
+
+#endif
diff --git a/testcases/kernel/syscalls/setuid/Makefile b/testcases/kernel/syscalls/setuid/Makefile
index 1fdd7bd76..88d6385d9 100644
--- a/testcases/kernel/syscalls/setuid/Makefile
+++ b/testcases/kernel/syscalls/setuid/Makefile
@@ -4,8 +4,5 @@ top_srcdir ?= ../../../..
include $(top_srcdir)/include/mk/testcases.mk
-#for compat_16.mk uses the compat_16_tst.h
-COMPAT_TST_16_H := 1
-
include $(abs_srcdir)/../utils/compat_16.mk
include $(top_srcdir)/include/mk/generic_leaf_target.mk
diff --git a/testcases/kernel/syscalls/setxattr/setxattr01.c b/testcases/kernel/syscalls/setxattr/setxattr01.c
index 8cd2821d0..31f41369a 100644
--- a/testcases/kernel/syscalls/setxattr/setxattr01.c
+++ b/testcases/kernel/syscalls/setxattr/setxattr01.c
@@ -137,7 +137,7 @@ static void verify_setxattr(unsigned int i)
{
/* some tests might require existing keys for each iteration */
if (tc[i].keyneeded) {
- SAFE_SETXATTR(FNAME, tc[i].key, tc[i].value, tc[i].size,
+ SAFE_SETXATTR(FNAME, tc[i].key, *tc[i].value, tc[i].size,
XATTR_CREATE);
}
diff --git a/testcases/kernel/syscalls/sighold/sighold02.c b/testcases/kernel/syscalls/sighold/sighold02.c
index 1cfb7688b..2807bf67e 100644
--- a/testcases/kernel/syscalls/sighold/sighold02.c
+++ b/testcases/kernel/syscalls/sighold/sighold02.c
@@ -1,9 +1,7 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Copyright (c) 2000 Silicon Graphics, Inc. All Rights Reserved.
- * AUTHOR : Bob Clark
- * CO-PILOT : Barrie Kletscher
- * DATE STARTED : 9/26/86
+ * Authors: Bob Clark, Barrie Kletscher
* Copyright (C) 2015 Cyril Hrubis <chrubis@suse.cz>
* Copyright (C) 2021 SUSE LLC Andrea Cervesato <andrea.cervesato@suse.com>
*/
@@ -12,8 +10,9 @@
* [Description]
*
* This test checks following conditions:
- * 1. sighold action to turn off the receipt of all signals was done without error.
- * 2. After signals were held, and sent, no signals were trapped.
+ *
+ * 1. sighold action to turn off the receipt of all signals was done without error.
+ * 2. After signals were held, and sent, no signals were trapped.
*/
#define _XOPEN_SOURCE 600
diff --git a/testcases/kernel/syscalls/splice/.gitignore b/testcases/kernel/syscalls/splice/.gitignore
index a3e502f00..88a8dff78 100644
--- a/testcases/kernel/syscalls/splice/.gitignore
+++ b/testcases/kernel/syscalls/splice/.gitignore
@@ -3,3 +3,5 @@
/splice03
/splice04
/splice05
+/splice06
+/splice07
diff --git a/testcases/kernel/syscalls/splice/splice06.c b/testcases/kernel/syscalls/splice/splice06.c
new file mode 100644
index 000000000..0cb5dec29
--- /dev/null
+++ b/testcases/kernel/syscalls/splice/splice06.c
@@ -0,0 +1,228 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (c) 2023 SUSE LLC <wegao@suse.com>
+ */
+
+/*\
+ * [Description]
+ *
+ * This test is cover splice() on proc files.
+ *
+ */
+
+#define _GNU_SOURCE
+
+#include <stdio.h>
+#include <errno.h>
+#include <string.h>
+#include <signal.h>
+#include <sys/types.h>
+#include <fcntl.h>
+#include <ctype.h>
+
+#include "tst_test.h"
+#include "lapi/splice.h"
+
+#define BUF_SIZE 100
+#define PIPE_MAX_INIT_SIZE 65536
+#define DOMAIN_INIT_NAME "LTP_INIT"
+#define DOMAIN_TEST_NAME "LTP_TEST"
+#define INTEGER_PROCFILE "/proc/sys/fs/pipe-max-size"
+#define STRING_PROCFILE "/proc/sys/kernel/domainname"
+static int pipe_max_test_size;
+
+static void format_str(char *str)
+{
+ int i;
+
+ for (i = 0; i < BUF_SIZE ; i++) {
+ if (!isdigit(str[i])) {
+ str[i] = '\0';
+ break;
+ }
+ }
+ if (i == BUF_SIZE)
+ tst_brk(TBROK, "can not find nonnumeric character from input string");
+}
+
+static int splice_read_num(const char *file)
+{
+ int pipes[2];
+ int fd_in;
+ int ret;
+ int num;
+ char buf[BUF_SIZE];
+
+ memset(buf, '\0', sizeof(buf));
+ fd_in = SAFE_OPEN(file, O_RDONLY);
+ SAFE_PIPE(pipes);
+
+ ret = splice(fd_in, NULL, pipes[1], NULL, BUF_SIZE - 1, 0);
+ if (ret < 0)
+ tst_brk(TBROK | TERRNO, "splice(fd_in, pipe) failed");
+
+ SAFE_READ(0, pipes[0], buf, BUF_SIZE);
+
+ /* Search for the first nonnumeric character and replace it with \0 */
+ format_str(buf);
+
+ if (tst_parse_int(buf, &num, 0, INT_MAX))
+ tst_brk(TBROK, "Invalid buffer num %s", buf);
+
+ SAFE_CLOSE(fd_in);
+ SAFE_CLOSE(pipes[0]);
+ SAFE_CLOSE(pipes[1]);
+
+ return num;
+}
+
+static char *splice_read_str(const char *file, char *dest)
+{
+ int pipes[2];
+ int fd_in;
+ int ret;
+
+ fd_in = SAFE_OPEN(file, O_RDONLY);
+ SAFE_PIPE(pipes);
+
+ ret = splice(fd_in, NULL, pipes[1], NULL, BUF_SIZE, 0);
+ if (ret < 0)
+ tst_brk(TBROK | TERRNO, "splice(fd_in, pipe) failed");
+
+ SAFE_READ(0, pipes[0], dest, BUF_SIZE);
+
+ SAFE_CLOSE(fd_in);
+ SAFE_CLOSE(pipes[0]);
+ SAFE_CLOSE(pipes[1]);
+
+ return dest;
+}
+
+
+static void splice_write_num(const char *file, int num)
+{
+ int pipes[2];
+ int fd_out;
+ int ret;
+ char buf[BUF_SIZE];
+
+ memset(buf, '\0', sizeof(buf));
+
+ fd_out = SAFE_OPEN(file, O_WRONLY, 0777);
+ SAFE_PIPE(pipes);
+ sprintf(buf, "%d", num);
+
+ SAFE_WRITE(SAFE_WRITE_ALL, pipes[1], buf, strlen(buf));
+
+ ret = splice(pipes[0], NULL, fd_out, NULL, BUF_SIZE, 0);
+ if (ret < 0)
+ tst_brk(TBROK | TERRNO, "splice write failed");
+
+ SAFE_CLOSE(fd_out);
+ SAFE_CLOSE(pipes[0]);
+ SAFE_CLOSE(pipes[1]);
+}
+
+static void splice_write_str(const char *file, char *dest)
+{
+ int pipes[2];
+ int fd_out;
+ int ret;
+
+ fd_out = SAFE_OPEN(file, O_WRONLY, 0777);
+ SAFE_PIPE(pipes);
+
+ SAFE_WRITE(SAFE_WRITE_ALL, pipes[1], dest, strlen(dest));
+
+ ret = splice(pipes[0], NULL, fd_out, NULL, BUF_SIZE, 0);
+ if (ret < 0)
+ tst_brk(TBROK | TERRNO, "splice write failed");
+
+ SAFE_CLOSE(fd_out);
+ SAFE_CLOSE(pipes[0]);
+ SAFE_CLOSE(pipes[1]);
+}
+
+static void file_write_num(const char *file, int num)
+{
+ SAFE_FILE_PRINTF(file, "%d", num);
+}
+
+static void file_write_str(const char *file, char *dest)
+{
+ SAFE_FILE_PRINTF(file, "%s", dest);
+}
+
+static int file_read_num(const char *file)
+{
+ int num;
+
+ SAFE_FILE_SCANF(file, "%d", &num);
+
+ return num;
+}
+
+static char *file_read_str(const char *file, char *dest)
+{
+ SAFE_FILE_SCANF(file, "%s", dest);
+ return dest;
+}
+
+static void splice_test(void)
+{
+
+ char buf_file[BUF_SIZE];
+ char buf_splice[BUF_SIZE];
+
+ if (file_read_num(INTEGER_PROCFILE) == splice_read_num(INTEGER_PROCFILE))
+ tst_res(TPASS, "Read num through splice correctly");
+ else
+ tst_brk(TBROK | TERRNO, "Read num through splice failed");
+
+ splice_write_num(INTEGER_PROCFILE, pipe_max_test_size);
+
+ if (file_read_num(INTEGER_PROCFILE) == pipe_max_test_size)
+ tst_res(TPASS, "Write num through splice correctly");
+ else
+ tst_brk(TBROK | TERRNO, "Write num through splice failed");
+
+ memset(buf_file, '\0', sizeof(buf_file));
+ memset(buf_splice, '\0', sizeof(buf_splice));
+
+ file_read_str(STRING_PROCFILE, buf_file);
+ splice_read_str(STRING_PROCFILE, buf_splice);
+
+ if (!strncmp(buf_file, buf_splice, strlen(buf_file)))
+ tst_res(TPASS, "Read string through splice correctly");
+ else
+ tst_brk(TBROK | TERRNO, "Read string through splice failed");
+
+ memset(buf_file, '\0', sizeof(buf_file));
+
+ splice_write_str(STRING_PROCFILE, DOMAIN_TEST_NAME);
+ file_read_str(STRING_PROCFILE, buf_file);
+
+ if (!strncmp(buf_file, DOMAIN_TEST_NAME, strlen(buf_file)))
+ tst_res(TPASS, "Write string through splice correctly");
+ else
+ tst_brk(TBROK | TERRNO, "Write string through splice failed");
+}
+
+static void setup(void)
+{
+ pipe_max_test_size = getpagesize();
+ file_write_str(STRING_PROCFILE, DOMAIN_INIT_NAME);
+ file_write_num(STRING_PROCFILE, PIPE_MAX_INIT_SIZE);
+}
+
+static struct tst_test test = {
+ .min_kver = "5.11",
+ .setup = setup,
+ .test_all = splice_test,
+ .needs_tmpdir = 1,
+ .save_restore = (const struct tst_path_val[]) {
+ {INTEGER_PROCFILE, NULL, TST_SR_TCONF},
+ {STRING_PROCFILE, NULL, TST_SR_TCONF},
+ {}
+ },
+};
diff --git a/testcases/kernel/syscalls/splice/splice07.c b/testcases/kernel/syscalls/splice/splice07.c
new file mode 100644
index 000000000..9c23e0aac
--- /dev/null
+++ b/testcases/kernel/syscalls/splice/splice07.c
@@ -0,0 +1,72 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+/*
+ * Copyright (C) 2023-2024 Cyril Hrubis <chrubis@suse.cz>
+ */
+
+/*\
+ * [Description]
+ *
+ * Iterate over all kinds of file descriptors and feed splice() with all possible
+ * combinations where at least one file descriptor is invalid. We do expect the
+ * syscall to fail either with EINVAL or EBADF.
+ */
+
+#define _GNU_SOURCE
+
+#include <sys/socket.h>
+#include <netinet/in.h>
+
+#include "tst_test.h"
+
+static void check_splice(struct tst_fd *fd_in, struct tst_fd *fd_out)
+{
+ /* These combinations just hang since the pipe is empty */
+ if (fd_in->type == TST_FD_PIPE_READ) {
+ switch (fd_out->type) {
+ case TST_FD_FILE:
+ case TST_FD_PIPE_WRITE:
+ case TST_FD_UNIX_SOCK:
+ case TST_FD_INET_SOCK:
+ case TST_FD_MEMFD:
+ return;
+ default:
+ break;
+ }
+ }
+
+ if (fd_out->type == TST_FD_PIPE_WRITE) {
+ switch (fd_in->type) {
+ /* While these combinations succeeed */
+ case TST_FD_DEV_ZERO:
+ case TST_FD_FILE:
+ case TST_FD_PROC_MAPS:
+ case TST_FD_MEMFD:
+ return;
+ /* And this complains about socket not being connected */
+ case TST_FD_INET_SOCK:
+ return;
+ default:
+ break;
+ }
+ }
+
+ const int exp_errnos[] = {EBADF, EINVAL};
+
+ TST_EXP_FAIL2_ARR(splice(fd_in->fd, NULL, fd_out->fd, NULL, 1, 0),
+ exp_errnos, "splice() on %s -> %s",
+ tst_fd_desc(fd_in), tst_fd_desc(fd_out));
+}
+
+static void verify_splice(void)
+{
+ TST_FD_FOREACH(fd_in) {
+ tst_res(TINFO, "%s -> ...", tst_fd_desc(&fd_in));
+ TST_FD_FOREACH(fd_out)
+ check_splice(&fd_in, &fd_out);
+ }
+}
+
+static struct tst_test test = {
+ .test_all = verify_splice,
+};
diff --git a/testcases/kernel/syscalls/swapon/swapon01.c b/testcases/kernel/syscalls/swapon/swapon01.c
index c334ae246..e59fb20a1 100644
--- a/testcases/kernel/syscalls/swapon/swapon01.c
+++ b/testcases/kernel/syscalls/swapon/swapon01.c
@@ -1,6 +1,7 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Copyright (c) Wipro Technologies Ltd, 2002. All Rights Reserved.
+ * Copyright (c) Linux Test Project, 2003-2024
*/
/*\
@@ -16,30 +17,26 @@
#include "lapi/syscalls.h"
#include "libswap.h"
+#define SWAP_FILE "swapfile01"
+
static void verify_swapon(void)
{
- TEST(tst_syscall(__NR_swapon, "./swapfile01", 0));
+ TST_EXP_PASS(tst_syscall(__NR_swapon, SWAP_FILE, 0));
- if (TST_RET == -1) {
- tst_res(TFAIL | TTERRNO, "Failed to turn on swapfile");
- } else {
- tst_res(TPASS, "Succeeded to turn on swapfile");
- /*we need to turn this swap file off for -i option */
- if (tst_syscall(__NR_swapoff, "./swapfile01") != 0) {
- tst_brk(TBROK | TERRNO, "Failed to turn off swapfile,"
- " system reboot after execution of LTP "
- "test suite is recommended.");
- }
+ if (TST_PASS && tst_syscall(__NR_swapoff, SWAP_FILE) != 0) {
+ tst_brk(TBROK | TERRNO,
+ "Failed to turn off swapfile, system reboot recommended");
}
}
static void setup(void)
{
- is_swap_supported("./tstswap");
- make_swapfile("swapfile01", 0);
+ is_swap_supported(SWAP_FILE);
+ make_swapfile(SWAP_FILE, 0);
}
static struct tst_test test = {
+ .needs_root = 1,
.needs_tmpdir = 1,
.test_all = verify_swapon,
.setup = setup
diff --git a/testcases/kernel/syscalls/swapon/swapon02.c b/testcases/kernel/syscalls/swapon/swapon02.c
index d34c17a80..fceea77be 100644
--- a/testcases/kernel/syscalls/swapon/swapon02.c
+++ b/testcases/kernel/syscalls/swapon/swapon02.c
@@ -1,56 +1,39 @@
// SPDX-License-Identifier: GPL-2.0-or-later
-
/*
* Copyright (c) Wipro Technologies Ltd, 2002. All Rights Reserved.
+ * Copyright (c) Linux Test Project, 2002-2023
*/
/*\
* [Description]
*
* This test case checks whether swapon(2) system call returns
- * 1. ENOENT when the path does not exist
- * 2. EINVAL when the path exists but is invalid
- * 3. EPERM when user is not a superuser
- * 4. EBUSY when the specified path is already being used as a swap area
+ * - ENOENT when the path does not exist
+ * - EINVAL when the path exists but is invalid
+ * - EPERM when user is not a superuser
+ * - EBUSY when the specified path is already being used as a swap area
*/
-#include <errno.h>
#include <pwd.h>
#include "tst_test.h"
#include "lapi/syscalls.h"
#include "libswap.h"
-static void setup01(void);
-static void cleanup01(void);
-
static uid_t nobody_uid;
static int do_swapoff;
static struct tcase {
char *err_desc;
int exp_errno;
- char *exp_errval;
char *path;
- void (*setup)(void);
- void (*cleanup)(void);
} tcases[] = {
- {"Path does not exist", ENOENT, "ENOENT", "./doesnotexist", NULL, NULL},
- {"Invalid path", EINVAL, "EINVAL", "./notswap", NULL, NULL},
- {"Permission denied", EPERM, "EPERM", "./swapfile01", setup01, cleanup01},
- {"File already used", EBUSY, "EBUSY", "./alreadyused", NULL, NULL},
+ {"Path does not exist", ENOENT, "./doesnotexist"},
+ {"Invalid path", EINVAL, "./notswap"},
+ {"Permission denied", EPERM, "./swapfile01"},
+ {"File already used", EBUSY, "./alreadyused"},
};
-static void setup01(void)
-{
- SAFE_SETEUID(nobody_uid);
-}
-
-static void cleanup01(void)
-{
- SAFE_SETEUID(0);
-}
-
static void setup(void)
{
struct passwd *nobody;
@@ -70,7 +53,7 @@ static void setup(void)
do_swapoff = 1;
}
-void cleanup(void)
+static void cleanup(void)
{
if (do_swapoff && tst_syscall(__NR_swapoff, "alreadyused"))
tst_res(TWARN | TERRNO, "swapoff(alreadyused) failed");
@@ -79,24 +62,19 @@ void cleanup(void)
static void verify_swapon(unsigned int i)
{
struct tcase *tc = tcases + i;
- if (tc->setup)
- tc->setup();
+ if (tc->exp_errno == EPERM)
+ SAFE_SETEUID(nobody_uid);
- TEST(tst_syscall(__NR_swapon, tc->path, 0));
+ TST_EXP_FAIL(tst_syscall(__NR_swapon, tc->path, 0), tc->exp_errno,
+ "swapon(2) fail with %s", tc->err_desc);
- if (tc->cleanup)
- tc->cleanup();
+ if (tc->exp_errno == EPERM)
+ SAFE_SETEUID(0);
- if (TST_RET == -1 && TST_ERR == tc->exp_errno) {
- tst_res(TPASS, "swapon(2) expected failure;"
- " Got errno - %s : %s",
- tc->exp_errval, tc->err_desc);
- return;
+ if (TST_RET != -1) {
+ tst_res(TFAIL, "swapon(2) failed unexpectedly, expected: %s",
+ tst_strerrno(tc->exp_errno));
}
-
- tst_res(TFAIL, "swapon(2) failed to produce expected error:"
- " %d, errno: %s and got %d.", tc->exp_errno,
- tc->exp_errval, TST_ERR);
}
static struct tst_test test = {
diff --git a/testcases/kernel/syscalls/swapon/swaponoff.h b/testcases/kernel/syscalls/swapon/swaponoff.h
index e3eae3fe3..900761bda 100644
--- a/testcases/kernel/syscalls/swapon/swaponoff.h
+++ b/testcases/kernel/syscalls/swapon/swaponoff.h
@@ -2,17 +2,7 @@
#ifndef __SWAP_ON_OFF_H_
#define __SWAP_ON_OFF_H_
-/*
- * Read swapon(2) / swapoff(2) for a full history lesson behind the value of
- * MAX_SWAPFILES.
- */
#include <linux/version.h>
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 18)
#define MAX_SWAPFILES 30
-#elif LINUX_VERSION_CODE > KERNEL_VERSION(2, 4, 10)
-#define MAX_SWAPFILES 32
-#else
-#define MAX_SWAPFILES 8
-#endif
#endif
diff --git a/testcases/kernel/syscalls/symlink/.gitignore b/testcases/kernel/syscalls/symlink/.gitignore
index d1497e680..6ea587ff3 100644
--- a/testcases/kernel/syscalls/symlink/.gitignore
+++ b/testcases/kernel/syscalls/symlink/.gitignore
@@ -2,4 +2,3 @@
/symlink02
/symlink03
/symlink04
-/symlink05
diff --git a/testcases/kernel/syscalls/symlink/symlink02.c b/testcases/kernel/syscalls/symlink/symlink02.c
index c18db2b37..d2226501e 100644
--- a/testcases/kernel/syscalls/symlink/symlink02.c
+++ b/testcases/kernel/syscalls/symlink/symlink02.c
@@ -1,208 +1,40 @@
+// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (c) 2000 Silicon Graphics, Inc. All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of version 2 of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- *
- * Further, this software is distributed without any warranty that it is
- * free of the rightful claim of any third person regarding infringement
- * or the like. Any license provided herein, whether implied or
- * otherwise, applies only to this software file. Patent licenses, if
- * any, provided herein do not apply to combinations of this program with
- * other software, or any other product whatsoever.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
- * Mountain View, CA 94043, or:
- *
- * http://www.sgi.com
- *
- * For further information regarding this notice, see:
- *
- * http://oss.sgi.com/projects/GenInfo/NoticeExplan/
- *
+ * Copyright (c) Linux Test Project, 2001-2023
+ * Author: William Roske
*/
-/* $Id: symlink02.c,v 1.6 2009/08/28 14:17:14 vapier Exp $ */
-/**********************************************************
- *
- * OS Test - Silicon Graphics, Inc.
- *
- * TEST IDENTIFIER : symlink02
- *
- * EXECUTED BY : anyone
- *
- * TEST TITLE : Basic test for symlink(2)
- *
- * PARENT DOCUMENT : usctpl01
- *
- * TEST CASE TOTAL : 1
- *
- * WALL CLOCK TIME : 1
- *
- * CPU TYPES : ALL
- *
- * AUTHOR : William Roske
- *
- * CO-PILOT : Dave Fenner
- *
- * DATE STARTED : 03/30/92
- *
- * INITIAL RELEASE : UNICOS 7.0
- *
- * TEST CASES
- *
- * 1.) symlink(2) returns...(See Description)
- *
- * INPUT SPECIFICATIONS
- * The standard options for system call tests are accepted.
- * (See the parse_opts(3) man page).
- *
- * OUTPUT SPECIFICATIONS
- *$
- * DURATION
- * Terminates - with frequency and infinite modes.
- *
- * SIGNALS
- * Uses SIGUSR1 to pause before test if option set.
- * (See the parse_opts(3) man page).
- *
- * RESOURCES
- * None
- *
- * ENVIRONMENTAL NEEDS
- * No run-time environmental needs.
- *
- * SPECIAL PROCEDURAL REQUIREMENTS
- * None
- *
- * INTERCASE DEPENDENCIES
- * None
- *
- * DETAILED DESCRIPTION
- * This is a Phase I test for the symlink(2) system call. It is intended
- * to provide a limited exposure of the system call, for now. It
- * should/will be extended when full functional tests are written for
- * symlink(2).
- *
- * Setup:
- * Setup signal handling.
- * Pause for SIGUSR1 if option specified.
- *
- * Test:
- * Loop if the proper options are given.
- * Execute system call
- * Check return code, if system call failed (return=-1)
- * Log the errno and Issue a FAIL message.
- * Otherwise, Issue a PASS message.
- *
- * Cleanup:
- * Print errno log and/or timing stats if options given
- *
- *
- *#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#**/
-#include <sys/types.h>
-#include <fcntl.h>
-#include <errno.h>
-#include <string.h>
-#include <signal.h>
-#include "test.h"
-#include "safe_macros.h"
-
-void setup();
-void cleanup();
+/*\
+ * [Description]
+ *
+ * Check the basic functionality of the symlink() system call.
+ */
-char *TCID = "symlink02";
-int TST_TOTAL = 1;
+#include "tst_test.h"
-char fname[255], symlnk[255];
-int fd;
+static char *fname, *symlnk;
-int main(int ac, char **av)
+static void verify_symlink(void)
{
- int lc;
-
- /***************************************************************
- * parse standard options
- ***************************************************************/
- tst_parse_opts(ac, av, NULL, NULL);
-
- /***************************************************************
- * perform global setup for test
- ***************************************************************/
- setup();
-
- /***************************************************************
- * check looping state if -c option given
- ***************************************************************/
- for (lc = 0; TEST_LOOPING(lc); lc++) {
-
- tst_count = 0;
-
- /*
- * Call symlink(2)
- */
- TEST(symlink(fname, symlnk));
-
- /* check return code */
- if (TEST_RETURN == -1) {
- tst_resm(TFAIL, "symlink(%s, %s) Failed, errno=%d : %s",
- fname, symlnk, TEST_ERRNO,
- strerror(TEST_ERRNO));
- } else {
- SAFE_UNLINK(cleanup, symlnk);
- }
- }
-
- /***************************************************************
- * cleanup and exit
- ***************************************************************/
- cleanup();
- tst_exit();
+ TST_EXP_POSITIVE(symlink(fname, symlnk), "symlink(%s, %s)",
+ fname, symlnk);
+ if (TST_RET == -1)
+ tst_res(TFAIL, "symlink(%s, %s) Failed", fname, symlnk);
+ else
+ SAFE_UNLINK(symlnk);
}
-/***************************************************************
- * setup() - performs all ONE TIME setup for this test.
- ***************************************************************/
-void setup(void)
+static void setup(void)
{
+ fname = tst_aprintf("tfile_%d", getpid());
- tst_sig(NOFORK, DEF_HANDLER, cleanup);
-
- TEST_PAUSE;
-
- tst_tmpdir();
-
- sprintf(fname, "tfile_%d", getpid());
- if ((fd = open(fname, O_RDWR | O_CREAT, 0700)) == -1) {
- tst_brkm(TBROK, cleanup,
- "open(%s, O_RDWR|O_CREAT,0700) Failed, errno=%d : %s",
- fname, errno, strerror(errno));
- }
-
- if (close(fd) == -1) {
- tst_resm(TWARN, "close(%s) Failed, errno=%d : %s",
- fname, errno, strerror(errno));
- }
- sprintf(symlnk, "st_%d", getpid());
+ symlnk = tst_aprintf("st_%d", getpid());
}
-/***************************************************************
- * cleanup() - performs all ONE TIME cleanup for this test at
- * completion or premature exit.
- ***************************************************************/
-void cleanup(void)
-{
-
- tst_rmdir();
-
-}
+static struct tst_test test = {
+ .needs_tmpdir = 1,
+ .setup = setup,
+ .test_all = verify_symlink,
+};
diff --git a/testcases/kernel/syscalls/symlink/symlink04.c b/testcases/kernel/syscalls/symlink/symlink04.c
index 2190b3b1b..c43a03a26 100644
--- a/testcases/kernel/syscalls/symlink/symlink04.c
+++ b/testcases/kernel/syscalls/symlink/symlink04.c
@@ -1,193 +1,64 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
/*
- *
- * Copyright (c) International Business Machines Corp., 2001
- *
- * 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
+ * Copyright (c) International Business Machines Corp., 2001
+ * Copyright (c) Linux Test Project, 2001-2023
+ * Author: John George
*/
-/*
- * Test Name : symlink04
- *
- * Test Description :
- * Verify that, symlink will succeed to creat a symbolic link of an existing
- * object name path.
- *
- * Expected Result:
- * symlink() should return value 0 on success and symbolic link of an
- * existing object should be created.
- *
- * Algorithm:
- * Setup:
- * Setup signal handling.
- * Create temporary directory.
- * Pause for SIGUSR1 if option specified.
- *
- * Test:
- * Loop if the proper options are given.
- * Execute system call
- * Check return code, if system call failed (return=-1)
- * Log the errno and Issue a FAIL message.
- * Otherwise,
- * Verify the Functionality of system call
- * if successful,
- * Issue Functionality-Pass message.
- * Otherwise,
- * Issue Functionality-Fail message.
- * Cleanup:
- * Print errno log and/or timing stats if options given
- * Delete the temporary directory created.
- *
- * Usage: <for command-line>
- * symlink04 [-c n] [-e] [-f] [-i n] [-I x] [-p x] [-t]
- * where, -c n : Run n copies concurrently.
- * -e : Turn on errno logging.
- * -f : Turn off functionality Testing.
- * -i n : Execute test n times.
- * -I x : Execute test for x seconds.
- * -P x : Pause for x seconds between iterations.
- * -t : Turn on syscall timing.
- *
- * History
- * 07/2001 John George
- * -Ported
- *
- * Restrictions:
- * None.
+/*\
+ * [Description]
*
+ * Check that a symbolic link may point to an existing file or
+ * to a nonexistent one.
*/
+#include <stdlib.h>
#include <stdio.h>
-#include <sys/types.h>
-#include <fcntl.h>
-#include <errno.h>
-#include <string.h>
-#include <signal.h>
-#include <sys/stat.h>
-#include "test.h"
-#include "safe_macros.h"
+#include "tst_test.h"
-#define TESTFILE "testfile"
-#define SYMFILE "slink_file"
-#define FILE_MODE S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH
+#define TESTFILE "testfile"
+#define NONFILE "noexistfile"
+#define SYMFILE "slink_file"
-char *TCID = "symlink04";
-int TST_TOTAL = 1;
+static char *testfile;
+static char *nonfile;
-void setup();
-void cleanup();
+static struct tcase {
+ char **srcfile;
+} tcases[] = {
+ {&testfile},
+ {&nonfile},
+};
-int main(int ac, char **av)
+static void setup(void)
{
- struct stat stat_buf; /* stat structure buffer */
- int lc;
-
- tst_parse_opts(ac, av, NULL, NULL);
-
- setup();
-
- for (lc = 0; TEST_LOOPING(lc); lc++) {
-
- tst_count = 0;
-
- /*
- * Call symlink(2) to create a symlink of
- * testfile.
- */
- TEST(symlink(TESTFILE, SYMFILE));
-
- if (TEST_RETURN == -1) {
- tst_resm(TFAIL, "symlink(%s, %s) Failed, errno=%d : %s",
- TESTFILE, SYMFILE, TEST_ERRNO,
- strerror(TEST_ERRNO));
- } else {
- /*
- * Get the symlink file status information
- * using lstat(2).
- */
- if (lstat(SYMFILE, &stat_buf) < 0) {
- tst_brkm(TFAIL, cleanup, "lstat(2) of "
- "%s failed, error:%d", SYMFILE,
- errno);
- }
-
- /* Check if the st_mode contains a link */
- if (!S_ISLNK(stat_buf.st_mode)) {
- tst_resm(TFAIL,
- "symlink of %s doesn't exist",
- TESTFILE);
- } else {
- tst_resm(TPASS, "symlink(%s, %s) "
- "functionality successful",
- TESTFILE, SYMFILE);
- }
- }
-
- /* Unlink the symlink file for next loop */
- SAFE_UNLINK(cleanup, SYMFILE);
- tst_count++; /* incr TEST_LOOP counter */
- }
-
- cleanup();
- tst_exit();
-
+ SAFE_TOUCH(TESTFILE, 0644, NULL);
}
-/*
- * void
- * setup() - performs all ONE TIME setup for this test.
- * Create a temporary directory and change directory to it.
- * Create a test file under temporary directory and close it
- */
-void setup(void)
+static void verify_symlink(unsigned int i)
{
- int fd; /* file handle for testfile */
+ struct tcase *tc = &tcases[i];
- tst_sig(NOFORK, DEF_HANDLER, cleanup);
+ struct stat stat_buf;
- /* Pause if that option was specified
- * TEST_PAUSE contains the code to fork the test with the -i option.
- * You want to make sure you do this before you create your temporary
- * directory.
- */
- TEST_PAUSE;
+ TST_EXP_PASS(symlink(*tc->srcfile, SYMFILE));
- tst_tmpdir();
+ SAFE_LSTAT(SYMFILE, &stat_buf);
- /* creat/open a testfile */
- if ((fd = open(TESTFILE, O_RDWR | O_CREAT, FILE_MODE)) == -1) {
- tst_brkm(TBROK, cleanup,
- "open(%s, O_RDWR|O_CREAT, %#o) Failed, errno=%d : %s",
- TESTFILE, FILE_MODE, errno, strerror(errno));
- }
+ if (!S_ISLNK(stat_buf.st_mode))
+ tst_res(TFAIL, "symlink of %s doesn't exist", *tc->srcfile);
- /* Close the temporary file created above */
- if (close(fd) == -1) {
- tst_resm(TBROK, "close(%s) Failed, errno=%d : %s",
- TESTFILE, errno, strerror(errno));
- }
+ SAFE_UNLINK(SYMFILE);
}
-/*
- * void
- * cleanup() - performs all ONE TIME cleanup for this test at
- * completion or premature exit.
- * Remove the test directory and testfile created in the setup.
- */
-void cleanup(void)
-{
-
- tst_rmdir();
-
-}
+static struct tst_test test = {
+ .tcnt = ARRAY_SIZE(tcases),
+ .setup = setup,
+ .test = verify_symlink,
+ .bufs = (struct tst_buffers []) {
+ {&testfile, .str = TESTFILE},
+ {&nonfile, .str = NONFILE},
+ {},
+ },
+ .needs_tmpdir = 1,
+};
diff --git a/testcases/kernel/syscalls/symlink/symlink05.c b/testcases/kernel/syscalls/symlink/symlink05.c
deleted file mode 100644
index 83b151f5d..000000000
--- a/testcases/kernel/syscalls/symlink/symlink05.c
+++ /dev/null
@@ -1,180 +0,0 @@
-/*
- *
- * Copyright (c) International Business Machines Corp., 2001
- *
- * 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
- */
-
-/*
- * Test Name : symlink05
- *
- * Test Description :
- * Verify that, symlink will succeed to creat a symbolic link of an
- * non-existing object name path.
- *
- * Expected Result:
- * symlink() should return value 0 on success and symlink of an
- * non-existing object should be created.
- *
- * Algorithm:
- * Setup:
- * Setup signal handling.
- * Create temporary directory.
- * Pause for SIGUSR1 if option specified.
- *
- * Test:
- * Loop if the proper options are given.
- * Execute system call
- * Check return code, if system call failed (return=-1)
- * Log the errno and Issue a FAIL message.
- * Otherwise,
- * Verify the Functionality of system call
- * if successful,
- * Issue Functionality-Pass message.
- * Otherwise,
- * Issue Functionality-Fail message.
- * Cleanup:
- * Print errno log and/or timing stats if options given
- * Delete the temporary directory created.
- *
- * Usage: <for command-line>
- * symlink05 [-c n] [-e] [-f] [-i n] [-I x] [-p x] [-t]
- * where, -c n : Run n copies concurrently.
- * -e : Turn on errno logging.
- * -f : Turn off functionality Testing.
- * -i n : Execute test n times.
- * -I x : Execute test for x seconds.
- * -P x : Pause for x seconds between iterations.
- * -t : Turn on syscall timing.
- *
- * History
- * 07/2001 John George
- * -Ported
- *
- * Restrictions:
- * This test should be run by 'non-super-user' only.
- *
- */
-
-#include <stdio.h>
-#include <sys/types.h>
-#include <fcntl.h>
-#include <errno.h>
-#include <string.h>
-#include <signal.h>
-#include <sys/stat.h>
-
-#include "test.h"
-#include "safe_macros.h"
-
-#define TESTFILE "testfile"
-#define SYMFILE "slink_file"
-
-char *TCID = "symlink05";
-int TST_TOTAL = 1;
-
-void setup();
-void cleanup();
-
-int main(int ac, char **av)
-{
- struct stat stat_buf; /* stat structure buffer */
- int lc;
-
- tst_parse_opts(ac, av, NULL, NULL);
-
- setup();
-
- for (lc = 0; TEST_LOOPING(lc); lc++) {
-
- tst_count = 0;
-
- /*
- * Call symlink(2) to create a symlink of
- * an non-existing testfile.
- */
- TEST(symlink(TESTFILE, SYMFILE));
-
- if (TEST_RETURN == -1) {
- tst_resm(TFAIL,
- "symlink(%s, %s) Failed, errno=%d : %s",
- TESTFILE, SYMFILE, TEST_ERRNO,
- strerror(TEST_ERRNO));
- } else {
- /*
- * Get the symlink file status information
- * using lstat(2).
- */
- if (lstat(SYMFILE, &stat_buf) < 0) {
- tst_brkm(TFAIL, cleanup, "lstat(2) of "
- "%s failed, error:%d",
- SYMFILE, errno);
- }
-
- /* Check if the st_mode contains a link */
- if (!S_ISLNK(stat_buf.st_mode)) {
- tst_resm(TFAIL,
- "symlink of %s doesn't exist",
- TESTFILE);
- } else {
- tst_resm(TPASS, "symlink(%s, %s) "
- "functionality successful",
- TESTFILE, SYMFILE);
- }
- }
-
- /* Unlink the symlink file for next loop */
- SAFE_UNLINK(cleanup, SYMFILE);
- tst_count++; /* incr TEST_LOOP counter */
- }
-
- cleanup();
- tst_exit();
-
-}
-
-/*
- * void
- * setup() - performs all ONE TIME setup for this test.
- * Create a temporary directory and change directory to it.
- */
-void setup(void)
-{
-
- tst_sig(NOFORK, DEF_HANDLER, cleanup);
-
- /* Pause if that option was specified
- * TEST_PAUSE contains the code to fork the test with the -i option.
- * You want to make sure you do this before you create your temporary
- * directory.
- */
- TEST_PAUSE;
-
- tst_tmpdir();
-
-}
-
-/*
- * void
- * cleanup() - performs all ONE TIME cleanup for this test at
- * completion or premature exit.
- * Remove the temporary directory created in the setup.
- */
-void cleanup(void)
-{
-
- tst_rmdir();
-
-}
diff --git a/testcases/kernel/syscalls/timerfd/.gitignore b/testcases/kernel/syscalls/timerfd/.gitignore
index ef388685d..ca6cbb1f4 100644
--- a/testcases/kernel/syscalls/timerfd/.gitignore
+++ b/testcases/kernel/syscalls/timerfd/.gitignore
@@ -1,6 +1,5 @@
/timerfd01
/timerfd02
-/timerfd03
/timerfd04
/timerfd_create01
/timerfd_gettime01
diff --git a/testcases/kernel/syscalls/timerfd/timerfd02.c b/testcases/kernel/syscalls/timerfd/timerfd02.c
index 936cdbc53..3dabfb5c0 100644
--- a/testcases/kernel/syscalls/timerfd/timerfd02.c
+++ b/testcases/kernel/syscalls/timerfd/timerfd02.c
@@ -1,174 +1,51 @@
-/******************************************************************************/
-/* */
-/* Copyright (c) Ulrich Drepper <drepper@redhat.com> */
-/* Copyright (c) International Business Machines Corp., 2009 */
-/* */
-/* 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 */
-/* */
-/******************************************************************************/
-/******************************************************************************/
-/* */
-/* File: timerfd02.c */
-/* */
-/* Description: This Program tests the new system call introduced in 2.6.27. */
-/* Ulrich´s comment as in: */
-/* http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=11fcb6c14676023d0bd437841f5dcd670e7990a0 */
-/* says: */
-/* The timerfd_create syscall already has a flags parameter. It just is */
-/* unused so far. This patch changes this by introducing the TFD_CLOEXEC */
-/* flag to set the close-on-exec flag for the returned file descriptor. A new */
-/* name TFD_CLOEXEC is introduced which in this implementation must have the */
-/* same value as O_CLOEXEC. */
-/* The following test must be adjusted for architectures other than x86 and */
-/* x86-64 and in case the syscall numbers changed. */
-/* */
-/* Usage: <for command-line> */
-/* timerfd02 [-c n] [-e][-i n] [-I x] [-p x] [-t] */
-/* where, -c n : Run n copies concurrently. */
-/* -e : Turn on errno logging. */
-/* -i n : Execute test n times. */
-/* -I x : Execute test for x seconds. */
-/* -P x : Pause for x seconds between iterations. */
-/* -t : Turn on syscall timing. */
-/* */
-/* Total Tests: 1 */
-/* */
-/* Test Name: timerfd02 */
-/* */
-/* Author: Ulrich Drepper <drepper@redhat.com> */
-/* */
-/* History: Created - Jan 08 2009 - Ulrich Drepper <drepper@redhat.com> */
-/* Ported to LTP */
-/* - Jan 08 2009 - Subrata <subrata@linux.vnet.ibm.com> */
-/******************************************************************************/
-
-#include <stdio.h>
-#include <time.h>
-#include <unistd.h>
-#include <sys/syscall.h>
-#include <errno.h>
-
-#include "test.h"
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (c) Ulrich Drepper <drepper@redhat.com>
+ * Copyright (c) International Business Machines Corp., 2009
+ * Copyright (C) 2023 SUSE LLC Andrea Cervesato <andrea.cervesato@suse.com>
+ */
+/*\
+ * [Description]
+ *
+ * This test verifies that:
+ * - TFD_CLOEXEC sets the close-on-exec file status flag on the new open file
+ * - TFD_NONBLOCK sets the O_NONBLOCK file status flag on the new open file
+ */
+
+#include "tst_test.h"
+#include "tst_safe_timerfd.h"
#include "lapi/fcntl.h"
#include "lapi/syscalls.h"
-#define TFD_CLOEXEC O_CLOEXEC
+static int fdesc;
-char *TCID = "timerfd02";
-int testno;
-int TST_TOTAL = 1;
+static struct test_case_t {
+ int flags;
+ int check;
+ int expected;
+} tcases[] = {
+ { 0, F_GETFD, 0 },
+ { TFD_CLOEXEC, F_GETFD, FD_CLOEXEC },
+ { TFD_NONBLOCK, F_GETFL, O_NONBLOCK }
+};
-/* Extern Global Functions */
-/******************************************************************************/
-/* */
-/* Function: cleanup */
-/* */
-/* Description: Performs all one time clean up for this test on successful */
-/* completion, premature exit or failure. Closes all temporary */
-/* files, removes all temporary directories exits the test with */
-/* appropriate return code by calling tst_exit() function. */
-/* */
-/* Input: None. */
-/* */
-/* Output: None. */
-/* */
-/* Return: On failure - Exits calling tst_exit(). Non '0' return code. */
-/* On success - Exits calling tst_exit(). With '0' return code. */
-/* */
-/******************************************************************************/
-void cleanup(void)
+static void run(unsigned int i)
{
+ struct test_case_t *tcase = &tcases[i];
- tst_rmdir();
-
+ TST_EXP_FD(fdesc = SAFE_TIMERFD_CREATE(CLOCK_REALTIME, tcase->flags));
+ TST_EXP_EQ_LI(SAFE_FCNTL(fdesc, tcase->check) & tcase->expected, tcase->expected);
+ SAFE_CLOSE(fdesc);
}
-/* Local Functions */
-/******************************************************************************/
-/* */
-/* Function: setup */
-/* */
-/* Description: Performs all one time setup for this test. This function is */
-/* typically used to capture signals, create temporary dirs */
-/* and temporary files that may be used in the course of this */
-/* test. */
-/* */
-/* Input: None. */
-/* */
-/* Output: None. */
-/* */
-/* Return: On failure - Exits by calling cleanup(). */
-/* On success - returns 0. */
-/* */
-/******************************************************************************/
-void setup(void)
+static void cleanup(void)
{
- /* Capture signals if any */
- /* Create temporary directories */
- TEST_PAUSE;
- tst_tmpdir();
+ if (fcntl(fdesc, F_GETFD) != -1)
+ SAFE_CLOSE(fdesc);
}
-int main(int argc, char *argv[])
-{
- int fd, coe;
- int lc;
-
- tst_parse_opts(argc, argv, NULL, NULL);
- setup();
-
- for (lc = 0; TEST_LOOPING(lc); ++lc) {
- tst_count = 0;
- for (testno = 0; testno < TST_TOTAL; ++testno) {
- fd = tst_syscall(__NR_timerfd_create,
- CLOCK_REALTIME, 0);
- if (fd == -1) {
- tst_brkm(TFAIL, cleanup,
- "timerfd_create(0) failed");
- }
- coe = fcntl(fd, F_GETFD);
- if (coe == -1) {
- tst_brkm(TBROK, cleanup, "fcntl failed");
- }
- if (coe & FD_CLOEXEC) {
- tst_brkm(TFAIL,
- cleanup,
- "timerfd_create(0) set close-on-exec flag");
- }
- close(fd);
-
- fd = tst_syscall(__NR_timerfd_create, CLOCK_REALTIME,
- TFD_CLOEXEC);
- if (fd == -1) {
- tst_brkm(TFAIL,
- cleanup,
- "timerfd_create(TFD_CLOEXEC) failed");
- }
- coe = fcntl(fd, F_GETFD);
- if (coe == -1) {
- tst_brkm(TBROK, cleanup, "fcntl failed");
- }
- if ((coe & FD_CLOEXEC) == 0) {
- tst_brkm(TFAIL,
- cleanup,
- "timerfd_create(TFD_CLOEXEC) set close-on-exec flag");
- }
- close(fd);
- tst_resm(TPASS, "timerfd_create(TFD_CLOEXEC) Passed");
- cleanup();
- }
- }
- tst_exit();
-}
+static struct tst_test test = {
+ .test = run,
+ .tcnt = ARRAY_SIZE(tcases),
+ .cleanup = cleanup,
+};
diff --git a/testcases/kernel/syscalls/timerfd/timerfd03.c b/testcases/kernel/syscalls/timerfd/timerfd03.c
deleted file mode 100644
index 89dec325f..000000000
--- a/testcases/kernel/syscalls/timerfd/timerfd03.c
+++ /dev/null
@@ -1,170 +0,0 @@
-/******************************************************************************/
-/* */
-/* Copyright (c) Ulrich Drepper <drepper@redhat.com> */
-/* Copyright (c) International Business Machines Corp., 2009 */
-/* */
-/* 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 */
-/* */
-/******************************************************************************/
-/******************************************************************************/
-/* */
-/* File: timerfd03.c */
-/* */
-/* Description: This Program tests the new system call introduced in 2.6.27. */
-/* Ulrich´s comment as in: */
-/* http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=6b1ef0e60d42f2fdaec26baee8327eb156347b4f */
-/* which says: */
-/* This patch adds support for the TFD_NONBLOCK flag to timerfd_create. The */
-/* additional changes needed are minimal. The following test must be adjusted */
-/* for architectures other than x86 and x86-64 and in case the syscall numbers*/
-/* changed. */
-/* */
-/* Usage: <for command-line> */
-/* timerfd03 [-c n] [-e][-i n] [-I x] [-p x] [-t] */
-/* where, -c n : Run n copies concurrently. */
-/* -e : Turn on errno logging. */
-/* -i n : Execute test n times. */
-/* -I x : Execute test for x seconds. */
-/* -P x : Pause for x seconds between iterations. */
-/* -t : Turn on syscall timing. */
-/* */
-/* Total Tests: 1 */
-/* */
-/* Test Name: timerfd03 */
-/* */
-/* Author: Ulrich Drepper <drepper@redhat.com> */
-/* */
-/* History: Created - Jan 13 2009 - Ulrich Drepper <drepper@redhat.com> */
-/* Ported to LTP */
-/* - Jan 13 2009 - Subrata <subrata@linux.vnet.ibm.com> */
-/******************************************************************************/
-#include <stdio.h>
-#include <time.h>
-#include <unistd.h>
-#include <sys/syscall.h>
-#include <errno.h>
-
-#include "test.h"
-#include "lapi/fcntl.h"
-#include "lapi/syscalls.h"
-
-#define TFD_NONBLOCK O_NONBLOCK
-
-char *TCID = "timerfd03";
-int testno;
-int TST_TOTAL = 1;
-
-/* Extern Global Functions */
-/******************************************************************************/
-/* */
-/* Function: cleanup */
-/* */
-/* Description: Performs all one time clean up for this test on successful */
-/* completion, premature exit or failure. Closes all temporary */
-/* files, removes all temporary directories exits the test with */
-/* appropriate return code by calling tst_exit() function. */
-/* */
-/* Input: None. */
-/* */
-/* Output: None. */
-/* */
-/* Return: On failure - Exits calling tst_exit(). Non '0' return code. */
-/* On success - Exits calling tst_exit(). With '0' return code. */
-/* */
-/******************************************************************************/
-void cleanup(void)
-{
-
- tst_rmdir();
-
-}
-
-/* Local Functions */
-/******************************************************************************/
-/* */
-/* Function: setup */
-/* */
-/* Description: Performs all one time setup for this test. This function is */
-/* typically used to capture signals, create temporary dirs */
-/* and temporary files that may be used in the course of this */
-/* test. */
-/* */
-/* Input: None. */
-/* */
-/* Output: None. */
-/* */
-/* Return: On failure - Exits by calling cleanup(). */
-/* On success - returns 0. */
-/* */
-/******************************************************************************/
-void setup(void)
-{
- /* Capture signals if any */
- /* Create temporary directories */
- TEST_PAUSE;
- tst_tmpdir();
-}
-
-int main(int argc, char *argv[])
-{
- int fd, fl;
- int lc;
-
- tst_parse_opts(argc, argv, NULL, NULL);
- setup();
-
- for (lc = 0; TEST_LOOPING(lc); ++lc) {
- tst_count = 0;
- for (testno = 0; testno < TST_TOTAL; ++testno) {
- fd = tst_syscall(__NR_timerfd_create,
- CLOCK_REALTIME, 0);
- if (fd == -1) {
- tst_brkm(TFAIL, cleanup,
- "timerfd_create(0) failed");
- }
- fl = fcntl(fd, F_GETFL);
- if (fl == -1) {
- tst_brkm(TBROK, cleanup, "fcntl failed");
- }
- if (fl & O_NONBLOCK) {
- tst_brkm(TFAIL,
- cleanup,
- "timerfd_create(0) set non-blocking mode");
- }
- close(fd);
-
- fd = tst_syscall(__NR_timerfd_create, CLOCK_REALTIME,
- TFD_NONBLOCK);
- if (fd == -1) {
- tst_brkm(TFAIL,
- cleanup,
- "timerfd_create(TFD_NONBLOCK) failed");
- }
- fl = fcntl(fd, F_GETFL);
- if (fl == -1) {
- tst_brkm(TBROK, cleanup, "fcntl failed");
- }
- if ((fl & O_NONBLOCK) == 0) {
- tst_brkm(TFAIL,
- cleanup,
- "timerfd_create(TFD_NONBLOCK) set non-blocking mode");
- }
- close(fd);
- tst_resm(TPASS, "timerfd_create(TFD_NONBLOCK) PASSED");
- cleanup();
- }
- }
- tst_exit();
-}
diff --git a/testcases/kernel/syscalls/umount/umount01.c b/testcases/kernel/syscalls/umount/umount01.c
index d05296dce..264c8f7d7 100644
--- a/testcases/kernel/syscalls/umount/umount01.c
+++ b/testcases/kernel/syscalls/umount/umount01.c
@@ -2,12 +2,15 @@
/*
* Copyright (c) Wipro Technologies Ltd, 2002. All Rights Reserved.
* Author: Nirmala Devi Dhanasekar <nirmala.devi@wipro.com>
+ * Copyright (c) Linux Test Project, 2002-2023
+ */
+
+/*\
+ * [Description]
*
- * Phase I test for the umount(2) system call.
- * It is intended to provide a limited exposure of the system call.
+ * Check the basic functionality of the umount(2) system call.
*/
-#include <errno.h>
#include <sys/mount.h>
#include "tst_test.h"
@@ -23,7 +26,7 @@ static void verify_umount(void)
mount_flag = 1;
}
- TEST(umount(MNTPOINT));
+ TST_EXP_PASS(umount(MNTPOINT));
if (TST_RET != 0 && TST_ERR == EBUSY) {
tst_res(TINFO, "umount() Failed with EBUSY "
@@ -31,12 +34,6 @@ static void verify_umount(void)
"is probing newly mounted dirs");
}
- if (TST_RET != 0) {
- tst_res(TFAIL | TTERRNO, "umount() Failed");
- return;
- }
-
- tst_res(TPASS, "umount() Passed");
mount_flag = 0;
}
diff --git a/testcases/kernel/syscalls/umount/umount02.c b/testcases/kernel/syscalls/umount/umount02.c
index 34a38c998..acc35e8a4 100644
--- a/testcases/kernel/syscalls/umount/umount02.c
+++ b/testcases/kernel/syscalls/umount/umount02.c
@@ -2,20 +2,24 @@
/*
* Copyright (c) Wipro Technologies Ltd, 2002. All Rights Reserved.
* Copyright (c) 2014 Cyril Hrubis <chrubis@suse.cz>
+ * Copyright (c) Linux Test Project, 2002-2023
* Author: Nirmala Devi Dhanasekar <nirmala.devi@wipro.com>
+ */
+
+/*\
+ * [Description]
*
* Check for basic errors returned by umount(2) system call.
*
* Verify that umount(2) returns -1 and sets errno to
- * 1) EBUSY if it cannot be umounted, because dir is still busy.
- * 2) EFAULT if specialfile or device file points to invalid address space.
- * 3) ENOENT if pathname was empty or has a nonexistent component.
- * 4) EINVAL if specialfile or device is invalid or not a mount point.
- * 5) ENAMETOOLONG if pathname was longer than MAXPATHLEN.
+ *
+ * 1. EBUSY if it cannot be umounted, because dir is still busy.
+ * 2. EFAULT if specialfile or device file points to invalid address space.
+ * 3. ENOENT if pathname was empty or has a nonexistent component.
+ * 4. EINVAL if specialfile or device is invalid or not a mount point.
+ * 5. ENAMETOOLONG if pathname was longer than MAXPATHLEN.
*/
-#include <errno.h>
-#include <string.h>
#include <sys/mount.h>
#include "tst_test.h"
@@ -41,21 +45,7 @@ static void verify_umount(unsigned int n)
{
struct tcase *tc = &tcases[n];
- TEST(umount(tc->mntpoint));
-
- if (TST_RET != -1) {
- tst_res(TFAIL, "umount() succeeds unexpectedly");
- return;
- }
-
- if (tc->exp_errno != TST_ERR) {
- tst_res(TFAIL | TTERRNO, "umount() should fail with %s",
- tst_strerrno(tc->exp_errno));
- return;
- }
-
- tst_res(TPASS | TTERRNO, "umount() fails as expected: %s",
- tc->err_desc);
+ TST_EXP_FAIL(umount(tc->mntpoint), tc->exp_errno);
}
static void setup(void)
diff --git a/testcases/kernel/syscalls/umount/umount03.c b/testcases/kernel/syscalls/umount/umount03.c
index 1cef06fa1..3260312f7 100644
--- a/testcases/kernel/syscalls/umount/umount03.c
+++ b/testcases/kernel/syscalls/umount/umount03.c
@@ -1,17 +1,19 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Copyright (c) Wipro Technologies Ltd, 2002. All Rights Reserved.
+ * Copyright (c) Linux Test Project, 2002-2023
* Author: Nirmala Devi Dhanasekar <nirmala.devi@wipro.com>
+ */
+
+/*\
+ * [Description]
*
- * Verify that umount(2) returns -1 and sets errno to EPERM if the user
+ * Verify that umount(2) returns -1 and sets errno to EPERM if the user
* is not the super-user.
*/
-#include <errno.h>
#include <pwd.h>
#include <sys/mount.h>
-#include <sys/types.h>
-#include <unistd.h>
#include "tst_test.h"
#define MNTPOINT "mntpoint"
@@ -20,19 +22,7 @@ static int mount_flag;
static void verify_umount(void)
{
- TEST(umount(MNTPOINT));
-
- if (TST_RET != -1) {
- tst_res(TFAIL, "umount() succeeds unexpectedly");
- return;
- }
-
- if (TST_ERR != EPERM) {
- tst_res(TFAIL | TTERRNO, "umount() should fail with EPERM");
- return;
- }
-
- tst_res(TPASS | TTERRNO, "umount() fails as expected");
+ TST_EXP_FAIL(umount(MNTPOINT), EPERM);
}
static void setup(void)
diff --git a/testcases/kernel/syscalls/utils/compat_16.mk b/testcases/kernel/syscalls/utils/compat_16.mk
index e81a00c40..71a8cc56f 100644
--- a/testcases/kernel/syscalls/utils/compat_16.mk
+++ b/testcases/kernel/syscalls/utils/compat_16.mk
@@ -60,7 +60,7 @@ MAKE_TARGETS += $(addsuffix _16,$(MAKE_TARGETS))
# (no .h file, no TST_USE_NEWER64_SYSCALL def).
DEF_16 := TST_USE_COMPAT16_SYSCALL
-ifneq ($(COMPAT_TST_16_H),1)
+ifeq ($(USE_LEGACY_COMPAT_16_H),1)
COMPAT_16_H := $(abs_srcdir)/../utils/compat_16.h
else
COMPAT_16_H := $(abs_srcdir)/../utils/compat_tst_16.h
diff --git a/testcases/kernel/syscalls/wait4/wait402.c b/testcases/kernel/syscalls/wait4/wait402.c
index 39b170253..36fba7378 100644
--- a/testcases/kernel/syscalls/wait4/wait402.c
+++ b/testcases/kernel/syscalls/wait4/wait402.c
@@ -1,101 +1,36 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
/*
- *
- * Copyright (c) International Business Machines Corp., 2001
- * Copyright (c) 2012 Cyril Hrubis <chrubis@suse.cz>
- *
- * 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
+ * Copyright (c) International Business Machines Corp., 2001
+ * Copyright (c) 2012 Cyril Hrubis <chrubis@suse.cz>
+ * Copyright (c) Linux Test Project, 2001-2015
+ * Copyright (c) 2023 Ioannis Bonatakis <ybonatakis@suse.com>
*/
- /*
- * wait402 - check for ECHILD errno when using an illegal pid value
- */
-
-#include "test.h"
+/*\
+ * [Description]
+ *
+ * Check for ECHILD errno when call wait4(2) with an invalid pid value.
+ */
-#include <errno.h>
-#define _USE_BSD
-#include <sys/types.h>
-#include <sys/resource.h>
+#include "tst_test.h"
#include <sys/wait.h>
-#include <stdlib.h>
-#include <string.h>
-
-char *TCID = "wait402";
-int TST_TOTAL = 1;
-
-static void cleanup(void);
-static void setup(void);
-
-static long get_pid_max(void)
-{
- long pid_max;
-
- SAFE_FILE_SCANF(NULL, "/proc/sys/kernel/pid_max", "%ld", &pid_max);
- return pid_max;
-}
+static pid_t pid_max;
-int main(int ac, char **av)
+static void run(void)
{
- int lc;
- pid_t epid = get_pid_max() + 1;
-
- int status = 1;
+ int status;
struct rusage rusage;
- tst_parse_opts(ac, av, NULL, NULL);
-
- setup();
-
- for (lc = 0; TEST_LOOPING(lc); lc++) {
- tst_count = 0;
-
- TEST(wait4(epid, &status, 0, &rusage));
-
- if (TEST_RETURN == 0) {
- tst_brkm(TFAIL, cleanup,
- "call failed to produce expected error - errno = %d - %s",
- TEST_ERRNO, strerror(TEST_ERRNO));
- }
-
- switch (TEST_ERRNO) {
- case ECHILD:
- tst_resm(TPASS,
- "received expected failure - errno = %d - %s",
- TEST_ERRNO, strerror(TEST_ERRNO));
- break;
- default:
- tst_brkm(TFAIL, cleanup,
- "call failed to produce expected "
- "error - errno = %d - %s", TEST_ERRNO,
- strerror(TEST_ERRNO));
- }
- }
-
- cleanup();
- tst_exit();
+ TST_EXP_FAIL2(wait4(pid_max + 1, &status, 0, &rusage), ECHILD);
}
static void setup(void)
{
-
- tst_sig(FORK, DEF_HANDLER, cleanup);
-
- TEST_PAUSE;
+ SAFE_FILE_SCANF("/proc/sys/kernel/pid_max", "%d\n", &pid_max);
}
-static void cleanup(void)
-{
-}
+static struct tst_test test = {
+ .test_all = run,
+ .setup = setup,
+};
diff --git a/testcases/kernel/syscalls/writev/writev07.c b/testcases/kernel/syscalls/writev/writev07.c
index b725f08db..3dda1caa4 100644
--- a/testcases/kernel/syscalls/writev/writev07.c
+++ b/testcases/kernel/syscalls/writev/writev07.c
@@ -4,20 +4,26 @@
* Copyright (c) Linux Test Project, 2016
*/
-/*
- * Test Description:
- * Verify writev() behaviour with partially valid iovec list.
- * Kernel <4.8 used to shorten write up to first bad invalid
- * iovec. Starting with 4.8, a writev with short data (under
- * page size) is likely to get shorten to 0 bytes and return
- * EFAULT.
+/*\
+ * [Description]
+ *
+ * Verify writev() behaviour with partially valid iovec list.
+ * Kernel <4.8 used to shorten write up to first bad invalid
+ * iovec. Starting with 4.8, a writev with short data (under
+ * page size) is likely to get shorten to 0 bytes and return
+ * EFAULT.
+ *
+ * This test doesn't make assumptions how much will write get
+ * shortened. It only tests that file content/offset after
+ * syscall corresponds to return value of writev().
*
- * This test doesn't make assumptions how much will write get
- * shortened. It only tests that file content/offset after
- * syscall corresponds to return value of writev().
+ * See: [RFC] writev() semantics with invalid iovec in the middle
+ * https://marc.info/?l=linux-kernel&m=147388891614289&w=2.
*
- * See: [RFC] writev() semantics with invalid iovec in the middle
- * https://marc.info/?l=linux-kernel&m=147388891614289&w=2
+ * This is also regression test for kernel commits:
+ *
+ * * 20c64ec83a9f ("iomap: fix a regression for partial write errors")
+ * * 3ac974796e5d ("iomap: fix short copy in iomap_write_iter()")
*/
#include <errno.h>
@@ -138,4 +144,9 @@ static struct tst_test test = {
.needs_tmpdir = 1,
.setup = setup,
.test_all = test_writev,
+ .tags = (const struct tst_tag[]) {
+ {"linux-git", "20c64ec83a9f"},
+ {"linux-git", "3ac974796e5d"},
+ {},
+ }
};
diff --git a/testcases/kernel/uevents/uevent01.c b/testcases/kernel/uevents/uevent01.c
index 5c65556c9..a1f994150 100644
--- a/testcases/kernel/uevents/uevent01.c
+++ b/testcases/kernel/uevents/uevent01.c
@@ -1,9 +1,11 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Copyright (C) 2019 Cyril Hrubis <chrubis@suse.cz>
+ * Copyright (c) Linux Test Project, 2019-2023
*/
-/*
+/*\
+ * [Description]
* Very simple uevent netlink socket test.
*
* We fork a child that listens for a kernel events while parents attaches and
diff --git a/testcases/kernel/uevents/uevent02.c b/testcases/kernel/uevents/uevent02.c
index 4355cd8db..daa1b4f12 100644
--- a/testcases/kernel/uevents/uevent02.c
+++ b/testcases/kernel/uevents/uevent02.c
@@ -1,9 +1,12 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Copyright (C) 2019 Cyril Hrubis <chrubis@suse.cz>
+ * Copyright (c) Linux Test Project, 2019-2023
*/
-/*
+/*\
+ * [Description]
+ *
* Very simple uevent netlink socket test.
*
* We fork a child that listens for a kernel events while parents creates and
@@ -24,7 +27,6 @@
#include "uevent.h"
#define TUN_PATH "/dev/net/tun"
-#define CONFIG_RPS "CONFIG_RPS"
#define MAX_UEVENTS 7
static struct uevent_desc add = {
@@ -127,10 +129,7 @@ static void verify_uevent(void)
static void setup(void)
{
- struct tst_kconfig_var kconfig = {
- .id = CONFIG_RPS,
- .id_len = sizeof(CONFIG_RPS) - 1,
- };
+ struct tst_kconfig_var kconfig = TST_KCONFIG_INIT("CONFIG_RPS");
int i = 0;
tst_kconfig_read(&kconfig, 1);
diff --git a/testcases/kernel/uevents/uevent03.c b/testcases/kernel/uevents/uevent03.c
index ed15fea93..5b3dd701f 100644
--- a/testcases/kernel/uevents/uevent03.c
+++ b/testcases/kernel/uevents/uevent03.c
@@ -1,9 +1,11 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Copyright (C) 2019 Cyril Hrubis <chrubis@suse.cz>
+ * Copyright (c) Linux Test Project, 2019-2023
*/
-/*
+/*\
+ * [Description]
* Very simple uevent netlink socket test.
*
* We fork a child that listens for a kernel events while parents creates and
diff --git a/testcases/lib/test.sh b/testcases/lib/test.sh
index 8947f47c1..d26cf5df0 100644
--- a/testcases/lib/test.sh
+++ b/testcases/lib/test.sh
@@ -108,7 +108,7 @@ tst_require_root()
tst_exit()
{
- if [ -n "${TST_CLEANUP:-}" -a -z "${TST_NO_CLEANUP:-}" ]; then
+ if [ -n "${TST_CLEANUP:-}" -a -z "${LTP_NO_CLEANUP:-}" ]; then
$TST_CLEANUP
fi
diff --git a/testcases/lib/tst_net.sh b/testcases/lib/tst_net.sh
index 6168db86b..6cf7f2fcb 100644
--- a/testcases/lib/tst_net.sh
+++ b/testcases/lib/tst_net.sh
@@ -1,7 +1,7 @@
#!/bin/sh
# SPDX-License-Identifier: GPL-2.0-or-later
# Copyright (c) 2014-2017 Oracle and/or its affiliates. All Rights Reserved.
-# Copyright (c) 2016-2023 Petr Vorel <pvorel@suse.cz>
+# Copyright (c) 2016-2024 Petr Vorel <pvorel@suse.cz>
# Author: Alexey Kodanev <alexey.kodanev@oracle.com>
[ -n "$TST_LIB_NET_LOADED" ] && return 0
@@ -745,12 +745,12 @@ tst_netload()
fi
OPTIND=0
- while getopts :a:H:d:n:N:r:R:S:b:t:T:fFe:m:A:D: opt; do
+ while getopts :a:c:H:n:N:r:R:S:b:t:T:fFe:m:A:D: opt; do
case "$opt" in
a) c_num="$OPTARG" ;;
H) c_opts="${c_opts}-H $OPTARG "
hostopt="$OPTARG" ;;
- d) rfile="$OPTARG" ;;
+ c) rfile="$OPTARG" ;;
n) c_opts="${c_opts}-n $OPTARG " ;;
N) c_opts="${c_opts}-N $OPTARG " ;;
r) c_requests="$OPTARG" ;;
@@ -766,7 +766,7 @@ tst_netload()
f) cs_opts="${cs_opts}-f " ;;
F) cs_opts="${cs_opts}-F " ;;
e) expect_res="$OPTARG" ;;
- D) [ "$TST_NETLOAD_BINDTODEVICE" = 1 ] && cs_opts="${cs_opts}-D $OPTARG "
+ D) [ "$TST_NETLOAD_BINDTODEVICE" = 1 ] && cs_opts="${cs_opts}-d $OPTARG "
bind_to_device=0 ;;
*) tst_brk_ TBROK "tst_netload: unknown option: $OPTARG" ;;
esac
@@ -776,8 +776,8 @@ tst_netload()
[ "$setup_srchost" = 1 ] && s_opts="${s_opts}-S $hostopt "
if [ "$bind_to_device" = 1 -a "$TST_NETLOAD_BINDTODEVICE" = 1 ]; then
- c_opts="${c_opts}-D $(tst_iface) "
- s_opts="${s_opts}-D $(tst_iface rhost) "
+ c_opts="${c_opts}-d $(tst_iface) "
+ s_opts="${s_opts}-d $(tst_iface rhost) "
fi
local expect_ret=0
@@ -790,7 +790,7 @@ tst_netload()
fi
s_opts="${cs_opts}${s_opts}-R $s_replies -B $TST_TMPDIR"
- c_opts="${cs_opts}${c_opts}-a $c_num -r $((c_requests / run_cnt)) -d $PWD/$rfile"
+ c_opts="${cs_opts}${c_opts}-a $c_num -r $((c_requests / run_cnt)) -c $PWD/$rfile"
tst_res_ TINFO "run server 'netstress $s_opts'"
tst_res_ TINFO "run client 'netstress -l $c_opts' $run_cnt times"
@@ -863,22 +863,33 @@ tst_netload()
# TIME: time that is compared to the base one
# THRESHOD_LOW: lower limit for TFAIL
# THRESHOD_HIGH: upper limit for TWARN
+#
+# Slow performance can be ignored with setting environment variable
+# LTP_NET_FEATURES_IGNORE_PERFORMANCE_FAILURE=1
tst_netload_compare()
{
local base_time=$1
local new_time=$2
local threshold_low=$3
local threshold_hi=$4
+ local ttype='TFAIL'
+ local msg res
if [ -z "$base_time" -o -z "$new_time" -o -z "$threshold_low" ]; then
tst_brk_ TBROK "tst_netload_compare: invalid argument(s)"
fi
- local res=$(((base_time - new_time) * 100 / base_time))
- local msg="performance result is ${res}%"
+ res=$(((base_time - new_time) * 100 / base_time))
+ msg="performance result is ${res}%"
if [ "$res" -lt "$threshold_low" ]; then
- tst_res_ TFAIL "$msg < threshold ${threshold_low}%"
+ if [ "$LTP_NET_FEATURES_IGNORE_PERFORMANCE_FAILURE" = 1 ]; then
+ ttype='TINFO';
+ tst_res_ TINFO "WARNING: slow performance is not treated as error due LTP_NET_FEATURES_IGNORE_PERFORMANCE_FAILURE=1"
+ else
+ tst_res_ TINFO "Following slow performance can be ignored with LTP_NET_FEATURES_IGNORE_PERFORMANCE_FAILURE=1"
+ fi
+ tst_res_ $ttype "$msg < threshold ${threshold_low}%"
return
fi
diff --git a/testcases/lib/tst_test.sh b/testcases/lib/tst_test.sh
index b3f451a21..72279cc37 100644
--- a/testcases/lib/tst_test.sh
+++ b/testcases/lib/tst_test.sh
@@ -30,8 +30,9 @@ trap "unset _tst_setup_timer_pid; tst_brk TBROK 'test terminated'" TERM
_tst_do_cleanup()
{
- if [ -n "$TST_DO_CLEANUP" -a -n "$TST_CLEANUP" -a -z "$TST_NO_CLEANUP" ]; then
+ if [ -n "$TST_DO_CLEANUP" -a -n "$TST_CLEANUP" -a -z "$LTP_NO_CLEANUP" ]; then
if command -v $TST_CLEANUP >/dev/null 2>/dev/null; then
+ TST_DO_CLEANUP=
$TST_CLEANUP
else
tst_res TWARN "TST_CLEANUP=$TST_CLEANUP declared, but function not defined (or cmd not found)"
@@ -130,12 +131,19 @@ tst_brk()
local res=$1
shift
- if [ "$TST_DO_EXIT" = 1 ]; then
+ # TBROK => TWARN on cleanup or exit
+ if [ "$res" = TBROK ] && [ "$TST_DO_EXIT" = 1 -o -z "$TST_DO_CLEANUP" -a -n "$TST_CLEANUP" ]; then
tst_res TWARN "$@"
+ TST_DO_CLEANUP=
return
fi
- tst_res "$res" "$@"
+ if [ "$res" != TBROK -a "$res" != TCONF ]; then
+ tst_res TBROK "tst_brk can be called only with TBROK or TCONF ($res)"
+ else
+ tst_res "$res" "$@"
+ fi
+
_tst_do_exit
}
@@ -902,6 +910,8 @@ if [ -z "$TST_NO_DEFAULT_RUN" ]; then
TST_ARGS="$@"
+ tst_res TINFO "Running: $(basename $0) $TST_ARGS"
+
OPTIND=1
while getopts ":hi:$TST_OPTS" _tst_name $TST_ARGS; do
diff --git a/testcases/network/README.md b/testcases/network/README.md
index a0a1d3d95..e1b1296d6 100644
--- a/testcases/network/README.md
+++ b/testcases/network/README.md
@@ -84,6 +84,10 @@ Where
Default values for all LTP network parameters are set in `testcases/lib/tst_net.sh`.
Network stress parameters are documented in `testcases/network/stress/README`.
+Tests which use `tst_netload_compare()` test also performance. They can fail on
+overloaded SUT. To ignore performance failure and test only the network functionality,
+set `LTP_NET_FEATURES_IGNORE_PERFORMANCE_FAILURE=1` environment variable.
+
## Debugging
Both single and two host configurations support debugging via
`TST_NET_RHOST_RUN_DEBUG=1` environment variable.
diff --git a/testcases/network/busy_poll/busy_poll01.sh b/testcases/network/busy_poll/busy_poll01.sh
index 65f4db3fe..620084fc2 100755
--- a/testcases/network/busy_poll/busy_poll01.sh
+++ b/testcases/network/busy_poll/busy_poll01.sh
@@ -39,7 +39,7 @@ test()
for x in 50 0; do
tst_res TINFO "set low latency busy poll to $x"
set_busy_poll $x
- tst_netload -H $(tst_ipaddr rhost) -n 10 -N 10 -d res_$x
+ tst_netload -H $(tst_ipaddr rhost) -n 10 -N 10 -c res_$x
done
tst_netload_compare $(cat res_0) $(cat res_50) 1
diff --git a/testcases/network/busy_poll/busy_poll02.sh b/testcases/network/busy_poll/busy_poll02.sh
index ebae4d2f5..8ba701cc2 100755
--- a/testcases/network/busy_poll/busy_poll02.sh
+++ b/testcases/network/busy_poll/busy_poll02.sh
@@ -31,7 +31,7 @@ test()
for x in 50 0; do
tst_res TINFO "set low latency busy poll to $x per socket"
set_busy_poll $x
- tst_netload -H $(tst_ipaddr rhost) -n 10 -N 10 -d res_$x -b $x
+ tst_netload -H $(tst_ipaddr rhost) -n 10 -N 10 -c res_$x -b $x
done
tst_netload_compare $(cat res_0) $(cat res_50) 1
diff --git a/testcases/network/busy_poll/busy_poll03.sh b/testcases/network/busy_poll/busy_poll03.sh
index 04d5978f7..d35dde6ec 100755
--- a/testcases/network/busy_poll/busy_poll03.sh
+++ b/testcases/network/busy_poll/busy_poll03.sh
@@ -33,7 +33,7 @@ test()
for x in 50 0; do
tst_res TINFO "set low latency busy poll to $x per $2 socket"
set_busy_poll $x
- tst_netload -H $(tst_ipaddr rhost) -n 10 -N 10 -d res_$x \
+ tst_netload -H $(tst_ipaddr rhost) -n 10 -N 10 -c res_$x \
-b $x -T $2
done
diff --git a/testcases/network/can/cve/can_bcm01.c b/testcases/network/can/cve/can_bcm01.c
index 79a827cfa..d9a835b03 100644
--- a/testcases/network/can/cve/can_bcm01.c
+++ b/testcases/network/can/cve/can_bcm01.c
@@ -1,16 +1,15 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Copyright (C) 2020 SUSE LLC <mdoucha@suse.cz>
+ */
+
+/*\
+ * [Description]
*
* CVE-2021-3609
*
* Test for race condition vulnerability in CAN BCM. Fixed in:
- *
- * commit d5f9023fa61ee8b94f37a93f08e94b136cf1e463
- * Author: Thadeu Lima de Souza Cascardo <cascardo@canonical.com>
- * Date: Sat Jun 19 13:18:13 2021 -0300
- *
- * can: bcm: delay release of struct bcm_op after synchronize_rcu()
+ * d5f9023fa61e ("can: bcm: delay release of struct bcm_op after synchronize_rcu()").
*
* The test is skipped when running in 32-bit compat mode. The kernel
* compatibility layer for CAN structures is not implemented at the
diff --git a/testcases/network/can/filter-tests/can_filter.c b/testcases/network/can/filter-tests/can_filter.c
index 19c7fc48d..1ea8ea18f 100644
--- a/testcases/network/can/filter-tests/can_filter.c
+++ b/testcases/network/can/filter-tests/can_filter.c
@@ -172,7 +172,7 @@ static void run(unsigned int n)
static struct tst_test test = {
.tcnt = TC,
.options = (struct tst_option[]) {
- {"D:", &can_dev_name, "CAN device name"},
+ {"d:", &can_dev_name, "CAN device name"},
{}
},
.setup = setup,
diff --git a/testcases/network/can/filter-tests/can_rcv_own_msgs.c b/testcases/network/can/filter-tests/can_rcv_own_msgs.c
index 6bb2619f4..ba40666dc 100644
--- a/testcases/network/can/filter-tests/can_rcv_own_msgs.c
+++ b/testcases/network/can/filter-tests/can_rcv_own_msgs.c
@@ -134,7 +134,7 @@ static void run(void)
static struct tst_test test = {
.options = (struct tst_option[]) {
- {"D:", &can_dev_name, "CAN device name"},
+ {"d:", &can_dev_name, "CAN device name"},
{}
},
.setup = setup,
diff --git a/testcases/network/iptables/.gitignore b/testcases/network/iptables/.gitignore
new file mode 100644
index 000000000..0f47a7313
--- /dev/null
+++ b/testcases/network/iptables/.gitignore
@@ -0,0 +1 @@
+nft02
diff --git a/testcases/network/iptables/Makefile b/testcases/network/iptables/Makefile
index 1b42f25db..02e228cbc 100644
--- a/testcases/network/iptables/Makefile
+++ b/testcases/network/iptables/Makefile
@@ -5,7 +5,7 @@
top_srcdir ?= ../../..
-include $(top_srcdir)/include/mk/env_pre.mk
+include $(top_srcdir)/include/mk/testcases.mk
INSTALL_TARGETS := *.sh
diff --git a/testcases/network/iptables/nft02.c b/testcases/network/iptables/nft02.c
new file mode 100644
index 000000000..8b7248c69
--- /dev/null
+++ b/testcases/network/iptables/nft02.c
@@ -0,0 +1,216 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (C) 2023 SUSE LLC
+ * Author: Marcos Paulo de Souza <mpdesouza@suse.com>
+ * LTP port: Martin Doucha <mdoucha@suse.cz>
+ */
+
+/*\
+ * [Description]
+ *
+ * CVE-2023-31248
+ *
+ * Test for use-after-free when adding a new rule to a chain deleted
+ * in the same netlink message batch.
+ *
+ * Kernel bug fixed in:
+ *
+ * commit 515ad530795c118f012539ed76d02bacfd426d89
+ * Author: Thadeu Lima de Souza Cascardo <cascardo@canonical.com>
+ * Date: Wed Jul 5 09:12:55 2023 -0300
+ *
+ * netfilter: nf_tables: do not ignore genmask when looking up chain by id
+ */
+
+#include <linux/netlink.h>
+#include <linux/tcp.h>
+#include <arpa/inet.h>
+#include <linux/netfilter.h>
+#include "lapi/nf_tables.h"
+#include <linux/netfilter/nfnetlink.h>
+#include "tst_test.h"
+#include "tst_netlink.h"
+
+#define TABNAME "ltp_table1"
+#define SRCCHAIN "ltp_chain_src"
+#define DESTCHAIN "ltp_chain_dest"
+#define DESTCHAIN_ID 77
+
+static uint32_t chain_id;
+static uint32_t imm_dreg, imm_verdict;
+static struct tst_netlink_context *ctx;
+
+/* Table creation config */
+static const struct tst_netlink_attr_list table_config[] = {
+ {NFTA_TABLE_NAME, TABNAME, strlen(TABNAME) + 1, NULL},
+ {0, NULL, -1, NULL}
+};
+
+/* Chain creation and deletion config */
+static const struct tst_netlink_attr_list destchain_config[] = {
+ {NFTA_TABLE_NAME, TABNAME, strlen(TABNAME) + 1, NULL},
+ {NFTA_CHAIN_NAME, DESTCHAIN, strlen(DESTCHAIN) + 1, NULL},
+ {NFTA_CHAIN_ID, &chain_id, sizeof(chain_id), NULL},
+ {0, NULL, -1, NULL}
+};
+
+static const struct tst_netlink_attr_list delchain_config[] = {
+ {NFTA_TABLE_NAME, TABNAME, strlen(TABNAME) + 1, NULL},
+ {NFTA_CHAIN_NAME, DESTCHAIN, strlen(DESTCHAIN) + 1, NULL},
+ {0, NULL, -1, NULL}
+};
+
+static const struct tst_netlink_attr_list srcchain_config[] = {
+ {NFTA_TABLE_NAME, TABNAME, strlen(TABNAME) + 1, NULL},
+ {NFTA_CHAIN_NAME, SRCCHAIN, strlen(SRCCHAIN) + 1, NULL},
+ {0, NULL, -1, NULL}
+};
+
+/* Rule creation config */
+static const struct tst_netlink_attr_list rule_verdict_config[] = {
+ {NFTA_VERDICT_CODE, &imm_verdict, sizeof(imm_verdict), NULL},
+ {NFTA_VERDICT_CHAIN_ID, &chain_id, sizeof(chain_id), NULL},
+ {0, NULL, -1, NULL}
+};
+
+static const struct tst_netlink_attr_list rule_data_config[] = {
+ {NFTA_IMMEDIATE_DREG, &imm_dreg, sizeof(imm_dreg), NULL},
+ {NFTA_IMMEDIATE_DATA, NULL, 0, (const struct tst_netlink_attr_list[]) {
+ {NFTA_DATA_VERDICT, NULL, 0, rule_verdict_config},
+ {0, NULL, -1, NULL}
+ }},
+ {0, NULL, -1, NULL}
+};
+
+static const struct tst_netlink_attr_list rule_expr_config[] = {
+ {NFTA_LIST_ELEM, NULL, 0, (const struct tst_netlink_attr_list[]) {
+ {NFTA_EXPR_NAME, "immediate", 10, NULL},
+ {NFTA_EXPR_DATA, NULL, 0, rule_data_config},
+ {0, NULL, -1, NULL}
+ }},
+ {0, NULL, -1, NULL}
+};
+
+static const struct tst_netlink_attr_list rule_config[] = {
+ {NFTA_RULE_EXPRESSIONS, NULL, 0, rule_expr_config},
+ {NFTA_RULE_TABLE, TABNAME, strlen(TABNAME) + 1, NULL},
+ {NFTA_RULE_CHAIN, SRCCHAIN, strlen(SRCCHAIN) + 1, NULL},
+ {0, NULL, -1, NULL}
+};
+
+static void setup(void)
+{
+ tst_setup_netns();
+
+ chain_id = htonl(DESTCHAIN_ID);
+ imm_dreg = htonl(NFT_REG_VERDICT);
+ imm_verdict = htonl(NFT_GOTO);
+}
+
+static void run(void)
+{
+ int ret;
+ struct nlmsghdr header;
+ struct nfgenmsg nfpayload;
+
+ memset(&header, 0, sizeof(header));
+ memset(&nfpayload, 0, sizeof(nfpayload));
+ nfpayload.version = NFNETLINK_V0;
+
+ ctx = NETLINK_CREATE_CONTEXT(NETLINK_NETFILTER);
+
+ /* Start netfilter batch */
+ header.nlmsg_type = NFNL_MSG_BATCH_BEGIN;
+ header.nlmsg_flags = NLM_F_REQUEST;
+ nfpayload.nfgen_family = AF_UNSPEC;
+ nfpayload.res_id = htons(NFNL_SUBSYS_NFTABLES);
+ NETLINK_ADD_MESSAGE(ctx, &header, &nfpayload, sizeof(nfpayload));
+
+ /* Add table */
+ header.nlmsg_type = (NFNL_SUBSYS_NFTABLES << 8) | NFT_MSG_NEWTABLE;
+ header.nlmsg_flags = NLM_F_REQUEST | NLM_F_CREATE;
+ nfpayload.nfgen_family = NFPROTO_IPV4;
+ nfpayload.res_id = htons(0);
+ NETLINK_ADD_MESSAGE(ctx, &header, &nfpayload, sizeof(nfpayload));
+ NETLINK_ADD_ATTR_LIST(ctx, table_config);
+
+ /* Add destination chain */
+ header.nlmsg_type = (NFNL_SUBSYS_NFTABLES << 8) | NFT_MSG_NEWCHAIN;
+ header.nlmsg_flags = NLM_F_REQUEST | NLM_F_CREATE;
+ nfpayload.nfgen_family = NFPROTO_IPV4;
+ nfpayload.res_id = htons(0);
+ NETLINK_ADD_MESSAGE(ctx, &header, &nfpayload, sizeof(nfpayload));
+ NETLINK_ADD_ATTR_LIST(ctx, destchain_config);
+
+ /* Delete destination chain */
+ header.nlmsg_type = (NFNL_SUBSYS_NFTABLES << 8) | NFT_MSG_DELCHAIN;
+ header.nlmsg_flags = NLM_F_REQUEST;
+ nfpayload.nfgen_family = NFPROTO_IPV4;
+ nfpayload.res_id = htons(0);
+ NETLINK_ADD_MESSAGE(ctx, &header, &nfpayload, sizeof(nfpayload));
+ NETLINK_ADD_ATTR_LIST(ctx, delchain_config);
+
+ /* Add source chain */
+ header.nlmsg_type = (NFNL_SUBSYS_NFTABLES << 8) | NFT_MSG_NEWCHAIN;
+ header.nlmsg_flags = NLM_F_REQUEST | NLM_F_CREATE;
+ nfpayload.nfgen_family = NFPROTO_IPV4;
+ nfpayload.res_id = htons(0);
+ NETLINK_ADD_MESSAGE(ctx, &header, &nfpayload, sizeof(nfpayload));
+ NETLINK_ADD_ATTR_LIST(ctx, srcchain_config);
+
+ /* Add rule to source chain. Require ACK and check for ENOENT error. */
+ header.nlmsg_type = (NFNL_SUBSYS_NFTABLES << 8) | NFT_MSG_NEWRULE;
+ header.nlmsg_flags = NLM_F_REQUEST | NLM_F_APPEND | NLM_F_CREATE |
+ NLM_F_ACK;
+ nfpayload.nfgen_family = NFPROTO_IPV4;
+ nfpayload.res_id = htons(0);
+ NETLINK_ADD_MESSAGE(ctx, &header, &nfpayload, sizeof(nfpayload));
+ NETLINK_ADD_ATTR_LIST(ctx, rule_config);
+
+ /* End batch */
+ header.nlmsg_type = NFNL_MSG_BATCH_END;
+ header.nlmsg_flags = NLM_F_REQUEST;
+ nfpayload.nfgen_family = AF_UNSPEC;
+ nfpayload.res_id = htons(NFNL_SUBSYS_NFTABLES);
+ NETLINK_ADD_MESSAGE(ctx, &header, &nfpayload, sizeof(nfpayload));
+
+ ret = NETLINK_SEND_VALIDATE(ctx);
+ TST_ERR = tst_netlink_errno;
+ NETLINK_DESTROY_CONTEXT(ctx);
+ ctx = NULL;
+
+ if (ret)
+ tst_res(TFAIL, "Netfilter chain list is corrupted");
+ else if (TST_ERR == ENOENT)
+ tst_res(TPASS, "Deleted netfilter chain cannot be referenced");
+ else if (TST_ERR == EOPNOTSUPP || TST_ERR == EINVAL)
+ tst_brk(TCONF, "Test requires unavailable netfilter features");
+ else
+ tst_brk(TBROK | TTERRNO, "Unknown nfnetlink error");
+}
+
+static void cleanup(void)
+{
+ NETLINK_DESTROY_CONTEXT(ctx);
+}
+
+static struct tst_test test = {
+ .test_all = run,
+ .setup = setup,
+ .cleanup = cleanup,
+ .taint_check = TST_TAINT_W | TST_TAINT_D,
+ .needs_kconfigs = (const char *[]) {
+ "CONFIG_USER_NS=y",
+ "CONFIG_NF_TABLES",
+ NULL
+ },
+ .save_restore = (const struct tst_path_val[]) {
+ {"/proc/sys/user/max_user_namespaces", "1024", TST_SR_SKIP},
+ {}
+ },
+ .tags = (const struct tst_tag[]) {
+ {"linux-git", "515ad530795c"},
+ {"CVE", "2023-31248"},
+ {}
+ }
+};
diff --git a/testcases/network/netstress/netstress.c b/testcases/network/netstress/netstress.c
index fb6281cd0..03bfe33f2 100644
--- a/testcases/network/netstress/netstress.c
+++ b/testcases/network/netstress/netstress.c
@@ -1,6 +1,7 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Copyright (c) 2014-2016 Oracle and/or its affiliates. All Rights Reserved.
+ * Copyright (c) 2014-2023 Petr Vorel <pvorel@suse.cz>
* Author: Alexey Kodanev <alexey.kodanev@oracle.com>
*/
@@ -1009,7 +1010,7 @@ static struct tst_test test = {
{"T:", &type, "Tcp (default), udp, udp_lite, dccp, sctp"},
{"z", &zcopy, "Enable SO_ZEROCOPY"},
{"P:", &reuse_port, "Enable SO_REUSEPORT"},
- {"D:", &dev, "Bind to device x"},
+ {"d:", &dev, "Bind to device x"},
{"H:", &server_addr, "Server name or IP address"},
{"l", &client_mode, "Become client, default is server"},
@@ -1018,7 +1019,7 @@ static struct tst_test test = {
{"n:", &narg, "Client message size"},
{"N:", &Narg, "Server message size"},
{"m:", &Targ, "Receive timeout in milliseconds (not used by UDP/DCCP client)"},
- {"d:", &rpath, "Path to file where result is saved"},
+ {"c:", &rpath, "Path to file where result is saved"},
{"A:", &Aarg, "Max payload length (generated randomly)"},
{"R:", &Rarg, "Server requests after which conn.closed"},
diff --git a/testcases/network/nfs/fsx-linux/fsx.sh b/testcases/network/nfs/fsx-linux/fsx.sh
index 9bb46ad6e..dbecbfaf9 100755
--- a/testcases/network/nfs/fsx-linux/fsx.sh
+++ b/testcases/network/nfs/fsx-linux/fsx.sh
@@ -14,10 +14,9 @@ do_test()
{
ITERATIONS=${ITERATIONS:=50000}
tst_res TINFO "starting fsx-linux -N $ITERATIONS..."
- fsx-linux -N $ITERATIONS testfile > fsx-out.log 2>&1
+ fsx-linux -N $ITERATIONS
if [ "$?" -ne 0 ]; then
tst_res TFAIL "Errors have resulted from this test"
- cat fsx-out.log
else
tst_res TPASS "fsx-linux test passed"
fi
diff --git a/testcases/network/nfs/nfs_stress/nfs05_make_tree.c b/testcases/network/nfs/nfs_stress/nfs05_make_tree.c
index e2243ac5e..f4ec5b332 100644
--- a/testcases/network/nfs/nfs_stress/nfs05_make_tree.c
+++ b/testcases/network/nfs/nfs_stress/nfs05_make_tree.c
@@ -46,7 +46,6 @@
#include <errno.h>
#include <linux/unistd.h>
-#include "lapi/mkdirat.h"
#include "tst_safe_pthread.h"
#include "tst_safe_stdio.h"
#include "tst_test.h"
diff --git a/testcases/network/nfs/nfs_stress/nfs06.sh b/testcases/network/nfs/nfs_stress/nfs06.sh
index 560df05b1..09e55fe34 100755
--- a/testcases/network/nfs/nfs_stress/nfs06.sh
+++ b/testcases/network/nfs/nfs_stress/nfs06.sh
@@ -34,7 +34,10 @@ do_test()
tst_res TINFO "waiting for pids:$pids"
for p in $pids; do
- wait $p || tst_brk TFAIL "fsstress process failed"
+ if ! wait $p; then
+ tst_res TFAIL "fsstress process failed"
+ return
+ fi
tst_res TINFO "fsstress '$p' completed"
done
pids=
diff --git a/testcases/network/nfs/nfs_stress/nfs_lib.sh b/testcases/network/nfs/nfs_stress/nfs_lib.sh
index a996f7cc8..d3de3b7f1 100644
--- a/testcases/network/nfs/nfs_stress/nfs_lib.sh
+++ b/testcases/network/nfs/nfs_stress/nfs_lib.sh
@@ -4,9 +4,9 @@
# Copyright (c) 2015-2018 Oracle and/or its affiliates. All Rights Reserved.
# Copyright (c) International Business Machines Corp., 2001
-VERSION=${VERSION:=3}
+VERSION=${VERSION:=4.2}
NFILES=${NFILES:=1000}
-SOCKET_TYPE="${SOCKET_TYPE:-udp}"
+SOCKET_TYPE="${SOCKET_TYPE:-tcp}"
NFS_TYPE=${NFS_TYPE:=nfs}
nfs_usage()
@@ -214,7 +214,7 @@ nfs_cleanup()
local_dir="$(get_local_dir $i $n)"
if grep -q "$local_dir" /proc/mounts; then
tst_res TINFO "Unmounting $local_dir"
- umount $local_dir
+ umount $local_dir || tst_res TWARN "Unmount failed"
fi
n=$(( n + 1 ))
done
diff --git a/testcases/network/nfs/nfslock01/nfslock01.sh b/testcases/network/nfs/nfslock01/nfslock01.sh
index 01d59ce85..1f8c2d755 100755
--- a/testcases/network/nfs/nfslock01/nfslock01.sh
+++ b/testcases/network/nfs/nfslock01/nfslock01.sh
@@ -68,7 +68,8 @@ do_test()
for p in $pids; do
wait $p
if [ $? -ne 0 ]; then
- tst_brk TFAIL "nfs_lock process failed"
+ tst_res TFAIL "nfs_lock process failed"
+ return
else
tst_res TINFO "$p completed"
fi
diff --git a/testcases/network/stress/route/route-lib.sh b/testcases/network/stress/route/route-lib.sh
index 163c15423..29aa2e913 100644
--- a/testcases/network/stress/route/route-lib.sh
+++ b/testcases/network/stress/route/route-lib.sh
@@ -97,10 +97,14 @@ test_netlink()
tst_res TINFO "running $cmd $opt"
$cmd $opt || ret=$?
if [ "$ret" -ne 0 ]; then
- [ $((ret & 3)) -ne 0 ] && \
- tst_brk TFAIL "$cmd failed"
+ if [ $((ret & 3)) -ne 0 ]; then
+ tst_res TFAIL "$cmd failed"
+ return
+ fi
+
[ $((ret & 32)) -ne 0 ] && \
tst_brk TCONF "not supported configuration"
+
[ $((ret & 4)) -ne 0 ] && \
tst_res TWARN "$cmd has warnings"
fi
diff --git a/testcases/network/stress/ssh/ssh-stress.sh b/testcases/network/stress/ssh/ssh-stress.sh
index e7c4d45ce..c27c27a28 100755
--- a/testcases/network/stress/ssh/ssh-stress.sh
+++ b/testcases/network/stress/ssh/ssh-stress.sh
@@ -93,8 +93,10 @@ IdentityFile $TST_TMPDIR/id_rsa\n\" > $RHOST_SSH_CONF"
test_ssh_connectivity()
{
- tst_rhost_run -c "$RHOST_SSH 'true >/dev/null 2>&1' >/dev/null"
- [ $? -ne 0 ] && tst_brk TFAIL "SSH not reachable"
+ if ! tst_rhost_run -c "$RHOST_SSH 'true >/dev/null 2>&1' >/dev/null"; then
+ tst_res TFAIL "SSH not reachable"
+ return
+ fi
}
test1()
@@ -121,7 +123,10 @@ test1()
[ $? -ne 0 ] && num=$((num + 1))
done
- [ $num -ne 0 ] && tst_brk TFAIL "$num ssh processes died unexpectedly during execution"
+ if [ $num -ne 0 ]; then
+ tst_res TFAIL "$num ssh processes died unexpectedly during execution"
+ return
+ fi
test_ssh_connectivity
@@ -216,7 +221,10 @@ test3()
# Setup an ssh tunnel from the remote host to testhost
tst_rhost_run -c "$RHOST_SSH -f -N -L $lport:$rhost:$port </dev/null >/dev/null 2>&1"
- [ "$?" -ne 0 ] && tst_brk TFAIL "Failed to create an SSH session with port forwarding"
+ if [ "$?" -ne 0 ]; then
+ tst_res TFAIL "Failed to create an SSH session with port forwarding"
+ return
+ fi
RHOST_PIDS=$(tst_rhost_run -c "pgrep -f '^ssh .*$lport:$rhost:$port'")
# Start the TCP traffic clients
diff --git a/testcases/network/tcp_cmds/host/host01.sh b/testcases/network/tcp_cmds/host/host01.sh
index 6a4067495..9ed44bae3 100755
--- a/testcases/network/tcp_cmds/host/host01.sh
+++ b/testcases/network/tcp_cmds/host/host01.sh
@@ -21,11 +21,12 @@ do_test()
if addr=$(host $lhost); then
addr=$(echo "$addr" | grep address | tail -1 | awk '{print $NF}')
if [ -z "$addr" ]; then
- tst_brk TFAIL "empty address"
+ tst_res TFAIL "empty address"
+ return
fi
EXPECT_PASS host $addr \>/dev/null
else
- tst_brk TFAIL "host $lhost on local machine failed"
+ tst_res TFAIL "host $lhost on local machine failed"
fi
}
diff --git a/testcases/network/tcp_cmds/ipneigh/ipneigh01.sh b/testcases/network/tcp_cmds/ipneigh/ipneigh01.sh
index e67ff5cc8..4b818357e 100755
--- a/testcases/network/tcp_cmds/ipneigh/ipneigh01.sh
+++ b/testcases/network/tcp_cmds/ipneigh/ipneigh01.sh
@@ -57,8 +57,10 @@ do_test()
for i in $(seq 1 $NUMLOOPS); do
- ping$TST_IPV6 -q -c1 $(tst_ipaddr rhost) -I $(tst_iface) > /dev/null || \
- tst_brk TFAIL "cannot ping $(tst_ipaddr rhost)"
+ if ! ping$TST_IPV6 -q -c1 $(tst_ipaddr rhost) -I $(tst_iface) > /dev/null; then
+ tst_res TFAIL "cannot ping $(tst_ipaddr rhost)"
+ return
+ fi
local k
local ret=1
@@ -66,19 +68,22 @@ do_test()
$SHOW_CMD | grep -q $(tst_ipaddr rhost)
if [ $? -eq 0 ]; then
ret=0
- break;
+ break
fi
tst_sleep 100ms
done
- [ "$ret" -ne 0 ] && \
- tst_brk TFAIL "$entry_name entry '$(tst_ipaddr rhost)' not listed"
+ if [ "$ret" -ne 0 ]; then
+ tst_res TFAIL "$entry_name entry '$(tst_ipaddr rhost)' not listed"
+ return
+ fi
$DEL_CMD
- $SHOW_CMD | grep -q "$(tst_ipaddr rhost).*$(tst_hwaddr rhost)" && \
- tst_brk TFAIL "'$DEL_CMD' failed, entry has " \
- "$(tst_hwaddr rhost)' $i/$NUMLOOPS"
+ if $SHOW_CMD | grep -q "$(tst_ipaddr rhost).*$(tst_hwaddr rhost)"; then
+ tst_res TFAIL "'$DEL_CMD' failed, entry has $(tst_hwaddr rhost)' $i/$NUMLOOPS"
+ return
+ fi
done
tst_res TPASS "verified adding/removing $entry_name cache entry"
diff --git a/testcases/network/virt/virt_lib.sh b/testcases/network/virt/virt_lib.sh
index e919bc3a5..2ee57b79a 100644
--- a/testcases/network/virt/virt_lib.sh
+++ b/testcases/network/virt/virt_lib.sh
@@ -175,7 +175,7 @@ virt_multiple_add_test()
for i in $(seq $start_id $max); do
virt_add ltp_v$i id $i $opt || \
- tst_brk TFAIL "failed to create 'ltp_v0 $opt'"
+ tst_brk TBROK "failed to create 'ltp_v$i $opt'"
ROD_SILENT "ip link set ltp_v$i up"
done
@@ -197,7 +197,7 @@ virt_add_delete_test()
for i in $(seq 0 $max); do
virt_add ltp_v0 $opt || \
- tst_brk TFAIL "failed to create 'ltp_v0 $opt'"
+ tst_brk TBROK "failed to create 'ltp_v0 $opt'"
ROD_SILENT "ip link set ltp_v0 up"
ROD_SILENT "ip link delete ltp_v0"
done
@@ -284,10 +284,10 @@ virt_compare_netperf()
local expect_res="${1:-pass}"
local opts="$2"
- tst_netload -H $ip_virt_remote $opts -d res_ipv4 -e $expect_res \
+ tst_netload -H $ip_virt_remote $opts -c res_ipv4 -e $expect_res \
-D ltp_v0 || ret1="fail"
- tst_netload -H ${ip6_virt_remote} $opts -d res_ipv6 -e $expect_res \
+ tst_netload -H ${ip6_virt_remote} $opts -c res_ipv6 -e $expect_res \
-D ltp_v0 || ret2="fail"
[ "$ret1" = "fail" -o "$ret2" = "fail" ] && return
@@ -295,7 +295,7 @@ virt_compare_netperf()
local vt="$(cat res_ipv4)"
local vt6="$(cat res_ipv6)"
- tst_netload -H $(tst_ipaddr rhost) $opts -d res_lan
+ tst_netload -H $(tst_ipaddr rhost) $opts -c res_lan
local lt="$(cat res_lan)"
tst_res TINFO "time lan IPv${TST_IPVER}($lt) $virt_type IPv4($vt) and IPv6($vt6) ms"
diff --git a/testcases/network/xinetd/xinetd_tests.sh b/testcases/network/xinetd/xinetd_tests.sh
index 505dae5d7..25ec91d26 100755
--- a/testcases/network/xinetd/xinetd_tests.sh
+++ b/testcases/network/xinetd/xinetd_tests.sh
@@ -91,9 +91,10 @@ xinetd_test()
for a in $check_addr; do
p=$(echo $pattern | sed "s/ADDR/$a/")
- echo '' | telnet $a 2>&1 | grep -qiE "$p"
- [ $? -ne 0 ] && \
- tst_brk TFAIL "not expected output for 'telnet $a'"
+ if ! echo '' | telnet $a 2>&1 | grep -qiE "$p"; then
+ tst_res TFAIL "not expected output for 'telnet $a'"
+ return
+ fi
done
tst_res TPASS "expected output with telnet $desc"
}
diff --git a/testcases/open_posix_testsuite/conformance/interfaces/pthread_cond_timedwait/4-3.c b/testcases/open_posix_testsuite/conformance/interfaces/pthread_cond_timedwait/4-3.c
index 5a49ffc35..305ab0454 100644
--- a/testcases/open_posix_testsuite/conformance/interfaces/pthread_cond_timedwait/4-3.c
+++ b/testcases/open_posix_testsuite/conformance/interfaces/pthread_cond_timedwait/4-3.c
@@ -69,7 +69,10 @@ typedef struct {
static struct {
pthread_mutex_t mtx;
pthread_cond_t cnd;
-} data;
+} data = {
+ PTHREAD_MUTEX_INITIALIZER,
+ PTHREAD_COND_INITIALIZER
+};
/* the following function keeps on sending the signal to the process */
static void *sendsig(void *arg)
diff --git a/testcases/open_posix_testsuite/conformance/interfaces/pthread_rwlock_unlock/4-1.c b/testcases/open_posix_testsuite/conformance/interfaces/pthread_rwlock_unlock/4-1.c
index 2db9e4cc6..d4a579edf 100644
--- a/testcases/open_posix_testsuite/conformance/interfaces/pthread_rwlock_unlock/4-1.c
+++ b/testcases/open_posix_testsuite/conformance/interfaces/pthread_rwlock_unlock/4-1.c
@@ -31,8 +31,8 @@ int main(void)
static pthread_rwlock_t rwlock;
int rc;
-#ifdef __linux__
- printf("Unlocking uninitialized rwlock is undefined on Linux\n");
+#if defined(__linux__) || defined(__NuttX__)
+ printf("Unlocking uninitialized rwlock is undefined on this OS\n");
return PTS_UNSUPPORTED;
#endif
diff --git a/testcases/open_posix_testsuite/conformance/interfaces/sem_timedwait/3-1.c b/testcases/open_posix_testsuite/conformance/interfaces/sem_timedwait/3-1.c
index fb6f2e6cb..739fe86a5 100644
--- a/testcases/open_posix_testsuite/conformance/interfaces/sem_timedwait/3-1.c
+++ b/testcases/open_posix_testsuite/conformance/interfaces/sem_timedwait/3-1.c
@@ -15,7 +15,7 @@
#include <sys/stat.h>
#include <sys/types.h>
#include <fcntl.h>
-#if __linux__
+#ifdef __linux__
#include <features.h>
#endif
#include <semaphore.h>
diff --git a/testcases/open_posix_testsuite/functional/mqueues/send_rev_2.c b/testcases/open_posix_testsuite/functional/mqueues/send_rev_2.c
index a0a49d159..22ecbb224 100644
--- a/testcases/open_posix_testsuite/functional/mqueues/send_rev_2.c
+++ b/testcases/open_posix_testsuite/functional/mqueues/send_rev_2.c
@@ -43,7 +43,7 @@ static int *send_1(void *mq)
printf("Enter into send_1 \n");
for (i = 0; i < MAX_MSG; i++) {
- if (-1 == mq_send(mq1, s_msg_ptr[i], MSG_SIZE, i)) {
+ if (-1 == mq_send(mq1, s_msg_ptr[i], strlen(s_msg_ptr[i]) + 1, i)) {
perror("mq_send doesn't return success \n");
pthread_exit((void *)1);
}
@@ -61,7 +61,7 @@ static int *send_2(void *mq)
printf("Enter into send_2 \n");
for (i = 0; i < MAX_MSG; i++) {
- if (-1 == mq_send(mq2, s_msg_ptr[i], MSG_SIZE, i)) {
+ if (-1 == mq_send(mq2, s_msg_ptr[i], strlen(s_msg_ptr[i]) + 1, i)) {
perror("mq_send doesn't return success \n");
pthread_exit((void *)1);
}
diff --git a/testcases/realtime/func/rt-migrate/rt-migrate.c b/testcases/realtime/func/rt-migrate/rt-migrate.c
index 97ab604c7..252e77e6a 100644
--- a/testcases/realtime/func/rt-migrate/rt-migrate.c
+++ b/testcases/realtime/func/rt-migrate/rt-migrate.c
@@ -74,6 +74,9 @@
#define VERSION_STRING "V 0.4LTP"
+#define CLAMP(x, lower, upper) (MIN(upper, MAX(x, lower)))
+#define CLAMP_PRIO(prio) CLAMP(prio, prio_min, prio_max)
+
int nr_tasks;
int lfd;
@@ -137,7 +140,7 @@ static unsigned long long interval = INTERVAL;
static unsigned long long run_interval = RUN_INTERVAL;
static unsigned long long max_err = MAX_ERR;
static int nr_runs = NR_RUNS;
-static int prio_start = PRIO_START;
+static int prio_start = PRIO_START, prio_min, prio_max;
static int check = 1;
static int stop;
@@ -284,8 +287,8 @@ static void print_results(void)
printf("Parent pid: %d\n", getpid());
for (t = 0; t < nr_tasks; t++) {
- printf(" Task %d (prio %d) (pid %ld):\n", t, t + prio_start,
- thread_pids[t]);
+ printf(" Task %d (prio %d) (pid %ld):\n", t,
+ CLAMP_PRIO(t + prio_start), thread_pids[t]);
printf(" Max: %lld us\n", tasks_max[t]);
printf(" Min: %lld us\n", tasks_min[t]);
printf(" Tot: %lld us\n", tasks_avg[t] * nr_runs);
@@ -394,6 +397,13 @@ static void stop_log(int sig)
int main(int argc, char **argv)
{
+ /*
+ * Determine the valid priority range; subtracting one from the
+ * maximum to reserve the highest prio for main thread.
+ */
+ prio_min = sched_get_priority_min(SCHED_FIFO);
+ prio_max = sched_get_priority_max(SCHED_FIFO) - 1;
+
int *threads;
long i;
int ret;
@@ -409,6 +419,10 @@ int main(int argc, char **argv)
numcpus = sysconf(_SC_NPROCESSORS_ONLN);
nr_tasks = numcpus + 1;
}
+ if (nr_tasks < 0) {
+ printf("The number of tasks must not be negative.\n");
+ exit(EXIT_FAILURE);
+ }
intervals = malloc(sizeof(stats_container_t) * nr_tasks);
if (!intervals)
@@ -448,7 +462,7 @@ int main(int argc, char **argv)
for (i = 0; i < nr_tasks; i++) {
threads[i] = create_fifo_thread(start_task, (void *)i,
- prio_start + i);
+ CLAMP_PRIO(prio_start + i));
}
/*
@@ -460,7 +474,8 @@ int main(int argc, char **argv)
/* up our prio above all tasks */
memset(&param, 0, sizeof(param));
- param.sched_priority = nr_tasks + prio_start;
+ param.sched_priority = CLAMP(nr_tasks + prio_start, prio_min,
+ prio_max + 1);
if (sched_setscheduler(0, SCHED_FIFO, &param))
debug(DBG_WARN, "Warning, can't set priority of main thread!\n");
intv.tv_sec = INTERVAL / NS_PER_SEC;
diff --git a/testscripts/autofs1.sh b/testscripts/autofs1.sh
deleted file mode 100755
index 324c4db93..000000000
--- a/testscripts/autofs1.sh
+++ /dev/null
@@ -1,273 +0,0 @@
-#!/bin/bash
-
-
-##############################################################
-#
-# Copyright (c) International Business Machines Corp., 2003
-#
-# 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
-#
-# FILE : autofs1.sh
-# USAGE : autofs1.sh <disk_partition>
-#
-# DESCRIPTION : A script that will test autofs on Linux system.
-# REQUIREMENTS:
-# 1) System with a floppy device with a floppy disk in it.
-# 2) A spare (scratch) disk partition of 100MB or larger.
-#
-# HISTORY :
-# 06/11/2003 Prakash Narayana (prakashn@us.ibm.com)
-# 08/01/2005 Michael Reed (mreed10@us.ibm.com)
-# - Added an check to see if a directory exists
-# - This prevents unnessary failures
-# - Correction to an echo statement
-# - Added an additional error message if a floppy disk is not present
-#
-# CODE COVERAGE:
-# 41.46% - fs/autofs/dirhash.c
-# 33.33% - fs/autofs/init.c
-# 27.70% - fs/autofs/inode.c
-# 38.16% - fs/autofs/root.c
-# 0.00% - fs/autofs/symlink.c
-# 43.40% - fs/autofs/waitq.c
-#
-##############################################################
-
-
-##############################################################
-#
-# Make sure that uid=root is running this script.
-# Validate the command line argument as a block special device.
-# Make sure that autofs package has been installed.
-# Make sure that autofs module is built into the kernel or loaded.
-#
-##############################################################
-
-if [ $UID != 0 ]
-then
- echo "FAILED: Must have root access to execute this script"
- exit 1
-fi
-
-if [ $# != 1 ]
-then
- echo "FAILED: Usage $0 <disk_partition>"
- echo "Example: $0 /dev/hdc1"
- exit 1
-else
- disk_partition=$1
- if [ ! -b $disk_partition ]
- then
- echo "FAILED: Usage $0 <block special disk_partition>"
- exit 1
- fi
- mkfs -t ext2 $disk_partition
-fi
-
-rpm -q -a | grep autofs
-if [ $? != 0 ]
-then
- echo "FAILED: autofs package is not installed"
- exit 1
-fi
-
-grep autofs /proc/filesystems
-if [ $? != 0 ]
-then
- echo "FAILED: autofs module is not built into the kernel or loaded"
- exit 1
-fi
-
-
-##############################################################
-#
-# Pick the floppy device name from /etc/fstab
-# Format (mkfs -t ext2) the floppy to ext2 file system
-# Create the /etc/auto.master
-# Create the /etc/auto.media
-# Create /AUTOFS directory.
-#
-##############################################################
-
-floppy_dev=`grep floppy /etc/fstab | awk '{print $1}'`
-
-echo "Found floppy device:$floppy_dev"
-
-if [ $floppy_dev != "" ]
-then
- /sbin/mkfs -t ext2 $floppy_dev
- if [ $? != 0 ]
- then
- echo "FAILED: mkfs -t ext2 $floppy_dev failed"
- echo "Insert a disk into the floppy drive"
- exit 1
- fi
-fi
-
-if [ ! -d /AUTOFS ]
-then
- mkdir -m 777 /AUTOFS
-fi
-
-echo "/AUTOFS/MEDIA /etc/auto.media" > /etc/auto.master
-echo "floppy -fstype=ext2 :$floppy_dev" > /etc/auto.media
-
-
-##############################################################
-#
-# Verify that "/etc/init.d/autofs start|restart|stop|status|reload"
-# command works.
-#
-# If fails, cleanup and exit.
-#
-##############################################################
-
-/etc/init.d/autofs start
-if [ $? != 0 ]
-then
- rm -rf /etc/auto.master /etc/auto.media /AUTOFS
- echo "FAILED: "/etc/init.d/autofs start""
- exit 1
-fi
-echo "Resuming test, please wait..."
-sleep 15
-
-/etc/init.d/autofs stop
-if [ $? != 0 ]
-then
- rm -rf /etc/auto.master /etc/auto.media /AUTOFS
- echo "FAILED: "/etc/init.d/autofs stop""
- exit 1
-else
- /etc/init.d/autofs start
-fi
-echo "Resuming test, please wait..."
-sleep 15
-
-/etc/init.d/autofs restart
-if [ $? != 0 ]
-then
- /etc/init.d/autofs stop
- rm -rf /etc/auto.master /etc/auto.media /AUTOFS
- echo "FAILED: "/etc/init.d/autofs restart""
- exit 1
-fi
-echo "Resuming test, please wait..."
-sleep 15
-
-/etc/init.d/autofs status
-if [ $? != 0 ]
-then
- /etc/init.d/autofs stop
- rm -rf /etc/auto.master /etc/auto.media /AUTOFS
- echo "FAILED: "/etc/init.d/autofs status""
- exit 1
-fi
-
-/etc/init.d/autofs reload
-if [ $? != 0 ]
-then
- /etc/init.d/autofs stop
- rm -rf /etc/auto.master /etc/auto.media /AUTOFS
- echo "FAILED: "/etc/init.d/autofs reload""
- exit 1
-fi
-
-
-##############################################################
-#
-# Tryout some error code paths by:
-# (1) Write into automount directory
-# (2) Remove automount parent directory
-# (3) Automount the floppy disk
-# (4) Hit automounter timeout by sleep 60; then wakeup with error
-# condition.
-#
-##############################################################
-
-echo "forcing error paths and conditions..."
-
-mkdir /AUTOFS/MEDIA/mydir >/dev/null 2>&1
-rm -rf /AUTOFS >/dev/null 2>&1
-
-mkdir /AUTOFS/MEDIA/floppy/test
-cp /etc/auto.master /etc/auto.media /AUTOFS/MEDIA/floppy/test
-sync; sync
-echo "Resuming test, please wait..."
-sleep 60
-mkdir /AUTOFS/MEDIA/mydir >/dev/null 2>&1
-rm -rf /AUTOFS >/dev/null 2>&1
-
-
-##############################################################
-#
-# Add an entry to the /etc/auto.master and reload.
-#
-##############################################################
-
-echo "/AUTOFS/DISK /etc/auto.disk" >> /etc/auto.master
-echo "disk -fstype=auto,rw,sync :$disk_partition " > /etc/auto.disk
-/etc/init.d/autofs reload
-echo "Resuming test, please wait..."
-sleep 30
-
-
-
-mkdir /AUTOFS/DISK/disk/test
-cp /etc/auto.master /etc/auto.media /AUTOFS/DISK/disk/test
-sync; sync
-echo "Resuming test, please wait..."
-sleep 60
-
-
-if [ -e /AUTOFS/DISK/disk/test ]; then
- cd /AUTOFS/DISK/disk/test
- umount /AUTOFS/DISK/disk/ >/dev/null 2>&1
- if [ $? = 0 ]
- then
- /etc/init.d/autofs stop
- rm -rf /etc/auto.master /etc/auto.media /etc/auto.disk /AUTOFS
- echo "FAILED: unmounted a busy file system!"
- exit 1
- fi
- cd
- umount /AUTOFS/DISK/disk/
-if [ $? != 0 ]
- then
- /etc/init.d/autofs stop
- rm -rf /etc/auto.master /etc/auto.media /etc/auto.disk /AUTOFS
- echo "FAILED: Could not unmount automounted file system"
- exit 1
- fi
-fi
-#
-# Mount the disk partition somewhere else and then reference automount
-# point for disk partition.
-#
-mount -t ext2 $disk_partition /mnt/
-ls -l /AUTOFS/DISK/disk
-umount /mnt
-
-
-#######################################################
-#
-# Just before exit, stop autofs and cleanup.
-#
-#######################################################
-
-/etc/init.d/autofs stop
-rm -rf /etc/auto.master /etc/auto.media /etc/auto.disk /AUTOFS
-echo "PASSED: $0 passed!"
-exit 0
diff --git a/testscripts/autofs4.sh b/testscripts/autofs4.sh
deleted file mode 100755
index 00119a604..000000000
--- a/testscripts/autofs4.sh
+++ /dev/null
@@ -1,259 +0,0 @@
-#!/bin/bash
-
-
-##############################################################
-#
-# Copyright (c) International Business Machines Corp., 2003
-#
-# 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
-#
-# FILE : autofs4.sh
-# USAGE : autofs4.sh <disk_partition>
-#
-# DESCRIPTION : A script that will test autofs on Linux system.
-# REQUIREMENTS:
-# 1) System with a floppy device with a floppy disk in it.
-# 2) A spare (scratch) disk partition of 100MB or larger.
-#
-# HISTORY :
-# 06/11/2003 Prakash Narayana (prakashn@us.ibm.com)
-#
-# CODE COVERAGE: 26.8% - fs/autofs4 (Total Coverage)
-#
-# 24.1% - fs/autofs4/expire.c
-# 33.3% - fs/autofs4/init.c
-# 24.0% - fs/autofs4/inode.c
-# 29.9% - fs/autofs4/root.c
-# 0.0% - fs/autofs4/symlink.c
-# 29.1% - fs/autofs4/waitq.c
-#
-##############################################################
-
-
-##############################################################
-#
-# Make sure that uid=root is running this script.
-# Validate the command line argument as a block special device.
-# Make sure that autofs package has been installed.
-# Make sure that autofs module is built into the kernel or loaded.
-#
-##############################################################
-
-if [ $UID != 0 ]
-then
- echo "FAILED: Must have root access to execute this script"
- exit 1
-fi
-
-if [ $# != 1 ]
-then
- echo "FAILED: Usage $0 <disk_partition>"
- exit 1
-else
- disk_partition=$1
- if [ ! -b $disk_partition ]
- then
- echo "FAILED: Usage $0 <block special disk_partition>"
- exit 1
- fi
- mkfs -t ext2 $disk_partition >/dev/null 2>&1
-fi
-
-rpm -q -a | grep autofs >/dev/null 2>&1
-if [ $? != 0 ]
-then
- echo "FAILED: autofs package is not installed"
- exit 1
-fi
-
-grep autofs /proc/filesystems >/dev/null 2>&1
-if [ $? != 0 ]
-then
- echo "FAILED: autofs module is not built into the kernel or loaded"
- exit 1
-fi
-
-
-##############################################################
-#
-# Pick the floppy device name from /etc/fstab
-# Format (mkfs -t ext2) the floppy to ext2 file system
-# Create the /etc/auto.master
-# Create the /etc/auto.media
-# Create /AUTOFS directory.
-#
-##############################################################
-
-floppy_dev=`grep floppy /etc/fstab | awk '{print $1}'`
-
-if [ $floppy_dev != "" ]
-then
- /sbin/mkfs -t ext2 $floppy_dev >/dev/null 2>&1
- if [ $? != 0 ]
- then
- echo "FAILED: mkfs -t ext2 $floppy_dev failed"
- exit 1
- fi
-fi
-
-if [ ! -d /AUTOFS ]
-then
- mkdir -m 755 /AUTOFS
-fi
-
-echo "/AUTOFS/MEDIA /etc/auto.media " > /etc/auto.master
-echo "floppy -fstype=ext2 :$floppy_dev" > /etc/auto.media
-
-
-##############################################################
-#
-# Verify that "/etc/init.d/autofs start|restart|stop|status|reload"
-# command works.
-#
-# If fails, cleanup and exit.
-#
-##############################################################
-
-/etc/init.d/autofs start >/dev/null 2>&1
-if [ $? != 0 ]
-then
- rm -rf /etc/auto.master /etc/auto.media /AUTOFS
- echo "FAILED: "/etc/init.d/autofs start""
- exit 1
-fi
-echo "Resuming test, please wait..."
-sleep 15
-
-/etc/init.d/autofs stop >/dev/null 2>&1
-if [ $? != 0 ]
-then
- rm -rf /etc/auto.master /etc/auto.media /AUTOFS
- echo "FAILED: "/etc/init.d/autofs stop""
- exit 1
-else
- /etc/init.d/autofs start >/dev/null 2>&1
-fi
-sleep 15
-
-/etc/init.d/autofs restart >/dev/null 2>&1
-if [ $? != 0 ]
-then
- /etc/init.d/autofs stop >/dev/null 2>&1
- rm -rf /etc/auto.master /etc/auto.media /AUTOFS
- echo "FAILED: "/etc/init.d/autofs restart""
- exit 1
-fi
-echo "Resuming test, please wait..."
-sleep 15
-
-/etc/init.d/autofs status >/dev/null 2>&1
-if [ $? != 0 ]
-then
- /etc/init.d/autofs stop >/dev/null 2>&1
- rm -rf /etc/auto.master /etc/auto.media /AUTOFS
- echo "FAILED: "/etc/init.d/autofs status""
- exit 1
-fi
-
-/etc/init.d/autofs reload >/dev/null 2>&1
-if [ $? != 0 ]
-then
- /etc/init.d/autofs stop >/dev/null 2>&1
- rm -rf /etc/auto.master /etc/auto.media /AUTOFS
- echo "FAILED: "/etc/init.d/autofs reload""
- exit 1
-fi
-
-
-##############################################################
-#
-# Tryout some error code paths by:
-# (1) Write into automount directory
-# (2) Remove automount parent directory
-# (3) Automount the floppy disk
-# (4) Hit automounter timeout by sleep 60; then wakeup with error
-# condition.
-#
-##############################################################
-
-mkdir /AUTOFS/MEDIA/mydir >/dev/null 2>&1
-rm -rf /AUTOFS >/dev/null 2>&1
-
-mkdir /AUTOFS/MEDIA/floppy/test
-cp /etc/auto.master /etc/auto.media /AUTOFS/MEDIA/floppy/test
-sync; sync
-echo "Resuming test, please wait..."
-sleep 60
-mkdir /AUTOFS/MEDIA/mydir >/dev/null 2>&1
-rm -rf /AUTOFS >/dev/null 2>&1
-
-
-##############################################################
-#
-# Add an entry to the /etc/auto.master and reload.
-#
-##############################################################
-
-echo "/AUTOFS/DISK /etc/auto.disk " >> /etc/auto.master
-echo "disk -fstype=ext2 :$disk_partition " > /etc/auto.disk
-/etc/init.d/autofs reload >/dev/null 2>&1
-echo "Resuming test, please wait..."
-sleep 30
-
-mkdir /AUTOFS/DISK/disk/test
-cp /etc/auto.master /etc/auto.media /AUTOFS/DISK/disk/test
-sync; sync
-echo "Resuming test, please wait..."
-sleep 60
-
-cd /AUTOFS/DISK/disk/test
-umount /AUTOFS/DISK/disk/ >/dev/null 2>&1
-if [ $? = 0 ]
-then
- /etc/init.d/autofs stop >/dev/null 2>&1
- rm -rf /etc/auto.master /etc/auto.media /etc/auto.disk /AUTOFS
- echo "FAILED: unmounted a busy file system!"
- exit 1
-fi
-cd
-
-umount /AUTOFS/DISK/disk/ >/dev/null 2>&1
-if [ $? != 0 ]
-then
- /etc/init.d/autofs stop >/dev/null 2>&1
- rm -rf /etc/auto.master /etc/auto.media /etc/auto.disk /AUTOFS
- echo "FAILED: Could not unmount automounted file system"
- exit 1
-fi
-
-#
-# Mount the disk partition somewhere else and then reference automount
-# point for disk partition.
-#
-mount -t ext2 $disk_partition /mnt/
-ls -l /AUTOFS/DISK/disk
-umount /mnt
-
-
-#######################################################
-#
-# Just before exit, stop autofs and cleanup.
-#
-#######################################################
-
-/etc/init.d/autofs stop >/dev/null 2>&1
-rm -rf /etc/auto.master /etc/auto.media /etc/auto.disk /AUTOFS
-echo "PASSED: $0 passed!"
-exit 0
diff --git a/testscripts/load_stress_all_kernel_modules.sh b/testscripts/load_stress_all_kernel_modules.sh
deleted file mode 100755
index 6e67b154a..000000000
--- a/testscripts/load_stress_all_kernel_modules.sh
+++ /dev/null
@@ -1,35 +0,0 @@
-#!/bin/sh
-################################################################################
-## ##
-## Copyright (c) International Business Machines Corp., 2009 ##
-## ##
-## 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 ##
-## ##
-################################################################################
-# ##
-# File : load_stress_all_kernel_modules.sh ##
-# ##
-# Description: Try to load all the modules present in the system, installed ##
-# both during Distro installation, or, custom kernel build. ##
-# ##
-# Author: Subrata Modak <subrata@linux.vnet.ibm.com> ##
-################################################################################
-
-for module in `modprobe -l | tr '\n' ' '`
- do
- insert_module=`basename $module .ko`
- modprobe -v $insert_module
-done
-
diff --git a/testscripts/ltp-scsi_debug.sh b/testscripts/ltp-scsi_debug.sh
deleted file mode 100755
index 37853002e..000000000
--- a/testscripts/ltp-scsi_debug.sh
+++ /dev/null
@@ -1,218 +0,0 @@
-#!/bin/bash
-
-# Check if scsi_debug module was built or not
-export kernel=$(uname -r)
-
-ls /lib/modules/$kernel/kernel/drivers/scsi | grep scsi_debug > /dev/null 2>&1
-if [ $? -ne 0 ];
-then
- echo "scsi_debug was not built in the kernel as a module"
- echo "Build scsi_debug as a module first before running the test"
-fi
-
-# Unload scsi_debug moudle if it was already loaded:
-lsmod | grep scsi_debug > /dev/null 2>&1
-if [ $? -eq 0 ];
-then
- echo "The scsi_debug module was already loaded, unload it before test..."
- rmmod -f scsi_debug
-fi
-lsmod | grep scsi_debug > /dev/null 2>&1
-if [ $? -eq 0 ];
-then
- echo "The scsi_debug module was not unloaded - unload error"
-else
- echo "The scsi_debug module was unloaded successfully"
- echo "start testing..."
-fi
-
-orig_count=$(cat /proc/partitions | wc -l)
-
-echo " Load the scsi_debug module..."
-modprobe scsi_debug
-if [ $? -ne 0 ];
-then
- echo "Can't load scsi_debug modules"
- exit
-fi
-
-echo "Check if scsi_debug was loaded..."
-lsmod | grep scsi_debug > /dev/null 2>&1
-if [ $? -eq 0 ];
-then
- echo "scsi_debug module was loaded successfully"
-else
- echo "scsi_debug module was not loaded"
- exit
-fi
-
-
-echo "Remove the scsi_debug device..."
-dev_name=$(ls /proc/scsi/scsi_debug)
-# echo $dev_name
-rm_dev=$dev_name:0:0:0
-# echo $rm_dev
-echo 1 > /sys/class/scsi_device/$rm_dev/device/delete
-
-echo "Check if the scsi_debug device was removed..."
-ls /sys/class/scsi_device | grep $rm_dev > /dev/null 2>&1
-if [ $? -eq 0 ];
-then
- echo "The device was not removed - remove error"
-else
- echo "The device $dev_name was removed successfully"
-fi
-
-echo "Add the device back..."
-echo "0 0 0" > /sys/class/scsi_host/host$dev_name/scan
-ls /sys/class/scsi_device | grep $rm_dev > /dev/null 2>&1
-if [ $? -ne 0 ];
-then
- echo "The device was not added - add device error"
-else
- echo "The device $dev_name was added back successfully"
-fi
-
-echo "Add a new host..."
-echo 1 > /sys/bus/pseudo/drivers/scsi_debug/add_host
-num_host=$(cat /sys/bus/pseudo/drivers/scsi_debug/add_host)
-if [ $num_host -ne 2 ];
-then
- echo "The new host was not added - add host error"
-else
- echo "The new host was added successfully"
-fi
-
-echo "Romove hosts..."
-echo -2 > /sys/bus/pseudo/drivers/scsi_debug/add_host
-num_host=$(cat /sys/bus/pseudo/drivers/scsi_debug/add_host)
-if [ $num_host -ne 0 ];
-then
- echo "The hosts were not removed - remove hosts error"
-else
- echo "The hosts were removed successfully"
-fi
-
-echo "Unload scsi_debug moudle..."
-rmmod -f scsi_debug
-lsmod | grep scsi_debug > /dev/null 2>&1
-if [ $? -eq 0 ];
-then
- echo "The scsi_debug module was not unloaded - unload error"
-else
- echo "The scsi_debug module was unloaded successfully"
-fi
-
-echo "Load scsi_debug with multiple hosts..."
-modprobe scsi_debug max_luns=2 num_tgts=2 add_host=2 dev_size_mb=20
-lsmod | grep scsi_debug > /dev/null 2>&1
-if [ $? -eq 0 ];
-then
- echo "The multiple scsi_debug modules were loaded successfully"
-else
- echo "The multiple scsi_debug modules were not loaded - load error"
-fi
-
-echo "Check if modules were loaded as required by premeters..."
-max_luns=$(cat /sys/bus/pseudo/drivers/scsi_debug/max_luns)
-add_host=$(cat /sys/bus/pseudo/drivers/scsi_debug/add_host)
-num_tgts=$(cat /sys/bus/pseudo/drivers/scsi_debug/num_tgts)
-# echo "max_lunx is $max_luns"
-# echo "add_host is $add_host"
-# echo "num_tgts is $num_tgts"
-
-premeter_err_ct=0;
-
-if [ $max_luns -ne 2 ];
-then
- echo "max_luns was not correct"
- premeter_err_ct=$premeter_err_ct+1;
-fi
-if [ $add_host -ne 2 ];
-then
- echo "add_host was not correct"
- premeter_err_ct=$premeter_err_ct+1;
-fi
-if [ $num_tgts -ne 2 ];
-then
- echo "num_tgts was not correct"
- premeter_err_ct=$premeter_err_ct+1;
-fi
-if [ $premeter_err_ct -eq 0 ];
-then
- echo "multiple scsi_debug was loaded as required premeters"
-else
- echo "multip.e scsi_debug was not loaded as required premeters"
-fi
-echo "scsi_debug first part of test has been done."
-
-echo "Now we are doing fs test for scsi_debug driver..."
-
-cd `dirname $0`
-export LTPROOT=${PWD}
-echo $LTPROOT | grep testscripts > /dev/null 2>&1
-if [ $? -eq 0 ]; then
- cd ..
- export LTPROOT=${PWD}
-fi
-
-export TMPBASE="/tmp"
-
-# check if the newly created scsi_debug partitions are in /proc/partitions file
-check_count=$(cat /proc/partitions | wc -l)
-save_count=$(( $check_count - $orig_count ))
-if [ $save_count -lt 4 ]; then
- echo "Not enough scsi_debug partitions to run the test"
- exit
-fi
-
-# Get the 4 partitions created by scsi_debug for testing
-cat /proc/partitions | awk '{print $4}' | tail -n 4 > $TMPBASE/partition-test
-echo "The 4 partitions used to run the test are:"
-part1=$(cat $TMPBASE/partition-test | tail -n 1)
-echo $part1
-part2=$(cat $TMPBASE/partition-test | head -n 3 | tail -n 1)
-echo $part2
-part3=$(cat $TMPBASE/partition-test | head -n 2 | tail -n 1)
-echo $part3
-part4=$(cat $TMPBASE/partition-test | head -n 1)
-echo $part4
-
-export PATH="${PATH}:${LTPROOT}/testcases/bin"
-
-mkdir /test >/dev/null 2>&1
-mkdir /test/growfiles >/dev/null 2>&1
-mkdir /test/growfiles/ext2 >/dev/null 2>&1
-mkdir /test/growfiles/ext3 >/dev/null 2>&1
-mkdir /test/growfiles/reiser >/dev/null 2>&1
-mkdir /test/growfiles/msdos >/dev/null 2>&1
-
-echo "----- make ext3 fs -----"
-mkfs -V -t ext3 /dev/$part1
-echo "----- make ext2 fs -----"
-mkfs -V -t ext2 /dev/$part2
-echo "----- make reiserfs fs -----"
-mkreiserfs -f /dev/$part3
-echo "----- make msdos fs -----"
-mkfs -V -t msdos -I /dev/$part4
-
-echo "----- Mount partitions -----"
-mount /dev/$part1 /test/growfiles/ext3
-mount /dev/$part2 /test/growfiles/ext2
-mount /dev/$part3 /test/growfiles/reiser
-mount /dev/$part4 /test/growfiles/msdos
-
-echo "----- Running tests ----- "
-echo "The test may take about 2 hours to finish..."
-sort -R ${LTPROOT}/runtest/scsi_debug.part1 -o ${TMPBASE}/scsi_debug
-
-${LTPROOT}/bin/ltp-pan -e -S -a scsi_debug -n scsi_debug -l ${TMPBASE}/fs-scsi_debug.log -o ${TMPBASE}/fs-scsi_debug.out -f ${TMPBASE}/scsi_debug
-
-wait $!
-
-umount -v /dev/$part1
-umount -v /dev/$part2
-umount -v /dev/$part3
-umount -v /dev/$part4
-
-echo "Look into /tmp/fs-scsi_debug.log and /tmp/fs-scsi_debug.out for detail results..."
diff --git a/testscripts/ltpdmmapper.sh b/testscripts/ltpdmmapper.sh
deleted file mode 100755
index f49e59626..000000000
--- a/testscripts/ltpdmmapper.sh
+++ /dev/null
@@ -1,204 +0,0 @@
-#!/bin/sh
-# This script should be run prior to running executing the filesystem tests.
-# valid devices need to be passed for Device Mapper to work correctly
-# 03/14/03 mridge@us.ibm.com added instance and time command line options
-
-cd `dirname $0`
-export LTPROOT=${PWD}
-echo $LTPROOT | grep testscripts > /dev/null 2>&1
-if [ $? -eq 0 ]; then
- cd ..
- export LTPROOT=${PWD}
-fi
-
-export TMPBASE="/tmp"
-
-
-usage()
-{
- cat <<-END >&2
- usage: ${0##*/} [ -a part1 ] [ -b part2 ]
-
- Note: In order to run this test, you must turn on "device mapper"
- component in kernel (it is under device drivers item when you
- run make menuconfig); and you must install userspace supporting
- files (libdevmapper and dmsetup). They are in the device-mapper
- package. You can download it from http://www.sistina.com. Follow
- the README/INSTALL file within the package to install it.
-
-
- defaults:
- part1=$part1
- part2=$part2
- ltproot=$LTPROOT
- tmpdir=$TMPBASE
-
- example: ${0##*/} -a hdc1 -b hdc2
-
-
- END
-exit
-}
-
-while getopts :a:b: arg
-do case $arg in
- a) part1=$OPTARG;;
- b) part2=$OPTARG;;
-
- \?) echo "************** Help Info: ********************"
- usage;;
- esac
-done
-
-if [ ! -n "$part1" ]; then
- echo "Missing 1st partition. You must pass 2 partitions for testing"
- usage;
- exit
-fi
-
-if [ ! -n "$part2" ]; then
- echo "Missing 2nd partition. You must pass 2 partitions for testing"
- usage;
- exit
-fi
-
-echo "Starting Device Mapper Tests..."
-
-echo "0 10240 linear " $part1 "0" > ltp-dev-mapper-table1
-echo "0 100000 linear " $part1 "0" > ltp-dev-mapper-table2
-echo "0 100000 linear " $part2 "0" > ltp-dev-mapper-table3
-echo "0 200000 striped 2 16 " $part1 "0" $part2 "0" > ltp-dev-mapper-table4
-
-echo "Creating Devices..."
-
-dmsetup create dm-test-1 ltp-dev-mapper-table1
-dmsetup create dm-test-2 ltp-dev-mapper-table2
-dmsetup create dm-test-3 ltp-dev-mapper-table3
-dmsetup create dm-test-4 ltp-dev-mapper-table4
-
-echo "Device Info..."
-
-dmsetup info dm-test-1
-dmsetup info dm-test-2
-dmsetup info dm-test-3
-dmsetup info dm-test-4
-
-echo "Device Dependancies..."
-
-dmsetup deps dm-test-1
-dmsetup deps dm-test-2
-dmsetup deps dm-test-3
-dmsetup deps dm-test-4
-
-echo "Device Status..."
-
-dmsetup status dm-test-1
-dmsetup status dm-test-2
-dmsetup status dm-test-3
-dmsetup status dm-test-4
-
-echo "Device Tables..."
-
-dmsetup table dm-test-1
-dmsetup table dm-test-2
-dmsetup table dm-test-3
-dmsetup table dm-test-4
-
-echo "Device Mapper Version..."
-
-dmsetup version
-
-echo "Device Waiting..."
-
-#dmsetup wait dm-test-1
-#dmsetup wait dm-test-2
-#dmsetup wait dm-test-3
-#dmsetup wait dm-test-4
-
-echo "Device Mapper Removing Devices..."
-
-dmsetup remove dm-test-1
-dmsetup remove dm-test-2
-dmsetup remove dm-test-3
-dmsetup remove dm-test-4
-
-echo "Device Mapper Re-Creating Devices..."
-
-dmsetup create dm-test-1 ltp-dev-mapper-table1
-dmsetup create dm-test-2 ltp-dev-mapper-table2
-dmsetup create dm-test-3 ltp-dev-mapper-table3
-dmsetup create dm-test-4 ltp-dev-mapper-table4
-
-echo "Re-Naming Devices..."
-
-dmsetup rename dm-test-1 dm-test-1-new
-dmsetup rename dm-test-2 dm-test-2-new
-dmsetup rename dm-test-3 dm-test-3-new
-dmsetup rename dm-test-4 dm-test-4-new
-
-echo "Suspend Devices..."
-
-dmsetup suspend dm-test-1-new
-dmsetup suspend dm-test-2-new
-dmsetup suspend dm-test-3-new
-dmsetup suspend dm-test-4-new
-
-echo "0 102400 linear " $part1 "0" > ltp-dev-mapper-table1
-echo "0 200000 linear " $part1 "0" > ltp-dev-mapper-table2
-echo "0 200000 linear " $part2 "0" > ltp-dev-mapper-table3
-echo "0 400000 striped 2 16 " $part1 "0" $part2 "0" > ltp-dev-mapper-table4
-
-echo "Re-loading Devices..."
-
-dmsetup reload dm-test-1-new ltp-dev-mapper-table1
-dmsetup reload dm-test-2-new ltp-dev-mapper-table2
-dmsetup reload dm-test-3-new ltp-dev-mapper-table3
-dmsetup reload dm-test-4-new ltp-dev-mapper-table4
-
-echo "Resuming Devices..."
-
-dmsetup resume dm-test-1-new
-dmsetup resume dm-test-2-new
-dmsetup resume dm-test-3-new
-dmsetup resume dm-test-4-new
-
-echo "Device Info..."
-
-dmsetup info dm-test-1-new
-dmsetup info dm-test-2-new
-dmsetup info dm-test-3-new
-dmsetup info dm-test-4-new
-
-echo "Device Dependancies..."
-
-dmsetup deps dm-test-1-new
-dmsetup deps dm-test-2-new
-dmsetup deps dm-test-3-new
-dmsetup deps dm-test-4-new
-
-echo "Device Status..."
-
-dmsetup status dm-test-1-new
-dmsetup status dm-test-2-new
-dmsetup status dm-test-3-new
-dmsetup status dm-test-4-new
-
-echo "Device Tables..."
-
-dmsetup table dm-test-1-new
-dmsetup table dm-test-2-new
-dmsetup table dm-test-3-new
-dmsetup table dm-test-4-new
-
-echo "Device Mapper Remove-all..."
-
-dmsetup remove_all
-
-echo "Device Mapper Checking Status - Shouldn't be anything to check"
-
-dmsetup status dm-test-1-new
-dmsetup status dm-test-2-new
-dmsetup status dm-test-3-new
-dmsetup status dm-test-4-new
-
-
diff --git a/testscripts/sysfs.sh b/testscripts/sysfs.sh
deleted file mode 100755
index e22f36fa2..000000000
--- a/testscripts/sysfs.sh
+++ /dev/null
@@ -1,121 +0,0 @@
-#!/bin/bash
-
-
-##############################################################
-#
-# Copyright (c) International Business Machines Corp., 2003
-#
-# 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
-#
-# FILE : sysfs.sh
-# USAGE : sysfs.sh [ -k <kernel_module> ]
-#
-# DESCRIPTION : A script that will test sysfs on Linux system.
-# REQUIREMENTS: CONFIG_DUMMY must have been used to build kernel, and the
-# dummy network module must exist.
-#
-# HISTORY :
-# 06/24/2003 Prakash Narayana (prakashn@us.ibm.com)
-#
-# CODE COVERAGE: 31.3% - fs/sysfs (Total Coverage)
-#
-# 0.0% - fs/sysfs/bin.c
-# 61.8% - fs/sysfs/dir.c
-# 27.5% - fs/sysfs/file.c
-# 40.4% - fs/sysfs/inode.c
-# 41.2% - fs/sysfs/mount.c
-# 58.1% - fs/sysfs/symlink.c
-#
-##############################################################
-
-
-MNT_POINT="/tmp/sysfs_$$"
-
-KERNEL_NAME=`uname -a | awk ' { print $3 } '`
-KERN_MODULE=/lib/modules/$KERNEL_NAME/kernel/drivers/net/dummy.ko
-USAGE="$0 [ -k <kernel_module> ]"
-
-
-##############################################################
-#
-# Make sure that uid=root is running this script.
-# Validate the command line arguments.
-#
-##############################################################
-
-if [ $UID != 0 ]
-then
- echo "FAILED: Must have root access to execute this script"
- exit 1
-fi
-
-while getopts k: args
-do
- case $args in
- k) KERN_MODULE=$OPTARG ;;
- \?) echo $USAGE ; exit 1 ;;
- esac
-done
-
-if [ -z "$KERN_MODULE" ]
-then
- echo $USAGE
- echo "FAILED: kernel module to insert not specified"
- exit 1
-fi
-
-# Here is the code coverage for fs/sysfs
-# insmod/rmmod net/dummy.ko creates and deletes a directory
-# under sysfs.
-# In kernel, 2.5.73 or higher, insert/delete base/firmware_class.ko
-
-mkdir -p -m 777 $MNT_POINT
-mount -t sysfs sysfs $MNT_POINT
-if [ $? != 0 ]
-then
- echo "FAILED: sysfs mount failed"
- exit 1
-fi
-
-insmod $KERN_MODULE
-if [ $? != 0 ]
-then
- umount $MNT_POINT
- rm -rf $MNT_POINT
- echo "FAILED: insmod failed"
- exit 1
-fi
-
-rmmod $KERN_MODULE
-if [ $? != 0 ]
-then
- umount $MNT_POINT
- rm -rf $MNT_POINT
- echo "FAILED: rmmod failed"
- exit 1
-fi
-
-
-#######################################################
-#
-# Just before exit, perform the cleanup.
-#
-#######################################################
-
-umount $MNT_POINT
-rm -rf $MNT_POINT
-
-echo "PASSED: $0 passed!"
-exit 0
diff --git a/tools/create-tarballs-metadata.sh b/tools/create-tarballs-metadata.sh
index e7f93d5c0..d0b9d0d97 100755
--- a/tools/create-tarballs-metadata.sh
+++ b/tools/create-tarballs-metadata.sh
@@ -1,17 +1,18 @@
-#!/bin/sh
+#!/bin/sh -eu
+# SPDX-License-Identifier: GPL-2.0-or-later
# Copyright (c) 2023 Petr Vorel <pvorel@suse.cz>
# Create tarballs and metadata for uploading after tagging release.
# https://github.com/linux-test-project/ltp/wiki/LTP-Release-Procedure
-set -e
+
+basedir="$(dirname "$0")"
+. "$basedir/lib.sh"
tag="$(date +%Y%m%d)"
tarball_dir="ltp-full-$tag"
extensions="bz2 xz"
checksums="md5 sha1 sha256"
-git_dir=$(cd $(dirname "$0")/..; pwd)
-dir="$(cd $git_dir/../; pwd)/ltp-release-$tag"
-
-. $(dirname "$0")/lib.sh
+git_dir=$(cd "$basedir/.."; pwd)
+dir="$(cd "$git_dir/../"; pwd)/ltp-release-$tag"
if [ -d $dir ]; then
ask "Directory '$dir' exists, will be deleted"
diff --git a/tools/create_dmesg_entries_for_each_test.awk b/tools/create_dmesg_entries_for_each_test.awk
index 25d750a55..ffd807fb4 100644
--- a/tools/create_dmesg_entries_for_each_test.awk
+++ b/tools/create_dmesg_entries_for_each_test.awk
@@ -27,6 +27,7 @@ NF && ! /^#/ {
for (i = 2; i <= NF; i++) {
s = s " " $i
}
+ sub(/[;]+$/, "", s)
s = s "; dmesg > " DMESG_DIR "/" $1 ".dmesg.log"
print s
}
diff --git a/tools/kirk b/tools/kirk
deleted file mode 160000
-Subproject 7e397fe1a2d34a100c7dbfa452bd5d86ca1ddb7
diff --git a/tools/ltx/ltx-src b/tools/ltx/ltx-src
deleted file mode 160000
-Subproject d6d1509479537f4fdfa9b5adcb67eb631271499
diff --git a/tools/tag-release.sh b/tools/tag-release.sh
index 2967c7b4d..b639efb25 100755
--- a/tools/tag-release.sh
+++ b/tools/tag-release.sh
@@ -1,18 +1,18 @@
-#!/bin/sh
+#!/bin/sh -eu
+# SPDX-License-Identifier: GPL-2.0-or-later
# Copyright (c) 2023 Petr Vorel <pvorel@suse.cz>
# Tag LTP release.
# https://github.com/linux-test-project/ltp/wiki/LTP-Release-Procedure
-set -e
+
+basedir="$(dirname "$0")"
+cd "$basedir/.."
+. "$basedir/lib.sh"
upstream_git="linux-test-project/ltp"
tag="$(date +%Y%m%d)"
old_tag="$(git describe --abbrev=0)"
tag_msg="LTP $tag"
-. $(dirname "$0")/lib.sh
-
-cd $(dirname "$0")/..
-
if ! git ls-remote --get-url origin | grep -q $upstream_git; then
quit "Not an upstream project"
fi