From 0a38b72d2ffb722f08c26dd734baef54ff788fde Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Fri, 15 May 2020 23:23:43 +0100 Subject: [PATCH 01/28] stress-hdd: use preadv, preadv2, pwritev, pwritev2 Exercise iovec family of read/write system calls to get more kernel coverage Signed-off-by: Colin Ian King --- Makefile.config | 24 ++++++++++++++++++++ stress-hdd.c | 47 +++++++++++++++++++++++++++++++++++++-- test/test-preadv.c | 52 ++++++++++++++++++++++++++++++++++++++++++++ test/test-preadv2.c | 52 ++++++++++++++++++++++++++++++++++++++++++++ test/test-pwritev.c | 14 +++++++++++- test/test-pwritev2.c | 50 ++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 236 insertions(+), 3 deletions(-) create mode 100644 test/test-preadv.c create mode 100644 test/test-preadv2.c create mode 100644 test/test-pwritev2.c diff --git a/Makefile.config b/Makefile.config index 0d306e1fbd32..826cf29e8158 100644 --- a/Makefile.config +++ b/Makefile.config @@ -2233,6 +2233,22 @@ $(info autoconfig: using prctl) endif endif +ifndef $(HAVE_PREADV) +HAVE_PREADV = $(shell $(MAKE) -f Makefile.config --no-print-directory $(HAVE_NOT) TEST_PROG=test-preadv have_test_prog) +ifeq ($(HAVE_PREADV),1) + CONFIG_CFLAGS += -DHAVE_PREADV +$(info autoconfig: using preadv) +endif +endif + +ifndef $(HAVE_PREADV2) +HAVE_PREADV2 = $(shell $(MAKE) -f Makefile.config --no-print-directory $(HAVE_NOT) TEST_PROG=test-preadv2 have_test_prog) +ifeq ($(HAVE_PREADV2),1) + CONFIG_CFLAGS += -DHAVE_PREADV2 +$(info autoconfig: using preadv2) +endif +endif + ifndef $(HAVE_PRLIMIT) HAVE_PRLIMIT = $(shell $(MAKE) -f Makefile.config --no-print-directory $(HAVE_NOT) TEST_PROG=test-prlimit have_test_prog) ifeq ($(HAVE_PRLIMIT),1) @@ -2297,6 +2313,14 @@ $(info autoconfig: using pwritev) endif endif +ifndef $(HAVE_PWRITEV2) +HAVE_PWRITEV2 = $(shell $(MAKE) -f Makefile.config --no-print-directory $(HAVE_NOT) TEST_PROG=test-pwritev2 have_test_prog) +ifeq ($(HAVE_PWRITEV2),1) + CONFIG_CFLAGS += -DHAVE_PWRITEV2 +$(info autoconfig: using pwritev2) +endif +endif + ifndef $(HAVE_RECVMMSG) HAVE_RECVMMSG = $(shell $(MAKE) -f Makefile.config --no-print-directory $(HAVE_NOT) TEST_PROG=test-recvmmsg have_test_prog) ifeq ($(HAVE_RECVMMSG),1) diff --git a/stress-hdd.c b/stress-hdd.c index 9bdf881e0f2e..a9a9dad53352 100644 --- a/stress-hdd.c +++ b/stress-hdd.c @@ -180,6 +180,9 @@ static ssize_t stress_hdd_write( size_t i; uint8_t *data = buf; const uint64_t sz = hdd_write_size / HDD_IO_VEC_MAX; + off_t offset; + + (void)offset; for (i = 0; i < HDD_IO_VEC_MAX; i++) { iov[i].iov_base = (void *)data; @@ -187,7 +190,27 @@ static ssize_t stress_hdd_write( data += sz; } - ret = writev(fd, iov, HDD_IO_VEC_MAX); + switch (stress_mwc8() & 3) { +#if defined(HAVE_PWRITEV2) + case 0: + /* 25% */ + ret = pwritev2(fd, iov, HDD_IO_VEC_MAX, -1, 0); + break; +#endif +#if defined(HAVE_PWRITEV) + case 1: + /* 25% */ + offset = lseek(fd, SEEK_CUR, 0); + if (offset != (off_t)-1) { + ret = pwritev(fd, iov, HDD_IO_VEC_MAX, offset); + break; + } + CASE_FALLTHROUGH; +#endif + default: + ret = writev(fd, iov, HDD_IO_VEC_MAX); + break; + } } else { ret = write(fd, buf, count); } @@ -229,6 +252,9 @@ static ssize_t stress_hdd_read( size_t i; uint8_t *data = buf; const uint64_t sz = hdd_write_size / HDD_IO_VEC_MAX; + off_t offset; + + (void)offset; for (i = 0; i < HDD_IO_VEC_MAX; i++) { iov[i].iov_base = (void *)data; @@ -236,7 +262,24 @@ static ssize_t stress_hdd_read( data += sz; } - return readv(fd, iov, HDD_IO_VEC_MAX); + switch (stress_mwc8() & 3) { +#if defined(HAVE_PREADV2) + case 0: + /* 25% */ + return preadv2(fd, iov, HDD_IO_VEC_MAX, -1, 0); +#endif +#if defined(HAVE_PREADV) + case 1: + /* 25% */ + offset = lseek(fd, SEEK_CUR, 0); + if (offset != (off_t)-1) + return preadv(fd, iov, HDD_IO_VEC_MAX, offset); + CASE_FALLTHROUGH; +#endif + default: + /* 50% */ + return readv(fd, iov, HDD_IO_VEC_MAX); + } } else { return read(fd, buf, count); } diff --git a/test/test-preadv.c b/test/test-preadv.c new file mode 100644 index 000000000000..6bcfea842a2d --- /dev/null +++ b/test/test-preadv.c @@ -0,0 +1,52 @@ +/* + * 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 +#include +#include + +#define IO_LEN (64) + +int main(void) +{ + struct iovec iov[1]; + char data[IO_LEN]; + int fd, rc; + + fd = open("/dev/zero", O_RDONLY); + if (fd < 0) + return -1; + + iov[0].iov_base = data; + iov[0].iov_len = (size_t)IO_LEN; + + rc = preadv(fd, iov, 1, 0); + (void)close(fd); + + return rc; +} diff --git a/test/test-preadv2.c b/test/test-preadv2.c new file mode 100644 index 000000000000..2f87933d2a02 --- /dev/null +++ b/test/test-preadv2.c @@ -0,0 +1,52 @@ +/* + * 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 +#include +#include + +#define IO_LEN (64) + +int main(void) +{ + struct iovec iov[1]; + char data[IO_LEN]; + int fd, rc; + + fd = open("/dev/zero", O_RDONLY); + if (fd < 0) + return -1; + + iov[0].iov_base = data; + iov[0].iov_len = (size_t)IO_LEN; + + rc = preadv2(fd, iov, 1, -1, 0); + (void)close(fd); + + return rc; +} diff --git a/test/test-pwritev.c b/test/test-pwritev.c index 153f3ff9de09..64d38f403534 100644 --- a/test/test-pwritev.c +++ b/test/test-pwritev.c @@ -24,15 +24,27 @@ */ #define _GNU_SOURCE +#include +#include +#include #include +#include int main(void) { struct iovec iov; char buffer[] = "hello world\n"; + int fd, rc; + + fd = open("/dev/zero", O_WRONLY); + if (fd < 0) + return -1; iov.iov_base = buffer; iov.iov_len = sizeof(buffer); - return pwritev(1, &iov, 1, 0); + rc = pwritev(fd, &iov, 1, 0); + (void)close(fd); + + return rc; } diff --git a/test/test-pwritev2.c b/test/test-pwritev2.c new file mode 100644 index 000000000000..1c7d5f52d477 --- /dev/null +++ b/test/test-pwritev2.c @@ -0,0 +1,50 @@ +/* + * 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 +#include +#include + +int main(void) +{ + struct iovec iov; + char buffer[] = "hello world\n"; + int fd, rc; + + fd = open("/dev/zero", O_WRONLY); + if (fd < 0) + return -1; + + iov.iov_base = buffer; + iov.iov_len = sizeof(buffer); + + rc = pwritev2(fd, &iov, 1, -1, 0); + (void)close(fd); + + return rc; +} -- 2.21.3