Skip to content
Navigation Menu
Toggle navigation
Sign in
In this repository
All GitHub Enterprise
↵
Jump to
↵
No suggested jump to results
In this repository
All GitHub Enterprise
↵
Jump to
↵
In this organization
All GitHub Enterprise
↵
Jump to
↵
In this repository
All GitHub Enterprise
↵
Jump to
↵
Sign in
Reseting focus
You signed in with another tab or window.
Reload
to refresh your session.
You signed out in another tab or window.
Reload
to refresh your session.
You switched accounts on another tab or window.
Reload
to refresh your session.
Dismiss alert
{{ message }}
mariux64
/
linux
Public
Notifications
You must be signed in to change notification settings
Fork
0
Star
0
Code
Issues
2
Pull requests
0
Actions
Projects
0
Wiki
Security
Insights
Additional navigation options
Code
Issues
Pull requests
Actions
Projects
Wiki
Security
Insights
Files
a0afdec
Documentation
LICENSES
arch
block
certs
crypto
drivers
fs
9p
adfs
affs
afs
autofs
bcachefs
befs
bfs
btrfs
tests
btrfs-tests.c
btrfs-tests.h
delayed-refs-tests.c
extent-buffer-tests.c
extent-io-tests.c
extent-map-tests.c
free-space-tests.c
free-space-tree-tests.c
inode-tests.c
qgroup-tests.c
raid-stripe-tree-tests.c
Kconfig
Makefile
accessors.c
accessors.h
acl.c
acl.h
async-thread.c
async-thread.h
backref.c
backref.h
bio.c
bio.h
block-group.c
block-group.h
block-rsv.c
block-rsv.h
btrfs_inode.h
compression.c
compression.h
ctree.c
ctree.h
defrag.c
defrag.h
delalloc-space.c
delalloc-space.h
delayed-inode.c
delayed-inode.h
delayed-ref.c
delayed-ref.h
dev-replace.c
dev-replace.h
dir-item.c
dir-item.h
direct-io.c
direct-io.h
discard.c
discard.h
disk-io.c
disk-io.h
export.c
export.h
extent-io-tree.c
extent-io-tree.h
extent-tree.c
extent-tree.h
extent_io.c
extent_io.h
extent_map.c
extent_map.h
fiemap.c
fiemap.h
file-item.c
file-item.h
file.c
file.h
free-space-cache.c
free-space-cache.h
free-space-tree.c
free-space-tree.h
fs.c
fs.h
inode-item.c
inode-item.h
inode.c
ioctl.c
ioctl.h
locking.c
locking.h
lru_cache.c
lru_cache.h
lzo.c
messages.c
messages.h
misc.h
ordered-data.c
ordered-data.h
orphan.c
orphan.h
print-tree.c
print-tree.h
props.c
props.h
qgroup.c
qgroup.h
raid-stripe-tree.c
raid-stripe-tree.h
raid56.c
raid56.h
rcu-string.h
ref-verify.c
ref-verify.h
reflink.c
reflink.h
relocation.c
relocation.h
root-tree.c
root-tree.h
scrub.c
scrub.h
send.c
send.h
space-info.c
space-info.h
subpage.c
subpage.h
super.c
super.h
sysfs.c
sysfs.h
transaction.c
transaction.h
tree-checker.c
tree-checker.h
tree-log.c
tree-log.h
tree-mod-log.c
tree-mod-log.h
ulist.c
ulist.h
uuid-tree.c
uuid-tree.h
verity.c
verity.h
volumes.c
volumes.h
xattr.c
xattr.h
zlib.c
zoned.c
zoned.h
zstd.c
cachefiles
ceph
coda
configfs
cramfs
crypto
debugfs
devpts
dlm
ecryptfs
efivarfs
efs
erofs
exfat
exportfs
ext2
ext4
f2fs
fat
freevxfs
fuse
gfs2
hfs
hfsplus
hostfs
hpfs
hugetlbfs
iomap
isofs
jbd2
jffs2
jfs
kernfs
lockd
minix
netfs
nfs
nfs_common
nfsd
nilfs2
nls
notify
ntfs3
ocfs2
omfs
openpromfs
orangefs
overlayfs
proc
pstore
qnx4
qnx6
quota
ramfs
romfs
smb
squashfs
sysfs
sysv
tests
tracefs
ubifs
udf
ufs
unicode
vboxsf
verity
xfs
zonefs
Kconfig
Kconfig.binfmt
Makefile
aio.c
anon_inodes.c
attr.c
backing-file.c
bad_inode.c
binfmt_elf.c
binfmt_elf_fdpic.c
binfmt_flat.c
binfmt_misc.c
binfmt_script.c
bpf_fs_kfuncs.c
buffer.c
char_dev.c
compat_binfmt_elf.c
coredump.c
d_path.c
dax.c
dcache.c
direct-io.c
drop_caches.c
eventfd.c
eventpoll.c
exec.c
fcntl.c
fhandle.c
file.c
file_table.c
filesystems.c
fs-writeback.c
fs_context.c
fs_parser.c
fs_pin.c
fs_struct.c
fs_types.c
fsopen.c
init.c
inode.c
internal.h
ioctl.c
kernel_read_file.c
libfs.c
locks.c
mbcache.c
mnt_idmapping.c
mount.h
mpage.c
namei.c
namespace.c
nsfs.c
open.c
pidfs.c
pipe.c
pnode.c
pnode.h
posix_acl.c
proc_namespace.c
read_write.c
readdir.c
remap_range.c
select.c
seq_file.c
signalfd.c
splice.c
stack.c
stat.c
statfs.c
super.c
sync.c
sysctls.c
timerfd.c
userfaultfd.c
utimes.c
xattr.c
include
init
io_uring
ipc
kernel
lib
mm
net
rust
samples
scripts
security
sound
tools
usr
virt
.clang-format
.clippy.toml
.cocciconfig
.editorconfig
.get_maintainer.ignore
.gitattributes
.gitignore
.mailmap
.rustfmt.toml
COPYING
CREDITS
Kbuild
Kconfig
MAINTAINERS
Makefile
README
Breadcrumbs
linux
/
fs
/
btrfs
/
tests
/
raid-stripe-tree-tests.c
Blame
Blame
Latest commit
History
History
550 lines (463 loc) · 13.1 KB
Breadcrumbs
linux
/
fs
/
btrfs
/
tests
/
raid-stripe-tree-tests.c
Top
File metadata and controls
Code
Blame
550 lines (463 loc) · 13.1 KB
Raw
// SPDX-License-Identifier: GPL-2.0 /* * Copyright (C) 2024 Western Digital Corporation or its affiliates. */ #include <linux/sizes.h> #include "../fs.h" #include "../disk-io.h" #include "../transaction.h" #include "../volumes.h" #include "../raid-stripe-tree.h" #include "btrfs-tests.h" #define RST_TEST_NUM_DEVICES (2) #define RST_TEST_RAID1_TYPE (BTRFS_BLOCK_GROUP_DATA | BTRFS_BLOCK_GROUP_RAID1) #define SZ_48K (SZ_32K + SZ_16K) typedef int (*test_func_t)(struct btrfs_trans_handle *trans); static struct btrfs_device *btrfs_device_by_devid(struct btrfs_fs_devices *fs_devices, u64 devid) { struct btrfs_device *dev; list_for_each_entry(dev, &fs_devices->devices, dev_list) { if (dev->devid == devid) return dev; } return NULL; } /* * Test a 64K RST write on a 2 disk RAID1 at a logical address of 1M and then * delete the 1st 32K, making the new start address 1M+32K. */ static int test_front_delete(struct btrfs_trans_handle *trans) { struct btrfs_fs_info *fs_info = trans->fs_info; struct btrfs_io_context *bioc; struct btrfs_io_stripe io_stripe = { 0 }; u64 map_type = RST_TEST_RAID1_TYPE; u64 logical = SZ_1M; u64 len = SZ_64K; int ret; bioc = alloc_btrfs_io_context(fs_info, logical, RST_TEST_NUM_DEVICES); if (!bioc) { test_std_err(TEST_ALLOC_IO_CONTEXT); ret = -ENOMEM; goto out; } io_stripe.dev = btrfs_device_by_devid(fs_info->fs_devices, 0); bioc->map_type = map_type; bioc->size = len; for (int i = 0; i < RST_TEST_NUM_DEVICES; i++) { struct btrfs_io_stripe *stripe = &bioc->stripes[i]; stripe->dev = btrfs_device_by_devid(fs_info->fs_devices, i); if (!stripe->dev) { test_err("cannot find device with devid %d", i); ret = -EINVAL; goto out; } stripe->physical = logical + i * SZ_1G; } ret = btrfs_insert_one_raid_extent(trans, bioc); if (ret) { test_err("inserting RAID extent failed: %d", ret); goto out; } ret = btrfs_get_raid_extent_offset(fs_info, logical, &len, map_type, 0, &io_stripe); if (ret) { test_err("lookup of RAID extent [%llu, %llu] failed", logical, logical + len); goto out; } if (io_stripe.physical != logical) { test_err("invalid physical address, expected %llu got %llu", logical, io_stripe.physical); ret = -EINVAL; goto out; } if (len != SZ_64K) { test_err("invalid stripe length, expected %llu got %llu", (u64)SZ_64K, len); ret = -EINVAL; goto out; } ret = btrfs_delete_raid_extent(trans, logical, SZ_16K); if (ret) { test_err("deleting RAID extent [%llu, %llu] failed", logical, logical + SZ_16K); goto out; } len -= SZ_16K; ret = btrfs_get_raid_extent_offset(fs_info, logical + SZ_16K, &len, map_type, 0, &io_stripe); if (ret) { test_err("lookup of RAID extent [%llu, %llu] failed", logical + SZ_16K, logical + SZ_64K); goto out; } if (io_stripe.physical != logical + SZ_16K) { test_err("invalid physical address, expected %llu, got %llu", logical + SZ_16K, io_stripe.physical); ret = -EINVAL; goto out; } if (len != SZ_48K) { test_err("invalid stripe length, expected %llu, got %llu", (u64)SZ_48K, len); ret = -EINVAL; goto out; } ret = btrfs_get_raid_extent_offset(fs_info, logical, &len, map_type, 0, &io_stripe); if (ret != -ENODATA) { ret = -EINVAL; test_err("lookup of RAID extent [%llu, %llu] succeeded, should fail", logical, logical + SZ_16K); goto out; } ret = btrfs_delete_raid_extent(trans, logical + SZ_16K, SZ_48K); out: btrfs_put_bioc(bioc); return ret; } /* * Test a 64K RST write on a 2 disk RAID1 at a logical address of 1M and then * truncate the stripe extent down to 32K. */ static int test_tail_delete(struct btrfs_trans_handle *trans) { struct btrfs_fs_info *fs_info = trans->fs_info; struct btrfs_io_context *bioc; struct btrfs_io_stripe io_stripe = { 0 }; u64 map_type = RST_TEST_RAID1_TYPE; u64 logical = SZ_1M; u64 len = SZ_64K; int ret; bioc = alloc_btrfs_io_context(fs_info, logical, RST_TEST_NUM_DEVICES); if (!bioc) { test_std_err(TEST_ALLOC_IO_CONTEXT); ret = -ENOMEM; goto out; } io_stripe.dev = btrfs_device_by_devid(fs_info->fs_devices, 0); bioc->map_type = map_type; bioc->size = len; for (int i = 0; i < RST_TEST_NUM_DEVICES; i++) { struct btrfs_io_stripe *stripe = &bioc->stripes[i]; stripe->dev = btrfs_device_by_devid(fs_info->fs_devices, i); if (!stripe->dev) { test_err("cannot find device with devid %d", i); ret = -EINVAL; goto out; } stripe->physical = logical + i * SZ_1G; } ret = btrfs_insert_one_raid_extent(trans, bioc); if (ret) { test_err("inserting RAID extent failed: %d", ret); goto out; } io_stripe.dev = btrfs_device_by_devid(fs_info->fs_devices, 0); if (!io_stripe.dev) { ret = -EINVAL; goto out; } ret = btrfs_get_raid_extent_offset(fs_info, logical, &len, map_type, 0, &io_stripe); if (ret) { test_err("lookup of RAID extent [%llu, %llu] failed", logical, logical + len); goto out; } if (io_stripe.physical != logical) { test_err("invalid physical address, expected %llu got %llu", logical, io_stripe.physical); ret = -EINVAL; goto out; } if (len != SZ_64K) { test_err("invalid stripe length, expected %llu got %llu", (u64)SZ_64K, len); ret = -EINVAL; goto out; } ret = btrfs_delete_raid_extent(trans, logical + SZ_48K, SZ_16K); if (ret) { test_err("deleting RAID extent [%llu, %llu] failed", logical + SZ_48K, logical + SZ_64K); goto out; } len = SZ_48K; ret = btrfs_get_raid_extent_offset(fs_info, logical, &len, map_type, 0, &io_stripe); if (ret) { test_err("lookup of RAID extent [%llu, %llu] failed", logical, logical + len); goto out; } if (io_stripe.physical != logical) { test_err("invalid physical address, expected %llu, got %llu", logical, io_stripe.physical); ret = -EINVAL; goto out; } if (len != SZ_48K) { test_err("invalid stripe length, expected %llu, got %llu", (u64)SZ_48K, len); ret = -EINVAL; goto out; } len = SZ_16K; ret = btrfs_get_raid_extent_offset(fs_info, logical + SZ_48K, &len, map_type, 0, &io_stripe); if (ret != -ENODATA) { test_err("lookup of RAID extent [%llu, %llu] succeeded should fail", logical + SZ_48K, logical + SZ_64K); ret = -EINVAL; goto out; } ret = btrfs_delete_raid_extent(trans, logical, len); if (ret) test_err("deleting RAID extent [%llu, %llu] failed", logical, logical + len); out: btrfs_put_bioc(bioc); return ret; } /* * Test a 64K RST write on a 2 disk RAID1 at a logical address of 1M and then * overwrite the whole range giving it new physical address at an offset of 1G. * The intent of this test is to exercise the 'update_raid_extent_item()' * function called be btrfs_insert_one_raid_extent(). */ static int test_create_update_delete(struct btrfs_trans_handle *trans) { struct btrfs_fs_info *fs_info = trans->fs_info; struct btrfs_io_context *bioc; struct btrfs_io_stripe io_stripe = { 0 }; u64 map_type = RST_TEST_RAID1_TYPE; u64 logical = SZ_1M; u64 len = SZ_64K; int ret; bioc = alloc_btrfs_io_context(fs_info, logical, RST_TEST_NUM_DEVICES); if (!bioc) { test_std_err(TEST_ALLOC_IO_CONTEXT); ret = -ENOMEM; goto out; } io_stripe.dev = btrfs_device_by_devid(fs_info->fs_devices, 0); bioc->map_type = map_type; bioc->size = len; for (int i = 0; i < RST_TEST_NUM_DEVICES; i++) { struct btrfs_io_stripe *stripe = &bioc->stripes[i]; stripe->dev = btrfs_device_by_devid(fs_info->fs_devices, i); if (!stripe->dev) { test_err("cannot find device with devid %d", i); ret = -EINVAL; goto out; } stripe->physical = logical + i * SZ_1G; } ret = btrfs_insert_one_raid_extent(trans, bioc); if (ret) { test_err("inserting RAID extent failed: %d", ret); goto out; } io_stripe.dev = btrfs_device_by_devid(fs_info->fs_devices, 0); if (!io_stripe.dev) { ret = -EINVAL; goto out; } ret = btrfs_get_raid_extent_offset(fs_info, logical, &len, map_type, 0, &io_stripe); if (ret) { test_err("lookup of RAID extent [%llu, %llu] failed", logical, logical + len); goto out; } if (io_stripe.physical != logical) { test_err("invalid physical address, expected %llu got %llu", logical, io_stripe.physical); ret = -EINVAL; goto out; } if (len != SZ_64K) { test_err("invalid stripe length, expected %llu got %llu", (u64)SZ_64K, len); ret = -EINVAL; goto out; } for (int i = 0; i < RST_TEST_NUM_DEVICES; i++) { struct btrfs_io_stripe *stripe = &bioc->stripes[i]; stripe->dev = btrfs_device_by_devid(fs_info->fs_devices, i); if (!stripe->dev) { test_err("cannot find device with devid %d", i); ret = -EINVAL; goto out; } stripe->physical = SZ_1G + logical + i * SZ_1G; } ret = btrfs_insert_one_raid_extent(trans, bioc); if (ret) { test_err("updating RAID extent failed: %d", ret); goto out; } ret = btrfs_get_raid_extent_offset(fs_info, logical, &len, map_type, 0, &io_stripe); if (ret) { test_err("lookup of RAID extent [%llu, %llu] failed", logical, logical + len); goto out; } if (io_stripe.physical != logical + SZ_1G) { test_err("invalid physical address, expected %llu, got %llu", logical + SZ_1G, io_stripe.physical); ret = -EINVAL; goto out; } if (len != SZ_64K) { test_err("invalid stripe length, expected %llu, got %llu", (u64)SZ_64K, len); ret = -EINVAL; goto out; } ret = btrfs_delete_raid_extent(trans, logical, len); if (ret) test_err("deleting RAID extent [%llu, %llu] failed", logical, logical + len); out: btrfs_put_bioc(bioc); return ret; } /* * Test a simple 64K RST write on a 2 disk RAID1 at a logical address of 1M. * The "physical" copy on device 0 is at 1M, on device 1 it is at 1G+1M. */ static int test_simple_create_delete(struct btrfs_trans_handle *trans) { struct btrfs_fs_info *fs_info = trans->fs_info; struct btrfs_io_context *bioc; struct btrfs_io_stripe io_stripe = { 0 }; u64 map_type = RST_TEST_RAID1_TYPE; u64 logical = SZ_1M; u64 len = SZ_64K; int ret; bioc = alloc_btrfs_io_context(fs_info, logical, RST_TEST_NUM_DEVICES); if (!bioc) { test_std_err(TEST_ALLOC_IO_CONTEXT); ret = -ENOMEM; goto out; } bioc->map_type = map_type; bioc->size = SZ_64K; for (int i = 0; i < RST_TEST_NUM_DEVICES; i++) { struct btrfs_io_stripe *stripe = &bioc->stripes[i]; stripe->dev = btrfs_device_by_devid(fs_info->fs_devices, i); if (!stripe->dev) { test_err("cannot find device with devid %d", i); ret = -EINVAL; goto out; } stripe->physical = logical + i * SZ_1G; } ret = btrfs_insert_one_raid_extent(trans, bioc); if (ret) { test_err("inserting RAID extent failed: %d", ret); goto out; } io_stripe.dev = btrfs_device_by_devid(fs_info->fs_devices, 0); if (!io_stripe.dev) { ret = -EINVAL; goto out; } ret = btrfs_get_raid_extent_offset(fs_info, logical, &len, map_type, 0, &io_stripe); if (ret) { test_err("lookup of RAID extent [%llu, %llu] failed", logical, logical + len); goto out; } if (io_stripe.physical != logical) { test_err("invalid physical address, expected %llu got %llu", logical, io_stripe.physical); ret = -EINVAL; goto out; } if (len != SZ_64K) { test_err("invalid stripe length, expected %llu got %llu", (u64)SZ_64K, len); ret = -EINVAL; goto out; } ret = btrfs_delete_raid_extent(trans, logical, len); if (ret) test_err("deleting RAID extent [%llu, %llu] failed", logical, logical + len); out: btrfs_put_bioc(bioc); return ret; } static const test_func_t tests[] = { test_simple_create_delete, test_create_update_delete, test_tail_delete, test_front_delete, }; static int run_test(test_func_t test, u32 sectorsize, u32 nodesize) { struct btrfs_trans_handle trans; struct btrfs_fs_info *fs_info; struct btrfs_root *root = NULL; int ret; fs_info = btrfs_alloc_dummy_fs_info(sectorsize, nodesize); if (!fs_info) { test_std_err(TEST_ALLOC_FS_INFO); ret = -ENOMEM; goto out; } root = btrfs_alloc_dummy_root(fs_info); if (IS_ERR(root)) { test_std_err(TEST_ALLOC_ROOT); ret = PTR_ERR(root); goto out; } btrfs_set_super_incompat_flags(root->fs_info->super_copy, BTRFS_FEATURE_INCOMPAT_RAID_STRIPE_TREE); root->root_key.objectid = BTRFS_RAID_STRIPE_TREE_OBJECTID; root->root_key.type = BTRFS_ROOT_ITEM_KEY; root->root_key.offset = 0; fs_info->stripe_root = root; root->fs_info->tree_root = root; root->node = alloc_test_extent_buffer(root->fs_info, nodesize); if (IS_ERR(root->node)) { test_std_err(TEST_ALLOC_EXTENT_BUFFER); ret = PTR_ERR(root->node); goto out; } btrfs_set_header_level(root->node, 0); btrfs_set_header_nritems(root->node, 0); root->alloc_bytenr += 2 * nodesize; for (int i = 0; i < RST_TEST_NUM_DEVICES; i++) { struct btrfs_device *dev; dev = btrfs_alloc_dummy_device(fs_info); if (IS_ERR(dev)) { test_err("cannot allocate device"); ret = PTR_ERR(dev); goto out; } dev->devid = i; } btrfs_init_dummy_trans(&trans, root->fs_info); ret = test(&trans); if (ret) goto out; out: btrfs_free_dummy_root(root); btrfs_free_dummy_fs_info(fs_info); return ret; } int btrfs_test_raid_stripe_tree(u32 sectorsize, u32 nodesize) { int ret = 0; test_msg("running raid-stripe-tree tests"); for (int i = 0; i < ARRAY_SIZE(tests); i++) { ret = run_test(tests[i], sectorsize, nodesize); if (ret) { test_err("test-case %ps failed with %d\n", tests[i], ret); goto out; } } out: return ret; }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
You can’t perform that action at this time.