Skip to content

Commit 326fa00

Browse files
authored
core/rawdb: fsync the index file after each freezer write (#28483)
* core/rawdb: fsync the index and data file after each freezer write * core/rawdb: fsync the data file in freezer after write
1 parent e38b9f1 commit 326fa00

File tree

4 files changed

+28
-10
lines changed

4 files changed

+28
-10
lines changed

core/rawdb/ancient_utils.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ package rawdb
1818

1919
import (
2020
"fmt"
21+
"path/filepath"
2122

2223
"github.com/ethereum/go-ethereum/common"
2324
"github.com/ethereum/go-ethereum/ethdb"
@@ -126,6 +127,8 @@ func InspectFreezerTable(ancient string, freezerName string, tableName string, s
126127
switch freezerName {
127128
case chainFreezerName:
128129
path, tables = resolveChainFreezerDir(ancient), chainFreezerNoSnappy
130+
case stateFreezerName:
131+
path, tables = filepath.Join(ancient, freezerName), stateFreezerNoSnappy
129132
default:
130133
return fmt.Errorf("unknown freezer, supported ones: %v", freezers)
131134
}

core/rawdb/freezer_batch.go

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -182,19 +182,27 @@ func (batch *freezerTableBatch) maybeCommit() error {
182182

183183
// commit writes the batched items to the backing freezerTable.
184184
func (batch *freezerTableBatch) commit() error {
185-
// Write data.
185+
// Write data. The head file is fsync'd after write to ensure the
186+
// data is truly transferred to disk.
186187
_, err := batch.t.head.Write(batch.dataBuffer)
187188
if err != nil {
188189
return err
189190
}
191+
if err := batch.t.head.Sync(); err != nil {
192+
return err
193+
}
190194
dataSize := int64(len(batch.dataBuffer))
191195
batch.dataBuffer = batch.dataBuffer[:0]
192196

193-
// Write indices.
197+
// Write indices. The index file is fsync'd after write to ensure the
198+
// data indexes are truly transferred to disk.
194199
_, err = batch.t.index.Write(batch.indexBuffer)
195200
if err != nil {
196201
return err
197202
}
203+
if err := batch.t.index.Sync(); err != nil {
204+
return err
205+
}
198206
indexSize := int64(len(batch.indexBuffer))
199207
batch.indexBuffer = batch.indexBuffer[:0]
200208

core/rawdb/freezer_table.go

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -215,7 +215,9 @@ func (t *freezerTable) repair() error {
215215
if t.readonly {
216216
return fmt.Errorf("index file(path: %s, name: %s) size is not a multiple of %d", t.path, t.name, indexEntrySize)
217217
}
218-
truncateFreezerFile(t.index, stat.Size()-overflow) // New file can't trigger this path
218+
if err := truncateFreezerFile(t.index, stat.Size()-overflow); err != nil {
219+
return err
220+
} // New file can't trigger this path
219221
}
220222
// Retrieve the file sizes and prepare for truncation
221223
if stat, err = t.index.Stat(); err != nil {
@@ -260,8 +262,8 @@ func (t *freezerTable) repair() error {
260262
// Print an error log if the index is corrupted due to an incorrect
261263
// last index item. While it is theoretically possible to have a zero offset
262264
// by storing all zero-size items, it is highly unlikely to occur in practice.
263-
if lastIndex.offset == 0 && offsetsSize%indexEntrySize > 1 {
264-
log.Error("Corrupted index file detected", "lastOffset", lastIndex.offset, "items", offsetsSize%indexEntrySize-1)
265+
if lastIndex.offset == 0 && offsetsSize/indexEntrySize > 1 {
266+
log.Error("Corrupted index file detected", "lastOffset", lastIndex.offset, "indexes", offsetsSize/indexEntrySize)
265267
}
266268
if t.readonly {
267269
t.head, err = t.openFile(lastIndex.filenum, openFreezerFileForReadOnly)
@@ -416,6 +418,9 @@ func (t *freezerTable) truncateHead(items uint64) error {
416418
if err := truncateFreezerFile(t.index, int64(length+1)*indexEntrySize); err != nil {
417419
return err
418420
}
421+
if err := t.index.Sync(); err != nil {
422+
return err
423+
}
419424
// Calculate the new expected size of the data file and truncate it
420425
var expected indexEntry
421426
if length == 0 {
@@ -438,13 +443,17 @@ func (t *freezerTable) truncateHead(items uint64) error {
438443
// Release any files _after the current head -- both the previous head
439444
// and any files which may have been opened for reading
440445
t.releaseFilesAfter(expected.filenum, true)
446+
441447
// Set back the historic head
442448
t.head = newHead
443449
t.headId = expected.filenum
444450
}
445451
if err := truncateFreezerFile(t.head, int64(expected.offset)); err != nil {
446452
return err
447453
}
454+
if err := t.head.Sync(); err != nil {
455+
return err
456+
}
448457
// All data files truncated, set internal counters and return
449458
t.headBytes = int64(expected.offset)
450459
t.items.Store(items)
@@ -589,10 +598,12 @@ func (t *freezerTable) Close() error {
589598
// error on Windows.
590599
doClose(t.index, true, true)
591600
doClose(t.meta, true, true)
601+
592602
// The preopened non-head data-files are all opened in readonly.
593603
// The head is opened in rw-mode, so we sync it here - but since it's also
594604
// part of t.files, it will be closed in the loop below.
595605
doClose(t.head, true, false) // sync but do not close
606+
596607
for _, f := range t.files {
597608
doClose(f, false, true) // close but do not sync
598609
}

core/rawdb/freezer_utils.go

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -73,11 +73,7 @@ func copyFrom(srcPath, destPath string, offset uint64, before func(f *os.File) e
7373
return err
7474
}
7575
f = nil
76-
77-
if err := os.Rename(fname, destPath); err != nil {
78-
return err
79-
}
80-
return nil
76+
return os.Rename(fname, destPath)
8177
}
8278

8379
// openFreezerFileForAppend opens a freezer table file and seeks to the end

0 commit comments

Comments
 (0)