diff --git a/Gemfile.lock b/Gemfile.lock index 1a713da..f7aad93 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -23,7 +23,7 @@ GEM multi_test (0.0.2) rspec-expectations (2.14.2) diff-lcs (>= 1.1.3, < 2.0) - thinp_xml (0.0.9) + thinp_xml (0.0.10) ejt_command_line (= 0.0.2) PLATFORMS diff --git a/caching/cache_dump.cc b/caching/cache_dump.cc index 73467cd..31ca00a 100644 --- a/caching/cache_dump.cc +++ b/caching/cache_dump.cc @@ -4,14 +4,24 @@ #include #include "version.h" +#include "caching/metadata.h" #include "caching/xml_format.h" +#include "persistent-data/file_utils.h" using namespace std; using namespace caching; +using namespace caching::superblock_detail; //---------------------------------------------------------------- namespace { + string to_string(unsigned char const *data) { + // FIXME: we're assuming the data is zero terminated here + return std::string(reinterpret_cast(data)); + } + + //-------------------------------- + string const STDOUT_PATH("-"); bool want_stdout(string const &output) { @@ -19,16 +29,30 @@ namespace { } int dump_(string const &dev, ostream &out) { + block_manager<>::ptr bm = open_bm(dev, block_io<>::READ_ONLY); + metadata::ptr md(new metadata(bm, metadata::OPEN)); emitter::ptr e = create_xml_emitter(out); + + superblock const &sb = md->sb_; + e->begin_superblock(to_string(sb.uuid), sb.data_block_size, sb.cache_blocks, to_string(sb.policy_name)); + e->end_superblock(); + return 0; } int dump(string const &dev, string const &output) { - if (want_stdout(output)) { - ofstream out(output.c_str()); - return dump_(dev, out); - } else - return dump_(dev, cout); + try { + if (want_stdout(output)) + return dump_(dev, cout); + else { + ofstream out(output.c_str()); + return dump_(dev, out); + } + + } catch (std::exception &e) { + cerr << e.what() << endl; + return 1; + } } void usage(ostream &out, string const &cmd) { diff --git a/caching/cache_restore.cc b/caching/cache_restore.cc index 7e64d4c..22cc452 100644 --- a/caching/cache_restore.cc +++ b/caching/cache_restore.cc @@ -20,7 +20,7 @@ using namespace std; namespace { int restore(string const &xml_file, string const &dev) { try { - block_manager<>::ptr bm = open_bm(dev, block_io<>::READ_ONLY); + block_manager<>::ptr bm = open_bm(dev, block_io<>::READ_WRITE); metadata::ptr md(new metadata(bm, metadata::CREATE)); emitter::ptr restorer = create_restore_emitter(md); diff --git a/caching/mapping_array.h b/caching/mapping_array.h index a938466..030ec4f 100644 --- a/caching/mapping_array.h +++ b/caching/mapping_array.h @@ -7,6 +7,11 @@ namespace caching { namespace mapping_array_detail { + enum mapping_flags { + M_VALID = 1, + M_DIRTY = 2 + }; + struct mapping { uint64_t oblock_; uint32_t flags_; diff --git a/caching/metadata.cc b/caching/metadata.cc index f9c02f2..d152874 100644 --- a/caching/metadata.cc +++ b/caching/metadata.cc @@ -1,4 +1,5 @@ #include "caching/metadata.h" +#include "caching/superblock.h" #include "persistent-data/space-maps/core.h" using namespace caching; @@ -27,18 +28,6 @@ namespace { lhs->set_count(b, rhs->get_count(b)); } } - - void init_superblock(superblock &sb) { -#if 0 - sb.magic_ = SUPERBLOCK_MAGIC; - sb.version_ = 1; - sb.data_mapping_root_ = mappings_->get_root(); - sb.device_details_root_ = details_->get_root(); - sb.data_block_size_ = data_block_size; - sb.metadata_block_size_ = MD_BLOCK_SIZE; - sb.metadata_nr_blocks_ = tm_->get_bm()->get_nr_blocks(); -#endif - } } //---------------------------------------------------------------- @@ -46,22 +35,16 @@ namespace { metadata::metadata(block_manager<>::ptr bm, open_type ot) { switch (ot) { - case OPEN: - throw runtime_error("not implemented"); + case CREATE: + create_metadata(bm); break; - case CREATE: - tm_ = open_tm(bm); - space_map::ptr core = tm_->get_sm(); - metadata_sm_ = create_metadata_sm(tm_, tm_->get_bm()->get_nr_blocks()); - copy_space_maps(metadata_sm_, core); - tm_->set_sm(metadata_sm_); + case OPEN: + open_metadata(bm); + break; - mappings_ = mapping_array::ptr(new mapping_array(tm_, mapping_array::ref_counter())); -// hints_ = hint_array::ptr(new hint_array(tm_)); - - ::memset(&sb_, 0, sizeof(sb_)); - init_superblock(sb_); + default: + throw runtime_error("unhandled open_type"); } } @@ -77,4 +60,42 @@ metadata::commit() superblock_traits::pack(sb_, *disk); } +void +metadata::init_superblock() +{ +#if 0 + sb_.magic_ = SUPERBLOCK_MAGIC; + sb_.version_ = 1; + sb_.data_mapping_root_ = mappings_->get_root(); + sb_.device_details_root_ = details_->get_root(); + sb_.data_block_size_ = data_block_size; + sb_.metadata_block_size_ = MD_BLOCK_SIZE; + sb_.metadata_nr_blocks_ = tm_->get_bm()->get_nr_blocks(); +#endif +} + +void +metadata::create_metadata(block_manager<>::ptr bm) +{ + tm_ = open_tm(bm); + + ::memset(&sb_, 0, sizeof(sb_)); + init_superblock(); + + space_map::ptr core = tm_->get_sm(); + metadata_sm_ = create_metadata_sm(tm_, tm_->get_bm()->get_nr_blocks()); + copy_space_maps(metadata_sm_, core); + tm_->set_sm(metadata_sm_); + + mappings_ = mapping_array::ptr(new mapping_array(tm_, mapping_array::ref_counter())); +// hints_ = hint_array::ptr(new hint_array(tm_)); +} + +void +metadata::open_metadata(block_manager<>::ptr bm) +{ + tm_ = open_tm(bm); + sb_ = read_superblock(tm_->get_bm()); +} + //---------------------------------------------------------------- diff --git a/caching/metadata.h b/caching/metadata.h index 7b956a5..20cb3d5 100644 --- a/caching/metadata.h +++ b/caching/metadata.h @@ -35,6 +35,12 @@ namespace caching { checked_space_map::ptr metadata_sm_; mapping_array::ptr mappings_; //hint_array::ptr hints_; + + private: + void init_superblock(); + + void create_metadata(block_manager<>::ptr bm); + void open_metadata(block_manager<>::ptr bm); }; }; diff --git a/caching/restore_emitter.cc b/caching/restore_emitter.cc index efca1de..f871e61 100644 --- a/caching/restore_emitter.cc +++ b/caching/restore_emitter.cc @@ -1,14 +1,15 @@ #include "caching/restore_emitter.h" #include "caching/superblock.h" +#include "caching/mapping_array.h" -using namespace std; using namespace caching; +using namespace mapping_array_detail; +using namespace std; +using namespace superblock_detail; //---------------------------------------------------------------- namespace { - using namespace superblock_detail; - class restorer : public emitter { public: restorer(metadata::ptr md) @@ -54,6 +55,11 @@ namespace { sb.read_misses = 0; sb.write_hits = 0; sb.write_misses = 0; + + struct mapping unmapped_value; + unmapped_value.oblock_ = 0; + unmapped_value.flags_ = 0; + md_->mappings_->grow(nr_cache_blocks, unmapped_value); } virtual void end_superblock() { diff --git a/caching/superblock.cc b/caching/superblock.cc index 4a8b153..e783e16 100644 --- a/caching/superblock.cc +++ b/caching/superblock.cc @@ -141,8 +141,7 @@ caching::superblock_validator() //-------------------------------- superblock_detail::superblock -caching::read_superblock(persistent_data::block_manager<>::ptr bm, - persistent_data::block_address location) +caching::read_superblock(block_manager<>::ptr bm, block_address location) { using namespace superblock_detail; @@ -160,6 +159,24 @@ caching::read_superblock(persistent_data::block_manager<>::ptr bm) return read_superblock(bm, SUPERBLOCK_LOCATION); } +void +caching::write_superblock(block_manager<>::ptr bm, + block_address location, + superblock_detail::superblock const &sb) +{ + using namespace superblock_detail; + + block_manager<>::write_ref w = bm->write_lock(location, superblock_validator()); + superblock_traits::pack(sb, *reinterpret_cast(&w.data())); +} + +void +caching::write_superblock(block_manager<>::ptr bm, + superblock_detail::superblock const &sb) +{ + write_superblock(bm, SUPERBLOCK_LOCATION, sb); +} + void caching::check_superblock(persistent_data::block_manager<>::ptr bm, superblock_detail::damage_visitor &visitor) diff --git a/caching/superblock.h b/caching/superblock.h index f6b9a0c..92db272 100644 --- a/caching/superblock.h +++ b/caching/superblock.h @@ -130,6 +130,13 @@ namespace caching { superblock_detail::superblock read_superblock(persistent_data::block_manager<>::ptr bm); superblock_detail::superblock read_superblock(persistent_data::block_manager<>::ptr bm, persistent_data::block_address location); + + void write_superblock(persistent_data::block_manager<>::ptr bm, + superblock_detail::superblock const &sb); + void write_superblock(persistent_data::block_manager<>::ptr bm, + persistent_data::block_address location, + superblock_detail::superblock const &sb); + void check_superblock(persistent_data::block_manager<>::ptr bm, superblock_detail::damage_visitor &visitor); } diff --git a/features/cache_dump.feature b/features/cache_dump.feature index 15bcecd..6ca41f6 100644 --- a/features/cache_dump.feature +++ b/features/cache_dump.feature @@ -41,6 +41,7 @@ Feature: cache_dump No input file provided. """ + @announce Scenario: dump/restore is a noop Given valid cache metadata When I cache_dump diff --git a/features/cache_restore.feature b/features/cache_restore.feature index 3e8c016..6b649cb 100644 --- a/features/cache_restore.feature +++ b/features/cache_restore.feature @@ -53,6 +53,7 @@ Feature: thin_restore No output file provided. """ + @announce Scenario: successfully restores a valid xml file Given a small xml file And an empty dev file diff --git a/features/step_definitions/cache_steps.rb b/features/step_definitions/cache_steps.rb index 342fd74..68c5739 100644 --- a/features/step_definitions/cache_steps.rb +++ b/features/step_definitions/cache_steps.rb @@ -74,14 +74,14 @@ end Given(/^valid cache metadata$/) do in_current_dir do - system("cache_xml create --nr-cache-blocks uniform[1000-5000] --nr-mappings uniform[500-1000] > #{xml_file}") + system("cache_xml create --nr-cache-blocks uniform[1000..5000] --nr-mappings uniform[500..1000] > #{xml_file}") end run_simple("dd if=/dev/zero of=#{dev_file} bs=4k count=1024") run_simple("cache_restore -i #{xml_file} -o #{dev_file}") end -Then(/^cache dumps (\d+) and (\d+) should be identical$/) do |arg1, arg2| +Then(/^cache dumps (\d+) and (\d+) should be identical$/) do |d1, d2| run_simple("diff -ub #{dump_files[d1.to_i]} #{dump_files[d2.to_i]}", true) end diff --git a/thin-provisioning/superblock.h b/thin-provisioning/superblock.h index a9377b0..d6d78e3 100644 --- a/thin-provisioning/superblock.h +++ b/thin-provisioning/superblock.h @@ -122,6 +122,8 @@ namespace thin_provisioning { persistent_data::block_manager<>::validator::ptr superblock_validator(); + // FIXME: should we put init_superblock in here too? + superblock_detail::superblock read_superblock(persistent_data::block_manager<>::ptr bm); superblock_detail::superblock read_superblock(persistent_data::block_manager<>::ptr bm, persistent_data::block_address location); void check_superblock(persistent_data::block_manager<>::ptr bm,