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