Skip to content

Commit 69ddee6

Browse files
committed
Merge bitcoin/bitcoin#27039: blockstorage: do not flush block to disk if it is already there
dfcef53 blockstorage: do not flush block to disk if it is already there (Matthew Zipkin) Pull request description: Closes bitcoin/bitcoin#2039 When reindexing from flat-file block storage there is no need to write anything back to disk, since the block data is already there. This PR skips flushing to disk those blocks that already have a known position in the datastore. Skipping this means that users can write-protect the `blk` files on disk which may be useful for security or even safely sharing that data between multiple bitcoind instances. `FindBlockPos()` may also flush the undo data file, but again this is skipped if the corresponding block position is known, like during the initial stage of a reindex when block data is being indexed. Once the block index is complete the validation mechanism will call `ConnectBlock()` which will save undo data at that time. The call stack looks like this: ``` init() ThreadImport() <-- process fReindex flag LoadExternalBlockFile() AcceptBlock() SaveBlockToDisk() FindBlockPos() FlushBlockFile() <-- unnecessary if block is already on disk ``` A larger refactor of this part of the code was started by mzumsande here: https://github.com/mzumsande/bitcoin/tree/202207_refactor_findblockpos including this fix, reviewers can let me know if the changes should be combined. ACKs for top commit: sipa: utACK dfcef53 mzumsande: re-ACK dfcef53 achow101: ACK dfcef53 furszy: Rebase diff ACK dfcef53. Tree-SHA512: 385c5ac1288b325135398d0ddd3ab788fa98cc0ca19bd2474c74039f2ce70d5088c1d1c9d4dd10aefcbd4c757767ec5805d07ba8cee9289a66f96e6f9eaa5279
2 parents 0b96a19 + dfcef53 commit 69ddee6

File tree

2 files changed

+17
-16
lines changed

2 files changed

+17
-16
lines changed

src/node/blockstorage.cpp

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -906,19 +906,19 @@ bool BlockManager::FindBlockPos(FlatFilePos& pos, unsigned int nAddSize, unsigne
906906
if (!fKnown) {
907907
LogPrint(BCLog::BLOCKSTORAGE, "Leaving block file %i: %s (onto %i) (height %i)\n",
908908
last_blockfile, m_blockfile_info[last_blockfile].ToString(), nFile, nHeight);
909-
}
910909

911-
// Do not propagate the return code. The flush concerns a previous block
912-
// and undo file that has already been written to. If a flush fails
913-
// here, and we crash, there is no expected additional block data
914-
// inconsistency arising from the flush failure here. However, the undo
915-
// data may be inconsistent after a crash if the flush is called during
916-
// a reindex. A flush error might also leave some of the data files
917-
// untrimmed.
918-
if (!FlushBlockFile(last_blockfile, !fKnown, finalize_undo)) {
919-
LogPrintLevel(BCLog::BLOCKSTORAGE, BCLog::Level::Warning,
920-
"Failed to flush previous block file %05i (finalize=%i, finalize_undo=%i) before opening new block file %05i\n",
921-
last_blockfile, !fKnown, finalize_undo, nFile);
910+
// Do not propagate the return code. The flush concerns a previous block
911+
// and undo file that has already been written to. If a flush fails
912+
// here, and we crash, there is no expected additional block data
913+
// inconsistency arising from the flush failure here. However, the undo
914+
// data may be inconsistent after a crash if the flush is called during
915+
// a reindex. A flush error might also leave some of the data files
916+
// untrimmed.
917+
if (!FlushBlockFile(last_blockfile, !fKnown, finalize_undo)) {
918+
LogPrintLevel(BCLog::BLOCKSTORAGE, BCLog::Level::Warning,
919+
"Failed to flush previous block file %05i (finalize=%i, finalize_undo=%i) before opening new block file %05i\n",
920+
last_blockfile, !fKnown, finalize_undo, nFile);
921+
}
922922
}
923923
// No undo data yet in the new file, so reset our undo-height tracking.
924924
m_blockfile_cursors[chain_type] = BlockfileCursor{nFile};

test/functional/feature_reindex_readonly.py

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ def reindex_readonly(self):
2424
opreturn = "6a"
2525
nulldata = fastprune_blockfile_size * "ff"
2626
self.generateblock(self.nodes[0], output=f"raw({opreturn}{nulldata})", transactions=[])
27+
block_count = self.nodes[0].getblockcount()
2728
self.stop_node(0)
2829

2930
assert (self.nodes[0].chain_path / "blocks" / "blk00000.dat").exists()
@@ -73,10 +74,10 @@ def reindex_readonly(self):
7374
pass
7475

7576
if undo_immutable:
76-
self.log.info("Attempt to restart and reindex the node with the unwritable block file")
77-
with self.nodes[0].assert_debug_log(expected_msgs=['FlushStateToDisk', 'failed to open file'], unexpected_msgs=[]):
78-
self.nodes[0].assert_start_raises_init_error(extra_args=['-reindex', '-fastprune'],
79-
expected_msg="Error: A fatal internal error occurred, see debug.log for details")
77+
self.log.debug("Attempt to restart and reindex the node with the unwritable block file")
78+
with self.nodes[0].wait_for_debug_log([b"Reindexing finished"]):
79+
self.start_node(0, extra_args=['-reindex', '-fastprune'])
80+
assert block_count == self.nodes[0].getblockcount()
8081
undo_immutable()
8182

8283
filename.chmod(0o777)

0 commit comments

Comments
 (0)