[AF_RXRPC]: Add an interface to the AF_RXRPC module for the AFS filesystem to use
[linux-2.6-block.git] / fs / afs / main.c
CommitLineData
ec26815a 1/* AFS client file system
1da177e4
LT
2 *
3 * Copyright (C) 2002 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>
1da177e4
LT
15#include <linux/completion.h>
16#include <rxrpc/rxrpc.h>
17#include <rxrpc/transport.h>
18#include <rxrpc/call.h>
19#include <rxrpc/peer.h>
20#include "cache.h"
21#include "cell.h"
22#include "server.h"
23#include "fsclient.h"
24#include "cmservice.h"
25#include "kafstimod.h"
26#include "kafsasyncd.h"
27#include "internal.h"
28
29struct rxrpc_transport *afs_transport;
30
31static int afs_adding_peer(struct rxrpc_peer *peer);
32static void afs_discarding_peer(struct rxrpc_peer *peer);
33
34
35MODULE_DESCRIPTION("AFS Client File System");
36MODULE_AUTHOR("Red Hat, Inc.");
37MODULE_LICENSE("GPL");
38
39static char *rootcell;
40
41module_param(rootcell, charp, 0);
42MODULE_PARM_DESC(rootcell, "root AFS cell name and VL server IP addr list");
43
44
45static struct rxrpc_peer_ops afs_peer_ops = {
46 .adding = afs_adding_peer,
47 .discarding = afs_discarding_peer,
48};
49
50struct list_head afs_cb_hash_tbl[AFS_CB_HASH_COUNT];
51DEFINE_SPINLOCK(afs_cb_hash_lock);
52
53#ifdef AFS_CACHING_SUPPORT
54static struct cachefs_netfs_operations afs_cache_ops = {
55 .get_page_cookie = afs_cache_get_page_cookie,
56};
57
58struct cachefs_netfs afs_cache_netfs = {
59 .name = "afs",
60 .version = 0,
61 .ops = &afs_cache_ops,
62};
63#endif
64
1da177e4
LT
65/*
66 * initialise the AFS client FS module
67 */
68static int __init afs_init(void)
69{
70 int loop, ret;
71
72 printk(KERN_INFO "kAFS: Red Hat AFS client v0.1 registering.\n");
73
74 /* initialise the callback hash table */
75 spin_lock_init(&afs_cb_hash_lock);
76 for (loop = AFS_CB_HASH_COUNT - 1; loop >= 0; loop--)
77 INIT_LIST_HEAD(&afs_cb_hash_tbl[loop]);
78
79 /* register the /proc stuff */
80 ret = afs_proc_init();
81 if (ret < 0)
82 return ret;
83
84#ifdef AFS_CACHING_SUPPORT
85 /* we want to be able to cache */
86 ret = cachefs_register_netfs(&afs_cache_netfs,
87 &afs_cache_cell_index_def);
1da177e4
LT
88 if (ret < 0)
89 goto error_cache;
90#endif
91
92 /* initialise the cell DB */
93 ret = afs_cell_init(rootcell);
94 if (ret < 0)
ec26815a 95 goto error_cell_init;
1da177e4
LT
96
97 /* start the timeout daemon */
98 ret = afs_kafstimod_start();
99 if (ret < 0)
ec26815a 100 goto error_kafstimod;
1da177e4
LT
101
102 /* start the async operation daemon */
103 ret = afs_kafsasyncd_start();
104 if (ret < 0)
ec26815a 105 goto error_kafsasyncd;
1da177e4
LT
106
107 /* create the RxRPC transport */
108 ret = rxrpc_create_transport(7001, &afs_transport);
109 if (ret < 0)
ec26815a 110 goto error_transport;
1da177e4
LT
111
112 afs_transport->peer_ops = &afs_peer_ops;
113
114 /* register the filesystems */
115 ret = afs_fs_init();
116 if (ret < 0)
ec26815a 117 goto error_fs;
1da177e4
LT
118
119 return ret;
120
ec26815a 121error_fs:
1da177e4 122 rxrpc_put_transport(afs_transport);
ec26815a 123error_transport:
1da177e4 124 afs_kafsasyncd_stop();
ec26815a 125error_kafsasyncd:
1da177e4 126 afs_kafstimod_stop();
ec26815a
DH
127error_kafstimod:
128error_cell_init:
1da177e4
LT
129#ifdef AFS_CACHING_SUPPORT
130 cachefs_unregister_netfs(&afs_cache_netfs);
ec26815a 131error_cache:
1da177e4
LT
132#endif
133 afs_cell_purge();
134 afs_proc_cleanup();
135 printk(KERN_ERR "kAFS: failed to register: %d\n", ret);
136 return ret;
ec26815a 137}
1da177e4
LT
138
139/* XXX late_initcall is kludgy, but the only alternative seems to create
140 * a transport upon the first mount, which is worse. Or is it?
141 */
142late_initcall(afs_init); /* must be called after net/ to create socket */
ec26815a 143
1da177e4
LT
144/*
145 * clean up on module removal
146 */
147static void __exit afs_exit(void)
148{
149 printk(KERN_INFO "kAFS: Red Hat AFS client v0.1 unregistering.\n");
150
151 afs_fs_exit();
152 rxrpc_put_transport(afs_transport);
153 afs_kafstimod_stop();
154 afs_kafsasyncd_stop();
155 afs_cell_purge();
1da177e4
LT
156#ifdef AFS_CACHING_SUPPORT
157 cachefs_unregister_netfs(&afs_cache_netfs);
158#endif
159 afs_proc_cleanup();
ec26815a 160}
1da177e4
LT
161
162module_exit(afs_exit);
163
1da177e4
LT
164/*
165 * notification that new peer record is being added
166 * - called from krxsecd
167 * - return an error to induce an abort
168 * - mustn't sleep (caller holds an rwlock)
169 */
170static int afs_adding_peer(struct rxrpc_peer *peer)
171{
172 struct afs_server *server;
173 int ret;
174
175 _debug("kAFS: Adding new peer %08x\n", ntohl(peer->addr.s_addr));
176
177 /* determine which server the peer resides in (if any) */
178 ret = afs_server_find_by_peer(peer, &server);
179 if (ret < 0)
180 return ret; /* none that we recognise, so abort */
181
182 _debug("Server %p{u=%d}\n", server, atomic_read(&server->usage));
183
184 _debug("Cell %p{u=%d}\n",
185 server->cell, atomic_read(&server->cell->usage));
186
187 /* cross-point the structs under a global lock */
188 spin_lock(&afs_server_peer_lock);
189 peer->user = server;
190 server->peer = peer;
191 spin_unlock(&afs_server_peer_lock);
192
193 afs_put_server(server);
194
195 return 0;
ec26815a 196}
1da177e4 197
1da177e4
LT
198/*
199 * notification that a peer record is being discarded
200 * - called from krxiod or krxsecd
201 */
202static void afs_discarding_peer(struct rxrpc_peer *peer)
203{
204 struct afs_server *server;
205
206 _enter("%p",peer);
207
208 _debug("Discarding peer %08x (rtt=%lu.%lumS)\n",
209 ntohl(peer->addr.s_addr),
210 (long) (peer->rtt / 1000),
211 (long) (peer->rtt % 1000));
212
213 /* uncross-point the structs under a global lock */
214 spin_lock(&afs_server_peer_lock);
215 server = peer->user;
216 if (server) {
217 peer->user = NULL;
218 server->peer = NULL;
219 }
220 spin_unlock(&afs_server_peer_lock);
221
222 _leave("");
1da177e4 223}