xref: /openbmc/linux/fs/afs/main.c (revision 1da177e4c3f41524e886b7f1b8a0c1fc7321cac2)
1*1da177e4SLinus Torvalds /* main.c: AFS client file system
2*1da177e4SLinus Torvalds  *
3*1da177e4SLinus Torvalds  * Copyright (C) 2002 Red Hat, Inc. All Rights Reserved.
4*1da177e4SLinus Torvalds  * Written by David Howells (dhowells@redhat.com)
5*1da177e4SLinus Torvalds  *
6*1da177e4SLinus Torvalds  * This program is free software; you can redistribute it and/or
7*1da177e4SLinus Torvalds  * modify it under the terms of the GNU General Public License
8*1da177e4SLinus Torvalds  * as published by the Free Software Foundation; either version
9*1da177e4SLinus Torvalds  * 2 of the License, or (at your option) any later version.
10*1da177e4SLinus Torvalds  */
11*1da177e4SLinus Torvalds 
12*1da177e4SLinus Torvalds #include <linux/module.h>
13*1da177e4SLinus Torvalds #include <linux/moduleparam.h>
14*1da177e4SLinus Torvalds #include <linux/init.h>
15*1da177e4SLinus Torvalds #include <linux/sched.h>
16*1da177e4SLinus Torvalds #include <linux/completion.h>
17*1da177e4SLinus Torvalds #include <rxrpc/rxrpc.h>
18*1da177e4SLinus Torvalds #include <rxrpc/transport.h>
19*1da177e4SLinus Torvalds #include <rxrpc/call.h>
20*1da177e4SLinus Torvalds #include <rxrpc/peer.h>
21*1da177e4SLinus Torvalds #include "cache.h"
22*1da177e4SLinus Torvalds #include "cell.h"
23*1da177e4SLinus Torvalds #include "server.h"
24*1da177e4SLinus Torvalds #include "fsclient.h"
25*1da177e4SLinus Torvalds #include "cmservice.h"
26*1da177e4SLinus Torvalds #include "kafstimod.h"
27*1da177e4SLinus Torvalds #include "kafsasyncd.h"
28*1da177e4SLinus Torvalds #include "internal.h"
29*1da177e4SLinus Torvalds 
30*1da177e4SLinus Torvalds struct rxrpc_transport *afs_transport;
31*1da177e4SLinus Torvalds 
32*1da177e4SLinus Torvalds static int afs_adding_peer(struct rxrpc_peer *peer);
33*1da177e4SLinus Torvalds static void afs_discarding_peer(struct rxrpc_peer *peer);
34*1da177e4SLinus Torvalds 
35*1da177e4SLinus Torvalds 
36*1da177e4SLinus Torvalds MODULE_DESCRIPTION("AFS Client File System");
37*1da177e4SLinus Torvalds MODULE_AUTHOR("Red Hat, Inc.");
38*1da177e4SLinus Torvalds MODULE_LICENSE("GPL");
39*1da177e4SLinus Torvalds 
40*1da177e4SLinus Torvalds static char *rootcell;
41*1da177e4SLinus Torvalds 
42*1da177e4SLinus Torvalds module_param(rootcell, charp, 0);
43*1da177e4SLinus Torvalds MODULE_PARM_DESC(rootcell, "root AFS cell name and VL server IP addr list");
44*1da177e4SLinus Torvalds 
45*1da177e4SLinus Torvalds 
46*1da177e4SLinus Torvalds static struct rxrpc_peer_ops afs_peer_ops = {
47*1da177e4SLinus Torvalds 	.adding		= afs_adding_peer,
48*1da177e4SLinus Torvalds 	.discarding	= afs_discarding_peer,
49*1da177e4SLinus Torvalds };
50*1da177e4SLinus Torvalds 
51*1da177e4SLinus Torvalds struct list_head afs_cb_hash_tbl[AFS_CB_HASH_COUNT];
52*1da177e4SLinus Torvalds DEFINE_SPINLOCK(afs_cb_hash_lock);
53*1da177e4SLinus Torvalds 
54*1da177e4SLinus Torvalds #ifdef AFS_CACHING_SUPPORT
55*1da177e4SLinus Torvalds static struct cachefs_netfs_operations afs_cache_ops = {
56*1da177e4SLinus Torvalds 	.get_page_cookie	= afs_cache_get_page_cookie,
57*1da177e4SLinus Torvalds };
58*1da177e4SLinus Torvalds 
59*1da177e4SLinus Torvalds struct cachefs_netfs afs_cache_netfs = {
60*1da177e4SLinus Torvalds 	.name			= "afs",
61*1da177e4SLinus Torvalds 	.version		= 0,
62*1da177e4SLinus Torvalds 	.ops			= &afs_cache_ops,
63*1da177e4SLinus Torvalds };
64*1da177e4SLinus Torvalds #endif
65*1da177e4SLinus Torvalds 
66*1da177e4SLinus Torvalds /*****************************************************************************/
67*1da177e4SLinus Torvalds /*
68*1da177e4SLinus Torvalds  * initialise the AFS client FS module
69*1da177e4SLinus Torvalds  */
70*1da177e4SLinus Torvalds static int __init afs_init(void)
71*1da177e4SLinus Torvalds {
72*1da177e4SLinus Torvalds 	int loop, ret;
73*1da177e4SLinus Torvalds 
74*1da177e4SLinus Torvalds 	printk(KERN_INFO "kAFS: Red Hat AFS client v0.1 registering.\n");
75*1da177e4SLinus Torvalds 
76*1da177e4SLinus Torvalds 	/* initialise the callback hash table */
77*1da177e4SLinus Torvalds 	spin_lock_init(&afs_cb_hash_lock);
78*1da177e4SLinus Torvalds 	for (loop = AFS_CB_HASH_COUNT - 1; loop >= 0; loop--)
79*1da177e4SLinus Torvalds 		INIT_LIST_HEAD(&afs_cb_hash_tbl[loop]);
80*1da177e4SLinus Torvalds 
81*1da177e4SLinus Torvalds 	/* register the /proc stuff */
82*1da177e4SLinus Torvalds 	ret = afs_proc_init();
83*1da177e4SLinus Torvalds 	if (ret < 0)
84*1da177e4SLinus Torvalds 		return ret;
85*1da177e4SLinus Torvalds 
86*1da177e4SLinus Torvalds #ifdef AFS_CACHING_SUPPORT
87*1da177e4SLinus Torvalds 	/* we want to be able to cache */
88*1da177e4SLinus Torvalds 	ret = cachefs_register_netfs(&afs_cache_netfs,
89*1da177e4SLinus Torvalds 				     &afs_cache_cell_index_def);
90*1da177e4SLinus Torvalds 	if (ret < 0)
91*1da177e4SLinus Torvalds 		goto error;
92*1da177e4SLinus Torvalds #endif
93*1da177e4SLinus Torvalds 
94*1da177e4SLinus Torvalds #ifdef CONFIG_KEYS_TURNED_OFF
95*1da177e4SLinus Torvalds 	ret = afs_key_register();
96*1da177e4SLinus Torvalds 	if (ret < 0)
97*1da177e4SLinus Torvalds 		goto error_cache;
98*1da177e4SLinus Torvalds #endif
99*1da177e4SLinus Torvalds 
100*1da177e4SLinus Torvalds 	/* initialise the cell DB */
101*1da177e4SLinus Torvalds 	ret = afs_cell_init(rootcell);
102*1da177e4SLinus Torvalds 	if (ret < 0)
103*1da177e4SLinus Torvalds 		goto error_keys;
104*1da177e4SLinus Torvalds 
105*1da177e4SLinus Torvalds 	/* start the timeout daemon */
106*1da177e4SLinus Torvalds 	ret = afs_kafstimod_start();
107*1da177e4SLinus Torvalds 	if (ret < 0)
108*1da177e4SLinus Torvalds 		goto error_keys;
109*1da177e4SLinus Torvalds 
110*1da177e4SLinus Torvalds 	/* start the async operation daemon */
111*1da177e4SLinus Torvalds 	ret = afs_kafsasyncd_start();
112*1da177e4SLinus Torvalds 	if (ret < 0)
113*1da177e4SLinus Torvalds 		goto error_kafstimod;
114*1da177e4SLinus Torvalds 
115*1da177e4SLinus Torvalds 	/* create the RxRPC transport */
116*1da177e4SLinus Torvalds 	ret = rxrpc_create_transport(7001, &afs_transport);
117*1da177e4SLinus Torvalds 	if (ret < 0)
118*1da177e4SLinus Torvalds 		goto error_kafsasyncd;
119*1da177e4SLinus Torvalds 
120*1da177e4SLinus Torvalds 	afs_transport->peer_ops = &afs_peer_ops;
121*1da177e4SLinus Torvalds 
122*1da177e4SLinus Torvalds 	/* register the filesystems */
123*1da177e4SLinus Torvalds 	ret = afs_fs_init();
124*1da177e4SLinus Torvalds 	if (ret < 0)
125*1da177e4SLinus Torvalds 		goto error_transport;
126*1da177e4SLinus Torvalds 
127*1da177e4SLinus Torvalds 	return ret;
128*1da177e4SLinus Torvalds 
129*1da177e4SLinus Torvalds  error_transport:
130*1da177e4SLinus Torvalds 	rxrpc_put_transport(afs_transport);
131*1da177e4SLinus Torvalds  error_kafsasyncd:
132*1da177e4SLinus Torvalds 	afs_kafsasyncd_stop();
133*1da177e4SLinus Torvalds  error_kafstimod:
134*1da177e4SLinus Torvalds 	afs_kafstimod_stop();
135*1da177e4SLinus Torvalds  error_keys:
136*1da177e4SLinus Torvalds #ifdef CONFIG_KEYS_TURNED_OFF
137*1da177e4SLinus Torvalds 	afs_key_unregister();
138*1da177e4SLinus Torvalds  error_cache:
139*1da177e4SLinus Torvalds #endif
140*1da177e4SLinus Torvalds #ifdef AFS_CACHING_SUPPORT
141*1da177e4SLinus Torvalds 	cachefs_unregister_netfs(&afs_cache_netfs);
142*1da177e4SLinus Torvalds  error:
143*1da177e4SLinus Torvalds #endif
144*1da177e4SLinus Torvalds 	afs_cell_purge();
145*1da177e4SLinus Torvalds 	afs_proc_cleanup();
146*1da177e4SLinus Torvalds 	printk(KERN_ERR "kAFS: failed to register: %d\n", ret);
147*1da177e4SLinus Torvalds 	return ret;
148*1da177e4SLinus Torvalds } /* end afs_init() */
149*1da177e4SLinus Torvalds 
150*1da177e4SLinus Torvalds /* XXX late_initcall is kludgy, but the only alternative seems to create
151*1da177e4SLinus Torvalds  * a transport upon the first mount, which is worse. Or is it?
152*1da177e4SLinus Torvalds  */
153*1da177e4SLinus Torvalds late_initcall(afs_init);	/* must be called after net/ to create socket */
154*1da177e4SLinus Torvalds /*****************************************************************************/
155*1da177e4SLinus Torvalds /*
156*1da177e4SLinus Torvalds  * clean up on module removal
157*1da177e4SLinus Torvalds  */
158*1da177e4SLinus Torvalds static void __exit afs_exit(void)
159*1da177e4SLinus Torvalds {
160*1da177e4SLinus Torvalds 	printk(KERN_INFO "kAFS: Red Hat AFS client v0.1 unregistering.\n");
161*1da177e4SLinus Torvalds 
162*1da177e4SLinus Torvalds 	afs_fs_exit();
163*1da177e4SLinus Torvalds 	rxrpc_put_transport(afs_transport);
164*1da177e4SLinus Torvalds 	afs_kafstimod_stop();
165*1da177e4SLinus Torvalds 	afs_kafsasyncd_stop();
166*1da177e4SLinus Torvalds 	afs_cell_purge();
167*1da177e4SLinus Torvalds #ifdef CONFIG_KEYS_TURNED_OFF
168*1da177e4SLinus Torvalds 	afs_key_unregister();
169*1da177e4SLinus Torvalds #endif
170*1da177e4SLinus Torvalds #ifdef AFS_CACHING_SUPPORT
171*1da177e4SLinus Torvalds 	cachefs_unregister_netfs(&afs_cache_netfs);
172*1da177e4SLinus Torvalds #endif
173*1da177e4SLinus Torvalds 	afs_proc_cleanup();
174*1da177e4SLinus Torvalds 
175*1da177e4SLinus Torvalds } /* end afs_exit() */
176*1da177e4SLinus Torvalds 
177*1da177e4SLinus Torvalds module_exit(afs_exit);
178*1da177e4SLinus Torvalds 
179*1da177e4SLinus Torvalds /*****************************************************************************/
180*1da177e4SLinus Torvalds /*
181*1da177e4SLinus Torvalds  * notification that new peer record is being added
182*1da177e4SLinus Torvalds  * - called from krxsecd
183*1da177e4SLinus Torvalds  * - return an error to induce an abort
184*1da177e4SLinus Torvalds  * - mustn't sleep (caller holds an rwlock)
185*1da177e4SLinus Torvalds  */
186*1da177e4SLinus Torvalds static int afs_adding_peer(struct rxrpc_peer *peer)
187*1da177e4SLinus Torvalds {
188*1da177e4SLinus Torvalds 	struct afs_server *server;
189*1da177e4SLinus Torvalds 	int ret;
190*1da177e4SLinus Torvalds 
191*1da177e4SLinus Torvalds 	_debug("kAFS: Adding new peer %08x\n", ntohl(peer->addr.s_addr));
192*1da177e4SLinus Torvalds 
193*1da177e4SLinus Torvalds 	/* determine which server the peer resides in (if any) */
194*1da177e4SLinus Torvalds 	ret = afs_server_find_by_peer(peer, &server);
195*1da177e4SLinus Torvalds 	if (ret < 0)
196*1da177e4SLinus Torvalds 		return ret; /* none that we recognise, so abort */
197*1da177e4SLinus Torvalds 
198*1da177e4SLinus Torvalds 	_debug("Server %p{u=%d}\n", server, atomic_read(&server->usage));
199*1da177e4SLinus Torvalds 
200*1da177e4SLinus Torvalds 	_debug("Cell %p{u=%d}\n",
201*1da177e4SLinus Torvalds 	       server->cell, atomic_read(&server->cell->usage));
202*1da177e4SLinus Torvalds 
203*1da177e4SLinus Torvalds 	/* cross-point the structs under a global lock */
204*1da177e4SLinus Torvalds 	spin_lock(&afs_server_peer_lock);
205*1da177e4SLinus Torvalds 	peer->user = server;
206*1da177e4SLinus Torvalds 	server->peer = peer;
207*1da177e4SLinus Torvalds 	spin_unlock(&afs_server_peer_lock);
208*1da177e4SLinus Torvalds 
209*1da177e4SLinus Torvalds 	afs_put_server(server);
210*1da177e4SLinus Torvalds 
211*1da177e4SLinus Torvalds 	return 0;
212*1da177e4SLinus Torvalds } /* end afs_adding_peer() */
213*1da177e4SLinus Torvalds 
214*1da177e4SLinus Torvalds /*****************************************************************************/
215*1da177e4SLinus Torvalds /*
216*1da177e4SLinus Torvalds  * notification that a peer record is being discarded
217*1da177e4SLinus Torvalds  * - called from krxiod or krxsecd
218*1da177e4SLinus Torvalds  */
219*1da177e4SLinus Torvalds static void afs_discarding_peer(struct rxrpc_peer *peer)
220*1da177e4SLinus Torvalds {
221*1da177e4SLinus Torvalds 	struct afs_server *server;
222*1da177e4SLinus Torvalds 
223*1da177e4SLinus Torvalds 	_enter("%p",peer);
224*1da177e4SLinus Torvalds 
225*1da177e4SLinus Torvalds 	_debug("Discarding peer %08x (rtt=%lu.%lumS)\n",
226*1da177e4SLinus Torvalds 	       ntohl(peer->addr.s_addr),
227*1da177e4SLinus Torvalds 	       (long) (peer->rtt / 1000),
228*1da177e4SLinus Torvalds 	       (long) (peer->rtt % 1000));
229*1da177e4SLinus Torvalds 
230*1da177e4SLinus Torvalds 	/* uncross-point the structs under a global lock */
231*1da177e4SLinus Torvalds 	spin_lock(&afs_server_peer_lock);
232*1da177e4SLinus Torvalds 	server = peer->user;
233*1da177e4SLinus Torvalds 	if (server) {
234*1da177e4SLinus Torvalds 		peer->user = NULL;
235*1da177e4SLinus Torvalds 		server->peer = NULL;
236*1da177e4SLinus Torvalds 	}
237*1da177e4SLinus Torvalds 	spin_unlock(&afs_server_peer_lock);
238*1da177e4SLinus Torvalds 
239*1da177e4SLinus Torvalds 	_leave("");
240*1da177e4SLinus Torvalds 
241*1da177e4SLinus Torvalds } /* end afs_discarding_peer() */
242*1da177e4SLinus Torvalds 
243*1da177e4SLinus Torvalds /*****************************************************************************/
244*1da177e4SLinus Torvalds /*
245*1da177e4SLinus Torvalds  * clear the dead space between task_struct and kernel stack
246*1da177e4SLinus Torvalds  * - called by supplying -finstrument-functions to gcc
247*1da177e4SLinus Torvalds  */
248*1da177e4SLinus Torvalds #if 0
249*1da177e4SLinus Torvalds void __cyg_profile_func_enter (void *this_fn, void *call_site)
250*1da177e4SLinus Torvalds __attribute__((no_instrument_function));
251*1da177e4SLinus Torvalds 
252*1da177e4SLinus Torvalds void __cyg_profile_func_enter (void *this_fn, void *call_site)
253*1da177e4SLinus Torvalds {
254*1da177e4SLinus Torvalds        asm volatile("  movl    %%esp,%%edi     \n"
255*1da177e4SLinus Torvalds                     "  andl    %0,%%edi        \n"
256*1da177e4SLinus Torvalds                     "  addl    %1,%%edi        \n"
257*1da177e4SLinus Torvalds                     "  movl    %%esp,%%ecx     \n"
258*1da177e4SLinus Torvalds                     "  subl    %%edi,%%ecx     \n"
259*1da177e4SLinus Torvalds                     "  shrl    $2,%%ecx        \n"
260*1da177e4SLinus Torvalds                     "  movl    $0xedededed,%%eax     \n"
261*1da177e4SLinus Torvalds                     "  rep stosl               \n"
262*1da177e4SLinus Torvalds                     :
263*1da177e4SLinus Torvalds                     : "i"(~(THREAD_SIZE - 1)), "i"(sizeof(struct thread_info))
264*1da177e4SLinus Torvalds                     : "eax", "ecx", "edi", "memory", "cc"
265*1da177e4SLinus Torvalds                     );
266*1da177e4SLinus Torvalds }
267*1da177e4SLinus Torvalds 
268*1da177e4SLinus Torvalds void __cyg_profile_func_exit(void *this_fn, void *call_site)
269*1da177e4SLinus Torvalds __attribute__((no_instrument_function));
270*1da177e4SLinus Torvalds 
271*1da177e4SLinus Torvalds void __cyg_profile_func_exit(void *this_fn, void *call_site)
272*1da177e4SLinus Torvalds {
273*1da177e4SLinus Torvalds        asm volatile("  movl    %%esp,%%edi     \n"
274*1da177e4SLinus Torvalds                     "  andl    %0,%%edi        \n"
275*1da177e4SLinus Torvalds                     "  addl    %1,%%edi        \n"
276*1da177e4SLinus Torvalds                     "  movl    %%esp,%%ecx     \n"
277*1da177e4SLinus Torvalds                     "  subl    %%edi,%%ecx     \n"
278*1da177e4SLinus Torvalds                     "  shrl    $2,%%ecx        \n"
279*1da177e4SLinus Torvalds                     "  movl    $0xdadadada,%%eax     \n"
280*1da177e4SLinus Torvalds                     "  rep stosl               \n"
281*1da177e4SLinus Torvalds                     :
282*1da177e4SLinus Torvalds                     : "i"(~(THREAD_SIZE - 1)), "i"(sizeof(struct thread_info))
283*1da177e4SLinus Torvalds                     : "eax", "ecx", "edi", "memory", "cc"
284*1da177e4SLinus Torvalds                     );
285*1da177e4SLinus Torvalds }
286*1da177e4SLinus Torvalds #endif
287