xref: /openbmc/linux/fs/afs/main.c (revision b908fe6b2d1294d93b0d0badf6bf4f9a2cd7d729)
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 
43*b908fe6bSDavid Howells struct afs_uuid afs_uuid;
44*b908fe6bSDavid Howells 
45*b908fe6bSDavid Howells /*
46*b908fe6bSDavid Howells  * get a client UUID
47*b908fe6bSDavid Howells  */
48*b908fe6bSDavid Howells static int __init afs_get_client_UUID(void)
49*b908fe6bSDavid Howells {
50*b908fe6bSDavid Howells 	struct timespec ts;
51*b908fe6bSDavid Howells 	u64 uuidtime;
52*b908fe6bSDavid Howells 	u16 clockseq;
53*b908fe6bSDavid Howells 	int ret;
54*b908fe6bSDavid Howells 
55*b908fe6bSDavid Howells 	/* read the MAC address of one of the external interfaces and construct
56*b908fe6bSDavid Howells 	 * a UUID from it */
57*b908fe6bSDavid Howells 	ret = afs_get_MAC_address(afs_uuid.node);
58*b908fe6bSDavid Howells 	if (ret < 0)
59*b908fe6bSDavid Howells 		return ret;
60*b908fe6bSDavid Howells 
61*b908fe6bSDavid Howells 	getnstimeofday(&ts);
62*b908fe6bSDavid Howells 	uuidtime = (u64) ts.tv_sec * 1000 * 1000 * 10;
63*b908fe6bSDavid Howells 	uuidtime += ts.tv_nsec / 100;
64*b908fe6bSDavid Howells 	uuidtime += AFS_UUID_TO_UNIX_TIME;
65*b908fe6bSDavid Howells 	afs_uuid.time_low = uuidtime;
66*b908fe6bSDavid Howells 	afs_uuid.time_mid = uuidtime >> 32;
67*b908fe6bSDavid Howells 	afs_uuid.time_hi_and_version = (uuidtime >> 48) & AFS_UUID_TIMEHI_MASK;
68*b908fe6bSDavid Howells 	afs_uuid.time_hi_and_version = AFS_UUID_VERSION_TIME;
69*b908fe6bSDavid Howells 
70*b908fe6bSDavid Howells 	get_random_bytes(&clockseq, 2);
71*b908fe6bSDavid Howells 	afs_uuid.clock_seq_low = clockseq;
72*b908fe6bSDavid Howells 	afs_uuid.clock_seq_hi_and_reserved =
73*b908fe6bSDavid Howells 		(clockseq >> 8) & AFS_UUID_CLOCKHI_MASK;
74*b908fe6bSDavid Howells 	afs_uuid.clock_seq_hi_and_reserved = AFS_UUID_VARIANT_STD;
75*b908fe6bSDavid Howells 
76*b908fe6bSDavid Howells 	_debug("AFS UUID: %08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
77*b908fe6bSDavid Howells 	       afs_uuid.time_low,
78*b908fe6bSDavid Howells 	       afs_uuid.time_mid,
79*b908fe6bSDavid Howells 	       afs_uuid.time_hi_and_version,
80*b908fe6bSDavid Howells 	       afs_uuid.clock_seq_hi_and_reserved,
81*b908fe6bSDavid Howells 	       afs_uuid.clock_seq_low,
82*b908fe6bSDavid Howells 	       afs_uuid.node[0], afs_uuid.node[1], afs_uuid.node[2],
83*b908fe6bSDavid Howells 	       afs_uuid.node[3], afs_uuid.node[4], afs_uuid.node[5]);
84*b908fe6bSDavid Howells 
85*b908fe6bSDavid Howells 	return 0;
86*b908fe6bSDavid Howells }
87*b908fe6bSDavid 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 
97*b908fe6bSDavid Howells 	ret = afs_get_client_UUID();
98*b908fe6bSDavid Howells 	if (ret < 0)
99*b908fe6bSDavid Howells 		return ret;
100*b908fe6bSDavid 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