2 * (C) 2001 Clemson University and The University of Chicago
4 * Changes by Acxiom Corporation to add proc file handler for pvfs2 client
5 * parameters, Copyright Acxiom Corporation, 2005.
7 * See COPYING in top-level directory.
11 #include "pvfs2-kernel.h"
12 #include "pvfs2-debugfs.h"
13 #include "pvfs2-sysfs.h"
15 /* PVFS2_VERSION is a ./configure define */
17 #define PVFS2_VERSION "Unknown"
21 * global variables declared here
24 /* array of client debug keyword/mask values */
25 struct client_debug_mask *cdm_array;
26 int cdm_element_count;
28 char kernel_debug_string[PVFS2_MAX_DEBUG_STRING_LEN] = "none";
29 char client_debug_string[PVFS2_MAX_DEBUG_STRING_LEN];
30 char client_debug_array_string[PVFS2_MAX_DEBUG_STRING_LEN];
32 char *debug_help_string;
33 int help_string_initialized;
34 struct dentry *help_file_dentry;
35 struct dentry *client_debug_dentry;
36 struct dentry *debug_dir;
37 int client_verbose_index;
39 struct pvfs2_stats g_pvfs2_stats;
41 /* the size of the hash tables for ops in progress */
42 int hash_table_size = 509;
44 static ulong module_parm_debug_mask;
45 __u64 gossip_debug_mask;
46 struct client_debug_mask client_debug_mask = { NULL, 0, 0 };
47 unsigned int kernel_mask_set_mod_init; /* implicitly false */
48 int op_timeout_secs = PVFS2_DEFAULT_OP_TIMEOUT_SECS;
49 int slot_timeout_secs = PVFS2_DEFAULT_SLOT_TIMEOUT_SECS;
51 MODULE_LICENSE("GPL");
52 MODULE_AUTHOR("PVFS2 Development Team");
53 MODULE_DESCRIPTION("The Linux Kernel VFS interface to PVFS2");
54 MODULE_PARM_DESC(module_parm_debug_mask, "debugging level (see pvfs2-debug.h for values)");
55 MODULE_PARM_DESC(op_timeout_secs, "Operation timeout in seconds");
56 MODULE_PARM_DESC(slot_timeout_secs, "Slot timeout in seconds");
57 MODULE_PARM_DESC(hash_table_size,
58 "size of hash table for operations in progress");
60 static struct file_system_type pvfs2_fs_type = {
63 .kill_sb = pvfs2_kill_sb,
67 module_param(hash_table_size, int, 0);
68 module_param(module_parm_debug_mask, ulong, 0644);
69 module_param(op_timeout_secs, int, 0);
70 module_param(slot_timeout_secs, int, 0);
72 /* synchronizes the request device file */
73 struct mutex devreq_mutex;
76 blocks non-priority requests from being queued for servicing. this
77 could be used for protecting the request list data structure, but
78 for now it's only being used to stall the op addition to the request
81 struct mutex request_mutex;
83 /* hash table for storing operations waiting for matching downcall */
84 struct list_head *htable_ops_in_progress;
85 DEFINE_SPINLOCK(htable_ops_in_progress_lock);
87 /* list for queueing upcall operations */
88 LIST_HEAD(pvfs2_request_list);
90 /* used to protect the above pvfs2_request_list */
91 DEFINE_SPINLOCK(pvfs2_request_list_lock);
93 /* used for incoming request notification */
94 DECLARE_WAIT_QUEUE_HEAD(pvfs2_request_list_waitq);
96 static int __init pvfs2_init(void)
101 /* convert input debug mask to a 64-bit unsigned integer */
102 gossip_debug_mask = (unsigned long long) module_parm_debug_mask;
105 * set the kernel's gossip debug string; invalid mask values will
108 debug_mask_to_string(&gossip_debug_mask, 0);
110 /* remove any invalid values from the mask */
111 debug_string_to_mask(kernel_debug_string, &gossip_debug_mask, 0);
114 * if the mask has a non-zero value, then indicate that the mask
115 * was set when the kernel module was loaded. The pvfs2 dev ioctl
116 * command will look at this boolean to determine if the kernel's
117 * debug mask should be overwritten when the client-core is started.
119 if (gossip_debug_mask != 0)
120 kernel_mask_set_mod_init = true;
122 /* print information message to the system log */
123 pr_info("pvfs2: pvfs2_init called with debug mask: :%s: :%llx:\n",
125 (unsigned long long)gossip_debug_mask);
127 ret = bdi_init(&pvfs2_backing_dev_info);
132 if (op_timeout_secs < 0)
135 if (slot_timeout_secs < 0)
136 slot_timeout_secs = 0;
138 /* initialize global book keeping data structures */
139 ret = op_cache_initialize();
143 ret = dev_req_cache_initialize();
147 ret = pvfs2_inode_cache_initialize();
151 ret = kiocb_cache_initialize();
155 /* Initialize the pvfsdev subsystem. */
156 ret = pvfs2_dev_init();
158 gossip_err("pvfs2: could not initialize device subsystem %d!\n",
163 mutex_init(&devreq_mutex);
164 mutex_init(&request_mutex);
166 htable_ops_in_progress =
167 kcalloc(hash_table_size, sizeof(struct list_head), GFP_KERNEL);
168 if (!htable_ops_in_progress) {
169 gossip_err("Failed to initialize op hashtable");
174 /* initialize a doubly linked at each hash table index */
175 for (i = 0; i < hash_table_size; i++)
176 INIT_LIST_HEAD(&htable_ops_in_progress[i]);
178 ret = fsid_key_table_initialize();
180 goto cleanup_progress_table;
183 * Build the contents of /sys/kernel/debug/orangefs/debug-help
184 * from the keywords in the kernel keyword/mask array.
186 * The keywords in the client keyword/mask array are
187 * unknown at boot time.
189 * orangefs_prepare_debugfs_help_string will be used again
190 * later to rebuild the debug-help file after the client starts
191 * and passes along the needed info. The argument signifies
192 * which time orangefs_prepare_debugfs_help_string is being
196 ret = orangefs_prepare_debugfs_help_string(1);
200 pvfs2_debugfs_init();
201 pvfs2_kernel_debug_init();
202 orangefs_sysfs_init();
204 ret = register_filesystem(&pvfs2_fs_type);
206 pr_info("pvfs2: module version %s loaded\n", PVFS2_VERSION);
210 pvfs2_debugfs_cleanup();
211 orangefs_sysfs_exit();
212 fsid_key_table_finalize();
214 cleanup_progress_table:
215 kfree(htable_ops_in_progress);
221 kiocb_cache_finalize();
224 pvfs2_inode_cache_finalize();
227 dev_req_cache_finalize();
233 bdi_destroy(&pvfs2_backing_dev_info);
239 static void __exit pvfs2_exit(void)
242 struct pvfs2_kernel_op_s *cur_op = NULL;
244 gossip_debug(GOSSIP_INIT_DEBUG, "pvfs2: pvfs2_exit called\n");
246 unregister_filesystem(&pvfs2_fs_type);
247 pvfs2_debugfs_cleanup();
248 orangefs_sysfs_exit();
249 fsid_key_table_finalize();
251 /* clear out all pending upcall op requests */
252 spin_lock(&pvfs2_request_list_lock);
253 while (!list_empty(&pvfs2_request_list)) {
254 cur_op = list_entry(pvfs2_request_list.next,
255 struct pvfs2_kernel_op_s,
257 list_del(&cur_op->list);
258 gossip_debug(GOSSIP_INIT_DEBUG,
259 "Freeing unhandled upcall request type %d\n",
260 cur_op->upcall.type);
263 spin_unlock(&pvfs2_request_list_lock);
265 for (i = 0; i < hash_table_size; i++)
266 while (!list_empty(&htable_ops_in_progress[i])) {
267 cur_op = list_entry(htable_ops_in_progress[i].next,
268 struct pvfs2_kernel_op_s,
273 kiocb_cache_finalize();
274 pvfs2_inode_cache_finalize();
275 dev_req_cache_finalize();
278 kfree(htable_ops_in_progress);
280 bdi_destroy(&pvfs2_backing_dev_info);
282 pr_info("pvfs2: module version %s unloaded\n", PVFS2_VERSION);
286 * What we do in this function is to walk the list of operations
287 * that are in progress in the hash table and mark them as purged as well.
289 void purge_inprogress_ops(void)
293 for (i = 0; i < hash_table_size; i++) {
294 struct pvfs2_kernel_op_s *op;
295 struct pvfs2_kernel_op_s *next;
297 list_for_each_entry_safe(op,
299 &htable_ops_in_progress[i],
301 spin_lock(&op->lock);
302 gossip_debug(GOSSIP_INIT_DEBUG,
303 "pvfs2-client-core: purging in-progress op tag "
306 get_opname_string(op));
307 set_op_state_purged(op);
308 spin_unlock(&op->lock);
309 wake_up_interruptible(&op->waitq);
314 module_init(pvfs2_init);
315 module_exit(pvfs2_exit);