1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright (c) Intel Corporation. 3 * All rights reserved. 4 */ 5 6 #include "spdk/stdinc.h" 7 #include "spdk_cunit.h" 8 #include "spdk/env.h" 9 #include "spdk_internal/mock.h" 10 11 #include "bdev/raid/raid5f.c" 12 13 DEFINE_STUB_V(raid_bdev_module_list_add, (struct raid_bdev_module *raid_module)); 14 DEFINE_STUB_V(raid_bdev_io_complete, (struct raid_bdev_io *raid_io, 15 enum spdk_bdev_io_status status)); 16 17 struct raid5f_params { 18 uint8_t num_base_bdevs; 19 uint64_t base_bdev_blockcnt; 20 uint32_t base_bdev_blocklen; 21 uint32_t strip_size; 22 }; 23 24 static struct raid5f_params *g_params; 25 static size_t g_params_count; 26 27 #define ARRAY_FOR_EACH(a, e) \ 28 for (e = a; e < a + SPDK_COUNTOF(a); e++) 29 30 #define RAID5F_PARAMS_FOR_EACH(p) \ 31 for (p = g_params; p < g_params + g_params_count; p++) 32 33 static int 34 test_setup(void) 35 { 36 uint8_t num_base_bdevs_values[] = { 3, 4, 5 }; 37 uint64_t base_bdev_blockcnt_values[] = { 1, 1024, 1024 * 1024 }; 38 uint32_t base_bdev_blocklen_values[] = { 512, 4096 }; 39 uint32_t strip_size_kb_values[] = { 1, 4, 128 }; 40 uint8_t *num_base_bdevs; 41 uint64_t *base_bdev_blockcnt; 42 uint32_t *base_bdev_blocklen; 43 uint32_t *strip_size_kb; 44 struct raid5f_params *params; 45 46 g_params_count = SPDK_COUNTOF(num_base_bdevs_values) * 47 SPDK_COUNTOF(base_bdev_blockcnt_values) * 48 SPDK_COUNTOF(base_bdev_blocklen_values) * 49 SPDK_COUNTOF(strip_size_kb_values); 50 g_params = calloc(g_params_count, sizeof(*g_params)); 51 if (!g_params) { 52 return -ENOMEM; 53 } 54 55 params = g_params; 56 57 ARRAY_FOR_EACH(num_base_bdevs_values, num_base_bdevs) { 58 ARRAY_FOR_EACH(base_bdev_blockcnt_values, base_bdev_blockcnt) { 59 ARRAY_FOR_EACH(base_bdev_blocklen_values, base_bdev_blocklen) { 60 ARRAY_FOR_EACH(strip_size_kb_values, strip_size_kb) { 61 params->num_base_bdevs = *num_base_bdevs; 62 params->base_bdev_blockcnt = *base_bdev_blockcnt; 63 params->base_bdev_blocklen = *base_bdev_blocklen; 64 params->strip_size = *strip_size_kb * 1024 / *base_bdev_blocklen; 65 if (params->strip_size == 0 || 66 params->strip_size > *base_bdev_blockcnt) { 67 g_params_count--; 68 continue; 69 } 70 params++; 71 } 72 } 73 } 74 } 75 76 return 0; 77 } 78 79 static int 80 test_cleanup(void) 81 { 82 free(g_params); 83 return 0; 84 } 85 86 static struct raid_bdev * 87 create_raid_bdev(struct raid5f_params *params) 88 { 89 struct raid_bdev *raid_bdev; 90 struct raid_base_bdev_info *base_info; 91 92 raid_bdev = calloc(1, sizeof(*raid_bdev)); 93 SPDK_CU_ASSERT_FATAL(raid_bdev != NULL); 94 95 raid_bdev->module = &g_raid5f_module; 96 raid_bdev->num_base_bdevs = params->num_base_bdevs; 97 raid_bdev->base_bdev_info = calloc(raid_bdev->num_base_bdevs, 98 sizeof(struct raid_base_bdev_info)); 99 SPDK_CU_ASSERT_FATAL(raid_bdev->base_bdev_info != NULL); 100 101 RAID_FOR_EACH_BASE_BDEV(raid_bdev, base_info) { 102 base_info->bdev = calloc(1, sizeof(*base_info->bdev)); 103 SPDK_CU_ASSERT_FATAL(base_info->bdev != NULL); 104 105 base_info->bdev->blockcnt = params->base_bdev_blockcnt; 106 base_info->bdev->blocklen = params->base_bdev_blocklen; 107 } 108 109 raid_bdev->strip_size = params->strip_size; 110 raid_bdev->strip_size_shift = spdk_u32log2(raid_bdev->strip_size); 111 raid_bdev->bdev.blocklen = params->base_bdev_blocklen; 112 113 return raid_bdev; 114 } 115 116 static void 117 delete_raid_bdev(struct raid_bdev *raid_bdev) 118 { 119 struct raid_base_bdev_info *base_info; 120 121 RAID_FOR_EACH_BASE_BDEV(raid_bdev, base_info) { 122 free(base_info->bdev); 123 } 124 free(raid_bdev->base_bdev_info); 125 free(raid_bdev); 126 } 127 128 static struct raid5f_info * 129 create_raid5f(struct raid5f_params *params) 130 { 131 struct raid_bdev *raid_bdev = create_raid_bdev(params); 132 133 SPDK_CU_ASSERT_FATAL(raid5f_start(raid_bdev) == 0); 134 135 return raid_bdev->module_private; 136 } 137 138 static void 139 delete_raid5f(struct raid5f_info *r5f_info) 140 { 141 struct raid_bdev *raid_bdev = r5f_info->raid_bdev; 142 143 raid5f_stop(raid_bdev); 144 145 delete_raid_bdev(raid_bdev); 146 } 147 148 static void 149 test_raid5f_start(void) 150 { 151 struct raid5f_params *params; 152 153 RAID5F_PARAMS_FOR_EACH(params) { 154 struct raid5f_info *r5f_info; 155 156 r5f_info = create_raid5f(params); 157 158 CU_ASSERT_EQUAL(r5f_info->stripe_blocks, params->strip_size * (params->num_base_bdevs - 1)); 159 CU_ASSERT_EQUAL(r5f_info->total_stripes, params->base_bdev_blockcnt / params->strip_size); 160 CU_ASSERT_EQUAL(r5f_info->raid_bdev->bdev.blockcnt, 161 (params->base_bdev_blockcnt - params->base_bdev_blockcnt % params->strip_size) * 162 (params->num_base_bdevs - 1)); 163 CU_ASSERT_EQUAL(r5f_info->raid_bdev->bdev.optimal_io_boundary, r5f_info->stripe_blocks); 164 165 delete_raid5f(r5f_info); 166 } 167 } 168 169 int 170 main(int argc, char **argv) 171 { 172 CU_pSuite suite = NULL; 173 unsigned int num_failures; 174 175 CU_set_error_action(CUEA_ABORT); 176 CU_initialize_registry(); 177 178 suite = CU_add_suite("raid5f", test_setup, test_cleanup); 179 CU_ADD_TEST(suite, test_raid5f_start); 180 181 CU_basic_set_mode(CU_BRM_VERBOSE); 182 CU_basic_run_tests(); 183 num_failures = CU_get_number_of_failures(); 184 CU_cleanup_registry(); 185 return num_failures; 186 } 187