12874c5fdSThomas 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; 90*f6cbb368SDavid Howells INIT_LIST_HEAD(&net->fs_probe_fast); 91*f6cbb368SDavid Howells INIT_LIST_HEAD(&net->fs_probe_slow); 92d2ddc776SDavid Howells INIT_HLIST_HEAD(&net->fs_proc); 93d2ddc776SDavid Howells 94d2ddc776SDavid Howells INIT_HLIST_HEAD(&net->fs_addresses4); 95d2ddc776SDavid Howells INIT_HLIST_HEAD(&net->fs_addresses6); 96d2ddc776SDavid Howells seqlock_init(&net->fs_addr_lock); 97d2ddc776SDavid Howells 98d2ddc776SDavid Howells INIT_WORK(&net->fs_manager, afs_manage_servers); 99d2ddc776SDavid Howells timer_setup(&net->fs_timer, afs_servers_timer, 0); 100*f6cbb368SDavid Howells INIT_WORK(&net->fs_prober, afs_fs_probe_dispatcher); 101*f6cbb368SDavid Howells timer_setup(&net->fs_probe_timer, afs_fs_probe_timer, 0); 102f044c884SDavid Howells 1036f8880d8SDavid Howells ret = -ENOMEM; 1046f8880d8SDavid Howells sysnames = kzalloc(sizeof(*sysnames), GFP_KERNEL); 1056f8880d8SDavid Howells if (!sysnames) 1066f8880d8SDavid Howells goto error_sysnames; 1076f8880d8SDavid Howells sysnames->subs[0] = (char *)&afs_init_sysname; 1086f8880d8SDavid Howells sysnames->nr = 1; 1096f8880d8SDavid Howells refcount_set(&sysnames->usage, 1); 1106f8880d8SDavid Howells net->sysnames = sysnames; 1116f8880d8SDavid Howells rwlock_init(&net->sysnames_lock); 1126f8880d8SDavid Howells 113f044c884SDavid Howells /* Register the /proc stuff */ 114f044c884SDavid Howells ret = afs_proc_init(net); 115f044c884SDavid Howells if (ret < 0) 116f044c884SDavid Howells goto error_proc; 117f044c884SDavid Howells 118f044c884SDavid Howells /* Initialise the cell DB */ 119f044c884SDavid Howells ret = afs_cell_init(net, rootcell); 120f044c884SDavid Howells if (ret < 0) 121f044c884SDavid Howells goto error_cell_init; 122f044c884SDavid Howells 123f044c884SDavid Howells /* Create the RxRPC transport */ 124f044c884SDavid Howells ret = afs_open_socket(net); 125f044c884SDavid Howells if (ret < 0) 126f044c884SDavid Howells goto error_open_socket; 127f044c884SDavid Howells 128f044c884SDavid Howells return 0; 129f044c884SDavid Howells 130f044c884SDavid Howells error_open_socket: 131989782dcSDavid Howells net->live = false; 132f044c884SDavid Howells afs_cell_purge(net); 133d2ddc776SDavid Howells afs_purge_servers(net); 134f044c884SDavid Howells error_cell_init: 135989782dcSDavid Howells net->live = false; 136f044c884SDavid Howells afs_proc_cleanup(net); 137f044c884SDavid Howells error_proc: 1386f8880d8SDavid Howells afs_put_sysnames(net->sysnames); 1396f8880d8SDavid Howells error_sysnames: 140989782dcSDavid Howells net->live = false; 141f044c884SDavid Howells return ret; 142f044c884SDavid Howells } 143f044c884SDavid Howells 144f044c884SDavid Howells /* 145f044c884SDavid Howells * Clean up and destroy an AFS network namespace record. 146f044c884SDavid Howells */ 1475b86d4ffSDavid Howells static void __net_exit afs_net_exit(struct net *net_ns) 148f044c884SDavid Howells { 1495b86d4ffSDavid Howells struct afs_net *net = afs_net(net_ns); 1505b86d4ffSDavid Howells 151f044c884SDavid Howells net->live = false; 152f044c884SDavid Howells afs_cell_purge(net); 153d2ddc776SDavid Howells afs_purge_servers(net); 154e3b2ffe0SDavid Howells afs_close_socket(net); 155f044c884SDavid Howells afs_proc_cleanup(net); 1566f8880d8SDavid Howells afs_put_sysnames(net->sysnames); 157f044c884SDavid Howells } 158b908fe6bSDavid Howells 1595b86d4ffSDavid Howells static struct pernet_operations afs_net_ops = { 1605b86d4ffSDavid Howells .init = afs_net_init, 1615b86d4ffSDavid Howells .exit = afs_net_exit, 1625b86d4ffSDavid Howells .id = &afs_net_id, 1635b86d4ffSDavid Howells .size = sizeof(struct afs_net), 1645b86d4ffSDavid Howells }; 1655b86d4ffSDavid Howells 166b908fe6bSDavid Howells /* 1671da177e4SLinus Torvalds * initialise the AFS client FS module 1681da177e4SLinus Torvalds */ 1691da177e4SLinus Torvalds static int __init afs_init(void) 1701da177e4SLinus Torvalds { 171f044c884SDavid Howells int ret = -ENOMEM; 1721da177e4SLinus Torvalds 1731da177e4SLinus Torvalds printk(KERN_INFO "kAFS: Red Hat AFS client v0.1 registering.\n"); 1741da177e4SLinus Torvalds 1750ad53eeeSTejun Heo afs_wq = alloc_workqueue("afs", 0, 0); 1760ad53eeeSTejun Heo if (!afs_wq) 177f044c884SDavid Howells goto error_afs_wq; 178f044c884SDavid Howells afs_async_calls = alloc_workqueue("kafsd", WQ_MEM_RECLAIM, 0); 179f044c884SDavid Howells if (!afs_async_calls) 180f044c884SDavid Howells goto error_async; 181f044c884SDavid Howells afs_lock_manager = alloc_workqueue("kafs_lockd", WQ_MEM_RECLAIM, 0); 182f044c884SDavid Howells if (!afs_lock_manager) 183f044c884SDavid Howells goto error_lockmgr; 1841da177e4SLinus Torvalds 1859b3f26c9SDavid Howells #ifdef CONFIG_AFS_FSCACHE 1861da177e4SLinus Torvalds /* we want to be able to cache */ 1879b3f26c9SDavid Howells ret = fscache_register_netfs(&afs_cache_netfs); 1881da177e4SLinus Torvalds if (ret < 0) 1891da177e4SLinus Torvalds goto error_cache; 1901da177e4SLinus Torvalds #endif 1911da177e4SLinus Torvalds 1925b86d4ffSDavid Howells ret = register_pernet_subsys(&afs_net_ops); 1931da177e4SLinus Torvalds if (ret < 0) 194f044c884SDavid Howells goto error_net; 1951da177e4SLinus Torvalds 1961da177e4SLinus Torvalds /* register the filesystems */ 1971da177e4SLinus Torvalds ret = afs_fs_init(); 1981da177e4SLinus Torvalds if (ret < 0) 199ec26815aSDavid Howells goto error_fs; 2001da177e4SLinus Torvalds 2015b86d4ffSDavid Howells afs_proc_symlink = proc_symlink("fs/afs", NULL, "../self/net/afs"); 2025b86d4ffSDavid Howells if (IS_ERR(afs_proc_symlink)) { 2035b86d4ffSDavid Howells ret = PTR_ERR(afs_proc_symlink); 2045b86d4ffSDavid Howells goto error_proc; 2055b86d4ffSDavid Howells } 2065b86d4ffSDavid Howells 2071da177e4SLinus Torvalds return ret; 2081da177e4SLinus Torvalds 2095b86d4ffSDavid Howells error_proc: 2105b86d4ffSDavid Howells afs_fs_exit(); 211ec26815aSDavid Howells error_fs: 2125b86d4ffSDavid Howells unregister_pernet_subsys(&afs_net_ops); 213f044c884SDavid Howells error_net: 2149b3f26c9SDavid Howells #ifdef CONFIG_AFS_FSCACHE 2159b3f26c9SDavid Howells fscache_unregister_netfs(&afs_cache_netfs); 216ec26815aSDavid Howells error_cache: 2171da177e4SLinus Torvalds #endif 218f044c884SDavid Howells destroy_workqueue(afs_lock_manager); 219f044c884SDavid Howells error_lockmgr: 220f044c884SDavid Howells destroy_workqueue(afs_async_calls); 221f044c884SDavid Howells error_async: 2220ad53eeeSTejun Heo destroy_workqueue(afs_wq); 223f044c884SDavid Howells error_afs_wq: 224416351f2SDavid Howells rcu_barrier(); 2251da177e4SLinus Torvalds printk(KERN_ERR "kAFS: failed to register: %d\n", ret); 2261da177e4SLinus Torvalds return ret; 227ec26815aSDavid Howells } 2281da177e4SLinus Torvalds 2291da177e4SLinus Torvalds /* XXX late_initcall is kludgy, but the only alternative seems to create 2301da177e4SLinus Torvalds * a transport upon the first mount, which is worse. Or is it? 2311da177e4SLinus Torvalds */ 2321da177e4SLinus Torvalds late_initcall(afs_init); /* must be called after net/ to create socket */ 233ec26815aSDavid Howells 2341da177e4SLinus Torvalds /* 2351da177e4SLinus Torvalds * clean up on module removal 2361da177e4SLinus Torvalds */ 2371da177e4SLinus Torvalds static void __exit afs_exit(void) 2381da177e4SLinus Torvalds { 2391da177e4SLinus Torvalds printk(KERN_INFO "kAFS: Red Hat AFS client v0.1 unregistering.\n"); 2401da177e4SLinus Torvalds 2415b86d4ffSDavid Howells proc_remove(afs_proc_symlink); 2421da177e4SLinus Torvalds afs_fs_exit(); 2435b86d4ffSDavid Howells unregister_pernet_subsys(&afs_net_ops); 2449b3f26c9SDavid Howells #ifdef CONFIG_AFS_FSCACHE 2459b3f26c9SDavid Howells fscache_unregister_netfs(&afs_cache_netfs); 2461da177e4SLinus Torvalds #endif 247f044c884SDavid Howells destroy_workqueue(afs_lock_manager); 248f044c884SDavid Howells destroy_workqueue(afs_async_calls); 249f044c884SDavid Howells destroy_workqueue(afs_wq); 250be080a6fSDavid Howells afs_clean_up_permit_cache(); 251416351f2SDavid Howells rcu_barrier(); 252ec26815aSDavid Howells } 2531da177e4SLinus Torvalds 2541da177e4SLinus Torvalds module_exit(afs_exit); 255