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 #if defined(CONFIG_ALPHA) 38 const char afs_init_sysname[] = "alpha_linux26"; 39 #elif defined(CONFIG_X86_64) 40 const char afs_init_sysname[] = "amd64_linux26"; 41 #elif defined(CONFIG_ARM) 42 const char afs_init_sysname[] = "arm_linux26"; 43 #elif defined(CONFIG_ARM64) 44 const char afs_init_sysname[] = "aarch64_linux26"; 45 #elif defined(CONFIG_X86_32) 46 const char afs_init_sysname[] = "i386_linux26"; 47 #elif defined(CONFIG_IA64) 48 const char afs_init_sysname[] = "ia64_linux26"; 49 #elif defined(CONFIG_PPC64) 50 const char afs_init_sysname[] = "ppc64_linux26"; 51 #elif defined(CONFIG_PPC32) 52 const char afs_init_sysname[] = "ppc_linux26"; 53 #elif defined(CONFIG_S390) 54 #ifdef CONFIG_64BIT 55 const char afs_init_sysname[] = "s390x_linux26"; 56 #else 57 const char afs_init_sysname[] = "s390_linux26"; 58 #endif 59 #elif defined(CONFIG_SPARC64) 60 const char afs_init_sysname[] = "sparc64_linux26"; 61 #elif defined(CONFIG_SPARC32) 62 const char afs_init_sysname[] = "sparc_linux26"; 63 #else 64 const char afs_init_sysname[] = "unknown_linux26"; 65 #endif 66 67 /* 68 * Initialise an AFS network namespace record. 69 */ 70 static int __net_init afs_net_init(struct afs_net *net) 71 { 72 struct afs_sysnames *sysnames; 73 int ret; 74 75 net->live = true; 76 generate_random_uuid((unsigned char *)&net->uuid); 77 78 INIT_WORK(&net->charge_preallocation_work, afs_charge_preallocation); 79 mutex_init(&net->socket_mutex); 80 81 net->cells = RB_ROOT; 82 seqlock_init(&net->cells_lock); 83 INIT_WORK(&net->cells_manager, afs_manage_cells); 84 timer_setup(&net->cells_timer, afs_cells_timer, 0); 85 86 spin_lock_init(&net->proc_cells_lock); 87 INIT_LIST_HEAD(&net->proc_cells); 88 89 seqlock_init(&net->fs_lock); 90 net->fs_servers = RB_ROOT; 91 INIT_LIST_HEAD(&net->fs_updates); 92 INIT_HLIST_HEAD(&net->fs_proc); 93 94 INIT_HLIST_HEAD(&net->fs_addresses4); 95 INIT_HLIST_HEAD(&net->fs_addresses6); 96 seqlock_init(&net->fs_addr_lock); 97 98 INIT_WORK(&net->fs_manager, afs_manage_servers); 99 timer_setup(&net->fs_timer, afs_servers_timer, 0); 100 101 ret = -ENOMEM; 102 sysnames = kzalloc(sizeof(*sysnames), GFP_KERNEL); 103 if (!sysnames) 104 goto error_sysnames; 105 sysnames->subs[0] = (char *)&afs_init_sysname; 106 sysnames->nr = 1; 107 refcount_set(&sysnames->usage, 1); 108 net->sysnames = sysnames; 109 rwlock_init(&net->sysnames_lock); 110 111 /* Register the /proc stuff */ 112 ret = afs_proc_init(net); 113 if (ret < 0) 114 goto error_proc; 115 116 /* Initialise the cell DB */ 117 ret = afs_cell_init(net, rootcell); 118 if (ret < 0) 119 goto error_cell_init; 120 121 /* Create the RxRPC transport */ 122 ret = afs_open_socket(net); 123 if (ret < 0) 124 goto error_open_socket; 125 126 return 0; 127 128 error_open_socket: 129 net->live = false; 130 afs_cell_purge(net); 131 afs_purge_servers(net); 132 error_cell_init: 133 net->live = false; 134 afs_proc_cleanup(net); 135 error_proc: 136 afs_put_sysnames(net->sysnames); 137 error_sysnames: 138 net->live = false; 139 return ret; 140 } 141 142 /* 143 * Clean up and destroy an AFS network namespace record. 144 */ 145 static void __net_exit afs_net_exit(struct afs_net *net) 146 { 147 net->live = false; 148 afs_cell_purge(net); 149 afs_purge_servers(net); 150 afs_close_socket(net); 151 afs_proc_cleanup(net); 152 afs_put_sysnames(net->sysnames); 153 } 154 155 /* 156 * initialise the AFS client FS module 157 */ 158 static int __init afs_init(void) 159 { 160 int ret = -ENOMEM; 161 162 printk(KERN_INFO "kAFS: Red Hat AFS client v0.1 registering.\n"); 163 164 afs_wq = alloc_workqueue("afs", 0, 0); 165 if (!afs_wq) 166 goto error_afs_wq; 167 afs_async_calls = alloc_workqueue("kafsd", WQ_MEM_RECLAIM, 0); 168 if (!afs_async_calls) 169 goto error_async; 170 afs_lock_manager = alloc_workqueue("kafs_lockd", WQ_MEM_RECLAIM, 0); 171 if (!afs_lock_manager) 172 goto error_lockmgr; 173 174 #ifdef CONFIG_AFS_FSCACHE 175 /* we want to be able to cache */ 176 ret = fscache_register_netfs(&afs_cache_netfs); 177 if (ret < 0) 178 goto error_cache; 179 #endif 180 181 ret = afs_net_init(&__afs_net); 182 if (ret < 0) 183 goto error_net; 184 185 /* register the filesystems */ 186 ret = afs_fs_init(); 187 if (ret < 0) 188 goto error_fs; 189 190 return ret; 191 192 error_fs: 193 afs_net_exit(&__afs_net); 194 error_net: 195 #ifdef CONFIG_AFS_FSCACHE 196 fscache_unregister_netfs(&afs_cache_netfs); 197 error_cache: 198 #endif 199 destroy_workqueue(afs_lock_manager); 200 error_lockmgr: 201 destroy_workqueue(afs_async_calls); 202 error_async: 203 destroy_workqueue(afs_wq); 204 error_afs_wq: 205 rcu_barrier(); 206 printk(KERN_ERR "kAFS: failed to register: %d\n", ret); 207 return ret; 208 } 209 210 /* XXX late_initcall is kludgy, but the only alternative seems to create 211 * a transport upon the first mount, which is worse. Or is it? 212 */ 213 late_initcall(afs_init); /* must be called after net/ to create socket */ 214 215 /* 216 * clean up on module removal 217 */ 218 static void __exit afs_exit(void) 219 { 220 printk(KERN_INFO "kAFS: Red Hat AFS client v0.1 unregistering.\n"); 221 222 afs_fs_exit(); 223 afs_net_exit(&__afs_net); 224 #ifdef CONFIG_AFS_FSCACHE 225 fscache_unregister_netfs(&afs_cache_netfs); 226 #endif 227 destroy_workqueue(afs_lock_manager); 228 destroy_workqueue(afs_async_calls); 229 destroy_workqueue(afs_wq); 230 afs_clean_up_permit_cache(); 231 rcu_barrier(); 232 } 233 234 module_exit(afs_exit); 235