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