Suport variable blocksizes in dm-bow restore

Test: Test that restore still works
Change-Id: I7259e3efd1cd0ee13c74336a7e53158b6bceed57
This commit is contained in:
Paul Lawrence 2019-01-10 13:06:07 -08:00
parent d6bbe746d7
commit 4f13a90a58

View file

@ -233,7 +233,6 @@ Status cp_prepareCheckpoint() {
} }
namespace { namespace {
const int kBlockSize = 4096;
const int kSectorSize = 512; const int kSectorSize = 512;
typedef uint64_t sector_t; typedef uint64_t sector_t;
@ -247,6 +246,7 @@ struct log_entry {
struct log_sector { struct log_sector {
uint32_t magic; uint32_t magic;
uint32_t block_size;
uint32_t count; uint32_t count;
uint32_t sequence; uint32_t sequence;
uint64_t sector0; uint64_t sector0;
@ -308,20 +308,21 @@ void crc32(const void* data, size_t n_bytes, uint32_t* crc) {
} }
} }
} // namespace void read(std::fstream& device, std::vector<log_entry> const& logs, sector_t sector, char* buffer,
uint32_t block_size) {
static void read(std::fstream& device, std::vector<log_entry> const& logs, sector_t sector, // Crude approach at first where we do this sector by sector and just scan
char* buffer) { // the entire logs for remappings each time
for (auto l = logs.rbegin(); l != logs.rend(); l++) for (auto l = logs.rbegin(); l != logs.rend(); l++)
if (sector >= l->source && (sector - l->source) * kSectorSize < l->size) if (sector >= l->source && (sector - l->source) * kSectorSize < l->size)
sector = sector - l->source + l->dest; sector = sector - l->source + l->dest;
device.seekg(sector * kSectorSize); device.seekg(sector * kSectorSize);
device.read(buffer, kBlockSize); device.read(buffer, block_size);
} }
static std::vector<char> read(std::fstream& device, std::vector<log_entry> const& logs, // Read from the device as though we were restoring, even if we are validating
bool validating, sector_t sector, uint32_t size) { std::vector<char> read(std::fstream& device, std::vector<log_entry> const& logs, bool validating,
sector_t sector, uint32_t size, uint32_t block_size) {
if (!validating) { if (!validating) {
std::vector<char> buffer(size); std::vector<char> buffer(size);
device.seekg(sector * kSectorSize); device.seekg(sector * kSectorSize);
@ -329,16 +330,15 @@ static std::vector<char> read(std::fstream& device, std::vector<log_entry> const
return buffer; return buffer;
} }
// Crude approach at first where we do this sector by sector and just scan
// the entire logs for remappings each time
std::vector<char> buffer(size); std::vector<char> buffer(size);
for (uint32_t i = 0; i < size; i += block_size, sector += block_size / kSectorSize)
for (uint32_t i = 0; i < size; i += kBlockSize, sector += kBlockSize / kSectorSize) read(device, logs, sector, &buffer[i], block_size);
read(device, logs, sector, &buffer[i]);
return buffer; return buffer;
} }
} // namespace
Status cp_restoreCheckpoint(const std::string& blockDevice) { Status cp_restoreCheckpoint(const std::string& blockDevice) {
bool validating = true; bool validating = true;
std::string action = "Validating"; std::string action = "Validating";
@ -353,17 +353,19 @@ Status cp_restoreCheckpoint(const std::string& blockDevice) {
PLOG(ERROR) << "Cannot open " << blockDevice; PLOG(ERROR) << "Cannot open " << blockDevice;
return Status::fromExceptionCode(errno, ("Cannot open " + blockDevice).c_str()); return Status::fromExceptionCode(errno, ("Cannot open " + blockDevice).c_str());
} }
auto buffer = read(device, logs, validating, 0, kBlockSize);
log_sector& ls = *reinterpret_cast<log_sector*>(&buffer[0]); log_sector original_ls;
if (ls.magic != kMagic) { device.read(reinterpret_cast<char*>(&original_ls), sizeof(original_ls));
if (original_ls.magic != kMagic) {
LOG(ERROR) << "No magic"; LOG(ERROR) << "No magic";
return Status::fromExceptionCode(EINVAL, "No magic"); return Status::fromExceptionCode(EINVAL, "No magic");
} }
LOG(INFO) << action << " " << ls.sequence << " log sectors"; LOG(INFO) << action << " " << original_ls.sequence << " log sectors";
for (int sequence = ls.sequence; sequence >= 0 && status.isOk(); sequence--) { for (int sequence = original_ls.sequence; sequence >= 0 && status.isOk(); sequence--) {
auto buffer = read(device, logs, validating, 0, kBlockSize); auto buffer =
read(device, logs, validating, 0, original_ls.block_size, original_ls.block_size);
log_sector& ls = *reinterpret_cast<log_sector*>(&buffer[0]); log_sector& ls = *reinterpret_cast<log_sector*>(&buffer[0]);
if (ls.magic != kMagic) { if (ls.magic != kMagic) {
LOG(ERROR) << "No magic!"; LOG(ERROR) << "No magic!";
@ -371,6 +373,12 @@ Status cp_restoreCheckpoint(const std::string& blockDevice) {
break; break;
} }
if (ls.block_size != original_ls.block_size) {
LOG(ERROR) << "Block size mismatch!";
status = Status::fromExceptionCode(EINVAL, "Block size mismatch");
break;
}
if ((int)ls.sequence != sequence) { if ((int)ls.sequence != sequence) {
LOG(ERROR) << "Expecting log sector " << sequence << " but got " << ls.sequence; LOG(ERROR) << "Expecting log sector " << sequence << " but got " << ls.sequence;
status = Status::fromExceptionCode( status = Status::fromExceptionCode(
@ -385,10 +393,10 @@ Status cp_restoreCheckpoint(const std::string& blockDevice) {
for (log_entry* le = &ls.entries[ls.count - 1]; le >= ls.entries; --le) { for (log_entry* le = &ls.entries[ls.count - 1]; le >= ls.entries; --le) {
LOG(INFO) << action << " " << le->size << " bytes from sector " << le->dest LOG(INFO) << action << " " << le->size << " bytes from sector " << le->dest
<< " to " << le->source << " with checksum " << std::hex << le->checksum; << " to " << le->source << " with checksum " << std::hex << le->checksum;
auto buffer = read(device, logs, validating, le->dest, le->size); auto buffer = read(device, logs, validating, le->dest, le->size, ls.block_size);
uint32_t checksum = le->source / (kBlockSize / kSectorSize); uint32_t checksum = le->source / (ls.block_size / kSectorSize);
for (size_t i = 0; i < le->size; i += kBlockSize) { for (size_t i = 0; i < le->size; i += ls.block_size) {
crc32(&buffer[i], kBlockSize, &checksum); crc32(&buffer[i], ls.block_size, &checksum);
} }
if (le->checksum && checksum != le->checksum) { if (le->checksum && checksum != le->checksum) {
@ -413,9 +421,10 @@ Status cp_restoreCheckpoint(const std::string& blockDevice) {
} }
LOG(WARNING) << "Checkpoint validation failed - attempting to roll forward"; LOG(WARNING) << "Checkpoint validation failed - attempting to roll forward";
auto buffer = read(device, logs, false, ls.sector0, kBlockSize); auto buffer = read(device, logs, false, original_ls.sector0, original_ls.block_size,
original_ls.block_size);
device.seekg(0); device.seekg(0);
device.write(&buffer[0], kBlockSize); device.write(&buffer[0], original_ls.block_size);
return Status::ok(); return Status::ok();
} }