aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenys Vlasenko <vda.linux@googlemail.com>2010-06-21 07:17:23 +0200
committerDenys Vlasenko <vda.linux@googlemail.com>2010-06-21 07:17:23 +0200
commitadbbee46ad0661bf695d2bfe7a07ebced4bbe780 (patch)
tree657c70f934a0cb2a882e07d997a063172a0ceae5
parent05a550b48abe8490264cacf14b68534c2f8ac3ed (diff)
downloadbusybox-w32-adbbee46ad0661bf695d2bfe7a07ebced4bbe780.tar.gz
busybox-w32-adbbee46ad0661bf695d2bfe7a07ebced4bbe780.tar.bz2
busybox-w32-adbbee46ad0661bf695d2bfe7a07ebced4bbe780.zip
bootchartd: added optional compat features
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r--include/libbb.h1
-rw-r--r--init/Config.src14
-rw-r--r--init/bootchartd.c154
-rw-r--r--procps/sysctl.c1
4 files changed, 127 insertions, 43 deletions
diff --git a/include/libbb.h b/include/libbb.h
index 22c72d9ee..5e962fdb6 100644
--- a/include/libbb.h
+++ b/include/libbb.h
@@ -1125,6 +1125,7 @@ typedef struct parser_t {
1125} parser_t; 1125} parser_t;
1126parser_t* config_open(const char *filename) FAST_FUNC; 1126parser_t* config_open(const char *filename) FAST_FUNC;
1127parser_t* config_open2(const char *filename, FILE* FAST_FUNC (*fopen_func)(const char *path)) FAST_FUNC; 1127parser_t* config_open2(const char *filename, FILE* FAST_FUNC (*fopen_func)(const char *path)) FAST_FUNC;
1128/* delims[0] is a comment char (use '\0' to disable), the rest are token delimiters */
1128int config_read(parser_t *parser, char **tokens, unsigned flags, const char *delims) FAST_FUNC; 1129int config_read(parser_t *parser, char **tokens, unsigned flags, const char *delims) FAST_FUNC;
1129#define config_read(parser, tokens, max, min, str, flags) \ 1130#define config_read(parser, tokens, max, min, str, flags) \
1130 config_read(parser, tokens, ((flags) | (((min) & 0xFF) << 8) | ((max) & 0xFF)), str) 1131 config_read(parser, tokens, ((flags) | (((min) & 0xFF) << 8) | ((max) & 0xFF)), str)
diff --git a/init/Config.src b/init/Config.src
index 2e9208150..590e29890 100644
--- a/init/Config.src
+++ b/init/Config.src
@@ -122,18 +122,4 @@ config MESG
122 Mesg controls access to your terminal by others. It is typically 122 Mesg controls access to your terminal by others. It is typically
123 used to allow or disallow other users to write to your terminal 123 used to allow or disallow other users to write to your terminal
124 124
125config BOOTCHARTD
126 bool "bootchartd"
127 default y
128 help
129 bootchartd is commonly used to profile the boot process
130 for the purpose of speeding it up. In this case, it is started
131 by the kernel as the init process. This is configured by adding
132 the init=/sbin/bootchartd option to the kernel command line.
133
134 It can also be used to monitor the resource usage of a specific
135 application or the running system in general. In this case,
136 bootchartd is started interactively by running bootchartd start
137 and stopped using bootchartd stop.
138
139endmenu 125endmenu
diff --git a/init/bootchartd.c b/init/bootchartd.c
index d1f9ed30e..1ed4f99fc 100644
--- a/init/bootchartd.c
+++ b/init/bootchartd.c
@@ -2,7 +2,58 @@
2/* 2/*
3 * Licensed under GPLv2 or later, see file LICENSE in this tarball for details. 3 * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
4 */ 4 */
5
6//config:config BOOTCHARTD
7//config: bool "bootchartd"
8//config: default y
9//config: help
10//config: bootchartd is commonly used to profile the boot process
11//config: for the purpose of speeding it up. In this case, it is started
12//config: by the kernel as the init process. This is configured by adding
13//config: the init=/sbin/bootchartd option to the kernel command line.
14//config:
15//config: It can also be used to monitor the resource usage of a specific
16//config: application or the running system in general. In this case,
17//config: bootchartd is started interactively by running bootchartd start
18//config: and stopped using bootchartd stop.
19//config:
20//config:config FEATURE_BOOTCHARTD_BLOATED_HEADER
21//config: bool "bootchartd"
22//config: default y
23//config: depends on BOOTCHARTD
24//config: help
25//config: Create extended header file compatible with "big" bootchartd.
26//config: "Big" bootchartd is a shell script and it dumps some
27//config: "convenient" info int the header, such as:
28//config: title = Boot chart for `hostname` (`date`)
29//config: system.uname = `uname -srvm`
30//config: system.release = `cat /etc/DISTRO-release`
31//config: system.cpu = `grep '^model name' /proc/cpuinfo | head -1` ($cpucount)
32//config: system.kernel.options = `cat /proc/cmdline`
33//config: This data is not mandatory for bootchart graph generation,
34//config: and is considered bloat. Nevertheless, this option
35//config: makes bootchartd applet to dump a subset of it.
36//config:
37//config:config FEATURE_BOOTCHARTD_CONFIG_FILE
38//config: bool "bootchartd"
39//config: default y
40//config: depends on BOOTCHARTD
41//config: help
42//config: Create extended header file compatible with "big" bootchartd.
43//config: "Big" bootchartd is a shell script and it dumps some
44//config: "convenient" info int the header, such as:
45//config: title = Boot chart for `hostname` (`date`)
46//config: system.uname = `uname -srvm`
47//config: system.release = `cat /etc/DISTRO-release`
48//config: system.cpu = `grep '^model name' /proc/cpuinfo | head -1` ($cpucount)
49//config: system.kernel.options = `cat /proc/cmdline`
50//config: This data is not mandatory for bootchart graph generation,
51//config: and is considered bloat. Nevertheless, this option
52//config: makes bootchartd applet to dump a subset of it.
53
5#include "libbb.h" 54#include "libbb.h"
55/* After libbb.h, since it needs sys/types.h on some systems */
56#include <sys/utsname.h>
6#include <sys/mount.h> 57#include <sys/mount.h>
7#ifndef MS_SILENT 58#ifndef MS_SILENT
8# define MS_SILENT (1 << 15) 59# define MS_SILENT (1 << 15)
@@ -19,15 +70,16 @@
19#define DO_SIGNAL_SYNC 1 70#define DO_SIGNAL_SYNC 1
20 71
21 72
22//Not supported: $PWD/bootchartd.conf and /etc/bootchartd.conf 73//$PWD/bootchartd.conf and /etc/bootchartd.conf:
23 74//supported options:
75//# Sampling period (in seconds)
76//SAMPLE_PERIOD=0.2
77//
78//not yet supported:
24//# tmpfs size 79//# tmpfs size
25//# (32 MB should suffice for ~20 minutes worth of log data, but YMMV) 80//# (32 MB should suffice for ~20 minutes worth of log data, but YMMV)
26//TMPFS_SIZE=32m 81//TMPFS_SIZE=32m
27// 82//
28//# Sampling period (in seconds)
29//SAMPLE_PERIOD=0.2
30//
31//# Whether to enable and store BSD process accounting information. The 83//# Whether to enable and store BSD process accounting information. The
32//# kernel needs to be configured to enable v3 accounting 84//# kernel needs to be configured to enable v3 accounting
33//# (CONFIG_BSD_PROCESS_ACCT_V3). accton from the GNU accounting utilities 85//# (CONFIG_BSD_PROCESS_ACCT_V3). accton from the GNU accounting utilities
@@ -126,7 +178,7 @@ static int dump_procs(FILE *fp, int look_for_login_process)
126 return found_login_process; 178 return found_login_process;
127} 179}
128 180
129static char *make_tempdir(const char *prog) 181static char *make_tempdir(void)
130{ 182{
131 char template[] = "/tmp/bootchart.XXXXXX"; 183 char template[] = "/tmp/bootchart.XXXXXX";
132 char *tempdir = xstrdup(mkdtemp(template)); 184 char *tempdir = xstrdup(mkdtemp(template));
@@ -151,18 +203,10 @@ static char *make_tempdir(const char *prog)
151 } else { 203 } else {
152 xchdir(tempdir); 204 xchdir(tempdir);
153 } 205 }
154 {
155 FILE *header_fp = xfopen("header", "w");
156 if (prog)
157 fprintf(header_fp, "profile.process = %s\n", prog);
158 fputs("version = "BC_VERSION_STR"\n", header_fp);
159 fclose(header_fp);
160 }
161
162 return tempdir; 206 return tempdir;
163} 207}
164 208
165static void do_logging(void) 209static void do_logging(int sample_pariod_us)
166{ 210{
167 //# Enable process accounting if configured 211 //# Enable process accounting if configured
168 //if [ "$PROCESS_ACCOUNTING" = "yes" ]; then 212 //if [ "$PROCESS_ACCOUNTING" = "yes" ]; then
@@ -205,26 +249,61 @@ static void do_logging(void)
205 } 249 }
206 fflush_all(); 250 fflush_all();
207 wait_more: 251 wait_more:
208 usleep(200*1000); 252 usleep(sample_pariod_us);
209 } 253 }
210 254
211 // [ -e kernel_pacct ] && accton off 255 // [ -e kernel_pacct ] && accton off
212} 256}
213 257
214static void finalize(char *tempdir) 258static void finalize(char *tempdir, const char *prog)
215{ 259{
216 //# Stop process accounting if configured 260 //# Stop process accounting if configured
217 //local pacct= 261 //local pacct=
218 //[ -e kernel_pacct ] && pacct=kernel_pacct 262 //[ -e kernel_pacct ] && pacct=kernel_pacct
219 263
220 //( 264 FILE *header_fp = xfopen("header", "w");
221 // echo "version = $VERSION" 265
222 // echo "title = Boot chart for $( hostname | sed q ) ($( date ))" 266 if (prog)
223 // echo "system.uname = $( uname -srvm | sed q )" 267 fprintf(header_fp, "profile.process = %s\n", prog);
224 // echo "system.release = $( sed q /etc/SuSE-release )" 268
225 // echo "system.cpu = $( grep '^model name' /proc/cpuinfo | sed q ) ($cpucount)" 269 fputs("version = "BC_VERSION_STR"\n", header_fp);
226 // echo "system.kernel.options = $( sed q /proc/cmdline )" 270
227 //) >> header 271 if (ENABLE_FEATURE_BOOTCHARTD_BLOATED_HEADER) {
272 char *hostname;
273 char *kcmdline;
274 time_t t;
275 struct tm tm_time;
276 /* x2 for possible localized data */
277 char date_buf[sizeof("Mon Jun 21 05:29:03 CEST 2010") * 2];
278 struct utsname unamebuf;
279
280 hostname = safe_gethostname();
281 time(&t);
282 localtime_r(&t, &tm_time);
283 strftime(date_buf, sizeof(date_buf), "%a %b %e %H:%M:%S %Z %Y", &tm_time);
284 fprintf(header_fp, "title = Boot chart for %s (%s)\n", hostname, date_buf);
285 if (ENABLE_FEATURE_CLEAN_UP)
286 free(hostname);
287
288 uname(&unamebuf); /* never fails */
289 /* same as uname -srvm */
290 fprintf(header_fp, "system.uname = %s %s %s %s\n",
291 unamebuf.sysname,
292 unamebuf.release,
293 unamebuf.version,
294 unamebuf.machine
295 );
296
297 //system.release = `cat /etc/DISTRO-release`
298 //system.cpu = `grep '^model name' /proc/cpuinfo | head -1` ($cpucount)
299
300 kcmdline = xmalloc_open_read_close("/proc/cmdline", NULL);
301 /* kcmdline includes trailing "\n" */
302 fprintf(header_fp, "system.kernel.options = %s", kcmdline);
303 if (ENABLE_FEATURE_CLEAN_UP)
304 free(kcmdline);
305 }
306 fclose(header_fp);
228 307
229 /* Package log files */ 308 /* Package log files */
230 system("tar -zcf /var/log/bootchart.tgz header *.log"); // + $pacct 309 system("tar -zcf /var/log/bootchart.tgz header *.log"); // + $pacct
@@ -256,6 +335,7 @@ static void finalize(char *tempdir)
256int bootchartd_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; 335int bootchartd_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
257int bootchartd_main(int argc UNUSED_PARAM, char **argv) 336int bootchartd_main(int argc UNUSED_PARAM, char **argv)
258{ 337{
338 int sample_pariod_us;
259 pid_t parent_pid, logger_pid; 339 pid_t parent_pid, logger_pid;
260 smallint cmd; 340 smallint cmd;
261 enum { 341 enum {
@@ -287,7 +367,23 @@ int bootchartd_main(int argc UNUSED_PARAM, char **argv)
287 cmd = CMD_PID1; 367 cmd = CMD_PID1;
288 } 368 }
289 369
290 /* Here we are in START or INIT state. Create logger child: */ 370 /* Here we are in START or INIT state */
371
372 /* Read config file: */
373 sample_pariod_us = 200 * 1000;
374 if (ENABLE_FEATURE_BOOTCHARTD_CONFIG_FILE) {
375 char* token[2];
376 parser_t *parser = config_open2("/etc/bootchartd.conf" + 5, fopen_for_read);
377 if (!parser)
378 parser = config_open2("/etc/bootchartd.conf", fopen_for_read);
379 while (config_read(parser, token, 2, 0, "#=", PARSE_NORMAL & ~PARSE_COLLAPSE)) {
380 if (strcmp(token[0], "SAMPLE_PERIOD") == 0 && token[1])
381 sample_pariod_us = atof(token[1]) * 1000000;
382 }
383 config_close(parser);
384 }
385
386 /* Create logger child: */
291 logger_pid = fork_or_rexec(argv); 387 logger_pid = fork_or_rexec(argv);
292 388
293 if (logger_pid == 0) { /* child */ 389 if (logger_pid == 0) { /* child */
@@ -312,9 +408,9 @@ int bootchartd_main(int argc UNUSED_PARAM, char **argv)
312 if (cmd == CMD_PID1 && !getenv("PATH")) 408 if (cmd == CMD_PID1 && !getenv("PATH"))
313 putenv((char*)bb_PATH_root_path); 409 putenv((char*)bb_PATH_root_path);
314 410
315 tempdir = make_tempdir(cmd == CMD_START ? argv[2] : NULL); 411 tempdir = make_tempdir();
316 do_logging(); 412 do_logging(sample_pariod_us);
317 finalize(tempdir); 413 finalize(tempdir, cmd == CMD_START ? argv[2] : NULL);
318 return EXIT_SUCCESS; 414 return EXIT_SUCCESS;
319 } 415 }
320 416
diff --git a/procps/sysctl.c b/procps/sysctl.c
index 7a5bf1435..fc601d637 100644
--- a/procps/sysctl.c
+++ b/procps/sysctl.c
@@ -212,6 +212,7 @@ static int sysctl_handle_preload_file(const char *filename)
212//TODO: comment may be only at line start. "var=1 #abc" - "1 #abc" is the value 212//TODO: comment may be only at line start. "var=1 #abc" - "1 #abc" is the value
213// (but _whitespace_ from ends should be trimmed first (and we do it right)) 213// (but _whitespace_ from ends should be trimmed first (and we do it right))
214//TODO: "var==1" is mishandled (must use "=1" as a value, but uses "1") 214//TODO: "var==1" is mishandled (must use "=1" as a value, but uses "1")
215// can it be fixed by removing PARSE_COLLAPSE bit?
215 while (config_read(parser, token, 2, 2, "# \t=", PARSE_NORMAL)) { 216 while (config_read(parser, token, 2, 2, "# \t=", PARSE_NORMAL)) {
216 char *tp; 217 char *tp;
217 sysctl_dots_to_slashes(token[0]); 218 sysctl_dots_to_slashes(token[0]);