diff options
author | Steven Rostedt <srostedt@redhat.com> | 2010-02-12 10:12:34 -0500 |
---|---|---|
committer | Steven Rostedt <rostedt@goodmis.org> | 2010-02-12 10:12:34 -0500 |
commit | 183e6167573572dbaed0d78a53bc40ed0168060c (patch) | |
tree | 28c538928adab2a123d0c09079b94e80faa41f01 | |
parent | b2202021815c7716b4b45087736697b78826415b (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.h | 1 | ||||
-rw-r--r-- | trace-input.c | 60 |
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 | ||
625 | void free_record(struct record *record) | 625 | static 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 | ||
635 | void 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 | |||
647 | static 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); |