linux/fs/btrfs/tests/btrfs-tests.c
<<
>>
Prefs
   1/*
   2 * Copyright (C) 2013 Fusion IO.  All rights reserved.
   3 *
   4 * This program is free software; you can redistribute it and/or
   5 * modify it under the terms of the GNU General Public
   6 * License v2 as published by the Free Software Foundation.
   7 *
   8 * This program is distributed in the hope that it will be useful,
   9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  11 * General Public License for more details.
  12 *
  13 * You should have received a copy of the GNU General Public
  14 * License along with this program; if not, write to the
  15 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
  16 * Boston, MA 021110-1307, USA.
  17 */
  18
  19#include <linux/fs.h>
  20#include <linux/mount.h>
  21#include <linux/magic.h>
  22#include "btrfs-tests.h"
  23#include "../ctree.h"
  24#include "../volumes.h"
  25#include "../disk-io.h"
  26#include "../qgroup.h"
  27
  28static struct vfsmount *test_mnt = NULL;
  29
  30static const struct super_operations btrfs_test_super_ops = {
  31        .alloc_inode    = btrfs_alloc_inode,
  32        .destroy_inode  = btrfs_test_destroy_inode,
  33};
  34
  35static struct dentry *btrfs_test_mount(struct file_system_type *fs_type,
  36                                       int flags, const char *dev_name,
  37                                       void *data)
  38{
  39        return mount_pseudo(fs_type, "btrfs_test:", &btrfs_test_super_ops,
  40                            NULL, BTRFS_TEST_MAGIC);
  41}
  42
  43static struct file_system_type test_type = {
  44        .name           = "btrfs_test_fs",
  45        .mount          = btrfs_test_mount,
  46        .kill_sb        = kill_anon_super,
  47};
  48
  49struct inode *btrfs_new_test_inode(void)
  50{
  51        return new_inode(test_mnt->mnt_sb);
  52}
  53
  54int btrfs_init_test_fs(void)
  55{
  56        int ret;
  57
  58        ret = register_filesystem(&test_type);
  59        if (ret) {
  60                printk(KERN_ERR "btrfs: cannot register test file system\n");
  61                return ret;
  62        }
  63
  64        test_mnt = kern_mount(&test_type);
  65        if (IS_ERR(test_mnt)) {
  66                printk(KERN_ERR "btrfs: cannot mount test file system\n");
  67                unregister_filesystem(&test_type);
  68                return ret;
  69        }
  70        return 0;
  71}
  72
  73void btrfs_destroy_test_fs(void)
  74{
  75        kern_unmount(test_mnt);
  76        unregister_filesystem(&test_type);
  77}
  78
  79struct btrfs_fs_info *btrfs_alloc_dummy_fs_info(void)
  80{
  81        struct btrfs_fs_info *fs_info = kzalloc(sizeof(struct btrfs_fs_info),
  82                                                GFP_NOFS);
  83
  84        if (!fs_info)
  85                return fs_info;
  86        fs_info->fs_devices = kzalloc(sizeof(struct btrfs_fs_devices),
  87                                      GFP_NOFS);
  88        if (!fs_info->fs_devices) {
  89                kfree(fs_info);
  90                return NULL;
  91        }
  92        fs_info->super_copy = kzalloc(sizeof(struct btrfs_super_block),
  93                                      GFP_NOFS);
  94        if (!fs_info->super_copy) {
  95                kfree(fs_info->fs_devices);
  96                kfree(fs_info);
  97                return NULL;
  98        }
  99
 100        if (init_srcu_struct(&fs_info->subvol_srcu)) {
 101                kfree(fs_info->fs_devices);
 102                kfree(fs_info->super_copy);
 103                kfree(fs_info);
 104                return NULL;
 105        }
 106
 107        spin_lock_init(&fs_info->buffer_lock);
 108        spin_lock_init(&fs_info->qgroup_lock);
 109        spin_lock_init(&fs_info->qgroup_op_lock);
 110        spin_lock_init(&fs_info->super_lock);
 111        spin_lock_init(&fs_info->fs_roots_radix_lock);
 112        spin_lock_init(&fs_info->tree_mod_seq_lock);
 113        mutex_init(&fs_info->qgroup_ioctl_lock);
 114        mutex_init(&fs_info->qgroup_rescan_lock);
 115        rwlock_init(&fs_info->tree_mod_log_lock);
 116        fs_info->running_transaction = NULL;
 117        fs_info->qgroup_tree = RB_ROOT;
 118        fs_info->qgroup_ulist = NULL;
 119        atomic64_set(&fs_info->tree_mod_seq, 0);
 120        INIT_LIST_HEAD(&fs_info->dirty_qgroups);
 121        INIT_LIST_HEAD(&fs_info->dead_roots);
 122        INIT_LIST_HEAD(&fs_info->tree_mod_seq_list);
 123        INIT_RADIX_TREE(&fs_info->buffer_radix, GFP_ATOMIC);
 124        INIT_RADIX_TREE(&fs_info->fs_roots_radix, GFP_ATOMIC);
 125        return fs_info;
 126}
 127
 128static void btrfs_free_dummy_fs_info(struct btrfs_fs_info *fs_info)
 129{
 130        struct radix_tree_iter iter;
 131        void **slot;
 132
 133        spin_lock(&fs_info->buffer_lock);
 134restart:
 135        radix_tree_for_each_slot(slot, &fs_info->buffer_radix, &iter, 0) {
 136                struct extent_buffer *eb;
 137
 138                eb = radix_tree_deref_slot_protected(slot, &fs_info->buffer_lock);
 139                if (!eb)
 140                        continue;
 141                /* Shouldn't happen but that kind of thinking creates CVE's */
 142                if (radix_tree_exception(eb)) {
 143                        if (radix_tree_deref_retry(eb))
 144                                goto restart;
 145                        continue;
 146                }
 147                spin_unlock(&fs_info->buffer_lock);
 148                free_extent_buffer_stale(eb);
 149                spin_lock(&fs_info->buffer_lock);
 150        }
 151        spin_unlock(&fs_info->buffer_lock);
 152
 153        btrfs_free_qgroup_config(fs_info);
 154        btrfs_free_fs_roots(fs_info);
 155        cleanup_srcu_struct(&fs_info->subvol_srcu);
 156        kfree(fs_info->super_copy);
 157        kfree(fs_info->fs_devices);
 158        kfree(fs_info);
 159}
 160
 161void btrfs_free_dummy_root(struct btrfs_root *root)
 162{
 163        if (!root)
 164                return;
 165        if (root->node)
 166                free_extent_buffer(root->node);
 167        if (root->fs_info)
 168                btrfs_free_dummy_fs_info(root->fs_info);
 169        kfree(root);
 170}
 171
 172