[systemd-devel] [PATCH 1/3] bootchart: add parameter "-C" to expand process names to the full cmdline

harald at redhat.com harald at redhat.com
Wed Mar 6 23:52:54 PST 2013


From: Harald Hoyer <harald at redhat.com>

---
 src/bootchart/bootchart.c |  7 ++++++-
 src/bootchart/bootchart.h |  3 ++-
 src/bootchart/log.c       | 33 +++++++++++++++++++++++++++++++--
 src/bootchart/svg.c       | 39 +++++++++++++++++++++++++++++++++------
 4 files changed, 72 insertions(+), 10 deletions(-)

diff --git a/src/bootchart/bootchart.c b/src/bootchart/bootchart.c
index af573da..543037d 100644
--- a/src/bootchart/bootchart.c
+++ b/src/bootchart/bootchart.c
@@ -76,6 +76,7 @@ bool entropy = false;
 bool initcall = true;
 bool relative = false;
 bool filter = true;
+bool show_cmdline = false;
 bool pss = false;
 int samples;
 int len = 500; /* we record len+1 (1 start sample) */
@@ -150,6 +151,7 @@ int main(int argc, char *argv[])
                         {"output",    required_argument,  NULL,  'o'},
                         {"init",      required_argument,  NULL,  'i'},
                         {"no-filter", no_argument,        NULL,  'F'},
+                        {"cmdline",   no_argument,        NULL,  'C'},
                         {"help",      no_argument,        NULL,  'h'},
                         {"scale-x",   required_argument,  NULL,  'x'},
                         {"scale-y",   required_argument,  NULL,  'y'},
@@ -159,7 +161,7 @@ int main(int argc, char *argv[])
 
                 gind = 0;
 
-                i = getopt_long(argc, argv, "erpf:n:o:i:Fhx:y:", opts, &gind);
+                i = getopt_long(argc, argv, "erpf:n:o:i:FChx:y:", opts, &gind);
                 if (i == -1)
                         break;
                 switch (i) {
@@ -175,6 +177,9 @@ int main(int argc, char *argv[])
                 case 'F':
                         filter = false;
                         break;
+                case 'C':
+                        show_cmdline = true;
+                        break;
                 case 'n':
                         r = safe_atoi(optarg, &len);
                         if (r < 0)
diff --git a/src/bootchart/bootchart.h b/src/bootchart/bootchart.h
index ea26c93..c42f971 100644
--- a/src/bootchart/bootchart.h
+++ b/src/bootchart/bootchart.h
@@ -61,7 +61,7 @@ struct ps_struct {
         struct ps_struct *next;       /* siblings */
 
         /* must match - otherwise it's a new process with same PID */
-        char name[16];
+        char name[256];
         int pid;
         int ppid;
 
@@ -101,6 +101,7 @@ extern struct cpu_stat_struct cpustat[];
 extern int pscount;
 extern bool relative;
 extern bool filter;
+extern bool show_cmdline;
 extern bool pss;
 extern bool entropy;
 extern bool initcall;
diff --git a/src/bootchart/log.c b/src/bootchart/log.c
index cf6c3a7..1e3f4a9 100644
--- a/src/bootchart/log.c
+++ b/src/bootchart/log.c
@@ -95,6 +95,26 @@ static char *bufgetline(char *buf)
         return c;
 }
 
+static int pid_cmdline_strncpy(char *buffer, int pid, size_t buf_len) {
+	char filename[PATH_MAX];
+	int _cleanup_close_ fd=-1;
+	ssize_t n;
+
+	sprintf(filename, "%d/cmdline", pid);
+	fd = openat(procfd, filename, O_RDONLY);
+	if (fd < 0)
+	        return -errno;
+
+	n = read(fd, buffer, buf_len-1);
+        if (n > 0) {
+                int i;
+                for (i = 0; i < n; i++)
+                        if (buffer[i] == '\0')
+                                buffer[i] = ' ';
+                buffer[n] = '\0';
+        }
+	return 0;
+}
 
 void log_sample(int sample)
 {
@@ -273,7 +293,12 @@ schedstat_next:
                         if (!sscanf(buf, "%s %*s %*s", key))
                                 continue;
 
-                        strncpy(ps->name, key, 16);
+                        strncpy(ps->name, key, 256);
+
+                        /* cmdline */
+                        if (show_cmdline)
+                                pid_cmdline_strncpy(ps->name, pid, 256);
+
                         /* discard line 2 */
                         m = bufgetline(buf);
                         if (!m)
@@ -433,7 +458,11 @@ catch_rename:
                         if (!sscanf(buf, "%s %*s %*s", key))
                                 continue;
 
-                        strncpy(ps->name, key, 16);
+                        strncpy(ps->name, key, 256);
+
+                        /* cmdline */
+                        if (show_cmdline)
+                                pid_cmdline_strncpy(ps->name, pid, 256);
                 }
         }
 }
diff --git a/src/bootchart/svg.c b/src/bootchart/svg.c
index f8a3776..4c78abd 100644
--- a/src/bootchart/svg.c
+++ b/src/bootchart/svg.c
@@ -267,6 +267,20 @@ static void svg_graph_box(int height)
         }
 }
 
+/* xml comments must not contain "--" */
+static char* xml_comment_encode(const char* name) {
+        char *enc_name, *p;
+
+        enc_name = strdup(name);
+        if (!enc_name)
+                return NULL;
+
+        for (p = enc_name; *p; p++)
+                if (p[0] == '-' && p[1] == '-')
+                        p[1] = '_';
+
+        return enc_name;
+}
 
 static void svg_pss_graph(void)
 {
@@ -369,7 +383,7 @@ static void svg_pss_graph(void)
                                 top = bottom + ps->sample[i].pss;
                                 /* draw a label with the process / PID */
                                 if ((i == 1) || (ps->sample[i - 1].pss <= (100 * scale_y)))
-                                        svg("  <text x=\"%.03f\" y=\"%.03f\">%s [%i]</text>\n",
+                                        svg("  <text x=\"%.03f\" y=\"%.03f\"><![CDATA[%s]]> [%i]</text>\n",
                                             time_to_graph(sampletime[i] - graph_start),
                                             kb_to_graph(1000000.0 - bottom - ((top -  bottom) / 2)),
                                             ps->name,
@@ -383,10 +397,17 @@ static void svg_pss_graph(void)
         svg("\n\n<!-- PSS map - csv format -->\n");
         ps = ps_first;
         while (ps->next_ps) {
+                char _cleanup_free_*enc_name;
                 ps = ps->next_ps;
                 if (!ps)
                         continue;
-                svg("<!-- %s [%d] pss=", ps->name, ps->pid);
+
+                enc_name = xml_comment_encode(ps->name);
+                if(!enc_name)
+                        continue;
+
+                svg("<!-- %s [%d] pss=", enc_name, ps->pid);
+
                 for (i = 0; i < samples ; i++) {
                         svg("%d," , ps->sample[i].pss);
                 }
@@ -816,14 +837,20 @@ static void svg_ps_bars(void)
         /* pass 2 - ps boxes */
         ps = ps_first;
         while ((ps = get_next_ps(ps))) {
+                char _cleanup_free_*enc_name;
+
                 double starttime;
                 int t;
 
                 if (!ps)
                         continue;
 
+                enc_name = xml_comment_encode(ps->name);
+                if(!enc_name)
+                        continue;
+
                 /* leave some trace of what we actually filtered etc. */
-                svg("<!-- %s [%i] ppid=%i runtime=%.03fs -->\n", ps->name, ps->pid,
+                svg("<!-- %s [%i] ppid=%i runtime=%.03fs -->\n", enc_name, ps->pid,
                     ps->ppid, ps->total);
 
                 /* it would be nice if we could use exec_start from /proc/pid/sched,
@@ -898,7 +925,7 @@ static void svg_ps_bars(void)
                         w = ps->first;
 
                 /* text label of process name */
-                svg("  <text x=\"%.03f\" y=\"%.03f\">%s [%i] <tspan class=\"run\">%.03fs</tspan></text>\n",
+                svg("  <text x=\"%.03f\" y=\"%.03f\"><![CDATA[%s]]> [%i]<tspan class=\"run\">%.03fs</tspan></text>\n",
                     time_to_graph(sampletime[w] - graph_start) + 5.0,
                     ps_to_graph(j) + 14.0,
                     ps->name,
@@ -1002,7 +1029,7 @@ static void svg_top_ten_cpu(void)
 
         svg("<text class=\"t2\" x=\"20\" y=\"0\">Top CPU consumers:</text>\n");
         for (n = 0; n < 10; n++)
-                svg("<text class=\"t3\" x=\"20\" y=\"%d\">%3.03fs - %s[%d]</text>\n",
+                svg("<text class=\"t3\" x=\"20\" y=\"%d\">%3.03fs - <![CDATA[%s]]> [%d]</text>\n",
                     20 + (n * 13),
                     top[n]->total,
                     top[n]->name,
@@ -1037,7 +1064,7 @@ static void svg_top_ten_pss(void)
 
         svg("<text class=\"t2\" x=\"20\" y=\"0\">Top PSS consumers:</text>\n");
         for (n = 0; n < 10; n++)
-                svg("<text class=\"t3\" x=\"20\" y=\"%d\">%dK - %s[%d]</text>\n",
+                svg("<text class=\"t3\" x=\"20\" y=\"%d\">%dK - <![CDATA[%s]]> [%d]</text>\n",
                     20 + (n * 13),
                     top[n]->pss_max,
                     top[n]->name,
-- 
1.8.1



More information about the systemd-devel mailing list