aboutsummaryrefslogtreecommitdiff
path: root/testcases/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'testcases/kernel')
-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
269 files changed, 4189 insertions, 19331 deletions
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