1575e9461SMike Marshall /* 2575e9461SMike Marshall * What: /sys/kernel/debug/orangefs/debug-help 3575e9461SMike Marshall * Date: June 2015 4575e9461SMike Marshall * Contact: Mike Marshall <hubcap@omnibond.com> 5575e9461SMike Marshall * Description: 6575e9461SMike Marshall * List of client and kernel debug keywords. 7575e9461SMike Marshall * 8575e9461SMike Marshall * 9575e9461SMike Marshall * What: /sys/kernel/debug/orangefs/client-debug 10575e9461SMike Marshall * Date: June 2015 11575e9461SMike Marshall * Contact: Mike Marshall <hubcap@omnibond.com> 12575e9461SMike Marshall * Description: 13575e9461SMike Marshall * Debug setting for "the client", the userspace 14575e9461SMike Marshall * helper for the kernel module. 15575e9461SMike Marshall * 16575e9461SMike Marshall * 17575e9461SMike Marshall * What: /sys/kernel/debug/orangefs/kernel-debug 18575e9461SMike Marshall * Date: June 2015 19575e9461SMike Marshall * Contact: Mike Marshall <hubcap@omnibond.com> 20575e9461SMike Marshall * Description: 21575e9461SMike Marshall * Debug setting for the orangefs kernel module. 22575e9461SMike Marshall * 23575e9461SMike Marshall * Any of the keywords, or comma-separated lists 24575e9461SMike Marshall * of keywords, from debug-help can be catted to 25575e9461SMike Marshall * client-debug or kernel-debug. 26575e9461SMike Marshall * 27575e9461SMike Marshall * "none", "all" and "verbose" are special keywords 28575e9461SMike Marshall * for client-debug. Setting client-debug to "all" 29575e9461SMike Marshall * is kind of like trying to drink water from a 30575e9461SMike Marshall * fire hose, "verbose" triggers most of the same 31575e9461SMike Marshall * output except for the constant flow of output 32575e9461SMike Marshall * from the main wait loop. 33575e9461SMike Marshall * 34575e9461SMike Marshall * "none" and "all" are similar settings for kernel-debug 35575e9461SMike Marshall * no need for a "verbose". 36575e9461SMike Marshall */ 37575e9461SMike Marshall #include <linux/debugfs.h> 38575e9461SMike Marshall #include <linux/slab.h> 39575e9461SMike Marshall 40575e9461SMike Marshall #include <linux/uaccess.h> 41575e9461SMike Marshall 42575e9461SMike Marshall #include "orangefs-debugfs.h" 43575e9461SMike Marshall #include "protocol.h" 44575e9461SMike Marshall #include "orangefs-kernel.h" 45575e9461SMike Marshall 4644f46410SMartin Brandenburg #define DEBUG_HELP_STRING_SIZE 4096 4744f46410SMartin Brandenburg #define HELP_STRING_UNINITIALIZED \ 4844f46410SMartin Brandenburg "Client Debug Keywords are unknown until the first time\n" \ 4944f46410SMartin Brandenburg "the client is started after boot.\n" 5044f46410SMartin Brandenburg #define ORANGEFS_KMOD_DEBUG_HELP_FILE "debug-help" 5144f46410SMartin Brandenburg #define ORANGEFS_KMOD_DEBUG_FILE "kernel-debug" 5244f46410SMartin Brandenburg #define ORANGEFS_CLIENT_DEBUG_FILE "client-debug" 5344f46410SMartin Brandenburg #define ORANGEFS_VERBOSE "verbose" 5444f46410SMartin Brandenburg #define ORANGEFS_ALL "all" 55575e9461SMike Marshall 5644f46410SMartin Brandenburg /* 5744f46410SMartin Brandenburg * An array of client_debug_mask will be built to hold debug keyword/mask 5844f46410SMartin Brandenburg * values fetched from userspace. 5944f46410SMartin Brandenburg */ 6044f46410SMartin Brandenburg struct client_debug_mask { 6144f46410SMartin Brandenburg char *keyword; 6244f46410SMartin Brandenburg __u64 mask1; 6344f46410SMartin Brandenburg __u64 mask2; 64575e9461SMike Marshall }; 65575e9461SMike Marshall 6644f46410SMartin Brandenburg static int orangefs_kernel_debug_init(void); 6744f46410SMartin Brandenburg 6844f46410SMartin Brandenburg static int orangefs_debug_help_open(struct inode *, struct file *); 69575e9461SMike Marshall static void *help_start(struct seq_file *, loff_t *); 70575e9461SMike Marshall static void *help_next(struct seq_file *, void *, loff_t *); 71575e9461SMike Marshall static void help_stop(struct seq_file *, void *); 72575e9461SMike Marshall static int help_show(struct seq_file *, void *); 73575e9461SMike Marshall 7444f46410SMartin Brandenburg static int orangefs_debug_open(struct inode *, struct file *); 75575e9461SMike Marshall 76575e9461SMike Marshall static ssize_t orangefs_debug_read(struct file *, 77575e9461SMike Marshall char __user *, 78575e9461SMike Marshall size_t, 79575e9461SMike Marshall loff_t *); 80575e9461SMike Marshall 81575e9461SMike Marshall static ssize_t orangefs_debug_write(struct file *, 82575e9461SMike Marshall const char __user *, 83575e9461SMike Marshall size_t, 84575e9461SMike Marshall loff_t *); 85575e9461SMike Marshall 8644f46410SMartin Brandenburg static int orangefs_prepare_cdm_array(char *); 8744f46410SMartin Brandenburg static void debug_mask_to_string(void *, int); 8844f46410SMartin Brandenburg static void do_k_string(void *, int); 8944f46410SMartin Brandenburg static void do_c_string(void *, int); 9044f46410SMartin Brandenburg static int keyword_is_amalgam(char *); 9144f46410SMartin Brandenburg static int check_amalgam_keyword(void *, int); 9244f46410SMartin Brandenburg static void debug_string_to_mask(char *, void *, int); 9344f46410SMartin Brandenburg static void do_c_mask(int, char *, struct client_debug_mask **); 9444f46410SMartin Brandenburg static void do_k_mask(int, char *, __u64 **); 9544f46410SMartin Brandenburg 9644f46410SMartin Brandenburg static char kernel_debug_string[ORANGEFS_MAX_DEBUG_STRING_LEN] = "none"; 9744f46410SMartin Brandenburg static char *debug_help_string; 9844f46410SMartin Brandenburg static char client_debug_string[ORANGEFS_MAX_DEBUG_STRING_LEN]; 9944f46410SMartin Brandenburg static char client_debug_array_string[ORANGEFS_MAX_DEBUG_STRING_LEN]; 10044f46410SMartin Brandenburg 10144f46410SMartin Brandenburg static struct dentry *help_file_dentry; 10244f46410SMartin Brandenburg static struct dentry *client_debug_dentry; 10344f46410SMartin Brandenburg static struct dentry *debug_dir; 10444f46410SMartin Brandenburg 10544f46410SMartin Brandenburg static unsigned int kernel_mask_set_mod_init; 10644f46410SMartin Brandenburg static int orangefs_debug_disabled = 1; 10744f46410SMartin Brandenburg static int help_string_initialized; 10844f46410SMartin Brandenburg 10944f46410SMartin Brandenburg static const struct seq_operations help_debug_ops = { 11044f46410SMartin Brandenburg .start = help_start, 11144f46410SMartin Brandenburg .next = help_next, 11244f46410SMartin Brandenburg .stop = help_stop, 11344f46410SMartin Brandenburg .show = help_show, 11444f46410SMartin Brandenburg }; 11544f46410SMartin Brandenburg 11644f46410SMartin Brandenburg const struct file_operations debug_help_fops = { 117*19ff7fccSMike Marshall .owner = THIS_MODULE, 11844f46410SMartin Brandenburg .open = orangefs_debug_help_open, 11944f46410SMartin Brandenburg .read = seq_read, 12044f46410SMartin Brandenburg .release = seq_release, 12144f46410SMartin Brandenburg .llseek = seq_lseek, 12244f46410SMartin Brandenburg }; 12344f46410SMartin Brandenburg 124575e9461SMike Marshall static const struct file_operations kernel_debug_fops = { 125*19ff7fccSMike Marshall .owner = THIS_MODULE, 126575e9461SMike Marshall .open = orangefs_debug_open, 127575e9461SMike Marshall .read = orangefs_debug_read, 128575e9461SMike Marshall .write = orangefs_debug_write, 129575e9461SMike Marshall .llseek = generic_file_llseek, 130575e9461SMike Marshall }; 131575e9461SMike Marshall 13244f46410SMartin Brandenburg static int client_all_index; 13344f46410SMartin Brandenburg static int client_verbose_index; 13444f46410SMartin Brandenburg 13544f46410SMartin Brandenburg static struct client_debug_mask *cdm_array; 13644f46410SMartin Brandenburg static int cdm_element_count; 13744f46410SMartin Brandenburg 13844f46410SMartin Brandenburg static struct client_debug_mask client_debug_mask; 13944f46410SMartin Brandenburg 14044f46410SMartin Brandenburg /* 14144f46410SMartin Brandenburg * Used to protect data in ORANGEFS_KMOD_DEBUG_FILE and 14244f46410SMartin Brandenburg * ORANGEFS_KMOD_DEBUG_FILE. 14344f46410SMartin Brandenburg */ 14444f46410SMartin Brandenburg static DEFINE_MUTEX(orangefs_debug_lock); 14544f46410SMartin Brandenburg 146dc033621SMike Marshall /* Used to protect data in ORANGEFS_KMOD_DEBUG_HELP_FILE */ 147dc033621SMike Marshall static DEFINE_MUTEX(orangefs_help_file_lock); 148dc033621SMike Marshall 149575e9461SMike Marshall /* 150575e9461SMike Marshall * initialize kmod debug operations, create orangefs debugfs dir and 151575e9461SMike Marshall * ORANGEFS_KMOD_DEBUG_HELP_FILE. 152575e9461SMike Marshall */ 15344f46410SMartin Brandenburg int orangefs_debugfs_init(int debug_mask) 154575e9461SMike Marshall { 155575e9461SMike Marshall int rc = -ENOMEM; 156575e9461SMike Marshall 15744f46410SMartin Brandenburg /* convert input debug mask to a 64-bit unsigned integer */ 15844f46410SMartin Brandenburg orangefs_gossip_debug_mask = (unsigned long long)debug_mask; 15944f46410SMartin Brandenburg 16044f46410SMartin Brandenburg /* 16144f46410SMartin Brandenburg * set the kernel's gossip debug string; invalid mask values will 16244f46410SMartin Brandenburg * be ignored. 16344f46410SMartin Brandenburg */ 16444f46410SMartin Brandenburg debug_mask_to_string(&orangefs_gossip_debug_mask, 0); 16544f46410SMartin Brandenburg 16644f46410SMartin Brandenburg /* remove any invalid values from the mask */ 16744f46410SMartin Brandenburg debug_string_to_mask(kernel_debug_string, &orangefs_gossip_debug_mask, 16844f46410SMartin Brandenburg 0); 16944f46410SMartin Brandenburg 17044f46410SMartin Brandenburg /* 17144f46410SMartin Brandenburg * if the mask has a non-zero value, then indicate that the mask 17244f46410SMartin Brandenburg * was set when the kernel module was loaded. The orangefs dev ioctl 17344f46410SMartin Brandenburg * command will look at this boolean to determine if the kernel's 17444f46410SMartin Brandenburg * debug mask should be overwritten when the client-core is started. 17544f46410SMartin Brandenburg */ 17644f46410SMartin Brandenburg if (orangefs_gossip_debug_mask != 0) 17744f46410SMartin Brandenburg kernel_mask_set_mod_init = true; 17844f46410SMartin Brandenburg 17944f46410SMartin Brandenburg pr_info("%s: called with debug mask: :%s: :%llx:\n", 18044f46410SMartin Brandenburg __func__, 18144f46410SMartin Brandenburg kernel_debug_string, 18244f46410SMartin Brandenburg (unsigned long long)orangefs_gossip_debug_mask); 18344f46410SMartin Brandenburg 184575e9461SMike Marshall debug_dir = debugfs_create_dir("orangefs", NULL); 1852180c52cSMike Marshall if (!debug_dir) { 1862180c52cSMike Marshall pr_info("%s: debugfs_create_dir failed.\n", __func__); 187575e9461SMike Marshall goto out; 1882180c52cSMike Marshall } 189575e9461SMike Marshall 190575e9461SMike Marshall help_file_dentry = debugfs_create_file(ORANGEFS_KMOD_DEBUG_HELP_FILE, 191575e9461SMike Marshall 0444, 192575e9461SMike Marshall debug_dir, 193575e9461SMike Marshall debug_help_string, 194575e9461SMike Marshall &debug_help_fops); 1952180c52cSMike Marshall if (!help_file_dentry) { 1962180c52cSMike Marshall pr_info("%s: debugfs_create_file failed.\n", __func__); 197575e9461SMike Marshall goto out; 1982180c52cSMike Marshall } 199575e9461SMike Marshall 200575e9461SMike Marshall orangefs_debug_disabled = 0; 20144f46410SMartin Brandenburg 20244f46410SMartin Brandenburg rc = orangefs_kernel_debug_init(); 203575e9461SMike Marshall 204575e9461SMike Marshall out: 205575e9461SMike Marshall 206575e9461SMike Marshall return rc; 207575e9461SMike Marshall } 208575e9461SMike Marshall 20944f46410SMartin Brandenburg /* 21044f46410SMartin Brandenburg * initialize the kernel-debug file. 21144f46410SMartin Brandenburg */ 21244f46410SMartin Brandenburg static int orangefs_kernel_debug_init(void) 21344f46410SMartin Brandenburg { 21444f46410SMartin Brandenburg int rc = -ENOMEM; 21544f46410SMartin Brandenburg struct dentry *ret; 21644f46410SMartin Brandenburg char *k_buffer = NULL; 21744f46410SMartin Brandenburg 21844f46410SMartin Brandenburg gossip_debug(GOSSIP_DEBUGFS_DEBUG, "%s: start\n", __func__); 21944f46410SMartin Brandenburg 22044f46410SMartin Brandenburg k_buffer = kzalloc(ORANGEFS_MAX_DEBUG_STRING_LEN, GFP_KERNEL); 22144f46410SMartin Brandenburg if (!k_buffer) 22244f46410SMartin Brandenburg goto out; 22344f46410SMartin Brandenburg 22444f46410SMartin Brandenburg if (strlen(kernel_debug_string) + 1 < ORANGEFS_MAX_DEBUG_STRING_LEN) { 22544f46410SMartin Brandenburg strcpy(k_buffer, kernel_debug_string); 22644f46410SMartin Brandenburg strcat(k_buffer, "\n"); 22744f46410SMartin Brandenburg } else { 22844f46410SMartin Brandenburg strcpy(k_buffer, "none\n"); 22944f46410SMartin Brandenburg pr_info("%s: overflow 1!\n", __func__); 23044f46410SMartin Brandenburg } 23144f46410SMartin Brandenburg 23244f46410SMartin Brandenburg ret = debugfs_create_file(ORANGEFS_KMOD_DEBUG_FILE, 23344f46410SMartin Brandenburg 0444, 23444f46410SMartin Brandenburg debug_dir, 23544f46410SMartin Brandenburg k_buffer, 23644f46410SMartin Brandenburg &kernel_debug_fops); 23744f46410SMartin Brandenburg if (!ret) { 23844f46410SMartin Brandenburg pr_info("%s: failed to create %s.\n", 23944f46410SMartin Brandenburg __func__, 24044f46410SMartin Brandenburg ORANGEFS_KMOD_DEBUG_FILE); 24144f46410SMartin Brandenburg goto out; 24244f46410SMartin Brandenburg } 24344f46410SMartin Brandenburg 24444f46410SMartin Brandenburg rc = 0; 24544f46410SMartin Brandenburg 24644f46410SMartin Brandenburg out: 24744f46410SMartin Brandenburg 24844f46410SMartin Brandenburg gossip_debug(GOSSIP_DEBUGFS_DEBUG, "%s: rc:%d:\n", __func__, rc); 24944f46410SMartin Brandenburg return rc; 25044f46410SMartin Brandenburg } 25144f46410SMartin Brandenburg 25244f46410SMartin Brandenburg 253575e9461SMike Marshall void orangefs_debugfs_cleanup(void) 254575e9461SMike Marshall { 255575e9461SMike Marshall debugfs_remove_recursive(debug_dir); 256575e9461SMike Marshall } 257575e9461SMike Marshall 258575e9461SMike Marshall /* open ORANGEFS_KMOD_DEBUG_HELP_FILE */ 259575e9461SMike Marshall static int orangefs_debug_help_open(struct inode *inode, struct file *file) 260575e9461SMike Marshall { 261575e9461SMike Marshall int rc = -ENODEV; 262575e9461SMike Marshall int ret; 263575e9461SMike Marshall 264575e9461SMike Marshall gossip_debug(GOSSIP_DEBUGFS_DEBUG, 265575e9461SMike Marshall "orangefs_debug_help_open: start\n"); 266575e9461SMike Marshall 267575e9461SMike Marshall if (orangefs_debug_disabled) 268575e9461SMike Marshall goto out; 269575e9461SMike Marshall 270575e9461SMike Marshall ret = seq_open(file, &help_debug_ops); 271575e9461SMike Marshall if (ret) 272575e9461SMike Marshall goto out; 273575e9461SMike Marshall 274575e9461SMike Marshall ((struct seq_file *)(file->private_data))->private = inode->i_private; 275575e9461SMike Marshall 276575e9461SMike Marshall rc = 0; 277575e9461SMike Marshall 278575e9461SMike Marshall out: 279575e9461SMike Marshall gossip_debug(GOSSIP_DEBUGFS_DEBUG, 280575e9461SMike Marshall "orangefs_debug_help_open: rc:%d:\n", 281575e9461SMike Marshall rc); 282575e9461SMike Marshall return rc; 283575e9461SMike Marshall } 284575e9461SMike Marshall 285575e9461SMike Marshall /* 286575e9461SMike Marshall * I think start always gets called again after stop. Start 287575e9461SMike Marshall * needs to return NULL when it is done. The whole "payload" 288575e9461SMike Marshall * in this case is a single (long) string, so by the second 289575e9461SMike Marshall * time we get to start (pos = 1), we're done. 290575e9461SMike Marshall */ 291575e9461SMike Marshall static void *help_start(struct seq_file *m, loff_t *pos) 292575e9461SMike Marshall { 293575e9461SMike Marshall void *payload = NULL; 294575e9461SMike Marshall 295575e9461SMike Marshall gossip_debug(GOSSIP_DEBUGFS_DEBUG, "help_start: start\n"); 296575e9461SMike Marshall 297dc033621SMike Marshall mutex_lock(&orangefs_help_file_lock); 298dc033621SMike Marshall 299575e9461SMike Marshall if (*pos == 0) 300575e9461SMike Marshall payload = m->private; 301575e9461SMike Marshall 302575e9461SMike Marshall return payload; 303575e9461SMike Marshall } 304575e9461SMike Marshall 305575e9461SMike Marshall static void *help_next(struct seq_file *m, void *v, loff_t *pos) 306575e9461SMike Marshall { 307575e9461SMike Marshall gossip_debug(GOSSIP_DEBUGFS_DEBUG, "help_next: start\n"); 308575e9461SMike Marshall 309575e9461SMike Marshall return NULL; 310575e9461SMike Marshall } 311575e9461SMike Marshall 312575e9461SMike Marshall static void help_stop(struct seq_file *m, void *p) 313575e9461SMike Marshall { 314575e9461SMike Marshall gossip_debug(GOSSIP_DEBUGFS_DEBUG, "help_stop: start\n"); 315dc033621SMike Marshall mutex_unlock(&orangefs_help_file_lock); 316575e9461SMike Marshall } 317575e9461SMike Marshall 318575e9461SMike Marshall static int help_show(struct seq_file *m, void *v) 319575e9461SMike Marshall { 320575e9461SMike Marshall gossip_debug(GOSSIP_DEBUGFS_DEBUG, "help_show: start\n"); 321575e9461SMike Marshall 322575e9461SMike Marshall seq_puts(m, v); 323575e9461SMike Marshall 324575e9461SMike Marshall return 0; 325575e9461SMike Marshall } 326575e9461SMike Marshall 327575e9461SMike Marshall /* 328575e9461SMike Marshall * initialize the client-debug file. 329575e9461SMike Marshall */ 330575e9461SMike Marshall int orangefs_client_debug_init(void) 331575e9461SMike Marshall { 332575e9461SMike Marshall 333575e9461SMike Marshall int rc = -ENOMEM; 334575e9461SMike Marshall char *c_buffer = NULL; 335575e9461SMike Marshall 336575e9461SMike Marshall gossip_debug(GOSSIP_DEBUGFS_DEBUG, "%s: start\n", __func__); 337575e9461SMike Marshall 338575e9461SMike Marshall c_buffer = kzalloc(ORANGEFS_MAX_DEBUG_STRING_LEN, GFP_KERNEL); 339575e9461SMike Marshall if (!c_buffer) 340575e9461SMike Marshall goto out; 341575e9461SMike Marshall 342575e9461SMike Marshall if (strlen(client_debug_string) + 1 < ORANGEFS_MAX_DEBUG_STRING_LEN) { 343575e9461SMike Marshall strcpy(c_buffer, client_debug_string); 344575e9461SMike Marshall strcat(c_buffer, "\n"); 345575e9461SMike Marshall } else { 346575e9461SMike Marshall strcpy(c_buffer, "none\n"); 347575e9461SMike Marshall pr_info("%s: overflow! 2\n", __func__); 348575e9461SMike Marshall } 349575e9461SMike Marshall 350575e9461SMike Marshall client_debug_dentry = debugfs_create_file(ORANGEFS_CLIENT_DEBUG_FILE, 351575e9461SMike Marshall 0444, 352575e9461SMike Marshall debug_dir, 353575e9461SMike Marshall c_buffer, 354575e9461SMike Marshall &kernel_debug_fops); 355575e9461SMike Marshall if (!client_debug_dentry) { 3562180c52cSMike Marshall pr_info("%s: failed to create updated %s.\n", 357575e9461SMike Marshall __func__, 358575e9461SMike Marshall ORANGEFS_CLIENT_DEBUG_FILE); 359575e9461SMike Marshall goto out; 360575e9461SMike Marshall } 361575e9461SMike Marshall 362575e9461SMike Marshall rc = 0; 363575e9461SMike Marshall 364575e9461SMike Marshall out: 365575e9461SMike Marshall 366575e9461SMike Marshall gossip_debug(GOSSIP_DEBUGFS_DEBUG, "%s: rc:%d:\n", __func__, rc); 367575e9461SMike Marshall return rc; 368575e9461SMike Marshall } 369575e9461SMike Marshall 370575e9461SMike Marshall /* open ORANGEFS_KMOD_DEBUG_FILE or ORANGEFS_CLIENT_DEBUG_FILE.*/ 37144f46410SMartin Brandenburg static int orangefs_debug_open(struct inode *inode, struct file *file) 372575e9461SMike Marshall { 373575e9461SMike Marshall int rc = -ENODEV; 374575e9461SMike Marshall 375575e9461SMike Marshall gossip_debug(GOSSIP_DEBUGFS_DEBUG, 376575e9461SMike Marshall "%s: orangefs_debug_disabled: %d\n", 377575e9461SMike Marshall __func__, 378575e9461SMike Marshall orangefs_debug_disabled); 379575e9461SMike Marshall 380575e9461SMike Marshall if (orangefs_debug_disabled) 381575e9461SMike Marshall goto out; 382575e9461SMike Marshall 383575e9461SMike Marshall rc = 0; 384575e9461SMike Marshall mutex_lock(&orangefs_debug_lock); 385575e9461SMike Marshall file->private_data = inode->i_private; 386575e9461SMike Marshall mutex_unlock(&orangefs_debug_lock); 387575e9461SMike Marshall 388575e9461SMike Marshall out: 389575e9461SMike Marshall gossip_debug(GOSSIP_DEBUGFS_DEBUG, 390575e9461SMike Marshall "orangefs_debug_open: rc: %d\n", 391575e9461SMike Marshall rc); 392575e9461SMike Marshall return rc; 393575e9461SMike Marshall } 394575e9461SMike Marshall 395575e9461SMike Marshall static ssize_t orangefs_debug_read(struct file *file, 396575e9461SMike Marshall char __user *ubuf, 397575e9461SMike Marshall size_t count, 398575e9461SMike Marshall loff_t *ppos) 399575e9461SMike Marshall { 400575e9461SMike Marshall char *buf; 401575e9461SMike Marshall int sprintf_ret; 402575e9461SMike Marshall ssize_t read_ret = -ENOMEM; 403575e9461SMike Marshall 404575e9461SMike Marshall gossip_debug(GOSSIP_DEBUGFS_DEBUG, "orangefs_debug_read: start\n"); 405575e9461SMike Marshall 406575e9461SMike Marshall buf = kmalloc(ORANGEFS_MAX_DEBUG_STRING_LEN, GFP_KERNEL); 407575e9461SMike Marshall if (!buf) 408575e9461SMike Marshall goto out; 409575e9461SMike Marshall 410575e9461SMike Marshall mutex_lock(&orangefs_debug_lock); 411575e9461SMike Marshall sprintf_ret = sprintf(buf, "%s", (char *)file->private_data); 412575e9461SMike Marshall mutex_unlock(&orangefs_debug_lock); 413575e9461SMike Marshall 414575e9461SMike Marshall read_ret = simple_read_from_buffer(ubuf, count, ppos, buf, sprintf_ret); 415575e9461SMike Marshall 416575e9461SMike Marshall kfree(buf); 417575e9461SMike Marshall 418575e9461SMike Marshall out: 419575e9461SMike Marshall gossip_debug(GOSSIP_DEBUGFS_DEBUG, 420575e9461SMike Marshall "orangefs_debug_read: ret: %zu\n", 421575e9461SMike Marshall read_ret); 422575e9461SMike Marshall 423575e9461SMike Marshall return read_ret; 424575e9461SMike Marshall } 425575e9461SMike Marshall 426575e9461SMike Marshall static ssize_t orangefs_debug_write(struct file *file, 427575e9461SMike Marshall const char __user *ubuf, 428575e9461SMike Marshall size_t count, 429575e9461SMike Marshall loff_t *ppos) 430575e9461SMike Marshall { 431575e9461SMike Marshall char *buf; 432575e9461SMike Marshall int rc = -EFAULT; 433575e9461SMike Marshall size_t silly = 0; 434575e9461SMike Marshall char *debug_string; 435575e9461SMike Marshall struct orangefs_kernel_op_s *new_op = NULL; 436575e9461SMike Marshall struct client_debug_mask c_mask = { NULL, 0, 0 }; 437575e9461SMike Marshall 438575e9461SMike Marshall gossip_debug(GOSSIP_DEBUGFS_DEBUG, 439f66debf1SAl Viro "orangefs_debug_write: %pD\n", 440f66debf1SAl Viro file); 441575e9461SMike Marshall 442575e9461SMike Marshall /* 443575e9461SMike Marshall * Thwart users who try to jamb a ridiculous number 444575e9461SMike Marshall * of bytes into the debug file... 445575e9461SMike Marshall */ 446575e9461SMike Marshall if (count > ORANGEFS_MAX_DEBUG_STRING_LEN + 1) { 447575e9461SMike Marshall silly = count; 448575e9461SMike Marshall count = ORANGEFS_MAX_DEBUG_STRING_LEN + 1; 449575e9461SMike Marshall } 450575e9461SMike Marshall 451dde58ca4SNicholas Mc Guire buf = kzalloc(ORANGEFS_MAX_DEBUG_STRING_LEN, GFP_KERNEL); 452575e9461SMike Marshall if (!buf) 453575e9461SMike Marshall goto out; 454575e9461SMike Marshall 455575e9461SMike Marshall if (copy_from_user(buf, ubuf, count - 1)) { 456575e9461SMike Marshall gossip_debug(GOSSIP_DEBUGFS_DEBUG, 457575e9461SMike Marshall "%s: copy_from_user failed!\n", 458575e9461SMike Marshall __func__); 459575e9461SMike Marshall goto out; 460575e9461SMike Marshall } 461575e9461SMike Marshall 462575e9461SMike Marshall /* 463575e9461SMike Marshall * Map the keyword string from userspace into a valid debug mask. 464575e9461SMike Marshall * The mapping process involves mapping the human-inputted string 465575e9461SMike Marshall * into a valid mask, and then rebuilding the string from the 466575e9461SMike Marshall * verified valid mask. 467575e9461SMike Marshall * 468575e9461SMike Marshall * A service operation is required to set a new client-side 469575e9461SMike Marshall * debug mask. 470575e9461SMike Marshall */ 471575e9461SMike Marshall if (!strcmp(file->f_path.dentry->d_name.name, 472575e9461SMike Marshall ORANGEFS_KMOD_DEBUG_FILE)) { 47344f46410SMartin Brandenburg debug_string_to_mask(buf, &orangefs_gossip_debug_mask, 0); 47444f46410SMartin Brandenburg debug_mask_to_string(&orangefs_gossip_debug_mask, 0); 475575e9461SMike Marshall debug_string = kernel_debug_string; 476575e9461SMike Marshall gossip_debug(GOSSIP_DEBUGFS_DEBUG, 477575e9461SMike Marshall "New kernel debug string is %s\n", 478575e9461SMike Marshall kernel_debug_string); 479575e9461SMike Marshall } else { 480575e9461SMike Marshall /* Can't reset client debug mask if client is not running. */ 481575e9461SMike Marshall if (is_daemon_in_service()) { 482575e9461SMike Marshall pr_info("%s: Client not running :%d:\n", 483575e9461SMike Marshall __func__, 484575e9461SMike Marshall is_daemon_in_service()); 485575e9461SMike Marshall goto out; 486575e9461SMike Marshall } 487575e9461SMike Marshall 488575e9461SMike Marshall debug_string_to_mask(buf, &c_mask, 1); 489575e9461SMike Marshall debug_mask_to_string(&c_mask, 1); 490575e9461SMike Marshall debug_string = client_debug_string; 491575e9461SMike Marshall 492575e9461SMike Marshall new_op = op_alloc(ORANGEFS_VFS_OP_PARAM); 493575e9461SMike Marshall if (!new_op) { 494575e9461SMike Marshall pr_info("%s: op_alloc failed!\n", __func__); 495575e9461SMike Marshall goto out; 496575e9461SMike Marshall } 497575e9461SMike Marshall 498575e9461SMike Marshall new_op->upcall.req.param.op = 499575e9461SMike Marshall ORANGEFS_PARAM_REQUEST_OP_TWO_MASK_VALUES; 500575e9461SMike Marshall new_op->upcall.req.param.type = ORANGEFS_PARAM_REQUEST_SET; 501575e9461SMike Marshall memset(new_op->upcall.req.param.s_value, 502575e9461SMike Marshall 0, 503575e9461SMike Marshall ORANGEFS_MAX_DEBUG_STRING_LEN); 504575e9461SMike Marshall sprintf(new_op->upcall.req.param.s_value, 505575e9461SMike Marshall "%llx %llx\n", 506575e9461SMike Marshall c_mask.mask1, 507575e9461SMike Marshall c_mask.mask2); 508575e9461SMike Marshall 509575e9461SMike Marshall /* service_operation returns 0 on success... */ 510575e9461SMike Marshall rc = service_operation(new_op, 511575e9461SMike Marshall "orangefs_param", 512575e9461SMike Marshall ORANGEFS_OP_INTERRUPTIBLE); 513575e9461SMike Marshall 514575e9461SMike Marshall if (rc) 515575e9461SMike Marshall gossip_debug(GOSSIP_DEBUGFS_DEBUG, 516575e9461SMike Marshall "%s: service_operation failed! rc:%d:\n", 517575e9461SMike Marshall __func__, 518575e9461SMike Marshall rc); 519575e9461SMike Marshall 520575e9461SMike Marshall op_release(new_op); 521575e9461SMike Marshall } 522575e9461SMike Marshall 523575e9461SMike Marshall mutex_lock(&orangefs_debug_lock); 524575e9461SMike Marshall memset(file->f_inode->i_private, 0, ORANGEFS_MAX_DEBUG_STRING_LEN); 525575e9461SMike Marshall sprintf((char *)file->f_inode->i_private, "%s\n", debug_string); 526575e9461SMike Marshall mutex_unlock(&orangefs_debug_lock); 527575e9461SMike Marshall 528575e9461SMike Marshall *ppos += count; 529575e9461SMike Marshall if (silly) 530575e9461SMike Marshall rc = silly; 531575e9461SMike Marshall else 532575e9461SMike Marshall rc = count; 533575e9461SMike Marshall 534575e9461SMike Marshall out: 535575e9461SMike Marshall gossip_debug(GOSSIP_DEBUGFS_DEBUG, 536575e9461SMike Marshall "orangefs_debug_write: rc: %d\n", 537575e9461SMike Marshall rc); 538575e9461SMike Marshall kfree(buf); 539575e9461SMike Marshall return rc; 540575e9461SMike Marshall } 54144f46410SMartin Brandenburg 54244f46410SMartin Brandenburg /* 54344f46410SMartin Brandenburg * After obtaining a string representation of the client's debug 54444f46410SMartin Brandenburg * keywords and their associated masks, this function is called to build an 54544f46410SMartin Brandenburg * array of these values. 54644f46410SMartin Brandenburg */ 54744f46410SMartin Brandenburg static int orangefs_prepare_cdm_array(char *debug_array_string) 54844f46410SMartin Brandenburg { 54944f46410SMartin Brandenburg int i; 55044f46410SMartin Brandenburg int rc = -EINVAL; 55144f46410SMartin Brandenburg char *cds_head = NULL; 55244f46410SMartin Brandenburg char *cds_delimiter = NULL; 55344f46410SMartin Brandenburg int keyword_len = 0; 55444f46410SMartin Brandenburg 55544f46410SMartin Brandenburg gossip_debug(GOSSIP_UTILS_DEBUG, "%s: start\n", __func__); 55644f46410SMartin Brandenburg 55744f46410SMartin Brandenburg /* 55844f46410SMartin Brandenburg * figure out how many elements the cdm_array needs. 55944f46410SMartin Brandenburg */ 56044f46410SMartin Brandenburg for (i = 0; i < strlen(debug_array_string); i++) 56144f46410SMartin Brandenburg if (debug_array_string[i] == '\n') 56244f46410SMartin Brandenburg cdm_element_count++; 56344f46410SMartin Brandenburg 56444f46410SMartin Brandenburg if (!cdm_element_count) { 56544f46410SMartin Brandenburg pr_info("No elements in client debug array string!\n"); 56644f46410SMartin Brandenburg goto out; 56744f46410SMartin Brandenburg } 56844f46410SMartin Brandenburg 56944f46410SMartin Brandenburg cdm_array = 57044f46410SMartin Brandenburg kzalloc(cdm_element_count * sizeof(struct client_debug_mask), 57144f46410SMartin Brandenburg GFP_KERNEL); 57244f46410SMartin Brandenburg if (!cdm_array) { 57344f46410SMartin Brandenburg pr_info("malloc failed for cdm_array!\n"); 57444f46410SMartin Brandenburg rc = -ENOMEM; 57544f46410SMartin Brandenburg goto out; 57644f46410SMartin Brandenburg } 57744f46410SMartin Brandenburg 57844f46410SMartin Brandenburg cds_head = debug_array_string; 57944f46410SMartin Brandenburg 58044f46410SMartin Brandenburg for (i = 0; i < cdm_element_count; i++) { 58144f46410SMartin Brandenburg cds_delimiter = strchr(cds_head, '\n'); 58244f46410SMartin Brandenburg *cds_delimiter = '\0'; 58344f46410SMartin Brandenburg 58444f46410SMartin Brandenburg keyword_len = strcspn(cds_head, " "); 58544f46410SMartin Brandenburg 58644f46410SMartin Brandenburg cdm_array[i].keyword = kzalloc(keyword_len + 1, GFP_KERNEL); 58744f46410SMartin Brandenburg if (!cdm_array[i].keyword) { 58844f46410SMartin Brandenburg rc = -ENOMEM; 58944f46410SMartin Brandenburg goto out; 59044f46410SMartin Brandenburg } 59144f46410SMartin Brandenburg 59244f46410SMartin Brandenburg sscanf(cds_head, 59344f46410SMartin Brandenburg "%s %llx %llx", 59444f46410SMartin Brandenburg cdm_array[i].keyword, 59544f46410SMartin Brandenburg (unsigned long long *)&(cdm_array[i].mask1), 59644f46410SMartin Brandenburg (unsigned long long *)&(cdm_array[i].mask2)); 59744f46410SMartin Brandenburg 59844f46410SMartin Brandenburg if (!strcmp(cdm_array[i].keyword, ORANGEFS_VERBOSE)) 59944f46410SMartin Brandenburg client_verbose_index = i; 60044f46410SMartin Brandenburg 60144f46410SMartin Brandenburg if (!strcmp(cdm_array[i].keyword, ORANGEFS_ALL)) 60244f46410SMartin Brandenburg client_all_index = i; 60344f46410SMartin Brandenburg 60444f46410SMartin Brandenburg cds_head = cds_delimiter + 1; 60544f46410SMartin Brandenburg } 60644f46410SMartin Brandenburg 60744f46410SMartin Brandenburg rc = cdm_element_count; 60844f46410SMartin Brandenburg 60944f46410SMartin Brandenburg gossip_debug(GOSSIP_UTILS_DEBUG, "%s: rc:%d:\n", __func__, rc); 61044f46410SMartin Brandenburg 61144f46410SMartin Brandenburg out: 61244f46410SMartin Brandenburg 61344f46410SMartin Brandenburg return rc; 61444f46410SMartin Brandenburg 61544f46410SMartin Brandenburg } 61644f46410SMartin Brandenburg 61744f46410SMartin Brandenburg /* 61844f46410SMartin Brandenburg * /sys/kernel/debug/orangefs/debug-help can be catted to 61944f46410SMartin Brandenburg * see all the available kernel and client debug keywords. 62044f46410SMartin Brandenburg * 621dc033621SMike Marshall * When orangefs.ko initializes, we have no idea what keywords the 62244f46410SMartin Brandenburg * client supports, nor their associated masks. 62344f46410SMartin Brandenburg * 624dc033621SMike Marshall * We pass through this function once at module-load and stamp a 62544f46410SMartin Brandenburg * boilerplate "we don't know" message for the client in the 62644f46410SMartin Brandenburg * debug-help file. We pass through here again when the client 62744f46410SMartin Brandenburg * starts and then we can fill out the debug-help file fully. 62844f46410SMartin Brandenburg * 62944f46410SMartin Brandenburg * The client might be restarted any number of times between 630dc033621SMike Marshall * module reloads, we only build the debug-help file the first time. 63144f46410SMartin Brandenburg */ 63244f46410SMartin Brandenburg int orangefs_prepare_debugfs_help_string(int at_boot) 63344f46410SMartin Brandenburg { 63444f46410SMartin Brandenburg char *client_title = "Client Debug Keywords:\n"; 63544f46410SMartin Brandenburg char *kernel_title = "Kernel Debug Keywords:\n"; 636dc033621SMike Marshall size_t string_size = DEBUG_HELP_STRING_SIZE; 637dc033621SMike Marshall size_t result_size; 638dc033621SMike Marshall size_t i; 639dc033621SMike Marshall char *new; 640dc033621SMike Marshall int rc = -EINVAL; 64144f46410SMartin Brandenburg 64244f46410SMartin Brandenburg gossip_debug(GOSSIP_UTILS_DEBUG, "%s: start\n", __func__); 64344f46410SMartin Brandenburg 644dc033621SMike Marshall if (at_boot) 64544f46410SMartin Brandenburg client_title = HELP_STRING_UNINITIALIZED; 646dc033621SMike Marshall 647dc033621SMike Marshall /* build a new debug_help_string. */ 648dc033621SMike Marshall new = kzalloc(DEBUG_HELP_STRING_SIZE, GFP_KERNEL); 649dc033621SMike Marshall if (!new) { 650dc033621SMike Marshall rc = -ENOMEM; 651dc033621SMike Marshall goto out; 652dc033621SMike Marshall } 653dc033621SMike Marshall 654dc033621SMike Marshall /* 655dc033621SMike Marshall * strlcat(dst, src, size) will append at most 656dc033621SMike Marshall * "size - strlen(dst) - 1" bytes of src onto dst, 657dc033621SMike Marshall * null terminating the result, and return the total 658dc033621SMike Marshall * length of the string it tried to create. 659dc033621SMike Marshall * 660dc033621SMike Marshall * We'll just plow through here building our new debug 661dc033621SMike Marshall * help string and let strlcat take care of assuring that 662dc033621SMike Marshall * dst doesn't overflow. 663dc033621SMike Marshall */ 664dc033621SMike Marshall strlcat(new, client_title, string_size); 665dc033621SMike Marshall 666dc033621SMike Marshall if (!at_boot) { 667dc033621SMike Marshall 66844f46410SMartin Brandenburg /* 66944f46410SMartin Brandenburg * fill the client keyword/mask array and remember 67044f46410SMartin Brandenburg * how many elements there were. 67144f46410SMartin Brandenburg */ 67244f46410SMartin Brandenburg cdm_element_count = 67344f46410SMartin Brandenburg orangefs_prepare_cdm_array(client_debug_array_string); 67444f46410SMartin Brandenburg if (cdm_element_count <= 0) 67544f46410SMartin Brandenburg goto out; 67644f46410SMartin Brandenburg 67744f46410SMartin Brandenburg for (i = 0; i < cdm_element_count; i++) { 678dc033621SMike Marshall strlcat(new, "\t", string_size); 679dc033621SMike Marshall strlcat(new, cdm_array[i].keyword, string_size); 680dc033621SMike Marshall strlcat(new, "\n", string_size); 68144f46410SMartin Brandenburg } 68244f46410SMartin Brandenburg } 68344f46410SMartin Brandenburg 684dc033621SMike Marshall strlcat(new, "\n", string_size); 685dc033621SMike Marshall strlcat(new, kernel_title, string_size); 68644f46410SMartin Brandenburg 68744f46410SMartin Brandenburg for (i = 0; i < num_kmod_keyword_mask_map; i++) { 688dc033621SMike Marshall strlcat(new, "\t", string_size); 689dc033621SMike Marshall strlcat(new, s_kmod_keyword_mask_map[i].keyword, string_size); 690dc033621SMike Marshall result_size = strlcat(new, "\n", string_size); 691dc033621SMike Marshall } 692dc033621SMike Marshall 693dc033621SMike Marshall /* See if we tried to put too many bytes into "new"... */ 694dc033621SMike Marshall if (result_size >= string_size) { 695dc033621SMike Marshall kfree(new); 696dc033621SMike Marshall goto out; 697dc033621SMike Marshall } 698dc033621SMike Marshall 699dc033621SMike Marshall if (at_boot) { 700dc033621SMike Marshall debug_help_string = new; 701dc033621SMike Marshall } else { 702dc033621SMike Marshall mutex_lock(&orangefs_help_file_lock); 703dc033621SMike Marshall memset(debug_help_string, 0, DEBUG_HELP_STRING_SIZE); 704dc033621SMike Marshall strlcat(debug_help_string, new, string_size); 705dc033621SMike Marshall mutex_unlock(&orangefs_help_file_lock); 70644f46410SMartin Brandenburg } 70744f46410SMartin Brandenburg 70844f46410SMartin Brandenburg rc = 0; 70944f46410SMartin Brandenburg 710dc033621SMike Marshall out: return rc; 71144f46410SMartin Brandenburg 71244f46410SMartin Brandenburg } 71344f46410SMartin Brandenburg 71444f46410SMartin Brandenburg /* 71544f46410SMartin Brandenburg * kernel = type 0 71644f46410SMartin Brandenburg * client = type 1 71744f46410SMartin Brandenburg */ 71844f46410SMartin Brandenburg static void debug_mask_to_string(void *mask, int type) 71944f46410SMartin Brandenburg { 72044f46410SMartin Brandenburg int i; 72144f46410SMartin Brandenburg int len = 0; 72244f46410SMartin Brandenburg char *debug_string; 72344f46410SMartin Brandenburg int element_count = 0; 72444f46410SMartin Brandenburg 72544f46410SMartin Brandenburg gossip_debug(GOSSIP_UTILS_DEBUG, "%s: start\n", __func__); 72644f46410SMartin Brandenburg 72744f46410SMartin Brandenburg if (type) { 72844f46410SMartin Brandenburg debug_string = client_debug_string; 72944f46410SMartin Brandenburg element_count = cdm_element_count; 73044f46410SMartin Brandenburg } else { 73144f46410SMartin Brandenburg debug_string = kernel_debug_string; 73244f46410SMartin Brandenburg element_count = num_kmod_keyword_mask_map; 73344f46410SMartin Brandenburg } 73444f46410SMartin Brandenburg 73544f46410SMartin Brandenburg memset(debug_string, 0, ORANGEFS_MAX_DEBUG_STRING_LEN); 73644f46410SMartin Brandenburg 73744f46410SMartin Brandenburg /* 73844f46410SMartin Brandenburg * Some keywords, like "all" or "verbose", are amalgams of 73944f46410SMartin Brandenburg * numerous other keywords. Make a special check for those 74044f46410SMartin Brandenburg * before grinding through the whole mask only to find out 74144f46410SMartin Brandenburg * later... 74244f46410SMartin Brandenburg */ 74344f46410SMartin Brandenburg if (check_amalgam_keyword(mask, type)) 74444f46410SMartin Brandenburg goto out; 74544f46410SMartin Brandenburg 74644f46410SMartin Brandenburg /* Build the debug string. */ 74744f46410SMartin Brandenburg for (i = 0; i < element_count; i++) 74844f46410SMartin Brandenburg if (type) 74944f46410SMartin Brandenburg do_c_string(mask, i); 75044f46410SMartin Brandenburg else 75144f46410SMartin Brandenburg do_k_string(mask, i); 75244f46410SMartin Brandenburg 75344f46410SMartin Brandenburg len = strlen(debug_string); 75444f46410SMartin Brandenburg 75544f46410SMartin Brandenburg if ((len) && (type)) 75644f46410SMartin Brandenburg client_debug_string[len - 1] = '\0'; 75744f46410SMartin Brandenburg else if (len) 75844f46410SMartin Brandenburg kernel_debug_string[len - 1] = '\0'; 75944f46410SMartin Brandenburg else if (type) 76044f46410SMartin Brandenburg strcpy(client_debug_string, "none"); 76144f46410SMartin Brandenburg else 76244f46410SMartin Brandenburg strcpy(kernel_debug_string, "none"); 76344f46410SMartin Brandenburg 76444f46410SMartin Brandenburg out: 76544f46410SMartin Brandenburg gossip_debug(GOSSIP_UTILS_DEBUG, "%s: string:%s:\n", __func__, debug_string); 76644f46410SMartin Brandenburg 76744f46410SMartin Brandenburg return; 76844f46410SMartin Brandenburg 76944f46410SMartin Brandenburg } 77044f46410SMartin Brandenburg 77144f46410SMartin Brandenburg static void do_k_string(void *k_mask, int index) 77244f46410SMartin Brandenburg { 77344f46410SMartin Brandenburg __u64 *mask = (__u64 *) k_mask; 77444f46410SMartin Brandenburg 77544f46410SMartin Brandenburg if (keyword_is_amalgam((char *) s_kmod_keyword_mask_map[index].keyword)) 77644f46410SMartin Brandenburg goto out; 77744f46410SMartin Brandenburg 77844f46410SMartin Brandenburg if (*mask & s_kmod_keyword_mask_map[index].mask_val) { 77944f46410SMartin Brandenburg if ((strlen(kernel_debug_string) + 78044f46410SMartin Brandenburg strlen(s_kmod_keyword_mask_map[index].keyword)) 78144f46410SMartin Brandenburg < ORANGEFS_MAX_DEBUG_STRING_LEN - 1) { 78244f46410SMartin Brandenburg strcat(kernel_debug_string, 78344f46410SMartin Brandenburg s_kmod_keyword_mask_map[index].keyword); 78444f46410SMartin Brandenburg strcat(kernel_debug_string, ","); 78544f46410SMartin Brandenburg } else { 78644f46410SMartin Brandenburg gossip_err("%s: overflow!\n", __func__); 78744f46410SMartin Brandenburg strcpy(kernel_debug_string, ORANGEFS_ALL); 78844f46410SMartin Brandenburg goto out; 78944f46410SMartin Brandenburg } 79044f46410SMartin Brandenburg } 79144f46410SMartin Brandenburg 79244f46410SMartin Brandenburg out: 79344f46410SMartin Brandenburg 79444f46410SMartin Brandenburg return; 79544f46410SMartin Brandenburg } 79644f46410SMartin Brandenburg 79744f46410SMartin Brandenburg static void do_c_string(void *c_mask, int index) 79844f46410SMartin Brandenburg { 79944f46410SMartin Brandenburg struct client_debug_mask *mask = (struct client_debug_mask *) c_mask; 80044f46410SMartin Brandenburg 80144f46410SMartin Brandenburg if (keyword_is_amalgam(cdm_array[index].keyword)) 80244f46410SMartin Brandenburg goto out; 80344f46410SMartin Brandenburg 80444f46410SMartin Brandenburg if ((mask->mask1 & cdm_array[index].mask1) || 80544f46410SMartin Brandenburg (mask->mask2 & cdm_array[index].mask2)) { 80644f46410SMartin Brandenburg if ((strlen(client_debug_string) + 80744f46410SMartin Brandenburg strlen(cdm_array[index].keyword) + 1) 80844f46410SMartin Brandenburg < ORANGEFS_MAX_DEBUG_STRING_LEN - 2) { 80944f46410SMartin Brandenburg strcat(client_debug_string, 81044f46410SMartin Brandenburg cdm_array[index].keyword); 81144f46410SMartin Brandenburg strcat(client_debug_string, ","); 81244f46410SMartin Brandenburg } else { 81344f46410SMartin Brandenburg gossip_err("%s: overflow!\n", __func__); 81444f46410SMartin Brandenburg strcpy(client_debug_string, ORANGEFS_ALL); 81544f46410SMartin Brandenburg goto out; 81644f46410SMartin Brandenburg } 81744f46410SMartin Brandenburg } 81844f46410SMartin Brandenburg out: 81944f46410SMartin Brandenburg return; 82044f46410SMartin Brandenburg } 82144f46410SMartin Brandenburg 82244f46410SMartin Brandenburg static int keyword_is_amalgam(char *keyword) 82344f46410SMartin Brandenburg { 82444f46410SMartin Brandenburg int rc = 0; 82544f46410SMartin Brandenburg 82644f46410SMartin Brandenburg if ((!strcmp(keyword, ORANGEFS_ALL)) || (!strcmp(keyword, ORANGEFS_VERBOSE))) 82744f46410SMartin Brandenburg rc = 1; 82844f46410SMartin Brandenburg 82944f46410SMartin Brandenburg return rc; 83044f46410SMartin Brandenburg } 83144f46410SMartin Brandenburg 83244f46410SMartin Brandenburg /* 83344f46410SMartin Brandenburg * kernel = type 0 83444f46410SMartin Brandenburg * client = type 1 83544f46410SMartin Brandenburg * 83644f46410SMartin Brandenburg * return 1 if we found an amalgam. 83744f46410SMartin Brandenburg */ 83844f46410SMartin Brandenburg static int check_amalgam_keyword(void *mask, int type) 83944f46410SMartin Brandenburg { 84044f46410SMartin Brandenburg __u64 *k_mask; 84144f46410SMartin Brandenburg struct client_debug_mask *c_mask; 84244f46410SMartin Brandenburg int k_all_index = num_kmod_keyword_mask_map - 1; 84344f46410SMartin Brandenburg int rc = 0; 84444f46410SMartin Brandenburg 84544f46410SMartin Brandenburg if (type) { 84644f46410SMartin Brandenburg c_mask = (struct client_debug_mask *) mask; 84744f46410SMartin Brandenburg 84844f46410SMartin Brandenburg if ((c_mask->mask1 == cdm_array[client_all_index].mask1) && 84944f46410SMartin Brandenburg (c_mask->mask2 == cdm_array[client_all_index].mask2)) { 85044f46410SMartin Brandenburg strcpy(client_debug_string, ORANGEFS_ALL); 85144f46410SMartin Brandenburg rc = 1; 85244f46410SMartin Brandenburg goto out; 85344f46410SMartin Brandenburg } 85444f46410SMartin Brandenburg 85544f46410SMartin Brandenburg if ((c_mask->mask1 == cdm_array[client_verbose_index].mask1) && 85644f46410SMartin Brandenburg (c_mask->mask2 == cdm_array[client_verbose_index].mask2)) { 85744f46410SMartin Brandenburg strcpy(client_debug_string, ORANGEFS_VERBOSE); 85844f46410SMartin Brandenburg rc = 1; 85944f46410SMartin Brandenburg goto out; 86044f46410SMartin Brandenburg } 86144f46410SMartin Brandenburg 86244f46410SMartin Brandenburg } else { 86344f46410SMartin Brandenburg k_mask = (__u64 *) mask; 86444f46410SMartin Brandenburg 86544f46410SMartin Brandenburg if (*k_mask >= s_kmod_keyword_mask_map[k_all_index].mask_val) { 86644f46410SMartin Brandenburg strcpy(kernel_debug_string, ORANGEFS_ALL); 86744f46410SMartin Brandenburg rc = 1; 86844f46410SMartin Brandenburg goto out; 86944f46410SMartin Brandenburg } 87044f46410SMartin Brandenburg } 87144f46410SMartin Brandenburg 87244f46410SMartin Brandenburg out: 87344f46410SMartin Brandenburg 87444f46410SMartin Brandenburg return rc; 87544f46410SMartin Brandenburg } 87644f46410SMartin Brandenburg 87744f46410SMartin Brandenburg /* 87844f46410SMartin Brandenburg * kernel = type 0 87944f46410SMartin Brandenburg * client = type 1 88044f46410SMartin Brandenburg */ 88144f46410SMartin Brandenburg static void debug_string_to_mask(char *debug_string, void *mask, int type) 88244f46410SMartin Brandenburg { 88344f46410SMartin Brandenburg char *unchecked_keyword; 88444f46410SMartin Brandenburg int i; 88544f46410SMartin Brandenburg char *strsep_fodder = kstrdup(debug_string, GFP_KERNEL); 88644f46410SMartin Brandenburg char *original_pointer; 88744f46410SMartin Brandenburg int element_count = 0; 88844f46410SMartin Brandenburg struct client_debug_mask *c_mask = NULL; 88944f46410SMartin Brandenburg __u64 *k_mask = NULL; 89044f46410SMartin Brandenburg 89144f46410SMartin Brandenburg gossip_debug(GOSSIP_UTILS_DEBUG, "%s: start\n", __func__); 89244f46410SMartin Brandenburg 89344f46410SMartin Brandenburg if (type) { 89444f46410SMartin Brandenburg c_mask = (struct client_debug_mask *)mask; 89544f46410SMartin Brandenburg element_count = cdm_element_count; 89644f46410SMartin Brandenburg } else { 89744f46410SMartin Brandenburg k_mask = (__u64 *)mask; 89844f46410SMartin Brandenburg *k_mask = 0; 89944f46410SMartin Brandenburg element_count = num_kmod_keyword_mask_map; 90044f46410SMartin Brandenburg } 90144f46410SMartin Brandenburg 90244f46410SMartin Brandenburg original_pointer = strsep_fodder; 90344f46410SMartin Brandenburg while ((unchecked_keyword = strsep(&strsep_fodder, ","))) 90444f46410SMartin Brandenburg if (strlen(unchecked_keyword)) { 90544f46410SMartin Brandenburg for (i = 0; i < element_count; i++) 90644f46410SMartin Brandenburg if (type) 90744f46410SMartin Brandenburg do_c_mask(i, 90844f46410SMartin Brandenburg unchecked_keyword, 90944f46410SMartin Brandenburg &c_mask); 91044f46410SMartin Brandenburg else 91144f46410SMartin Brandenburg do_k_mask(i, 91244f46410SMartin Brandenburg unchecked_keyword, 91344f46410SMartin Brandenburg &k_mask); 91444f46410SMartin Brandenburg } 91544f46410SMartin Brandenburg 91644f46410SMartin Brandenburg kfree(original_pointer); 91744f46410SMartin Brandenburg } 91844f46410SMartin Brandenburg 91944f46410SMartin Brandenburg static void do_c_mask(int i, char *unchecked_keyword, 92044f46410SMartin Brandenburg struct client_debug_mask **sane_mask) 92144f46410SMartin Brandenburg { 92244f46410SMartin Brandenburg 92344f46410SMartin Brandenburg if (!strcmp(cdm_array[i].keyword, unchecked_keyword)) { 92444f46410SMartin Brandenburg (**sane_mask).mask1 = (**sane_mask).mask1 | cdm_array[i].mask1; 92544f46410SMartin Brandenburg (**sane_mask).mask2 = (**sane_mask).mask2 | cdm_array[i].mask2; 92644f46410SMartin Brandenburg } 92744f46410SMartin Brandenburg } 92844f46410SMartin Brandenburg 92944f46410SMartin Brandenburg static void do_k_mask(int i, char *unchecked_keyword, __u64 **sane_mask) 93044f46410SMartin Brandenburg { 93144f46410SMartin Brandenburg 93244f46410SMartin Brandenburg if (!strcmp(s_kmod_keyword_mask_map[i].keyword, unchecked_keyword)) 93344f46410SMartin Brandenburg **sane_mask = (**sane_mask) | 93444f46410SMartin Brandenburg s_kmod_keyword_mask_map[i].mask_val; 93544f46410SMartin Brandenburg } 93644f46410SMartin Brandenburg 93744f46410SMartin Brandenburg int orangefs_debugfs_new_client_mask(void __user *arg) 93844f46410SMartin Brandenburg { 93944f46410SMartin Brandenburg struct dev_mask2_info_s mask2_info = {0}; 94044f46410SMartin Brandenburg int ret; 94144f46410SMartin Brandenburg 94244f46410SMartin Brandenburg ret = copy_from_user(&mask2_info, 94344f46410SMartin Brandenburg (void __user *)arg, 94444f46410SMartin Brandenburg sizeof(struct dev_mask2_info_s)); 94544f46410SMartin Brandenburg 94644f46410SMartin Brandenburg if (ret != 0) 94744f46410SMartin Brandenburg return -EIO; 94844f46410SMartin Brandenburg 94944f46410SMartin Brandenburg client_debug_mask.mask1 = mask2_info.mask1_value; 95044f46410SMartin Brandenburg client_debug_mask.mask2 = mask2_info.mask2_value; 95144f46410SMartin Brandenburg 95244f46410SMartin Brandenburg pr_info("%s: client debug mask has been been received " 95344f46410SMartin Brandenburg ":%llx: :%llx:\n", 95444f46410SMartin Brandenburg __func__, 95544f46410SMartin Brandenburg (unsigned long long)client_debug_mask.mask1, 95644f46410SMartin Brandenburg (unsigned long long)client_debug_mask.mask2); 95744f46410SMartin Brandenburg 95844f46410SMartin Brandenburg return ret; 95944f46410SMartin Brandenburg } 96044f46410SMartin Brandenburg 96144f46410SMartin Brandenburg int orangefs_debugfs_new_client_string(void __user *arg) 96244f46410SMartin Brandenburg { 96344f46410SMartin Brandenburg int ret; 96444f46410SMartin Brandenburg 96544f46410SMartin Brandenburg ret = copy_from_user(&client_debug_array_string, 96644f46410SMartin Brandenburg (void __user *)arg, 96744f46410SMartin Brandenburg ORANGEFS_MAX_DEBUG_STRING_LEN); 968dc033621SMike Marshall 969dc033621SMike Marshall if (ret != 0) { 970dc033621SMike Marshall pr_info("%s: CLIENT_STRING: copy_from_user failed\n", 971dc033621SMike Marshall __func__); 97244f46410SMartin Brandenburg return -EIO; 973dc033621SMike Marshall } 97444f46410SMartin Brandenburg 97544f46410SMartin Brandenburg /* 97644f46410SMartin Brandenburg * The real client-core makes an effort to ensure 97744f46410SMartin Brandenburg * that actual strings that aren't too long to fit in 97844f46410SMartin Brandenburg * this buffer is what we get here. We're going to use 97944f46410SMartin Brandenburg * string functions on the stuff we got, so we'll make 98044f46410SMartin Brandenburg * this extra effort to try and keep from 98144f46410SMartin Brandenburg * flowing out of this buffer when we use the string 98244f46410SMartin Brandenburg * functions, even if somehow the stuff we end up 98344f46410SMartin Brandenburg * with here is garbage. 98444f46410SMartin Brandenburg */ 98544f46410SMartin Brandenburg client_debug_array_string[ORANGEFS_MAX_DEBUG_STRING_LEN - 1] = 98644f46410SMartin Brandenburg '\0'; 98744f46410SMartin Brandenburg 98844f46410SMartin Brandenburg pr_info("%s: client debug array string has been received.\n", 98944f46410SMartin Brandenburg __func__); 99044f46410SMartin Brandenburg 99144f46410SMartin Brandenburg if (!help_string_initialized) { 99244f46410SMartin Brandenburg 993dc033621SMike Marshall /* Build a proper debug help string. */ 99444f46410SMartin Brandenburg if (orangefs_prepare_debugfs_help_string(0)) { 99544f46410SMartin Brandenburg gossip_err("%s: no debug help string \n", 99644f46410SMartin Brandenburg __func__); 99744f46410SMartin Brandenburg return -EIO; 99844f46410SMartin Brandenburg } 99944f46410SMartin Brandenburg 100044f46410SMartin Brandenburg } 100144f46410SMartin Brandenburg 100244f46410SMartin Brandenburg debug_mask_to_string(&client_debug_mask, 1); 100344f46410SMartin Brandenburg 100444f46410SMartin Brandenburg debugfs_remove(client_debug_dentry); 100544f46410SMartin Brandenburg 100644f46410SMartin Brandenburg orangefs_client_debug_init(); 100744f46410SMartin Brandenburg 100844f46410SMartin Brandenburg help_string_initialized++; 100944f46410SMartin Brandenburg 101044f46410SMartin Brandenburg return ret; 101144f46410SMartin Brandenburg } 101244f46410SMartin Brandenburg 101344f46410SMartin Brandenburg int orangefs_debugfs_new_debug(void __user *arg) 101444f46410SMartin Brandenburg { 101544f46410SMartin Brandenburg struct dev_mask_info_s mask_info = {0}; 101644f46410SMartin Brandenburg int ret; 101744f46410SMartin Brandenburg 101844f46410SMartin Brandenburg ret = copy_from_user(&mask_info, 101944f46410SMartin Brandenburg (void __user *)arg, 102044f46410SMartin Brandenburg sizeof(mask_info)); 102144f46410SMartin Brandenburg 102244f46410SMartin Brandenburg if (ret != 0) 102344f46410SMartin Brandenburg return -EIO; 102444f46410SMartin Brandenburg 102544f46410SMartin Brandenburg if (mask_info.mask_type == KERNEL_MASK) { 102644f46410SMartin Brandenburg if ((mask_info.mask_value == 0) 102744f46410SMartin Brandenburg && (kernel_mask_set_mod_init)) { 102844f46410SMartin Brandenburg /* 102944f46410SMartin Brandenburg * the kernel debug mask was set when the 103044f46410SMartin Brandenburg * kernel module was loaded; don't override 103144f46410SMartin Brandenburg * it if the client-core was started without 103244f46410SMartin Brandenburg * a value for ORANGEFS_KMODMASK. 103344f46410SMartin Brandenburg */ 103444f46410SMartin Brandenburg return 0; 103544f46410SMartin Brandenburg } 103644f46410SMartin Brandenburg debug_mask_to_string(&mask_info.mask_value, 103744f46410SMartin Brandenburg mask_info.mask_type); 103844f46410SMartin Brandenburg orangefs_gossip_debug_mask = mask_info.mask_value; 103944f46410SMartin Brandenburg pr_info("%s: kernel debug mask has been modified to " 104044f46410SMartin Brandenburg ":%s: :%llx:\n", 104144f46410SMartin Brandenburg __func__, 104244f46410SMartin Brandenburg kernel_debug_string, 104344f46410SMartin Brandenburg (unsigned long long)orangefs_gossip_debug_mask); 104444f46410SMartin Brandenburg } else if (mask_info.mask_type == CLIENT_MASK) { 104544f46410SMartin Brandenburg debug_mask_to_string(&mask_info.mask_value, 104644f46410SMartin Brandenburg mask_info.mask_type); 104744f46410SMartin Brandenburg pr_info("%s: client debug mask has been modified to" 104844f46410SMartin Brandenburg ":%s: :%llx:\n", 104944f46410SMartin Brandenburg __func__, 105044f46410SMartin Brandenburg client_debug_string, 105144f46410SMartin Brandenburg llu(mask_info.mask_value)); 105244f46410SMartin Brandenburg } else { 105344f46410SMartin Brandenburg gossip_lerr("Invalid mask type....\n"); 105444f46410SMartin Brandenburg return -EINVAL; 105544f46410SMartin Brandenburg } 105644f46410SMartin Brandenburg 105744f46410SMartin Brandenburg return ret; 105844f46410SMartin Brandenburg } 1059