diff -Nru stress-ng-0.11.19/core-cache.c stress-ng-0.11.21/core-cache.c --- stress-ng-0.11.19/core-cache.c 2020-08-24 14:14:41.000000000 +0000 +++ stress-ng-0.11.21/core-cache.c 2020-09-16 22:00:11.000000000 +0000 @@ -185,29 +185,29 @@ goto out; } - (void)snprintf(path, sizeof(path), "%s/type", index_path); + (void)stress_mk_filename(path, sizeof(path), index_path, "type"); if (stress_get_string_from_file(path, tmp, sizeof(tmp)) < 0) goto out; cache->type = (stress_cache_type_t)stress_get_cache_type(tmp); if (cache->type == CACHE_TYPE_UNKNOWN) goto out; - (void)snprintf(path, sizeof(path), "%s/size", index_path); + (void)stress_mk_filename(path, sizeof(path), index_path, "size"); if (stress_get_string_from_file(path, tmp, sizeof(tmp)) < 0) goto out; cache->size = stress_size_to_bytes(tmp); - (void)snprintf(path, sizeof(path), "%s/level", index_path); + (void)stress_mk_filename(path, sizeof(path), index_path, "level"); if (stress_get_string_from_file(path, tmp, sizeof(tmp)) < 0) goto out; cache->level = (uint16_t)atoi(tmp); - (void)snprintf(path, sizeof(path), "%s/coherency_line_size", index_path); + (void)stress_mk_filename(path, sizeof(path), index_path, "coherency_line_size"); if (stress_get_string_from_file(path, tmp, sizeof(tmp)) < 0) goto out; cache->line_size = (uint32_t)atoi(tmp); - (void)snprintf(path, sizeof(path), "%s/ways_of_associativity", index_path); + (void)stress_mk_filename(path, sizeof(path), index_path, "ways_of_associativity"); if (stress_get_string_from_file(path, tmp, sizeof(tmp)) < 0) cache->ways = atoi(tmp); else @@ -330,7 +330,7 @@ return ret; } - (void)snprintf(path, sizeof(path), "%s/%s", cpu_path, SYS_CPU_CACHE_DIR); + (void)stress_mk_filename(path, sizeof(path), cpu_path, SYS_CPU_CACHE_DIR); n = scandir(path, &namelist, NULL, alphasort); if (n < 0) { /* @@ -368,7 +368,7 @@ char fullpath[strlen(path) + strlen(name) + 2]; (void)memset(fullpath, 0, sizeof(fullpath)); - (void)snprintf(fullpath, sizeof(fullpath), "%s/%s", path, name); + (void)stress_mk_filename(fullpath, sizeof(fullpath), path, name); if (stress_add_cpu_cache_detail(&cpu->caches[j++], fullpath) != EXIT_SUCCESS) goto err; } @@ -429,7 +429,7 @@ stress_cpu_t *const cpu = &cpus->cpus[j]; (void)memset(fullpath, 0, sizeof(fullpath)); - (void)snprintf(fullpath, sizeof(fullpath), "%s/%s", SYS_CPU_PREFIX, name); + (void)stress_mk_filename(fullpath, sizeof(fullpath), SYS_CPU_PREFIX, name); cpu->num = j; if (j == 0) { /* 1st CPU cannot be taken offline */ diff -Nru stress-ng-0.11.19/core-helper.c stress-ng-0.11.21/core-helper.c --- stress-ng-0.11.19/core-helper.c 2020-08-24 14:14:41.000000000 +0000 +++ stress-ng-0.11.21/core-helper.c 2020-09-16 22:00:11.000000000 +0000 @@ -168,6 +168,26 @@ static const char *stress_temp_path = "."; /* + * stress_mk_filename() + * generate a full file name from a path and filename + */ +size_t stress_mk_filename( + char *fullname, + const size_t fullname_len, + const char *pathname, + const char *filename) +{ + /* + * This may not be efficient, but it works. Do not + * be tempted to optimize this, it is not used frequently + * and is not a CPU bottleneck. + */ + (void)shim_strlcpy(fullname, pathname, fullname_len); + (void)shim_strlcat(fullname, "/", fullname_len); + return shim_strlcat(fullname, filename, fullname_len); +} + +/* * stress_get_pagesize() * get pagesize */ @@ -1906,3 +1926,44 @@ return -1; } #endif + +/* + * stress_read_buffer() + * In addition to read() this function makes sure all bytes have been + * written. You're also able to ignore EINTR interrupts which could happen + * on alarm() in the parent process. + */ +ssize_t stress_read_buffer(int fd, void* buffer, ssize_t size, bool ignore_int) { + ssize_t rbytes=0, ret; + do { +ignore_eintr: + ret = read(fd, (buffer) + rbytes, size - rbytes); + if (ignore_int && ret < 0 && errno == EINTR) + goto ignore_eintr; + if (ret > 0) + rbytes += ret; + } while (ret > 0 && rbytes != size); + pr_dbg_v("stress_read_buffer: size=%ld read=%ld sz2=%ld\n", size, rbytes, ret); + return (ret <= 0)? ret:rbytes; +} + +/* + * stress_write_buffer() + * In addition to write() this function makes sure all bytes have been + * written. You're also able to ignore EINTR interrupts which could happen + * on alarm() in the parent process. + */ +ssize_t stress_write_buffer(int fd, void* buffer, ssize_t size, bool ignore_int) { + ssize_t wbytes=0, ret; + do { +ignore_eintr: + ret = write(fd, (buffer) + wbytes, size - wbytes); + /* retry if interrupted */ + if (ignore_int && ret < 0 && errno == EINTR) + goto ignore_eintr; + if (ret > 0) + wbytes += ret; + } while (ret > 0 && wbytes != size); + pr_dbg_v("stress_write_buffer: size=%ld written=%ld sz2=%ld\n", size, wbytes, ret); + return (ret <= 0)? ret:wbytes; +} diff -Nru stress-ng-0.11.19/core-io-uring.c stress-ng-0.11.21/core-io-uring.c --- stress-ng-0.11.19/core-io-uring.c 1970-01-01 00:00:00.000000000 +0000 +++ stress-ng-0.11.21/core-io-uring.c 2020-09-16 22:00:11.000000000 +0000 @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2013-2020 Canonical, 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 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. + * + * This code is a complete clean re-write of the stress tool by + * Colin Ian King and attempts to be + * backwardly compatible with the stress tool by Amos Waterland + * but has more stress tests and more + * functionality. + * + */ + +#if defined(__linux__) && \ + defined(HAVE_LINUX_IO_URING_H) +#include +#endif diff -Nru stress-ng-0.11.19/core-out-of-memory.c stress-ng-0.11.21/core-out-of-memory.c --- stress-ng-0.11.19/core-out-of-memory.c 2020-08-24 14:14:41.000000000 +0000 +++ stress-ng-0.11.21/core-out-of-memory.c 2020-09-16 22:00:11.000000000 +0000 @@ -189,6 +189,19 @@ int ooms = 0; int segvs = 0; int buserrs = 0; + size_t signal = 0; + + /* + * Kill child multiple times, start with SIGALRM and work up + */ + static const int signals[] = { + SIGALRM, + SIGALRM, + SIGALRM, + SIGALRM, + SIGTERM, + SIGKILL + }; again: if (!keep_stressing()) @@ -206,14 +219,25 @@ int status, ret; (void)setpgid(pid, g_pgrp); + +rewait: ret = waitpid(pid, &status, 0); if (ret < 0) { + /* No longer alive? */ + if (errno == ECHILD) + goto report; if (errno != EINTR) pr_dbg("%s: waitpid(): errno=%d (%s)\n", args->name, errno, strerror(errno)); - (void)kill(pid, SIGTERM); - (void)kill(pid, SIGKILL); - (void)waitpid(pid, &status, 0); + + (void)kill(pid, signals[signal]); + if (signal < SIZEOF_ARRAY(signals)) + signal++; + else + goto report; + + shim_usleep(500000); + goto rewait; } else if (WIFSIGNALED(status)) { pr_dbg("%s: child died: %s (instance %d)\n", args->name, stress_strsignal(WTERMSIG(status)), @@ -225,7 +249,7 @@ } /* If we got killed by OOM killer, re-start */ - if (WTERMSIG(status) == SIGKILL) { + if ((signals[signal] != SIGKILL) && (WTERMSIG(status) == SIGKILL)) { /* * The --oomable flag was enabled, so * the behaviour here is to no longer @@ -278,6 +302,8 @@ } _exit(func(args, context)); } + +report: if (ooms + segvs + buserrs > 0) pr_dbg("%s: OOM restarts: %d" ", SIGSEGV restarts: %d" diff -Nru stress-ng-0.11.19/core-personality.c stress-ng-0.11.21/core-personality.c --- stress-ng-0.11.19/core-personality.c 2020-08-24 14:14:41.000000000 +0000 +++ stress-ng-0.11.21/core-personality.c 2020-09-16 22:00:11.000000000 +0000 @@ -23,8 +23,7 @@ * */ -#include "stress-ng.h" - -#if defined(__linux__) +#if defined(__linux__) && \ + defined(HAVE_SYS_PERSONALITY_H) #include #endif diff -Nru stress-ng-0.11.19/core-shim.c stress-ng-0.11.21/core-shim.c --- stress-ng-0.11.19/core-shim.c 2020-08-24 14:14:41.000000000 +0000 +++ stress-ng-0.11.21/core-shim.c 2020-09-16 22:00:11.000000000 +0000 @@ -1765,3 +1765,17 @@ return (int)shim_enosys(0, tv, tz); #endif } + +/* + * shim_close_range() + * wrapper for close_range - close a range of + * file descriptors + */ +int shim_close_range(unsigned int fd, unsigned int max_fd) +{ +#if defined(__NR_close_range) + return (int)syscall(__NR_close_range, fd, max_fd); +#else + return (int)shim_enosys(0, fd, max_fd); +#endif +} diff -Nru stress-ng-0.11.19/debian/changelog stress-ng-0.11.21/debian/changelog --- stress-ng-0.11.19/debian/changelog 2020-08-24 14:13:11.000000000 +0000 +++ stress-ng-0.11.21/debian/changelog 2020-09-16 21:58:21.000000000 +0000 @@ -1,3 +1,160 @@ +stress-ng (0.11.21-1) unstable; urgency=medium + + [Colin Ian King] + * Makefile: bump version + * Manual: update date + * stress-unshare: don't report ENOSPC as a failure in the unshare + * Makefile: remove personality info, it is distracting + * stress-clock: fix build warnings BSD systems + * Makefile: remove -DHAVE_LINUX_IO_URING_H, it was included for testing + * stress-dev: fix build warnings on non-Linux platforms + * stress-dev: fix build error on non-linux systems with Xen guest + checking + * README: update number of stress tests + * stress-dirdeep: add post recursion yield point check + * stress-io-uring: add built-time checking for io-uring opcode enums + * Makefile: provide personality build information + * Makefile: make core first to keep order alphabetic + * stress-io-uring: exercise NOP and FSYNC IO opcodes + * stress-sysfs: skip over gcov sysfs debug files + * stress-dirdeep: declare dirfd when HAVE_LINKAT is also defined + * stress-dirdeep: exercise linkat in a few different ways + * stress-clock: add build time check for TIMER_ABSTIME + * core-helper: use shim strl* functions + * stress-eventfd: remove { } for one line block statement + * stress-eventfd: perform illegal writes periodically + * stress-unshare: add in missing empty line + * stress-io-uring: reap resources at end of test, exercise fdinfo + * stress-io-uring: remove CLASS_INTERRUPT from stressor classes + * Add stress_mk_filename to make a filename from full path and name + * stress-inotify: fix build warning + * io-uring: fix help, it was cut-n-pasted from io async stressor + * Add io-uring stressor to exercise io-uring system calls + * stress-inotify: some minor code style changes, no functional changes + * stress-inotify: optimization: get bad fd just once + * stress-inotify: fix build failures on systems without IN_MASK_CREATE + and IN_MASK_ADD + * stress-shm-sysv: exercise SYSV namespace objects + * stress-sem-sysv: remove busy loop, replace it with pause + * stress-sem: remove busy loop, replace it with pause + * stress-fanotify: fix build warning on declaration of bad_fd + * stress-fanotify: fix build failure with systems where FAN_MARK_INODE + is not defined + * stress-fanotify: fix name shadowing on function parameter mnts + * stress-timerfd: fix shadowing of variable ret + * stress-close: fix variable shadowing of ret + * stress-dev: add some device timeouts on slow optical devices + * stress-fallocate: remove some whitespaces/lines + * stress-fallocate: exercise illegal offset and lengths + * stress-fallocate: exercise illegal fallocate on a pipe + * stress-fallocate: add a blank line + * stress-fallocate: exercise some illegal modes + * stress-dev: allow hpet checking if not a Xen guest + * stress-timerfd: fix check of CLOCK_REALTIME_ALARM + + [Piyush Goyal] + * stress-schedpolicy: exercise invalid sched_getattr syscalls + * stress-timer:exercise nanosleep on invalid timespec + * stress-clock: exercise clock_nanosleep on invalid timespec + * stress-clock: Exercise clock_nanosleep on invalid clock id + * stress-clock: exercise clock_adjtime on invalid clock id + * stress-eventfd: exercise illegal writes on event fd + * stress-eventfd: initialise the value written in event fd + * stress-eventfd: read from event fd on a small buffer + * stress-eventfd: exercise eventfd with invalid flags + * Makefile.config: add build time check for epoll_create + * stress-inotify: exercise inotify_rm_watch on non-inotify fd + * stress-inotify: exercise inotify_rm_watch on invalid wd + * stress-inotify: exercise inotify_rm_watch on bad fd + * stress-inotify: Exercise inotify_add_watch on bad_fd + * stress-inotify: exercise inotify_add_watch on already existing fd + * stress-inotify: exercise inotify_add_watch with two operations + * stress-inotify: exercise inotify_add_watch with bad mask + * stress-inotify: exercise invalid inotify_init1 + * syscalls.txt: add inotify_init syscall + * stress-inotify: add syscall inotify1 and exercise it + * stress-fanotify: exercise invalid combination of flags + * stress-fanotify: add build time check for FAN_MARK_MOUNT + * stress-fanotify: Add fanotify syscalls + * stress-fanotify: Add test for fanotify_mark syscall + * stress-fanotify: Exercise fanotify_mark on bad fd + * stress-fanotify: Exercise fanotify_mark with invalid flag + * stress-fanotify: add test_fanotify_mark + * stress-fanotify: Exercise fanotify_init syscalls with different flags + * stress-fanotify: Add fanotify_init syscalls + * stress-timerfd: Exercise timerfd_settime with invalid flags + * stress-timerfd: Exercise non valid timerfd file descriptor + + -- Colin King Wed, 16 Sep 2020 22:58:21 +0100 + +stress-ng (0.11.20-1) unstable; urgency=medium + + [André Wild] + * Fix error if only HAVE_TERMIOS is not set + * stress-zlib: Fixes race conditions during deflate/inflate + * stress-ipsec-mb: Fixes out of bounds access of unterminated funcs + array + * stress-zlib: new zlib stressor options + + [Colin Ian King] + * Makefile: bump version + * stress-zlib: cast pid_t to int for %d format specifier + * stress-timerfd: only define cap_wake_alarm when it is required + * stress-open: cast pid_t to int for %d format specifier + * stress-timerfd: add build checks for CLOCK_REALTIME_* timers + * stress-memthrash: fix premature termination by OOM handler + * stress-memthrash: fix typo in comment "Wait" -> "Wake" + * stress-zlib: use %zd for ssize_t, fixes build warning on GNU/HURD + * stress-vforkmany: improve waiting by terminating child + * stress-open: fix build failures on systems that don't support O_PATH + * stress-close: add directory clean up at end + * stress-affinity: use 16 processes to hammer affinity changes per + stressor + * stress-af-alg: break some overly long lines + * stress-af-alg: add string overflow sanity check + * stress-access: break wide defined() checks to 2 lines + * stress-madvise: make signal message text plural on > 1 SIGBUS signals + * stress-zlib: move declaration of reval, voidify return from waitpid + * stress-close: remove duplicated bad_fd declaration + * stress-zlib: print args.stream_bytes as unsigned long long + * stress-ng.h: build in target clone types if gcc supports the feature + * stress-enosys: re-write int $80 x86-64 syscall + * stress-dev: clean up intentation + * syscalls.txt: add openat2 notes + * Makefile.config: add config test for struct open_how + * stress-open: call open() directly if possible + * stress-open: add openat system call check and exercise it + * stress-close: exercise new close_range system call + + [Piyush Goyal] + * stress-timerfd: Exercise non valid timerfd file descriptor + * stress-timerfd: Add invalid timerfd_gettime syscalls on bad fd + * stress-numa: Add check mbind cannot succeed without capability + * stress-pidfd: Exercise invalid pidfd_getfd syscall + * stress-numa: Add MPOL_F_MEMS_ALLOWED flag get_mempolicy syscalls + * stress-close: Exercise faccessat syscall on file fd + * stress-xattr: Reorganise and exercise invalid fgetxattr syscall + * stress-xattr: Exercise getxattr with small value buffer + * stress-timerfd: Exercise invalid timerfd_create syscall + * stress-timerfd: Add check timerfd_create cannot succeed without + capability + * stress-xattr: Exercise invalid lgetxattr syscall + * stress-pidfd: Exercise pidfd_getfd syscall with bad_fd + * stress-numa: Exercise invalid mbind syscall + * stress-numa: Add invalid get_mempolicy syscalls + * stress-numa: Exercise invalid get_mempolicy syscall + * stress-xattr: Exercise invalid fgetxattr syscall + * stress-close: Exercise faccessat syscall with invalid flags + * stress-close: Exercise faccessat syscall on bad dirfd + * stress-dev: Exercise VT_RESIZE and VT_RESIZEX ioctl syscall + * stress-dev: Exercise KDGKBDIACR ioctl syscall + * Makefile.config: Define Macros HAVE_UNIMAPDESC + * stress-dev: Exercise KDGKBSENT and KDSKBSENT ioctl syscalls + * stress-dev: Exercise GIO_UNISCRNMAP and PIO_UNISCRNMAP ioctl syscalls + * stress-dev: Exercise GIO_SCRNMAP and PIO_SCRNMAP ioctl syscalls + + -- Colin King Mon, 7 Sep 2020 17:41:24 +0100 + stress-ng (0.11.19-1) unstable; urgency=medium [Colin Ian King ] diff -Nru stress-ng-0.11.19/Makefile stress-ng-0.11.21/Makefile --- stress-ng-0.11.19/Makefile 2020-08-24 14:14:41.000000000 +0000 +++ stress-ng-0.11.21/Makefile 2020-09-16 22:00:11.000000000 +0000 @@ -16,7 +16,7 @@ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # -VERSION=0.11.19 +VERSION=0.11.21 # # Codename "synthetic system strainer" # @@ -142,6 +142,7 @@ stress-ioport.c \ stress-ioprio.c \ stress-iosync.c \ + stress-io-uring.c \ stress-ipsec-mb.c \ stress-itimer.c \ stress-judy.c \ @@ -338,7 +339,7 @@ core-try-open.c \ stress-ng.c -SRC = $(STRESS_SRC) $(CORE_SRC) +SRC = $(CORE_SRC) $(STRESS_SRC) OBJS = $(SRC:.c=.o) APPARMOR_PARSER=/sbin/apparmor_parser @@ -394,11 +395,23 @@ # extract the PER_* personality enums # personality.h: - @$(CPP) core-personality.c | $(GREP) -e "PER_[A-Z0-9]* =.*," | cut -d "=" -f 1 \ + @$(CPP) $(CONFIG_CFLAGS) core-personality.c | $(GREP) -e "PER_[A-Z0-9]* =.*," | cut -d "=" -f 1 \ | sed "s/.$$/,/" > personality.h + @echo "MK personality.h" stress-personality.c: personality.h +# +# extract IORING_OP enums and #define HAVE_ prefixed values +# so we can check if these enums exist +# +io-uring.h: + @$(CPP) $(CONFIG_CLFAGS) core-io-uring.c | grep IORING_OP | sed 's/,//' | \ + sed 's/IORING_OP_/#define HAVE_IORING_OP_/' > io-uring.h + @echo "MK io-uring.h" + +stress-io-uring.c: io-uring.h + core-perf.o: core-perf.c core-perf-event.c @$(CC) $(CFLAGS) -E core-perf-event.c | grep "PERF_COUNT" | \ sed 's/,/ /' | sed s/'^ *//' | \ @@ -421,7 +434,8 @@ rm -rf stress-ng-$(VERSION) mkdir stress-ng-$(VERSION) cp -rp Makefile Makefile.config $(SRC) stress-ng.h stress-ng.1 \ - core-personality.c COPYING syscalls.txt mascot README \ + core-personality.c core-io-uring.c \ + COPYING syscalls.txt mascot README \ stress-af-alg-defconfigs.h README.Android test snap \ TODO core-perf-event.c usr.bin.pulseaudio.eg \ stress-version.h bash-completion example-jobs .travis.yml \ @@ -439,6 +453,7 @@ @rm -f stress-ng $(OBJS) stress-ng.1.gz stress-ng.pdf @rm -f stress-ng-$(VERSION).tar.xz @rm -f personality.h + @rm -f io-uring.h @rm -f perf-event.h @rm -f apparmor-data.bin @rm -f *.o diff -Nru stress-ng-0.11.19/Makefile.config stress-ng-0.11.21/Makefile.config --- stress-ng-0.11.19/Makefile.config 2020-08-24 14:14:41.000000000 +0000 +++ stress-ng-0.11.21/Makefile.config 2020-09-16 22:00:11.000000000 +0000 @@ -939,6 +939,14 @@ endif endif +ifndef $(HAVE_LINUX_IO_URING_H) +HAVE_LINUX_IO_URING_H = $(shell $(MAKE) $(MAKE_OPTS) HEADER=linux/io_uring.h have_header_h) +ifeq ($(HAVE_LINUX_IO_URING_H),1) + CONFIG_CFLAGS += -DHAVE_LINUX_IO_URING_H +$(info autoconfig: using linux/io_uring.h) +endif +endif + ifndef $(HAVE_LINUX_KD_H) HAVE_LINUX_KD_H = $(shell $(MAKE) $(MAKE_OPTS) HEADER=linux/kd.h have_header_h) ifeq ($(HAVE_LINUX_KD_H),1) @@ -1585,6 +1593,14 @@ endif endif +ifndef $(HAVE_EPOLL_CREATE) +HAVE_EPOLL_CREATE = $(shell $(MAKE) $(MAKE_OPTS) TEST_PROG=test-epoll-create have_test_prog) +ifeq ($(HAVE_EPOLL_CREATE),1) + CONFIG_CFLAGS += -DHAVE_EPOLL_CREATE +$(info autoconfig: using epoll_create) +endif +endif + ifndef $(HAVE_EPOLL_CREATE1) HAVE_EPOLL_CREATE1 = $(shell $(MAKE) $(MAKE_OPTS) TEST_PROG=test-epoll-create1 have_test_prog) ifeq ($(HAVE_EPOLL_CREATE1),1) @@ -1883,6 +1899,14 @@ endif endif +ifndef $(HAVE_INOTIFY1) +HAVE_INOTIFY1 = $(shell $(MAKE) $(MAKE_OPTS) TEST_PROG=test-inotify1 have_test_prog) +ifeq ($(HAVE_INOTIFY1),1) + CONFIG_CFLAGS += -DHAVE_INOTIFY1 +$(info autoconfig: using inotify1) +endif +endif + ifndef $(HAVE_IOPORT) HAVE_IOPORT = $(shell $(MAKE) $(MAKE_OPTS) TEST_PROG=test-ioport have_test_prog) ifeq ($(HAVE_IOPORT),1) @@ -1933,6 +1957,14 @@ endif endif +ifndef $(HAVE_LINKAT) +HAVE_LINKAT = $(shell $(MAKE) $(MAKE_OPTS) TEST_PROG=test-linkat have_test_prog) +ifeq ($(HAVE_LINKAT),1) + CONFIG_CFLAGS += -DHAVE_LINKAT +$(info autoconfig: using linkat) +endif +endif + ifndef $(HAVE_LISTXATTR) HAVE_LISTXATTR = $(shell $(MAKE) $(MAKE_OPTS) TEST_PROG=test-listxattr have_test_prog) ifeq ($(HAVE_LISTXATTR),1) @@ -2127,6 +2159,14 @@ endif endif +ifndef $(HAVE_OPENAT) +HAVE_OPENAT = $(shell $(MAKE) $(MAKE_OPTS) TEST_PROG=test-openat have_test_prog) +ifeq ($(HAVE_OPENAT),1) + CONFIG_CFLAGS += -DHAVE_OPENAT +$(info autoconfig: using openat) +endif +endif + ifndef $(HAVE_OPEN_BY_HANDLE_AT) HAVE_OPEN_BY_HANDLE_AT = $(shell $(MAKE) $(MAKE_OPTS) TEST_PROG=test-open-by-handle-at have_test_prog) ifeq ($(HAVE_OPEN_BY_HANDLE_AT),1) @@ -2797,6 +2837,14 @@ endif endif +ifndef $(HAVE_KBDIACRS) +HAVE_KBDIACRS = $(shell $(MAKE) $(MAKE_OPTS) TEST_PROG=test-kbdiacrs have_test_prog) +ifeq ($(HAVE_KBDIACRS),1) + CONFIG_CFLAGS += -DHAVE_KBDIACRS +$(info autoconfig: using struct kbdiacrs) +endif +endif + ifndef $(HAVE_KBENTRY) HAVE_KBENTRY = $(shell $(MAKE) $(MAKE_OPTS) TEST_PROG=test-kbentry have_test_prog) ifeq ($(HAVE_KBENTRY),1) @@ -2813,6 +2861,14 @@ endif endif +ifndef $(HAVE_KBSENTRY) +HAVE_KBSENTRY = $(shell $(MAKE) $(MAKE_OPTS) TEST_PROG=test-kbsentry have_test_prog) +ifeq ($(HAVE_KBSENTRY),1) + CONFIG_CFLAGS += -DHAVE_KBSENTRY +$(info autoconfig: using struct kbsentry) +endif +endif + ifndef $(HAVE_MEDIA_DEVICE_INFO) HAVE_MEDIA_DEVICE_INFO = $(shell $(MAKE) $(MAKE_OPTS) TEST_PROG=test-media_device_info have_test_prog) ifeq ($(HAVE_MEDIA_DEVICE_INFO),1) @@ -2829,6 +2885,14 @@ endif endif +ifndef $(HAVE_OPEN_HOW) +HAVE_OPEN_HOW = $(shell $(MAKE) $(MAKE_OPTS) TEST_PROG=test-open_how have_test_prog) +ifeq ($(HAVE_OPEN_HOW),1) + CONFIG_CFLAGS += -DHAVE_OPEN_HOW +$(info autoconfig: using struct open_how) +endif +endif + ifndef $(HAVE_SERIAL_ICOUNTER) HAVE_SERIAL_ICOUNTER = $(shell $(MAKE) $(MAKE_OPTS) TEST_PROG=test-serial-icounter have_test_prog) ifeq ($(HAVE_SERIAL_ICOUNTER),1) @@ -2869,6 +2933,14 @@ endif endif +ifndef $(HAVE_UNIMAPDESC) +HAVE_UNIMAPDESC = $(shell $(MAKE) $(MAKE_OPTS) TEST_PROG=test-unimapdesc have_test_prog) +ifeq ($(HAVE_UNIMAPDESC),1) + CONFIG_CFLAGS += -DHAVE_UNIMAPDESC +$(info autoconfig: using struct unimapdesc) +endif +endif + ifndef $(HAVE_USER_DESC) HAVE_USER_DESC = $(shell $(MAKE) $(MAKE_OPTS) TEST_PROG=test-user-desc have_test_prog) ifeq ($(HAVE_USER_DESC),1) @@ -2877,6 +2949,14 @@ endif endif +ifndef $(HAVE_VT_CONSIZE) +HAVE_VT_CONSIZE = $(shell $(MAKE) $(MAKE_OPTS) TEST_PROG=test-vt_consize have_test_prog) +ifeq ($(HAVE_VT_CONSIZE),1) + CONFIG_CFLAGS += -DHAVE_VT_CONSIZE +$(info autoconfig: using struct vt_consize) +endif +endif + ifndef $(HAVE_VT_MODE) HAVE_VT_MODE = $(shell $(MAKE) $(MAKE_OPTS) TEST_PROG=test-vt_mode have_test_prog) ifeq ($(HAVE_VT_MODE),1) @@ -2885,6 +2965,14 @@ endif endif +ifndef $(HAVE_VT_SIZES) +HAVE_VT_SIZES = $(shell $(MAKE) $(MAKE_OPTS) TEST_PROG=test-vt_sizes have_test_prog) +ifeq ($(HAVE_VT_SIZES),1) + CONFIG_CFLAGS += -DHAVE_VT_SIZES +$(info autoconfig: using struct vt_sizes) +endif +endif + ifndef $(HAVE_VT_STAT) HAVE_VT_STAT = $(shell $(MAKE) $(MAKE_OPTS) TEST_PROG=test-vt_stat have_test_prog) ifeq ($(HAVE_VT_STAT),1) diff -Nru stress-ng-0.11.19/README stress-ng-0.11.21/README --- stress-ng-0.11.19/README 2020-08-24 14:14:41.000000000 +0000 +++ stress-ng-0.11.21/README 2020-09-16 22:00:11.000000000 +0000 @@ -4,7 +4,7 @@ was designed to exercise various physical subsystems of a computer as well as the various operating system kernel interfaces. Stress-ng features: - * over 230 stress tests + * over 240 stress tests * 78 CPU specific stress tests that exercise floating point, integer, bit manipulation and control flow * over 20 virtual memory stress tests diff -Nru stress-ng-0.11.19/stress-access.c stress-ng-0.11.21/stress-access.c --- stress-ng-0.11.19/stress-access.c 2020-08-24 14:14:41.000000000 +0000 +++ stress-ng-0.11.21/stress-access.c 2020-09-16 22:00:11.000000000 +0000 @@ -147,7 +147,8 @@ ret = faccessat(bad_fd, filename, modes[i].access_mode, 0); (void)ret; #endif -#if defined(HAVE_FACCESSAT2) && defined(AT_SYMLINK_NOFOLLOW) +#if defined(HAVE_FACCESSAT2) && \ + defined(AT_SYMLINK_NOFOLLOW) ret = faccessat2(AT_FDCWD, filename, modes[i].access_mode, AT_SYMLINK_NOFOLLOW); if ((ret < 0) && (errno != ENOSYS)) { pr_fail("%s: faccessat2 %3.3o on chmod mode %3.3o failed: %d (%s)\n", diff -Nru stress-ng-0.11.19/stress-af-alg.c stress-ng-0.11.21/stress-af-alg.c --- stress-ng-0.11.19/stress-af-alg.c 2020-08-24 14:14:41.000000000 +0000 +++ stress-ng-0.11.21/stress-af-alg.c 2020-09-16 22:00:11.000000000 +0000 @@ -123,11 +123,14 @@ static stress_crypto_type_t name_to_type(const char *buffer) { char *ptr = strchr(buffer, ':'); + const char *end = ptr + strlen(buffer); size_t i; if (!ptr) return CRYPTO_UNKNOWN; ptr += 2; + if (ptr >= end) + return CRYPTO_UNKNOWN; for (i = 0; i < SIZEOF_ARRAY(crypto_type_info); i++) { const size_t n = strlen(crypto_type_info[i].name); @@ -157,7 +160,9 @@ * some crypto engines may return EINVAL, so flag these up in * debug and ignore them for the next iteration */ -static void stress_af_alg_ignore(const stress_args_t *args, stress_crypto_info_t *info) +static void stress_af_alg_ignore( + const stress_args_t *args, + stress_crypto_info_t *info) { if ((args->instance == 0) && (!info->ignore)) { pr_dbg("%s: sendmsg using %s failed with EINVAL, skipping crypto engine\n", @@ -669,7 +674,9 @@ break; retries--; - if ((!keep_stressing_flag()) || (retries < 0) || (errno != EAFNOSUPPORT)) { + if ((!keep_stressing_flag()) || + (retries < 0) || + (errno != EAFNOSUPPORT)) { if (errno == EAFNOSUPPORT) { /* * If we got got here, the protocol is not supported diff -Nru stress-ng-0.11.19/stress-affinity.c stress-ng-0.11.21/stress-affinity.c --- stress-ng-0.11.19/stress-affinity.c 2020-08-24 14:14:41.000000000 +0000 +++ stress-ng-0.11.21/stress-affinity.c 2020-09-16 22:00:11.000000000 +0000 @@ -24,6 +24,8 @@ */ #include "stress-ng.h" +#define STRESS_AFFINITY_PROCS (16) + static const stress_help_t help[] = { { NULL, "affinity N", "start N workers that rapidly change CPU affinity" }, { NULL, "affinity-ops N","stop after N affinity bogo operations" }, @@ -76,16 +78,71 @@ return 0; } -static int stress_affinity(const stress_args_t *args) +static void stress_affinity_reap(pid_t *pids) { - uint32_t cpu = args->instance; - const uint32_t cpus = (uint32_t)stress_get_processors_configured(); - cpu_set_t mask; - bool affinity_rand = false; + size_t i; + const pid_t mypid = getpid(); - (void)stress_get_setting("affinity-rand", &affinity_rand); + /* + * Kill and reap children + */ + for (i = 1; i < STRESS_AFFINITY_PROCS; i++) { + if ((pids[i] > 1) && (pids[i] != mypid)) + kill(pids[i], SIGKILL); + } + for (i = 1; i < STRESS_AFFINITY_PROCS; i++) { + if ((pids[i] > 1) && (pids[i] != mypid)) { + int status; + + (void)waitpid(pids[i], &status, 0); + } + } +} + +/* + * stress_affinity_racy_count() + * racy bogo op counter, we have a lot of contention + * if we lock the args->counter, so sum per-process + * counters in a racy way. + */ +static uint64_t stress_affinity_racy_count(uint64_t *counters) +{ + register uint64_t count = 0; + register size_t i; + + for (i = 0; i < STRESS_AFFINITY_PROCS; i++) + count += counters[i]; + + return count; +} + +/* + * affinity_keep_stressing() + * check if SIGALRM has triggered to the bogo ops count + * has been reached, counter is racy, but that's OK + */ +static bool HOT OPTIMIZE3 affinity_keep_stressing( + const stress_args_t *args, + uint64_t *counters) +{ + return (LIKELY(g_keep_stressing_flag) && + LIKELY(!args->max_ops || + (stress_affinity_racy_count(counters) < args->max_ops))); +} + +static void stress_affinity_child( + const stress_args_t *args, + const bool affinity_rand, + const uint32_t cpus, + uint64_t *counters, + pid_t *pids, + size_t instance) +{ + uint32_t cpu = args->instance; do { + cpu_set_t mask; + cpu = affinity_rand ? (stress_mwc32() >> 4) : cpu + 1; cpu %= cpus; CPU_ZERO(&mask); @@ -113,8 +170,61 @@ args->name, cpu); } } - inc_counter(args); - } while (keep_stressing()); + counters[instance]++; + } while (affinity_keep_stressing(args, counters)); + + stress_affinity_reap(pids); +} + +static int stress_affinity(const stress_args_t *args) +{ + const uint32_t cpus = (uint32_t)stress_get_processors_configured(); + bool affinity_rand = false; + pid_t pids[STRESS_AFFINITY_PROCS]; + size_t i; + size_t counters_sz = ((sizeof(uint64_t) * (STRESS_AFFINITY_PROCS)) + args->page_size) + & ~(args->page_size - 1); + uint64_t *counters; + + (void)stress_get_setting("affinity-rand", &affinity_rand); + + counters = (uint64_t *)mmap(NULL, counters_sz, PROT_READ | PROT_WRITE, + MAP_SHARED | MAP_ANONYMOUS, -1, 0); + if (!counters) { + pr_inf("%s: cannot mmap %zd bytes for shared counters, skipping stressor\n", + args->name, counters_sz); + return EXIT_NO_RESOURCE; + } + + /* + * process slots 1..STRESS_AFFINITY_PROCS are the children, + * slot 0 is the parent. + */ + for (i = 1; i < STRESS_AFFINITY_PROCS; i++) { + pids[i] = fork(); + + if (pids[i] == 0) { + stress_affinity_child(args, affinity_rand, cpus, counters, pids, i); + _exit(EXIT_SUCCESS); + } + } + + stress_affinity_child(args, affinity_rand, cpus, counters, pids, 0); + + /* + * The first process to hit the bogo op limit or get a SIGALRM + * will have reap'd the processes, but to be safe, reap again + * to ensure all processes are really dead and reaped. + */ + stress_affinity_reap(pids); + + /* + * Set counter, this is always going to be >= the bogo_ops + * threshold because it is racy, but that is OK + */ + set_counter(args, stress_affinity_racy_count(counters)); + + (void)munmap((void *)counters, counters_sz); return EXIT_SUCCESS; } diff -Nru stress-ng-0.11.19/stress-apparmor.c stress-ng-0.11.21/stress-apparmor.c --- stress-ng-0.11.19/stress-apparmor.c 2020-08-24 14:14:41.000000000 +0000 +++ stress-ng-0.11.21/stress-apparmor.c 2020-09-16 22:00:11.000000000 +0000 @@ -74,7 +74,7 @@ return -1; } /* ..and see if profiles are accessible */ - (void)snprintf(path, sizeof(path), "%s/%s", apparmor_path, "profiles"); + (void)stress_mk_filename(path, sizeof(path), apparmor_path, "profiles"); if ((fd = open(path, O_RDONLY)) < 0) { switch (errno) { case EACCES: @@ -186,14 +186,12 @@ switch (d->d_type) { case DT_DIR: if (recurse) { - (void)snprintf(name, sizeof(name), - "%s/%s", path, d->d_name); + (void)stress_mk_filename(name, sizeof(name), path, d->d_name); stress_apparmor_dir(name, recurse, depth + 1); } break; case DT_REG: - (void)snprintf(name, sizeof(name), - "%s/%s", path, d->d_name); + (void)stress_mk_filename(name, sizeof(name), path, d->d_name); stress_apparmor_read(name); break; default: @@ -262,7 +260,7 @@ char path[PATH_MAX]; (void)name; - (void)snprintf(path, sizeof(path), "%s/%s", apparmor_path, "profiles"); + (void)stress_mk_filename(path, sizeof(path), apparmor_path, "profiles"); do { stress_apparmor_read(path); @@ -286,7 +284,7 @@ char path[PATH_MAX]; (void)name; - (void)snprintf(path, sizeof(path), "%s/%s", apparmor_path, "features"); + (void)stress_mk_filename(path, sizeof(path), apparmor_path, "features"); do { stress_apparmor_dir(path, true, 0); @@ -346,9 +344,11 @@ if (ret < 0) { aa_kernel_interface_unref(kern_if); - pr_inf("%s: aa_kernel_interface_replace_policy() failed, " - "errno=%d (%s)\n", name, errno, - strerror(errno)); + if (errno == ENOENT) { + pr_inf("%s: aa_kernel_interface_replace_policy() failed, " + "errno=%d (%s)\n", name, errno, + strerror(errno)); + } } /* diff -Nru stress-ng-0.11.19/stress-bad-ioctl.c stress-ng-0.11.21/stress-bad-ioctl.c --- stress-ng-0.11.19/stress-bad-ioctl.c 2020-08-24 14:14:41.000000000 +0000 +++ stress-ng-0.11.21/stress-bad-ioctl.c 2020-09-16 22:00:11.000000000 +0000 @@ -277,7 +277,7 @@ continue; } - (void)snprintf(tmp, sizeof(tmp), "%s/%s", path, d->d_name); + (void)stress_mk_filename(tmp, sizeof(tmp), path, d->d_name); switch (d->d_type) { case DT_DIR: if (!recurse) diff -Nru stress-ng-0.11.19/stress-binderfs.c stress-ng-0.11.21/stress-binderfs.c --- stress-ng-0.11.19/stress-binderfs.c 2020-08-24 14:14:41.000000000 +0000 +++ stress-ng-0.11.21/stress-binderfs.c 2020-09-16 22:00:11.000000000 +0000 @@ -117,7 +117,7 @@ } } - (void)snprintf(filename, sizeof(filename), "%s/%s", + (void)stress_mk_filename(filename, sizeof(filename), pathname, "binder-control"); fd = open(filename, O_RDONLY | O_CLOEXEC); if (fd < 0) { diff -Nru stress-ng-0.11.19/stress-clock.c stress-ng-0.11.21/stress-clock.c --- stress-ng-0.11.19/stress-clock.c 2020-08-24 14:14:41.000000000 +0000 +++ stress-ng-0.11.21/stress-clock.c 2020-09-16 22:00:11.000000000 +0000 @@ -128,6 +128,27 @@ } #endif +#if (defined(__NR_clock_adjtime) && \ + defined(HAVE_SYS_TIMEX_H) && \ + defined(ADJ_SETOFFSET)) || \ + (defined(HAVE_CLOCK_NANOSLEEP) && \ + defined(TIMER_ABSTIME)) +#define CHECK_INVALID_CLOCK_ID (1) +#endif + +#if defined(CHECK_INVALID_CLOCK_ID) +/* + * check_invalid_clock_id() + * function to check if given clock_id is valid + */ +static inline bool check_invalid_clock_id(const clockid_t id) { + struct timespec tp; + + (void)memset(&tp, 0, sizeof(tp)); + return (clock_gettime(id, &tp) != 0); +} +#endif + #define FD_TO_CLOCKID(fd) ((~(clockid_t)(fd) << 3) | 3) /* @@ -145,6 +166,10 @@ bool test_invalid_timespec = true; const bool is_root = stress_check_capability(SHIM_CAP_IS_ROOT); +#if defined(CHECK_INVALID_CLOCK_ID) + const bool invalid_clock_id = check_invalid_clock_id(INT_MAX); +#endif + do { #if defined(CLOCK_THREAD_CPUTIME_ID) && \ defined(HAVE_CLOCK_GETTIME) && \ @@ -277,10 +302,35 @@ } #endif -#if defined(HAVE_CLOCK_NANOSLEEP) +#if defined(HAVE_CLOCK_NANOSLEEP) && \ + defined(TIMER_ABSTIME) { size_t i; struct timespec t; + static int n = 0; + + if (n++ >= 1024) { + n = 0; + int ret_st; + + /* Exercise clock_nanosleep on invalid clock id */ + if (invalid_clock_id) { + (void)memset(&t, 0, sizeof(t)); + ret_st = clock_nanosleep(INT_MAX, TIMER_ABSTIME, &t, NULL); + (void)ret_st; + } + + /* Exercise clock_adjtime on non-permitted timespec object values */ + (void)memset(&t, 0, sizeof(t)); + t.tv_sec = -1; + ret_st = clock_nanosleep(clocks_nanosleep[0], TIMER_ABSTIME, &t, NULL); + (void)ret_st; + + (void)memset(&t, 0, sizeof(t)); + t.tv_nsec = 1000000000; + ret_st = clock_nanosleep(clocks_nanosleep[0], TIMER_ABSTIME, &t, NULL); + (void)ret_st; + } /* * Exercise clock_nanosleep for each clock @@ -311,6 +361,15 @@ size_t i; struct shim_timex tx; + /* Exercise clock_adjtime on invalid clock id */ + if (invalid_clock_id) { + int ret_st; + + (void)memset(&tx, 0, sizeof(tx)); + ret_st = shim_clock_adjtime(INT_MAX, &tx); + (void)ret_st; + } + /* * Exercise clock_adjtime */ diff -Nru stress-ng-0.11.19/stress-close.c stress-ng-0.11.21/stress-close.c --- stress-ng-0.11.19/stress-close.c 2020-08-24 14:14:41.000000000 +0000 +++ stress-ng-0.11.21/stress-close.c 2020-09-16 22:00:11.000000000 +0000 @@ -34,6 +34,8 @@ #define MAX_PTHREADS (3) #define SHM_NAME_LEN (128) +#define FDS_START (1024) +#define FDS_TO_DUP (8) static volatile int fd, dupfd; static volatile uint64_t max_delay_us = 1; @@ -119,9 +121,15 @@ #endif while (keep_stressing()) { - int fd_rnd = (int)stress_mwc32(); + int fd_rnd = (int)stress_mwc32() + 64; const uint64_t delay = max_delay_us ? stress_mwc32() % max_delay_us : 0; + int fds[FDS_TO_DUP], i, ret; + + for (i = 0; i < FDS_TO_DUP; i++) { + fds[i] = dup2(fileno(stderr), i + FDS_START); + } + shim_usleep_interruptible(delay); if (fd != -1) (void)close(fd); @@ -135,6 +143,19 @@ if (fcntl((int)fd_rnd, F_GETFL) == -1) (void)close(fd_rnd); #endif + /* + * close a range of fds + */ + ret = shim_close_range(FDS_START, FDS_START + FDS_TO_DUP); + if ((ret < 1) && (errno == ENOSYS)) { + for (i = 0; i < FDS_TO_DUP; i++) + (void)close(fds[i]); + } + /* + * close an invalid range of fds + */ + ret = shim_close_range(FDS_START + FDS_TO_DUP, FDS_START); + (void)ret; } return &nowt; @@ -156,6 +177,10 @@ const gid_t gid = getgid(); const bool not_root = !stress_check_capability(SHIM_CAP_IS_ROOT); double max_duration = 0.0; +#if defined(HAVE_FACCESSAT) + int file_fd = -1; + char filename[PATH_MAX]; +#endif #if defined(HAVE_LIB_RT) char shm_name[SHM_NAME_LEN]; #endif @@ -185,6 +210,21 @@ } } +#if defined(HAVE_FACCESSAT) + { + ret = stress_temp_dir_mk_args(args); + if (ret < 0) + return exit_status(-ret); + (void)stress_temp_filename_args(args, filename, sizeof(filename), stress_mwc32()); + file_fd = open(filename, O_CREAT | O_RDWR, S_IRUSR | S_IWUSR); + if (file_fd < 0) { + pr_err("%s: cannot create %s\n", args->name, filename); + return exit_status(errno); + } + (void)unlink(filename); + } +#endif + do { size_t domain, type; int pipefds[2]; @@ -299,6 +339,30 @@ #if defined(HAVE_FACCESSAT) ret = faccessat(fd, "", F_OK, 0); (void)ret; + + /* + * Exercise bad dirfd resulting in Error EBADF + */ + ret = faccessat(bad_fd, "", F_OK, 0); + (void)ret; + + /* + * Exercise invalid flags syscall + */ + ret = faccessat(fd, "", ~0, 0); + (void)ret; + + /* + * Invalid faccessat syscall with pathname is relative and dirfd + * is a file descriptor referring to a file other than a directory + */ + ret = faccessat(file_fd, "./", F_OK, 0); + if (ret >= 0) { + pr_fail("%s: faccessat opened file descriptor succeeded unexpectedly, " + "errno=%d (%s)\n", args->name, errno, strerror(errno)); + (void)close(ret); + goto tidy; + } #endif ret = fstat(fd, &statbuf); (void)ret; @@ -334,6 +398,11 @@ } } +#if defined(HAVE_FACCESSAT) + (void)close(file_fd); + (void)stress_temp_dir_rm_args(args); +#endif + return rc; } diff -Nru stress-ng-0.11.19/stress-dev.c stress-ng-0.11.21/stress-dev.c --- stress-ng-0.11.19/stress-dev.c 2020-08-24 14:14:41.000000000 +0000 +++ stress-ng-0.11.21/stress-dev.c 2020-09-16 22:00:11.000000000 +0000 @@ -77,6 +77,132 @@ return (s1 < s2) ? -1 : 1; } +/* + * ioctl_set_timeout() + * set a itimer to interrupt ioctl call after secs seconds + */ +static void ioctl_set_timeout(const double secs) +{ +#if defined(ITIMER_REAL) + if (secs > 0.0) { + struct itimerval it; + int ret; + + it.it_interval.tv_sec = (time_t)secs; + it.it_interval.tv_usec = (suseconds_t)(1000000.0 * (secs - (time_t)secs)); + it.it_value.tv_sec = it.it_interval.tv_sec; + it.it_value.tv_usec = it.it_interval.tv_usec; + ret = setitimer(ITIMER_REAL, &it, NULL); + (void)ret; + } +#else + (void)secs; +#endif +} + +/* + * ioctl_clr_timeout() + * clear itimer ioctl timeout alarm + */ +static void ioctl_clr_timeout(void) +{ +#if defined(ITIMER_REAL) + struct itimerval it; + int ret; + + (void)memset(&it, 0, sizeof(it)); + ret = setitimer(ITIMER_REAL, &it, NULL); + (void)ret; +#endif +} + +/* + * IOCTL_TIMEOUT() + * execute code, if time taken is > secs then + * execute the action. Note there are limitations + * to the code that can be passed into the macro, + * variable declarations must be one variable at a + * time without any commas + */ +#define IOCTL_TIMEOUT(secs, code, action) \ +{ \ + static bool timed_out_ = false; \ + double timeout_t_ = stress_time_now(); \ + \ + if (!timed_out_) { \ + ioctl_set_timeout(secs); \ + code \ + ioctl_clr_timeout(); \ + } \ + if (stress_time_now() >= timeout_t_ + secs) { \ + timed_out_ = true; \ + action; \ + } \ +} + +/* + * linux_xen_guest() + * return true if stress-ng is running + * as a Linux Xen guest. + */ +static bool linux_xen_guest(void) +{ +#if defined(__linux__) + static bool xen_guest = false; + static bool xen_guest_cached = false; + struct stat statbuf; + int ret; + DIR *dp; + struct dirent *de; + + if (xen_guest_cached) + return xen_guest; + + /* + * The features file is a good indicator for a Xen guest + */ + ret = stat("/sys/hypervisor/properties/features", &statbuf); + if (ret == 0) { + xen_guest = true; + goto done; + } + if (errno == EACCES) { + xen_guest = true; + goto done; + } + + /* + * Non-dot files in /sys/bus/xen/devices indicate a Xen guest too + */ + dp = opendir("/sys/bus/xen/devices"); + if (dp) { + while ((de = readdir(dp)) != NULL) { + if (de->d_name[0] != '.') { + xen_guest = true; + break; + } + } + (void)closedir(dp); + if (xen_guest) + goto done; + } + + /* + * At this point Xen is being sneaky and pretending, so + * apart from inspecting dmesg (which may not be possible), + * assume it's not a Xen hosted guest. + */ + xen_guest = false; +done: + xen_guest_cached = true; + + return xen_guest; +#else + return false; +#endif +} + + #if defined(__linux__) && \ defined(HAVE_LINUX_MEDIA_H) && \ defined(MEDIA_IOC_DEVICE_INFO) @@ -1043,6 +1169,7 @@ (void)memset(&entry, 0, sizeof(entry)); entry.cdte_track = track; entry.cdte_format = CDROM_MSF; + if (ioctl(fd, CDROMREADTOCENTRY, &entry) == 0) { *min = entry.cdte_addr.msf.minute; *seconds = entry.cdte_addr.msf.second; @@ -1066,6 +1193,7 @@ #if defined(CDROMREADTOCHDR) && \ defined(HAVE_CDROM_MSF) && \ defined(HAVE_CDROM_TOCHDR) + IOCTL_TIMEOUT(0.10, { struct cdrom_tochdr header; /* Reading the number of tracks on disc */ @@ -1075,7 +1203,7 @@ starttrk = header.cdth_trk0; endtrk = header.cdth_trk1; } - } + }, return); #endif /* Return if endtrack is not set or starttrk is invalid */ @@ -1086,7 +1214,7 @@ #if defined(CDROMPLAYTRKIND) && \ defined(HAVE_CDROM_TI) && \ defined(CDROMPAUSE) - { + IOCTL_TIMEOUT(0.10, { struct cdrom_ti ti; int ret; @@ -1096,7 +1224,7 @@ ret = ioctl(fd, CDROMPAUSE, 0); (void)ret; } - } + }, return); #endif #if defined(CDROMREADTOCENTRY) && \ @@ -1115,15 +1243,17 @@ #if defined(CDROMPLAYMSF) && \ defined(CDROMPAUSE) - if (ioctl(fd, CDROMPLAYMSF, &msf) == 0) { - ret = ioctl(fd, CDROMPAUSE, 0); - (void)ret; - } + IOCTL_TIMEOUT(0.10, { + if (ioctl(fd, CDROMPLAYMSF, &msf) == 0) { + ret = ioctl(fd, CDROMPAUSE, 0); + (void)ret; + } + }, return); #endif #if defined(CDROMREADRAW) && \ defined(CD_FRAMESIZE_RAW) - { + IOCTL_TIMEOUT(0.10, { union { struct cdrom_msf msf; /* input */ char buffer[CD_FRAMESIZE_RAW]; /* return */ @@ -1132,12 +1262,12 @@ arg.msf = msf; ret = ioctl(fd, CDROMREADRAW, &arg); (void)ret; - } + }, return); #endif #if defined(CDROMREADMODE1) && \ defined(CD_FRAMESIZE) - { + IOCTL_TIMEOUT(0.10, { union { struct cdrom_msf msf; /* input */ char buffer[CD_FRAMESIZE]; /* return */ @@ -1146,12 +1276,12 @@ arg.msf = msf; ret = ioctl(fd, CDROMREADMODE1, &arg); (void)ret; - } + }, return); #endif #if defined(CDROMREADMODE2) && \ defined(CD_FRAMESIZE_RAW0) - { + IOCTL_TIMEOUT(0.10, { union { struct cdrom_msf msf; /* input */ char buffer[CD_FRAMESIZE_RAW0]; /* return */ @@ -1160,7 +1290,7 @@ arg.msf = msf; ret = ioctl(fd, CDROMREADMODE2, &arg); (void)ret; - } + }, return); #endif } #endif @@ -1181,40 +1311,40 @@ #if defined(CDROM_GET_MCN) && \ defined(HAVE_CDROM_MCN) - { + IOCTL_TIMEOUT(0.10, { struct cdrom_mcn mcn; int ret; (void)memset(&mcn, 0, sizeof(mcn)); ret = ioctl(fd, CDROM_GET_MCN, &mcn); (void)ret; - } + }, return); #endif #if defined(CDROMREADTOCHDR) && \ defined(HAVE_CDROM_TOCHDR) - { + IOCTL_TIMEOUT(0.10, { struct cdrom_tochdr header; int ret; (void)memset(&header, 0, sizeof(header)); ret = ioctl(fd, CDROMREADTOCHDR, &header); (void)ret; - } + }, return); #endif #if defined(CDROMREADTOCENTRY) && \ defined(HAVE_CDROM_TOCENTRY) - { + IOCTL_TIMEOUT(0.10, { struct cdrom_tocentry entry; int ret; (void)memset(&entry, 0, sizeof(entry)); ret = ioctl(fd, CDROMREADTOCENTRY, &entry); (void)ret; - } + }, return); #endif #if defined(CDROMVOLREAD) && \ defined(HAVE_CDROM_VOLCTRL) - { + IOCTL_TIMEOUT(0.10, { struct cdrom_volctrl volume; int ret; @@ -1226,62 +1356,62 @@ } #endif (void)ret; - } + }, return); #endif #if defined(CDROMSUBCHNL) && \ defined(HAVE_CDROM_SUBCHNL) - { + IOCTL_TIMEOUT(0.10, { struct cdrom_subchnl q; int ret; (void)memset(&q, 0, sizeof(q)); ret = ioctl(fd, CDROMSUBCHNL, &q); (void)ret; - } + }, return); #endif #if defined(CDROMREADAUDIO) && \ defined(HAVE_CDROM_READ_AUDIO) - { + IOCTL_TIMEOUT(0.10, { struct cdrom_read_audio ra; int ret; (void)memset(&ra, 0, sizeof(ra)); ret = ioctl(fd, CDROMREADAUDIO, &ra); (void)ret; - } + }, return); #endif #if defined(CDROMREADCOOKED) && \ defined(CD_FRAMESIZE) - { + IOCTL_TIMEOUT(0.10, { uint8_t buffer[CD_FRAMESIZE]; int ret; (void)memset(&buffer, 0, sizeof(buffer)); ret = ioctl(fd, CDROMREADCOOKED, buffer); (void)ret; - } + }, return); #endif #if defined(CDROMREADALL) && \ defined(CD_FRAMESIZE) - { + IOCTL_TIMEOUT(0.10, { uint8_t buffer[CD_FRAMESIZE]; int ret; (void)memset(&buffer, 0, sizeof(buffer)); ret = ioctl(fd, CDROMREADALL, buffer); (void)ret; - } + }, return); #endif #if defined(CDROMSEEK) && \ defined(HAVE_CDROM_MSF) - { + IOCTL_TIMEOUT(0.10, { struct cdrom_msf msf; int ret; (void)memset(&msf, 0, sizeof(msf)); ret = ioctl(fd, CDROMSEEK, &msf); (void)ret; - } + }, return); #endif #if defined(CDROMGETSPINDOWN) { @@ -1310,105 +1440,123 @@ (void)ret; } #endif + + #if defined(CDROM_DISC_STATUS) - { + IOCTL_TIMEOUT(0.10, { int ret; ret = ioctl(fd, CDROM_DISC_STATUS, 0); (void)ret; - } + }, return); #endif #if defined(CDROM_GET_CAPABILITY) - { + IOCTL_TIMEOUT(0.10, { int ret; ret = ioctl(fd, CDROM_GET_CAPABILITY, 0); (void)ret; - } + }, return); #endif #if defined(CDROM_CHANGER_NSLOTS) - { + IOCTL_TIMEOUT(0.10, { int ret; ret = ioctl(fd, CDROM_CHANGER_NSLOTS, 0); (void)ret; - } + }, return); #endif #if defined(CDROM_NEXT_WRITABLE) - { + IOCTL_TIMEOUT(0.10, { int ret; long next; ret = ioctl(fd, CDROM_NEXT_WRITABLE, &next); (void)ret; - } + }, return); #endif #if defined(CDROM_LAST_WRITTEN) - { + IOCTL_TIMEOUT(0.10, { int ret; long last; ret = ioctl(fd, CDROM_LAST_WRITTEN, &last); (void)ret; - } + }, return); #endif -#if defined(CDROM_MEDIA_CHANGED) - { - int ret, slot = 0; +#if defined(CDROM_MEDIA_CHANGED) && 0 + IOCTL_TIMEOUT(0.10, { + int ret; + int slot = 0; ret = ioctl(fd, CDROM_MEDIA_CHANGED, slot); (void)ret; - + }, return); +#endif #if defined(CDSL_NONE) - slot = CDSL_NONE; + IOCTL_TIMEOUT(0.10, { + int ret; + int slot = CDSL_NONE; + ret = ioctl(fd, CDROM_MEDIA_CHANGED, slot); (void)ret; + }, return); #endif #if defined(CDSL_CURRENT) - slot = CDSL_CURRENT; + IOCTL_TIMEOUT(0.10, { + int ret; + int slot = CDSL_CURRENT; + ret = ioctl(fd, CDROM_MEDIA_CHANGED, slot); (void)ret; -#endif - } + }, return); #endif #if defined(CDROMPAUSE) - { + IOCTL_TIMEOUT(0.10, { int ret; ret = ioctl(fd, CDROMPAUSE, 0); (void)ret; - } + }, return); #endif #if defined(CDROMRESUME) - { + IOCTL_TIMEOUT(0.10, { int ret; ret = ioctl(fd, CDROMRESUME, 0); (void)ret; - } + }, return); #endif #if defined(CDROM_DRIVE_STATUS) - { - int ret, slot = 0; + IOCTL_TIMEOUT(0.10, { + int ret; + int slot = 0; ret = ioctl(fd, CDROM_DRIVE_STATUS, slot); (void)ret; - + }, return); #if defined(CDSL_NONE) - slot = CDSL_NONE; + IOCTL_TIMEOUT(0.10, { + int ret; + int slot = CDSL_NONE; + ret = ioctl(fd, CDROM_DRIVE_STATUS, slot); (void)ret; + }, return); #endif #if defined(CDSL_CURRENT) - slot = CDSL_CURRENT; + IOCTL_TIMEOUT(0.10, { + int ret; + int slot = CDSL_CURRENT; + ret = ioctl(fd, CDROM_DRIVE_STATUS, slot); (void)ret; + }, return); #endif - } #endif #if defined(DVD_READ_STRUCT) && \ defined(HAVE_DVD_STRUCT) - { + IOCTL_TIMEOUT(0.10, { dvd_struct s; int ret; @@ -1456,20 +1604,21 @@ s.type = UINT8_MAX; ret = ioctl(fd, DVD_READ_STRUCT, &s); (void)ret; - } + }, return); #endif #if defined(CDROMAUDIOBUFSIZ) - { - int val = INT_MIN, ret; + IOCTL_TIMEOUT(0.10, { + int val = INT_MIN; + int ret; /* Invalid CDROMAUDIOBUFSIZ call with negative buffer size */ ret = ioctl(fd, CDROMAUDIOBUFSIZ, val); (void)ret; - } + }, return); #endif #if defined(DVD_AUTH) && \ defined(HAVE_DVD_AUTHINFO) - { + IOCTL_TIMEOUT(0.40, { int ret; dvd_authinfo ai; @@ -1537,12 +1686,13 @@ ai.type = ~0; ret = ioctl(fd, DVD_AUTH, &ai); (void)ret; - } + }, return); #endif #if defined(CDROM_DEBUG) - { - int debug, ret; + IOCTL_TIMEOUT(0.10, { + int debug; + int ret; /* Enable the DEBUG Messages */ debug = 1; @@ -1553,32 +1703,33 @@ debug = 0; ret = ioctl(fd, CDROM_DEBUG, debug); (void)ret; - } + }, return); #endif #if defined(CDROM_SELECT_SPEED) - { - int ret, i; + IOCTL_TIMEOUT(0.10, { + unsigned int i; unsigned int speed; + int ret; for (i = 8; i < 16; i++) { speed = 1UL << i; ret = ioctl(fd, CDROM_SELECT_SPEED, speed); (void)ret; } - } + }, return); #endif #if defined(CDROMPLAYBLK) && \ defined(HAVE_CDROM_BLK) - { + IOCTL_TIMEOUT(0.10, { struct cdrom_blk blk; int ret; (void)memset(&blk, 0, sizeof(blk)); ret = ioctl(fd, CDROMPLAYBLK, &blk); (void)ret; - } + }, return); #endif } #endif @@ -1768,6 +1919,40 @@ } #endif +#if defined(HAVE_LINUX_KD_H) && \ + defined(GIO_SCRNMAP) && \ + defined(E_TABSZ) + { + unsigned char argp[E_TABSZ]; + int ret; + + ret = ioctl(fd, GIO_SCRNMAP, argp); +#if defined(PIO_SCRNMAP) + if (ret == 0) { + ret = ioctl(fd, PIO_SCRNMAP, argp); + } +#endif + (void)ret; + } +#endif + +#if defined(HAVE_LINUX_KD_H) && \ + defined(GIO_UNISCRNMAP) && \ + defined(E_TABSZ) + { + unsigned short argp[E_TABSZ]; + int ret; + + ret = ioctl(fd, GIO_UNISCRNMAP, argp); +#if defined(PIO_UNISCRNMAP) + if (ret == 0) { + ret = ioctl(fd, PIO_UNISCRNMAP, argp); + } +#endif + (void)ret; + } +#endif + #if defined(HAVE_LINUX_KD_H) && \ defined(KDGKBMODE) { @@ -1839,6 +2024,74 @@ } #endif +#if defined(HAVE_LINUX_KD_H) && \ + defined(KDGKBDIACR) && \ + defined(HAVE_KBDIACRS) + { + int ret; + struct kbdiacrs argp; + + (void)memset(&argp, 0, sizeof(argp)); + ret = ioctl(fd, KDGKBDIACR, &argp); + (void)ret; + } +#endif + +#if defined(HAVE_LINUX_KD_H) && \ + defined(VT_RESIZE) && \ + defined(HAVE_VT_SIZES) && \ + defined(CAP_SYS_TTY_CONFIG) + { + int ret; + struct vt_sizes argp; + bool perm = stress_check_capability(CAP_SYS_TTY_CONFIG); + + /* Exercise only if permission is not present */ + if (!perm) { + (void)memset(&argp, 0, sizeof(argp)); + ret = ioctl(fd, VT_RESIZE, &argp); + (void)ret; + } + } +#endif + +#if defined(HAVE_LINUX_KD_H) && \ + defined(VT_RESIZEX) && \ + defined(HAVE_VT_CONSIZE) && \ + defined(CAP_SYS_TTY_CONFIG) + { + int ret; + struct vt_consize argp; + bool perm = stress_check_capability(CAP_SYS_TTY_CONFIG); + + /* Exercise only if permission is not present */ + if (!perm) { + (void)memset(&argp, 0, sizeof(argp)); + ret = ioctl(fd, VT_RESIZEX, &argp); + (void)ret; + } + } +#endif + +#if defined(HAVE_LINUX_KD_H) && \ + defined(KDGKBSENT) && \ + defined(HAVE_KBSENTRY) + { + int ret; + struct kbsentry argp; + + (void)memset(&argp, 0, sizeof(argp)); + ret = ioctl(fd, KDGKBSENT, &argp); +#if defined(KDSKBSENT) + if (ret == 0) { + ret = ioctl(fd, KDSKBSENT, &argp); + (void)ret; + } +#endif + (void)ret; + } +#endif + #if defined(HAVE_LINUX_VT_H) && \ defined(VT_GETMODE) && \ defined(HAVE_VT_MODE) @@ -1943,6 +2196,12 @@ (void)fd; (void)devpath; + /* + * Avoid https://bugs.xenserver.org/browse/XSO-809 + */ + if (linux_xen_guest()) + return; + #if defined(HPET_INFO) { struct hpet_info info; @@ -2226,7 +2485,8 @@ double t_start; bool timeout = false; #if defined(HAVE_TERMIOS_H) && \ - defined(TCGETS) + defined(TCGETS) && \ + defined(HAVE_TERMIOS) struct termios tios; #endif ret = shim_pthread_spin_lock(&lock); @@ -2240,7 +2500,6 @@ t_start = stress_time_now(); - if ((fd = open(path, O_RDONLY | O_NONBLOCK)) < 0) { if (errno == EINTR) goto next; @@ -2271,7 +2530,8 @@ #endif } #if defined(HAVE_TERMIOS_H) && \ - defined(TCGETS) + defined(TCGETS) && \ + defined(HAVE_TERMIOS) if (S_ISCHR(buf.st_mode) && strncmp("/dev/vsock", path, 9) && strncmp("/dev/dri", path, 7) && @@ -2494,10 +2754,10 @@ continue; /* - * Xen clients hang on hpet when running as root - * see: LP#1741409, so avoid opening /dev/hpet - */ - if (!euid && !strcmp(d->d_name, "hpet")) + * Avoid https://bugs.xenserver.org/browse/XSO-809 + * see: LP#1741409, so avoid opening /dev/hpet + */ + if (!strcmp(d->d_name, "hpet") && linux_xen_guest()) continue; len = strlen(d->d_name); @@ -2517,7 +2777,7 @@ continue; } - (void)snprintf(tmp, sizeof(tmp), "%s/%s", path, d->d_name); + (void)stress_mk_filename(tmp, sizeof(tmp), path, d->d_name); switch (d->d_type) { case DT_DIR: if (!recurse) @@ -2695,6 +2955,13 @@ (void)shim_pthread_spin_destroy(&lock); + /* + * Ensure we don't get build warnings if these are not + * referenced. + */ + (void)ioctl_set_timeout; + (void)ioctl_clr_timeout; + return rc; } stressor_info_t stress_dev_info = { diff -Nru stress-ng-0.11.19/stress-dirdeep.c stress-ng-0.11.21/stress-dirdeep.c --- stress-ng-0.11.19/stress-dirdeep.c 2020-08-24 14:14:41.000000000 +0000 +++ stress-ng-0.11.21/stress-dirdeep.c 2020-09-16 22:00:11.000000000 +0000 @@ -61,32 +61,6 @@ } /* - * stress_dirdeep_sync() - * attempt to sync a directory - */ -static void stress_dirdeep_sync(const char *path) -{ -#if defined(O_DIRECTORY) - int fd; - - fd = open(path, O_RDONLY | O_DIRECTORY); - if (fd < 0) - return; - - /* - * The interesting part of fsync is that in - * theory we can fsync a read only file and - * this could be a directory too. So try and - * sync. - */ - (void)shim_fsync(fd); - (void)close(fd); -#else - (void)path; -#endif -} - -/* * stress_dirdeep_make() * depth-first tree creation, create lots of sub-trees with * dirdeep_dir number of subtress per level. @@ -105,6 +79,10 @@ { uint32_t i; int ret; +#if defined(HAVE_LINKAT) && \ + defined(O_DIRECTORY) + int dirfd; +#endif const uint64_t inodes_avail = stress_get_filesystem_available_inodes(); if (*min_inodes_free > inodes_avail) @@ -145,6 +123,7 @@ (void)close(fd); } + path[len] = '/'; path[len + 1] = 's'; /* symlink */ path[len + 2] = '\0'; @@ -155,15 +134,70 @@ ret = link(linkpath, path); (void)ret; - for (i = 0; i < dirdeep_dirs; i++) { + for (i = 0; keep_stressing() && (i < dirdeep_dirs); i++) { path[len + 1] = '0' + i; - stress_dirdeep_make(args, linkpath, path, len + 2, path_len, - dirdeep_dirs, dirdeep_inodes, inodes_target_free, - min_inodes_free, depth + 1); + stress_dirdeep_make(args, linkpath, path, len + 2, + path_len, dirdeep_dirs, dirdeep_inodes, + inodes_target_free, min_inodes_free, + depth + 1); } + if (!keep_stressing()) + return; path[len] = '\0'; - stress_dirdeep_sync(path); +#if defined(HAVE_LINKAT) && \ + defined(O_DIRECTORY) + + dirfd = open(path, O_RDONLY | O_DIRECTORY); + if (dirfd >= 0) { +#if defined(AT_EMPTY_PATH) && \ + defined(O_PATH) + int pathfd; +#endif + + /* + * Exercise linkat onto hardlink h + */ + ret = linkat(dirfd, "h", dirfd, "a", 0); + (void)ret; +#if defined(AT_SYMLINK_FOLLOW) + /* + * Exercise linkat AT_SYMLINK_FOLLOW onto hardlink h + */ + ret = linkat(dirfd, "h", dirfd, "b", AT_SYMLINK_FOLLOW); + (void)ret; +#endif +#if defined(AT_EMPTY_PATH) && \ + defined(O_PATH) + /* + * Exercise linkat AT_EMPTY_PATH onto hardlink h + */ + path[len] = '/'; + path[len + 1] = 'h'; + path[len + 2] = '\0'; + + pathfd = open(path, O_PATH | O_RDONLY); + if (pathfd >= 0) { + /* + * Need CAP_DAC_READ_SEARCH for this to work, + * ignore return for now + */ + ret = linkat(pathfd, "", dirfd, "c", AT_EMPTY_PATH); + (void)ret; + (void)close(pathfd); + } + path[len] = '\0'; +#endif + /* + * The interesting part of fsync is that in + * theory we can fsync a read only file and + * this could be a directory too. So try and + * sync. + */ + (void)shim_fsync(dirfd); + (void)close(dirfd); + } +#endif } /* @@ -187,6 +221,8 @@ { sec, nsec } }; #endif + if (!keep_stressing()) + return; if (len + 2 >= path_len) return; @@ -304,8 +340,7 @@ (void)stress_temp_dir_args(args, rootpath, sizeof(rootpath)); path_len = strlen(rootpath); - (void)shim_strlcpy(linkpath, rootpath, sizeof(linkpath)); - (void)shim_strlcat(linkpath, "/f", sizeof(linkpath) - 3); + (void)stress_mk_filename(linkpath, sizeof(linkpath), rootpath, "/f"); pr_dbg("%s: %" PRIu64 " inodes available, exercising up to %" PRIu64 " inodes\n", args->name, inodes_avail, inodes_avail - inodes_target_free); diff -Nru stress-ng-0.11.19/stress-dnotify.c stress-ng-0.11.21/stress-dnotify.c --- stress-ng-0.11.19/stress-dnotify.c 2020-08-24 14:14:41.000000000 +0000 +++ stress-ng-0.11.21/stress-dnotify.c 2020-09-16 22:00:11.000000000 +0000 @@ -147,19 +147,6 @@ } /* - * mk_filename() - * simple helper to create a filename - */ -static inline void mk_filename( - char *filename, - const size_t len, - const char *path, - const char *name) -{ - (void)snprintf(filename, len, "%s/%s", path, name); -} - -/* * mk_file() * create file of length len bytes */ @@ -220,7 +207,7 @@ { char filepath[PATH_MAX]; - mk_filename(filepath, PATH_MAX, path, "dnotify_file"); + stress_mk_filename(filepath, sizeof(filepath), path, "dnotify_file"); if (mk_file(args, filepath, 4096) < 0) return; @@ -262,7 +249,7 @@ { char filepath[PATH_MAX]; - mk_filename(filepath, PATH_MAX, path, "dnotify_file"); + stress_mk_filename(filepath, sizeof(filepath), path, "dnotify_file"); if (mk_file(args, filepath, 4096) < 0) return; @@ -306,7 +293,7 @@ { char filepath[PATH_MAX]; - mk_filename(filepath, PATH_MAX, path, "dnotify_file"); + stress_mk_filename(filepath, sizeof(filepath), path, "dnotify_file"); dnotify_exercise(args, filepath, path, dnotify_modify_helper, DN_MODIFY, NULL); } @@ -331,7 +318,7 @@ { char filepath[PATH_MAX]; - mk_filename(filepath, PATH_MAX, path, "dnotify_file"); + stress_mk_filename(filepath, sizeof(filepath), path, "dnotify_file"); dnotify_exercise(args, filepath, path, dnotify_creat_helper, DN_CREATE, NULL); (void)rm_file(args, filepath); @@ -351,7 +338,7 @@ { char filepath[PATH_MAX]; - mk_filename(filepath, PATH_MAX, path, "dnotify_file"); + stress_mk_filename(filepath, sizeof(filepath), path, "dnotify_file"); if (mk_file(args, filepath, 4096) < 0) return; dnotify_exercise(args, filepath, path, @@ -379,8 +366,8 @@ { char oldfile[PATH_MAX], newfile[PATH_MAX]; - mk_filename(oldfile, PATH_MAX, path, "dnotify_file"); - mk_filename(newfile, PATH_MAX, path, "dnotify_file_renamed"); + stress_mk_filename(oldfile, sizeof(oldfile), path, "dnotify_file"); + stress_mk_filename(newfile, sizeof(newfile), path, "dnotify_file_renamed"); if (mk_file(args, oldfile, 4096) < 0) return; diff -Nru stress-ng-0.11.19/stress-efivar.c stress-ng-0.11.21/stress-efivar.c --- stress-ng-0.11.19/stress-efivar.c 2020-08-24 14:14:41.000000000 +0000 +++ stress-ng-0.11.21/stress-efivar.c 2020-09-16 22:00:11.000000000 +0000 @@ -129,7 +129,7 @@ char filename[PATH_MAX]; struct stat statbuf; - (void)snprintf(filename, sizeof filename, + (void)snprintf(filename, sizeof(filename), "%s/%s/%s", vars, varname, field); if ((fd = open(filename, O_RDONLY)) < 0) return rc; @@ -184,7 +184,7 @@ (void)efi_get_data(args, varname, efi_sysfs_names[i], data, sizeof(data)); } - (void)snprintf(filename, sizeof filename, "%s/%s", efi_vars, varname); + (void)stress_mk_filename(filename, sizeof(filename), efi_vars, varname); if ((fd = open(filename, O_RDONLY)) < 0) return -1; diff -Nru stress-ng-0.11.19/stress-enosys.c stress-ng-0.11.21/stress-enosys.c --- stress-ng-0.11.19/stress-enosys.c 2020-08-24 14:14:41.000000000 +0000 +++ stress-ng-0.11.21/stress-enosys.c 2020-09-16 22:00:11.000000000 +0000 @@ -82,9 +82,9 @@ * x86_64_syscall6() * syscall 6 arg wrapper */ -static inline long x86_64_syscall6(long number, long arg1, long arg2, - long arg3, long arg4, long arg5, - long arg6) +static inline long x86_64_syscall6( + long number, long arg1, long arg2, + long arg3, long arg4, long arg5, long arg6) { long ret; unsigned long _arg1 = arg1; @@ -115,32 +115,34 @@ #endif #if defined(STRESS_EXERCISE_X86_0X80) -static inline long x86_0x80_syscall6(long number, long arg1, long arg2, - long arg3, long arg4, long arg5, - long arg6) +static inline int x86_0x80_syscall6( + long number, long arg1, long arg2, + long arg3, long arg4, long arg5, + long arg6) { - long ret; - unsigned int _num = number; - unsigned int _arg1 = arg1; - unsigned int _arg2 = arg2; - unsigned int _arg3 = arg3; - unsigned int _arg4 = arg4; - unsigned int _arg5 = arg5; - unsigned int _arg6 = arg6; + int ret; - register int __num asm ("eax") = _num; - register int __arg1 asm ("ebx") = _arg1; - register int __arg2 asm ("ecx") = _arg2; - register int __arg3 asm ("edx") = _arg3; - register int __arg4 asm ("esi") = _arg4; - register int __arg5 asm ("edi") = _arg5; - register int __arg6 asm ("ebp") = _arg6; + asm ( + "movl %6, %%eax\n" + "movl %%eax, %%ebp\n" + "movl %0, %%eax\n" + "movl %1, %%ebx\n" + "movl %2, %%ecx\n" + "movl %3, %%edx\n" + "movl %4, %%esi\n" + "movl %5, %%edi\n" + "int $0x80\n" + "" + : [ret] "=rm" (ret) + : "m" (number), + "m" (arg1), + "m" (arg2), + "m" (arg3), + "m" (arg4), + "m" (arg5), + "m" (arg6) + : "memory"); - asm volatile ("int $0x80\n\t" - : "=a" (ret) - : "0" (__num), "r" (__arg1), "r" (__arg2), "r" (__arg3), - "r" (__arg4), "r" (__arg5), "r" (__arg6) - : "memory"); if (ret < 0) { errno = -ret; ret = -1; diff -Nru stress-ng-0.11.19/stress-epoll.c stress-ng-0.11.21/stress-epoll.c --- stress-ng-0.11.19/stress-epoll.c 2020-08-24 14:14:41.000000000 +0000 +++ stress-ng-0.11.21/stress-epoll.c 2020-09-16 22:00:11.000000000 +0000 @@ -36,6 +36,7 @@ #define MAX_SERVERS (4) #if defined(HAVE_SYS_EPOLL_H) && \ + defined(HAVE_EPOLL_CREATE) && \ defined(HAVE_LIB_RT) && \ defined(HAVE_TIMER_CREATE) && \ defined(HAVE_TIMER_DELETE) && \ @@ -102,6 +103,7 @@ }; #if defined(HAVE_SYS_EPOLL_H) && \ + defined(HAVE_EPOLL_CREATE) && \ defined(HAVE_LIB_RT) && \ defined(HAVE_TIMER_CREATE) && \ defined(HAVE_TIMER_DELETE) && \ diff -Nru stress-ng-0.11.19/stress-eventfd.c stress-ng-0.11.21/stress-eventfd.c --- stress-ng-0.11.19/stress-eventfd.c 2020-08-24 14:14:41.000000000 +0000 +++ stress-ng-0.11.21/stress-eventfd.c 2020-09-16 22:00:11.000000000 +0000 @@ -55,7 +55,7 @@ static int stress_eventfd(const stress_args_t *args) { pid_t pid; - int fd1, fd2, rc; + int fd1, fd2, test_fd, rc; int flags = 0; bool eventfd_nonblock = false; @@ -88,6 +88,11 @@ return rc; } + /* Exercise eventfd on invalid flags */ + test_fd = eventfd(0, ~0); + if (test_fd >= 0) + (void)close(test_fd); + again: pid = fork(); if (pid < 0) { @@ -100,13 +105,20 @@ (void)close(fd2); return EXIT_FAILURE; } else if (pid == 0) { + int n = 0; + (void)setpgid(0, g_pgrp); stress_parent_died_alarm(); (void)sched_settings_apply(true); while (keep_stressing_flag()) { - uint64_t val; + uint64_t val = 0; ssize_t ret; + char re[7]; + + /* Exercise read on small buffer */ + ret = read(fd1, re, sizeof(re)); + (void)ret; for (;;) { if (!keep_stressing_flag()) @@ -127,8 +139,24 @@ } break; } - val = 1; + /* + * Periodically exercise with invalid writes + */ + if (n++ >= 64) { + n = 0; + + /* Exercise write using small buffer */ + ret = write(fd1, re, sizeof(re)); + (void)ret; + + /* Exercise write on buffer out of range */ + val = ~0; + ret = write(fd1, &val, sizeof(val)); + (void)ret; + } + + val = 1; for (;;) { if (!keep_stressing_flag()) goto exit_child; diff -Nru stress-ng-0.11.19/stress-fallocate.c stress-ng-0.11.21/stress-fallocate.c --- stress-ng-0.11.19/stress-fallocate.c 2020-08-24 14:14:41.000000000 +0000 +++ stress-ng-0.11.21/stress-fallocate.c 2020-09-16 22:00:11.000000000 +0000 @@ -68,6 +68,25 @@ }; /* + * illegal mode flags mixes + */ +static const int illegal_modes[] = { + ~0, +#if defined(FALLOC_FL_PUNCH_HOLE) && defined(FALLOC_FL_ZERO_RANGE) + FALLOC_FL_PUNCH_HOLE | FALLOC_FL_ZERO_RANGE, +#endif +#if defined(FALLOC_FL_PUNCH_HOLE) + FALLOC_FL_PUNCH_HOLE, +#endif +#if defined(FALLOC_FL_COLLAPSE_RANGE) && defined(FALLOC_FL_ZERO_RANGE) + FALLOC_FL_COLLAPSE_RANGE | FALLOC_FL_ZERO_RANGE, +#endif +#if defined(FALLOC_FL_INSERT_RANGE) && defined(FALLOC_FL_ZERO_RANGE) + FALLOC_FL_INSERT_RANGE | FALLOC_FL_ZERO_RANGE, +#endif +}; + +/* * stress_fallocate * stress I/O via fallocate and ftruncate */ @@ -78,6 +97,7 @@ char filename[PATH_MAX]; uint64_t ftrunc_errs = 0; off_t fallocate_bytes = DEFAULT_FALLOCATE_BYTES; + int pipe_fds[2], pipe_ret; if (!stress_get_setting("fallocate-bytes", &fallocate_bytes)) { if (g_opt_flags & OPT_FLAGS_MAXIMIZE) @@ -104,6 +124,8 @@ } (void)unlink(filename); + pipe_ret = pipe(pipe_fds); + do { #if defined(HAVE_POSIX_FALLOCATE) ret = posix_fallocate(fd, (off_t)0, fallocate_bytes); @@ -156,6 +178,7 @@ * non-portable Linux fallocate() */ int i; + (void)shim_fallocate(fd, 0, (off_t)0, fallocate_bytes); if (!keep_stressing_flag()) break; @@ -163,7 +186,7 @@ for (i = 0; i < 64; i++) { off_t offset = (stress_mwc64() % fallocate_bytes) & ~0xfff; - int j = (stress_mwc32() >> 8) % SIZEOF_ARRAY(modes); + size_t j = (stress_mwc32() >> 8) % SIZEOF_ARRAY(modes); (void)shim_fallocate(fd, modes[j], offset, 64 * KB); if (!keep_stressing_flag()) @@ -186,11 +209,46 @@ #endif (void)ret; + /* + * Exercise with various illegal mode flags + */ + if (SIZEOF_ARRAY(illegal_modes) > 1) { + size_t i; + + for (i = 0; i < SIZEOF_ARRAY(illegal_modes); i++) { + ret = shim_fallocate(fd, illegal_modes[i], (off_t)0, fallocate_bytes); + (void)ret; + } + } + + /* + * fallocate on a pipe is illegal + */ + if (pipe_ret == 0) { + ret = posix_fallocate(pipe_fds[0], (off_t)0, fallocate_bytes); + (void)ret; + ret = posix_fallocate(pipe_fds[1], (off_t)0, fallocate_bytes); + (void)ret; + } + /* + * exercise illegal negative offset and lengths + */ + ret = posix_fallocate(fd, (off_t)-1, (off_t)0); + (void)ret; + ret = posix_fallocate(fd, (off_t)0, (off_t)-1); + (void)ret; + ret = posix_fallocate(fd, (off_t)-1, (off_t)-1); + (void)ret; + inc_counter(args); } while (keep_stressing()); if (ftrunc_errs) pr_dbg("%s: %" PRIu64 " ftruncate errors occurred.\n", args->name, ftrunc_errs); + if (pipe_ret == 0) { + (void)close(pipe_fds[0]); + (void)close(pipe_fds[1]); + } (void)close(fd); (void)stress_temp_dir_rm_args(args); diff -Nru stress-ng-0.11.19/stress-fanotify.c stress-ng-0.11.21/stress-fanotify.c --- stress-ng-0.11.19/stress-fanotify.c 2020-08-24 14:14:41.000000000 +0000 +++ stress-ng-0.11.21/stress-fanotify.c 2020-09-16 22:00:11.000000000 +0000 @@ -209,15 +209,83 @@ } /* + * test_fanotify_mark() + * tests fanotify_mark syscall + */ +static int test_fanotify_mark(const char *name, char *mounts[]) +{ + int ret_fd, ret; +#if defined(FAN_MARK_INODE) + const int bad_fd = stress_get_bad_fd(); +#endif + + ret_fd = fanotify_init(0, 0); + if (ret_fd < 0) { + pr_err("%s: cannot initialize fanotify, errno=%d (%s)\n", + name, errno, strerror(errno)); + return -1; + } + + /* Exercise fanotify_mark with invalid mask */ +#if defined(FAN_MARK_MOUNT) + ret = fanotify_mark(ret_fd, FAN_MARK_ADD | FAN_MARK_MOUNT, + ~0, AT_FDCWD, mounts[0]); + (void)ret; +#endif + + /* Exercise fanotify_mark with invalid flag */ + ret = fanotify_mark(ret_fd, ~0, FAN_ACCESS, AT_FDCWD, mounts[0]); + (void)ret; + + /* Exercise fanotify_mark on bad fd */ +#if defined(FAN_MARK_INODE) + ret = fanotify_mark(bad_fd, FAN_MARK_ADD | FAN_MARK_INODE, + FAN_ACCESS, AT_FDCWD, mounts[0]); + (void)ret; +#endif + + /* Exercise fanotify_mark by passing two operations simultaneously */ + ret = fanotify_mark(ret_fd, FAN_MARK_REMOVE | FAN_MARK_ADD, + FAN_ACCESS, AT_FDCWD, mounts[0]); + (void)ret; + + /* Exercise valid fanotify_mark to increase kernel coverage */ +#if defined(FAN_MARK_INODE) + ret = fanotify_mark(ret_fd, FAN_MARK_ADD | FAN_MARK_INODE, + FAN_ACCESS, AT_FDCWD, mounts[0]); + (void)ret; +#endif + +#if defined(FAN_MARK_IGNORED_MASK) + ret = fanotify_mark(ret_fd, FAN_MARK_ADD | FAN_MARK_IGNORED_MASK, + FAN_ACCESS, AT_FDCWD, mounts[0]); + (void)ret; +#endif + + /* Exercise other invalid combinations of flags */ + ret = fanotify_mark(ret_fd, FAN_MARK_REMOVE, + 0, AT_FDCWD, mnts[0]); + (void)ret; + +#if defined(FAN_MARK_ONLYDIR) + ret = fanotify_mark(ret_fd, FAN_MARK_FLUSH | FAN_MARK_ONLYDIR, + FAN_ACCESS, AT_FDCWD, mnts[0]); + (void)ret; +#endif + + (void)close(ret_fd); + + return 0; +} + +/* * fanotify_event_init() * initialize fanotify */ -static int fanotify_event_init(const char *name) +static int fanotify_event_init(const char *name, char *mounts[]) { int fan_fd, count = 0, i; - (void)memset(mnts, 0, sizeof(mnts)); - fan_fd = fanotify_init(0, 0); if (fan_fd < 0) { pr_err("%s: cannot initialize fanotify, errno=%d (%s)\n", @@ -225,16 +293,6 @@ return -1; } - /* do all mount points */ - n_mnts = stress_mount_get(mnts, MAX_MNTS); - if (n_mnts < 1) { - pr_err("%s: setmntent cannot get mount points from " - "/proc/self/mounts, errno=%d (%s)\n", - name, errno, strerror(errno)); - (void)close(fan_fd); - return -1; - } - /* * Gather all mounted file systems and monitor them */ @@ -247,14 +305,14 @@ for (j = 0; j < SIZEOF_ARRAY(fan_stress_settings); j++) { #if defined(FAN_MARK_MOUNT) ret = fanotify_mark(fan_fd, FAN_MARK_ADD | FAN_MARK_MOUNT, - fan_stress_settings[j], AT_FDCWD, mnts[i]); + fan_stress_settings[j], AT_FDCWD, mounts[i]); if (ret == 0) count++; #endif #if defined(FAN_MARK_FILESYSTEM) ret = fanotify_mark(fan_fd, FAN_MARK_ADD | FAN_MARK_FILESYSTEM, - fan_stress_settings[j], AT_FDCWD, mnts[i]); + fan_stress_settings[j], AT_FDCWD, mounts[i]); if (ret == 0) count++; #endif @@ -329,12 +387,23 @@ (void)memset(&account, 0, sizeof(account)); stress_temp_dir_args(args, pathname, sizeof(pathname)); - (void)snprintf(filename, sizeof(filename), "%s/%s", pathname, "fanotify_file"); + (void)stress_mk_filename(filename, sizeof(filename), pathname, "fanotify_file"); ret = stress_temp_dir_mk_args(args); if (ret < 0) return exit_status(-ret); pid = fork(); + + /* do all mount points */ + (void)memset(mnts, 0, sizeof(mnts)); + + n_mnts = stress_mount_get(mnts, MAX_MNTS); + if (n_mnts < 1) { + pr_err("%s: cannot get mount point information\n", args->name); + rc = EXIT_NO_RESOURCE; + goto tidy; + } + if (pid < 0) { pr_err("%s: fork failed: errno=%d (%s)\n", args->name, errno, strerror(errno)); @@ -402,13 +471,20 @@ goto tidy; } - fan_fd = fanotify_event_init(args->name); + fan_fd = fanotify_event_init(args->name, mnts); if (fan_fd < 0) { free(buffer); rc = EXIT_FAILURE; goto tidy; } + ret = test_fanotify_mark(args->name, mnts); + if (ret < 0) { + free(buffer); + rc = EXIT_FAILURE; + goto tidy; + } + do { fd_set rfds; ssize_t len; @@ -473,6 +549,87 @@ metadata = FAN_EVENT_NEXT(metadata, len); } } + + /* + * Exercise fanotify_init with all possible values + * of flag argument to increase kernel coverage + */ +#if defined(FAN_CLASS_CONTENT) + { + int ret_fd; + + ret_fd = fanotify_init(FAN_CLASS_CONTENT, 0); + if (ret_fd != -1) { + (void)close(ret_fd); + } + } +#endif + +#if defined(FAN_CLASS_PRE_CONTENT) + { + int ret_fd; + + ret_fd = fanotify_init(FAN_CLASS_PRE_CONTENT, 0); + if (ret_fd != -1) { + (void)close(ret_fd); + } + } +#endif + +#if defined(FAN_UNLIMITED_QUEUE) + { + int ret_fd; + + ret_fd = fanotify_init(FAN_UNLIMITED_QUEUE, 0); + if (ret_fd != -1) { + (void)close(ret_fd); + } + } +#endif + +#if defined(FAN_UNLIMITED_MARKS) + { + int ret_fd; + + ret_fd = fanotify_init(FAN_UNLIMITED_MARKS, 0); + if (ret_fd != -1) { + (void)close(ret_fd); + } + } +#endif + +#if defined(FAN_CLOEXEC) + { + int ret_fd; + + ret_fd = fanotify_init(FAN_CLOEXEC, 0); + if (ret_fd != -1) { + (void)close(ret_fd); + } + } +#endif + +#if defined(FAN_NONBLOCK) + { + int ret_fd; + + ret_fd = fanotify_init(FAN_NONBLOCK, 0); + if (ret_fd != -1) { + (void)close(ret_fd); + } + } +#endif + +#if defined(FAN_ENABLE_AUDIT) + { + int ret_fd; + + ret_fd = fanotify_init(FAN_ENABLE_AUDIT, 0); + if (ret_fd != -1) { + (void)close(ret_fd); + } + } +#endif } while (keep_stressing()); free(buffer); diff -Nru stress-ng-0.11.19/stress-filename.c stress-ng-0.11.21/stress-filename.c --- stress-ng-0.11.19/stress-filename.c 2020-08-24 14:14:41.000000000 +0000 +++ stress-ng-0.11.21/stress-filename.c 2020-09-16 22:00:11.000000000 +0000 @@ -196,8 +196,8 @@ if (stress_is_dot_filename(d->d_name)) continue; - (void)snprintf(filename, sizeof(filename), - "%s/%s", path, d->d_name); + (void)stress_mk_filename(filename, sizeof(filename), + path, d->d_name); (void)unlink(filename); } (void)closedir(dir); diff -Nru stress-ng-0.11.19/stress-fstat.c stress-ng-0.11.21/stress-fstat.c --- stress-ng-0.11.19/stress-fstat.c 2020-08-24 14:14:41.000000000 +0000 +++ stress-ng-0.11.21/stress-fstat.c 2020-09-16 22:00:11.000000000 +0000 @@ -255,7 +255,7 @@ goto free_cache; } - (void)snprintf(path, sizeof(path), "%s/%s", fstat_dir, d->d_name); + (void)stress_mk_filename(path, sizeof(path), fstat_dir, d->d_name); if (do_not_stat(path)) continue; if ((si = calloc(1, sizeof(*si))) == NULL) { diff -Nru stress-ng-0.11.19/stress-getdent.c stress-ng-0.11.21/stress-getdent.c --- stress-ng-0.11.19/stress-getdent.c 2020-08-24 14:14:41.000000000 +0000 +++ stress-ng-0.11.21/stress-getdent.c 2020-09-16 22:00:11.000000000 +0000 @@ -148,7 +148,7 @@ stress_is_dot_filename(d->d_name)) { char newpath[PATH_MAX]; - (void)snprintf(newpath, sizeof(newpath), "%s/%s", path, d->d_name); + (void)stress_mk_filename(newpath, sizeof(newpath), path, d->d_name); rc = stress_getdents_rand(args, newpath, recurse, depth - 1, page_size, bad_fd); if (rc < 0) goto exit_free; @@ -223,7 +223,7 @@ stress_is_dot_filename(d->d_name)) { char newpath[PATH_MAX]; - (void)snprintf(newpath, sizeof(newpath), "%s/%s", path, d->d_name); + (void)stress_mk_filename(newpath, sizeof(newpath), path, d->d_name); rc = stress_getdents_rand(args, newpath, recurse, depth - 1, page_size, bad_fd); if (rc < 0) goto exit_free; diff -Nru stress-ng-0.11.19/stress-inotify.c stress-ng-0.11.21/stress-inotify.c --- stress-ng-0.11.19/stress-inotify.c 2020-08-24 14:14:41.000000000 +0000 +++ stress-ng-0.11.21/stress-inotify.c 2020-09-16 22:00:11.000000000 +0000 @@ -33,6 +33,7 @@ }; #if defined(HAVE_INOTIFY) && \ + defined(HAVE_INOTIFY1) && \ defined(HAVE_SYS_INOTIFY_H) && \ defined(HAVE_SYS_SELECT_H) && \ NEED_GLIBC(2,9,0) @@ -44,7 +45,7 @@ #define BUF_SIZE (4096) typedef int (*stress_inotify_helper)(const stress_args_t *args, const char *path, const void *private); -typedef void (*stress_inotify_func)(const stress_args_t *args, const char *path); +typedef void (*stress_inotify_func)(const stress_args_t *args, const char *path, const int bad_fd); typedef struct { const stress_inotify_func func; @@ -52,6 +53,128 @@ } stress_inotify_t; /* + * exercise_inotify1() + * exercise inotify1 with all valid and invalid flags + */ +static void exercise_inotify1() +{ +#if defined(IN_NONBLOCK) && defined(IN_CLOEXEC) + int fd; + + fd = inotify_init1(IN_NONBLOCK); + if (fd >= 0) + (void)close(fd); + + fd = inotify_init1(IN_CLOEXEC); + if (fd >= 0) + (void)close(fd); + + /* Exercise inotify1 with invalid flag */ + fd = inotify_init1(~0); + if (fd >= 0) + (void)close(fd); +#endif +} + +/* + * exercise_inotify_add_watch() + * exercise inotify_add_watch with all valid and invalid mask + */ +static void exercise_inotify_add_watch( + const char *watchname, + const int bad_fd) +{ + int fd, wd; +#if defined(IN_MASK_CREATE) && \ + defined(IN_MASK_ADD) + int wd2; +#endif + + (void)bad_fd; + + fd = inotify_init(); + if (fd < 0) + return; + + /* Exercise inotify_add_watch on invalid mask */ + wd = inotify_add_watch(fd, watchname, 0); + if (wd >= 0) + (void)inotify_rm_watch(fd, wd); + + wd = inotify_add_watch(fd, watchname, ~0); + if (wd >= 0) + (void)inotify_rm_watch(fd, wd); + +#if defined(IN_MASK_CREATE) && \ + defined(IN_MASK_ADD) + /* Exercise inotify_add_watch with two operations */ + wd = inotify_add_watch(fd, watchname, IN_MASK_CREATE | IN_MASK_ADD); + if (wd >= 0) + (void)inotify_rm_watch(fd, wd); +#endif + +#if defined(IN_MASK_CREATE) && \ + defined(IN_MASK_ADD) + /* + * Exercise invalid inotify_add_watch by passing IN_MASK_CREATE in mask + * and pathname refers to a file already being watched by the same fd + */ + wd = inotify_add_watch(fd, watchname, IN_MASK_ADD); + wd2 = inotify_add_watch(fd, watchname, IN_MASK_CREATE); + if (wd >= 0) + (void)inotify_rm_watch(fd, wd); + if (wd2 >= 0) + (void)inotify_rm_watch(fd, wd2); +#endif + +#if defined(IN_MASK_ADD) + /* Exercise inotify_add_watch on bad_fd */ + wd = inotify_add_watch(bad_fd, watchname, IN_MASK_ADD); + if (wd >= 0) + (void)inotify_rm_watch(fd, wd); +#endif + + (void)close(fd); +} + +/* + * exercise_inotify_rm_watch() + * exercise inotify_rm_watch with all valid and invalid mask + */ +static void exercise_inotify_rm_watch(const int bad_fd) +{ + int fd, ret; + + (void)bad_fd; + + fd = inotify_init(); + if (fd < 0) + return; + + /* Exercise inotify_rm_watch on bad fd */ + ret = inotify_rm_watch(bad_fd, -1); + (void)ret; + + /* Exercise inotify_rm_watch on invalid wd */ + ret = inotify_rm_watch(fd, 1); + (void)ret; + + /* Close inotify file descriptor */ + (void)close(fd); + + /* Exercise inotify_rm_watch on non inotify fd */ +#if defined(HAVE_EPOLL_CREATE1) + fd = epoll_create1(0); + if (fd < 0) + return; + ret = inotify_rm_watch(fd, 1); + (void)ret; +#endif + + (void)close(fd); +} + +/* * inotify_exercise() * run a given test helper function 'func' and see if this triggers the * required inotify event flags 'flags'. @@ -63,10 +186,16 @@ const char *matchname, /* Filename we expect inotify event to report */ const stress_inotify_helper func, /* Helper func */ const int flags, /* IN_* flags to watch for */ - void *private) /* Helper func private data */ + void *private, /* Helper func private data */ + const int bad_fd) /* A bad file descriptor */ { int fd, wd, check_flags = flags, n = 0; char buffer[1024]; + + exercise_inotify1(); + exercise_inotify_add_watch(watchname, bad_fd); + exercise_inotify_rm_watch(bad_fd); + retry: n++; if ((fd = inotify_init()) < 0) { @@ -213,7 +342,7 @@ if (stress_is_dot_filename(d->d_name)) continue; - (void)snprintf(filename, sizeof(filename), "%s/%s", + (void)stress_mk_filename(filename, sizeof(filename), path, d->d_name); (void)rm_file(args, filename); } @@ -243,19 +372,6 @@ } /* - * mk_filename() - * simple helper to create a filename - */ -static inline void mk_filename( - char *filename, - const size_t len, - const char *path, - const char *name) -{ - (void)snprintf(filename, len, "%s/%s", path, name); -} - -/* * mk_file() * create file of length len bytes */ @@ -314,16 +430,19 @@ return 0; } -static void inotify_attrib_file(const stress_args_t *args, const char *path) +static void inotify_attrib_file( + const stress_args_t *args, + const char *path, + const int bad_fd) { char filepath[PATH_MAX]; - mk_filename(filepath, sizeof(filepath), path, "inotify_file"); + stress_mk_filename(filepath, sizeof(filepath), path, "inotify_file"); if (mk_file(args, filepath, 4096) < 0) return; inotify_exercise(args, filepath, path, "inotify_file", - inotify_attrib_helper, IN_ATTRIB, NULL); + inotify_attrib_helper, IN_ATTRIB, NULL, bad_fd); (void)rm_file(args, filepath); } #endif @@ -358,16 +477,19 @@ return rc; } -static void inotify_access_file(const stress_args_t *args, const char *path) +static void inotify_access_file( + const stress_args_t *args, + const char *path, + const int bad_fd) { char filepath[PATH_MAX]; - mk_filename(filepath, sizeof(filepath), path, "inotify_file"); + stress_mk_filename(filepath, sizeof(filepath), path, "inotify_file"); if (mk_file(args, filepath, 4096) < 0) return; inotify_exercise(args, filepath, path, "inotify_file", - inotify_access_helper, IN_ACCESS, NULL); + inotify_access_helper, IN_ACCESS, NULL, bad_fd); (void)rm_file(args, filepath); } #endif @@ -404,13 +526,16 @@ return rc; } -static void inotify_modify_file(const stress_args_t *args, const char *path) +static void inotify_modify_file( + const stress_args_t *args, + const char *path, + const int bad_fd) { char filepath[PATH_MAX]; - mk_filename(filepath, sizeof(filepath), path, "inotify_file"); + stress_mk_filename(filepath, sizeof(filepath), path, "inotify_file"); inotify_exercise(args, filepath, path, "inotify_file", - inotify_modify_helper, IN_MODIFY, NULL); + inotify_modify_helper, IN_MODIFY, NULL, bad_fd); } #endif @@ -431,13 +556,16 @@ return 0; } -static void inotify_creat_file(const stress_args_t *args, const char *path) +static void inotify_creat_file( + const stress_args_t *args, + const char *path, + const int bad_fd) { char filepath[PATH_MAX]; - mk_filename(filepath, sizeof(filepath), path, "inotify_file"); + stress_mk_filename(filepath, sizeof(filepath), path, "inotify_file"); inotify_exercise(args, filepath, path, "inotify_file", - inotify_creat_helper, IN_CREATE, NULL); + inotify_creat_helper, IN_CREATE, NULL, bad_fd); (void)rm_file(args, filepath); } #endif @@ -460,15 +588,18 @@ return 0; } -static void inotify_open_file(const stress_args_t *args, const char *path) +static void inotify_open_file( + const stress_args_t *args, + const char *path, + const int bad_fd) { char filepath[PATH_MAX]; - mk_filename(filepath, sizeof(filepath), path, "inotify_file"); + stress_mk_filename(filepath, sizeof(filepath), path, "inotify_file"); if (mk_file(args, filepath, 4096) < 0) return; inotify_exercise(args, filepath, path, "inotify_file", - inotify_open_helper, IN_OPEN, NULL); + inotify_open_helper, IN_OPEN, NULL, bad_fd); (void)rm_file(args, filepath); } #endif @@ -484,15 +615,18 @@ return rm_file(args, path); } -static void inotify_delete_file(const stress_args_t *args, const char *path) +static void inotify_delete_file( + const stress_args_t *args, + const char *path, + const int bad_fd) { char filepath[PATH_MAX]; - mk_filename(filepath, sizeof(filepath), path, "inotify_file"); + stress_mk_filename(filepath, sizeof(filepath), path, "inotify_file"); if (mk_file(args, filepath, 4096) < 0) return; inotify_exercise(args, filepath, path, "inotify_file", - inotify_delete_helper, IN_DELETE, NULL); + inotify_delete_helper, IN_DELETE, NULL, bad_fd); /* We remove (again) it just in case the test failed */ (void)rm_file(args, filepath); } @@ -509,15 +643,18 @@ return rm_dir(args, path); } -static void inotify_delete_self(const stress_args_t *args, const char *path) +static void inotify_delete_self( + const stress_args_t *args, + const char *path, + const int bad_fd) { char filepath[PATH_MAX]; - mk_filename(filepath, sizeof(filepath), path, "inotify_dir"); + stress_mk_filename(filepath, sizeof(filepath), path, "inotify_dir"); if (mk_dir(args, filepath) < 0) return; inotify_exercise(args, filepath, filepath, "inotify_dir", - inotify_delete_self_helper, IN_DELETE_SELF, NULL); + inotify_delete_self_helper, IN_DELETE_SELF, NULL, bad_fd); /* We remove (again) in case the test failed */ (void)rm_dir(args, filepath); } @@ -540,17 +677,20 @@ } #endif -static void inotify_move_self(const stress_args_t *args, const char *path) +static void inotify_move_self( + const stress_args_t *args, + const char *path, + const int bad_fd) { char filepath[PATH_MAX], newpath[PATH_MAX]; - mk_filename(filepath, sizeof(filepath), path, "inotify_dir"); + stress_mk_filename(filepath, sizeof(filepath), path, "inotify_dir"); if (mk_dir(args, filepath) < 0) return; - mk_filename(newpath, sizeof(newpath), path, "renamed_dir"); + stress_mk_filename(newpath, sizeof(newpath), path, "renamed_dir"); inotify_exercise(args, filepath, filepath, "inotify_dir", - inotify_move_self_helper, IN_MOVE_SELF, newpath); + inotify_move_self_helper, IN_MOVE_SELF, newpath, bad_fd); (void)rm_dir(args, newpath); (void)rm_dir(args, filepath); /* In case rename failed */ } @@ -571,21 +711,24 @@ return 0; } -static void inotify_moved_to(const stress_args_t *args, const char *path) +static void inotify_moved_to( + const stress_args_t *args, + const char *path, + const int bad_fd) { char olddir[PATH_MAX - 16], oldfile[PATH_MAX], newfile[PATH_MAX]; - mk_filename(olddir, sizeof(olddir), path, "new_dir"); + stress_mk_filename(olddir, sizeof(olddir), path, "new_dir"); (void)rm_dir(args, olddir); if (mk_dir(args, olddir) < 0) return; - mk_filename(oldfile, sizeof(oldfile), olddir, "inotify_file"); + stress_mk_filename(oldfile, sizeof(oldfile), olddir, "inotify_file"); if (mk_file(args, oldfile, 4096) < 0) return; - mk_filename(newfile, sizeof(newfile), path, "inotify_file"); + stress_mk_filename(newfile, sizeof(newfile), path, "inotify_file"); inotify_exercise(args, newfile, path, "inotify_dir", - inotify_moved_to_helper, IN_MOVED_TO, oldfile); + inotify_moved_to_helper, IN_MOVED_TO, oldfile, bad_fd); (void)rm_file(args, newfile); (void)rm_dir(args, olddir); } @@ -607,20 +750,23 @@ return 0; } -static void inotify_moved_from(const stress_args_t *args, const char *path) +static void inotify_moved_from( + const stress_args_t *args, + const char *path, + const int bad_fd) { char oldfile[PATH_MAX], newdir[PATH_MAX - 16], newfile[PATH_MAX]; - mk_filename(oldfile, sizeof(oldfile), path, "inotify_file"); + stress_mk_filename(oldfile, sizeof(oldfile), path, "inotify_file"); if (mk_file(args, oldfile, 4096) < 0) return; - mk_filename(newdir, sizeof(newdir), path, "new_dir"); + stress_mk_filename(newdir, sizeof(newdir), path, "new_dir"); (void)rm_dir(args, newdir); if (mk_dir(args, newdir) < 0) return; - mk_filename(newfile, sizeof(newfile), newdir, "inotify_file"); + stress_mk_filename(newfile, sizeof(newfile), newdir, "inotify_file"); inotify_exercise(args, oldfile, path, "inotify_dir", - inotify_moved_from_helper, IN_MOVED_FROM, newfile); + inotify_moved_from_helper, IN_MOVED_FROM, newfile, bad_fd); (void)rm_file(args, newfile); (void)rm_file(args, oldfile); /* In case rename failed */ (void)rm_dir(args, newdir); @@ -640,12 +786,15 @@ return 0; } -static void inotify_close_write_file(const stress_args_t *args, const char *path) +static void inotify_close_write_file( + const stress_args_t *args, + const char *path, + const int bad_fd) { char filepath[PATH_MAX]; int fd; - mk_filename(filepath, sizeof(filepath), path, "inotify_file"); + stress_mk_filename(filepath, sizeof(filepath), path, "inotify_file"); if (mk_file(args, filepath, 4096) < 0) return; @@ -656,7 +805,7 @@ } inotify_exercise(args, filepath, path, "inotify_file", - inotify_close_write_helper, IN_CLOSE_WRITE, (void*)&fd); + inotify_close_write_helper, IN_CLOSE_WRITE, (void*)&fd, bad_fd); (void)rm_file(args, filepath); (void)close(fd); } @@ -675,12 +824,15 @@ return 0; } -static void inotify_close_nowrite_file(const stress_args_t *args, const char *path) +static void inotify_close_nowrite_file( + const stress_args_t *args, + const char *path, + const int bad_fd) { char filepath[PATH_MAX]; int fd; - mk_filename(filepath, sizeof(filepath), path, "inotify_file"); + stress_mk_filename(filepath, sizeof(filepath), path, "inotify_file"); if (mk_file(args, filepath, 4096) < 0) return; @@ -692,7 +844,7 @@ } inotify_exercise(args, filepath, path, "inotify_file", - inotify_close_nowrite_helper, IN_CLOSE_NOWRITE, (void*)&fd); + inotify_close_nowrite_helper, IN_CLOSE_NOWRITE, (void*)&fd, bad_fd); (void)rm_file(args, filepath); (void)close(fd); } @@ -746,6 +898,7 @@ { char pathname[PATH_MAX - 16]; int ret, i; + const int bad_fd = stress_get_bad_fd(); stress_temp_dir_args(args, pathname, sizeof(pathname)); ret = stress_temp_dir_mk_args(args); @@ -753,7 +906,7 @@ return exit_status(-ret); do { for (i = 0; keep_stressing_flag() && inotify_stressors[i].func; i++) - inotify_stressors[i].func(args, pathname); + inotify_stressors[i].func(args, pathname, bad_fd); inc_counter(args); } while (keep_stressing()); (void)stress_temp_dir_rm_args(args); diff -Nru stress-ng-0.11.19/stress-io-uring.c stress-ng-0.11.21/stress-io-uring.c --- stress-ng-0.11.19/stress-io-uring.c 1970-01-01 00:00:00.000000000 +0000 +++ stress-ng-0.11.21/stress-io-uring.c 2020-09-16 22:00:11.000000000 +0000 @@ -0,0 +1,532 @@ +/* + * Copyright (C) 2013-2020 Canonical, 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 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. + * + * This code is a complete clean re-write of the stress tool by + * Colin Ian King and attempts to be + * backwardly compatible with the stress tool by Amos Waterland + * but has more stress tests and more + * functionality. + * + */ +#include "stress-ng.h" +#include "io-uring.h" + +static const stress_help_t help[] = { + { NULL, "io-uring N", "start N workers that issue io-uring I/O requests" }, + { NULL, "io-uring-ops N", "stop after N bogo io-uring I/O requests" }, + { NULL, NULL, NULL } +}; + +#if defined(HAVE_LINUX_IO_URING_H) && \ + defined(__NR_io_uring_enter) && \ + defined(__NR_io_uring_setup) && \ + defined(IORING_OFF_SQ_RING) && \ + defined(IORING_OFF_CQ_RING) && \ + defined(IORING_OFF_SQES) && \ + defined(HAVE_POSIX_MEMALIGN) && \ + (defined(HAVE_IORING_OP_WRITEV) || \ + defined(HAVE_IORING_OP_READV) || \ + defined(HAVE_IORING_OP_FSYNC) || \ + defined(HAVE_IORING_OP_NOP)) + +/* + * io uring file info + */ +typedef struct { + int fd; /* file descriptor */ + struct iovec *iovecs; /* iovecs array 1 per block to submit */ + off_t file_size; /* size of the file (bytes) */ + size_t blocks; /* number of blocks to action */ + size_t block_size; /* per block size */ +} stress_io_uring_file_t; + +/* + * io uring submission queue info + */ +typedef struct { + unsigned *head; + unsigned *tail; + unsigned *ring_mask; + unsigned *ring_entries; + unsigned *flags; + unsigned *array; +} stress_uring_io_sq_ring_t; + +/* + * io uring completion queue info + */ +typedef struct { + unsigned *head; + unsigned *tail; + unsigned *ring_mask; + unsigned *ring_entries; + struct io_uring_cqe *cqes; +} stress_uring_io_cq_ring_t; + +/* + * io uring submission info + */ +typedef struct { + stress_uring_io_sq_ring_t sq_ring; + stress_uring_io_cq_ring_t cq_ring; + struct io_uring_sqe *sqes_mmap; + void *sq_mmap; + void *cq_mmap; + int io_uring_fd; + size_t sq_size; + size_t cq_size; + size_t sqes_size; +} stress_io_uring_submit_t; + +/* + * shim_io_uring_setup + * wrapper for io_uring_setup() + */ +static int shim_io_uring_setup(unsigned entries, struct io_uring_params *p) +{ + return (int)syscall(__NR_io_uring_setup, entries, p); +} + +/* + * shim_io_uring_enter + * wrapper for o_uring_enter() + */ +static int shim_io_uring_enter( + int fd, + unsigned int to_submit, + unsigned int min_complete, + unsigned int flags) +{ + return (int)syscall(__NR_io_uring_enter, fd, to_submit, + min_complete, flags, NULL, 0); +} + +/* + * stress_io_uring_free_iovecs() + * free uring file iovecs + */ +static void stress_io_uring_free_iovecs(stress_io_uring_file_t *io_uring_file) +{ + size_t i; + + for (i = 0; i < io_uring_file->blocks; i++) + free(io_uring_file->iovecs[i].iov_base); + + free(io_uring_file->iovecs); + io_uring_file->iovecs = NULL; +} + +/* + * stress_setup_io_uring() + * setup the io uring + */ +static int stress_setup_io_uring( + const stress_args_t *args, + stress_io_uring_submit_t *submit) +{ + stress_uring_io_sq_ring_t *sring = &submit->sq_ring; + stress_uring_io_cq_ring_t *cring = &submit->cq_ring; + struct io_uring_params p; + + (void)memset(&p, 0, sizeof(p)); + submit->io_uring_fd = shim_io_uring_setup(1, &p); + if (submit->io_uring_fd < 0) { + pr_err("%s: io_uring_setup failed: errno=%d (%s)\n", + args->name, errno, strerror(errno)); + return EXIT_FAILURE; + } + submit->sq_size = p.sq_off.array + p.sq_entries * sizeof(unsigned); + submit->cq_size = p.cq_off.cqes + p.cq_entries * sizeof(struct io_uring_cqe); + if (p.features & IORING_FEAT_SINGLE_MMAP) { + if (submit->cq_size > submit->sq_size) + submit->sq_size = submit->cq_size; + submit->cq_size = submit->sq_size; + } + + submit->sq_mmap = mmap(NULL, submit->sq_size, PROT_READ | PROT_WRITE, + MAP_SHARED | MAP_POPULATE, + submit->io_uring_fd, IORING_OFF_SQ_RING); + if (submit->sq_mmap == MAP_FAILED) { + pr_inf("%s: could not mmap submission queue buffer, errno=%d (%s)\n", + args->name, errno, strerror(errno)); + return EXIT_NO_RESOURCE; + } + + if (p.features & IORING_FEAT_SINGLE_MMAP) { + submit->cq_mmap = submit->sq_mmap; + } else { + submit->cq_mmap = mmap(NULL, submit->cq_size, PROT_READ | PROT_WRITE, + MAP_SHARED | MAP_POPULATE, + submit->io_uring_fd, IORING_OFF_CQ_RING); + if (submit->cq_mmap == MAP_FAILED) { + pr_inf("%s: could not mmap completion queue buffer, errno=%d (%s)\n", + args->name, errno, strerror(errno)); + (void)munmap(submit->sq_mmap, submit->cq_size); + return EXIT_NO_RESOURCE; + } + } + + sring->head = submit->sq_mmap + p.sq_off.head; + sring->tail = submit->sq_mmap + p.sq_off.tail; + sring->ring_mask = submit->sq_mmap + p.sq_off.ring_mask; + sring->ring_entries = submit->sq_mmap + p.sq_off.ring_entries; + sring->flags = submit->sq_mmap + p.sq_off.flags; + sring->array = submit->sq_mmap + p.sq_off.array; + + submit->sqes_size = p.sq_entries * sizeof(struct io_uring_sqe); + submit->sqes_mmap = mmap(NULL, submit->sqes_size, + PROT_READ | PROT_WRITE, MAP_SHARED | MAP_POPULATE, + submit->io_uring_fd, IORING_OFF_SQES); + if (submit->sqes_mmap == MAP_FAILED) { + pr_inf("%s: count not mmap submission queue buffer, errno=%d (%s)\n", + args->name, errno, strerror(errno)); + (void)munmap(submit->cq_mmap, submit->cq_size); + (void)munmap(submit->sq_mmap, submit->sq_size); + return EXIT_NO_RESOURCE; + } + + cring->head = submit->cq_mmap + p.cq_off.head; + cring->tail = submit->cq_mmap + p.cq_off.tail; + cring->ring_mask = submit->cq_mmap + p.cq_off.ring_mask; + cring->ring_entries = submit->cq_mmap + p.cq_off.ring_entries; + cring->cqes = submit->cq_mmap + p.cq_off.cqes; + + return EXIT_SUCCESS; +} + +/* + * stress_close_io_uring() + * close and cleanup behind us + */ +static void stress_close_io_uring(stress_io_uring_submit_t *submit) +{ + (void)close(submit->io_uring_fd); + + (void)munmap(submit->sqes_mmap, submit->sqes_size); + if (submit->cq_mmap != submit->sq_mmap) + (void)munmap(submit->cq_mmap, submit->cq_size); + (void)munmap(submit->sq_mmap, submit->sq_size); +} + +static int stress_io_uring_submit( + const stress_args_t *args, + stress_io_uring_submit_t *submit, + stress_io_uring_file_t *io_uring_file, + const int opcode) +{ + int ret; + + ret = shim_io_uring_enter(submit->io_uring_fd, 1, + 1, IORING_ENTER_GETEVENTS); + if (ret < 0) { + pr_fail("%s: io_uring_enter failed, opcode=%d, errno=%d (%s)\n", + args->name, opcode, errno, strerror(errno)); + stress_io_uring_free_iovecs(io_uring_file); + return EXIT_FAILURE; + } + return EXIT_SUCCESS; +} + +#if defined(HAVE_IORING_OP_READV) || \ + defined(HAVE_IORING_OP_WRITEV) +/* + * stress_io_uring_iovec_submit() + * perform a iovec submit over io_uring + */ +static int stress_io_uring_iovec_submit( + const stress_args_t *args, + stress_io_uring_submit_t *submit, + stress_io_uring_file_t *io_uring_file, + const int opcode) +{ + stress_uring_io_sq_ring_t *sring = &submit->sq_ring; + unsigned index = 0, tail = 0, next_tail = 0; + struct io_uring_sqe *sqe; + + next_tail = tail = *sring->tail; + next_tail++; + shim_mb(); + index = tail & *submit->sq_ring.ring_mask; + sqe = &submit->sqes_mmap[index]; + (void)memset(sqe, 0, sizeof(*sqe)); + + sqe->fd = io_uring_file->fd; + sqe->flags = 0; + sqe->opcode = opcode; + sqe->addr = (unsigned long)io_uring_file->iovecs; + sqe->len = io_uring_file->blocks; + sqe->off = 0; + sqe->user_data = (unsigned long long)io_uring_file; + sring->array[index] = index; + tail = next_tail; + + if (*sring->tail != tail) { + *sring->tail = tail; + shim_mb(); + } + + return stress_io_uring_submit(args, submit, io_uring_file, opcode); +} +#endif + +#if defined(HAVE_IORING_OP_FSYNC) +/* + * stress_io_uring_fsync_submit() + * perform a fsync submit over io_uring + */ +static int stress_io_uring_fsync_submit( + const stress_args_t *args, + stress_io_uring_submit_t *submit, + stress_io_uring_file_t *io_uring_file) +{ + stress_uring_io_sq_ring_t *sring = &submit->sq_ring; + unsigned index = 0, tail = 0, next_tail = 0; + struct io_uring_sqe *sqe; + + next_tail = tail = *sring->tail; + next_tail++; + shim_mb(); + index = tail & *submit->sq_ring.ring_mask; + sqe = &submit->sqes_mmap[index]; + (void)memset(sqe, 0, sizeof(*sqe)); + + sqe->fd = io_uring_file->fd; + sqe->opcode = IORING_OP_FSYNC; + sqe->len = 512; + sqe->off = 0; + sqe->user_data = (unsigned long long)io_uring_file; + sring->array[index] = index; + tail = next_tail; + + if (*sring->tail != tail) { + *sring->tail = tail; + shim_mb(); + } + return stress_io_uring_submit(args, submit, io_uring_file, IORING_OP_FSYNC); +} +#endif + +#if defined(HAVE_IORING_OP_NOP) +/* + * stress_io_uring_nop_submit() + * perform a nop submit over io_uring + */ +static int stress_io_uring_nop_submit( + const stress_args_t *args, + stress_io_uring_submit_t *submit, + stress_io_uring_file_t *io_uring_file) +{ + stress_uring_io_sq_ring_t *sring = &submit->sq_ring; + unsigned index = 0, tail = 0, next_tail = 0; + struct io_uring_sqe *sqe; + + next_tail = tail = *sring->tail; + next_tail++; + shim_mb(); + index = tail & *submit->sq_ring.ring_mask; + sqe = &submit->sqes_mmap[index]; + (void)memset(sqe, 0, sizeof(*sqe)); + + sqe->opcode = IORING_OP_NOP; + sring->array[index] = index; + tail = next_tail; + + if (*sring->tail != tail) { + *sring->tail = tail; + shim_mb(); + } + return stress_io_uring_submit(args, submit, io_uring_file, IORING_OP_NOP); +} +#endif + +/* + * stress_io_uring_iovec_complete() + * handle pending iovec I/Os to complete + */ +static int stress_io_uring_iovec_complete( + const stress_args_t *args, + stress_io_uring_submit_t *submit) +{ + stress_uring_io_cq_ring_t *cring = &submit->cq_ring; + struct io_uring_cqe *cqe; + unsigned head = *cring->head; + int ret = EXIT_SUCCESS; + + while (keep_stressing()) { + shim_mb(); + + /* Empty? */ + if (head == *cring->tail) + break; + + cqe = &cring->cqes[head & *submit->cq_ring.ring_mask]; + if (cqe->res < 0) { + const int err = abs(cqe->res); + + pr_err("%s: completion uring io error: %d (%s)\n", + args->name, err, strerror(err)); + ret = EXIT_FAILURE; + } + head++; + } + + *cring->head = head; + shim_mb(); + + return ret; +} + +/* + * stress_io_uring_fdinfo() + * io_uring provides an fdinfo handler, so exercise this + * and silently ignore failyues + */ +static void stress_io_uring_fdinfo(const int io_uring_fd) +{ + char path[PATH_MAX]; + char buf[4096]; + int ret; + + (void)snprintf(path, sizeof(path), "/proc/%d/fdinfo/%d", + getpid(), io_uring_fd); + + ret = system_read(path, buf, sizeof(buf)); + (void)ret; +} + +/* + * stress_io_uring + * stress asynchronous I/O + */ +static int stress_io_uring(const stress_args_t *args) +{ + int ret, rc = EXIT_FAILURE; + char filename[PATH_MAX]; + stress_io_uring_file_t io_uring_file; + size_t i; + const size_t blocks = 1024; + const size_t block_size = 512; + off_t file_size = (off_t)blocks * block_size; + stress_io_uring_submit_t submit; + + (void)memset(&submit, 0, sizeof(submit)); + (void)memset(&io_uring_file, 0, sizeof(io_uring_file)); + + io_uring_file.file_size = file_size; + io_uring_file.blocks = blocks; + io_uring_file.block_size = block_size; + io_uring_file.iovecs = calloc(blocks, sizeof(*io_uring_file.iovecs)); + + for (i = 0; (i < blocks) && (file_size > 0); i++) { + const size_t iov_len = (file_size > (off_t)block_size) ? (size_t)block_size : (size_t)file_size; + + io_uring_file.iovecs[i].iov_len = iov_len; + if (posix_memalign(&io_uring_file.iovecs[i].iov_base, block_size, block_size)) { + pr_inf("%s: cannot allocate iovecs\n", args->name); + stress_io_uring_free_iovecs(&io_uring_file); + return EXIT_NO_RESOURCE; + } + file_size -= iov_len; + } + + ret = stress_temp_dir_mk_args(args); + if (ret < 0) + return exit_status(-ret); + + (void)stress_temp_filename_args(args, + filename, sizeof(filename), stress_mwc32()); + + rc = stress_setup_io_uring(args, &submit); + if (rc != EXIT_SUCCESS) + goto clean; + + if ((io_uring_file.fd = open(filename, O_CREAT | O_RDWR, S_IRUSR | S_IWUSR)) < 0) { + rc = exit_status(errno); + pr_fail("%s: open on %s failed, errno=%d (%s)\n", + args->name, filename, errno, strerror(errno)); + goto clean; + } + (void)unlink(filename); + + rc = EXIT_SUCCESS; + i = 0; + do { +#if defined(HAVE_IORING_OP_WRITEV) + rc = stress_io_uring_iovec_submit(args, &submit, &io_uring_file, IORING_OP_WRITEV); + if (rc != EXIT_SUCCESS) + break; + rc = stress_io_uring_iovec_complete(args, &submit); + if (rc != EXIT_SUCCESS) + break; +#endif + +#if defined(HAVE_IORING_OP_READV) + rc = stress_io_uring_iovec_submit(args, &submit, &io_uring_file, IORING_OP_READV); + if (rc != EXIT_SUCCESS) + break; + rc = stress_io_uring_iovec_complete(args, &submit); + if (rc != EXIT_SUCCESS) + break; +#endif + +#if defined(HAVE_IORING_OP_NOP) + rc = stress_io_uring_nop_submit(args, &submit, &io_uring_file); + if (rc != EXIT_SUCCESS) + break; + rc = stress_io_uring_iovec_complete(args, &submit); + if (rc != EXIT_SUCCESS) + break; +#endif + + /* + * occasional sync and fdinfo reads + */ + if (i++ > 1024) { + i = 0; +#if defined(HAVE_IORING_OP_FSYNC) + rc = stress_io_uring_fsync_submit(args, &submit, &io_uring_file); + if (rc != EXIT_SUCCESS) + break; + rc = stress_io_uring_iovec_complete(args, &submit); + if (rc != EXIT_SUCCESS) + break; +#endif + + stress_io_uring_fdinfo(submit.io_uring_fd); + } + inc_counter(args); + } while (keep_stressing()); + + (void)close(io_uring_file.fd); +clean: + stress_close_io_uring(&submit); + (void)stress_temp_dir_rm_args(args); + return rc; +} + +stressor_info_t stress_io_uring_info = { + .stressor = stress_io_uring, + .class = CLASS_IO | CLASS_OS, + .help = help +}; +#else +stressor_info_t stress_io_uring_info = { + .stressor = stress_not_implemented, + .class = CLASS_IO | CLASS_OS, + .help = help +}; +#endif diff -Nru stress-ng-0.11.19/stress-ipsec-mb.c stress-ng-0.11.21/stress-ipsec-mb.c --- stress-ng-0.11.19/stress-ipsec-mb.c 2020-08-24 14:14:41.000000000 +0000 +++ stress-ng-0.11.21/stress-ipsec-mb.c 2020-09-16 22:00:11.000000000 +0000 @@ -35,6 +35,7 @@ static const stress_opt_set_func_t opt_set_funcs[] = { { OPT_ipsec_mb_feature, stress_set_ipsec_mb_feature }, + { 0, NULL } }; #if defined(HAVE_INTEL_IPSEC_MB_H) && \ diff -Nru stress-ng-0.11.19/stress-madvise.c stress-ng-0.11.21/stress-madvise.c --- stress-ng-0.11.19/stress-madvise.c 2020-08-24 14:14:41.000000000 +0000 +++ stress-ng-0.11.21/stress-madvise.c 2020-09-16 22:00:11.000000000 +0000 @@ -406,8 +406,8 @@ (void)stress_temp_dir_rm_args(args); if (sigbus_count) - pr_inf("%s: caught %" PRIu64 " SIGBUS signals\n", - args->name, sigbus_count); + pr_inf("%s: caught %" PRIu64 " SIGBUS signal%s\n", + args->name, sigbus_count, sigbus_count == 1 ? "" : "s"); return EXIT_SUCCESS; } diff -Nru stress-ng-0.11.19/stress-memthrash.c stress-ng-0.11.21/stress-memthrash.c --- stress-ng-0.11.19/stress-memthrash.c 2020-08-24 14:14:41.000000000 +0000 +++ stress-ng-0.11.21/stress-memthrash.c 2020-09-16 22:00:11.000000000 +0000 @@ -462,7 +462,7 @@ } } - /* Wait parent up, all done! */ + /* Wake parent up, all done! */ (void)kill(args->pid, SIGALRM); return &nowt; } @@ -498,13 +498,20 @@ return n > 1 ? "s" : ""; } +static void stress_memthrash_sigalrm_handler(int signum) +{ + (void)signum; + + thread_terminate = true; +} + static int stress_memthrash_child(const stress_args_t *args, void *ctxt) { stress_memthrash_context_t *context = (stress_memthrash_context_t *)ctxt; const uint32_t max_threads = context->max_threads; uint32_t i; pthread_t pthreads[max_threads]; - int ret[max_threads]; + int pthreads_ret[max_threads], ret; stress_pthread_args_t pargs; int flags = MAP_PRIVATE | MAP_ANONYMOUS; @@ -512,11 +519,14 @@ flags |= MAP_POPULATE; #endif + ret = stress_sighandler(args->name, SIGALRM, stress_memthrash_sigalrm_handler, NULL); + (void)ret; + pargs.args = args; pargs.data = context->memthrash_method->func; (void)memset(pthreads, 0, sizeof(pthreads)); - (void)memset(ret, 0, sizeof(ret)); + (void)memset(pthreads_ret, 0, sizeof(pthreads_ret)); mmap_retry: mem = mmap(NULL, MEM_SIZE, PROT_READ | PROT_WRITE, flags, -1, 0); @@ -536,15 +546,15 @@ } for (i = 0; i < max_threads; i++) { - ret[i] = pthread_create(&pthreads[i], NULL, + pthreads_ret[i] = pthread_create(&pthreads[i], NULL, stress_memthrash_func, (void *)&pargs); - if (ret[i]) { + if (pthreads_ret[i]) { /* Just give up and go to next thread */ - if (ret[i] == EAGAIN) + if (pthreads_ret[i] == EAGAIN) continue; /* Something really unexpected */ pr_fail("%s: pthread create failed, errno=%d (%s)\n", - args->name, ret[i], strerror(ret[i])); + args->name, pthreads_ret[i], strerror(pthreads_ret[i])); goto reap; } if (!keep_stressing_flag()) @@ -556,11 +566,11 @@ reap: thread_terminate = true; for (i = 0; i < max_threads; i++) { - if (!ret[i]) { - ret[i] = pthread_join(pthreads[i], NULL); - if (ret[i] && (ret[i] != ESRCH)) { + if (!pthreads_ret[i]) { + pthreads_ret[i] = pthread_join(pthreads[i], NULL); + if (pthreads_ret[i] && (pthreads_ret[i] != ESRCH)) { pr_fail("%s: pthread join failed, errno=%d (%s)\n", - args->name, ret[i], strerror(ret[i])); + args->name, pthreads_ret[i], strerror(pthreads_ret[i])); } } } diff -Nru stress-ng-0.11.19/stress-ng.1 stress-ng-0.11.21/stress-ng.1 --- stress-ng-0.11.19/stress-ng.1 2020-08-24 14:14:41.000000000 +0000 +++ stress-ng-0.11.21/stress-ng.1 2020-09-16 22:00:11.000000000 +0000 @@ -2,7 +2,7 @@ .\" First parameter, NAME, should be all caps .\" Second parameter, SECTION, should be 1-8, maybe w/ subsection .\" other parameters are allowed: see man(7), man(1) -.TH STRESS-NG 1 "Jul 17, 2020" +.TH STRESS-NG 1 "Sep 16, 2020" .\" Please adjust this date whenever revising the manpage. .\" .\" Some roff macros, for reference: @@ -418,11 +418,15 @@ stop access workers after N bogo access sanity checks. .TP .B \-\-affinity N -start N workers that rapidly change CPU affinity (only on Linux). Rapidly -switching CPU affinity can contribute to poor cache behaviour. +start N workers that run 16 processes that rapidly change CPU affinity +(only on Linux). Rapidly switching CPU affinity can contribute to +poor cache behaviour and high context switch rate. .TP .B \-\-affinity\-ops N -stop affinity workers after N bogo affinity operations (only on Linux). +stop affinity workers after N bogo affinity operations (only on Linux). Note +that the counters across the 16 processes are not locked to improve affinity +test rates so the final number of bogo-ops will be equal or more than the +specified ops stop threshold because of racy unlocked bogo-op counting. .TP .B \-\-affinity\-rand switch CPU affinity randomly rather than the default of sequentially. @@ -1815,6 +1819,14 @@ .B \-\-ioprio\-ops N stop after N io priority bogo operations. .TP +.B \-\-io\-uring N +start N workers that perform iovec write and read I/O operations using the +Linux io-uring interface. On each bogo-loop 1024 \(mu 512 byte writes and +1024 \(mu reads are performed on a temporary file. +.TP +.B \-\-io\-uring\-ops +stop after N rounds of write and reads. +.TP .B \-\-ipsec\-mb N start N workers that perform cryptographic processing using the highly optimized Intel Multi-Buffer Crypto for IPsec library. Depending on the @@ -4287,6 +4299,65 @@ T} .TE .TP +.B \-\-zlib\-window-bits W +specify the window bits used to specify the history buffer size. The value is +specified as the base two logarithm of the buffer size (e.g. value 9 is 2^9 = +512 bytes). +Default is 15. +.PP +.RS +.nf +Values: +-8-(-15): raw deflate format + 8-15: zlib format + 24-31: gzip format + 40-47: inflate auto format detection using zlib deflate format +.fi +.RE +.PP +.B \-\-zlib\-mem-level L +specify the reserved compression state memory for zlib. +Default is 8. +.PP +.RS +.nf +Values: +1 = minimum memory usage +9 = maximum memory usage +.fi +.RE +.TP +.B \-\-zlib\-strategy S +specifies the strategy to use when deflating data. This is used to tune the +compression algorithm. +Default is 0. +.PP +.RS +.nf +Values: +0: used for normal data (Z_DEFAULT_STRATEGY) +1: for data generated by a filter or predictor (Z_FILTERED) +2: forces huffman encoding (Z_HUFFMAN_ONLY) +3: Limit match distances to one run-length-encoding (Z_RLE) +4: prevents dynamic huffman codes (Z_FIXED) +.fi +.RE +.TP +.B \-\-zlib\-stream-bytes S +specify the amount of bytes to deflate until deflate should finish the block +and return with Z_STREAM_END. One can specify the size in units of Bytes, +KBytes, MBytes and GBytes using the suffix b, k, m or g. +Default is 0 which creates and endless stream until stressor ends. +.PP +.RS +.nf +Values: +0: creates an endless deflate stream until stressor stops +n: creates an stream of n bytes over and over again. Each block will be closed with Z_STREAM_END. +.fi +.RE +.TP +.TP .B \-\-zombie N start N workers that create zombie processes. This will rapidly try to create a default of 8192 child processes that immediately die and wait in a zombie diff -Nru stress-ng-0.11.19/stress-ng.c stress-ng-0.11.21/stress-ng.c --- stress-ng-0.11.19/stress-ng.c 2020-08-24 14:14:41.000000000 +0000 +++ stress-ng-0.11.21/stress-ng.c 2020-09-16 22:00:11.000000000 +0000 @@ -435,6 +435,8 @@ { "ioport-opts",1, 0, OPT_ioport_opts }, { "ioprio", 1, 0, OPT_ioprio }, { "ioprio-ops", 1, 0, OPT_ioprio_ops }, + { "io-uring", 1, 0, OPT_io_uring }, + { "io-uring-ops",1, 0, OPT_io_uring_ops }, { "ipsec-mb", 1, 0, OPT_ipsec_mb }, { "ipsec-mb-ops",1, 0, OPT_ipsec_mb_ops }, { "ipsec-mb-feature",1, 0, OPT_ipsec_mb_feature }, @@ -920,6 +922,10 @@ { "zlib-ops", 1, 0, OPT_zlib_ops }, { "zlib-method",1, 0, OPT_zlib_method }, { "zlib-level", 1, 0, OPT_zlib_level }, + { "zlib-mem-level", 1, 0, OPT_zlib_mem_level }, + { "zlib-window-bits", 1, 0, OPT_zlib_window_bits }, + { "zlib-stream-bytes", 1, 0, OPT_zlib_stream_bytes, }, + { "zlib-strategy", 1, 0, OPT_zlib_strategy, }, { "zombie", 1, 0, OPT_zombie }, { "zombie-ops", 1, 0, OPT_zombie_ops }, { "zombie-max", 1, 0, OPT_zombie_max }, diff -Nru stress-ng-0.11.19/stress-ng.h stress-ng-0.11.21/stress-ng.h --- stress-ng-0.11.19/stress-ng.h 2020-08-24 14:14:41.000000000 +0000 +++ stress-ng-0.11.21/stress-ng.h 2020-09-16 22:00:11.000000000 +0000 @@ -488,6 +488,10 @@ #include #endif +#if defined(HAVE_LINUX_IO_URING_H) +#include +#endif + #if defined(HAVE_LINUX_FIEMAP_H) #include #endif @@ -1251,6 +1255,14 @@ extern void pr_inf_lock(bool *locked, const char *fmt, ...) FORMAT(printf, 2, 3); extern void pr_dbg_lock(bool *locked, const char *fmt, ...) FORMAT(printf, 2, 3); +/* volatile debug print macro */ +#ifdef DEBUG +#define pr_dbg_v(fmt, ...) \ + do { if (DEBUG) pr_dbg(fmt, __VA_ARGS__); } while (0) +#else +#define pr_dbg_v(fmt, ...) +#endif + #if defined(HAVE_SYSLOG_H) #define shim_syslog(priority, format, ...) \ syslog(priority, format, __VA_ARGS__) @@ -1678,7 +1690,67 @@ /* GCC5.0+ target_clones attribute */ #if defined(HAVE_TARGET_CLONES) && defined(STRESS_ARCH_X86) -#define TARGET_CLONES __attribute__((target_clones("mmx","sse","sse2","ssse3", "sse4.1", "sse4a", "avx", "avx2", "arch=skylake-avx512", "default"))) +#if defined(__MMX_WITH_SSE__) +#define TARGET_CLONE_MMX "mmx", +#else +#define TARGET_CLONE_MMX +#endif + +#if defined(__AVX__) +#define TARGET_CLONE_AVX "avx", +#else +#define TARGET_CLONE_AVX +#endif + +#if defined(__AVX2__) +#define TARGET_CLONE_AVX2 "avx2", +#else +#define TARGET_CLONE_AVX2 +#endif + +#if defined(__SSE__) +#define TARGET_CLONE_SSE "sse", +#else +#define TARGET_CLONE_SSE +#endif + +#if defined(__SSE2__) +#define TARGET_CLONE_SSE2 "sse2", +#else +#define TARGET_CLONE_SSE2 +#endif + +#if defined(__SSE3__) +#define TARGET_CLONE_SSE3 "sse3", +#else +#define TARGET_CLONE_SSE3 +#endif + +#if defined(__SSSE3__) +#define TARGET_CLONE_SSSE3 "ssse3", +#else +#define TARGET_CLONE_SSSE3 +#endif + +#if defined(__SSE4_1__) +#define TARGET_CLONE_SSE4_1 "sse4.1", +#else +#define TARGET_CLONE_SSE4_1 +#endif + +#if defined(__SSE4_2__) +#define TARGET_CLONE_SSE4_2 "sse4.2", +#else +#define TARGET_CLONE_SSE4_2 +#endif + +#if defined(__AVX512F__) +#define TARGET_CLONE_SKYLAKE_AVX512 "arch=skylake-avx512", +#else +#define TARGET_CLONE_SKYLAKE_AVX512 +#endif + +#define TARGET_CLONES __attribute__((target_clones(TARGET_CLONE_AVX TARGET_CLONE_AVX2 TARGET_CLONE_MMX TARGET_CLONE_SSE TARGET_CLONE_SSE2 TARGET_CLONE_SSE3 TARGET_CLONE_SSSE3 TARGET_CLONE_SSE4_1 TARGET_CLONE_SSE4_2 TARGET_CLONE_SKYLAKE_AVX512 "default"))) #elif defined(HAVE_TARGET_CLONES) && defined(STRESS_ARCH_PPC64) #define TARGET_CLONES __attribute__((target_clones("cpu=power9,default"))) #else @@ -2246,6 +2318,7 @@ MACRO(iomix) \ MACRO(ioport) \ MACRO(ioprio) \ + MACRO(io_uring) \ MACRO(ipsec_mb) \ MACRO(itimer) \ MACRO(judy) \ @@ -2763,6 +2836,9 @@ OPT_io_ops, + OPT_io_uring, + OPT_io_uring_ops, + OPT_ipsec_mb, OPT_ipsec_mb_ops, OPT_ipsec_mb_feature, @@ -3398,7 +3474,11 @@ OPT_zlib, OPT_zlib_ops, OPT_zlib_level, + OPT_zlib_mem_level, OPT_zlib_method, + OPT_zlib_window_bits, + OPT_zlib_stream_bytes, + OPT_zlib_strategy, OPT_zombie, OPT_zombie_ops, @@ -3677,6 +3757,8 @@ #define STRESS_OOMABLE_DROP_CAP (0x00000001) /* Drop capabilities */ /* Misc helpers */ +extern size_t stress_mk_filename(char *fullname, const size_t fullname_len, + const char *pathname, const char *filename); extern void stress_set_oom_adjustment(const char *name, const bool killable); extern WARN_UNUSED bool stress_process_oomed(const pid_t pid); extern WARN_UNUSED int stress_oomable_child(const stress_args_t *args, @@ -3772,6 +3854,8 @@ const size_t page_size); extern WARN_UNUSED uint64_t stress_get_phys_mem_size(void); extern WARN_UNUSED uint64_t stress_get_filesystem_size(void); +extern WARN_UNUSED ssize_t stress_read_buffer(int, void*, ssize_t, bool); +extern WARN_UNUSED ssize_t stress_write_buffer(int, void*, ssize_t, bool); extern WARN_UNUSED uint64_t stress_get_filesystem_available_inodes(void); extern char *stress_uint64_to_str(char *str, size_t len, const uint64_t val); extern WARN_UNUSED int stress_drop_capabilities(const char *name); @@ -4040,6 +4124,7 @@ extern int shim_clock_gettime(clockid_t clk_id, struct timespec *tp); extern int shim_clock_settime(clockid_t clk_id, struct timespec *tp); extern int sys_clone3(struct shim_clone_args *cl_args, size_t size); +extern int shim_close_range(unsigned int fd, unsigned int max_fd); extern ssize_t shim_copy_file_range(int fd_in, shim_loff_t *off_in, int fd_out, shim_loff_t *off_out, size_t len, unsigned int flags); extern int shim_dup3(int oldfd, int newfd, int flags); diff -Nru stress-ng-0.11.19/stress-numa.c stress-ng-0.11.21/stress-numa.c --- stress-ng-0.11.19/stress-numa.c 2020-08-24 14:14:41.000000000 +0000 +++ stress-ng-0.11.21/stress-numa.c 2020-09-16 22:00:11.000000000 +0000 @@ -182,6 +182,7 @@ uint8_t *buf; stress_node_t *n; int rc = EXIT_FAILURE; + const bool cap_sys_nice = stress_check_capability(SHIM_CAP_SYS_NICE); numa_nodes = stress_numa_get_mem_nodes(&n, &max_nodes); if (numa_nodes < 1) { @@ -229,6 +230,30 @@ goto err; } } + + /* Exercise invalid flag */ + ret = shim_get_mempolicy(&mode, node_mask, max_nodes, + (unsigned long)buf, ~0); + (void)ret; + + /* Exercise invalid NULL addr condition */ + ret = shim_get_mempolicy(&mode, node_mask, max_nodes, + (unsigned long)NULL, MPOL_F_ADDR); + (void)ret; + + ret = shim_get_mempolicy(&mode, node_mask, max_nodes, + (unsigned long)buf, MPOL_F_NODE); + (void)ret; + + /* Exercise MPOL_F_MEMS_ALLOWED flag syscalls */ + ret = shim_get_mempolicy(&mode, node_mask, max_nodes, + (unsigned long)buf, MPOL_F_MEMS_ALLOWED); + (void)ret; + + ret = shim_get_mempolicy(&mode, node_mask, max_nodes, + (unsigned long)buf, MPOL_F_MEMS_ALLOWED | MPOL_F_NODE); + (void)ret; + if (!keep_stressing_flag()) break; @@ -300,6 +325,21 @@ if (!keep_stressing_flag()) break; + /* Exercise invalid flag */ + ret = shim_mbind(buf, MMAP_SZ, MPOL_BIND, node_mask, + max_nodes, ~0); + (void)ret; + + /* Check mbind syscall cannot succeed without capability */ + if (!cap_sys_nice) { + ret = shim_mbind(buf, MMAP_SZ, MPOL_BIND, node_mask, + max_nodes, MPOL_MF_MOVE_ALL); + if (ret >= 0) { + pr_fail("%s: mbind without capability CAP_SYS_NICE unexpectedly succeeded, " + "errno=%d (%s)\n", args->name, errno, strerror(errno)); + } + } + /* Move to next node */ n = n->next; diff -Nru stress-ng-0.11.19/stress-open.c stress-ng-0.11.21/stress-open.c --- stress-ng-0.11.19/stress-open.c 2020-08-24 14:14:41.000000000 +0000 +++ stress-ng-0.11.21/stress-open.c 2020-09-16 22:00:11.000000000 +0000 @@ -32,6 +32,24 @@ { NULL, NULL, NULL } }; +static inline int open_arg2(const char *pathname, int flags) +{ +#if defined(__NR_open) + return syscall(__NR_open, pathname, flags); +#else + return open(pathname, flags); +#endif +} + +static inline int open_arg3(const char *pathname, int flags, mode_t mode) +{ +#if defined(__NR_open) + return syscall(__NR_open, pathname, flags, mode); +#else + return open(pathname, flags, mode); +#endif +} + static int open_dev_zero_rd(void) { int flags = 0; @@ -51,7 +69,7 @@ flags |= (stress_mwc32() & O_NONBLOCK); #endif - return open("/dev/zero", O_RDONLY | flags); + return open_arg2("/dev/zero", O_RDONLY | flags); } static int open_dev_null_wr(void) @@ -79,7 +97,7 @@ flags |= (stress_mwc32() & O_SYNC); #endif - return open("/dev/null", O_WRONLY | flags); + return open_arg2("/dev/null", O_WRONLY | flags); } #if defined(O_TMPFILE) @@ -98,7 +116,7 @@ #if defined(O_DIRECT) flags |= (stress_mwc32() & O_DIRECT); #endif - return open("/tmp", O_TMPFILE | flags | O_RDWR, S_IRUSR | S_IWUSR); + return open_arg3("/tmp", O_TMPFILE | flags | O_RDWR, S_IRUSR | S_IWUSR); } #endif @@ -106,7 +124,7 @@ static int open_tmpfile_no_rdwr(void) { /* Force -EINVAL, need O_WRONLY or O_RDWR to succeed */ - return open("/tmp", O_TMPFILE, S_IRUSR | S_IWUSR); + return open_arg3("/tmp", O_TMPFILE, S_IRUSR | S_IWUSR); } #endif @@ -120,28 +138,68 @@ #if defined(O_TMPFILE) && defined(O_EXCL) static int open_tmp_rdwr_excl(void) { - return open("/tmp", O_TMPFILE | O_EXCL | O_RDWR, S_IRUSR | S_IWUSR); + return open_arg3("/tmp", O_TMPFILE | O_EXCL | O_RDWR, S_IRUSR | S_IWUSR); } #endif #if defined(O_DIRECTORY) static int open_dir(void) { - return open(".", O_DIRECTORY | O_RDONLY); + return open_arg2(".", O_DIRECTORY | O_RDONLY); } #endif #if defined(O_PATH) static int open_path(void) { - return open(".", O_DIRECTORY | O_PATH); + return open_arg2(".", O_DIRECTORY | O_PATH); } #endif #if defined(O_CREAT) static int open_create_eisdir(void) { - return open(".", O_CREAT, S_IRUSR | S_IWUSR); + return open_arg3(".", O_CREAT, S_IRUSR | S_IWUSR); +} +#endif + +#if defined(HAVE_OPENAT) && defined(AT_FDCWD) +static int open_with_openat_cwd(void) +{ + char filename[PATH_MAX]; + int fd; + + (void)snprintf(filename, sizeof(filename), "stress-open-%d-%" PRIu32, + (int)getpid(), stress_mwc32()); + + fd = openat(AT_FDCWD, filename, O_CREAT | O_RDWR, S_IRUSR | S_IWUSR); + if (fd >= 0) + (void)unlink(filename); + return fd; +} +#endif + +#if defined(HAVE_OPENAT) && \ + defined(AT_FDCWD) && \ + defined(O_PATH) && \ + defined(O_DIRECTORY) +static int open_with_openat_dirfd(void) +{ + char filename[PATH_MAX]; + int fd, dirfd; + + (void)snprintf(filename, sizeof(filename), "stress-open-%d-%" PRIu32, + (int)getpid(), stress_mwc32()); + + dirfd = open_arg2(".", O_DIRECTORY | O_PATH); + if (dirfd < 0) + return -1; + + fd = openat(dirfd, filename, O_CREAT | O_RDWR, S_IRUSR | S_IWUSR); + if (fd >= 0) + (void)unlink(filename); + (void)close(dirfd); + return fd; } #endif @@ -151,7 +209,8 @@ #if defined(O_TMPFILE) open_tmp_rdwr, #endif -#if defined(O_TMPFILE) && defined(O_EXCL) +#if defined(O_TMPFILE) && \ + defined(O_EXCL) open_tmp_rdwr_excl, #endif #if defined(O_TMPFILE) @@ -163,12 +222,24 @@ #if defined(O_PATH) open_path, #endif -#if defined(HAVE_POSIX_OPENPT) && defined(O_RDWR) && defined(N_NOCTTY) +#if defined(HAVE_POSIX_OPENPT) && \ + defined(O_RDWR) && \ + defined(N_NOCTTY) open_pt, #endif #if defined(O_CREAT) open_create_eisdir, #endif +#if defined(HAVE_OPENAT) && \ + defined(AT_FDCWD) + open_with_openat_cwd, +#endif +#if defined(HAVE_OPENAT) && \ + defined(AT_FDCWD) && \ + defined(O_PATH) && \ + defined(O_DIRECTORY) + open_with_openat_dirfd, +#endif }; /* diff -Nru stress-ng-0.11.19/stress-pidfd.c stress-ng-0.11.21/stress-pidfd.c --- stress-ng-0.11.19/stress-pidfd.c 2020-08-24 14:14:41.000000000 +0000 +++ stress-ng-0.11.21/stress-pidfd.c 2020-09-16 22:00:11.000000000 +0000 @@ -112,6 +112,8 @@ */ static int stress_pidfd(const stress_args_t *args) { + const int bad_fd = stress_get_bad_fd(); + while (keep_stressing()) { pid_t pid; @@ -142,6 +144,18 @@ if (ret >= 0) (void)close(ret); + /* Exercise with invalid flags */ + ret = shim_pidfd_getfd(pidfd, 0, ~0); + /* Ignore failure, close fd if success */ + if (ret >= 0) + (void)close(ret); + + /* Exercise with bad_fd */ + ret = shim_pidfd_getfd(pidfd, bad_fd, 0); + /* Ignore failure, close fd if success */ + if (ret >= 0) + (void)close(ret); + ret = shim_pidfd_send_signal(pidfd, 0, NULL, 0); if (ret != 0) { if (errno == ENOSYS) { diff -Nru stress-ng-0.11.19/stress-procfs.c stress-ng-0.11.21/stress-procfs.c --- stress-ng-0.11.19/stress-procfs.c 2020-08-24 14:14:41.000000000 +0000 +++ stress-ng-0.11.21/stress-procfs.c 2020-09-16 22:00:11.000000000 +0000 @@ -427,7 +427,7 @@ if ((d->d_type == DT_REG) || (d->d_type == DT_LNK)) { ret = shim_pthread_spin_lock(&lock); if (!ret) { - (void)snprintf(tmp, sizeof(tmp), "%s/%s", path, d->d_name); + (void)stress_mk_filename(tmp, sizeof(tmp), path, d->d_name); (void)shim_strlcpy(proc_path, tmp, sizeof(proc_path)); (void)shim_pthread_spin_unlock(&lock); @@ -449,7 +449,7 @@ struct dirent *d = dlist[i]; if (d && d->d_type == DT_DIR) { - (void)snprintf(tmp, sizeof(tmp), "%s/%s", path, d->d_name); + (void)stress_mk_filename(tmp, sizeof(tmp), path, d->d_name); free(d); dlist[i] = NULL; @@ -491,7 +491,7 @@ name = dlist[j]->d_name; if (isdigit(name[0])) { - (void)snprintf(path, sizeof(path), "/proc/%s", name); + (void)stress_mk_filename(path, sizeof(path), "/proc", name); break; } } diff -Nru stress-ng-0.11.19/stress-ramfs.c stress-ng-0.11.21/stress-ramfs.c --- stress-ng-0.11.19/stress-ramfs.c 2020-08-24 14:14:41.000000000 +0000 +++ stress-ng-0.11.21/stress-ramfs.c 2020-09-16 22:00:11.000000000 +0000 @@ -140,8 +140,8 @@ struct stat statbuf; int fd, rc = EXIT_SUCCESS; - (void)snprintf(filename, sizeof(filename), "%s/mnt", pathname); - (void)snprintf(symlinkname, sizeof(symlinkname), "%s/lnk", pathname); + (void)stress_mk_filename(filename, sizeof(filename), pathname, "mnt"); + (void)stress_mk_filename(symlinkname, sizeof(symlinkname), pathname, "lnk"); fd = open(filename, O_CREAT | O_RDWR, S_IRUSR | S_IWUSR); if (fd < 0) { diff -Nru stress-ng-0.11.19/stress-schedpolicy.c stress-ng-0.11.21/stress-schedpolicy.c --- stress-ng-0.11.19/stress-schedpolicy.c 2020-08-24 14:14:41.000000000 +0000 +++ stress-ng-0.11.21/stress-schedpolicy.c 2020-09-16 22:00:11.000000000 +0000 @@ -199,6 +199,13 @@ #if defined(HAVE_SCHED_GETATTR) && \ defined(HAVE_SCHED_SETATTR) + /* Exercise invalid sched_getattr syscalls */ + ret = shim_sched_getattr(pid, &attr, sizeof(attr), ~0); + (void)ret; + + ret = shim_sched_getattr(-1, &attr, sizeof(attr), 0); + (void)ret; + /* * Nothing too clever here, just get and set for now */ diff -Nru stress-ng-0.11.19/stress-sem.c stress-ng-0.11.21/stress-sem.c --- stress-ng-0.11.19/stress-sem.c 2020-08-24 14:14:41.000000000 +0000 +++ stress-ng-0.11.21/stress-sem.c 2020-09-16 22:00:11.000000000 +0000 @@ -171,7 +171,7 @@ /* Wait for termination */ while (keep_stressing()) - (void)shim_usleep(100000); + pause(); for (i = 0; i < semaphore_posix_procs; i++) { int ret; diff -Nru stress-ng-0.11.19/stress-sem-sysv.c stress-ng-0.11.21/stress-sem-sysv.c --- stress-ng-0.11.19/stress-sem-sysv.c 2020-08-24 14:14:41.000000000 +0000 +++ stress-ng-0.11.21/stress-sem-sysv.c 2020-09-16 22:00:11.000000000 +0000 @@ -443,7 +443,7 @@ } /* Wait for termination */ while (keep_stressing()) - (void)shim_usleep(100000); + pause(); reap: for (i = 0; i < semaphore_sysv_procs; i++) { if (pids[i] > 0) diff -Nru stress-ng-0.11.19/stress-shm-sysv.c stress-ng-0.11.21/stress-shm-sysv.c --- stress-ng-0.11.19/stress-shm-sysv.c 2020-08-24 14:14:41.000000000 +0000 +++ stress-ng-0.11.21/stress-shm-sysv.c 2020-09-16 22:00:11.000000000 +0000 @@ -159,6 +159,58 @@ } #endif +#if defined(__linux__) +/* + * stress_shm_sysv_linux_proc_map() + * exercise the correspronding /proc/$PID/map_files/ mapping + * with the shm address space. Ignore errors, we just want + * to exercise the kernel + */ +static void stress_shm_sysv_linux_proc_map(const void *addr, const size_t sz) +{ + int fd; + char path[PATH_MAX]; + const int len = (int)sizeof(void *); + const ptrdiff_t start = (ptrdiff_t)addr, end = start + sz; + + (void)snprintf(path, sizeof(path), "/proc/%d/map_files/%*.*tx-%*.*tx", + getpid(), len, len, start, len, len, end); + + /* + * Normally can only open if we have PTRACE_MODE_READ_FSCREDS, + * silently ignore failure + */ + fd = open(path, O_RDONLY); + if (fd) { + char pathlink[PATH_MAX]; + void *ptr; + int ret; + + /* + * Readlink will return the /SYSV key info, but since this kind + * of interface may change format, we skip checking it against + * the key + */ + ret = readlink(path, pathlink, sizeof(pathlink)); + (void)ret; + + /* + * The vfs allows us to mmap this file, which corresponds + * to the same physical pages of the shm allocation + */ + ptr = mmap(NULL, sz, PROT_READ, MAP_PRIVATE | MAP_ANONYMOUS, + -1, 0); + if (ptr != MAP_FAILED) + munmap(ptr, sz); + + /* + * We can fsync it to.. + */ + (void)fsync(fd); + (void)close(fd); + } +} +#endif /* * stress_shm_sysv_child() * stress out the shm allocations. This can be killed by @@ -374,9 +426,9 @@ } #endif - /* - * Exercise NUMA mem_policy on shm - */ + /* + * Exercise NUMA mem_policy on shm + */ #if defined(__NR_get_mempolicy) && \ defined(__NR_set_mempolicy) { @@ -392,7 +444,9 @@ (void)ret; } #endif - +#if defined(__linux__) + stress_shm_sysv_linux_proc_map(addr, sz); +#endif inc_counter(args); } diff -Nru stress-ng-0.11.19/stress-sysfs.c stress-ng-0.11.21/stress-sysfs.c --- stress-ng-0.11.19/stress-sysfs.c 2020-08-24 14:14:41.000000000 +0000 +++ stress-ng-0.11.21/stress-sysfs.c 2020-09-16 22:00:11.000000000 +0000 @@ -439,6 +439,10 @@ if (depth > 20) return; + /* Don't want to reset any GCOV metrics */ + if (!strcmp(path, "/sys/kernel/debug/gcov")) + return; + mixup = stress_mwc32(); dlist = NULL; n = scandir(path, &dlist, NULL, mixup_sort); @@ -461,7 +465,7 @@ if (stress_is_dot_filename(d->d_name)) goto dt_reg_free; - (void)snprintf(tmp, sizeof(tmp), "%s/%s", path, d->d_name); + (void)stress_mk_filename(tmp, sizeof(tmp), path, d->d_name); /* Is it in the hash of bad paths? */ if (stress_hash_get(sysfs_hash_table, tmp)) goto dt_reg_free; @@ -528,7 +532,7 @@ if (d->d_type != DT_DIR) goto dt_dir_free; - (void)snprintf(tmp, sizeof(tmp), "%s/%s", path, d->d_name); + (void)stress_mk_filename(tmp, sizeof(tmp), path, d->d_name); ret = stat(tmp, &buf); if (ret < 0) goto dt_dir_free; diff -Nru stress-ng-0.11.19/stress-timer.c stress-ng-0.11.21/stress-timer.c --- stress-ng-0.11.19/stress-timer.c 2020-08-24 14:14:41.000000000 +0000 +++ stress-ng-0.11.21/stress-timer.c 2020-09-16 22:00:11.000000000 +0000 @@ -165,6 +165,7 @@ struct itimerspec timer; sigset_t mask; uint64_t timer_freq = DEFAULT_TIMER_FREQ; + int n = 0; (void)sigemptyset(&mask); (void)sigaddset(&mask, SIGINT); @@ -202,11 +203,28 @@ do { struct timespec req; + int ret; + + if (n++ >= 1024) { + n = 0; + + /* Exercise nanosleep on non-permitted timespec object values */ + (void)memset(&req, 0, sizeof(req)); + req.tv_sec = -1; + ret= nanosleep(&req, NULL); + (void)ret; + + (void)memset(&req, 0, sizeof(req)); + req.tv_nsec = 1000000000; + ret = nanosleep(&req, NULL); + (void)ret; + } req.tv_sec = 0; req.tv_nsec = 10000000; (void)nanosleep(&req, NULL); set_counter(args, timer_counter); + } while (keep_stressing()); if (timer_delete(timerid) < 0) { diff -Nru stress-ng-0.11.19/stress-timerfd.c stress-ng-0.11.21/stress-timerfd.c --- stress-ng-0.11.19/stress-timerfd.c 2020-08-24 14:14:41.000000000 +0000 +++ stress-ng-0.11.21/stress-timerfd.c 2020-09-16 22:00:11.000000000 +0000 @@ -107,6 +107,13 @@ int timerfd[TIMERFD_MAX], procfd, count = 0, i, max_timerfd = -1; char filename[PATH_MAX]; bool timerfd_rand = false; + int file_fd = -1; + char file_fd_name[PATH_MAX]; +#if defined(CLOCK_BOOTTIME_ALARM) + const bool cap_wake_alarm = stress_check_capability(SHIM_CAP_WAKE_ALARM); +#endif + const int bad_fd = stress_get_bad_fd(); + int ret; (void)stress_get_setting("timerfd-rand", &timerfd_rand); @@ -134,6 +141,37 @@ max_timerfd = timerfd[i]; } + /* Create a non valid timerfd file descriptor */ + ret = stress_temp_dir_mk_args(args); + if (ret < 0) + return exit_status(-ret); + (void)stress_temp_filename_args(args, file_fd_name, sizeof(file_fd_name), stress_mwc32()); + file_fd = open(file_fd_name, O_CREAT | O_RDWR, S_IRUSR | S_IWUSR); + if (file_fd < 0) { + pr_err("%s: cannot create %s\n", args->name, file_fd_name); + return exit_status(errno); + } + (void)unlink(file_fd_name); + +#if defined(CLOCK_REALTIME_ALARM) + /* Check timerfd_create cannot succeed without capability */ + if (!cap_wake_alarm) { + ret = timerfd_create(CLOCK_REALTIME_ALARM, 0); + if (ret >= 0) { + pr_fail("%s: timerfd_create without capability CAP_WAKE_ALARM unexpectedly" + "succeeded, errno=%d (%s)\n", args->name, errno, strerror(errno)); + (void)close(ret); + } + } +#endif + +#if defined(CLOCK_REALTIME) + /* Exercise timerfd_create with invalid flags */ + ret = timerfd_create(CLOCK_REALTIME, ~0); + if (ret >= 0) + (void)close(ret); +#endif + if (count == 0) { pr_fail("%s: timerfd_create failed, no timers created\n", args->name); return EXIT_FAILURE; @@ -157,7 +195,6 @@ procfd = open(filename, O_RDONLY); do { - int ret; uint64_t expval; struct itimerspec value; struct timeval timeout; @@ -211,6 +248,24 @@ inc_counter(args); } + /* Exercise invalid timerfd_gettime syscalls on bad fd */ + ret = timerfd_gettime(bad_fd, &value); + (void)ret; + + ret = timerfd_gettime(file_fd, &value); + (void)ret; + + /* Exercise invalid timerfd_settime syscalls on bad fd */ + ret = timerfd_settime(bad_fd, 0, &timer, NULL); + (void)ret; + + ret = timerfd_settime(file_fd, 0, &timer, NULL); + (void)ret; + + /* Exercise timerfd_settime with invalid flags */ + ret = timerfd_settime(bad_fd, ~0, &timer, NULL);; + (void)ret; + /* * Periodically read /proc/$pid/fdinfo/$timerfd, * we don't care about failures, we just want to @@ -234,6 +289,8 @@ } if (procfd > -1) (void)close(procfd); + (void)close(file_fd); + (void)stress_temp_dir_rm_args(args); return EXIT_SUCCESS; } diff -Nru stress-ng-0.11.19/stress-unshare.c stress-ng-0.11.21/stress-unshare.c --- stress-ng-0.11.19/stress-unshare.c 2020-08-24 14:14:41.000000000 +0000 +++ stress-ng-0.11.21/stress-unshare.c 2020-09-16 22:00:11.000000000 +0000 @@ -57,8 +57,12 @@ static void check_unshare(const stress_args_t *args, int flags, const char *flags_name) { int rc; + rc = shim_unshare(flags); - if ((rc < 0) && (errno != EPERM) && (errno != EINVAL)) { + if ((rc < 0) && + (errno != EPERM) && + (errno != EINVAL) && + (errno != ENOSPC)) { pr_fail("%s: unshare(%s) failed, errno=%d (%s)\n", args->name, flags_name, errno, strerror(errno)); diff -Nru stress-ng-0.11.19/stress-vforkmany.c stress-ng-0.11.21/stress-vforkmany.c --- stress-ng-0.11.19/stress-vforkmany.c 2020-08-24 14:14:41.000000000 +0000 +++ stress-ng-0.11.21/stress-vforkmany.c 2020-09-16 22:00:11.000000000 +0000 @@ -46,6 +46,27 @@ STRESS_PRAGMA_POP /* + * vforkmany_wait() + * wait and then kill + */ +static void vforkmany_wait(const pid_t pid) +{ + int sig = SIGALRM; + + for (;;) { + int ret, status; + + errno = 0; + ret = waitpid(pid, &status, 0); + if ((ret >= 0) || (errno != EINTR)) + break; + + (void)kill(pid, sig); + sig = SIGKILL; + } +} + +/* * stress_vforkmany() * stress by vfork'ing as many processes as possible. * vfork has interesting semantics, the parent blocks @@ -56,7 +77,6 @@ */ static int stress_vforkmany(const stress_args_t *args) { - static int status; static pid_t chpid; static volatile int instance = 0; static uint8_t stack_sig[SIGSTKSZ + SIGSTKSZ]; @@ -167,7 +187,7 @@ _exit(0); } /* parent, wait for child, and exit if not top parent */ - (void)shim_waitpid(pid, &status, 0); + (void)vforkmany_wait(pid); if (!first) _exit(0); } while (keep_stressing()); @@ -192,7 +212,7 @@ *terminate = true; (void)kill(chpid, SIGALRM); - (void)shim_waitpid(chpid, &chstatus, 0); + (void)waitpid(chpid, &chstatus, 0); } tidy: (void)munmap((void *)terminate_mmap, args->page_size); diff -Nru stress-ng-0.11.19/stress-xattr.c stress-ng-0.11.21/stress-xattr.c --- stress-ng-0.11.19/stress-xattr.c 2020-08-24 14:14:41.000000000 +0000 +++ stress-ng-0.11.21/stress-xattr.c 2020-09-16 22:00:11.000000000 +0000 @@ -69,8 +69,10 @@ char attrname[32]; char value[32]; char tmp[sizeof(value)]; + char small_tmp[1]; ssize_t sz; char *buffer; + char bad_attrname[32]; for (i = 0; i < MAX_XATTRS; i++) { (void)snprintf(attrname, sizeof(attrname), "user.var_%d", i); @@ -153,6 +155,10 @@ goto out_close; } + /* Exercise getxattr syscall having small value buffer */ + ret = shim_getxattr(filename, attrname, small_tmp, sizeof(small_tmp)); + (void)ret; + ret = shim_getxattr(filename, attrname, tmp, sizeof(tmp)); if (ret < 0) { pr_fail("%s: getxattr failed, errno=%d (%s)\n", @@ -177,6 +183,10 @@ args->name, ret, value, ret, tmp); goto out_close; } + + /* Invalid attribute name */ + (void)memset(&bad_attrname, 0, sizeof(bad_attrname)); + ret = shim_lgetxattr(filename, bad_attrname, tmp, sizeof(tmp)); #endif } @@ -186,6 +196,15 @@ ret = shim_fgetxattr(bad_fd, "user.var_bad", tmp, sizeof(tmp)); (void)ret; + /* Invalid attribute name */ + (void)memset(&bad_attrname, 0, sizeof(bad_attrname)); + ret = shim_fgetxattr(fd, bad_attrname, tmp, sizeof(tmp)); + (void)ret; + + /* Exercise fgetxattr syscall having small value buffer */ + ret = shim_fgetxattr(fd, attrname, small_tmp, sizeof(small_tmp)); + (void)ret; + /* Determine how large a buffer we required... */ sz = shim_flistxattr(fd, NULL, 0); if (sz < 0) { diff -Nru stress-ng-0.11.19/stress-zlib.c stress-ng-0.11.21/stress-zlib.c --- stress-ng-0.11.19/stress-zlib.c 2020-08-24 14:14:41.000000000 +0000 +++ stress-ng-0.11.21/stress-zlib.c 2020-09-16 22:00:11.000000000 +0000 @@ -25,11 +25,15 @@ #include "stress-ng.h" static const stress_help_t help[] = { - { NULL, "zlib N", "start N workers compressing data with zlib" }, - { NULL, "zlib-ops N", "stop after N zlib bogo compression operations" }, - { NULL, "zlib-level L", "specify zlib compression level 0=fast, 9=best" }, - { NULL, "zlib-method M", "specify zlib random data generation method M" }, - { NULL, NULL, NULL } + { NULL, "zlib N", "start N workers compressing data with zlib" }, + { NULL, "zlib-level L", "specify zlib compression level 0=fast, 9=best" }, + { NULL, "zlib-mem-level L", "specify zlib compression state memory usage 1=minimum, 9=maximum" }, + { NULL, "zlib-method M", "specify zlib random data generation method M" }, + { NULL, "zlib-ops N", "stop after N zlib bogo compression operations" }, + { NULL, "zlib-strategy S", "specify zlib strategy 0=default, 1=filtered, 2=huffman only, 3=rle, 4=fixed" }, + { NULL, "zlib-stream-bytes S", "specify the number of bytes to deflate until the current stream will be closed" }, + { NULL, "zlib-window-bits W", "specify zlib window bits -8-(-15) | 8-15 | 24-31 | 40-47" }, + { NULL, NULL, NULL } }; #if defined(HAVE_LIB_Z) @@ -54,11 +58,21 @@ typedef struct { uint64_t xsum; + uint64_t xchars; bool error; bool pipe_broken; bool interrupted; } stress_xsum_t; +typedef struct { + char *data_func; /* pointer to data generator fucntion */ + int32_t window_bits; /* zlib window bits */ + uint32_t level; /* zlib compression level */ + uint32_t mem_level; /* zlib memory usage */ + uint32_t strategy; /* zlib strategy */ + uint64_t stream_bytes; /* size of generated data until deflate should generate Z_STREAM_END */ +} stress_zlib_args_t; + typedef struct morse { char ch; char *str; @@ -931,6 +945,20 @@ } /* + * stress_set_zlib_mem_level + * set the amount of reserved memory for the compression state, 1..9, + * 1 = minimum, 9 = maximum + */ +static int stress_set_zlib_mem_level(const char *opt) +{ + uint32_t zlib_mem_level; + + zlib_mem_level = stress_get_uint32(opt); + stress_check_range("zlib-mem-level", zlib_mem_level, 1, 9); + return stress_set_setting("zlib-mem-level", TYPE_ID_UINT32, &zlib_mem_level); +} + +/* * stress_set_zlib_method() * set the default zlib random data method */ @@ -954,10 +982,71 @@ return -1; } +/* + * stress_set_zlib_window_bits + * specify the window bits used to allocate the history buffer size. The value is + * specified as the base two logarithm of the buffer size (e.g. value 9 is 2^9 = + * 512 bytes). + * 8-(-15): raw format + * 8-15: zlib format + * 24-31: gzip format (zlib format +16) + * 40-47: autodetect format when using inflate (zlib format +32) + * hint: stress-ng uses zlib format as default for deflate + */ +static int stress_set_zlib_window_bits(const char *opt) +{ + int32_t zlib_window_bits; + + zlib_window_bits = stress_get_int32(opt); + if (zlib_window_bits > 31) { + /* auto detect inflate format */ + stress_check_range("zlib-window-bits", zlib_window_bits, 40, 47); + } else if (zlib_window_bits > 15) { + /* gzip format */ + stress_check_range("zlib-window-bits", zlib_window_bits, 24, 31); + } else if (zlib_window_bits > 0) { + /* zlib format */ + stress_check_range("zlib-window-bits", zlib_window_bits, 8, 15); + } else { + stress_check_range("zlib-window-bits", zlib_window_bits, -15, -8); + } + return stress_set_setting("zlib-window-bits", TYPE_ID_INT32, &zlib_window_bits); +} + +/* + * stress_set_zlib_stream_bytes + * create chunks instead of an endless deflate stream + */ +static int stress_set_zlib_stream_bytes(const char *opt) +{ + uint64_t zlib_stream_bytes; + + zlib_stream_bytes = (size_t)stress_get_uint64_byte_memory(opt, 1); + stress_check_range_bytes("zlib-stream-bytes", zlib_stream_bytes, 0, MAX_MEM_LIMIT); + return stress_set_setting("zlib-stream-bytes", TYPE_ID_UINT64, &zlib_stream_bytes); +} + +/* + * stress_set_zlib_strategy + * set the zlib compression strategy to be used for compression + */ +static int stress_set_zlib_strategy(const char *opt) +{ + uint32_t zlib_strategy; + + zlib_strategy = stress_get_uint32(opt); + stress_check_range("zlib-strategy", zlib_strategy, Z_DEFAULT_STRATEGY, Z_FIXED); + return stress_set_setting("zlib-strategy", TYPE_ID_UINT32, &zlib_strategy); +} + static const stress_opt_set_func_t opt_set_funcs[] = { - { OPT_zlib_level, stress_set_zlib_level }, - { OPT_zlib_method, stress_set_zlib_method }, - { 0, NULL } + { OPT_zlib_level, stress_set_zlib_level }, + { OPT_zlib_mem_level, stress_set_zlib_mem_level }, + { OPT_zlib_method, stress_set_zlib_method }, + { OPT_zlib_window_bits, stress_set_zlib_window_bits }, + { OPT_zlib_stream_bytes, stress_set_zlib_stream_bytes }, + { OPT_zlib_strategy, stress_set_zlib_strategy }, + { 0, NULL } }; /* @@ -976,19 +1065,31 @@ errno, strerror(errno)); return buf; case Z_STREAM_ERROR: - return "invalid compression level"; + return "inconsistent stream or invalid parameter level/memory/strategy/window-bits (Z_STREAM_ERROR)"; case Z_DATA_ERROR: - return "invalid or incomplete deflate data"; + return "invalid or incomplete deflate data or stream was freed prematurely (Z_DATA_ERROR)"; case Z_MEM_ERROR: - return "out of memory"; + return "out of memory (Z_MEM_ERROR)"; case Z_VERSION_ERROR: - return "zlib version mismatch"; + return "zlib version mismatch (Z_VERSION_ERROR)"; default: (void)snprintf(buf, sizeof(buf), "unknown zlib error %d\n", zlib_err); return buf; } } +/* + * stress_zlib_get_args() + * get all zlib arguments at once + */ +static void stress_zlib_get_args(stress_zlib_args_t *parms) { + (void)stress_get_setting("zlib-level", &parms->level); + (void)stress_get_setting("zlib-mem-level", &parms->mem_level); + (void)stress_get_setting("zlib-method", &parms->data_func); + (void)stress_get_setting("zlib-window-bits", &parms->window_bits); + (void)stress_get_setting("zlib-stream-bytes", &parms->stream_bytes); + (void)stress_get_setting("zlib-strategy", &parms->strategy); +} /* * stress_zlib_inflate() @@ -1000,14 +1101,18 @@ const int fd, const int xsum_fd) { + ssize_t sz; int ret, err = 0; z_stream stream_inf; - uint64_t xsum_chars = 0; static unsigned char in[DATA_SIZE]; static unsigned char out[DATA_SIZE]; stress_xsum_t xsum; + stress_zlib_args_t zlib_args; + + (void)stress_zlib_get_args(&zlib_args); xsum.xsum = 0; + xsum.xchars = 0; xsum.error = false; xsum.pipe_broken = false; xsum.interrupted = false; @@ -1018,77 +1123,112 @@ stream_inf.avail_in = 0; stream_inf.next_in = Z_NULL; - ret = inflateInit(&stream_inf); - if (ret != Z_OK) { - pr_fail("%s: zlib inflateInit error: %s\n", - args->name, stress_zlib_err(ret)); - xsum.error = true; - goto xsum_error; - } - + pr_dbg("INF: lvl=%d mem-lvl=%d wbits=%d strategy=%d\n", + zlib_args.level, zlib_args.mem_level, zlib_args.window_bits, + zlib_args.strategy); do { - ssize_t sz; - - sz = read(fd, in, DATA_SIZE); - if (sz < 0) { - if ((errno != EINTR) && (errno != EPIPE)) { - pr_fail("%s: zlib inflate pipe read error: errno=%d (%s)\n", - args->name, errno, strerror(errno)); - (void)inflateEnd(&stream_inf); - xsum.error = true; - goto xsum_error; - } else { - if (errno == EINTR) - xsum.interrupted = true; - if (errno == EPIPE) - xsum.pipe_broken = true; - break; - } - } - - if (sz == 0) { - xsum.pipe_broken = true; - break; + ret = inflateInit2(&stream_inf, zlib_args.window_bits); + if (ret != Z_OK) { + pr_fail("%s: zlib inflateInit error: %s\n", + args->name, stress_zlib_err(ret)); + xsum.error = true; + goto xsum_error; } - stream_inf.avail_in = sz; - stream_inf.next_in = in; - do { - stream_inf.avail_out = DATA_SIZE; - stream_inf.next_out = out; - - ret = inflate(&stream_inf, Z_NO_FLUSH); - switch (ret) { - case Z_NEED_DICT: - case Z_DATA_ERROR: - case Z_MEM_ERROR: + int def_size; + /* read buffer size first */ + sz = stress_read_buffer(fd, &def_size, sizeof(def_size), false); + if (sz == 0) { + break; + } else if (sz != sizeof(def_size)) { + (void)inflateEnd(&stream_inf); + if ((errno != EINTR) && (errno != EPIPE)) { + pr_fail("%s: zlib pipe read size error: %s (ret=%zd errno=%d)\n", + args->name, strerror(errno), sz, errno); + xsum.error = true; + goto xsum_error; + } else { + if (errno == EINTR) + xsum.interrupted = true; + if (errno == EPIPE) + xsum.pipe_broken = true; + goto finish; + } + } + /* read deflated buffer */ + sz = stress_read_buffer(fd, in, def_size, false); + if (sz == 0) { + break; + } else if (sz != def_size) { (void)inflateEnd(&stream_inf); - goto xsum_error; + if ((errno != EINTR) && (errno != EPIPE)) { + pr_fail("%s: zlib pipe read buffer error: %s (ret=%zd errno=%d)\n", + args->name, strerror(errno), sz, errno); + xsum.error = true; + goto xsum_error; + } else { + if (errno == EINTR) + xsum.interrupted = true; + if (errno == EPIPE) + xsum.pipe_broken = true; + goto finish; + } } - if (g_opt_flags & OPT_FLAGS_VERIFY) { - size_t i; + stream_inf.avail_in = sz; + stream_inf.next_in = in; + do { + stream_inf.avail_out = DATA_SIZE; + stream_inf.next_out = out; + + pr_dbg_v("INF: %6d %6d\n", stream_inf.avail_in, + stream_inf.avail_out); + ret = inflate(&stream_inf, Z_NO_FLUSH); + pr_dbg_v("INF: %6d %6d written=%6lld rc=%2d\n", + stream_inf.avail_in, + stream_inf.avail_out, + DATA_SIZE - stream_inf.avail_out, ret); + + switch (ret) { + case Z_BUF_ERROR: + pr_dbg_v("%s: zlib inflate error: %s\n", + args->name, stress_zlib_err(ret)); + break; + case Z_NEED_DICT: + case Z_DATA_ERROR: + case Z_MEM_ERROR: + pr_fail("%s: zlib inflate error: %s\n", + args->name, stress_zlib_err(ret)); + (void)inflateEnd(&stream_inf); + goto xsum_error; + } + + if (g_opt_flags & OPT_FLAGS_VERIFY) { + size_t i; - for (i = 0; i < DATA_SIZE - stream_inf.avail_out; i++) { - xsum.xsum += (uint64_t)out[i]; - xsum_chars++; + for (i = 0; i < DATA_SIZE - stream_inf.avail_out; i++) { + xsum.xsum += (uint64_t)out[i]; + xsum.xchars++; + } } - } - } while (stream_inf.avail_out == 0); - } while (ret != Z_STREAM_END); + } while (stream_inf.avail_out == 0); + } while (ret != Z_STREAM_END); + (void)inflateEnd(&stream_inf); + stream_inf.zalloc = Z_NULL; + stream_inf.zfree = Z_NULL; + stream_inf.opaque = Z_NULL; + } while (sz > 0); - /* +finish: if (g_opt_flags & OPT_FLAGS_VERIFY) { - pr_dbg("%s: inflate xsum value %" PRIu64 - ", xsum_chars %" PRIu64 "\n", - args->name, xsum.xsum, xsum_chars); + pr_dbg_v("%s: inflate xsum value %" PRIu64 + ", xsum.xchars %" PRIu64 "\n", + args->name, xsum.xsum, xsum.xchars); } - */ - (void)inflateEnd(&stream_inf); if (write(xsum_fd, &xsum, sizeof(xsum)) < 0) { - pr_fail("%s: zlib inflate pipe write failed, errno=%d (%s)\n", + pr_fail("%s: zlib inflate pipe write failed for xsum, errno=%d (%s)\n", args->name, err, strerror(err)); } return ((ret == Z_OK) || (ret == Z_STREAM_END)) ? @@ -1111,22 +1251,22 @@ static int stress_zlib_deflate( const stress_args_t *args, const int fd, - const int xsum_fd, - const int zlib_level) + const int xsum_fd) { + uint64_t stream_bytes_out = 0; int ret, err = 0; - bool do_run; z_stream stream_def; uint64_t bytes_in = 0, bytes_out = 0; - uint64_t xsum_chars = 0; int flush; stress_zlib_rand_data_info_t *opt_zlib_rand_data_func = &zlib_rand_data_methods[0]; + stress_zlib_args_t zlib_args; double t1, t2; stress_xsum_t xsum; - (void)stress_get_setting("zlib-method", &opt_zlib_rand_data_func); + (void)stress_zlib_get_args(&zlib_args); xsum.xsum = 0; + xsum.xchars = 0; xsum.error = false; xsum.pipe_broken = false; xsum.interrupted = false; @@ -1136,70 +1276,133 @@ stream_def.opaque = Z_NULL; t1 = stress_time_now(); - ret = deflateInit(&stream_def, zlib_level); - if (ret != Z_OK) { - pr_fail("%s: zlib deflateInit error: %s\n", - args->name, stress_zlib_err(ret)); - xsum.error = true; - ret = EXIT_FAILURE; - goto xsum_error; - } + /* default to zlib format if inflate auto detect has been used */ + if (zlib_args.window_bits > 31) + zlib_args.window_bits = zlib_args.window_bits - 32; + + pr_dbg("DEF: lvl=%d mem-lvl=%d wbits=%d strategy=%d stream-bytes=%llu\n", + zlib_args.level, zlib_args.mem_level, zlib_args.window_bits, + zlib_args.strategy, (unsigned long long)zlib_args.stream_bytes); do { - static uint32_t in[DATA_SIZE / sizeof(uint32_t)]; - unsigned char *xsum_in = (unsigned char *)in; - - opt_zlib_rand_data_func->func(args, in, DATA_SIZE); + ret = deflateInit2(&stream_def, zlib_args.level, + Z_DEFLATED, zlib_args.window_bits, + zlib_args.mem_level, zlib_args.strategy); + if (ret != Z_OK) { + pr_fail("%s: zlib deflateInit error: %s\n", + args->name, stress_zlib_err(ret)); + xsum.error = true; + ret = EXIT_FAILURE; + goto xsum_error; + } - stream_def.avail_in = DATA_SIZE; - stream_def.next_in = (unsigned char *)in; + stream_bytes_out = 0; + do { + static unsigned char in[DATA_SIZE]; + unsigned char *xsum_in = (unsigned char *)in; - if (g_opt_flags & OPT_FLAGS_VERIFY) { - for (int i = 0; i < (int)(DATA_SIZE / sizeof(unsigned char)); i++) { - xsum.xsum += (uint64_t)xsum_in[i]; - xsum_chars++; - } - } + int gen_sz = (zlib_args.stream_bytes - stream_bytes_out >= DATA_SIZE + || zlib_args.stream_bytes - stream_bytes_out == 0 + || zlib_args.stream_bytes == 0) + ? DATA_SIZE : (zlib_args.stream_bytes - stream_bytes_out); + + if (zlib_args.stream_bytes > 0) + flush = (stream_bytes_out + gen_sz < zlib_args.stream_bytes + && keep_stressing()) + ? Z_NO_FLUSH : Z_FINISH; + else + flush = keep_stressing() ? Z_NO_FLUSH : Z_FINISH; - do_run = keep_stressing(); - flush = do_run ? Z_NO_FLUSH : Z_FINISH; - bytes_in += DATA_SIZE; + opt_zlib_rand_data_func->func(args, (uint32_t *)in, (DATA_SIZE/sizeof(uint32_t))); - do { - static unsigned char out[DATA_SIZE]; - int def_size, rc; + stream_def.avail_in = gen_sz; + stream_def.next_in = (unsigned char *)in; - stream_def.avail_out = DATA_SIZE; - stream_def.next_out = out; - rc = deflate(&stream_def, flush); - - if (rc == Z_STREAM_ERROR) { - pr_fail("%s: zlib deflate error: %s\n", - args->name, stress_zlib_err(rc)); - (void)deflateEnd(&stream_def); - ret = EXIT_FAILURE; - goto xsum_error; + if (g_opt_flags & OPT_FLAGS_VERIFY) { + for (int i = 0; i < gen_sz; i++) { + xsum.xsum += xsum_in[i]; + xsum.xchars++; + } } - def_size = DATA_SIZE - stream_def.avail_out; - bytes_out += def_size; - if (write(fd, out, def_size) != def_size) { - if ((errno != EINTR) && (errno != EPIPE) && (errno != 0)) { - pr_fail("%s: write failed, errno=%d (%s)\n", - args->name, errno, strerror(errno)); + + bytes_in += DATA_SIZE; + do { + static unsigned char out[DATA_SIZE]; + ssize_t sz; + int def_size; + + stream_def.avail_out = DATA_SIZE; + stream_def.next_out = out; + + pr_dbg_v("DEF: %6d %6d\n", stream_def.avail_in, + stream_def.avail_out); + ret = deflate(&stream_def, flush); + pr_dbg_v("DEF: %6d %6d written=%6lld rc=%2d\n", + stream_def.avail_in, + stream_def.avail_out, + DATA_SIZE - stream_def.avail_out, ret); + + if (ret == Z_STREAM_ERROR) { + pr_fail("%s: zlib deflate error: %s\n", + args->name, stress_zlib_err(ret)); (void)deflateEnd(&stream_def); ret = EXIT_FAILURE; goto xsum_error; - } else { - if (errno == EINTR) - xsum.interrupted = true; - if (errno == EPIPE) - xsum.pipe_broken = true; - goto finish; } - } - inc_counter(args); - } while (stream_def.avail_out == 0); - } while (flush != Z_FINISH); + def_size = DATA_SIZE - stream_def.avail_out; + bytes_out += def_size; + stream_bytes_out += (def_size) ? gen_sz : 0; + + /* continue if nothing has been deflated */ + if (def_size == 0) + continue; + + /* write buffer length value */ + sz = stress_write_buffer(fd, &def_size, sizeof(def_size), true); + if (sz == 0) { + break; + } else if (sz != sizeof(def_size)) { + (void)deflateEnd(&stream_def); + if ((errno != EINTR) && (errno != EPIPE) && (errno != 0)) { + pr_fail("%s: zlib pipe write size error: %s (ret=%zd errno=%d)\n", + args->name, strerror(errno), sz, errno); + ret = EXIT_FAILURE; + goto xsum_error; + } else { + if (errno == EINTR) + xsum.interrupted = true; + if (errno == EPIPE) + xsum.pipe_broken = true; + goto finish; + } + } + /* write deflate buffer */ + sz = stress_write_buffer(fd, out, def_size, true); + if (sz == 0) { + break; + } else if (sz != def_size) { + (void)deflateEnd(&stream_def); + if ((errno != EINTR) && (errno != EPIPE) && (errno != 0)) { + pr_fail("%s: zlib pipe write buffer error: %s (ret=%zd errno=%d)\n", + args->name, strerror(errno), sz, errno); + ret = EXIT_FAILURE; + goto xsum_error; + } else { + if (errno == EINTR) + xsum.interrupted = true; + if (errno == EPIPE) + xsum.pipe_broken = true; + goto finish; + } + } + inc_counter(args); + } while (stream_def.avail_out == 0); + } while (ret != Z_STREAM_END); + (void)deflateEnd(&stream_def); + stream_def.zalloc = Z_NULL; + stream_def.zfree = Z_NULL; + stream_def.opaque = Z_NULL; + } while (keep_stressing()); finish: t2 = stress_time_now(); @@ -1208,19 +1411,16 @@ bytes_in ? 100.0 * (double)bytes_out / (double)bytes_in : 0, (t2 - t1 > 0.0) ? (bytes_in / (t2 - t1)) / MB : 0.0); - /* if (g_opt_flags & OPT_FLAGS_VERIFY) { - pr_dbg("%s: deflate xsum value %" PRIu64 - ", xsum_chars %" PRIu64 "\n", - args->name, xsum.xsum, xsum_chars); + pr_dbg_v("%s: deflate xsum value %" PRIu64 + ", xsum.xchars %" PRIu64 "\n", + args->name, xsum.xsum, xsum.xchars); } - */ - (void)deflateEnd(&stream_def); ret = EXIT_SUCCESS; xsum_error: if (write(xsum_fd, &xsum, sizeof(xsum)) < 0 ) { - pr_fail("%s: zlib deflate pipe write error: errno=%d (%s)\n", + pr_fail("%s: zlib deflate pipe write error for xsum: errno=%d (%s)\n", args->name, err, strerror(err)); } @@ -1238,7 +1438,6 @@ int err = 0; pid_t pid; stress_xsum_t deflate_xsum, inflate_xsum; - uint32_t zlib_level = Z_BEST_COMPRESSION; /* best compression */ ssize_t n; bool bad_xsum_reads = false; bool error = false; @@ -1250,8 +1449,6 @@ if (stress_sighandler(args->name, SIGPIPE, stress_sigpipe_handler, NULL) < 0) return EXIT_FAILURE; - (void)stress_get_setting("zlib-level", &zlib_level); - if (pipe(fds) < 0) { pr_err("%s: pipe failed, errno=%d (%s)\n", args->name, errno, strerror(errno)); @@ -1297,12 +1494,15 @@ (void)close(fds[0]); _exit(ret); } else { + int retval; + (void)close(fds[0]); - ret = stress_zlib_deflate(args, fds[1], deflate_xsum_fds[1], (int)zlib_level); + ret = stress_zlib_deflate(args, fds[1], deflate_xsum_fds[1]); (void)close(fds[1]); + (void)waitpid(pid, &retval, 0); } - n = read(deflate_xsum_fds[0], &deflate_xsum, sizeof(deflate_xsum)); + n = stress_read_buffer(deflate_xsum_fds[0], &deflate_xsum, sizeof(deflate_xsum), false); if (n != sizeof(deflate_xsum)) { bad_xsum_reads = true; if ((errno != EINTR) && (errno != EPIPE)) { @@ -1315,7 +1515,7 @@ error |= deflate_xsum.error; } - n = read(inflate_xsum_fds[0], &inflate_xsum, sizeof(inflate_xsum)); + n = stress_read_buffer(inflate_xsum_fds[0], &inflate_xsum, sizeof(inflate_xsum), false); if (n != sizeof(inflate_xsum)) { bad_xsum_reads = true; if ((errno != EINTR) && (errno != EPIPE)) { @@ -1329,8 +1529,9 @@ } if (pipe_broken || bad_xsum_reads || interrupted || error) { - pr_inf("%s: cannot verify inflate/deflate checksums:%s%s%s%s%s%s%s\n", + pr_inf("%s: cannot verify inflate(%d)/deflate checksums:%s%s%s%s%s%s%s\n", args->name, + (int)pid, interrupted ? " interrupted" : "", (interrupted & pipe_broken) ? " and" : "", pipe_broken ? " broken pipe" : "", @@ -1339,16 +1540,26 @@ ((interrupted | pipe_broken | error) & bad_xsum_reads) ? " and" : "", bad_xsum_reads ? " could not read checksums" : ""); } else { - if ((g_opt_flags & OPT_FLAGS_VERIFY) && - (deflate_xsum.xsum != inflate_xsum.xsum)) { - pr_fail("%s: zlib xsum values do NOT match " - "deflate xsum %" PRIu64 - " vs inflate xsum %" PRIu64 "\n", - args->name, deflate_xsum.xsum, inflate_xsum.xsum); - ret = EXIT_FAILURE; + if (g_opt_flags & OPT_FLAGS_VERIFY) { + if (deflate_xsum.xsum != inflate_xsum.xsum) { + pr_fail("%s: zlib xsum values do NOT match " + "%" PRIu64 "/%" PRIu64 + "(deflate/inflate)" + " vs " + "%" PRIu64 "/%" PRIu64 + "(deflated/inflated bytes)\n", + args->name, deflate_xsum.xsum, + inflate_xsum.xsum, deflate_xsum.xchars, + inflate_xsum.xchars); + ret = EXIT_FAILURE; + } else { + pr_inf("%s: zlib xsum values matches " + "%" PRIu64"/%" PRIu64 + "(deflate/inflate)\n", args->name, + deflate_xsum.xsum, inflate_xsum.xsum); + } } } - (void)close(deflate_xsum_fds[0]); (void)close(deflate_xsum_fds[1]); (void)close(inflate_xsum_fds[0]); @@ -1362,7 +1573,16 @@ static void stress_zlib_set_default(void) { + char value[21]; + + (void)snprintf(value, 21, "%d", Z_BEST_COMPRESSION); + stress_set_zlib_level(value); + stress_set_zlib_mem_level("8"); stress_set_zlib_method("random"); + stress_set_zlib_window_bits("15"); + stress_set_zlib_stream_bytes("0"); + (void)snprintf(value, 21, "%d", Z_DEFAULT_STRATEGY); + stress_set_zlib_strategy(value); } stressor_info_t stress_zlib_info = { diff -Nru stress-ng-0.11.19/syscalls.txt stress-ng-0.11.21/syscalls.txt --- stress-ng-0.11.19/syscalls.txt 2020-08-24 14:14:41.000000000 +0000 +++ stress-ng-0.11.21/syscalls.txt 2020-09-16 22:00:11.000000000 +0000 @@ -126,15 +126,16 @@ init_module inotify_add_watch inotify inotify_init inotify +inotify_init1 inotify inotify_rm_watch inotify io_cancel aiol io_destroy aiol io_getevents aiol io_setup aiol io_submit aiol -io_uring_enter +io_uring_enter io_uring io_uring_register -io_uring_setup +io_uring_setup io_uring ioctl pty, fiemap, rtc, urandom, userfaultfd ioperm ditto iopl ditto @@ -150,7 +151,7 @@ lchown chown lgetxattr xattr link link -linkat +linkat dirdeep listen sock listxattr xattr llistxattr xattr @@ -204,8 +205,8 @@ nice nice open dentry, open, etc open_by_handle_at handle -openat io -openat2 +openat io, open +openat2 waiting for open_how struct in glibc open_tree pause kcmp, wait perf_event_open --perf option diff -Nru stress-ng-0.11.19/test/test-epoll-create.c stress-ng-0.11.21/test/test-epoll-create.c --- stress-ng-0.11.19/test/test-epoll-create.c 1970-01-01 00:00:00.000000000 +0000 +++ stress-ng-0.11.21/test/test-epoll-create.c 2020-09-16 22:00:11.000000000 +0000 @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2013-2020 Canonical, 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 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. + * + * This code is a complete clean re-write of the stress tool by + * Colin Ian King and attempts to be + * backwardly compatible with the stress tool by Amos Waterland + * but has more stress tests and more + * functionality. + * + */ + +#define _GNU_SOURCE + +#include + +int main(void) +{ + return epoll_create(10); +} diff -Nru stress-ng-0.11.19/test/test-inotify1.c stress-ng-0.11.21/test/test-inotify1.c --- stress-ng-0.11.19/test/test-inotify1.c 1970-01-01 00:00:00.000000000 +0000 +++ stress-ng-0.11.21/test/test-inotify1.c 2020-09-16 22:00:11.000000000 +0000 @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2012-2020 Canonical, 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 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. + * + * This code is a complete clean re-write of the stress tool by + * Colin Ian King and attempts to be + * backwardly compatible with the stress tool by Amos Waterland + * but has more stress tests and more + * functionality. + */ + +#include +#include + +int main(void) +{ + int fd; + + fd = inotify_init1(0); + if (fd < 0) { + return -1; + } + + (void)close(fd); + return 0; +} diff -Nru stress-ng-0.11.19/test/test-kbdiacrs.c stress-ng-0.11.21/test/test-kbdiacrs.c --- stress-ng-0.11.19/test/test-kbdiacrs.c 1970-01-01 00:00:00.000000000 +0000 +++ stress-ng-0.11.21/test/test-kbdiacrs.c 2020-09-16 22:00:11.000000000 +0000 @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2013-2020 Canonical, 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 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. + * + * This code is a complete clean re-write of the stress tool by + * Colin Ian King and attempts to be + * backwardly compatible with the stress tool by Amos Waterland + * but has more stress tests and more + * functionality. + * + */ +#include + +int main(void) +{ + struct kbdiacrs m; + + (void)m; + + return sizeof(m); +} diff -Nru stress-ng-0.11.19/test/test-kbsentry.c stress-ng-0.11.21/test/test-kbsentry.c --- stress-ng-0.11.19/test/test-kbsentry.c 1970-01-01 00:00:00.000000000 +0000 +++ stress-ng-0.11.21/test/test-kbsentry.c 2020-09-16 22:00:11.000000000 +0000 @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2013-2020 Canonical, 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 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. + * + * This code is a complete clean re-write of the stress tool by + * Colin Ian King and attempts to be + * backwardly compatible with the stress tool by Amos Waterland + * but has more stress tests and more + * functionality. + * + */ +#include + +int main(void) +{ + struct kbsentry m; + + (void)m; + + return sizeof(m); +} diff -Nru stress-ng-0.11.19/test/test-linkat.c stress-ng-0.11.21/test/test-linkat.c --- stress-ng-0.11.19/test/test-linkat.c 1970-01-01 00:00:00.000000000 +0000 +++ stress-ng-0.11.21/test/test-linkat.c 2020-09-16 22:00:11.000000000 +0000 @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2013-2020 Canonical, 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 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. + * + * This code is a complete clean re-write of the stress tool by + * Colin Ian King and attempts to be + * backwardly compatible with the stress tool by Amos Waterland + * but has more stress tests and more + * functionality. + * + */ +#include + +int main(void) +{ + return linkat(0, "a", 1, "b", 0); +} diff -Nru stress-ng-0.11.19/test/test-openat.c stress-ng-0.11.21/test/test-openat.c --- stress-ng-0.11.19/test/test-openat.c 1970-01-01 00:00:00.000000000 +0000 +++ stress-ng-0.11.21/test/test-openat.c 2020-09-16 22:00:11.000000000 +0000 @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2013-2020 Canonical, 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 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. + * + * This code is a complete clean re-write of the stress tool by + * Colin Ian King and attempts to be + * backwardly compatible with the stress tool by Amos Waterland + * but has more stress tests and more + * functionality. + * + */ +#define _GNU_SOURCE + +#include +#include +#include + +int main(void) +{ + return openat(AT_FDCWD, "test", O_RDWR); +} diff -Nru stress-ng-0.11.19/test/test-open_how.c stress-ng-0.11.21/test/test-open_how.c --- stress-ng-0.11.19/test/test-open_how.c 1970-01-01 00:00:00.000000000 +0000 +++ stress-ng-0.11.21/test/test-open_how.c 2020-09-16 22:00:11.000000000 +0000 @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2013-2020 Canonical, 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 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. + * + * This code is a complete clean re-write of the stress tool by + * Colin Ian King and attempts to be + * backwardly compatible with the stress tool by Amos Waterland + * but has more stress tests and more + * functionality. + * + */ +#include +#include +#include + +int main(void) +{ + struct open_how how; + + (void)how; + + return sizeof(how); +} diff -Nru stress-ng-0.11.19/test/test-vt_consize.c stress-ng-0.11.21/test/test-vt_consize.c --- stress-ng-0.11.19/test/test-vt_consize.c 1970-01-01 00:00:00.000000000 +0000 +++ stress-ng-0.11.21/test/test-vt_consize.c 2020-09-16 22:00:11.000000000 +0000 @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2013-2020 Canonical, 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 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. + * + * This code is a complete clean re-write of the stress tool by + * Colin Ian King and attempts to be + * backwardly compatible with the stress tool by Amos Waterland + * but has more stress tests and more + * functionality. + * + */ +#include + +int main(void) +{ + struct vt_consize vc; + + (void)vc; + + return sizeof(vc); +} diff -Nru stress-ng-0.11.19/test/test-vt_sizes.c stress-ng-0.11.21/test/test-vt_sizes.c --- stress-ng-0.11.19/test/test-vt_sizes.c 1970-01-01 00:00:00.000000000 +0000 +++ stress-ng-0.11.21/test/test-vt_sizes.c 2020-09-16 22:00:11.000000000 +0000 @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2013-2020 Canonical, 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 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. + * + * This code is a complete clean re-write of the stress tool by + * Colin Ian King and attempts to be + * backwardly compatible with the stress tool by Amos Waterland + * but has more stress tests and more + * functionality. + * + */ +#include + +int main(void) +{ + struct vt_sizes vt; + + (void)vt; + + return sizeof(vt); +}