1 /* AFS client file system 2 * 3 * Copyright (C) 2002,5 Red Hat, Inc. All Rights Reserved. 4 * Written by David Howells (dhowells@redhat.com) 5 * 6 * This program is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU General Public License 8 * as published by the Free Software Foundation; either version 9 * 2 of the License, or (at your option) any later version. 10 */ 11 12 #include <linux/module.h> 13 #include <linux/moduleparam.h> 14 #include <linux/init.h> 15 #include <linux/completion.h> 16 #include <linux/sched.h> 17 #include "internal.h" 18 19 MODULE_DESCRIPTION("AFS Client File System"); 20 MODULE_AUTHOR("Red Hat, Inc."); 21 MODULE_LICENSE("GPL"); 22 23 unsigned afs_debug; 24 module_param_named(debug, afs_debug, uint, S_IWUSR | S_IRUGO); 25 MODULE_PARM_DESC(debug, "AFS debugging mask"); 26 27 static char *rootcell; 28 29 module_param(rootcell, charp, 0); 30 MODULE_PARM_DESC(rootcell, "root AFS cell name and VL server IP addr list"); 31 32 struct afs_uuid afs_uuid; 33 struct workqueue_struct *afs_wq; 34 35 /* 36 * get a client UUID 37 */ 38 static int __init afs_get_client_UUID(void) 39 { 40 struct timespec ts; 41 u64 uuidtime; 42 u16 clockseq; 43 int ret; 44 45 /* read the MAC address of one of the external interfaces and construct 46 * a UUID from it */ 47 ret = afs_get_MAC_address(afs_uuid.node, sizeof(afs_uuid.node)); 48 if (ret < 0) 49 return ret; 50 51 getnstimeofday(&ts); 52 uuidtime = (u64) ts.tv_sec * 1000 * 1000 * 10; 53 uuidtime += ts.tv_nsec / 100; 54 uuidtime += AFS_UUID_TO_UNIX_TIME; 55 afs_uuid.time_low = uuidtime; 56 afs_uuid.time_mid = uuidtime >> 32; 57 afs_uuid.time_hi_and_version = (uuidtime >> 48) & AFS_UUID_TIMEHI_MASK; 58 afs_uuid.time_hi_and_version = AFS_UUID_VERSION_TIME; 59 60 get_random_bytes(&clockseq, 2); 61 afs_uuid.clock_seq_low = clockseq; 62 afs_uuid.clock_seq_hi_and_reserved = 63 (clockseq >> 8) & AFS_UUID_CLOCKHI_MASK; 64 afs_uuid.clock_seq_hi_and_reserved = AFS_UUID_VARIANT_STD; 65 66 _debug("AFS UUID: %08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x", 67 afs_uuid.time_low, 68 afs_uuid.time_mid, 69 afs_uuid.time_hi_and_version, 70 afs_uuid.clock_seq_hi_and_reserved, 71 afs_uuid.clock_seq_low, 72 afs_uuid.node[0], afs_uuid.node[1], afs_uuid.node[2], 73 afs_uuid.node[3], afs_uuid.node[4], afs_uuid.node[5]); 74 75 return 0; 76 } 77 78 /* 79 * initialise the AFS client FS module 80 */ 81 static int __init afs_init(void) 82 { 83 int ret; 84 85 printk(KERN_INFO "kAFS: Red Hat AFS client v0.1 registering.\n"); 86 87 ret = afs_get_client_UUID(); 88 if (ret < 0) 89 return ret; 90 91 /* create workqueue */ 92 ret = -ENOMEM; 93 afs_wq = alloc_workqueue("afs", 0, 0); 94 if (!afs_wq) 95 return ret; 96 97 /* register the /proc stuff */ 98 ret = afs_proc_init(); 99 if (ret < 0) 100 goto error_proc; 101 102 #ifdef CONFIG_AFS_FSCACHE 103 /* we want to be able to cache */ 104 ret = fscache_register_netfs(&afs_cache_netfs); 105 if (ret < 0) 106 goto error_cache; 107 #endif 108 109 /* initialise the cell DB */ 110 ret = afs_cell_init(rootcell); 111 if (ret < 0) 112 goto error_cell_init; 113 114 /* initialise the VL update process */ 115 ret = afs_vlocation_update_init(); 116 if (ret < 0) 117 goto error_vl_update_init; 118 119 /* initialise the callback update process */ 120 ret = afs_callback_update_init(); 121 if (ret < 0) 122 goto error_callback_update_init; 123 124 /* create the RxRPC transport */ 125 ret = afs_open_socket(); 126 if (ret < 0) 127 goto error_open_socket; 128 129 /* register the filesystems */ 130 ret = afs_fs_init(); 131 if (ret < 0) 132 goto error_fs; 133 134 return ret; 135 136 error_fs: 137 afs_close_socket(); 138 error_open_socket: 139 afs_callback_update_kill(); 140 error_callback_update_init: 141 afs_vlocation_purge(); 142 error_vl_update_init: 143 afs_cell_purge(); 144 error_cell_init: 145 #ifdef CONFIG_AFS_FSCACHE 146 fscache_unregister_netfs(&afs_cache_netfs); 147 error_cache: 148 #endif 149 afs_proc_cleanup(); 150 error_proc: 151 destroy_workqueue(afs_wq); 152 rcu_barrier(); 153 printk(KERN_ERR "kAFS: failed to register: %d\n", ret); 154 return ret; 155 } 156 157 /* XXX late_initcall is kludgy, but the only alternative seems to create 158 * a transport upon the first mount, which is worse. Or is it? 159 */ 160 late_initcall(afs_init); /* must be called after net/ to create socket */ 161 162 /* 163 * clean up on module removal 164 */ 165 static void __exit afs_exit(void) 166 { 167 printk(KERN_INFO "kAFS: Red Hat AFS client v0.1 unregistering.\n"); 168 169 afs_fs_exit(); 170 afs_kill_lock_manager(); 171 afs_close_socket(); 172 afs_purge_servers(); 173 afs_callback_update_kill(); 174 afs_vlocation_purge(); 175 destroy_workqueue(afs_wq); 176 afs_cell_purge(); 177 #ifdef CONFIG_AFS_FSCACHE 178 fscache_unregister_netfs(&afs_cache_netfs); 179 #endif 180 afs_proc_cleanup(); 181 rcu_barrier(); 182 } 183 184 module_exit(afs_exit); 185