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