Skip to content

Commit

Permalink
init: Take lock on blocks directory in BlockManager ctor
Browse files Browse the repository at this point in the history
  • Loading branch information
TheCharlatan committed Feb 13, 2025
1 parent 9b37088 commit 1ba7ff6
Show file tree
Hide file tree
Showing 4 changed files with 41 additions and 6 deletions.
5 changes: 3 additions & 2 deletions src/init.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1109,8 +1109,9 @@ static bool LockDirectory(const fs::path& dir, bool probeOnly)
}
static bool LockDirectories(bool probeOnly)
{
return LockDirectory(gArgs.GetDataDirNet(), probeOnly) && \
LockDirectory(gArgs.GetBlocksDirPath(), probeOnly);
// Only allow probing the blocks directory, the BlockManager takes the lock internally.
return LockDirectory(gArgs.GetDataDirNet(), probeOnly) &&
(probeOnly ? LockDirectory(gArgs.GetBlocksDirPath(), probeOnly) : true);
}

bool AppInitSanityChecks(const kernel::Context& kernel)
Expand Down
7 changes: 4 additions & 3 deletions src/init/common.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -117,9 +117,10 @@ bool StartLogging(const ArgsManager& args)
}

if (!LogInstance().m_log_timestamps)
LogPrintf("Startup time: %s\n", FormatISO8601DateTime(GetTime()));
LogPrintf("Default data directory %s\n", fs::PathToString(GetDefaultDataDir()));
LogPrintf("Using data directory %s\n", fs::PathToString(gArgs.GetDataDirNet()));
LogInfo("Startup time: %s", FormatISO8601DateTime(GetTime()));
LogInfo("Default data directory %s", fs::PathToString(GetDefaultDataDir()));
LogInfo("Using data directory %s", fs::PathToString(gArgs.GetDataDirNet()));
LogInfo("Using blocks directory %s", fs::PathToString(gArgs.GetBlocksDirPath()));

// Only log conf file usage message if conf file actually exists.
fs::path config_file_path = args.GetConfigFilePath();
Expand Down
26 changes: 25 additions & 1 deletion src/node/blockstorage.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@

#include <node/blockstorage.h>

#include <bitcoin-build-config.h> // IWYU pragma: keep

#include <arith_uint256.h>
#include <chain.h>
#include <consensus/params.h>
Expand Down Expand Up @@ -31,6 +33,7 @@
#include <util/batchpriority.h>
#include <util/check.h>
#include <util/fs.h>
#include <util/fs_helpers.h>
#include <util/signalinterrupt.h>
#include <util/strencodings.h>
#include <util/translation.h>
Expand Down Expand Up @@ -1164,8 +1167,29 @@ static auto InitBlocksdirXorKey(const BlockManager::Options& opts)
return std::vector<std::byte>{xor_key.begin(), xor_key.end()};
}

BlockDirLock::BlockDirLock(const fs::path& blocks_dir)
: m_path{blocks_dir}
{
// Make sure only a single BlockManager is using the blocks directory.
switch (util::LockDirectory(blocks_dir, ".lock", false)) {
case util::LockResult::ErrorWrite:
throw std::runtime_error(strprintf(_("Cannot write to block directory '%s'; check permissions."), fs::PathToString(blocks_dir)).original);
case util::LockResult::ErrorLock:
throw std::runtime_error(strprintf(_("Cannot obtain a lock on block directory %s. %s is probably already running."), fs::PathToString(blocks_dir), CLIENT_NAME).original);
case util::LockResult::Success:
return;
} // no default case, so the compiler can warn about missing cases
assert(false);
}

BlockDirLock::~BlockDirLock()
{
UnlockDirectory(m_path, ".lock");
}

BlockManager::BlockManager(const util::SignalInterrupt& interrupt, Options opts)
: m_prune_mode{opts.prune_target > 0},
: m_lock{BlockDirLock(opts.blocks_dir)},
m_prune_mode{opts.prune_target > 0},
m_xor_key{InitBlocksdirXorKey(opts)},
m_opts{std::move(opts)},
m_block_file_seq{FlatFileSeq{m_opts.blocks_dir, "blk", m_opts.fast_prune ? 0x4000 /* 16kB */ : BLOCKFILE_CHUNK_SIZE}},
Expand Down
9 changes: 9 additions & 0 deletions src/node/blockstorage.h
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,14 @@ struct BlockfileCursor {

std::ostream& operator<<(std::ostream& os, const BlockfileCursor& cursor);

class BlockDirLock
{
fs::path m_path;

public:
explicit BlockDirLock(const fs::path& blocks_dir);
~BlockDirLock();
};

/**
* Maintains a tree of blocks (stored in `m_block_index`) which is consulted
Expand All @@ -141,6 +149,7 @@ class BlockManager
friend ChainstateManager;

private:
BlockDirLock m_lock;
const CChainParams& GetParams() const { return m_opts.chainparams; }
const Consensus::Params& GetConsensus() const { return m_opts.chainparams.GetConsensus(); }
/**
Expand Down

0 comments on commit 1ba7ff6

Please sign in to comment.