xref: /linux/fs/afs/main.c (revision f044c8847bb61eff5e1e95b6f6bb950e7f4a73a4)
1ec26815aSDavid Howells /* AFS client file system
21da177e4SLinus Torvalds  *
39b3f26c9SDavid Howells  * Copyright (C) 2002,5 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>
16e8edc6e0SAlexey Dobriyan #include <linux/sched.h>
17e0661dfcSDavid Howells #include <linux/random.h>
188e8d7f13SDavid Howells #define CREATE_TRACE_POINTS
191da177e4SLinus Torvalds #include "internal.h"
201da177e4SLinus Torvalds 
211da177e4SLinus Torvalds MODULE_DESCRIPTION("AFS Client File System");
221da177e4SLinus Torvalds MODULE_AUTHOR("Red Hat, Inc.");
231da177e4SLinus Torvalds MODULE_LICENSE("GPL");
241da177e4SLinus Torvalds 
2508e0e7c8SDavid Howells unsigned afs_debug;
2608e0e7c8SDavid Howells module_param_named(debug, afs_debug, uint, S_IWUSR | S_IRUGO);
27424b00e2SPaul Bolle MODULE_PARM_DESC(debug, "AFS debugging mask");
2808e0e7c8SDavid Howells 
291da177e4SLinus Torvalds static char *rootcell;
301da177e4SLinus Torvalds 
311da177e4SLinus Torvalds module_param(rootcell, charp, 0);
321da177e4SLinus Torvalds MODULE_PARM_DESC(rootcell, "root AFS cell name and VL server IP addr list");
331da177e4SLinus Torvalds 
340ad53eeeSTejun Heo struct workqueue_struct *afs_wq;
35*f044c884SDavid Howells struct afs_net __afs_net;
36*f044c884SDavid Howells 
37*f044c884SDavid Howells /*
38*f044c884SDavid Howells  * Initialise an AFS network namespace record.
39*f044c884SDavid Howells  */
40*f044c884SDavid Howells static int __net_init afs_net_init(struct afs_net *net)
41*f044c884SDavid Howells {
42*f044c884SDavid Howells 	int ret;
43*f044c884SDavid Howells 
44*f044c884SDavid Howells 	net->live = true;
45*f044c884SDavid Howells 	generate_random_uuid((unsigned char *)&net->uuid);
46*f044c884SDavid Howells 
47*f044c884SDavid Howells 	INIT_WORK(&net->charge_preallocation_work, afs_charge_preallocation);
48*f044c884SDavid Howells 	mutex_init(&net->socket_mutex);
49*f044c884SDavid Howells 	INIT_LIST_HEAD(&net->cells);
50*f044c884SDavid Howells 	rwlock_init(&net->cells_lock);
51*f044c884SDavid Howells 	init_rwsem(&net->cells_sem);
52*f044c884SDavid Howells 	init_waitqueue_head(&net->cells_freeable_wq);
53*f044c884SDavid Howells 	init_rwsem(&net->proc_cells_sem);
54*f044c884SDavid Howells 	INIT_LIST_HEAD(&net->proc_cells);
55*f044c884SDavid Howells 	INIT_LIST_HEAD(&net->vl_updates);
56*f044c884SDavid Howells 	INIT_LIST_HEAD(&net->vl_graveyard);
57*f044c884SDavid Howells 	INIT_DELAYED_WORK(&net->vl_reaper, afs_vlocation_reaper);
58*f044c884SDavid Howells 	INIT_DELAYED_WORK(&net->vl_updater, afs_vlocation_updater);
59*f044c884SDavid Howells 	spin_lock_init(&net->vl_updates_lock);
60*f044c884SDavid Howells 	spin_lock_init(&net->vl_graveyard_lock);
61*f044c884SDavid Howells 	net->servers = RB_ROOT;
62*f044c884SDavid Howells 	rwlock_init(&net->servers_lock);
63*f044c884SDavid Howells 	INIT_LIST_HEAD(&net->server_graveyard);
64*f044c884SDavid Howells 	spin_lock_init(&net->server_graveyard_lock);
65*f044c884SDavid Howells 	INIT_DELAYED_WORK(&net->server_reaper, afs_reap_server);
66*f044c884SDavid Howells 
67*f044c884SDavid Howells 	/* Register the /proc stuff */
68*f044c884SDavid Howells 	ret = afs_proc_init(net);
69*f044c884SDavid Howells 	if (ret < 0)
70*f044c884SDavid Howells 		goto error_proc;
71*f044c884SDavid Howells 
72*f044c884SDavid Howells 	/* Initialise the cell DB */
73*f044c884SDavid Howells 	ret = afs_cell_init(net, rootcell);
74*f044c884SDavid Howells 	if (ret < 0)
75*f044c884SDavid Howells 		goto error_cell_init;
76*f044c884SDavid Howells 
77*f044c884SDavid Howells 	/* Create the RxRPC transport */
78*f044c884SDavid Howells 	ret = afs_open_socket(net);
79*f044c884SDavid Howells 	if (ret < 0)
80*f044c884SDavid Howells 		goto error_open_socket;
81*f044c884SDavid Howells 
82*f044c884SDavid Howells 	return 0;
83*f044c884SDavid Howells 
84*f044c884SDavid Howells error_open_socket:
85*f044c884SDavid Howells 	afs_vlocation_purge(net);
86*f044c884SDavid Howells 	afs_cell_purge(net);
87*f044c884SDavid Howells error_cell_init:
88*f044c884SDavid Howells 	afs_proc_cleanup(net);
89*f044c884SDavid Howells error_proc:
90*f044c884SDavid Howells 	return ret;
91*f044c884SDavid Howells }
92*f044c884SDavid Howells 
93*f044c884SDavid Howells /*
94*f044c884SDavid Howells  * Clean up and destroy an AFS network namespace record.
95*f044c884SDavid Howells  */
96*f044c884SDavid Howells static void __net_exit afs_net_exit(struct afs_net *net)
97*f044c884SDavid Howells {
98*f044c884SDavid Howells 	net->live = false;
99*f044c884SDavid Howells 	afs_close_socket(net);
100*f044c884SDavid Howells 	afs_purge_servers(net);
101*f044c884SDavid Howells 	afs_vlocation_purge(net);
102*f044c884SDavid Howells 	afs_cell_purge(net);
103*f044c884SDavid Howells 	afs_proc_cleanup(net);
104*f044c884SDavid Howells }
105b908fe6bSDavid Howells 
106b908fe6bSDavid Howells /*
1071da177e4SLinus Torvalds  * initialise the AFS client FS module
1081da177e4SLinus Torvalds  */
1091da177e4SLinus Torvalds static int __init afs_init(void)
1101da177e4SLinus Torvalds {
111*f044c884SDavid Howells 	int ret = -ENOMEM;
1121da177e4SLinus Torvalds 
1131da177e4SLinus Torvalds 	printk(KERN_INFO "kAFS: Red Hat AFS client v0.1 registering.\n");
1141da177e4SLinus Torvalds 
1150ad53eeeSTejun Heo 	afs_wq = alloc_workqueue("afs", 0, 0);
1160ad53eeeSTejun Heo 	if (!afs_wq)
117*f044c884SDavid Howells 		goto error_afs_wq;
118*f044c884SDavid Howells 	afs_async_calls = alloc_workqueue("kafsd", WQ_MEM_RECLAIM, 0);
119*f044c884SDavid Howells 	if (!afs_async_calls)
120*f044c884SDavid Howells 		goto error_async;
121*f044c884SDavid Howells 	afs_vlocation_update_worker =
122*f044c884SDavid Howells 		alloc_workqueue("kafs_vlupdated", WQ_MEM_RECLAIM, 0);
123*f044c884SDavid Howells 	if (!afs_vlocation_update_worker)
124*f044c884SDavid Howells 		goto error_vl_up;
125*f044c884SDavid Howells 	afs_callback_update_worker =
126*f044c884SDavid Howells 		alloc_ordered_workqueue("kafs_callbackd", WQ_MEM_RECLAIM);
127*f044c884SDavid Howells 	if (!afs_callback_update_worker)
128*f044c884SDavid Howells 		goto error_callback;
129*f044c884SDavid Howells 	afs_lock_manager = alloc_workqueue("kafs_lockd", WQ_MEM_RECLAIM, 0);
130*f044c884SDavid Howells 	if (!afs_lock_manager)
131*f044c884SDavid Howells 		goto error_lockmgr;
1321da177e4SLinus Torvalds 
1339b3f26c9SDavid Howells #ifdef CONFIG_AFS_FSCACHE
1341da177e4SLinus Torvalds 	/* we want to be able to cache */
1359b3f26c9SDavid Howells 	ret = fscache_register_netfs(&afs_cache_netfs);
1361da177e4SLinus Torvalds 	if (ret < 0)
1371da177e4SLinus Torvalds 		goto error_cache;
1381da177e4SLinus Torvalds #endif
1391da177e4SLinus Torvalds 
140*f044c884SDavid Howells 	ret = afs_net_init(&__afs_net);
1411da177e4SLinus Torvalds 	if (ret < 0)
142*f044c884SDavid Howells 		goto error_net;
1431da177e4SLinus Torvalds 
1441da177e4SLinus Torvalds 	/* register the filesystems */
1451da177e4SLinus Torvalds 	ret = afs_fs_init();
1461da177e4SLinus Torvalds 	if (ret < 0)
147ec26815aSDavid Howells 		goto error_fs;
1481da177e4SLinus Torvalds 
1491da177e4SLinus Torvalds 	return ret;
1501da177e4SLinus Torvalds 
151ec26815aSDavid Howells error_fs:
152*f044c884SDavid Howells 	afs_net_exit(&__afs_net);
153*f044c884SDavid Howells error_net:
1549b3f26c9SDavid Howells #ifdef CONFIG_AFS_FSCACHE
1559b3f26c9SDavid Howells 	fscache_unregister_netfs(&afs_cache_netfs);
156ec26815aSDavid Howells error_cache:
1571da177e4SLinus Torvalds #endif
158*f044c884SDavid Howells 	destroy_workqueue(afs_lock_manager);
159*f044c884SDavid Howells error_lockmgr:
160*f044c884SDavid Howells 	destroy_workqueue(afs_callback_update_worker);
161*f044c884SDavid Howells error_callback:
162*f044c884SDavid Howells 	destroy_workqueue(afs_vlocation_update_worker);
163*f044c884SDavid Howells error_vl_up:
164*f044c884SDavid Howells 	destroy_workqueue(afs_async_calls);
165*f044c884SDavid Howells error_async:
1660ad53eeeSTejun Heo 	destroy_workqueue(afs_wq);
167*f044c884SDavid Howells error_afs_wq:
168416351f2SDavid Howells 	rcu_barrier();
1691da177e4SLinus Torvalds 	printk(KERN_ERR "kAFS: failed to register: %d\n", ret);
1701da177e4SLinus Torvalds 	return ret;
171ec26815aSDavid Howells }
1721da177e4SLinus Torvalds 
1731da177e4SLinus Torvalds /* XXX late_initcall is kludgy, but the only alternative seems to create
1741da177e4SLinus Torvalds  * a transport upon the first mount, which is worse. Or is it?
1751da177e4SLinus Torvalds  */
1761da177e4SLinus Torvalds late_initcall(afs_init);	/* must be called after net/ to create socket */
177ec26815aSDavid Howells 
1781da177e4SLinus Torvalds /*
1791da177e4SLinus Torvalds  * clean up on module removal
1801da177e4SLinus Torvalds  */
1811da177e4SLinus Torvalds static void __exit afs_exit(void)
1821da177e4SLinus Torvalds {
1831da177e4SLinus Torvalds 	printk(KERN_INFO "kAFS: Red Hat AFS client v0.1 unregistering.\n");
1841da177e4SLinus Torvalds 
1851da177e4SLinus Torvalds 	afs_fs_exit();
186*f044c884SDavid Howells 	afs_net_exit(&__afs_net);
1879b3f26c9SDavid Howells #ifdef CONFIG_AFS_FSCACHE
1889b3f26c9SDavid Howells 	fscache_unregister_netfs(&afs_cache_netfs);
1891da177e4SLinus Torvalds #endif
190*f044c884SDavid Howells 	destroy_workqueue(afs_lock_manager);
191*f044c884SDavid Howells 	destroy_workqueue(afs_callback_update_worker);
192*f044c884SDavid Howells 	destroy_workqueue(afs_vlocation_update_worker);
193*f044c884SDavid Howells 	destroy_workqueue(afs_async_calls);
194*f044c884SDavid Howells 	destroy_workqueue(afs_wq);
195416351f2SDavid Howells 	rcu_barrier();
196ec26815aSDavid Howells }
1971da177e4SLinus Torvalds 
1981da177e4SLinus Torvalds module_exit(afs_exit);
199