@@ -1252,7 +1252,7 @@ static inline unsigned long rb_page_write(struct buffer_page *bpage)
12521252 return local_read (& bpage -> write ) & RB_WRITE_MASK ;
12531253}
12541254
1255- static void
1255+ static int
12561256rb_remove_pages (struct ring_buffer_per_cpu * cpu_buffer , unsigned int nr_pages )
12571257{
12581258 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)
13591359 } while (to_remove_page != last_page );
13601360
13611361 RB_WARN_ON (cpu_buffer , nr_removed );
1362+
1363+ return nr_removed == 0 ;
13621364}
13631365
1364- static void
1365- rb_insert_pages (struct ring_buffer_per_cpu * cpu_buffer ,
1366- struct list_head * pages , unsigned nr_pages )
1366+ static int
1367+ rb_insert_pages (struct ring_buffer_per_cpu * cpu_buffer )
13671368{
1368- struct buffer_page * bpage ;
1369- struct list_head * p ;
1370- unsigned i ;
1369+ struct list_head * pages = & cpu_buffer -> new_pages ;
1370+ int retries , success ;
13711371
13721372 raw_spin_lock_irq (& cpu_buffer -> reader_lock );
1373- /* stop the writers while inserting pages */
1374- atomic_inc (& cpu_buffer -> record_disabled );
1375- rb_head_page_deactivate (cpu_buffer );
1373+ /*
1374+ * We are holding the reader lock, so the reader page won't be swapped
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 ;
13761393
1377- for (i = 0 ; i < nr_pages ; i ++ ) {
1378- if (RB_WARN_ON (cpu_buffer , list_empty (pages )))
1379- goto out ;
1380- p = pages -> next ;
1381- bpage = list_entry (p , struct buffer_page , list );
1382- list_del_init (& bpage -> list );
1383- list_add_tail (& bpage -> list , cpu_buffer -> pages );
1394+ head_page = & rb_set_head_page (cpu_buffer )-> list ;
1395+ prev_page = head_page -> prev ;
1396+
1397+ first_page = pages -> next ;
1398+ last_page = pages -> prev ;
1399+
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+ }
13841418 }
1385- rb_reset_cpu (cpu_buffer );
1386- rb_check_pages (cpu_buffer );
13871419
1388- out :
1389- atomic_dec (& cpu_buffer -> record_disabled );
1420+ if (success )
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 );
13901427 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 ;
13911439}
13921440
13931441static void rb_update_pages (struct ring_buffer_per_cpu * cpu_buffer )
13941442{
1443+ int success ;
1444+
13951445 if (cpu_buffer -> nr_pages_to_update > 0 )
1396- rb_insert_pages (cpu_buffer , & cpu_buffer -> new_pages ,
1397- cpu_buffer -> nr_pages_to_update );
1446+ success = rb_insert_pages (cpu_buffer );
13981447 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 );
14001450
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 ;
14021453}
14031454
14041455static void update_pages_handler (struct work_struct * work )
@@ -3772,6 +3823,7 @@ rb_reset_cpu(struct ring_buffer_per_cpu *cpu_buffer)
37723823 cpu_buffer -> commit_page = cpu_buffer -> head_page ;
37733824
37743825 INIT_LIST_HEAD (& cpu_buffer -> reader_page -> list );
3826+ INIT_LIST_HEAD (& cpu_buffer -> new_pages );
37753827 local_set (& cpu_buffer -> reader_page -> write , 0 );
37763828 local_set (& cpu_buffer -> reader_page -> entries , 0 );
37773829 local_set (& cpu_buffer -> reader_page -> page -> commit , 0 );
0 commit comments