History

ring-buffer: Skip invalid sub-buffers when validating persistent ring buffer

Skip invalid sub-buffers when validating the persistent ring buffer instead of discarding the entire ring buffer. Only skipped buffers are invalidated (cleared). If the cache data in memory fails to be synchronized during a reboot, the persistent ring buffer may become partially corrupted, but other sub-buffers may still contain readable event data. Only discard the subbuffers that are found to be corrupted. Link: https://lore.kernel.org/all/20260520185018.051228084@kernel.org/

Masami Hiramatsu (Google) committed 5 months ago

Commit eb3bd271 parent e7ae89a1 file · +73 −47Browse files

Unified · Split

kernel/trace/ring_buffer.c+73−47
@@ -370,6 +370,12 @@ static __always_inline unsigned int rb_page_commit(struct buffer_page *bpage) · 369 unmodified lines
370370 return local_read(&bpage->page->commit);
371371 }
372372
373+/* Size is determined by what has been committed */
374+static __always_inline unsigned int rb_page_size(struct buffer_page *bpage)
375+{
376+ return rb_page_commit(bpage) & ~RB_MISSED_MASK;
377+}
378+
373379 static void free_buffer_page(struct buffer_page *bpage)
374380 {
375381 /* Range pages are not to be freed */
@@ -1762,7 +1768,6 @@ static bool rb_cpu_meta_valid(struct ring_buffer_cpu_meta *meta, int cpu, · 1386 unmodified lines
17621768 unsigned long *subbuf_mask)
17631769 {
17641770 int subbuf_size = PAGE_SIZE;
1765− struct buffer_data_page *subbuf;
17661771 unsigned long buffers_start;
17671772 unsigned long buffers_end;
17681773 int i;
@@ -1770,6 +1775,11 @@ static bool rb_cpu_meta_valid(struct ring_buffer_cpu_meta *meta, int cpu, · 1 unmodified line
17701775 if (!subbuf_mask)
17711776 return false;
17721777
1778+ if (meta->subbuf_size != PAGE_SIZE) {
1779+ pr_info("Ring buffer boot meta [%d] invalid subbuf_size\n", cpu);
1780+ return false;
1781+ }
1782+
17731783 buffers_start = meta->first_buffer;
17741784 buffers_end = meta->first_buffer + (subbuf_size * meta->nr_subbufs);
17751785
@@ -1786,11 +1796,12 @@ static bool rb_cpu_meta_valid(struct ring_buffer_cpu_meta *meta, int cpu, · 10 unmodified lines
17861796 return false;
17871797 }
17881798
1789− subbuf = rb_subbufs_from_meta(meta);
1790−
17911799 bitmap_clear(subbuf_mask, 0, meta->nr_subbufs);
17921800
1793− /* Is the meta buffers and the subbufs themselves have correct data? */
1801+ /*
1802+ * Ensure the meta::buffers array has correct data. The data in each subbufs
1803+ * are checked later in rb_meta_validate_events().
1804+ */
17941805 for (i = 0; i < meta->nr_subbufs; i++) {
17951806 if (meta->buffers[i] < 0 ||
17961807 meta->buffers[i] >= meta->nr_subbufs) {
@@ -1798,18 +1809,12 @@ static bool rb_cpu_meta_valid(struct ring_buffer_cpu_meta *meta, int cpu, · 1 unmodified line
17981809 return false;
17991810 }
18001811
1801− if ((unsigned)local_read(&subbuf->commit) > subbuf_size) {
1802− pr_info("Ring buffer boot meta [%d] buffer invalid commit\n", cpu);
1803− return false;
1804− }
1805−
18061812 if (test_bit(meta->buffers[i], subbuf_mask)) {
18071813 pr_info("Ring buffer boot meta [%d] array has duplicates\n", cpu);
18081814 return false;
18091815 }
18101816
18111817 set_bit(meta->buffers[i], subbuf_mask);
1812− subbuf = (void *)subbuf + subbuf_size;
18131818 }
18141819
18151820 return true;
@@ -1873,13 +1878,22 @@ static int rb_read_data_buffer(struct buffer_data_page *dpage, int tail, int cpu · 57 unmodified lines
18731878 return events;
18741879 }
18751880
1876−static int rb_validate_buffer(struct buffer_data_page *dpage, int cpu)
1881+static int rb_validate_buffer(struct buffer_data_page *dpage, int cpu,
1882+ struct ring_buffer_cpu_meta *meta)
18771883 {
18781884 unsigned long long ts;
1885+ unsigned long tail;
18791886 u64 delta;
1880− int tail;
18811887
1882− tail = local_read(&dpage->commit);
1888+ /*
1889+ * When a sub-buffer is recovered from a read, the commit value may
1890+ * have RB_MISSED_* bits set, as these bits are reset on reuse.
1891+ * Even after clearing these bits, a commit value greater than the
1892+ * subbuf_size is considered invalid.
1893+ */
1894+ tail = local_read(&dpage->commit) & ~RB_MISSED_MASK;
1895+ if (tail > meta->subbuf_size - BUF_PAGE_HDR_SIZE)
1896+ return -1;
18831897 return rb_read_data_buffer(dpage, tail, cpu, &ts, &delta);
18841898 }
18851899
@@ -1890,6 +1904,7 @@ static void rb_meta_validate_events(struct ring_buffer_per_cpu *cpu_buffer) · 4 unmodified lines
18901904 struct buffer_page *head_page, *orig_head, *orig_reader;
18911905 unsigned long entry_bytes = 0;
18921906 unsigned long entries = 0;
1907+ int discarded = 0;
18931908 int ret;
18941909 u64 ts;
18951910 int i;
@@ -1901,14 +1916,19 @@ static void rb_meta_validate_events(struct ring_buffer_per_cpu *cpu_buffer) · 5 unmodified lines
19011916 orig_reader = cpu_buffer->reader_page;
19021917
19031918 /* Do the reader page first */
1904− ret = rb_validate_buffer(orig_reader->page, cpu_buffer->cpu);
1919+ ret = rb_validate_buffer(orig_reader->page, cpu_buffer->cpu, meta);
19051920 if (ret < 0) {
1906− pr_info("Ring buffer reader page is invalid\n");
1907− goto invalid;
1921+ pr_info("Ring buffer meta [%d] invalid reader page detected\n",
1922+ cpu_buffer->cpu);
1923+ discarded++;
1924+ /* Instead of discard whole ring buffer, discard only this sub-buffer. */
1925+ local_set(&orig_reader->entries, 0);
1926+ local_set(&orig_reader->page->commit, 0);
1927+ } else {
1928+ entries += ret;
1929+ entry_bytes += rb_page_size(orig_reader);
1930+ local_set(&orig_reader->entries, ret);
19081931 }
1909− entries += ret;
1910− entry_bytes += local_read(&orig_reader->page->commit);
1911− local_set(&orig_reader->entries, ret);
19121932
19131933 ts = head_page->page->time_stamp;
19141934
@@ -1936,7 +1956,7 @@ static void rb_meta_validate_events(struct ring_buffer_per_cpu *cpu_buffer) · 21 unmodified lines
19361956 break;
19371957
19381958 /* Stop rewind if the page is invalid. */
1939− ret = rb_validate_buffer(head_page->page, cpu_buffer->cpu);
1959+ ret = rb_validate_buffer(head_page->page, cpu_buffer->cpu, meta);
19401960 if (ret < 0)
19411961 break;
19421962
@@ -1945,7 +1965,7 @@ static void rb_meta_validate_events(struct ring_buffer_per_cpu *cpu_buffer) · 2 unmodified lines
19451965 if (ret)
19461966 local_inc(&cpu_buffer->pages_touched);
19471967 entries += ret;
1948− entry_bytes += rb_page_commit(head_page);
1968+ entry_bytes += rb_page_size(head_page);
19491969 }
19501970 if (i)
19511971 pr_info("Ring buffer [%d] rewound %d pages\n", cpu_buffer->cpu, i);
@@ -2015,21 +2035,24 @@ static void rb_meta_validate_events(struct ring_buffer_per_cpu *cpu_buffer) · 63 unmodified lines
20152035 if (head_page == orig_reader)
20162036 continue;
20172037
2018− ret = rb_validate_buffer(head_page->page, cpu_buffer->cpu);
2038+ ret = rb_validate_buffer(head_page->page, cpu_buffer->cpu, meta);
20192039 if (ret < 0) {
2020− pr_info("Ring buffer meta [%d] invalid buffer page\n",
2021− cpu_buffer->cpu);
2022− goto invalid;
2023− }
2024−
2025− /* If the buffer has content, update pages_touched */
2026− if (ret)
2027− local_inc(&cpu_buffer->pages_touched);
2028−
2029− entries += ret;
2030− entry_bytes += local_read(&head_page->page->commit);
2031− local_set(&head_page->entries, ret);
2040+ if (!discarded)
2041+ pr_info("Ring buffer meta [%d] invalid buffer page detected\n",
2042+ cpu_buffer->cpu);
2043+ discarded++;
2044+ /* Instead of discard whole ring buffer, discard only this sub-buffer. */
2045+ local_set(&head_page->entries, 0);
2046+ local_set(&head_page->page->commit, 0);
2047+ } else {
2048+ /* If the buffer has content, update pages_touched */
2049+ if (ret)
2050+ local_inc(&cpu_buffer->pages_touched);
20322051
2052+ entries += ret;
2053+ entry_bytes += rb_page_size(head_page);
2054+ local_set(&head_page->entries, ret);
2055+ }
20332056 if (head_page == cpu_buffer->commit_page)
20342057 break;
20352058 }
@@ -2043,7 +2066,10 @@ static void rb_meta_validate_events(struct ring_buffer_per_cpu *cpu_buffer) · 7 unmodified lines
20432066 local_set(&cpu_buffer->entries, entries);
20442067 local_set(&cpu_buffer->entries_bytes, entry_bytes);
20452068
2046− pr_info("Ring buffer meta [%d] is from previous boot!\n", cpu_buffer->cpu);
2069+ pr_info("Ring buffer meta [%d] is from previous boot!", cpu_buffer->cpu);
2070+ if (discarded)
2071+ pr_cont(" (%d pages discarded)", discarded);
2072+ pr_cont("\n");
20472073 return;
20482074
20492075 invalid:
@@ -3330,12 +3356,6 @@ rb_iter_head_event(struct ring_buffer_iter *iter) · 1280 unmodified lines
33303356 return NULL;
33313357 }
33323358
3333−/* Size is determined by what has been committed */
3334−static __always_inline unsigned rb_page_size(struct buffer_page *bpage)
3335−{
3336− return rb_page_commit(bpage) & ~RB_MISSED_MASK;
3337−}
3338−
33393359 static __always_inline unsigned
33403360 rb_commit_index(struct ring_buffer_per_cpu *cpu_buffer)
33413361 {
@@ -5636,8 +5656,9 @@ __rb_get_reader_page_from_remote(struct ring_buffer_per_cpu *cpu_buffer) · 2294 unmodified lines
56365656 static struct buffer_page *
56375657 __rb_get_reader_page(struct ring_buffer_per_cpu *cpu_buffer)
56385658 {
5639− struct buffer_page *reader = NULL;
5659+ int max_loops = cpu_buffer->ring_meta ? cpu_buffer->nr_pages : 3;
56405660 unsigned long bsize = READ_ONCE(cpu_buffer->buffer->subbuf_size);
5661+ struct buffer_page *reader = NULL;
56415662 unsigned long overwrite;
56425663 unsigned long flags;
56435664 int nr_loops = 0;
@@ -5649,11 +5670,14 @@ __rb_get_reader_page(struct ring_buffer_per_cpu *cpu_buffer) · 5 unmodified lines
56495670 again:
56505671 /*
56515672 * This should normally only loop twice. But because the
5652− * start of the reader inserts an empty page, it causes
5653− * a case where we will loop three times. There should be no
5654− * reason to loop four times (that I know of).
5673+ * start of the reader inserts an empty page, it causes a
5674+ * case where we will loop three times. There should be no
5675+ * reason to loop four times unless the ring buffer is a
5676+ * recovered persistent ring buffer. For persistent ring buffers,
5677+ * invalid pages are reset during recovery, so there may be more
5678+ * than 3 contiguous pages can be empty, but less than nr_pages.
56555679 */
5656− if (RB_WARN_ON(cpu_buffer, ++nr_loops > 3)) {
5680+ if (RB_WARN_ON(cpu_buffer, ++nr_loops > max_loops)) {
56575681 reader = NULL;
56585682 goto out;
56595683 }
@@ -5950,12 +5974,14 @@ rb_iter_peek(struct ring_buffer_iter *iter, u64 *ts) · 290 unmodified lines
59505974 struct ring_buffer_per_cpu *cpu_buffer;
59515975 struct ring_buffer_event *event;
59525976 int nr_loops = 0;
5977+ int max_loops;
59535978
59545979 if (ts)
59555980 *ts = 0;
59565981
59575982 cpu_buffer = iter->cpu_buffer;
59585983 buffer = cpu_buffer->buffer;
5984+ max_loops = cpu_buffer->ring_meta ? cpu_buffer->nr_pages : 3;
59595985
59605986 /*
59615987 * Check if someone performed a consuming read to the buffer
@@ -5978,7 +6004,7 @@ rb_iter_peek(struct ring_buffer_iter *iter, u64 *ts) · 16 unmodified lines
59786004 * the ring buffer with an active write as the consumer is.
59796005 * Do not warn if the three failures is reached.
59806006 */
5981− if (++nr_loops > 3)
6007+ if (++nr_loops > max_loops)
59826008 return NULL;
59836009
59846010 if (rb_per_cpu_empty(cpu_buffer))

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t