thin-provisioning-tools/thin-provisioning/superblock.h

149 lines
4.0 KiB
C++

#ifndef THIN_SUPERBLOCK_H
#define THIN_SUPERBLOCK_H
#include "base/endian_utils.h"
#include "persistent-data/block.h"
#include "persistent-data/data-structures/ref_counter.h"
//----------------------------------------------------------------
namespace thin_provisioning {
namespace superblock_detail {
using namespace base;
using namespace persistent_data;
unsigned const SPACE_MAP_ROOT_SIZE = 128;
typedef unsigned char __u8;
struct superblock_disk {
le32 csum_;
le32 flags_;
le64 blocknr_;
__u8 uuid_[16];
le64 magic_;
le32 version_;
le32 time_;
le64 trans_id_;
/* root for userspace's transaction (for migration and friends) */
le64 metadata_snap_;
__u8 data_space_map_root_[SPACE_MAP_ROOT_SIZE];
__u8 metadata_space_map_root_[SPACE_MAP_ROOT_SIZE];
/* 2 level btree mapping (dev_id, (dev block, time)) -> data block */
le64 data_mapping_root_;
/* device detail root mapping dev_id -> device_details */
le64 device_details_root_;
le32 data_block_size_; /* in 512-byte sectors */
le32 metadata_block_size_; /* in 512-byte sectors */
le64 metadata_nr_blocks_;
le32 compat_flags_;
le32 compat_ro_flags_;
le32 incompat_flags_;
} __attribute__ ((packed));
struct superblock {
uint32_t csum_;
uint32_t flags_;
uint64_t blocknr_;
unsigned char uuid_[16];
uint64_t magic_;
uint32_t version_;
uint32_t time_;
uint64_t trans_id_;
/* root for userspace's transaction (for migration and friends) */
uint64_t metadata_snap_;
unsigned char data_space_map_root_[SPACE_MAP_ROOT_SIZE];
unsigned char metadata_space_map_root_[SPACE_MAP_ROOT_SIZE];
/* 2 level btree mapping (dev_id, (dev block, time)) -> data block */
uint64_t data_mapping_root_;
/* device detail root mapping dev_id -> device_details */
uint64_t device_details_root_;
uint32_t data_block_size_; /* in 512-byte sectors */
uint32_t metadata_block_size_; /* in 512-byte sectors */
uint64_t metadata_nr_blocks_;
uint32_t compat_flags_;
uint32_t compat_ro_flags_;
uint32_t incompat_flags_;
bool get_needs_check_flag() const;
void set_needs_check_flag(bool val = true);
};
struct superblock_traits {
typedef superblock_disk disk_type;
typedef superblock value_type;
typedef no_op_ref_counter<superblock> ref_counter;
static void unpack(superblock_disk const &disk, superblock &core);
static void pack(superblock const &core, superblock_disk &disk);
};
block_address const SUPERBLOCK_LOCATION = 0;
uint32_t const SUPERBLOCK_MAGIC = 27022010;
uint32_t const METADATA_VERSION = 2;
//--------------------------------
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;
};
}
bcache::validator::ptr superblock_validator();
// FIXME: should we put init_superblock in here too?
// FIXME: make the bm const, and pass by reference rather than ptr
superblock_detail::superblock read_superblock(persistent_data::block_manager const &bm);
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 check_superblock(persistent_data::block_manager::ptr bm,
superblock_detail::damage_visitor &visitor,
persistent_data::block_address sb_location = superblock_detail::SUPERBLOCK_LOCATION);
}
//----------------------------------------------------------------
#endif