Commit 259032bfe379281bf7cba512b7705bdb4ce41db5
Committed by
Steven Rostedt
1 parent
6331c28c96
Exists in
master
and in
38 other branches
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 | } |