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 INIT_LIST_HEAD(&net->vl_updates); 59 INIT_LIST_HEAD(&net->vl_graveyard); 60 INIT_DELAYED_WORK(&net->vl_reaper, afs_vlocation_reaper); 61 INIT_DELAYED_WORK(&net->vl_updater, afs_vlocation_updater); 62 spin_lock_init(&net->vl_updates_lock); 63 spin_lock_init(&net->vl_graveyard_lock); 64 net->servers = RB_ROOT; 65 rwlock_init(&net->servers_lock); 66 INIT_LIST_HEAD(&net->server_graveyard); 67 spin_lock_init(&net->server_graveyard_lock); 68 INIT_WORK(&net->server_reaper, afs_reap_server); 69 timer_setup(&net->server_timer, afs_server_timer, 0); 70 71 /* Register the /proc stuff */ 72 ret = afs_proc_init(net); 73 if (ret < 0) 74 goto error_proc; 75 76 /* Initialise the cell DB */ 77 ret = afs_cell_init(net, rootcell); 78 if (ret < 0) 79 goto error_cell_init; 80 81 /* Create the RxRPC transport */ 82 ret = afs_open_socket(net); 83 if (ret < 0) 84 goto error_open_socket; 85 86 return 0; 87 88 error_open_socket: 89 net->live = false; 90 afs_vlocation_purge(net); 91 afs_cell_purge(net); 92 error_cell_init: 93 net->live = false; 94 afs_proc_cleanup(net); 95 error_proc: 96 net->live = false; 97 return ret; 98 } 99 100 /* 101 * Clean up and destroy an AFS network namespace record. 102 */ 103 static void __net_exit afs_net_exit(struct afs_net *net) 104 { 105 net->live = false; 106 afs_purge_servers(net); 107 afs_vlocation_purge(net); 108 afs_cell_purge(net); 109 afs_close_socket(net); 110 afs_proc_cleanup(net); 111 } 112 113 /* 114 * initialise the AFS client FS module 115 */ 116 static int __init afs_init(void) 117 { 118 int ret = -ENOMEM; 119 120 printk(KERN_INFO "kAFS: Red Hat AFS client v0.1 registering.\n"); 121 122 afs_wq = alloc_workqueue("afs", 0, 0); 123 if (!afs_wq) 124 goto error_afs_wq; 125 afs_async_calls = alloc_workqueue("kafsd", WQ_MEM_RECLAIM, 0); 126 if (!afs_async_calls) 127 goto error_async; 128 afs_vlocation_update_worker = 129 alloc_workqueue("kafs_vlupdated", WQ_MEM_RECLAIM, 0); 130 if (!afs_vlocation_update_worker) 131 goto error_vl_up; 132 afs_lock_manager = alloc_workqueue("kafs_lockd", WQ_MEM_RECLAIM, 0); 133 if (!afs_lock_manager) 134 goto error_lockmgr; 135 136 #ifdef CONFIG_AFS_FSCACHE 137 /* we want to be able to cache */ 138 ret = fscache_register_netfs(&afs_cache_netfs); 139 if (ret < 0) 140 goto error_cache; 141 #endif 142 143 ret = afs_net_init(&__afs_net); 144 if (ret < 0) 145 goto error_net; 146 147 /* register the filesystems */ 148 ret = afs_fs_init(); 149 if (ret < 0) 150 goto error_fs; 151 152 return ret; 153 154 error_fs: 155 afs_net_exit(&__afs_net); 156 error_net: 157 #ifdef CONFIG_AFS_FSCACHE 158 fscache_unregister_netfs(&afs_cache_netfs); 159 error_cache: 160 #endif 161 destroy_workqueue(afs_lock_manager); 162 error_lockmgr: 163 destroy_workqueue(afs_vlocation_update_worker); 164 error_vl_up: 165 destroy_workqueue(afs_async_calls); 166 error_async: 167 destroy_workqueue(afs_wq); 168 error_afs_wq: 169 rcu_barrier(); 170 printk(KERN_ERR "kAFS: failed to register: %d\n", ret); 171 return ret; 172 } 173 174 /* XXX late_initcall is kludgy, but the only alternative seems to create 175 * a transport upon the first mount, which is worse. Or is it? 176 */ 177 late_initcall(afs_init); /* must be called after net/ to create socket */ 178 179 /* 180 * clean up on module removal 181 */ 182 static void __exit afs_exit(void) 183 { 184 printk(KERN_INFO "kAFS: Red Hat AFS client v0.1 unregistering.\n"); 185 186 afs_fs_exit(); 187 afs_net_exit(&__afs_net); 188 #ifdef CONFIG_AFS_FSCACHE 189 fscache_unregister_netfs(&afs_cache_netfs); 190 #endif 191 destroy_workqueue(afs_lock_manager); 192 destroy_workqueue(afs_vlocation_update_worker); 193 destroy_workqueue(afs_async_calls); 194 destroy_workqueue(afs_wq); 195 afs_clean_up_permit_cache(); 196 rcu_barrier(); 197 } 198 199 module_exit(afs_exit); 200