diff mbox series

[v2,1/2] syscalls/ioctl_loop06: Using LOOP_CONFIGURE to test invalid block size

Message ID 1594363189-20972-1-git-send-email-xuyang2018.jy@cn.fujitsu.com
State Superseded
Headers show
Series [v2,1/2] syscalls/ioctl_loop06: Using LOOP_CONFIGURE to test invalid block size | expand

Commit Message

Yang Xu July 10, 2020, 6:39 a.m. UTC
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(-)

Comments

Cyril Hrubis July 22, 2020, 9:45 a.m. UTC | #1
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;
Yang Xu July 22, 2020, 10:15 a.m. UTC | #2
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;
>
Cyril Hrubis July 22, 2020, 12:59 p.m. UTC | #3
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.
Yang Xu July 23, 2020, 9:41 a.m. UTC | #4
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?
>
diff mbox series

Patch

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,