1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3 * Copyright (c) 2020 FUJITSU LIMITED. All rights reserved.
4 * Author: Yang Xu <xuyang2018.jy@cn.jujitsu.com>
5 *
6 * This is a basic ioctl error test about loopdevice
7 * LOOP_SET_BLOCK_SIZE.
8 */
9
10 #include <stdio.h>
11 #include <unistd.h>
12 #include <sys/types.h>
13 #include <stdlib.h>
14 #include "lapi/loop.h"
15 #include "tst_test.h"
16
17 static char dev_path[1024];
18 static int dev_num, dev_fd, attach_flag;
19 static unsigned int invalid_value, half_value, unalign_value;
20
21 static struct tcase {
22 unsigned int *setvalue;
23 int exp_err;
24 char *message;
25 } tcases[] = {
26 {&half_value, EINVAL, "arg < 512"},
27 {&invalid_value, EINVAL, "arg > PAGE_SIZE"},
28 {&unalign_value, EINVAL, "arg != power_of_2"},
29 };
30
verify_ioctl_loop(unsigned int n)31 static void verify_ioctl_loop(unsigned int n)
32 {
33 struct tcase *tc = &tcases[n];
34
35 tst_res(TINFO, "%s", tc->message);
36 TEST(ioctl(dev_fd, LOOP_SET_BLOCK_SIZE, *(tc->setvalue)));
37 if (TST_RET == 0) {
38 tst_res(TFAIL, "LOOP_SET_BLOCK_SIZE succeed unexpectedly");
39 return;
40 }
41
42 if (TST_ERR == tc->exp_err) {
43 tst_res(TPASS | TTERRNO, "LOOP_SET_BLOCK_SIZE failed as expected");
44 } else {
45 tst_res(TFAIL | TTERRNO, "LOOP_SET_BLOCK_SIZE failed expected %s got",
46 tst_strerrno(tc->exp_err));
47 }
48 }
49
setup(void)50 static void setup(void)
51 {
52 unsigned int pg_size;
53
54 dev_num = tst_find_free_loopdev(dev_path, sizeof(dev_path));
55 if (dev_num < 0)
56 tst_brk(TBROK, "Failed to find free loop device");
57
58 tst_fill_file("test.img", 0, 1024, 1024);
59 tst_attach_device(dev_path, "test.img");
60 attach_flag = 1;
61 half_value = 256;
62 pg_size = getpagesize();
63 invalid_value = pg_size * 2 ;
64 unalign_value = pg_size - 1;
65
66 dev_fd = SAFE_OPEN(dev_path, O_RDWR);
67
68 if (ioctl(dev_fd, LOOP_SET_BLOCK_SIZE, 512) && errno == EINVAL)
69 tst_brk(TCONF, "LOOP_SET_BLOCK_SIZE is not supported");
70 }
71
cleanup(void)72 static void cleanup(void)
73 {
74 if (dev_fd > 0)
75 SAFE_CLOSE(dev_fd);
76 if (attach_flag)
77 tst_detach_device(dev_path);
78 }
79
80 static struct tst_test test = {
81 .setup = setup,
82 .cleanup = cleanup,
83 .test = verify_ioctl_loop,
84 .tcnt = ARRAY_SIZE(tcases),
85 .needs_root = 1,
86 .needs_tmpdir = 1,
87 .needs_drivers = (const char *const []) {
88 "loop",
89 NULL
90 }
91 };
92