Explicitly free allocated buffer when status is not ok (#6903)

Summary:
Currently we rely on `BlockContents` to implicitly free the allocated scratch buffer, but when IO error happens, it doesn't make sense to construct the `BlockContents` which might be corrupted. In the stress test, we find that `assert(req.result.size() == block_size(handle));` fails because of potential IO errors.

In this PR, we explicitly free the scratch buffer on error without constructing `BlockContents`.
Pull Request resolved: https://github.com/facebook/rocksdb/pull/6903

Test Plan: watch stress test

Reviewed By: anand1976

Differential Revision: D21823869

Pulled By: cheng-chang

fbshipit-source-id: 5603fc80e9bf3f44a9d7250ddebd871afe1eb89f
main
Cheng Chang 5 years ago committed by Facebook GitHub Bot
parent 038e02d8d9
commit bcb9e41080
  1. 12
      table/block_based/block_based_table_reader.cc

@ -1727,6 +1727,7 @@ void BlockBasedTable::RetrieveMultipleBlocks(
} }
BlockContents raw_block_contents; BlockContents raw_block_contents;
if (s.ok()) {
if (!use_shared_buffer) { if (!use_shared_buffer) {
// We allocated a buffer for this block. Give ownership of it to // We allocated a buffer for this block. Give ownership of it to
// BlockContents so it can free the memory // BlockContents so it can free the memory
@ -1746,7 +1747,7 @@ void BlockBasedTable::RetrieveMultipleBlocks(
raw_block_contents.is_raw_block = true; raw_block_contents.is_raw_block = true;
#endif #endif
if (s.ok() && options.verify_checksums) { if (options.verify_checksums) {
PERF_TIMER_GUARD(block_checksum_time); PERF_TIMER_GUARD(block_checksum_time);
const char* data = req.result.data(); const char* data = req.result.data();
uint32_t expected = uint32_t expected =
@ -1756,11 +1757,14 @@ void BlockBasedTable::RetrieveMultipleBlocks(
// begin address of each read request, we need to add the offset // begin address of each read request, we need to add the offset
// in each read request. Checksum is stored in the block trailer, // in each read request. Checksum is stored in the block trailer,
// which is handle.size() + 1. // which is handle.size() + 1.
s = ROCKSDB_NAMESPACE::VerifyChecksum(footer.checksum(), s = ROCKSDB_NAMESPACE::VerifyChecksum(
data + req_offset, footer.checksum(), data + req_offset, handle.size() + 1, expected);
handle.size() + 1, expected);
TEST_SYNC_POINT_CALLBACK("RetrieveMultipleBlocks:VerifyChecksum", &s); TEST_SYNC_POINT_CALLBACK("RetrieveMultipleBlocks:VerifyChecksum", &s);
} }
} else if (!use_shared_buffer) {
// Free the allocated scratch buffer.
delete[] req.scratch;
}
if (s.ok()) { if (s.ok()) {
// When the blocks share the same underlying buffer (scratch or direct io // When the blocks share the same underlying buffer (scratch or direct io

Loading…
Cancel
Save