1ec26815aSDavid Howells /* AFS client file system 21da177e4SLinus Torvalds * 39b3f26c9SDavid Howells * Copyright (C) 2002,5 Red Hat, Inc. All Rights Reserved. 41da177e4SLinus Torvalds * Written by David Howells (dhowells@redhat.com) 51da177e4SLinus Torvalds * 61da177e4SLinus Torvalds * This program is free software; you can redistribute it and/or 71da177e4SLinus Torvalds * modify it under the terms of the GNU General Public License 81da177e4SLinus Torvalds * as published by the Free Software Foundation; either version 91da177e4SLinus Torvalds * 2 of the License, or (at your option) any later version. 101da177e4SLinus Torvalds */ 111da177e4SLinus Torvalds 121da177e4SLinus Torvalds #include <linux/module.h> 131da177e4SLinus Torvalds #include <linux/moduleparam.h> 141da177e4SLinus Torvalds #include <linux/init.h> 151da177e4SLinus Torvalds #include <linux/completion.h> 16e8edc6e0SAlexey Dobriyan #include <linux/sched.h> 17e0661dfcSDavid Howells #include <linux/random.h> 188e8d7f13SDavid Howells #define CREATE_TRACE_POINTS 191da177e4SLinus Torvalds #include "internal.h" 201da177e4SLinus Torvalds 211da177e4SLinus Torvalds MODULE_DESCRIPTION("AFS Client File System"); 221da177e4SLinus Torvalds MODULE_AUTHOR("Red Hat, Inc."); 231da177e4SLinus Torvalds MODULE_LICENSE("GPL"); 241da177e4SLinus Torvalds 2508e0e7c8SDavid Howells unsigned afs_debug; 2608e0e7c8SDavid Howells module_param_named(debug, afs_debug, uint, S_IWUSR | S_IRUGO); 27424b00e2SPaul Bolle MODULE_PARM_DESC(debug, "AFS debugging mask"); 2808e0e7c8SDavid Howells 291da177e4SLinus Torvalds static char *rootcell; 301da177e4SLinus Torvalds 311da177e4SLinus Torvalds module_param(rootcell, charp, 0); 321da177e4SLinus Torvalds MODULE_PARM_DESC(rootcell, "root AFS cell name and VL server IP addr list"); 331da177e4SLinus Torvalds 340ad53eeeSTejun Heo struct workqueue_struct *afs_wq; 35*f044c884SDavid Howells struct afs_net __afs_net; 36*f044c884SDavid Howells 37*f044c884SDavid Howells /* 38*f044c884SDavid Howells * Initialise an AFS network namespace record. 39*f044c884SDavid Howells */ 40*f044c884SDavid Howells static int __net_init afs_net_init(struct afs_net *net) 41*f044c884SDavid Howells { 42*f044c884SDavid Howells int ret; 43*f044c884SDavid Howells 44*f044c884SDavid Howells net->live = true; 45*f044c884SDavid Howells generate_random_uuid((unsigned char *)&net->uuid); 46*f044c884SDavid Howells 47*f044c884SDavid Howells INIT_WORK(&net->charge_preallocation_work, afs_charge_preallocation); 48*f044c884SDavid Howells mutex_init(&net->socket_mutex); 49*f044c884SDavid Howells INIT_LIST_HEAD(&net->cells); 50*f044c884SDavid Howells rwlock_init(&net->cells_lock); 51*f044c884SDavid Howells init_rwsem(&net->cells_sem); 52*f044c884SDavid Howells init_waitqueue_head(&net->cells_freeable_wq); 53*f044c884SDavid Howells init_rwsem(&net->proc_cells_sem); 54*f044c884SDavid Howells INIT_LIST_HEAD(&net->proc_cells); 55*f044c884SDavid Howells INIT_LIST_HEAD(&net->vl_updates); 56*f044c884SDavid Howells INIT_LIST_HEAD(&net->vl_graveyard); 57*f044c884SDavid Howells INIT_DELAYED_WORK(&net->vl_reaper, afs_vlocation_reaper); 58*f044c884SDavid Howells INIT_DELAYED_WORK(&net->vl_updater, afs_vlocation_updater); 59*f044c884SDavid Howells spin_lock_init(&net->vl_updates_lock); 60*f044c884SDavid Howells spin_lock_init(&net->vl_graveyard_lock); 61*f044c884SDavid Howells net->servers = RB_ROOT; 62*f044c884SDavid Howells rwlock_init(&net->servers_lock); 63*f044c884SDavid Howells INIT_LIST_HEAD(&net->server_graveyard); 64*f044c884SDavid Howells spin_lock_init(&net->server_graveyard_lock); 65*f044c884SDavid Howells INIT_DELAYED_WORK(&net->server_reaper, afs_reap_server); 66*f044c884SDavid Howells 67*f044c884SDavid Howells /* Register the /proc stuff */ 68*f044c884SDavid Howells ret = afs_proc_init(net); 69*f044c884SDavid Howells if (ret < 0) 70*f044c884SDavid Howells goto error_proc; 71*f044c884SDavid Howells 72*f044c884SDavid Howells /* Initialise the cell DB */ 73*f044c884SDavid Howells ret = afs_cell_init(net, rootcell); 74*f044c884SDavid Howells if (ret < 0) 75*f044c884SDavid Howells goto error_cell_init; 76*f044c884SDavid Howells 77*f044c884SDavid Howells /* Create the RxRPC transport */ 78*f044c884SDavid Howells ret = afs_open_socket(net); 79*f044c884SDavid Howells if (ret < 0) 80*f044c884SDavid Howells goto error_open_socket; 81*f044c884SDavid Howells 82*f044c884SDavid Howells return 0; 83*f044c884SDavid Howells 84*f044c884SDavid Howells error_open_socket: 85*f044c884SDavid Howells afs_vlocation_purge(net); 86*f044c884SDavid Howells afs_cell_purge(net); 87*f044c884SDavid Howells error_cell_init: 88*f044c884SDavid Howells afs_proc_cleanup(net); 89*f044c884SDavid Howells error_proc: 90*f044c884SDavid Howells return ret; 91*f044c884SDavid Howells } 92*f044c884SDavid Howells 93*f044c884SDavid Howells /* 94*f044c884SDavid Howells * Clean up and destroy an AFS network namespace record. 95*f044c884SDavid Howells */ 96*f044c884SDavid Howells static void __net_exit afs_net_exit(struct afs_net *net) 97*f044c884SDavid Howells { 98*f044c884SDavid Howells net->live = false; 99*f044c884SDavid Howells afs_close_socket(net); 100*f044c884SDavid Howells afs_purge_servers(net); 101*f044c884SDavid Howells afs_vlocation_purge(net); 102*f044c884SDavid Howells afs_cell_purge(net); 103*f044c884SDavid Howells afs_proc_cleanup(net); 104*f044c884SDavid Howells } 105b908fe6bSDavid Howells 106b908fe6bSDavid Howells /* 1071da177e4SLinus Torvalds * initialise the AFS client FS module 1081da177e4SLinus Torvalds */ 1091da177e4SLinus Torvalds static int __init afs_init(void) 1101da177e4SLinus Torvalds { 111*f044c884SDavid Howells int ret = -ENOMEM; 1121da177e4SLinus Torvalds 1131da177e4SLinus Torvalds printk(KERN_INFO "kAFS: Red Hat AFS client v0.1 registering.\n"); 1141da177e4SLinus Torvalds 1150ad53eeeSTejun Heo afs_wq = alloc_workqueue("afs", 0, 0); 1160ad53eeeSTejun Heo if (!afs_wq) 117*f044c884SDavid Howells goto error_afs_wq; 118*f044c884SDavid Howells afs_async_calls = alloc_workqueue("kafsd", WQ_MEM_RECLAIM, 0); 119*f044c884SDavid Howells if (!afs_async_calls) 120*f044c884SDavid Howells goto error_async; 121*f044c884SDavid Howells afs_vlocation_update_worker = 122*f044c884SDavid Howells alloc_workqueue("kafs_vlupdated", WQ_MEM_RECLAIM, 0); 123*f044c884SDavid Howells if (!afs_vlocation_update_worker) 124*f044c884SDavid Howells goto error_vl_up; 125*f044c884SDavid Howells afs_callback_update_worker = 126*f044c884SDavid Howells alloc_ordered_workqueue("kafs_callbackd", WQ_MEM_RECLAIM); 127*f044c884SDavid Howells if (!afs_callback_update_worker) 128*f044c884SDavid Howells goto error_callback; 129*f044c884SDavid Howells afs_lock_manager = alloc_workqueue("kafs_lockd", WQ_MEM_RECLAIM, 0); 130*f044c884SDavid Howells if (!afs_lock_manager) 131*f044c884SDavid Howells goto error_lockmgr; 1321da177e4SLinus Torvalds 1339b3f26c9SDavid Howells #ifdef CONFIG_AFS_FSCACHE 1341da177e4SLinus Torvalds /* we want to be able to cache */ 1359b3f26c9SDavid Howells ret = fscache_register_netfs(&afs_cache_netfs); 1361da177e4SLinus Torvalds if (ret < 0) 1371da177e4SLinus Torvalds goto error_cache; 1381da177e4SLinus Torvalds #endif 1391da177e4SLinus Torvalds 140*f044c884SDavid Howells ret = afs_net_init(&__afs_net); 1411da177e4SLinus Torvalds if (ret < 0) 142*f044c884SDavid Howells goto error_net; 1431da177e4SLinus Torvalds 1441da177e4SLinus Torvalds /* register the filesystems */ 1451da177e4SLinus Torvalds ret = afs_fs_init(); 1461da177e4SLinus Torvalds if (ret < 0) 147ec26815aSDavid Howells goto error_fs; 1481da177e4SLinus Torvalds 1491da177e4SLinus Torvalds return ret; 1501da177e4SLinus Torvalds 151ec26815aSDavid Howells error_fs: 152*f044c884SDavid Howells afs_net_exit(&__afs_net); 153*f044c884SDavid Howells error_net: 1549b3f26c9SDavid Howells #ifdef CONFIG_AFS_FSCACHE 1559b3f26c9SDavid Howells fscache_unregister_netfs(&afs_cache_netfs); 156ec26815aSDavid Howells error_cache: 1571da177e4SLinus Torvalds #endif 158*f044c884SDavid Howells destroy_workqueue(afs_lock_manager); 159*f044c884SDavid Howells error_lockmgr: 160*f044c884SDavid Howells destroy_workqueue(afs_callback_update_worker); 161*f044c884SDavid Howells error_callback: 162*f044c884SDavid Howells destroy_workqueue(afs_vlocation_update_worker); 163*f044c884SDavid Howells error_vl_up: 164*f044c884SDavid Howells destroy_workqueue(afs_async_calls); 165*f044c884SDavid Howells error_async: 1660ad53eeeSTejun Heo destroy_workqueue(afs_wq); 167*f044c884SDavid Howells error_afs_wq: 168416351f2SDavid Howells rcu_barrier(); 1691da177e4SLinus Torvalds printk(KERN_ERR "kAFS: failed to register: %d\n", ret); 1701da177e4SLinus Torvalds return ret; 171ec26815aSDavid Howells } 1721da177e4SLinus Torvalds 1731da177e4SLinus Torvalds /* XXX late_initcall is kludgy, but the only alternative seems to create 1741da177e4SLinus Torvalds * a transport upon the first mount, which is worse. Or is it? 1751da177e4SLinus Torvalds */ 1761da177e4SLinus Torvalds late_initcall(afs_init); /* must be called after net/ to create socket */ 177ec26815aSDavid Howells 1781da177e4SLinus Torvalds /* 1791da177e4SLinus Torvalds * clean up on module removal 1801da177e4SLinus Torvalds */ 1811da177e4SLinus Torvalds static void __exit afs_exit(void) 1821da177e4SLinus Torvalds { 1831da177e4SLinus Torvalds printk(KERN_INFO "kAFS: Red Hat AFS client v0.1 unregistering.\n"); 1841da177e4SLinus Torvalds 1851da177e4SLinus Torvalds afs_fs_exit(); 186*f044c884SDavid Howells afs_net_exit(&__afs_net); 1879b3f26c9SDavid Howells #ifdef CONFIG_AFS_FSCACHE 1889b3f26c9SDavid Howells fscache_unregister_netfs(&afs_cache_netfs); 1891da177e4SLinus Torvalds #endif 190*f044c884SDavid Howells destroy_workqueue(afs_lock_manager); 191*f044c884SDavid Howells destroy_workqueue(afs_callback_update_worker); 192*f044c884SDavid Howells destroy_workqueue(afs_vlocation_update_worker); 193*f044c884SDavid Howells destroy_workqueue(afs_async_calls); 194*f044c884SDavid Howells destroy_workqueue(afs_wq); 195416351f2SDavid Howells rcu_barrier(); 196ec26815aSDavid Howells } 1971da177e4SLinus Torvalds 1981da177e4SLinus Torvalds module_exit(afs_exit); 199