diff options
author | Li Zhong <zhong@linux.vnet.ibm.com> | 2015-04-13 03:48:37 -0400 |
---|---|---|
committer | Michael Ellerman <mpe@ellerman.id.au> | 2015-04-13 23:19:15 -0400 |
commit | 7debc970ae7a5573ed43a1dfa242fd1a5390d21a (patch) | |
tree | 3bf20766ecf79b8d3e8a41d16bde04bd8f369d6b /arch/powerpc/perf | |
parent | ad30cb9946515f72af5c3e89ad9de18870c1a1e7 (diff) |
powerpc/perf/hv-24x7: Fail 24x7 initcall if create_events_from_catalog() fails
As Michael pointed out, create_events_from_catalog() fails when we
either have:
- a kernel bug
- some sort of hypervisor misconfiguration
- ENOMEM
In all the above cases, we can also fail 24x7 initcall.
For hypervisor errors, EIO is used so there is something reported
in dmesg.
Signed-off-by: Li Zhong <zhong@linux.vnet.ibm.com>
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
Diffstat (limited to 'arch/powerpc/perf')
-rw-r--r-- | arch/powerpc/perf/hv-24x7.c | 37 |
1 files changed, 29 insertions, 8 deletions
diff --git a/arch/powerpc/perf/hv-24x7.c b/arch/powerpc/perf/hv-24x7.c index ead8878ca62b..ff413615a87c 100644 --- a/arch/powerpc/perf/hv-24x7.c +++ b/arch/powerpc/perf/hv-24x7.c | |||
@@ -647,7 +647,7 @@ static ssize_t catalog_event_len_validate(struct hv_24x7_event_data *event, | |||
647 | 647 | ||
648 | #define MAX_4K (SIZE_MAX / 4096) | 648 | #define MAX_4K (SIZE_MAX / 4096) |
649 | 649 | ||
650 | static void create_events_from_catalog(struct attribute ***events_, | 650 | static int create_events_from_catalog(struct attribute ***events_, |
651 | struct attribute ***event_descs_, | 651 | struct attribute ***event_descs_, |
652 | struct attribute ***event_long_descs_) | 652 | struct attribute ***event_long_descs_) |
653 | { | 653 | { |
@@ -665,19 +665,25 @@ static void create_events_from_catalog(struct attribute ***events_, | |||
665 | void *event_data, *end; | 665 | void *event_data, *end; |
666 | struct hv_24x7_event_data *event; | 666 | struct hv_24x7_event_data *event; |
667 | struct rb_root ev_uniq = RB_ROOT; | 667 | struct rb_root ev_uniq = RB_ROOT; |
668 | int ret = 0; | ||
668 | 669 | ||
669 | if (!page) | 670 | if (!page) { |
671 | ret = -ENOMEM; | ||
670 | goto e_out; | 672 | goto e_out; |
673 | } | ||
671 | 674 | ||
672 | hret = h_get_24x7_catalog_page(page, 0, 0); | 675 | hret = h_get_24x7_catalog_page(page, 0, 0); |
673 | if (hret) | 676 | if (hret) { |
677 | ret = -EIO; | ||
674 | goto e_free; | 678 | goto e_free; |
679 | } | ||
675 | 680 | ||
676 | catalog_version_num = be64_to_cpu(page_0->version); | 681 | catalog_version_num = be64_to_cpu(page_0->version); |
677 | catalog_page_len = be32_to_cpu(page_0->length); | 682 | catalog_page_len = be32_to_cpu(page_0->length); |
678 | 683 | ||
679 | if (MAX_4K < catalog_page_len) { | 684 | if (MAX_4K < catalog_page_len) { |
680 | pr_err("invalid page count: %zu\n", catalog_page_len); | 685 | pr_err("invalid page count: %zu\n", catalog_page_len); |
686 | ret = -EIO; | ||
681 | goto e_free; | 687 | goto e_free; |
682 | } | 688 | } |
683 | 689 | ||
@@ -696,6 +702,7 @@ static void create_events_from_catalog(struct attribute ***events_, | |||
696 | || (MAX_4K - event_data_offs < event_data_len)) { | 702 | || (MAX_4K - event_data_offs < event_data_len)) { |
697 | pr_err("invalid event data offs %zu and/or len %zu\n", | 703 | pr_err("invalid event data offs %zu and/or len %zu\n", |
698 | event_data_offs, event_data_len); | 704 | event_data_offs, event_data_len); |
705 | ret = -EIO; | ||
699 | goto e_free; | 706 | goto e_free; |
700 | } | 707 | } |
701 | 708 | ||
@@ -704,12 +711,14 @@ static void create_events_from_catalog(struct attribute ***events_, | |||
704 | event_data_offs, | 711 | event_data_offs, |
705 | event_data_offs + event_data_len, | 712 | event_data_offs + event_data_len, |
706 | catalog_page_len); | 713 | catalog_page_len); |
714 | ret = -EIO; | ||
707 | goto e_free; | 715 | goto e_free; |
708 | } | 716 | } |
709 | 717 | ||
710 | if (SIZE_MAX / MAX_EVENTS_PER_EVENT_DATA - 1 < event_entry_count) { | 718 | if (SIZE_MAX / MAX_EVENTS_PER_EVENT_DATA - 1 < event_entry_count) { |
711 | pr_err("event_entry_count %zu is invalid\n", | 719 | pr_err("event_entry_count %zu is invalid\n", |
712 | event_entry_count); | 720 | event_entry_count); |
721 | ret = -EIO; | ||
713 | goto e_free; | 722 | goto e_free; |
714 | } | 723 | } |
715 | 724 | ||
@@ -722,6 +731,7 @@ static void create_events_from_catalog(struct attribute ***events_, | |||
722 | event_data = vmalloc(event_data_bytes); | 731 | event_data = vmalloc(event_data_bytes); |
723 | if (!event_data) { | 732 | if (!event_data) { |
724 | pr_err("could not allocate event data\n"); | 733 | pr_err("could not allocate event data\n"); |
734 | ret = -ENOMEM; | ||
725 | goto e_free; | 735 | goto e_free; |
726 | } | 736 | } |
727 | 737 | ||
@@ -741,6 +751,7 @@ static void create_events_from_catalog(struct attribute ***events_, | |||
741 | if (hret) { | 751 | if (hret) { |
742 | pr_err("failed to get event data in page %zu\n", | 752 | pr_err("failed to get event data in page %zu\n", |
743 | i + event_data_offs); | 753 | i + event_data_offs); |
754 | ret = -EIO; | ||
744 | goto e_event_data; | 755 | goto e_event_data; |
745 | } | 756 | } |
746 | } | 757 | } |
@@ -788,18 +799,24 @@ static void create_events_from_catalog(struct attribute ***events_, | |||
788 | event_idx_last, event_entry_count, junk_events); | 799 | event_idx_last, event_entry_count, junk_events); |
789 | 800 | ||
790 | events = kmalloc_array(attr_max + 1, sizeof(*events), GFP_KERNEL); | 801 | events = kmalloc_array(attr_max + 1, sizeof(*events), GFP_KERNEL); |
791 | if (!events) | 802 | if (!events) { |
803 | ret = -ENOMEM; | ||
792 | goto e_event_data; | 804 | goto e_event_data; |
805 | } | ||
793 | 806 | ||
794 | event_descs = kmalloc_array(event_idx + 1, sizeof(*event_descs), | 807 | event_descs = kmalloc_array(event_idx + 1, sizeof(*event_descs), |
795 | GFP_KERNEL); | 808 | GFP_KERNEL); |
796 | if (!event_descs) | 809 | if (!event_descs) { |
810 | ret = -ENOMEM; | ||
797 | goto e_event_attrs; | 811 | goto e_event_attrs; |
812 | } | ||
798 | 813 | ||
799 | event_long_descs = kmalloc_array(event_idx + 1, | 814 | event_long_descs = kmalloc_array(event_idx + 1, |
800 | sizeof(*event_long_descs), GFP_KERNEL); | 815 | sizeof(*event_long_descs), GFP_KERNEL); |
801 | if (!event_long_descs) | 816 | if (!event_long_descs) { |
817 | ret = -ENOMEM; | ||
802 | goto e_event_descs; | 818 | goto e_event_descs; |
819 | } | ||
803 | 820 | ||
804 | /* Iterate over the catalog filling in the attribute vector */ | 821 | /* Iterate over the catalog filling in the attribute vector */ |
805 | for (junk_events = 0, event_attr_ct = 0, desc_ct = 0, long_desc_ct = 0, | 822 | for (junk_events = 0, event_attr_ct = 0, desc_ct = 0, long_desc_ct = 0, |
@@ -853,7 +870,7 @@ static void create_events_from_catalog(struct attribute ***events_, | |||
853 | *events_ = events; | 870 | *events_ = events; |
854 | *event_descs_ = event_descs; | 871 | *event_descs_ = event_descs; |
855 | *event_long_descs_ = event_long_descs; | 872 | *event_long_descs_ = event_long_descs; |
856 | return; | 873 | return 0; |
857 | 874 | ||
858 | e_event_descs: | 875 | e_event_descs: |
859 | kfree(event_descs); | 876 | kfree(event_descs); |
@@ -867,6 +884,7 @@ e_out: | |||
867 | *events_ = NULL; | 884 | *events_ = NULL; |
868 | *event_descs_ = NULL; | 885 | *event_descs_ = NULL; |
869 | *event_long_descs_ = NULL; | 886 | *event_long_descs_ = NULL; |
887 | return ret; | ||
870 | } | 888 | } |
871 | 889 | ||
872 | static ssize_t catalog_read(struct file *filp, struct kobject *kobj, | 890 | static ssize_t catalog_read(struct file *filp, struct kobject *kobj, |
@@ -1275,10 +1293,13 @@ static int hv_24x7_init(void) | |||
1275 | /* sampling not supported */ | 1293 | /* sampling not supported */ |
1276 | h_24x7_pmu.capabilities |= PERF_PMU_CAP_NO_INTERRUPT; | 1294 | h_24x7_pmu.capabilities |= PERF_PMU_CAP_NO_INTERRUPT; |
1277 | 1295 | ||
1278 | create_events_from_catalog(&event_group.attrs, | 1296 | r = create_events_from_catalog(&event_group.attrs, |
1279 | &event_desc_group.attrs, | 1297 | &event_desc_group.attrs, |
1280 | &event_long_desc_group.attrs); | 1298 | &event_long_desc_group.attrs); |
1281 | 1299 | ||
1300 | if (r) | ||
1301 | return r; | ||
1302 | |||
1282 | r = perf_pmu_register(&h_24x7_pmu, h_24x7_pmu.name, -1); | 1303 | r = perf_pmu_register(&h_24x7_pmu, h_24x7_pmu.name, -1); |
1283 | if (r) | 1304 | if (r) |
1284 | return r; | 1305 | return r; |