1f08c3bdfSopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 2f08c3bdfSopenharmony_ci/* 3f08c3bdfSopenharmony_ci * Copyright (c) 2020 FUJITSU LIMITED. All rights reserved. 4f08c3bdfSopenharmony_ci * Copyright (c) Linux Test Project, 2022 5f08c3bdfSopenharmony_ci * Author: Yang Xu <xuyang2018.jy@cn.jujitsu.com> 6f08c3bdfSopenharmony_ci */ 7f08c3bdfSopenharmony_ci 8f08c3bdfSopenharmony_ci/*\ 9f08c3bdfSopenharmony_ci * [Description] 10f08c3bdfSopenharmony_ci * 11f08c3bdfSopenharmony_ci * Tests invalid block size of loopdevice by using ioctl() with 12f08c3bdfSopenharmony_ci * LOOP_SET_BLOCK_SIZE and LOOP_CONFIGURE flags. 13f08c3bdfSopenharmony_ci */ 14f08c3bdfSopenharmony_ci 15f08c3bdfSopenharmony_ci#include <stdio.h> 16f08c3bdfSopenharmony_ci#include <unistd.h> 17f08c3bdfSopenharmony_ci#include <sys/types.h> 18f08c3bdfSopenharmony_ci#include <stdlib.h> 19f08c3bdfSopenharmony_ci#include "lapi/loop.h" 20f08c3bdfSopenharmony_ci#include "tst_test.h" 21f08c3bdfSopenharmony_ci 22f08c3bdfSopenharmony_cistatic char dev_path[1024]; 23f08c3bdfSopenharmony_cistatic int dev_num, dev_fd, file_fd, attach_flag, loop_configure_sup = 1; 24f08c3bdfSopenharmony_cistatic unsigned int invalid_value, half_value, unalign_value; 25f08c3bdfSopenharmony_cistatic struct loop_config loopconfig; 26f08c3bdfSopenharmony_ci 27f08c3bdfSopenharmony_cistatic struct tcase { 28f08c3bdfSopenharmony_ci unsigned int *setvalue; 29f08c3bdfSopenharmony_ci int ioctl_flag; 30f08c3bdfSopenharmony_ci char *message; 31f08c3bdfSopenharmony_ci} tcases[] = { 32f08c3bdfSopenharmony_ci {&half_value, LOOP_SET_BLOCK_SIZE, 33f08c3bdfSopenharmony_ci "Using LOOP_SET_BLOCK_SIZE with arg < 512"}, 34f08c3bdfSopenharmony_ci 35f08c3bdfSopenharmony_ci {&invalid_value, LOOP_SET_BLOCK_SIZE, 36f08c3bdfSopenharmony_ci "Using LOOP_SET_BLOCK_SIZE with arg > PAGE_SIZE"}, 37f08c3bdfSopenharmony_ci 38f08c3bdfSopenharmony_ci {&unalign_value, LOOP_SET_BLOCK_SIZE, 39f08c3bdfSopenharmony_ci "Using LOOP_SET_BLOCK_SIZE with arg != power_of_2"}, 40f08c3bdfSopenharmony_ci 41f08c3bdfSopenharmony_ci {&half_value, LOOP_CONFIGURE, 42f08c3bdfSopenharmony_ci "Using LOOP_CONFIGURE with block_size < 512"}, 43f08c3bdfSopenharmony_ci 44f08c3bdfSopenharmony_ci {&invalid_value, LOOP_CONFIGURE, 45f08c3bdfSopenharmony_ci "Using LOOP_CONFIGURE with block_size > PAGE_SIZE"}, 46f08c3bdfSopenharmony_ci 47f08c3bdfSopenharmony_ci {&unalign_value, LOOP_CONFIGURE, 48f08c3bdfSopenharmony_ci "Using LOOP_CONFIGURE with block_size != power_of_2"}, 49f08c3bdfSopenharmony_ci}; 50f08c3bdfSopenharmony_ci 51f08c3bdfSopenharmony_cistatic void verify_ioctl_loop(unsigned int n) 52f08c3bdfSopenharmony_ci{ 53f08c3bdfSopenharmony_ci if (tcases[n].ioctl_flag == LOOP_CONFIGURE) 54f08c3bdfSopenharmony_ci TEST(ioctl(dev_fd, LOOP_CONFIGURE, &loopconfig)); 55f08c3bdfSopenharmony_ci else 56f08c3bdfSopenharmony_ci TEST(ioctl(dev_fd, LOOP_SET_BLOCK_SIZE, *(tcases[n].setvalue))); 57f08c3bdfSopenharmony_ci 58f08c3bdfSopenharmony_ci if (TST_RET == 0) { 59f08c3bdfSopenharmony_ci tst_res(TFAIL, "Set block size succeed unexpectedly"); 60f08c3bdfSopenharmony_ci if (tcases[n].ioctl_flag == LOOP_CONFIGURE) 61f08c3bdfSopenharmony_ci tst_detach_device_by_fd(dev_path, dev_fd); 62f08c3bdfSopenharmony_ci return; 63f08c3bdfSopenharmony_ci } 64f08c3bdfSopenharmony_ci if (TST_ERR == EINVAL) 65f08c3bdfSopenharmony_ci tst_res(TPASS | TTERRNO, "Set block size failed as expected"); 66f08c3bdfSopenharmony_ci else 67f08c3bdfSopenharmony_ci tst_res(TFAIL | TTERRNO, "Set block size failed expected EINVAL got"); 68f08c3bdfSopenharmony_ci} 69f08c3bdfSopenharmony_ci 70f08c3bdfSopenharmony_cistatic void run(unsigned int n) 71f08c3bdfSopenharmony_ci{ 72f08c3bdfSopenharmony_ci struct tcase *tc = &tcases[n]; 73f08c3bdfSopenharmony_ci 74f08c3bdfSopenharmony_ci tst_res(TINFO, "%s", tc->message); 75f08c3bdfSopenharmony_ci if (tc->ioctl_flag == LOOP_SET_BLOCK_SIZE) { 76f08c3bdfSopenharmony_ci if (!attach_flag) { 77f08c3bdfSopenharmony_ci tst_attach_device(dev_path, "test.img"); 78f08c3bdfSopenharmony_ci attach_flag = 1; 79f08c3bdfSopenharmony_ci } 80f08c3bdfSopenharmony_ci verify_ioctl_loop(n); 81f08c3bdfSopenharmony_ci return; 82f08c3bdfSopenharmony_ci } 83f08c3bdfSopenharmony_ci 84f08c3bdfSopenharmony_ci if (tc->ioctl_flag == LOOP_CONFIGURE && !loop_configure_sup) { 85f08c3bdfSopenharmony_ci tst_res(TCONF, "LOOP_CONFIGURE ioctl not supported"); 86f08c3bdfSopenharmony_ci return; 87f08c3bdfSopenharmony_ci } 88f08c3bdfSopenharmony_ci if (attach_flag) { 89f08c3bdfSopenharmony_ci tst_detach_device_by_fd(dev_path, dev_fd); 90f08c3bdfSopenharmony_ci attach_flag = 0; 91f08c3bdfSopenharmony_ci } 92f08c3bdfSopenharmony_ci loopconfig.block_size = *(tc->setvalue); 93f08c3bdfSopenharmony_ci verify_ioctl_loop(n); 94f08c3bdfSopenharmony_ci} 95f08c3bdfSopenharmony_ci 96f08c3bdfSopenharmony_cistatic void setup(void) 97f08c3bdfSopenharmony_ci{ 98f08c3bdfSopenharmony_ci unsigned int pg_size; 99f08c3bdfSopenharmony_ci int ret; 100f08c3bdfSopenharmony_ci 101f08c3bdfSopenharmony_ci dev_num = tst_find_free_loopdev(dev_path, sizeof(dev_path)); 102f08c3bdfSopenharmony_ci if (dev_num < 0) 103f08c3bdfSopenharmony_ci tst_brk(TBROK, "Failed to find free loop device"); 104f08c3bdfSopenharmony_ci 105f08c3bdfSopenharmony_ci tst_fill_file("test.img", 0, 1024, 1024); 106f08c3bdfSopenharmony_ci half_value = 256; 107f08c3bdfSopenharmony_ci pg_size = getpagesize(); 108f08c3bdfSopenharmony_ci invalid_value = pg_size * 2 ; 109f08c3bdfSopenharmony_ci unalign_value = pg_size - 1; 110f08c3bdfSopenharmony_ci 111f08c3bdfSopenharmony_ci dev_fd = SAFE_OPEN(dev_path, O_RDWR); 112f08c3bdfSopenharmony_ci 113f08c3bdfSopenharmony_ci if (ioctl(dev_fd, LOOP_SET_BLOCK_SIZE, 512) && errno == EINVAL) 114f08c3bdfSopenharmony_ci tst_brk(TCONF, "LOOP_SET_BLOCK_SIZE is not supported"); 115f08c3bdfSopenharmony_ci 116f08c3bdfSopenharmony_ci file_fd = SAFE_OPEN("test.img", O_RDWR); 117f08c3bdfSopenharmony_ci loopconfig.fd = -1; 118f08c3bdfSopenharmony_ci ret = ioctl(dev_fd, LOOP_CONFIGURE, &loopconfig); 119f08c3bdfSopenharmony_ci if (ret && errno != EBADF) { 120f08c3bdfSopenharmony_ci tst_res(TINFO | TERRNO, "LOOP_CONFIGURE is not supported"); 121f08c3bdfSopenharmony_ci loop_configure_sup = 0; 122f08c3bdfSopenharmony_ci return; 123f08c3bdfSopenharmony_ci } 124f08c3bdfSopenharmony_ci loopconfig.fd = file_fd; 125f08c3bdfSopenharmony_ci} 126f08c3bdfSopenharmony_ci 127f08c3bdfSopenharmony_cistatic void cleanup(void) 128f08c3bdfSopenharmony_ci{ 129f08c3bdfSopenharmony_ci if (dev_fd > 0) 130f08c3bdfSopenharmony_ci SAFE_CLOSE(dev_fd); 131f08c3bdfSopenharmony_ci if (file_fd > 0) 132f08c3bdfSopenharmony_ci SAFE_CLOSE(file_fd); 133f08c3bdfSopenharmony_ci if (attach_flag) 134f08c3bdfSopenharmony_ci tst_detach_device(dev_path); 135f08c3bdfSopenharmony_ci} 136f08c3bdfSopenharmony_ci 137f08c3bdfSopenharmony_cistatic struct tst_test test = { 138f08c3bdfSopenharmony_ci .setup = setup, 139f08c3bdfSopenharmony_ci .cleanup = cleanup, 140f08c3bdfSopenharmony_ci .test = run, 141f08c3bdfSopenharmony_ci .tcnt = ARRAY_SIZE(tcases), 142f08c3bdfSopenharmony_ci .needs_root = 1, 143f08c3bdfSopenharmony_ci .needs_tmpdir = 1, 144f08c3bdfSopenharmony_ci .needs_drivers = (const char *const []) { 145f08c3bdfSopenharmony_ci "loop", 146f08c3bdfSopenharmony_ci NULL 147f08c3bdfSopenharmony_ci } 148f08c3bdfSopenharmony_ci}; 149