File Index
Files and directories
Sign in
FILE

btrfs-tests.c

File preview with syntax highlighting.

linux-6.19.14/fs/btrfs/tests/btrfs-tests.c C
  1// SPDX-License-Identifier: GPL-2.0
  2/*
  3 * Copyright (C) 2013 Fusion IO.  All rights reserved.
  4 */
  5
  6#include <linux/fs.h>
  7#include <linux/mount.h>
  8#include <linux/pseudo_fs.h>
  9#include <linux/magic.h>
 10#include "btrfs-tests.h"
 11#include "../ctree.h"
 12#include "../free-space-cache.h"
 13#include "../free-space-tree.h"
 14#include "../transaction.h"
 15#include "../volumes.h"
 16#include "../disk-io.h"
 17#include "../qgroup.h"
 18#include "../block-group.h"
 19#include "../fs.h"
 20
 21static struct vfsmount *test_mnt = NULL;
 22
 23const char *test_error[] = {
 24	[TEST_ALLOC_FS_INFO]	     = "cannot allocate fs_info",
 25	[TEST_ALLOC_ROOT]	     = "cannot allocate root",
 26	[TEST_ALLOC_EXTENT_BUFFER]   = "cannot extent buffer",
 27	[TEST_ALLOC_PATH]	     = "cannot allocate path",
 28	[TEST_ALLOC_INODE]	     = "cannot allocate inode",
 29	[TEST_ALLOC_BLOCK_GROUP]     = "cannot allocate block group",
 30	[TEST_ALLOC_EXTENT_MAP]      = "cannot allocate extent map",
 31	[TEST_ALLOC_CHUNK_MAP]       = "cannot allocate chunk map",
 32	[TEST_ALLOC_IO_CONTEXT]	     = "cannot allocate io context",
 33	[TEST_ALLOC_TRANSACTION]     = "cannot allocate transaction",
 34};
 35
 36static const struct super_operations btrfs_test_super_ops = {
 37	.alloc_inode	= btrfs_alloc_inode,
 38	.destroy_inode	= btrfs_test_destroy_inode,
 39};
 40
 41
 42static int btrfs_test_init_fs_context(struct fs_context *fc)
 43{
 44	struct pseudo_fs_context *ctx = init_pseudo(fc, BTRFS_TEST_MAGIC);
 45	if (!ctx)
 46		return -ENOMEM;
 47	ctx->ops = &btrfs_test_super_ops;
 48	return 0;
 49}
 50
 51static struct file_system_type test_type = {
 52	.name		= "btrfs_test_fs",
 53	.init_fs_context = btrfs_test_init_fs_context,
 54	.kill_sb	= kill_anon_super,
 55};
 56
 57struct inode *btrfs_new_test_inode(void)
 58{
 59	struct inode *inode;
 60
 61	inode = new_inode(test_mnt->mnt_sb);
 62	if (!inode)
 63		return NULL;
 64
 65	inode->i_mode = S_IFREG;
 66	btrfs_set_inode_number(BTRFS_I(inode), BTRFS_FIRST_FREE_OBJECTID);
 67	inode_init_owner(&nop_mnt_idmap, inode, NULL, S_IFREG);
 68
 69	return inode;
 70}
 71
 72static int btrfs_init_test_fs(void)
 73{
 74	int ret;
 75
 76	ret = register_filesystem(&test_type);
 77	if (ret) {
 78		printk(KERN_ERR "btrfs: cannot register test file system\n");
 79		return ret;
 80	}
 81
 82	test_mnt = kern_mount(&test_type);
 83	if (IS_ERR(test_mnt)) {
 84		printk(KERN_ERR "btrfs: cannot mount test file system\n");
 85		unregister_filesystem(&test_type);
 86		return PTR_ERR(test_mnt);
 87	}
 88	return 0;
 89}
 90
 91static void btrfs_destroy_test_fs(void)
 92{
 93	kern_unmount(test_mnt);
 94	unregister_filesystem(&test_type);
 95}
 96
 97struct btrfs_device *btrfs_alloc_dummy_device(struct btrfs_fs_info *fs_info)
 98{
 99	struct btrfs_device *dev;
100
101	dev = kzalloc(sizeof(*dev), GFP_KERNEL);
102	if (!dev)
103		return ERR_PTR(-ENOMEM);
104
105	btrfs_extent_io_tree_init(fs_info, &dev->alloc_state, 0);
106	INIT_LIST_HEAD(&dev->dev_list);
107	list_add(&dev->dev_list, &fs_info->fs_devices->devices);
108
109	return dev;
110}
111
112static void btrfs_free_dummy_device(struct btrfs_device *dev)
113{
114	btrfs_extent_io_tree_release(&dev->alloc_state);
115	kfree(dev);
116}
117
118struct btrfs_fs_info *btrfs_alloc_dummy_fs_info(u32 nodesize, u32 sectorsize)
119{
120	struct btrfs_fs_info *fs_info = kzalloc(sizeof(struct btrfs_fs_info),
121						GFP_KERNEL);
122
123	if (!fs_info)
124		return fs_info;
125	fs_info->fs_devices = kzalloc(sizeof(struct btrfs_fs_devices),
126				      GFP_KERNEL);
127	if (!fs_info->fs_devices) {
128		kfree(fs_info);
129		return NULL;
130	}
131	INIT_LIST_HEAD(&fs_info->fs_devices->devices);
132
133	fs_info->super_copy = kzalloc(sizeof(struct btrfs_super_block),
134				      GFP_KERNEL);
135	if (!fs_info->super_copy) {
136		kfree(fs_info->fs_devices);
137		kfree(fs_info);
138		return NULL;
139	}
140
141	btrfs_init_fs_info(fs_info);
142
143	fs_info->nodesize = nodesize;
144	fs_info->sectorsize = sectorsize;
145	fs_info->sectorsize_bits = ilog2(sectorsize);
146
147	/* CRC32C csum size. */
148	fs_info->csum_size = 4;
149	fs_info->csums_per_leaf = BTRFS_MAX_ITEM_SIZE(fs_info) /
150		fs_info->csum_size;
151	set_bit(BTRFS_FS_STATE_DUMMY_FS_INFO, &fs_info->fs_state);
152
153	test_mnt->mnt_sb->s_fs_info = fs_info;
154
155	return fs_info;
156}
157
158void btrfs_free_dummy_fs_info(struct btrfs_fs_info *fs_info)
159{
160	struct btrfs_device *dev, *tmp;
161	struct extent_buffer *eb;
162	unsigned long index;
163
164	if (!fs_info)
165		return;
166
167	if (WARN_ON(!btrfs_is_testing(fs_info)))
168		return;
169
170	test_mnt->mnt_sb->s_fs_info = NULL;
171
172	xa_lock_irq(&fs_info->buffer_tree);
173	xa_for_each(&fs_info->buffer_tree, index, eb) {
174		xa_unlock_irq(&fs_info->buffer_tree);
175		free_extent_buffer(eb);
176		xa_lock_irq(&fs_info->buffer_tree);
177	}
178	xa_unlock_irq(&fs_info->buffer_tree);
179
180	btrfs_mapping_tree_free(fs_info);
181	list_for_each_entry_safe(dev, tmp, &fs_info->fs_devices->devices,
182				 dev_list) {
183		btrfs_free_dummy_device(dev);
184	}
185	btrfs_free_qgroup_config(fs_info);
186	btrfs_free_fs_roots(fs_info);
187	kfree(fs_info->super_copy);
188	btrfs_check_leaked_roots(fs_info);
189	btrfs_extent_buffer_leak_debug_check(fs_info);
190	kfree(fs_info->fs_devices);
191	kfree(fs_info);
192}
193
194void btrfs_free_dummy_root(struct btrfs_root *root)
195{
196	if (IS_ERR_OR_NULL(root))
197		return;
198	/* Will be freed by btrfs_free_fs_roots */
199	if (WARN_ON(test_bit(BTRFS_ROOT_IN_RADIX, &root->state)))
200		return;
201	btrfs_global_root_delete(root);
202	btrfs_put_root(root);
203}
204
205struct btrfs_block_group *
206btrfs_alloc_dummy_block_group(struct btrfs_fs_info *fs_info,
207			      unsigned long length)
208{
209	struct btrfs_block_group *cache;
210
211	cache = kzalloc(sizeof(*cache), GFP_KERNEL);
212	if (!cache)
213		return NULL;
214	cache->free_space_ctl = kzalloc(sizeof(*cache->free_space_ctl),
215					GFP_KERNEL);
216	if (!cache->free_space_ctl) {
217		kfree(cache);
218		return NULL;
219	}
220
221	cache->start = 0;
222	cache->length = length;
223	cache->full_stripe_len = fs_info->sectorsize;
224	cache->fs_info = fs_info;
225
226	INIT_LIST_HEAD(&cache->list);
227	INIT_LIST_HEAD(&cache->cluster_list);
228	INIT_LIST_HEAD(&cache->bg_list);
229	btrfs_init_free_space_ctl(cache, cache->free_space_ctl);
230	mutex_init(&cache->free_space_lock);
231
232	return cache;
233}
234
235void btrfs_free_dummy_block_group(struct btrfs_block_group *cache)
236{
237	if (!cache)
238		return;
239	btrfs_remove_free_space_cache(cache);
240	kfree(cache->free_space_ctl);
241	kfree(cache);
242}
243
244void btrfs_init_dummy_transaction(struct btrfs_transaction *trans, struct btrfs_fs_info *fs_info)
245{
246	memset(trans, 0, sizeof(*trans));
247	trans->fs_info = fs_info;
248	xa_init(&trans->delayed_refs.head_refs);
249	xa_init(&trans->delayed_refs.dirty_extents);
250	spin_lock_init(&trans->delayed_refs.lock);
251}
252
253void btrfs_init_dummy_trans(struct btrfs_trans_handle *trans,
254			    struct btrfs_fs_info *fs_info)
255{
256	memset(trans, 0, sizeof(*trans));
257	trans->transid = 1;
258	trans->type = __TRANS_DUMMY;
259	trans->fs_info = fs_info;
260}
261
262int btrfs_run_sanity_tests(void)
263{
264	int ret, i;
265	u32 sectorsize, nodesize;
266	u32 test_sectorsize[] = {
267		PAGE_SIZE,
268	};
269	ret = btrfs_init_test_fs();
270	if (ret)
271		return ret;
272	for (i = 0; i < ARRAY_SIZE(test_sectorsize); i++) {
273		sectorsize = test_sectorsize[i];
274		for (nodesize = sectorsize;
275		     nodesize <= BTRFS_MAX_METADATA_BLOCKSIZE;
276		     nodesize <<= 1) {
277			pr_info("BTRFS: selftest: sectorsize: %u  nodesize: %u\n",
278				sectorsize, nodesize);
279			ret = btrfs_test_free_space_cache(sectorsize, nodesize);
280			if (ret)
281				goto out;
282			ret = btrfs_test_extent_buffer_operations(sectorsize,
283				nodesize);
284			if (ret)
285				goto out;
286			ret = btrfs_test_extent_io(sectorsize, nodesize);
287			if (ret)
288				goto out;
289			ret = btrfs_test_inodes(sectorsize, nodesize);
290			if (ret)
291				goto out;
292			ret = btrfs_test_qgroups(sectorsize, nodesize);
293			if (ret)
294				goto out;
295			ret = btrfs_test_free_space_tree(sectorsize, nodesize);
296			if (ret)
297				goto out;
298			ret = btrfs_test_raid_stripe_tree(sectorsize, nodesize);
299			if (ret)
300				goto out;
301			ret = btrfs_test_delayed_refs(sectorsize, nodesize);
302			if (ret)
303				goto out;
304		}
305	}
306	ret = btrfs_test_extent_map();
307
308out:
309	btrfs_destroy_test_fs();
310	return ret;
311}
~/ Read-only file preview.