Fixes #2039
This PR allows node operators to set file permissions on finalized blk files to be read-only.
Generally, we assume that the node can write to anything within the data directory. But, in this case, the finalized blk files don't need to be written to again. So, it might be useful to be able to set them as read-only.
This only makes sense with finalized block files as blk files that have logical space under the 128 MiB limit need to be writable for appending additional blocks.
Using read-only permissions had caused a problem while using -reindex because there was an unnecessary flush being performed on unmodified blk files within BlockManager::FlushBlockFile.
The flush would show up in logs in two ways:
2022-11-19T14:26:57Z [loadblk] Loaded 119965 blocks from external file in 3868921ms
2022-11-19T14:26:57Z [loadblk] Reindexing block file blk00001.dat...
2022-11-19T14:26:57Z [loadblk] Unable to open file /tmp/btc/blocks/blk00000.dat
2022-11-19T14:26:57Z [loadblk] ERROR: Flush: failed to open file 0
2022-11-19T14:26:57Z [loadblk] *** Flushing block file to disk failed. This is likely the result of an I/O error.
2022-11-19T14:26:57Z [loadblk] Error: A fatal internal error occurred, see debug.log for details
or
2022-11-19T13:17:59Z [loadblk] [bench] FlushStateToDisk: write block and undo data to disk started
2022-11-19T13:17:59Z [loadblk] Unable to open file /tmp/btc/blocks/blk00000.dat
2022-11-19T13:17:59Z [loadblk] ERROR: Flush: failed to open file 0
2022-11-19T13:17:59Z [loadblk] *** Flushing block file to disk failed. This is likely the result of an I/O error.
2022-11-19T13:17:59Z [loadblk] Error: A fatal internal error occurred, see debug.log for details
2022-11-19T13:18:14Z [loadblk] [bench] FlushStateToDisk: write block and undo data to disk completed (15582.56ms)
2022-11-19T13:18:14Z [loadblk] [bench] FlushStateToDisk: write block index to disk started
2022-11-19T13:18:14Z [loadblk] [leveldb] WriteBatch memory usage: db=index, before=0.0MiB, after=0.0MiB
2022-11-19T13:18:14Z [loadblk] [bench] FlushStateToDisk: write block index to disk completed (4.38ms)
To test these changes, you can grab some linearized test blk files over at https://github.com/mruddy/test_blk_files You only need to import a handful of the files to test that the flush doesn't cause the problem anymore.
Once you have the files, setup with:
mkdir -p /tmp/btc && ./src/qt/bitcoin-qt -debug -logthreadnames -datadir=/tmp/btc -loadblock=/readonly/btc/main/blk{00000..00005}.dat -connect=0
When those are done importing, stop the node and run
chmod 0400 /tmp/btc/blocks/blk00000.dat
Finally, start the node again, and this time run the reindex and verify that the failure does not occur as will occur without this PR's patch.
./src/qt/bitcoin-qt -debug -logthreadnames -datadir=/tmp/btc -reindex -connect=0