2018-04-03 17:23:33 +00:00
|
|
|
// SPDX-License-Identifier: GPL-2.0
|
2013-10-09 16:00:56 +00:00
|
|
|
/*
|
|
|
|
* Copyright (C) 2013 Fusion IO. All rights reserved.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <linux/fs.h>
|
|
|
|
#include <linux/mount.h>
|
2019-03-25 16:38:25 +00:00
|
|
|
#include <linux/pseudo_fs.h>
|
2013-10-09 16:00:56 +00:00
|
|
|
#include <linux/magic.h>
|
|
|
|
#include "btrfs-tests.h"
|
|
|
|
#include "../ctree.h"
|
2015-09-30 03:50:36 +00:00
|
|
|
#include "../free-space-cache.h"
|
|
|
|
#include "../free-space-tree.h"
|
|
|
|
#include "../transaction.h"
|
2014-05-07 21:06:09 +00:00
|
|
|
#include "../volumes.h"
|
|
|
|
#include "../disk-io.h"
|
|
|
|
#include "../qgroup.h"
|
2019-06-20 19:37:44 +00:00
|
|
|
#include "../block-group.h"
|
2022-10-19 14:50:51 +00:00
|
|
|
#include "../fs.h"
|
2013-10-09 16:00:56 +00:00
|
|
|
|
|
|
|
static struct vfsmount *test_mnt = NULL;
|
|
|
|
|
2019-03-15 16:23:30 +00:00
|
|
|
const char *test_error[] = {
|
|
|
|
[TEST_ALLOC_FS_INFO] = "cannot allocate fs_info",
|
|
|
|
[TEST_ALLOC_ROOT] = "cannot allocate root",
|
|
|
|
[TEST_ALLOC_EXTENT_BUFFER] = "cannot extent buffer",
|
|
|
|
[TEST_ALLOC_PATH] = "cannot allocate path",
|
|
|
|
[TEST_ALLOC_INODE] = "cannot allocate inode",
|
|
|
|
[TEST_ALLOC_BLOCK_GROUP] = "cannot allocate block group",
|
|
|
|
[TEST_ALLOC_EXTENT_MAP] = "cannot allocate extent map",
|
btrfs: use a dedicated data structure for chunk maps
Currently we abuse the extent_map structure for two purposes:
1) To actually represent extents for inodes;
2) To represent chunk mappings.
This is odd and has several disadvantages:
1) To create a chunk map, we need to do two memory allocations: one for
an extent_map structure and another one for a map_lookup structure, so
more potential for an allocation failure and more complicated code to
manage and link two structures;
2) For a chunk map we actually only use 3 fields (24 bytes) of the
respective extent map structure: the 'start' field to have the logical
start address of the chunk, the 'len' field to have the chunk's size,
and the 'orig_block_len' field to contain the chunk's stripe size.
Besides wasting a memory, it's also odd and not intuitive at all to
have the stripe size in a field named 'orig_block_len'.
We are also using 'block_len' of the extent_map structure to contain
the chunk size, so we have 2 fields for the same value, 'len' and
'block_len', which is pointless;
3) When an extent map is associated to a chunk mapping, we set the bit
EXTENT_FLAG_FS_MAPPING on its flags and then make its member named
'map_lookup' point to the associated map_lookup structure. This means
that for an extent map associated to an inode extent, we are not using
this 'map_lookup' pointer, so wasting 8 bytes (on a 64 bits platform);
4) Extent maps associated to a chunk mapping are never merged or split so
it's pointless to use the existing extent map infrastructure.
So add a dedicated data structure named 'btrfs_chunk_map' to represent
chunk mappings, this is basically the existing map_lookup structure with
some extra fields:
1) 'start' to contain the chunk logical address;
2) 'chunk_len' to contain the chunk's length;
3) 'stripe_size' for the stripe size;
4) 'rb_node' for insertion into a rb tree;
5) 'refs' for reference counting.
This way we do a single memory allocation for chunk mappings and we don't
waste memory for them with unused/unnecessary fields from an extent_map.
We also save 8 bytes from the extent_map structure by removing the
'map_lookup' pointer, so the size of struct extent_map is reduced from
144 bytes down to 136 bytes, and we can now have 30 extents map per 4K
page instead of 28.
Reviewed-by: Josef Bacik <josef@toxicpanda.com>
Signed-off-by: Filipe Manana <fdmanana@suse.com>
Reviewed-by: David Sterba <dsterba@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
2023-11-21 13:38:38 +00:00
|
|
|
[TEST_ALLOC_CHUNK_MAP] = "cannot allocate chunk map",
|
2024-10-02 10:11:48 +00:00
|
|
|
[TEST_ALLOC_IO_CONTEXT] = "cannot allocate io context",
|
2024-11-14 15:03:34 +00:00
|
|
|
[TEST_ALLOC_TRANSACTION] = "cannot allocate transaction",
|
2019-03-15 16:23:30 +00:00
|
|
|
};
|
|
|
|
|
2013-10-11 18:44:09 +00:00
|
|
|
static const struct super_operations btrfs_test_super_ops = {
|
|
|
|
.alloc_inode = btrfs_alloc_inode,
|
|
|
|
.destroy_inode = btrfs_test_destroy_inode,
|
|
|
|
};
|
|
|
|
|
2019-03-25 16:38:25 +00:00
|
|
|
|
|
|
|
static int btrfs_test_init_fs_context(struct fs_context *fc)
|
2013-10-09 16:00:56 +00:00
|
|
|
{
|
2019-03-25 16:38:25 +00:00
|
|
|
struct pseudo_fs_context *ctx = init_pseudo(fc, BTRFS_TEST_MAGIC);
|
|
|
|
if (!ctx)
|
|
|
|
return -ENOMEM;
|
|
|
|
ctx->ops = &btrfs_test_super_ops;
|
|
|
|
return 0;
|
2013-10-09 16:00:56 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static struct file_system_type test_type = {
|
|
|
|
.name = "btrfs_test_fs",
|
2019-03-25 16:38:25 +00:00
|
|
|
.init_fs_context = btrfs_test_init_fs_context,
|
2013-10-09 16:00:56 +00:00
|
|
|
.kill_sb = kill_anon_super,
|
|
|
|
};
|
|
|
|
|
|
|
|
struct inode *btrfs_new_test_inode(void)
|
|
|
|
{
|
Btrfs: fix selftests failure due to uninitialized i_mode in test inodes
Some of the self tests create a test inode, setup some extents and then do
calls to btrfs_get_extent() to test that the corresponding extent maps
exist and are correct. However btrfs_get_extent(), since the 5.2 merge
window, now errors out when it finds a regular or prealloc extent for an
inode that does not correspond to a regular file (its ->i_mode is not
S_IFREG). This causes the self tests to fail sometimes, specially when
KASAN, slub_debug and page poisoning are enabled:
$ modprobe btrfs
modprobe: ERROR: could not insert 'btrfs': Invalid argument
$ dmesg
[ 9414.691648] Btrfs loaded, crc32c=crc32c-intel, debug=on, assert=on, integrity-checker=on, ref-verify=on
[ 9414.692655] BTRFS: selftest: sectorsize: 4096 nodesize: 4096
[ 9414.692658] BTRFS: selftest: running btrfs free space cache tests
[ 9414.692918] BTRFS: selftest: running extent only tests
[ 9414.693061] BTRFS: selftest: running bitmap only tests
[ 9414.693366] BTRFS: selftest: running bitmap and extent tests
[ 9414.696455] BTRFS: selftest: running space stealing from bitmap to extent tests
[ 9414.697131] BTRFS: selftest: running extent buffer operation tests
[ 9414.697133] BTRFS: selftest: running btrfs_split_item tests
[ 9414.697564] BTRFS: selftest: running extent I/O tests
[ 9414.697583] BTRFS: selftest: running find delalloc tests
[ 9415.081125] BTRFS: selftest: running find_first_clear_extent_bit test
[ 9415.081278] BTRFS: selftest: running extent buffer bitmap tests
[ 9415.124192] BTRFS: selftest: running inode tests
[ 9415.124195] BTRFS: selftest: running btrfs_get_extent tests
[ 9415.127909] BTRFS: selftest: running hole first btrfs_get_extent test
[ 9415.128343] BTRFS critical (device (efault)): regular/prealloc extent found for non-regular inode 256
[ 9415.131428] BTRFS: selftest: fs/btrfs/tests/inode-tests.c:904 expected a real extent, got 0
This happens because the test inodes are created without ever initializing
the i_mode field of the inode, and neither VFS's new_inode() nor the btrfs
callback btrfs_alloc_inode() initialize the i_mode. Initialization of the
i_mode is done through the various callbacks used by the VFS to create
new inodes (regular files, directories, symlinks, tmpfiles, etc), which
all call btrfs_new_inode() which in turn calls inode_init_owner(), which
sets the inode's i_mode. Since the tests only uses new_inode() to create
the test inodes, the i_mode was never initialized.
This always happens on a VM I used with kasan, slub_debug and many other
debug facilities enabled. It also happened to someone who reported this
on bugzilla (on a 5.3-rc).
Fix this by setting i_mode to S_IFREG at btrfs_new_test_inode().
Fixes: 6bf9e4bd6a2778 ("btrfs: inode: Verify inode mode to avoid NULL pointer dereference")
Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=204397
Signed-off-by: Filipe Manana <fdmanana@suse.com>
Reviewed-by: Qu Wenruo <wqu@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
2019-09-18 12:08:52 +00:00
|
|
|
struct inode *inode;
|
|
|
|
|
|
|
|
inode = new_inode(test_mnt->mnt_sb);
|
2020-12-15 17:00:26 +00:00
|
|
|
if (!inode)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
inode->i_mode = S_IFREG;
|
2024-05-05 12:47:02 +00:00
|
|
|
btrfs_set_inode_number(BTRFS_I(inode), BTRFS_FIRST_FREE_OBJECTID);
|
2023-01-13 11:49:25 +00:00
|
|
|
inode_init_owner(&nop_mnt_idmap, inode, NULL, S_IFREG);
|
Btrfs: fix selftests failure due to uninitialized i_mode in test inodes
Some of the self tests create a test inode, setup some extents and then do
calls to btrfs_get_extent() to test that the corresponding extent maps
exist and are correct. However btrfs_get_extent(), since the 5.2 merge
window, now errors out when it finds a regular or prealloc extent for an
inode that does not correspond to a regular file (its ->i_mode is not
S_IFREG). This causes the self tests to fail sometimes, specially when
KASAN, slub_debug and page poisoning are enabled:
$ modprobe btrfs
modprobe: ERROR: could not insert 'btrfs': Invalid argument
$ dmesg
[ 9414.691648] Btrfs loaded, crc32c=crc32c-intel, debug=on, assert=on, integrity-checker=on, ref-verify=on
[ 9414.692655] BTRFS: selftest: sectorsize: 4096 nodesize: 4096
[ 9414.692658] BTRFS: selftest: running btrfs free space cache tests
[ 9414.692918] BTRFS: selftest: running extent only tests
[ 9414.693061] BTRFS: selftest: running bitmap only tests
[ 9414.693366] BTRFS: selftest: running bitmap and extent tests
[ 9414.696455] BTRFS: selftest: running space stealing from bitmap to extent tests
[ 9414.697131] BTRFS: selftest: running extent buffer operation tests
[ 9414.697133] BTRFS: selftest: running btrfs_split_item tests
[ 9414.697564] BTRFS: selftest: running extent I/O tests
[ 9414.697583] BTRFS: selftest: running find delalloc tests
[ 9415.081125] BTRFS: selftest: running find_first_clear_extent_bit test
[ 9415.081278] BTRFS: selftest: running extent buffer bitmap tests
[ 9415.124192] BTRFS: selftest: running inode tests
[ 9415.124195] BTRFS: selftest: running btrfs_get_extent tests
[ 9415.127909] BTRFS: selftest: running hole first btrfs_get_extent test
[ 9415.128343] BTRFS critical (device (efault)): regular/prealloc extent found for non-regular inode 256
[ 9415.131428] BTRFS: selftest: fs/btrfs/tests/inode-tests.c:904 expected a real extent, got 0
This happens because the test inodes are created without ever initializing
the i_mode field of the inode, and neither VFS's new_inode() nor the btrfs
callback btrfs_alloc_inode() initialize the i_mode. Initialization of the
i_mode is done through the various callbacks used by the VFS to create
new inodes (regular files, directories, symlinks, tmpfiles, etc), which
all call btrfs_new_inode() which in turn calls inode_init_owner(), which
sets the inode's i_mode. Since the tests only uses new_inode() to create
the test inodes, the i_mode was never initialized.
This always happens on a VM I used with kasan, slub_debug and many other
debug facilities enabled. It also happened to someone who reported this
on bugzilla (on a 5.3-rc).
Fix this by setting i_mode to S_IFREG at btrfs_new_test_inode().
Fixes: 6bf9e4bd6a2778 ("btrfs: inode: Verify inode mode to avoid NULL pointer dereference")
Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=204397
Signed-off-by: Filipe Manana <fdmanana@suse.com>
Reviewed-by: Qu Wenruo <wqu@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
2019-09-18 12:08:52 +00:00
|
|
|
|
|
|
|
return inode;
|
2013-10-09 16:00:56 +00:00
|
|
|
}
|
|
|
|
|
2016-06-20 17:16:40 +00:00
|
|
|
static int btrfs_init_test_fs(void)
|
2013-10-09 16:00:56 +00:00
|
|
|
{
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
ret = register_filesystem(&test_type);
|
|
|
|
if (ret) {
|
|
|
|
printk(KERN_ERR "btrfs: cannot register test file system\n");
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
test_mnt = kern_mount(&test_type);
|
|
|
|
if (IS_ERR(test_mnt)) {
|
|
|
|
printk(KERN_ERR "btrfs: cannot mount test file system\n");
|
|
|
|
unregister_filesystem(&test_type);
|
2016-06-17 17:20:40 +00:00
|
|
|
return PTR_ERR(test_mnt);
|
2013-10-09 16:00:56 +00:00
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2016-06-20 17:16:40 +00:00
|
|
|
static void btrfs_destroy_test_fs(void)
|
2013-10-09 16:00:56 +00:00
|
|
|
{
|
|
|
|
kern_unmount(test_mnt);
|
|
|
|
unregister_filesystem(&test_type);
|
|
|
|
}
|
2014-05-07 21:06:09 +00:00
|
|
|
|
2019-11-19 12:05:51 +00:00
|
|
|
struct btrfs_device *btrfs_alloc_dummy_device(struct btrfs_fs_info *fs_info)
|
|
|
|
{
|
|
|
|
struct btrfs_device *dev;
|
|
|
|
|
|
|
|
dev = kzalloc(sizeof(*dev), GFP_KERNEL);
|
|
|
|
if (!dev)
|
|
|
|
return ERR_PTR(-ENOMEM);
|
|
|
|
|
2025-04-04 11:17:13 +00:00
|
|
|
btrfs_extent_io_tree_init(fs_info, &dev->alloc_state, 0);
|
2019-11-19 12:05:51 +00:00
|
|
|
INIT_LIST_HEAD(&dev->dev_list);
|
|
|
|
list_add(&dev->dev_list, &fs_info->fs_devices->devices);
|
|
|
|
|
|
|
|
return dev;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void btrfs_free_dummy_device(struct btrfs_device *dev)
|
|
|
|
{
|
2025-04-04 11:17:13 +00:00
|
|
|
btrfs_extent_io_tree_release(&dev->alloc_state);
|
2019-11-19 12:05:51 +00:00
|
|
|
kfree(dev);
|
|
|
|
}
|
|
|
|
|
2016-06-15 13:22:56 +00:00
|
|
|
struct btrfs_fs_info *btrfs_alloc_dummy_fs_info(u32 nodesize, u32 sectorsize)
|
2014-05-07 21:06:09 +00:00
|
|
|
{
|
|
|
|
struct btrfs_fs_info *fs_info = kzalloc(sizeof(struct btrfs_fs_info),
|
2016-01-22 09:28:24 +00:00
|
|
|
GFP_KERNEL);
|
2014-05-07 21:06:09 +00:00
|
|
|
|
|
|
|
if (!fs_info)
|
|
|
|
return fs_info;
|
|
|
|
fs_info->fs_devices = kzalloc(sizeof(struct btrfs_fs_devices),
|
2016-01-22 09:28:24 +00:00
|
|
|
GFP_KERNEL);
|
2014-05-07 21:06:09 +00:00
|
|
|
if (!fs_info->fs_devices) {
|
|
|
|
kfree(fs_info);
|
|
|
|
return NULL;
|
|
|
|
}
|
2020-01-24 14:32:59 +00:00
|
|
|
INIT_LIST_HEAD(&fs_info->fs_devices->devices);
|
|
|
|
|
2014-05-07 21:06:09 +00:00
|
|
|
fs_info->super_copy = kzalloc(sizeof(struct btrfs_super_block),
|
2016-01-22 09:28:24 +00:00
|
|
|
GFP_KERNEL);
|
2014-05-07 21:06:09 +00:00
|
|
|
if (!fs_info->super_copy) {
|
|
|
|
kfree(fs_info->fs_devices);
|
|
|
|
kfree(fs_info);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2020-01-24 14:32:59 +00:00
|
|
|
btrfs_init_fs_info(fs_info);
|
|
|
|
|
2016-06-15 13:22:56 +00:00
|
|
|
fs_info->nodesize = nodesize;
|
|
|
|
fs_info->sectorsize = sectorsize;
|
2020-07-01 18:45:04 +00:00
|
|
|
fs_info->sectorsize_bits = ilog2(sectorsize);
|
2024-11-14 15:03:34 +00:00
|
|
|
|
|
|
|
/* CRC32C csum size. */
|
|
|
|
fs_info->csum_size = 4;
|
|
|
|
fs_info->csums_per_leaf = BTRFS_MAX_ITEM_SIZE(fs_info) /
|
|
|
|
fs_info->csum_size;
|
2016-06-20 18:14:09 +00:00
|
|
|
set_bit(BTRFS_FS_STATE_DUMMY_FS_INFO, &fs_info->fs_state);
|
|
|
|
|
|
|
|
test_mnt->mnt_sb->s_fs_info = fs_info;
|
|
|
|
|
2014-05-07 21:06:09 +00:00
|
|
|
return fs_info;
|
|
|
|
}
|
|
|
|
|
2016-06-20 18:14:09 +00:00
|
|
|
void btrfs_free_dummy_fs_info(struct btrfs_fs_info *fs_info)
|
2014-05-07 21:06:09 +00:00
|
|
|
{
|
2019-11-19 12:05:51 +00:00
|
|
|
struct btrfs_device *dev, *tmp;
|
2025-04-28 14:52:55 +00:00
|
|
|
struct extent_buffer *eb;
|
|
|
|
unsigned long index;
|
2014-05-07 21:06:09 +00:00
|
|
|
|
2016-06-20 18:14:09 +00:00
|
|
|
if (!fs_info)
|
|
|
|
return;
|
|
|
|
|
2024-04-17 22:47:13 +00:00
|
|
|
if (WARN_ON(!btrfs_is_testing(fs_info)))
|
2016-06-20 18:14:09 +00:00
|
|
|
return;
|
|
|
|
|
|
|
|
test_mnt->mnt_sb->s_fs_info = NULL;
|
|
|
|
|
2025-04-28 14:52:55 +00:00
|
|
|
xa_lock_irq(&fs_info->buffer_tree);
|
|
|
|
xa_for_each(&fs_info->buffer_tree, index, eb) {
|
|
|
|
xa_unlock_irq(&fs_info->buffer_tree);
|
|
|
|
free_extent_buffer(eb);
|
|
|
|
xa_lock_irq(&fs_info->buffer_tree);
|
2014-05-07 21:06:09 +00:00
|
|
|
}
|
2025-04-28 14:52:55 +00:00
|
|
|
xa_unlock_irq(&fs_info->buffer_tree);
|
2014-05-07 21:06:09 +00:00
|
|
|
|
btrfs: use a dedicated data structure for chunk maps
Currently we abuse the extent_map structure for two purposes:
1) To actually represent extents for inodes;
2) To represent chunk mappings.
This is odd and has several disadvantages:
1) To create a chunk map, we need to do two memory allocations: one for
an extent_map structure and another one for a map_lookup structure, so
more potential for an allocation failure and more complicated code to
manage and link two structures;
2) For a chunk map we actually only use 3 fields (24 bytes) of the
respective extent map structure: the 'start' field to have the logical
start address of the chunk, the 'len' field to have the chunk's size,
and the 'orig_block_len' field to contain the chunk's stripe size.
Besides wasting a memory, it's also odd and not intuitive at all to
have the stripe size in a field named 'orig_block_len'.
We are also using 'block_len' of the extent_map structure to contain
the chunk size, so we have 2 fields for the same value, 'len' and
'block_len', which is pointless;
3) When an extent map is associated to a chunk mapping, we set the bit
EXTENT_FLAG_FS_MAPPING on its flags and then make its member named
'map_lookup' point to the associated map_lookup structure. This means
that for an extent map associated to an inode extent, we are not using
this 'map_lookup' pointer, so wasting 8 bytes (on a 64 bits platform);
4) Extent maps associated to a chunk mapping are never merged or split so
it's pointless to use the existing extent map infrastructure.
So add a dedicated data structure named 'btrfs_chunk_map' to represent
chunk mappings, this is basically the existing map_lookup structure with
some extra fields:
1) 'start' to contain the chunk logical address;
2) 'chunk_len' to contain the chunk's length;
3) 'stripe_size' for the stripe size;
4) 'rb_node' for insertion into a rb tree;
5) 'refs' for reference counting.
This way we do a single memory allocation for chunk mappings and we don't
waste memory for them with unused/unnecessary fields from an extent_map.
We also save 8 bytes from the extent_map structure by removing the
'map_lookup' pointer, so the size of struct extent_map is reduced from
144 bytes down to 136 bytes, and we can now have 30 extents map per 4K
page instead of 28.
Reviewed-by: Josef Bacik <josef@toxicpanda.com>
Signed-off-by: Filipe Manana <fdmanana@suse.com>
Reviewed-by: David Sterba <dsterba@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
2023-11-21 13:38:38 +00:00
|
|
|
btrfs_mapping_tree_free(fs_info);
|
2019-11-19 12:05:51 +00:00
|
|
|
list_for_each_entry_safe(dev, tmp, &fs_info->fs_devices->devices,
|
|
|
|
dev_list) {
|
|
|
|
btrfs_free_dummy_device(dev);
|
|
|
|
}
|
2014-05-07 21:06:09 +00:00
|
|
|
btrfs_free_qgroup_config(fs_info);
|
|
|
|
btrfs_free_fs_roots(fs_info);
|
|
|
|
kfree(fs_info->super_copy);
|
2020-01-24 14:33:00 +00:00
|
|
|
btrfs_check_leaked_roots(fs_info);
|
2020-02-14 21:11:42 +00:00
|
|
|
btrfs_extent_buffer_leak_debug_check(fs_info);
|
2014-05-07 21:06:09 +00:00
|
|
|
kfree(fs_info->fs_devices);
|
|
|
|
kfree(fs_info);
|
|
|
|
}
|
|
|
|
|
|
|
|
void btrfs_free_dummy_root(struct btrfs_root *root)
|
|
|
|
{
|
2022-11-01 02:53:54 +00:00
|
|
|
if (IS_ERR_OR_NULL(root))
|
2014-05-07 21:06:09 +00:00
|
|
|
return;
|
2016-06-20 18:14:09 +00:00
|
|
|
/* Will be freed by btrfs_free_fs_roots */
|
2022-07-15 11:59:21 +00:00
|
|
|
if (WARN_ON(test_bit(BTRFS_ROOT_IN_RADIX, &root->state)))
|
2016-06-20 18:14:09 +00:00
|
|
|
return;
|
2021-11-05 20:45:51 +00:00
|
|
|
btrfs_global_root_delete(root);
|
2020-01-24 14:33:01 +00:00
|
|
|
btrfs_put_root(root);
|
2014-05-07 21:06:09 +00:00
|
|
|
}
|
|
|
|
|
2019-10-29 18:20:18 +00:00
|
|
|
struct btrfs_block_group *
|
2016-06-15 13:22:56 +00:00
|
|
|
btrfs_alloc_dummy_block_group(struct btrfs_fs_info *fs_info,
|
|
|
|
unsigned long length)
|
2015-09-30 03:50:36 +00:00
|
|
|
{
|
2019-10-29 18:20:18 +00:00
|
|
|
struct btrfs_block_group *cache;
|
2015-09-30 03:50:36 +00:00
|
|
|
|
2016-01-22 09:28:24 +00:00
|
|
|
cache = kzalloc(sizeof(*cache), GFP_KERNEL);
|
2015-09-30 03:50:36 +00:00
|
|
|
if (!cache)
|
|
|
|
return NULL;
|
|
|
|
cache->free_space_ctl = kzalloc(sizeof(*cache->free_space_ctl),
|
2016-01-22 09:28:24 +00:00
|
|
|
GFP_KERNEL);
|
2015-09-30 03:50:36 +00:00
|
|
|
if (!cache->free_space_ctl) {
|
|
|
|
kfree(cache);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2019-10-23 16:48:22 +00:00
|
|
|
cache->start = 0;
|
|
|
|
cache->length = length;
|
2016-06-15 13:22:56 +00:00
|
|
|
cache->full_stripe_len = fs_info->sectorsize;
|
|
|
|
cache->fs_info = fs_info;
|
2015-09-30 03:50:36 +00:00
|
|
|
|
|
|
|
INIT_LIST_HEAD(&cache->list);
|
|
|
|
INIT_LIST_HEAD(&cache->cluster_list);
|
|
|
|
INIT_LIST_HEAD(&cache->bg_list);
|
2020-10-23 13:58:08 +00:00
|
|
|
btrfs_init_free_space_ctl(cache, cache->free_space_ctl);
|
2015-09-30 03:50:36 +00:00
|
|
|
mutex_init(&cache->free_space_lock);
|
|
|
|
|
|
|
|
return cache;
|
|
|
|
}
|
|
|
|
|
2019-10-29 18:20:18 +00:00
|
|
|
void btrfs_free_dummy_block_group(struct btrfs_block_group *cache)
|
2015-09-30 03:50:36 +00:00
|
|
|
{
|
|
|
|
if (!cache)
|
|
|
|
return;
|
2022-08-08 20:10:27 +00:00
|
|
|
btrfs_remove_free_space_cache(cache);
|
2015-09-30 03:50:36 +00:00
|
|
|
kfree(cache->free_space_ctl);
|
|
|
|
kfree(cache);
|
|
|
|
}
|
|
|
|
|
2024-11-14 15:03:34 +00:00
|
|
|
void btrfs_init_dummy_transaction(struct btrfs_transaction *trans, struct btrfs_fs_info *fs_info)
|
|
|
|
{
|
|
|
|
memset(trans, 0, sizeof(*trans));
|
|
|
|
trans->fs_info = fs_info;
|
|
|
|
xa_init(&trans->delayed_refs.head_refs);
|
|
|
|
xa_init(&trans->delayed_refs.dirty_extents);
|
|
|
|
spin_lock_init(&trans->delayed_refs.lock);
|
|
|
|
}
|
|
|
|
|
2018-05-10 12:44:40 +00:00
|
|
|
void btrfs_init_dummy_trans(struct btrfs_trans_handle *trans,
|
|
|
|
struct btrfs_fs_info *fs_info)
|
2015-09-30 03:50:36 +00:00
|
|
|
{
|
|
|
|
memset(trans, 0, sizeof(*trans));
|
|
|
|
trans->transid = 1;
|
|
|
|
trans->type = __TRANS_DUMMY;
|
2018-05-10 12:44:40 +00:00
|
|
|
trans->fs_info = fs_info;
|
2015-09-30 03:50:36 +00:00
|
|
|
}
|
2016-06-20 17:16:40 +00:00
|
|
|
|
|
|
|
int btrfs_run_sanity_tests(void)
|
|
|
|
{
|
|
|
|
int ret, i;
|
|
|
|
u32 sectorsize, nodesize;
|
|
|
|
u32 test_sectorsize[] = {
|
|
|
|
PAGE_SIZE,
|
|
|
|
};
|
|
|
|
ret = btrfs_init_test_fs();
|
|
|
|
if (ret)
|
|
|
|
return ret;
|
|
|
|
for (i = 0; i < ARRAY_SIZE(test_sectorsize); i++) {
|
|
|
|
sectorsize = test_sectorsize[i];
|
|
|
|
for (nodesize = sectorsize;
|
|
|
|
nodesize <= BTRFS_MAX_METADATA_BLOCKSIZE;
|
|
|
|
nodesize <<= 1) {
|
|
|
|
pr_info("BTRFS: selftest: sectorsize: %u nodesize: %u\n",
|
|
|
|
sectorsize, nodesize);
|
|
|
|
ret = btrfs_test_free_space_cache(sectorsize, nodesize);
|
|
|
|
if (ret)
|
|
|
|
goto out;
|
|
|
|
ret = btrfs_test_extent_buffer_operations(sectorsize,
|
|
|
|
nodesize);
|
|
|
|
if (ret)
|
|
|
|
goto out;
|
|
|
|
ret = btrfs_test_extent_io(sectorsize, nodesize);
|
|
|
|
if (ret)
|
|
|
|
goto out;
|
|
|
|
ret = btrfs_test_inodes(sectorsize, nodesize);
|
|
|
|
if (ret)
|
|
|
|
goto out;
|
|
|
|
ret = btrfs_test_qgroups(sectorsize, nodesize);
|
|
|
|
if (ret)
|
|
|
|
goto out;
|
|
|
|
ret = btrfs_test_free_space_tree(sectorsize, nodesize);
|
|
|
|
if (ret)
|
|
|
|
goto out;
|
2024-10-02 10:11:48 +00:00
|
|
|
ret = btrfs_test_raid_stripe_tree(sectorsize, nodesize);
|
|
|
|
if (ret)
|
|
|
|
goto out;
|
2024-11-14 15:03:34 +00:00
|
|
|
ret = btrfs_test_delayed_refs(sectorsize, nodesize);
|
|
|
|
if (ret)
|
|
|
|
goto out;
|
2016-06-20 17:16:40 +00:00
|
|
|
}
|
|
|
|
}
|
2018-01-05 19:51:12 +00:00
|
|
|
ret = btrfs_test_extent_map();
|
2018-01-12 16:52:58 +00:00
|
|
|
|
2016-06-20 17:16:40 +00:00
|
|
|
out:
|
|
|
|
btrfs_destroy_test_fs();
|
|
|
|
return ret;
|
|
|
|
}
|