xref: /openbmc/linux/fs/afs/main.c (revision 1da177e4)
11da177e4SLinus Torvalds /* main.c: AFS client file system
21da177e4SLinus Torvalds  *
31da177e4SLinus Torvalds  * Copyright (C) 2002 Red Hat, Inc. All Rights Reserved.
41da177e4SLinus Torvalds  * Written by David Howells (dhowells@redhat.com)
51da177e4SLinus Torvalds  *
61da177e4SLinus Torvalds  * This program is free software; you can redistribute it and/or
71da177e4SLinus Torvalds  * modify it under the terms of the GNU General Public License
81da177e4SLinus Torvalds  * as published by the Free Software Foundation; either version
91da177e4SLinus Torvalds  * 2 of the License, or (at your option) any later version.
101da177e4SLinus Torvalds  */
111da177e4SLinus Torvalds 
121da177e4SLinus Torvalds #include <linux/module.h>
131da177e4SLinus Torvalds #include <linux/moduleparam.h>
141da177e4SLinus Torvalds #include <linux/init.h>
151da177e4SLinus Torvalds #include <linux/sched.h>
161da177e4SLinus Torvalds #include <linux/completion.h>
171da177e4SLinus Torvalds #include <rxrpc/rxrpc.h>
181da177e4SLinus Torvalds #include <rxrpc/transport.h>
191da177e4SLinus Torvalds #include <rxrpc/call.h>
201da177e4SLinus Torvalds #include <rxrpc/peer.h>
211da177e4SLinus Torvalds #include "cache.h"
221da177e4SLinus Torvalds #include "cell.h"
231da177e4SLinus Torvalds #include "server.h"
241da177e4SLinus Torvalds #include "fsclient.h"
251da177e4SLinus Torvalds #include "cmservice.h"
261da177e4SLinus Torvalds #include "kafstimod.h"
271da177e4SLinus Torvalds #include "kafsasyncd.h"
281da177e4SLinus Torvalds #include "internal.h"
291da177e4SLinus Torvalds 
301da177e4SLinus Torvalds struct rxrpc_transport *afs_transport;
311da177e4SLinus Torvalds 
321da177e4SLinus Torvalds static int afs_adding_peer(struct rxrpc_peer *peer);
331da177e4SLinus Torvalds static void afs_discarding_peer(struct rxrpc_peer *peer);
341da177e4SLinus Torvalds 
351da177e4SLinus Torvalds 
361da177e4SLinus Torvalds MODULE_DESCRIPTION("AFS Client File System");
371da177e4SLinus Torvalds MODULE_AUTHOR("Red Hat, Inc.");
381da177e4SLinus Torvalds MODULE_LICENSE("GPL");
391da177e4SLinus Torvalds 
401da177e4SLinus Torvalds static char *rootcell;
411da177e4SLinus Torvalds 
421da177e4SLinus Torvalds module_param(rootcell, charp, 0);
431da177e4SLinus Torvalds MODULE_PARM_DESC(rootcell, "root AFS cell name and VL server IP addr list");
441da177e4SLinus Torvalds 
451da177e4SLinus Torvalds 
461da177e4SLinus Torvalds static struct rxrpc_peer_ops afs_peer_ops = {
471da177e4SLinus Torvalds 	.adding		= afs_adding_peer,
481da177e4SLinus Torvalds 	.discarding	= afs_discarding_peer,
491da177e4SLinus Torvalds };
501da177e4SLinus Torvalds 
511da177e4SLinus Torvalds struct list_head afs_cb_hash_tbl[AFS_CB_HASH_COUNT];
521da177e4SLinus Torvalds DEFINE_SPINLOCK(afs_cb_hash_lock);
531da177e4SLinus Torvalds 
541da177e4SLinus Torvalds #ifdef AFS_CACHING_SUPPORT
551da177e4SLinus Torvalds static struct cachefs_netfs_operations afs_cache_ops = {
561da177e4SLinus Torvalds 	.get_page_cookie	= afs_cache_get_page_cookie,
571da177e4SLinus Torvalds };
581da177e4SLinus Torvalds 
591da177e4SLinus Torvalds struct cachefs_netfs afs_cache_netfs = {
601da177e4SLinus Torvalds 	.name			= "afs",
611da177e4SLinus Torvalds 	.version		= 0,
621da177e4SLinus Torvalds 	.ops			= &afs_cache_ops,
631da177e4SLinus Torvalds };
641da177e4SLinus Torvalds #endif
651da177e4SLinus Torvalds 
661da177e4SLinus Torvalds /*****************************************************************************/
671da177e4SLinus Torvalds /*
681da177e4SLinus Torvalds  * initialise the AFS client FS module
691da177e4SLinus Torvalds  */
701da177e4SLinus Torvalds static int __init afs_init(void)
711da177e4SLinus Torvalds {
721da177e4SLinus Torvalds 	int loop, ret;
731da177e4SLinus Torvalds 
741da177e4SLinus Torvalds 	printk(KERN_INFO "kAFS: Red Hat AFS client v0.1 registering.\n");
751da177e4SLinus Torvalds 
761da177e4SLinus Torvalds 	/* initialise the callback hash table */
771da177e4SLinus Torvalds 	spin_lock_init(&afs_cb_hash_lock);
781da177e4SLinus Torvalds 	for (loop = AFS_CB_HASH_COUNT - 1; loop >= 0; loop--)
791da177e4SLinus Torvalds 		INIT_LIST_HEAD(&afs_cb_hash_tbl[loop]);
801da177e4SLinus Torvalds 
811da177e4SLinus Torvalds 	/* register the /proc stuff */
821da177e4SLinus Torvalds 	ret = afs_proc_init();
831da177e4SLinus Torvalds 	if (ret < 0)
841da177e4SLinus Torvalds 		return ret;
851da177e4SLinus Torvalds 
861da177e4SLinus Torvalds #ifdef AFS_CACHING_SUPPORT
871da177e4SLinus Torvalds 	/* we want to be able to cache */
881da177e4SLinus Torvalds 	ret = cachefs_register_netfs(&afs_cache_netfs,
891da177e4SLinus Torvalds 				     &afs_cache_cell_index_def);
901da177e4SLinus Torvalds 	if (ret < 0)
911da177e4SLinus Torvalds 		goto error;
921da177e4SLinus Torvalds #endif
931da177e4SLinus Torvalds 
941da177e4SLinus Torvalds #ifdef CONFIG_KEYS_TURNED_OFF
951da177e4SLinus Torvalds 	ret = afs_key_register();
961da177e4SLinus Torvalds 	if (ret < 0)
971da177e4SLinus Torvalds 		goto error_cache;
981da177e4SLinus Torvalds #endif
991da177e4SLinus Torvalds 
1001da177e4SLinus Torvalds 	/* initialise the cell DB */
1011da177e4SLinus Torvalds 	ret = afs_cell_init(rootcell);
1021da177e4SLinus Torvalds 	if (ret < 0)
1031da177e4SLinus Torvalds 		goto error_keys;
1041da177e4SLinus Torvalds 
1051da177e4SLinus Torvalds 	/* start the timeout daemon */
1061da177e4SLinus Torvalds 	ret = afs_kafstimod_start();
1071da177e4SLinus Torvalds 	if (ret < 0)
1081da177e4SLinus Torvalds 		goto error_keys;
1091da177e4SLinus Torvalds 
1101da177e4SLinus Torvalds 	/* start the async operation daemon */
1111da177e4SLinus Torvalds 	ret = afs_kafsasyncd_start();
1121da177e4SLinus Torvalds 	if (ret < 0)
1131da177e4SLinus Torvalds 		goto error_kafstimod;
1141da177e4SLinus Torvalds 
1151da177e4SLinus Torvalds 	/* create the RxRPC transport */
1161da177e4SLinus Torvalds 	ret = rxrpc_create_transport(7001, &afs_transport);
1171da177e4SLinus Torvalds 	if (ret < 0)
1181da177e4SLinus Torvalds 		goto error_kafsasyncd;
1191da177e4SLinus Torvalds 
1201da177e4SLinus Torvalds 	afs_transport->peer_ops = &afs_peer_ops;
1211da177e4SLinus Torvalds 
1221da177e4SLinus Torvalds 	/* register the filesystems */
1231da177e4SLinus Torvalds 	ret = afs_fs_init();
1241da177e4SLinus Torvalds 	if (ret < 0)
1251da177e4SLinus Torvalds 		goto error_transport;
1261da177e4SLinus Torvalds 
1271da177e4SLinus Torvalds 	return ret;
1281da177e4SLinus Torvalds 
1291da177e4SLinus Torvalds  error_transport:
1301da177e4SLinus Torvalds 	rxrpc_put_transport(afs_transport);
1311da177e4SLinus Torvalds  error_kafsasyncd:
1321da177e4SLinus Torvalds 	afs_kafsasyncd_stop();
1331da177e4SLinus Torvalds  error_kafstimod:
1341da177e4SLinus Torvalds 	afs_kafstimod_stop();
1351da177e4SLinus Torvalds  error_keys:
1361da177e4SLinus Torvalds #ifdef CONFIG_KEYS_TURNED_OFF
1371da177e4SLinus Torvalds 	afs_key_unregister();
1381da177e4SLinus Torvalds  error_cache:
1391da177e4SLinus Torvalds #endif
1401da177e4SLinus Torvalds #ifdef AFS_CACHING_SUPPORT
1411da177e4SLinus Torvalds 	cachefs_unregister_netfs(&afs_cache_netfs);
1421da177e4SLinus Torvalds  error:
1431da177e4SLinus Torvalds #endif
1441da177e4SLinus Torvalds 	afs_cell_purge();
1451da177e4SLinus Torvalds 	afs_proc_cleanup();
1461da177e4SLinus Torvalds 	printk(KERN_ERR "kAFS: failed to register: %d\n", ret);
1471da177e4SLinus Torvalds 	return ret;
1481da177e4SLinus Torvalds } /* end afs_init() */
1491da177e4SLinus Torvalds 
1501da177e4SLinus Torvalds /* XXX late_initcall is kludgy, but the only alternative seems to create
1511da177e4SLinus Torvalds  * a transport upon the first mount, which is worse. Or is it?
1521da177e4SLinus Torvalds  */
1531da177e4SLinus Torvalds late_initcall(afs_init);	/* must be called after net/ to create socket */
1541da177e4SLinus Torvalds /*****************************************************************************/
1551da177e4SLinus Torvalds /*
1561da177e4SLinus Torvalds  * clean up on module removal
1571da177e4SLinus Torvalds  */
1581da177e4SLinus Torvalds static void __exit afs_exit(void)
1591da177e4SLinus Torvalds {
1601da177e4SLinus Torvalds 	printk(KERN_INFO "kAFS: Red Hat AFS client v0.1 unregistering.\n");
1611da177e4SLinus Torvalds 
1621da177e4SLinus Torvalds 	afs_fs_exit();
1631da177e4SLinus Torvalds 	rxrpc_put_transport(afs_transport);
1641da177e4SLinus Torvalds 	afs_kafstimod_stop();
1651da177e4SLinus Torvalds 	afs_kafsasyncd_stop();
1661da177e4SLinus Torvalds 	afs_cell_purge();
1671da177e4SLinus Torvalds #ifdef CONFIG_KEYS_TURNED_OFF
1681da177e4SLinus Torvalds 	afs_key_unregister();
1691da177e4SLinus Torvalds #endif
1701da177e4SLinus Torvalds #ifdef AFS_CACHING_SUPPORT
1711da177e4SLinus Torvalds 	cachefs_unregister_netfs(&afs_cache_netfs);
1721da177e4SLinus Torvalds #endif
1731da177e4SLinus Torvalds 	afs_proc_cleanup();
1741da177e4SLinus Torvalds 
1751da177e4SLinus Torvalds } /* end afs_exit() */
1761da177e4SLinus Torvalds 
1771da177e4SLinus Torvalds module_exit(afs_exit);
1781da177e4SLinus Torvalds 
1791da177e4SLinus Torvalds /*****************************************************************************/
1801da177e4SLinus Torvalds /*
1811da177e4SLinus Torvalds  * notification that new peer record is being added
1821da177e4SLinus Torvalds  * - called from krxsecd
1831da177e4SLinus Torvalds  * - return an error to induce an abort
1841da177e4SLinus Torvalds  * - mustn't sleep (caller holds an rwlock)
1851da177e4SLinus Torvalds  */
1861da177e4SLinus Torvalds static int afs_adding_peer(struct rxrpc_peer *peer)
1871da177e4SLinus Torvalds {
1881da177e4SLinus Torvalds 	struct afs_server *server;
1891da177e4SLinus Torvalds 	int ret;
1901da177e4SLinus Torvalds 
1911da177e4SLinus Torvalds 	_debug("kAFS: Adding new peer %08x\n", ntohl(peer->addr.s_addr));
1921da177e4SLinus Torvalds 
1931da177e4SLinus Torvalds 	/* determine which server the peer resides in (if any) */
1941da177e4SLinus Torvalds 	ret = afs_server_find_by_peer(peer, &server);
1951da177e4SLinus Torvalds 	if (ret < 0)
1961da177e4SLinus Torvalds 		return ret; /* none that we recognise, so abort */
1971da177e4SLinus Torvalds 
1981da177e4SLinus Torvalds 	_debug("Server %p{u=%d}\n", server, atomic_read(&server->usage));
1991da177e4SLinus Torvalds 
2001da177e4SLinus Torvalds 	_debug("Cell %p{u=%d}\n",
2011da177e4SLinus Torvalds 	       server->cell, atomic_read(&server->cell->usage));
2021da177e4SLinus Torvalds 
2031da177e4SLinus Torvalds 	/* cross-point the structs under a global lock */
2041da177e4SLinus Torvalds 	spin_lock(&afs_server_peer_lock);
2051da177e4SLinus Torvalds 	peer->user = server;
2061da177e4SLinus Torvalds 	server->peer = peer;
2071da177e4SLinus Torvalds 	spin_unlock(&afs_server_peer_lock);
2081da177e4SLinus Torvalds 
2091da177e4SLinus Torvalds 	afs_put_server(server);
2101da177e4SLinus Torvalds 
2111da177e4SLinus Torvalds 	return 0;
2121da177e4SLinus Torvalds } /* end afs_adding_peer() */
2131da177e4SLinus Torvalds 
2141da177e4SLinus Torvalds /*****************************************************************************/
2151da177e4SLinus Torvalds /*
2161da177e4SLinus Torvalds  * notification that a peer record is being discarded
2171da177e4SLinus Torvalds  * - called from krxiod or krxsecd
2181da177e4SLinus Torvalds  */
2191da177e4SLinus Torvalds static void afs_discarding_peer(struct rxrpc_peer *peer)
2201da177e4SLinus Torvalds {
2211da177e4SLinus Torvalds 	struct afs_server *server;
2221da177e4SLinus Torvalds 
2231da177e4SLinus Torvalds 	_enter("%p",peer);
2241da177e4SLinus Torvalds 
2251da177e4SLinus Torvalds 	_debug("Discarding peer %08x (rtt=%lu.%lumS)\n",
2261da177e4SLinus Torvalds 	       ntohl(peer->addr.s_addr),
2271da177e4SLinus Torvalds 	       (long) (peer->rtt / 1000),
2281da177e4SLinus Torvalds 	       (long) (peer->rtt % 1000));
2291da177e4SLinus Torvalds 
2301da177e4SLinus Torvalds 	/* uncross-point the structs under a global lock */
2311da177e4SLinus Torvalds 	spin_lock(&afs_server_peer_lock);
2321da177e4SLinus Torvalds 	server = peer->user;
2331da177e4SLinus Torvalds 	if (server) {
2341da177e4SLinus Torvalds 		peer->user = NULL;
2351da177e4SLinus Torvalds 		server->peer = NULL;
2361da177e4SLinus Torvalds 	}
2371da177e4SLinus Torvalds 	spin_unlock(&afs_server_peer_lock);
2381da177e4SLinus Torvalds 
2391da177e4SLinus Torvalds 	_leave("");
2401da177e4SLinus Torvalds 
2411da177e4SLinus Torvalds } /* end afs_discarding_peer() */
2421da177e4SLinus Torvalds 
2431da177e4SLinus Torvalds /*****************************************************************************/
2441da177e4SLinus Torvalds /*
2451da177e4SLinus Torvalds  * clear the dead space between task_struct and kernel stack
2461da177e4SLinus Torvalds  * - called by supplying -finstrument-functions to gcc
2471da177e4SLinus Torvalds  */
2481da177e4SLinus Torvalds #if 0
2491da177e4SLinus Torvalds void __cyg_profile_func_enter (void *this_fn, void *call_site)
2501da177e4SLinus Torvalds __attribute__((no_instrument_function));
2511da177e4SLinus Torvalds 
2521da177e4SLinus Torvalds void __cyg_profile_func_enter (void *this_fn, void *call_site)
2531da177e4SLinus Torvalds {
2541da177e4SLinus Torvalds        asm volatile("  movl    %%esp,%%edi     \n"
2551da177e4SLinus Torvalds                     "  andl    %0,%%edi        \n"
2561da177e4SLinus Torvalds                     "  addl    %1,%%edi        \n"
2571da177e4SLinus Torvalds                     "  movl    %%esp,%%ecx     \n"
2581da177e4SLinus Torvalds                     "  subl    %%edi,%%ecx     \n"
2591da177e4SLinus Torvalds                     "  shrl    $2,%%ecx        \n"
2601da177e4SLinus Torvalds                     "  movl    $0xedededed,%%eax     \n"
2611da177e4SLinus Torvalds                     "  rep stosl               \n"
2621da177e4SLinus Torvalds                     :
2631da177e4SLinus Torvalds                     : "i"(~(THREAD_SIZE - 1)), "i"(sizeof(struct thread_info))
2641da177e4SLinus Torvalds                     : "eax", "ecx", "edi", "memory", "cc"
2651da177e4SLinus Torvalds                     );
2661da177e4SLinus Torvalds }
2671da177e4SLinus Torvalds 
2681da177e4SLinus Torvalds void __cyg_profile_func_exit(void *this_fn, void *call_site)
2691da177e4SLinus Torvalds __attribute__((no_instrument_function));
2701da177e4SLinus Torvalds 
2711da177e4SLinus Torvalds void __cyg_profile_func_exit(void *this_fn, void *call_site)
2721da177e4SLinus Torvalds {
2731da177e4SLinus Torvalds        asm volatile("  movl    %%esp,%%edi     \n"
2741da177e4SLinus Torvalds                     "  andl    %0,%%edi        \n"
2751da177e4SLinus Torvalds                     "  addl    %1,%%edi        \n"
2761da177e4SLinus Torvalds                     "  movl    %%esp,%%ecx     \n"
2771da177e4SLinus Torvalds                     "  subl    %%edi,%%ecx     \n"
2781da177e4SLinus Torvalds                     "  shrl    $2,%%ecx        \n"
2791da177e4SLinus Torvalds                     "  movl    $0xdadadada,%%eax     \n"
2801da177e4SLinus Torvalds                     "  rep stosl               \n"
2811da177e4SLinus Torvalds                     :
2821da177e4SLinus Torvalds                     : "i"(~(THREAD_SIZE - 1)), "i"(sizeof(struct thread_info))
2831da177e4SLinus Torvalds                     : "eax", "ecx", "edi", "memory", "cc"
2841da177e4SLinus Torvalds                     );
2851da177e4SLinus Torvalds }
2861da177e4SLinus Torvalds #endif
287