Loading...
Note: File does not exist in v5.4.
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
17typedef int (*test_func_t)(struct btrfs_trans_handle *trans);
18
19static 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 */
36static 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);
136out:
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 */
145static 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
246out:
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 */
257static 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
369out:
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 */
378static 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
449out:
450 btrfs_put_bioc(bioc);
451 return ret;
452}
453
454static 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
461static 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
516out:
517 btrfs_free_dummy_root(root);
518 btrfs_free_dummy_fs_info(fs_info);
519
520 return ret;
521}
522
523int 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
536out:
537 return ret;
538}