diff options
Diffstat (limited to 'kernel/trace/ring_buffer.c')
| -rw-r--r-- | kernel/trace/ring_buffer.c | 102 |
1 files changed, 77 insertions, 25 deletions
diff --git a/kernel/trace/ring_buffer.c b/kernel/trace/ring_buffer.c index 27ac37efb2b0..d673ef03d16d 100644 --- a/kernel/trace/ring_buffer.c +++ b/kernel/trace/ring_buffer.c | |||
| @@ -1252,7 +1252,7 @@ static inline unsigned long rb_page_write(struct buffer_page *bpage) | |||
| 1252 | return local_read(&bpage->write) & RB_WRITE_MASK; | 1252 | return local_read(&bpage->write) & RB_WRITE_MASK; |
| 1253 | } | 1253 | } |
| 1254 | 1254 | ||
| 1255 | static void | 1255 | static int |
| 1256 | rb_remove_pages(struct ring_buffer_per_cpu *cpu_buffer, unsigned int nr_pages) | 1256 | rb_remove_pages(struct ring_buffer_per_cpu *cpu_buffer, unsigned int nr_pages) |
| 1257 | { | 1257 | { |
| 1258 | struct list_head *tail_page, *to_remove, *next_page; | 1258 | struct list_head *tail_page, *to_remove, *next_page; |
| @@ -1359,46 +1359,97 @@ rb_remove_pages(struct ring_buffer_per_cpu *cpu_buffer, unsigned int nr_pages) | |||
| 1359 | } while (to_remove_page != last_page); | 1359 | } while (to_remove_page != last_page); |
| 1360 | 1360 | ||
| 1361 | RB_WARN_ON(cpu_buffer, nr_removed); | 1361 | RB_WARN_ON(cpu_buffer, nr_removed); |
| 1362 | |||
| 1363 | return nr_removed == 0; | ||
| 1362 | } | 1364 | } |
| 1363 | 1365 | ||
| 1364 | static void | 1366 | static int |
| 1365 | rb_insert_pages(struct ring_buffer_per_cpu *cpu_buffer, | 1367 | rb_insert_pages(struct ring_buffer_per_cpu *cpu_buffer) |
| 1366 | struct list_head *pages, unsigned nr_pages) | ||
| 1367 | { | 1368 | { |
| 1368 | struct buffer_page *bpage; | 1369 | struct list_head *pages = &cpu_buffer->new_pages; |
| 1369 | struct list_head *p; | 1370 | int retries, success; |
| 1370 | unsigned i; | ||
| 1371 | 1371 | ||
| 1372 | raw_spin_lock_irq(&cpu_buffer->reader_lock); | 1372 | raw_spin_lock_irq(&cpu_buffer->reader_lock); |
| 1373 | /* stop the writers while inserting pages */ | 1373 | /* |
| 1374 | atomic_inc(&cpu_buffer->record_disabled); | 1374 | * We are holding the reader lock, so the reader page won't be swapped |
| 1375 | rb_head_page_deactivate(cpu_buffer); | 1375 | * in the ring buffer. Now we are racing with the writer trying to |
| 1376 | * move head page and the tail page. | ||
| 1377 | * We are going to adapt the reader page update process where: | ||
| 1378 | * 1. We first splice the start and end of list of new pages between | ||
| 1379 | * the head page and its previous page. | ||
| 1380 | * 2. We cmpxchg the prev_page->next to point from head page to the | ||
| 1381 | * start of new pages list. | ||
| 1382 | * 3. Finally, we update the head->prev to the end of new list. | ||
| 1383 | * | ||
| 1384 | * We will try this process 10 times, to make sure that we don't keep | ||
| 1385 | * spinning. | ||
| 1386 | */ | ||
| 1387 | retries = 10; | ||
| 1388 | success = 0; | ||
| 1389 | while (retries--) { | ||
| 1390 | struct list_head *head_page, *prev_page, *r; | ||
| 1391 | struct list_head *last_page, *first_page; | ||
| 1392 | struct list_head *head_page_with_bit; | ||
| 1376 | 1393 | ||
| 1377 | for (i = 0; i < nr_pages; i++) { | 1394 | head_page = &rb_set_head_page(cpu_buffer)->list; |
| 1378 | if (RB_WARN_ON(cpu_buffer, list_empty(pages))) | 1395 | prev_page = head_page->prev; |
| 1379 | goto out; | 1396 | |
| 1380 | p = pages->next; | 1397 | first_page = pages->next; |
| 1381 | bpage = list_entry(p, struct buffer_page, list); | 1398 | last_page = pages->prev; |
| 1382 | list_del_init(&bpage->list); | 1399 | |
| 1383 | list_add_tail(&bpage->list, cpu_buffer->pages); | 1400 | head_page_with_bit = (struct list_head *) |
| 1401 | ((unsigned long)head_page | RB_PAGE_HEAD); | ||
| 1402 | |||
| 1403 | last_page->next = head_page_with_bit; | ||
| 1404 | first_page->prev = prev_page; | ||
| 1405 | |||
| 1406 | r = cmpxchg(&prev_page->next, head_page_with_bit, first_page); | ||
| 1407 | |||
| 1408 | if (r == head_page_with_bit) { | ||
| 1409 | /* | ||
| 1410 | * yay, we replaced the page pointer to our new list, | ||
| 1411 | * now, we just have to update to head page's prev | ||
| 1412 | * pointer to point to end of list | ||
| 1413 | */ | ||
| 1414 | head_page->prev = last_page; | ||
| 1415 | success = 1; | ||
| 1416 | break; | ||
| 1417 | } | ||
| 1384 | } | 1418 | } |
| 1385 | rb_reset_cpu(cpu_buffer); | ||
| 1386 | rb_check_pages(cpu_buffer); | ||
| 1387 | 1419 | ||
| 1388 | out: | 1420 | if (success) |
| 1389 | atomic_dec(&cpu_buffer->record_disabled); | 1421 | INIT_LIST_HEAD(pages); |
| 1422 | /* | ||
| 1423 | * If we weren't successful in adding in new pages, warn and stop | ||
| 1424 | * tracing | ||
| 1425 | */ | ||
| 1426 | RB_WARN_ON(cpu_buffer, !success); | ||
| 1390 | raw_spin_unlock_irq(&cpu_buffer->reader_lock); | 1427 | raw_spin_unlock_irq(&cpu_buffer->reader_lock); |
| 1428 | |||
| 1429 | /* free pages if they weren't inserted */ | ||
| 1430 | if (!success) { | ||
| 1431 | struct buffer_page *bpage, *tmp; | ||
| 1432 | list_for_each_entry_safe(bpage, tmp, &cpu_buffer->new_pages, | ||
| 1433 | list) { | ||
| 1434 | list_del_init(&bpage->list); | ||
| 1435 | free_buffer_page(bpage); | ||
| 1436 | } | ||
| 1437 | } | ||
| 1438 | return success; | ||
| 1391 | } | 1439 | } |
| 1392 | 1440 | ||
| 1393 | static void rb_update_pages(struct ring_buffer_per_cpu *cpu_buffer) | 1441 | static void rb_update_pages(struct ring_buffer_per_cpu *cpu_buffer) |
| 1394 | { | 1442 | { |
| 1443 | int success; | ||
| 1444 | |||
| 1395 | if (cpu_buffer->nr_pages_to_update > 0) | 1445 | if (cpu_buffer->nr_pages_to_update > 0) |
| 1396 | rb_insert_pages(cpu_buffer, &cpu_buffer->new_pages, | 1446 | success = rb_insert_pages(cpu_buffer); |
| 1397 | cpu_buffer->nr_pages_to_update); | ||
| 1398 | else | 1447 | else |
| 1399 | rb_remove_pages(cpu_buffer, -cpu_buffer->nr_pages_to_update); | 1448 | success = rb_remove_pages(cpu_buffer, |
| 1449 | -cpu_buffer->nr_pages_to_update); | ||
| 1400 | 1450 | ||
| 1401 | cpu_buffer->nr_pages += cpu_buffer->nr_pages_to_update; | 1451 | if (success) |
| 1452 | cpu_buffer->nr_pages += cpu_buffer->nr_pages_to_update; | ||
| 1402 | } | 1453 | } |
| 1403 | 1454 | ||
| 1404 | static void update_pages_handler(struct work_struct *work) | 1455 | static void update_pages_handler(struct work_struct *work) |
| @@ -3772,6 +3823,7 @@ rb_reset_cpu(struct ring_buffer_per_cpu *cpu_buffer) | |||
| 3772 | cpu_buffer->commit_page = cpu_buffer->head_page; | 3823 | cpu_buffer->commit_page = cpu_buffer->head_page; |
| 3773 | 3824 | ||
| 3774 | INIT_LIST_HEAD(&cpu_buffer->reader_page->list); | 3825 | INIT_LIST_HEAD(&cpu_buffer->reader_page->list); |
| 3826 | INIT_LIST_HEAD(&cpu_buffer->new_pages); | ||
| 3775 | local_set(&cpu_buffer->reader_page->write, 0); | 3827 | local_set(&cpu_buffer->reader_page->write, 0); |
| 3776 | local_set(&cpu_buffer->reader_page->entries, 0); | 3828 | local_set(&cpu_buffer->reader_page->entries, 0); |
| 3777 | local_set(&cpu_buffer->reader_page->page->commit, 0); | 3829 | local_set(&cpu_buffer->reader_page->page->commit, 0); |
