aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSteven Rostedt <srostedt@redhat.com>2010-02-12 10:12:34 -0500
committerSteven Rostedt <rostedt@goodmis.org>2010-02-12 10:12:34 -0500
commit183e6167573572dbaed0d78a53bc40ed0168060c (patch)
tree28c538928adab2a123d0c09079b94e80faa41f01
parentb2202021815c7716b4b45087736697b78826415b (diff)
trace-cmd: Add locked attribute to record and debug peek freeing
Add a "locked" attribute to the record structure. This will be set when a peek is returned and cleared on read. This will help debug cases that incorrectly free a record returned by peek. The internal helper function free_next() is added to do the freeing of the next record used by peek. Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
-rw-r--r--parse-events.h1
-rw-r--r--trace-input.c60
2 files changed, 36 insertions, 25 deletions
diff --git a/parse-events.h b/parse-events.h
index e6ea2ab..66e0eb5 100644
--- a/parse-events.h
+++ b/parse-events.h
@@ -21,6 +21,7 @@ struct record {
21 int size; /* size of data */ 21 int size; /* size of data */
22 void *data; 22 void *data;
23 int cpu; 23 int cpu;
24 int locked; /* Do not allow freeing */
24 void *private; 25 void *private;
25}; 26};
26 27
diff --git a/trace-input.c b/trace-input.c
index 306b7a5..8c2a738 100644
--- a/trace-input.c
+++ b/trace-input.c
@@ -622,11 +622,8 @@ static void free_page(struct tracecmd_input *handle, int cpu)
622 handle->cpu_data[cpu].page = NULL; 622 handle->cpu_data[cpu].page = NULL;
623} 623}
624 624
625void free_record(struct record *record) 625static void __free_record(struct record *record)
626{ 626{
627 if (!record)
628 return;
629
630 if (record->private) { 627 if (record->private) {
631 struct page *page = record->private; 628 struct page *page = record->private;
632 __free_page(page->handle, page); 629 __free_page(page->handle, page);
@@ -635,6 +632,29 @@ void free_record(struct record *record)
635 free(record); 632 free(record);
636} 633}
637 634
635void free_record(struct record *record)
636{
637 if (!record)
638 return;
639
640 if (record->locked)
641 die("freeing record when it is locked!");
642 record->data = NULL;
643
644 __free_record(record);
645}
646
647static void free_next(struct tracecmd_input *handle, int cpu)
648{
649 struct record *record = handle->cpu_data[cpu].next;
650
651 if (!record)
652 return;
653
654 handle->cpu_data[cpu].next = NULL;
655 __free_record(record);
656}
657
638/* 658/*
639 * Page is mapped, now read in the page header info. 659 * Page is mapped, now read in the page header info.
640 */ 660 */
@@ -833,10 +853,7 @@ peek_event(struct tracecmd_input *handle, unsigned long long offset,
833 * tracecmd_read_at. 853 * tracecmd_read_at.
834 */ 854 */
835 update_page_info(handle, cpu); 855 update_page_info(handle, cpu);
836 if (handle->cpu_data[cpu].next) { 856 free_next(handle, cpu);
837 free_record(handle->cpu_data[cpu].next);
838 handle->cpu_data[cpu].next = NULL;
839 }
840 857
841 do { 858 do {
842 free_record(record); 859 free_record(record);
@@ -1016,10 +1033,7 @@ tracecmd_read_cpu_first(struct tracecmd_input *handle, int cpu)
1016 return NULL; 1033 return NULL;
1017 1034
1018 handle->cpu_data[cpu].index = 0; 1035 handle->cpu_data[cpu].index = 0;
1019 if (handle->cpu_data[cpu].next) { 1036 free_next(handle, cpu);
1020 free_record(handle->cpu_data[cpu].next);
1021 handle->cpu_data[cpu].next = NULL;
1022 }
1023 1037
1024 return tracecmd_read_data(handle, cpu); 1038 return tracecmd_read_data(handle, cpu);
1025} 1039}
@@ -1415,6 +1429,8 @@ tracecmd_peek_data(struct tracecmd_input *handle, int cpu)
1415 if (handle->cpu_data[cpu].next) { 1429 if (handle->cpu_data[cpu].next) {
1416 1430
1417 record = handle->cpu_data[cpu].next; 1431 record = handle->cpu_data[cpu].next;
1432 if (!record->data)
1433 die("Something freed the record");
1418 1434
1419 if (handle->cpu_data[cpu].timestamp == record->ts) 1435 if (handle->cpu_data[cpu].timestamp == record->ts)
1420 return record; 1436 return record;
@@ -1423,7 +1439,7 @@ tracecmd_peek_data(struct tracecmd_input *handle, int cpu)
1423 * The timestamp changed, which means the cached 1439 * The timestamp changed, which means the cached
1424 * record is no longer valid. Reread a new record. 1440 * record is no longer valid. Reread a new record.
1425 */ 1441 */
1426 free_record(record); 1442 free_next(handle, cpu);
1427 } 1443 }
1428 1444
1429 if (!page) 1445 if (!page)
@@ -1495,6 +1511,7 @@ read_again:
1495 1511
1496 record->record_size = handle->cpu_data[cpu].index - index; 1512 record->record_size = handle->cpu_data[cpu].index - index;
1497 record->private = page; 1513 record->private = page;
1514 record->locked = 1;
1498 page->ref_count++; 1515 page->ref_count++;
1499 1516
1500 return record; 1517 return record;
@@ -1517,6 +1534,8 @@ tracecmd_read_data(struct tracecmd_input *handle, int cpu)
1517 1534
1518 record = tracecmd_peek_data(handle, cpu); 1535 record = tracecmd_peek_data(handle, cpu);
1519 handle->cpu_data[cpu].next = NULL; 1536 handle->cpu_data[cpu].next = NULL;
1537 if (record)
1538 record->locked = 0;
1520 1539
1521 return record; 1540 return record;
1522} 1541}
@@ -1606,10 +1625,7 @@ tracecmd_read_prev(struct tracecmd_input *handle, struct record *record)
1606 index = offset - page_offset; 1625 index = offset - page_offset;
1607 1626
1608 /* Note, the record passed in could have been a peek */ 1627 /* Note, the record passed in could have been a peek */
1609 if (cpu_data->next) { 1628 free_next(handle, cpu);
1610 free_record(cpu_data->next);
1611 cpu_data->next = NULL;
1612 }
1613 1629
1614 /* Reset the cursor */ 1630 /* Reset the cursor */
1615 /* Should not happen */ 1631 /* Should not happen */
@@ -1975,14 +1991,8 @@ void tracecmd_close(struct tracecmd_input *handle)
1975 return; 1991 return;
1976 1992
1977 for (cpu = 0; cpu < handle->cpus; cpu++) { 1993 for (cpu = 0; cpu < handle->cpus; cpu++) {
1978 struct record *rec; 1994 /* The tracecmd_peek_data may have cached a record */
1979 /* 1995 free_next(handle, cpu);
1980 * The tracecmd_peek_data may have cached a record
1981 * Do a read to flush it out.
1982 */
1983 rec = tracecmd_read_data(handle, cpu);
1984 if (rec)
1985 free_record(rec);
1986 free_page(handle, cpu); 1996 free_page(handle, cpu);
1987 if (!list_empty(&handle->cpu_data[cpu].pages)) 1997 if (!list_empty(&handle->cpu_data[cpu].pages))
1988 warning("pages still allocated on cpu %d", cpu); 1998 warning("pages still allocated on cpu %d", cpu);