* [LTP] [PATCH v1 0/4] *** Add LOOP_CONFIGURE ioctl test ***
@ 2020-06-11 10:35 Yang Xu
2020-06-11 10:35 ` [LTP] [PATCH v1 1/4] lapi: Add fallback for LOOP_CONFIGURE ioctl and struct loop_config Yang Xu
` (4 more replies)
0 siblings, 5 replies; 28+ messages in thread
From: Yang Xu @ 2020-06-11 10:35 UTC (permalink / raw)
To: ltp
Since kernel commit[1], it has added LOOP_CONFIGURE ioctl test.
From this commit, loop_set_fd calls loop_configure with zero
loop_config.
struct loop_config {
__u32 fd;
__u32 block_size;
struct loop_info64 info;
__u64 __reserved[8];
}
In addition to doing what LOOP_SET_STATUS can do, LOOP_CONFIGURE can
also be used to:
- Set the correct block size immediately by setting
loop_config.block_size (I test this in ioctl_loop08.c, like old
ioctl_loop06.c)
- Explicitly request direct I/O mode by setting LO_FLAGS_DIRECT_IO
in loop_config.info.lo_flags (I test this in ioctl_loop09.c, like old
ioctl_loop05.c)
- Explicitly request read-only mode by setting LO_FLAGS_READ_ONLY
in loop_config.info.lo_flags (I test this in old ioctl_loop02.c)
[1]https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=3448914e8cc550ba792d4ccc74471d1ca4293a
Yang Xu (4):
lapi: Add fallback for LOOP_CONFIGURE ioctl and struct loop_config
syscalls/ioctl_loop02: Using LOOP_CONFIGURE to set read_only
syscalls/ioctl_loop08: Add LOOP_CONFIGURE error test with invalid
block size
syscalls/ioctl_loop09: Add LOOP_CONFIGURE ioctl test with direct I/O
flag
configure.ac | 1 +
include/lapi/loop.h | 23 +++
runtest/syscalls | 2 +
testcases/kernel/syscalls/ioctl/.gitignore | 2 +
.../kernel/syscalls/ioctl/ioctl_loop02.c | 53 ++++--
.../kernel/syscalls/ioctl/ioctl_loop08.c | 101 ++++++++++++
.../kernel/syscalls/ioctl/ioctl_loop09.c | 151 ++++++++++++++++++
7 files changed, 324 insertions(+), 9 deletions(-)
create mode 100644 testcases/kernel/syscalls/ioctl/ioctl_loop08.c
create mode 100644 testcases/kernel/syscalls/ioctl/ioctl_loop09.c
--
2.23.0
^ permalink raw reply [flat|nested] 28+ messages in thread* [LTP] [PATCH v1 1/4] lapi: Add fallback for LOOP_CONFIGURE ioctl and struct loop_config 2020-06-11 10:35 [LTP] [PATCH v1 0/4] *** Add LOOP_CONFIGURE ioctl test *** Yang Xu @ 2020-06-11 10:35 ` Yang Xu 2020-07-08 13:18 ` Cyril Hrubis 2020-06-11 10:35 ` [LTP] [PATCH v1 2/4] syscalls/ioctl_loop02: Using LOOP_CONFIGURE to set read_only Yang Xu ` (3 subsequent siblings) 4 siblings, 1 reply; 28+ messages in thread From: Yang Xu @ 2020-06-11 10:35 UTC (permalink / raw) To: ltp Signed-off-by: Yang Xu <xuyang2018.jy@cn.fujitsu.com> --- configure.ac | 1 + include/lapi/loop.h | 23 +++++++++++++++++++++++ 2 files changed, 24 insertions(+) diff --git a/configure.ac b/configure.ac index 1d3ea58d0..7d2be1df7 100644 --- a/configure.ac +++ b/configure.ac @@ -150,6 +150,7 @@ AC_CHECK_TYPES([struct file_dedupe_range],,,[#include <linux/fs.h>]) AC_CHECK_TYPES([struct fs_quota_statv],,,[#include <xfs/xqm.h>]) AC_CHECK_TYPES([struct if_nextdqblk],,,[#include <linux/quota.h>]) AC_CHECK_TYPES([struct iovec],,,[#include <sys/uio.h>]) +AC_CHECK_TYPES([struct loop_config],,,[#include <linux/loop.h>]) AC_CHECK_TYPES([struct mmsghdr],,,[ #define _GNU_SOURCE diff --git a/include/lapi/loop.h b/include/lapi/loop.h index c69328613..87a902317 100644 --- a/include/lapi/loop.h +++ b/include/lapi/loop.h @@ -6,6 +6,7 @@ #ifndef LAPI_LOOP_H #define LAPI_LOOP_H +#include "config.h" #include <linux/types.h> #include <linux/loop.h> @@ -29,4 +30,26 @@ # define LOOP_SET_BLOCK_SIZE 0x4C09 #endif +#ifndef LOOP_CONFIGURE +# define LOOP_CONFIGURE 0x4C0A +#endif + +#ifndef HAVE_STRUCT_LOOP_CONFIG +/* + * struct loop_config - Complete configuration for a loop device. + * @fd: fd of the file to be used as a backing file for the loop device. + * @block_size: block size to use; ignored if 0. + * @info: struct loop_info64 to configure the loop device with. + * + * This structure is used with the LOOP_CONFIGURE ioctl, and can be used to + * atomically setup and configure all loop device parameters at once. + */ +struct loop_config { + __u32 fd; + __u32 block_size; + struct loop_info64 info; + __u64 __reserved[8]; +}; +#endif + #endif -- 2.23.0 ^ permalink raw reply related [flat|nested] 28+ messages in thread
* [LTP] [PATCH v1 1/4] lapi: Add fallback for LOOP_CONFIGURE ioctl and struct loop_config 2020-06-11 10:35 ` [LTP] [PATCH v1 1/4] lapi: Add fallback for LOOP_CONFIGURE ioctl and struct loop_config Yang Xu @ 2020-07-08 13:18 ` Cyril Hrubis 0 siblings, 0 replies; 28+ messages in thread From: Cyril Hrubis @ 2020-07-08 13:18 UTC (permalink / raw) To: ltp Hi! Pushed, thanks. -- Cyril Hrubis chrubis@suse.cz ^ permalink raw reply [flat|nested] 28+ messages in thread
* [LTP] [PATCH v1 2/4] syscalls/ioctl_loop02: Using LOOP_CONFIGURE to set read_only 2020-06-11 10:35 [LTP] [PATCH v1 0/4] *** Add LOOP_CONFIGURE ioctl test *** Yang Xu 2020-06-11 10:35 ` [LTP] [PATCH v1 1/4] lapi: Add fallback for LOOP_CONFIGURE ioctl and struct loop_config Yang Xu @ 2020-06-11 10:35 ` Yang Xu 2020-07-08 13:15 ` Cyril Hrubis 2020-06-11 10:35 ` [LTP] [PATCH v1 3/4] syscalls/ioctl_loop08: Add LOOP_CONFIGURE error test with invalid block size Yang Xu ` (2 subsequent siblings) 4 siblings, 1 reply; 28+ messages in thread From: Yang Xu @ 2020-06-11 10:35 UTC (permalink / raw) To: ltp Since kernel commit 3448914e8cc5("loop: Add LOOP_CONFIGURE ioctl"), it can explicitly request read-only mode by setting LO_FLAGS_READ_ONLY in loop_config.info.lo_flags regardless of backing file open mode. Signed-off-by: Yang Xu <xuyang2018.jy@cn.fujitsu.com> --- .../kernel/syscalls/ioctl/ioctl_loop02.c | 53 +++++++++++++++---- 1 file changed, 44 insertions(+), 9 deletions(-) diff --git a/testcases/kernel/syscalls/ioctl/ioctl_loop02.c b/testcases/kernel/syscalls/ioctl/ioctl_loop02.c index c43172ca1..c497017f5 100644 --- a/testcases/kernel/syscalls/ioctl/ioctl_loop02.c +++ b/testcases/kernel/syscalls/ioctl/ioctl_loop02.c @@ -11,6 +11,9 @@ * For LOOP_CHANGE_FD, this operation is possible only if the loop device * is read-only and the new backing store is the same size and type as the * old backing store. + * + * If using LOOP_CONFIGURE ioctl, we can set LO_FLAGS_READ_ONLY + * flag even though backing file with write mode. */ #include <stdio.h> @@ -22,15 +25,39 @@ static int file_fd, file_change_fd, file_fd_invalid; static char backing_path[1024], backing_file_path[1024], backing_file_change_path[1024]; -static int attach_flag, dev_fd, file_fd; +static int attach_flag, dev_fd, loop_configure_sup = 1; static char loop_ro_path[1024], dev_path[1024]; +static struct loop_config loopconfig; + +static struct tcase { + int mode; + int ioctl; + char *message; +} tcases[] = { + {O_RDONLY, LOOP_SET_FD, "Using LOOP_SET_FD to setup loopdevice"}, + {O_RDWR, LOOP_CONFIGURE, "Using LOOP_CONFIGURE with read_only flag to setup loopdevice"}, +}; -static void verify_ioctl_loop(void) +static void verify_ioctl_loop(unsigned int n) { + struct tcase *tc = &tcases[n]; struct loop_info loopinfoget; + tst_res(TINFO, "%s", tc->message); + file_fd = SAFE_OPEN("test.img", tc->mode); dev_fd = SAFE_OPEN(dev_path, O_RDWR); - SAFE_IOCTL(dev_fd, LOOP_SET_FD, file_fd); + + if (tc->ioctl == LOOP_SET_FD) { + SAFE_IOCTL(dev_fd, LOOP_SET_FD, file_fd); + } else { + if (!loop_configure_sup) { + tst_res(TCONF, + "Current environmet doesn't support LOOP_CONFIGURE ioctl, skip this"); + return; + } + loopconfig.fd = file_fd; + SAFE_IOCTL(dev_fd, LOOP_CONFIGURE, &loopconfig); + } attach_flag = 1; TST_ASSERT_INT(loop_ro_path, 1); @@ -38,11 +65,6 @@ static void verify_ioctl_loop(void) memset(&loopinfoget, 0, sizeof(loopinfoget)); - /* - * In drivers/block/loop.c code, set status function doesn't handle - * LO_FLAGS_READ_ONLY flag and ignore it. Only loop_set_fd with readonly - * mode, lo_flags will include LO_FLAGS_READ_ONLY. - */ SAFE_IOCTL(dev_fd, LOOP_GET_STATUS, &loopinfoget); if (loopinfoget.lo_flags & ~LO_FLAGS_READ_ONLY) @@ -83,6 +105,7 @@ static void verify_ioctl_loop(void) static void setup(void) { int dev_num; + int ret; char *tmpdir = tst_get_tmpdir(); dev_num = tst_find_free_loopdev(dev_path, sizeof(dev_path)); @@ -103,6 +126,17 @@ static void setup(void) file_fd = SAFE_OPEN("test.img", O_RDONLY); file_change_fd = SAFE_OPEN("test1.img", O_RDWR); file_fd_invalid = SAFE_OPEN("test2.img", O_RDWR); + + dev_fd = SAFE_OPEN(dev_path, O_RDWR); + loopconfig.fd = -1; + ret = ioctl(dev_fd, LOOP_CONFIGURE, &loopconfig); + + if (ret && errno != EBADF) { + tst_res(TINFO | TERRNO, "LOOP_CONFIGURE is not supported"); + loop_configure_sup = 0; + } + loopconfig.info.lo_flags = LO_FLAGS_READ_ONLY; + SAFE_CLOSE(dev_fd); } static void cleanup(void) @@ -122,7 +156,8 @@ static void cleanup(void) static struct tst_test test = { .setup = setup, .cleanup = cleanup, - .test_all = verify_ioctl_loop, + .tcnt = ARRAY_SIZE(tcases), + .test = verify_ioctl_loop, .needs_root = 1, .needs_tmpdir = 1, .needs_drivers = (const char *const []) { -- 2.23.0 ^ permalink raw reply related [flat|nested] 28+ messages in thread
* [LTP] [PATCH v1 2/4] syscalls/ioctl_loop02: Using LOOP_CONFIGURE to set read_only 2020-06-11 10:35 ` [LTP] [PATCH v1 2/4] syscalls/ioctl_loop02: Using LOOP_CONFIGURE to set read_only Yang Xu @ 2020-07-08 13:15 ` Cyril Hrubis 0 siblings, 0 replies; 28+ messages in thread From: Cyril Hrubis @ 2020-07-08 13:15 UTC (permalink / raw) To: ltp Hi! Pushed with a few fixed, thanks. * Shortened some overly long messages * Fixed the code not to leak open file descriptors - removed useless open of file_fd in setup - moved TCONF check in run before fds are opened - added close for file_fd at the end of the run (this fixes runs with -i N especially on older kernels) diff --git a/testcases/kernel/syscalls/ioctl/ioctl_loop02.c b/testcases/kernel/syscalls/ioctl/ioctl_loop02.c index 549154fa1..3a03d052a 100644 --- a/testcases/kernel/syscalls/ioctl/ioctl_loop02.c +++ b/testcases/kernel/syscalls/ioctl/ioctl_loop02.c @@ -35,7 +35,7 @@ static struct tcase { char *message; } tcases[] = { {O_RDONLY, LOOP_SET_FD, "Using LOOP_SET_FD to setup loopdevice"}, - {O_RDWR, LOOP_CONFIGURE, "Using LOOP_CONFIGURE with read_only flag to setup loopdevice"}, + {O_RDWR, LOOP_CONFIGURE, "Using LOOP_CONFIGURE with read_only flag"}, }; static void verify_ioctl_loop(unsigned int n) @@ -43,6 +43,11 @@ static void verify_ioctl_loop(unsigned int n) struct tcase *tc = &tcases[n]; struct loop_info loopinfoget; + if (tc->ioctl == LOOP_CONFIGURE && !loop_configure_sup) { + tst_res(TCONF, "LOOP_CONFIGURE ioctl not supported"); + return; + } + tst_res(TINFO, "%s", tc->message); file_fd = SAFE_OPEN("test.img", tc->mode); dev_fd = SAFE_OPEN(dev_path, O_RDWR); @@ -50,11 +55,6 @@ static void verify_ioctl_loop(unsigned int n) if (tc->ioctl == LOOP_SET_FD) { SAFE_IOCTL(dev_fd, LOOP_SET_FD, file_fd); } else { - if (!loop_configure_sup) { - tst_res(TCONF, - "Current environmet doesn't support LOOP_CONFIGURE ioctl, skip this"); - return; - } loopconfig.fd = file_fd; SAFE_IOCTL(dev_fd, LOOP_CONFIGURE, &loopconfig); } @@ -98,6 +98,7 @@ static void verify_ioctl_loop(unsigned int n) } SAFE_CLOSE(dev_fd); + SAFE_CLOSE(file_fd); tst_detach_device(dev_path); attach_flag = 0; } @@ -123,7 +124,6 @@ static void setup(void) free(tmpdir); - file_fd = SAFE_OPEN("test.img", O_RDONLY); file_change_fd = SAFE_OPEN("test1.img", O_RDWR); file_fd_invalid = SAFE_OPEN("test2.img", O_RDWR); -- Cyril Hrubis chrubis@suse.cz ^ permalink raw reply related [flat|nested] 28+ messages in thread
* [LTP] [PATCH v1 3/4] syscalls/ioctl_loop08: Add LOOP_CONFIGURE error test with invalid block size 2020-06-11 10:35 [LTP] [PATCH v1 0/4] *** Add LOOP_CONFIGURE ioctl test *** Yang Xu 2020-06-11 10:35 ` [LTP] [PATCH v1 1/4] lapi: Add fallback for LOOP_CONFIGURE ioctl and struct loop_config Yang Xu 2020-06-11 10:35 ` [LTP] [PATCH v1 2/4] syscalls/ioctl_loop02: Using LOOP_CONFIGURE to set read_only Yang Xu @ 2020-06-11 10:35 ` Yang Xu 2020-07-08 14:00 ` Cyril Hrubis 2020-06-11 10:35 ` [LTP] [PATCH v1 4/4] syscalls/ioctl_loop09: Add LOOP_CONFIGURE ioctl test with direct I/O flag Yang Xu 2020-07-06 1:45 ` [LTP] [PATCH v1 0/4] *** Add LOOP_CONFIGURE ioctl test *** Yang Xu 4 siblings, 1 reply; 28+ messages in thread From: Yang Xu @ 2020-06-11 10:35 UTC (permalink / raw) To: ltp Since kernel commit 3448914e8cc5("loop: Add LOOP_CONFIGURE ioctl"), it can set the correct block size immediately by setting loop_config.block_size. Signed-off-by: Yang Xu <xuyang2018.jy@cn.fujitsu.com> --- runtest/syscalls | 1 + testcases/kernel/syscalls/ioctl/.gitignore | 1 + .../kernel/syscalls/ioctl/ioctl_loop08.c | 101 ++++++++++++++++++ 3 files changed, 103 insertions(+) create mode 100644 testcases/kernel/syscalls/ioctl/ioctl_loop08.c diff --git a/runtest/syscalls b/runtest/syscalls index cd0c65094..7259f2a92 100644 --- a/runtest/syscalls +++ b/runtest/syscalls @@ -536,6 +536,7 @@ ioctl_loop04 ioctl_loop04 ioctl_loop05 ioctl_loop05 ioctl_loop06 ioctl_loop06 ioctl_loop07 ioctl_loop07 +ioctl_loop08 ioctl_loop08 ioctl_ns01 ioctl_ns01 ioctl_ns02 ioctl_ns02 diff --git a/testcases/kernel/syscalls/ioctl/.gitignore b/testcases/kernel/syscalls/ioctl/.gitignore index 3a3d49adc..97134aa0b 100644 --- a/testcases/kernel/syscalls/ioctl/.gitignore +++ b/testcases/kernel/syscalls/ioctl/.gitignore @@ -13,6 +13,7 @@ /ioctl_loop05 /ioctl_loop06 /ioctl_loop07 +/ioctl_loop08 /ioctl_ns01 /ioctl_ns02 /ioctl_ns03 diff --git a/testcases/kernel/syscalls/ioctl/ioctl_loop08.c b/testcases/kernel/syscalls/ioctl/ioctl_loop08.c new file mode 100644 index 000000000..93b75a381 --- /dev/null +++ b/testcases/kernel/syscalls/ioctl/ioctl_loop08.c @@ -0,0 +1,101 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (c) 2020 FUJITSU LIMITED. All rights reserved. + * Author: Yang Xu <xuyang2018.jy@cn.jujitsu.com> + * + * This is a basic ioctl test about loopdevice. + * It is designed to test LOOP_CONFIGURE ioctl with invalid block size config. + * It is similar with ioctl_loop06.c. + */ + +#include <stdio.h> +#include <unistd.h> +#include <sys/types.h> +#include <stdlib.h> +#include "lapi/loop.h" +#include "tst_test.h" + +static char dev_path[1024]; +static int dev_num, dev_fd, file_fd; +static unsigned int invalid_value, half_value, unalign_value; +static struct loop_config loopconfig; + +static struct tcase { + unsigned int *setvalue; + int exp_err; + char *message; +} tcases[] = { + {&half_value, EINVAL, "arg < 512"}, + {&invalid_value, EINVAL, "arg > PAGE_SIZE"}, + {&unalign_value, EINVAL, "arg != power_of_2"}, +}; + +static void verify_ioctl_loop(unsigned int n) +{ + struct tcase *tc = &tcases[n]; + + tst_res(TINFO, "%s", tc->message); + loopconfig.block_size = *(tc->setvalue); + TEST(ioctl(dev_fd, LOOP_CONFIGURE, &loopconfig)); + if (TST_RET == 0) { + tst_res(TFAIL, "LOOP_CONFIGURE block_size succeed unexpectedly"); + TST_RETRY_FUNC(ioctl(dev_fd, LOOP_CLR_FD, 0), TST_RETVAL_EQ0); + return; + } + + if (TST_ERR == tc->exp_err) { + tst_res(TPASS | TTERRNO, "LOOP_CONFIGURE block failed as expected"); + } else { + tst_res(TFAIL | TTERRNO, "LOOP_CONFIGURE block size failed expected %s got", + tst_strerrno(tc->exp_err)); + } +} + +static void setup(void) +{ + unsigned int pg_size; + int ret; + + dev_num = tst_find_free_loopdev(dev_path, sizeof(dev_path)); + if (dev_num < 0) + tst_brk(TBROK, "Failed to find free loop device"); + + tst_fill_file("test.img", 0, 1024, 1024); + half_value = 256; + pg_size = getpagesize(); + invalid_value = pg_size * 2 ; + unalign_value = pg_size - 1; + + dev_fd = SAFE_OPEN(dev_path, O_RDWR); + file_fd = SAFE_OPEN("test.img", O_RDWR); + loopconfig.fd = file_fd; + + ret = ioctl(dev_fd, LOOP_CONFIGURE, &loopconfig); + if (ret == 0) { + TST_RETRY_FUNC(ioctl(dev_fd, LOOP_CLR_FD, 0), TST_RETVAL_EQ0); + return; + } + if (errno == EINVAL) + tst_brk(TCONF, "LOOP_CONFIGURE is not supported"); +} + +static void cleanup(void) +{ + if (dev_fd > 0) + SAFE_CLOSE(dev_fd); + if (file_fd > 0) + SAFE_CLOSE(file_fd); +} + +static struct tst_test test = { + .setup = setup, + .cleanup = cleanup, + .test = verify_ioctl_loop, + .tcnt = ARRAY_SIZE(tcases), + .needs_root = 1, + .needs_tmpdir = 1, + .needs_drivers = (const char *const []) { + "loop", + NULL + } +}; -- 2.23.0 ^ permalink raw reply related [flat|nested] 28+ messages in thread
* [LTP] [PATCH v1 3/4] syscalls/ioctl_loop08: Add LOOP_CONFIGURE error test with invalid block size 2020-06-11 10:35 ` [LTP] [PATCH v1 3/4] syscalls/ioctl_loop08: Add LOOP_CONFIGURE error test with invalid block size Yang Xu @ 2020-07-08 14:00 ` Cyril Hrubis 0 siblings, 0 replies; 28+ messages in thread From: Cyril Hrubis @ 2020-07-08 14:00 UTC (permalink / raw) To: ltp Hi! > + * This is a basic ioctl test about loopdevice. > + * It is designed to test LOOP_CONFIGURE ioctl with invalid block size config. > + * It is similar with ioctl_loop06.c. > + */ Actually wouldn't it be easier to just add this to the ioctl_loop06.c? I guess that we can have a run() function that would execute the verify_ioctl_loop() with n and also pass flag down which ioctl to use. -- Cyril Hrubis chrubis@suse.cz ^ permalink raw reply [flat|nested] 28+ messages in thread
* [LTP] [PATCH v1 4/4] syscalls/ioctl_loop09: Add LOOP_CONFIGURE ioctl test with direct I/O flag 2020-06-11 10:35 [LTP] [PATCH v1 0/4] *** Add LOOP_CONFIGURE ioctl test *** Yang Xu ` (2 preceding siblings ...) 2020-06-11 10:35 ` [LTP] [PATCH v1 3/4] syscalls/ioctl_loop08: Add LOOP_CONFIGURE error test with invalid block size Yang Xu @ 2020-06-11 10:35 ` Yang Xu 2020-07-08 14:00 ` Cyril Hrubis 2020-07-06 1:45 ` [LTP] [PATCH v1 0/4] *** Add LOOP_CONFIGURE ioctl test *** Yang Xu 4 siblings, 1 reply; 28+ messages in thread From: Yang Xu @ 2020-06-11 10:35 UTC (permalink / raw) To: ltp Since kernel commit 3448914e8cc5("loop: Add LOOP_CONFIGURE ioctl"), it can explicitly request direct I/O mode by setting LO_FLAGS_DIRECT_IO in loop_config.info.lo_flags. Signed-off-by: Yang Xu <xuyang2018.jy@cn.fujitsu.com> --- runtest/syscalls | 1 + testcases/kernel/syscalls/ioctl/.gitignore | 1 + .../kernel/syscalls/ioctl/ioctl_loop09.c | 151 ++++++++++++++++++ 3 files changed, 153 insertions(+) create mode 100644 testcases/kernel/syscalls/ioctl/ioctl_loop09.c diff --git a/runtest/syscalls b/runtest/syscalls index 7259f2a92..df99a0600 100644 --- a/runtest/syscalls +++ b/runtest/syscalls @@ -537,6 +537,7 @@ ioctl_loop05 ioctl_loop05 ioctl_loop06 ioctl_loop06 ioctl_loop07 ioctl_loop07 ioctl_loop08 ioctl_loop08 +ioctl_loop09 ioctl_loop09 ioctl_ns01 ioctl_ns01 ioctl_ns02 ioctl_ns02 diff --git a/testcases/kernel/syscalls/ioctl/.gitignore b/testcases/kernel/syscalls/ioctl/.gitignore index 97134aa0b..0decf6ea1 100644 --- a/testcases/kernel/syscalls/ioctl/.gitignore +++ b/testcases/kernel/syscalls/ioctl/.gitignore @@ -14,6 +14,7 @@ /ioctl_loop06 /ioctl_loop07 /ioctl_loop08 +/ioctl_loop09 /ioctl_ns01 /ioctl_ns02 /ioctl_ns03 diff --git a/testcases/kernel/syscalls/ioctl/ioctl_loop09.c b/testcases/kernel/syscalls/ioctl/ioctl_loop09.c new file mode 100644 index 000000000..c291afeb6 --- /dev/null +++ b/testcases/kernel/syscalls/ioctl/ioctl_loop09.c @@ -0,0 +1,151 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (c) 2020 FUJITSU LIMITED. All rights reserved. + * Author: Yang Xu <xuyang2018.jy@cn.jujitsu.com> + * + * This is a basic ioctl test about loopdevice. It sets LO_FLAGS_DIRECT_IO + * in loop_config.info.lo_flags by using LOOP_CONFIGURE instead of using + * LOOP_SET_DIRECT_IO. It is similar with ioctl_loop05.c. + */ + +#include <stdio.h> +#include <unistd.h> +#include <string.h> +#include <stdlib.h> +#include <sys/mount.h> +#include "lapi/loop.h" +#include "tst_test.h" +#include "tst_safe_stdio.h" + +#define DIO_MESSAGE "In dio mode" +#define NON_DIO_MESSAGE "In non dio mode" + +static char dev_path[1024], sys_loop_diopath[1024]; +static int dev_num, dev_fd, file_fd, block_devfd, logical_block_size; +static struct loop_config loopconfig; +static struct tcase { + int multi; /*logical_block_size / 2 as unit */ + int dio_value; + char *message; +} tcases[] = { + {0, 1, "Without setting lo_offset or sizelimit"}, + {2, 1, "With offset equal to logical_block_size"}, + {1, 0, "less than logical_block_size"}, +}; + +static void check_dio_value(int flag) +{ + struct loop_info loopinfoget; + + memset(&loopinfoget, 0, sizeof(loopinfoget)); + + SAFE_IOCTL(dev_fd, LOOP_GET_STATUS, &loopinfoget); + tst_res(TINFO, "%s", flag ? DIO_MESSAGE : NON_DIO_MESSAGE); + + if (loopinfoget.lo_flags & LO_FLAGS_DIRECT_IO) + tst_res(flag ? TPASS : TFAIL, "lo_flags has LO_FLAGS_DIRECT_IO flag"); + else + tst_res(flag ? TFAIL : TPASS, "lo_flags doesn't have LO_FLAGS_DIRECT_IO flag"); + + TST_ASSERT_INT(sys_loop_diopath, flag); +} + +static void find_backing_bdpath(char *buf) +{ + const char *const df_cmd[] = {"df", "-T", ".", NULL}; + char line[PATH_MAX]; + FILE *file; + + SAFE_CMD(df_cmd, "1.txt", NULL); + file = SAFE_FOPEN("1.txt", "r"); + + while (fgets(line, sizeof(line), file) != NULL) { + sscanf(line, "%s", buf); + if (strstr(buf, "/dev/") != NULL) + break; + } + SAFE_FCLOSE(file); +} + +static void verify_ioctl_loop(unsigned int n) +{ + struct tcase *tc = &tcases[n]; + + loopconfig.info.lo_offset = tc->multi * logical_block_size / 2; + + tst_res(TINFO, "%s", tc->message); + /* + * When we call loop_configure ioctl successfully and detach it, + * the subquent loo_configure without non-zero lo_offset or sizelimit + * may trigger the blk_update_request I/O error. To avoid this, sleep + * 1s to ensure last blk_update_request has completed. + */ + sleep(1); + + /* + * loop_cofigure calls loop_update_dio() function, it will ignore the result + * of setting dio. It is different from loop_set_dio. + */ + TST_RETRY_FUNC(ioctl(dev_fd, LOOP_CONFIGURE, &loopconfig), TST_RETVAL_EQ0); + check_dio_value(tc->dio_value); + TST_RETRY_FUNC(ioctl(dev_fd, LOOP_CLR_FD, 0), TST_RETVAL_EQ0); +} + +static void setup(void) +{ + int ret; + char buf[100]; + + if (tst_fs_type(".") == TST_TMPFS_MAGIC) + tst_brk(TCONF, "tmpfd doesn't support O_DIRECT flag"); + + dev_num = tst_find_free_loopdev(dev_path, sizeof(dev_path)); + if (dev_num < 0) + tst_brk(TBROK, "Failed to find free loop device"); + + sprintf(sys_loop_diopath, "/sys/block/loop%d/loop/dio", dev_num); + tst_fill_file("test.img", 0, 1024, 1024); + dev_fd = SAFE_OPEN(dev_path, O_RDWR); + file_fd = SAFE_OPEN("test.img", O_RDWR); + + find_backing_bdpath(buf); + block_devfd = SAFE_OPEN(buf, O_RDWR); + + SAFE_IOCTL(block_devfd, BLKSSZGET, &logical_block_size); + tst_res(TINFO, "backing dev logical_block_size is %d", logical_block_size); + SAFE_CLOSE(block_devfd); + loopconfig.fd = -1; + ret = ioctl(dev_fd, LOOP_CONFIGURE, &loopconfig); + + if (ret && errno != EBADF) + tst_brk(TCONF | TERRNO, "LOOP_CONFIGURE is not supported"); + loopconfig.fd = file_fd; + loopconfig.info.lo_flags = LO_FLAGS_DIRECT_IO; +} + +static void cleanup(void) +{ + if (dev_fd > 0) + SAFE_CLOSE(dev_fd); + if (block_devfd > 0) + SAFE_CLOSE(block_devfd); + if (file_fd > 0) + SAFE_CLOSE(file_fd); +} + +static struct tst_test test = { + .setup = setup, + .cleanup = cleanup, + .tcnt = ARRAY_SIZE(tcases), + .test = verify_ioctl_loop, + .needs_root = 1, + .needs_tmpdir = 1, + .needs_drivers = (const char *const []) { + "loop", + NULL + }, + .needs_cmds = (const char *const []) { + "df", + NULL + } +}; -- 2.23.0 ^ permalink raw reply related [flat|nested] 28+ messages in thread
* [LTP] [PATCH v1 4/4] syscalls/ioctl_loop09: Add LOOP_CONFIGURE ioctl test with direct I/O flag 2020-06-11 10:35 ` [LTP] [PATCH v1 4/4] syscalls/ioctl_loop09: Add LOOP_CONFIGURE ioctl test with direct I/O flag Yang Xu @ 2020-07-08 14:00 ` Cyril Hrubis 2020-07-10 6:39 ` [LTP] [PATCH v2 1/2] syscalls/ioctl_loop06: Using LOOP_CONFIGURE to test invalid block size Yang Xu 0 siblings, 1 reply; 28+ messages in thread From: Cyril Hrubis @ 2020-07-08 14:00 UTC (permalink / raw) To: ltp Hi! And here as well. -- Cyril Hrubis chrubis@suse.cz ^ permalink raw reply [flat|nested] 28+ messages in thread
* [LTP] [PATCH v2 1/2] syscalls/ioctl_loop06: Using LOOP_CONFIGURE to test invalid block size 2020-07-08 14:00 ` Cyril Hrubis @ 2020-07-10 6:39 ` Yang Xu 2020-07-10 6:39 ` [LTP] [PATCH v2 2/2] syscalls/ioctl_loop05: Using LOOP_CONFIGURE to set direct io Yang Xu 2020-07-22 9:45 ` [LTP] [PATCH v2 1/2] syscalls/ioctl_loop06: Using LOOP_CONFIGURE to test invalid block size Cyril Hrubis 0 siblings, 2 replies; 28+ messages in thread From: Yang Xu @ 2020-07-10 6:39 UTC (permalink / raw) To: ltp Since kernel commit 3448914e8cc5("loop: Add LOOP_CONFIGURE ioctl"), it can set the correct block size immediately by setting loop_config.block_size. Signed-off-by: Yang Xu <xuyang2018.jy@cn.fujitsu.com> --- .../kernel/syscalls/ioctl/ioctl_loop06.c | 89 +++++++++++++++---- 1 file changed, 73 insertions(+), 16 deletions(-) diff --git a/testcases/kernel/syscalls/ioctl/ioctl_loop06.c b/testcases/kernel/syscalls/ioctl/ioctl_loop06.c index 096ec9363..2f172a09d 100644 --- a/testcases/kernel/syscalls/ioctl/ioctl_loop06.c +++ b/testcases/kernel/syscalls/ioctl/ioctl_loop06.c @@ -3,8 +3,8 @@ * Copyright (c) 2020 FUJITSU LIMITED. All rights reserved. * Author: Yang Xu <xuyang2018.jy@cn.jujitsu.com> * - * This is a basic ioctl error test about loopdevice - * LOOP_SET_BLOCK_SIZE. + * This is a basic error test about the invalid block size of loopdevice + * by using LOOP_SET_BLOCK_SIZE or LOOP_CONFIGURE ioctl. */ #include <stdio.h> @@ -15,41 +15,86 @@ #include "tst_test.h" static char dev_path[1024]; -static int dev_num, dev_fd, attach_flag; +static int dev_num, dev_fd, file_fd, attach_flag, loop_configure_sup = 1; static unsigned int invalid_value, half_value, unalign_value; +static struct loop_config loopconfig; static struct tcase { unsigned int *setvalue; - int exp_err; + int ioctl_flag; char *message; } tcases[] = { - {&half_value, EINVAL, "arg < 512"}, - {&invalid_value, EINVAL, "arg > PAGE_SIZE"}, - {&unalign_value, EINVAL, "arg != power_of_2"}, + {&half_value, LOOP_SET_BLOCK_SIZE, + "Using LOOP_SET_BLOCK_SIZE with arg < 512"}, + + {&invalid_value, LOOP_SET_BLOCK_SIZE, + "Using LOOP_SET_BLOCK_SIZE with arg > PAGE_SIZE"}, + + {&unalign_value, LOOP_SET_BLOCK_SIZE, + "Using LOOP_SET_BLOCK_SIZE with arg != power_of_2"}, + + {&half_value, LOOP_CONFIGURE, + "Using LOOP_CONFIGURE with block_size < 512"}, + + {&invalid_value, LOOP_CONFIGURE, + "Using LOOP_CONFIGURE with block_size > PAGE_SIZE"}, + + {&unalign_value, LOOP_CONFIGURE, + "Using LOOP_CONFIGURE with block_size != power_of_2"}, }; static void verify_ioctl_loop(unsigned int n) +{ + if (tcases[n].ioctl_flag == LOOP_CONFIGURE) + TEST(ioctl(dev_fd, LOOP_CONFIGURE, &loopconfig)); + else + TEST(ioctl(dev_fd, LOOP_SET_BLOCK_SIZE, *(tcases[n].setvalue))); + + if (TST_RET == 0) { + tst_res(TFAIL, "Set block size succeed unexpectedly"); + if (tcases[n].ioctl_flag == LOOP_CONFIGURE) + TST_RETRY_FUNC(ioctl(dev_fd, LOOP_CLR_FD, 0), TST_RETVAL_EQ0); + return; + } + if (TST_ERR == EINVAL) + tst_res(TPASS | TTERRNO, "Set block size failed as expected"); + else + tst_res(TFAIL | TTERRNO, "Set block size failed expected EINVAL got"); +} + +static void run(unsigned int n) { struct tcase *tc = &tcases[n]; tst_res(TINFO, "%s", tc->message); - TEST(ioctl(dev_fd, LOOP_SET_BLOCK_SIZE, *(tc->setvalue))); - if (TST_RET == 0) { - tst_res(TFAIL, "LOOP_SET_BLOCK_SIZE succeed unexpectedly"); + if (tc->ioctl_flag == LOOP_SET_BLOCK_SIZE) { + if (!attach_flag) { + tst_attach_device(dev_path, "test.img"); + attach_flag = 1; + } + verify_ioctl_loop(n); return; } - if (TST_ERR == tc->exp_err) { - tst_res(TPASS | TTERRNO, "LOOP_SET_BLOCK_SIZE failed as expected"); - } else { - tst_res(TFAIL | TTERRNO, "LOOP_SET_BLOCK_SIZE failed expected %s got", - tst_strerrno(tc->exp_err)); + if (tc->ioctl_flag == LOOP_CONFIGURE && !loop_configure_sup) { + tst_res(TCONF, "LOOP_CONFIGURE ioctl not supported"); + return; + } + if (attach_flag) { + SAFE_CLOSE(dev_fd); + tst_detach_device(dev_path); + attach_flag = 0; } + if (dev_fd < 0) + dev_fd = SAFE_OPEN(dev_path, O_RDWR); + loopconfig.block_size = *(tc->setvalue); + verify_ioctl_loop(n); } static void setup(void) { unsigned int pg_size; + int ret; dev_num = tst_find_free_loopdev(dev_path, sizeof(dev_path)); if (dev_num < 0) @@ -67,12 +112,24 @@ static void setup(void) if (ioctl(dev_fd, LOOP_SET_BLOCK_SIZE, 512) && errno == EINVAL) tst_brk(TCONF, "LOOP_SET_BLOCK_SIZE is not supported"); + + file_fd = SAFE_OPEN("test.img", O_RDWR); + loopconfig.fd = -1; + ret = ioctl(dev_fd, LOOP_CONFIGURE, &loopconfig); + if (ret && errno != EBADF) { + tst_res(TINFO | TERRNO, "LOOP_CONFIGURE is not supported"); + loop_configure_sup = 0; + return; + } + loopconfig.fd = file_fd; } static void cleanup(void) { if (dev_fd > 0) SAFE_CLOSE(dev_fd); + if (file_fd > 0) + SAFE_CLOSE(file_fd); if (attach_flag) tst_detach_device(dev_path); } @@ -80,7 +137,7 @@ static void cleanup(void) static struct tst_test test = { .setup = setup, .cleanup = cleanup, - .test = verify_ioctl_loop, + .test = run, .tcnt = ARRAY_SIZE(tcases), .needs_root = 1, .needs_tmpdir = 1, -- 2.23.0 ^ permalink raw reply related [flat|nested] 28+ messages in thread
* [LTP] [PATCH v2 2/2] syscalls/ioctl_loop05: Using LOOP_CONFIGURE to set direct io 2020-07-10 6:39 ` [LTP] [PATCH v2 1/2] syscalls/ioctl_loop06: Using LOOP_CONFIGURE to test invalid block size Yang Xu @ 2020-07-10 6:39 ` Yang Xu 2020-07-30 7:28 ` Yang Xu 2020-07-22 9:45 ` [LTP] [PATCH v2 1/2] syscalls/ioctl_loop06: Using LOOP_CONFIGURE to test invalid block size Cyril Hrubis 1 sibling, 1 reply; 28+ messages in thread From: Yang Xu @ 2020-07-10 6:39 UTC (permalink / raw) To: ltp Since kernel commit 3448914e8cc5("loop: Add LOOP_CONFIGURE ioctl"), it can explicitly request direct I/O mode by setting LO_FLAGS_DIRECT_IO in loop_config.info.lo_flags. Signed-off-by: Yang Xu <xuyang2018.jy@cn.fujitsu.com> --- .../kernel/syscalls/ioctl/ioctl_loop05.c | 154 +++++++++++++----- 1 file changed, 117 insertions(+), 37 deletions(-) diff --git a/testcases/kernel/syscalls/ioctl/ioctl_loop05.c b/testcases/kernel/syscalls/ioctl/ioctl_loop05.c index e3c14faab..6abb27998 100644 --- a/testcases/kernel/syscalls/ioctl/ioctl_loop05.c +++ b/testcases/kernel/syscalls/ioctl/ioctl_loop05.c @@ -19,6 +19,9 @@ * enabled but falls back to buffered I/O later on. This is the case at least * for Btrfs. Because of that the test passes both with failure as well as * success with non-zero offset. + * + * Also use LOOP_CONFIGURE to test this by setting LO_FLAGS_DIRECT_IO + * in loop_config.info.lo_flags. */ #include <stdio.h> @@ -32,8 +35,36 @@ #define DIO_MESSAGE "In dio mode" #define NON_DIO_MESSAGE "In non dio mode" -static char dev_path[1024], sys_loop_diopath[1024], backing_file_path[1024];; +static char dev_path[1024], sys_loop_diopath[1024], backing_file_path[1024]; static int dev_num, dev_fd, block_devfd, attach_flag, logical_block_size; +static int file_fd, loop_configure_sup = 1; +static struct loop_config loopconfig; +static struct loop_info loopinfo; + +static struct tcase { + int multi; /*logical_block_size / 2 as unit */ + int dio_value; + int ioctl_flag; + char *message; +} tcases[] = { + {0, 1, LOOP_SET_DIRECT_IO, + "Using LOOP_SET_DIRET_IO without setting lo_offset or sizelimit"}, + + {2, 1, LOOP_SET_DIRECT_IO, + "Using LOOP_SET_DIRECT_IO With offset equal to logical_block_size"}, + + {1, 0, LOOP_SET_DIRECT_IO, + "Using LOOP_SET_DIRECT_IO with offset less than logical_block_size"}, + + {0, 1, LOOP_CONFIGURE, + "Using LOOP_CONFIGURE without setting lo_offset or sizelimit"}, + + {2, 1, LOOP_CONFIGURE, + "Using LOOP_CONFIGURE With offset equal to logical_block_size"}, + + {1, 0, LOOP_CONFIGURE, + "Using LOOP_CONFIGURE witg offset less than logical_block_size"}, +}; static void check_dio_value(int flag) { @@ -42,61 +73,94 @@ static void check_dio_value(int flag) memset(&loopinfoget, 0, sizeof(loopinfoget)); SAFE_IOCTL(dev_fd, LOOP_GET_STATUS, &loopinfoget); - tst_res(TINFO, "%s", flag ? DIO_MESSAGE : NON_DIO_MESSAGE); if (loopinfoget.lo_flags & LO_FLAGS_DIRECT_IO) - tst_res(flag ? TPASS : TFAIL, "lo_flags has LO_FLAGS_DIRECT_IO flag"); + tst_res(flag ? TPASS : TFAIL, + "%s, lo_flags has LO_FLAGS_DIRECT_IO flag", + flag ? DIO_MESSAGE : NON_DIO_MESSAGE); else - tst_res(flag ? TFAIL : TPASS, "lo_flags doesn't have LO_FLAGS_DIRECT_IO flag"); + tst_res(flag ? TFAIL : TPASS, + "%s, lo_flags doesn't have LO_FLAGS_DIRECT_IO flag", + flag ? DIO_MESSAGE : NON_DIO_MESSAGE); TST_ASSERT_INT(sys_loop_diopath, flag); } -static void verify_ioctl_loop(void) +static void verify_ioctl_loop(unsigned int n) { - struct loop_info loopinfo; - - memset(&loopinfo, 0, sizeof(loopinfo)); - TST_RETRY_FUNC(ioctl(dev_fd, LOOP_SET_STATUS, &loopinfo), TST_RETVAL_EQ0); + if (tcases[n].ioctl_flag == LOOP_SET_DIRECT_IO) { + TST_RETRY_FUNC(ioctl(dev_fd, LOOP_SET_STATUS, &loopinfo), TST_RETVAL_EQ0); + + TEST(ioctl(dev_fd, LOOP_SET_DIRECT_IO, 1)); + if (TST_RET == 0) { + if (tcases[n].dio_value) + tst_res(TPASS, "set direct io succeeded"); + else + tst_res(TPASS, "set direct io succeeded, offset is ignored"); + check_dio_value(1); + SAFE_IOCTL(dev_fd, LOOP_SET_DIRECT_IO, 0); + return; + } + if (TST_ERR == EINVAL && !tcases[n].dio_value) + tst_res(TPASS | TTERRNO, + "set direct io failed as expected"); + else + tst_res(TFAIL | TTERRNO, "set direct io failed"); + return; + } + /* + * When we call loop_configure ioctl successfully and detach it, + * the subquent loop_configure without non-zero lo_offset or + * sizelimit may trigger the blk_update_request I/O error. + * To avoid this, sleep 1s to ensure last blk_update_request has + * completed. + */ + sleep(1); + /* + * loop_cofigure calls loop_update_dio() function, it will ignore + * the result of setting dio. It is different from loop_set_dio. + */ + TST_RETRY_FUNC(ioctl(dev_fd, LOOP_CONFIGURE, &loopconfig), TST_RETVAL_EQ0); + check_dio_value(tcases[n].dio_value); + TST_RETRY_FUNC(ioctl(dev_fd, LOOP_CLR_FD, 0), TST_RETVAL_EQ0); +} - tst_res(TINFO, "Without setting lo_offset or sizelimit"); - SAFE_IOCTL(dev_fd, LOOP_SET_DIRECT_IO, 1); - check_dio_value(1); +static void run(unsigned int n) +{ + struct tcase *tc = &tcases[n]; - SAFE_IOCTL(dev_fd, LOOP_SET_DIRECT_IO, 0); - check_dio_value(0); + tst_res(TINFO, "%s", tc->message); - tst_res(TINFO, "With offset equal to logical_block_size"); - loopinfo.lo_offset = logical_block_size; - TST_RETRY_FUNC(ioctl(dev_fd, LOOP_SET_STATUS, &loopinfo), TST_RETVAL_EQ0); - TEST(ioctl(dev_fd, LOOP_SET_DIRECT_IO, 1)); - if (TST_RET == 0) { - tst_res(TPASS, "LOOP_SET_DIRECT_IO succeeded"); - check_dio_value(1); + if (tc->ioctl_flag == LOOP_SET_DIRECT_IO) { + if (!attach_flag) { + tst_attach_device(dev_path, "test.img"); + attach_flag = 1; + } SAFE_IOCTL(dev_fd, LOOP_SET_DIRECT_IO, 0); - } else { - tst_res(TFAIL | TTERRNO, "LOOP_SET_DIRECT_IO failed"); + check_dio_value(0); + loopinfo.lo_offset = logical_block_size * tc->multi / 2; + verify_ioctl_loop(n); + return; } - - tst_res(TINFO, "With nonzero offset less than logical_block_size"); - loopinfo.lo_offset = logical_block_size / 2; - TST_RETRY_FUNC(ioctl(dev_fd, LOOP_SET_STATUS, &loopinfo), TST_RETVAL_EQ0); - - TEST(ioctl(dev_fd, LOOP_SET_DIRECT_IO, 1)); - if (TST_RET == 0) { - tst_res(TPASS, "LOOP_SET_DIRECT_IO succeeded, offset is ignored"); - SAFE_IOCTL(dev_fd, LOOP_SET_DIRECT_IO, 0); + if (tc->ioctl_flag == LOOP_CONFIGURE && !loop_configure_sup) { + tst_res(TCONF, "LOOP_CONFIGURE ioctl not supported"); return; } - if (TST_ERR == EINVAL) - tst_res(TPASS | TTERRNO, "LOOP_SET_DIRECT_IO failed as expected"); - else - tst_res(TFAIL | TTERRNO, "LOOP_SET_DIRECT_IO failed expected EINVAL got"); + if (attach_flag) { + SAFE_CLOSE(dev_fd); + tst_detach_device(dev_path); + attach_flag = 0; + } + if (dev_fd < 0) + dev_fd = SAFE_OPEN(dev_path, O_RDWR); + loopconfig.info.lo_offset = logical_block_size * tc->multi / 2; + verify_ioctl_loop(n); } static void setup(void) { char bd_path[100]; + int ret; if (tst_fs_type(".") == TST_TMPFS_MAGIC) tst_brk(TCONF, "tmpfd doesn't support O_DIRECT flag"); @@ -128,8 +192,21 @@ static void setup(void) SAFE_IOCTL(block_devfd, BLKSSZGET, &logical_block_size); tst_res(TINFO, "backing dev(%s) logical_block_size is %d", bd_path, logical_block_size); SAFE_CLOSE(block_devfd); + if (logical_block_size > 512) TST_RETRY_FUNC(ioctl(dev_fd, LOOP_SET_BLOCK_SIZE, logical_block_size), TST_RETVAL_EQ0); + + file_fd = SAFE_OPEN("test.img", O_RDWR); + loopconfig.fd = -1; + ret = ioctl(dev_fd, LOOP_CONFIGURE, &loopconfig); + if (ret && errno != EBADF) { + tst_res(TINFO | TERRNO, "LOOP_CONFIGURE is not supported"); + loop_configure_sup = 0; + return; + } + loopconfig.block_size = logical_block_size; + loopconfig.fd = file_fd; + loopconfig.info.lo_flags = LO_FLAGS_DIRECT_IO; } static void cleanup(void) @@ -138,6 +215,8 @@ static void cleanup(void) SAFE_CLOSE(dev_fd); if (block_devfd > 0) SAFE_CLOSE(block_devfd); + if (file_fd > 0) + SAFE_CLOSE(file_fd); if (attach_flag) tst_detach_device(dev_path); } @@ -145,7 +224,8 @@ static void cleanup(void) static struct tst_test test = { .setup = setup, .cleanup = cleanup, - .test_all = verify_ioctl_loop, + .test = run, + .tcnt = ARRAY_SIZE(tcases), .needs_root = 1, .needs_tmpdir = 1, .needs_drivers = (const char *const []) { -- 2.23.0 ^ permalink raw reply related [flat|nested] 28+ messages in thread
* [LTP] [PATCH v2 2/2] syscalls/ioctl_loop05: Using LOOP_CONFIGURE to set direct io 2020-07-10 6:39 ` [LTP] [PATCH v2 2/2] syscalls/ioctl_loop05: Using LOOP_CONFIGURE to set direct io Yang Xu @ 2020-07-30 7:28 ` Yang Xu 0 siblings, 0 replies; 28+ messages in thread From: Yang Xu @ 2020-07-30 7:28 UTC (permalink / raw) To: ltp Hi Martijn CC block kernel guys I have a question when using loop_configure ioctl to set direct io flag. In ltp testcase ioctl_loop05, I modify this case as the follow (Using loop_configure ioctl to set direct io mode with different logical_block_size). But sometimes I met a problem that loop_configure ioctl succeed but the flag doesn't take effect. the test (need to merge this patch[1] and remove sleep) ioctl_loop05.c:132: INFO: Using LOOP_SET_DIRECT_IO with offset less than logical_block_size ioctl_loop05.c:84: PASS: In non dio mode, lo_flags doesn't have LO_FLAGS_DIRECT_IO flag ioctl_loop05.c:86: PASS: /sys/block/loop0/loop/dio = 0 ioctl_loop05.c:106: PASS: set direct io failed as expected: EINVAL (22) ioctl_loop05.c:132: INFO: Using LOOP_CONFIGURE without setting lo_offset or sizelimit ioctl_loop05.c:80: PASS: In dio mode, lo_flags has LO_FLAGS_DIRECT_IO flag ioctl_loop05.c:86: PASS: /sys/block/loop0/loop/dio = 1 ioctl_loop05.c:132: INFO: Using LOOP_CONFIGURE With offset equal to logical_block_size ioctl_loop05.c:80: PASS: In dio mode, lo_flags has LO_FLAGS_DIRECT_IO flag ioctl_loop05.c:86: PASS: /sys/block/loop0/loop/dio = 1 ioctl_loop05.c:132: INFO: Using LOOP_CONFIGURE witg offset less than logical_block_size ioctl_loop05.c:80: FAIL: In non dio mode, lo_flags has LO_FLAGS_DIRECT_IO flag ioctl_loop05.c:86: FAIL: /sys/block/loop0/loop/dio != 0 got 1 Summary: passed 17 failed 2 skipped 0 warnings 0 dmesg [75103.201861] loop_set_status: loop0 () has still dirty pages (nrpages=3) [75103.321850] blk_update_request: I/O error, dev loop0, sector 2047 op 0x0:(READ) flags 0x80700 phys_seg 1 prio class 0 [75103.337105] blk_update_request: I/O error, dev loop0, sector 2047 op 0x0:(READ) flags 0x0 phys_seg 1 prio class 0 [75103.337816] Buffer I/O error on dev loop0, logical block 255, async page read It seems that the last blk_update_request has not completed but the subquent blk request (loop_configure ioctl with non zero size or logic block size triggers) has started.So kernel has this warning.Is it right? Is it a expected behaviour? [1]https://patchwork.ozlabs.org/project/ltp/patch/1595556357-29932-2-git-send-email-xuyang2018.jy@cn.fujitsu.com/ Best Regards Yang Xu > Since kernel commit 3448914e8cc5("loop: Add LOOP_CONFIGURE ioctl"), > it can explicitly request direct I/O mode by setting LO_FLAGS_DIRECT_IO > in loop_config.info.lo_flags. > > Signed-off-by: Yang Xu <xuyang2018.jy@cn.fujitsu.com> > --- > .../kernel/syscalls/ioctl/ioctl_loop05.c | 154 +++++++++++++----- > 1 file changed, 117 insertions(+), 37 deletions(-) > > diff --git a/testcases/kernel/syscalls/ioctl/ioctl_loop05.c b/testcases/kernel/syscalls/ioctl/ioctl_loop05.c > index e3c14faab..6abb27998 100644 > --- a/testcases/kernel/syscalls/ioctl/ioctl_loop05.c > +++ b/testcases/kernel/syscalls/ioctl/ioctl_loop05.c > @@ -19,6 +19,9 @@ > * enabled but falls back to buffered I/O later on. This is the case at least > * for Btrfs. Because of that the test passes both with failure as well as > * success with non-zero offset. > + * > + * Also use LOOP_CONFIGURE to test this by setting LO_FLAGS_DIRECT_IO > + * in loop_config.info.lo_flags. > */ > > #include <stdio.h> > @@ -32,8 +35,36 @@ > #define DIO_MESSAGE "In dio mode" > #define NON_DIO_MESSAGE "In non dio mode" > > -static char dev_path[1024], sys_loop_diopath[1024], backing_file_path[1024];; > +static char dev_path[1024], sys_loop_diopath[1024], backing_file_path[1024]; > static int dev_num, dev_fd, block_devfd, attach_flag, logical_block_size; > +static int file_fd, loop_configure_sup = 1; > +static struct loop_config loopconfig; > +static struct loop_info loopinfo; > + > +static struct tcase { > + int multi; /*logical_block_size / 2 as unit */ > + int dio_value; > + int ioctl_flag; > + char *message; > +} tcases[] = { > + {0, 1, LOOP_SET_DIRECT_IO, > + "Using LOOP_SET_DIRET_IO without setting lo_offset or sizelimit"}, > + > + {2, 1, LOOP_SET_DIRECT_IO, > + "Using LOOP_SET_DIRECT_IO With offset equal to logical_block_size"}, > + > + {1, 0, LOOP_SET_DIRECT_IO, > + "Using LOOP_SET_DIRECT_IO with offset less than logical_block_size"}, > + > + {0, 1, LOOP_CONFIGURE, > + "Using LOOP_CONFIGURE without setting lo_offset or sizelimit"}, > + > + {2, 1, LOOP_CONFIGURE, > + "Using LOOP_CONFIGURE With offset equal to logical_block_size"}, > + > + {1, 0, LOOP_CONFIGURE, > + "Using LOOP_CONFIGURE witg offset less than logical_block_size"}, > +}; > > static void check_dio_value(int flag) > { > @@ -42,61 +73,94 @@ static void check_dio_value(int flag) > memset(&loopinfoget, 0, sizeof(loopinfoget)); > > SAFE_IOCTL(dev_fd, LOOP_GET_STATUS, &loopinfoget); > - tst_res(TINFO, "%s", flag ? DIO_MESSAGE : NON_DIO_MESSAGE); > > if (loopinfoget.lo_flags & LO_FLAGS_DIRECT_IO) > - tst_res(flag ? TPASS : TFAIL, "lo_flags has LO_FLAGS_DIRECT_IO flag"); > + tst_res(flag ? TPASS : TFAIL, > + "%s, lo_flags has LO_FLAGS_DIRECT_IO flag", > + flag ? DIO_MESSAGE : NON_DIO_MESSAGE); > else > - tst_res(flag ? TFAIL : TPASS, "lo_flags doesn't have LO_FLAGS_DIRECT_IO flag"); > + tst_res(flag ? TFAIL : TPASS, > + "%s, lo_flags doesn't have LO_FLAGS_DIRECT_IO flag", > + flag ? DIO_MESSAGE : NON_DIO_MESSAGE); > > TST_ASSERT_INT(sys_loop_diopath, flag); > } > > -static void verify_ioctl_loop(void) > +static void verify_ioctl_loop(unsigned int n) > { > - struct loop_info loopinfo; > - > - memset(&loopinfo, 0, sizeof(loopinfo)); > - TST_RETRY_FUNC(ioctl(dev_fd, LOOP_SET_STATUS, &loopinfo), TST_RETVAL_EQ0); > + if (tcases[n].ioctl_flag == LOOP_SET_DIRECT_IO) { > + TST_RETRY_FUNC(ioctl(dev_fd, LOOP_SET_STATUS, &loopinfo), TST_RETVAL_EQ0); > + > + TEST(ioctl(dev_fd, LOOP_SET_DIRECT_IO, 1)); > + if (TST_RET == 0) { > + if (tcases[n].dio_value) > + tst_res(TPASS, "set direct io succeeded"); > + else > + tst_res(TPASS, "set direct io succeeded, offset is ignored"); > + check_dio_value(1); > + SAFE_IOCTL(dev_fd, LOOP_SET_DIRECT_IO, 0); > + return; > + } > + if (TST_ERR == EINVAL && !tcases[n].dio_value) > + tst_res(TPASS | TTERRNO, > + "set direct io failed as expected"); > + else > + tst_res(TFAIL | TTERRNO, "set direct io failed"); > + return; > + } > + /* > + * When we call loop_configure ioctl successfully and detach it, > + * the subquent loop_configure without non-zero lo_offset or > + * sizelimit may trigger the blk_update_request I/O error. > + * To avoid this, sleep 1s to ensure last blk_update_request has > + * completed. > + */ > + sleep(1); > + /* > + * loop_cofigure calls loop_update_dio() function, it will ignore > + * the result of setting dio. It is different from loop_set_dio. > + */ > + TST_RETRY_FUNC(ioctl(dev_fd, LOOP_CONFIGURE, &loopconfig), TST_RETVAL_EQ0); > + check_dio_value(tcases[n].dio_value); > + TST_RETRY_FUNC(ioctl(dev_fd, LOOP_CLR_FD, 0), TST_RETVAL_EQ0); > +} > > - tst_res(TINFO, "Without setting lo_offset or sizelimit"); > - SAFE_IOCTL(dev_fd, LOOP_SET_DIRECT_IO, 1); > - check_dio_value(1); > +static void run(unsigned int n) > +{ > + struct tcase *tc = &tcases[n]; > > - SAFE_IOCTL(dev_fd, LOOP_SET_DIRECT_IO, 0); > - check_dio_value(0); > + tst_res(TINFO, "%s", tc->message); > > - tst_res(TINFO, "With offset equal to logical_block_size"); > - loopinfo.lo_offset = logical_block_size; > - TST_RETRY_FUNC(ioctl(dev_fd, LOOP_SET_STATUS, &loopinfo), TST_RETVAL_EQ0); > - TEST(ioctl(dev_fd, LOOP_SET_DIRECT_IO, 1)); > - if (TST_RET == 0) { > - tst_res(TPASS, "LOOP_SET_DIRECT_IO succeeded"); > - check_dio_value(1); > + if (tc->ioctl_flag == LOOP_SET_DIRECT_IO) { > + if (!attach_flag) { > + tst_attach_device(dev_path, "test.img"); > + attach_flag = 1; > + } > SAFE_IOCTL(dev_fd, LOOP_SET_DIRECT_IO, 0); > - } else { > - tst_res(TFAIL | TTERRNO, "LOOP_SET_DIRECT_IO failed"); > + check_dio_value(0); > + loopinfo.lo_offset = logical_block_size * tc->multi / 2; > + verify_ioctl_loop(n); > + return; > } > - > - tst_res(TINFO, "With nonzero offset less than logical_block_size"); > - loopinfo.lo_offset = logical_block_size / 2; > - TST_RETRY_FUNC(ioctl(dev_fd, LOOP_SET_STATUS, &loopinfo), TST_RETVAL_EQ0); > - > - TEST(ioctl(dev_fd, LOOP_SET_DIRECT_IO, 1)); > - if (TST_RET == 0) { > - tst_res(TPASS, "LOOP_SET_DIRECT_IO succeeded, offset is ignored"); > - SAFE_IOCTL(dev_fd, LOOP_SET_DIRECT_IO, 0); > + if (tc->ioctl_flag == LOOP_CONFIGURE && !loop_configure_sup) { > + tst_res(TCONF, "LOOP_CONFIGURE ioctl not supported"); > return; > } > - if (TST_ERR == EINVAL) > - tst_res(TPASS | TTERRNO, "LOOP_SET_DIRECT_IO failed as expected"); > - else > - tst_res(TFAIL | TTERRNO, "LOOP_SET_DIRECT_IO failed expected EINVAL got"); > + if (attach_flag) { > + SAFE_CLOSE(dev_fd); > + tst_detach_device(dev_path); > + attach_flag = 0; > + } > + if (dev_fd < 0) > + dev_fd = SAFE_OPEN(dev_path, O_RDWR); > + loopconfig.info.lo_offset = logical_block_size * tc->multi / 2; > + verify_ioctl_loop(n); > } > > static void setup(void) > { > char bd_path[100]; > + int ret; > > if (tst_fs_type(".") == TST_TMPFS_MAGIC) > tst_brk(TCONF, "tmpfd doesn't support O_DIRECT flag"); > @@ -128,8 +192,21 @@ static void setup(void) > SAFE_IOCTL(block_devfd, BLKSSZGET, &logical_block_size); > tst_res(TINFO, "backing dev(%s) logical_block_size is %d", bd_path, logical_block_size); > SAFE_CLOSE(block_devfd); > + > if (logical_block_size > 512) > TST_RETRY_FUNC(ioctl(dev_fd, LOOP_SET_BLOCK_SIZE, logical_block_size), TST_RETVAL_EQ0); > + > + file_fd = SAFE_OPEN("test.img", O_RDWR); > + loopconfig.fd = -1; > + ret = ioctl(dev_fd, LOOP_CONFIGURE, &loopconfig); > + if (ret && errno != EBADF) { > + tst_res(TINFO | TERRNO, "LOOP_CONFIGURE is not supported"); > + loop_configure_sup = 0; > + return; > + } > + loopconfig.block_size = logical_block_size; > + loopconfig.fd = file_fd; > + loopconfig.info.lo_flags = LO_FLAGS_DIRECT_IO; > } > > static void cleanup(void) > @@ -138,6 +215,8 @@ static void cleanup(void) > SAFE_CLOSE(dev_fd); > if (block_devfd > 0) > SAFE_CLOSE(block_devfd); > + if (file_fd > 0) > + SAFE_CLOSE(file_fd); > if (attach_flag) > tst_detach_device(dev_path); > } > @@ -145,7 +224,8 @@ static void cleanup(void) > static struct tst_test test = { > .setup = setup, > .cleanup = cleanup, > - .test_all = verify_ioctl_loop, > + .test = run, > + .tcnt = ARRAY_SIZE(tcases), > .needs_root = 1, > .needs_tmpdir = 1, > .needs_drivers = (const char *const []) { > ^ permalink raw reply [flat|nested] 28+ messages in thread
* [LTP] [PATCH v2 1/2] syscalls/ioctl_loop06: Using LOOP_CONFIGURE to test invalid block size 2020-07-10 6:39 ` [LTP] [PATCH v2 1/2] syscalls/ioctl_loop06: Using LOOP_CONFIGURE to test invalid block size Yang Xu 2020-07-10 6:39 ` [LTP] [PATCH v2 2/2] syscalls/ioctl_loop05: Using LOOP_CONFIGURE to set direct io Yang Xu @ 2020-07-22 9:45 ` Cyril Hrubis 2020-07-22 10:15 ` Yang Xu 1 sibling, 1 reply; 28+ messages in thread From: Cyril Hrubis @ 2020-07-22 9:45 UTC (permalink / raw) To: ltp Hi! Do we really need to close and open the dev_fd repeatedly and also we don't have to attach the device in the test setup? I.e. it should work the same with: diff --git a/testcases/kernel/syscalls/ioctl/ioctl_loop06.c b/testcases/kernel/syscalls/ioctl/ioctl_loop06.c index 2f172a09d..7936af4ac 100644 --- a/testcases/kernel/syscalls/ioctl/ioctl_loop06.c +++ b/testcases/kernel/syscalls/ioctl/ioctl_loop06.c @@ -81,12 +81,9 @@ static void run(unsigned int n) return; } if (attach_flag) { - SAFE_CLOSE(dev_fd); tst_detach_device(dev_path); attach_flag = 0; } - if (dev_fd < 0) - dev_fd = SAFE_OPEN(dev_path, O_RDWR); loopconfig.block_size = *(tc->setvalue); verify_ioctl_loop(n); } @@ -101,8 +98,6 @@ static void setup(void) tst_brk(TBROK, "Failed to find free loop device"); tst_fill_file("test.img", 0, 1024, 1024); - tst_attach_device(dev_path, "test.img"); - attach_flag = 1; half_value = 256; pg_size = getpagesize(); invalid_value = pg_size * 2; -- Cyril Hrubis chrubis@suse.cz ^ permalink raw reply related [flat|nested] 28+ messages in thread
* [LTP] [PATCH v2 1/2] syscalls/ioctl_loop06: Using LOOP_CONFIGURE to test invalid block size 2020-07-22 9:45 ` [LTP] [PATCH v2 1/2] syscalls/ioctl_loop06: Using LOOP_CONFIGURE to test invalid block size Cyril Hrubis @ 2020-07-22 10:15 ` Yang Xu 2020-07-22 12:59 ` Cyril Hrubis 0 siblings, 1 reply; 28+ messages in thread From: Yang Xu @ 2020-07-22 10:15 UTC (permalink / raw) To: ltp Hi Cyril > Hi! > Do we really need to close and open the dev_fd repeatedly and also we > don't have to attach the device in the test setup? YES, we don't need to attach the device in the setup because LOOP_SET_BLOCK_SIZE checks works well(return ENXIO if supports, return EINVAL if not supports) when not attaching device. But for close and open the dev_fd repeatedly, I think it is necessary because when we detach device firstly without closing dev fd, it will report the warnging as below: tst_device.c:89: INFO: Found free device 0 '/dev/loop0' ioctl_loop06.c:69: INFO: Using LOOP_SET_BLOCK_SIZE with arg < 512 ioctl_loop06.c:60: PASS: Set block size failed as expected: EINVAL (22) ioctl_loop06.c:69: INFO: Using LOOP_SET_BLOCK_SIZE with arg > PAGE_SIZE ioctl_loop06.c:60: PASS: Set block size failed as expected: EINVAL (22) ioctl_loop06.c:69: INFO: Using LOOP_SET_BLOCK_SIZE with arg != power_of_2 ioctl_loop06.c:60: PASS: Set block size failed as expected: EINVAL (22) ioctl_loop06.c:69: INFO: Using LOOP_CONFIGURE with block_size < 512 tst_device.c:223: WARN: ioctl(/dev/loop0, LOOP_CLR_FD, 0) no ENXIO for too long ioctl_loop06.c:62: FAIL: Set block size failed expected EINVAL got: EBUSY (16) That is why I close dev_fd firstly and then detach device in cleanup function. > > I.e. it should work the same with: > > diff --git a/testcases/kernel/syscalls/ioctl/ioctl_loop06.c b/testcases/kernel/syscalls/ioctl/ioctl_loop06.c > index 2f172a09d..7936af4ac 100644 > --- a/testcases/kernel/syscalls/ioctl/ioctl_loop06.c > +++ b/testcases/kernel/syscalls/ioctl/ioctl_loop06.c > @@ -81,12 +81,9 @@ static void run(unsigned int n) > return; > } > if (attach_flag) { > - SAFE_CLOSE(dev_fd); > tst_detach_device(dev_path); > attach_flag = 0; > } > - if (dev_fd < 0) > - dev_fd = SAFE_OPEN(dev_path, O_RDWR); > loopconfig.block_size = *(tc->setvalue); > verify_ioctl_loop(n); > } > @@ -101,8 +98,6 @@ static void setup(void) > tst_brk(TBROK, "Failed to find free loop device"); > > tst_fill_file("test.img", 0, 1024, 1024); > - tst_attach_device(dev_path, "test.img"); > - attach_flag = 1; > half_value = 256; > pg_size = getpagesize(); > invalid_value = pg_size * 2; > ^ permalink raw reply [flat|nested] 28+ messages in thread
* [LTP] [PATCH v2 1/2] syscalls/ioctl_loop06: Using LOOP_CONFIGURE to test invalid block size 2020-07-22 10:15 ` Yang Xu @ 2020-07-22 12:59 ` Cyril Hrubis 2020-07-23 9:41 ` Yang Xu 2020-07-24 2:05 ` [LTP] [PATCH v3 " Yang Xu 0 siblings, 2 replies; 28+ messages in thread From: Cyril Hrubis @ 2020-07-22 12:59 UTC (permalink / raw) To: ltp Hi! > > Do we really need to close and open the dev_fd repeatedly and also we > > don't have to attach the device in the test setup? > YES, we don't need to attach the device in the setup because > LOOP_SET_BLOCK_SIZE checks works well(return ENXIO if supports, return > EINVAL if not supports) when not attaching device. > > But for close and open the dev_fd repeatedly, I think it is necessary > because when we detach device firstly without closing dev fd, it will > report the warnging as below: > > tst_device.c:89: INFO: Found free device 0 '/dev/loop0' > ioctl_loop06.c:69: INFO: Using LOOP_SET_BLOCK_SIZE with arg < 512 > ioctl_loop06.c:60: PASS: Set block size failed as expected: EINVAL (22) > ioctl_loop06.c:69: INFO: Using LOOP_SET_BLOCK_SIZE with arg > PAGE_SIZE > ioctl_loop06.c:60: PASS: Set block size failed as expected: EINVAL (22) > ioctl_loop06.c:69: INFO: Using LOOP_SET_BLOCK_SIZE with arg != power_of_2 > ioctl_loop06.c:60: PASS: Set block size failed as expected: EINVAL (22) > ioctl_loop06.c:69: INFO: Using LOOP_CONFIGURE with block_size < 512 > tst_device.c:223: WARN: ioctl(/dev/loop0, LOOP_CLR_FD, 0) no ENXIO for > too long > ioctl_loop06.c:62: FAIL: Set block size failed expected EINVAL got: > EBUSY (16) > > That is why I close dev_fd firstly and then detach device in cleanup > function. Ah, right, the tst_detach_device() opens the dev_path so the function fails to destroy it because the device is opened twice at that point. I guess that proper solution would be to add a tst_detach_device_by_fd() and change the library so that tst_detach_device() opens the dev_path and calls tst_detach_device_by_fd() internally. -- Cyril Hrubis chrubis@suse.cz ^ permalink raw reply [flat|nested] 28+ messages in thread
* [LTP] [PATCH v2 1/2] syscalls/ioctl_loop06: Using LOOP_CONFIGURE to test invalid block size 2020-07-22 12:59 ` Cyril Hrubis @ 2020-07-23 9:41 ` Yang Xu 2020-07-24 2:05 ` [LTP] [PATCH v3 " Yang Xu 1 sibling, 0 replies; 28+ messages in thread From: Yang Xu @ 2020-07-23 9:41 UTC (permalink / raw) To: ltp HI Cyril > Hi! >>> Do we really need to close and open the dev_fd repeatedly and also we >>> don't have to attach the device in the test setup? >> YES, we don't need to attach the device in the setup because >> LOOP_SET_BLOCK_SIZE checks works well(return ENXIO if supports, return >> EINVAL if not supports) when not attaching device. >> >> But for close and open the dev_fd repeatedly, I think it is necessary >> because when we detach device firstly without closing dev fd, it will >> report the warnging as below: >> >> tst_device.c:89: INFO: Found free device 0 '/dev/loop0' >> ioctl_loop06.c:69: INFO: Using LOOP_SET_BLOCK_SIZE with arg < 512 >> ioctl_loop06.c:60: PASS: Set block size failed as expected: EINVAL (22) >> ioctl_loop06.c:69: INFO: Using LOOP_SET_BLOCK_SIZE with arg > PAGE_SIZE >> ioctl_loop06.c:60: PASS: Set block size failed as expected: EINVAL (22) >> ioctl_loop06.c:69: INFO: Using LOOP_SET_BLOCK_SIZE with arg != power_of_2 >> ioctl_loop06.c:60: PASS: Set block size failed as expected: EINVAL (22) >> ioctl_loop06.c:69: INFO: Using LOOP_CONFIGURE with block_size < 512 >> tst_device.c:223: WARN: ioctl(/dev/loop0, LOOP_CLR_FD, 0) no ENXIO for >> too long >> ioctl_loop06.c:62: FAIL: Set block size failed expected EINVAL got: >> EBUSY (16) >> >> That is why I close dev_fd firstly and then detach device in cleanup >> function. > > Ah, right, the tst_detach_device() opens the dev_path so the function > fails to destroy it because the device is opened twice at that point. > > I guess that proper solution would be to add a tst_detach_device_by_fd() > and change the library so that tst_detach_device() opens the dev_path > and calls tst_detach_device_by_fd() internally. Should I send a v3 patch or you directly use the new api for this patch? > ^ permalink raw reply [flat|nested] 28+ messages in thread
* [LTP] [PATCH v3 1/2] syscalls/ioctl_loop06: Using LOOP_CONFIGURE to test invalid block size 2020-07-22 12:59 ` Cyril Hrubis 2020-07-23 9:41 ` Yang Xu @ 2020-07-24 2:05 ` Yang Xu 2020-07-24 2:05 ` [LTP] [PATCH v3 2/2] syscalls/ioctl_loop05: Using LOOP_CONFIGURE to set direct io Yang Xu 2020-07-29 10:07 ` [LTP] [PATCH v3 1/2] syscalls/ioctl_loop06: Using LOOP_CONFIGURE to test invalid block size Cyril Hrubis 1 sibling, 2 replies; 28+ messages in thread From: Yang Xu @ 2020-07-24 2:05 UTC (permalink / raw) To: ltp Since kernel commit 3448914e8cc5("loop: Add LOOP_CONFIGURE ioctl"), it can set the correct block size immediately by setting loop_config.block_size. Signed-off-by: Yang Xu <xuyang2018.jy@cn.fujitsu.com> --- v2-v3: 1.remove tst_attch_device in setup 2.use tst_detach_device_by_fd api .../kernel/syscalls/ioctl/ioctl_loop06.c | 88 +++++++++++++++---- 1 file changed, 70 insertions(+), 18 deletions(-) diff --git a/testcases/kernel/syscalls/ioctl/ioctl_loop06.c b/testcases/kernel/syscalls/ioctl/ioctl_loop06.c index 096ec9363..d073c120b 100644 --- a/testcases/kernel/syscalls/ioctl/ioctl_loop06.c +++ b/testcases/kernel/syscalls/ioctl/ioctl_loop06.c @@ -3,8 +3,8 @@ * Copyright (c) 2020 FUJITSU LIMITED. All rights reserved. * Author: Yang Xu <xuyang2018.jy@cn.jujitsu.com> * - * This is a basic ioctl error test about loopdevice - * LOOP_SET_BLOCK_SIZE. + * This is a basic error test about the invalid block size of loopdevice + * by using LOOP_SET_BLOCK_SIZE or LOOP_CONFIGURE ioctl. */ #include <stdio.h> @@ -15,49 +15,89 @@ #include "tst_test.h" static char dev_path[1024]; -static int dev_num, dev_fd, attach_flag; +static int dev_num, dev_fd, file_fd, attach_flag, loop_configure_sup = 1; static unsigned int invalid_value, half_value, unalign_value; +static struct loop_config loopconfig; static struct tcase { unsigned int *setvalue; - int exp_err; + int ioctl_flag; char *message; } tcases[] = { - {&half_value, EINVAL, "arg < 512"}, - {&invalid_value, EINVAL, "arg > PAGE_SIZE"}, - {&unalign_value, EINVAL, "arg != power_of_2"}, + {&half_value, LOOP_SET_BLOCK_SIZE, + "Using LOOP_SET_BLOCK_SIZE with arg < 512"}, + + {&invalid_value, LOOP_SET_BLOCK_SIZE, + "Using LOOP_SET_BLOCK_SIZE with arg > PAGE_SIZE"}, + + {&unalign_value, LOOP_SET_BLOCK_SIZE, + "Using LOOP_SET_BLOCK_SIZE with arg != power_of_2"}, + + {&half_value, LOOP_CONFIGURE, + "Using LOOP_CONFIGURE with block_size < 512"}, + + {&invalid_value, LOOP_CONFIGURE, + "Using LOOP_CONFIGURE with block_size > PAGE_SIZE"}, + + {&unalign_value, LOOP_CONFIGURE, + "Using LOOP_CONFIGURE with block_size != power_of_2"}, }; static void verify_ioctl_loop(unsigned int n) +{ + if (tcases[n].ioctl_flag == LOOP_CONFIGURE) + TEST(ioctl(dev_fd, LOOP_CONFIGURE, &loopconfig)); + else + TEST(ioctl(dev_fd, LOOP_SET_BLOCK_SIZE, *(tcases[n].setvalue))); + + if (TST_RET == 0) { + tst_res(TFAIL, "Set block size succeed unexpectedly"); + if (tcases[n].ioctl_flag == LOOP_CONFIGURE) + TST_RETRY_FUNC(ioctl(dev_fd, LOOP_CLR_FD, 0), TST_RETVAL_EQ0); + return; + } + if (TST_ERR == EINVAL) + tst_res(TPASS | TTERRNO, "Set block size failed as expected"); + else + tst_res(TFAIL | TTERRNO, "Set block size failed expected EINVAL got"); +} + +static void run(unsigned int n) { struct tcase *tc = &tcases[n]; tst_res(TINFO, "%s", tc->message); - TEST(ioctl(dev_fd, LOOP_SET_BLOCK_SIZE, *(tc->setvalue))); - if (TST_RET == 0) { - tst_res(TFAIL, "LOOP_SET_BLOCK_SIZE succeed unexpectedly"); + if (tc->ioctl_flag == LOOP_SET_BLOCK_SIZE) { + if (!attach_flag) { + tst_attach_device(dev_path, "test.img"); + attach_flag = 1; + } + verify_ioctl_loop(n); return; } - if (TST_ERR == tc->exp_err) { - tst_res(TPASS | TTERRNO, "LOOP_SET_BLOCK_SIZE failed as expected"); - } else { - tst_res(TFAIL | TTERRNO, "LOOP_SET_BLOCK_SIZE failed expected %s got", - tst_strerrno(tc->exp_err)); + if (tc->ioctl_flag == LOOP_CONFIGURE && !loop_configure_sup) { + tst_res(TCONF, "LOOP_CONFIGURE ioctl not supported"); + return; } + if (attach_flag) { + tst_detach_device_by_fd(dev_path, dev_fd); + attach_flag = 0; + } + loopconfig.block_size = *(tc->setvalue); + verify_ioctl_loop(n); } static void setup(void) { unsigned int pg_size; + int ret; dev_num = tst_find_free_loopdev(dev_path, sizeof(dev_path)); if (dev_num < 0) tst_brk(TBROK, "Failed to find free loop device"); tst_fill_file("test.img", 0, 1024, 1024); - tst_attach_device(dev_path, "test.img"); - attach_flag = 1; half_value = 256; pg_size = getpagesize(); invalid_value = pg_size * 2 ; @@ -67,12 +107,24 @@ static void setup(void) if (ioctl(dev_fd, LOOP_SET_BLOCK_SIZE, 512) && errno == EINVAL) tst_brk(TCONF, "LOOP_SET_BLOCK_SIZE is not supported"); + + file_fd = SAFE_OPEN("test.img", O_RDWR); + loopconfig.fd = -1; + ret = ioctl(dev_fd, LOOP_CONFIGURE, &loopconfig); + if (ret && errno != EBADF) { + tst_res(TINFO | TERRNO, "LOOP_CONFIGURE is not supported"); + loop_configure_sup = 0; + return; + } + loopconfig.fd = file_fd; } static void cleanup(void) { if (dev_fd > 0) SAFE_CLOSE(dev_fd); + if (file_fd > 0) + SAFE_CLOSE(file_fd); if (attach_flag) tst_detach_device(dev_path); } @@ -80,7 +132,7 @@ static void cleanup(void) static struct tst_test test = { .setup = setup, .cleanup = cleanup, - .test = verify_ioctl_loop, + .test = run, .tcnt = ARRAY_SIZE(tcases), .needs_root = 1, .needs_tmpdir = 1, -- 2.23.0 ^ permalink raw reply related [flat|nested] 28+ messages in thread
* [LTP] [PATCH v3 2/2] syscalls/ioctl_loop05: Using LOOP_CONFIGURE to set direct io 2020-07-24 2:05 ` [LTP] [PATCH v3 " Yang Xu @ 2020-07-24 2:05 ` Yang Xu 2020-07-29 11:39 ` Cyril Hrubis 2020-07-29 12:58 ` Cyril Hrubis 2020-07-29 10:07 ` [LTP] [PATCH v3 1/2] syscalls/ioctl_loop06: Using LOOP_CONFIGURE to test invalid block size Cyril Hrubis 1 sibling, 2 replies; 28+ messages in thread From: Yang Xu @ 2020-07-24 2:05 UTC (permalink / raw) To: ltp Since kernel commit 3448914e8cc5("loop: Add LOOP_CONFIGURE ioctl"), it can explicitly request direct I/O mode by setting LO_FLAGS_DIRECT_IO in loop_config.info.lo_flags. Signed-off-by: Yang Xu <xuyang2018.jy@cn.fujitsu.com> --- v2->v3: 1.Use tst_detach_device_by_fd api .../kernel/syscalls/ioctl/ioctl_loop05.c | 151 +++++++++++++----- 1 file changed, 114 insertions(+), 37 deletions(-) diff --git a/testcases/kernel/syscalls/ioctl/ioctl_loop05.c b/testcases/kernel/syscalls/ioctl/ioctl_loop05.c index e3c14faab..7491e62fa 100644 --- a/testcases/kernel/syscalls/ioctl/ioctl_loop05.c +++ b/testcases/kernel/syscalls/ioctl/ioctl_loop05.c @@ -19,6 +19,9 @@ * enabled but falls back to buffered I/O later on. This is the case at least * for Btrfs. Because of that the test passes both with failure as well as * success with non-zero offset. + * + * Also use LOOP_CONFIGURE to test this by setting LO_FLAGS_DIRECT_IO + * in loop_config.info.lo_flags. */ #include <stdio.h> @@ -32,8 +35,36 @@ #define DIO_MESSAGE "In dio mode" #define NON_DIO_MESSAGE "In non dio mode" -static char dev_path[1024], sys_loop_diopath[1024], backing_file_path[1024];; +static char dev_path[1024], sys_loop_diopath[1024], backing_file_path[1024]; static int dev_num, dev_fd, block_devfd, attach_flag, logical_block_size; +static int file_fd, loop_configure_sup = 1; +static struct loop_config loopconfig; +static struct loop_info loopinfo; + +static struct tcase { + int multi; /*logical_block_size / 2 as unit */ + int dio_value; + int ioctl_flag; + char *message; +} tcases[] = { + {0, 1, LOOP_SET_DIRECT_IO, + "Using LOOP_SET_DIRET_IO without setting lo_offset or sizelimit"}, + + {2, 1, LOOP_SET_DIRECT_IO, + "Using LOOP_SET_DIRECT_IO With offset equal to logical_block_size"}, + + {1, 0, LOOP_SET_DIRECT_IO, + "Using LOOP_SET_DIRECT_IO with offset less than logical_block_size"}, + + {0, 1, LOOP_CONFIGURE, + "Using LOOP_CONFIGURE without setting lo_offset or sizelimit"}, + + {2, 1, LOOP_CONFIGURE, + "Using LOOP_CONFIGURE With offset equal to logical_block_size"}, + + {1, 0, LOOP_CONFIGURE, + "Using LOOP_CONFIGURE witg offset less than logical_block_size"}, +}; static void check_dio_value(int flag) { @@ -42,61 +73,91 @@ static void check_dio_value(int flag) memset(&loopinfoget, 0, sizeof(loopinfoget)); SAFE_IOCTL(dev_fd, LOOP_GET_STATUS, &loopinfoget); - tst_res(TINFO, "%s", flag ? DIO_MESSAGE : NON_DIO_MESSAGE); if (loopinfoget.lo_flags & LO_FLAGS_DIRECT_IO) - tst_res(flag ? TPASS : TFAIL, "lo_flags has LO_FLAGS_DIRECT_IO flag"); + tst_res(flag ? TPASS : TFAIL, + "%s, lo_flags has LO_FLAGS_DIRECT_IO flag", + flag ? DIO_MESSAGE : NON_DIO_MESSAGE); else - tst_res(flag ? TFAIL : TPASS, "lo_flags doesn't have LO_FLAGS_DIRECT_IO flag"); + tst_res(flag ? TFAIL : TPASS, + "%s, lo_flags doesn't have LO_FLAGS_DIRECT_IO flag", + flag ? DIO_MESSAGE : NON_DIO_MESSAGE); TST_ASSERT_INT(sys_loop_diopath, flag); } -static void verify_ioctl_loop(void) +static void verify_ioctl_loop(unsigned int n) { - struct loop_info loopinfo; - - memset(&loopinfo, 0, sizeof(loopinfo)); - TST_RETRY_FUNC(ioctl(dev_fd, LOOP_SET_STATUS, &loopinfo), TST_RETVAL_EQ0); + if (tcases[n].ioctl_flag == LOOP_SET_DIRECT_IO) { + TST_RETRY_FUNC(ioctl(dev_fd, LOOP_SET_STATUS, &loopinfo), TST_RETVAL_EQ0); + + TEST(ioctl(dev_fd, LOOP_SET_DIRECT_IO, 1)); + if (TST_RET == 0) { + if (tcases[n].dio_value) + tst_res(TPASS, "set direct io succeeded"); + else + tst_res(TPASS, "set direct io succeeded, offset is ignored"); + check_dio_value(1); + SAFE_IOCTL(dev_fd, LOOP_SET_DIRECT_IO, 0); + return; + } + if (TST_ERR == EINVAL && !tcases[n].dio_value) + tst_res(TPASS | TTERRNO, + "set direct io failed as expected"); + else + tst_res(TFAIL | TTERRNO, "set direct io failed"); + return; + } + /* + * When we call loop_configure ioctl successfully and detach it, + * the subquent loop_configure without non-zero lo_offset or + * sizelimit may trigger the blk_update_request I/O error. + * To avoid this, sleep 1s to ensure last blk_update_request has + * completed. + */ + sleep(1); + /* + * loop_cofigure calls loop_update_dio() function, it will ignore + * the result of setting dio. It is different from loop_set_dio. + */ + TST_RETRY_FUNC(ioctl(dev_fd, LOOP_CONFIGURE, &loopconfig), TST_RETVAL_EQ0); + check_dio_value(tcases[n].dio_value); + TST_RETRY_FUNC(ioctl(dev_fd, LOOP_CLR_FD, 0), TST_RETVAL_EQ0); +} - tst_res(TINFO, "Without setting lo_offset or sizelimit"); - SAFE_IOCTL(dev_fd, LOOP_SET_DIRECT_IO, 1); - check_dio_value(1); +static void run(unsigned int n) +{ + struct tcase *tc = &tcases[n]; - SAFE_IOCTL(dev_fd, LOOP_SET_DIRECT_IO, 0); - check_dio_value(0); + tst_res(TINFO, "%s", tc->message); - tst_res(TINFO, "With offset equal to logical_block_size"); - loopinfo.lo_offset = logical_block_size; - TST_RETRY_FUNC(ioctl(dev_fd, LOOP_SET_STATUS, &loopinfo), TST_RETVAL_EQ0); - TEST(ioctl(dev_fd, LOOP_SET_DIRECT_IO, 1)); - if (TST_RET == 0) { - tst_res(TPASS, "LOOP_SET_DIRECT_IO succeeded"); - check_dio_value(1); + if (tc->ioctl_flag == LOOP_SET_DIRECT_IO) { + if (!attach_flag) { + tst_attach_device(dev_path, "test.img"); + attach_flag = 1; + } SAFE_IOCTL(dev_fd, LOOP_SET_DIRECT_IO, 0); - } else { - tst_res(TFAIL | TTERRNO, "LOOP_SET_DIRECT_IO failed"); + check_dio_value(0); + loopinfo.lo_offset = logical_block_size * tc->multi / 2; + verify_ioctl_loop(n); + return; } - - tst_res(TINFO, "With nonzero offset less than logical_block_size"); - loopinfo.lo_offset = logical_block_size / 2; - TST_RETRY_FUNC(ioctl(dev_fd, LOOP_SET_STATUS, &loopinfo), TST_RETVAL_EQ0); - - TEST(ioctl(dev_fd, LOOP_SET_DIRECT_IO, 1)); - if (TST_RET == 0) { - tst_res(TPASS, "LOOP_SET_DIRECT_IO succeeded, offset is ignored"); - SAFE_IOCTL(dev_fd, LOOP_SET_DIRECT_IO, 0); + if (tc->ioctl_flag == LOOP_CONFIGURE && !loop_configure_sup) { + tst_res(TCONF, "LOOP_CONFIGURE ioctl not supported"); return; } - if (TST_ERR == EINVAL) - tst_res(TPASS | TTERRNO, "LOOP_SET_DIRECT_IO failed as expected"); - else - tst_res(TFAIL | TTERRNO, "LOOP_SET_DIRECT_IO failed expected EINVAL got"); + if (attach_flag) { + tst_detach_device_by_fd(dev_path, dev_fd); + attach_flag = 0; + } + loopconfig.info.lo_offset = logical_block_size * tc->multi / 2; + verify_ioctl_loop(n); } static void setup(void) { char bd_path[100]; + int ret; if (tst_fs_type(".") == TST_TMPFS_MAGIC) tst_brk(TCONF, "tmpfd doesn't support O_DIRECT flag"); @@ -128,8 +189,21 @@ static void setup(void) SAFE_IOCTL(block_devfd, BLKSSZGET, &logical_block_size); tst_res(TINFO, "backing dev(%s) logical_block_size is %d", bd_path, logical_block_size); SAFE_CLOSE(block_devfd); + if (logical_block_size > 512) TST_RETRY_FUNC(ioctl(dev_fd, LOOP_SET_BLOCK_SIZE, logical_block_size), TST_RETVAL_EQ0); + + file_fd = SAFE_OPEN("test.img", O_RDWR); + loopconfig.fd = -1; + ret = ioctl(dev_fd, LOOP_CONFIGURE, &loopconfig); + if (ret && errno != EBADF) { + tst_res(TINFO | TERRNO, "LOOP_CONFIGURE is not supported"); + loop_configure_sup = 0; + return; + } + loopconfig.block_size = logical_block_size; + loopconfig.fd = file_fd; + loopconfig.info.lo_flags = LO_FLAGS_DIRECT_IO; } static void cleanup(void) @@ -138,6 +212,8 @@ static void cleanup(void) SAFE_CLOSE(dev_fd); if (block_devfd > 0) SAFE_CLOSE(block_devfd); + if (file_fd > 0) + SAFE_CLOSE(file_fd); if (attach_flag) tst_detach_device(dev_path); } @@ -145,7 +221,8 @@ static void cleanup(void) static struct tst_test test = { .setup = setup, .cleanup = cleanup, - .test_all = verify_ioctl_loop, + .test = run, + .tcnt = ARRAY_SIZE(tcases), .needs_root = 1, .needs_tmpdir = 1, .needs_drivers = (const char *const []) { -- 2.23.0 ^ permalink raw reply related [flat|nested] 28+ messages in thread
* [LTP] [PATCH v3 2/2] syscalls/ioctl_loop05: Using LOOP_CONFIGURE to set direct io 2020-07-24 2:05 ` [LTP] [PATCH v3 2/2] syscalls/ioctl_loop05: Using LOOP_CONFIGURE to set direct io Yang Xu @ 2020-07-29 11:39 ` Cyril Hrubis 2020-07-30 8:49 ` Yang Xu 2020-07-29 12:58 ` Cyril Hrubis 1 sibling, 1 reply; 28+ messages in thread From: Cyril Hrubis @ 2020-07-29 11:39 UTC (permalink / raw) To: ltp Hi! I started look at this patch however the first thing I've found out is that our mountinfo parser is wrong. If you look at man 5 proc it says: 36 35 98:0 /mnt1 /mnt2 rw,noatime master:1 - ext3 /dev/root rw,errors=continue (1)(2)(3) (4) (5) (6) (7) (8) (9) (10) (11) (7) optional fields: zero or more fields of the form "tag[:value]"; see below. So we cannot really parse the information with a static scanf() string, since the number of elements in the line is not constant. And it does fail on some of the machines I do have here since there is no optional fields present. So I guess that we will have to write a parser that reads that information line by line after all. -- Cyril Hrubis chrubis@suse.cz ^ permalink raw reply [flat|nested] 28+ messages in thread
* [LTP] [PATCH v3 2/2] syscalls/ioctl_loop05: Using LOOP_CONFIGURE to set direct io 2020-07-29 11:39 ` Cyril Hrubis @ 2020-07-30 8:49 ` Yang Xu 2020-07-30 9:28 ` Cyril Hrubis 0 siblings, 1 reply; 28+ messages in thread From: Yang Xu @ 2020-07-30 8:49 UTC (permalink / raw) To: ltp HI Cyril > Hi! > I started look at this patch however the first thing I've found out is that > our mountinfo parser is wrong. If you look at man 5 proc it says: > > 36 35 98:0 /mnt1 /mnt2 rw,noatime master:1 - ext3 /dev/root rw,errors=continue > (1)(2)(3) (4) (5) (6) (7) (8) (9) (10) (11) > > > (7) optional fields: zero or more fields of the form > "tag[:value]"; see below. > > So we cannot really parse the information with a static scanf() string, > since the number of elements in the line is not constant. > > And it does fail on some of the machines I do have here since there is > no optional fields present. > > So I guess that we will have to write a parser that reads that > information line by line after all. I doubt how machies will have more or zero fields in (7). But I think you are right, How about using the (3) field and second to last field. Then we can avoid zero or more filed in (7). the code as below? diff --git a/lib/tst_device.c b/lib/tst_device.c index 8d8bc5b40..36d6666fe 100644 --- a/lib/tst_device.c +++ b/lib/tst_device.c @@ -497,16 +497,31 @@ unsigned long tst_dev_bytes_written(const char *dev) void tst_find_backing_dev(const char *path, char *dev) { - char fmt[1024]; + char fmt[20]; struct stat buf; + FILE *file; + char line[PATH_MAX]; + char *pre = NULL; + char *next = NULL; if (stat(path, &buf) < 0) tst_brkm(TWARN | TERRNO, NULL, "stat() failed"); - snprintf(fmt, sizeof(fmt), "%%*i %%*i %u:%u %%*s %%*s %%*s %%*s %%*s %%*s %%s %%*s", - major(buf.st_dev), minor(buf.st_dev)); + snprintf(fmt, sizeof(fmt), "%u:%u", major(buf.st_dev), minor(buf.st_dev)); + file = SAFE_FOPEN(NULL, "/proc/self/mountinfo", "r"); - SAFE_FILE_LINES_SCANF(NULL, "/proc/self/mountinfo", fmt, dev); + while (fgets(line, sizeof(line), file)) { + if (strstr(line, fmt) != NULL) { + pre = strtok_r(line, " ", &next); + while(pre != NULL) { + strcpy(dev, pre); + pre = strtok_r(NULL, " ", &next); + if (strlen(next) == 0) + break; + } + break; + } + } if (stat(dev, &buf) < 0) tst_brkm(TWARN | TERRNO, NULL, "stat(%s) failed", dev); > ^ permalink raw reply related [flat|nested] 28+ messages in thread
* [LTP] [PATCH v3 2/2] syscalls/ioctl_loop05: Using LOOP_CONFIGURE to set direct io 2020-07-30 8:49 ` Yang Xu @ 2020-07-30 9:28 ` Cyril Hrubis 2020-07-30 10:08 ` Yang Xu 0 siblings, 1 reply; 28+ messages in thread From: Cyril Hrubis @ 2020-07-30 9:28 UTC (permalink / raw) To: ltp Hi! > > So I guess that we will have to write a parser that reads that > > information line by line after all. > I doubt how machies will have more or zero fields in (7). But I think > you are right, Well that's what I do have here. > How about using the (3) field and second to last field. Then we can > avoid zero or more filed in (7). the code as below?? Actually looking into util-linux code it says that th the optional fields are terminated with " - ", see: https://git.kernel.org/pub/scm/utils/util-linux/util-linux.git/tree/libmount/src/tab_parse.c#n177 So I guess the safest option would be: * Match the line by major:minor as you do * Then strstr() for " - " should land us directly to field (8) -- Cyril Hrubis chrubis@suse.cz ^ permalink raw reply [flat|nested] 28+ messages in thread
* [LTP] [PATCH v3 2/2] syscalls/ioctl_loop05: Using LOOP_CONFIGURE to set direct io 2020-07-30 9:28 ` Cyril Hrubis @ 2020-07-30 10:08 ` Yang Xu 2020-07-30 10:38 ` Cyril Hrubis 0 siblings, 1 reply; 28+ messages in thread From: Yang Xu @ 2020-07-30 10:08 UTC (permalink / raw) To: ltp HI Cyril > Hi! >>> So I guess that we will have to write a parser that reads that >>> information line by line after all. >> I doubt how machies will have more or zero fields in (7). But I think >> you are right, > > Well that's what I do have here. > >> How about using the (3) field and second to last field. Then we can >> avoid zero or more filed in (7). the code as below?? > > Actually looking into util-linux code it says that th the optional > fields are terminated with " - ", see: > > https://git.kernel.org/pub/scm/utils/util-linux/util-linux.git/tree/libmount/src/tab_parse.c#n177 > > So I guess the safest option would be: > > * Match the line by major:minor as you do > * Then strstr() for " - " should land us directly to field (8) Yes, using " - " more easily and faster. code as below? index 8d8bc5b40..bdd93f19e 100644 --- a/lib/tst_device.c +++ b/lib/tst_device.c @@ -497,17 +497,30 @@ unsigned long tst_dev_bytes_written(const char *dev) void tst_find_backing_dev(const char *path, char *dev) { - char fmt[1024]; + char fmt[20]; struct stat buf; + FILE *file; + char line[PATH_MAX]; + char *pre = NULL; + char *next = NULL; if (stat(path, &buf) < 0) tst_brkm(TWARN | TERRNO, NULL, "stat() failed"); - snprintf(fmt, sizeof(fmt), "%%*i %%*i %u:%u %%*s %%*s %%*s %%*s %%*s %%*s %%s %%*s", - major(buf.st_dev), minor(buf.st_dev)); + snprintf(fmt, sizeof(fmt), "%u:%u", major(buf.st_dev), minor(buf.st_dev)); + file = SAFE_FOPEN(NULL, "/proc/self/mountinfo", "r"); - SAFE_FILE_LINES_SCANF(NULL, "/proc/self/mountinfo", fmt, dev); + while (fgets(line, sizeof(line), file)) { + if (strstr(line, fmt) != NULL) { + pre = strstr(line, " - "); + pre = strtok_r(pre, " ", &next); + pre = strtok_r(NULL, " ", &next); + pre = strtok_r(NULL, " ", &next); + strcpy(dev, pre); + } + } + SAFE_FCLOSE(NULL, file); if (stat(dev, &buf) < 0) tst_brkm(TWARN | TERRNO, NULL, "stat(%s) failed", dev); > ^ permalink raw reply related [flat|nested] 28+ messages in thread
* [LTP] [PATCH v3 2/2] syscalls/ioctl_loop05: Using LOOP_CONFIGURE to set direct io 2020-07-30 10:08 ` Yang Xu @ 2020-07-30 10:38 ` Cyril Hrubis 0 siblings, 0 replies; 28+ messages in thread From: Cyril Hrubis @ 2020-07-30 10:38 UTC (permalink / raw) To: ltp Hi! > index 8d8bc5b40..bdd93f19e 100644 > --- a/lib/tst_device.c > +++ b/lib/tst_device.c > @@ -497,17 +497,30 @@ unsigned long tst_dev_bytes_written(const char *dev) > > void tst_find_backing_dev(const char *path, char *dev) > { > - char fmt[1024]; > + char fmt[20]; > struct stat buf; > + FILE *file; > + char line[PATH_MAX]; > + char *pre = NULL; > + char *next = NULL; > > if (stat(path, &buf) < 0) > tst_brkm(TWARN | TERRNO, NULL, "stat() failed"); > > - snprintf(fmt, sizeof(fmt), "%%*i %%*i %u:%u %%*s %%*s %%*s %%*s > %%*s %%*s %%s %%*s", > - major(buf.st_dev), minor(buf.st_dev)); > + snprintf(fmt, sizeof(fmt), "%u:%u", major(buf.st_dev), > minor(buf.st_dev)); > + file = SAFE_FOPEN(NULL, "/proc/self/mountinfo", "r"); > > - SAFE_FILE_LINES_SCANF(NULL, "/proc/self/mountinfo", fmt, dev); > + while (fgets(line, sizeof(line), file)) { > + if (strstr(line, fmt) != NULL) { > + pre = strstr(line, " - "); > + pre = strtok_r(pre, " ", &next); > + pre = strtok_r(NULL, " ", &next); > + pre = strtok_r(NULL, " ", &next); > + strcpy(dev, pre); We should break; here as well, since we already found the result. > + } > + } > > + SAFE_FCLOSE(NULL, file); > if (stat(dev, &buf) < 0) > tst_brkm(TWARN | TERRNO, NULL, "stat(%s) failed", dev); Otherwise it looks good. -- Cyril Hrubis chrubis@suse.cz ^ permalink raw reply [flat|nested] 28+ messages in thread
* [LTP] [PATCH v3 2/2] syscalls/ioctl_loop05: Using LOOP_CONFIGURE to set direct io 2020-07-24 2:05 ` [LTP] [PATCH v3 2/2] syscalls/ioctl_loop05: Using LOOP_CONFIGURE to set direct io Yang Xu 2020-07-29 11:39 ` Cyril Hrubis @ 2020-07-29 12:58 ` Cyril Hrubis 1 sibling, 0 replies; 28+ messages in thread From: Cyril Hrubis @ 2020-07-29 12:58 UTC (permalink / raw) To: ltp Hi! > + /* > + * When we call loop_configure ioctl successfully and detach it, > + * the subquent loop_configure without non-zero lo_offset or > + * sizelimit may trigger the blk_update_request I/O error. > + * To avoid this, sleep 1s to ensure last blk_update_request has > + * completed. > + */ > + sleep(1); This sounds to me like a kernel bug. Have you tried asking kernel developers if this is expected behavior before we attempt work around the problem in tests? -- Cyril Hrubis chrubis@suse.cz ^ permalink raw reply [flat|nested] 28+ messages in thread
* [LTP] [PATCH v3 1/2] syscalls/ioctl_loop06: Using LOOP_CONFIGURE to test invalid block size 2020-07-24 2:05 ` [LTP] [PATCH v3 " Yang Xu 2020-07-24 2:05 ` [LTP] [PATCH v3 2/2] syscalls/ioctl_loop05: Using LOOP_CONFIGURE to set direct io Yang Xu @ 2020-07-29 10:07 ` Cyril Hrubis 2020-07-29 10:43 ` Yang Xu 1 sibling, 1 reply; 28+ messages in thread From: Cyril Hrubis @ 2020-07-29 10:07 UTC (permalink / raw) To: ltp Hi! > static void verify_ioctl_loop(unsigned int n) > +{ > + if (tcases[n].ioctl_flag == LOOP_CONFIGURE) > + TEST(ioctl(dev_fd, LOOP_CONFIGURE, &loopconfig)); > + else > + TEST(ioctl(dev_fd, LOOP_SET_BLOCK_SIZE, *(tcases[n].setvalue))); > + > + if (TST_RET == 0) { > + tst_res(TFAIL, "Set block size succeed unexpectedly"); > + if (tcases[n].ioctl_flag == LOOP_CONFIGURE) > + TST_RETRY_FUNC(ioctl(dev_fd, LOOP_CLR_FD, 0), TST_RETVAL_EQ0); I guess that we can use the tst_detach_device_by_fd() here as well right? If you agree with that change I will change this and push the patch. -- Cyril Hrubis chrubis@suse.cz ^ permalink raw reply [flat|nested] 28+ messages in thread
* [LTP] [PATCH v3 1/2] syscalls/ioctl_loop06: Using LOOP_CONFIGURE to test invalid block size 2020-07-29 10:07 ` [LTP] [PATCH v3 1/2] syscalls/ioctl_loop06: Using LOOP_CONFIGURE to test invalid block size Cyril Hrubis @ 2020-07-29 10:43 ` Yang Xu 2020-07-31 14:15 ` Cyril Hrubis 0 siblings, 1 reply; 28+ messages in thread From: Yang Xu @ 2020-07-29 10:43 UTC (permalink / raw) To: ltp Hi Cyril > Hi! >> static void verify_ioctl_loop(unsigned int n) >> +{ >> + if (tcases[n].ioctl_flag == LOOP_CONFIGURE) >> + TEST(ioctl(dev_fd, LOOP_CONFIGURE, &loopconfig)); >> + else >> + TEST(ioctl(dev_fd, LOOP_SET_BLOCK_SIZE, *(tcases[n].setvalue))); >> + >> + if (TST_RET == 0) { >> + tst_res(TFAIL, "Set block size succeed unexpectedly"); >> + if (tcases[n].ioctl_flag == LOOP_CONFIGURE) >> + TST_RETRY_FUNC(ioctl(dev_fd, LOOP_CLR_FD, 0), TST_RETVAL_EQ0); > > I guess that we can use the tst_detach_device_by_fd() here as well > right? > > If you agree with that change I will change this and push the patch. Agree. > ^ permalink raw reply [flat|nested] 28+ messages in thread
* [LTP] [PATCH v3 1/2] syscalls/ioctl_loop06: Using LOOP_CONFIGURE to test invalid block size 2020-07-29 10:43 ` Yang Xu @ 2020-07-31 14:15 ` Cyril Hrubis 0 siblings, 0 replies; 28+ messages in thread From: Cyril Hrubis @ 2020-07-31 14:15 UTC (permalink / raw) To: ltp Hi! Pushed, thanks. -- Cyril Hrubis chrubis@suse.cz ^ permalink raw reply [flat|nested] 28+ messages in thread
* [LTP] [PATCH v1 0/4] *** Add LOOP_CONFIGURE ioctl test *** 2020-06-11 10:35 [LTP] [PATCH v1 0/4] *** Add LOOP_CONFIGURE ioctl test *** Yang Xu ` (3 preceding siblings ...) 2020-06-11 10:35 ` [LTP] [PATCH v1 4/4] syscalls/ioctl_loop09: Add LOOP_CONFIGURE ioctl test with direct I/O flag Yang Xu @ 2020-07-06 1:45 ` Yang Xu 4 siblings, 0 replies; 28+ messages in thread From: Yang Xu @ 2020-07-06 1:45 UTC (permalink / raw) To: ltp Hi ping. > Since kernel commit[1], it has added LOOP_CONFIGURE ioctl test. > From this commit, loop_set_fd calls loop_configure with zero > loop_config. > > struct loop_config { > __u32 fd; > __u32 block_size; > struct loop_info64 info; > __u64 __reserved[8]; > } > > In addition to doing what LOOP_SET_STATUS can do, LOOP_CONFIGURE can > also be used to: > - Set the correct block size immediately by setting > loop_config.block_size (I test this in ioctl_loop08.c, like old > ioctl_loop06.c) > - Explicitly request direct I/O mode by setting LO_FLAGS_DIRECT_IO > in loop_config.info.lo_flags (I test this in ioctl_loop09.c, like old > ioctl_loop05.c) > - Explicitly request read-only mode by setting LO_FLAGS_READ_ONLY > in loop_config.info.lo_flags (I test this in old ioctl_loop02.c) > > > [1]https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=3448914e8cc550ba792d4ccc74471d1ca4293a > > Yang Xu (4): > lapi: Add fallback for LOOP_CONFIGURE ioctl and struct loop_config > syscalls/ioctl_loop02: Using LOOP_CONFIGURE to set read_only > syscalls/ioctl_loop08: Add LOOP_CONFIGURE error test with invalid > block size > syscalls/ioctl_loop09: Add LOOP_CONFIGURE ioctl test with direct I/O > flag > > configure.ac | 1 + > include/lapi/loop.h | 23 +++ > runtest/syscalls | 2 + > testcases/kernel/syscalls/ioctl/.gitignore | 2 + > .../kernel/syscalls/ioctl/ioctl_loop02.c | 53 ++++-- > .../kernel/syscalls/ioctl/ioctl_loop08.c | 101 ++++++++++++ > .../kernel/syscalls/ioctl/ioctl_loop09.c | 151 ++++++++++++++++++ > 7 files changed, 324 insertions(+), 9 deletions(-) > create mode 100644 testcases/kernel/syscalls/ioctl/ioctl_loop08.c > create mode 100644 testcases/kernel/syscalls/ioctl/ioctl_loop09.c > ^ permalink raw reply [flat|nested] 28+ messages in thread
end of thread, other threads:[~2020-07-31 14:15 UTC | newest] Thread overview: 28+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2020-06-11 10:35 [LTP] [PATCH v1 0/4] *** Add LOOP_CONFIGURE ioctl test *** Yang Xu 2020-06-11 10:35 ` [LTP] [PATCH v1 1/4] lapi: Add fallback for LOOP_CONFIGURE ioctl and struct loop_config Yang Xu 2020-07-08 13:18 ` Cyril Hrubis 2020-06-11 10:35 ` [LTP] [PATCH v1 2/4] syscalls/ioctl_loop02: Using LOOP_CONFIGURE to set read_only Yang Xu 2020-07-08 13:15 ` Cyril Hrubis 2020-06-11 10:35 ` [LTP] [PATCH v1 3/4] syscalls/ioctl_loop08: Add LOOP_CONFIGURE error test with invalid block size Yang Xu 2020-07-08 14:00 ` Cyril Hrubis 2020-06-11 10:35 ` [LTP] [PATCH v1 4/4] syscalls/ioctl_loop09: Add LOOP_CONFIGURE ioctl test with direct I/O flag Yang Xu 2020-07-08 14:00 ` Cyril Hrubis 2020-07-10 6:39 ` [LTP] [PATCH v2 1/2] syscalls/ioctl_loop06: Using LOOP_CONFIGURE to test invalid block size Yang Xu 2020-07-10 6:39 ` [LTP] [PATCH v2 2/2] syscalls/ioctl_loop05: Using LOOP_CONFIGURE to set direct io Yang Xu 2020-07-30 7:28 ` Yang Xu 2020-07-22 9:45 ` [LTP] [PATCH v2 1/2] syscalls/ioctl_loop06: Using LOOP_CONFIGURE to test invalid block size Cyril Hrubis 2020-07-22 10:15 ` Yang Xu 2020-07-22 12:59 ` Cyril Hrubis 2020-07-23 9:41 ` Yang Xu 2020-07-24 2:05 ` [LTP] [PATCH v3 " Yang Xu 2020-07-24 2:05 ` [LTP] [PATCH v3 2/2] syscalls/ioctl_loop05: Using LOOP_CONFIGURE to set direct io Yang Xu 2020-07-29 11:39 ` Cyril Hrubis 2020-07-30 8:49 ` Yang Xu 2020-07-30 9:28 ` Cyril Hrubis 2020-07-30 10:08 ` Yang Xu 2020-07-30 10:38 ` Cyril Hrubis 2020-07-29 12:58 ` Cyril Hrubis 2020-07-29 10:07 ` [LTP] [PATCH v3 1/2] syscalls/ioctl_loop06: Using LOOP_CONFIGURE to test invalid block size Cyril Hrubis 2020-07-29 10:43 ` Yang Xu 2020-07-31 14:15 ` Cyril Hrubis 2020-07-06 1:45 ` [LTP] [PATCH v1 0/4] *** Add LOOP_CONFIGURE ioctl test *** Yang Xu
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox