2011-12-16 00:04:31 +05:30
|
|
|
// Copyright (C) 2011 Red Hat, Inc. All rights reserved.
|
2011-12-06 19:23:05 +05:30
|
|
|
//
|
2011-12-06 19:13:56 +05:30
|
|
|
// 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
|
|
|
|
// <http://www.gnu.org/licenses/>.
|
|
|
|
|
2013-11-19 15:53:35 +05:30
|
|
|
#include "base/endian_utils.h"
|
|
|
|
|
2013-06-19 21:48:39 +05:30
|
|
|
#include "persistent-data/space-maps/disk.h"
|
|
|
|
#include "persistent-data/space-maps/disk_structures.h"
|
|
|
|
#include "persistent-data/space-maps/recursive.h"
|
|
|
|
#include "persistent-data/space-maps/careful_alloc.h"
|
2013-01-11 03:06:38 +05:30
|
|
|
|
2013-12-11 22:58:14 +05:30
|
|
|
#include "persistent-data/data-structures/btree_damage_visitor.h"
|
2014-02-19 21:38:05 +05:30
|
|
|
#include "persistent-data/data-structures/btree_counter.h"
|
2013-01-11 03:06:38 +05:30
|
|
|
#include "persistent-data/checksum.h"
|
2020-06-15 11:29:16 +05:30
|
|
|
#include "base/math_utils.h"
|
2013-01-11 03:06:38 +05:30
|
|
|
#include "persistent-data/transaction_manager.h"
|
2011-08-31 17:18:41 +05:30
|
|
|
|
|
|
|
using namespace persistent_data;
|
|
|
|
using namespace std;
|
|
|
|
using namespace sm_disk_detail;
|
|
|
|
|
|
|
|
//----------------------------------------------------------------
|
|
|
|
|
|
|
|
namespace {
|
2011-11-03 20:14:00 +05:30
|
|
|
uint64_t const BITMAP_CSUM_XOR = 240779;
|
|
|
|
|
2014-07-25 19:16:51 +05:30
|
|
|
struct bitmap_block_validator : public bcache::validator {
|
|
|
|
virtual void check(void const *raw, block_address location) const {
|
|
|
|
bitmap_header const *data = reinterpret_cast<bitmap_header const *>(raw);
|
2011-11-03 20:14:00 +05:30
|
|
|
crc32c sum(BITMAP_CSUM_XOR);
|
|
|
|
sum.append(&data->not_used, MD_BLOCK_SIZE - sizeof(uint32_t));
|
|
|
|
if (sum.get_sum() != to_cpu<uint32_t>(data->csum))
|
2012-02-27 19:37:16 +05:30
|
|
|
throw checksum_error("bad checksum in space map bitmap");
|
2011-11-03 20:14:00 +05:30
|
|
|
|
|
|
|
if (to_cpu<uint64_t>(data->blocknr) != location)
|
2012-02-27 19:37:16 +05:30
|
|
|
throw checksum_error("bad block nr in space map bitmap");
|
2011-11-03 20:14:00 +05:30
|
|
|
}
|
|
|
|
|
2016-02-27 12:51:13 +05:30
|
|
|
virtual bool check_raw(void const *raw) const {
|
|
|
|
bitmap_header const *data = reinterpret_cast<bitmap_header const *>(raw);
|
|
|
|
crc32c sum(BITMAP_CSUM_XOR);
|
|
|
|
sum.append(&data->not_used, MD_BLOCK_SIZE - sizeof(uint32_t));
|
|
|
|
if (sum.get_sum() != to_cpu<uint32_t>(data->csum))
|
|
|
|
return false;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2014-07-25 19:16:51 +05:30
|
|
|
virtual void prepare(void *raw, block_address location) const {
|
|
|
|
bitmap_header *data = reinterpret_cast<bitmap_header *>(raw);
|
2013-03-22 20:06:31 +05:30
|
|
|
data->blocknr = to_disk<base::le64, uint64_t>(location);
|
2011-11-03 20:14:00 +05:30
|
|
|
|
|
|
|
crc32c sum(BITMAP_CSUM_XOR);
|
|
|
|
sum.append(&data->not_used, MD_BLOCK_SIZE - sizeof(uint32_t));
|
2013-03-22 20:06:31 +05:30
|
|
|
data->csum = to_disk<base::le32>(sum.get_sum());
|
2011-11-03 20:14:00 +05:30
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2011-11-07 16:04:43 +05:30
|
|
|
//--------------------------------
|
|
|
|
|
|
|
|
// FIXME: factor out the common code in these validators
|
2014-07-25 19:16:51 +05:30
|
|
|
struct index_block_validator : public bcache::validator {
|
|
|
|
virtual void check(void const *raw, block_address location) const {
|
|
|
|
metadata_index const *mi = reinterpret_cast<metadata_index const *>(raw);
|
2011-11-07 16:04:43 +05:30
|
|
|
crc32c sum(INDEX_CSUM_XOR);
|
|
|
|
sum.append(&mi->padding_, MD_BLOCK_SIZE - sizeof(uint32_t));
|
|
|
|
if (sum.get_sum() != to_cpu<uint32_t>(mi->csum_))
|
2012-02-27 19:37:16 +05:30
|
|
|
throw checksum_error("bad checksum in metadata index block");
|
2011-11-07 16:04:43 +05:30
|
|
|
|
|
|
|
if (to_cpu<uint64_t>(mi->blocknr_) != location)
|
2012-02-27 19:37:16 +05:30
|
|
|
throw checksum_error("bad block nr in metadata index block");
|
2011-11-07 16:04:43 +05:30
|
|
|
}
|
|
|
|
|
2016-02-27 12:51:13 +05:30
|
|
|
virtual bool check_raw(void const *raw) const {
|
|
|
|
metadata_index const *mi = reinterpret_cast<metadata_index const *>(raw);
|
|
|
|
crc32c sum(INDEX_CSUM_XOR);
|
|
|
|
sum.append(&mi->padding_, MD_BLOCK_SIZE - sizeof(uint32_t));
|
|
|
|
if (sum.get_sum() != to_cpu<uint32_t>(mi->csum_))
|
|
|
|
return false;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2014-07-25 19:16:51 +05:30
|
|
|
virtual void prepare(void *raw, block_address location) const {
|
|
|
|
metadata_index *mi = reinterpret_cast<metadata_index *>(raw);
|
2013-03-22 20:06:31 +05:30
|
|
|
mi->blocknr_ = to_disk<base::le64, uint64_t>(location);
|
2011-11-07 16:04:43 +05:30
|
|
|
|
|
|
|
crc32c sum(INDEX_CSUM_XOR);
|
|
|
|
sum.append(&mi->padding_, MD_BLOCK_SIZE - sizeof(uint32_t));
|
2013-03-22 20:06:31 +05:30
|
|
|
mi->csum_ = to_disk<base::le32>(sum.get_sum());
|
2011-11-07 16:04:43 +05:30
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
//--------------------------------
|
|
|
|
|
2011-08-31 17:18:41 +05:30
|
|
|
class bitmap {
|
|
|
|
public:
|
|
|
|
typedef transaction_manager::read_ref read_ref;
|
|
|
|
typedef transaction_manager::write_ref write_ref;
|
|
|
|
|
2014-08-26 15:44:49 +05:30
|
|
|
bitmap(transaction_manager &tm,
|
2013-04-26 18:45:20 +05:30
|
|
|
index_entry const &ie,
|
2014-07-25 19:16:51 +05:30
|
|
|
bcache::validator::ptr v)
|
2011-08-31 17:18:41 +05:30
|
|
|
: tm_(tm),
|
2013-04-26 18:45:20 +05:30
|
|
|
validator_(v),
|
2011-08-31 17:18:41 +05:30
|
|
|
ie_(ie) {
|
|
|
|
}
|
|
|
|
|
|
|
|
ref_t lookup(unsigned b) const {
|
2014-08-26 15:44:49 +05:30
|
|
|
read_ref rr = tm_.read_lock(ie_.blocknr_, validator_);
|
2017-09-04 22:35:19 +05:30
|
|
|
return __lookup_raw(bitmap_data(rr), b);
|
2011-08-31 17:18:41 +05:30
|
|
|
}
|
|
|
|
|
|
|
|
void insert(unsigned b, ref_t n) {
|
2014-08-26 15:44:49 +05:30
|
|
|
write_ref wr = tm_.shadow(ie_.blocknr_, validator_).first;
|
2011-08-31 17:18:41 +05:30
|
|
|
void *bits = bitmap_data(wr);
|
|
|
|
bool was_free = !test_bit_le(bits, b * 2) && !test_bit_le(bits, b * 2 + 1);
|
|
|
|
if (n == 1 || n == 3)
|
|
|
|
set_bit_le(bits, b * 2 + 1);
|
|
|
|
else
|
|
|
|
clear_bit_le(bits, b * 2 + 1);
|
|
|
|
|
|
|
|
if (n == 2 || n == 3)
|
|
|
|
set_bit_le(bits, b * 2);
|
|
|
|
else
|
|
|
|
clear_bit_le(bits, b * 2);
|
|
|
|
|
|
|
|
ie_.blocknr_ = wr.get_location();
|
|
|
|
|
|
|
|
if (was_free && n > 0) {
|
|
|
|
ie_.nr_free_--;
|
|
|
|
if (b == ie_.none_free_before_)
|
|
|
|
ie_.none_free_before_++;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!was_free && n == 0) {
|
|
|
|
ie_.nr_free_++;
|
|
|
|
if (b < ie_.none_free_before_)
|
|
|
|
ie_.none_free_before_ = b;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-11-03 20:14:00 +05:30
|
|
|
boost::optional<unsigned> find_free(unsigned begin, unsigned end) {
|
2018-10-31 15:40:51 +05:30
|
|
|
begin = max(begin, ie_.none_free_before_);
|
|
|
|
if (begin >= end)
|
|
|
|
return boost::optional<unsigned>();
|
|
|
|
|
2017-09-04 22:35:19 +05:30
|
|
|
read_ref rr = tm_.read_lock(ie_.blocknr_, validator_);
|
|
|
|
void const *bits = bitmap_data(rr);
|
2018-10-31 15:40:51 +05:30
|
|
|
|
|
|
|
// specify the search range inside the bitmap, in 64-bit unit
|
|
|
|
le64 const *w = reinterpret_cast<le64 const *>(bits);
|
|
|
|
le64 const *le64_begin = w + (begin >> 5); // w + div_down(begin, 32)
|
|
|
|
le64 const *le64_end = w + ((end + 31) >> 5); // w + div_up(end, 32)
|
|
|
|
|
|
|
|
for (le64 const *ptr = le64_begin; ptr < le64_end; ptr++) {
|
|
|
|
// specify the search range among a 64-bit of entries
|
|
|
|
unsigned entry_begin = (ptr == le64_begin) ? (begin & 0x1F) : 0;
|
|
|
|
unsigned entry_end = ((ptr == le64_end - 1) && (end & 0x1F)) ?
|
|
|
|
(end & 0x1F) : 32;
|
|
|
|
int i;
|
|
|
|
if ((i = find_free_entry(ptr, entry_begin, entry_end)) >= 0)
|
|
|
|
return ((ptr - w) << 5) + i;
|
|
|
|
}
|
2011-08-31 17:18:41 +05:30
|
|
|
|
2011-11-03 20:14:00 +05:30
|
|
|
return boost::optional<unsigned>();
|
2011-08-31 17:18:41 +05:30
|
|
|
}
|
|
|
|
|
|
|
|
index_entry const &get_ie() const {
|
|
|
|
return ie_;
|
|
|
|
}
|
|
|
|
|
2011-10-25 15:57:59 +05:30
|
|
|
void iterate(block_address offset, block_address hi, space_map::iterator &it) const {
|
2014-08-26 15:44:49 +05:30
|
|
|
read_ref rr = tm_.read_lock(ie_.blocknr_, validator_);
|
2011-10-25 15:57:59 +05:30
|
|
|
void const *bits = bitmap_data(rr);
|
|
|
|
|
|
|
|
for (unsigned b = 0; b < hi; b++) {
|
|
|
|
ref_t b1 = test_bit_le(bits, b * 2);
|
|
|
|
ref_t b2 = test_bit_le(bits, b * 2 + 1);
|
|
|
|
ref_t result = b2 ? 1 : 0;
|
2015-01-16 15:45:55 +05:30
|
|
|
result |= b1 ? 2 : 0;
|
2011-10-25 15:57:59 +05:30
|
|
|
it(offset + b, result);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-08-31 17:18:41 +05:30
|
|
|
private:
|
2011-09-01 15:12:57 +05:30
|
|
|
void *bitmap_data(transaction_manager::write_ref &wr) {
|
2014-07-25 19:16:51 +05:30
|
|
|
bitmap_header *h = reinterpret_cast<bitmap_header *>(wr.data());
|
2011-08-31 17:18:41 +05:30
|
|
|
return h + 1;
|
|
|
|
}
|
|
|
|
|
2011-09-01 15:12:57 +05:30
|
|
|
void const *bitmap_data(transaction_manager::read_ref &rr) const {
|
2014-07-25 19:16:51 +05:30
|
|
|
bitmap_header const *h = reinterpret_cast<bitmap_header const *>(rr.data());
|
2011-08-31 17:18:41 +05:30
|
|
|
return h + 1;
|
|
|
|
}
|
|
|
|
|
2017-09-04 22:35:19 +05:30
|
|
|
ref_t __lookup_raw(void const *bits, unsigned b) const {
|
|
|
|
ref_t b1 = test_bit_le(bits, b * 2);
|
|
|
|
ref_t b2 = test_bit_le(bits, b * 2 + 1);
|
|
|
|
ref_t result = b2 ? 1 : 0;
|
|
|
|
result |= b1 ? 2 : 0;
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2018-10-31 15:40:51 +05:30
|
|
|
// find a free entry (a 2-bit pair) among the specified range in the input bits
|
|
|
|
int find_free_entry(le64 const* bits, unsigned entry_begin, unsigned entry_end) {
|
|
|
|
uint64_t v = to_cpu<uint64_t>(*bits);
|
|
|
|
v >>= (entry_begin * 2);
|
|
|
|
for (; entry_begin < entry_end; entry_begin++) {
|
|
|
|
if (!(v & 0x3)) {
|
|
|
|
return entry_begin;
|
|
|
|
}
|
|
|
|
v = v >> 2;
|
|
|
|
}
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2014-08-26 15:44:49 +05:30
|
|
|
transaction_manager &tm_;
|
2014-07-25 19:16:51 +05:30
|
|
|
bcache::validator::ptr validator_;
|
2013-04-26 18:45:20 +05:30
|
|
|
|
2011-08-31 17:18:41 +05:30
|
|
|
index_entry ie_;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct ref_count_traits {
|
2013-03-22 20:06:31 +05:30
|
|
|
typedef le32 disk_type;
|
2011-08-31 17:18:41 +05:30
|
|
|
typedef uint32_t value_type;
|
2013-02-01 18:34:05 +05:30
|
|
|
typedef no_op_ref_counter<uint32_t> ref_counter;
|
2011-08-31 17:18:41 +05:30
|
|
|
|
|
|
|
static void unpack(disk_type const &d, value_type &v) {
|
|
|
|
v = to_cpu<value_type>(d);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void pack(value_type const &v, disk_type &d) {
|
|
|
|
d = to_disk<disk_type>(v);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2013-12-11 22:58:14 +05:30
|
|
|
#if 0
|
2011-09-02 15:56:42 +05:30
|
|
|
class ref_count_checker : public btree_checker<1, ref_count_traits> {
|
2011-08-31 17:18:41 +05:30
|
|
|
public:
|
2020-04-30 19:32:43 +05:30
|
|
|
typedef std::shared_ptr<ref_count_checker> ptr;
|
2011-08-31 17:18:41 +05:30
|
|
|
|
2011-09-02 15:56:42 +05:30
|
|
|
ref_count_checker(block_counter &counter)
|
2011-08-31 18:08:22 +05:30
|
|
|
: btree_checker<1, ref_count_traits>(counter) {
|
2011-08-31 17:18:41 +05:30
|
|
|
}
|
|
|
|
};
|
2013-12-11 22:58:14 +05:30
|
|
|
#endif
|
|
|
|
|
|
|
|
class index_entry_visitor {
|
|
|
|
public:
|
|
|
|
virtual ~index_entry_visitor() {}
|
|
|
|
virtual void visit(index_entry const &ie) = 0;
|
|
|
|
virtual void visit(run<block_address> const &missing) = 0;
|
|
|
|
};
|
2011-08-31 17:18:41 +05:30
|
|
|
|
2011-11-10 20:13:15 +05:30
|
|
|
class index_store {
|
|
|
|
public:
|
2020-04-30 19:32:43 +05:30
|
|
|
typedef std::shared_ptr<index_store> ptr;
|
2011-11-10 20:13:15 +05:30
|
|
|
|
2020-04-08 16:53:28 +05:30
|
|
|
virtual ~index_store() {}
|
|
|
|
|
2014-02-19 21:38:05 +05:30
|
|
|
virtual void count_metadata(block_counter &bc) const = 0;
|
2011-11-10 20:13:15 +05:30
|
|
|
virtual void resize(block_address nr_indexes) = 0;
|
|
|
|
virtual index_entry find_ie(block_address b) const = 0;
|
|
|
|
virtual void save_ie(block_address b, struct index_entry ie) = 0;
|
|
|
|
virtual void commit_ies() = 0;
|
|
|
|
virtual ptr clone() const = 0;
|
|
|
|
virtual block_address get_root() const = 0;
|
2013-12-11 22:58:14 +05:30
|
|
|
virtual void visit(index_entry_visitor &v, block_address nr_index_entries) const = 0;
|
2011-11-10 20:13:15 +05:30
|
|
|
};
|
|
|
|
|
|
|
|
unsigned const ENTRIES_PER_BLOCK = (MD_BLOCK_SIZE - sizeof(bitmap_header)) * 4;
|
|
|
|
|
2011-11-10 21:00:36 +05:30
|
|
|
class sm_disk : public checked_space_map {
|
2011-08-31 17:18:41 +05:30
|
|
|
public:
|
2020-04-30 19:32:43 +05:30
|
|
|
typedef std::shared_ptr<sm_disk> ptr;
|
2011-08-31 17:18:41 +05:30
|
|
|
typedef transaction_manager::read_ref read_ref;
|
|
|
|
typedef transaction_manager::write_ref write_ref;
|
|
|
|
|
2011-11-10 21:00:36 +05:30
|
|
|
sm_disk(index_store::ptr indexes,
|
2014-08-26 15:44:49 +05:30
|
|
|
transaction_manager &tm)
|
2011-08-31 17:18:41 +05:30
|
|
|
: tm_(tm),
|
2013-04-26 18:45:20 +05:30
|
|
|
bitmap_validator_(new bitmap_block_validator),
|
2011-11-10 20:13:15 +05:30
|
|
|
indexes_(indexes),
|
2011-08-31 17:18:41 +05:30
|
|
|
nr_blocks_(0),
|
|
|
|
nr_allocated_(0),
|
2017-04-11 14:10:08 +05:30
|
|
|
search_start_(0),
|
2011-08-31 17:18:41 +05:30
|
|
|
ref_counts_(tm_, ref_count_traits::ref_counter()) {
|
|
|
|
}
|
|
|
|
|
2011-11-10 21:00:36 +05:30
|
|
|
sm_disk(index_store::ptr indexes,
|
2014-08-26 15:44:49 +05:30
|
|
|
transaction_manager &tm,
|
2011-11-10 21:00:36 +05:30
|
|
|
sm_root const &root)
|
2011-08-31 17:18:41 +05:30
|
|
|
: tm_(tm),
|
2013-04-26 18:45:20 +05:30
|
|
|
bitmap_validator_(new bitmap_block_validator),
|
2011-11-10 20:13:15 +05:30
|
|
|
indexes_(indexes),
|
2011-08-31 17:18:41 +05:30
|
|
|
nr_blocks_(root.nr_blocks_),
|
|
|
|
nr_allocated_(root.nr_allocated_),
|
2017-04-11 14:10:08 +05:30
|
|
|
search_start_(0),
|
2011-08-31 17:18:41 +05:30
|
|
|
ref_counts_(tm_, root.ref_count_root_, ref_count_traits::ref_counter()) {
|
|
|
|
}
|
|
|
|
|
|
|
|
block_address get_nr_blocks() const {
|
|
|
|
return nr_blocks_;
|
|
|
|
}
|
|
|
|
|
|
|
|
block_address get_nr_free() const {
|
|
|
|
return nr_blocks_ - nr_allocated_;
|
|
|
|
}
|
|
|
|
|
|
|
|
ref_t get_count(block_address b) const {
|
|
|
|
ref_t count = lookup_bitmap(b);
|
|
|
|
if (count == 3)
|
|
|
|
return lookup_ref_count(b);
|
|
|
|
|
|
|
|
return count;
|
|
|
|
}
|
|
|
|
|
2017-04-11 15:18:49 +05:30
|
|
|
template <typename Mut>
|
|
|
|
void modify_count(block_address b, Mut const &m) {
|
|
|
|
check_block(b);
|
|
|
|
|
|
|
|
index_entry ie = indexes_->find_ie(b / ENTRIES_PER_BLOCK);
|
|
|
|
bitmap bm(tm_, ie, bitmap_validator_);
|
2011-08-31 17:18:41 +05:30
|
|
|
|
2017-04-11 15:18:49 +05:30
|
|
|
ref_t old = bm.lookup(b % ENTRIES_PER_BLOCK);
|
|
|
|
if (old == 3)
|
|
|
|
old = lookup_ref_count(b);
|
|
|
|
ref_t c = m(old);
|
2011-08-31 17:18:41 +05:30
|
|
|
|
|
|
|
if (c > 2) {
|
2017-04-11 15:18:49 +05:30
|
|
|
if (old < 3) {
|
|
|
|
bm.insert(b % ENTRIES_PER_BLOCK, 3);
|
|
|
|
indexes_->save_ie(b / ENTRIES_PER_BLOCK, bm.get_ie());
|
|
|
|
}
|
2011-08-31 17:18:41 +05:30
|
|
|
insert_ref_count(b, c);
|
|
|
|
} else {
|
|
|
|
if (old > 2)
|
|
|
|
remove_ref_count(b);
|
2017-04-11 15:18:49 +05:30
|
|
|
bm.insert(b % ENTRIES_PER_BLOCK, c);
|
|
|
|
indexes_->save_ie(b / ENTRIES_PER_BLOCK, bm.get_ie());
|
2011-08-31 17:18:41 +05:30
|
|
|
}
|
|
|
|
|
|
|
|
if (old == 0)
|
|
|
|
nr_allocated_++;
|
2017-04-11 14:10:08 +05:30
|
|
|
else if (c == 0) {
|
|
|
|
if (b < search_start_)
|
|
|
|
search_start_ = b;
|
2011-08-31 17:18:41 +05:30
|
|
|
nr_allocated_--;
|
2017-04-11 14:10:08 +05:30
|
|
|
}
|
2011-08-31 17:18:41 +05:30
|
|
|
}
|
|
|
|
|
2017-04-11 15:18:49 +05:30
|
|
|
struct override {
|
|
|
|
override(ref_t new_value)
|
|
|
|
: new_value_(new_value) {
|
|
|
|
}
|
|
|
|
|
|
|
|
ref_t operator()(ref_t old) const {
|
|
|
|
return new_value_;
|
|
|
|
}
|
|
|
|
|
|
|
|
ref_t new_value_;
|
|
|
|
};
|
|
|
|
|
|
|
|
void set_count(block_address b, ref_t c) {
|
|
|
|
override m(c);
|
|
|
|
modify_count(b, m);
|
|
|
|
}
|
|
|
|
|
2011-08-31 17:18:41 +05:30
|
|
|
void commit() {
|
2011-11-10 21:12:02 +05:30
|
|
|
indexes_->commit_ies();
|
2011-08-31 17:18:41 +05:30
|
|
|
}
|
|
|
|
|
2020-05-26 13:27:13 +05:30
|
|
|
void inc(block_address b, uint32_t count) override {
|
2017-04-11 14:10:08 +05:30
|
|
|
if (b == search_start_)
|
|
|
|
search_start_++;
|
|
|
|
|
2020-05-26 13:27:13 +05:30
|
|
|
modify_count(b, [count](ref_t c) {return c + count;});
|
2011-08-31 17:18:41 +05:30
|
|
|
}
|
|
|
|
|
2020-05-26 13:27:13 +05:30
|
|
|
void dec(block_address b, uint32_t count) override {
|
|
|
|
modify_count(b, [count](ref_t c) {return c - count;});
|
2011-08-31 17:18:41 +05:30
|
|
|
}
|
|
|
|
|
2013-04-23 15:27:47 +05:30
|
|
|
maybe_block find_free(span_iterator &it) {
|
2013-01-11 02:35:10 +05:30
|
|
|
for (maybe_span ms = it.first(); ms; ms = it.next()) {
|
|
|
|
block_address begin = ms->first;
|
|
|
|
block_address end = ms->second;
|
2011-11-16 18:23:37 +05:30
|
|
|
|
2017-04-11 14:10:08 +05:30
|
|
|
if (end < search_start_)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if (begin < search_start_)
|
|
|
|
begin = search_start_;
|
|
|
|
|
2013-01-11 02:35:10 +05:30
|
|
|
block_address begin_index = begin / ENTRIES_PER_BLOCK;
|
|
|
|
block_address end_index = div_up<block_address>(end, ENTRIES_PER_BLOCK);
|
2011-11-16 18:23:37 +05:30
|
|
|
|
2013-01-11 02:35:10 +05:30
|
|
|
for (block_address index = begin_index; index < end_index; index++) {
|
|
|
|
index_entry ie = indexes_->find_ie(index);
|
2011-08-31 17:18:41 +05:30
|
|
|
|
2013-04-26 18:45:20 +05:30
|
|
|
bitmap bm(tm_, ie, bitmap_validator_);
|
2013-01-11 02:35:10 +05:30
|
|
|
unsigned bit_begin = (index == begin_index) ? (begin % ENTRIES_PER_BLOCK) : 0;
|
2019-01-03 16:16:35 +05:30
|
|
|
unsigned bit_end = (index == end_index - 1) ?
|
|
|
|
(end - ENTRIES_PER_BLOCK * index) : ENTRIES_PER_BLOCK;
|
2013-01-11 02:35:10 +05:30
|
|
|
|
2013-06-25 18:18:02 +05:30
|
|
|
boost::optional<unsigned> maybe_b = bm.find_free(bit_begin, bit_end);
|
2013-01-11 02:35:10 +05:30
|
|
|
if (maybe_b) {
|
|
|
|
block_address b = (index * ENTRIES_PER_BLOCK) + *maybe_b;
|
2017-04-11 14:10:08 +05:30
|
|
|
if (b)
|
|
|
|
search_start_ = b - 1;
|
2013-01-11 02:35:10 +05:30
|
|
|
return b;
|
|
|
|
}
|
2011-11-03 20:14:00 +05:30
|
|
|
}
|
2011-08-31 17:18:41 +05:30
|
|
|
}
|
|
|
|
|
2011-11-16 18:23:37 +05:30
|
|
|
return maybe_block();
|
2011-08-31 17:18:41 +05:30
|
|
|
}
|
|
|
|
|
|
|
|
virtual void extend(block_address extra_blocks) {
|
|
|
|
block_address nr_blocks = nr_blocks_ + extra_blocks;
|
|
|
|
|
2011-11-10 20:13:15 +05:30
|
|
|
block_address bitmap_count = div_up<block_address>(nr_blocks, ENTRIES_PER_BLOCK);
|
|
|
|
block_address old_bitmap_count = div_up<block_address>(nr_blocks_, ENTRIES_PER_BLOCK);
|
|
|
|
|
|
|
|
indexes_->resize(bitmap_count);
|
2011-08-31 17:18:41 +05:30
|
|
|
for (block_address i = old_bitmap_count; i < bitmap_count; i++) {
|
2014-08-26 15:44:49 +05:30
|
|
|
write_ref wr = tm_.new_block(bitmap_validator_);
|
2011-08-31 17:18:41 +05:30
|
|
|
|
2011-11-03 20:14:00 +05:30
|
|
|
index_entry ie;
|
2011-08-31 17:18:41 +05:30
|
|
|
ie.blocknr_ = wr.get_location();
|
|
|
|
ie.nr_free_ = i == (bitmap_count - 1) ?
|
2018-04-17 18:30:44 +05:30
|
|
|
(nr_blocks - ENTRIES_PER_BLOCK * i) : ENTRIES_PER_BLOCK;
|
2011-08-31 17:18:41 +05:30
|
|
|
ie.none_free_before_ = 0;
|
|
|
|
|
2011-11-10 21:12:02 +05:30
|
|
|
indexes_->save_ie(i, ie);
|
2011-08-31 17:18:41 +05:30
|
|
|
}
|
|
|
|
|
|
|
|
nr_blocks_ = nr_blocks;
|
|
|
|
}
|
|
|
|
|
2013-12-11 22:58:14 +05:30
|
|
|
virtual void visit(space_map_detail::visitor &v) const {
|
|
|
|
#if 0
|
|
|
|
ref_count_checker rcv(v);
|
|
|
|
ref_counts_.visit_depth_first(rcv);
|
2011-11-10 20:13:15 +05:30
|
|
|
|
|
|
|
block_address nr_entries = div_up<block_address>(get_nr_blocks(), ENTRIES_PER_BLOCK);
|
2013-12-11 22:58:14 +05:30
|
|
|
indexes_->visit(v, nr_entries);
|
|
|
|
#endif
|
2011-08-31 17:18:41 +05:30
|
|
|
}
|
|
|
|
|
2011-10-25 15:57:59 +05:30
|
|
|
struct look_aside_iterator : public iterator {
|
2011-11-10 21:00:36 +05:30
|
|
|
look_aside_iterator(sm_disk const &smd, iterator &it)
|
2011-10-25 15:57:59 +05:30
|
|
|
: smd_(smd),
|
|
|
|
it_(it) {
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual void operator () (block_address b, ref_t c) {
|
|
|
|
it_(b, c == 3 ? smd_.lookup_ref_count(b) : c);
|
|
|
|
}
|
|
|
|
|
2011-11-10 21:00:36 +05:30
|
|
|
sm_disk const &smd_;
|
2011-10-25 15:57:59 +05:30
|
|
|
iterator &it_;
|
|
|
|
};
|
|
|
|
|
|
|
|
friend struct look_aside_iterator;
|
|
|
|
|
|
|
|
virtual void iterate(iterator &it) const {
|
|
|
|
look_aside_iterator wrapper(*this, it);
|
2011-11-10 20:13:15 +05:30
|
|
|
unsigned nr_indexes = div_up<block_address>(nr_blocks_, ENTRIES_PER_BLOCK);
|
2011-10-25 15:57:59 +05:30
|
|
|
|
|
|
|
for (unsigned i = 0; i < nr_indexes; i++) {
|
2018-04-17 18:30:44 +05:30
|
|
|
unsigned hi = (i == nr_indexes - 1) ? (nr_blocks_ - ENTRIES_PER_BLOCK * i) : ENTRIES_PER_BLOCK;
|
2011-11-10 21:12:02 +05:30
|
|
|
index_entry ie = indexes_->find_ie(i);
|
2013-04-26 18:45:20 +05:30
|
|
|
bitmap bm(tm_, ie, bitmap_validator_);
|
2011-11-10 20:13:15 +05:30
|
|
|
bm.iterate(i * ENTRIES_PER_BLOCK, hi, wrapper);
|
2011-10-25 15:57:59 +05:30
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-02-19 21:38:05 +05:30
|
|
|
virtual void count_metadata(block_counter &bc) const {
|
|
|
|
indexes_->count_metadata(bc);
|
|
|
|
|
|
|
|
noop_value_counter<uint32_t> vc;
|
|
|
|
count_btree_blocks(ref_counts_, bc, vc);
|
|
|
|
}
|
|
|
|
|
2011-11-16 18:47:23 +05:30
|
|
|
virtual size_t root_size() const {
|
2011-11-10 20:13:15 +05:30
|
|
|
return sizeof(sm_root_disk);
|
|
|
|
}
|
|
|
|
|
2011-11-16 18:47:23 +05:30
|
|
|
virtual void copy_root(void *dest, size_t len) const {
|
2011-11-10 20:13:15 +05:30
|
|
|
sm_root_disk d;
|
|
|
|
sm_root v;
|
|
|
|
|
|
|
|
if (len < sizeof(d))
|
|
|
|
throw runtime_error("root too small");
|
|
|
|
|
2011-11-10 21:00:36 +05:30
|
|
|
v.nr_blocks_ = sm_disk::get_nr_blocks();
|
|
|
|
v.nr_allocated_ = sm_disk::get_nr_allocated();
|
2011-11-10 20:13:15 +05:30
|
|
|
v.bitmap_root_ = get_index_store()->get_root();
|
2011-11-10 21:00:36 +05:30
|
|
|
v.ref_count_root_ = sm_disk::get_ref_count_root();
|
2011-11-10 20:13:15 +05:30
|
|
|
|
|
|
|
sm_root_traits::pack(v, d);
|
|
|
|
::memcpy(dest, &d, sizeof(d));
|
|
|
|
}
|
|
|
|
|
2011-11-16 18:45:32 +05:30
|
|
|
virtual checked_space_map::ptr clone() const {
|
|
|
|
sm_root root;
|
|
|
|
root.nr_blocks_ = nr_blocks_;
|
|
|
|
root.nr_allocated_ = nr_allocated_;
|
|
|
|
root.bitmap_root_ = indexes_->get_root();
|
|
|
|
root.ref_count_root_ = ref_counts_.get_root();
|
|
|
|
return checked_space_map::ptr(
|
|
|
|
new sm_disk(indexes_->clone(), tm_, root));
|
|
|
|
}
|
|
|
|
|
2011-08-31 17:18:41 +05:30
|
|
|
protected:
|
2014-08-26 15:44:49 +05:30
|
|
|
transaction_manager &get_tm() const {
|
2011-08-31 17:18:41 +05:30
|
|
|
return tm_;
|
|
|
|
}
|
|
|
|
|
|
|
|
block_address get_nr_allocated() const {
|
|
|
|
return nr_allocated_;
|
|
|
|
}
|
|
|
|
|
|
|
|
block_address get_ref_count_root() const {
|
|
|
|
return ref_counts_.get_root();
|
|
|
|
}
|
|
|
|
|
2011-11-10 20:13:15 +05:30
|
|
|
index_store::ptr get_index_store() const {
|
|
|
|
return indexes_;
|
2011-08-31 17:18:41 +05:30
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
2013-06-14 20:06:01 +05:30
|
|
|
void check_block(block_address b) const {
|
|
|
|
if (b >= nr_blocks_) {
|
|
|
|
std::ostringstream out;
|
|
|
|
out << "space map disk: block out of bounds ("
|
|
|
|
<< b << " >= " << nr_blocks_ << ")";
|
|
|
|
throw std::runtime_error(out.str());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-08-31 17:18:41 +05:30
|
|
|
ref_t lookup_bitmap(block_address b) const {
|
2013-06-14 20:06:01 +05:30
|
|
|
check_block(b);
|
|
|
|
|
2011-11-10 21:12:02 +05:30
|
|
|
index_entry ie = indexes_->find_ie(b / ENTRIES_PER_BLOCK);
|
2013-04-26 18:45:20 +05:30
|
|
|
bitmap bm(tm_, ie, bitmap_validator_);
|
2011-11-10 20:13:15 +05:30
|
|
|
return bm.lookup(b % ENTRIES_PER_BLOCK);
|
2011-08-31 17:18:41 +05:30
|
|
|
}
|
|
|
|
|
|
|
|
void insert_bitmap(block_address b, unsigned n) {
|
2013-06-14 20:06:01 +05:30
|
|
|
check_block(b);
|
|
|
|
|
2011-08-31 17:18:41 +05:30
|
|
|
if (n > 3)
|
|
|
|
throw runtime_error("bitmap can only hold 2 bit values");
|
|
|
|
|
2011-11-10 21:12:02 +05:30
|
|
|
index_entry ie = indexes_->find_ie(b / ENTRIES_PER_BLOCK);
|
2013-04-26 18:45:20 +05:30
|
|
|
bitmap bm(tm_, ie, bitmap_validator_);
|
2011-11-10 20:13:15 +05:30
|
|
|
bm.insert(b % ENTRIES_PER_BLOCK, n);
|
2011-11-10 21:12:02 +05:30
|
|
|
indexes_->save_ie(b / ENTRIES_PER_BLOCK, bm.get_ie());
|
2011-08-31 17:18:41 +05:30
|
|
|
}
|
|
|
|
|
|
|
|
ref_t lookup_ref_count(block_address b) const {
|
|
|
|
uint64_t key[1] = {b};
|
2013-06-25 18:18:02 +05:30
|
|
|
boost::optional<ref_t> mvalue = ref_counts_.lookup(key);
|
2011-08-31 17:18:41 +05:30
|
|
|
if (!mvalue)
|
|
|
|
throw runtime_error("ref count not in tree");
|
|
|
|
return *mvalue;
|
|
|
|
}
|
|
|
|
|
|
|
|
void insert_ref_count(block_address b, ref_t count) {
|
|
|
|
uint64_t key[1] = {b};
|
|
|
|
ref_counts_.insert(key, count);
|
|
|
|
}
|
|
|
|
|
|
|
|
void remove_ref_count(block_address b) {
|
|
|
|
uint64_t key[1] = {b};
|
|
|
|
ref_counts_.remove(key);
|
|
|
|
}
|
|
|
|
|
2014-08-26 15:44:49 +05:30
|
|
|
transaction_manager &tm_;
|
2014-07-25 19:16:51 +05:30
|
|
|
bcache::validator::ptr bitmap_validator_;
|
2011-11-10 20:13:15 +05:30
|
|
|
index_store::ptr indexes_;
|
2011-08-31 17:18:41 +05:30
|
|
|
block_address nr_blocks_;
|
|
|
|
block_address nr_allocated_;
|
2017-04-11 14:10:08 +05:30
|
|
|
block_address search_start_;
|
2011-08-31 17:18:41 +05:30
|
|
|
|
|
|
|
btree<1, ref_count_traits> ref_counts_;
|
|
|
|
};
|
|
|
|
|
2013-12-11 22:58:14 +05:30
|
|
|
//--------------------------------
|
2011-08-31 17:18:41 +05:30
|
|
|
|
2013-12-11 22:58:14 +05:30
|
|
|
class ie_value_visitor {
|
|
|
|
public:
|
2020-04-08 16:42:59 +05:30
|
|
|
ie_value_visitor(index_entry_visitor &v) {}
|
2011-08-31 17:18:41 +05:30
|
|
|
|
2013-12-11 22:58:14 +05:30
|
|
|
virtual void visit(btree_path const &path, sm_disk_detail::index_entry const &ie) {
|
|
|
|
// FIXME: finish
|
|
|
|
}
|
|
|
|
};
|
2011-08-31 17:18:41 +05:30
|
|
|
|
2013-12-11 22:58:14 +05:30
|
|
|
class ie_damage_visitor {
|
|
|
|
public:
|
2020-04-08 16:42:59 +05:30
|
|
|
ie_damage_visitor(index_entry_visitor &v) {}
|
2011-09-01 18:35:01 +05:30
|
|
|
|
2013-12-11 22:58:14 +05:30
|
|
|
virtual void visit(btree_path const &path, btree_detail::damage const &d) {
|
|
|
|
// FIXME: finish
|
2011-08-31 17:18:41 +05:30
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2011-11-10 20:13:15 +05:30
|
|
|
class btree_index_store : public index_store {
|
2011-08-31 17:18:41 +05:30
|
|
|
public:
|
2020-04-30 19:32:43 +05:30
|
|
|
typedef std::shared_ptr<btree_index_store> ptr;
|
2011-08-31 17:18:41 +05:30
|
|
|
|
2014-08-26 15:44:49 +05:30
|
|
|
btree_index_store(transaction_manager &tm)
|
2011-11-10 20:13:15 +05:30
|
|
|
: tm_(tm),
|
|
|
|
bitmaps_(tm, index_entry_traits::ref_counter()) {
|
2011-08-31 17:18:41 +05:30
|
|
|
}
|
|
|
|
|
2014-08-26 15:44:49 +05:30
|
|
|
btree_index_store(transaction_manager &tm,
|
2011-11-10 20:13:15 +05:30
|
|
|
block_address root)
|
|
|
|
: tm_(tm),
|
|
|
|
bitmaps_(tm, root, index_entry_traits::ref_counter()) {
|
2011-08-31 17:18:41 +05:30
|
|
|
}
|
|
|
|
|
2014-02-19 21:38:05 +05:30
|
|
|
//--------------------------------
|
|
|
|
|
|
|
|
struct index_entry_counter {
|
|
|
|
index_entry_counter(block_counter &bc)
|
|
|
|
: bc_(bc) {
|
|
|
|
}
|
|
|
|
|
|
|
|
void visit(btree_detail::node_location const &loc, index_entry const &ie) {
|
|
|
|
if (ie.blocknr_ != 0)
|
|
|
|
bc_.inc(ie.blocknr_);
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
block_counter &bc_;
|
|
|
|
};
|
|
|
|
|
|
|
|
virtual void count_metadata(block_counter &bc) const {
|
|
|
|
index_entry_counter vc(bc);
|
|
|
|
count_btree_blocks(bitmaps_, bc, vc);
|
|
|
|
}
|
|
|
|
|
|
|
|
//--------------------------------
|
|
|
|
|
2011-11-10 20:13:15 +05:30
|
|
|
virtual void resize(block_address nr_entries) {
|
|
|
|
// No op
|
2011-08-31 17:18:41 +05:30
|
|
|
}
|
|
|
|
|
2011-11-10 20:13:15 +05:30
|
|
|
virtual index_entry find_ie(block_address ie_index) const {
|
|
|
|
uint64_t key[1] = {ie_index};
|
2013-06-25 18:18:02 +05:30
|
|
|
boost::optional<index_entry> mindex = bitmaps_.lookup(key);
|
2011-11-10 20:13:15 +05:30
|
|
|
if (!mindex)
|
|
|
|
throw runtime_error("Couldn't lookup bitmap");
|
2011-08-31 17:18:41 +05:30
|
|
|
|
2011-11-10 20:13:15 +05:30
|
|
|
return *mindex;
|
|
|
|
}
|
2011-08-31 17:18:41 +05:30
|
|
|
|
2011-11-10 20:13:15 +05:30
|
|
|
virtual void save_ie(block_address ie_index, struct index_entry ie) {
|
|
|
|
uint64_t key[1] = {ie_index};
|
|
|
|
bitmaps_.insert(key, ie);
|
|
|
|
}
|
2011-11-03 20:14:00 +05:30
|
|
|
|
2011-11-10 20:13:15 +05:30
|
|
|
virtual void commit_ies() {
|
|
|
|
// No op
|
2011-08-31 17:18:41 +05:30
|
|
|
}
|
|
|
|
|
2011-11-10 20:13:15 +05:30
|
|
|
virtual index_store::ptr clone() const {
|
|
|
|
return index_store::ptr(new btree_index_store(tm_, bitmaps_.get_root()));
|
|
|
|
}
|
2011-08-31 17:18:41 +05:30
|
|
|
|
2011-11-10 20:13:15 +05:30
|
|
|
virtual block_address get_root() const {
|
|
|
|
return bitmaps_.get_root();
|
|
|
|
}
|
|
|
|
|
2013-12-11 22:58:14 +05:30
|
|
|
virtual void visit(index_entry_visitor &v, block_address nr_index_entries) const {
|
|
|
|
ie_value_visitor vv(v);
|
|
|
|
ie_damage_visitor dv(v);
|
|
|
|
btree_visit_values(bitmaps_, vv, dv);
|
2011-08-31 17:18:41 +05:30
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
2014-08-26 15:44:49 +05:30
|
|
|
transaction_manager &tm_;
|
2011-11-10 20:13:15 +05:30
|
|
|
btree<1, index_entry_traits> bitmaps_;
|
|
|
|
};
|
2011-08-31 17:18:41 +05:30
|
|
|
|
2011-11-10 20:13:15 +05:30
|
|
|
class metadata_index_store : public index_store {
|
2011-08-31 17:18:41 +05:30
|
|
|
public:
|
2020-04-30 19:32:43 +05:30
|
|
|
typedef std::shared_ptr<metadata_index_store> ptr;
|
2011-08-31 17:18:41 +05:30
|
|
|
|
2014-08-26 15:44:49 +05:30
|
|
|
metadata_index_store(transaction_manager &tm)
|
2011-11-10 20:13:15 +05:30
|
|
|
: tm_(tm) {
|
2020-04-30 19:00:01 +05:30
|
|
|
block_manager::write_ref wr = tm_.new_block(index_validator());
|
2011-11-07 16:04:43 +05:30
|
|
|
bitmap_root_ = wr.get_location();
|
2011-08-31 17:18:41 +05:30
|
|
|
}
|
|
|
|
|
2014-08-26 15:44:49 +05:30
|
|
|
metadata_index_store(transaction_manager &tm, block_address root, block_address nr_indexes)
|
2011-11-10 20:13:15 +05:30
|
|
|
: tm_(tm),
|
|
|
|
bitmap_root_(root) {
|
|
|
|
resize(nr_indexes);
|
2011-08-31 17:18:41 +05:30
|
|
|
load_ies();
|
|
|
|
}
|
|
|
|
|
2014-02-19 21:38:05 +05:30
|
|
|
virtual void count_metadata(block_counter &bc) const {
|
2015-04-08 17:02:00 +05:30
|
|
|
bc.inc(bitmap_root_);
|
|
|
|
|
2014-02-19 21:38:05 +05:30
|
|
|
for (unsigned i = 0; i < entries_.size(); i++) {
|
|
|
|
block_address b = entries_[i].blocknr_;
|
|
|
|
|
|
|
|
if (b != 0)
|
|
|
|
bc.inc(b);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-11-10 20:13:15 +05:30
|
|
|
virtual void resize(block_address nr_indexes) {
|
|
|
|
entries_.resize(nr_indexes);
|
2011-08-31 17:18:41 +05:30
|
|
|
}
|
|
|
|
|
2011-11-10 20:13:15 +05:30
|
|
|
virtual index_entry find_ie(block_address ie_index) const {
|
|
|
|
return entries_[ie_index];
|
|
|
|
}
|
2011-08-31 17:18:41 +05:30
|
|
|
|
2011-11-10 20:13:15 +05:30
|
|
|
virtual void save_ie(block_address ie_index, struct index_entry ie) {
|
|
|
|
entries_[ie_index] = ie;
|
|
|
|
}
|
2011-08-31 17:18:41 +05:30
|
|
|
|
2011-11-10 20:13:15 +05:30
|
|
|
virtual void commit_ies() {
|
2020-04-30 19:00:01 +05:30
|
|
|
std::pair<block_manager::write_ref, bool> p =
|
2014-08-26 15:44:49 +05:30
|
|
|
tm_.shadow(bitmap_root_, index_validator());
|
2011-11-03 20:14:00 +05:30
|
|
|
|
2011-11-10 20:13:15 +05:30
|
|
|
bitmap_root_ = p.first.get_location();
|
2014-07-25 19:16:51 +05:30
|
|
|
metadata_index *mdi = reinterpret_cast<metadata_index *>(p.first.data());
|
2011-11-10 20:13:15 +05:30
|
|
|
|
|
|
|
for (unsigned i = 0; i < entries_.size(); i++)
|
|
|
|
index_entry_traits::pack(entries_[i], mdi->index[i]);
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual index_store::ptr clone() const {
|
|
|
|
return index_store::ptr(new metadata_index_store(tm_, bitmap_root_, entries_.size()));
|
2011-08-31 17:18:41 +05:30
|
|
|
}
|
|
|
|
|
2011-11-10 20:13:15 +05:30
|
|
|
virtual block_address get_root() const {
|
|
|
|
return bitmap_root_;
|
|
|
|
}
|
2011-08-31 17:18:41 +05:30
|
|
|
|
2013-12-11 22:58:14 +05:30
|
|
|
virtual void visit(index_entry_visitor &vv, block_address nr_index_entries) const {
|
|
|
|
for (unsigned i = 0; i < entries_.size(); i++)
|
|
|
|
if (entries_[i].blocknr_ != 0)
|
|
|
|
vv.visit(entries_[i]);
|
|
|
|
|
|
|
|
#if 0
|
2011-08-31 17:18:41 +05:30
|
|
|
counter.inc(bitmap_root_);
|
|
|
|
for (unsigned i = 0; i < entries_.size(); i++)
|
2011-11-10 21:00:36 +05:30
|
|
|
// FIXME: this looks like a hack
|
2011-08-31 17:18:41 +05:30
|
|
|
if (entries_[i].blocknr_ != 0) // superblock
|
|
|
|
counter.inc(entries_[i].blocknr_);
|
2013-12-11 22:58:14 +05:30
|
|
|
#endif
|
2011-08-31 17:18:41 +05:30
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
void load_ies() {
|
2020-04-30 19:00:01 +05:30
|
|
|
block_manager::read_ref rr =
|
2014-08-26 15:44:49 +05:30
|
|
|
tm_.read_lock(bitmap_root_, index_validator());
|
2011-08-31 17:18:41 +05:30
|
|
|
|
2014-07-25 19:16:51 +05:30
|
|
|
metadata_index const *mdi = reinterpret_cast<metadata_index const *>(rr.data());
|
2011-11-10 20:13:15 +05:30
|
|
|
for (unsigned i = 0; i < entries_.size(); i++)
|
2011-08-31 17:18:41 +05:30
|
|
|
index_entry_traits::unpack(*(mdi->index + i), entries_[i]);
|
|
|
|
}
|
|
|
|
|
2014-08-26 15:44:49 +05:30
|
|
|
transaction_manager &tm_;
|
2011-11-10 20:13:15 +05:30
|
|
|
block_address bitmap_root_;
|
|
|
|
std::vector<index_entry> entries_;
|
|
|
|
};
|
2011-08-31 17:18:41 +05:30
|
|
|
}
|
|
|
|
|
|
|
|
//----------------------------------------------------------------
|
|
|
|
|
|
|
|
checked_space_map::ptr
|
2014-08-26 15:44:49 +05:30
|
|
|
persistent_data::create_disk_sm(transaction_manager &tm,
|
2011-08-31 17:18:41 +05:30
|
|
|
block_address nr_blocks)
|
|
|
|
{
|
2011-11-10 21:00:36 +05:30
|
|
|
index_store::ptr store(new btree_index_store(tm));
|
|
|
|
checked_space_map::ptr sm(new sm_disk(store, tm));
|
2011-08-31 17:18:41 +05:30
|
|
|
sm->extend(nr_blocks);
|
2011-11-21 17:47:38 +05:30
|
|
|
sm->commit();
|
2011-08-31 17:18:41 +05:30
|
|
|
return sm;
|
|
|
|
}
|
|
|
|
|
|
|
|
checked_space_map::ptr
|
2016-06-19 22:10:10 +05:30
|
|
|
persistent_data::open_disk_sm(transaction_manager &tm, void const *root)
|
2011-08-31 17:18:41 +05:30
|
|
|
{
|
|
|
|
sm_root_disk d;
|
|
|
|
sm_root v;
|
|
|
|
|
|
|
|
::memcpy(&d, root, sizeof(d));
|
|
|
|
sm_root_traits::unpack(d, v);
|
2011-11-10 21:00:36 +05:30
|
|
|
index_store::ptr store(new btree_index_store(tm, v.bitmap_root_));
|
|
|
|
return checked_space_map::ptr(new sm_disk(store, tm, v));
|
2011-08-31 17:18:41 +05:30
|
|
|
}
|
|
|
|
|
|
|
|
checked_space_map::ptr
|
2014-08-26 15:44:49 +05:30
|
|
|
persistent_data::create_metadata_sm(transaction_manager &tm, block_address nr_blocks)
|
2011-11-03 20:14:00 +05:30
|
|
|
{
|
2011-11-10 21:00:36 +05:30
|
|
|
index_store::ptr store(new metadata_index_store(tm));
|
|
|
|
checked_space_map::ptr sm(new sm_disk(store, tm));
|
2015-06-24 21:02:17 +05:30
|
|
|
|
|
|
|
if (nr_blocks > MAX_METADATA_BLOCKS) {
|
|
|
|
cerr << "truncating metadata device to " << MAX_METADATA_BLOCKS << " 4k blocks\n";
|
|
|
|
nr_blocks = MAX_METADATA_BLOCKS;
|
|
|
|
}
|
2011-11-03 20:14:00 +05:30
|
|
|
sm->extend(nr_blocks);
|
2011-11-21 17:47:38 +05:30
|
|
|
sm->commit();
|
2013-01-11 02:35:10 +05:30
|
|
|
return create_careful_alloc_sm(
|
2011-11-21 17:47:38 +05:30
|
|
|
create_recursive_sm(sm));
|
2011-11-03 20:14:00 +05:30
|
|
|
}
|
|
|
|
|
|
|
|
checked_space_map::ptr
|
2016-06-19 22:10:10 +05:30
|
|
|
persistent_data::open_metadata_sm(transaction_manager &tm, void const *root)
|
2011-08-31 17:18:41 +05:30
|
|
|
{
|
|
|
|
sm_root_disk d;
|
|
|
|
sm_root v;
|
|
|
|
|
|
|
|
::memcpy(&d, root, sizeof(d));
|
|
|
|
sm_root_traits::unpack(d, v);
|
2011-11-10 21:00:36 +05:30
|
|
|
block_address nr_indexes = div_up<block_address>(v.nr_blocks_, ENTRIES_PER_BLOCK);
|
|
|
|
index_store::ptr store(new metadata_index_store(tm, v.bitmap_root_, nr_indexes));
|
2013-01-11 02:35:10 +05:30
|
|
|
return create_careful_alloc_sm(
|
2011-11-21 17:47:38 +05:30
|
|
|
create_recursive_sm(
|
|
|
|
checked_space_map::ptr(new sm_disk(store, tm, v))));
|
2011-08-31 17:18:41 +05:30
|
|
|
}
|
|
|
|
|
2016-02-27 12:51:05 +05:30
|
|
|
bcache::validator::ptr
|
|
|
|
persistent_data::bitmap_validator() {
|
|
|
|
return bcache::validator::ptr(new bitmap_block_validator());
|
|
|
|
}
|
|
|
|
|
|
|
|
bcache::validator::ptr
|
|
|
|
persistent_data::index_validator() {
|
|
|
|
return bcache::validator::ptr(new index_block_validator());
|
|
|
|
}
|
|
|
|
|
2016-03-21 22:46:41 +05:30
|
|
|
block_address
|
|
|
|
persistent_data::get_nr_blocks_in_data_sm(transaction_manager &tm, void *root)
|
|
|
|
{
|
|
|
|
sm_root_disk d;
|
|
|
|
sm_root v;
|
|
|
|
|
|
|
|
::memcpy(&d, root, sizeof(d));
|
|
|
|
sm_root_traits::unpack(d, v);
|
|
|
|
return v.nr_blocks_;
|
|
|
|
}
|
|
|
|
|
2011-08-31 17:18:41 +05:30
|
|
|
//----------------------------------------------------------------
|