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