mirror of https://github.com/facebook/rocksdb.git
Fix file checksum mismatch due to padded bytes when block_align=true (#12542)
Summary:
**Context/Summary:**
When `BlockBasedTableOptions::block_align=true`, we pad bytes to align blocks d41e568b1c/table/block_based/block_based_table_builder.cc (L1415-L1421)
.
Those bytes are not included in generating the file checksum upon file creation. But `VerifyFileChecksums()` includes those bytes in generating the file check to compare against the checksum generating upon file creation. Therefore a file checksum mismatch is returned in `VerifyFileChecksums()`.
We decided to include those padded bytes in generating the checksum upon file creation.
Bonus: also fix surrounding code to use actual padded bytes for verification - see https://github.com/facebook/rocksdb/pull/12542#discussion_r1571429163
Pull Request resolved: https://github.com/facebook/rocksdb/pull/12542
Test Plan:
- New UT
- Benchmark
```
TEST_TMPDIR=/dev/shm ./db_bench --benchmarks=fillseq[-X300] --num=100000 --block_align=1 --compression_type=none
```
Pre-PR:
fillseq [AVG 300 runs] : 422857 (± 3942) ops/sec; 46.8 (± 0.4) MB/sec
Post-PR:
fillseq [AVG 300 runs] : 424707 (± 3799) ops/sec; 47.0 (± 0.4) MB/sec
Reviewed By: ajkr
Differential Revision: D56168447
Pulled By: hx235
fbshipit-source-id: 96209ef950d42943d336f11968ae3fcf9872fc2c
This commit is contained in:
parent
bcfe4a0dcf
commit
7d83b4e3e5
|
@ -205,15 +205,17 @@ IOStatus WritableFileWriter::Pad(const IOOptions& opts,
|
|||
assert(pad_bytes < kDefaultPageSize);
|
||||
size_t left = pad_bytes;
|
||||
size_t cap = buf_.Capacity() - buf_.CurrentSize();
|
||||
size_t pad_start = buf_.CurrentSize();
|
||||
const size_t pad_start = buf_.CurrentSize();
|
||||
|
||||
// Assume pad_bytes is small compared to buf_ capacity. So we always
|
||||
// use buf_ rather than write directly to file in certain cases like
|
||||
// Append() does.
|
||||
size_t actual_pad_bytes = 0;
|
||||
while (left) {
|
||||
size_t append_bytes = std::min(cap, left);
|
||||
buf_.PadWith(append_bytes, 0);
|
||||
left -= append_bytes;
|
||||
actual_pad_bytes += append_bytes;
|
||||
if (left > 0) {
|
||||
IOStatus s = Flush(io_options);
|
||||
if (!s.ok()) {
|
||||
|
@ -226,10 +228,13 @@ IOStatus WritableFileWriter::Pad(const IOOptions& opts,
|
|||
pending_sync_ = true;
|
||||
uint64_t cur_size = filesize_.load(std::memory_order_acquire);
|
||||
filesize_.store(cur_size + pad_bytes, std::memory_order_release);
|
||||
|
||||
Slice data(buf_.BufferStart() + pad_start, actual_pad_bytes);
|
||||
UpdateFileChecksum(data);
|
||||
if (perform_data_verification_) {
|
||||
buffered_data_crc32c_checksum_ =
|
||||
crc32c::Extend(buffered_data_crc32c_checksum_,
|
||||
buf_.BufferStart() + pad_start, pad_bytes);
|
||||
buf_.BufferStart() + pad_start, actual_pad_bytes);
|
||||
}
|
||||
return IOStatus::OK();
|
||||
}
|
||||
|
|
|
@ -5505,6 +5505,29 @@ TEST_P(BlockBasedTableTest, BlockAlignTest) {
|
|||
table_reader.reset();
|
||||
}
|
||||
|
||||
TEST_P(BlockBasedTableTest, FixBlockAlignMismatchedFileChecksums) {
|
||||
Options options;
|
||||
options.create_if_missing = true;
|
||||
options.compression = kNoCompression;
|
||||
options.file_checksum_gen_factory = GetFileChecksumGenCrc32cFactory();
|
||||
BlockBasedTableOptions bbto;
|
||||
bbto.block_align = true;
|
||||
bbto.block_size = 1024;
|
||||
options.table_factory.reset(NewBlockBasedTableFactory(bbto));
|
||||
const std::string kDBPath =
|
||||
test::PerThreadDBPath("block_align_padded_bytes_verify_file_checksums");
|
||||
ASSERT_OK(DestroyDB(kDBPath, options));
|
||||
DB* db;
|
||||
ASSERT_OK(DB::Open(options, kDBPath, &db));
|
||||
ASSERT_OK(db->Put(WriteOptions(), "k1", "v1"));
|
||||
ASSERT_OK(db->Flush(FlushOptions()));
|
||||
// Before the fix, VerifyFileChecksums() will fail as padded bytes from
|
||||
// aligning blocks are used to generate the checksum to compare against the
|
||||
// one not generated by padded bytes
|
||||
ASSERT_OK(db->VerifyFileChecksums(ReadOptions()));
|
||||
delete db;
|
||||
}
|
||||
|
||||
TEST_P(BlockBasedTableTest, PropertiesBlockRestartPointTest) {
|
||||
BlockBasedTableOptions bbto = GetBlockBasedTableOptions();
|
||||
bbto.block_align = true;
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
Fix a bug causing `VerifyFileChecksums()` to return false-positive corruption under `BlockBasedTableOptions::block_align=true`
|
Loading…
Reference in New Issue