From 5b92f410eca3121079418659eb81ca2a4e372807 Mon Sep 17 00:00:00 2001 From: Joe Thornber Date: Thu, 28 Sep 2017 14:39:24 +0100 Subject: [PATCH] [*_restore] if things go wrong wipe the superblock. So we don't leave the metadata device with partially restored metadata. --- base/file_utils.cc | 13 +++++++++++++ base/file_utils.h | 1 + caching/cache_restore.cc | 12 +++++++++--- era/era_restore.cc | 6 ++++++ thin-provisioning/thin_restore.cc | 6 ++++++ 5 files changed, 35 insertions(+), 3 deletions(-) diff --git a/base/file_utils.cc b/base/file_utils.cc index d35784e..b8741d2 100644 --- a/base/file_utils.cc +++ b/base/file_utils.cc @@ -9,6 +9,7 @@ #include #include #include +#include //---------------------------------------------------------------- @@ -140,4 +141,16 @@ file_utils::get_file_length(string const &file) { return nr_bytes; } +void +file_utils::zero_superblock(std::string const &path) +{ + unsigned const SUPERBLOCK_SIZE = 4096; + char buffer[SUPERBLOCK_SIZE]; + int fd = open_block_file(path, SUPERBLOCK_SIZE, true, true); + + memset(buffer, 0, SUPERBLOCK_SIZE); + if (::write(fd, buffer, SUPERBLOCK_SIZE) != SUPERBLOCK_SIZE) + throw runtime_error("couldn't zero superblock"); +} + //---------------------------------------------------------------- diff --git a/base/file_utils.h b/base/file_utils.h index d50c273..2ee20ab 100644 --- a/base/file_utils.h +++ b/base/file_utils.h @@ -14,6 +14,7 @@ namespace file_utils { int create_block_file(std::string const &path, off_t file_size); int open_block_file(std::string const &path, off_t min_size, bool writeable, bool excl = true); uint64_t get_file_length(std::string const &file); + void zero_superblock(std::string const &path); } //---------------------------------------------------------------- diff --git a/caching/cache_restore.cc b/caching/cache_restore.cc index 685255e..f4c71a2 100644 --- a/caching/cache_restore.cc +++ b/caching/cache_restore.cc @@ -57,16 +57,20 @@ namespace { } int restore(flags const &fs) { + bool metadata_touched = false; + try { block_manager<>::ptr bm = open_bm(*fs.output, block_manager<>::READ_WRITE); + + check_file_exists(*fs.input); + ifstream in(fs.input->c_str(), ifstream::in); + + metadata_touched = true; metadata::ptr md(new metadata(bm, metadata::CREATE)); emitter::ptr restorer = create_restore_emitter(md, fs.metadata_version, fs.clean_shutdown ? CLEAN_SHUTDOWN : NO_CLEAN_SHUTDOWN); - check_file_exists(*fs.input); - ifstream in(fs.input->c_str(), ifstream::in); - unique_ptr monitor = create_monitor(fs.quiet); parse_xml(in, restorer, get_file_length(*fs.input), *monitor); @@ -74,6 +78,8 @@ namespace { override_version(md, fs); } catch (std::exception &e) { + if (metadata_touched) + zero_superblock(*fs.output); cerr << e.what() << endl; return 1; } diff --git a/era/era_restore.cc b/era/era_restore.cc index 97dff35..6eb9343 100644 --- a/era/era_restore.cc +++ b/era/era_restore.cc @@ -1,5 +1,6 @@ #include "version.h" +#include "base/file_utils.h" #include "base/output_file_requirements.h" #include "era/commands.h" #include "era/metadata.h" @@ -33,14 +34,19 @@ namespace { }; int restore(flags const &fs, bool quiet) { + bool metadata_touched = false; try { block_manager<>::ptr bm = open_bm(*fs.output, block_manager<>::READ_WRITE); + file_utils::check_file_exists(*fs.output); + metadata_touched = true; metadata::ptr md(new metadata(bm, metadata::CREATE)); emitter::ptr restorer = create_restore_emitter(*md); parse_xml(*fs.input, restorer, fs.quiet); } catch (std::exception &e) { + if (metadata_touched) + file_utils::zero_superblock(*fs.output); cerr << e.what() << endl; return 1; } diff --git a/thin-provisioning/thin_restore.cc b/thin-provisioning/thin_restore.cc index 6c23c04..fb052fa 100644 --- a/thin-provisioning/thin_restore.cc +++ b/thin-provisioning/thin_restore.cc @@ -16,6 +16,7 @@ // with thin-provisioning-tools. If not, see // . +#include "base/file_utils.h" #include "base/output_file_requirements.h" #include "persistent-data/file_utils.h" #include "thin-provisioning/commands.h" @@ -44,15 +45,20 @@ using namespace thin_provisioning; namespace { int restore(string const &backup_file, string const &dev, bool quiet) { + bool metadata_touched = false; try { // The block size gets updated by the restorer. block_manager<>::ptr bm(open_bm(dev, block_manager<>::READ_WRITE)); + file_utils::check_file_exists(backup_file); + metadata_touched = true; metadata::ptr md(new metadata(bm, metadata::CREATE, 128, 0)); emitter::ptr restorer = create_restore_emitter(md); parse_xml(backup_file, restorer, quiet); } catch (std::exception &e) { + if (metadata_touched) + file_utils::zero_superblock(dev); cerr << e.what() << endl; return 1; }