aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSteven Rostedt <srostedt@redhat.com>2009-04-02 00:09:41 -0400
committerIngo Molnar <mingo@elte.hu>2009-04-13 18:00:53 -0400
commitfa1b47dd85453ec7d4bcfe4aa4a2d172ba452fc3 (patch)
tree3e5f14cccd9e4ec772310c1b2792b6f4b84bf7cb
parente45f2e2bd298e1ff687448e5fd15a3588b5807ec (diff)
ring-buffer: add ring_buffer_discard_commit
The ring_buffer_discard_commit is similar to ring_buffer_event_discard but it can only be done on an event that has yet to be commited. Unpredictable results can happen otherwise. The main difference between ring_buffer_discard_commit and ring_buffer_event_discard is that ring_buffer_discard_commit will try to free the data in the ring buffer if nothing has addded data after the reserved event. If something did, then it acts almost the same as ring_buffer_event_discard followed by a ring_buffer_unlock_commit. Note, either ring_buffer_commit_discard and ring_buffer_unlock_commit can be called on an event, not both. This commit also exports both discard functions to be usable by GPL modules. Signed-off-by: Steven Rostedt <srostedt@redhat.com> Signed-off-by: Ingo Molnar <mingo@elte.hu>
-rw-r--r--include/linux/ring_buffer.h29
-rw-r--r--kernel/trace/ring_buffer.c125
2 files changed, 133 insertions, 21 deletions
diff --git a/include/linux/ring_buffer.h b/include/linux/ring_buffer.h
index e1b7b2173885..f0aa486d131c 100644
--- a/include/linux/ring_buffer.h
+++ b/include/linux/ring_buffer.h
@@ -68,9 +68,38 @@ ring_buffer_event_time_delta(struct ring_buffer_event *event)
68 return event->time_delta; 68 return event->time_delta;
69} 69}
70 70
71/*
72 * ring_buffer_event_discard can discard any event in the ring buffer.
73 * it is up to the caller to protect against a reader from
74 * consuming it or a writer from wrapping and replacing it.
75 *
76 * No external protection is needed if this is called before
77 * the event is commited. But in that case it would be better to
78 * use ring_buffer_discard_commit.
79 *
80 * Note, if an event that has not been committed is discarded
81 * with ring_buffer_event_discard, it must still be committed.
82 */
71void ring_buffer_event_discard(struct ring_buffer_event *event); 83void ring_buffer_event_discard(struct ring_buffer_event *event);
72 84
73/* 85/*
86 * ring_buffer_discard_commit will remove an event that has not
87 * ben committed yet. If this is used, then ring_buffer_unlock_commit
88 * must not be called on the discarded event. This function
89 * will try to remove the event from the ring buffer completely
90 * if another event has not been written after it.
91 *
92 * Example use:
93 *
94 * if (some_condition)
95 * ring_buffer_discard_commit(buffer, event);
96 * else
97 * ring_buffer_unlock_commit(buffer, event);
98 */
99void ring_buffer_discard_commit(struct ring_buffer *buffer,
100 struct ring_buffer_event *event);
101
102/*
74 * size is in bytes for each per CPU buffer. 103 * size is in bytes for each per CPU buffer.
75 */ 104 */
76struct ring_buffer * 105struct ring_buffer *
diff --git a/kernel/trace/ring_buffer.c b/kernel/trace/ring_buffer.c
index 74a11808c282..f935bd5ec3e8 100644
--- a/kernel/trace/ring_buffer.c
+++ b/kernel/trace/ring_buffer.c
@@ -205,27 +205,6 @@ static void rb_event_set_padding(struct ring_buffer_event *event)
205 event->time_delta = 0; 205 event->time_delta = 0;
206} 206}
207 207
208/**
209 * ring_buffer_event_discard - discard an event in the ring buffer
210 * @buffer: the ring buffer
211 * @event: the event to discard
212 *
213 * Sometimes a event that is in the ring buffer needs to be ignored.
214 * This function lets the user discard an event in the ring buffer
215 * and then that event will not be read later.
216 *
217 * Note, it is up to the user to be careful with this, and protect
218 * against races. If the user discards an event that has been consumed
219 * it is possible that it could corrupt the ring buffer.
220 */
221void ring_buffer_event_discard(struct ring_buffer_event *event)
222{
223 event->type = RINGBUF_TYPE_PADDING;
224 /* time delta must be non zero */
225 if (!event->time_delta)
226 event->time_delta = 1;
227}
228
229static unsigned 208static unsigned
230rb_event_data_length(struct ring_buffer_event *event) 209rb_event_data_length(struct ring_buffer_event *event)
231{ 210{
@@ -1571,6 +1550,110 @@ int ring_buffer_unlock_commit(struct ring_buffer *buffer,
1571EXPORT_SYMBOL_GPL(ring_buffer_unlock_commit); 1550EXPORT_SYMBOL_GPL(ring_buffer_unlock_commit);
1572 1551
1573/** 1552/**
1553 * ring_buffer_event_discard - discard any event in the ring buffer
1554 * @event: the event to discard
1555 *
1556 * Sometimes a event that is in the ring buffer needs to be ignored.
1557 * This function lets the user discard an event in the ring buffer
1558 * and then that event will not be read later.
1559 *
1560 * Note, it is up to the user to be careful with this, and protect
1561 * against races. If the user discards an event that has been consumed
1562 * it is possible that it could corrupt the ring buffer.
1563 */
1564void ring_buffer_event_discard(struct ring_buffer_event *event)
1565{
1566 event->type = RINGBUF_TYPE_PADDING;
1567 /* time delta must be non zero */
1568 if (!event->time_delta)
1569 event->time_delta = 1;
1570}
1571EXPORT_SYMBOL_GPL(ring_buffer_event_discard);
1572
1573/**
1574 * ring_buffer_commit_discard - discard an event that has not been committed
1575 * @buffer: the ring buffer
1576 * @event: non committed event to discard
1577 *
1578 * This is similar to ring_buffer_event_discard but must only be
1579 * performed on an event that has not been committed yet. The difference
1580 * is that this will also try to free the event from the ring buffer
1581 * if another event has not been added behind it.
1582 *
1583 * If another event has been added behind it, it will set the event
1584 * up as discarded, and perform the commit.
1585 *
1586 * If this function is called, do not call ring_buffer_unlock_commit on
1587 * the event.
1588 */
1589void ring_buffer_discard_commit(struct ring_buffer *buffer,
1590 struct ring_buffer_event *event)
1591{
1592 struct ring_buffer_per_cpu *cpu_buffer;
1593 unsigned long new_index, old_index;
1594 struct buffer_page *bpage;
1595 unsigned long index;
1596 unsigned long addr;
1597 int cpu;
1598
1599 /* The event is discarded regardless */
1600 ring_buffer_event_discard(event);
1601
1602 /*
1603 * This must only be called if the event has not been
1604 * committed yet. Thus we can assume that preemption
1605 * is still disabled.
1606 */
1607 RB_WARN_ON(buffer, !preempt_count());
1608
1609 cpu = smp_processor_id();
1610 cpu_buffer = buffer->buffers[cpu];
1611
1612 new_index = rb_event_index(event);
1613 old_index = new_index + rb_event_length(event);
1614 addr = (unsigned long)event;
1615 addr &= PAGE_MASK;
1616
1617 bpage = cpu_buffer->tail_page;
1618
1619 if (bpage == (void *)addr && rb_page_write(bpage) == old_index) {
1620 /*
1621 * This is on the tail page. It is possible that
1622 * a write could come in and move the tail page
1623 * and write to the next page. That is fine
1624 * because we just shorten what is on this page.
1625 */
1626 index = local_cmpxchg(&bpage->write, old_index, new_index);
1627 if (index == old_index)
1628 goto out;
1629 }
1630
1631 /*
1632 * The commit is still visible by the reader, so we
1633 * must increment entries.
1634 */
1635 cpu_buffer->entries++;
1636 out:
1637 /*
1638 * If a write came in and pushed the tail page
1639 * we still need to update the commit pointer
1640 * if we were the commit.
1641 */
1642 if (rb_is_commit(cpu_buffer, event))
1643 rb_set_commit_to_write(cpu_buffer);
1644
1645 /*
1646 * Only the last preempt count needs to restore preemption.
1647 */
1648 if (preempt_count() == 1)
1649 ftrace_preempt_enable(per_cpu(rb_need_resched, cpu));
1650 else
1651 preempt_enable_no_resched_notrace();
1652
1653}
1654EXPORT_SYMBOL_GPL(ring_buffer_discard_commit);
1655
1656/**
1574 * ring_buffer_write - write data to the buffer without reserving 1657 * ring_buffer_write - write data to the buffer without reserving
1575 * @buffer: The ring buffer to write to. 1658 * @buffer: The ring buffer to write to.
1576 * @length: The length of the data being written (excluding the event header) 1659 * @length: The length of the data being written (excluding the event header)