linuxppc-dev.lists.ozlabs.org archive mirror
 help / color / mirror / Atom feed
* [RFC PATCH powerpc] perf/hv-24x7 set the attr group to NULL if events failed to be initialized
@ 2015-02-15  9:42 Li Zhong
  2015-03-25  9:51 ` [RFC, " Michael Ellerman
  0 siblings, 1 reply; 7+ messages in thread
From: Li Zhong @ 2015-02-15  9:42 UTC (permalink / raw)
  To: PowerPC email list; +Cc: Sukadev Bhattiprolu, Paul Mackerras

sysfs_create_groups() creates groups one by one in the attr_groups array
before a NULL entry is encountered. But if an error is seen, it stops
and removes all the groups already created:
        for (i = 0; groups[i]; i++) {
                error = sysfs_create_group(kobj, groups[i]);
                if (error) {
                        while (--i >= 0)
                                sysfs_remove_group(kobj, groups[i]);
                        break;
                }
        }

And for the three event groups of 24x7, if it is not supported,
according to the above logic, it causes format and interface group to be
removed because of the error.

This patch moves the three events groups to the end of the attr groups,
and if create_events_from_catalog() fails to set their attributes, we
set them to NULL in attr_groups.

Signed-off-by: Li Zhong <zhong@linux.vnet.ibm.com>
---
 arch/powerpc/perf/hv-24x7.c | 37 ++++++++++++++++++++++++++++---------
 1 file changed, 28 insertions(+), 9 deletions(-)

diff --git a/arch/powerpc/perf/hv-24x7.c b/arch/powerpc/perf/hv-24x7.c
index 9445a82..1e433f7 100644
--- a/arch/powerpc/perf/hv-24x7.c
+++ b/arch/powerpc/perf/hv-24x7.c
@@ -637,7 +637,7 @@ static ssize_t catalog_event_len_validate(struct hv_24x7_event_data *event,
 
 #define MAX_4K (SIZE_MAX / 4096)
 
-static void create_events_from_catalog(struct attribute ***events_,
+static int create_events_from_catalog(struct attribute ***events_,
 		struct attribute ***event_descs_,
 		struct attribute ***event_long_descs_)
 {
@@ -843,7 +843,7 @@ static void create_events_from_catalog(struct attribute ***events_,
 	*events_ = events;
 	*event_descs_ = event_descs;
 	*event_long_descs_ = event_long_descs;
-	return;
+	return 0;
 
 e_event_descs:
 	kfree(event_descs);
@@ -857,6 +857,7 @@ e_out:
 	*events_ = NULL;
 	*event_descs_ = NULL;
 	*event_long_descs_ = NULL;
+	return -1;
 }
 
 static ssize_t catalog_read(struct file *filp, struct kobject *kobj,
@@ -967,13 +968,25 @@ static struct attribute_group if_group = {
 	.attrs = if_attrs,
 };
 
+enum GROUP_INDEX {
+	FORMAT,
+	IF,
+	EVENT,
+	EVENT_DESC,
+	EVENT_LONG_DESC,
+	MAX
+};
+
+/*
+ * keep the attr group whose attr is set in init (may fail)
+ * at the end
+ */
 static const struct attribute_group *attr_groups[] = {
-	&format_group,
-	&event_group,
-	&event_desc_group,
-	&event_long_desc_group,
-	&if_group,
-	NULL,
+	[FORMAT] = &format_group,
+	[IF] = &if_group,
+	[EVENT] = &event_group,
+	[EVENT_DESC] = &event_desc_group,
+	[EVENT_LONG_DESC] = &event_long_desc_group
 };
 
 DEFINE_PER_CPU(char, hv_24x7_reqb[4096]) __aligned(4096);
@@ -1219,10 +1232,16 @@ static int hv_24x7_init(void)
 	/* sampling not supported */
 	h_24x7_pmu.capabilities |= PERF_PMU_CAP_NO_INTERRUPT;
 
-	create_events_from_catalog(&event_group.attrs,
+	r = create_events_from_catalog(&event_group.attrs,
 				   &event_desc_group.attrs,
 				   &event_long_desc_group.attrs);
 
+	if (r) {
+		h_24x7_pmu.attr_groups[EVENT] =
+		h_24x7_pmu.attr_groups[EVENT_DESC] =
+		h_24x7_pmu.attr_groups[EVENT_LONG_DESC] = 0;
+	}
+
 	r = perf_pmu_register(&h_24x7_pmu, h_24x7_pmu.name, -1);
 	if (r)
 		return r;

^ permalink raw reply related	[flat|nested] 7+ messages in thread

* Re: [RFC, powerpc] perf/hv-24x7 set the attr group to NULL if events failed to be initialized
  2015-02-15  9:42 [RFC PATCH powerpc] perf/hv-24x7 set the attr group to NULL if events failed to be initialized Li Zhong
@ 2015-03-25  9:51 ` Michael Ellerman
  2015-03-25 18:41   ` Sukadev Bhattiprolu
  0 siblings, 1 reply; 7+ messages in thread
From: Michael Ellerman @ 2015-03-25  9:51 UTC (permalink / raw)
  To: Li Zhong, PowerPC email list; +Cc: Sukadev Bhattiprolu, Paul Mackerras

On Sun, 2015-15-02 at 09:42:57 UTC, Li Zhong wrote:
> sysfs_create_groups() creates groups one by one in the attr_groups array
> before a NULL entry is encountered. But if an error is seen, it stops
> and removes all the groups already created:
>         for (i = 0; groups[i]; i++) {
>                 error = sysfs_create_group(kobj, groups[i]);
>                 if (error) {
>                         while (--i >= 0)
>                                 sysfs_remove_group(kobj, groups[i]);
>                         break;
>                 }
>         }
> 
> And for the three event groups of 24x7, if it is not supported,
> according to the above logic, it causes format and interface group to be
> removed because of the error.
> 
> This patch moves the three events groups to the end of the attr groups,
> and if create_events_from_catalog() fails to set their attributes, we
> set them to NULL in attr_groups.

But why are we continuing at all if create_events_from_catalog() fails?

Shouldn't that just be a fatal error and we bail?

cheers

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [RFC, powerpc] perf/hv-24x7 set the attr group to NULL if events failed to be initialized
  2015-03-25  9:51 ` [RFC, " Michael Ellerman
@ 2015-03-25 18:41   ` Sukadev Bhattiprolu
  2015-03-26  3:51     ` Michael Ellerman
  0 siblings, 1 reply; 7+ messages in thread
From: Sukadev Bhattiprolu @ 2015-03-25 18:41 UTC (permalink / raw)
  To: Michael Ellerman; +Cc: Paul Mackerras, PowerPC email list, Li Zhong

Michael Ellerman [mpe@ellerman.id.au] wrote:
| On Sun, 2015-15-02 at 09:42:57 UTC, Li Zhong wrote:
| > This patch moves the three events groups to the end of the attr groups,
| > and if create_events_from_catalog() fails to set their attributes, we
| > set them to NULL in attr_groups.
| 
| But why are we continuing at all if create_events_from_catalog() fails?
| 
| Shouldn't that just be a fatal error and we bail?

Well, even if create_events_from_catalog() fails, we can continue to use
the 24x7 events, rather clumsily, as long as the catalog is readable.  i.e.
parse /sys/bus/event_source/devices/hv_24x7/interface/catalog to find event
offset and run:

	perf stat -C 0 -e hv_24x7/domain=2,offset=8,core=0/ workload
Suka

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [RFC, powerpc] perf/hv-24x7 set the attr group to NULL if events failed to be initialized
  2015-03-25 18:41   ` Sukadev Bhattiprolu
@ 2015-03-26  3:51     ` Michael Ellerman
  2015-04-10  8:42       ` [RFC v2 powerpc] perf/hv-24x7 fail 24x7 initcall if create_events_from_catalog() fails Li Zhong
  0 siblings, 1 reply; 7+ messages in thread
From: Michael Ellerman @ 2015-03-26  3:51 UTC (permalink / raw)
  To: Sukadev Bhattiprolu; +Cc: Paul Mackerras, PowerPC email list, Li Zhong

On Wed, 2015-03-25 at 11:41 -0700, Sukadev Bhattiprolu wrote:
> Michael Ellerman [mpe@ellerman.id.au] wrote:
> | On Sun, 2015-15-02 at 09:42:57 UTC, Li Zhong wrote:
> | > This patch moves the three events groups to the end of the attr groups,
> | > and if create_events_from_catalog() fails to set their attributes, we
> | > set them to NULL in attr_groups.
> | 
> | But why are we continuing at all if create_events_from_catalog() fails?
> | 
> | Shouldn't that just be a fatal error and we bail?
> 
> Well, even if create_events_from_catalog() fails, we can continue to use
> the 24x7 events, rather clumsily, as long as the catalog is readable.  i.e.
> parse /sys/bus/event_source/devices/hv_24x7/interface/catalog to find event
> offset and run:
> 
> 	perf stat -C 0 -e hv_24x7/domain=2,offset=8,core=0/ workload


Yeah I guess, but is that really useful? And is it a case we want to support?

It seems to me if create_events_from_catalog() fails then we either have:
  - a kernel bug
  - some sort of hypervisor misconfiguration
  - ENOMEM (in which case the system's probably dead anyway)

So in all cases trying to continue on seems fairly pointless to me.

cheers

^ permalink raw reply	[flat|nested] 7+ messages in thread

* [RFC v2 powerpc] perf/hv-24x7  fail 24x7 initcall if create_events_from_catalog() fails
  2015-03-26  3:51     ` Michael Ellerman
@ 2015-04-10  8:42       ` Li Zhong
  2015-04-10 10:55         ` Michael Ellerman
  0 siblings, 1 reply; 7+ messages in thread
From: Li Zhong @ 2015-04-10  8:42 UTC (permalink / raw)
  To: Michael Ellerman; +Cc: Paul Mackerras, Sukadev Bhattiprolu, PowerPC email list

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. 

In the patch below, I used ENODEV for hypervisor errors, not sure 
whether some other error values is more proper here. 

Signed-off-by: Li Zhong <zhong@linux.vnet.ibm.com>
--- arch/powerpc/perf/hv-24x7.c | 37 +++++++++++++++++++++++++++++--------
 1 file changed, 29 insertions(+), 8 deletions(-)

diff --git a/arch/powerpc/perf/hv-24x7.c b/arch/powerpc/perf/hv-24x7.c
index 9445a82..5efc276 100644
--- a/arch/powerpc/perf/hv-24x7.c
+++ b/arch/powerpc/perf/hv-24x7.c
@@ -637,7 +637,7 @@ static ssize_t catalog_event_len_validate(struct hv_24x7_event_data *event,
 
 #define MAX_4K (SIZE_MAX / 4096)
 
-static void create_events_from_catalog(struct attribute ***events_,
+static int create_events_from_catalog(struct attribute ***events_,
 		struct attribute ***event_descs_,
 		struct attribute ***event_long_descs_)
 {
@@ -655,19 +655,25 @@ static void create_events_from_catalog(struct attribute ***events_,
 	void *event_data, *end;
 	struct hv_24x7_event_data *event;
 	struct rb_root ev_uniq = RB_ROOT;
+	int ret = 0;
 
-	if (!page)
+	if (!page) {
+		ret = -ENOMEM;
 		goto e_out;
+	}
 
 	hret = h_get_24x7_catalog_page(page, 0, 0);
-	if (hret)
+	if (hret) {
+		ret = -ENODEV;
 		goto e_free;
+	}
 
 	catalog_version_num = be64_to_cpu(page_0->version);
 	catalog_page_len = be32_to_cpu(page_0->length);
 
 	if (MAX_4K < catalog_page_len) {
 		pr_err("invalid page count: %zu\n", catalog_page_len);
+		ret = -ENODEV;
 		goto e_free;
 	}
 
@@ -686,6 +692,7 @@ static void create_events_from_catalog(struct attribute ***events_,
 			|| (MAX_4K - event_data_offs < event_data_len)) {
 		pr_err("invalid event data offs %zu and/or len %zu\n",
 				event_data_offs, event_data_len);
+		ret = -ENODEV;
 		goto e_free;
 	}
 
@@ -694,12 +701,14 @@ static void create_events_from_catalog(struct attribute ***events_,
 				event_data_offs,
 				event_data_offs + event_data_len,
 				catalog_page_len);
+		ret = -ENODEV;
 		goto e_free;
 	}
 
 	if (SIZE_MAX / MAX_EVENTS_PER_EVENT_DATA - 1 < event_entry_count) {
 		pr_err("event_entry_count %zu is invalid\n",
 				event_entry_count);
+		ret = -ENODEV;
 		goto e_free;
 	}
 
@@ -712,6 +721,7 @@ static void create_events_from_catalog(struct attribute ***events_,
 	event_data = vmalloc(event_data_bytes);
 	if (!event_data) {
 		pr_err("could not allocate event data\n");
+		ret = -ENOMEM;
 		goto e_free;
 	}
 
@@ -731,6 +741,7 @@ static void create_events_from_catalog(struct attribute ***events_,
 		if (hret) {
 			pr_err("failed to get event data in page %zu\n",
 					i + event_data_offs);
+			ret = -ENODEV;
 			goto e_event_data;
 		}
 	}
@@ -778,18 +789,24 @@ static void create_events_from_catalog(struct attribute ***events_,
 				event_idx_last, event_entry_count, junk_events);
 
 	events = kmalloc_array(attr_max + 1, sizeof(*events), GFP_KERNEL);
-	if (!events)
+	if (!events) {
+		ret = -ENOMEM;
 		goto e_event_data;
+	}
 
 	event_descs = kmalloc_array(event_idx + 1, sizeof(*event_descs),
 				GFP_KERNEL);
-	if (!event_descs)
+	if (!event_descs) {
+		ret = -ENOMEM;
 		goto e_event_attrs;
+	}
 
 	event_long_descs = kmalloc_array(event_idx + 1,
 			sizeof(*event_long_descs), GFP_KERNEL);
-	if (!event_long_descs)
+	if (!event_long_descs) {
+		ret = -ENOMEM;
 		goto e_event_descs;
+	}
 
 	/* Iterate over the catalog filling in the attribute vector */
 	for (junk_events = 0, event_attr_ct = 0, desc_ct = 0, long_desc_ct = 0,
@@ -843,7 +860,7 @@ static void create_events_from_catalog(struct attribute ***events_,
 	*events_ = events;
 	*event_descs_ = event_descs;
 	*event_long_descs_ = event_long_descs;
-	return;
+	return 0;
 
 e_event_descs:
 	kfree(event_descs);
@@ -857,6 +874,7 @@ e_out:
 	*events_ = NULL;
 	*event_descs_ = NULL;
 	*event_long_descs_ = NULL;
+	return ret;
 }
 
 static ssize_t catalog_read(struct file *filp, struct kobject *kobj,
@@ -1219,10 +1237,13 @@ static int hv_24x7_init(void)
 	/* sampling not supported */
 	h_24x7_pmu.capabilities |= PERF_PMU_CAP_NO_INTERRUPT;
 
-	create_events_from_catalog(&event_group.attrs,
+	r = create_events_from_catalog(&event_group.attrs,
 				   &event_desc_group.attrs,
 				   &event_long_desc_group.attrs);
 
+	if (r)
+		return r;
+
 	r = perf_pmu_register(&h_24x7_pmu, h_24x7_pmu.name, -1);
 	if (r)
 		return r;

^ permalink raw reply related	[flat|nested] 7+ messages in thread

* Re: [RFC v2 powerpc] perf/hv-24x7  fail 24x7 initcall if create_events_from_catalog() fails
  2015-04-10  8:42       ` [RFC v2 powerpc] perf/hv-24x7 fail 24x7 initcall if create_events_from_catalog() fails Li Zhong
@ 2015-04-10 10:55         ` Michael Ellerman
  2015-04-13  7:48           ` [PATCH v3 " Li Zhong
  0 siblings, 1 reply; 7+ messages in thread
From: Michael Ellerman @ 2015-04-10 10:55 UTC (permalink / raw)
  To: Li Zhong; +Cc: Paul Mackerras, Sukadev Bhattiprolu, PowerPC email list

On Fri, 2015-04-10 at 16:42 +0800, Li Zhong wrote:
> 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. 

Thanks.
 
> In the patch below, I used ENODEV for hypervisor errors, not sure 
> whether some other error values is more proper here. 

ENODEV is a special case, if an initcall returns ENODEV no error is reported to
dmesg.

In this case I think we would like an error to be reported, so EIO would be
better I think.

cheers

^ permalink raw reply	[flat|nested] 7+ messages in thread

* [PATCH v3 powerpc] perf/hv-24x7  fail 24x7 initcall if create_events_from_catalog() fails
  2015-04-10 10:55         ` Michael Ellerman
@ 2015-04-13  7:48           ` Li Zhong
  0 siblings, 0 replies; 7+ messages in thread
From: Li Zhong @ 2015-04-13  7:48 UTC (permalink / raw)
  To: Michael Ellerman; +Cc: Paul Mackerras, Sukadev Bhattiprolu, PowerPC email list

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>
---
 arch/powerpc/perf/hv-24x7.c | 37 +++++++++++++++++++++++++++++--------
 1 file changed, 29 insertions(+), 8 deletions(-)

diff --git a/arch/powerpc/perf/hv-24x7.c b/arch/powerpc/perf/hv-24x7.c
index 9445a82..ead1420 100644
--- a/arch/powerpc/perf/hv-24x7.c
+++ b/arch/powerpc/perf/hv-24x7.c
@@ -637,7 +637,7 @@ static ssize_t catalog_event_len_validate(struct hv_24x7_event_data *event,
 
 #define MAX_4K (SIZE_MAX / 4096)
 
-static void create_events_from_catalog(struct attribute ***events_,
+static int create_events_from_catalog(struct attribute ***events_,
 		struct attribute ***event_descs_,
 		struct attribute ***event_long_descs_)
 {
@@ -655,19 +655,25 @@ static void create_events_from_catalog(struct attribute ***events_,
 	void *event_data, *end;
 	struct hv_24x7_event_data *event;
 	struct rb_root ev_uniq = RB_ROOT;
+	int ret = 0;
 
-	if (!page)
+	if (!page) {
+		ret = -ENOMEM;
 		goto e_out;
+	}
 
 	hret = h_get_24x7_catalog_page(page, 0, 0);
-	if (hret)
+	if (hret) {
+		ret = -EIO;
 		goto e_free;
+	}
 
 	catalog_version_num = be64_to_cpu(page_0->version);
 	catalog_page_len = be32_to_cpu(page_0->length);
 
 	if (MAX_4K < catalog_page_len) {
 		pr_err("invalid page count: %zu\n", catalog_page_len);
+		ret = -EIO;
 		goto e_free;
 	}
 
@@ -686,6 +692,7 @@ static void create_events_from_catalog(struct attribute ***events_,
 			|| (MAX_4K - event_data_offs < event_data_len)) {
 		pr_err("invalid event data offs %zu and/or len %zu\n",
 				event_data_offs, event_data_len);
+		ret = -EIO;
 		goto e_free;
 	}
 
@@ -694,12 +701,14 @@ static void create_events_from_catalog(struct attribute ***events_,
 				event_data_offs,
 				event_data_offs + event_data_len,
 				catalog_page_len);
+		ret = -EIO;
 		goto e_free;
 	}
 
 	if (SIZE_MAX / MAX_EVENTS_PER_EVENT_DATA - 1 < event_entry_count) {
 		pr_err("event_entry_count %zu is invalid\n",
 				event_entry_count);
+		ret = -EIO;
 		goto e_free;
 	}
 
@@ -712,6 +721,7 @@ static void create_events_from_catalog(struct attribute ***events_,
 	event_data = vmalloc(event_data_bytes);
 	if (!event_data) {
 		pr_err("could not allocate event data\n");
+		ret = -ENOMEM;
 		goto e_free;
 	}
 
@@ -731,6 +741,7 @@ static void create_events_from_catalog(struct attribute ***events_,
 		if (hret) {
 			pr_err("failed to get event data in page %zu\n",
 					i + event_data_offs);
+			ret = -EIO;
 			goto e_event_data;
 		}
 	}
@@ -778,18 +789,24 @@ static void create_events_from_catalog(struct attribute ***events_,
 				event_idx_last, event_entry_count, junk_events);
 
 	events = kmalloc_array(attr_max + 1, sizeof(*events), GFP_KERNEL);
-	if (!events)
+	if (!events) {
+		ret = -ENOMEM;
 		goto e_event_data;
+	}
 
 	event_descs = kmalloc_array(event_idx + 1, sizeof(*event_descs),
 				GFP_KERNEL);
-	if (!event_descs)
+	if (!event_descs) {
+		ret = -ENOMEM;
 		goto e_event_attrs;
+	}
 
 	event_long_descs = kmalloc_array(event_idx + 1,
 			sizeof(*event_long_descs), GFP_KERNEL);
-	if (!event_long_descs)
+	if (!event_long_descs) {
+		ret = -ENOMEM;
 		goto e_event_descs;
+	}
 
 	/* Iterate over the catalog filling in the attribute vector */
 	for (junk_events = 0, event_attr_ct = 0, desc_ct = 0, long_desc_ct = 0,
@@ -843,7 +860,7 @@ static void create_events_from_catalog(struct attribute ***events_,
 	*events_ = events;
 	*event_descs_ = event_descs;
 	*event_long_descs_ = event_long_descs;
-	return;
+	return 0;
 
 e_event_descs:
 	kfree(event_descs);
@@ -857,6 +874,7 @@ e_out:
 	*events_ = NULL;
 	*event_descs_ = NULL;
 	*event_long_descs_ = NULL;
+	return ret;
 }
 
 static ssize_t catalog_read(struct file *filp, struct kobject *kobj,
@@ -1219,10 +1237,13 @@ static int hv_24x7_init(void)
 	/* sampling not supported */
 	h_24x7_pmu.capabilities |= PERF_PMU_CAP_NO_INTERRUPT;
 
-	create_events_from_catalog(&event_group.attrs,
+	r = create_events_from_catalog(&event_group.attrs,
 				   &event_desc_group.attrs,
 				   &event_long_desc_group.attrs);
 
+	if (r)
+		return r;
+
 	r = perf_pmu_register(&h_24x7_pmu, h_24x7_pmu.name, -1);
 	if (r)
 		return r;

^ permalink raw reply related	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2015-04-13  7:52 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2015-02-15  9:42 [RFC PATCH powerpc] perf/hv-24x7 set the attr group to NULL if events failed to be initialized Li Zhong
2015-03-25  9:51 ` [RFC, " Michael Ellerman
2015-03-25 18:41   ` Sukadev Bhattiprolu
2015-03-26  3:51     ` Michael Ellerman
2015-04-10  8:42       ` [RFC v2 powerpc] perf/hv-24x7 fail 24x7 initcall if create_events_from_catalog() fails Li Zhong
2015-04-10 10:55         ` Michael Ellerman
2015-04-13  7:48           ` [PATCH v3 " Li Zhong

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).