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