<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/">
    <channel>
        <title>[PATCH v3 3/3] perf script/python: Pass event/thread/dso name and symbol info to event handler in python</title>
        <description> Also as suggested by Arnaldo, pack all these parameters to a dictionary,
which is more expandable for adding new parameters while keep the
compatibility for old scripts.

Signed-off-by: Feng Tang &amp;lt;feng.tang@intel.com&amp;gt;
---
 .../util/scripting-engines/trace-event-python.c    |   32 +++++++++++++++----
 1 files changed, 25 insertions(+), 7 deletions(-)

diff --git a/tools/perf/util/scripting-engines/trace-event-python.c b/tools/perf/util/scripting-engines/trace-event-python.c
index 97f4fad..e8ac480 100644
--- a/tools/perf/util/scripting-engines/trace-event-python.c
+++ b/tools/perf/util/scripting-engines/trace-event-python.c
@@ -336,15 +336,23 @@ static void python_process_general_event(union perf_event *pevent __unused,
 				 struct machine *machine __unused,
 				 struct addr_location *al)
 {
-	PyObject *handler, *retval, *t;
+	PyObject *handler, *retval, *t, *dict;
 	static char handler_name[64];
 	unsigned n = 0;
-	void *data = sample-&amp;gt;raw_data;
+	struct thread *thread = al-&amp;gt;thread;
 
+	/*
+	 * Use the MAX_FIELDS to make the function expandable, though
+	 * currently there is only one itme for the tuple.
+	 */
 	t = PyTuple_New(MAX_FIELDS);
 	if (!t)
 		Py_FatalError(&amp;quot;couldn't create Python tuple&amp;quot;);
 
+	dict = PyDict_New();
+	if (!dict)
+		Py_FatalError(&amp;quot;couldn't create Python dictionary&amp;quot;);
+
 	snprintf(handler_name, sizeof(handler_name), &amp;quot;%s&amp;quot;, &amp;quot;process_event&amp;quot;);
 
 	handler = PyDict_GetItemString(main_dict, handler_name);
@@ -353,14 +361,23 @@ static void python_process_general_event(union perf_event *pevent __unused,
 		goto exit;
 	}
 
-	/* Pass 4 parameters: event_attr, perf_sample, raw data, thread name */
-	PyTuple_SetItem(t, n++, PyString_FromStringAndSize(
+	PyDict_SetItemString(dict, &amp;quot;ev_name&amp;quot;, PyString_FromString(event_name(evsel)));
+	PyDict_SetItemString(dict, &amp;quot;attr&amp;quot;, PyString_FromStringAndSize(
 			(const char *)&amp;amp;evsel-&amp;gt;attr, sizeof(evsel-&amp;gt;attr)));
-	PyTuple_SetItem(t, n++, PyString_FromStringAndSize(
+	PyDict_SetItemString(dict, &amp;quot;sample&amp;quot;, PyString_FromStringAndSize(
 			(const char *)sample, sizeof(*sample)));
-	PyTuple_SetItem(t, n++, PyString_FromStringAndSize(
-			data, sample-&amp;gt;raw_size));
+	PyDict_SetItemString(dict, &amp;quot;raw_buf&amp;quot;, PyString_FromStringAndSize(
+			(const char *)sample-&amp;gt;raw_data, sample-&amp;gt;raw_size));
+	PyDict_SetItemString(dict, &amp;quot;comm&amp;quot;,
+			PyString_FromString(thread-&amp;gt;comm));
+	PyDict_SetItemString(dict, &amp;quot;dso&amp;quot;,
+			PyString_FromString(al-&amp;gt;map-&amp;gt;dso-&amp;gt;name));
+	if (al-&amp;gt;sym) {
+		PyDict_SetItemString(dict, &amp;quot;symbol&amp;quot;,
+			PyString_FromString(al-&amp;gt;sym-&amp;gt;name));
+	}
 
+	PyTuple_SetItem(t, n++, dict);
 	if (_PyTuple_Resize(&amp;amp;t, n) == -1)
 		Py_FatalError(&amp;quot;error resizing Python tuple&amp;quot;);
 
@@ -368,6 +385,7 @@ static void python_process_general_event(union perf_event *pevent __unused,
 	if (retval == NULL)
 		handler_call_die(handler_name);
 exit:
+	Py_DECREF(dict);
 	Py_DECREF(t);
 }
 
-- 
1.7.1

--
To unsubscribe from this list: send the line &amp;quot;unsubscribe linux-kernel&amp;quot; in
the body of a message to &amp;#109;&amp;#97;&amp;#106;&amp;#111;&amp;#114;&amp;#100;&amp;#111;&amp;#109;&amp;#111;&amp;#64;&amp;#118;&amp;#103;&amp;#101;&amp;#114;&amp;#46;&amp;#107;&amp;#101;&amp;#114;&amp;#110;&amp;#101;&amp;#108;&amp;#46;&amp;#111;&amp;#114;&amp;#103;
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/</description>
        <link>http://www.serverphorums.com/read.php?12,515012,515012#msg-515012</link>
        <lastBuildDate>Sat, 25 May 2013 01:05:39 +0200</lastBuildDate>
        <generator>Phorum 5.2.18</generator>
        <item>
            <guid>http://www.serverphorums.com/read.php?12,515012,521281#msg-521281</guid>
            <title>Re: [PATCH v3 3/3] perf script/python: Pass event/thread/dso name and symbol info to event handler in python</title>
            <link>http://www.serverphorums.com/read.php?12,515012,521281#msg-521281</link>
            <description><![CDATA[ On Thu, 28 Jun 2012 14:29:31 -0300<br />
Arnaldo Carvalho de Melo &lt;acme@redhat.com&gt; wrote:<br />
<br />
&gt; Em Thu, Jun 28, 2012 at 04:50:27PM +0800, Feng Tang escreveu:<br />
&gt; &gt; On Wed, 27 Jun 2012 15:58:17 -0300<br />
&gt; &gt; Arnaldo Carvalho de Melo &lt;acme@redhat.com&gt; wrote:<br />
&gt; &gt; &gt; Now old scrips will break, as the tuple they expect:<br />
&gt; &gt; &gt; <br />
&gt; &gt; &gt;  (attr, sample, raw_data)<br />
&gt; &gt; &gt; <br />
&gt; &gt; &gt; will not be there.<br />
&gt; &gt; <br />
&gt; &gt; Actually, there are no such scripts out. Current perf python script only<br />
&gt; &gt; supports the trace point type, while perl scriptt has the support for<br />
&gt; &gt; general events. It is my first patch &quot;perf script: Add general python <br />
&gt; &gt; handler to process non-tracepoint events&quot; which bring this (attr, sample,<br />
&gt; &gt; raw_data) in to be on the same page as perl. So this won't be a problem<br />
&gt; &gt; when the 3 patches are merged together. <br />
&gt; <br />
&gt; Cool, I forgot about that, thanks for correcting me :-)<br />
&gt; <br />
&gt; But even then, perf and python diverged in this... anyway, not a big<br />
&gt; deal, I guess, the info available for perl scripts will be available in<br />
&gt; the dict as well, right?<br />
<br />
No, current perl code will pass 4 rather raw data structures to the<br />
script's &quot;process_event&quot;: pevent-&gt;header, evel-&gt;attr, sample, sample-&gt;raw_data<br />
<br />
	XPUSHs(sv_2mortal(newSVpvn((const char *)pevent, pevent-&gt;header.size)));<br />
	XPUSHs(sv_2mortal(newSVpvn((const char *)&amp;evsel-&gt;attr, sizeof(evsel-&gt;attr))));<br />
	XPUSHs(sv_2mortal(newSVpvn((const char *)sample, sizeof(*sample))));<br />
	XPUSHs(sv_2mortal(newSVpvn((const char *)sample-&gt;raw_data, sample-&gt;raw_size)));<br />
<br />
my patch only have the last 3 ones plus extra event_name/dso_name/symobl,<br />
while missing the &quot;pevent-&gt;header&quot;, do you want me to add it?<br />
<br />
&gt;  <br />
&gt; &gt; &gt; The first two patches in this series don't apply anymore, please find<br />
&gt; &gt; &gt; them attached fixed, please check if they work as expected.<br />
&gt; <br />
&gt; &gt; Thanks a lot for fixing them, I'll generate perf tool patch against the<br />
&gt; &gt; &quot;perf/core&quot; branch of your git tree on kernel.org from now on.<br />
&gt; &gt; <br />
&gt; &gt; Btw, I have 2 more python scripts based on these patches, will add them<br />
&gt; &gt; to this serie for your review.<br />
&gt; <br />
&gt; Ok, will take a look at them.<br />
<br />
Thanks,<br />
<br />
- Feng<br />
--<br />
To unsubscribe from this list: send the line &quot;unsubscribe linux-kernel&quot; in<br />
the body of a message to <a href="mailto:&#109;&#97;&#106;&#111;&#114;&#100;&#111;&#109;&#111;&#64;&#118;&#103;&#101;&#114;&#46;&#107;&#101;&#114;&#110;&#101;&#108;&#46;&#111;&#114;&#103;">&#109;&#97;&#106;&#111;&#114;&#100;&#111;&#109;&#111;&#64;&#118;&#103;&#101;&#114;&#46;&#107;&#101;&#114;&#110;&#101;&#108;&#46;&#111;&#114;&#103;</a><br />
More majordomo info at  <a href="http://vger.kernel.org/majordomo-info.html" target="_blank"  rel="nofollow">http://vger.kernel.org/majordomo-info.html</a><br />
Please read the FAQ at  <a href="http://www.tux.org/lkml/" target="_blank"  rel="nofollow">http://www.tux.org/lkml/</a>]]></description>
            <dc:creator>Feng Tang</dc:creator>
            <category>Linux Kernel</category>
            <pubDate>Fri, 29 Jun 2012 03:30:01 +0200</pubDate>
        </item>
        <item>
            <guid>http://www.serverphorums.com/read.php?12,515012,521146#msg-521146</guid>
            <title>Re: [PATCH v3 3/3] perf script/python: Pass event/thread/dso name and symbol info to event handler in python</title>
            <link>http://www.serverphorums.com/read.php?12,515012,521146#msg-521146</link>
            <description><![CDATA[ Em Thu, Jun 28, 2012 at 04:50:27PM +0800, Feng Tang escreveu:<br />
&gt; On Wed, 27 Jun 2012 15:58:17 -0300<br />
&gt; Arnaldo Carvalho de Melo &lt;acme@redhat.com&gt; wrote:<br />
&gt; &gt; Now old scrips will break, as the tuple they expect:<br />
&gt; &gt; <br />
&gt; &gt;  (attr, sample, raw_data)<br />
&gt; &gt; <br />
&gt; &gt; will not be there.<br />
&gt; <br />
&gt; Actually, there are no such scripts out. Current perf python script only<br />
&gt; supports the trace point type, while perl scriptt has the support for<br />
&gt; general events. It is my first patch &quot;perf script: Add general python <br />
&gt; handler to process non-tracepoint events&quot; which bring this (attr, sample,<br />
&gt; raw_data) in to be on the same page as perl. So this won't be a problem<br />
&gt; when the 3 patches are merged together. <br />
<br />
Cool, I forgot about that, thanks for correcting me :-)<br />
<br />
But even then, perf and python diverged in this... anyway, not a big<br />
deal, I guess, the info available for perl scripts will be available in<br />
the dict as well, right?<br />
 <br />
&gt; &gt; The first two patches in this series don't apply anymore, please find<br />
&gt; &gt; them attached fixed, please check if they work as expected.<br />
<br />
&gt; Thanks a lot for fixing them, I'll generate perf tool patch against the<br />
&gt; &quot;perf/core&quot; branch of your git tree on kernel.org from now on.<br />
&gt; <br />
&gt; Btw, I have 2 more python scripts based on these patches, will add them<br />
&gt; to this serie for your review.<br />
<br />
Ok, will take a look at them.<br />
<br />
- Arnaldo<br />
--<br />
To unsubscribe from this list: send the line &quot;unsubscribe linux-kernel&quot; in<br />
the body of a message to <a href="mailto:&#109;&#97;&#106;&#111;&#114;&#100;&#111;&#109;&#111;&#64;&#118;&#103;&#101;&#114;&#46;&#107;&#101;&#114;&#110;&#101;&#108;&#46;&#111;&#114;&#103;">&#109;&#97;&#106;&#111;&#114;&#100;&#111;&#109;&#111;&#64;&#118;&#103;&#101;&#114;&#46;&#107;&#101;&#114;&#110;&#101;&#108;&#46;&#111;&#114;&#103;</a><br />
More majordomo info at  <a href="http://vger.kernel.org/majordomo-info.html" target="_blank"  rel="nofollow">http://vger.kernel.org/majordomo-info.html</a><br />
Please read the FAQ at  <a href="http://www.tux.org/lkml/" target="_blank"  rel="nofollow">http://www.tux.org/lkml/</a>]]></description>
            <dc:creator>Arnaldo Carvalho de Melo</dc:creator>
            <category>Linux Kernel</category>
            <pubDate>Thu, 28 Jun 2012 19:40:01 +0200</pubDate>
        </item>
        <item>
            <guid>http://www.serverphorums.com/read.php?12,515012,520781#msg-520781</guid>
            <title>Re: [PATCH v3 3/3] perf script/python: Pass event/thread/dso name and symbol info to event handler in python</title>
            <link>http://www.serverphorums.com/read.php?12,515012,520781#msg-520781</link>
            <description><![CDATA[ Hi Arnaldo,<br />
<br />
On Wed, 27 Jun 2012 15:58:17 -0300<br />
Arnaldo Carvalho de Melo &lt;acme@redhat.com&gt; wrote:<br />
<br />
&gt; Em Mon, Jun 18, 2012 at 02:10:39PM +0800, Feng Tang escreveu:<br />
&gt; &gt; Also as suggested by Arnaldo, pack all these parameters to a dictionary,<br />
&gt; &gt; which is more expandable for adding new parameters while keep the<br />
&gt; &gt; compatibility for old scripts.<br />
&gt; &gt; <br />
&gt; &gt; Signed-off-by: Feng Tang &lt;feng.tang@intel.com&gt;<br />
&gt; &gt; ---<br />
&gt; &gt;  .../util/scripting-engines/trace-event-python.c    |   32<br />
&gt; &gt; +++++++++++++++---- 1 files changed, 25 insertions(+), 7 deletions(-)<br />
&gt; &gt; <br />
&gt; &gt; diff --git a/tools/perf/util/scripting-engines/trace-event-python.c<br />
&gt; &gt; b/tools/perf/util/scripting-engines/trace-event-python.c index<br />
&gt; &gt; 97f4fad..e8ac480 100644 ---<br />
&gt; &gt; a/tools/perf/util/scripting-engines/trace-event-python.c +++<br />
&gt; &gt; b/tools/perf/util/scripting-engines/trace-event-python.c @@ -336,15 +336,23<br />
&gt; &gt; @@ static void python_process_general_event(union perf_event *pevent<br />
&gt; &gt; __unused, struct machine *machine __unused, struct addr_location *al)<br />
&gt; &gt;  {<br />
&gt; &gt; -	PyObject *handler, *retval, *t;<br />
&gt; &gt; +	PyObject *handler, *retval, *t, *dict;<br />
&gt; &gt;  	static char handler_name[64];<br />
&gt; &gt;  	unsigned n = 0;<br />
&gt; &gt; -	void *data = sample-&gt;raw_data;<br />
&gt; &gt; +	struct thread *thread = al-&gt;thread;<br />
&gt; &gt;  <br />
&gt; &gt; +	/*<br />
&gt; &gt; +	 * Use the MAX_FIELDS to make the function expandable, though<br />
&gt; &gt; +	 * currently there is only one itme for the tuple.<br />
&gt; &gt; +	 */<br />
&gt; &gt;  	t = PyTuple_New(MAX_FIELDS);<br />
&gt; &gt;  	if (!t)<br />
&gt; &gt;  		Py_FatalError(&quot;couldn't create Python tuple&quot;);<br />
&gt; &gt;  <br />
&gt; &gt; +	dict = PyDict_New();<br />
&gt; &gt; +	if (!dict)<br />
&gt; &gt; +		Py_FatalError(&quot;couldn't create Python dictionary&quot;);<br />
&gt; &gt; +<br />
&gt; &gt;  	snprintf(handler_name, sizeof(handler_name), &quot;%s&quot;,<br />
&gt; &gt; &quot;process_event&quot;); <br />
&gt; &gt;  	handler = PyDict_GetItemString(main_dict, handler_name);<br />
&gt; &gt; @@ -353,14 +361,23 @@ static void python_process_general_event(union<br />
&gt; &gt; perf_event *pevent __unused, goto exit;<br />
&gt; &gt;  	}<br />
&gt; &gt;  <br />
&gt; &gt; -	/* Pass 4 parameters: event_attr, perf_sample, raw data, thread<br />
&gt; &gt; name */<br />
&gt; &gt; -	PyTuple_SetItem(t, n++, PyString_FromStringAndSize(<br />
&gt; &gt; +	PyDict_SetItemString(dict, &quot;ev_name&quot;,<br />
&gt; &gt; PyString_FromString(event_name(evsel)));<br />
&gt; &gt; +	PyDict_SetItemString(dict, &quot;attr&quot;, PyString_FromStringAndSize(<br />
&gt; &gt;  			(const char *)&amp;evsel-&gt;attr, sizeof(evsel-&gt;attr)));<br />
&gt; &gt; -	PyTuple_SetItem(t, n++, PyString_FromStringAndSize(<br />
&gt; &gt; +	PyDict_SetItemString(dict, &quot;sample&quot;, PyString_FromStringAndSize(<br />
&gt; &gt;  			(const char *)sample, sizeof(*sample)));<br />
&gt; &gt; -	PyTuple_SetItem(t, n++, PyString_FromStringAndSize(<br />
&gt; &gt; -			data, sample-&gt;raw_size));<br />
&gt; &gt; +	PyDict_SetItemString(dict, &quot;raw_buf&quot;, PyString_FromStringAndSize(<br />
&gt; &gt; +			(const char *)sample-&gt;raw_data, sample-&gt;raw_size));<br />
&gt; &gt; +	PyDict_SetItemString(dict, &quot;comm&quot;,<br />
&gt; &gt; +			PyString_FromString(thread-&gt;comm));<br />
&gt; &gt; +	PyDict_SetItemString(dict, &quot;dso&quot;,<br />
&gt; &gt; +			PyString_FromString(al-&gt;map-&gt;dso-&gt;name));<br />
&gt; &gt; +	if (al-&gt;sym) {<br />
&gt; &gt; +		PyDict_SetItemString(dict, &quot;symbol&quot;,<br />
&gt; &gt; +			PyString_FromString(al-&gt;sym-&gt;name));<br />
&gt; &gt; +	}<br />
&gt; &gt;  <br />
&gt; &gt; +	PyTuple_SetItem(t, n++, dict);<br />
&gt; <br />
&gt; Now old scrips will break, as the tuple they expect:<br />
&gt; <br />
&gt;  (attr, sample, raw_data)<br />
&gt; <br />
&gt; will not be there.<br />
<br />
Actually, there are no such scripts out. Current perf python script only<br />
supports the trace point type, while perl scriptt has the support for<br />
general events. It is my first patch &quot;perf script: Add general python <br />
handler to process non-tracepoint events&quot; which bring this (attr, sample,<br />
raw_data) in to be on the same page as perl. So this won't be a problem<br />
when the 3 patches are merged together. <br />
<br />
&gt; <br />
&gt; The first two patches in this series don't apply anymore, please find<br />
&gt; them attached fixed, please check if they work as expected.<br />
Thanks a lot for fixing them, I'll generate perf tool patch against the<br />
&quot;perf/core&quot; branch of your git tree on kernel.org from now on.<br />
<br />
Btw, I have 2 more python scripts based on these patches, will add them<br />
to this serie for your review.<br />
<br />
Thanks,<br />
Feng<br />
<br />
--<br />
To unsubscribe from this list: send the line &quot;unsubscribe linux-kernel&quot; in<br />
the body of a message to <a href="mailto:&#109;&#97;&#106;&#111;&#114;&#100;&#111;&#109;&#111;&#64;&#118;&#103;&#101;&#114;&#46;&#107;&#101;&#114;&#110;&#101;&#108;&#46;&#111;&#114;&#103;">&#109;&#97;&#106;&#111;&#114;&#100;&#111;&#109;&#111;&#64;&#118;&#103;&#101;&#114;&#46;&#107;&#101;&#114;&#110;&#101;&#108;&#46;&#111;&#114;&#103;</a><br />
More majordomo info at  <a href="http://vger.kernel.org/majordomo-info.html" target="_blank"  rel="nofollow">http://vger.kernel.org/majordomo-info.html</a><br />
Please read the FAQ at  <a href="http://www.tux.org/lkml/" target="_blank"  rel="nofollow">http://www.tux.org/lkml/</a>]]></description>
            <dc:creator>Feng Tang</dc:creator>
            <category>Linux Kernel</category>
            <pubDate>Thu, 28 Jun 2012 11:00:02 +0200</pubDate>
        </item>
        <item>
            <guid>http://www.serverphorums.com/read.php?12,515012,520400#msg-520400</guid>
            <title>Re: [PATCH v3 3/3] perf script/python: Pass event/thread/dso name and symbol info to event handler in python</title>
            <link>http://www.serverphorums.com/read.php?12,515012,520400#msg-520400</link>
            <description><![CDATA[ Em Mon, Jun 18, 2012 at 02:10:39PM +0800, Feng Tang escreveu:<br />
&gt; Also as suggested by Arnaldo, pack all these parameters to a dictionary,<br />
&gt; which is more expandable for adding new parameters while keep the<br />
&gt; compatibility for old scripts.<br />
&gt; <br />
&gt; Signed-off-by: Feng Tang &lt;feng.tang@intel.com&gt;<br />
&gt; ---<br />
&gt;  .../util/scripting-engines/trace-event-python.c    |   32 +++++++++++++++----<br />
&gt;  1 files changed, 25 insertions(+), 7 deletions(-)<br />
&gt; <br />
&gt; diff --git a/tools/perf/util/scripting-engines/trace-event-python.c b/tools/perf/util/scripting-engines/trace-event-python.c<br />
&gt; index 97f4fad..e8ac480 100644<br />
&gt; --- a/tools/perf/util/scripting-engines/trace-event-python.c<br />
&gt; +++ b/tools/perf/util/scripting-engines/trace-event-python.c<br />
&gt; @@ -336,15 +336,23 @@ static void python_process_general_event(union perf_event *pevent __unused,<br />
&gt;  				 struct machine *machine __unused,<br />
&gt;  				 struct addr_location *al)<br />
&gt;  {<br />
&gt; -	PyObject *handler, *retval, *t;<br />
&gt; +	PyObject *handler, *retval, *t, *dict;<br />
&gt;  	static char handler_name[64];<br />
&gt;  	unsigned n = 0;<br />
&gt; -	void *data = sample-&gt;raw_data;<br />
&gt; +	struct thread *thread = al-&gt;thread;<br />
&gt;  <br />
&gt; +	/*<br />
&gt; +	 * Use the MAX_FIELDS to make the function expandable, though<br />
&gt; +	 * currently there is only one itme for the tuple.<br />
&gt; +	 */<br />
&gt;  	t = PyTuple_New(MAX_FIELDS);<br />
&gt;  	if (!t)<br />
&gt;  		Py_FatalError(&quot;couldn't create Python tuple&quot;);<br />
&gt;  <br />
&gt; +	dict = PyDict_New();<br />
&gt; +	if (!dict)<br />
&gt; +		Py_FatalError(&quot;couldn't create Python dictionary&quot;);<br />
&gt; +<br />
&gt;  	snprintf(handler_name, sizeof(handler_name), &quot;%s&quot;, &quot;process_event&quot;);<br />
&gt;  <br />
&gt;  	handler = PyDict_GetItemString(main_dict, handler_name);<br />
&gt; @@ -353,14 +361,23 @@ static void python_process_general_event(union perf_event *pevent __unused,<br />
&gt;  		goto exit;<br />
&gt;  	}<br />
&gt;  <br />
&gt; -	/* Pass 4 parameters: event_attr, perf_sample, raw data, thread name */<br />
&gt; -	PyTuple_SetItem(t, n++, PyString_FromStringAndSize(<br />
&gt; +	PyDict_SetItemString(dict, &quot;ev_name&quot;, PyString_FromString(event_name(evsel)));<br />
&gt; +	PyDict_SetItemString(dict, &quot;attr&quot;, PyString_FromStringAndSize(<br />
&gt;  			(const char *)&amp;evsel-&gt;attr, sizeof(evsel-&gt;attr)));<br />
&gt; -	PyTuple_SetItem(t, n++, PyString_FromStringAndSize(<br />
&gt; +	PyDict_SetItemString(dict, &quot;sample&quot;, PyString_FromStringAndSize(<br />
&gt;  			(const char *)sample, sizeof(*sample)));<br />
&gt; -	PyTuple_SetItem(t, n++, PyString_FromStringAndSize(<br />
&gt; -			data, sample-&gt;raw_size));<br />
&gt; +	PyDict_SetItemString(dict, &quot;raw_buf&quot;, PyString_FromStringAndSize(<br />
&gt; +			(const char *)sample-&gt;raw_data, sample-&gt;raw_size));<br />
&gt; +	PyDict_SetItemString(dict, &quot;comm&quot;,<br />
&gt; +			PyString_FromString(thread-&gt;comm));<br />
&gt; +	PyDict_SetItemString(dict, &quot;dso&quot;,<br />
&gt; +			PyString_FromString(al-&gt;map-&gt;dso-&gt;name));<br />
&gt; +	if (al-&gt;sym) {<br />
&gt; +		PyDict_SetItemString(dict, &quot;symbol&quot;,<br />
&gt; +			PyString_FromString(al-&gt;sym-&gt;name));<br />
&gt; +	}<br />
&gt;  <br />
&gt; +	PyTuple_SetItem(t, n++, dict);<br />
<br />
Now old scrips will break, as the tuple they expect:<br />
<br />
 (attr, sample, raw_data)<br />
<br />
will not be there.<br />
<br />
To not break those scripts you must leave it there and add the new ones<br />
in a python compatible way. I.e. have you tested the existing scripts<br />
using the new perf tool with your patches applied? They must continue to<br />
work.<br />
<br />
I.e. leave the old tuple and add the dict at the end somehow.<br />
<br />
The first two patches in this series don't apply anymore, please find<br />
them attached fixed, please check if they work as expected.<br />
<br />
- Arnaldo<br />
From 429bf5a8d5b27b444cbdfaea088d883d8921fb48 Mon Sep 17 00:00:00 2001<br />
From: Feng Tang &lt;feng.tang@intel.com&gt;<br />
Date: Wed, 27 Jun 2012 15:07:02 -0300<br />
Subject: [PATCH 1/2] perf script: Add general python handler to process non-tracepoint events<br />
Content-Type: text/plain; charset=&quot;UTF-8&quot;<br />
<br />
This patch just follows Robert Richter's idea and the commit 37a058ea0<br />
	&quot;perf script: Add generic perl handler to process events&quot;<br />
to similarly add a python handler for general events other than tracepoints.<br />
<br />
For non-tracepoint events, this patch will try to find a function named<br />
&quot;process_event&quot; in the python script, and pass the event attribute,<br />
perf_sample, raw_data in format of raw string. And the python script can<br />
use &quot;struct&quot; module's unpack function to disasemble the needed info and process.<br />
<br />
Signed-off-by: Feng Tang &lt;feng.tang@intel.com&gt;<br />
Cc: Andi Kleen &lt;andi@firstfloor.org&gt;<br />
Cc: David Ahern &lt;dsahern@gmail.com&gt;<br />
Cc: Peter Zijlstra &lt;peterz@infradead.org&gt;<br />
Cc: Robert Richter &lt;robert.richter@amd.com&gt;<br />
Cc: Stephane Eranian &lt;eranian@google.com&gt;<br />
<a href="http://lkml.kernel.org/r/1339999839-14007-2-git-send-email-feng.tang@intel.com" target="_blank"  rel="nofollow">http://lkml.kernel.org/r/1339999839-14007-2-git-send-email-feng.tang@intel.com</a><br />
[ committer note: Fixed up wrt da37896, i.e. pevent parm in script event handlers ]<br />
Signed-off-by: Arnaldo Carvalho de Melo &lt;acme@redhat.com&gt;<br />
---<br />
 .../util/scripting-engines/trace-event-python.c    |   71 ++++++++++++++++++--<br />
 1 files changed, 65 insertions(+), 6 deletions(-)<br />
<br />
diff --git a/tools/perf/util/scripting-engines/trace-event-python.c b/tools/perf/util/scripting-engines/trace-event-python.c<br />
index a8ca2f8..3fae022 100644<br />
--- a/tools/perf/util/scripting-engines/trace-event-python.c<br />
+++ b/tools/perf/util/scripting-engines/trace-event-python.c<br />
@@ -31,6 +31,7 @@<br />
 #include &quot;../event.h&quot;<br />
 #include &quot;../thread.h&quot;<br />
 #include &quot;../trace-event.h&quot;<br />
+#include &quot;../evsel.h&quot;<br />
 <br />
 PyMODINIT_FUNC initperf_trace_context(void);<br />
 <br />
@@ -210,12 +211,12 @@ struct event_format *find_cache_event(struct pevent *pevent, int type)<br />
 	return event;<br />
 }<br />
 <br />
-static void python_process_event(union perf_event *perf_event __unused,<br />
-				 struct pevent *pevent,<br />
-				 struct perf_sample *sample,<br />
-				 struct perf_evsel *evsel __unused,<br />
-				 struct machine *machine __unused,<br />
-				 struct thread *thread)<br />
+static void python_process_tracepoint(union perf_event *perf_event __unused,<br />
+				      struct pevent *pevent,<br />
+				      struct perf_sample *sample,<br />
+				      struct perf_evsel *evsel __unused,<br />
+				      struct machine *machine __unused,<br />
+				      struct thread *thread)<br />
 {<br />
 	PyObject *handler, *retval, *context, *t, *obj, *dict = NULL;<br />
 	static char handler_name[256];<br />
@@ -331,6 +332,64 @@ static void python_process_event(union perf_event *perf_event __unused,<br />
 	Py_DECREF(t);<br />
 }<br />
 <br />
+static void python_process_general_event(union perf_event *perf_event __unused,<br />
+					 struct pevent *pevent,<br />
+					 struct perf_sample *sample,<br />
+					 struct perf_evsel *evsel,<br />
+					 struct machine *machine __unused,<br />
+					 struct thread *thread __unused)<br />
+{<br />
+	PyObject *handler, *retval, *t;<br />
+	static char handler_name[64];<br />
+	unsigned n = 0;<br />
+	void *data = sample-&gt;raw_data;<br />
+<br />
+	t = PyTuple_New(MAX_FIELDS);<br />
+	if (!t)<br />
+		Py_FatalError(&quot;couldn't create Python tuple&quot;);<br />
+<br />
+	snprintf(handler_name, sizeof(handler_name), &quot;%s&quot;, &quot;process_event&quot;);<br />
+<br />
+	handler = PyDict_GetItemString(main_dict, handler_name);<br />
+	if (handler &amp;&amp; !PyCallable_Check(handler)) {<br />
+		handler = NULL;<br />
+		goto exit;<br />
+	}<br />
+<br />
+	/* Pass 3 parameters: event_attr, perf_sample, raw data */<br />
+	PyTuple_SetItem(t, n++, PyString_FromStringAndSize((void *)&amp;evsel-&gt;attr, sizeof(evsel-&gt;attr)));<br />
+	PyTuple_SetItem(t, n++, PyString_FromStringAndSize((void *)sample, sizeof(*sample)));<br />
+	PyTuple_SetItem(t, n++, PyString_FromStringAndSize(data, sample-&gt;raw_size));<br />
+<br />
+	if (_PyTuple_Resize(&amp;t, n) == -1)<br />
+		Py_FatalError(&quot;error resizing Python tuple&quot;);<br />
+<br />
+	retval = PyObject_CallObject(handler, t);<br />
+	if (retval == NULL)<br />
+		handler_call_die(handler_name);<br />
+exit:<br />
+	Py_DECREF(t);<br />
+}<br />
+<br />
+static void python_process_event(union perf_event *perf_event,<br />
+				 struct pevent *pevent,<br />
+				 struct perf_sample *sample,<br />
+				 struct perf_evsel *evsel,<br />
+				 struct machine *machine,<br />
+				 struct thread *thread)<br />
+{<br />
+	switch (evsel-&gt;attr.type) {<br />
+	case PERF_TYPE_TRACEPOINT:<br />
+		python_process_tracepoint(perf_event, pevent, sample, evsel,<br />
+					  machine, thread);<br />
+		break;<br />
+	/* Reserve for future process_hw/sw/raw APIs */<br />
+	default:<br />
+		python_process_general_event(perf_event, pevent, sample, evsel,<br />
+					     machine, thread);<br />
+	}<br />
+}<br />
+<br />
 static int run_start_sub(void)<br />
 {<br />
 	PyObject *handler, *retval;<br />
-- <br />
1.7.1<br />
<br />
From 16c5860d9f34236920ebb71b346417c638aa7198 Mon Sep 17 00:00:00 2001<br />
From: Feng Tang &lt;feng.tang@intel.com&gt;<br />
Date: Wed, 27 Jun 2012 15:24:16 -0300<br />
Subject: [PATCH 2/2] perf script: Replace &quot;struct thread&quot; with &quot;struct addr_location&quot; as a parameter for &quot;process_event()&quot;<br />
Content-Type: text/plain; charset=&quot;UTF-8&quot;<br />
<br />
Both perl and python script start processing events other than trace<br />
points, and it's useful to pass the resolved symbol and the dso info to<br />
the event handler in script for better analysis and statistics.<br />
<br />
Struct thread is already a member of struct addr_location, using<br />
addr_location will keep the thread info, while providing additional<br />
symbol and dso info if exist, so that the script itself doesn't need to<br />
bother to do the symbol resolving and dso searching work.<br />
<br />
Signed-off-by: Feng Tang &lt;feng.tang@intel.com&gt;<br />
Acked-by: David Ahern &lt;dsahern@gmail.com&gt;<br />
Tested-by: David Ahern &lt;dsahern@gmail.com&gt;<br />
Cc: David Ahern &lt;dsahern@gmail.com&gt;<br />
Cc: Peter Zijlstra &lt;peterz@infradead.org&gt;<br />
Cc: Robert Richter &lt;robert.richter@amd.com&gt;<br />
Cc: Andi Kleen &lt;andi@firstfloor.org&gt;<br />
Cc: Stephane Eranian &lt;eranian@google.com&gt;<br />
Link: <a href="http://lkml.kernel.org/r/1339999839-14007-3-git-send-email-feng.tang@intel.com&gt" target="_blank"  rel="nofollow">http://lkml.kernel.org/r/1339999839-14007-3-git-send-email-feng.tang@intel.com&gt</a>;<br />
Signed-off-by: Arnaldo Carvalho de Melo &lt;acme@redhat.com&gt;<br />
---<br />
 tools/perf/builtin-script.c                        |    5 +++--<br />
 .../perf/util/scripting-engines/trace-event-perl.c |   13 +++++++------<br />
 .../util/scripting-engines/trace-event-python.c    |   13 +++++++------<br />
 tools/perf/util/trace-event-scripting.c            |    2 +-<br />
 tools/perf/util/trace-event.h                      |    5 +++--<br />
 5 files changed, 21 insertions(+), 17 deletions(-)<br />
<br />
diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c<br />
index 1e60ab7..e588090 100644<br />
--- a/tools/perf/builtin-script.c<br />
+++ b/tools/perf/builtin-script.c<br />
@@ -420,9 +420,10 @@ static void process_event(union perf_event *event __unused,<br />
 			  struct perf_sample *sample,<br />
 			  struct perf_evsel *evsel,<br />
 			  struct machine *machine,<br />
-			  struct thread *thread)<br />
+			  struct addr_location *al)<br />
 {<br />
 	struct perf_event_attr *attr = &amp;evsel-&gt;attr;<br />
+	struct thread *thread = al-&gt;thread;<br />
 <br />
 	if (output[attr-&gt;type].fields == 0)<br />
 		return;<br />
@@ -538,7 +539,7 @@ static int process_sample_event(struct perf_tool *tool __used,<br />
 		return 0;<br />
 <br />
 	scripting_ops-&gt;process_event(event, scr-&gt;session-&gt;pevent,<br />
-				     sample, evsel, machine, thread);<br />
+				     sample, evsel, machine, &amp;al);<br />
 <br />
 	evsel-&gt;hists.stats.total_period += sample-&gt;period;<br />
 	return 0;<br />
diff --git a/tools/perf/util/scripting-engines/trace-event-perl.c b/tools/perf/util/scripting-engines/trace-event-perl.c<br />
index b3620fe..3f64cd0 100644<br />
--- a/tools/perf/util/scripting-engines/trace-event-perl.c<br />
+++ b/tools/perf/util/scripting-engines/trace-event-perl.c<br />
@@ -258,7 +258,7 @@ static void perl_process_tracepoint(union perf_event *perf_event __unused,<br />
 				    struct perf_sample *sample,<br />
 				    struct perf_evsel *evsel,<br />
 				    struct machine *machine __unused,<br />
-				    struct thread *thread)<br />
+				    struct addr_location *al)<br />
 {<br />
 	struct format_field *field;<br />
 	static char handler[256];<br />
@@ -270,6 +270,7 @@ static void perl_process_tracepoint(union perf_event *perf_event __unused,<br />
 	int cpu = sample-&gt;cpu;<br />
 	void *data = sample-&gt;raw_data;<br />
 	unsigned long long nsecs = sample-&gt;time;<br />
+	struct thread *thread = al-&gt;thread;<br />
 	char *comm = thread-&gt;comm;<br />
 <br />
 	dSP;<br />
@@ -347,9 +348,9 @@ static void perl_process_tracepoint(union perf_event *perf_event __unused,<br />
 <br />
 static void perl_process_event_generic(union perf_event *pevent __unused,<br />
 				       struct perf_sample *sample,<br />
-				       struct perf_evsel *evsel __unused,<br />
+				       struct perf_evsel *evsel,<br />
 				       struct machine *machine __unused,<br />
-				       struct thread *thread __unused)<br />
+				       struct addr_location *al __unused)<br />
 {<br />
 	dSP;<br />
 <br />
@@ -376,10 +377,10 @@ static void perl_process_event(union perf_event *event,<br />
 			       struct perf_sample *sample,<br />
 			       struct perf_evsel *evsel,<br />
 			       struct machine *machine,<br />
-			       struct thread *thread)<br />
+			       struct addr_location *al)<br />
 {<br />
-	perl_process_tracepoint(event, pevent, sample, evsel, machine, thread);<br />
-	perl_process_event_generic(event, sample, evsel, machine, thread);<br />
+	perl_process_tracepoint(event, pevent, sample, evsel, machine, al);<br />
+	perl_process_event_generic(event, sample, evsel, machine, al);<br />
 }<br />
 <br />
 static void run_start_sub(void)<br />
diff --git a/tools/perf/util/scripting-engines/trace-event-python.c b/tools/perf/util/scripting-engines/trace-event-python.c<br />
index 3fae022..0be4ec0 100644<br />
--- a/tools/perf/util/scripting-engines/trace-event-python.c<br />
+++ b/tools/perf/util/scripting-engines/trace-event-python.c<br />
@@ -216,7 +216,7 @@ static void python_process_tracepoint(union perf_event *perf_event __unused,<br />
 				      struct perf_sample *sample,<br />
 				      struct perf_evsel *evsel __unused,<br />
 				      struct machine *machine __unused,<br />
-				      struct thread *thread)<br />
+				      struct addr_location *al)<br />
 {<br />
 	PyObject *handler, *retval, *context, *t, *obj, *dict = NULL;<br />
 	static char handler_name[256];<br />
@@ -230,6 +230,7 @@ static void python_process_tracepoint(union perf_event *perf_event __unused,<br />
 	int cpu = sample-&gt;cpu;<br />
 	void *data = sample-&gt;raw_data;<br />
 	unsigned long long nsecs = sample-&gt;time;<br />
+	struct thread *thread = al-&gt;thread;<br />
 	char *comm = thread-&gt;comm;<br />
 <br />
 	t = PyTuple_New(MAX_FIELDS);<br />
@@ -337,7 +338,7 @@ static void python_process_general_event(union perf_event *perf_event __unused,<br />
 					 struct perf_sample *sample,<br />
 					 struct perf_evsel *evsel,<br />
 					 struct machine *machine __unused,<br />
-					 struct thread *thread __unused)<br />
+					 struct addr_location *al __unused)<br />
 {<br />
 	PyObject *handler, *retval, *t;<br />
 	static char handler_name[64];<br />
@@ -356,7 +357,7 @@ static void python_process_general_event(union perf_event *perf_event __unused,<br />
 		goto exit;<br />
 	}<br />
 <br />
-	/* Pass 3 parameters: event_attr, perf_sample, raw data */<br />
+	/* Pass 4 parameters: event_attr, perf_sample, raw data, thread name */<br />
 	PyTuple_SetItem(t, n++, PyString_FromStringAndSize((void *)&amp;evsel-&gt;attr, sizeof(evsel-&gt;attr)));<br />
 	PyTuple_SetItem(t, n++, PyString_FromStringAndSize((void *)sample, sizeof(*sample)));<br />
 	PyTuple_SetItem(t, n++, PyString_FromStringAndSize(data, sample-&gt;raw_size));<br />
@@ -376,17 +377,17 @@ static void python_process_event(union perf_event *perf_event,<br />
 				 struct perf_sample *sample,<br />
 				 struct perf_evsel *evsel,<br />
 				 struct machine *machine,<br />
-				 struct thread *thread)<br />
+				 struct addr_location *al)<br />
 {<br />
 	switch (evsel-&gt;attr.type) {<br />
 	case PERF_TYPE_TRACEPOINT:<br />
 		python_process_tracepoint(perf_event, pevent, sample, evsel,<br />
-					  machine, thread);<br />
+					  machine, al);<br />
 		break;<br />
 	/* Reserve for future process_hw/sw/raw APIs */<br />
 	default:<br />
 		python_process_general_event(perf_event, pevent, sample, evsel,<br />
-					     machine, thread);<br />
+					     machine, al);<br />
 	}<br />
 }<br />
 <br />
diff --git a/tools/perf/util/trace-event-scripting.c b/tools/perf/util/trace-event-scripting.c<br />
index 474aa7a..c8dc56c 100644<br />
--- a/tools/perf/util/trace-event-scripting.c<br />
+++ b/tools/perf/util/trace-event-scripting.c<br />
@@ -40,7 +40,7 @@ static void process_event_unsupported(union perf_event *event __unused,<br />
 				      struct perf_sample *sample __unused,<br />
 				      struct perf_evsel *evsel __unused,<br />
 				      struct machine *machine __unused,<br />
-				      struct thread *thread __unused)<br />
+				      struct addr_location *al __unused)<br />
 {<br />
 }<br />
 <br />
diff --git a/tools/perf/util/trace-event.h b/tools/perf/util/trace-event.h<br />
index 8fef1d6..8ec1de7 100644<br />
--- a/tools/perf/util/trace-event.h<br />
+++ b/tools/perf/util/trace-event.h<br />
@@ -9,7 +9,6 @@ struct machine;<br />
 struct perf_sample;<br />
 union perf_event;<br />
 struct perf_tool;<br />
-struct thread;<br />
 <br />
 extern int header_page_size_size;<br />
 extern int header_page_ts_size;<br />
@@ -74,6 +73,8 @@ struct tracing_data *tracing_data_get(struct list_head *pattrs,<br />
 void tracing_data_put(struct tracing_data *tdata);<br />
 <br />
 <br />
+struct addr_location;<br />
+<br />
 struct scripting_ops {<br />
 	const char *name;<br />
 	int (*start_script) (const char *script, int argc, const char **argv);<br />
@@ -83,7 +84,7 @@ struct scripting_ops {<br />
 			       struct perf_sample *sample,<br />
 			       struct perf_evsel *evsel,<br />
 			       struct machine *machine,<br />
-			       struct thread *thread);<br />
+			       struct addr_location *al);<br />
 	int (*generate_script) (struct pevent *pevent, const char *outfile);<br />
 };<br />
 <br />
-- <br />
1.7.1]]></description>
            <dc:creator>Arnaldo Carvalho de Melo</dc:creator>
            <category>Linux Kernel</category>
            <pubDate>Wed, 27 Jun 2012 21:00:02 +0200</pubDate>
        </item>
        <item>
            <guid>http://www.serverphorums.com/read.php?12,515012,515012#msg-515012</guid>
            <title>[PATCH v3 3/3] perf script/python: Pass event/thread/dso name and symbol info to event handler in python</title>
            <link>http://www.serverphorums.com/read.php?12,515012,515012#msg-515012</link>
            <description><![CDATA[ Also as suggested by Arnaldo, pack all these parameters to a dictionary,<br />
which is more expandable for adding new parameters while keep the<br />
compatibility for old scripts.<br />
<br />
Signed-off-by: Feng Tang &lt;feng.tang@intel.com&gt;<br />
---<br />
 .../util/scripting-engines/trace-event-python.c    |   32 +++++++++++++++----<br />
 1 files changed, 25 insertions(+), 7 deletions(-)<br />
<br />
diff --git a/tools/perf/util/scripting-engines/trace-event-python.c b/tools/perf/util/scripting-engines/trace-event-python.c<br />
index 97f4fad..e8ac480 100644<br />
--- a/tools/perf/util/scripting-engines/trace-event-python.c<br />
+++ b/tools/perf/util/scripting-engines/trace-event-python.c<br />
@@ -336,15 +336,23 @@ static void python_process_general_event(union perf_event *pevent __unused,<br />
 				 struct machine *machine __unused,<br />
 				 struct addr_location *al)<br />
 {<br />
-	PyObject *handler, *retval, *t;<br />
+	PyObject *handler, *retval, *t, *dict;<br />
 	static char handler_name[64];<br />
 	unsigned n = 0;<br />
-	void *data = sample-&gt;raw_data;<br />
+	struct thread *thread = al-&gt;thread;<br />
 <br />
+	/*<br />
+	 * Use the MAX_FIELDS to make the function expandable, though<br />
+	 * currently there is only one itme for the tuple.<br />
+	 */<br />
 	t = PyTuple_New(MAX_FIELDS);<br />
 	if (!t)<br />
 		Py_FatalError(&quot;couldn't create Python tuple&quot;);<br />
 <br />
+	dict = PyDict_New();<br />
+	if (!dict)<br />
+		Py_FatalError(&quot;couldn't create Python dictionary&quot;);<br />
+<br />
 	snprintf(handler_name, sizeof(handler_name), &quot;%s&quot;, &quot;process_event&quot;);<br />
 <br />
 	handler = PyDict_GetItemString(main_dict, handler_name);<br />
@@ -353,14 +361,23 @@ static void python_process_general_event(union perf_event *pevent __unused,<br />
 		goto exit;<br />
 	}<br />
 <br />
-	/* Pass 4 parameters: event_attr, perf_sample, raw data, thread name */<br />
-	PyTuple_SetItem(t, n++, PyString_FromStringAndSize(<br />
+	PyDict_SetItemString(dict, &quot;ev_name&quot;, PyString_FromString(event_name(evsel)));<br />
+	PyDict_SetItemString(dict, &quot;attr&quot;, PyString_FromStringAndSize(<br />
 			(const char *)&amp;evsel-&gt;attr, sizeof(evsel-&gt;attr)));<br />
-	PyTuple_SetItem(t, n++, PyString_FromStringAndSize(<br />
+	PyDict_SetItemString(dict, &quot;sample&quot;, PyString_FromStringAndSize(<br />
 			(const char *)sample, sizeof(*sample)));<br />
-	PyTuple_SetItem(t, n++, PyString_FromStringAndSize(<br />
-			data, sample-&gt;raw_size));<br />
+	PyDict_SetItemString(dict, &quot;raw_buf&quot;, PyString_FromStringAndSize(<br />
+			(const char *)sample-&gt;raw_data, sample-&gt;raw_size));<br />
+	PyDict_SetItemString(dict, &quot;comm&quot;,<br />
+			PyString_FromString(thread-&gt;comm));<br />
+	PyDict_SetItemString(dict, &quot;dso&quot;,<br />
+			PyString_FromString(al-&gt;map-&gt;dso-&gt;name));<br />
+	if (al-&gt;sym) {<br />
+		PyDict_SetItemString(dict, &quot;symbol&quot;,<br />
+			PyString_FromString(al-&gt;sym-&gt;name));<br />
+	}<br />
 <br />
+	PyTuple_SetItem(t, n++, dict);<br />
 	if (_PyTuple_Resize(&amp;t, n) == -1)<br />
 		Py_FatalError(&quot;error resizing Python tuple&quot;);<br />
 <br />
@@ -368,6 +385,7 @@ static void python_process_general_event(union perf_event *pevent __unused,<br />
 	if (retval == NULL)<br />
 		handler_call_die(handler_name);<br />
 exit:<br />
+	Py_DECREF(dict);<br />
 	Py_DECREF(t);<br />
 }<br />
 <br />
-- <br />
1.7.1<br />
<br />
--<br />
To unsubscribe from this list: send the line &quot;unsubscribe linux-kernel&quot; in<br />
the body of a message to <a href="mailto:&#109;&#97;&#106;&#111;&#114;&#100;&#111;&#109;&#111;&#64;&#118;&#103;&#101;&#114;&#46;&#107;&#101;&#114;&#110;&#101;&#108;&#46;&#111;&#114;&#103;">&#109;&#97;&#106;&#111;&#114;&#100;&#111;&#109;&#111;&#64;&#118;&#103;&#101;&#114;&#46;&#107;&#101;&#114;&#110;&#101;&#108;&#46;&#111;&#114;&#103;</a><br />
More majordomo info at  <a href="http://vger.kernel.org/majordomo-info.html" target="_blank"  rel="nofollow">http://vger.kernel.org/majordomo-info.html</a><br />
Please read the FAQ at  <a href="http://www.tux.org/lkml/" target="_blank"  rel="nofollow">http://www.tux.org/lkml/</a>]]></description>
            <dc:creator>Feng Tang</dc:creator>
            <category>Linux Kernel</category>
            <pubDate>Mon, 18 Jun 2012 08:20:03 +0200</pubDate>
        </item>
    </channel>
</rss>
