1 /* 2 * (C) 2001 Clemson University and The University of Chicago 3 * 4 * Changes by Acxiom Corporation to add proc file handler for pvfs2 client 5 * parameters, Copyright Acxiom Corporation, 2005. 6 * 7 * See COPYING in top-level directory. 8 */ 9 10 #include "protocol.h" 11 #include "orangefs-kernel.h" 12 #include "orangefs-debugfs.h" 13 #include "orangefs-sysfs.h" 14 15 /* ORANGEFS_VERSION is a ./configure define */ 16 #ifndef ORANGEFS_VERSION 17 #define ORANGEFS_VERSION "upstream" 18 #endif 19 20 /* 21 * global variables declared here 22 */ 23 24 struct orangefs_stats orangefs_stats; 25 26 /* the size of the hash tables for ops in progress */ 27 int hash_table_size = 509; 28 29 static ulong module_parm_debug_mask; 30 __u64 orangefs_gossip_debug_mask; 31 int op_timeout_secs = ORANGEFS_DEFAULT_OP_TIMEOUT_SECS; 32 int slot_timeout_secs = ORANGEFS_DEFAULT_SLOT_TIMEOUT_SECS; 33 int orangefs_dcache_timeout_msecs = 50; 34 int orangefs_getattr_timeout_msecs = 50; 35 36 MODULE_LICENSE("GPL"); 37 MODULE_AUTHOR("ORANGEFS Development Team"); 38 MODULE_DESCRIPTION("The Linux Kernel VFS interface to ORANGEFS"); 39 MODULE_PARM_DESC(module_parm_debug_mask, "debugging level (see orangefs-debug.h for values)"); 40 MODULE_PARM_DESC(op_timeout_secs, "Operation timeout in seconds"); 41 MODULE_PARM_DESC(slot_timeout_secs, "Slot timeout in seconds"); 42 MODULE_PARM_DESC(hash_table_size, 43 "size of hash table for operations in progress"); 44 45 static struct file_system_type orangefs_fs_type = { 46 .name = "pvfs2", 47 .mount = orangefs_mount, 48 .kill_sb = orangefs_kill_sb, 49 .owner = THIS_MODULE, 50 }; 51 52 module_param(hash_table_size, int, 0); 53 module_param(module_parm_debug_mask, ulong, 0644); 54 module_param(op_timeout_secs, int, 0); 55 module_param(slot_timeout_secs, int, 0); 56 57 /* 58 * Blocks non-priority requests from being queued for servicing. This 59 * could be used for protecting the request list data structure, but 60 * for now it's only being used to stall the op addition to the request 61 * list 62 */ 63 DEFINE_MUTEX(orangefs_request_mutex); 64 65 /* hash table for storing operations waiting for matching downcall */ 66 struct list_head *orangefs_htable_ops_in_progress; 67 DEFINE_SPINLOCK(orangefs_htable_ops_in_progress_lock); 68 69 /* list for queueing upcall operations */ 70 LIST_HEAD(orangefs_request_list); 71 72 /* used to protect the above orangefs_request_list */ 73 DEFINE_SPINLOCK(orangefs_request_list_lock); 74 75 /* used for incoming request notification */ 76 DECLARE_WAIT_QUEUE_HEAD(orangefs_request_list_waitq); 77 78 static int __init orangefs_init(void) 79 { 80 int ret = -1; 81 __u32 i = 0; 82 83 ret = bdi_init(&orangefs_backing_dev_info); 84 85 if (ret) 86 return ret; 87 88 if (op_timeout_secs < 0) 89 op_timeout_secs = 0; 90 91 if (slot_timeout_secs < 0) 92 slot_timeout_secs = 0; 93 94 /* initialize global book keeping data structures */ 95 ret = op_cache_initialize(); 96 if (ret < 0) 97 goto err; 98 99 ret = orangefs_inode_cache_initialize(); 100 if (ret < 0) 101 goto cleanup_op; 102 103 orangefs_htable_ops_in_progress = 104 kcalloc(hash_table_size, sizeof(struct list_head), GFP_KERNEL); 105 if (!orangefs_htable_ops_in_progress) { 106 gossip_err("Failed to initialize op hashtable"); 107 ret = -ENOMEM; 108 goto cleanup_inode; 109 } 110 111 /* initialize a doubly linked at each hash table index */ 112 for (i = 0; i < hash_table_size; i++) 113 INIT_LIST_HEAD(&orangefs_htable_ops_in_progress[i]); 114 115 ret = fsid_key_table_initialize(); 116 if (ret < 0) 117 goto cleanup_progress_table; 118 119 /* 120 * Build the contents of /sys/kernel/debug/orangefs/debug-help 121 * from the keywords in the kernel keyword/mask array. 122 * 123 * The keywords in the client keyword/mask array are 124 * unknown at boot time. 125 * 126 * orangefs_prepare_debugfs_help_string will be used again 127 * later to rebuild the debug-help-string after the client starts 128 * and passes along the needed info. The argument signifies 129 * which time orangefs_prepare_debugfs_help_string is being 130 * called. 131 */ 132 ret = orangefs_prepare_debugfs_help_string(1); 133 if (ret) 134 goto cleanup_key_table; 135 136 ret = orangefs_debugfs_init(module_parm_debug_mask); 137 if (ret) 138 goto debugfs_init_failed; 139 140 ret = orangefs_sysfs_init(); 141 if (ret) 142 goto sysfs_init_failed; 143 144 /* Initialize the orangefsdev subsystem. */ 145 ret = orangefs_dev_init(); 146 if (ret < 0) { 147 gossip_err("%s: could not initialize device subsystem %d!\n", 148 __func__, 149 ret); 150 goto cleanup_device; 151 } 152 153 ret = register_filesystem(&orangefs_fs_type); 154 if (ret == 0) { 155 pr_info("%s: module version %s loaded\n", 156 __func__, 157 ORANGEFS_VERSION); 158 ret = 0; 159 goto out; 160 } 161 162 orangefs_sysfs_exit(); 163 164 cleanup_device: 165 orangefs_dev_cleanup(); 166 167 sysfs_init_failed: 168 169 debugfs_init_failed: 170 orangefs_debugfs_cleanup(); 171 172 cleanup_key_table: 173 fsid_key_table_finalize(); 174 175 cleanup_progress_table: 176 kfree(orangefs_htable_ops_in_progress); 177 178 cleanup_inode: 179 orangefs_inode_cache_finalize(); 180 181 cleanup_op: 182 op_cache_finalize(); 183 184 err: 185 bdi_destroy(&orangefs_backing_dev_info); 186 187 out: 188 return ret; 189 } 190 191 static void __exit orangefs_exit(void) 192 { 193 int i = 0; 194 gossip_debug(GOSSIP_INIT_DEBUG, "orangefs: orangefs_exit called\n"); 195 196 unregister_filesystem(&orangefs_fs_type); 197 orangefs_debugfs_cleanup(); 198 orangefs_sysfs_exit(); 199 fsid_key_table_finalize(); 200 orangefs_dev_cleanup(); 201 BUG_ON(!list_empty(&orangefs_request_list)); 202 for (i = 0; i < hash_table_size; i++) 203 BUG_ON(!list_empty(&orangefs_htable_ops_in_progress[i])); 204 205 orangefs_inode_cache_finalize(); 206 op_cache_finalize(); 207 208 kfree(orangefs_htable_ops_in_progress); 209 210 bdi_destroy(&orangefs_backing_dev_info); 211 212 pr_info("orangefs: module version %s unloaded\n", ORANGEFS_VERSION); 213 } 214 215 /* 216 * What we do in this function is to walk the list of operations 217 * that are in progress in the hash table and mark them as purged as well. 218 */ 219 void purge_inprogress_ops(void) 220 { 221 int i; 222 223 for (i = 0; i < hash_table_size; i++) { 224 struct orangefs_kernel_op_s *op; 225 struct orangefs_kernel_op_s *next; 226 227 spin_lock(&orangefs_htable_ops_in_progress_lock); 228 list_for_each_entry_safe(op, 229 next, 230 &orangefs_htable_ops_in_progress[i], 231 list) { 232 set_op_state_purged(op); 233 gossip_debug(GOSSIP_DEV_DEBUG, 234 "%s: op:%s: op_state:%d: process:%s:\n", 235 __func__, 236 get_opname_string(op), 237 op->op_state, 238 current->comm); 239 } 240 spin_unlock(&orangefs_htable_ops_in_progress_lock); 241 } 242 } 243 244 module_init(orangefs_init); 245 module_exit(orangefs_exit); 246