main.c 5.7 KB
Newer Older
D
David Howells 已提交
1
/* AFS client file system
L
Linus Torvalds 已提交
2
 *
D
David Howells 已提交
3
 * Copyright (C) 2002,5 Red Hat, Inc. All Rights Reserved.
L
Linus Torvalds 已提交
4 5 6 7 8 9 10 11 12 13 14 15
 * Written by David Howells (dhowells@redhat.com)
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version
 * 2 of the License, or (at your option) any later version.
 */

#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/init.h>
#include <linux/completion.h>
A
Alexey Dobriyan 已提交
16
#include <linux/sched.h>
D
David Howells 已提交
17
#include <linux/random.h>
D
David Howells 已提交
18
#define CREATE_TRACE_POINTS
L
Linus Torvalds 已提交
19 20 21 22 23 24
#include "internal.h"

MODULE_DESCRIPTION("AFS Client File System");
MODULE_AUTHOR("Red Hat, Inc.");
MODULE_LICENSE("GPL");

25 26
unsigned afs_debug;
module_param_named(debug, afs_debug, uint, S_IWUSR | S_IRUGO);
27
MODULE_PARM_DESC(debug, "AFS debugging mask");
28

L
Linus Torvalds 已提交
29 30 31 32 33
static char *rootcell;

module_param(rootcell, charp, 0);
MODULE_PARM_DESC(rootcell, "root AFS cell name and VL server IP addr list");

34
struct workqueue_struct *afs_wq;
35 36
struct afs_net __afs_net;

37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66
#if defined(CONFIG_ALPHA)
const char afs_init_sysname[] = "alpha_linux26";
#elif defined(CONFIG_X86_64)
const char afs_init_sysname[] = "amd64_linux26";
#elif defined(CONFIG_ARM)
const char afs_init_sysname[] = "arm_linux26";
#elif defined(CONFIG_ARM64)
const char afs_init_sysname[] = "aarch64_linux26";
#elif defined(CONFIG_X86_32)
const char afs_init_sysname[] = "i386_linux26";
#elif defined(CONFIG_IA64)
const char afs_init_sysname[] = "ia64_linux26";
#elif defined(CONFIG_PPC64)
const char afs_init_sysname[] = "ppc64_linux26";
#elif defined(CONFIG_PPC32)
const char afs_init_sysname[] = "ppc_linux26";
#elif defined(CONFIG_S390)
#ifdef CONFIG_64BIT
const char afs_init_sysname[] = "s390x_linux26";
#else
const char afs_init_sysname[] = "s390_linux26";
#endif
#elif defined(CONFIG_SPARC64)
const char afs_init_sysname[] = "sparc64_linux26";
#elif defined(CONFIG_SPARC32)
const char afs_init_sysname[] = "sparc_linux26";
#else
const char afs_init_sysname[] = "unknown_linux26";
#endif

67 68 69 70 71
/*
 * Initialise an AFS network namespace record.
 */
static int __net_init afs_net_init(struct afs_net *net)
{
72
	struct afs_sysnames *sysnames;
73 74 75 76 77 78 79
	int ret;

	net->live = true;
	generate_random_uuid((unsigned char *)&net->uuid);

	INIT_WORK(&net->charge_preallocation_work, afs_charge_preallocation);
	mutex_init(&net->socket_mutex);
80 81 82 83 84 85 86

	net->cells = RB_ROOT;
	seqlock_init(&net->cells_lock);
	INIT_WORK(&net->cells_manager, afs_manage_cells);
	timer_setup(&net->cells_timer, afs_cells_timer, 0);

	spin_lock_init(&net->proc_cells_lock);
87
	INIT_LIST_HEAD(&net->proc_cells);
88

89 90 91 92 93 94 95 96 97 98 99
	seqlock_init(&net->fs_lock);
	net->fs_servers = RB_ROOT;
	INIT_LIST_HEAD(&net->fs_updates);
	INIT_HLIST_HEAD(&net->fs_proc);

	INIT_HLIST_HEAD(&net->fs_addresses4);
	INIT_HLIST_HEAD(&net->fs_addresses6);
	seqlock_init(&net->fs_addr_lock);

	INIT_WORK(&net->fs_manager, afs_manage_servers);
	timer_setup(&net->fs_timer, afs_servers_timer, 0);
100

101 102 103 104 105 106 107 108 109 110
	ret = -ENOMEM;
	sysnames = kzalloc(sizeof(*sysnames), GFP_KERNEL);
	if (!sysnames)
		goto error_sysnames;
	sysnames->subs[0] = (char *)&afs_init_sysname;
	sysnames->nr = 1;
	refcount_set(&sysnames->usage, 1);
	net->sysnames = sysnames;
	rwlock_init(&net->sysnames_lock);

111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128
	/* Register the /proc stuff */
	ret = afs_proc_init(net);
	if (ret < 0)
		goto error_proc;

	/* Initialise the cell DB */
	ret = afs_cell_init(net, rootcell);
	if (ret < 0)
		goto error_cell_init;

	/* Create the RxRPC transport */
	ret = afs_open_socket(net);
	if (ret < 0)
		goto error_open_socket;

	return 0;

error_open_socket:
129
	net->live = false;
130
	afs_cell_purge(net);
131
	afs_purge_servers(net);
132
error_cell_init:
133
	net->live = false;
134 135
	afs_proc_cleanup(net);
error_proc:
136 137
	afs_put_sysnames(net->sysnames);
error_sysnames:
138
	net->live = false;
139 140 141 142 143 144 145 146 147 148
	return ret;
}

/*
 * Clean up and destroy an AFS network namespace record.
 */
static void __net_exit afs_net_exit(struct afs_net *net)
{
	net->live = false;
	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

L
Linus Torvalds 已提交
155 156 157 158 159
/*
 * initialise the AFS client FS module
 */
static int __init afs_init(void)
{
160
	int ret = -ENOMEM;
L
Linus Torvalds 已提交
161 162 163

	printk(KERN_INFO "kAFS: Red Hat AFS client v0.1 registering.\n");

164 165
	afs_wq = alloc_workqueue("afs", 0, 0);
	if (!afs_wq)
166 167 168 169 170 171 172
		goto error_afs_wq;
	afs_async_calls = alloc_workqueue("kafsd", WQ_MEM_RECLAIM, 0);
	if (!afs_async_calls)
		goto error_async;
	afs_lock_manager = alloc_workqueue("kafs_lockd", WQ_MEM_RECLAIM, 0);
	if (!afs_lock_manager)
		goto error_lockmgr;
L
Linus Torvalds 已提交
173

D
David Howells 已提交
174
#ifdef CONFIG_AFS_FSCACHE
L
Linus Torvalds 已提交
175
	/* we want to be able to cache */
D
David Howells 已提交
176
	ret = fscache_register_netfs(&afs_cache_netfs);
L
Linus Torvalds 已提交
177 178 179 180
	if (ret < 0)
		goto error_cache;
#endif

181
	ret = afs_net_init(&__afs_net);
182
	if (ret < 0)
183
		goto error_net;
L
Linus Torvalds 已提交
184 185 186 187

	/* register the filesystems */
	ret = afs_fs_init();
	if (ret < 0)
D
David Howells 已提交
188
		goto error_fs;
L
Linus Torvalds 已提交
189 190 191

	return ret;

D
David Howells 已提交
192
error_fs:
193 194
	afs_net_exit(&__afs_net);
error_net:
D
David Howells 已提交
195 196
#ifdef CONFIG_AFS_FSCACHE
	fscache_unregister_netfs(&afs_cache_netfs);
D
David Howells 已提交
197
error_cache:
L
Linus Torvalds 已提交
198
#endif
199 200 201 202
	destroy_workqueue(afs_lock_manager);
error_lockmgr:
	destroy_workqueue(afs_async_calls);
error_async:
203
	destroy_workqueue(afs_wq);
204
error_afs_wq:
D
David Howells 已提交
205
	rcu_barrier();
L
Linus Torvalds 已提交
206 207
	printk(KERN_ERR "kAFS: failed to register: %d\n", ret);
	return ret;
D
David Howells 已提交
208
}
L
Linus Torvalds 已提交
209 210 211 212 213

/* XXX late_initcall is kludgy, but the only alternative seems to create
 * a transport upon the first mount, which is worse. Or is it?
 */
late_initcall(afs_init);	/* must be called after net/ to create socket */
D
David Howells 已提交
214

L
Linus Torvalds 已提交
215 216 217 218 219 220 221 222
/*
 * clean up on module removal
 */
static void __exit afs_exit(void)
{
	printk(KERN_INFO "kAFS: Red Hat AFS client v0.1 unregistering.\n");

	afs_fs_exit();
223
	afs_net_exit(&__afs_net);
D
David Howells 已提交
224 225
#ifdef CONFIG_AFS_FSCACHE
	fscache_unregister_netfs(&afs_cache_netfs);
L
Linus Torvalds 已提交
226
#endif
227 228 229
	destroy_workqueue(afs_lock_manager);
	destroy_workqueue(afs_async_calls);
	destroy_workqueue(afs_wq);
D
David Howells 已提交
230
	afs_clean_up_permit_cache();
D
David Howells 已提交
231
	rcu_barrier();
D
David Howells 已提交
232
}
L
Linus Torvalds 已提交
233 234

module_exit(afs_exit);