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 size_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 pr_info("%s: overflow 1!\n", __func__); 250 } 251 252 debugfs_create_file_aux_num(ORANGEFS_KMOD_DEBUG_FILE, 0444, debug_dir, k_buffer, 253 0, &kernel_debug_fops); 254 } 255 256 257 void orangefs_debugfs_cleanup(void) 258 { 259 debugfs_remove_recursive(debug_dir); 260 kfree(debug_help_string); 261 debug_help_string = NULL; 262 } 263 264 /* open ORANGEFS_KMOD_DEBUG_HELP_FILE */ 265 static int orangefs_debug_help_open(struct inode *inode, struct file *file) 266 { 267 int rc = -ENODEV; 268 int ret; 269 270 gossip_debug(GOSSIP_DEBUGFS_DEBUG, 271 "orangefs_debug_help_open: start\n"); 272 273 if (orangefs_debug_disabled) 274 goto out; 275 276 ret = seq_open(file, &help_debug_ops); 277 if (ret) 278 goto out; 279 280 ((struct seq_file *)(file->private_data))->private = inode->i_private; 281 282 rc = 0; 283 284 out: 285 gossip_debug(GOSSIP_DEBUGFS_DEBUG, 286 "orangefs_debug_help_open: rc:%d:\n", 287 rc); 288 return rc; 289 } 290 291 /* 292 * I think start always gets called again after stop. Start 293 * needs to return NULL when it is done. The whole "payload" 294 * in this case is a single (long) string, so by the second 295 * time we get to start (pos = 1), we're done. 296 */ 297 static void *help_start(struct seq_file *m, loff_t *pos) 298 { 299 void *payload = NULL; 300 301 gossip_debug(GOSSIP_DEBUGFS_DEBUG, "help_start: start\n"); 302 303 mutex_lock(&orangefs_help_file_lock); 304 305 if (*pos == 0) 306 payload = m->private; 307 308 return payload; 309 } 310 311 static void *help_next(struct seq_file *m, void *v, loff_t *pos) 312 { 313 (*pos)++; 314 gossip_debug(GOSSIP_DEBUGFS_DEBUG, "help_next: start\n"); 315 316 return NULL; 317 } 318 319 static void help_stop(struct seq_file *m, void *p) 320 { 321 gossip_debug(GOSSIP_DEBUGFS_DEBUG, "help_stop: start\n"); 322 mutex_unlock(&orangefs_help_file_lock); 323 } 324 325 static int help_show(struct seq_file *m, void *v) 326 { 327 gossip_debug(GOSSIP_DEBUGFS_DEBUG, "help_show: start\n"); 328 329 seq_puts(m, v); 330 331 return 0; 332 } 333 334 /* 335 * initialize the client-debug file. 336 */ 337 static void orangefs_client_debug_init(void) 338 { 339 static char c_buffer[ORANGEFS_MAX_DEBUG_STRING_LEN] = { }; 340 size_t len = 341 strscpy(c_buffer, client_debug_string, sizeof(c_buffer) - 1); 342 343 if (len > 0) { 344 c_buffer[len] = '\n'; 345 c_buffer[len + 1] = '\0'; 346 } else { 347 strscpy(c_buffer, "none\n"); 348 pr_info("%s: overflow! 2\n", __func__); 349 } 350 351 client_debug_dentry = debugfs_create_file_aux_num( 352 ORANGEFS_CLIENT_DEBUG_FILE, 353 0444, debug_dir, c_buffer, 1, 354 &kernel_debug_fops); 355 } 356 357 /* open ORANGEFS_KMOD_DEBUG_FILE or ORANGEFS_CLIENT_DEBUG_FILE.*/ 358 static int orangefs_debug_open(struct inode *inode, struct file *file) 359 { 360 int rc = -ENODEV; 361 362 gossip_debug(GOSSIP_DEBUGFS_DEBUG, 363 "%s: orangefs_debug_disabled: %d\n", 364 __func__, 365 orangefs_debug_disabled); 366 367 if (orangefs_debug_disabled) 368 goto out; 369 370 rc = 0; 371 mutex_lock(&orangefs_debug_lock); 372 file->private_data = inode->i_private; 373 mutex_unlock(&orangefs_debug_lock); 374 375 out: 376 gossip_debug(GOSSIP_DEBUGFS_DEBUG, 377 "orangefs_debug_open: rc: %d\n", 378 rc); 379 return rc; 380 } 381 382 static ssize_t orangefs_debug_read(struct file *file, 383 char __user *ubuf, 384 size_t count, 385 loff_t *ppos) 386 { 387 char *buf; 388 int sprintf_ret; 389 ssize_t read_ret = -ENOMEM; 390 391 gossip_debug(GOSSIP_DEBUGFS_DEBUG, "orangefs_debug_read: start\n"); 392 393 buf = kmalloc(ORANGEFS_MAX_DEBUG_STRING_LEN, GFP_KERNEL); 394 if (!buf) 395 goto out; 396 397 mutex_lock(&orangefs_debug_lock); 398 sprintf_ret = scnprintf(buf, ORANGEFS_MAX_DEBUG_STRING_LEN, "%s", (char *)file->private_data); 399 mutex_unlock(&orangefs_debug_lock); 400 401 read_ret = simple_read_from_buffer(ubuf, count, ppos, buf, sprintf_ret); 402 403 kfree(buf); 404 405 out: 406 gossip_debug(GOSSIP_DEBUGFS_DEBUG, 407 "orangefs_debug_read: ret: %zu\n", 408 read_ret); 409 410 return read_ret; 411 } 412 413 static ssize_t orangefs_debug_write(struct file *file, 414 const char __user *ubuf, 415 size_t count, 416 loff_t *ppos) 417 { 418 char *buf; 419 int rc = -EFAULT; 420 size_t silly = 0; 421 char *debug_string; 422 struct orangefs_kernel_op_s *new_op = NULL; 423 struct client_debug_mask c_mask = { NULL, 0, 0 }; 424 char *s; 425 426 gossip_debug(GOSSIP_DEBUGFS_DEBUG, 427 "orangefs_debug_write: %pD\n", 428 file); 429 430 if (count == 0) 431 return 0; 432 433 /* 434 * Thwart users who try to jamb a ridiculous number 435 * of bytes into the debug file... 436 */ 437 if (count > ORANGEFS_MAX_DEBUG_STRING_LEN) { 438 silly = count; 439 count = ORANGEFS_MAX_DEBUG_STRING_LEN; 440 } 441 442 buf = memdup_user_nul(ubuf, count); 443 if (IS_ERR(buf)) { 444 gossip_debug(GOSSIP_DEBUGFS_DEBUG, 445 "%s: memdup_user_nul failed!\n", 446 __func__); 447 rc = PTR_ERR(buf); 448 buf = NULL; 449 goto out; 450 } 451 strim(buf); 452 453 /* 454 * Map the keyword string from userspace into a valid debug mask. 455 * The mapping process involves mapping the human-inputted string 456 * into a valid mask, and then rebuilding the string from the 457 * verified valid mask. 458 * 459 * A service operation is required to set a new client-side 460 * debug mask. 461 */ 462 if (!debugfs_get_aux_num(file)) { // kernel-debug 463 debug_string_to_mask(buf, &orangefs_gossip_debug_mask, 0); 464 debug_mask_to_string(&orangefs_gossip_debug_mask, 0); 465 debug_string = kernel_debug_string; 466 gossip_debug(GOSSIP_DEBUGFS_DEBUG, 467 "New kernel debug string is %s\n", 468 kernel_debug_string); 469 } else { 470 /* Can't reset client debug mask if client is not running. */ 471 if (is_daemon_in_service()) { 472 pr_info("%s: Client not running :%d:\n", 473 __func__, 474 is_daemon_in_service()); 475 goto out; 476 } 477 478 debug_string_to_mask(buf, &c_mask, 1); 479 debug_mask_to_string(&c_mask, 1); 480 debug_string = client_debug_string; 481 482 new_op = op_alloc(ORANGEFS_VFS_OP_PARAM); 483 if (!new_op) { 484 pr_info("%s: op_alloc failed!\n", __func__); 485 goto out; 486 } 487 488 new_op->upcall.req.param.op = 489 ORANGEFS_PARAM_REQUEST_OP_TWO_MASK_VALUES; 490 new_op->upcall.req.param.type = ORANGEFS_PARAM_REQUEST_SET; 491 memset(new_op->upcall.req.param.s_value, 492 0, 493 ORANGEFS_MAX_DEBUG_STRING_LEN); 494 sprintf(new_op->upcall.req.param.s_value, 495 "%llx %llx\n", 496 c_mask.mask1, 497 c_mask.mask2); 498 499 /* service_operation returns 0 on success... */ 500 rc = service_operation(new_op, 501 "orangefs_param", 502 ORANGEFS_OP_INTERRUPTIBLE); 503 504 if (rc) 505 gossip_debug(GOSSIP_DEBUGFS_DEBUG, 506 "%s: service_operation failed! rc:%d:\n", 507 __func__, 508 rc); 509 510 op_release(new_op); 511 } 512 513 mutex_lock(&orangefs_debug_lock); 514 s = file_inode(file)->i_private; 515 memset(s, 0, ORANGEFS_MAX_DEBUG_STRING_LEN); 516 sprintf(s, "%s\n", debug_string); 517 mutex_unlock(&orangefs_debug_lock); 518 519 *ppos += count; 520 if (silly) 521 rc = silly; 522 else 523 rc = count; 524 525 out: 526 gossip_debug(GOSSIP_DEBUGFS_DEBUG, 527 "orangefs_debug_write: rc: %d\n", 528 rc); 529 kfree(buf); 530 return rc; 531 } 532 533 /* 534 * After obtaining a string representation of the client's debug 535 * keywords and their associated masks, this function is called to build an 536 * array of these values. 537 */ 538 static int orangefs_prepare_cdm_array(char *debug_array_string) 539 { 540 int i; 541 int rc = -EINVAL; 542 char *cds_head = NULL; 543 char *cds_delimiter = NULL; 544 int keyword_len = 0; 545 546 gossip_debug(GOSSIP_UTILS_DEBUG, "%s: start\n", __func__); 547 548 /* 549 * figure out how many elements the cdm_array needs. 550 */ 551 for (i = 0; i < strlen(debug_array_string); i++) 552 if (debug_array_string[i] == '\n') 553 cdm_element_count++; 554 555 if (!cdm_element_count) { 556 pr_info("No elements in client debug array string!\n"); 557 goto out; 558 } 559 560 cdm_array = kzalloc_objs(*cdm_array, cdm_element_count); 561 if (!cdm_array) { 562 rc = -ENOMEM; 563 goto out; 564 } 565 566 cds_head = debug_array_string; 567 568 for (i = 0; i < cdm_element_count; i++) { 569 cds_delimiter = strchr(cds_head, '\n'); 570 *cds_delimiter = '\0'; 571 572 keyword_len = strcspn(cds_head, " "); 573 574 cdm_array[i].keyword = kzalloc(keyword_len + 1, GFP_KERNEL); 575 if (!cdm_array[i].keyword) { 576 rc = -ENOMEM; 577 goto out; 578 } 579 580 sscanf(cds_head, 581 "%s %llx %llx", 582 cdm_array[i].keyword, 583 (unsigned long long *)&(cdm_array[i].mask1), 584 (unsigned long long *)&(cdm_array[i].mask2)); 585 586 if (!strcmp(cdm_array[i].keyword, ORANGEFS_VERBOSE)) 587 client_verbose_index = i; 588 589 if (!strcmp(cdm_array[i].keyword, ORANGEFS_ALL)) 590 client_all_index = i; 591 592 cds_head = cds_delimiter + 1; 593 } 594 595 rc = cdm_element_count; 596 597 gossip_debug(GOSSIP_UTILS_DEBUG, "%s: rc:%d:\n", __func__, rc); 598 599 out: 600 601 return rc; 602 603 } 604 605 /* 606 * /sys/kernel/debug/orangefs/debug-help can be catted to 607 * see all the available kernel and client debug keywords. 608 * 609 * When orangefs.ko initializes, we have no idea what keywords the 610 * client supports, nor their associated masks. 611 * 612 * We pass through this function once at module-load and stamp a 613 * boilerplate "we don't know" message for the client in the 614 * debug-help file. We pass through here again when the client 615 * starts and then we can fill out the debug-help file fully. 616 * 617 * The client might be restarted any number of times between 618 * module reloads, we only build the debug-help file the first time. 619 */ 620 int orangefs_prepare_debugfs_help_string(int at_boot) 621 { 622 char *client_title = "Client Debug Keywords:\n"; 623 char *kernel_title = "Kernel Debug Keywords:\n"; 624 size_t string_size = DEBUG_HELP_STRING_SIZE; 625 size_t result_size; 626 size_t i; 627 char *new; 628 int rc = -EINVAL; 629 630 gossip_debug(GOSSIP_UTILS_DEBUG, "%s: start\n", __func__); 631 632 if (at_boot) 633 client_title = HELP_STRING_UNINITIALIZED; 634 635 /* build a new debug_help_string. */ 636 new = kzalloc(DEBUG_HELP_STRING_SIZE, GFP_KERNEL); 637 if (!new) { 638 rc = -ENOMEM; 639 goto out; 640 } 641 642 /* 643 * strlcat(dst, src, size) will append at most 644 * "size - strlen(dst) - 1" bytes of src onto dst, 645 * null terminating the result, and return the total 646 * length of the string it tried to create. 647 * 648 * We'll just plow through here building our new debug 649 * help string and let strlcat take care of assuring that 650 * dst doesn't overflow. 651 */ 652 strlcat(new, client_title, string_size); 653 654 if (!at_boot) { 655 656 /* 657 * fill the client keyword/mask array and remember 658 * how many elements there were. 659 */ 660 cdm_element_count = 661 orangefs_prepare_cdm_array(client_debug_array_string); 662 if (cdm_element_count <= 0) { 663 kfree(new); 664 goto out; 665 } 666 667 for (i = 0; i < cdm_element_count; i++) { 668 strlcat(new, "\t", string_size); 669 strlcat(new, cdm_array[i].keyword, string_size); 670 strlcat(new, "\n", string_size); 671 } 672 } 673 674 strlcat(new, "\n", string_size); 675 strlcat(new, kernel_title, string_size); 676 677 for (i = 0; i < num_kmod_keyword_mask_map; i++) { 678 strlcat(new, "\t", string_size); 679 strlcat(new, s_kmod_keyword_mask_map[i].keyword, string_size); 680 result_size = strlcat(new, "\n", string_size); 681 } 682 683 /* See if we tried to put too many bytes into "new"... */ 684 if (result_size >= string_size) { 685 kfree(new); 686 goto out; 687 } 688 689 if (at_boot) { 690 debug_help_string = new; 691 } else { 692 mutex_lock(&orangefs_help_file_lock); 693 memset(debug_help_string, 0, DEBUG_HELP_STRING_SIZE); 694 strlcat(debug_help_string, new, string_size); 695 mutex_unlock(&orangefs_help_file_lock); 696 kfree(new); 697 } 698 699 rc = 0; 700 701 out: return rc; 702 703 } 704 705 /* 706 * kernel = type 0 707 * client = type 1 708 */ 709 static void debug_mask_to_string(void *mask, int type) 710 { 711 int i; 712 int len = 0; 713 char *debug_string; 714 int element_count = 0; 715 716 gossip_debug(GOSSIP_UTILS_DEBUG, "%s: start\n", __func__); 717 718 if (type) { 719 debug_string = client_debug_string; 720 element_count = cdm_element_count; 721 } else { 722 debug_string = kernel_debug_string; 723 element_count = num_kmod_keyword_mask_map; 724 } 725 726 memset(debug_string, 0, ORANGEFS_MAX_DEBUG_STRING_LEN); 727 728 /* 729 * Some keywords, like "all" or "verbose", are amalgams of 730 * numerous other keywords. Make a special check for those 731 * before grinding through the whole mask only to find out 732 * later... 733 */ 734 if (check_amalgam_keyword(mask, type)) 735 goto out; 736 737 /* Build the debug string. */ 738 for (i = 0; i < element_count; i++) 739 if (type) 740 do_c_string(mask, i); 741 else 742 do_k_string(mask, i); 743 744 len = strlen(debug_string); 745 746 if ((len) && (type)) 747 client_debug_string[len - 1] = '\0'; 748 else if (len) 749 kernel_debug_string[len - 1] = '\0'; 750 else if (type) 751 strscpy(client_debug_string, "none"); 752 else 753 strscpy(kernel_debug_string, "none"); 754 755 out: 756 gossip_debug(GOSSIP_UTILS_DEBUG, "%s: string:%s:\n", __func__, debug_string); 757 758 return; 759 } 760 761 static void do_k_string(void *k_mask, int index) 762 { 763 __u64 *mask = (__u64 *) k_mask; 764 765 if (keyword_is_amalgam((char *) s_kmod_keyword_mask_map[index].keyword)) 766 goto out; 767 768 if (*mask & s_kmod_keyword_mask_map[index].mask_val) { 769 if ((strlen(kernel_debug_string) + 770 strlen(s_kmod_keyword_mask_map[index].keyword) + 1) 771 < ORANGEFS_MAX_DEBUG_STRING_LEN) { 772 strcat(kernel_debug_string, 773 s_kmod_keyword_mask_map[index].keyword); 774 strcat(kernel_debug_string, ","); 775 } else { 776 gossip_err("%s: overflow!\n", __func__); 777 strscpy(kernel_debug_string, ORANGEFS_ALL); 778 goto out; 779 } 780 } 781 782 out: 783 784 return; 785 } 786 787 static void do_c_string(void *c_mask, int index) 788 { 789 struct client_debug_mask *mask = (struct client_debug_mask *) c_mask; 790 791 if (keyword_is_amalgam(cdm_array[index].keyword)) 792 goto out; 793 794 if ((mask->mask1 & cdm_array[index].mask1) || 795 (mask->mask2 & cdm_array[index].mask2)) { 796 if ((strlen(client_debug_string) + 797 strlen(cdm_array[index].keyword) + 1) 798 < ORANGEFS_MAX_DEBUG_STRING_LEN) { 799 strcat(client_debug_string, 800 cdm_array[index].keyword); 801 strcat(client_debug_string, ","); 802 } else { 803 gossip_err("%s: overflow!\n", __func__); 804 strscpy(client_debug_string, ORANGEFS_ALL); 805 goto out; 806 } 807 } 808 out: 809 return; 810 } 811 812 static int keyword_is_amalgam(char *keyword) 813 { 814 int rc = 0; 815 816 if ((!strcmp(keyword, ORANGEFS_ALL)) || (!strcmp(keyword, ORANGEFS_VERBOSE))) 817 rc = 1; 818 819 return rc; 820 } 821 822 /* 823 * kernel = type 0 824 * client = type 1 825 * 826 * return 1 if we found an amalgam. 827 */ 828 static int check_amalgam_keyword(void *mask, int type) 829 { 830 __u64 *k_mask; 831 struct client_debug_mask *c_mask; 832 int k_all_index = num_kmod_keyword_mask_map - 1; 833 int rc = 0; 834 835 if (type) { 836 c_mask = (struct client_debug_mask *) mask; 837 838 if ((c_mask->mask1 == cdm_array[client_all_index].mask1) && 839 (c_mask->mask2 == cdm_array[client_all_index].mask2)) { 840 strscpy(client_debug_string, ORANGEFS_ALL); 841 rc = 1; 842 goto out; 843 } 844 845 if ((c_mask->mask1 == cdm_array[client_verbose_index].mask1) && 846 (c_mask->mask2 == cdm_array[client_verbose_index].mask2)) { 847 strscpy(client_debug_string, ORANGEFS_VERBOSE); 848 rc = 1; 849 goto out; 850 } 851 852 } else { 853 k_mask = (__u64 *) mask; 854 855 if (*k_mask >= s_kmod_keyword_mask_map[k_all_index].mask_val) { 856 strscpy(kernel_debug_string, ORANGEFS_ALL); 857 rc = 1; 858 goto out; 859 } 860 } 861 862 out: 863 864 return rc; 865 } 866 867 /* 868 * kernel = type 0 869 * client = type 1 870 */ 871 static void debug_string_to_mask(char *debug_string, void *mask, int type) 872 { 873 int i; 874 char *strsep_fodder = kstrdup(debug_string, GFP_KERNEL); 875 char *trimmed; 876 char *token; 877 char *original_pointer; 878 int element_count = 0; 879 struct client_debug_mask *c_mask = NULL; 880 __u64 *k_mask = NULL; 881 882 gossip_debug(GOSSIP_UTILS_DEBUG, "%s: start\n", __func__); 883 884 if (type) { 885 c_mask = (struct client_debug_mask *)mask; 886 element_count = cdm_element_count; 887 } else { 888 k_mask = (__u64 *)mask; 889 *k_mask = 0; 890 element_count = num_kmod_keyword_mask_map; 891 } 892 893 original_pointer = strsep_fodder; 894 while ((token = strsep(&strsep_fodder, ",")) != NULL) { 895 trimmed = strim(token); 896 if (*trimmed) { 897 for (i = 0; i < element_count; i++) 898 if (type) 899 do_c_mask(i, trimmed, &c_mask); 900 else 901 do_k_mask(i, trimmed, &k_mask); 902 903 } 904 } 905 906 kfree(original_pointer); 907 } 908 909 static void do_c_mask(int i, char *unchecked_keyword, 910 struct client_debug_mask **sane_mask) 911 { 912 913 if (!strcmp(cdm_array[i].keyword, unchecked_keyword)) { 914 (**sane_mask).mask1 = (**sane_mask).mask1 | cdm_array[i].mask1; 915 (**sane_mask).mask2 = (**sane_mask).mask2 | cdm_array[i].mask2; 916 } 917 } 918 919 static void do_k_mask(int i, char *unchecked_keyword, __u64 **sane_mask) 920 { 921 922 if (!strcmp(s_kmod_keyword_mask_map[i].keyword, unchecked_keyword)) 923 **sane_mask = (**sane_mask) | 924 s_kmod_keyword_mask_map[i].mask_val; 925 } 926 927 int orangefs_debugfs_new_client_mask(void __user *arg) 928 { 929 struct dev_mask2_info_s mask2_info = {0}; 930 int ret; 931 932 ret = copy_from_user(&mask2_info, 933 (void __user *)arg, 934 sizeof(struct dev_mask2_info_s)); 935 936 if (ret != 0) 937 return -EIO; 938 939 client_debug_mask.mask1 = mask2_info.mask1_value; 940 client_debug_mask.mask2 = mask2_info.mask2_value; 941 942 pr_info("%s: client debug mask has been been received " 943 ":%llx: :%llx:\n", 944 __func__, 945 (unsigned long long)client_debug_mask.mask1, 946 (unsigned long long)client_debug_mask.mask2); 947 948 return ret; 949 } 950 951 int orangefs_debugfs_new_client_string(void __user *arg) 952 { 953 int ret; 954 955 ret = copy_from_user(&client_debug_array_string, 956 (void __user *)arg, 957 ORANGEFS_MAX_DEBUG_STRING_LEN); 958 959 if (ret != 0) { 960 pr_info("%s: CLIENT_STRING: copy_from_user failed\n", 961 __func__); 962 return -EFAULT; 963 } 964 965 /* 966 * The real client-core makes an effort to ensure 967 * that actual strings that aren't too long to fit in 968 * this buffer is what we get here. We're going to use 969 * string functions on the stuff we got, so we'll make 970 * this extra effort to try and keep from 971 * flowing out of this buffer when we use the string 972 * functions, even if somehow the stuff we end up 973 * with here is garbage. 974 */ 975 client_debug_array_string[ORANGEFS_MAX_DEBUG_STRING_LEN - 1] = 976 '\0'; 977 978 pr_info("%s: client debug array string has been received.\n", 979 __func__); 980 981 if (!help_string_initialized) { 982 983 /* Build a proper debug help string. */ 984 ret = orangefs_prepare_debugfs_help_string(0); 985 if (ret) { 986 gossip_err("%s: no debug help string \n", 987 __func__); 988 return ret; 989 } 990 991 } 992 993 debug_mask_to_string(&client_debug_mask, 1); 994 995 debugfs_remove(client_debug_dentry); 996 997 orangefs_client_debug_init(); 998 999 help_string_initialized++; 1000 1001 return 0; 1002 } 1003 1004 int orangefs_debugfs_new_debug(void __user *arg) 1005 { 1006 struct dev_mask_info_s mask_info = {0}; 1007 int ret; 1008 1009 ret = copy_from_user(&mask_info, 1010 (void __user *)arg, 1011 sizeof(mask_info)); 1012 1013 if (ret != 0) 1014 return -EIO; 1015 1016 if (mask_info.mask_type == KERNEL_MASK) { 1017 if ((mask_info.mask_value == 0) 1018 && (kernel_mask_set_mod_init)) { 1019 /* 1020 * the kernel debug mask was set when the 1021 * kernel module was loaded; don't override 1022 * it if the client-core was started without 1023 * a value for ORANGEFS_KMODMASK. 1024 */ 1025 return 0; 1026 } 1027 debug_mask_to_string(&mask_info.mask_value, 1028 mask_info.mask_type); 1029 orangefs_gossip_debug_mask = mask_info.mask_value; 1030 pr_info("%s: kernel debug mask has been modified to " 1031 ":%s: :%llx:\n", 1032 __func__, 1033 kernel_debug_string, 1034 (unsigned long long)orangefs_gossip_debug_mask); 1035 } else if (mask_info.mask_type == CLIENT_MASK) { 1036 debug_mask_to_string(&mask_info.mask_value, 1037 mask_info.mask_type); 1038 pr_info("%s: client debug mask has been modified to" 1039 ":%s: :%llx:\n", 1040 __func__, 1041 client_debug_string, 1042 llu(mask_info.mask_value)); 1043 } else { 1044 gossip_err("Invalid mask type....\n"); 1045 return -EINVAL; 1046 } 1047 1048 return ret; 1049 } 1050