diff options
Diffstat (limited to 'fs/orangefs/orangefs-debugfs.c')
-rw-r--r-- | fs/orangefs/orangefs-debugfs.c | 147 |
1 files changed, 64 insertions, 83 deletions
diff --git a/fs/orangefs/orangefs-debugfs.c b/fs/orangefs/orangefs-debugfs.c index eb09aa026723..d484068ca716 100644 --- a/fs/orangefs/orangefs-debugfs.c +++ b/fs/orangefs/orangefs-debugfs.c | |||
@@ -141,6 +141,9 @@ static struct client_debug_mask client_debug_mask; | |||
141 | */ | 141 | */ |
142 | static DEFINE_MUTEX(orangefs_debug_lock); | 142 | static DEFINE_MUTEX(orangefs_debug_lock); |
143 | 143 | ||
144 | /* Used to protect data in ORANGEFS_KMOD_DEBUG_HELP_FILE */ | ||
145 | static DEFINE_MUTEX(orangefs_help_file_lock); | ||
146 | |||
144 | /* | 147 | /* |
145 | * initialize kmod debug operations, create orangefs debugfs dir and | 148 | * initialize kmod debug operations, create orangefs debugfs dir and |
146 | * ORANGEFS_KMOD_DEBUG_HELP_FILE. | 149 | * ORANGEFS_KMOD_DEBUG_HELP_FILE. |
@@ -289,6 +292,8 @@ static void *help_start(struct seq_file *m, loff_t *pos) | |||
289 | 292 | ||
290 | gossip_debug(GOSSIP_DEBUGFS_DEBUG, "help_start: start\n"); | 293 | gossip_debug(GOSSIP_DEBUGFS_DEBUG, "help_start: start\n"); |
291 | 294 | ||
295 | mutex_lock(&orangefs_help_file_lock); | ||
296 | |||
292 | if (*pos == 0) | 297 | if (*pos == 0) |
293 | payload = m->private; | 298 | payload = m->private; |
294 | 299 | ||
@@ -305,6 +310,7 @@ static void *help_next(struct seq_file *m, void *v, loff_t *pos) | |||
305 | static void help_stop(struct seq_file *m, void *p) | 310 | static void help_stop(struct seq_file *m, void *p) |
306 | { | 311 | { |
307 | gossip_debug(GOSSIP_DEBUGFS_DEBUG, "help_stop: start\n"); | 312 | gossip_debug(GOSSIP_DEBUGFS_DEBUG, "help_stop: start\n"); |
313 | mutex_unlock(&orangefs_help_file_lock); | ||
308 | } | 314 | } |
309 | 315 | ||
310 | static int help_show(struct seq_file *m, void *v) | 316 | static int help_show(struct seq_file *m, void *v) |
@@ -610,32 +616,54 @@ out: | |||
610 | * /sys/kernel/debug/orangefs/debug-help can be catted to | 616 | * /sys/kernel/debug/orangefs/debug-help can be catted to |
611 | * see all the available kernel and client debug keywords. | 617 | * see all the available kernel and client debug keywords. |
612 | * | 618 | * |
613 | * When the kernel boots, we have no idea what keywords the | 619 | * When orangefs.ko initializes, we have no idea what keywords the |
614 | * client supports, nor their associated masks. | 620 | * client supports, nor their associated masks. |
615 | * | 621 | * |
616 | * We pass through this function once at boot and stamp a | 622 | * We pass through this function once at module-load and stamp a |
617 | * boilerplate "we don't know" message for the client in the | 623 | * boilerplate "we don't know" message for the client in the |
618 | * debug-help file. We pass through here again when the client | 624 | * debug-help file. We pass through here again when the client |
619 | * starts and then we can fill out the debug-help file fully. | 625 | * starts and then we can fill out the debug-help file fully. |
620 | * | 626 | * |
621 | * The client might be restarted any number of times between | 627 | * The client might be restarted any number of times between |
622 | * reboots, we only build the debug-help file the first time. | 628 | * module reloads, we only build the debug-help file the first time. |
623 | */ | 629 | */ |
624 | int orangefs_prepare_debugfs_help_string(int at_boot) | 630 | int orangefs_prepare_debugfs_help_string(int at_boot) |
625 | { | 631 | { |
626 | int rc = -EINVAL; | ||
627 | int i; | ||
628 | int byte_count = 0; | ||
629 | char *client_title = "Client Debug Keywords:\n"; | 632 | char *client_title = "Client Debug Keywords:\n"; |
630 | char *kernel_title = "Kernel Debug Keywords:\n"; | 633 | char *kernel_title = "Kernel Debug Keywords:\n"; |
634 | size_t string_size = DEBUG_HELP_STRING_SIZE; | ||
635 | size_t result_size; | ||
636 | size_t i; | ||
637 | char *new; | ||
638 | int rc = -EINVAL; | ||
631 | 639 | ||
632 | gossip_debug(GOSSIP_UTILS_DEBUG, "%s: start\n", __func__); | 640 | gossip_debug(GOSSIP_UTILS_DEBUG, "%s: start\n", __func__); |
633 | 641 | ||
634 | if (at_boot) { | 642 | if (at_boot) |
635 | byte_count += strlen(HELP_STRING_UNINITIALIZED); | ||
636 | client_title = HELP_STRING_UNINITIALIZED; | 643 | client_title = HELP_STRING_UNINITIALIZED; |
637 | } else { | 644 | |
638 | /* | 645 | /* build a new debug_help_string. */ |
646 | new = kzalloc(DEBUG_HELP_STRING_SIZE, GFP_KERNEL); | ||
647 | if (!new) { | ||
648 | rc = -ENOMEM; | ||
649 | goto out; | ||
650 | } | ||
651 | |||
652 | /* | ||
653 | * strlcat(dst, src, size) will append at most | ||
654 | * "size - strlen(dst) - 1" bytes of src onto dst, | ||
655 | * null terminating the result, and return the total | ||
656 | * length of the string it tried to create. | ||
657 | * | ||
658 | * We'll just plow through here building our new debug | ||
659 | * help string and let strlcat take care of assuring that | ||
660 | * dst doesn't overflow. | ||
661 | */ | ||
662 | strlcat(new, client_title, string_size); | ||
663 | |||
664 | if (!at_boot) { | ||
665 | |||
666 | /* | ||
639 | * fill the client keyword/mask array and remember | 667 | * fill the client keyword/mask array and remember |
640 | * how many elements there were. | 668 | * how many elements there were. |
641 | */ | 669 | */ |
@@ -644,64 +672,40 @@ int orangefs_prepare_debugfs_help_string(int at_boot) | |||
644 | if (cdm_element_count <= 0) | 672 | if (cdm_element_count <= 0) |
645 | goto out; | 673 | goto out; |
646 | 674 | ||
647 | /* Count the bytes destined for debug_help_string. */ | ||
648 | byte_count += strlen(client_title); | ||
649 | |||
650 | for (i = 0; i < cdm_element_count; i++) { | 675 | for (i = 0; i < cdm_element_count; i++) { |
651 | byte_count += strlen(cdm_array[i].keyword + 2); | 676 | strlcat(new, "\t", string_size); |
652 | if (byte_count >= DEBUG_HELP_STRING_SIZE) { | 677 | strlcat(new, cdm_array[i].keyword, string_size); |
653 | pr_info("%s: overflow 1!\n", __func__); | 678 | strlcat(new, "\n", string_size); |
654 | goto out; | ||
655 | } | ||
656 | } | 679 | } |
657 | |||
658 | gossip_debug(GOSSIP_UTILS_DEBUG, | ||
659 | "%s: cdm_element_count:%d:\n", | ||
660 | __func__, | ||
661 | cdm_element_count); | ||
662 | } | 680 | } |
663 | 681 | ||
664 | byte_count += strlen(kernel_title); | 682 | strlcat(new, "\n", string_size); |
683 | strlcat(new, kernel_title, string_size); | ||
684 | |||
665 | for (i = 0; i < num_kmod_keyword_mask_map; i++) { | 685 | for (i = 0; i < num_kmod_keyword_mask_map; i++) { |
666 | byte_count += | 686 | strlcat(new, "\t", string_size); |
667 | strlen(s_kmod_keyword_mask_map[i].keyword + 2); | 687 | strlcat(new, s_kmod_keyword_mask_map[i].keyword, string_size); |
668 | if (byte_count >= DEBUG_HELP_STRING_SIZE) { | 688 | result_size = strlcat(new, "\n", string_size); |
669 | pr_info("%s: overflow 2!\n", __func__); | ||
670 | goto out; | ||
671 | } | ||
672 | } | 689 | } |
673 | 690 | ||
674 | /* build debug_help_string. */ | 691 | /* See if we tried to put too many bytes into "new"... */ |
675 | debug_help_string = kzalloc(DEBUG_HELP_STRING_SIZE, GFP_KERNEL); | 692 | if (result_size >= string_size) { |
676 | if (!debug_help_string) { | 693 | kfree(new); |
677 | rc = -ENOMEM; | ||
678 | goto out; | 694 | goto out; |
679 | } | 695 | } |
680 | 696 | ||
681 | strcat(debug_help_string, client_title); | 697 | if (at_boot) { |
682 | 698 | debug_help_string = new; | |
683 | if (!at_boot) { | 699 | } else { |
684 | for (i = 0; i < cdm_element_count; i++) { | 700 | mutex_lock(&orangefs_help_file_lock); |
685 | strcat(debug_help_string, "\t"); | 701 | memset(debug_help_string, 0, DEBUG_HELP_STRING_SIZE); |
686 | strcat(debug_help_string, cdm_array[i].keyword); | 702 | strlcat(debug_help_string, new, string_size); |
687 | strcat(debug_help_string, "\n"); | 703 | mutex_unlock(&orangefs_help_file_lock); |
688 | } | ||
689 | } | ||
690 | |||
691 | strcat(debug_help_string, "\n"); | ||
692 | strcat(debug_help_string, kernel_title); | ||
693 | |||
694 | for (i = 0; i < num_kmod_keyword_mask_map; i++) { | ||
695 | strcat(debug_help_string, "\t"); | ||
696 | strcat(debug_help_string, s_kmod_keyword_mask_map[i].keyword); | ||
697 | strcat(debug_help_string, "\n"); | ||
698 | } | 704 | } |
699 | 705 | ||
700 | rc = 0; | 706 | rc = 0; |
701 | 707 | ||
702 | out: | 708 | out: return rc; |
703 | |||
704 | return rc; | ||
705 | 709 | ||
706 | } | 710 | } |
707 | 711 | ||
@@ -959,8 +963,12 @@ int orangefs_debugfs_new_client_string(void __user *arg) | |||
959 | ret = copy_from_user(&client_debug_array_string, | 963 | ret = copy_from_user(&client_debug_array_string, |
960 | (void __user *)arg, | 964 | (void __user *)arg, |
961 | ORANGEFS_MAX_DEBUG_STRING_LEN); | 965 | ORANGEFS_MAX_DEBUG_STRING_LEN); |
962 | if (ret != 0) | 966 | |
967 | if (ret != 0) { | ||
968 | pr_info("%s: CLIENT_STRING: copy_from_user failed\n", | ||
969 | __func__); | ||
963 | return -EIO; | 970 | return -EIO; |
971 | } | ||
964 | 972 | ||
965 | /* | 973 | /* |
966 | * The real client-core makes an effort to ensure | 974 | * The real client-core makes an effort to ensure |
@@ -975,45 +983,18 @@ int orangefs_debugfs_new_client_string(void __user *arg) | |||
975 | client_debug_array_string[ORANGEFS_MAX_DEBUG_STRING_LEN - 1] = | 983 | client_debug_array_string[ORANGEFS_MAX_DEBUG_STRING_LEN - 1] = |
976 | '\0'; | 984 | '\0'; |
977 | 985 | ||
978 | if (ret != 0) { | ||
979 | pr_info("%s: CLIENT_STRING: copy_from_user failed\n", | ||
980 | __func__); | ||
981 | return -EIO; | ||
982 | } | ||
983 | |||
984 | pr_info("%s: client debug array string has been received.\n", | 986 | pr_info("%s: client debug array string has been received.\n", |
985 | __func__); | 987 | __func__); |
986 | 988 | ||
987 | if (!help_string_initialized) { | 989 | if (!help_string_initialized) { |
988 | 990 | ||
989 | /* Free the "we don't know yet" default string... */ | 991 | /* Build a proper debug help string. */ |
990 | kfree(debug_help_string); | ||
991 | |||
992 | /* build a proper debug help string */ | ||
993 | if (orangefs_prepare_debugfs_help_string(0)) { | 992 | if (orangefs_prepare_debugfs_help_string(0)) { |
994 | gossip_err("%s: no debug help string \n", | 993 | gossip_err("%s: no debug help string \n", |
995 | __func__); | 994 | __func__); |
996 | return -EIO; | 995 | return -EIO; |
997 | } | 996 | } |
998 | 997 | ||
999 | /* Replace the boilerplate boot-time debug-help file. */ | ||
1000 | debugfs_remove(help_file_dentry); | ||
1001 | |||
1002 | help_file_dentry = | ||
1003 | debugfs_create_file( | ||
1004 | ORANGEFS_KMOD_DEBUG_HELP_FILE, | ||
1005 | 0444, | ||
1006 | debug_dir, | ||
1007 | debug_help_string, | ||
1008 | &debug_help_fops); | ||
1009 | |||
1010 | if (!help_file_dentry) { | ||
1011 | gossip_err("%s: debugfs_create_file failed for" | ||
1012 | " :%s:!\n", | ||
1013 | __func__, | ||
1014 | ORANGEFS_KMOD_DEBUG_HELP_FILE); | ||
1015 | return -EIO; | ||
1016 | } | ||
1017 | } | 998 | } |
1018 | 999 | ||
1019 | debug_mask_to_string(&client_debug_mask, 1); | 1000 | debug_mask_to_string(&client_debug_mask, 1); |