Linux 6.13-rc4
[linux.git] / fs / btrfs / tests / raid-stripe-tree-tests.c
blob30f17eb7b6a8a1dfa9f66ed5508da42a70db1fa3
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3 * Copyright (C) 2024 Western Digital Corporation or its affiliates.
4 */
6 #include <linux/sizes.h>
7 #include "../fs.h"
8 #include "../disk-io.h"
9 #include "../transaction.h"
10 #include "../volumes.h"
11 #include "../raid-stripe-tree.h"
12 #include "btrfs-tests.h"
14 #define RST_TEST_NUM_DEVICES (2)
15 #define RST_TEST_RAID1_TYPE (BTRFS_BLOCK_GROUP_DATA | BTRFS_BLOCK_GROUP_RAID1)
17 typedef int (*test_func_t)(struct btrfs_trans_handle *trans);
19 static struct btrfs_device *btrfs_device_by_devid(struct btrfs_fs_devices *fs_devices,
20 u64 devid)
22 struct btrfs_device *dev;
24 list_for_each_entry(dev, &fs_devices->devices, dev_list) {
25 if (dev->devid == devid)
26 return dev;
29 return NULL;
33 * Test a 64K RST write on a 2 disk RAID1 at a logical address of 1M and then
34 * delete the 1st 32K, making the new start address 1M+32K.
36 static int test_front_delete(struct btrfs_trans_handle *trans)
38 struct btrfs_fs_info *fs_info = trans->fs_info;
39 struct btrfs_io_context *bioc;
40 struct btrfs_io_stripe io_stripe = { 0 };
41 u64 map_type = RST_TEST_RAID1_TYPE;
42 u64 logical = SZ_1M;
43 u64 len = SZ_64K;
44 int ret;
46 bioc = alloc_btrfs_io_context(fs_info, logical, RST_TEST_NUM_DEVICES);
47 if (!bioc) {
48 test_std_err(TEST_ALLOC_IO_CONTEXT);
49 ret = -ENOMEM;
50 goto out;
53 io_stripe.dev = btrfs_device_by_devid(fs_info->fs_devices, 0);
54 bioc->map_type = map_type;
55 bioc->size = len;
57 for (int i = 0; i < RST_TEST_NUM_DEVICES; i++) {
58 struct btrfs_io_stripe *stripe = &bioc->stripes[i];
60 stripe->dev = btrfs_device_by_devid(fs_info->fs_devices, i);
61 if (!stripe->dev) {
62 test_err("cannot find device with devid %d", i);
63 ret = -EINVAL;
64 goto out;
67 stripe->physical = logical + i * SZ_1G;
70 ret = btrfs_insert_one_raid_extent(trans, bioc);
71 if (ret) {
72 test_err("inserting RAID extent failed: %d", ret);
73 goto out;
76 ret = btrfs_get_raid_extent_offset(fs_info, logical, &len, map_type, 0, &io_stripe);
77 if (ret) {
78 test_err("lookup of RAID extent [%llu, %llu] failed", logical,
79 logical + len);
80 goto out;
83 if (io_stripe.physical != logical) {
84 test_err("invalid physical address, expected %llu got %llu",
85 logical, io_stripe.physical);
86 ret = -EINVAL;
87 goto out;
90 if (len != SZ_64K) {
91 test_err("invalid stripe length, expected %llu got %llu",
92 (u64)SZ_64K, len);
93 ret = -EINVAL;
94 goto out;
97 ret = btrfs_delete_raid_extent(trans, logical, SZ_32K);
98 if (ret) {
99 test_err("deleting RAID extent [%llu, %llu] failed", logical,
100 logical + SZ_32K);
101 goto out;
104 len = SZ_32K;
105 ret = btrfs_get_raid_extent_offset(fs_info, logical + SZ_32K, &len,
106 map_type, 0, &io_stripe);
107 if (ret) {
108 test_err("lookup of RAID extent [%llu, %llu] failed",
109 logical + SZ_32K, logical + SZ_32K + len);
110 goto out;
113 if (io_stripe.physical != logical + SZ_32K) {
114 test_err("invalid physical address, expected %llu, got %llu",
115 logical + SZ_32K, io_stripe.physical);
116 ret = -EINVAL;
117 goto out;
120 if (len != SZ_32K) {
121 test_err("invalid stripe length, expected %llu, got %llu",
122 (u64)SZ_32K, len);
123 ret = -EINVAL;
124 goto out;
127 ret = btrfs_get_raid_extent_offset(fs_info, logical, &len, map_type, 0, &io_stripe);
128 if (!ret) {
129 ret = -EINVAL;
130 test_err("lookup of RAID extent [%llu, %llu] succeeded, should fail",
131 logical, logical + SZ_32K);
132 goto out;
135 ret = btrfs_delete_raid_extent(trans, logical + SZ_32K, SZ_32K);
136 out:
137 btrfs_put_bioc(bioc);
138 return ret;
142 * Test a 64K RST write on a 2 disk RAID1 at a logical address of 1M and then
143 * truncate the stripe extent down to 32K.
145 static int test_tail_delete(struct btrfs_trans_handle *trans)
147 struct btrfs_fs_info *fs_info = trans->fs_info;
148 struct btrfs_io_context *bioc;
149 struct btrfs_io_stripe io_stripe = { 0 };
150 u64 map_type = RST_TEST_RAID1_TYPE;
151 u64 logical = SZ_1M;
152 u64 len = SZ_64K;
153 int ret;
155 bioc = alloc_btrfs_io_context(fs_info, logical, RST_TEST_NUM_DEVICES);
156 if (!bioc) {
157 test_std_err(TEST_ALLOC_IO_CONTEXT);
158 ret = -ENOMEM;
159 goto out;
162 io_stripe.dev = btrfs_device_by_devid(fs_info->fs_devices, 0);
163 bioc->map_type = map_type;
164 bioc->size = len;
166 for (int i = 0; i < RST_TEST_NUM_DEVICES; i++) {
167 struct btrfs_io_stripe *stripe = &bioc->stripes[i];
169 stripe->dev = btrfs_device_by_devid(fs_info->fs_devices, i);
170 if (!stripe->dev) {
171 test_err("cannot find device with devid %d", i);
172 ret = -EINVAL;
173 goto out;
176 stripe->physical = logical + i * SZ_1G;
179 ret = btrfs_insert_one_raid_extent(trans, bioc);
180 if (ret) {
181 test_err("inserting RAID extent failed: %d", ret);
182 goto out;
185 io_stripe.dev = btrfs_device_by_devid(fs_info->fs_devices, 0);
186 if (!io_stripe.dev) {
187 ret = -EINVAL;
188 goto out;
191 ret = btrfs_get_raid_extent_offset(fs_info, logical, &len, map_type, 0, &io_stripe);
192 if (ret) {
193 test_err("lookup of RAID extent [%llu, %llu] failed", logical,
194 logical + len);
195 goto out;
198 if (io_stripe.physical != logical) {
199 test_err("invalid physical address, expected %llu got %llu",
200 logical, io_stripe.physical);
201 ret = -EINVAL;
202 goto out;
205 if (len != SZ_64K) {
206 test_err("invalid stripe length, expected %llu got %llu",
207 (u64)SZ_64K, len);
208 ret = -EINVAL;
209 goto out;
212 ret = btrfs_delete_raid_extent(trans, logical + SZ_32K, SZ_32K);
213 if (ret) {
214 test_err("deleting RAID extent [%llu, %llu] failed",
215 logical + SZ_32K, logical + SZ_64K);
216 goto out;
219 len = SZ_32K;
220 ret = btrfs_get_raid_extent_offset(fs_info, logical, &len, map_type, 0, &io_stripe);
221 if (ret) {
222 test_err("lookup of RAID extent [%llu, %llu] failed", logical,
223 logical + len);
224 goto out;
227 if (io_stripe.physical != logical) {
228 test_err("invalid physical address, expected %llu, got %llu",
229 logical, io_stripe.physical);
230 ret = -EINVAL;
231 goto out;
234 if (len != SZ_32K) {
235 test_err("invalid stripe length, expected %llu, got %llu",
236 (u64)SZ_32K, len);
237 ret = -EINVAL;
238 goto out;
241 ret = btrfs_delete_raid_extent(trans, logical, len);
242 if (ret)
243 test_err("deleting RAID extent [%llu, %llu] failed", logical,
244 logical + len);
246 out:
247 btrfs_put_bioc(bioc);
248 return ret;
252 * Test a 64K RST write on a 2 disk RAID1 at a logical address of 1M and then
253 * overwrite the whole range giving it new physical address at an offset of 1G.
254 * The intent of this test is to exercise the 'update_raid_extent_item()'
255 * function called be btrfs_insert_one_raid_extent().
257 static int test_create_update_delete(struct btrfs_trans_handle *trans)
259 struct btrfs_fs_info *fs_info = trans->fs_info;
260 struct btrfs_io_context *bioc;
261 struct btrfs_io_stripe io_stripe = { 0 };
262 u64 map_type = RST_TEST_RAID1_TYPE;
263 u64 logical = SZ_1M;
264 u64 len = SZ_64K;
265 int ret;
267 bioc = alloc_btrfs_io_context(fs_info, logical, RST_TEST_NUM_DEVICES);
268 if (!bioc) {
269 test_std_err(TEST_ALLOC_IO_CONTEXT);
270 ret = -ENOMEM;
271 goto out;
274 io_stripe.dev = btrfs_device_by_devid(fs_info->fs_devices, 0);
275 bioc->map_type = map_type;
276 bioc->size = len;
278 for (int i = 0; i < RST_TEST_NUM_DEVICES; i++) {
279 struct btrfs_io_stripe *stripe = &bioc->stripes[i];
281 stripe->dev = btrfs_device_by_devid(fs_info->fs_devices, i);
282 if (!stripe->dev) {
283 test_err("cannot find device with devid %d", i);
284 ret = -EINVAL;
285 goto out;
288 stripe->physical = logical + i * SZ_1G;
291 ret = btrfs_insert_one_raid_extent(trans, bioc);
292 if (ret) {
293 test_err("inserting RAID extent failed: %d", ret);
294 goto out;
297 io_stripe.dev = btrfs_device_by_devid(fs_info->fs_devices, 0);
298 if (!io_stripe.dev) {
299 ret = -EINVAL;
300 goto out;
303 ret = btrfs_get_raid_extent_offset(fs_info, logical, &len, map_type, 0, &io_stripe);
304 if (ret) {
305 test_err("lookup of RAID extent [%llu, %llu] failed", logical,
306 logical + len);
307 goto out;
310 if (io_stripe.physical != logical) {
311 test_err("invalid physical address, expected %llu got %llu",
312 logical, io_stripe.physical);
313 ret = -EINVAL;
314 goto out;
317 if (len != SZ_64K) {
318 test_err("invalid stripe length, expected %llu got %llu",
319 (u64)SZ_64K, len);
320 ret = -EINVAL;
321 goto out;
324 for (int i = 0; i < RST_TEST_NUM_DEVICES; i++) {
325 struct btrfs_io_stripe *stripe = &bioc->stripes[i];
327 stripe->dev = btrfs_device_by_devid(fs_info->fs_devices, i);
328 if (!stripe->dev) {
329 test_err("cannot find device with devid %d", i);
330 ret = -EINVAL;
331 goto out;
334 stripe->physical = SZ_1G + logical + i * SZ_1G;
337 ret = btrfs_insert_one_raid_extent(trans, bioc);
338 if (ret) {
339 test_err("updating RAID extent failed: %d", ret);
340 goto out;
343 ret = btrfs_get_raid_extent_offset(fs_info, logical, &len, map_type, 0, &io_stripe);
344 if (ret) {
345 test_err("lookup of RAID extent [%llu, %llu] failed", logical,
346 logical + len);
347 goto out;
350 if (io_stripe.physical != logical + SZ_1G) {
351 test_err("invalid physical address, expected %llu, got %llu",
352 logical + SZ_1G, io_stripe.physical);
353 ret = -EINVAL;
354 goto out;
357 if (len != SZ_64K) {
358 test_err("invalid stripe length, expected %llu, got %llu",
359 (u64)SZ_64K, len);
360 ret = -EINVAL;
361 goto out;
364 ret = btrfs_delete_raid_extent(trans, logical, len);
365 if (ret)
366 test_err("deleting RAID extent [%llu, %llu] failed", logical,
367 logical + len);
369 out:
370 btrfs_put_bioc(bioc);
371 return ret;
375 * Test a simple 64K RST write on a 2 disk RAID1 at a logical address of 1M.
376 * The "physical" copy on device 0 is at 1M, on device 1 it is at 1G+1M.
378 static int test_simple_create_delete(struct btrfs_trans_handle *trans)
380 struct btrfs_fs_info *fs_info = trans->fs_info;
381 struct btrfs_io_context *bioc;
382 struct btrfs_io_stripe io_stripe = { 0 };
383 u64 map_type = RST_TEST_RAID1_TYPE;
384 u64 logical = SZ_1M;
385 u64 len = SZ_64K;
386 int ret;
388 bioc = alloc_btrfs_io_context(fs_info, logical, RST_TEST_NUM_DEVICES);
389 if (!bioc) {
390 test_std_err(TEST_ALLOC_IO_CONTEXT);
391 ret = -ENOMEM;
392 goto out;
395 bioc->map_type = map_type;
396 bioc->size = SZ_64K;
398 for (int i = 0; i < RST_TEST_NUM_DEVICES; i++) {
399 struct btrfs_io_stripe *stripe = &bioc->stripes[i];
401 stripe->dev = btrfs_device_by_devid(fs_info->fs_devices, i);
402 if (!stripe->dev) {
403 test_err("cannot find device with devid %d", i);
404 ret = -EINVAL;
405 goto out;
408 stripe->physical = logical + i * SZ_1G;
411 ret = btrfs_insert_one_raid_extent(trans, bioc);
412 if (ret) {
413 test_err("inserting RAID extent failed: %d", ret);
414 goto out;
417 io_stripe.dev = btrfs_device_by_devid(fs_info->fs_devices, 0);
418 if (!io_stripe.dev) {
419 ret = -EINVAL;
420 goto out;
423 ret = btrfs_get_raid_extent_offset(fs_info, logical, &len, map_type, 0, &io_stripe);
424 if (ret) {
425 test_err("lookup of RAID extent [%llu, %llu] failed", logical,
426 logical + len);
427 goto out;
430 if (io_stripe.physical != logical) {
431 test_err("invalid physical address, expected %llu got %llu",
432 logical, io_stripe.physical);
433 ret = -EINVAL;
434 goto out;
437 if (len != SZ_64K) {
438 test_err("invalid stripe length, expected %llu got %llu",
439 (u64)SZ_64K, len);
440 ret = -EINVAL;
441 goto out;
444 ret = btrfs_delete_raid_extent(trans, logical, len);
445 if (ret)
446 test_err("deleting RAID extent [%llu, %llu] failed", logical,
447 logical + len);
449 out:
450 btrfs_put_bioc(bioc);
451 return ret;
454 static const test_func_t tests[] = {
455 test_simple_create_delete,
456 test_create_update_delete,
457 test_tail_delete,
458 test_front_delete,
461 static int run_test(test_func_t test, u32 sectorsize, u32 nodesize)
463 struct btrfs_trans_handle trans;
464 struct btrfs_fs_info *fs_info;
465 struct btrfs_root *root = NULL;
466 int ret;
468 fs_info = btrfs_alloc_dummy_fs_info(sectorsize, nodesize);
469 if (!fs_info) {
470 test_std_err(TEST_ALLOC_FS_INFO);
471 ret = -ENOMEM;
472 goto out;
475 root = btrfs_alloc_dummy_root(fs_info);
476 if (IS_ERR(root)) {
477 test_std_err(TEST_ALLOC_ROOT);
478 ret = PTR_ERR(root);
479 goto out;
481 btrfs_set_super_compat_ro_flags(root->fs_info->super_copy,
482 BTRFS_FEATURE_INCOMPAT_RAID_STRIPE_TREE);
483 root->root_key.objectid = BTRFS_RAID_STRIPE_TREE_OBJECTID;
484 root->root_key.type = BTRFS_ROOT_ITEM_KEY;
485 root->root_key.offset = 0;
486 fs_info->stripe_root = root;
487 root->fs_info->tree_root = root;
489 root->node = alloc_test_extent_buffer(root->fs_info, nodesize);
490 if (IS_ERR(root->node)) {
491 test_std_err(TEST_ALLOC_EXTENT_BUFFER);
492 ret = PTR_ERR(root->node);
493 goto out;
495 btrfs_set_header_level(root->node, 0);
496 btrfs_set_header_nritems(root->node, 0);
497 root->alloc_bytenr += 2 * nodesize;
499 for (int i = 0; i < RST_TEST_NUM_DEVICES; i++) {
500 struct btrfs_device *dev;
502 dev = btrfs_alloc_dummy_device(fs_info);
503 if (IS_ERR(dev)) {
504 test_err("cannot allocate device");
505 ret = PTR_ERR(dev);
506 goto out;
508 dev->devid = i;
511 btrfs_init_dummy_trans(&trans, root->fs_info);
512 ret = test(&trans);
513 if (ret)
514 goto out;
516 out:
517 btrfs_free_dummy_root(root);
518 btrfs_free_dummy_fs_info(fs_info);
520 return ret;
523 int btrfs_test_raid_stripe_tree(u32 sectorsize, u32 nodesize)
525 int ret = 0;
527 test_msg("running raid-stripe-tree tests");
528 for (int i = 0; i < ARRAY_SIZE(tests); i++) {
529 ret = run_test(tests[i], sectorsize, nodesize);
530 if (ret) {
531 test_err("test-case %ps failed with %d\n", tests[i], ret);
532 goto out;
536 out:
537 return ret;