2013-05-21 17:50:03 +05:30
|
|
|
#include "persistent-data/checksum.h"
|
|
|
|
#include "persistent-data/errors.h"
|
2013-05-21 17:16:07 +05:30
|
|
|
#include "thin-provisioning/superblock.h"
|
2015-07-27 19:00:09 +05:30
|
|
|
#include "persistent-data/file_utils.h"
|
2011-07-22 20:39:56 +05:30
|
|
|
|
2017-04-29 23:21:52 +05:30
|
|
|
#include <sstream>
|
|
|
|
|
2011-07-22 20:39:56 +05:30
|
|
|
using namespace thin_provisioning;
|
2013-05-21 17:16:07 +05:30
|
|
|
using namespace superblock_detail;
|
2017-04-29 23:21:52 +05:30
|
|
|
using namespace std;
|
2011-07-22 20:39:56 +05:30
|
|
|
|
|
|
|
//----------------------------------------------------------------
|
|
|
|
|
|
|
|
void
|
|
|
|
superblock_traits::unpack(superblock_disk const &disk, superblock &value)
|
|
|
|
{
|
|
|
|
value.csum_ = to_cpu<uint32_t>(disk.csum_);
|
2012-03-08 18:41:55 +05:30
|
|
|
value.flags_ = to_cpu<uint32_t>(disk.flags_);
|
2011-07-22 20:39:56 +05:30
|
|
|
value.blocknr_ = to_cpu<uint64_t>(disk.blocknr_);
|
|
|
|
|
|
|
|
::memcpy(value.uuid_, disk.uuid_, sizeof(value.uuid_));
|
|
|
|
value.magic_ = to_cpu<uint64_t>(disk.magic_);
|
|
|
|
value.version_ = to_cpu<uint32_t>(disk.version_);
|
|
|
|
value.time_ = to_cpu<uint32_t>(disk.time_);
|
|
|
|
|
|
|
|
value.trans_id_ = to_cpu<uint64_t>(disk.trans_id_);
|
2012-05-17 17:35:26 +05:30
|
|
|
value.metadata_snap_ = to_cpu<uint64_t>(disk.metadata_snap_);
|
2011-07-22 20:39:56 +05:30
|
|
|
|
|
|
|
::memcpy(value.data_space_map_root_,
|
|
|
|
disk.data_space_map_root_,
|
|
|
|
sizeof(value.data_space_map_root_));
|
|
|
|
::memcpy(value.metadata_space_map_root_,
|
|
|
|
disk.metadata_space_map_root_,
|
|
|
|
sizeof(value.metadata_space_map_root_));
|
|
|
|
|
|
|
|
value.data_mapping_root_ = to_cpu<uint64_t>(disk.data_mapping_root_);
|
|
|
|
value.device_details_root_ = to_cpu<uint64_t>(disk.device_details_root_);
|
|
|
|
value.data_block_size_ = to_cpu<uint32_t>(disk.data_block_size_);
|
|
|
|
|
|
|
|
value.metadata_block_size_ = to_cpu<uint32_t>(disk.metadata_block_size_);
|
|
|
|
value.metadata_nr_blocks_ = to_cpu<uint64_t>(disk.metadata_nr_blocks_);
|
|
|
|
|
|
|
|
value.compat_flags_ = to_cpu<uint32_t>(disk.compat_flags_);
|
2013-08-15 20:56:17 +05:30
|
|
|
value.compat_ro_flags_ = to_cpu<uint32_t>(disk.compat_ro_flags_);
|
2011-07-22 20:39:56 +05:30
|
|
|
value.incompat_flags_ = to_cpu<uint32_t>(disk.incompat_flags_);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
superblock_traits::pack(superblock const &value, superblock_disk &disk)
|
|
|
|
{
|
2013-03-22 21:18:43 +05:30
|
|
|
disk.csum_ = to_disk<le32>(value.csum_);
|
|
|
|
disk.flags_ = to_disk<le32>(value.flags_);
|
|
|
|
disk.blocknr_ = to_disk<le64>(value.blocknr_);
|
2011-07-22 20:39:56 +05:30
|
|
|
|
|
|
|
::memcpy(disk.uuid_, value.uuid_, sizeof(disk.uuid_));
|
2013-03-22 21:18:43 +05:30
|
|
|
disk.magic_ = to_disk<le64>(value.magic_);
|
|
|
|
disk.version_ = to_disk<le32>(value.version_);
|
|
|
|
disk.time_ = to_disk<le32>(value.time_);
|
2011-07-22 20:39:56 +05:30
|
|
|
|
2013-03-22 21:18:43 +05:30
|
|
|
disk.trans_id_ = to_disk<le64>(value.trans_id_);
|
|
|
|
disk.metadata_snap_ = to_disk<le64>(value.metadata_snap_);
|
2011-07-22 20:39:56 +05:30
|
|
|
|
|
|
|
::memcpy(disk.data_space_map_root_,
|
|
|
|
value.data_space_map_root_,
|
|
|
|
sizeof(disk.data_space_map_root_));
|
|
|
|
::memcpy(disk.metadata_space_map_root_,
|
|
|
|
value.metadata_space_map_root_,
|
|
|
|
sizeof(disk.metadata_space_map_root_));
|
|
|
|
|
2013-03-22 21:18:43 +05:30
|
|
|
disk.data_mapping_root_ = to_disk<le64>(value.data_mapping_root_);
|
|
|
|
disk.device_details_root_ = to_disk<le64>(value.device_details_root_);
|
|
|
|
disk.data_block_size_ = to_disk<le32>(value.data_block_size_);
|
2011-07-22 20:39:56 +05:30
|
|
|
|
2013-03-22 21:18:43 +05:30
|
|
|
disk.metadata_block_size_ = to_disk<le32>(value.metadata_block_size_);
|
|
|
|
disk.metadata_nr_blocks_ = to_disk<le64>(value.metadata_nr_blocks_);
|
2011-07-22 20:39:56 +05:30
|
|
|
|
2013-03-22 21:18:43 +05:30
|
|
|
disk.compat_flags_ = to_disk<le32>(value.compat_flags_);
|
2013-08-15 20:56:17 +05:30
|
|
|
disk.compat_ro_flags_ = to_disk<le32>(value.compat_ro_flags_);
|
2013-03-22 21:18:43 +05:30
|
|
|
disk.incompat_flags_ = to_disk<le32>(value.incompat_flags_);
|
2011-07-22 20:39:56 +05:30
|
|
|
}
|
|
|
|
|
|
|
|
//----------------------------------------------------------------
|
2013-05-21 17:16:07 +05:30
|
|
|
|
2013-05-21 17:50:03 +05:30
|
|
|
namespace {
|
|
|
|
using namespace persistent_data;
|
|
|
|
using namespace superblock_detail;
|
|
|
|
|
|
|
|
uint32_t const SUPERBLOCK_CSUM_SEED = 160774;
|
|
|
|
|
2014-07-25 19:16:51 +05:30
|
|
|
struct sb_validator : public bcache::validator {
|
|
|
|
virtual void check(void const *raw, block_address location) const {
|
|
|
|
superblock_disk const *sbd = reinterpret_cast<superblock_disk const *>(raw);
|
2013-05-21 17:50:03 +05:30
|
|
|
crc32c sum(SUPERBLOCK_CSUM_SEED);
|
|
|
|
sum.append(&sbd->flags_, MD_BLOCK_SIZE - sizeof(uint32_t));
|
2016-02-26 23:01:24 +05:30
|
|
|
if (sum.get_sum() != to_cpu<uint32_t>(sbd->csum_)) {
|
|
|
|
ostringstream out;
|
|
|
|
out << "bad checksum in superblock, wanted " << sum.get_sum();
|
|
|
|
throw checksum_error(out.str());
|
|
|
|
}
|
2013-05-21 17:50:03 +05:30
|
|
|
}
|
|
|
|
|
2016-02-27 12:51:13 +05:30
|
|
|
virtual bool check_raw(void const *raw) const {
|
2014-07-25 19:16:51 +05:30
|
|
|
superblock_disk const *sbd = reinterpret_cast<superblock_disk const *>(raw);
|
2013-05-21 17:50:03 +05:30
|
|
|
crc32c sum(SUPERBLOCK_CSUM_SEED);
|
|
|
|
sum.append(&sbd->flags_, MD_BLOCK_SIZE - sizeof(uint32_t));
|
|
|
|
if (sum.get_sum() != to_cpu<uint32_t>(sbd->csum_))
|
2016-02-27 12:51:13 +05:30
|
|
|
return false;
|
|
|
|
return true;
|
2013-05-21 17:50:03 +05:30
|
|
|
}
|
|
|
|
|
2014-07-25 19:16:51 +05:30
|
|
|
virtual void prepare(void *raw, block_address location) const {
|
|
|
|
superblock_disk *sbd = reinterpret_cast<superblock_disk *>(raw);
|
2013-05-21 17:50:03 +05:30
|
|
|
crc32c sum(SUPERBLOCK_CSUM_SEED);
|
|
|
|
sum.append(&sbd->flags_, MD_BLOCK_SIZE - sizeof(uint32_t));
|
|
|
|
sbd->csum_ = to_disk<base::le32>(sum.get_sum());
|
|
|
|
}
|
|
|
|
};
|
2013-05-21 17:16:07 +05:30
|
|
|
}
|
|
|
|
|
2014-07-25 19:16:51 +05:30
|
|
|
bcache::validator::ptr
|
2013-05-21 17:50:03 +05:30
|
|
|
thin_provisioning::superblock_validator()
|
2013-05-21 17:16:07 +05:30
|
|
|
{
|
2014-07-25 19:16:51 +05:30
|
|
|
return bcache::validator::ptr(new sb_validator);
|
2013-05-21 17:16:07 +05:30
|
|
|
}
|
|
|
|
|
|
|
|
//----------------------------------------------------------------
|
2013-05-21 18:31:17 +05:30
|
|
|
|
|
|
|
namespace thin_provisioning {
|
|
|
|
namespace superblock_detail {
|
2014-03-27 17:30:17 +05:30
|
|
|
namespace {
|
|
|
|
unsigned const NEEDS_CHECK_BIT = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
|
|
|
superblock::get_needs_check_flag() const {
|
|
|
|
return flags_ & (1 << NEEDS_CHECK_BIT);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
superblock::set_needs_check_flag(bool val) {
|
|
|
|
if (val)
|
|
|
|
flags_ |= (1 << NEEDS_CHECK_BIT);
|
|
|
|
else
|
|
|
|
flags_ &= ~(1 << NEEDS_CHECK_BIT);
|
|
|
|
};
|
|
|
|
|
2013-05-21 18:31:17 +05:30
|
|
|
superblock_corruption::superblock_corruption(std::string const &desc)
|
|
|
|
: desc_(desc) {
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
superblock_corruption::visit(damage_visitor &v) const {
|
|
|
|
v.visit(*this);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
damage_visitor::visit(damage const &d) {
|
|
|
|
d.visit(*this);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-04-30 19:00:01 +05:30
|
|
|
superblock_detail::superblock read_superblock(block_manager const &bm, block_address location)
|
2013-05-21 20:19:20 +05:30
|
|
|
{
|
|
|
|
using namespace superblock_detail;
|
|
|
|
|
|
|
|
superblock sb;
|
2020-04-30 19:00:01 +05:30
|
|
|
block_manager::read_ref r = bm.read_lock(location, superblock_validator());
|
2014-07-25 19:16:51 +05:30
|
|
|
superblock_disk const *sbd = reinterpret_cast<superblock_disk const *>(r.data());
|
2013-05-21 20:19:20 +05:30
|
|
|
superblock_traits::unpack(*sbd, sb);
|
|
|
|
return sb;
|
|
|
|
}
|
|
|
|
|
2020-04-30 19:00:01 +05:30
|
|
|
superblock_detail::superblock read_superblock(block_manager::ptr bm, block_address location)
|
2016-02-26 18:20:17 +05:30
|
|
|
{
|
|
|
|
return read_superblock(*bm, location);
|
|
|
|
}
|
|
|
|
|
2020-04-30 19:00:01 +05:30
|
|
|
superblock_detail::superblock read_superblock(block_manager::ptr bm)
|
2013-07-16 21:09:40 +05:30
|
|
|
{
|
|
|
|
return read_superblock(bm, SUPERBLOCK_LOCATION);
|
|
|
|
}
|
|
|
|
|
2020-04-30 19:00:01 +05:30
|
|
|
superblock_detail::superblock read_superblock(block_manager const &bm)
|
2016-02-26 18:20:17 +05:30
|
|
|
{
|
|
|
|
return read_superblock(bm, SUPERBLOCK_LOCATION);
|
|
|
|
}
|
|
|
|
|
2020-04-30 19:00:01 +05:30
|
|
|
void write_superblock(block_manager::ptr bm, superblock_detail::superblock const &sb)
|
2014-03-27 17:30:17 +05:30
|
|
|
{
|
2020-04-30 19:00:01 +05:30
|
|
|
block_manager::write_ref w = bm->write_lock(SUPERBLOCK_LOCATION, superblock_validator());
|
2014-07-25 19:16:51 +05:30
|
|
|
superblock_disk *disk = reinterpret_cast<superblock_disk *>(w.data());
|
2014-03-27 17:30:17 +05:30
|
|
|
superblock_traits::pack(sb, *disk);
|
|
|
|
}
|
|
|
|
|
2013-05-21 18:31:17 +05:30
|
|
|
void
|
2020-04-30 19:00:01 +05:30
|
|
|
check_superblock(block_manager::ptr bm,
|
2020-06-09 18:49:59 +05:30
|
|
|
superblock_detail::damage_visitor &visitor,
|
|
|
|
block_address sb_location) {
|
2013-05-21 18:31:17 +05:30
|
|
|
using namespace superblock_detail;
|
|
|
|
|
|
|
|
try {
|
2020-06-09 18:49:59 +05:30
|
|
|
bm->read_lock(sb_location, superblock_validator());
|
2013-05-21 18:31:17 +05:30
|
|
|
|
|
|
|
} catch (std::exception const &e) {
|
|
|
|
visitor.visit(superblock_corruption(e.what()));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//----------------------------------------------------------------
|