1 /* AFS client file system 2 * 3 * Copyright (C) 2002 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 "internal.h" 17 18 MODULE_DESCRIPTION("AFS Client File System"); 19 MODULE_AUTHOR("Red Hat, Inc."); 20 MODULE_LICENSE("GPL"); 21 22 unsigned afs_debug; 23 module_param_named(debug, afs_debug, uint, S_IWUSR | S_IRUGO); 24 MODULE_PARM_DESC(afs_debug, "AFS debugging mask"); 25 26 static char *rootcell; 27 28 module_param(rootcell, charp, 0); 29 MODULE_PARM_DESC(rootcell, "root AFS cell name and VL server IP addr list"); 30 31 #ifdef AFS_CACHING_SUPPORT 32 static struct cachefs_netfs_operations afs_cache_ops = { 33 .get_page_cookie = afs_cache_get_page_cookie, 34 }; 35 36 struct cachefs_netfs afs_cache_netfs = { 37 .name = "afs", 38 .version = 0, 39 .ops = &afs_cache_ops, 40 }; 41 #endif 42 43 struct afs_uuid afs_uuid; 44 45 /* 46 * get a client UUID 47 */ 48 static int __init afs_get_client_UUID(void) 49 { 50 struct timespec ts; 51 u64 uuidtime; 52 u16 clockseq; 53 int ret; 54 55 /* read the MAC address of one of the external interfaces and construct 56 * a UUID from it */ 57 ret = afs_get_MAC_address(afs_uuid.node, sizeof(afs_uuid.node)); 58 if (ret < 0) 59 return ret; 60 61 getnstimeofday(&ts); 62 uuidtime = (u64) ts.tv_sec * 1000 * 1000 * 10; 63 uuidtime += ts.tv_nsec / 100; 64 uuidtime += AFS_UUID_TO_UNIX_TIME; 65 afs_uuid.time_low = uuidtime; 66 afs_uuid.time_mid = uuidtime >> 32; 67 afs_uuid.time_hi_and_version = (uuidtime >> 48) & AFS_UUID_TIMEHI_MASK; 68 afs_uuid.time_hi_and_version = AFS_UUID_VERSION_TIME; 69 70 get_random_bytes(&clockseq, 2); 71 afs_uuid.clock_seq_low = clockseq; 72 afs_uuid.clock_seq_hi_and_reserved = 73 (clockseq >> 8) & AFS_UUID_CLOCKHI_MASK; 74 afs_uuid.clock_seq_hi_and_reserved = AFS_UUID_VARIANT_STD; 75 76 _debug("AFS UUID: %08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x", 77 afs_uuid.time_low, 78 afs_uuid.time_mid, 79 afs_uuid.time_hi_and_version, 80 afs_uuid.clock_seq_hi_and_reserved, 81 afs_uuid.clock_seq_low, 82 afs_uuid.node[0], afs_uuid.node[1], afs_uuid.node[2], 83 afs_uuid.node[3], afs_uuid.node[4], afs_uuid.node[5]); 84 85 return 0; 86 } 87 88 /* 89 * initialise the AFS client FS module 90 */ 91 static int __init afs_init(void) 92 { 93 int ret; 94 95 printk(KERN_INFO "kAFS: Red Hat AFS client v0.1 registering.\n"); 96 97 ret = afs_get_client_UUID(); 98 if (ret < 0) 99 return ret; 100 101 /* register the /proc stuff */ 102 ret = afs_proc_init(); 103 if (ret < 0) 104 return ret; 105 106 #ifdef AFS_CACHING_SUPPORT 107 /* we want to be able to cache */ 108 ret = cachefs_register_netfs(&afs_cache_netfs, 109 &afs_cache_cell_index_def); 110 if (ret < 0) 111 goto error_cache; 112 #endif 113 114 /* initialise the cell DB */ 115 ret = afs_cell_init(rootcell); 116 if (ret < 0) 117 goto error_cell_init; 118 119 /* initialise the VL update process */ 120 ret = afs_vlocation_update_init(); 121 if (ret < 0) 122 goto error_vl_update_init; 123 124 /* initialise the callback update process */ 125 ret = afs_callback_update_init(); 126 127 /* create the RxRPC transport */ 128 ret = afs_open_socket(); 129 if (ret < 0) 130 goto error_open_socket; 131 132 /* register the filesystems */ 133 ret = afs_fs_init(); 134 if (ret < 0) 135 goto error_fs; 136 137 return ret; 138 139 error_fs: 140 afs_close_socket(); 141 error_open_socket: 142 error_vl_update_init: 143 error_cell_init: 144 #ifdef AFS_CACHING_SUPPORT 145 cachefs_unregister_netfs(&afs_cache_netfs); 146 error_cache: 147 #endif 148 afs_callback_update_kill(); 149 afs_vlocation_purge(); 150 afs_cell_purge(); 151 afs_proc_cleanup(); 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_close_socket(); 171 afs_purge_servers(); 172 afs_callback_update_kill(); 173 afs_vlocation_purge(); 174 flush_scheduled_work(); 175 afs_cell_purge(); 176 #ifdef AFS_CACHING_SUPPORT 177 cachefs_unregister_netfs(&afs_cache_netfs); 178 #endif 179 afs_proc_cleanup(); 180 rcu_barrier(); 181 } 182 183 module_exit(afs_exit); 184