aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSteven Rostedt <srostedt@redhat.com>2009-12-18 13:28:16 -0500
committerSteven Rostedt <rostedt@goodmis.org>2009-12-18 13:28:16 -0500
commitb05f27dc7d0dab346e20795ce4d9f6d56d3e18ea (patch)
treef04d884bb24f28edcdaf7a01119e11e1eca1badf
parentd889066760e48795b4c778e4589ec089e41f009d (diff)
trace-cmd: Have function graph keep record around
The function graph tracer looks forward in the trace to determine if a function is a leaf or not. In doing so, it causes the mapping of records to change. This produces a nasty side effect where the caller can have the record stored, and it will suddenly invalidate the record's mapping. This refreshes the record passed in and does a trick by calling the tracecmd_peek_data function that will cache the location after the leaf function's return entry. This unfortunately causes a side effect too where if the last entry in the trace is a leaf function, we can't hide the exit entry and it will print regardless. But this side effect wont crash the application, but the previous side effect will. Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
-rw-r--r--trace-ftrace.c29
-rw-r--r--trace-input.c18
2 files changed, 44 insertions, 3 deletions
diff --git a/trace-ftrace.c b/trace-ftrace.c
index 0920430..459f74b 100644
--- a/trace-ftrace.c
+++ b/trace-ftrace.c
@@ -250,12 +250,37 @@ fgraph_ent_handler(struct trace_seq *s, struct record *record,
250 rec = tracecmd_peek_data(tracecmd_curr_thread_handle, cpu); 250 rec = tracecmd_peek_data(tracecmd_curr_thread_handle, cpu);
251 if (rec) 251 if (rec)
252 rec = get_return_for_leaf(s, cpu, pid, val, rec); 252 rec = get_return_for_leaf(s, cpu, pid, val, rec);
253 if (rec) 253
254 if (rec) {
255 /*
256 * The record returned needs to be freed.
257 * We also do a new peek on this CPU to update the
258 * record cache. (peek caches the record, but the
259 * refresh below will update the CPU iterator.
260 * If peek has a record in cache, it will update the
261 * iterator to that)
262 */
254 ret = print_graph_entry_leaf(s, event, data, rec); 263 ret = print_graph_entry_leaf(s, event, data, rec);
255 else 264 free_record(rec);
265 tracecmd_peek_data(tracecmd_curr_thread_handle, cpu);
266 } else
256 ret = print_graph_nested(s, event, data); 267 ret = print_graph_nested(s, event, data);
257 268
258 free(data); 269 free(data);
270
271 /*
272 * The above peek may unmap the record given to us.
273 * But callers may still have a reference to that record.
274 * We need to make sure it is still mapped.
275 *
276 * Note, this causes a known bug. If the last item in the trace
277 * was a leaf function, we can't remove it. The peek cache
278 * above will be NULL (no records after the leaf) so a new peek
279 * will simply read the return entry of the leaf and print it
280 * again.
281 */
282 tracecmd_refresh_record(tracecmd_curr_thread_handle,
283 record);
259 return ret; 284 return ret;
260} 285}
261 286
diff --git a/trace-input.c b/trace-input.c
index 5c8dfae..8cc8865 100644
--- a/trace-input.c
+++ b/trace-input.c
@@ -1137,13 +1137,29 @@ tracecmd_peek_data(struct tracecmd_input *handle, int cpu)
1137 unsigned long long extend; 1137 unsigned long long extend;
1138 unsigned int type_len; 1138 unsigned int type_len;
1139 int length; 1139 int length;
1140 int ret;
1140 1141
1141 /* Hack to work around function graph read ahead */ 1142 /* Hack to work around function graph read ahead */
1142 tracecmd_curr_thread_handle = handle; 1143 tracecmd_curr_thread_handle = handle;
1143 1144
1144 if (handle->cpu_data[cpu].next) { 1145 if (handle->cpu_data[cpu].next) {
1145 /* Make sure it's still mapped */ 1146 /* Make sure it's still mapped */
1146 tracecmd_refresh_record(handle, handle->cpu_data[cpu].next); 1147 ret = tracecmd_refresh_record(handle, handle->cpu_data[cpu].next);
1148 if (ret < 0) {
1149 free_record(handle->cpu_data[cpu].next);
1150 handle->cpu_data[cpu].next = NULL;
1151 return NULL;
1152 }
1153 /*
1154 * Make sure the index and timestamp are where
1155 * we want them, because the refresh did not update it.
1156 */
1157 if (ret && handle->cpu_data[cpu].timestamp != record->ts) {
1158 handle->cpu_data[cpu].index =
1159 (record->offset & (handle->page_size - 1)) +
1160 record->record_size;
1161 handle->cpu_data[cpu].timestamp = record->ts;
1162 }
1147 return handle->cpu_data[cpu].next; 1163 return handle->cpu_data[cpu].next;
1148 } 1164 }
1149 1165