xref: /openbmc/linux/fs/afs/main.c (revision ec9c948546a84d0dcee851be1009a8066958e69d)
1ec26815aSDavid Howells /* 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/completion.h>
161da177e4SLinus Torvalds #include "internal.h"
171da177e4SLinus Torvalds 
181da177e4SLinus Torvalds MODULE_DESCRIPTION("AFS Client File System");
191da177e4SLinus Torvalds MODULE_AUTHOR("Red Hat, Inc.");
201da177e4SLinus Torvalds MODULE_LICENSE("GPL");
211da177e4SLinus Torvalds 
2208e0e7c8SDavid Howells unsigned afs_debug;
2308e0e7c8SDavid Howells module_param_named(debug, afs_debug, uint, S_IWUSR | S_IRUGO);
2408e0e7c8SDavid Howells MODULE_PARM_DESC(afs_debug, "AFS debugging mask");
2508e0e7c8SDavid Howells 
261da177e4SLinus Torvalds static char *rootcell;
271da177e4SLinus Torvalds 
281da177e4SLinus Torvalds module_param(rootcell, charp, 0);
291da177e4SLinus Torvalds MODULE_PARM_DESC(rootcell, "root AFS cell name and VL server IP addr list");
301da177e4SLinus Torvalds 
311da177e4SLinus Torvalds #ifdef AFS_CACHING_SUPPORT
321da177e4SLinus Torvalds static struct cachefs_netfs_operations afs_cache_ops = {
331da177e4SLinus Torvalds 	.get_page_cookie	= afs_cache_get_page_cookie,
341da177e4SLinus Torvalds };
351da177e4SLinus Torvalds 
361da177e4SLinus Torvalds struct cachefs_netfs afs_cache_netfs = {
371da177e4SLinus Torvalds 	.name			= "afs",
381da177e4SLinus Torvalds 	.version		= 0,
391da177e4SLinus Torvalds 	.ops			= &afs_cache_ops,
401da177e4SLinus Torvalds };
411da177e4SLinus Torvalds #endif
421da177e4SLinus Torvalds 
43b908fe6bSDavid Howells struct afs_uuid afs_uuid;
44b908fe6bSDavid Howells 
45b908fe6bSDavid Howells /*
46b908fe6bSDavid Howells  * get a client UUID
47b908fe6bSDavid Howells  */
48b908fe6bSDavid Howells static int __init afs_get_client_UUID(void)
49b908fe6bSDavid Howells {
50b908fe6bSDavid Howells 	struct timespec ts;
51b908fe6bSDavid Howells 	u64 uuidtime;
52b908fe6bSDavid Howells 	u16 clockseq;
53b908fe6bSDavid Howells 	int ret;
54b908fe6bSDavid Howells 
55b908fe6bSDavid Howells 	/* read the MAC address of one of the external interfaces and construct
56b908fe6bSDavid Howells 	 * a UUID from it */
57*ec9c9485SDavid Howells 	ret = afs_get_MAC_address(afs_uuid.node, sizeof(afs_uuid.node));
58b908fe6bSDavid Howells 	if (ret < 0)
59b908fe6bSDavid Howells 		return ret;
60b908fe6bSDavid Howells 
61b908fe6bSDavid Howells 	getnstimeofday(&ts);
62b908fe6bSDavid Howells 	uuidtime = (u64) ts.tv_sec * 1000 * 1000 * 10;
63b908fe6bSDavid Howells 	uuidtime += ts.tv_nsec / 100;
64b908fe6bSDavid Howells 	uuidtime += AFS_UUID_TO_UNIX_TIME;
65b908fe6bSDavid Howells 	afs_uuid.time_low = uuidtime;
66b908fe6bSDavid Howells 	afs_uuid.time_mid = uuidtime >> 32;
67b908fe6bSDavid Howells 	afs_uuid.time_hi_and_version = (uuidtime >> 48) & AFS_UUID_TIMEHI_MASK;
68b908fe6bSDavid Howells 	afs_uuid.time_hi_and_version = AFS_UUID_VERSION_TIME;
69b908fe6bSDavid Howells 
70b908fe6bSDavid Howells 	get_random_bytes(&clockseq, 2);
71b908fe6bSDavid Howells 	afs_uuid.clock_seq_low = clockseq;
72b908fe6bSDavid Howells 	afs_uuid.clock_seq_hi_and_reserved =
73b908fe6bSDavid Howells 		(clockseq >> 8) & AFS_UUID_CLOCKHI_MASK;
74b908fe6bSDavid Howells 	afs_uuid.clock_seq_hi_and_reserved = AFS_UUID_VARIANT_STD;
75b908fe6bSDavid Howells 
76b908fe6bSDavid Howells 	_debug("AFS UUID: %08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
77b908fe6bSDavid Howells 	       afs_uuid.time_low,
78b908fe6bSDavid Howells 	       afs_uuid.time_mid,
79b908fe6bSDavid Howells 	       afs_uuid.time_hi_and_version,
80b908fe6bSDavid Howells 	       afs_uuid.clock_seq_hi_and_reserved,
81b908fe6bSDavid Howells 	       afs_uuid.clock_seq_low,
82b908fe6bSDavid Howells 	       afs_uuid.node[0], afs_uuid.node[1], afs_uuid.node[2],
83b908fe6bSDavid Howells 	       afs_uuid.node[3], afs_uuid.node[4], afs_uuid.node[5]);
84b908fe6bSDavid Howells 
85b908fe6bSDavid Howells 	return 0;
86b908fe6bSDavid Howells }
87b908fe6bSDavid Howells 
881da177e4SLinus Torvalds /*
891da177e4SLinus Torvalds  * initialise the AFS client FS module
901da177e4SLinus Torvalds  */
911da177e4SLinus Torvalds static int __init afs_init(void)
921da177e4SLinus Torvalds {
9308e0e7c8SDavid Howells 	int ret;
941da177e4SLinus Torvalds 
951da177e4SLinus Torvalds 	printk(KERN_INFO "kAFS: Red Hat AFS client v0.1 registering.\n");
961da177e4SLinus Torvalds 
97b908fe6bSDavid Howells 	ret = afs_get_client_UUID();
98b908fe6bSDavid Howells 	if (ret < 0)
99b908fe6bSDavid Howells 		return ret;
100b908fe6bSDavid Howells 
1011da177e4SLinus Torvalds 	/* register the /proc stuff */
1021da177e4SLinus Torvalds 	ret = afs_proc_init();
1031da177e4SLinus Torvalds 	if (ret < 0)
1041da177e4SLinus Torvalds 		return ret;
1051da177e4SLinus Torvalds 
1061da177e4SLinus Torvalds #ifdef AFS_CACHING_SUPPORT
1071da177e4SLinus Torvalds 	/* we want to be able to cache */
1081da177e4SLinus Torvalds 	ret = cachefs_register_netfs(&afs_cache_netfs,
1091da177e4SLinus Torvalds 				     &afs_cache_cell_index_def);
1101da177e4SLinus Torvalds 	if (ret < 0)
1111da177e4SLinus Torvalds 		goto error_cache;
1121da177e4SLinus Torvalds #endif
1131da177e4SLinus Torvalds 
1141da177e4SLinus Torvalds 	/* initialise the cell DB */
1151da177e4SLinus Torvalds 	ret = afs_cell_init(rootcell);
1161da177e4SLinus Torvalds 	if (ret < 0)
117ec26815aSDavid Howells 		goto error_cell_init;
1181da177e4SLinus Torvalds 
11908e0e7c8SDavid Howells 	/* initialise the VL update process */
12008e0e7c8SDavid Howells 	ret = afs_vlocation_update_init();
1211da177e4SLinus Torvalds 	if (ret < 0)
12208e0e7c8SDavid Howells 		goto error_vl_update_init;
1231da177e4SLinus Torvalds 
12408e0e7c8SDavid Howells 	/* initialise the callback update process */
12508e0e7c8SDavid Howells 	ret = afs_callback_update_init();
1261da177e4SLinus Torvalds 
1271da177e4SLinus Torvalds 	/* create the RxRPC transport */
12808e0e7c8SDavid Howells 	ret = afs_open_socket();
1291da177e4SLinus Torvalds 	if (ret < 0)
13008e0e7c8SDavid Howells 		goto error_open_socket;
1311da177e4SLinus Torvalds 
1321da177e4SLinus Torvalds 	/* register the filesystems */
1331da177e4SLinus Torvalds 	ret = afs_fs_init();
1341da177e4SLinus Torvalds 	if (ret < 0)
135ec26815aSDavid Howells 		goto error_fs;
1361da177e4SLinus Torvalds 
1371da177e4SLinus Torvalds 	return ret;
1381da177e4SLinus Torvalds 
139ec26815aSDavid Howells error_fs:
14008e0e7c8SDavid Howells 	afs_close_socket();
14108e0e7c8SDavid Howells error_open_socket:
14208e0e7c8SDavid Howells error_vl_update_init:
143ec26815aSDavid Howells error_cell_init:
1441da177e4SLinus Torvalds #ifdef AFS_CACHING_SUPPORT
1451da177e4SLinus Torvalds 	cachefs_unregister_netfs(&afs_cache_netfs);
146ec26815aSDavid Howells error_cache:
1471da177e4SLinus Torvalds #endif
14808e0e7c8SDavid Howells 	afs_callback_update_kill();
14908e0e7c8SDavid Howells 	afs_vlocation_purge();
1501da177e4SLinus Torvalds 	afs_cell_purge();
1511da177e4SLinus Torvalds 	afs_proc_cleanup();
1521da177e4SLinus Torvalds 	printk(KERN_ERR "kAFS: failed to register: %d\n", ret);
1531da177e4SLinus Torvalds 	return ret;
154ec26815aSDavid Howells }
1551da177e4SLinus Torvalds 
1561da177e4SLinus Torvalds /* XXX late_initcall is kludgy, but the only alternative seems to create
1571da177e4SLinus Torvalds  * a transport upon the first mount, which is worse. Or is it?
1581da177e4SLinus Torvalds  */
1591da177e4SLinus Torvalds late_initcall(afs_init);	/* must be called after net/ to create socket */
160ec26815aSDavid Howells 
1611da177e4SLinus Torvalds /*
1621da177e4SLinus Torvalds  * clean up on module removal
1631da177e4SLinus Torvalds  */
1641da177e4SLinus Torvalds static void __exit afs_exit(void)
1651da177e4SLinus Torvalds {
1661da177e4SLinus Torvalds 	printk(KERN_INFO "kAFS: Red Hat AFS client v0.1 unregistering.\n");
1671da177e4SLinus Torvalds 
1681da177e4SLinus Torvalds 	afs_fs_exit();
16908e0e7c8SDavid Howells 	afs_close_socket();
17008e0e7c8SDavid Howells 	afs_purge_servers();
17108e0e7c8SDavid Howells 	afs_callback_update_kill();
17208e0e7c8SDavid Howells 	afs_vlocation_purge();
17308e0e7c8SDavid Howells 	flush_scheduled_work();
1741da177e4SLinus Torvalds 	afs_cell_purge();
1751da177e4SLinus Torvalds #ifdef AFS_CACHING_SUPPORT
1761da177e4SLinus Torvalds 	cachefs_unregister_netfs(&afs_cache_netfs);
1771da177e4SLinus Torvalds #endif
1781da177e4SLinus Torvalds 	afs_proc_cleanup();
179ec26815aSDavid Howells }
1801da177e4SLinus Torvalds 
1811da177e4SLinus Torvalds module_exit(afs_exit);
182