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