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