diff --git a/Makefile.in b/Makefile.in
index 505166d..0d19c7f 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -48,7 +48,7 @@ PDATA_SOURCE=\
SOURCE=\
$(PDATA_SOURCE) \
\
- cache/metadata_disk_structures.cc \
+ caching/superblock.cc \
\
thin-provisioning/device_tree.cc \
thin-provisioning/file_utils.cc \
@@ -66,7 +66,7 @@ SOURCE=\
PDATA_OBJECTS=$(subst .cc,.o,$(SOURCE))
CXX_PROGRAM_SOURCE=\
- cache/check.cc \
+ caching/check.cc \
\
thin-provisioning/thin_check.cc \
thin-provisioning/thin_dump.cc \
@@ -228,11 +228,11 @@ CACHE_CHECK_SOURCE=\
persistent-data/space-maps/recursive.cc \
persistent-data/space-maps/careful_alloc.cc \
persistent-data/transaction_manager.cc \
- cache/metadata_disk_structures.cc
+ caching/superblock.cc
CACHE_CHECK_OBJECTS=$(subst .cc,.o,$(CACHE_CHECK_SOURCE))
-cache_check: $(CACHE_CHECK_OBJECTS) cache/check.o
+cache_check: $(CACHE_CHECK_OBJECTS) caching/check.o
@echo " [LD] $@"
$(V) $(CXX) $(CXXFLAGS) $(LDFLAGS) -o $@ $+ $(LIBS)
diff --git a/cache/metadata_disk_structures.h b/cache/metadata_disk_structures.h
deleted file mode 100644
index fe6d261..0000000
--- a/cache/metadata_disk_structures.h
+++ /dev/null
@@ -1,120 +0,0 @@
-// Copyright (C) 2012 Red Hat, Inc. All rights reserved.
-//
-// This file is part of the thin-provisioning-tools source.
-//
-// thin-provisioning-tools is free software: you can redistribute it
-// and/or modify it under the terms of the GNU General Public License
-// as published by the Free Software Foundation, either version 3 of
-// the License, or (at your option) any later version.
-//
-// thin-provisioning-tools is distributed in the hope that it will be
-// useful, but WITHOUT ANY WARRANTY; without even the implied warranty
-// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License along
-// with thin-provisioning-tools. If not, see
-// .
-
-#ifndef CACHE_METADATA_DISK_STRUCTURES_H
-#define CACHE_METADATA_DISK_STRUCTURES_H
-
-#include "persistent-data/endian_utils.h"
-#include "persistent-data/data-structures/btree.h"
-
-//----------------------------------------------------------------
-
-// FIXME: rename to just METADATA_DISK_STRUCTURES
-namespace cache_tools {
- using namespace base; // FIXME: don't use namespaces in headers.
-
- unsigned const SPACE_MAP_ROOT_SIZE = 128;
- unsigned const CACHE_POLICY_NAME_SIZE = 16;
- unsigned const CACHE_POLICY_VERSION_SIZE = 3;
-
- typedef unsigned char __u8;
-
- struct superblock_disk {
- le32 csum;
- le32 flags;
- le64 blocknr;
-
- __u8 uuid[16];
- le64 magic;
- le32 version;
-
- __u8 policy_name[CACHE_POLICY_NAME_SIZE];
- le32 policy_version[CACHE_POLICY_VERSION_SIZE];
- le32 policy_hint_size;
-
- __u8 metadata_space_map_root[SPACE_MAP_ROOT_SIZE];
-
- le64 mapping_root;
- le64 hint_root;
-
- le64 discard_root;
- le64 discard_block_size;
- le64 discard_nr_blocks;
-
- le32 data_block_size; /* in 512-byte sectors */
- le32 metadata_block_size; /* in 512-byte sectors */
- le32 cache_blocks;
-
- le32 compat_flags;
- le32 compat_ro_flags;
- le32 incompat_flags;
-
- le32 read_hits;
- le32 read_misses;
- le32 write_hits;
- le32 write_misses;
- } __attribute__ ((packed));
-
- struct superblock {
- uint32_t csum;
- uint32_t flags;
- uint64_t blocknr;
-
- __u8 uuid[16];
- uint64_t magic;
- uint32_t version;
-
- __u8 policy_name[CACHE_POLICY_NAME_SIZE];
- uint32_t policy_version[CACHE_POLICY_VERSION_SIZE];
- uint32_t policy_hint_size;
-
- __u8 metadata_space_map_root[SPACE_MAP_ROOT_SIZE];
-
- uint64_t mapping_root;
- uint64_t hint_root;
-
- uint64_t discard_root;
- uint64_t discard_block_size;
- uint64_t discard_nr_blocks;
-
- uint32_t data_block_size; /* in 512-byte sectors */
- uint32_t metadata_block_size; /* in 512-byte sectors */
- uint32_t cache_blocks;
-
- uint32_t compat_flags;
- uint32_t compat_ro_flags;
- uint32_t incompat_flags;
-
- uint32_t read_hits;
- uint32_t read_misses;
- uint32_t write_hits;
- uint32_t write_misses;
- };
-
- struct superblock_traits {
- typedef superblock_disk disk_type;
- typedef superblock value_type;
-
- static void unpack(superblock_disk const &disk, superblock &value);
- static void pack(superblock const &value, superblock_disk &disk);
- };
-}
-
-//----------------------------------------------------------------
-
-#endif
diff --git a/cache/cache_metadata.h b/caching/cache_metadata.h
similarity index 100%
rename from cache/cache_metadata.h
rename to caching/cache_metadata.h
diff --git a/cache/check.cc b/caching/check.cc
similarity index 100%
rename from cache/check.cc
rename to caching/check.cc
diff --git a/cache/dump.cc b/caching/dump.cc
similarity index 100%
rename from cache/dump.cc
rename to caching/dump.cc
diff --git a/caching/metadata_disk_structures.cc b/caching/metadata_disk_structures.cc
new file mode 100644
index 0000000..8face77
--- /dev/null
+++ b/caching/metadata_disk_structures.cc
@@ -0,0 +1,28 @@
+// Copyright (C) 2012 Red Hat, Inc. All rights reserved.
+//
+// This file is part of the thin-provisioning-tools source.
+//
+// thin-provisioning-tools is free software: you can redistribute it
+// and/or modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation, either version 3 of
+// the License, or (at your option) any later version.
+//
+// thin-provisioning-tools is distributed in the hope that it will be
+// useful, but WITHOUT ANY WARRANTY; without even the implied warranty
+// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with thin-provisioning-tools. If not, see
+// .
+
+#include "metadata_disk_structures.h"
+
+#include
+
+using namespace cache_tools;
+
+//----------------------------------------------------------------
+
+
+//----------------------------------------------------------------
diff --git a/caching/metadata_disk_structures.h b/caching/metadata_disk_structures.h
new file mode 100644
index 0000000..ef2363e
--- /dev/null
+++ b/caching/metadata_disk_structures.h
@@ -0,0 +1,35 @@
+// Copyright (C) 2012 Red Hat, Inc. All rights reserved.
+//
+// This file is part of the thin-provisioning-tools source.
+//
+// thin-provisioning-tools is free software: you can redistribute it
+// and/or modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation, either version 3 of
+// the License, or (at your option) any later version.
+//
+// thin-provisioning-tools is distributed in the hope that it will be
+// useful, but WITHOUT ANY WARRANTY; without even the implied warranty
+// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with thin-provisioning-tools. If not, see
+// .
+
+#ifndef CACHE_METADATA_DISK_STRUCTURES_H
+#define CACHE_METADATA_DISK_STRUCTURES_H
+
+#include "persistent-data/endian_utils.h"
+#include "persistent-data/data-structures/btree.h"
+
+//----------------------------------------------------------------
+
+// FIXME: rename to just METADATA_DISK_STRUCTURES
+namespace cache_tools {
+ using namespace base; // FIXME: don't use namespaces in headers.
+
+}
+
+//----------------------------------------------------------------
+
+#endif
diff --git a/cache/metadata_disk_structures.cc b/caching/superblock.cc
similarity index 59%
rename from cache/metadata_disk_structures.cc
rename to caching/superblock.cc
index d822fbd..4a8b153 100644
--- a/cache/metadata_disk_structures.cc
+++ b/caching/superblock.cc
@@ -1,26 +1,7 @@
-// Copyright (C) 2012 Red Hat, Inc. All rights reserved.
-//
-// This file is part of the thin-provisioning-tools source.
-//
-// thin-provisioning-tools is free software: you can redistribute it
-// and/or modify it under the terms of the GNU General Public License
-// as published by the Free Software Foundation, either version 3 of
-// the License, or (at your option) any later version.
-//
-// thin-provisioning-tools is distributed in the hope that it will be
-// useful, but WITHOUT ANY WARRANTY; without even the implied warranty
-// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License along
-// with thin-provisioning-tools. If not, see
-// .
+#include "caching/superblock.h"
-#include "metadata_disk_structures.h"
-
-#include
-
-using namespace cache_tools;
+using namespace caching;
+using namespace superblock_detail;
//----------------------------------------------------------------
@@ -110,4 +91,87 @@ superblock_traits::pack(superblock const &core, superblock_disk &disk)
disk.write_misses = to_disk(core.write_misses);
}
+//--------------------------------
+
+superblock_corruption::superblock_corruption(std::string const &desc)
+ : desc_(desc)
+{
+}
+
+void
+superblock_corruption::visit(damage_visitor &v) const
+{
+ v.visit(*this);
+}
+
+//--------------------------------
+
+namespace {
+ using namespace persistent_data;
+ using namespace superblock_detail;
+
+ uint32_t const VERSION = 1;
+ unsigned const SECTOR_TO_BLOCK_SHIFT = 3;
+ uint32_t const SUPERBLOCK_CSUM_SEED = 9031977;
+
+ struct sb_validator : public block_manager<>::validator {
+ virtual void check(buffer<> const &b, block_address location) const {
+ superblock_disk const *sbd = reinterpret_cast(&b);
+ crc32c sum(SUPERBLOCK_CSUM_SEED);
+ sum.append(&sbd->flags, MD_BLOCK_SIZE - sizeof(uint32_t));
+ if (sum.get_sum() != to_cpu(sbd->csum))
+ throw checksum_error("bad checksum in superblock");
+ }
+
+ virtual void prepare(buffer<> &b, block_address location) const {
+ superblock_disk *sbd = reinterpret_cast(&b);
+ crc32c sum(SUPERBLOCK_CSUM_SEED);
+ sum.append(&sbd->flags, MD_BLOCK_SIZE - sizeof(uint32_t));
+ sbd->csum = to_disk(sum.get_sum());
+ }
+ };
+}
+
+persistent_data::block_manager<>::validator::ptr
+caching::superblock_validator()
+{
+ return block_manager<>::validator::ptr(new sb_validator);
+}
+
+//--------------------------------
+
+superblock_detail::superblock
+caching::read_superblock(persistent_data::block_manager<>::ptr bm,
+ persistent_data::block_address location)
+{
+ using namespace superblock_detail;
+
+ superblock sb;
+ block_manager<>::read_ref r = bm->read_lock(location, superblock_validator());
+ superblock_disk const *sbd = reinterpret_cast(&r.data());
+ superblock_traits::unpack(*sbd, sb);
+
+ return sb;
+}
+
+superblock_detail::superblock
+caching::read_superblock(persistent_data::block_manager<>::ptr bm)
+{
+ return read_superblock(bm, SUPERBLOCK_LOCATION);
+}
+
+void
+caching::check_superblock(persistent_data::block_manager<>::ptr bm,
+ superblock_detail::damage_visitor &visitor)
+{
+ using namespace superblock_detail;
+
+ try {
+ bm->read_lock(SUPERBLOCK_LOCATION, superblock_validator());
+
+ } catch (std::exception const &e) {
+ visitor.visit(superblock_corruption(e.what()));
+ }
+}
+
//----------------------------------------------------------------
diff --git a/caching/superblock.h b/caching/superblock.h
new file mode 100644
index 0000000..f6b9a0c
--- /dev/null
+++ b/caching/superblock.h
@@ -0,0 +1,139 @@
+#ifndef CACHE_SUPERBLOCK_H
+#define CACHE_SUPERBLOCK_H
+
+#include "persistent-data/endian_utils.h"
+#include "persistent-data/data-structures/btree.h"
+
+//----------------------------------------------------------------
+
+namespace caching {
+ namespace superblock_detail {
+ using namespace base;
+
+ unsigned const SPACE_MAP_ROOT_SIZE = 128;
+ unsigned const CACHE_POLICY_NAME_SIZE = 16;
+ unsigned const CACHE_POLICY_VERSION_SIZE = 3;
+
+ typedef unsigned char __u8;
+
+ struct superblock_disk {
+ le32 csum;
+ le32 flags;
+ le64 blocknr;
+
+ __u8 uuid[16];
+ le64 magic;
+ le32 version;
+
+ __u8 policy_name[CACHE_POLICY_NAME_SIZE];
+ le32 policy_version[CACHE_POLICY_VERSION_SIZE];
+ le32 policy_hint_size;
+
+ __u8 metadata_space_map_root[SPACE_MAP_ROOT_SIZE];
+
+ le64 mapping_root;
+ le64 hint_root;
+
+ le64 discard_root;
+ le64 discard_block_size;
+ le64 discard_nr_blocks;
+
+ le32 data_block_size; /* in 512-byte sectors */
+ le32 metadata_block_size; /* in 512-byte sectors */
+ le32 cache_blocks;
+
+ le32 compat_flags;
+ le32 compat_ro_flags;
+ le32 incompat_flags;
+
+ le32 read_hits;
+ le32 read_misses;
+ le32 write_hits;
+ le32 write_misses;
+ } __attribute__ ((packed));
+
+ struct superblock {
+ uint32_t csum;
+ uint32_t flags;
+ uint64_t blocknr;
+
+ __u8 uuid[16];
+ uint64_t magic;
+ uint32_t version;
+
+ __u8 policy_name[CACHE_POLICY_NAME_SIZE];
+ uint32_t policy_version[CACHE_POLICY_VERSION_SIZE];
+ uint32_t policy_hint_size;
+
+ __u8 metadata_space_map_root[SPACE_MAP_ROOT_SIZE];
+
+ uint64_t mapping_root;
+ uint64_t hint_root;
+
+ uint64_t discard_root;
+ uint64_t discard_block_size;
+ uint64_t discard_nr_blocks;
+
+ uint32_t data_block_size; /* in 512-byte sectors */
+ uint32_t metadata_block_size; /* in 512-byte sectors */
+ uint32_t cache_blocks;
+
+ uint32_t compat_flags;
+ uint32_t compat_ro_flags;
+ uint32_t incompat_flags;
+
+ uint32_t read_hits;
+ uint32_t read_misses;
+ uint32_t write_hits;
+ uint32_t write_misses;
+ };
+
+ struct superblock_traits {
+ typedef superblock_disk disk_type;
+ typedef superblock value_type;
+
+ static void unpack(superblock_disk const &disk, superblock &value);
+ static void pack(superblock const &value, superblock_disk &disk);
+ };
+
+ block_address const SUPERBLOCK_LOCATION = 0;
+ uint32_t const SUPERBLOCK_MAGIC = 06142003;
+
+ //--------------------------------
+
+ class damage_visitor;
+
+ struct damage {
+ virtual ~damage() {}
+ virtual void visit(damage_visitor &v) const = 0;
+ };
+
+ struct superblock_corruption : public damage {
+ superblock_corruption(std::string const &desc);
+ void visit(damage_visitor &v) const;
+
+ std::string desc_;
+ };
+
+ class damage_visitor {
+ public:
+ virtual ~damage_visitor() {}
+
+ void visit(damage const &d);
+
+ virtual void visit(superblock_corruption const &d) = 0;
+ };
+ }
+
+ persistent_data::block_manager<>::validator::ptr superblock_validator();
+
+ 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,
+ superblock_detail::damage_visitor &visitor);
+}
+
+//----------------------------------------------------------------
+
+#endif