Bug #121250 Fil_shard::do_io() skips complete_io() on DB_PAGE_IS_STALE after prepare_file_for_io()
Submitted: 9 Sep 15:52
Reporter: Marcin Babij (OCA) Email Updates:
Status: Open Impact on me:
None 
Category:MySQL Server: InnoDB storage engine Severity:S3 (Non-critical)
Version:8.0.49, 8.4.12, 9.7.3 OS:Any
Assigned to: CPU Architecture:Any

[9 Sep 15:52] Marcin Babij
Description:
Related to Bug#39244016. That fix is already in 8.0/8.4/9.7/trunk. A second bug remains on 8.0, 8.4, and 9.7:
Fil_shard::prepare_file_for_io() increments fil_node_t::n_pending_ios. After it succeeds, every return from Fil_shard::do_io() must call Fil_shard::complete_io() to decrement that counter (and put the file back on the LRU when it hits 0). The ignore_missing() path already does complete_io() + mutex_release().
However, the write path for a stale page whose page_no is past file->size (tablespace truncated while dirty pages remain in the buffer pool) still does only mutex_release() and return DB_PAGE_IS_STALE. n_pending_ios stays elevated and the file never returns to the LRU - later close/truncate/open-file-limit handling can hang.
Trunk is not affected - WL#15464 rewrote do_io() so a complete_io_and_postprocess_result guard always runs after prepare_file_for_io(), including this stale write.
I will attach:
- io_complete_8.0.patch — production complete_io() plus MTR test (applies to current 8.0; same logic on 8.4/9.7)
- io_complete_trunk.patch — MTR test + DEBUG_SYNC only for trunk for regression testing.

How to repeat:
MTR test innodb.tablespace_truncate_fil_shard (in the attached patches).
It dirties pages in a session temporary table, forces the session temp file closed via innodb_set_open_files_limit(15) and many donor tables, then races SET GLOBAL innodb_buf_flush_list_now=ON with disconnect (ibt::Tablespace_pool::free_ts -> fil_truncate_tablespace). DEBUG_SYNC stops in Fil_shard::open_file after FIL_SHARD is released because the open-files right could not be acquired.
Without complete_io() (8.0/8.4/9.7): the flush thread hits the stale page after prepare_file_for_io() and the test hangs (n_pending_ios leak / file not closable).

Suggested fix:
In Fil_shard::do_io(), on the DB_PAGE_IS_STALE return after prepare_file_for_io() succeeded, call complete_io(file, req_type) before mutex_release(), matching the adjacent ignore_missing() path.
[9 Sep 15:53] Marcin Babij
8.0 patch

Attachment: io_complete_8.0.patch (text/x-patch), 4.55 KiB.

[9 Sep 15:54] Marcin Babij
trunk test

Attachment: io_complete_trunk.patch (text/x-patch), 3.82 KiB.