aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/trace-cmd-restore.1.txt90
-rw-r--r--Documentation/trace-cmd.1.txt3
-rw-r--r--Makefile2
-rw-r--r--trace-cmd.c3
-rw-r--r--trace-cmd.h1
-rw-r--r--trace-local.h2
-rw-r--r--trace-output.c14
-rw-r--r--trace-restore.c146
-rw-r--r--trace-usage.c8
9 files changed, 260 insertions, 9 deletions
diff --git a/Documentation/trace-cmd-restore.1.txt b/Documentation/trace-cmd-restore.1.txt
new file mode 100644
index 0000000..6fd6ba4
--- /dev/null
+++ b/Documentation/trace-cmd-restore.1.txt
@@ -0,0 +1,90 @@
1TRACE-CMD-RESTORE(1)
2====================
3
4NAME
5----
6trace-cmd-restore - restore a failed trace record
7
8SYNOPSIS
9--------
10*trace-cmd restore* ['OPTIONS'] ['command'] cpu-file [cpu-file ...]
11
12DESCRIPTION
13-----------
14The trace-cmd(1) restore command will restore a crashed trace-cmd-record(1)
15file. If for some reason a trace-cmd record fails, it will leave a the
16per-cpu data files and not create the final trace.dat file. The trace-cmd
17restore will append the files to create a working trace.dat file that can
18be read with trace-cmd-report(1).
19
20When trace-cmd record runs, it spawns off a process per CPU and writes
21to a per cpu file usually called 'trace.dat.cpuX', where X represents the
22CPU number that it is tracing. If the -o option was used in the trace-cmd
23record, then the CPU data files will have that name instead of the
24'trace.dat' name. If a unexpected crash occurs before the tracing
25is finished, then the per CPU files will still exist but there will
26not be any trace.dat file to read from. trace-cmd restore will allow you
27to create a trace.dat file with the existing data files.
28
29OPTIONS
30-------
31*-c*::
32 Create a partial trace.dat file from the machine, to be used with
33 a full trace-cmd restore at another time. This option is useful for
34 embedded devices. If a server contains the cpu files of a crashed
35 trace-cmd record (or trace-cmd listen), trace-cmd restore can be
36 executed on the embedded device with the -c option to get all the
37 stored information of that embedded device. Then the file created
38 could be copied to the server to run the trace-cmd restore there
39 with the cpu files.
40
41 If *-o* is not specified, then the file created will be called
42 'trace-partial.dat'. This is because the file is not a full version
43 of something that trace-cmd-report(1) could use.
44
45*-o* output'::
46 By default, trace-cmd restore will create a 'trace.dat' file
47 (or 'trace-partial.dat' if *-c* is specified). You can
48 specify a different file to write to with the *-o* option.
49
50*-i* input::
51 By default, trace-cmd restore will read the information of the
52 current system to create the initial data stored in the 'trace.dat'
53 file. If the crash was on another machine, then that machine should
54 have the trace-cmd restore run with the *-c* option to create the
55 trace.dat partial file. Then that file can be copied to the current
56 machine where trace-cmd restore will use *-i* to load that file
57 instead of reading from the current system.
58
59EXAMPLES
60--------
61
62If a crash happened on another box, you could run:
63
64 $ trace-cmd restore -c -o box-partial.dat
65
66Then on the server that has the cpu files:
67
68 $ trace-cmd restore -i box-partial.dat trace.dat.cpu0 trace.dat.cpu1
69
70This would create a trace.dat file for the embedded box.
71
72SEE ALSO
73--------
74trace-cmd(1), trace-cmd-record(1), trace-cmd-report(1), trace-cmd-start(1),
75trace-cmd-stop(1), trace-cmd-extract(1), trace-cmd-reset(1), trace-cmd-split(1),
76trace-cmd-list(1), trace-cmd-listen(1)
77
78AUTHOR
79------
80Written by Steven Rostedt, <rostedt@goodmis.org>
81
82RESOURCES
83---------
84git://git.kernel.org/pub/scm/linux/kernel/git/rostedt/trace-cmd.git
85
86COPYING
87-------
88Copyright \(C) 2010 Red Hat, Inc. Free use of this software is granted under
89the terms of the GNU Public License (GPL).
90
diff --git a/Documentation/trace-cmd.1.txt b/Documentation/trace-cmd.1.txt
index fb4cadd..14c543c 100644
--- a/Documentation/trace-cmd.1.txt
+++ b/Documentation/trace-cmd.1.txt
@@ -43,6 +43,8 @@ COMMANDS
43 43
44 listen - open up a port to listen for remote tracing connections. 44 listen - open up a port to listen for remote tracing connections.
45 45
46 restore - restore the data files of a crashed run of trace-cmd record
47
46 48
47OPTIONS 49OPTIONS
48------- 50-------
@@ -56,6 +58,7 @@ SEE ALSO
56-------- 58--------
57trace-cmd-record(1), trace-cmd-report(1), trace-cmd-start(1), 59trace-cmd-record(1), trace-cmd-report(1), trace-cmd-start(1),
58trace-cmd-stop(1), trace-cmd-extract(1), trace-cmd-reset(1), 60trace-cmd-stop(1), trace-cmd-extract(1), trace-cmd-reset(1),
61trace-cmd-restore(1),
59trace-cmd-split(1), trace-cmd-list(1), trace-cmd-listen(1), 62trace-cmd-split(1), trace-cmd-list(1), trace-cmd-listen(1),
60trace-cmd.dat(5) 63trace-cmd.dat(5)
61 64
diff --git a/Makefile b/Makefile
index 54a8b29..c72dda6 100644
--- a/Makefile
+++ b/Makefile
@@ -262,7 +262,7 @@ KERNEL_SHARK_OBJS = $(TRACE_VIEW_OBJS) $(TRACE_GRAPH_OBJS) $(TRACE_GUI_OBJS) \
262 262
263PEVENT_LIB_OBJS = parse-events.o trace-seq.o parse-filter.o parse-utils.o 263PEVENT_LIB_OBJS = parse-events.o trace-seq.o parse-filter.o parse-utils.o
264TCMD_LIB_OBJS = $(PEVENT_LIB_OBJS) trace-util.o trace-input.o trace-ftrace.o \ 264TCMD_LIB_OBJS = $(PEVENT_LIB_OBJS) trace-util.o trace-input.o trace-ftrace.o \
265 trace-output.o trace-record.o 265 trace-output.o trace-record.o trace-restore.o
266 266
267PLUGIN_OBJS = plugin_hrtimer.o plugin_kmem.o plugin_sched_switch.o \ 267PLUGIN_OBJS = plugin_hrtimer.o plugin_kmem.o plugin_sched_switch.o \
268 plugin_mac80211.o plugin_jbd2.o plugin_function.o 268 plugin_mac80211.o plugin_jbd2.o plugin_function.o
diff --git a/trace-cmd.c b/trace-cmd.c
index 7afc5ac..6fbac8c 100644
--- a/trace-cmd.c
+++ b/trace-cmd.c
@@ -1429,6 +1429,9 @@ int main (int argc, char **argv)
1429 } else if (strcmp(argv[1], "split") == 0) { 1429 } else if (strcmp(argv[1], "split") == 0) {
1430 trace_split(argc, argv); 1430 trace_split(argc, argv);
1431 exit(0); 1431 exit(0);
1432 } else if (strcmp(argv[1], "restore") == 0) {
1433 trace_restore(argc, argv);
1434 exit(0);
1432 } else if ((record = (strcmp(argv[1], "record") == 0)) || 1435 } else if ((record = (strcmp(argv[1], "record") == 0)) ||
1433 (strcmp(argv[1], "start") == 0) || 1436 (strcmp(argv[1], "start") == 0) ||
1434 ((extract = strcmp(argv[1], "extract") == 0))) { 1437 ((extract = strcmp(argv[1], "extract") == 0))) {
diff --git a/trace-cmd.h b/trace-cmd.h
index d8ebccd..b2586bf 100644
--- a/trace-cmd.h
+++ b/trace-cmd.h
@@ -160,6 +160,7 @@ struct tracecmd_output *tracecmd_create_file_latency(const char *output_file, in
160struct tracecmd_output *tracecmd_create_file(const char *output_file, 160struct tracecmd_output *tracecmd_create_file(const char *output_file,
161 int cpus, char * const *cpu_data_files); 161 int cpus, char * const *cpu_data_files);
162struct tracecmd_output *tracecmd_create_init_fd(int fd); 162struct tracecmd_output *tracecmd_create_init_fd(int fd);
163struct tracecmd_output *tracecmd_create_init_file(const char *output_file);
163void tracecmd_output_close(struct tracecmd_output *handle); 164void tracecmd_output_close(struct tracecmd_output *handle);
164struct tracecmd_output *tracecmd_copy(struct tracecmd_input *ihandle, 165struct tracecmd_output *tracecmd_copy(struct tracecmd_input *ihandle,
165 const char *file); 166 const char *file);
diff --git a/trace-local.h b/trace-local.h
index 60b8b5e..0ae798d 100644
--- a/trace-local.h
+++ b/trace-local.h
@@ -42,4 +42,6 @@ void trace_split(int argc, char **argv);
42 42
43void trace_listen(int argc, char **argv); 43void trace_listen(int argc, char **argv);
44 44
45void trace_restore(int argc, char **argv);
46
45#endif /* __TRACE_LOCAL_H */ 47#endif /* __TRACE_LOCAL_H */
diff --git a/trace-output.c b/trace-output.c
index c34e8b2..14fe0f1 100644
--- a/trace-output.c
+++ b/trace-output.c
@@ -860,16 +860,14 @@ struct tracecmd_output *tracecmd_create_file(const char *output_file,
860 return handle; 860 return handle;
861} 861}
862 862
863struct tracecmd_output * 863struct tracecmd_output *tracecmd_create_init_fd(int fd)
864tracecmd_create_init_fd(int fd)
865{ 864{
866 struct tracecmd_output *handle; 865 return create_file_fd(fd, NULL);
867 866}
868 handle = create_file_fd(fd, NULL);
869 if (!handle)
870 return NULL;
871 867
872 return handle; 868struct tracecmd_output *tracecmd_create_init_file(const char *output_file)
869{
870 return create_file(output_file, NULL);
873} 871}
874 872
875/** 873/**
diff --git a/trace-restore.c b/trace-restore.c
new file mode 100644
index 0000000..cf8c14f
--- /dev/null
+++ b/trace-restore.c
@@ -0,0 +1,146 @@
1/*
2 * Copyright (C) 2009, 2010 Red Hat Inc, Steven Rostedt <srostedt@redhat.com>
3 *
4 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; version 2 of the License (not later!)
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 *
19 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
20 */
21#define _LARGEFILE64_SOURCE
22#define _GNU_SOURCE
23#include <dirent.h>
24#include <stdio.h>
25#include <stdlib.h>
26#include <string.h>
27#include <getopt.h>
28#include <stdarg.h>
29#include <sys/types.h>
30#include <sys/stat.h>
31#include <sys/wait.h>
32#include <sys/mman.h>
33#include <pthread.h>
34#include <fcntl.h>
35#include <signal.h>
36#include <unistd.h>
37#include <ctype.h>
38#include <errno.h>
39
40#include "trace-local.h"
41
42void trace_restore (int argc, char **argv)
43{
44 struct tracecmd_output *handle;
45 const char *output_file = "trace.dat";
46 const char *output = NULL;
47 const char *input = NULL;
48 struct stat st1;
49 struct stat st2;
50 int first_arg;
51 int create_only = 0;
52 int args;
53 int c;
54
55 if (argc < 2)
56 usage(argv);
57
58 if (strcmp(argv[1], "restore") != 0)
59 usage(argv);
60
61 while ((c = getopt(argc-1, argv+1, "+hco:i:")) >= 0) {
62 switch (c) {
63 case 'h':
64 usage(argv);
65 break;
66 case 'c':
67 if (input)
68 die("-c and -i are incompatible");
69 create_only = 1;
70 /* make output default to partial */
71 output_file = "trace-partial.dat";
72 break;
73
74 case 'o':
75 if (output)
76 die("only one output file allowed");
77 output = optarg;
78 break;
79
80 case 'i':
81 if (input)
82 die("only one input file allowed");
83 if (create_only)
84 die("-c and -i are incompatible");
85 input = optarg;
86 break;
87
88 default:
89 usage(argv);
90 }
91 }
92
93 if (!output)
94 output = output_file;
95
96 if ((argc - optind) <= 1) {
97 if (!create_only) {
98 warning("No data files found");
99 usage(argv);
100 }
101
102 handle = tracecmd_create_init_file(output);
103 if (!handle)
104 die("Unabled to create output file %s", output);
105 tracecmd_output_close(handle);
106 exit(0);
107 }
108 first_arg = optind + 1;
109 args = argc - first_arg;
110 printf("first = %d %s args=%d\n", first_arg, argv[first_arg], args);
111
112 /* Make sure input and output are not the same file */
113 if (input && output) {
114 if (stat(input, &st1) < 0)
115 die("%s:", input);
116 /* output exists? otherwise we don't care */
117 if (stat(output, &st2) == 0) {
118 if (st1.st_ino == st2.st_ino &&
119 st1.st_dev == st2.st_dev)
120 die("input and output file are the same");
121 }
122 }
123
124 if (input) {
125 struct tracecmd_input *ihandle;
126
127 ihandle = tracecmd_alloc(input);
128 if (!ihandle)
129 die("error reading file %s", input);
130 /* make sure headers are ok */
131 if (tracecmd_read_headers(ihandle) < 0)
132 die("error reading file %s headers", input);
133
134 handle = tracecmd_copy(ihandle, output);
135 tracecmd_close(ihandle);
136 } else
137 handle = tracecmd_create_init_file(output);
138
139 if (!handle)
140 die("error writing to %s", output);
141
142 if (tracecmd_append_cpu_data(handle, args, &argv[first_arg]) < 0)
143 die("failed to append data");
144
145 return;
146}
diff --git a/trace-usage.c b/trace-usage.c
index 8f70f29..5dd691c 100644
--- a/trace-usage.c
+++ b/trace-usage.c
@@ -123,6 +123,14 @@ static struct usage_help usage_help[] = {
123 " -o list available options\n" 123 " -o list available options\n"
124 }, 124 },
125 { 125 {
126 "restore",
127 "restore a crashed record",
128 " %s restore [-c][-o file][-i file] cpu-file [cpu-file ...]\n"
129 " -c create a partial trace.dat file only\n"
130 " -o output file\n"
131 " -i parital trace.dat file for input\n"
132 },
133 {
126 NULL, NULL, NULL 134 NULL, NULL, NULL
127 } 135 }
128}; 136};