orangefs: Fix kmemleak in orangefs_sysfs_init()
[linux-block.git] / fs / orangefs / orangefs-debugfs.c
CommitLineData
b2441318 1// SPDX-License-Identifier: GPL-2.0
274dcf55
MM
2/*
3 * What: /sys/kernel/debug/orangefs/debug-help
4 * Date: June 2015
5 * Contact: Mike Marshall <hubcap@omnibond.com>
6 * Description:
7 * List of client and kernel debug keywords.
8 *
9 *
10 * What: /sys/kernel/debug/orangefs/client-debug
11 * Date: June 2015
12 * Contact: Mike Marshall <hubcap@omnibond.com>
13 * Description:
14 * Debug setting for "the client", the userspace
15 * helper for the kernel module.
16 *
17 *
18 * What: /sys/kernel/debug/orangefs/kernel-debug
19 * Date: June 2015
20 * Contact: Mike Marshall <hubcap@omnibond.com>
21 * Description:
22 * Debug setting for the orangefs kernel module.
23 *
24 * Any of the keywords, or comma-separated lists
25 * of keywords, from debug-help can be catted to
26 * client-debug or kernel-debug.
27 *
28 * "none", "all" and "verbose" are special keywords
29 * for client-debug. Setting client-debug to "all"
30 * is kind of like trying to drink water from a
31 * fire hose, "verbose" triggers most of the same
32 * output except for the constant flow of output
33 * from the main wait loop.
34 *
35 * "none" and "all" are similar settings for kernel-debug
36 * no need for a "verbose".
37 */
38#include <linux/debugfs.h>
39#include <linux/slab.h>
40
41#include <linux/uaccess.h>
42
575e9461 43#include "orangefs-debugfs.h"
274dcf55 44#include "protocol.h"
575e9461 45#include "orangefs-kernel.h"
274dcf55 46
44f46410
MB
47#define DEBUG_HELP_STRING_SIZE 4096
48#define HELP_STRING_UNINITIALIZED \
49 "Client Debug Keywords are unknown until the first time\n" \
50 "the client is started after boot.\n"
51#define ORANGEFS_KMOD_DEBUG_HELP_FILE "debug-help"
52#define ORANGEFS_KMOD_DEBUG_FILE "kernel-debug"
53#define ORANGEFS_CLIENT_DEBUG_FILE "client-debug"
54#define ORANGEFS_VERBOSE "verbose"
55#define ORANGEFS_ALL "all"
274dcf55 56
44f46410
MB
57/*
58 * An array of client_debug_mask will be built to hold debug keyword/mask
59 * values fetched from userspace.
60 */
61struct client_debug_mask {
62 char *keyword;
63 __u64 mask1;
64 __u64 mask2;
274dcf55
MM
65};
66
0979cf95 67static void orangefs_kernel_debug_init(void);
44f46410
MB
68
69static int orangefs_debug_help_open(struct inode *, struct file *);
274dcf55
MM
70static void *help_start(struct seq_file *, loff_t *);
71static void *help_next(struct seq_file *, void *, loff_t *);
72static void help_stop(struct seq_file *, void *);
73static int help_show(struct seq_file *, void *);
74
44f46410 75static int orangefs_debug_open(struct inode *, struct file *);
274dcf55
MM
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
44f46410
MB
87static int orangefs_prepare_cdm_array(char *);
88static void debug_mask_to_string(void *, int);
89static void do_k_string(void *, int);
90static void do_c_string(void *, int);
91static int keyword_is_amalgam(char *);
92static int check_amalgam_keyword(void *, int);
93static void debug_string_to_mask(char *, void *, int);
94static void do_c_mask(int, char *, struct client_debug_mask **);
95static void do_k_mask(int, char *, __u64 **);
96
97static char kernel_debug_string[ORANGEFS_MAX_DEBUG_STRING_LEN] = "none";
98static char *debug_help_string;
99static char client_debug_string[ORANGEFS_MAX_DEBUG_STRING_LEN];
100static char client_debug_array_string[ORANGEFS_MAX_DEBUG_STRING_LEN];
101
44f46410
MB
102static struct dentry *client_debug_dentry;
103static struct dentry *debug_dir;
104
105static unsigned int kernel_mask_set_mod_init;
106static int orangefs_debug_disabled = 1;
107static int help_string_initialized;
108
109static const struct seq_operations help_debug_ops = {
110 .start = help_start,
111 .next = help_next,
112 .stop = help_stop,
113 .show = help_show,
114};
115
3cf796af 116static const struct file_operations debug_help_fops = {
19ff7fcc 117 .owner = THIS_MODULE,
44f46410
MB
118 .open = orangefs_debug_help_open,
119 .read = seq_read,
120 .release = seq_release,
121 .llseek = seq_lseek,
122};
123
274dcf55 124static const struct file_operations kernel_debug_fops = {
19ff7fcc 125 .owner = THIS_MODULE,
274dcf55
MM
126 .open = orangefs_debug_open,
127 .read = orangefs_debug_read,
128 .write = orangefs_debug_write,
129 .llseek = generic_file_llseek,
130};
131
44f46410
MB
132static int client_all_index;
133static int client_verbose_index;
134
135static struct client_debug_mask *cdm_array;
136static int cdm_element_count;
137
138static struct client_debug_mask client_debug_mask;
139
140/*
141 * Used to protect data in ORANGEFS_KMOD_DEBUG_FILE and
142 * ORANGEFS_KMOD_DEBUG_FILE.
143 */
144static DEFINE_MUTEX(orangefs_debug_lock);
145
dc033621
MM
146/* Used to protect data in ORANGEFS_KMOD_DEBUG_HELP_FILE */
147static DEFINE_MUTEX(orangefs_help_file_lock);
148
274dcf55
MM
149/*
150 * initialize kmod debug operations, create orangefs debugfs dir and
151 * ORANGEFS_KMOD_DEBUG_HELP_FILE.
152 */
0979cf95 153void orangefs_debugfs_init(int debug_mask)
274dcf55 154{
44f46410
MB
155 /* convert input debug mask to a 64-bit unsigned integer */
156 orangefs_gossip_debug_mask = (unsigned long long)debug_mask;
157
158 /*
159 * set the kernel's gossip debug string; invalid mask values will
160 * be ignored.
161 */
162 debug_mask_to_string(&orangefs_gossip_debug_mask, 0);
163
164 /* remove any invalid values from the mask */
165 debug_string_to_mask(kernel_debug_string, &orangefs_gossip_debug_mask,
166 0);
167
168 /*
169 * if the mask has a non-zero value, then indicate that the mask
170 * was set when the kernel module was loaded. The orangefs dev ioctl
171 * command will look at this boolean to determine if the kernel's
172 * debug mask should be overwritten when the client-core is started.
173 */
174 if (orangefs_gossip_debug_mask != 0)
175 kernel_mask_set_mod_init = true;
176
177 pr_info("%s: called with debug mask: :%s: :%llx:\n",
178 __func__,
179 kernel_debug_string,
180 (unsigned long long)orangefs_gossip_debug_mask);
181
274dcf55 182 debug_dir = debugfs_create_dir("orangefs", NULL);
274dcf55 183
f095adba
GKH
184 debugfs_create_file(ORANGEFS_KMOD_DEBUG_HELP_FILE, 0444, debug_dir,
185 debug_help_string, &debug_help_fops);
274dcf55
MM
186
187 orangefs_debug_disabled = 0;
44f46410 188
0979cf95 189 orangefs_kernel_debug_init();
44f46410
MB
190}
191
192/*
193 * initialize the kernel-debug file.
194 */
0979cf95 195static void orangefs_kernel_debug_init(void)
44f46410
MB
196{
197 int rc = -ENOMEM;
44f46410
MB
198 char *k_buffer = NULL;
199
200 gossip_debug(GOSSIP_DEBUGFS_DEBUG, "%s: start\n", __func__);
201
202 k_buffer = kzalloc(ORANGEFS_MAX_DEBUG_STRING_LEN, GFP_KERNEL);
203 if (!k_buffer)
204 goto out;
205
206 if (strlen(kernel_debug_string) + 1 < ORANGEFS_MAX_DEBUG_STRING_LEN) {
207 strcpy(k_buffer, kernel_debug_string);
208 strcat(k_buffer, "\n");
209 } else {
210 strcpy(k_buffer, "none\n");
211 pr_info("%s: overflow 1!\n", __func__);
212 }
213
f095adba
GKH
214 debugfs_create_file(ORANGEFS_KMOD_DEBUG_FILE, 0444, debug_dir, k_buffer,
215 &kernel_debug_fops);
44f46410 216
274dcf55 217out:
44f46410 218 gossip_debug(GOSSIP_DEBUGFS_DEBUG, "%s: rc:%d:\n", __func__, rc);
274dcf55
MM
219}
220
44f46410 221
8bb8aefd 222void orangefs_debugfs_cleanup(void)
274dcf55 223{
2fa37fd7 224 debugfs_remove_recursive(debug_dir);
d23417a5
ZX
225 kfree(debug_help_string);
226 debug_help_string = NULL;
274dcf55
MM
227}
228
229/* open ORANGEFS_KMOD_DEBUG_HELP_FILE */
230static int orangefs_debug_help_open(struct inode *inode, struct file *file)
231{
232 int rc = -ENODEV;
233 int ret;
234
235 gossip_debug(GOSSIP_DEBUGFS_DEBUG,
236 "orangefs_debug_help_open: start\n");
237
238 if (orangefs_debug_disabled)
239 goto out;
240
241 ret = seq_open(file, &help_debug_ops);
242 if (ret)
243 goto out;
244
245 ((struct seq_file *)(file->private_data))->private = inode->i_private;
246
247 rc = 0;
248
249out:
250 gossip_debug(GOSSIP_DEBUGFS_DEBUG,
251 "orangefs_debug_help_open: rc:%d:\n",
252 rc);
253 return rc;
254}
255
256/*
257 * I think start always gets called again after stop. Start
258 * needs to return NULL when it is done. The whole "payload"
259 * in this case is a single (long) string, so by the second
260 * time we get to start (pos = 1), we're done.
261 */
262static void *help_start(struct seq_file *m, loff_t *pos)
263{
264 void *payload = NULL;
265
266 gossip_debug(GOSSIP_DEBUGFS_DEBUG, "help_start: start\n");
267
dc033621
MM
268 mutex_lock(&orangefs_help_file_lock);
269
274dcf55
MM
270 if (*pos == 0)
271 payload = m->private;
272
273 return payload;
274}
275
276static void *help_next(struct seq_file *m, void *v, loff_t *pos)
277{
9f198a2a 278 (*pos)++;
274dcf55
MM
279 gossip_debug(GOSSIP_DEBUGFS_DEBUG, "help_next: start\n");
280
281 return NULL;
282}
283
284static void help_stop(struct seq_file *m, void *p)
285{
286 gossip_debug(GOSSIP_DEBUGFS_DEBUG, "help_stop: start\n");
dc033621 287 mutex_unlock(&orangefs_help_file_lock);
274dcf55
MM
288}
289
290static int help_show(struct seq_file *m, void *v)
291{
292 gossip_debug(GOSSIP_DEBUGFS_DEBUG, "help_show: start\n");
293
294 seq_puts(m, v);
295
296 return 0;
297}
298
274dcf55
MM
299/*
300 * initialize the client-debug file.
301 */
7a3bc1f0 302static int orangefs_client_debug_init(void)
274dcf55
MM
303{
304
305 int rc = -ENOMEM;
306 char *c_buffer = NULL;
307
308 gossip_debug(GOSSIP_DEBUGFS_DEBUG, "%s: start\n", __func__);
309
8bb8aefd 310 c_buffer = kzalloc(ORANGEFS_MAX_DEBUG_STRING_LEN, GFP_KERNEL);
274dcf55
MM
311 if (!c_buffer)
312 goto out;
313
8bb8aefd 314 if (strlen(client_debug_string) + 1 < ORANGEFS_MAX_DEBUG_STRING_LEN) {
274dcf55
MM
315 strcpy(c_buffer, client_debug_string);
316 strcat(c_buffer, "\n");
317 } else {
318 strcpy(c_buffer, "none\n");
319 pr_info("%s: overflow! 2\n", __func__);
320 }
321
322 client_debug_dentry = debugfs_create_file(ORANGEFS_CLIENT_DEBUG_FILE,
323 0444,
324 debug_dir,
325 c_buffer,
326 &kernel_debug_fops);
274dcf55
MM
327
328 rc = 0;
329
330out:
274dcf55
MM
331
332 gossip_debug(GOSSIP_DEBUGFS_DEBUG, "%s: rc:%d:\n", __func__, rc);
333 return rc;
334}
335
336/* open ORANGEFS_KMOD_DEBUG_FILE or ORANGEFS_CLIENT_DEBUG_FILE.*/
44f46410 337static int orangefs_debug_open(struct inode *inode, struct file *file)
274dcf55
MM
338{
339 int rc = -ENODEV;
340
341 gossip_debug(GOSSIP_DEBUGFS_DEBUG,
342 "%s: orangefs_debug_disabled: %d\n",
343 __func__,
344 orangefs_debug_disabled);
345
346 if (orangefs_debug_disabled)
347 goto out;
348
349 rc = 0;
350 mutex_lock(&orangefs_debug_lock);
351 file->private_data = inode->i_private;
352 mutex_unlock(&orangefs_debug_lock);
353
354out:
355 gossip_debug(GOSSIP_DEBUGFS_DEBUG,
356 "orangefs_debug_open: rc: %d\n",
357 rc);
358 return rc;
359}
360
361static ssize_t orangefs_debug_read(struct file *file,
362 char __user *ubuf,
363 size_t count,
364 loff_t *ppos)
365{
366 char *buf;
367 int sprintf_ret;
368 ssize_t read_ret = -ENOMEM;
369
370 gossip_debug(GOSSIP_DEBUGFS_DEBUG, "orangefs_debug_read: start\n");
371
8bb8aefd 372 buf = kmalloc(ORANGEFS_MAX_DEBUG_STRING_LEN, GFP_KERNEL);
274dcf55
MM
373 if (!buf)
374 goto out;
375
376 mutex_lock(&orangefs_debug_lock);
377 sprintf_ret = sprintf(buf, "%s", (char *)file->private_data);
378 mutex_unlock(&orangefs_debug_lock);
379
380 read_ret = simple_read_from_buffer(ubuf, count, ppos, buf, sprintf_ret);
381
382 kfree(buf);
383
384out:
385 gossip_debug(GOSSIP_DEBUGFS_DEBUG,
386 "orangefs_debug_read: ret: %zu\n",
387 read_ret);
388
389 return read_ret;
390}
391
392static ssize_t orangefs_debug_write(struct file *file,
393 const char __user *ubuf,
394 size_t count,
395 loff_t *ppos)
396{
397 char *buf;
398 int rc = -EFAULT;
399 size_t silly = 0;
400 char *debug_string;
8bb8aefd 401 struct orangefs_kernel_op_s *new_op = NULL;
274dcf55 402 struct client_debug_mask c_mask = { NULL, 0, 0 };
45063097 403 char *s;
274dcf55
MM
404
405 gossip_debug(GOSSIP_DEBUGFS_DEBUG,
f66debf1
AV
406 "orangefs_debug_write: %pD\n",
407 file);
274dcf55 408
907bfcd8
DC
409 if (count == 0)
410 return 0;
411
274dcf55
MM
412 /*
413 * Thwart users who try to jamb a ridiculous number
414 * of bytes into the debug file...
415 */
8bb8aefd 416 if (count > ORANGEFS_MAX_DEBUG_STRING_LEN + 1) {
274dcf55 417 silly = count;
8bb8aefd 418 count = ORANGEFS_MAX_DEBUG_STRING_LEN + 1;
274dcf55
MM
419 }
420
dde58ca4 421 buf = kzalloc(ORANGEFS_MAX_DEBUG_STRING_LEN, GFP_KERNEL);
274dcf55
MM
422 if (!buf)
423 goto out;
274dcf55
MM
424
425 if (copy_from_user(buf, ubuf, count - 1)) {
426 gossip_debug(GOSSIP_DEBUGFS_DEBUG,
427 "%s: copy_from_user failed!\n",
428 __func__);
429 goto out;
430 }
431
432 /*
433 * Map the keyword string from userspace into a valid debug mask.
434 * The mapping process involves mapping the human-inputted string
435 * into a valid mask, and then rebuilding the string from the
436 * verified valid mask.
437 *
438 * A service operation is required to set a new client-side
439 * debug mask.
440 */
441 if (!strcmp(file->f_path.dentry->d_name.name,
442 ORANGEFS_KMOD_DEBUG_FILE)) {
44f46410
MB
443 debug_string_to_mask(buf, &orangefs_gossip_debug_mask, 0);
444 debug_mask_to_string(&orangefs_gossip_debug_mask, 0);
274dcf55
MM
445 debug_string = kernel_debug_string;
446 gossip_debug(GOSSIP_DEBUGFS_DEBUG,
447 "New kernel debug string is %s\n",
448 kernel_debug_string);
449 } else {
450 /* Can't reset client debug mask if client is not running. */
451 if (is_daemon_in_service()) {
452 pr_info("%s: Client not running :%d:\n",
453 __func__,
454 is_daemon_in_service());
455 goto out;
456 }
457
458 debug_string_to_mask(buf, &c_mask, 1);
459 debug_mask_to_string(&c_mask, 1);
460 debug_string = client_debug_string;
461
8bb8aefd 462 new_op = op_alloc(ORANGEFS_VFS_OP_PARAM);
274dcf55
MM
463 if (!new_op) {
464 pr_info("%s: op_alloc failed!\n", __func__);
465 goto out;
466 }
467
468 new_op->upcall.req.param.op =
8bb8aefd
YL
469 ORANGEFS_PARAM_REQUEST_OP_TWO_MASK_VALUES;
470 new_op->upcall.req.param.type = ORANGEFS_PARAM_REQUEST_SET;
274dcf55
MM
471 memset(new_op->upcall.req.param.s_value,
472 0,
8bb8aefd 473 ORANGEFS_MAX_DEBUG_STRING_LEN);
274dcf55
MM
474 sprintf(new_op->upcall.req.param.s_value,
475 "%llx %llx\n",
476 c_mask.mask1,
477 c_mask.mask2);
478
479 /* service_operation returns 0 on success... */
480 rc = service_operation(new_op,
8bb8aefd
YL
481 "orangefs_param",
482 ORANGEFS_OP_INTERRUPTIBLE);
274dcf55
MM
483
484 if (rc)
485 gossip_debug(GOSSIP_DEBUGFS_DEBUG,
486 "%s: service_operation failed! rc:%d:\n",
487 __func__,
488 rc);
489
490 op_release(new_op);
491 }
492
493 mutex_lock(&orangefs_debug_lock);
45063097
AV
494 s = file_inode(file)->i_private;
495 memset(s, 0, ORANGEFS_MAX_DEBUG_STRING_LEN);
496 sprintf(s, "%s\n", debug_string);
274dcf55
MM
497 mutex_unlock(&orangefs_debug_lock);
498
499 *ppos += count;
500 if (silly)
501 rc = silly;
502 else
503 rc = count;
504
505out:
506 gossip_debug(GOSSIP_DEBUGFS_DEBUG,
507 "orangefs_debug_write: rc: %d\n",
508 rc);
509 kfree(buf);
510 return rc;
511}
44f46410
MB
512
513/*
514 * After obtaining a string representation of the client's debug
515 * keywords and their associated masks, this function is called to build an
516 * array of these values.
517 */
518static int orangefs_prepare_cdm_array(char *debug_array_string)
519{
520 int i;
521 int rc = -EINVAL;
522 char *cds_head = NULL;
523 char *cds_delimiter = NULL;
524 int keyword_len = 0;
525
526 gossip_debug(GOSSIP_UTILS_DEBUG, "%s: start\n", __func__);
527
528 /*
529 * figure out how many elements the cdm_array needs.
530 */
531 for (i = 0; i < strlen(debug_array_string); i++)
532 if (debug_array_string[i] == '\n')
533 cdm_element_count++;
534
535 if (!cdm_element_count) {
536 pr_info("No elements in client debug array string!\n");
537 goto out;
538 }
539
5e273a0e 540 cdm_array = kcalloc(cdm_element_count, sizeof(*cdm_array), GFP_KERNEL);
44f46410 541 if (!cdm_array) {
44f46410
MB
542 rc = -ENOMEM;
543 goto out;
544 }
545
546 cds_head = debug_array_string;
547
548 for (i = 0; i < cdm_element_count; i++) {
549 cds_delimiter = strchr(cds_head, '\n');
550 *cds_delimiter = '\0';
551
552 keyword_len = strcspn(cds_head, " ");
553
554 cdm_array[i].keyword = kzalloc(keyword_len + 1, GFP_KERNEL);
555 if (!cdm_array[i].keyword) {
556 rc = -ENOMEM;
557 goto out;
558 }
559
560 sscanf(cds_head,
561 "%s %llx %llx",
562 cdm_array[i].keyword,
563 (unsigned long long *)&(cdm_array[i].mask1),
564 (unsigned long long *)&(cdm_array[i].mask2));
565
566 if (!strcmp(cdm_array[i].keyword, ORANGEFS_VERBOSE))
567 client_verbose_index = i;
568
569 if (!strcmp(cdm_array[i].keyword, ORANGEFS_ALL))
570 client_all_index = i;
571
572 cds_head = cds_delimiter + 1;
573 }
574
575 rc = cdm_element_count;
576
577 gossip_debug(GOSSIP_UTILS_DEBUG, "%s: rc:%d:\n", __func__, rc);
578
579out:
580
581 return rc;
582
583}
584
585/*
586 * /sys/kernel/debug/orangefs/debug-help can be catted to
587 * see all the available kernel and client debug keywords.
588 *
dc033621 589 * When orangefs.ko initializes, we have no idea what keywords the
44f46410
MB
590 * client supports, nor their associated masks.
591 *
dc033621 592 * We pass through this function once at module-load and stamp a
44f46410
MB
593 * boilerplate "we don't know" message for the client in the
594 * debug-help file. We pass through here again when the client
595 * starts and then we can fill out the debug-help file fully.
596 *
597 * The client might be restarted any number of times between
dc033621 598 * module reloads, we only build the debug-help file the first time.
44f46410
MB
599 */
600int orangefs_prepare_debugfs_help_string(int at_boot)
601{
44f46410
MB
602 char *client_title = "Client Debug Keywords:\n";
603 char *kernel_title = "Kernel Debug Keywords:\n";
dc033621
MM
604 size_t string_size = DEBUG_HELP_STRING_SIZE;
605 size_t result_size;
606 size_t i;
607 char *new;
608 int rc = -EINVAL;
44f46410
MB
609
610 gossip_debug(GOSSIP_UTILS_DEBUG, "%s: start\n", __func__);
611
dc033621 612 if (at_boot)
44f46410 613 client_title = HELP_STRING_UNINITIALIZED;
dc033621
MM
614
615 /* build a new debug_help_string. */
616 new = kzalloc(DEBUG_HELP_STRING_SIZE, GFP_KERNEL);
617 if (!new) {
618 rc = -ENOMEM;
619 goto out;
620 }
621
622 /*
623 * strlcat(dst, src, size) will append at most
624 * "size - strlen(dst) - 1" bytes of src onto dst,
625 * null terminating the result, and return the total
626 * length of the string it tried to create.
627 *
628 * We'll just plow through here building our new debug
629 * help string and let strlcat take care of assuring that
630 * dst doesn't overflow.
631 */
632 strlcat(new, client_title, string_size);
633
634 if (!at_boot) {
635
636 /*
44f46410
MB
637 * fill the client keyword/mask array and remember
638 * how many elements there were.
639 */
640 cdm_element_count =
641 orangefs_prepare_cdm_array(client_debug_array_string);
4defb5f9
CIK
642 if (cdm_element_count <= 0) {
643 kfree(new);
44f46410 644 goto out;
4defb5f9 645 }
44f46410 646
44f46410 647 for (i = 0; i < cdm_element_count; i++) {
dc033621
MM
648 strlcat(new, "\t", string_size);
649 strlcat(new, cdm_array[i].keyword, string_size);
650 strlcat(new, "\n", string_size);
44f46410 651 }
44f46410
MB
652 }
653
dc033621
MM
654 strlcat(new, "\n", string_size);
655 strlcat(new, kernel_title, string_size);
656
44f46410 657 for (i = 0; i < num_kmod_keyword_mask_map; i++) {
dc033621
MM
658 strlcat(new, "\t", string_size);
659 strlcat(new, s_kmod_keyword_mask_map[i].keyword, string_size);
660 result_size = strlcat(new, "\n", string_size);
44f46410
MB
661 }
662
dc033621
MM
663 /* See if we tried to put too many bytes into "new"... */
664 if (result_size >= string_size) {
665 kfree(new);
44f46410
MB
666 goto out;
667 }
668
dc033621
MM
669 if (at_boot) {
670 debug_help_string = new;
671 } else {
672 mutex_lock(&orangefs_help_file_lock);
673 memset(debug_help_string, 0, DEBUG_HELP_STRING_SIZE);
674 strlcat(debug_help_string, new, string_size);
675 mutex_unlock(&orangefs_help_file_lock);
d23417a5 676 kfree(new);
44f46410
MB
677 }
678
679 rc = 0;
680
dc033621 681out: return rc;
44f46410
MB
682
683}
684
685/*
686 * kernel = type 0
687 * client = type 1
688 */
689static void debug_mask_to_string(void *mask, int type)
690{
691 int i;
692 int len = 0;
693 char *debug_string;
694 int element_count = 0;
695
696 gossip_debug(GOSSIP_UTILS_DEBUG, "%s: start\n", __func__);
697
698 if (type) {
699 debug_string = client_debug_string;
700 element_count = cdm_element_count;
701 } else {
702 debug_string = kernel_debug_string;
703 element_count = num_kmod_keyword_mask_map;
704 }
705
706 memset(debug_string, 0, ORANGEFS_MAX_DEBUG_STRING_LEN);
707
708 /*
709 * Some keywords, like "all" or "verbose", are amalgams of
710 * numerous other keywords. Make a special check for those
711 * before grinding through the whole mask only to find out
712 * later...
713 */
714 if (check_amalgam_keyword(mask, type))
715 goto out;
716
717 /* Build the debug string. */
718 for (i = 0; i < element_count; i++)
719 if (type)
720 do_c_string(mask, i);
721 else
722 do_k_string(mask, i);
723
724 len = strlen(debug_string);
725
726 if ((len) && (type))
727 client_debug_string[len - 1] = '\0';
728 else if (len)
729 kernel_debug_string[len - 1] = '\0';
730 else if (type)
731 strcpy(client_debug_string, "none");
732 else
733 strcpy(kernel_debug_string, "none");
734
735out:
736gossip_debug(GOSSIP_UTILS_DEBUG, "%s: string:%s:\n", __func__, debug_string);
737
738 return;
739
740}
741
742static void do_k_string(void *k_mask, int index)
743{
744 __u64 *mask = (__u64 *) k_mask;
745
746 if (keyword_is_amalgam((char *) s_kmod_keyword_mask_map[index].keyword))
747 goto out;
748
749 if (*mask & s_kmod_keyword_mask_map[index].mask_val) {
750 if ((strlen(kernel_debug_string) +
751 strlen(s_kmod_keyword_mask_map[index].keyword))
752 < ORANGEFS_MAX_DEBUG_STRING_LEN - 1) {
753 strcat(kernel_debug_string,
754 s_kmod_keyword_mask_map[index].keyword);
755 strcat(kernel_debug_string, ",");
756 } else {
757 gossip_err("%s: overflow!\n", __func__);
758 strcpy(kernel_debug_string, ORANGEFS_ALL);
759 goto out;
760 }
761 }
762
763out:
764
765 return;
766}
767
768static void do_c_string(void *c_mask, int index)
769{
770 struct client_debug_mask *mask = (struct client_debug_mask *) c_mask;
771
772 if (keyword_is_amalgam(cdm_array[index].keyword))
773 goto out;
774
775 if ((mask->mask1 & cdm_array[index].mask1) ||
776 (mask->mask2 & cdm_array[index].mask2)) {
777 if ((strlen(client_debug_string) +
778 strlen(cdm_array[index].keyword) + 1)
779 < ORANGEFS_MAX_DEBUG_STRING_LEN - 2) {
780 strcat(client_debug_string,
781 cdm_array[index].keyword);
782 strcat(client_debug_string, ",");
783 } else {
784 gossip_err("%s: overflow!\n", __func__);
785 strcpy(client_debug_string, ORANGEFS_ALL);
786 goto out;
787 }
788 }
789out:
790 return;
791}
792
793static int keyword_is_amalgam(char *keyword)
794{
795 int rc = 0;
796
797 if ((!strcmp(keyword, ORANGEFS_ALL)) || (!strcmp(keyword, ORANGEFS_VERBOSE)))
798 rc = 1;
799
800 return rc;
801}
802
803/*
804 * kernel = type 0
805 * client = type 1
806 *
807 * return 1 if we found an amalgam.
808 */
809static int check_amalgam_keyword(void *mask, int type)
810{
811 __u64 *k_mask;
812 struct client_debug_mask *c_mask;
813 int k_all_index = num_kmod_keyword_mask_map - 1;
814 int rc = 0;
815
816 if (type) {
817 c_mask = (struct client_debug_mask *) mask;
818
819 if ((c_mask->mask1 == cdm_array[client_all_index].mask1) &&
820 (c_mask->mask2 == cdm_array[client_all_index].mask2)) {
821 strcpy(client_debug_string, ORANGEFS_ALL);
822 rc = 1;
823 goto out;
824 }
825
826 if ((c_mask->mask1 == cdm_array[client_verbose_index].mask1) &&
827 (c_mask->mask2 == cdm_array[client_verbose_index].mask2)) {
828 strcpy(client_debug_string, ORANGEFS_VERBOSE);
829 rc = 1;
830 goto out;
831 }
832
833 } else {
834 k_mask = (__u64 *) mask;
835
836 if (*k_mask >= s_kmod_keyword_mask_map[k_all_index].mask_val) {
837 strcpy(kernel_debug_string, ORANGEFS_ALL);
838 rc = 1;
839 goto out;
840 }
841 }
842
843out:
844
845 return rc;
846}
847
848/*
849 * kernel = type 0
850 * client = type 1
851 */
852static void debug_string_to_mask(char *debug_string, void *mask, int type)
853{
854 char *unchecked_keyword;
855 int i;
856 char *strsep_fodder = kstrdup(debug_string, GFP_KERNEL);
857 char *original_pointer;
858 int element_count = 0;
859 struct client_debug_mask *c_mask = NULL;
860 __u64 *k_mask = NULL;
861
862 gossip_debug(GOSSIP_UTILS_DEBUG, "%s: start\n", __func__);
863
864 if (type) {
865 c_mask = (struct client_debug_mask *)mask;
866 element_count = cdm_element_count;
867 } else {
868 k_mask = (__u64 *)mask;
869 *k_mask = 0;
870 element_count = num_kmod_keyword_mask_map;
871 }
872
873 original_pointer = strsep_fodder;
874 while ((unchecked_keyword = strsep(&strsep_fodder, ",")))
875 if (strlen(unchecked_keyword)) {
876 for (i = 0; i < element_count; i++)
877 if (type)
878 do_c_mask(i,
879 unchecked_keyword,
880 &c_mask);
881 else
882 do_k_mask(i,
883 unchecked_keyword,
884 &k_mask);
885 }
886
887 kfree(original_pointer);
888}
889
890static void do_c_mask(int i, char *unchecked_keyword,
891 struct client_debug_mask **sane_mask)
892{
893
894 if (!strcmp(cdm_array[i].keyword, unchecked_keyword)) {
895 (**sane_mask).mask1 = (**sane_mask).mask1 | cdm_array[i].mask1;
896 (**sane_mask).mask2 = (**sane_mask).mask2 | cdm_array[i].mask2;
897 }
898}
899
900static void do_k_mask(int i, char *unchecked_keyword, __u64 **sane_mask)
901{
902
903 if (!strcmp(s_kmod_keyword_mask_map[i].keyword, unchecked_keyword))
904 **sane_mask = (**sane_mask) |
905 s_kmod_keyword_mask_map[i].mask_val;
906}
907
908int orangefs_debugfs_new_client_mask(void __user *arg)
909{
910 struct dev_mask2_info_s mask2_info = {0};
911 int ret;
912
913 ret = copy_from_user(&mask2_info,
914 (void __user *)arg,
915 sizeof(struct dev_mask2_info_s));
916
917 if (ret != 0)
918 return -EIO;
919
920 client_debug_mask.mask1 = mask2_info.mask1_value;
921 client_debug_mask.mask2 = mask2_info.mask2_value;
922
923 pr_info("%s: client debug mask has been been received "
924 ":%llx: :%llx:\n",
925 __func__,
926 (unsigned long long)client_debug_mask.mask1,
927 (unsigned long long)client_debug_mask.mask2);
928
929 return ret;
930}
931
dd59a647 932int orangefs_debugfs_new_client_string(void __user *arg)
44f46410
MB
933{
934 int ret;
935
936 ret = copy_from_user(&client_debug_array_string,
05973c2e
MM
937 (void __user *)arg,
938 ORANGEFS_MAX_DEBUG_STRING_LEN);
dc033621
MM
939
940 if (ret != 0) {
941 pr_info("%s: CLIENT_STRING: copy_from_user failed\n",
942 __func__);
05973c2e 943 return -EFAULT;
dc033621 944 }
44f46410
MB
945
946 /*
947 * The real client-core makes an effort to ensure
948 * that actual strings that aren't too long to fit in
949 * this buffer is what we get here. We're going to use
950 * string functions on the stuff we got, so we'll make
951 * this extra effort to try and keep from
952 * flowing out of this buffer when we use the string
953 * functions, even if somehow the stuff we end up
954 * with here is garbage.
955 */
956 client_debug_array_string[ORANGEFS_MAX_DEBUG_STRING_LEN - 1] =
957 '\0';
05973c2e 958
44f46410
MB
959 pr_info("%s: client debug array string has been received.\n",
960 __func__);
961
962 if (!help_string_initialized) {
963
dc033621 964 /* Build a proper debug help string. */
05973c2e
MM
965 ret = orangefs_prepare_debugfs_help_string(0);
966 if (ret) {
44f46410
MB
967 gossip_err("%s: no debug help string \n",
968 __func__);
05973c2e 969 return ret;
44f46410
MB
970 }
971
44f46410
MB
972 }
973
974 debug_mask_to_string(&client_debug_mask, 1);
975
976 debugfs_remove(client_debug_dentry);
977
978 orangefs_client_debug_init();
979
980 help_string_initialized++;
981
05973c2e 982 return 0;
44f46410
MB
983}
984
dd59a647 985int orangefs_debugfs_new_debug(void __user *arg)
44f46410
MB
986{
987 struct dev_mask_info_s mask_info = {0};
988 int ret;
989
990 ret = copy_from_user(&mask_info,
991 (void __user *)arg,
992 sizeof(mask_info));
993
994 if (ret != 0)
995 return -EIO;
996
997 if (mask_info.mask_type == KERNEL_MASK) {
998 if ((mask_info.mask_value == 0)
999 && (kernel_mask_set_mod_init)) {
1000 /*
1001 * the kernel debug mask was set when the
1002 * kernel module was loaded; don't override
1003 * it if the client-core was started without
1004 * a value for ORANGEFS_KMODMASK.
1005 */
1006 return 0;
1007 }
1008 debug_mask_to_string(&mask_info.mask_value,
1009 mask_info.mask_type);
1010 orangefs_gossip_debug_mask = mask_info.mask_value;
1011 pr_info("%s: kernel debug mask has been modified to "
1012 ":%s: :%llx:\n",
1013 __func__,
1014 kernel_debug_string,
1015 (unsigned long long)orangefs_gossip_debug_mask);
1016 } else if (mask_info.mask_type == CLIENT_MASK) {
1017 debug_mask_to_string(&mask_info.mask_value,
1018 mask_info.mask_type);
1019 pr_info("%s: client debug mask has been modified to"
1020 ":%s: :%llx:\n",
1021 __func__,
1022 client_debug_string,
1023 llu(mask_info.mask_value));
1024 } else {
79d7cd61 1025 gossip_err("Invalid mask type....\n");
44f46410
MB
1026 return -EINVAL;
1027 }
1028
1029 return ret;
1030}