Skip to content

Commit 93da53e

Browse files
xuyang0410metan-ucw
authored andcommitted
syscalls/ioctl_loop05: Add LOOP_SET_DIRECT_IO ioctl test
LOOP_SET_DIRECT_IO can update a live loop device dio mode. It needs the backing file also supports dio mode and the lo_offset is aligned with the logical block size as returned by BLKSSZGET ioctl. It was introduced into kernel since 4.10 commit ab1cb278bc70 ("block: loop: introduce ioctl command of LOOP_SET_DIRECT_IO"). Signed-off-by: Yang Xu <[email protected]> Reviewed-by: Cyril Hrubis <[email protected]>
1 parent 308fc16 commit 93da53e

File tree

3 files changed

+129
-0
lines changed

3 files changed

+129
-0
lines changed

runtest/syscalls

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -533,6 +533,7 @@ ioctl_loop01 ioctl_loop01
533533
ioctl_loop02 ioctl_loop02
534534
ioctl_loop03 ioctl_loop03
535535
ioctl_loop04 ioctl_loop04
536+
ioctl_loop05 ioctl_loop05
536537

537538
ioctl_ns01 ioctl_ns01
538539
ioctl_ns02 ioctl_ns02

testcases/kernel/syscalls/ioctl/.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
/ioctl_loop02
1111
/ioctl_loop03
1212
/ioctl_loop04
13+
/ioctl_loop05
1314
/ioctl_ns01
1415
/ioctl_ns02
1516
/ioctl_ns03
Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
// SPDX-License-Identifier: GPL-2.0-or-later
2+
/*
3+
* Copyright (c) 2020 FUJITSU LIMITED. All rights reserved.
4+
* Author: Yang Xu <[email protected]>
5+
*
6+
* This is a basic ioctl test about loopdevice.
7+
*
8+
* It is designed to test LOOP_SET_DIRECT_IO can updata a live
9+
* loop device dio mode. It need the backing file also supports
10+
* dio mode and the lo_offset is aligned with the logical block size.
11+
*/
12+
#include <stdio.h>
13+
#include <unistd.h>
14+
#include <string.h>
15+
#include <stdlib.h>
16+
#include <sys/mount.h>
17+
#include "lapi/loop.h"
18+
#include "tst_test.h"
19+
20+
#define DIO_MESSAGE "In dio mode"
21+
#define NON_DIO_MESSAGE "In non dio mode"
22+
23+
static char dev_path[1024], sys_loop_diopath[1024];
24+
static int dev_num, dev_fd, attach_flag, logical_block_size;
25+
26+
static void check_dio_value(int flag)
27+
{
28+
struct loop_info loopinfoget;
29+
30+
memset(&loopinfoget, 0, sizeof(loopinfoget));
31+
32+
SAFE_IOCTL(dev_fd, LOOP_GET_STATUS, &loopinfoget);
33+
tst_res(TINFO, "%s", flag ? DIO_MESSAGE : NON_DIO_MESSAGE);
34+
35+
if (loopinfoget.lo_flags & LO_FLAGS_DIRECT_IO)
36+
tst_res(flag ? TPASS : TFAIL, "lo_flags has LO_FLAGS_DIRECT_IO flag");
37+
else
38+
tst_res(flag ? TFAIL : TPASS, "lo_flags doesn't have LO_FLAGS_DIRECT_IO flag");
39+
40+
TST_ASSERT_INT(sys_loop_diopath, flag);
41+
}
42+
43+
static void verify_ioctl_loop(void)
44+
{
45+
struct loop_info loopinfo;
46+
47+
memset(&loopinfo, 0, sizeof(loopinfo));
48+
49+
tst_res(TINFO, "Without setting lo_offset or sizelimit");
50+
SAFE_IOCTL(dev_fd, LOOP_SET_DIRECT_IO, 1);
51+
check_dio_value(1);
52+
53+
SAFE_IOCTL(dev_fd, LOOP_SET_DIRECT_IO, 0);
54+
check_dio_value(0);
55+
56+
tst_res(TINFO, "With offset equal to logical_block_size");
57+
loopinfo.lo_offset = logical_block_size;
58+
TST_RETRY_FUNC(ioctl(dev_fd, LOOP_SET_STATUS, &loopinfo), TST_RETVAL_EQ0);
59+
TEST(ioctl(dev_fd, LOOP_SET_DIRECT_IO, 1));
60+
if (TST_RET == 0) {
61+
tst_res(TPASS, "LOOP_SET_DIRECT_IO succeeded");
62+
check_dio_value(1);
63+
SAFE_IOCTL(dev_fd, LOOP_SET_DIRECT_IO, 0);
64+
} else {
65+
tst_res(TFAIL | TTERRNO, "LOOP_SET_DIRECT_IO failed");
66+
}
67+
68+
tst_res(TINFO, "With nonzero offset less than logical_block_size");
69+
loopinfo.lo_offset = logical_block_size / 2;
70+
TST_RETRY_FUNC(ioctl(dev_fd, LOOP_SET_STATUS, &loopinfo), TST_RETVAL_EQ0);
71+
72+
TEST(ioctl(dev_fd, LOOP_SET_DIRECT_IO, 1));
73+
if (TST_RET == 0) {
74+
tst_res(TFAIL, "LOOP_SET_DIRECT_IO succeeded unexpectedly");
75+
SAFE_IOCTL(dev_fd, LOOP_SET_DIRECT_IO, 0);
76+
return;
77+
}
78+
if (TST_ERR == EINVAL)
79+
tst_res(TPASS | TTERRNO, "LOOP_SET_DIRECT_IO failed as expected");
80+
else
81+
tst_res(TFAIL | TTERRNO, "LOOP_SET_DIRECT_IO failed expected EINVAL got");
82+
83+
loopinfo.lo_offset = 0;
84+
TST_RETRY_FUNC(ioctl(dev_fd, LOOP_SET_STATUS, &loopinfo), TST_RETVAL_EQ0);
85+
}
86+
87+
static void setup(void)
88+
{
89+
if (tst_fs_type(".") == TST_TMPFS_MAGIC)
90+
tst_brk(TCONF, "tmpfd doesn't support O_DIRECT flag");
91+
92+
dev_num = tst_find_free_loopdev(dev_path, sizeof(dev_path));
93+
if (dev_num < 0)
94+
tst_brk(TBROK, "Failed to find free loop device");
95+
96+
sprintf(sys_loop_diopath, "/sys/block/loop%d/loop/dio", dev_num);
97+
tst_fill_file("test.img", 0, 1024, 1024);
98+
tst_attach_device(dev_path, "test.img");
99+
attach_flag = 1;
100+
dev_fd = SAFE_OPEN(dev_path, O_RDWR);
101+
102+
if (ioctl(dev_fd, LOOP_SET_DIRECT_IO, 0) && errno == EINVAL)
103+
tst_brk(TCONF, "LOOP_SET_DIRECT_IO is not supported");
104+
105+
SAFE_IOCTL(dev_fd, BLKSSZGET, &logical_block_size);
106+
tst_res(TINFO, "%s default logical_block_size is %d", dev_path, logical_block_size);
107+
}
108+
109+
static void cleanup(void)
110+
{
111+
if (dev_fd > 0)
112+
SAFE_CLOSE(dev_fd);
113+
if (attach_flag)
114+
tst_detach_device(dev_path);
115+
}
116+
117+
static struct tst_test test = {
118+
.setup = setup,
119+
.cleanup = cleanup,
120+
.test_all = verify_ioctl_loop,
121+
.needs_root = 1,
122+
.needs_tmpdir = 1,
123+
.needs_drivers = (const char *const []) {
124+
"loop",
125+
NULL
126+
}
127+
};

0 commit comments

Comments
 (0)