xref: /linux/fs/btrfs/tests/raid-stripe-tree-tests.c (revision 7f71507851fc7764b36a3221839607d3a45c2025)
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Copyright (C) 2024 Western Digital Corporation or its affiliates.
4  */
5 
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"
13 
14 #define RST_TEST_NUM_DEVICES	(2)
15 #define RST_TEST_RAID1_TYPE	(BTRFS_BLOCK_GROUP_DATA | BTRFS_BLOCK_GROUP_RAID1)
16 
17 typedef int (*test_func_t)(struct btrfs_trans_handle *trans);
18 
19 static struct btrfs_device *btrfs_device_by_devid(struct btrfs_fs_devices *fs_devices,
20 						  u64 devid)
21 {
22 	struct btrfs_device *dev;
23 
24 	list_for_each_entry(dev, &fs_devices->devices, dev_list) {
25 		if (dev->devid == devid)
26 			return dev;
27 	}
28 
29 	return NULL;
30 }
31 
32 /*
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.
35  */
36 static int test_front_delete(struct btrfs_trans_handle *trans)
37 {
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;
45 
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;
51 	}
52 
53 	io_stripe.dev = btrfs_device_by_devid(fs_info->fs_devices, 0);
54 	bioc->map_type = map_type;
55 	bioc->size = len;
56 
57 	for (int i = 0; i < RST_TEST_NUM_DEVICES; i++) {
58 		struct btrfs_io_stripe *stripe = &bioc->stripes[i];
59 
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;
65 		}
66 
67 		stripe->physical = logical + i * SZ_1G;
68 	}
69 
70 	ret = btrfs_insert_one_raid_extent(trans, bioc);
71 	if (ret) {
72 		test_err("inserting RAID extent failed: %d", ret);
73 		goto out;
74 	}
75 
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;
81 	}
82 
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;
88 	}
89 
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;
95 	}
96 
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;
102 	}
103 
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;
111 	}
112 
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;
118 	}
119 
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;
125 	}
126 
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;
133 	}
134 
135 	ret = btrfs_delete_raid_extent(trans, logical + SZ_32K, SZ_32K);
136 out:
137 	btrfs_put_bioc(bioc);
138 	return ret;
139 }
140 
141 /*
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.
144  */
145 static int test_tail_delete(struct btrfs_trans_handle *trans)
146 {
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;
154 
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;
160 	}
161 
162 	io_stripe.dev = btrfs_device_by_devid(fs_info->fs_devices, 0);
163 	bioc->map_type = map_type;
164 	bioc->size = len;
165 
166 	for (int i = 0; i < RST_TEST_NUM_DEVICES; i++) {
167 		struct btrfs_io_stripe *stripe = &bioc->stripes[i];
168 
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;
174 		}
175 
176 		stripe->physical = logical + i * SZ_1G;
177 	}
178 
179 	ret = btrfs_insert_one_raid_extent(trans, bioc);
180 	if (ret) {
181 		test_err("inserting RAID extent failed: %d", ret);
182 		goto out;
183 	}
184 
185 	io_stripe.dev = btrfs_device_by_devid(fs_info->fs_devices, 0);
186 	if (!io_stripe.dev) {
187 		ret = -EINVAL;
188 		goto out;
189 	}
190 
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;
196 	}
197 
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;
203 	}
204 
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;
210 	}
211 
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;
217 	}
218 
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;
225 	}
226 
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;
232 	}
233 
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;
239 	}
240 
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);
245 
246 out:
247 	btrfs_put_bioc(bioc);
248 	return ret;
249 }
250 
251 /*
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().
256  */
257 static int test_create_update_delete(struct btrfs_trans_handle *trans)
258 {
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;
266 
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;
272 	}
273 
274 	io_stripe.dev = btrfs_device_by_devid(fs_info->fs_devices, 0);
275 	bioc->map_type = map_type;
276 	bioc->size = len;
277 
278 	for (int i = 0; i < RST_TEST_NUM_DEVICES; i++) {
279 		struct btrfs_io_stripe *stripe = &bioc->stripes[i];
280 
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;
286 		}
287 
288 		stripe->physical = logical + i * SZ_1G;
289 	}
290 
291 	ret = btrfs_insert_one_raid_extent(trans, bioc);
292 	if (ret) {
293 		test_err("inserting RAID extent failed: %d", ret);
294 		goto out;
295 	}
296 
297 	io_stripe.dev = btrfs_device_by_devid(fs_info->fs_devices, 0);
298 	if (!io_stripe.dev) {
299 		ret = -EINVAL;
300 		goto out;
301 	}
302 
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;
308 	}
309 
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;
315 	}
316 
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;
322 	}
323 
324 	for (int i = 0; i < RST_TEST_NUM_DEVICES; i++) {
325 		struct btrfs_io_stripe *stripe = &bioc->stripes[i];
326 
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;
332 		}
333 
334 		stripe->physical = SZ_1G + logical + i * SZ_1G;
335 	}
336 
337 	ret = btrfs_insert_one_raid_extent(trans, bioc);
338 	if (ret) {
339 		test_err("updating RAID extent failed: %d", ret);
340 		goto out;
341 	}
342 
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;
348 	}
349 
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;
355 	}
356 
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;
362 	}
363 
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);
368 
369 out:
370 	btrfs_put_bioc(bioc);
371 	return ret;
372 }
373 
374 /*
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.
377  */
378 static int test_simple_create_delete(struct btrfs_trans_handle *trans)
379 {
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;
387 
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;
393 	}
394 
395 	bioc->map_type = map_type;
396 	bioc->size = SZ_64K;
397 
398 	for (int i = 0; i < RST_TEST_NUM_DEVICES; i++) {
399 		struct btrfs_io_stripe *stripe = &bioc->stripes[i];
400 
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;
406 		}
407 
408 		stripe->physical = logical + i * SZ_1G;
409 	}
410 
411 	ret = btrfs_insert_one_raid_extent(trans, bioc);
412 	if (ret) {
413 		test_err("inserting RAID extent failed: %d", ret);
414 		goto out;
415 	}
416 
417 	io_stripe.dev = btrfs_device_by_devid(fs_info->fs_devices, 0);
418 	if (!io_stripe.dev) {
419 		ret = -EINVAL;
420 		goto out;
421 	}
422 
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;
428 	}
429 
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;
435 	}
436 
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;
442 	}
443 
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);
448 
449 out:
450 	btrfs_put_bioc(bioc);
451 	return ret;
452 }
453 
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,
459 };
460 
461 static int run_test(test_func_t test, u32 sectorsize, u32 nodesize)
462 {
463 	struct btrfs_trans_handle trans;
464 	struct btrfs_fs_info *fs_info;
465 	struct btrfs_root *root = NULL;
466 	int ret;
467 
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;
473 	}
474 
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;
480 	}
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;
488 
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;
494 	}
495 	btrfs_set_header_level(root->node, 0);
496 	btrfs_set_header_nritems(root->node, 0);
497 	root->alloc_bytenr += 2 * nodesize;
498 
499 	for (int i = 0; i < RST_TEST_NUM_DEVICES; i++) {
500 		struct btrfs_device *dev;
501 
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;
507 		}
508 		dev->devid = i;
509 	}
510 
511 	btrfs_init_dummy_trans(&trans, root->fs_info);
512 	ret = test(&trans);
513 	if (ret)
514 		goto out;
515 
516 out:
517 	btrfs_free_dummy_root(root);
518 	btrfs_free_dummy_fs_info(fs_info);
519 
520 	return ret;
521 }
522 
523 int btrfs_test_raid_stripe_tree(u32 sectorsize, u32 nodesize)
524 {
525 	int ret = 0;
526 
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;
533 		}
534 	}
535 
536 out:
537 	return ret;
538 }
539