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> 185b86d4ffSDavid Howells #include <linux/proc_fs.h> 198e8d7f13SDavid Howells #define CREATE_TRACE_POINTS 201da177e4SLinus Torvalds #include "internal.h" 211da177e4SLinus Torvalds 221da177e4SLinus Torvalds MODULE_DESCRIPTION("AFS Client File System"); 231da177e4SLinus Torvalds MODULE_AUTHOR("Red Hat, Inc."); 241da177e4SLinus Torvalds MODULE_LICENSE("GPL"); 251da177e4SLinus Torvalds 2608e0e7c8SDavid Howells unsigned afs_debug; 2708e0e7c8SDavid Howells module_param_named(debug, afs_debug, uint, S_IWUSR | S_IRUGO); 28424b00e2SPaul Bolle MODULE_PARM_DESC(debug, "AFS debugging mask"); 2908e0e7c8SDavid Howells 301da177e4SLinus Torvalds static char *rootcell; 311da177e4SLinus Torvalds 321da177e4SLinus Torvalds module_param(rootcell, charp, 0); 331da177e4SLinus Torvalds MODULE_PARM_DESC(rootcell, "root AFS cell name and VL server IP addr list"); 341da177e4SLinus Torvalds 350ad53eeeSTejun Heo struct workqueue_struct *afs_wq; 365b86d4ffSDavid Howells static struct proc_dir_entry *afs_proc_symlink; 37f044c884SDavid Howells 386f8880d8SDavid Howells #if defined(CONFIG_ALPHA) 396f8880d8SDavid Howells const char afs_init_sysname[] = "alpha_linux26"; 406f8880d8SDavid Howells #elif defined(CONFIG_X86_64) 416f8880d8SDavid Howells const char afs_init_sysname[] = "amd64_linux26"; 426f8880d8SDavid Howells #elif defined(CONFIG_ARM) 436f8880d8SDavid Howells const char afs_init_sysname[] = "arm_linux26"; 446f8880d8SDavid Howells #elif defined(CONFIG_ARM64) 456f8880d8SDavid Howells const char afs_init_sysname[] = "aarch64_linux26"; 466f8880d8SDavid Howells #elif defined(CONFIG_X86_32) 476f8880d8SDavid Howells const char afs_init_sysname[] = "i386_linux26"; 486f8880d8SDavid Howells #elif defined(CONFIG_IA64) 496f8880d8SDavid Howells const char afs_init_sysname[] = "ia64_linux26"; 506f8880d8SDavid Howells #elif defined(CONFIG_PPC64) 516f8880d8SDavid Howells const char afs_init_sysname[] = "ppc64_linux26"; 526f8880d8SDavid Howells #elif defined(CONFIG_PPC32) 536f8880d8SDavid Howells const char afs_init_sysname[] = "ppc_linux26"; 546f8880d8SDavid Howells #elif defined(CONFIG_S390) 556f8880d8SDavid Howells #ifdef CONFIG_64BIT 566f8880d8SDavid Howells const char afs_init_sysname[] = "s390x_linux26"; 576f8880d8SDavid Howells #else 586f8880d8SDavid Howells const char afs_init_sysname[] = "s390_linux26"; 596f8880d8SDavid Howells #endif 606f8880d8SDavid Howells #elif defined(CONFIG_SPARC64) 616f8880d8SDavid Howells const char afs_init_sysname[] = "sparc64_linux26"; 626f8880d8SDavid Howells #elif defined(CONFIG_SPARC32) 636f8880d8SDavid Howells const char afs_init_sysname[] = "sparc_linux26"; 646f8880d8SDavid Howells #else 656f8880d8SDavid Howells const char afs_init_sysname[] = "unknown_linux26"; 666f8880d8SDavid Howells #endif 676f8880d8SDavid Howells 68f044c884SDavid Howells /* 69f044c884SDavid Howells * Initialise an AFS network namespace record. 70f044c884SDavid Howells */ 715b86d4ffSDavid Howells static int __net_init afs_net_init(struct net *net_ns) 72f044c884SDavid Howells { 736f8880d8SDavid Howells struct afs_sysnames *sysnames; 745b86d4ffSDavid Howells struct afs_net *net = afs_net(net_ns); 75f044c884SDavid Howells int ret; 76f044c884SDavid Howells 775b86d4ffSDavid Howells net->net = net_ns; 78f044c884SDavid Howells net->live = true; 79f044c884SDavid Howells generate_random_uuid((unsigned char *)&net->uuid); 80f044c884SDavid Howells 81f044c884SDavid Howells INIT_WORK(&net->charge_preallocation_work, afs_charge_preallocation); 82f044c884SDavid Howells mutex_init(&net->socket_mutex); 83989782dcSDavid Howells 84989782dcSDavid Howells net->cells = RB_ROOT; 85989782dcSDavid Howells seqlock_init(&net->cells_lock); 86989782dcSDavid Howells INIT_WORK(&net->cells_manager, afs_manage_cells); 87989782dcSDavid Howells timer_setup(&net->cells_timer, afs_cells_timer, 0); 88989782dcSDavid Howells 890da0b7fdSDavid Howells mutex_init(&net->proc_cells_lock); 90*6b3944e4SDavid Howells INIT_HLIST_HEAD(&net->proc_cells); 91989782dcSDavid Howells 92d2ddc776SDavid Howells seqlock_init(&net->fs_lock); 93d2ddc776SDavid Howells net->fs_servers = RB_ROOT; 94d2ddc776SDavid Howells INIT_LIST_HEAD(&net->fs_updates); 95d2ddc776SDavid Howells INIT_HLIST_HEAD(&net->fs_proc); 96d2ddc776SDavid Howells 97d2ddc776SDavid Howells INIT_HLIST_HEAD(&net->fs_addresses4); 98d2ddc776SDavid Howells INIT_HLIST_HEAD(&net->fs_addresses6); 99d2ddc776SDavid Howells seqlock_init(&net->fs_addr_lock); 100d2ddc776SDavid Howells 101d2ddc776SDavid Howells INIT_WORK(&net->fs_manager, afs_manage_servers); 102d2ddc776SDavid Howells timer_setup(&net->fs_timer, afs_servers_timer, 0); 103f044c884SDavid Howells 1046f8880d8SDavid Howells ret = -ENOMEM; 1056f8880d8SDavid Howells sysnames = kzalloc(sizeof(*sysnames), GFP_KERNEL); 1066f8880d8SDavid Howells if (!sysnames) 1076f8880d8SDavid Howells goto error_sysnames; 1086f8880d8SDavid Howells sysnames->subs[0] = (char *)&afs_init_sysname; 1096f8880d8SDavid Howells sysnames->nr = 1; 1106f8880d8SDavid Howells refcount_set(&sysnames->usage, 1); 1116f8880d8SDavid Howells net->sysnames = sysnames; 1126f8880d8SDavid Howells rwlock_init(&net->sysnames_lock); 1136f8880d8SDavid Howells 114f044c884SDavid Howells /* Register the /proc stuff */ 115f044c884SDavid Howells ret = afs_proc_init(net); 116f044c884SDavid Howells if (ret < 0) 117f044c884SDavid Howells goto error_proc; 118f044c884SDavid Howells 119f044c884SDavid Howells /* Initialise the cell DB */ 120f044c884SDavid Howells ret = afs_cell_init(net, rootcell); 121f044c884SDavid Howells if (ret < 0) 122f044c884SDavid Howells goto error_cell_init; 123f044c884SDavid Howells 124f044c884SDavid Howells /* Create the RxRPC transport */ 125f044c884SDavid Howells ret = afs_open_socket(net); 126f044c884SDavid Howells if (ret < 0) 127f044c884SDavid Howells goto error_open_socket; 128f044c884SDavid Howells 129f044c884SDavid Howells return 0; 130f044c884SDavid Howells 131f044c884SDavid Howells error_open_socket: 132989782dcSDavid Howells net->live = false; 133f044c884SDavid Howells afs_cell_purge(net); 134d2ddc776SDavid Howells afs_purge_servers(net); 135f044c884SDavid Howells error_cell_init: 136989782dcSDavid Howells net->live = false; 137f044c884SDavid Howells afs_proc_cleanup(net); 138f044c884SDavid Howells error_proc: 1396f8880d8SDavid Howells afs_put_sysnames(net->sysnames); 1406f8880d8SDavid Howells error_sysnames: 141989782dcSDavid Howells net->live = false; 142f044c884SDavid Howells return ret; 143f044c884SDavid Howells } 144f044c884SDavid Howells 145f044c884SDavid Howells /* 146f044c884SDavid Howells * Clean up and destroy an AFS network namespace record. 147f044c884SDavid Howells */ 1485b86d4ffSDavid Howells static void __net_exit afs_net_exit(struct net *net_ns) 149f044c884SDavid Howells { 1505b86d4ffSDavid Howells struct afs_net *net = afs_net(net_ns); 1515b86d4ffSDavid Howells 152f044c884SDavid Howells net->live = false; 153f044c884SDavid Howells afs_cell_purge(net); 154d2ddc776SDavid Howells afs_purge_servers(net); 155e3b2ffe0SDavid Howells afs_close_socket(net); 156f044c884SDavid Howells afs_proc_cleanup(net); 1576f8880d8SDavid Howells afs_put_sysnames(net->sysnames); 158f044c884SDavid Howells } 159b908fe6bSDavid Howells 1605b86d4ffSDavid Howells static struct pernet_operations afs_net_ops = { 1615b86d4ffSDavid Howells .init = afs_net_init, 1625b86d4ffSDavid Howells .exit = afs_net_exit, 1635b86d4ffSDavid Howells .id = &afs_net_id, 1645b86d4ffSDavid Howells .size = sizeof(struct afs_net), 1655b86d4ffSDavid Howells }; 1665b86d4ffSDavid Howells 167b908fe6bSDavid Howells /* 1681da177e4SLinus Torvalds * initialise the AFS client FS module 1691da177e4SLinus Torvalds */ 1701da177e4SLinus Torvalds static int __init afs_init(void) 1711da177e4SLinus Torvalds { 172f044c884SDavid Howells int ret = -ENOMEM; 1731da177e4SLinus Torvalds 1741da177e4SLinus Torvalds printk(KERN_INFO "kAFS: Red Hat AFS client v0.1 registering.\n"); 1751da177e4SLinus Torvalds 1760ad53eeeSTejun Heo afs_wq = alloc_workqueue("afs", 0, 0); 1770ad53eeeSTejun Heo if (!afs_wq) 178f044c884SDavid Howells goto error_afs_wq; 179f044c884SDavid Howells afs_async_calls = alloc_workqueue("kafsd", WQ_MEM_RECLAIM, 0); 180f044c884SDavid Howells if (!afs_async_calls) 181f044c884SDavid Howells goto error_async; 182f044c884SDavid Howells afs_lock_manager = alloc_workqueue("kafs_lockd", WQ_MEM_RECLAIM, 0); 183f044c884SDavid Howells if (!afs_lock_manager) 184f044c884SDavid Howells goto error_lockmgr; 1851da177e4SLinus Torvalds 1869b3f26c9SDavid Howells #ifdef CONFIG_AFS_FSCACHE 1871da177e4SLinus Torvalds /* we want to be able to cache */ 1889b3f26c9SDavid Howells ret = fscache_register_netfs(&afs_cache_netfs); 1891da177e4SLinus Torvalds if (ret < 0) 1901da177e4SLinus Torvalds goto error_cache; 1911da177e4SLinus Torvalds #endif 1921da177e4SLinus Torvalds 1935b86d4ffSDavid Howells ret = register_pernet_subsys(&afs_net_ops); 1941da177e4SLinus Torvalds if (ret < 0) 195f044c884SDavid Howells goto error_net; 1961da177e4SLinus Torvalds 1971da177e4SLinus Torvalds /* register the filesystems */ 1981da177e4SLinus Torvalds ret = afs_fs_init(); 1991da177e4SLinus Torvalds if (ret < 0) 200ec26815aSDavid Howells goto error_fs; 2011da177e4SLinus Torvalds 2025b86d4ffSDavid Howells afs_proc_symlink = proc_symlink("fs/afs", NULL, "../self/net/afs"); 2035b86d4ffSDavid Howells if (IS_ERR(afs_proc_symlink)) { 2045b86d4ffSDavid Howells ret = PTR_ERR(afs_proc_symlink); 2055b86d4ffSDavid Howells goto error_proc; 2065b86d4ffSDavid Howells } 2075b86d4ffSDavid Howells 2081da177e4SLinus Torvalds return ret; 2091da177e4SLinus Torvalds 2105b86d4ffSDavid Howells error_proc: 2115b86d4ffSDavid Howells afs_fs_exit(); 212ec26815aSDavid Howells error_fs: 2135b86d4ffSDavid Howells unregister_pernet_subsys(&afs_net_ops); 214f044c884SDavid Howells error_net: 2159b3f26c9SDavid Howells #ifdef CONFIG_AFS_FSCACHE 2169b3f26c9SDavid Howells fscache_unregister_netfs(&afs_cache_netfs); 217ec26815aSDavid Howells error_cache: 2181da177e4SLinus Torvalds #endif 219f044c884SDavid Howells destroy_workqueue(afs_lock_manager); 220f044c884SDavid Howells error_lockmgr: 221f044c884SDavid Howells destroy_workqueue(afs_async_calls); 222f044c884SDavid Howells error_async: 2230ad53eeeSTejun Heo destroy_workqueue(afs_wq); 224f044c884SDavid Howells error_afs_wq: 225416351f2SDavid Howells rcu_barrier(); 2261da177e4SLinus Torvalds printk(KERN_ERR "kAFS: failed to register: %d\n", ret); 2271da177e4SLinus Torvalds return ret; 228ec26815aSDavid Howells } 2291da177e4SLinus Torvalds 2301da177e4SLinus Torvalds /* XXX late_initcall is kludgy, but the only alternative seems to create 2311da177e4SLinus Torvalds * a transport upon the first mount, which is worse. Or is it? 2321da177e4SLinus Torvalds */ 2331da177e4SLinus Torvalds late_initcall(afs_init); /* must be called after net/ to create socket */ 234ec26815aSDavid Howells 2351da177e4SLinus Torvalds /* 2361da177e4SLinus Torvalds * clean up on module removal 2371da177e4SLinus Torvalds */ 2381da177e4SLinus Torvalds static void __exit afs_exit(void) 2391da177e4SLinus Torvalds { 2401da177e4SLinus Torvalds printk(KERN_INFO "kAFS: Red Hat AFS client v0.1 unregistering.\n"); 2411da177e4SLinus Torvalds 2425b86d4ffSDavid Howells proc_remove(afs_proc_symlink); 2431da177e4SLinus Torvalds afs_fs_exit(); 2445b86d4ffSDavid Howells unregister_pernet_subsys(&afs_net_ops); 2459b3f26c9SDavid Howells #ifdef CONFIG_AFS_FSCACHE 2469b3f26c9SDavid Howells fscache_unregister_netfs(&afs_cache_netfs); 2471da177e4SLinus Torvalds #endif 248f044c884SDavid Howells destroy_workqueue(afs_lock_manager); 249f044c884SDavid Howells destroy_workqueue(afs_async_calls); 250f044c884SDavid Howells destroy_workqueue(afs_wq); 251be080a6fSDavid Howells afs_clean_up_permit_cache(); 252416351f2SDavid Howells rcu_barrier(); 253ec26815aSDavid Howells } 2541da177e4SLinus Torvalds 2551da177e4SLinus Torvalds module_exit(afs_exit); 256