MDEV-40204: Unexpected Linux AIO errors drop the tablespace/subsequent reads fatal#5397
MDEV-40204: Unexpected Linux AIO errors drop the tablespace/subsequent reads fatal#5397grooverdan wants to merge 8 commits into
Conversation
…t reads fatal When a tablespace is dropped for any internal reason, the reading of that tables results in a DB_TABLESPACE_DELETED error. The default handling of this error is a fatal case. The implementaiton is changes to handle the DB_TABLESPACE_DELETED just like a table error DB_TABLE_NOT_FOUND to cleanup, log error, but continue.
This lead to a double release in some cases. fil_space_t::io, the usual caller of os_aio can handle failures and so can buf_dblwr_t::flush_buffered_writes
WIP. Assumptions are being made.
Just returning error to keep buf_page in memory?
Ignore errors here and when time needs to write a proper block it can succeed or fail then.
Coding safety - don't ignore failures of fil_space_t::io() or os_aio().
There was a problem hiding this comment.
Code Review
This pull request adds error handling and unused-result warnings for asynchronous I/O operations across InnoDB's buffer pool flushing and doublewrite buffer mechanisms. The review feedback highlights several critical issues: changing an "if" to "else if" in "fil_space_t::io" can bypass error handling and cause a tablespace reference leak; returning "false" on I/O failure in "buf_page_t::flush" without resetting the page's I/O fix state will permanently lock the page; failing the second of two asynchronous writes in "flush_buffered_writes" can lead to duplicate overlapping writes on retry; and a placeholder comment in "flush_buffered_writes_completed" should be replaced with proper error logging.
Important
The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.
| if (fio.err != DB_SUCCESS) | ||
| return false; |
There was a problem hiding this comment.
If space->io fails and we return false here, the page's I/O fix state (which was set to BUF_IO_WRITE prior to flushing) is left uncleared. Because the asynchronous I/O completion callback will never be called, the page will remain permanently locked in the write-busy state, leading to hangs or deadlocks on subsequent access. You must reset the page's I/O fix state (e.g., using set_io_fix(BUF_IO_NONE)) before returning false.
if (fio.err != DB_SUCCESS)
{
set_io_fix(BUF_IO_NONE);
return false;
}| || os_aio(request, write_buf + (size << srv_page_size_shift), | ||
| os_offset_t{block2.page_no()} << srv_page_size_shift, | ||
| (old_first_free - size) << srv_page_size_shift) | ||
| != DB_SUCCESS) |
There was a problem hiding this comment.
If the first os_aio call succeeds but the second one fails, returning false here is problematic because the first asynchronous write is already in flight. If the caller retries the flush, it may submit a duplicate asynchronous write for the first block, leading to concurrent overlapping writes on the same file descriptor/offset, which can cause data corruption or undefined behavior.
| if (fil.err != DB_SUCCESS) | ||
| { | ||
| // TODO, or cry | ||
| } |
There was a problem hiding this comment.
The placeholder comment // TODO, or cry should be replaced with proper error handling or at least an error log message. If writing to the doublewrite buffer completes but writing to the actual tablespace fails, it is a serious issue that should be logged so that administrators are aware of the I/O failure.
if (fil.err != DB_SUCCESS)
{
sql_print_error("InnoDB: Doublewrite copy to tablespace failed with error %d", fil.err);
}
When a tablespace is dropped for any internal reason, the reading of that tables results in a DB_TABLESPACE_DELETED error.
The default handling of this error is a fatal case.
The implementation is changes to handle the DB_TABLESPACE_DELETED just like a table error DB_TABLE_NOT_FOUND to cleanup, log error, but continue.