From: Cyril Hrubis <chrubis@suse.cz>
To: Andrea Cervesato <andrea.cervesato@suse.com>
Cc: ltp@lists.linux.it
Subject: Re: [LTP] [PATCH v1] Refactoring dio_sparse.c using LTP API
Date: Mon, 6 Dec 2021 15:07:25 +0100 [thread overview]
Message-ID: <Ya4ZHdAsCz+/421w@yuki> (raw)
In-Reply-To: <20211201134846.14352-1-andrea.cervesato@suse.com>
Hi!
> Signed-off-by: Andrea Cervesato <andrea.cervesato@suse.com>
> ---
> testcases/kernel/io/ltp-aiodio/common.h | 32 +++
> testcases/kernel/io/ltp-aiodio/dio_sparse.c | 248 +++++++-------------
> 2 files changed, 119 insertions(+), 161 deletions(-)
>
> diff --git a/testcases/kernel/io/ltp-aiodio/common.h b/testcases/kernel/io/ltp-aiodio/common.h
> index fefeed2cf..0d050b626 100644
> --- a/testcases/kernel/io/ltp-aiodio/common.h
> +++ b/testcases/kernel/io/ltp-aiodio/common.h
> @@ -7,6 +7,9 @@
> #define AIODIO_COMMON_H__
>
> #include <stdlib.h>
> +#include <unistd.h>
> +#include <string.h>
> +#include <sys/mman.h>
> #include "tst_test.h"
>
> static inline char *check_zero(char *buf, int size)
> @@ -51,4 +54,33 @@ static inline void io_append(const char *path, char pattern, int flags, size_t b
> SAFE_CLOSE(fd);
> }
>
> +/*
> + * This code tries to create dirty free blocks on
> + * the HDD so there is a chance that blocks to be allocated
> + * for a file are filled with something else than zeroes.
> + *
> + * The usefulness of this is IMHO questionable.
> + */
> +static inline void dirty_freeblocks(int size)
> +{
> + char *filename = "dirty_file";
> + int fd;
> + void *p;
> + int pg;
> +
> + pg = getpagesize();
> + size = ((size + pg - 1) / pg) * pg;
We can replace this with LTP_ALIGN() macro now that we are moving the
code...
> + fd = SAFE_OPEN(filename, O_CREAT | O_RDWR, 0600);
> + SAFE_FTRUNCATE(fd, size);
> +
> + p = SAFE_MMAP(NULL, size, PROT_WRITE | PROT_READ, MAP_SHARED | MAP_FILE, fd, 0);
> + memset(p, 0xaa, size);
> + msync(p, size, MS_SYNC);
> + munmap(p, size);
> +
> + SAFE_CLOSE(fd);
> + SAFE_UNLINK(filename);
> +}
> +
> #endif /* AIODIO_COMMON_H__ */
> diff --git a/testcases/kernel/io/ltp-aiodio/dio_sparse.c b/testcases/kernel/io/ltp-aiodio/dio_sparse.c
> index 3f44e92ea..cb1b25d1b 100644
> --- a/testcases/kernel/io/ltp-aiodio/dio_sparse.c
> +++ b/testcases/kernel/io/ltp-aiodio/dio_sparse.c
> @@ -1,3 +1,4 @@
> +// SPDX-License-Identifier: GPL-2.0-or-later
> /*
> * Copyright (c) 2004 Daniel McNeil <daniel@osdl.org>
> * 2004 Open Source Development Lab
> @@ -6,206 +7,131 @@
> *
> * Copyright (c) 2011 Cyril Hrubis <chrubis@suse.cz>
> *
> - * This program is free software; you can redistribute it and/or modify
> - * it under the terms of the GNU General Public License as published by
> - * the Free Software Foundation; either version 2 of the License, or
> - * (at your option) any later version.
> - *
> - * This program is distributed in the hope that it will be useful,
> - * but WITHOUT ANY WARRANTY; without even the implied warranty of
> - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
> - * the GNU General Public License for more details.
> + * Copyright (C) 2021 SUSE LLC Andrea Cervesato <andrea.cervesato@suse.com>
> + */
> +
> +/*\
> + * [Description]
> *
> - * 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
> + * Create a sparse file using O_DIRECT while other processes are doing
> + * buffered reads and check if the buffer reads always see zero.
> */
>
> #define _GNU_SOURCE
>
> #include <stdlib.h>
> -#include <sys/types.h>
> -#include <signal.h>
> -#include <errno.h>
> -#include <fcntl.h>
> -#include <stdio.h>
> #include <unistd.h>
> -#include <memory.h>
> -#include <sys/mman.h>
> +#include <string.h>
> #include <sys/wait.h>
> -#include <limits.h>
> -#include <getopt.h>
> -
> -#include "test.h"
> -#include "safe_macros.h"
> +#include "tst_test.h"
> +#include "common.h"
>
> #define NUM_CHILDREN 1000
> +#define FILE_SIZE (100 * 1024 * 1024)
> +#define WRITE_SIZE 1024
>
> -static void setup(void);
> -static void cleanup(void);
> -static void usage(void);
> -static int debug = 0;
> -static int fd;
> -
> -char *TCID = "dio_sparse";
> -int TST_TOTAL = 1;
> +static int *run_child;
>
> -#include "common_sparse.h"
> -
> -/*
> - * Write zeroes using O_DIRECT into sparse file.
> - */
> -int dio_sparse(int fd, int align, int writesize, int filesize, int offset)
> +static void dio_sparse(int fd, int filesize, int writesize)
> {
> void *bufptr = NULL;
> - int i, w;
> + int i;
> + int w;
>
> - TEST(posix_memalign(&bufptr, align, writesize));
> - if (TEST_RETURN) {
> - tst_resm(TBROK | TRERRNO, "cannot allocate aligned memory");
> - return 1;
> - }
> + bufptr = SAFE_MEMALIGN(getpagesize(), writesize);
>
> memset(bufptr, 0, writesize);
> - lseek(fd, offset, SEEK_SET);
> - for (i = offset; i < filesize;) {
> - if ((w = write(fd, bufptr, writesize)) != writesize) {
> - tst_resm(TBROK | TERRNO, "write() returned %d", w);
> - return 1;
> - }
> + SAFE_LSEEK(fd, 0, SEEK_SET);
>
> + for (i = 0; i < filesize;) {
> + w = SAFE_WRITE(0, fd, bufptr, writesize);
> i += w;
> }
> -
> - return 0;
> -}
> -
> -void usage(void)
> -{
> - fprintf(stderr, "usage: dio_sparse [-d] [-n children] [-s filesize]"
> - " [-w writesize] [-o offset]]\n");
> - exit(1);
> }
>
> -int main(int argc, char **argv)
> +static void read_sparse(const char *filename, int filesize)
> {
> - char *filename = "dio_sparse";
> - int pid[NUM_CHILDREN];
> - int num_children = 1;
> + char buff[4096];
> + int fd;
> int i;
> - long alignment = 512;
> - int writesize = 65536;
> - int filesize = 100 * 1024 * 1024;
> - int offset = 0;
> - int c;
> - int children_errors = 0;
> - int ret;
> -
> - while ((c = getopt(argc, argv, "dw:n:a:s:o:")) != -1) {
> - char *endp;
> - switch (c) {
> - case 'd':
> - debug++;
> - break;
> - case 'a':
> - alignment = strtol(optarg, &endp, 0);
> - alignment = scale_by_kmg(alignment, *endp);
> - break;
> - case 'w':
> - writesize = strtol(optarg, &endp, 0);
> - writesize = scale_by_kmg(writesize, *endp);
> - break;
> - case 's':
> - filesize = strtol(optarg, &endp, 0);
> - filesize = scale_by_kmg(filesize, *endp);
> - break;
> - case 'o':
> - offset = strtol(optarg, &endp, 0);
> - offset = scale_by_kmg(offset, *endp);
> - break;
> - case 'n':
> - num_children = atoi(optarg);
> - if (num_children > NUM_CHILDREN) {
> - fprintf(stderr,
> - "number of children limited to %d\n",
> - NUM_CHILDREN);
> - num_children = NUM_CHILDREN;
First of all these parameters should be defined in the tst_option
structure and exposed in the tst_test structure.
See: https://github.com/linux-test-project/ltp/wiki/C-Test-API#15-test-specific-command-line-options
> + int r;
> +
> + while ((fd = open(filename, O_RDONLY, 0666)) < 0)
> + usleep(100);
> +
> + tst_res(TINFO, "child %i reading file", getpid());
> +
> + SAFE_LSEEK(fd, SEEK_SET, 0);
There is no need to seek newly opened file to the start.
> + while (*run_child) {
> + off_t offset = 0;
> + char *bufoff;
And the seek should be here, right?
> + for (i = 0; i < filesize + 1; i += sizeof(buff)) {
> + r = SAFE_READ(0, fd, buff, sizeof(buff));
> + if (r > 0) {
> + bufoff = check_zero(buff, r);
> + if (bufoff) {
> + tst_res(TINFO, "non-zero read at offset %zu",
> + offset + (bufoff - buff));
> + break;
> + }
> + offset += r;
> }
> - break;
> - case '?':
> - usage();
> - break;
> }
> }
>
> - setup();
> - tst_resm(TINFO, "Dirtying free blocks");
> - dirty_freeblocks(filesize);
> + SAFE_CLOSE(fd);
> +}
Also this function should go to the common header so that we can reuse
it later on...
> +static void setup(void)
> +{
> + run_child = SAFE_MMAP(NULL, sizeof(int), PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1, 0);
> +}
>
> - fd = SAFE_OPEN(cleanup, filename,
> - O_DIRECT | O_WRONLY | O_CREAT | O_EXCL, 0600);
> - SAFE_FTRUNCATE(cleanup, fd, filesize);
> +static void cleanup(void)
> +{
> + SAFE_MUNMAP(run_child, sizeof(int));
> +}
>
> - tst_resm(TINFO, "Starting I/O tests");
> - signal(SIGTERM, SIG_DFL);
> - for (i = 0; i < num_children; i++) {
> - switch (pid[i] = fork()) {
> - case 0:
> - SAFE_CLOSE(NULL, fd);
> - read_sparse(filename, filesize);
> - break;
> - case -1:
> - while (i-- > 0)
> - kill(pid[i], SIGTERM);
> -
> - tst_brkm(TBROK | TERRNO, cleanup, "fork()");
> - default:
> - continue;
> - }
> - }
> - tst_sig(FORK, DEF_HANDLER, cleanup);
> +static void run(void)
> +{
> + char *filename = "sparse_file";
> + int filesize = FILE_SIZE;
> + int num_children = NUM_CHILDREN;
> + int writesize = WRITE_SIZE;
> + int status;
> + int fd;
> + int i;
>
> - ret = dio_sparse(fd, alignment, writesize, filesize, offset);
> + tst_res(TINFO, "Dirtying free blocks");
> + dirty_freeblocks(filesize);
Maybe the dirty_freeblocks() should go to the test setup, so that we do
it once in case we requested multiple test iterations with -i
> - tst_resm(TINFO, "Killing childrens(s)");
> + fd = SAFE_OPEN(filename, O_DIRECT | O_WRONLY | O_CREAT, 0666);
> + SAFE_FTRUNCATE(fd, filesize);
>
> - for (i = 0; i < num_children; i++)
> - kill(pid[i], SIGTERM);
> + *run_child = 1;
>
> for (i = 0; i < num_children; i++) {
> - int status;
> - pid_t p;
> -
> - p = waitpid(pid[i], &status, 0);
> - if (p < 0) {
> - tst_resm(TBROK | TERRNO, "waitpid()");
> - } else {
> - if (WIFEXITED(status) && WEXITSTATUS(status) == 10)
> - children_errors++;
> + if (!SAFE_FORK()) {
> + read_sparse(filename, filesize);
> + return;
> }
> }
>
> - if (children_errors)
> - tst_resm(TFAIL, "%i children(s) exited abnormally",
> - children_errors);
> + dio_sparse(fd, filesize, writesize);
>
> - if (!children_errors && !ret)
> - tst_resm(TPASS, "Test passed");
> + if (SAFE_WAITPID(-1, &status, WNOHANG))
> + tst_res(TFAIL, "Non zero bytes read");
> + else
> + tst_res(TPASS, "All bytes read were zeroed");
>
> - cleanup();
> - tst_exit();
> -}
> -
> -static void setup(void)
> -{
> - tst_sig(FORK, DEF_HANDLER, cleanup);
> - tst_tmpdir();
> + *run_child = 0;
> }
>
> -static void cleanup(void)
> -{
> - if (fd > 0 && close(fd))
> - tst_resm(TWARN | TERRNO, "Failed to close file");
> -
> - tst_rmdir();
> -}
> +static struct tst_test test = {
> + .test_all = run,
> + .setup = setup,
> + .cleanup = cleanup,
> + .needs_tmpdir = 1,
> + .forks_child = 1,
> +};
> --
> 2.34.0
>
>
> --
> Mailing list info: https://lists.linux.it/listinfo/ltp
--
Cyril Hrubis
chrubis@suse.cz
--
Mailing list info: https://lists.linux.it/listinfo/ltp
prev parent reply other threads:[~2021-12-06 14:06 UTC|newest]
Thread overview: 2+ messages / expand[flat|nested] mbox.gz Atom feed top
2021-12-01 13:48 [LTP] [PATCH v1] Refactoring dio_sparse.c using LTP API Andrea Cervesato via ltp
2021-12-06 14:07 ` Cyril Hrubis [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=Ya4ZHdAsCz+/421w@yuki \
--to=chrubis@suse.cz \
--cc=andrea.cervesato@suse.com \
--cc=ltp@lists.linux.it \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.