@@ -1046,42 +1046,52 @@ static page_id_t buf_flush_check_neighbors(const fil_space_t &space,
1046
1046
return i;
1047
1047
}
1048
1048
1049
- MY_ATTRIBUTE ((nonnull))
1049
+ MY_ATTRIBUTE ((nonnull, warn_unused_result ))
1050
1050
/* * Write punch-hole or zeroes of the freed ranges when
1051
1051
innodb_immediate_scrub_data_uncompressed from the freed ranges.
1052
- @param space tablespace which may contain ranges of freed pages */
1053
- static void buf_flush_freed_pages(fil_space_t *space)
1052
+ @param space tablespace which may contain ranges of freed pages
1053
+ @param writable whether the tablespace is writable
1054
+ @return number of pages written or hole-punched */
1055
+ static uint32_t buf_flush_freed_pages(fil_space_t *space, bool writable)
1054
1056
{
1055
1057
const bool punch_hole= space->punch_hole ;
1056
- if (!srv_immediate_scrub_data_uncompressed && !punch_hole)
1057
- return ;
1058
- lsn_t flush_to_disk_lsn= log_sys.get_flushed_lsn ();
1058
+ if (!punch_hole && !srv_immediate_scrub_data_uncompressed)
1059
+ return 0 ;
1060
+
1061
+ mysql_mutex_assert_not_owner (&buf_pool.flush_list_mutex );
1062
+ mysql_mutex_assert_not_owner (&buf_pool.mutex );
1059
1063
1060
- std::unique_lock<std::mutex> freed_lock ( space->freed_range_mutex );
1061
- if (space->freed_ranges .empty ()
1062
- || flush_to_disk_lsn < space->get_last_freed_lsn ())
1064
+ space->freed_range_mutex . lock ( );
1065
+ if (space->freed_ranges .empty () ||
1066
+ log_sys. get_flushed_lsn () < space->get_last_freed_lsn ())
1063
1067
{
1064
- freed_lock .unlock ();
1065
- return ;
1068
+ space-> freed_range_mutex .unlock ();
1069
+ return 0 ;
1066
1070
}
1067
1071
1072
+ const unsigned physical_size{space->physical_size ()};
1073
+
1068
1074
range_set freed_ranges= std::move (space->freed_ranges );
1069
- freed_lock. unlock () ;
1075
+ uint32_t written= 0 ;
1070
1076
1071
- for (const auto &range : freed_ranges)
1077
+ if (!writable);
1078
+ else if (punch_hole)
1072
1079
{
1073
- const ulint physical_size= space->physical_size ();
1074
-
1075
- if (punch_hole)
1080
+ for (const auto &range : freed_ranges)
1076
1081
{
1082
+ written+= range.last - range.first + 1 ;
1077
1083
space->reacquire ();
1078
1084
space->io (IORequest (IORequest::PUNCH_RANGE),
1079
1085
os_offset_t {range.first } * physical_size,
1080
1086
(range.last - range.first + 1 ) * physical_size,
1081
1087
nullptr );
1082
1088
}
1083
- else if (srv_immediate_scrub_data_uncompressed)
1089
+ }
1090
+ else
1091
+ {
1092
+ for (const auto &range : freed_ranges)
1084
1093
{
1094
+ written+= range.last - range.first + 1 ;
1085
1095
for (os_offset_t i= range.first ; i <= range.last ; i++)
1086
1096
{
1087
1097
space->reacquire ();
@@ -1090,8 +1100,10 @@ static void buf_flush_freed_pages(fil_space_t *space)
1090
1100
const_cast <byte*>(field_ref_zero));
1091
1101
}
1092
1102
}
1093
- buf_pool.stat .n_pages_written += (range.last - range.first + 1 );
1094
1103
}
1104
+
1105
+ space->freed_range_mutex .unlock ();
1106
+ return written;
1095
1107
}
1096
1108
1097
1109
/* * Flushes to disk all flushable pages within the flush area
@@ -1213,14 +1225,12 @@ static ulint buf_free_from_unzip_LRU_list_batch(ulint max)
1213
1225
1214
1226
/* * Start writing out pages for a tablespace.
1215
1227
@param id tablespace identifier
1216
- @return tablespace
1217
- @retval nullptr if the pages for this tablespace should be discarded */
1218
- static fil_space_t *buf_flush_space (const uint32_t id)
1228
+ @return tablespace and number of pages written */
1229
+ static std::pair<fil_space_t *, uint32_t > buf_flush_space (const uint32_t id)
1219
1230
{
1220
- fil_space_t *space= fil_space_t::get (id);
1221
- if (space)
1222
- buf_flush_freed_pages (space);
1223
- return space;
1231
+ if (fil_space_t *space= fil_space_t::get (id))
1232
+ return {space, buf_flush_freed_pages (space, true )};
1233
+ return {nullptr , 0 };
1224
1234
}
1225
1235
1226
1236
struct flush_counters_t
@@ -1288,6 +1298,7 @@ static void buf_flush_LRU_list_batch(ulint max, flush_counters_t *n)
1288
1298
n->flushed + n->evicted < max) ||
1289
1299
recv_recovery_is_on ()); ++scanned)
1290
1300
{
1301
+ retry:
1291
1302
buf_page_t *prev= UT_LIST_GET_PREV (LRU, bpage);
1292
1303
const lsn_t oldest_modification= bpage->oldest_modification ();
1293
1304
buf_pool.lru_hp .set (prev);
@@ -1309,10 +1320,18 @@ static void buf_flush_LRU_list_batch(ulint max, flush_counters_t *n)
1309
1320
{
1310
1321
if (last_space_id != space_id)
1311
1322
{
1323
+ buf_pool.lru_hp .set (bpage);
1324
+ mysql_mutex_unlock (&buf_pool.mutex );
1312
1325
if (space)
1313
1326
space->release ();
1314
- space= buf_flush_space (space_id);
1327
+ auto p= buf_flush_space (space_id);
1328
+ space= p.first ;
1315
1329
last_space_id= space_id;
1330
+ mysql_mutex_lock (&buf_pool.mutex );
1331
+ if (p.second )
1332
+ buf_pool.stat .n_pages_written += p.second ;
1333
+ bpage= buf_pool.lru_hp .get ();
1334
+ goto retry;
1316
1335
}
1317
1336
else
1318
1337
ut_ad (!space);
@@ -1455,10 +1474,28 @@ static ulint buf_do_flush_list_batch(ulint max_n, lsn_t lsn)
1455
1474
{
1456
1475
if (last_space_id != space_id)
1457
1476
{
1477
+ mysql_mutex_lock (&buf_pool.flush_list_mutex );
1478
+ buf_pool.flush_hp .set (bpage);
1479
+ mysql_mutex_unlock (&buf_pool.flush_list_mutex );
1480
+ mysql_mutex_unlock (&buf_pool.mutex );
1458
1481
if (space)
1459
1482
space->release ();
1460
- space= buf_flush_space (space_id);
1483
+ auto p= buf_flush_space (space_id);
1484
+ space= p.first ;
1461
1485
last_space_id= space_id;
1486
+ mysql_mutex_lock (&buf_pool.mutex );
1487
+ if (p.second )
1488
+ buf_pool.stat .n_pages_written += p.second ;
1489
+ mysql_mutex_lock (&buf_pool.flush_list_mutex );
1490
+ bpage= buf_pool.flush_hp .get ();
1491
+ if (!bpage)
1492
+ break ;
1493
+ if (bpage->id () != page_id)
1494
+ continue ;
1495
+ buf_pool.flush_hp .set (UT_LIST_GET_PREV (list, bpage));
1496
+ if (bpage->oldest_modification () <= 1 || !bpage->ready_for_flush ())
1497
+ goto next;
1498
+ mysql_mutex_unlock (&buf_pool.flush_list_mutex );
1462
1499
}
1463
1500
else
1464
1501
ut_ad (!space);
@@ -1486,6 +1523,7 @@ static ulint buf_do_flush_list_batch(ulint max_n, lsn_t lsn)
1486
1523
}
1487
1524
1488
1525
mysql_mutex_lock (&buf_pool.flush_list_mutex );
1526
+ next:
1489
1527
bpage= buf_pool.flush_hp .get ();
1490
1528
}
1491
1529
@@ -1582,11 +1620,14 @@ bool buf_flush_list_space(fil_space_t *space, ulint *n_flushed)
1582
1620
bool may_have_skipped= false ;
1583
1621
ulint max_n_flush= srv_io_capacity;
1584
1622
1585
- mysql_mutex_lock (&buf_pool.mutex );
1586
- mysql_mutex_lock (&buf_pool.flush_list_mutex );
1587
-
1588
1623
bool acquired= space->acquire ();
1589
- buf_flush_freed_pages (space);
1624
+ {
1625
+ const uint32_t written{buf_flush_freed_pages (space, acquired)};
1626
+ mysql_mutex_lock (&buf_pool.mutex );
1627
+ if (written)
1628
+ buf_pool.stat .n_pages_written += written;
1629
+ }
1630
+ mysql_mutex_lock (&buf_pool.flush_list_mutex );
1590
1631
1591
1632
for (buf_page_t *bpage= UT_LIST_GET_LAST (buf_pool.flush_list ); bpage; )
1592
1633
{
0 commit comments