core/rawdb: skip setting flushOffset in read-only mode (#31173)

This PR addresses a flaw in the freezer table upgrade path.

In v1.15.0, freezer table v2 was introduced, including an additional 
field (`flushOffset`) maintained in the metadata file. To ensure 
backward compatibility, an upgrade path was implemented for legacy
freezer tables by setting `flushOffset` to the size of the index file.

However, if the freezer table is opened in read-only mode, this file 
write operation is rejected, causing Geth to shut down entirely.

Given that invalid items in the freezer index file can be detected and 
truncated, all items in freezer v0 index files are guaranteed to be
complete. Therefore, when operating in read-only mode, it is safe to
use the  freezer data without performing an upgrade.
This commit is contained in:
rjl493456442 2025-02-13 21:48:03 +08:00 committed by GitHub
parent 8ec4a06b3f
commit 913fee4be9
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
1 changed files with 7 additions and 0 deletions

View File

@ -405,6 +405,13 @@ func (t *freezerTable) repairIndex() error {
// If legacy metadata is detected, attempt to recover the offset from the
// index file to avoid clearing the entire table.
if t.metadata.version == freezerTableV1 {
// Skip truncation if the legacy metadata is opened in read-only mode.
// Since all items in the legacy index file were forcibly synchronized,
// data integrity is guaranteed. Therefore, it's safe to leave any extra
// items untruncated in this special scenario.
if t.readonly {
return nil
}
t.logger.Info("Recovering freezer flushOffset for legacy table", "offset", size)
return t.metadata.setFlushOffset(size, true)
}