1*2874c5fdSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later 2ec26815aSDavid Howells /* AFS client file system 31da177e4SLinus Torvalds * 49b3f26c9SDavid Howells * Copyright (C) 2002,5 Red Hat, Inc. All Rights Reserved. 51da177e4SLinus Torvalds * Written by David Howells (dhowells@redhat.com) 61da177e4SLinus Torvalds */ 71da177e4SLinus Torvalds 81da177e4SLinus Torvalds #include <linux/module.h> 91da177e4SLinus Torvalds #include <linux/moduleparam.h> 101da177e4SLinus Torvalds #include <linux/init.h> 111da177e4SLinus Torvalds #include <linux/completion.h> 12e8edc6e0SAlexey Dobriyan #include <linux/sched.h> 13e0661dfcSDavid Howells #include <linux/random.h> 145b86d4ffSDavid Howells #include <linux/proc_fs.h> 158e8d7f13SDavid Howells #define CREATE_TRACE_POINTS 161da177e4SLinus Torvalds #include "internal.h" 171da177e4SLinus Torvalds 181da177e4SLinus Torvalds MODULE_DESCRIPTION("AFS Client File System"); 191da177e4SLinus Torvalds MODULE_AUTHOR("Red Hat, Inc."); 201da177e4SLinus Torvalds MODULE_LICENSE("GPL"); 211da177e4SLinus Torvalds 2208e0e7c8SDavid Howells unsigned afs_debug; 2308e0e7c8SDavid Howells module_param_named(debug, afs_debug, uint, S_IWUSR | S_IRUGO); 24424b00e2SPaul Bolle MODULE_PARM_DESC(debug, "AFS debugging mask"); 2508e0e7c8SDavid Howells 261da177e4SLinus Torvalds static char *rootcell; 271da177e4SLinus Torvalds 281da177e4SLinus Torvalds module_param(rootcell, charp, 0); 291da177e4SLinus Torvalds MODULE_PARM_DESC(rootcell, "root AFS cell name and VL server IP addr list"); 301da177e4SLinus Torvalds 310ad53eeeSTejun Heo struct workqueue_struct *afs_wq; 325b86d4ffSDavid Howells static struct proc_dir_entry *afs_proc_symlink; 33f044c884SDavid Howells 346f8880d8SDavid Howells #if defined(CONFIG_ALPHA) 356f8880d8SDavid Howells const char afs_init_sysname[] = "alpha_linux26"; 366f8880d8SDavid Howells #elif defined(CONFIG_X86_64) 376f8880d8SDavid Howells const char afs_init_sysname[] = "amd64_linux26"; 386f8880d8SDavid Howells #elif defined(CONFIG_ARM) 396f8880d8SDavid Howells const char afs_init_sysname[] = "arm_linux26"; 406f8880d8SDavid Howells #elif defined(CONFIG_ARM64) 416f8880d8SDavid Howells const char afs_init_sysname[] = "aarch64_linux26"; 426f8880d8SDavid Howells #elif defined(CONFIG_X86_32) 436f8880d8SDavid Howells const char afs_init_sysname[] = "i386_linux26"; 446f8880d8SDavid Howells #elif defined(CONFIG_IA64) 456f8880d8SDavid Howells const char afs_init_sysname[] = "ia64_linux26"; 466f8880d8SDavid Howells #elif defined(CONFIG_PPC64) 476f8880d8SDavid Howells const char afs_init_sysname[] = "ppc64_linux26"; 486f8880d8SDavid Howells #elif defined(CONFIG_PPC32) 496f8880d8SDavid Howells const char afs_init_sysname[] = "ppc_linux26"; 506f8880d8SDavid Howells #elif defined(CONFIG_S390) 516f8880d8SDavid Howells #ifdef CONFIG_64BIT 526f8880d8SDavid Howells const char afs_init_sysname[] = "s390x_linux26"; 536f8880d8SDavid Howells #else 546f8880d8SDavid Howells const char afs_init_sysname[] = "s390_linux26"; 556f8880d8SDavid Howells #endif 566f8880d8SDavid Howells #elif defined(CONFIG_SPARC64) 576f8880d8SDavid Howells const char afs_init_sysname[] = "sparc64_linux26"; 586f8880d8SDavid Howells #elif defined(CONFIG_SPARC32) 596f8880d8SDavid Howells const char afs_init_sysname[] = "sparc_linux26"; 606f8880d8SDavid Howells #else 616f8880d8SDavid Howells const char afs_init_sysname[] = "unknown_linux26"; 626f8880d8SDavid Howells #endif 636f8880d8SDavid Howells 64f044c884SDavid Howells /* 65f044c884SDavid Howells * Initialise an AFS network namespace record. 66f044c884SDavid Howells */ 675b86d4ffSDavid Howells static int __net_init afs_net_init(struct net *net_ns) 68f044c884SDavid Howells { 696f8880d8SDavid Howells struct afs_sysnames *sysnames; 705b86d4ffSDavid Howells struct afs_net *net = afs_net(net_ns); 71f044c884SDavid Howells int ret; 72f044c884SDavid Howells 735b86d4ffSDavid Howells net->net = net_ns; 74f044c884SDavid Howells net->live = true; 75f044c884SDavid Howells generate_random_uuid((unsigned char *)&net->uuid); 76f044c884SDavid Howells 77f044c884SDavid Howells INIT_WORK(&net->charge_preallocation_work, afs_charge_preallocation); 78f044c884SDavid Howells mutex_init(&net->socket_mutex); 79989782dcSDavid Howells 80989782dcSDavid Howells net->cells = RB_ROOT; 81989782dcSDavid Howells seqlock_init(&net->cells_lock); 82989782dcSDavid Howells INIT_WORK(&net->cells_manager, afs_manage_cells); 83989782dcSDavid Howells timer_setup(&net->cells_timer, afs_cells_timer, 0); 84989782dcSDavid Howells 850da0b7fdSDavid Howells mutex_init(&net->proc_cells_lock); 866b3944e4SDavid Howells INIT_HLIST_HEAD(&net->proc_cells); 87989782dcSDavid Howells 88d2ddc776SDavid Howells seqlock_init(&net->fs_lock); 89d2ddc776SDavid Howells net->fs_servers = RB_ROOT; 90d2ddc776SDavid Howells INIT_LIST_HEAD(&net->fs_updates); 91d2ddc776SDavid Howells INIT_HLIST_HEAD(&net->fs_proc); 92d2ddc776SDavid Howells 93d2ddc776SDavid Howells INIT_HLIST_HEAD(&net->fs_addresses4); 94d2ddc776SDavid Howells INIT_HLIST_HEAD(&net->fs_addresses6); 95d2ddc776SDavid Howells seqlock_init(&net->fs_addr_lock); 96d2ddc776SDavid Howells 97d2ddc776SDavid Howells INIT_WORK(&net->fs_manager, afs_manage_servers); 98d2ddc776SDavid Howells timer_setup(&net->fs_timer, afs_servers_timer, 0); 99f044c884SDavid Howells 1006f8880d8SDavid Howells ret = -ENOMEM; 1016f8880d8SDavid Howells sysnames = kzalloc(sizeof(*sysnames), GFP_KERNEL); 1026f8880d8SDavid Howells if (!sysnames) 1036f8880d8SDavid Howells goto error_sysnames; 1046f8880d8SDavid Howells sysnames->subs[0] = (char *)&afs_init_sysname; 1056f8880d8SDavid Howells sysnames->nr = 1; 1066f8880d8SDavid Howells refcount_set(&sysnames->usage, 1); 1076f8880d8SDavid Howells net->sysnames = sysnames; 1086f8880d8SDavid Howells rwlock_init(&net->sysnames_lock); 1096f8880d8SDavid Howells 110f044c884SDavid Howells /* Register the /proc stuff */ 111f044c884SDavid Howells ret = afs_proc_init(net); 112f044c884SDavid Howells if (ret < 0) 113f044c884SDavid Howells goto error_proc; 114f044c884SDavid Howells 115f044c884SDavid Howells /* Initialise the cell DB */ 116f044c884SDavid Howells ret = afs_cell_init(net, rootcell); 117f044c884SDavid Howells if (ret < 0) 118f044c884SDavid Howells goto error_cell_init; 119f044c884SDavid Howells 120f044c884SDavid Howells /* Create the RxRPC transport */ 121f044c884SDavid Howells ret = afs_open_socket(net); 122f044c884SDavid Howells if (ret < 0) 123f044c884SDavid Howells goto error_open_socket; 124f044c884SDavid Howells 125f044c884SDavid Howells return 0; 126f044c884SDavid Howells 127f044c884SDavid Howells error_open_socket: 128989782dcSDavid Howells net->live = false; 129f044c884SDavid Howells afs_cell_purge(net); 130d2ddc776SDavid Howells afs_purge_servers(net); 131f044c884SDavid Howells error_cell_init: 132989782dcSDavid Howells net->live = false; 133f044c884SDavid Howells afs_proc_cleanup(net); 134f044c884SDavid Howells error_proc: 1356f8880d8SDavid Howells afs_put_sysnames(net->sysnames); 1366f8880d8SDavid Howells error_sysnames: 137989782dcSDavid Howells net->live = false; 138f044c884SDavid Howells return ret; 139f044c884SDavid Howells } 140f044c884SDavid Howells 141f044c884SDavid Howells /* 142f044c884SDavid Howells * Clean up and destroy an AFS network namespace record. 143f044c884SDavid Howells */ 1445b86d4ffSDavid Howells static void __net_exit afs_net_exit(struct net *net_ns) 145f044c884SDavid Howells { 1465b86d4ffSDavid Howells struct afs_net *net = afs_net(net_ns); 1475b86d4ffSDavid Howells 148f044c884SDavid Howells net->live = false; 149f044c884SDavid Howells afs_cell_purge(net); 150d2ddc776SDavid Howells afs_purge_servers(net); 151e3b2ffe0SDavid Howells afs_close_socket(net); 152f044c884SDavid Howells afs_proc_cleanup(net); 1536f8880d8SDavid Howells afs_put_sysnames(net->sysnames); 154f044c884SDavid Howells } 155b908fe6bSDavid Howells 1565b86d4ffSDavid Howells static struct pernet_operations afs_net_ops = { 1575b86d4ffSDavid Howells .init = afs_net_init, 1585b86d4ffSDavid Howells .exit = afs_net_exit, 1595b86d4ffSDavid Howells .id = &afs_net_id, 1605b86d4ffSDavid Howells .size = sizeof(struct afs_net), 1615b86d4ffSDavid Howells }; 1625b86d4ffSDavid Howells 163b908fe6bSDavid Howells /* 1641da177e4SLinus Torvalds * initialise the AFS client FS module 1651da177e4SLinus Torvalds */ 1661da177e4SLinus Torvalds static int __init afs_init(void) 1671da177e4SLinus Torvalds { 168f044c884SDavid Howells int ret = -ENOMEM; 1691da177e4SLinus Torvalds 1701da177e4SLinus Torvalds printk(KERN_INFO "kAFS: Red Hat AFS client v0.1 registering.\n"); 1711da177e4SLinus Torvalds 1720ad53eeeSTejun Heo afs_wq = alloc_workqueue("afs", 0, 0); 1730ad53eeeSTejun Heo if (!afs_wq) 174f044c884SDavid Howells goto error_afs_wq; 175f044c884SDavid Howells afs_async_calls = alloc_workqueue("kafsd", WQ_MEM_RECLAIM, 0); 176f044c884SDavid Howells if (!afs_async_calls) 177f044c884SDavid Howells goto error_async; 178f044c884SDavid Howells afs_lock_manager = alloc_workqueue("kafs_lockd", WQ_MEM_RECLAIM, 0); 179f044c884SDavid Howells if (!afs_lock_manager) 180f044c884SDavid Howells goto error_lockmgr; 1811da177e4SLinus Torvalds 1829b3f26c9SDavid Howells #ifdef CONFIG_AFS_FSCACHE 1831da177e4SLinus Torvalds /* we want to be able to cache */ 1849b3f26c9SDavid Howells ret = fscache_register_netfs(&afs_cache_netfs); 1851da177e4SLinus Torvalds if (ret < 0) 1861da177e4SLinus Torvalds goto error_cache; 1871da177e4SLinus Torvalds #endif 1881da177e4SLinus Torvalds 1895b86d4ffSDavid Howells ret = register_pernet_subsys(&afs_net_ops); 1901da177e4SLinus Torvalds if (ret < 0) 191f044c884SDavid Howells goto error_net; 1921da177e4SLinus Torvalds 1931da177e4SLinus Torvalds /* register the filesystems */ 1941da177e4SLinus Torvalds ret = afs_fs_init(); 1951da177e4SLinus Torvalds if (ret < 0) 196ec26815aSDavid Howells goto error_fs; 1971da177e4SLinus Torvalds 1985b86d4ffSDavid Howells afs_proc_symlink = proc_symlink("fs/afs", NULL, "../self/net/afs"); 1995b86d4ffSDavid Howells if (IS_ERR(afs_proc_symlink)) { 2005b86d4ffSDavid Howells ret = PTR_ERR(afs_proc_symlink); 2015b86d4ffSDavid Howells goto error_proc; 2025b86d4ffSDavid Howells } 2035b86d4ffSDavid Howells 2041da177e4SLinus Torvalds return ret; 2051da177e4SLinus Torvalds 2065b86d4ffSDavid Howells error_proc: 2075b86d4ffSDavid Howells afs_fs_exit(); 208ec26815aSDavid Howells error_fs: 2095b86d4ffSDavid Howells unregister_pernet_subsys(&afs_net_ops); 210f044c884SDavid Howells error_net: 2119b3f26c9SDavid Howells #ifdef CONFIG_AFS_FSCACHE 2129b3f26c9SDavid Howells fscache_unregister_netfs(&afs_cache_netfs); 213ec26815aSDavid Howells error_cache: 2141da177e4SLinus Torvalds #endif 215f044c884SDavid Howells destroy_workqueue(afs_lock_manager); 216f044c884SDavid Howells error_lockmgr: 217f044c884SDavid Howells destroy_workqueue(afs_async_calls); 218f044c884SDavid Howells error_async: 2190ad53eeeSTejun Heo destroy_workqueue(afs_wq); 220f044c884SDavid Howells error_afs_wq: 221416351f2SDavid Howells rcu_barrier(); 2221da177e4SLinus Torvalds printk(KERN_ERR "kAFS: failed to register: %d\n", ret); 2231da177e4SLinus Torvalds return ret; 224ec26815aSDavid Howells } 2251da177e4SLinus Torvalds 2261da177e4SLinus Torvalds /* XXX late_initcall is kludgy, but the only alternative seems to create 2271da177e4SLinus Torvalds * a transport upon the first mount, which is worse. Or is it? 2281da177e4SLinus Torvalds */ 2291da177e4SLinus Torvalds late_initcall(afs_init); /* must be called after net/ to create socket */ 230ec26815aSDavid Howells 2311da177e4SLinus Torvalds /* 2321da177e4SLinus Torvalds * clean up on module removal 2331da177e4SLinus Torvalds */ 2341da177e4SLinus Torvalds static void __exit afs_exit(void) 2351da177e4SLinus Torvalds { 2361da177e4SLinus Torvalds printk(KERN_INFO "kAFS: Red Hat AFS client v0.1 unregistering.\n"); 2371da177e4SLinus Torvalds 2385b86d4ffSDavid Howells proc_remove(afs_proc_symlink); 2391da177e4SLinus Torvalds afs_fs_exit(); 2405b86d4ffSDavid Howells unregister_pernet_subsys(&afs_net_ops); 2419b3f26c9SDavid Howells #ifdef CONFIG_AFS_FSCACHE 2429b3f26c9SDavid Howells fscache_unregister_netfs(&afs_cache_netfs); 2431da177e4SLinus Torvalds #endif 244f044c884SDavid Howells destroy_workqueue(afs_lock_manager); 245f044c884SDavid Howells destroy_workqueue(afs_async_calls); 246f044c884SDavid Howells destroy_workqueue(afs_wq); 247be080a6fSDavid Howells afs_clean_up_permit_cache(); 248416351f2SDavid Howells rcu_barrier(); 249ec26815aSDavid Howells } 2501da177e4SLinus Torvalds 2511da177e4SLinus Torvalds module_exit(afs_exit); 252