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