Skip to content

Conversation

TheBlueMatt
Copy link
Contributor

Built on #11281 and one commit from #11824, this removes almost all cs_main holds in ReadBlockFromDisk calls in net_processing/RPC/REST. Only real worry here is if something gets pruned out from under us during reading, so some previously-asserts in net_processing are now LogPrints.

@TheBlueMatt TheBlueMatt force-pushed the 2017-12-no-readblockfromdisk-csmain branch from c20ff7d to 571f4ad Compare December 15, 2017 23:43
@laanwj
Copy link
Member

laanwj commented Dec 16, 2017

Concept ACK. Good to have less contention on the cs_main lock, it seems a good idea to release it during I/O.

Copy link
Contributor

@promag promag left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

utACK 571f4ad.

@@ -144,6 +138,12 @@ UniValue blockToJSON(const CBlock& block, const CBlockIndex* blockindex, bool tx

if (blockindex->pprev)
result.push_back(Pair("previousblockhash", blockindex->pprev->GetBlockHash().GetHex()));
LOCK(cs_main);
int confirmations = -1;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Avoid lock here by receiving the pindex tip? (with the cost of jumping thru pprev).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That still wouldn't solve it for the chainActive.Next() call, so you'd need cs_main either way. Less code diff to just do it as-is.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Something along this should work:

const CBlockIndex* pindex = tip;
const CBlockIndex* pnext = nullptr;
int confirmations = 0;
while (pindex && pindex != blockindex && pindex->nHeight >= blockindex->nHeight) {
    pnext = pindex;
    pindex = pindex->pprev;
    confirmations++;
}
if (pindex != blockindex) confirmations = -1;

This approach avoids accessing chainActive, blockToJSON just needs to receive the tip. This sounds more correct to me because a RPC can take a snapshot of the tip (and then leave cs_main) and all the remaining execution is consistent with that tip.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Submitted suggestion as #12151.

@jonasschnelli
Copy link
Contributor

Needs rebase on rebased #11281
Concept ACK

Copy link
Contributor

@promag promag left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Needs rebase.

@@ -144,6 +138,12 @@ UniValue blockToJSON(const CBlock& block, const CBlockIndex* blockindex, bool tx

if (blockindex->pprev)
result.push_back(Pair("previousblockhash", blockindex->pprev->GetBlockHash().GetHex()));
LOCK(cs_main);
int confirmations = -1;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Submitted suggestion as #12151.

@TheBlueMatt
Copy link
Contributor Author

Awaiting re-rebase of #11281. Will probably just wait for that to get merged.

Copy link
Contributor

@jimpo jimpo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The concurrent access to data on disk makes me a little nervous. Is it worth having a separate read-write lock around reading/writing block files?

@@ -1044,6 +1044,8 @@ bool static ProcessGetBlockData(CNode* pfrom, const Consensus::Params& consensus
fWitnessesPresentInARecentCompactBlock = fWitnessesPresentInMostRecentCompactBlock;
}

const CBlockIndex *pindex = nullptr;
{
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I find the indentation here confusing. I assume it's not indented to help reviewers, so maybe indent in a separate commit?

@@ -1085,16 +1089,20 @@ bool static ProcessGetBlockData(CNode* pfrom, const Consensus::Params& consensus
}
// Pruned nodes may have deleted the block, so check whether
// it's available before trying to send.
if (send && (mi->second->nStatus & BLOCK_HAVE_DATA))
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add a // releases cs_main if there is no indentation.

@@ -1085,16 +1089,20 @@ bool static ProcessGetBlockData(CNode* pfrom, const Consensus::Params& consensus
}
// Pruned nodes may have deleted the block, so check whether
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This comment should get moved up to line 1066.

@TheBlueMatt
Copy link
Contributor Author

@jimpo are you aware of any modern systems that have an issue reading from the middle of a file while it is being appended to? That sounds like it should be considered a critical kernel bug if anything, no?

@jimpo
Copy link
Contributor

jimpo commented Jan 11, 2018

I say that mostly because of the pruning race.

@TheBlueMatt
Copy link
Contributor Author

Pruning should be atomic still, no? Either we opened the file, then any unlink operations on the underlying file will result in us being able to finish reading, or we didn't open the file, so we can return false. I'm skeptical it can ever result in corrupt data, or am I missing some way Windows operates? It's definitely worth auditing that ReadBlockFromDisk returning false is handled properly everywhere!

@promag
Copy link
Contributor

promag commented Feb 3, 2018

Needs rebase.

@TheBlueMatt TheBlueMatt force-pushed the 2017-12-no-readblockfromdisk-csmain branch from 571f4ad to 030c233 Compare March 27, 2018 20:22
@TheBlueMatt
Copy link
Contributor Author

Rebased.

@TheBlueMatt TheBlueMatt force-pushed the 2017-12-no-readblockfromdisk-csmain branch from 030c233 to 7f538c1 Compare March 28, 2018 18:24
@TheBlueMatt TheBlueMatt force-pushed the 2017-12-no-readblockfromdisk-csmain branch from 7f538c1 to 44d93b3 Compare April 28, 2018 01:32
@TheBlueMatt
Copy link
Contributor Author

Rebased. In addition to RPC latency in some calls, this should also now make a nontrivial difference to -txindex nodes restart resync after an unclean shutdown (which, at least, should be useful to me).

@TheBlueMatt TheBlueMatt force-pushed the 2017-12-no-readblockfromdisk-csmain branch from 44d93b3 to b49fa7c Compare April 28, 2018 02:00
@TheBlueMatt TheBlueMatt force-pushed the 2017-12-no-readblockfromdisk-csmain branch from b49fa7c to cb14810 Compare April 28, 2018 02:19
@promag
Copy link
Contributor

promag commented May 3, 2018

Needs rebase.

maflcko pushed a commit to maflcko/bitcoin-core that referenced this pull request Jan 4, 2019
…ockheaderToJSON

b9f226b rpc: Remove cs_main lock from blockToJSON and blockHeaderToJSON (João Barbosa)
343b98c rpc: Specify chain tip instead of chain in GetDifficulty (João Barbosa)
54dc13b rpc: Fix SoftForkMajorityDesc and SoftForkDesc signatures (João Barbosa)

Pull request description:

  Motivated by bitcoin#11913 (comment), this pull makes `blockToJSON` and `blockheaderToJSON` free of `cs_main` locks.

  Locking `cs_main` was required to access `chainActive` in order to check if the block was in the chain and to retrieve the next block index.

  With the this approach, `CBlockIndex::GetAncestor()` is used in a way to check if the block belongs to the specified chain tip and, at the same time, get the next block index.

Tree-SHA512: a6720ace0182c19033bbed1a404f729d793574db8ab16e0966ffe412145611e32c30aaab02975d225df6d439d7b9ef2070e732b16137a902b0293c8cddfeb85f
jasonbcox pushed a commit to Bitcoin-ABC/bitcoin-abc that referenced this pull request May 31, 2019
…erToJSON

Summary:
backport PR12151 https://github.com/bitcoin/bitcoin/pull/12151/files
b9f226b41f rpc: Remove cs_main lock from blockToJSON and blockHeaderToJSON (João Barbosa)
343b98cbcd rpc: Specify chain tip instead of chain in GetDifficulty (João Barbosa)
54dc13b6a2 rpc: Fix SoftForkMajorityDesc and SoftForkDesc signatures (João Barbosa)

Pull request description:

  Motivated by bitcoin/bitcoin#11913 (comment), this pull makes `blockToJSON` and `blockheaderToJSON` free of `cs_main` locks.

  Locking `cs_main` was required to access `chainActive` in order to check if the block was in the chain and to retrieve the next block index.

  With the this approach, `CBlockIndex::GetAncestor()` is used in a way to check if the block belongs to the specified chain tip and, at the same time, get the next block index.

Backport note: The modification of `get_difficulty_for_null_tip cannot` be included in this due to divergent and conflicting histories; this situation will be amended in D3012.

Depends on D3070

Test Plan:
`make check`
`test_runner.py`

Reviewers: jasonbcox, Fabien, #bitcoin_abc, deadalnix

Reviewed By: jasonbcox, Fabien, #bitcoin_abc, deadalnix

Differential Revision: https://reviews.bitcoinabc.org/D3021
jonspock pushed a commit to devaultcrypto/devault that referenced this pull request Jun 23, 2019
…erToJSON

Summary:
backport PR12151 https://github.com/bitcoin/bitcoin/pull/12151/files
b9f226b41f rpc: Remove cs_main lock from blockToJSON and blockHeaderToJSON (João Barbosa)
343b98cbcd rpc: Specify chain tip instead of chain in GetDifficulty (João Barbosa)
54dc13b6a2 rpc: Fix SoftForkMajorityDesc and SoftForkDesc signatures (João Barbosa)

Pull request description:

  Motivated by bitcoin/bitcoin#11913 (comment), this pull makes `blockToJSON` and `blockheaderToJSON` free of `cs_main` locks.

  Locking `cs_main` was required to access `chainActive` in order to check if the block was in the chain and to retrieve the next block index.

  With the this approach, `CBlockIndex::GetAncestor()` is used in a way to check if the block belongs to the specified chain tip and, at the same time, get the next block index.

Backport note: The modification of `get_difficulty_for_null_tip cannot` be included in this due to divergent and conflicting histories; this situation will be amended in D3012.

Depends on D3070

Test Plan:
`make check`
`test_runner.py`

Reviewers: jasonbcox, Fabien, #bitcoin_abc, deadalnix

Reviewed By: jasonbcox, Fabien, #bitcoin_abc, deadalnix

Differential Revision: https://reviews.bitcoinabc.org/D3021
jtoomim pushed a commit to jtoomim/bitcoin-abc that referenced this pull request Jun 29, 2019
…erToJSON

Summary:
backport PR12151 https://github.com/bitcoin/bitcoin/pull/12151/files
b9f226b41f rpc: Remove cs_main lock from blockToJSON and blockHeaderToJSON (João Barbosa)
343b98cbcd rpc: Specify chain tip instead of chain in GetDifficulty (João Barbosa)
54dc13b6a2 rpc: Fix SoftForkMajorityDesc and SoftForkDesc signatures (João Barbosa)

Pull request description:

  Motivated by bitcoin/bitcoin#11913 (comment), this pull makes `blockToJSON` and `blockheaderToJSON` free of `cs_main` locks.

  Locking `cs_main` was required to access `chainActive` in order to check if the block was in the chain and to retrieve the next block index.

  With the this approach, `CBlockIndex::GetAncestor()` is used in a way to check if the block belongs to the specified chain tip and, at the same time, get the next block index.

Backport note: The modification of `get_difficulty_for_null_tip cannot` be included in this due to divergent and conflicting histories; this situation will be amended in D3012.

Depends on D3070

Test Plan:
`make check`
`test_runner.py`

Reviewers: jasonbcox, Fabien, #bitcoin_abc, deadalnix

Reviewed By: jasonbcox, Fabien, #bitcoin_abc, deadalnix

Differential Revision: https://reviews.bitcoinabc.org/D3021
jonspock pushed a commit to devaultcrypto/devault that referenced this pull request Jul 9, 2019
…erToJSON

Summary:
backport PR12151 https://github.com/bitcoin/bitcoin/pull/12151/files
b9f226b41f rpc: Remove cs_main lock from blockToJSON and blockHeaderToJSON (João Barbosa)
343b98cbcd rpc: Specify chain tip instead of chain in GetDifficulty (João Barbosa)
54dc13b6a2 rpc: Fix SoftForkMajorityDesc and SoftForkDesc signatures (João Barbosa)

Pull request description:

  Motivated by bitcoin/bitcoin#11913 (comment), this pull makes `blockToJSON` and `blockheaderToJSON` free of `cs_main` locks.

  Locking `cs_main` was required to access `chainActive` in order to check if the block was in the chain and to retrieve the next block index.

  With the this approach, `CBlockIndex::GetAncestor()` is used in a way to check if the block belongs to the specified chain tip and, at the same time, get the next block index.

Backport note: The modification of `get_difficulty_for_null_tip cannot` be included in this due to divergent and conflicting histories; this situation will be amended in D3012.

Depends on D3070

Test Plan:
`make check`
`test_runner.py`

Reviewers: jasonbcox, Fabien, #bitcoin_abc, deadalnix

Reviewed By: jasonbcox, Fabien, #bitcoin_abc, deadalnix

Differential Revision: https://reviews.bitcoinabc.org/D3021
Munkybooty pushed a commit to Munkybooty/dash that referenced this pull request Aug 14, 2021
…ockheaderToJSON

b9f226b rpc: Remove cs_main lock from blockToJSON and blockHeaderToJSON (João Barbosa)
343b98c rpc: Specify chain tip instead of chain in GetDifficulty (João Barbosa)
54dc13b rpc: Fix SoftForkMajorityDesc and SoftForkDesc signatures (João Barbosa)

Pull request description:

  Motivated by bitcoin#11913 (comment), this pull makes `blockToJSON` and `blockheaderToJSON` free of `cs_main` locks.

  Locking `cs_main` was required to access `chainActive` in order to check if the block was in the chain and to retrieve the next block index.

  With the this approach, `CBlockIndex::GetAncestor()` is used in a way to check if the block belongs to the specified chain tip and, at the same time, get the next block index.

Tree-SHA512: a6720ace0182c19033bbed1a404f729d793574db8ab16e0966ffe412145611e32c30aaab02975d225df6d439d7b9ef2070e732b16137a902b0293c8cddfeb85f
Munkybooty pushed a commit to Munkybooty/dash that referenced this pull request Aug 24, 2021
…ockheaderToJSON

b9f226b rpc: Remove cs_main lock from blockToJSON and blockHeaderToJSON (João Barbosa)
343b98c rpc: Specify chain tip instead of chain in GetDifficulty (João Barbosa)
54dc13b rpc: Fix SoftForkMajorityDesc and SoftForkDesc signatures (João Barbosa)

Pull request description:

  Motivated by bitcoin#11913 (comment), this pull makes `blockToJSON` and `blockheaderToJSON` free of `cs_main` locks.

  Locking `cs_main` was required to access `chainActive` in order to check if the block was in the chain and to retrieve the next block index.

  With the this approach, `CBlockIndex::GetAncestor()` is used in a way to check if the block belongs to the specified chain tip and, at the same time, get the next block index.

Tree-SHA512: a6720ace0182c19033bbed1a404f729d793574db8ab16e0966ffe412145611e32c30aaab02975d225df6d439d7b9ef2070e732b16137a902b0293c8cddfeb85f
Munkybooty pushed a commit to Munkybooty/dash that referenced this pull request Aug 24, 2021
…ockheaderToJSON

b9f226b rpc: Remove cs_main lock from blockToJSON and blockHeaderToJSON (João Barbosa)
343b98c rpc: Specify chain tip instead of chain in GetDifficulty (João Barbosa)
54dc13b rpc: Fix SoftForkMajorityDesc and SoftForkDesc signatures (João Barbosa)

Pull request description:

  Motivated by bitcoin#11913 (comment), this pull makes `blockToJSON` and `blockheaderToJSON` free of `cs_main` locks.

  Locking `cs_main` was required to access `chainActive` in order to check if the block was in the chain and to retrieve the next block index.

  With the this approach, `CBlockIndex::GetAncestor()` is used in a way to check if the block belongs to the specified chain tip and, at the same time, get the next block index.

Tree-SHA512: a6720ace0182c19033bbed1a404f729d793574db8ab16e0966ffe412145611e32c30aaab02975d225df6d439d7b9ef2070e732b16137a902b0293c8cddfeb85f
UdjinM6 pushed a commit to UdjinM6/dash that referenced this pull request Aug 24, 2021
…ockheaderToJSON

b9f226b rpc: Remove cs_main lock from blockToJSON and blockHeaderToJSON (João Barbosa)
343b98c rpc: Specify chain tip instead of chain in GetDifficulty (João Barbosa)
54dc13b rpc: Fix SoftForkMajorityDesc and SoftForkDesc signatures (João Barbosa)

Pull request description:

  Motivated by bitcoin#11913 (comment), this pull makes `blockToJSON` and `blockheaderToJSON` free of `cs_main` locks.

  Locking `cs_main` was required to access `chainActive` in order to check if the block was in the chain and to retrieve the next block index.

  With the this approach, `CBlockIndex::GetAncestor()` is used in a way to check if the block belongs to the specified chain tip and, at the same time, get the next block index.

Tree-SHA512: a6720ace0182c19033bbed1a404f729d793574db8ab16e0966ffe412145611e32c30aaab02975d225df6d439d7b9ef2070e732b16137a902b0293c8cddfeb85f
Munkybooty pushed a commit to Munkybooty/dash that referenced this pull request Aug 24, 2021
…ockheaderToJSON

b9f226b rpc: Remove cs_main lock from blockToJSON and blockHeaderToJSON (João Barbosa)
343b98c rpc: Specify chain tip instead of chain in GetDifficulty (João Barbosa)
54dc13b rpc: Fix SoftForkMajorityDesc and SoftForkDesc signatures (João Barbosa)

Pull request description:

  Motivated by bitcoin#11913 (comment), this pull makes `blockToJSON` and `blockheaderToJSON` free of `cs_main` locks.

  Locking `cs_main` was required to access `chainActive` in order to check if the block was in the chain and to retrieve the next block index.

  With the this approach, `CBlockIndex::GetAncestor()` is used in a way to check if the block belongs to the specified chain tip and, at the same time, get the next block index.

Tree-SHA512: a6720ace0182c19033bbed1a404f729d793574db8ab16e0966ffe412145611e32c30aaab02975d225df6d439d7b9ef2070e732b16137a902b0293c8cddfeb85f
Munkybooty pushed a commit to Munkybooty/dash that referenced this pull request Aug 24, 2021
…ockheaderToJSON

b9f226b rpc: Remove cs_main lock from blockToJSON and blockHeaderToJSON (João Barbosa)
343b98c rpc: Specify chain tip instead of chain in GetDifficulty (João Barbosa)
54dc13b rpc: Fix SoftForkMajorityDesc and SoftForkDesc signatures (João Barbosa)

Pull request description:

  Motivated by bitcoin#11913 (comment), this pull makes `blockToJSON` and `blockheaderToJSON` free of `cs_main` locks.

  Locking `cs_main` was required to access `chainActive` in order to check if the block was in the chain and to retrieve the next block index.

  With the this approach, `CBlockIndex::GetAncestor()` is used in a way to check if the block belongs to the specified chain tip and, at the same time, get the next block index.

Tree-SHA512: a6720ace0182c19033bbed1a404f729d793574db8ab16e0966ffe412145611e32c30aaab02975d225df6d439d7b9ef2070e732b16137a902b0293c8cddfeb85f
@bitcoin bitcoin locked as resolved and limited conversation to collaborators Dec 16, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants