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 34 /* 35 * get a client UUID 36 */ 37 static int __init afs_get_client_UUID(void) 38 { 39 struct timespec ts; 40 u64 uuidtime; 41 u16 clockseq; 42 int ret; 43 44 /* read the MAC address of one of the external interfaces and construct 45 * a UUID from it */ 46 ret = afs_get_MAC_address(afs_uuid.node, sizeof(afs_uuid.node)); 47 if (ret < 0) 48 return ret; 49 50 getnstimeofday(&ts); 51 uuidtime = (u64) ts.tv_sec * 1000 * 1000 * 10; 52 uuidtime += ts.tv_nsec / 100; 53 uuidtime += AFS_UUID_TO_UNIX_TIME; 54 afs_uuid.time_low = uuidtime; 55 afs_uuid.time_mid = uuidtime >> 32; 56 afs_uuid.time_hi_and_version = (uuidtime >> 48) & AFS_UUID_TIMEHI_MASK; 57 afs_uuid.time_hi_and_version = AFS_UUID_VERSION_TIME; 58 59 get_random_bytes(&clockseq, 2); 60 afs_uuid.clock_seq_low = clockseq; 61 afs_uuid.clock_seq_hi_and_reserved = 62 (clockseq >> 8) & AFS_UUID_CLOCKHI_MASK; 63 afs_uuid.clock_seq_hi_and_reserved = AFS_UUID_VARIANT_STD; 64 65 _debug("AFS UUID: %08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x", 66 afs_uuid.time_low, 67 afs_uuid.time_mid, 68 afs_uuid.time_hi_and_version, 69 afs_uuid.clock_seq_hi_and_reserved, 70 afs_uuid.clock_seq_low, 71 afs_uuid.node[0], afs_uuid.node[1], afs_uuid.node[2], 72 afs_uuid.node[3], afs_uuid.node[4], afs_uuid.node[5]); 73 74 return 0; 75 } 76 77 /* 78 * initialise the AFS client FS module 79 */ 80 static int __init afs_init(void) 81 { 82 int ret; 83 84 printk(KERN_INFO "kAFS: Red Hat AFS client v0.1 registering.\n"); 85 86 ret = afs_get_client_UUID(); 87 if (ret < 0) 88 return ret; 89 90 /* register the /proc stuff */ 91 ret = afs_proc_init(); 92 if (ret < 0) 93 return ret; 94 95 #ifdef CONFIG_AFS_FSCACHE 96 /* we want to be able to cache */ 97 ret = fscache_register_netfs(&afs_cache_netfs); 98 if (ret < 0) 99 goto error_cache; 100 #endif 101 102 /* initialise the cell DB */ 103 ret = afs_cell_init(rootcell); 104 if (ret < 0) 105 goto error_cell_init; 106 107 /* initialise the VL update process */ 108 ret = afs_vlocation_update_init(); 109 if (ret < 0) 110 goto error_vl_update_init; 111 112 /* initialise the callback update process */ 113 ret = afs_callback_update_init(); 114 if (ret < 0) 115 goto error_callback_update_init; 116 117 /* create the RxRPC transport */ 118 ret = afs_open_socket(); 119 if (ret < 0) 120 goto error_open_socket; 121 122 /* register the filesystems */ 123 ret = afs_fs_init(); 124 if (ret < 0) 125 goto error_fs; 126 127 return ret; 128 129 error_fs: 130 afs_close_socket(); 131 error_open_socket: 132 afs_callback_update_kill(); 133 error_callback_update_init: 134 afs_vlocation_purge(); 135 error_vl_update_init: 136 afs_cell_purge(); 137 error_cell_init: 138 #ifdef CONFIG_AFS_FSCACHE 139 fscache_unregister_netfs(&afs_cache_netfs); 140 error_cache: 141 #endif 142 afs_proc_cleanup(); 143 rcu_barrier(); 144 printk(KERN_ERR "kAFS: failed to register: %d\n", ret); 145 return ret; 146 } 147 148 /* XXX late_initcall is kludgy, but the only alternative seems to create 149 * a transport upon the first mount, which is worse. Or is it? 150 */ 151 late_initcall(afs_init); /* must be called after net/ to create socket */ 152 153 /* 154 * clean up on module removal 155 */ 156 static void __exit afs_exit(void) 157 { 158 printk(KERN_INFO "kAFS: Red Hat AFS client v0.1 unregistering.\n"); 159 160 afs_fs_exit(); 161 afs_kill_lock_manager(); 162 afs_close_socket(); 163 afs_purge_servers(); 164 afs_callback_update_kill(); 165 afs_vlocation_purge(); 166 flush_scheduled_work(); 167 afs_cell_purge(); 168 #ifdef CONFIG_AFS_FSCACHE 169 fscache_unregister_netfs(&afs_cache_netfs); 170 #endif 171 afs_proc_cleanup(); 172 rcu_barrier(); 173 } 174 175 module_exit(afs_exit); 176