Skip to content

Commit 5dfa37c

Browse files
xuyang0410metan-ucw
authored andcommitted
syscalls/ioctl_loop02: Add LO_FLAGS_READ_ONLY and LOOP_CHANGE_FD test
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. Signed-off-by: Yang Xu <[email protected]> Signed-off-by: Cyril Hrubis <[email protected]>
1 parent 4f3ff1f commit 5dfa37c

File tree

3 files changed

+134
-0
lines changed

3 files changed

+134
-0
lines changed

runtest/syscalls

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -530,6 +530,7 @@ ioctl07 ioctl07
530530
ioctl08 ioctl08
531531

532532
ioctl_loop01 ioctl_loop01
533+
ioctl_loop02 ioctl_loop02
533534

534535
ioctl_ns01 ioctl_ns01
535536
ioctl_ns02 ioctl_ns02

testcases/kernel/syscalls/ioctl/.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
/ioctl07
88
/ioctl08
99
/ioctl_loop01
10+
/ioctl_loop02
1011
/ioctl_ns01
1112
/ioctl_ns02
1213
/ioctl_ns03
Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
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 LO_FLAGS_READ_ONLY (similar as losetup -r)
9+
* and LOOP_CHANGE_FD.
10+
*
11+
* For LOOP_CHANGE_FD, this operation is possible only if the loop device
12+
* is read-only and the new backing store is the same size and type as the
13+
* old backing store.
14+
*/
15+
16+
#include <stdio.h>
17+
#include <unistd.h>
18+
#include <string.h>
19+
#include <stdlib.h>
20+
#include "lapi/loop.h"
21+
#include "tst_test.h"
22+
23+
static int file_fd, file_change_fd, file_fd_invalid;
24+
static char backing_path[1024], backing_file_path[1024], backing_file_change_path[1024];
25+
static int attach_flag, dev_fd, file_fd;
26+
static char loop_ro_path[1024], dev_path[1024];
27+
28+
static void verify_ioctl_loop(void)
29+
{
30+
struct loop_info loopinfoget;
31+
32+
dev_fd = SAFE_OPEN(dev_path, O_RDWR);
33+
SAFE_IOCTL(dev_fd, LOOP_SET_FD, file_fd);
34+
attach_flag = 1;
35+
36+
TST_ASSERT_INT(loop_ro_path, 1);
37+
TST_ASSERT_STR(backing_path, backing_file_path);
38+
39+
memset(&loopinfoget, 0, sizeof(loopinfoget));
40+
41+
/*
42+
* In drivers/block/loop.c code, set status function doesn't handle
43+
* LO_FLAGS_READ_ONLY flag and ignore it. Only loop_set_fd with readonly
44+
* mode, lo_flags will include LO_FLAGS_READ_ONLY.
45+
*/
46+
SAFE_IOCTL(dev_fd, LOOP_GET_STATUS, &loopinfoget);
47+
48+
if (loopinfoget.lo_flags & ~LO_FLAGS_READ_ONLY)
49+
tst_res(TFAIL, "lo_flags has unexpected %d flag", loopinfoget.lo_flags);
50+
else
51+
tst_res(TPASS, "lo_flags only has default LO_FLAGS_READ_ONLY flag");
52+
53+
TEST(write(dev_fd, "xx", 2));
54+
if (TST_RET != -1)
55+
tst_res(TFAIL, "write succeed unexpectedly");
56+
else
57+
tst_res(TPASS | TTERRNO, "Can not write data in RO mode");
58+
59+
TEST(ioctl(dev_fd, LOOP_CHANGE_FD, file_change_fd));
60+
if (TST_RET) {
61+
tst_res(TFAIL | TTERRNO, "LOOP_CHANGE_FD failed");
62+
} else {
63+
tst_res(TPASS, "LOOP_CHANGE_FD succeeded");
64+
TST_ASSERT_INT(loop_ro_path, 1);
65+
TST_ASSERT_STR(backing_path, backing_file_change_path);
66+
}
67+
68+
TEST(ioctl(dev_fd, LOOP_CHANGE_FD, file_fd_invalid));
69+
if (TST_RET) {
70+
if (TST_ERR == EINVAL)
71+
tst_res(TPASS | TTERRNO, "LOOP_CHANGE_FD failed as expected");
72+
else
73+
tst_res(TFAIL | TTERRNO, "LOOP_CHANGE_FD failed expected EINVAL got");
74+
} else {
75+
tst_res(TFAIL, "LOOP_CHANGE_FD succeeded");
76+
}
77+
78+
SAFE_CLOSE(dev_fd);
79+
tst_detach_device(dev_path);
80+
attach_flag = 0;
81+
}
82+
83+
static void setup(void)
84+
{
85+
int dev_num;
86+
87+
char *tmpdir = tst_get_tmpdir();
88+
dev_num = tst_find_free_loopdev(dev_path, sizeof(dev_path));
89+
if (dev_num < 0)
90+
tst_brk(TBROK, "Failed to find free loop device");
91+
92+
tst_fill_file("test.img", 0, 1024, 10);
93+
tst_fill_file("test1.img", 0, 1024, 10);
94+
tst_fill_file("test2.img", 0, 2048, 20);
95+
96+
sprintf(backing_path, "/sys/block/loop%d/loop/backing_file", dev_num);
97+
sprintf(backing_file_path, "%s/test.img", tmpdir);
98+
sprintf(backing_file_change_path, "%s/test1.img", tmpdir);
99+
sprintf(loop_ro_path, "/sys/block/loop%d/ro", dev_num);
100+
101+
free(tmpdir);
102+
103+
file_fd = SAFE_OPEN("test.img", O_RDONLY);
104+
file_change_fd = SAFE_OPEN("test1.img", O_RDWR);
105+
file_fd_invalid = SAFE_OPEN("test2.img", O_RDWR);
106+
}
107+
108+
static void cleanup(void)
109+
{
110+
if (dev_fd > 0)
111+
SAFE_CLOSE(dev_fd);
112+
if (file_fd > 0)
113+
SAFE_CLOSE(file_fd);
114+
if (file_change_fd > 0)
115+
SAFE_CLOSE(file_change_fd);
116+
if (file_fd_invalid > 0)
117+
SAFE_CLOSE(file_fd_invalid);
118+
if (attach_flag)
119+
tst_detach_device(dev_path);
120+
}
121+
122+
static struct tst_test test = {
123+
.setup = setup,
124+
.cleanup = cleanup,
125+
.test_all = verify_ioctl_loop,
126+
.needs_root = 1,
127+
.needs_tmpdir = 1,
128+
.needs_drivers = (const char *const []) {
129+
"loop",
130+
NULL
131+
}
132+
};

0 commit comments

Comments
 (0)