linux/fs/afs/main.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-or-later
   2/* AFS client file system
   3 *
   4 * Copyright (C) 2002,5 Red Hat, Inc. All Rights Reserved.
   5 * Written by David Howells (dhowells@redhat.com)
   6 */
   7
   8#include <linux/module.h>
   9#include <linux/moduleparam.h>
  10#include <linux/init.h>
  11#include <linux/completion.h>
  12#include <linux/sched.h>
  13#include <linux/random.h>
  14#include <linux/proc_fs.h>
  15#define CREATE_TRACE_POINTS
  16#include "internal.h"
  17
  18MODULE_DESCRIPTION("AFS Client File System");
  19MODULE_AUTHOR("Red Hat, Inc.");
  20MODULE_LICENSE("GPL");
  21
  22unsigned afs_debug;
  23module_param_named(debug, afs_debug, uint, S_IWUSR | S_IRUGO);
  24MODULE_PARM_DESC(debug, "AFS debugging mask");
  25
  26static char *rootcell;
  27
  28module_param(rootcell, charp, 0);
  29MODULE_PARM_DESC(rootcell, "root AFS cell name and VL server IP addr list");
  30
  31struct workqueue_struct *afs_wq;
  32static struct proc_dir_entry *afs_proc_symlink;
  33
  34#if defined(CONFIG_ALPHA)
  35const char afs_init_sysname[] = "alpha_linux26";
  36#elif defined(CONFIG_X86_64)
  37const char afs_init_sysname[] = "amd64_linux26";
  38#elif defined(CONFIG_ARM)
  39const char afs_init_sysname[] = "arm_linux26";
  40#elif defined(CONFIG_ARM64)
  41const char afs_init_sysname[] = "aarch64_linux26";
  42#elif defined(CONFIG_X86_32)
  43const char afs_init_sysname[] = "i386_linux26";
  44#elif defined(CONFIG_IA64)
  45const char afs_init_sysname[] = "ia64_linux26";
  46#elif defined(CONFIG_PPC64)
  47const char afs_init_sysname[] = "ppc64_linux26";
  48#elif defined(CONFIG_PPC32)
  49const char afs_init_sysname[] = "ppc_linux26";
  50#elif defined(CONFIG_S390)
  51#ifdef CONFIG_64BIT
  52const char afs_init_sysname[] = "s390x_linux26";
  53#else
  54const char afs_init_sysname[] = "s390_linux26";
  55#endif
  56#elif defined(CONFIG_SPARC64)
  57const char afs_init_sysname[] = "sparc64_linux26";
  58#elif defined(CONFIG_SPARC32)
  59const char afs_init_sysname[] = "sparc_linux26";
  60#else
  61const char afs_init_sysname[] = "unknown_linux26";
  62#endif
  63
  64/*
  65 * Initialise an AFS network namespace record.
  66 */
  67static int __net_init afs_net_init(struct net *net_ns)
  68{
  69        struct afs_sysnames *sysnames;
  70        struct afs_net *net = afs_net(net_ns);
  71        int ret;
  72
  73        net->net = net_ns;
  74        net->live = true;
  75        generate_random_uuid((unsigned char *)&net->uuid);
  76
  77        INIT_WORK(&net->charge_preallocation_work, afs_charge_preallocation);
  78        mutex_init(&net->socket_mutex);
  79
  80        net->cells = RB_ROOT;
  81        init_rwsem(&net->cells_lock);
  82        INIT_WORK(&net->cells_manager, afs_manage_cells);
  83        timer_setup(&net->cells_timer, afs_cells_timer, 0);
  84
  85        mutex_init(&net->cells_alias_lock);
  86        mutex_init(&net->proc_cells_lock);
  87        INIT_HLIST_HEAD(&net->proc_cells);
  88
  89        seqlock_init(&net->fs_lock);
  90        net->fs_servers = RB_ROOT;
  91        INIT_LIST_HEAD(&net->fs_probe_fast);
  92        INIT_LIST_HEAD(&net->fs_probe_slow);
  93        INIT_HLIST_HEAD(&net->fs_proc);
  94
  95        INIT_HLIST_HEAD(&net->fs_addresses4);
  96        INIT_HLIST_HEAD(&net->fs_addresses6);
  97        seqlock_init(&net->fs_addr_lock);
  98
  99        INIT_WORK(&net->fs_manager, afs_manage_servers);
 100        timer_setup(&net->fs_timer, afs_servers_timer, 0);
 101        INIT_WORK(&net->fs_prober, afs_fs_probe_dispatcher);
 102        timer_setup(&net->fs_probe_timer, afs_fs_probe_timer, 0);
 103        atomic_set(&net->servers_outstanding, 1);
 104
 105        ret = -ENOMEM;
 106        sysnames = kzalloc(sizeof(*sysnames), GFP_KERNEL);
 107        if (!sysnames)
 108                goto error_sysnames;
 109        sysnames->subs[0] = (char *)&afs_init_sysname;
 110        sysnames->nr = 1;
 111        refcount_set(&sysnames->usage, 1);
 112        net->sysnames = sysnames;
 113        rwlock_init(&net->sysnames_lock);
 114
 115        /* Register the /proc stuff */
 116        ret = afs_proc_init(net);
 117        if (ret < 0)
 118                goto error_proc;
 119
 120        /* Initialise the cell DB */
 121        ret = afs_cell_init(net, rootcell);
 122        if (ret < 0)
 123                goto error_cell_init;
 124
 125        /* Create the RxRPC transport */
 126        ret = afs_open_socket(net);
 127        if (ret < 0)
 128                goto error_open_socket;
 129
 130        return 0;
 131
 132error_open_socket:
 133        net->live = false;
 134        afs_fs_probe_cleanup(net);
 135        afs_cell_purge(net);
 136        afs_purge_servers(net);
 137error_cell_init:
 138        net->live = false;
 139        afs_proc_cleanup(net);
 140error_proc:
 141        afs_put_sysnames(net->sysnames);
 142error_sysnames:
 143        net->live = false;
 144        return ret;
 145}
 146
 147/*
 148 * Clean up and destroy an AFS network namespace record.
 149 */
 150static void __net_exit afs_net_exit(struct net *net_ns)
 151{
 152        struct afs_net *net = afs_net(net_ns);
 153
 154        net->live = false;
 155        afs_fs_probe_cleanup(net);
 156        afs_cell_purge(net);
 157        afs_purge_servers(net);
 158        afs_close_socket(net);
 159        afs_proc_cleanup(net);
 160        afs_put_sysnames(net->sysnames);
 161}
 162
 163static struct pernet_operations afs_net_ops = {
 164        .init   = afs_net_init,
 165        .exit   = afs_net_exit,
 166        .id     = &afs_net_id,
 167        .size   = sizeof(struct afs_net),
 168};
 169
 170/*
 171 * initialise the AFS client FS module
 172 */
 173static int __init afs_init(void)
 174{
 175        int ret = -ENOMEM;
 176
 177        printk(KERN_INFO "kAFS: Red Hat AFS client v0.1 registering.\n");
 178
 179        afs_wq = alloc_workqueue("afs", 0, 0);
 180        if (!afs_wq)
 181                goto error_afs_wq;
 182        afs_async_calls = alloc_workqueue("kafsd", WQ_MEM_RECLAIM, 0);
 183        if (!afs_async_calls)
 184                goto error_async;
 185        afs_lock_manager = alloc_workqueue("kafs_lockd", WQ_MEM_RECLAIM, 0);
 186        if (!afs_lock_manager)
 187                goto error_lockmgr;
 188
 189#ifdef CONFIG_AFS_FSCACHE
 190        /* we want to be able to cache */
 191        ret = fscache_register_netfs(&afs_cache_netfs);
 192        if (ret < 0)
 193                goto error_cache;
 194#endif
 195
 196        ret = register_pernet_device(&afs_net_ops);
 197        if (ret < 0)
 198                goto error_net;
 199
 200        /* register the filesystems */
 201        ret = afs_fs_init();
 202        if (ret < 0)
 203                goto error_fs;
 204
 205        afs_proc_symlink = proc_symlink("fs/afs", NULL, "../self/net/afs");
 206        if (!afs_proc_symlink) {
 207                ret = -ENOMEM;
 208                goto error_proc;
 209        }
 210
 211        return ret;
 212
 213error_proc:
 214        afs_fs_exit();
 215error_fs:
 216        unregister_pernet_device(&afs_net_ops);
 217error_net:
 218#ifdef CONFIG_AFS_FSCACHE
 219        fscache_unregister_netfs(&afs_cache_netfs);
 220error_cache:
 221#endif
 222        destroy_workqueue(afs_lock_manager);
 223error_lockmgr:
 224        destroy_workqueue(afs_async_calls);
 225error_async:
 226        destroy_workqueue(afs_wq);
 227error_afs_wq:
 228        rcu_barrier();
 229        printk(KERN_ERR "kAFS: failed to register: %d\n", ret);
 230        return ret;
 231}
 232
 233/* XXX late_initcall is kludgy, but the only alternative seems to create
 234 * a transport upon the first mount, which is worse. Or is it?
 235 */
 236late_initcall(afs_init);        /* must be called after net/ to create socket */
 237
 238/*
 239 * clean up on module removal
 240 */
 241static void __exit afs_exit(void)
 242{
 243        printk(KERN_INFO "kAFS: Red Hat AFS client v0.1 unregistering.\n");
 244
 245        proc_remove(afs_proc_symlink);
 246        afs_fs_exit();
 247        unregister_pernet_device(&afs_net_ops);
 248#ifdef CONFIG_AFS_FSCACHE
 249        fscache_unregister_netfs(&afs_cache_netfs);
 250#endif
 251        destroy_workqueue(afs_lock_manager);
 252        destroy_workqueue(afs_async_calls);
 253        destroy_workqueue(afs_wq);
 254        afs_clean_up_permit_cache();
 255        rcu_barrier();
 256}
 257
 258module_exit(afs_exit);
 259