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