Commit 259032bfe379281bf7cba512b7705bdb4ce41db5

Authored by Sonny Rao
Committed by Steven Rostedt
1 parent 6331c28c96

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>

Showing 1 changed file with 29 additions and 91 deletions Side-by-side Diff

tools/perf/util/trace-event-info.c
... ... @@ -183,106 +183,59 @@
183 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 189 unsigned long long size = 0;
189   - char buf[BUFSIZ];
190   - int r;
  190 + char buf[BUFSIZ], *sizep;
  191 + off_t hdr_pos = lseek(output_fd, 0, SEEK_CUR);
  192 + int r, fd;
191 193  
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   -
208 194 fd = open(file, O_RDONLY);
209 195 if (fd < 0)
210 196 die("Can't read '%s'", file);
211   - size = copy_file_fd(fd);
212   - close(fd);
213 197  
214   - return size;
215   -}
  198 + /* put in zeros for file size, then fill true size later */
  199 + write_or_die(&size, hdr_sz);
216 200  
217   -static unsigned long get_size_fd(int fd)
218   -{
219   - unsigned long long size = 0;
220   - char buf[BUFSIZ];
221   - int r;
222   -
223 201 do {
224 202 r = read(fd, buf, BUFSIZ);
225   - if (r > 0)
  203 + if (r > 0) {
226 204 size += r;
  205 + write_or_die(buf, r);
  206 + }
227 207 } while (r > 0);
  208 + close(fd);
228 209  
229   - lseek(fd, 0, SEEK_SET);
  210 + /* ugh, handle big-endian hdr_size == 4 */
  211 + sizep = (char*)&size;
  212 + if (bigendian())
  213 + sizep += sizeof(u64) - hdr_sz;
230 214  
231   - return size;
  215 + if (pwrite(output_fd, sizep, hdr_sz, hdr_pos) < 0)
  216 + die("writing to %s", output_file);
232 217 }
233 218  
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);
244   -
245   - return size;
246   -}
247   -
248 219 static void read_header_files(void)
249 220 {
250   - unsigned long long size, check_size;
251 221 char *path;
252   - int fd;
  222 + struct stat st;
253 223  
254 224 path = get_tracing_file("events/header_page");
255   - fd = open(path, O_RDONLY);
256   - if (fd < 0)
  225 + if (stat(path, &st) < 0)
257 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 228 write_or_die("header_page", 12);
263   - write_or_die(&size, 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);
  229 + record_file(path, 8);
270 230 put_tracing_file(path);
271 231  
272 232 path = get_tracing_file("events/header_event");
273   - fd = open(path, O_RDONLY);
274   - if (fd < 0)
  233 + if (stat(path, &st) < 0)
275 234 die("can't read '%s'", path);
276 235  
277   - size = get_size_fd(fd);
278   -
279 236 write_or_die("header_event", 13);
280   - write_or_die(&size, 8);
281   - check_size = copy_file_fd(fd);
282   - if (size != check_size)
283   - die("wrong size for '%s'", path);
  237 + record_file(path, 8);
284 238 put_tracing_file(path);
285   - close(fd);
286 239 }
287 240  
288 241 static bool name_in_tp_list(char *sys, struct tracepoint_path *tps)
... ... @@ -298,7 +251,6 @@
298 251  
299 252 static void copy_event_system(const char *sys, struct tracepoint_path *tps)
300 253 {
301   - unsigned long long size, check_size;
302 254 struct dirent *dent;
303 255 struct stat st;
304 256 char *format;
... ... @@ -338,14 +290,8 @@
338 290 sprintf(format, "%s/%s/format", sys, dent->d_name);
339 291 ret = stat(format, &st);
340 292  
341   - if (ret >= 0) {
342   - /* unfortunately, you can not stat debugfs files for size */
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   - }
  293 + if (ret >= 0)
  294 + record_file(format, 8);
349 295  
350 296 free(format);
351 297 }
... ... @@ -426,7 +372,7 @@
426 372  
427 373 static void read_proc_kallsyms(void)
428 374 {
429   - unsigned int size, check_size;
  375 + unsigned int size;
430 376 const char *path = "/proc/kallsyms";
431 377 struct stat st;
432 378 int ret;
433 379  
... ... @@ -438,17 +384,12 @@
438 384 write_or_die(&size, 4);
439 385 return;
440 386 }
441   - size = get_size(path);
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   -
  387 + record_file(path, 4);
447 388 }
448 389  
449 390 static void read_ftrace_printk(void)
450 391 {
451   - unsigned int size, check_size;
  392 + unsigned int size;
452 393 char *path;
453 394 struct stat st;
454 395 int ret;
... ... @@ -461,11 +402,8 @@
461 402 write_or_die(&size, 4);
462 403 goto out;
463 404 }
464   - size = get_size(path);
465   - write_or_die(&size, 4);
466   - check_size = copy_file(path);
467   - if (size != check_size)
468   - die("error in size of file '%s'", path);
  405 + record_file(path, 4);
  406 +
469 407 out:
470 408 put_tracing_file(path);
471 409 }