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