1 /* AFS client file system 2 * 3 * Copyright (C) 2002,5 Red Hat, Inc. All Rights Reserved. 4 * Written by David Howells (dhowells@redhat.com) 5 * 6 * This program is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU General Public License 8 * as published by the Free Software Foundation; either version 9 * 2 of the License, or (at your option) any later version. 10 */ 11 12 #include <linux/module.h> 13 #include <linux/moduleparam.h> 14 #include <linux/init.h> 15 #include <linux/completion.h> 16 #include <linux/sched.h> 17 #include <linux/random.h> 18 #define CREATE_TRACE_POINTS 19 #include "internal.h" 20 21 MODULE_DESCRIPTION("AFS Client File System"); 22 MODULE_AUTHOR("Red Hat, Inc."); 23 MODULE_LICENSE("GPL"); 24 25 unsigned afs_debug; 26 module_param_named(debug, afs_debug, uint, S_IWUSR | S_IRUGO); 27 MODULE_PARM_DESC(debug, "AFS debugging mask"); 28 29 static char *rootcell; 30 31 module_param(rootcell, charp, 0); 32 MODULE_PARM_DESC(rootcell, "root AFS cell name and VL server IP addr list"); 33 34 struct workqueue_struct *afs_wq; 35 struct afs_net __afs_net; 36 37 /* 38 * Initialise an AFS network namespace record. 39 */ 40 static int __net_init afs_net_init(struct afs_net *net) 41 { 42 int ret; 43 44 net->live = true; 45 generate_random_uuid((unsigned char *)&net->uuid); 46 47 INIT_WORK(&net->charge_preallocation_work, afs_charge_preallocation); 48 mutex_init(&net->socket_mutex); 49 50 net->cells = RB_ROOT; 51 seqlock_init(&net->cells_lock); 52 INIT_WORK(&net->cells_manager, afs_manage_cells); 53 timer_setup(&net->cells_timer, afs_cells_timer, 0); 54 55 spin_lock_init(&net->proc_cells_lock); 56 INIT_LIST_HEAD(&net->proc_cells); 57 58 seqlock_init(&net->fs_lock); 59 net->fs_servers = RB_ROOT; 60 INIT_LIST_HEAD(&net->fs_updates); 61 INIT_HLIST_HEAD(&net->fs_proc); 62 63 INIT_HLIST_HEAD(&net->fs_addresses4); 64 INIT_HLIST_HEAD(&net->fs_addresses6); 65 seqlock_init(&net->fs_addr_lock); 66 67 INIT_WORK(&net->fs_manager, afs_manage_servers); 68 timer_setup(&net->fs_timer, afs_servers_timer, 0); 69 70 /* Register the /proc stuff */ 71 ret = afs_proc_init(net); 72 if (ret < 0) 73 goto error_proc; 74 75 /* Initialise the cell DB */ 76 ret = afs_cell_init(net, rootcell); 77 if (ret < 0) 78 goto error_cell_init; 79 80 /* Create the RxRPC transport */ 81 ret = afs_open_socket(net); 82 if (ret < 0) 83 goto error_open_socket; 84 85 return 0; 86 87 error_open_socket: 88 net->live = false; 89 afs_cell_purge(net); 90 afs_purge_servers(net); 91 error_cell_init: 92 net->live = false; 93 afs_proc_cleanup(net); 94 error_proc: 95 net->live = false; 96 return ret; 97 } 98 99 /* 100 * Clean up and destroy an AFS network namespace record. 101 */ 102 static void __net_exit afs_net_exit(struct afs_net *net) 103 { 104 net->live = false; 105 afs_cell_purge(net); 106 afs_purge_servers(net); 107 afs_close_socket(net); 108 afs_proc_cleanup(net); 109 } 110 111 /* 112 * initialise the AFS client FS module 113 */ 114 static int __init afs_init(void) 115 { 116 int ret = -ENOMEM; 117 118 printk(KERN_INFO "kAFS: Red Hat AFS client v0.1 registering.\n"); 119 120 afs_wq = alloc_workqueue("afs", 0, 0); 121 if (!afs_wq) 122 goto error_afs_wq; 123 afs_async_calls = alloc_workqueue("kafsd", WQ_MEM_RECLAIM, 0); 124 if (!afs_async_calls) 125 goto error_async; 126 afs_lock_manager = alloc_workqueue("kafs_lockd", WQ_MEM_RECLAIM, 0); 127 if (!afs_lock_manager) 128 goto error_lockmgr; 129 130 #ifdef CONFIG_AFS_FSCACHE 131 /* we want to be able to cache */ 132 ret = fscache_register_netfs(&afs_cache_netfs); 133 if (ret < 0) 134 goto error_cache; 135 #endif 136 137 ret = afs_net_init(&__afs_net); 138 if (ret < 0) 139 goto error_net; 140 141 /* register the filesystems */ 142 ret = afs_fs_init(); 143 if (ret < 0) 144 goto error_fs; 145 146 return ret; 147 148 error_fs: 149 afs_net_exit(&__afs_net); 150 error_net: 151 #ifdef CONFIG_AFS_FSCACHE 152 fscache_unregister_netfs(&afs_cache_netfs); 153 error_cache: 154 #endif 155 destroy_workqueue(afs_lock_manager); 156 error_lockmgr: 157 destroy_workqueue(afs_async_calls); 158 error_async: 159 destroy_workqueue(afs_wq); 160 error_afs_wq: 161 rcu_barrier(); 162 printk(KERN_ERR "kAFS: failed to register: %d\n", ret); 163 return ret; 164 } 165 166 /* XXX late_initcall is kludgy, but the only alternative seems to create 167 * a transport upon the first mount, which is worse. Or is it? 168 */ 169 late_initcall(afs_init); /* must be called after net/ to create socket */ 170 171 /* 172 * clean up on module removal 173 */ 174 static void __exit afs_exit(void) 175 { 176 printk(KERN_INFO "kAFS: Red Hat AFS client v0.1 unregistering.\n"); 177 178 afs_fs_exit(); 179 afs_net_exit(&__afs_net); 180 #ifdef CONFIG_AFS_FSCACHE 181 fscache_unregister_netfs(&afs_cache_netfs); 182 #endif 183 destroy_workqueue(afs_lock_manager); 184 destroy_workqueue(afs_async_calls); 185 destroy_workqueue(afs_wq); 186 afs_clean_up_permit_cache(); 187 rcu_barrier(); 188 } 189 190 module_exit(afs_exit); 191