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 28 static struct vfsmount *test_mnt = NULL; 29 30 static const struct super_operations btrfs_test_super_ops = { 31 .alloc_inode = btrfs_alloc_inode, 32 .destroy_inode = btrfs_test_destroy_inode, 33 }; 34 35 static 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 43 static struct file_system_type test_type = { 44 .name = "btrfs_test_fs", 45 .mount = btrfs_test_mount, 46 .kill_sb = kill_anon_super, 47 }; 48 49 struct inode *btrfs_new_test_inode(void) 50 { 51 return new_inode(test_mnt->mnt_sb); 52 } 53 54 int 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 73 void btrfs_destroy_test_fs(void) 74 { 75 kern_unmount(test_mnt); 76 unregister_filesystem(&test_type); 77 } 78 79 struct 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 128 static 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); 134 restart: 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 161 void 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