blob: 9eb7972ae10d90c37ccd80369caa4f9d72669f6c [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);
104 if (!debug_dir)
105 goto out;
106
107 help_file_dentry = debugfs_create_file(ORANGEFS_KMOD_DEBUG_HELP_FILE,
108 0444,
109 debug_dir,
110 debug_help_string,
111 &debug_help_fops);
112 if (!help_file_dentry)
113 goto out;
114
115 orangefs_debug_disabled = 0;
116 rc = 0;
117
118out:
119 if (rc)
Yi Liu8bb8aef2015-11-24 15:12:14 -0500120 orangefs_debugfs_cleanup();
Mike Marshall274dcf52015-07-17 10:38:13 -0400121
122 return rc;
123}
124
Yi Liu8bb8aef2015-11-24 15:12:14 -0500125void orangefs_debugfs_cleanup(void)
Mike Marshall274dcf52015-07-17 10:38:13 -0400126{
127 debugfs_remove_recursive(debug_dir);
128}
129
130/* open ORANGEFS_KMOD_DEBUG_HELP_FILE */
131static int orangefs_debug_help_open(struct inode *inode, struct file *file)
132{
133 int rc = -ENODEV;
134 int ret;
135
136 gossip_debug(GOSSIP_DEBUGFS_DEBUG,
137 "orangefs_debug_help_open: start\n");
138
139 if (orangefs_debug_disabled)
140 goto out;
141
142 ret = seq_open(file, &help_debug_ops);
143 if (ret)
144 goto out;
145
146 ((struct seq_file *)(file->private_data))->private = inode->i_private;
147
148 rc = 0;
149
150out:
151 gossip_debug(GOSSIP_DEBUGFS_DEBUG,
152 "orangefs_debug_help_open: rc:%d:\n",
153 rc);
154 return rc;
155}
156
157/*
158 * I think start always gets called again after stop. Start
159 * needs to return NULL when it is done. The whole "payload"
160 * in this case is a single (long) string, so by the second
161 * time we get to start (pos = 1), we're done.
162 */
163static void *help_start(struct seq_file *m, loff_t *pos)
164{
165 void *payload = NULL;
166
167 gossip_debug(GOSSIP_DEBUGFS_DEBUG, "help_start: start\n");
168
169 if (*pos == 0)
170 payload = m->private;
171
172 return payload;
173}
174
175static void *help_next(struct seq_file *m, void *v, loff_t *pos)
176{
177 gossip_debug(GOSSIP_DEBUGFS_DEBUG, "help_next: start\n");
178
179 return NULL;
180}
181
182static void help_stop(struct seq_file *m, void *p)
183{
184 gossip_debug(GOSSIP_DEBUGFS_DEBUG, "help_stop: start\n");
185}
186
187static int help_show(struct seq_file *m, void *v)
188{
189 gossip_debug(GOSSIP_DEBUGFS_DEBUG, "help_show: start\n");
190
191 seq_puts(m, v);
192
193 return 0;
194}
195
196/*
197 * initialize the kernel-debug file.
198 */
Yi Liu8bb8aef2015-11-24 15:12:14 -0500199int orangefs_kernel_debug_init(void)
Mike Marshall274dcf52015-07-17 10:38:13 -0400200{
201
202 int rc = -ENOMEM;
203 struct dentry *ret;
204 char *k_buffer = NULL;
205
206 gossip_debug(GOSSIP_DEBUGFS_DEBUG, "%s: start\n", __func__);
207
Yi Liu8bb8aef2015-11-24 15:12:14 -0500208 k_buffer = kzalloc(ORANGEFS_MAX_DEBUG_STRING_LEN, GFP_KERNEL);
Mike Marshall274dcf52015-07-17 10:38:13 -0400209 if (!k_buffer)
210 goto out;
211
Yi Liu8bb8aef2015-11-24 15:12:14 -0500212 if (strlen(kernel_debug_string) + 1 < ORANGEFS_MAX_DEBUG_STRING_LEN) {
Mike Marshall274dcf52015-07-17 10:38:13 -0400213 strcpy(k_buffer, kernel_debug_string);
214 strcat(k_buffer, "\n");
215 } else {
216 strcpy(k_buffer, "none\n");
217 pr_info("%s: overflow 1!\n", __func__);
218 }
219
220 ret = debugfs_create_file(ORANGEFS_KMOD_DEBUG_FILE,
221 0444,
222 debug_dir,
223 k_buffer,
224 &kernel_debug_fops);
225 if (!ret) {
226 pr_info("%s: failed to create %s.\n",
227 __func__,
228 ORANGEFS_KMOD_DEBUG_FILE);
229 goto out;
230 }
231
232 rc = 0;
233
234out:
235 if (rc)
Yi Liu8bb8aef2015-11-24 15:12:14 -0500236 orangefs_debugfs_cleanup();
Mike Marshall274dcf52015-07-17 10:38:13 -0400237
238 gossip_debug(GOSSIP_DEBUGFS_DEBUG, "%s: rc:%d:\n", __func__, rc);
239 return rc;
240}
241
242/*
243 * initialize the client-debug file.
244 */
Yi Liu8bb8aef2015-11-24 15:12:14 -0500245int orangefs_client_debug_init(void)
Mike Marshall274dcf52015-07-17 10:38:13 -0400246{
247
248 int rc = -ENOMEM;
249 char *c_buffer = NULL;
250
251 gossip_debug(GOSSIP_DEBUGFS_DEBUG, "%s: start\n", __func__);
252
Yi Liu8bb8aef2015-11-24 15:12:14 -0500253 c_buffer = kzalloc(ORANGEFS_MAX_DEBUG_STRING_LEN, GFP_KERNEL);
Mike Marshall274dcf52015-07-17 10:38:13 -0400254 if (!c_buffer)
255 goto out;
256
Yi Liu8bb8aef2015-11-24 15:12:14 -0500257 if (strlen(client_debug_string) + 1 < ORANGEFS_MAX_DEBUG_STRING_LEN) {
Mike Marshall274dcf52015-07-17 10:38:13 -0400258 strcpy(c_buffer, client_debug_string);
259 strcat(c_buffer, "\n");
260 } else {
261 strcpy(c_buffer, "none\n");
262 pr_info("%s: overflow! 2\n", __func__);
263 }
264
265 client_debug_dentry = debugfs_create_file(ORANGEFS_CLIENT_DEBUG_FILE,
266 0444,
267 debug_dir,
268 c_buffer,
269 &kernel_debug_fops);
270 if (!client_debug_dentry) {
271 pr_info("%s: failed to create %s.\n",
272 __func__,
273 ORANGEFS_CLIENT_DEBUG_FILE);
274 goto out;
275 }
276
277 rc = 0;
278
279out:
280 if (rc)
Yi Liu8bb8aef2015-11-24 15:12:14 -0500281 orangefs_debugfs_cleanup();
Mike Marshall274dcf52015-07-17 10:38:13 -0400282
283 gossip_debug(GOSSIP_DEBUGFS_DEBUG, "%s: rc:%d:\n", __func__, rc);
284 return rc;
285}
286
287/* open ORANGEFS_KMOD_DEBUG_FILE or ORANGEFS_CLIENT_DEBUG_FILE.*/
288int orangefs_debug_open(struct inode *inode, struct file *file)
289{
290 int rc = -ENODEV;
291
292 gossip_debug(GOSSIP_DEBUGFS_DEBUG,
293 "%s: orangefs_debug_disabled: %d\n",
294 __func__,
295 orangefs_debug_disabled);
296
297 if (orangefs_debug_disabled)
298 goto out;
299
300 rc = 0;
301 mutex_lock(&orangefs_debug_lock);
302 file->private_data = inode->i_private;
303 mutex_unlock(&orangefs_debug_lock);
304
305out:
306 gossip_debug(GOSSIP_DEBUGFS_DEBUG,
307 "orangefs_debug_open: rc: %d\n",
308 rc);
309 return rc;
310}
311
312static ssize_t orangefs_debug_read(struct file *file,
313 char __user *ubuf,
314 size_t count,
315 loff_t *ppos)
316{
317 char *buf;
318 int sprintf_ret;
319 ssize_t read_ret = -ENOMEM;
320
321 gossip_debug(GOSSIP_DEBUGFS_DEBUG, "orangefs_debug_read: start\n");
322
Yi Liu8bb8aef2015-11-24 15:12:14 -0500323 buf = kmalloc(ORANGEFS_MAX_DEBUG_STRING_LEN, GFP_KERNEL);
Mike Marshall274dcf52015-07-17 10:38:13 -0400324 if (!buf)
325 goto out;
326
327 mutex_lock(&orangefs_debug_lock);
328 sprintf_ret = sprintf(buf, "%s", (char *)file->private_data);
329 mutex_unlock(&orangefs_debug_lock);
330
331 read_ret = simple_read_from_buffer(ubuf, count, ppos, buf, sprintf_ret);
332
333 kfree(buf);
334
335out:
336 gossip_debug(GOSSIP_DEBUGFS_DEBUG,
337 "orangefs_debug_read: ret: %zu\n",
338 read_ret);
339
340 return read_ret;
341}
342
343static ssize_t orangefs_debug_write(struct file *file,
344 const char __user *ubuf,
345 size_t count,
346 loff_t *ppos)
347{
348 char *buf;
349 int rc = -EFAULT;
350 size_t silly = 0;
351 char *debug_string;
Yi Liu8bb8aef2015-11-24 15:12:14 -0500352 struct orangefs_kernel_op_s *new_op = NULL;
Mike Marshall274dcf52015-07-17 10:38:13 -0400353 struct client_debug_mask c_mask = { NULL, 0, 0 };
354
355 gossip_debug(GOSSIP_DEBUGFS_DEBUG,
356 "orangefs_debug_write: %s\n",
357 file->f_path.dentry->d_name.name);
358
359 /*
360 * Thwart users who try to jamb a ridiculous number
361 * of bytes into the debug file...
362 */
Yi Liu8bb8aef2015-11-24 15:12:14 -0500363 if (count > ORANGEFS_MAX_DEBUG_STRING_LEN + 1) {
Mike Marshall274dcf52015-07-17 10:38:13 -0400364 silly = count;
Yi Liu8bb8aef2015-11-24 15:12:14 -0500365 count = ORANGEFS_MAX_DEBUG_STRING_LEN + 1;
Mike Marshall274dcf52015-07-17 10:38:13 -0400366 }
367
Nicholas Mc Guiredde58ca2015-12-22 17:13:50 +0100368 buf = kzalloc(ORANGEFS_MAX_DEBUG_STRING_LEN, GFP_KERNEL);
Mike Marshall274dcf52015-07-17 10:38:13 -0400369 if (!buf)
370 goto out;
Mike Marshall274dcf52015-07-17 10:38:13 -0400371
372 if (copy_from_user(buf, ubuf, count - 1)) {
373 gossip_debug(GOSSIP_DEBUGFS_DEBUG,
374 "%s: copy_from_user failed!\n",
375 __func__);
376 goto out;
377 }
378
379 /*
380 * Map the keyword string from userspace into a valid debug mask.
381 * The mapping process involves mapping the human-inputted string
382 * into a valid mask, and then rebuilding the string from the
383 * verified valid mask.
384 *
385 * A service operation is required to set a new client-side
386 * debug mask.
387 */
388 if (!strcmp(file->f_path.dentry->d_name.name,
389 ORANGEFS_KMOD_DEBUG_FILE)) {
390 debug_string_to_mask(buf, &gossip_debug_mask, 0);
391 debug_mask_to_string(&gossip_debug_mask, 0);
392 debug_string = kernel_debug_string;
393 gossip_debug(GOSSIP_DEBUGFS_DEBUG,
394 "New kernel debug string is %s\n",
395 kernel_debug_string);
396 } else {
397 /* Can't reset client debug mask if client is not running. */
398 if (is_daemon_in_service()) {
399 pr_info("%s: Client not running :%d:\n",
400 __func__,
401 is_daemon_in_service());
402 goto out;
403 }
404
405 debug_string_to_mask(buf, &c_mask, 1);
406 debug_mask_to_string(&c_mask, 1);
407 debug_string = client_debug_string;
408
Yi Liu8bb8aef2015-11-24 15:12:14 -0500409 new_op = op_alloc(ORANGEFS_VFS_OP_PARAM);
Mike Marshall274dcf52015-07-17 10:38:13 -0400410 if (!new_op) {
411 pr_info("%s: op_alloc failed!\n", __func__);
412 goto out;
413 }
414
415 new_op->upcall.req.param.op =
Yi Liu8bb8aef2015-11-24 15:12:14 -0500416 ORANGEFS_PARAM_REQUEST_OP_TWO_MASK_VALUES;
417 new_op->upcall.req.param.type = ORANGEFS_PARAM_REQUEST_SET;
Mike Marshall274dcf52015-07-17 10:38:13 -0400418 memset(new_op->upcall.req.param.s_value,
419 0,
Yi Liu8bb8aef2015-11-24 15:12:14 -0500420 ORANGEFS_MAX_DEBUG_STRING_LEN);
Mike Marshall274dcf52015-07-17 10:38:13 -0400421 sprintf(new_op->upcall.req.param.s_value,
422 "%llx %llx\n",
423 c_mask.mask1,
424 c_mask.mask2);
425
426 /* service_operation returns 0 on success... */
427 rc = service_operation(new_op,
Yi Liu8bb8aef2015-11-24 15:12:14 -0500428 "orangefs_param",
429 ORANGEFS_OP_INTERRUPTIBLE);
Mike Marshall274dcf52015-07-17 10:38:13 -0400430
431 if (rc)
432 gossip_debug(GOSSIP_DEBUGFS_DEBUG,
433 "%s: service_operation failed! rc:%d:\n",
434 __func__,
435 rc);
436
437 op_release(new_op);
438 }
439
440 mutex_lock(&orangefs_debug_lock);
Yi Liu8bb8aef2015-11-24 15:12:14 -0500441 memset(file->f_inode->i_private, 0, ORANGEFS_MAX_DEBUG_STRING_LEN);
Mike Marshall274dcf52015-07-17 10:38:13 -0400442 sprintf((char *)file->f_inode->i_private, "%s\n", debug_string);
443 mutex_unlock(&orangefs_debug_lock);
444
445 *ppos += count;
446 if (silly)
447 rc = silly;
448 else
449 rc = count;
450
451out:
452 gossip_debug(GOSSIP_DEBUGFS_DEBUG,
453 "orangefs_debug_write: rc: %d\n",
454 rc);
455 kfree(buf);
456 return rc;
457}