From e5e840ff1f9bc67153a1d3aa90b6a86455fc3ffa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Thu, 13 Aug 2026 08:28:49 +0300 Subject: [PATCH] MDEV-40728 Recovery wrongly fails if FILE_CREATE is followed by FILE_RENAME fil_name_process(): Simplify the logic. If no matching tablespace is found but file_name_t::create_lsn had been set in response to parsing a FILE_CREATE record, try to apply FILE_RENAME to deferred_spaces. deferred_spaces.deferred_dblwr(): Skip newly created tablespaces to avoid a bogus invocation of fil_space_free(). --- storage/innobase/log/log0recv.cc | 61 ++++++++++++++++++-------------- 1 file changed, 34 insertions(+), 27 deletions(-) diff --git a/storage/innobase/log/log0recv.cc b/storage/innobase/log/log0recv.cc index f82556d3f3ba9..ccac65924db1f 100644 --- a/storage/innobase/log/log0recv.cc +++ b/storage/innobase/log/log0recv.cc @@ -937,6 +937,18 @@ static struct d++; continue; } + else + { + recv_spaces_t::iterator it{recv_spaces.find(d->first)}; + if (UNIV_UNLIKELY(it == recv_spaces.end())) + ut_ad("inconsistent data structures" == 0); + else if (it->second.create_lsn) + /* + Because a FILE_CREATE record exists, the entire file must + be recoverable via log records. + */ + goto next_item; + } const page_id_t page_id{d->first, 0}; const byte *page= recv_sys.dblwr.find_page(page_id, max_lsn); if (!page) @@ -1322,19 +1334,14 @@ static void fil_name_process(const char *name, ulint len, uint32_t space_id, ut_ad(p.first->first == space_id); file_name_t& f = p.first->second; - + ut_ad(!f.space || f.space->id == space_id); auto d = deferred_spaces.find(space_id); - if (d) { - if (deleted) { - d->deleted = true; - goto got_deleted; - } - goto reload; - } if (deleted) { -got_deleted: /* Got FILE_DELETE */ + if (d) { + d->deleted = true; + } if (!p.second && f.status != file_name_t::DELETED) { f.status = file_name_t::DELETED; if (f.space != NULL) { @@ -1344,10 +1351,9 @@ static void fil_name_process(const char *name, ulint len, uint32_t space_id, } ut_ad(f.space == NULL); - goto reset_create; - } else if (p.second // the first FILE_MODIFY or FILE_RENAME + f.create_lsn = 0; + } else if (d || p.second /* the first FILE_MODIFY or FILE_RENAME */ || f.name != fname.name) { -reload: if (f.name.size() == 0) { /* Augment the recv_spaces.emplace_hint() for the FILE_MODIFY record that had been added by @@ -1361,7 +1367,8 @@ static void fil_name_process(const char *name, ulint len, uint32_t space_id, the space_id. If not, ignore the file after displaying a note. Abort if there are multiple files with the same space_id. */ - switch (fil_ibd_load(space_id, fname.name.c_str(), space)) { + switch (fil_load_status s + = fil_ibd_load(space_id, fname.name.c_str(), space)) { case FIL_LOAD_OK: ut_ad(space != NULL); @@ -1396,25 +1403,28 @@ static void fil_name_process(const char *name, ulint len, uint32_t space_id, break; case FIL_LOAD_ID_CHANGED: - ut_ad(space == NULL); - break; - case FIL_LOAD_NOT_FOUND: /* No matching tablespace was found; maybe it was renamed, and we will find a subsequent FILE_* record. */ ut_ad(space == NULL); - if (srv_operation == SRV_OPERATION_RESTORE && d - && ftype == FILE_RENAME) { + if (f.create_lsn) { + if (d && ftype == FILE_RENAME) { rename: - d->file_name = fname.name; - f.name = fname.name; + d->file_name = fname.name; + f.name = fname.name; + } break; } - if (f.create_lsn) { - return; + if (ftype == FILE_CREATE) { + f.create_lsn = lsn; + break; + } + + if (s == FIL_LOAD_ID_CHANGED) { + break; } if (srv_force_recovery @@ -1434,11 +1444,10 @@ static void fil_name_process(const char *name, ulint len, uint32_t space_id, int(fname.name.size()), fname.name.data(), space_id); } - return; + break; case FIL_LOAD_DEFER: - if (d && ftype == FILE_RENAME - && srv_operation == SRV_OPERATION_RESTORE) { + if (d && ftype == FILE_RENAME && f.create_lsn) { goto rename; } /* Skip the deferred spaces @@ -1470,8 +1479,6 @@ static void fil_name_process(const char *name, ulint len, uint32_t space_id, " due to innodb_force_recovery", int(len), name, space_id); } -reset_create: - f.create_lsn = 0; } else if (ftype == FILE_CREATE && !f.space) { f.create_lsn = lsn; }