[cache] a lot of format 2 changes
This commit is contained in:
parent
bce4acf214
commit
05c4b7b400
@ -248,7 +248,12 @@ namespace {
|
|||||||
{
|
{
|
||||||
nested_output::nest _ = out.push();
|
nested_output::nest _ = out.push();
|
||||||
mapping_array ma(*tm, mapping_array::ref_counter(), sb.mapping_root, sb.cache_blocks);
|
mapping_array ma(*tm, mapping_array::ref_counter(), sb.mapping_root, sb.cache_blocks);
|
||||||
check_mapping_array(ma, mapping_rep);
|
check_mapping_array(ma, mapping_rep, sb.version);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sb.version >= 2) {
|
||||||
|
persistent_data::bitset dirty(*tm, *sb.dirty_root, sb.cache_blocks);
|
||||||
|
// FIXME: is there no bitset checker?
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -275,6 +280,7 @@ namespace {
|
|||||||
{
|
{
|
||||||
nested_output::nest _ = out.push();
|
nested_output::nest _ = out.push();
|
||||||
persistent_data::bitset discards(*tm, sb.discard_root, sb.discard_nr_blocks);
|
persistent_data::bitset discards(*tm, sb.discard_root, sb.discard_nr_blocks);
|
||||||
|
// FIXME: is there no bitset checker?
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -43,29 +43,33 @@ namespace {
|
|||||||
struct flags {
|
struct flags {
|
||||||
flags()
|
flags()
|
||||||
: metadata_version(1),
|
: metadata_version(1),
|
||||||
override_metadata_version(false),
|
|
||||||
clean_shutdown(true),
|
clean_shutdown(true),
|
||||||
quiet(false) {
|
quiet(false),
|
||||||
|
override_metadata_version(false),
|
||||||
|
override_version(1) {
|
||||||
}
|
}
|
||||||
|
|
||||||
optional<string> input;
|
optional<string> input;
|
||||||
optional<string> output;
|
optional<string> output;
|
||||||
|
|
||||||
uint32_t metadata_version;
|
uint32_t metadata_version;
|
||||||
bool override_metadata_version;
|
|
||||||
bool clean_shutdown;
|
bool clean_shutdown;
|
||||||
bool quiet;
|
bool quiet;
|
||||||
|
|
||||||
|
bool override_metadata_version;
|
||||||
|
unsigned override_version;
|
||||||
};
|
};
|
||||||
|
|
||||||
int restore(flags const &fs) {
|
int restore(flags const &fs) {
|
||||||
try {
|
try {
|
||||||
block_manager<>::ptr bm = open_bm(*fs.output, block_manager<>::READ_WRITE);
|
block_manager<>::ptr bm = open_bm(*fs.output, block_manager<>::READ_WRITE);
|
||||||
metadata::ptr md(new metadata(bm, metadata::CREATE));
|
metadata::ptr md(new metadata(bm, metadata::CREATE));
|
||||||
emitter::ptr restorer = create_restore_emitter(md, fs.clean_shutdown);
|
emitter::ptr restorer = create_restore_emitter(md, fs.clean_shutdown,
|
||||||
|
fs.metadata_version);
|
||||||
|
|
||||||
if (fs.override_metadata_version) {
|
if (fs.override_metadata_version) {
|
||||||
cerr << "overriding" << endl;
|
cerr << "overriding" << endl;
|
||||||
md->sb_.version = fs.metadata_version;
|
md->sb_.version = fs.override_version;
|
||||||
}
|
}
|
||||||
|
|
||||||
check_file_exists(*fs.input);
|
check_file_exists(*fs.input);
|
||||||
@ -95,12 +99,13 @@ cache_restore_cmd::usage(std::ostream &out) const
|
|||||||
{
|
{
|
||||||
out << "Usage: " << get_name() << " [options]" << endl
|
out << "Usage: " << get_name() << " [options]" << endl
|
||||||
<< "Options:" << endl
|
<< "Options:" << endl
|
||||||
<< " {-h|--help}" << endl
|
<< " {-h|--help}\n"
|
||||||
<< " {-i|--input} <input xml file>" << endl
|
<< " {-i|--input} <input xml file>\n"
|
||||||
<< " {-o|--output} <output device or file>" << endl
|
<< " {-o|--output} <output device or file>\n"
|
||||||
<< " {-q|--quiet}" << endl
|
<< " {-q|--quiet}\n"
|
||||||
<< " {-V|--version}" << endl
|
<< " {--metadata-version} <1 or 2>\n"
|
||||||
<< endl
|
<< " {-V|--version}\n"
|
||||||
|
<< "\n"
|
||||||
<< " {--debug-override-metadata-version} <integer>" << endl
|
<< " {--debug-override-metadata-version} <integer>" << endl
|
||||||
<< " {--omit-clean-shutdown}" << endl;
|
<< " {--omit-clean-shutdown}" << endl;
|
||||||
}
|
}
|
||||||
@ -114,6 +119,7 @@ cache_restore_cmd::run(int argc, char **argv)
|
|||||||
option const long_opts[] = {
|
option const long_opts[] = {
|
||||||
{ "debug-override-metadata-version", required_argument, NULL, 0 },
|
{ "debug-override-metadata-version", required_argument, NULL, 0 },
|
||||||
{ "omit-clean-shutdown", no_argument, NULL, 1 },
|
{ "omit-clean-shutdown", no_argument, NULL, 1 },
|
||||||
|
{ "metadata-version", required_argument, NULL, 2 },
|
||||||
{ "help", no_argument, NULL, 'h'},
|
{ "help", no_argument, NULL, 'h'},
|
||||||
{ "input", required_argument, NULL, 'i' },
|
{ "input", required_argument, NULL, 'i' },
|
||||||
{ "output", required_argument, NULL, 'o'},
|
{ "output", required_argument, NULL, 'o'},
|
||||||
@ -125,14 +131,23 @@ cache_restore_cmd::run(int argc, char **argv)
|
|||||||
while ((c = getopt_long(argc, argv, short_opts, long_opts, NULL)) != -1) {
|
while ((c = getopt_long(argc, argv, short_opts, long_opts, NULL)) != -1) {
|
||||||
switch(c) {
|
switch(c) {
|
||||||
case 0:
|
case 0:
|
||||||
fs.metadata_version = lexical_cast<uint32_t>(optarg);
|
|
||||||
fs.override_metadata_version = true;
|
fs.override_metadata_version = true;
|
||||||
|
fs.override_version = lexical_cast<uint32_t>(optarg);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 1:
|
case 1:
|
||||||
fs.clean_shutdown = false;
|
fs.clean_shutdown = false;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case 2:
|
||||||
|
fs.metadata_version = lexical_cast<uint32_t>(optarg);
|
||||||
|
if ((fs.metadata_version < MIN_METADATA_VERSION) ||
|
||||||
|
(fs.metadata_version > MAX_METADATA_VERSION)) {
|
||||||
|
cerr << "Bad metadata version\n\n";
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
case 'h':
|
case 'h':
|
||||||
usage(cout);
|
usage(cout);
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -60,8 +60,9 @@ invalid_mapping::visit(damage_visitor &v) const
|
|||||||
namespace {
|
namespace {
|
||||||
class check_mapping_visitor : public mapping_visitor {
|
class check_mapping_visitor : public mapping_visitor {
|
||||||
public:
|
public:
|
||||||
check_mapping_visitor(damage_visitor &visitor)
|
check_mapping_visitor(damage_visitor &visitor, unsigned metadata_version)
|
||||||
: visitor_(visitor) {
|
: visitor_(visitor),
|
||||||
|
allowed_flags_(metadata_version == 1 ? (M_VALID | M_DIRTY) : M_VALID) {
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void visit(block_address cblock, mapping const &m) {
|
virtual void visit(block_address cblock, mapping const &m) {
|
||||||
@ -90,12 +91,13 @@ namespace {
|
|||||||
seen_oblocks_.insert(m.oblock_);
|
seen_oblocks_.insert(m.oblock_);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool unknown_flags(mapping const &m) {
|
bool unknown_flags(mapping const &m) {
|
||||||
return (m.flags_ & ~(M_VALID | M_DIRTY));
|
return m.flags_ & ~allowed_flags_;
|
||||||
}
|
}
|
||||||
|
|
||||||
damage_visitor &visitor_;
|
damage_visitor &visitor_;
|
||||||
set<block_address> seen_oblocks_;
|
set<block_address> seen_oblocks_;
|
||||||
|
uint32_t allowed_flags_;
|
||||||
};
|
};
|
||||||
|
|
||||||
class ll_damage_visitor {
|
class ll_damage_visitor {
|
||||||
@ -123,9 +125,9 @@ caching::walk_mapping_array(mapping_array const &array,
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
caching::check_mapping_array(mapping_array const &array, damage_visitor &visitor)
|
caching::check_mapping_array(mapping_array const &array, damage_visitor &visitor, unsigned metadata_version)
|
||||||
{
|
{
|
||||||
check_mapping_visitor mv(visitor);
|
check_mapping_visitor mv(visitor, metadata_version);
|
||||||
walk_mapping_array(array, mv, visitor);
|
walk_mapping_array(array, mv, visitor);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -91,7 +91,8 @@ namespace caching {
|
|||||||
mapping_array_damage::damage_visitor &dv);
|
mapping_array_damage::damage_visitor &dv);
|
||||||
|
|
||||||
void check_mapping_array(mapping_array const &array,
|
void check_mapping_array(mapping_array const &array,
|
||||||
mapping_array_damage::damage_visitor &visitor);
|
mapping_array_damage::damage_visitor &visitor,
|
||||||
|
unsigned metadata_version);
|
||||||
}
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------
|
//----------------------------------------------------------------
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
#include "persistent-data/space-maps/core.h"
|
#include "persistent-data/space-maps/core.h"
|
||||||
|
|
||||||
using namespace caching;
|
using namespace caching;
|
||||||
|
namespace pd = persistent_data;
|
||||||
|
|
||||||
//----------------------------------------------------------------
|
//----------------------------------------------------------------
|
||||||
|
|
||||||
@ -30,15 +31,11 @@ namespace {
|
|||||||
|
|
||||||
//----------------------------------------------------------------
|
//----------------------------------------------------------------
|
||||||
|
|
||||||
metadata::metadata(block_manager<>::ptr bm, open_type ot)
|
metadata::metadata(block_manager<>::ptr bm, open_type ot, unsigned metadata_version)
|
||||||
{
|
{
|
||||||
switch (ot) {
|
switch (ot) {
|
||||||
case CREATE:
|
case CREATE:
|
||||||
create_metadata(bm);
|
create_metadata(bm, metadata_version);
|
||||||
break;
|
|
||||||
|
|
||||||
case OPEN:
|
|
||||||
open_metadata(bm);
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
@ -46,6 +43,11 @@ metadata::metadata(block_manager<>::ptr bm, open_type ot)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
metadata::metadata(block_manager<>::ptr bm)
|
||||||
|
{
|
||||||
|
open_metadata(bm);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
metadata::commit(bool clean_shutdown)
|
metadata::commit(bool clean_shutdown)
|
||||||
{
|
{
|
||||||
@ -65,7 +67,7 @@ metadata::setup_hint_array(size_t width)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
metadata::create_metadata(block_manager<>::ptr bm)
|
metadata::create_metadata(block_manager<>::ptr bm, unsigned metadata_version)
|
||||||
{
|
{
|
||||||
tm_ = open_tm(bm);
|
tm_ = open_tm(bm);
|
||||||
|
|
||||||
@ -79,7 +81,10 @@ metadata::create_metadata(block_manager<>::ptr bm)
|
|||||||
// We can't instantiate the hint array yet, since we don't know the
|
// We can't instantiate the hint array yet, since we don't know the
|
||||||
// hint width.
|
// hint width.
|
||||||
|
|
||||||
discard_bits_ = persistent_data::bitset::ptr(new persistent_data::bitset(*tm_));
|
discard_bits_ = pd::bitset::ptr(new pd::bitset(*tm_));
|
||||||
|
|
||||||
|
if (metadata_version >= 2)
|
||||||
|
dirty_bits_ = pd::bitset::ptr(new pd::bitset(*tm_));
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -100,8 +105,12 @@ metadata::open_metadata(block_manager<>::ptr bm)
|
|||||||
sb_.hint_root, sb_.cache_blocks));
|
sb_.hint_root, sb_.cache_blocks));
|
||||||
|
|
||||||
if (sb_.discard_root)
|
if (sb_.discard_root)
|
||||||
discard_bits_ = persistent_data::bitset::ptr(
|
discard_bits_ = pd::bitset::ptr(
|
||||||
new persistent_data::bitset(*tm_, sb_.discard_root, sb_.discard_nr_blocks));
|
new pd::bitset(*tm_, sb_.discard_root, sb_.discard_nr_blocks));
|
||||||
|
|
||||||
|
if (sb_.version >= 2)
|
||||||
|
dirty_bits_ = pd::bitset::ptr(
|
||||||
|
new pd::bitset(*tm_, *sb_.dirty_root, sb_.cache_blocks));
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -27,7 +27,8 @@ namespace caching {
|
|||||||
typedef block_manager<>::write_ref write_ref;
|
typedef block_manager<>::write_ref write_ref;
|
||||||
typedef boost::shared_ptr<metadata> ptr;
|
typedef boost::shared_ptr<metadata> ptr;
|
||||||
|
|
||||||
metadata(block_manager<>::ptr bm, open_type ot);
|
metadata(block_manager<>::ptr bm, open_type ot, unsigned metadata_version = 2); // Create only
|
||||||
|
metadata(block_manager<>::ptr bm);
|
||||||
|
|
||||||
void commit(bool clean_shutdown = true);
|
void commit(bool clean_shutdown = true);
|
||||||
void setup_hint_array(size_t width);
|
void setup_hint_array(size_t width);
|
||||||
@ -40,11 +41,12 @@ namespace caching {
|
|||||||
mapping_array::ptr mappings_;
|
mapping_array::ptr mappings_;
|
||||||
hint_array::ptr hints_;
|
hint_array::ptr hints_;
|
||||||
persistent_data::bitset::ptr discard_bits_;
|
persistent_data::bitset::ptr discard_bits_;
|
||||||
|
persistent_data::bitset::ptr dirty_bits_;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void init_superblock();
|
void init_superblock();
|
||||||
|
|
||||||
void create_metadata(block_manager<>::ptr bm);
|
void create_metadata(block_manager<>::ptr bm, unsigned metadata_version);
|
||||||
void open_metadata(block_manager<>::ptr bm);
|
void open_metadata(block_manager<>::ptr bm);
|
||||||
|
|
||||||
void commit_space_map();
|
void commit_space_map();
|
||||||
|
@ -11,10 +11,11 @@ using namespace superblock_damage;
|
|||||||
namespace {
|
namespace {
|
||||||
class restorer : public emitter {
|
class restorer : public emitter {
|
||||||
public:
|
public:
|
||||||
restorer(metadata::ptr md, bool clean_shutdown)
|
restorer(metadata::ptr md, bool clean_shutdown, unsigned metadata_version)
|
||||||
: in_superblock_(false),
|
: in_superblock_(false),
|
||||||
md_(md),
|
md_(md),
|
||||||
clean_shutdown_(clean_shutdown) {
|
clean_shutdown_(clean_shutdown),
|
||||||
|
metadata_version_(metadata_version) {
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void begin_superblock(std::string const &uuid,
|
virtual void begin_superblock(std::string const &uuid,
|
||||||
@ -24,6 +25,7 @@ namespace {
|
|||||||
size_t hint_width) {
|
size_t hint_width) {
|
||||||
|
|
||||||
superblock &sb = md_->sb_;
|
superblock &sb = md_->sb_;
|
||||||
|
sb.version = metadata_version_;
|
||||||
strncpy((char *) sb.policy_name, policy.c_str(), sizeof(sb.policy_name));
|
strncpy((char *) sb.policy_name, policy.c_str(), sizeof(sb.policy_name));
|
||||||
memset(sb.policy_version, 0, sizeof(sb.policy_version)); // FIXME: should come from xml
|
memset(sb.policy_version, 0, sizeof(sb.policy_version)); // FIXME: should come from xml
|
||||||
sb.policy_hint_size = hint_width;
|
sb.policy_hint_size = hint_width;
|
||||||
@ -37,6 +39,10 @@ namespace {
|
|||||||
unmapped_value.flags_ = 0;
|
unmapped_value.flags_ = 0;
|
||||||
md_->mappings_->grow(nr_cache_blocks, unmapped_value);
|
md_->mappings_->grow(nr_cache_blocks, unmapped_value);
|
||||||
|
|
||||||
|
if (metadata_version_ > 1)
|
||||||
|
// make everything dirty by default
|
||||||
|
md_->dirty_bits_->grow(nr_cache_blocks, true);
|
||||||
|
|
||||||
vector<unsigned char> hint_value(hint_width, '\0');
|
vector<unsigned char> hint_value(hint_width, '\0');
|
||||||
md_->hints_->grow(nr_cache_blocks, hint_value);
|
md_->hints_->grow(nr_cache_blocks, hint_value);
|
||||||
}
|
}
|
||||||
@ -60,8 +66,11 @@ namespace {
|
|||||||
m.oblock_ = oblock;
|
m.oblock_ = oblock;
|
||||||
m.flags_ = M_VALID;
|
m.flags_ = M_VALID;
|
||||||
|
|
||||||
|
if (metadata_version_ == 1) {
|
||||||
if (dirty)
|
if (dirty)
|
||||||
m.flags_ = m.flags_ | M_DIRTY;
|
m.flags_ = m.flags_ | M_DIRTY;
|
||||||
|
} else
|
||||||
|
md_->dirty_bits_->set(cblock, dirty);
|
||||||
|
|
||||||
md_->mappings_->set(cblock, m);
|
md_->mappings_->set(cblock, m);
|
||||||
}
|
}
|
||||||
@ -98,15 +107,17 @@ namespace {
|
|||||||
bool in_superblock_;
|
bool in_superblock_;
|
||||||
metadata::ptr md_;
|
metadata::ptr md_;
|
||||||
bool clean_shutdown_;
|
bool clean_shutdown_;
|
||||||
|
unsigned metadata_version_;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------
|
//----------------------------------------------------------------
|
||||||
|
|
||||||
emitter::ptr
|
emitter::ptr
|
||||||
caching::create_restore_emitter(metadata::ptr md, bool clean_shutdown)
|
caching::create_restore_emitter(metadata::ptr md, unsigned metadata_version,
|
||||||
|
bool clean_shutdown)
|
||||||
{
|
{
|
||||||
return emitter::ptr(new restorer(md, clean_shutdown));
|
return emitter::ptr(new restorer(md, clean_shutdown, metadata_version));
|
||||||
}
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------
|
//----------------------------------------------------------------
|
||||||
|
@ -7,7 +7,9 @@
|
|||||||
//----------------------------------------------------------------
|
//----------------------------------------------------------------
|
||||||
|
|
||||||
namespace caching {
|
namespace caching {
|
||||||
emitter::ptr create_restore_emitter(metadata::ptr md, bool clean_shutdown = true);
|
emitter::ptr create_restore_emitter(metadata::ptr md,
|
||||||
|
unsigned metadata_version,
|
||||||
|
bool clean_shutdown = true);
|
||||||
}
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------
|
//----------------------------------------------------------------
|
||||||
|
@ -45,6 +45,8 @@ namespace {
|
|||||||
le32 write_misses;
|
le32 write_misses;
|
||||||
|
|
||||||
le32 policy_version[CACHE_POLICY_VERSION_SIZE];
|
le32 policy_version[CACHE_POLICY_VERSION_SIZE];
|
||||||
|
|
||||||
|
le64 dirty_root; // format 2 only
|
||||||
} __attribute__ ((packed));
|
} __attribute__ ((packed));
|
||||||
|
|
||||||
struct superblock_traits {
|
struct superblock_traits {
|
||||||
@ -57,7 +59,7 @@ namespace {
|
|||||||
|
|
||||||
uint32_t const SUPERBLOCK_MAGIC = 06142003;
|
uint32_t const SUPERBLOCK_MAGIC = 06142003;
|
||||||
uint32_t const VERSION_BEGIN = 1;
|
uint32_t const VERSION_BEGIN = 1;
|
||||||
uint32_t const VERSION_END = 2;
|
uint32_t const VERSION_END = 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------
|
//----------------------------------------------------------------
|
||||||
@ -195,6 +197,9 @@ superblock_traits::unpack(superblock_disk const &disk, superblock &core)
|
|||||||
core.read_misses = to_cpu<uint32_t>(disk.read_misses);
|
core.read_misses = to_cpu<uint32_t>(disk.read_misses);
|
||||||
core.write_hits = to_cpu<uint32_t>(disk.write_hits);
|
core.write_hits = to_cpu<uint32_t>(disk.write_hits);
|
||||||
core.write_misses = to_cpu<uint32_t>(disk.write_misses);
|
core.write_misses = to_cpu<uint32_t>(disk.write_misses);
|
||||||
|
|
||||||
|
if (core.version >= 2)
|
||||||
|
core.dirty_root = to_cpu<uint64_t>(disk.dirty_root);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
#include "base/endian_utils.h"
|
#include "base/endian_utils.h"
|
||||||
#include "persistent-data/data-structures/btree.h"
|
#include "persistent-data/data-structures/btree.h"
|
||||||
|
|
||||||
|
#include <boost/optional.hpp>
|
||||||
#include <set>
|
#include <set>
|
||||||
|
|
||||||
//----------------------------------------------------------------
|
//----------------------------------------------------------------
|
||||||
@ -11,6 +12,8 @@
|
|||||||
namespace caching {
|
namespace caching {
|
||||||
typedef unsigned char __u8;
|
typedef unsigned char __u8;
|
||||||
|
|
||||||
|
unsigned const MIN_METADATA_VERSION = 1;
|
||||||
|
unsigned const MAX_METADATA_VERSION = 2;
|
||||||
unsigned const SPACE_MAP_ROOT_SIZE = 128;
|
unsigned const SPACE_MAP_ROOT_SIZE = 128;
|
||||||
unsigned const CACHE_POLICY_NAME_SIZE = 16;
|
unsigned const CACHE_POLICY_NAME_SIZE = 16;
|
||||||
unsigned const CACHE_POLICY_VERSION_SIZE = 3;
|
unsigned const CACHE_POLICY_VERSION_SIZE = 3;
|
||||||
@ -78,6 +81,8 @@ namespace caching {
|
|||||||
uint32_t read_misses;
|
uint32_t read_misses;
|
||||||
uint32_t write_hits;
|
uint32_t write_hits;
|
||||||
uint32_t write_misses;
|
uint32_t write_misses;
|
||||||
|
|
||||||
|
boost::optional<uint64_t> dirty_root;
|
||||||
};
|
};
|
||||||
|
|
||||||
enum incompat_bits {
|
enum incompat_bits {
|
||||||
|
Loading…
Reference in New Issue
Block a user