diff --git a/Makefile b/Makefile index 3136130..fc0ecb3 100644 --- a/Makefile +++ b/Makefile @@ -6,6 +6,7 @@ SOURCE=\ checksum.cc \ endian_utils.cc \ error_set.cc \ + hex_dump.cc \ metadata.cc \ metadata_disk_structures.cc \ space_map_disk.cc \ @@ -15,7 +16,7 @@ OBJECTS=$(subst .cc,.o,$(SOURCE)) TOP_DIR:=$(PWD) CPPFLAGS=-Wall -g -I$(TOP_DIR) #CPPFLAGS=-Wall -std=c++0x -g -I$(TOP_DIR) -LIBS=-lz -lstdc++ +LIBS=-lstdc++ .PHONEY: test-programs diff --git a/btree.h b/btree.h index 5be91e2..722cb25 100644 --- a/btree.h +++ b/btree.h @@ -38,6 +38,8 @@ namespace persistent_data { using namespace std; using namespace boost; + uint32_t const BTREE_CSUM_XOR = 121107; + //------------------------------------------------ // On disk data layout for btree nodes enum node_flags { @@ -74,6 +76,8 @@ namespace persistent_data { public: explicit node_ref(block_address b, disk_node *raw); + uint32_t get_checksum() const; + block_address get_location() const { return location_; } @@ -125,8 +129,11 @@ namespace persistent_data { template void inc_children(RefCounter &rc); - // FIXME: remove - void *raw() { + disk_node *raw() { + return raw_; + } + + disk_node const *raw() const { return raw_; } diff --git a/btree.tcc b/btree.tcc index 1f3c6d8..97d1978 100644 --- a/btree.tcc +++ b/btree.tcc @@ -16,6 +16,13 @@ node_ref::node_ref(block_address location, disk_node *raw) { } +template +uint32_t +node_ref::get_checksum() const +{ + return to_cpu(raw_->header.csum); +} + template block_address node_ref::get_block_nr() const diff --git a/btree_checker.h b/btree_checker.h index 78d1d0d..4e238df 100644 --- a/btree_checker.h +++ b/btree_checker.h @@ -3,7 +3,9 @@ #include "btree.h" +#include "checksum.h" #include "error_set.h" +#include "hex_dump.h" #include #include @@ -78,6 +80,8 @@ namespace persistent_data { if (already_visited(n)) return false; + check_sum(n); + if (!key) new_root(level); @@ -95,6 +99,8 @@ namespace persistent_data { if (already_visited(n)) return false; + check_sum(n); + if (!key) new_root(level); @@ -104,7 +110,7 @@ namespace persistent_data { check_ordered_keys(n); check_parent_key(key, n); check_leaf_key(level, n); - + return true; } @@ -114,6 +120,8 @@ namespace persistent_data { if (already_visited(n)) return false; + check_sum(n); + if (!key) new_root(level); @@ -149,6 +157,22 @@ namespace persistent_data { return false; } + template + void check_sum(node const &n) const { + crc32c sum(BTREE_CSUM_XOR); + + disk_node const *data = n.raw(); + sum.append(&data->header.flags, MD_BLOCK_SIZE - sizeof(uint32_t)); + if (sum.get_sum() != n.get_checksum()) { + std::ostringstream out; + out << "checksum error for block " << n.get_block_nr() + << ", sum was " << sum.get_sum() + << ", expected " << n.get_checksum(); + errs_->add_child(out.str()); + throw runtime_error(out.str()); + } + } + template void check_block_nr(node const &n) const { if (n.get_location() != n.get_block_nr()) { diff --git a/checksum.cc b/checksum.cc index 4dd37ab..a62e615 100644 --- a/checksum.cc +++ b/checksum.cc @@ -1,25 +1,31 @@ #include "checksum.h" -#include +#include using namespace base; //---------------------------------------------------------------- -crc32::crc32(uint32_t seed) - : sum_(seed) { +crc32c::crc32c(uint32_t xor_value) + : xor_value_(xor_value), + sum_(0) +{ } void -crc32::append(void const *buffer, unsigned len) +crc32c::append(void const *buffer, unsigned len) { - sum_ = ::crc32(sum_, reinterpret_cast(buffer), len); + uint32_t const powers = 0x1EDC6F41; + + boost::crc_basic<32> crc(powers, 0xffffffff, 0, true, true); + crc.process_bytes(buffer, len); + sum_ = crc.checksum(); } uint32_t -crc32::get_sum() const +crc32c::get_sum() const { - return sum_; + return sum_ ^ xor_value_; } //---------------------------------------------------------------- diff --git a/checksum.h b/checksum.h index 76f4f9d..53553cb 100644 --- a/checksum.h +++ b/checksum.h @@ -6,13 +6,15 @@ //---------------------------------------------------------------- namespace base { - class crc32 { - crc32(uint32_t seed); + class crc32c { + public: + crc32c(uint32_t xor_value); void append(void const *buffer, unsigned len); uint32_t get_sum() const; private: + uint32_t xor_value_; uint32_t sum_; }; } diff --git a/hex_dump.cc b/hex_dump.cc new file mode 100644 index 0000000..8957770 --- /dev/null +++ b/hex_dump.cc @@ -0,0 +1,24 @@ +#include "hex_dump.h" + +#include +#include + +using namespace std; + +//---------------------------------------------------------------- + +void base::hex_dump(ostream &out, void const *data_, size_t len) +{ + unsigned char const *data = reinterpret_cast(data_), + *end = data + len; + out << hex; + + while (data < end) { + for (unsigned i = 0; i < 16 && data < end; i++, data++) + out << setw(2) << setfill('0') << (unsigned) *data << " "; + out << endl; + } + out << dec; +} + +//---------------------------------------------------------------- diff --git a/hex_dump.h b/hex_dump.h new file mode 100644 index 0000000..823fa9d --- /dev/null +++ b/hex_dump.h @@ -0,0 +1,14 @@ +#ifndef HEX_DUMP_H +#define HEX_DUMP_H + +#include + +//---------------------------------------------------------------- + +namespace base { + void hex_dump(std::ostream &out, void const *data, size_t len); +} + +//---------------------------------------------------------------- + +#endif diff --git a/metadata.cc b/metadata.cc index a03bf66..80f42bb 100644 --- a/metadata.cc +++ b/metadata.cc @@ -74,6 +74,17 @@ namespace { superblock sb; block_manager<>::read_ref r = bm->read_lock(SUPERBLOCK_LOCATION); superblock_disk const *sbd = reinterpret_cast(&r.data()); + + crc32c sum(160774); + sum.append(&sbd->flags_, MD_BLOCK_SIZE - sizeof(uint32_t)); + if (sum.get_sum() != to_cpu(sbd->csum_)) { + ostringstream out; + out << "bad checksum in superblock, calculated " + << sum.get_sum() + << ", superblock contains " << to_cpu(sbd->csum_); + throw runtime_error(out.str()); + } + superblock_traits::unpack(*sbd, sb); return sb; } diff --git a/space_map_disk.cc b/space_map_disk.cc index 49e72d0..59fc67b 100644 --- a/space_map_disk.cc +++ b/space_map_disk.cc @@ -81,6 +81,11 @@ namespace { } private: + void check_crc(transaction_manager::read_ref &rr) { + crc32c sum(240779); + // sum.append(reinterpret_cast(&rr.data()[0]); + } + void *bitmap_data(transaction_manager::write_ref &wr) { bitmap_header *h = reinterpret_cast(&wr.data()[0]); return h + 1;