Linux Audio

Check our new training course

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}