1 /* main.c: AFS client file system 2 * 3 * Copyright (C) 2002 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 <rxrpc/rxrpc.h> 17 #include <rxrpc/transport.h> 18 #include <rxrpc/call.h> 19 #include <rxrpc/peer.h> 20 #include "cache.h" 21 #include "cell.h" 22 #include "server.h" 23 #include "fsclient.h" 24 #include "cmservice.h" 25 #include "kafstimod.h" 26 #include "kafsasyncd.h" 27 #include "internal.h" 28 29 struct rxrpc_transport *afs_transport; 30 31 static int afs_adding_peer(struct rxrpc_peer *peer); 32 static void afs_discarding_peer(struct rxrpc_peer *peer); 33 34 35 MODULE_DESCRIPTION("AFS Client File System"); 36 MODULE_AUTHOR("Red Hat, Inc."); 37 MODULE_LICENSE("GPL"); 38 39 static char *rootcell; 40 41 module_param(rootcell, charp, 0); 42 MODULE_PARM_DESC(rootcell, "root AFS cell name and VL server IP addr list"); 43 44 45 static struct rxrpc_peer_ops afs_peer_ops = { 46 .adding = afs_adding_peer, 47 .discarding = afs_discarding_peer, 48 }; 49 50 struct list_head afs_cb_hash_tbl[AFS_CB_HASH_COUNT]; 51 DEFINE_SPINLOCK(afs_cb_hash_lock); 52 53 #ifdef AFS_CACHING_SUPPORT 54 static struct cachefs_netfs_operations afs_cache_ops = { 55 .get_page_cookie = afs_cache_get_page_cookie, 56 }; 57 58 struct cachefs_netfs afs_cache_netfs = { 59 .name = "afs", 60 .version = 0, 61 .ops = &afs_cache_ops, 62 }; 63 #endif 64 65 /*****************************************************************************/ 66 /* 67 * initialise the AFS client FS module 68 */ 69 static int __init afs_init(void) 70 { 71 int loop, ret; 72 73 printk(KERN_INFO "kAFS: Red Hat AFS client v0.1 registering.\n"); 74 75 /* initialise the callback hash table */ 76 spin_lock_init(&afs_cb_hash_lock); 77 for (loop = AFS_CB_HASH_COUNT - 1; loop >= 0; loop--) 78 INIT_LIST_HEAD(&afs_cb_hash_tbl[loop]); 79 80 /* register the /proc stuff */ 81 ret = afs_proc_init(); 82 if (ret < 0) 83 return ret; 84 85 #ifdef AFS_CACHING_SUPPORT 86 /* we want to be able to cache */ 87 ret = cachefs_register_netfs(&afs_cache_netfs, 88 &afs_cache_cell_index_def); 89 if (ret < 0) 90 goto error; 91 #endif 92 93 #ifdef CONFIG_KEYS_TURNED_OFF 94 ret = afs_key_register(); 95 if (ret < 0) 96 goto error_cache; 97 #endif 98 99 /* initialise the cell DB */ 100 ret = afs_cell_init(rootcell); 101 if (ret < 0) 102 goto error_keys; 103 104 /* start the timeout daemon */ 105 ret = afs_kafstimod_start(); 106 if (ret < 0) 107 goto error_keys; 108 109 /* start the async operation daemon */ 110 ret = afs_kafsasyncd_start(); 111 if (ret < 0) 112 goto error_kafstimod; 113 114 /* create the RxRPC transport */ 115 ret = rxrpc_create_transport(7001, &afs_transport); 116 if (ret < 0) 117 goto error_kafsasyncd; 118 119 afs_transport->peer_ops = &afs_peer_ops; 120 121 /* register the filesystems */ 122 ret = afs_fs_init(); 123 if (ret < 0) 124 goto error_transport; 125 126 return ret; 127 128 error_transport: 129 rxrpc_put_transport(afs_transport); 130 error_kafsasyncd: 131 afs_kafsasyncd_stop(); 132 error_kafstimod: 133 afs_kafstimod_stop(); 134 error_keys: 135 #ifdef CONFIG_KEYS_TURNED_OFF 136 afs_key_unregister(); 137 error_cache: 138 #endif 139 #ifdef AFS_CACHING_SUPPORT 140 cachefs_unregister_netfs(&afs_cache_netfs); 141 error: 142 #endif 143 afs_cell_purge(); 144 afs_proc_cleanup(); 145 printk(KERN_ERR "kAFS: failed to register: %d\n", ret); 146 return ret; 147 } /* end afs_init() */ 148 149 /* XXX late_initcall is kludgy, but the only alternative seems to create 150 * a transport upon the first mount, which is worse. Or is it? 151 */ 152 late_initcall(afs_init); /* must be called after net/ to create socket */ 153 /*****************************************************************************/ 154 /* 155 * clean up on module removal 156 */ 157 static void __exit afs_exit(void) 158 { 159 printk(KERN_INFO "kAFS: Red Hat AFS client v0.1 unregistering.\n"); 160 161 afs_fs_exit(); 162 rxrpc_put_transport(afs_transport); 163 afs_kafstimod_stop(); 164 afs_kafsasyncd_stop(); 165 afs_cell_purge(); 166 #ifdef CONFIG_KEYS_TURNED_OFF 167 afs_key_unregister(); 168 #endif 169 #ifdef AFS_CACHING_SUPPORT 170 cachefs_unregister_netfs(&afs_cache_netfs); 171 #endif 172 afs_proc_cleanup(); 173 174 } /* end afs_exit() */ 175 176 module_exit(afs_exit); 177 178 /*****************************************************************************/ 179 /* 180 * notification that new peer record is being added 181 * - called from krxsecd 182 * - return an error to induce an abort 183 * - mustn't sleep (caller holds an rwlock) 184 */ 185 static int afs_adding_peer(struct rxrpc_peer *peer) 186 { 187 struct afs_server *server; 188 int ret; 189 190 _debug("kAFS: Adding new peer %08x\n", ntohl(peer->addr.s_addr)); 191 192 /* determine which server the peer resides in (if any) */ 193 ret = afs_server_find_by_peer(peer, &server); 194 if (ret < 0) 195 return ret; /* none that we recognise, so abort */ 196 197 _debug("Server %p{u=%d}\n", server, atomic_read(&server->usage)); 198 199 _debug("Cell %p{u=%d}\n", 200 server->cell, atomic_read(&server->cell->usage)); 201 202 /* cross-point the structs under a global lock */ 203 spin_lock(&afs_server_peer_lock); 204 peer->user = server; 205 server->peer = peer; 206 spin_unlock(&afs_server_peer_lock); 207 208 afs_put_server(server); 209 210 return 0; 211 } /* end afs_adding_peer() */ 212 213 /*****************************************************************************/ 214 /* 215 * notification that a peer record is being discarded 216 * - called from krxiod or krxsecd 217 */ 218 static void afs_discarding_peer(struct rxrpc_peer *peer) 219 { 220 struct afs_server *server; 221 222 _enter("%p",peer); 223 224 _debug("Discarding peer %08x (rtt=%lu.%lumS)\n", 225 ntohl(peer->addr.s_addr), 226 (long) (peer->rtt / 1000), 227 (long) (peer->rtt % 1000)); 228 229 /* uncross-point the structs under a global lock */ 230 spin_lock(&afs_server_peer_lock); 231 server = peer->user; 232 if (server) { 233 peer->user = NULL; 234 server->peer = NULL; 235 } 236 spin_unlock(&afs_server_peer_lock); 237 238 _leave(""); 239 240 } /* end afs_discarding_peer() */ 241 242 /*****************************************************************************/ 243 /* 244 * clear the dead space between task_struct and kernel stack 245 * - called by supplying -finstrument-functions to gcc 246 */ 247 #if 0 248 void __cyg_profile_func_enter (void *this_fn, void *call_site) 249 __attribute__((no_instrument_function)); 250 251 void __cyg_profile_func_enter (void *this_fn, void *call_site) 252 { 253 asm volatile(" movl %%esp,%%edi \n" 254 " andl %0,%%edi \n" 255 " addl %1,%%edi \n" 256 " movl %%esp,%%ecx \n" 257 " subl %%edi,%%ecx \n" 258 " shrl $2,%%ecx \n" 259 " movl $0xedededed,%%eax \n" 260 " rep stosl \n" 261 : 262 : "i"(~(THREAD_SIZE - 1)), "i"(sizeof(struct thread_info)) 263 : "eax", "ecx", "edi", "memory", "cc" 264 ); 265 } 266 267 void __cyg_profile_func_exit(void *this_fn, void *call_site) 268 __attribute__((no_instrument_function)); 269 270 void __cyg_profile_func_exit(void *this_fn, void *call_site) 271 { 272 asm volatile(" movl %%esp,%%edi \n" 273 " andl %0,%%edi \n" 274 " addl %1,%%edi \n" 275 " movl %%esp,%%ecx \n" 276 " subl %%edi,%%ecx \n" 277 " shrl $2,%%ecx \n" 278 " movl $0xdadadada,%%eax \n" 279 " rep stosl \n" 280 : 281 : "i"(~(THREAD_SIZE - 1)), "i"(sizeof(struct thread_info)) 282 : "eax", "ecx", "edi", "memory", "cc" 283 ); 284 } 285 #endif 286