blob: d80537dadcd87737f09b013ed4031c6d5ae75783 [file] [log] [blame]
Mike Marshall274dcf52015-07-17 10:38:13 -04001/*
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 "pvfs2-kernel.h"
12#include "pvfs2-debugfs.h"
13#include "pvfs2-sysfs.h"
14
15/* PVFS2_VERSION is a ./configure define */
16#ifndef PVFS2_VERSION
17#define PVFS2_VERSION "Unknown"
18#endif
19
20/*
21 * global variables declared here
22 */
23
24/* array of client debug keyword/mask values */
25struct client_debug_mask *cdm_array;
26int cdm_element_count;
27
28char kernel_debug_string[PVFS2_MAX_DEBUG_STRING_LEN] = "none";
29char client_debug_string[PVFS2_MAX_DEBUG_STRING_LEN];
30char client_debug_array_string[PVFS2_MAX_DEBUG_STRING_LEN];
31
32char *debug_help_string;
33int help_string_initialized;
34struct dentry *help_file_dentry;
35struct dentry *client_debug_dentry;
36struct dentry *debug_dir;
37int client_verbose_index;
38int client_all_index;
39struct pvfs2_stats g_pvfs2_stats;
40
41/* the size of the hash tables for ops in progress */
42int hash_table_size = 509;
43
44static ulong module_parm_debug_mask;
45__u64 gossip_debug_mask;
46struct client_debug_mask client_debug_mask = { NULL, 0, 0 };
47unsigned int kernel_mask_set_mod_init; /* implicitly false */
48int op_timeout_secs = PVFS2_DEFAULT_OP_TIMEOUT_SECS;
49int slot_timeout_secs = PVFS2_DEFAULT_SLOT_TIMEOUT_SECS;
Mike Marshall274dcf52015-07-17 10:38:13 -040050
51MODULE_LICENSE("GPL");
52MODULE_AUTHOR("PVFS2 Development Team");
53MODULE_DESCRIPTION("The Linux Kernel VFS interface to PVFS2");
54MODULE_PARM_DESC(module_parm_debug_mask, "debugging level (see pvfs2-debug.h for values)");
55MODULE_PARM_DESC(op_timeout_secs, "Operation timeout in seconds");
56MODULE_PARM_DESC(slot_timeout_secs, "Slot timeout in seconds");
57MODULE_PARM_DESC(hash_table_size,
58 "size of hash table for operations in progress");
59
60static struct file_system_type pvfs2_fs_type = {
61 .name = "pvfs2",
62 .mount = pvfs2_mount,
63 .kill_sb = pvfs2_kill_sb,
64 .owner = THIS_MODULE,
65};
66
67module_param(hash_table_size, int, 0);
Sasha Levincb987f32015-08-03 00:08:59 -040068module_param(module_parm_debug_mask, ulong, 0644);
Mike Marshall274dcf52015-07-17 10:38:13 -040069module_param(op_timeout_secs, int, 0);
70module_param(slot_timeout_secs, int, 0);
71
72/* synchronizes the request device file */
73struct mutex devreq_mutex;
74
75/*
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
79 list
80*/
81struct mutex request_mutex;
82
83/* hash table for storing operations waiting for matching downcall */
84struct list_head *htable_ops_in_progress;
85DEFINE_SPINLOCK(htable_ops_in_progress_lock);
86
87/* list for queueing upcall operations */
88LIST_HEAD(pvfs2_request_list);
89
90/* used to protect the above pvfs2_request_list */
91DEFINE_SPINLOCK(pvfs2_request_list_lock);
92
93/* used for incoming request notification */
94DECLARE_WAIT_QUEUE_HEAD(pvfs2_request_list_waitq);
95
96static int __init pvfs2_init(void)
97{
98 int ret = -1;
99 __u32 i = 0;
100
101 /* convert input debug mask to a 64-bit unsigned integer */
102 gossip_debug_mask = (unsigned long long) module_parm_debug_mask;
103
104 /*
105 * set the kernel's gossip debug string; invalid mask values will
106 * be ignored.
107 */
108 debug_mask_to_string(&gossip_debug_mask, 0);
109
110 /* remove any invalid values from the mask */
111 debug_string_to_mask(kernel_debug_string, &gossip_debug_mask, 0);
112
113 /*
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.
118 */
119 if (gossip_debug_mask != 0)
120 kernel_mask_set_mod_init = true;
121
122 /* print information message to the system log */
123 pr_info("pvfs2: pvfs2_init called with debug mask: :%s: :%llx:\n",
124 kernel_debug_string,
125 (unsigned long long)gossip_debug_mask);
126
127 ret = bdi_init(&pvfs2_backing_dev_info);
128
129 if (ret)
130 return ret;
131
132 if (op_timeout_secs < 0)
133 op_timeout_secs = 0;
134
135 if (slot_timeout_secs < 0)
136 slot_timeout_secs = 0;
137
138 /* initialize global book keeping data structures */
139 ret = op_cache_initialize();
140 if (ret < 0)
141 goto err;
142
143 ret = dev_req_cache_initialize();
144 if (ret < 0)
145 goto cleanup_op;
146
147 ret = pvfs2_inode_cache_initialize();
148 if (ret < 0)
149 goto cleanup_req;
150
151 ret = kiocb_cache_initialize();
152 if (ret < 0)
153 goto cleanup_inode;
154
155 /* Initialize the pvfsdev subsystem. */
156 ret = pvfs2_dev_init();
157 if (ret < 0) {
158 gossip_err("pvfs2: could not initialize device subsystem %d!\n",
159 ret);
160 goto cleanup_kiocb;
161 }
162
163 mutex_init(&devreq_mutex);
164 mutex_init(&request_mutex);
165
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");
170 ret = -ENOMEM;
171 goto cleanup_device;
172 }
173
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]);
177
178 ret = fsid_key_table_initialize();
179 if (ret < 0)
180 goto cleanup_progress_table;
181
182 /*
183 * Build the contents of /sys/kernel/debug/orangefs/debug-help
184 * from the keywords in the kernel keyword/mask array.
185 *
186 * The keywords in the client keyword/mask array are
187 * unknown at boot time.
188 *
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
193 * called.
194 *
195 */
196 ret = orangefs_prepare_debugfs_help_string(1);
197 if (ret)
198 goto out;
199
200 pvfs2_debugfs_init();
201 pvfs2_kernel_debug_init();
202 orangefs_sysfs_init();
203
204 ret = register_filesystem(&pvfs2_fs_type);
205 if (ret == 0) {
206 pr_info("pvfs2: module version %s loaded\n", PVFS2_VERSION);
207 return 0;
208 }
209
210 pvfs2_debugfs_cleanup();
211 orangefs_sysfs_exit();
212 fsid_key_table_finalize();
213
214cleanup_progress_table:
215 kfree(htable_ops_in_progress);
216
217cleanup_device:
218 pvfs2_dev_cleanup();
219
220cleanup_kiocb:
221 kiocb_cache_finalize();
222
223cleanup_inode:
224 pvfs2_inode_cache_finalize();
225
226cleanup_req:
227 dev_req_cache_finalize();
228
229cleanup_op:
230 op_cache_finalize();
231
232err:
233 bdi_destroy(&pvfs2_backing_dev_info);
234
235out:
236 return ret;
237}
238
239static void __exit pvfs2_exit(void)
240{
241 int i = 0;
242 struct pvfs2_kernel_op_s *cur_op = NULL;
243
244 gossip_debug(GOSSIP_INIT_DEBUG, "pvfs2: pvfs2_exit called\n");
245
246 unregister_filesystem(&pvfs2_fs_type);
247 pvfs2_debugfs_cleanup();
248 orangefs_sysfs_exit();
249 fsid_key_table_finalize();
250 pvfs2_dev_cleanup();
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,
256 list);
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);
261 op_release(cur_op);
262 }
263 spin_unlock(&pvfs2_request_list_lock);
264
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,
269 list);
270 op_release(cur_op);
271 }
272
273 kiocb_cache_finalize();
274 pvfs2_inode_cache_finalize();
275 dev_req_cache_finalize();
276 op_cache_finalize();
277
278 kfree(htable_ops_in_progress);
279
280 bdi_destroy(&pvfs2_backing_dev_info);
281
282 pr_info("pvfs2: module version %s unloaded\n", PVFS2_VERSION);
283}
284
285/*
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.
288 */
289void purge_inprogress_ops(void)
290{
291 int i;
292
293 for (i = 0; i < hash_table_size; i++) {
294 struct pvfs2_kernel_op_s *op;
295 struct pvfs2_kernel_op_s *next;
296
297 list_for_each_entry_safe(op,
298 next,
299 &htable_ops_in_progress[i],
300 list) {
301 spin_lock(&op->lock);
302 gossip_debug(GOSSIP_INIT_DEBUG,
303 "pvfs2-client-core: purging in-progress op tag "
304 "%llu %s\n",
305 llu(op->tag),
306 get_opname_string(op));
307 set_op_state_purged(op);
308 spin_unlock(&op->lock);
309 wake_up_interruptible(&op->waitq);
310 }
311 }
312}
313
314module_init(pvfs2_init);
315module_exit(pvfs2_exit);