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 = strlen(kernel_debug_string); 242 243 gossip_debug(GOSSIP_DEBUGFS_DEBUG, "%s: start\n", __func__); 244 245 if (len + 1 < ORANGEFS_MAX_DEBUG_STRING_LEN) { 246 memcpy(k_buffer, kernel_debug_string, len); 247 k_buffer[len] = '\n'; 248 k_buffer[len + 1] = '\0'; 249 } else { 250 strscpy(k_buffer, "none\n"); 251 pr_info("%s: overflow 1!\n", __func__); 252 } 253 254 debugfs_create_file_aux_num(ORANGEFS_KMOD_DEBUG_FILE, 0444, debug_dir, k_buffer, 255 0, &kernel_debug_fops); 256 } 257 258 259 void orangefs_debugfs_cleanup(void) 260 { 261 debugfs_remove_recursive(debug_dir); 262 kfree(debug_help_string); 263 debug_help_string = NULL; 264 } 265 266 /* open ORANGEFS_KMOD_DEBUG_HELP_FILE */ 267 static int orangefs_debug_help_open(struct inode *inode, struct file *file) 268 { 269 int rc = -ENODEV; 270 int ret; 271 272 gossip_debug(GOSSIP_DEBUGFS_DEBUG, 273 "orangefs_debug_help_open: start\n"); 274 275 if (orangefs_debug_disabled) 276 goto out; 277 278 ret = seq_open(file, &help_debug_ops); 279 if (ret) 280 goto out; 281 282 ((struct seq_file *)(file->private_data))->private = inode->i_private; 283 284 rc = 0; 285 286 out: 287 gossip_debug(GOSSIP_DEBUGFS_DEBUG, 288 "orangefs_debug_help_open: rc:%d:\n", 289 rc); 290 return rc; 291 } 292 293 /* 294 * I think start always gets called again after stop. Start 295 * needs to return NULL when it is done. The whole "payload" 296 * in this case is a single (long) string, so by the second 297 * time we get to start (pos = 1), we're done. 298 */ 299 static void *help_start(struct seq_file *m, loff_t *pos) 300 { 301 void *payload = NULL; 302 303 gossip_debug(GOSSIP_DEBUGFS_DEBUG, "help_start: start\n"); 304 305 mutex_lock(&orangefs_help_file_lock); 306 307 if (*pos == 0) 308 payload = m->private; 309 310 return payload; 311 } 312 313 static void *help_next(struct seq_file *m, void *v, loff_t *pos) 314 { 315 (*pos)++; 316 gossip_debug(GOSSIP_DEBUGFS_DEBUG, "help_next: start\n"); 317 318 return NULL; 319 } 320 321 static void help_stop(struct seq_file *m, void *p) 322 { 323 gossip_debug(GOSSIP_DEBUGFS_DEBUG, "help_stop: start\n"); 324 mutex_unlock(&orangefs_help_file_lock); 325 } 326 327 static int help_show(struct seq_file *m, void *v) 328 { 329 gossip_debug(GOSSIP_DEBUGFS_DEBUG, "help_show: start\n"); 330 331 seq_puts(m, v); 332 333 return 0; 334 } 335 336 /* 337 * initialize the client-debug file. 338 */ 339 static void orangefs_client_debug_init(void) 340 { 341 static char c_buffer[ORANGEFS_MAX_DEBUG_STRING_LEN] = { }; 342 size_t len = strlen(client_debug_string); 343 344 gossip_debug(GOSSIP_DEBUGFS_DEBUG, "%s: start\n", __func__); 345 346 if (len + 1 < ORANGEFS_MAX_DEBUG_STRING_LEN) { 347 memcpy(c_buffer, client_debug_string, len); 348 c_buffer[len] = '\n'; 349 c_buffer[len + 1] = '\0'; 350 } else { 351 strscpy(c_buffer, "none\n"); 352 pr_info("%s: overflow! 2\n", __func__); 353 } 354 355 client_debug_dentry = debugfs_create_file_aux_num( 356 ORANGEFS_CLIENT_DEBUG_FILE, 357 0444, debug_dir, c_buffer, 1, 358 &kernel_debug_fops); 359 } 360 361 /* open ORANGEFS_KMOD_DEBUG_FILE or ORANGEFS_CLIENT_DEBUG_FILE.*/ 362 static int orangefs_debug_open(struct inode *inode, struct file *file) 363 { 364 int rc = -ENODEV; 365 366 gossip_debug(GOSSIP_DEBUGFS_DEBUG, 367 "%s: orangefs_debug_disabled: %d\n", 368 __func__, 369 orangefs_debug_disabled); 370 371 if (orangefs_debug_disabled) 372 goto out; 373 374 rc = 0; 375 mutex_lock(&orangefs_debug_lock); 376 file->private_data = inode->i_private; 377 mutex_unlock(&orangefs_debug_lock); 378 379 out: 380 gossip_debug(GOSSIP_DEBUGFS_DEBUG, 381 "orangefs_debug_open: rc: %d\n", 382 rc); 383 return rc; 384 } 385 386 static ssize_t orangefs_debug_read(struct file *file, 387 char __user *ubuf, 388 size_t count, 389 loff_t *ppos) 390 { 391 char *buf; 392 int sprintf_ret; 393 ssize_t read_ret = -ENOMEM; 394 395 gossip_debug(GOSSIP_DEBUGFS_DEBUG, "orangefs_debug_read: start\n"); 396 397 buf = kmalloc(ORANGEFS_MAX_DEBUG_STRING_LEN, GFP_KERNEL); 398 if (!buf) 399 goto out; 400 401 mutex_lock(&orangefs_debug_lock); 402 sprintf_ret = scnprintf(buf, ORANGEFS_MAX_DEBUG_STRING_LEN, "%s", (char *)file->private_data); 403 mutex_unlock(&orangefs_debug_lock); 404 405 read_ret = simple_read_from_buffer(ubuf, count, ppos, buf, sprintf_ret); 406 407 kfree(buf); 408 409 out: 410 gossip_debug(GOSSIP_DEBUGFS_DEBUG, 411 "orangefs_debug_read: ret: %zu\n", 412 read_ret); 413 414 return read_ret; 415 } 416 417 static ssize_t orangefs_debug_write(struct file *file, 418 const char __user *ubuf, 419 size_t count, 420 loff_t *ppos) 421 { 422 char *buf; 423 int rc = -EFAULT; 424 size_t silly = 0; 425 char *debug_string; 426 struct orangefs_kernel_op_s *new_op = NULL; 427 struct client_debug_mask c_mask = { NULL, 0, 0 }; 428 char *s; 429 430 gossip_debug(GOSSIP_DEBUGFS_DEBUG, 431 "orangefs_debug_write: %pD\n", 432 file); 433 434 if (count == 0) 435 return 0; 436 437 /* 438 * Thwart users who try to jamb a ridiculous number 439 * of bytes into the debug file... 440 */ 441 if (count > ORANGEFS_MAX_DEBUG_STRING_LEN) { 442 silly = count; 443 count = ORANGEFS_MAX_DEBUG_STRING_LEN; 444 } 445 446 buf = memdup_user_nul(ubuf, count - 1); 447 if (IS_ERR(buf)) { 448 gossip_debug(GOSSIP_DEBUGFS_DEBUG, 449 "%s: memdup_user_nul failed!\n", 450 __func__); 451 rc = PTR_ERR(buf); 452 buf = NULL; 453 goto out; 454 } 455 456 /* 457 * Map the keyword string from userspace into a valid debug mask. 458 * The mapping process involves mapping the human-inputted string 459 * into a valid mask, and then rebuilding the string from the 460 * verified valid mask. 461 * 462 * A service operation is required to set a new client-side 463 * debug mask. 464 */ 465 if (!debugfs_get_aux_num(file)) { // kernel-debug 466 debug_string_to_mask(buf, &orangefs_gossip_debug_mask, 0); 467 debug_mask_to_string(&orangefs_gossip_debug_mask, 0); 468 debug_string = kernel_debug_string; 469 gossip_debug(GOSSIP_DEBUGFS_DEBUG, 470 "New kernel debug string is %s\n", 471 kernel_debug_string); 472 } else { 473 /* Can't reset client debug mask if client is not running. */ 474 if (is_daemon_in_service()) { 475 pr_info("%s: Client not running :%d:\n", 476 __func__, 477 is_daemon_in_service()); 478 goto out; 479 } 480 481 debug_string_to_mask(buf, &c_mask, 1); 482 debug_mask_to_string(&c_mask, 1); 483 debug_string = client_debug_string; 484 485 new_op = op_alloc(ORANGEFS_VFS_OP_PARAM); 486 if (!new_op) { 487 pr_info("%s: op_alloc failed!\n", __func__); 488 goto out; 489 } 490 491 new_op->upcall.req.param.op = 492 ORANGEFS_PARAM_REQUEST_OP_TWO_MASK_VALUES; 493 new_op->upcall.req.param.type = ORANGEFS_PARAM_REQUEST_SET; 494 memset(new_op->upcall.req.param.s_value, 495 0, 496 ORANGEFS_MAX_DEBUG_STRING_LEN); 497 sprintf(new_op->upcall.req.param.s_value, 498 "%llx %llx\n", 499 c_mask.mask1, 500 c_mask.mask2); 501 502 /* service_operation returns 0 on success... */ 503 rc = service_operation(new_op, 504 "orangefs_param", 505 ORANGEFS_OP_INTERRUPTIBLE); 506 507 if (rc) 508 gossip_debug(GOSSIP_DEBUGFS_DEBUG, 509 "%s: service_operation failed! rc:%d:\n", 510 __func__, 511 rc); 512 513 op_release(new_op); 514 } 515 516 mutex_lock(&orangefs_debug_lock); 517 s = file_inode(file)->i_private; 518 memset(s, 0, ORANGEFS_MAX_DEBUG_STRING_LEN); 519 sprintf(s, "%s\n", debug_string); 520 mutex_unlock(&orangefs_debug_lock); 521 522 *ppos += count; 523 if (silly) 524 rc = silly; 525 else 526 rc = count; 527 528 out: 529 gossip_debug(GOSSIP_DEBUGFS_DEBUG, 530 "orangefs_debug_write: rc: %d\n", 531 rc); 532 kfree(buf); 533 return rc; 534 } 535 536 /* 537 * After obtaining a string representation of the client's debug 538 * keywords and their associated masks, this function is called to build an 539 * array of these values. 540 */ 541 static int orangefs_prepare_cdm_array(char *debug_array_string) 542 { 543 int i; 544 int rc = -EINVAL; 545 char *cds_head = NULL; 546 char *cds_delimiter = NULL; 547 int keyword_len = 0; 548 549 gossip_debug(GOSSIP_UTILS_DEBUG, "%s: start\n", __func__); 550 551 /* 552 * figure out how many elements the cdm_array needs. 553 */ 554 for (i = 0; i < strlen(debug_array_string); i++) 555 if (debug_array_string[i] == '\n') 556 cdm_element_count++; 557 558 if (!cdm_element_count) { 559 pr_info("No elements in client debug array string!\n"); 560 goto out; 561 } 562 563 cdm_array = kcalloc(cdm_element_count, sizeof(*cdm_array), GFP_KERNEL); 564 if (!cdm_array) { 565 rc = -ENOMEM; 566 goto out; 567 } 568 569 cds_head = debug_array_string; 570 571 for (i = 0; i < cdm_element_count; i++) { 572 cds_delimiter = strchr(cds_head, '\n'); 573 *cds_delimiter = '\0'; 574 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 char *unchecked_keyword; 877 int i; 878 char *strsep_fodder = kstrdup(debug_string, GFP_KERNEL); 879 char *original_pointer; 880 int element_count = 0; 881 struct client_debug_mask *c_mask = NULL; 882 __u64 *k_mask = NULL; 883 884 gossip_debug(GOSSIP_UTILS_DEBUG, "%s: start\n", __func__); 885 886 if (type) { 887 c_mask = (struct client_debug_mask *)mask; 888 element_count = cdm_element_count; 889 } else { 890 k_mask = (__u64 *)mask; 891 *k_mask = 0; 892 element_count = num_kmod_keyword_mask_map; 893 } 894 895 original_pointer = strsep_fodder; 896 while ((unchecked_keyword = strsep(&strsep_fodder, ","))) 897 if (strlen(unchecked_keyword)) { 898 for (i = 0; i < element_count; i++) 899 if (type) 900 do_c_mask(i, 901 unchecked_keyword, 902 &c_mask); 903 else 904 do_k_mask(i, 905 unchecked_keyword, 906 &k_mask); 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