1 /* 2 * Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved. 3 * Copyright (C) 2004-2006 Red Hat, Inc. All rights reserved. 4 * 5 * This copyrighted material is made available to anyone wishing to use, 6 * modify, copy, or redistribute it subject to the terms and conditions 7 * of the GNU General Public License version 2. 8 */ 9 10 #include <linux/slab.h> 11 #include <linux/spinlock.h> 12 #include <linux/completion.h> 13 #include <linux/buffer_head.h> 14 #include <linux/module.h> 15 #include <linux/init.h> 16 #include <linux/gfs2_ondisk.h> 17 #include <asm/atomic.h> 18 19 #include "gfs2.h" 20 #include "incore.h" 21 #include "super.h" 22 #include "sys.h" 23 #include "util.h" 24 #include "glock.h" 25 #include "quota.h" 26 #include "recovery.h" 27 #include "dir.h" 28 29 static struct shrinker qd_shrinker = { 30 .shrink = gfs2_shrink_qd_memory, 31 .seeks = DEFAULT_SEEKS, 32 }; 33 34 static void gfs2_init_inode_once(void *foo) 35 { 36 struct gfs2_inode *ip = foo; 37 38 inode_init_once(&ip->i_inode); 39 init_rwsem(&ip->i_rw_mutex); 40 INIT_LIST_HEAD(&ip->i_trunc_list); 41 ip->i_alloc = NULL; 42 } 43 44 static void gfs2_init_glock_once(void *foo) 45 { 46 struct gfs2_glock *gl = foo; 47 48 INIT_HLIST_NODE(&gl->gl_list); 49 spin_lock_init(&gl->gl_spin); 50 INIT_LIST_HEAD(&gl->gl_holders); 51 INIT_LIST_HEAD(&gl->gl_lru); 52 INIT_LIST_HEAD(&gl->gl_ail_list); 53 atomic_set(&gl->gl_ail_count, 0); 54 } 55 56 static void gfs2_init_gl_aspace_once(void *foo) 57 { 58 struct gfs2_glock *gl = foo; 59 struct address_space *mapping = (struct address_space *)(gl + 1); 60 61 gfs2_init_glock_once(gl); 62 address_space_init_once(mapping); 63 } 64 65 /** 66 * init_gfs2_fs - Register GFS2 as a filesystem 67 * 68 * Returns: 0 on success, error code on failure 69 */ 70 71 static int __init init_gfs2_fs(void) 72 { 73 int error; 74 75 gfs2_str2qstr(&gfs2_qdot, "."); 76 gfs2_str2qstr(&gfs2_qdotdot, ".."); 77 78 error = gfs2_sys_init(); 79 if (error) 80 return error; 81 82 error = gfs2_glock_init(); 83 if (error) 84 goto fail; 85 86 error = -ENOMEM; 87 gfs2_glock_cachep = kmem_cache_create("gfs2_glock", 88 sizeof(struct gfs2_glock), 89 0, 0, 90 gfs2_init_glock_once); 91 if (!gfs2_glock_cachep) 92 goto fail; 93 94 gfs2_glock_aspace_cachep = kmem_cache_create("gfs2_glock(aspace)", 95 sizeof(struct gfs2_glock) + 96 sizeof(struct address_space), 97 0, 0, gfs2_init_gl_aspace_once); 98 99 if (!gfs2_glock_aspace_cachep) 100 goto fail; 101 102 gfs2_inode_cachep = kmem_cache_create("gfs2_inode", 103 sizeof(struct gfs2_inode), 104 0, SLAB_RECLAIM_ACCOUNT| 105 SLAB_MEM_SPREAD, 106 gfs2_init_inode_once); 107 if (!gfs2_inode_cachep) 108 goto fail; 109 110 gfs2_bufdata_cachep = kmem_cache_create("gfs2_bufdata", 111 sizeof(struct gfs2_bufdata), 112 0, 0, NULL); 113 if (!gfs2_bufdata_cachep) 114 goto fail; 115 116 gfs2_rgrpd_cachep = kmem_cache_create("gfs2_rgrpd", 117 sizeof(struct gfs2_rgrpd), 118 0, 0, NULL); 119 if (!gfs2_rgrpd_cachep) 120 goto fail; 121 122 gfs2_quotad_cachep = kmem_cache_create("gfs2_quotad", 123 sizeof(struct gfs2_quota_data), 124 0, 0, NULL); 125 if (!gfs2_quotad_cachep) 126 goto fail; 127 128 register_shrinker(&qd_shrinker); 129 130 error = register_filesystem(&gfs2_fs_type); 131 if (error) 132 goto fail; 133 134 error = register_filesystem(&gfs2meta_fs_type); 135 if (error) 136 goto fail_unregister; 137 138 error = -ENOMEM; 139 gfs_recovery_wq = alloc_workqueue("gfs_recovery", 140 WQ_MEM_RECLAIM | WQ_FREEZABLE, 0); 141 if (!gfs_recovery_wq) 142 goto fail_wq; 143 144 gfs2_register_debugfs(); 145 146 printk("GFS2 (built %s %s) installed\n", __DATE__, __TIME__); 147 148 return 0; 149 150 fail_wq: 151 unregister_filesystem(&gfs2meta_fs_type); 152 fail_unregister: 153 unregister_filesystem(&gfs2_fs_type); 154 fail: 155 unregister_shrinker(&qd_shrinker); 156 gfs2_glock_exit(); 157 158 if (gfs2_quotad_cachep) 159 kmem_cache_destroy(gfs2_quotad_cachep); 160 161 if (gfs2_rgrpd_cachep) 162 kmem_cache_destroy(gfs2_rgrpd_cachep); 163 164 if (gfs2_bufdata_cachep) 165 kmem_cache_destroy(gfs2_bufdata_cachep); 166 167 if (gfs2_inode_cachep) 168 kmem_cache_destroy(gfs2_inode_cachep); 169 170 if (gfs2_glock_aspace_cachep) 171 kmem_cache_destroy(gfs2_glock_aspace_cachep); 172 173 if (gfs2_glock_cachep) 174 kmem_cache_destroy(gfs2_glock_cachep); 175 176 gfs2_sys_uninit(); 177 return error; 178 } 179 180 /** 181 * exit_gfs2_fs - Unregister the file system 182 * 183 */ 184 185 static void __exit exit_gfs2_fs(void) 186 { 187 unregister_shrinker(&qd_shrinker); 188 gfs2_glock_exit(); 189 gfs2_unregister_debugfs(); 190 unregister_filesystem(&gfs2_fs_type); 191 unregister_filesystem(&gfs2meta_fs_type); 192 destroy_workqueue(gfs_recovery_wq); 193 194 kmem_cache_destroy(gfs2_quotad_cachep); 195 kmem_cache_destroy(gfs2_rgrpd_cachep); 196 kmem_cache_destroy(gfs2_bufdata_cachep); 197 kmem_cache_destroy(gfs2_inode_cachep); 198 kmem_cache_destroy(gfs2_glock_aspace_cachep); 199 kmem_cache_destroy(gfs2_glock_cachep); 200 201 gfs2_sys_uninit(); 202 } 203 204 MODULE_DESCRIPTION("Global File System"); 205 MODULE_AUTHOR("Red Hat, Inc."); 206 MODULE_LICENSE("GPL"); 207 208 module_init(init_gfs2_fs); 209 module_exit(exit_gfs2_fs); 210 211