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