blob: 1714a737d5563ba3fd6dbbd468837b9e9f66de7e [file] [log] [blame]
Mike Marshall274dcf52015-07-17 10:38:13 -04001/*
2 * What: /sys/kernel/debug/orangefs/debug-help
3 * Date: June 2015
4 * Contact: Mike Marshall <hubcap@omnibond.com>
5 * Description:
6 * List of client and kernel debug keywords.
7 *
8 *
9 * What: /sys/kernel/debug/orangefs/client-debug
10 * Date: June 2015
11 * Contact: Mike Marshall <hubcap@omnibond.com>
12 * Description:
13 * Debug setting for "the client", the userspace
14 * helper for the kernel module.
15 *
16 *
17 * What: /sys/kernel/debug/orangefs/kernel-debug
18 * Date: June 2015
19 * Contact: Mike Marshall <hubcap@omnibond.com>
20 * Description:
21 * Debug setting for the orangefs kernel module.
22 *
23 * Any of the keywords, or comma-separated lists
24 * of keywords, from debug-help can be catted to
25 * client-debug or kernel-debug.
26 *
27 * "none", "all" and "verbose" are special keywords
28 * for client-debug. Setting client-debug to "all"
29 * is kind of like trying to drink water from a
30 * fire hose, "verbose" triggers most of the same
31 * output except for the constant flow of output
32 * from the main wait loop.
33 *
34 * "none" and "all" are similar settings for kernel-debug
35 * no need for a "verbose".
36 */
37#include <linux/debugfs.h>
38#include <linux/slab.h>
39
40#include <linux/uaccess.h>
41
Mike Marshall575e9462015-12-04 12:56:14 -050042#include "orangefs-debugfs.h"
Mike Marshall274dcf52015-07-17 10:38:13 -040043#include "protocol.h"
Mike Marshall575e9462015-12-04 12:56:14 -050044#include "orangefs-kernel.h"
Mike Marshall274dcf52015-07-17 10:38:13 -040045
46static int orangefs_debug_disabled = 1;
47
48static int orangefs_debug_help_open(struct inode *, struct file *);
49
50const struct file_operations debug_help_fops = {
51 .open = orangefs_debug_help_open,
52 .read = seq_read,
53 .release = seq_release,
54 .llseek = seq_lseek,
55};
56
57static void *help_start(struct seq_file *, loff_t *);
58static void *help_next(struct seq_file *, void *, loff_t *);
59static void help_stop(struct seq_file *, void *);
60static int help_show(struct seq_file *, void *);
61
62static const struct seq_operations help_debug_ops = {
63 .start = help_start,
64 .next = help_next,
65 .stop = help_stop,
66 .show = help_show,
67};
68
69/*
70 * Used to protect data in ORANGEFS_KMOD_DEBUG_FILE and
71 * ORANGEFS_KMOD_DEBUG_FILE.
72 */
Mike Marshall84d02152015-07-28 13:27:51 -040073static DEFINE_MUTEX(orangefs_debug_lock);
Mike Marshall274dcf52015-07-17 10:38:13 -040074
75int orangefs_debug_open(struct inode *, struct file *);
76
77static ssize_t orangefs_debug_read(struct file *,
78 char __user *,
79 size_t,
80 loff_t *);
81
82static ssize_t orangefs_debug_write(struct file *,
83 const char __user *,
84 size_t,
85 loff_t *);
86
87static const struct file_operations kernel_debug_fops = {
88 .open = orangefs_debug_open,
89 .read = orangefs_debug_read,
90 .write = orangefs_debug_write,
91 .llseek = generic_file_llseek,
92};
93
94/*
95 * initialize kmod debug operations, create orangefs debugfs dir and
96 * ORANGEFS_KMOD_DEBUG_HELP_FILE.
97 */
Yi Liu8bb8aef2015-11-24 15:12:14 -050098int orangefs_debugfs_init(void)
Mike Marshall274dcf52015-07-17 10:38:13 -040099{
100
101 int rc = -ENOMEM;
102
103 debug_dir = debugfs_create_dir("orangefs", NULL);
Mike Marshall2180c522016-03-14 15:30:39 -0400104 if (!debug_dir) {
105 pr_info("%s: debugfs_create_dir failed.\n", __func__);
Mike Marshall274dcf52015-07-17 10:38:13 -0400106 goto out;
Mike Marshall2180c522016-03-14 15:30:39 -0400107 }
Mike Marshall274dcf52015-07-17 10:38:13 -0400108
109 help_file_dentry = debugfs_create_file(ORANGEFS_KMOD_DEBUG_HELP_FILE,
110 0444,
111 debug_dir,
112 debug_help_string,
113 &debug_help_fops);
Mike Marshall2180c522016-03-14 15:30:39 -0400114 if (!help_file_dentry) {
115 pr_info("%s: debugfs_create_file failed.\n", __func__);
Mike Marshall274dcf52015-07-17 10:38:13 -0400116 goto out;
Mike Marshall2180c522016-03-14 15:30:39 -0400117 }
Mike Marshall274dcf52015-07-17 10:38:13 -0400118
119 orangefs_debug_disabled = 0;
120 rc = 0;
121
122out:
Mike Marshall274dcf52015-07-17 10:38:13 -0400123
124 return rc;
125}
126
Yi Liu8bb8aef2015-11-24 15:12:14 -0500127void orangefs_debugfs_cleanup(void)
Mike Marshall274dcf52015-07-17 10:38:13 -0400128{
kbuild test robot2fa37fd2016-03-27 02:54:23 +0800129 debugfs_remove_recursive(debug_dir);
Mike Marshall274dcf52015-07-17 10:38:13 -0400130}
131
132/* open ORANGEFS_KMOD_DEBUG_HELP_FILE */
133static int orangefs_debug_help_open(struct inode *inode, struct file *file)
134{
135 int rc = -ENODEV;
136 int ret;
137
138 gossip_debug(GOSSIP_DEBUGFS_DEBUG,
139 "orangefs_debug_help_open: start\n");
140
141 if (orangefs_debug_disabled)
142 goto out;
143
144 ret = seq_open(file, &help_debug_ops);
145 if (ret)
146 goto out;
147
148 ((struct seq_file *)(file->private_data))->private = inode->i_private;
149
150 rc = 0;
151
152out:
153 gossip_debug(GOSSIP_DEBUGFS_DEBUG,
154 "orangefs_debug_help_open: rc:%d:\n",
155 rc);
156 return rc;
157}
158
159/*
160 * I think start always gets called again after stop. Start
161 * needs to return NULL when it is done. The whole "payload"
162 * in this case is a single (long) string, so by the second
163 * time we get to start (pos = 1), we're done.
164 */
165static void *help_start(struct seq_file *m, loff_t *pos)
166{
167 void *payload = NULL;
168
169 gossip_debug(GOSSIP_DEBUGFS_DEBUG, "help_start: start\n");
170
171 if (*pos == 0)
172 payload = m->private;
173
174 return payload;
175}
176
177static void *help_next(struct seq_file *m, void *v, loff_t *pos)
178{
179 gossip_debug(GOSSIP_DEBUGFS_DEBUG, "help_next: start\n");
180
181 return NULL;
182}
183
184static void help_stop(struct seq_file *m, void *p)
185{
186 gossip_debug(GOSSIP_DEBUGFS_DEBUG, "help_stop: start\n");
187}
188
189static int help_show(struct seq_file *m, void *v)
190{
191 gossip_debug(GOSSIP_DEBUGFS_DEBUG, "help_show: start\n");
192
193 seq_puts(m, v);
194
195 return 0;
196}
197
198/*
199 * initialize the kernel-debug file.
200 */
Yi Liu8bb8aef2015-11-24 15:12:14 -0500201int orangefs_kernel_debug_init(void)
Mike Marshall274dcf52015-07-17 10:38:13 -0400202{
Mike Marshall274dcf52015-07-17 10:38:13 -0400203 int rc = -ENOMEM;
204 struct dentry *ret;
205 char *k_buffer = NULL;
206
207 gossip_debug(GOSSIP_DEBUGFS_DEBUG, "%s: start\n", __func__);
208
Yi Liu8bb8aef2015-11-24 15:12:14 -0500209 k_buffer = kzalloc(ORANGEFS_MAX_DEBUG_STRING_LEN, GFP_KERNEL);
Mike Marshall274dcf52015-07-17 10:38:13 -0400210 if (!k_buffer)
211 goto out;
212
Yi Liu8bb8aef2015-11-24 15:12:14 -0500213 if (strlen(kernel_debug_string) + 1 < ORANGEFS_MAX_DEBUG_STRING_LEN) {
Mike Marshall274dcf52015-07-17 10:38:13 -0400214 strcpy(k_buffer, kernel_debug_string);
215 strcat(k_buffer, "\n");
216 } else {
217 strcpy(k_buffer, "none\n");
218 pr_info("%s: overflow 1!\n", __func__);
219 }
220
221 ret = debugfs_create_file(ORANGEFS_KMOD_DEBUG_FILE,
222 0444,
223 debug_dir,
224 k_buffer,
225 &kernel_debug_fops);
226 if (!ret) {
227 pr_info("%s: failed to create %s.\n",
228 __func__,
229 ORANGEFS_KMOD_DEBUG_FILE);
230 goto out;
231 }
232
233 rc = 0;
234
235out:
Mike Marshall274dcf52015-07-17 10:38:13 -0400236
237 gossip_debug(GOSSIP_DEBUGFS_DEBUG, "%s: rc:%d:\n", __func__, rc);
238 return rc;
239}
240
241/*
242 * initialize the client-debug file.
243 */
Yi Liu8bb8aef2015-11-24 15:12:14 -0500244int orangefs_client_debug_init(void)
Mike Marshall274dcf52015-07-17 10:38:13 -0400245{
246
247 int rc = -ENOMEM;
248 char *c_buffer = NULL;
249
250 gossip_debug(GOSSIP_DEBUGFS_DEBUG, "%s: start\n", __func__);
251
Yi Liu8bb8aef2015-11-24 15:12:14 -0500252 c_buffer = kzalloc(ORANGEFS_MAX_DEBUG_STRING_LEN, GFP_KERNEL);
Mike Marshall274dcf52015-07-17 10:38:13 -0400253 if (!c_buffer)
254 goto out;
255
Yi Liu8bb8aef2015-11-24 15:12:14 -0500256 if (strlen(client_debug_string) + 1 < ORANGEFS_MAX_DEBUG_STRING_LEN) {
Mike Marshall274dcf52015-07-17 10:38:13 -0400257 strcpy(c_buffer, client_debug_string);
258 strcat(c_buffer, "\n");
259 } else {
260 strcpy(c_buffer, "none\n");
261 pr_info("%s: overflow! 2\n", __func__);
262 }
263
264 client_debug_dentry = debugfs_create_file(ORANGEFS_CLIENT_DEBUG_FILE,
265 0444,
266 debug_dir,
267 c_buffer,
268 &kernel_debug_fops);
269 if (!client_debug_dentry) {
Mike Marshall2180c522016-03-14 15:30:39 -0400270 pr_info("%s: failed to create updated %s.\n",
Mike Marshall274dcf52015-07-17 10:38:13 -0400271 __func__,
272 ORANGEFS_CLIENT_DEBUG_FILE);
273 goto out;
274 }
275
276 rc = 0;
277
278out:
Mike Marshall274dcf52015-07-17 10:38:13 -0400279
280 gossip_debug(GOSSIP_DEBUGFS_DEBUG, "%s: rc:%d:\n", __func__, rc);
281 return rc;
282}
283
284/* open ORANGEFS_KMOD_DEBUG_FILE or ORANGEFS_CLIENT_DEBUG_FILE.*/
285int orangefs_debug_open(struct inode *inode, struct file *file)
286{
287 int rc = -ENODEV;
288
289 gossip_debug(GOSSIP_DEBUGFS_DEBUG,
290 "%s: orangefs_debug_disabled: %d\n",
291 __func__,
292 orangefs_debug_disabled);
293
294 if (orangefs_debug_disabled)
295 goto out;
296
297 rc = 0;
298 mutex_lock(&orangefs_debug_lock);
299 file->private_data = inode->i_private;
300 mutex_unlock(&orangefs_debug_lock);
301
302out:
303 gossip_debug(GOSSIP_DEBUGFS_DEBUG,
304 "orangefs_debug_open: rc: %d\n",
305 rc);
306 return rc;
307}
308
309static ssize_t orangefs_debug_read(struct file *file,
310 char __user *ubuf,
311 size_t count,
312 loff_t *ppos)
313{
314 char *buf;
315 int sprintf_ret;
316 ssize_t read_ret = -ENOMEM;
317
318 gossip_debug(GOSSIP_DEBUGFS_DEBUG, "orangefs_debug_read: start\n");
319
Yi Liu8bb8aef2015-11-24 15:12:14 -0500320 buf = kmalloc(ORANGEFS_MAX_DEBUG_STRING_LEN, GFP_KERNEL);
Mike Marshall274dcf52015-07-17 10:38:13 -0400321 if (!buf)
322 goto out;
323
324 mutex_lock(&orangefs_debug_lock);
325 sprintf_ret = sprintf(buf, "%s", (char *)file->private_data);
326 mutex_unlock(&orangefs_debug_lock);
327
328 read_ret = simple_read_from_buffer(ubuf, count, ppos, buf, sprintf_ret);
329
330 kfree(buf);
331
332out:
333 gossip_debug(GOSSIP_DEBUGFS_DEBUG,
334 "orangefs_debug_read: ret: %zu\n",
335 read_ret);
336
337 return read_ret;
338}
339
340static ssize_t orangefs_debug_write(struct file *file,
341 const char __user *ubuf,
342 size_t count,
343 loff_t *ppos)
344{
345 char *buf;
346 int rc = -EFAULT;
347 size_t silly = 0;
348 char *debug_string;
Yi Liu8bb8aef2015-11-24 15:12:14 -0500349 struct orangefs_kernel_op_s *new_op = NULL;
Mike Marshall274dcf52015-07-17 10:38:13 -0400350 struct client_debug_mask c_mask = { NULL, 0, 0 };
351
352 gossip_debug(GOSSIP_DEBUGFS_DEBUG,
353 "orangefs_debug_write: %s\n",
354 file->f_path.dentry->d_name.name);
355
356 /*
357 * Thwart users who try to jamb a ridiculous number
358 * of bytes into the debug file...
359 */
Yi Liu8bb8aef2015-11-24 15:12:14 -0500360 if (count > ORANGEFS_MAX_DEBUG_STRING_LEN + 1) {
Mike Marshall274dcf52015-07-17 10:38:13 -0400361 silly = count;
Yi Liu8bb8aef2015-11-24 15:12:14 -0500362 count = ORANGEFS_MAX_DEBUG_STRING_LEN + 1;
Mike Marshall274dcf52015-07-17 10:38:13 -0400363 }
364
Nicholas Mc Guiredde58ca2015-12-22 17:13:50 +0100365 buf = kzalloc(ORANGEFS_MAX_DEBUG_STRING_LEN, GFP_KERNEL);
Mike Marshall274dcf52015-07-17 10:38:13 -0400366 if (!buf)
367 goto out;
Mike Marshall274dcf52015-07-17 10:38:13 -0400368
369 if (copy_from_user(buf, ubuf, count - 1)) {
370 gossip_debug(GOSSIP_DEBUGFS_DEBUG,
371 "%s: copy_from_user failed!\n",
372 __func__);
373 goto out;
374 }
375
376 /*
377 * Map the keyword string from userspace into a valid debug mask.
378 * The mapping process involves mapping the human-inputted string
379 * into a valid mask, and then rebuilding the string from the
380 * verified valid mask.
381 *
382 * A service operation is required to set a new client-side
383 * debug mask.
384 */
385 if (!strcmp(file->f_path.dentry->d_name.name,
386 ORANGEFS_KMOD_DEBUG_FILE)) {
387 debug_string_to_mask(buf, &gossip_debug_mask, 0);
388 debug_mask_to_string(&gossip_debug_mask, 0);
389 debug_string = kernel_debug_string;
390 gossip_debug(GOSSIP_DEBUGFS_DEBUG,
391 "New kernel debug string is %s\n",
392 kernel_debug_string);
393 } else {
394 /* Can't reset client debug mask if client is not running. */
395 if (is_daemon_in_service()) {
396 pr_info("%s: Client not running :%d:\n",
397 __func__,
398 is_daemon_in_service());
399 goto out;
400 }
401
402 debug_string_to_mask(buf, &c_mask, 1);
403 debug_mask_to_string(&c_mask, 1);
404 debug_string = client_debug_string;
405
Yi Liu8bb8aef2015-11-24 15:12:14 -0500406 new_op = op_alloc(ORANGEFS_VFS_OP_PARAM);
Mike Marshall274dcf52015-07-17 10:38:13 -0400407 if (!new_op) {
408 pr_info("%s: op_alloc failed!\n", __func__);
409 goto out;
410 }
411
412 new_op->upcall.req.param.op =
Yi Liu8bb8aef2015-11-24 15:12:14 -0500413 ORANGEFS_PARAM_REQUEST_OP_TWO_MASK_VALUES;
414 new_op->upcall.req.param.type = ORANGEFS_PARAM_REQUEST_SET;
Mike Marshall274dcf52015-07-17 10:38:13 -0400415 memset(new_op->upcall.req.param.s_value,
416 0,
Yi Liu8bb8aef2015-11-24 15:12:14 -0500417 ORANGEFS_MAX_DEBUG_STRING_LEN);
Mike Marshall274dcf52015-07-17 10:38:13 -0400418 sprintf(new_op->upcall.req.param.s_value,
419 "%llx %llx\n",
420 c_mask.mask1,
421 c_mask.mask2);
422
423 /* service_operation returns 0 on success... */
424 rc = service_operation(new_op,
Yi Liu8bb8aef2015-11-24 15:12:14 -0500425 "orangefs_param",
426 ORANGEFS_OP_INTERRUPTIBLE);
Mike Marshall274dcf52015-07-17 10:38:13 -0400427
428 if (rc)
429 gossip_debug(GOSSIP_DEBUGFS_DEBUG,
430 "%s: service_operation failed! rc:%d:\n",
431 __func__,
432 rc);
433
434 op_release(new_op);
435 }
436
437 mutex_lock(&orangefs_debug_lock);
Yi Liu8bb8aef2015-11-24 15:12:14 -0500438 memset(file->f_inode->i_private, 0, ORANGEFS_MAX_DEBUG_STRING_LEN);
Mike Marshall274dcf52015-07-17 10:38:13 -0400439 sprintf((char *)file->f_inode->i_private, "%s\n", debug_string);
440 mutex_unlock(&orangefs_debug_lock);
441
442 *ppos += count;
443 if (silly)
444 rc = silly;
445 else
446 rc = count;
447
448out:
449 gossip_debug(GOSSIP_DEBUGFS_DEBUG,
450 "orangefs_debug_write: rc: %d\n",
451 rc);
452 kfree(buf);
453 return rc;
454}