Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/fs/afs/main.c
26285 views
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 ([email protected])
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
18
MODULE_DESCRIPTION("AFS Client File System");
19
MODULE_AUTHOR("Red Hat, Inc.");
20
MODULE_LICENSE("GPL");
21
22
unsigned afs_debug;
23
module_param_named(debug, afs_debug, uint, S_IWUSR | S_IRUGO);
24
MODULE_PARM_DESC(debug, "AFS debugging mask");
25
26
static char *rootcell;
27
28
module_param(rootcell, charp, 0);
29
MODULE_PARM_DESC(rootcell, "root AFS cell name and VL server IP addr list");
30
31
struct workqueue_struct *afs_wq;
32
static struct proc_dir_entry *afs_proc_symlink;
33
34
#if defined(CONFIG_ALPHA)
35
const char afs_init_sysname[] = "alpha_linux26";
36
#elif defined(CONFIG_X86_64)
37
const char afs_init_sysname[] = "amd64_linux26";
38
#elif defined(CONFIG_ARM)
39
const char afs_init_sysname[] = "arm_linux26";
40
#elif defined(CONFIG_ARM64)
41
const char afs_init_sysname[] = "aarch64_linux26";
42
#elif defined(CONFIG_X86_32)
43
const char afs_init_sysname[] = "i386_linux26";
44
#elif defined(CONFIG_PPC64)
45
const char afs_init_sysname[] = "ppc64_linux26";
46
#elif defined(CONFIG_PPC32)
47
const char afs_init_sysname[] = "ppc_linux26";
48
#elif defined(CONFIG_S390)
49
#ifdef CONFIG_64BIT
50
const char afs_init_sysname[] = "s390x_linux26";
51
#else
52
const char afs_init_sysname[] = "s390_linux26";
53
#endif
54
#elif defined(CONFIG_SPARC64)
55
const char afs_init_sysname[] = "sparc64_linux26";
56
#elif defined(CONFIG_SPARC32)
57
const char afs_init_sysname[] = "sparc_linux26";
58
#else
59
const char afs_init_sysname[] = "unknown_linux26";
60
#endif
61
62
/*
63
* Initialise an AFS network namespace record.
64
*/
65
static int __net_init afs_net_init(struct net *net_ns)
66
{
67
struct afs_sysnames *sysnames;
68
struct afs_net *net = afs_net(net_ns);
69
int ret;
70
71
net->net = net_ns;
72
net->live = true;
73
generate_random_uuid((unsigned char *)&net->uuid);
74
75
INIT_WORK(&net->charge_preallocation_work, afs_charge_preallocation);
76
INIT_WORK(&net->rx_oob_work, afs_process_oob_queue);
77
mutex_init(&net->socket_mutex);
78
79
net->cells = RB_ROOT;
80
idr_init(&net->cells_dyn_ino);
81
init_rwsem(&net->cells_lock);
82
mutex_init(&net->cells_alias_lock);
83
mutex_init(&net->proc_cells_lock);
84
INIT_HLIST_HEAD(&net->proc_cells);
85
86
seqlock_init(&net->fs_lock);
87
INIT_LIST_HEAD(&net->fs_probe_fast);
88
INIT_LIST_HEAD(&net->fs_probe_slow);
89
INIT_HLIST_HEAD(&net->fs_proc);
90
91
INIT_WORK(&net->fs_prober, afs_fs_probe_dispatcher);
92
timer_setup(&net->fs_probe_timer, afs_fs_probe_timer, 0);
93
atomic_set(&net->servers_outstanding, 1);
94
95
ret = -ENOMEM;
96
sysnames = kzalloc(sizeof(*sysnames), GFP_KERNEL);
97
if (!sysnames)
98
goto error_sysnames;
99
sysnames->subs[0] = (char *)&afs_init_sysname;
100
sysnames->nr = 1;
101
refcount_set(&sysnames->usage, 1);
102
net->sysnames = sysnames;
103
rwlock_init(&net->sysnames_lock);
104
105
/* Register the /proc stuff */
106
ret = afs_proc_init(net);
107
if (ret < 0)
108
goto error_proc;
109
110
/* Initialise the cell DB */
111
ret = afs_cell_init(net, rootcell);
112
if (ret < 0)
113
goto error_cell_init;
114
115
/* Create the RxRPC transport */
116
ret = afs_open_socket(net);
117
if (ret < 0)
118
goto error_open_socket;
119
120
return 0;
121
122
error_open_socket:
123
net->live = false;
124
afs_fs_probe_cleanup(net);
125
afs_cell_purge(net);
126
afs_wait_for_servers(net);
127
error_cell_init:
128
net->live = false;
129
afs_proc_cleanup(net);
130
error_proc:
131
afs_put_sysnames(net->sysnames);
132
error_sysnames:
133
idr_destroy(&net->cells_dyn_ino);
134
net->live = false;
135
return ret;
136
}
137
138
/*
139
* Clean up and destroy an AFS network namespace record.
140
*/
141
static void __net_exit afs_net_exit(struct net *net_ns)
142
{
143
struct afs_net *net = afs_net(net_ns);
144
145
net->live = false;
146
afs_fs_probe_cleanup(net);
147
afs_cell_purge(net);
148
afs_wait_for_servers(net);
149
afs_close_socket(net);
150
afs_proc_cleanup(net);
151
afs_put_sysnames(net->sysnames);
152
idr_destroy(&net->cells_dyn_ino);
153
kfree_rcu(rcu_access_pointer(net->address_prefs), rcu);
154
}
155
156
static struct pernet_operations afs_net_ops = {
157
.init = afs_net_init,
158
.exit = afs_net_exit,
159
.id = &afs_net_id,
160
.size = sizeof(struct afs_net),
161
};
162
163
/*
164
* initialise the AFS client FS module
165
*/
166
static int __init afs_init(void)
167
{
168
int ret = -ENOMEM;
169
170
printk(KERN_INFO "kAFS: Red Hat AFS client v0.1 registering.\n");
171
172
afs_wq = alloc_workqueue("afs", 0, 0);
173
if (!afs_wq)
174
goto error_afs_wq;
175
afs_async_calls = alloc_workqueue("kafsd", WQ_MEM_RECLAIM | WQ_UNBOUND, 0);
176
if (!afs_async_calls)
177
goto error_async;
178
afs_lock_manager = alloc_workqueue("kafs_lockd", WQ_MEM_RECLAIM, 0);
179
if (!afs_lock_manager)
180
goto error_lockmgr;
181
182
ret = register_pernet_device(&afs_net_ops);
183
if (ret < 0)
184
goto error_net;
185
186
/* register the filesystems */
187
ret = afs_fs_init();
188
if (ret < 0)
189
goto error_fs;
190
191
afs_proc_symlink = proc_symlink("fs/afs", NULL, "../self/net/afs");
192
if (!afs_proc_symlink) {
193
ret = -ENOMEM;
194
goto error_proc;
195
}
196
197
return ret;
198
199
error_proc:
200
afs_fs_exit();
201
error_fs:
202
unregister_pernet_device(&afs_net_ops);
203
error_net:
204
destroy_workqueue(afs_lock_manager);
205
error_lockmgr:
206
destroy_workqueue(afs_async_calls);
207
error_async:
208
destroy_workqueue(afs_wq);
209
error_afs_wq:
210
rcu_barrier();
211
printk(KERN_ERR "kAFS: failed to register: %d\n", ret);
212
return ret;
213
}
214
215
/* XXX late_initcall is kludgy, but the only alternative seems to create
216
* a transport upon the first mount, which is worse. Or is it?
217
*/
218
late_initcall(afs_init); /* must be called after net/ to create socket */
219
220
/*
221
* clean up on module removal
222
*/
223
static void __exit afs_exit(void)
224
{
225
printk(KERN_INFO "kAFS: Red Hat AFS client v0.1 unregistering.\n");
226
227
proc_remove(afs_proc_symlink);
228
afs_fs_exit();
229
unregister_pernet_device(&afs_net_ops);
230
destroy_workqueue(afs_lock_manager);
231
destroy_workqueue(afs_async_calls);
232
destroy_workqueue(afs_wq);
233
afs_clean_up_permit_cache();
234
rcu_barrier();
235
}
236
237
module_exit(afs_exit);
238
239