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