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