diff options
| author | Sonny Rao <sonnyrao@chromium.org> | 2011-07-13 23:34:43 -0400 |
|---|---|---|
| committer | Steven Rostedt <rostedt@goodmis.org> | 2011-07-14 15:53:01 -0400 |
| commit | 259032bfe379281bf7cba512b7705bdb4ce41db5 (patch) | |
| tree | 56c656f3ecb9779e70f6c9a3ad1db68a7a38a6ca /tools | |
| parent | 6331c28c962561aee59e5a493b7556a4bb585957 (diff) | |
perf: Robustify proc and debugfs file recording
While attempting to create a timechart of boot up I found perf didn't
tolerate modules being loaded/unloaded. This patch fixes this by
reading the file once and then writing the size read at the correct
point in the file. It also simplifies the code somewhat.
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Ingo Molnar <mingo@elte.hu>
Cc: Arnaldo Carvalho de Melo <acme@ghostprotocols.net>
Signed-off-by: Sonny Rao <sonnyrao@chromium.org>
Signed-off-by: Michael Neuling <mikey@neuling.org>
Link: http://lkml.kernel.org/r/10011.1310614483@neuling.org
Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
Diffstat (limited to 'tools')
| -rw-r--r-- | tools/perf/util/trace-event-info.c | 120 |
1 files changed, 29 insertions, 91 deletions
diff --git a/tools/perf/util/trace-event-info.c b/tools/perf/util/trace-event-info.c index 35729f4c40cb..3403f814ad72 100644 --- a/tools/perf/util/trace-event-info.c +++ b/tools/perf/util/trace-event-info.c | |||
| @@ -183,106 +183,59 @@ int bigendian(void) | |||
| 183 | return *ptr == 0x01020304; | 183 | return *ptr == 0x01020304; |
| 184 | } | 184 | } |
| 185 | 185 | ||
| 186 | static unsigned long long copy_file_fd(int fd) | 186 | /* unfortunately, you can not stat debugfs or proc files for size */ |
| 187 | static void record_file(const char *file, size_t hdr_sz) | ||
| 187 | { | 188 | { |
| 188 | unsigned long long size = 0; | 189 | unsigned long long size = 0; |
| 189 | char buf[BUFSIZ]; | 190 | char buf[BUFSIZ], *sizep; |
| 190 | int r; | 191 | off_t hdr_pos = lseek(output_fd, 0, SEEK_CUR); |
| 191 | 192 | int r, fd; | |
| 192 | do { | ||
| 193 | r = read(fd, buf, BUFSIZ); | ||
| 194 | if (r > 0) { | ||
| 195 | size += r; | ||
| 196 | write_or_die(buf, r); | ||
| 197 | } | ||
| 198 | } while (r > 0); | ||
| 199 | |||
| 200 | return size; | ||
| 201 | } | ||
| 202 | |||
| 203 | static unsigned long long copy_file(const char *file) | ||
| 204 | { | ||
| 205 | unsigned long long size = 0; | ||
| 206 | int fd; | ||
| 207 | 193 | ||
| 208 | fd = open(file, O_RDONLY); | 194 | fd = open(file, O_RDONLY); |
| 209 | if (fd < 0) | 195 | if (fd < 0) |
| 210 | die("Can't read '%s'", file); | 196 | die("Can't read '%s'", file); |
| 211 | size = copy_file_fd(fd); | ||
| 212 | close(fd); | ||
| 213 | 197 | ||
| 214 | return size; | 198 | /* put in zeros for file size, then fill true size later */ |
| 215 | } | 199 | write_or_die(&size, hdr_sz); |
| 216 | |||
| 217 | static unsigned long get_size_fd(int fd) | ||
| 218 | { | ||
| 219 | unsigned long long size = 0; | ||
| 220 | char buf[BUFSIZ]; | ||
| 221 | int r; | ||
| 222 | 200 | ||
| 223 | do { | 201 | do { |
| 224 | r = read(fd, buf, BUFSIZ); | 202 | r = read(fd, buf, BUFSIZ); |
| 225 | if (r > 0) | 203 | if (r > 0) { |
| 226 | size += r; | 204 | size += r; |
| 205 | write_or_die(buf, r); | ||
| 206 | } | ||
| 227 | } while (r > 0); | 207 | } while (r > 0); |
| 228 | |||
| 229 | lseek(fd, 0, SEEK_SET); | ||
| 230 | |||
| 231 | return size; | ||
| 232 | } | ||
| 233 | |||
| 234 | static unsigned long get_size(const char *file) | ||
| 235 | { | ||
| 236 | unsigned long long size = 0; | ||
| 237 | int fd; | ||
| 238 | |||
| 239 | fd = open(file, O_RDONLY); | ||
| 240 | if (fd < 0) | ||
| 241 | die("Can't read '%s'", file); | ||
| 242 | size = get_size_fd(fd); | ||
| 243 | close(fd); | 208 | close(fd); |
| 244 | 209 | ||
| 245 | return size; | 210 | /* ugh, handle big-endian hdr_size == 4 */ |
| 211 | sizep = (char*)&size; | ||
| 212 | if (bigendian()) | ||
| 213 | sizep += sizeof(u64) - hdr_sz; | ||
| 214 | |||
| 215 | if (pwrite(output_fd, sizep, hdr_sz, hdr_pos) < 0) | ||
| 216 | die("writing to %s", output_file); | ||
| 246 | } | 217 | } |
| 247 | 218 | ||
| 248 | static void read_header_files(void) | 219 | static void read_header_files(void) |
| 249 | { | 220 | { |
| 250 | unsigned long long size, check_size; | ||
| 251 | char *path; | 221 | char *path; |
| 252 | int fd; | 222 | struct stat st; |
| 253 | 223 | ||
| 254 | path = get_tracing_file("events/header_page"); | 224 | path = get_tracing_file("events/header_page"); |
| 255 | fd = open(path, O_RDONLY); | 225 | if (stat(path, &st) < 0) |
| 256 | if (fd < 0) | ||
| 257 | die("can't read '%s'", path); | 226 | die("can't read '%s'", path); |
| 258 | 227 | ||
| 259 | /* unfortunately, you can not stat debugfs files for size */ | ||
| 260 | size = get_size_fd(fd); | ||
| 261 | |||
| 262 | write_or_die("header_page", 12); | 228 | write_or_die("header_page", 12); |
| 263 | write_or_die(&size, 8); | 229 | record_file(path, 8); |
| 264 | check_size = copy_file_fd(fd); | ||
| 265 | close(fd); | ||
| 266 | |||
| 267 | if (size != check_size) | ||
| 268 | die("wrong size for '%s' size=%lld read=%lld", | ||
| 269 | path, size, check_size); | ||
| 270 | put_tracing_file(path); | 230 | put_tracing_file(path); |
| 271 | 231 | ||
| 272 | path = get_tracing_file("events/header_event"); | 232 | path = get_tracing_file("events/header_event"); |
| 273 | fd = open(path, O_RDONLY); | 233 | if (stat(path, &st) < 0) |
| 274 | if (fd < 0) | ||
| 275 | die("can't read '%s'", path); | 234 | die("can't read '%s'", path); |
| 276 | 235 | ||
| 277 | size = get_size_fd(fd); | ||
| 278 | |||
| 279 | write_or_die("header_event", 13); | 236 | write_or_die("header_event", 13); |
| 280 | write_or_die(&size, 8); | 237 | record_file(path, 8); |
| 281 | check_size = copy_file_fd(fd); | ||
| 282 | if (size != check_size) | ||
| 283 | die("wrong size for '%s'", path); | ||
| 284 | put_tracing_file(path); | 238 | put_tracing_file(path); |
| 285 | close(fd); | ||
| 286 | } | 239 | } |
| 287 | 240 | ||
| 288 | static bool name_in_tp_list(char *sys, struct tracepoint_path *tps) | 241 | static bool name_in_tp_list(char *sys, struct tracepoint_path *tps) |
| @@ -298,7 +251,6 @@ static bool name_in_tp_list(char *sys, struct tracepoint_path *tps) | |||
| 298 | 251 | ||
| 299 | static void copy_event_system(const char *sys, struct tracepoint_path *tps) | 252 | static void copy_event_system(const char *sys, struct tracepoint_path *tps) |
| 300 | { | 253 | { |
| 301 | unsigned long long size, check_size; | ||
| 302 | struct dirent *dent; | 254 | struct dirent *dent; |
| 303 | struct stat st; | 255 | struct stat st; |
| 304 | char *format; | 256 | char *format; |
| @@ -338,14 +290,8 @@ static void copy_event_system(const char *sys, struct tracepoint_path *tps) | |||
| 338 | sprintf(format, "%s/%s/format", sys, dent->d_name); | 290 | sprintf(format, "%s/%s/format", sys, dent->d_name); |
| 339 | ret = stat(format, &st); | 291 | ret = stat(format, &st); |
| 340 | 292 | ||
| 341 | if (ret >= 0) { | 293 | if (ret >= 0) |
| 342 | /* unfortunately, you can not stat debugfs files for size */ | 294 | record_file(format, 8); |
| 343 | size = get_size(format); | ||
| 344 | write_or_die(&size, 8); | ||
| 345 | check_size = copy_file(format); | ||
| 346 | if (size != check_size) | ||
| 347 | die("error in size of file '%s'", format); | ||
| 348 | } | ||
| 349 | 295 | ||
| 350 | free(format); | 296 | free(format); |
| 351 | } | 297 | } |
| @@ -426,7 +372,7 @@ static void read_event_files(struct tracepoint_path *tps) | |||
| 426 | 372 | ||
| 427 | static void read_proc_kallsyms(void) | 373 | static void read_proc_kallsyms(void) |
| 428 | { | 374 | { |
| 429 | unsigned int size, check_size; | 375 | unsigned int size; |
| 430 | const char *path = "/proc/kallsyms"; | 376 | const char *path = "/proc/kallsyms"; |
| 431 | struct stat st; | 377 | struct stat st; |
| 432 | int ret; | 378 | int ret; |
| @@ -438,17 +384,12 @@ static void read_proc_kallsyms(void) | |||
| 438 | write_or_die(&size, 4); | 384 | write_or_die(&size, 4); |
| 439 | return; | 385 | return; |
| 440 | } | 386 | } |
| 441 | size = get_size(path); | 387 | record_file(path, 4); |
| 442 | write_or_die(&size, 4); | ||
| 443 | check_size = copy_file(path); | ||
| 444 | if (size != check_size) | ||
| 445 | die("error in size of file '%s'", path); | ||
| 446 | |||
| 447 | } | 388 | } |
| 448 | 389 | ||
| 449 | static void read_ftrace_printk(void) | 390 | static void read_ftrace_printk(void) |
| 450 | { | 391 | { |
| 451 | unsigned int size, check_size; | 392 | unsigned int size; |
| 452 | char *path; | 393 | char *path; |
| 453 | struct stat st; | 394 | struct stat st; |
| 454 | int ret; | 395 | int ret; |
| @@ -461,11 +402,8 @@ static void read_ftrace_printk(void) | |||
| 461 | write_or_die(&size, 4); | 402 | write_or_die(&size, 4); |
| 462 | goto out; | 403 | goto out; |
| 463 | } | 404 | } |
| 464 | size = get_size(path); | 405 | record_file(path, 4); |
| 465 | write_or_die(&size, 4); | 406 | |
| 466 | check_size = copy_file(path); | ||
| 467 | if (size != check_size) | ||
| 468 | die("error in size of file '%s'", path); | ||
| 469 | out: | 407 | out: |
| 470 | put_tracing_file(path); | 408 | put_tracing_file(path); |
| 471 | } | 409 | } |
