Merge pull request from zhscn/wip-4k-laddr

crimson/os/seastore: make laddr_t block aligned

Reviewed-by: Yingxin Cheng <yingxin.cheng@intel.com>
This commit is contained in:
Yingxin 2024-08-30 10:38:59 +08:00 committed by GitHub
commit fc16b162be
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
37 changed files with 1352 additions and 330 deletions

View File

@ -17,7 +17,7 @@ using BackrefNode = FixedKVNode<paddr_t>;
struct backref_map_val_t {
extent_len_t len = 0; ///< length of extents
laddr_t laddr = 0; ///< logical address of extents
laddr_t laddr = L_ADDR_MIN; ///< logical address of extents
extent_types_t type = extent_types_t::ROOT;
backref_map_val_t() = default;
@ -36,7 +36,7 @@ std::ostream& operator<<(std::ostream &out, const backref_map_val_t& val);
struct backref_map_val_le_t {
extent_len_le_t len = init_extent_len_le(0);
laddr_le_t laddr = laddr_le_t(0);
laddr_le_t laddr = laddr_le_t(L_ADDR_MIN);
extent_types_le_t type = 0;
backref_map_val_le_t() = default;

View File

@ -226,12 +226,18 @@ public:
assert(!is_end());
auto val = get_val();
auto key = get_key();
node_key_t end{};
if constexpr (std::is_same_v<node_key_t, laddr_t>) {
end = (key + val.len).checked_to_laddr();
} else {
end = key + val.len;
}
return std::make_unique<pin_t>(
ctx,
leaf.node,
leaf.pos,
val,
fixed_kv_node_meta_t<node_key_t>{ key, key + val.len, 0 });
fixed_kv_node_meta_t<node_key_t>{ key, end, 0 });
}
typename leaf_node_t::Ref get_leaf_node() {

View File

@ -977,10 +977,9 @@ public:
TCachedExtentRef<T> ext;
if (original_bptr.has_value()) {
// shallow copy the buffer from original extent
auto nbp = ceph::bufferptr(
*original_bptr,
remap_laddr - original_laddr,
remap_length);
auto remap_offset = remap_laddr.get_byte_distance<
extent_len_t>(original_laddr);
auto nbp = ceph::bufferptr(*original_bptr, remap_offset, remap_length);
// ExtentPlacementManager::alloc_new_extent will make a new
// (relative/temp) paddr, so make extent directly
ext = CachedExtent::make_cached_extent_ref<T>(std::move(nbp));

View File

@ -1325,7 +1325,7 @@ public:
void on_rewrite(Transaction&, CachedExtent &extent, extent_len_t off) final {
assert(get_type() == extent.get_type());
auto &lextent = (LogicalCachedExtent&)extent;
set_laddr(lextent.get_laddr() + off);
set_laddr((lextent.get_laddr() + off).checked_to_laddr());
}
bool has_laddr() const {

View File

@ -0,0 +1,758 @@
// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
// vim: ts=8 sw=2 smarttab
#pragma once
#include "crimson/os/seastore/seastore_types.h"
namespace crimson::os::seastore {
namespace details {
// this interval_set structure is copied from include/interval_set.h to allow
// use the different type for length as the laddr_t becomes struct, and avoid
// changing the behaviors of other components.
//
// The latest commit is 58860ce3f60489d258aaa10fd783e68083261937
template<typename T, typename L, template<typename, typename, typename ...> class C = std::map>
class interval_set {
public:
using Map = C<T, L>;
using value_type = typename Map::value_type;
using offset_type = T;
using length_type = L;
using reference = value_type&;
using const_reference = const value_type&;
using size_type = typename Map::size_type;
class const_iterator;
class iterator
{
public:
using difference_type = ssize_t;
using value_type = typename Map::value_type;
using pointer = typename Map::value_type*;
using reference = typename Map::value_type&;
using iterator_category = std::forward_iterator_tag;
explicit iterator(typename Map::iterator iter)
: _iter(iter)
{ }
// For the copy constructor and assignment operator, the compiler-generated functions, which
// perform simple bitwise copying, should be fine.
bool operator==(const iterator& rhs) const {
return (_iter == rhs._iter);
}
bool operator!=(const iterator& rhs) const {
return (_iter != rhs._iter);
}
// Dereference this iterator to get a pair.
reference operator*() const {
return *_iter;
}
// Return the interval start.
offset_type get_start() const {
return _iter->first;
}
// Return the interval length.
length_type get_len() const {
return _iter->second;
}
offset_type get_end() const {
return _iter->first + _iter->second;
}
// Set the interval length.
void set_len(const length_type& len) {
_iter->second = len;
}
// Preincrement
iterator& operator++()
{
++_iter;
return *this;
}
// Postincrement
iterator operator++(int)
{
iterator prev(_iter);
++_iter;
return prev;
}
// Predecrement
iterator& operator--()
{
--_iter;
return *this;
}
// Postdecrement
iterator operator--(int)
{
iterator prev(_iter);
--_iter;
return prev;
}
friend class interval_set::const_iterator;
protected:
typename Map::iterator _iter;
friend class interval_set;
};
class const_iterator
{
public:
using difference_type = ssize_t;
using value_type = const typename Map::value_type;
using pointer = const typename Map::value_type*;
using reference = const typename Map::value_type&;
using iterator_category = std::forward_iterator_tag;
explicit const_iterator(typename Map::const_iterator iter)
: _iter(iter)
{ }
const_iterator(const iterator &i)
: _iter(i._iter)
{ }
// For the copy constructor and assignment operator, the compiler-generated functions, which
// perform simple bitwise copying, should be fine.
bool operator==(const const_iterator& rhs) const {
return (_iter == rhs._iter);
}
bool operator!=(const const_iterator& rhs) const {
return (_iter != rhs._iter);
}
// Dereference this iterator to get a pair.
reference operator*() const {
return *_iter;
}
// Return the interval start.
offset_type get_start() const {
return _iter->first;
}
offset_type get_end() const {
return _iter->first + _iter->second;
}
// Return the interval length.
length_type get_len() const {
return _iter->second;
}
// Preincrement
const_iterator& operator++()
{
++_iter;
return *this;
}
// Postincrement
const_iterator operator++(int)
{
const_iterator prev(_iter);
++_iter;
return prev;
}
// Predecrement
iterator& operator--()
{
--_iter;
return *this;
}
// Postdecrement
iterator operator--(int)
{
iterator prev(_iter);
--_iter;
return prev;
}
protected:
typename Map::const_iterator _iter;
};
interval_set() = default;
interval_set(Map&& other) {
m.swap(other);
for (const auto& p : m) {
_size += p.second;
}
}
size_type num_intervals() const
{
return m.size();
}
iterator begin() {
return iterator(m.begin());
}
iterator lower_bound(T start) {
return iterator(find_inc_m(start));
}
iterator end() {
return iterator(m.end());
}
const_iterator begin() const {
return const_iterator(m.begin());
}
const_iterator lower_bound(T start) const {
return const_iterator(find_inc(start));
}
const_iterator end() const {
return const_iterator(m.end());
}
// helpers
private:
auto find_inc(T start) const {
auto p = m.lower_bound(start); // p->first >= start
if (p != m.begin() &&
(p == m.end() || p->first > start)) {
--p; // might overlap?
if (p->first + p->second <= start)
++p; // it doesn't.
}
return p;
}
auto find_inc_m(T start) {
auto p = m.lower_bound(start);
if (p != m.begin() &&
(p == m.end() || p->first > start)) {
--p; // might overlap?
if (p->first + p->second <= start)
++p; // it doesn't.
}
return p;
}
auto find_adj(T start) const {
auto p = m.lower_bound(start);
if (p != m.begin() &&
(p == m.end() || p->first > start)) {
--p; // might touch?
if (p->first + p->second < start)
++p; // it doesn't.
}
return p;
}
auto find_adj_m(T start) {
auto p = m.lower_bound(start);
if (p != m.begin() &&
(p == m.end() || p->first > start)) {
--p; // might touch?
if (p->first + p->second < start)
++p; // it doesn't.
}
return p;
}
void intersection_size_asym(const interval_set &s, const interval_set &l) {
auto ps = s.m.begin();
ceph_assert(ps != s.m.end());
auto offset = ps->first;
bool first = true;
auto mi = m.begin();
while (1) {
if (first)
first = false;
auto pl = l.find_inc(offset);
if (pl == l.m.end())
break;
while (ps != s.m.end() && ps->first + ps->second <= pl->first)
++ps;
if (ps == s.m.end())
break;
offset = pl->first + pl->second;
if (offset <= ps->first) {
offset = ps->first;
continue;
}
if (*ps == *pl) {
do {
mi = m.insert(mi, *ps);
_size += ps->second;
++ps;
++pl;
} while (ps != s.m.end() && pl != l.m.end() && *ps == *pl);
if (ps == s.m.end())
break;
offset = ps->first;
continue;
}
auto start = std::max<T>(ps->first, pl->first);
auto en = std::min<T>(ps->first + ps->second, offset);
ceph_assert(en > start);
mi = m.emplace_hint(mi, start, en - start);
_size += mi->second;
if (ps->first + ps->second <= offset) {
++ps;
if (ps == s.m.end())
break;
offset = ps->first;
}
}
}
bool subset_size_sym(const interval_set &b) const {
auto pa = m.begin(), pb = b.m.begin();
const auto a_end = m.end(), b_end = b.m.end();
while (pa != a_end && pb != b_end) {
while (pb->first + pb->second <= pa->first) {
++pb;
if (pb == b_end)
return false;
}
if (*pa == *pb) {
do {
++pa;
++pb;
} while (pa != a_end && pb != b_end && *pa == *pb);
continue;
}
// interval begins before other
if (pa->first < pb->first)
return false;
// interval is longer than other
if (pa->first + pa->second > pb->first + pb->second)
return false;
++pa;
}
return pa == a_end;
}
public:
bool operator==(const interval_set& other) const {
return _size == other._size && m == other.m;
}
uint64_t size() const {
return _size;
}
void bound_encode(size_t& p) const {
denc_traits<Map>::bound_encode(m, p);
}
void encode(ceph::buffer::list::contiguous_appender& p) const {
denc(m, p);
}
void decode(ceph::buffer::ptr::const_iterator& p) {
denc(m, p);
_size = 0;
for (const auto& p : m) {
_size += p.second;
}
}
void decode(ceph::buffer::list::iterator& p) {
denc(m, p);
_size = 0;
for (const auto& p : m) {
_size += p.second;
}
}
void encode_nohead(ceph::buffer::list::contiguous_appender& p) const {
denc_traits<Map>::encode_nohead(m, p);
}
void decode_nohead(int n, ceph::buffer::ptr::const_iterator& p) {
denc_traits<Map>::decode_nohead(n, m, p);
_size = 0;
for (const auto& p : m) {
_size += p.second;
}
}
void clear() {
m.clear();
_size = 0;
}
bool contains(T i, T *pstart=0, L *plen=0) const {
auto p = find_inc(i);
if (p == m.end()) return false;
if (p->first > i) return false;
if (p->first+p->second <= i) return false;
ceph_assert(p->first <= i && p->first+p->second > i);
if (pstart)
*pstart = p->first;
if (plen)
*plen = p->second;
return true;
}
bool contains(T start, L len) const {
auto p = find_inc(start);
if (p == m.end()) return false;
if (p->first > start) return false;
if (p->first+p->second <= start) return false;
ceph_assert(p->first <= start && p->first+p->second > start);
if (p->first+p->second < start+len) return false;
return true;
}
bool intersects(T start, L len) const {
interval_set a;
a.insert(start, len);
interval_set i;
i.intersection_of( *this, a );
if (i.empty()) return false;
return true;
}
// outer range of set
bool empty() const {
return m.empty();
}
offset_type range_start() const {
ceph_assert(!empty());
auto p = m.begin();
return p->first;
}
offset_type range_end() const {
ceph_assert(!empty());
auto p = m.rbegin();
return p->first + p->second;
}
// interval start after p (where p not in set)
bool starts_after(T i) const {
ceph_assert(!contains(i));
auto p = find_inc(i);
if (p == m.end()) return false;
return true;
}
offset_type start_after(T i) const {
ceph_assert(!contains(i));
auto p = find_inc(i);
return p->first;
}
// interval end that contains start
offset_type end_after(T start) const {
ceph_assert(contains(start));
auto p = find_inc(start);
return p->first+p->second;
}
void insert(T val) {
insert(val, 1);
}
void insert(T start, L len, T *pstart=0, L *plen=0) {
//cout << "insert " << start << "~" << len << endl;
ceph_assert(len > 0);
_size += len;
auto p = find_adj_m(start);
if (p == m.end()) {
m[start] = len; // new interval
if (pstart)
*pstart = start;
if (plen)
*plen = len;
} else {
if (p->first < start) {
if (p->first + p->second != start) {
//cout << "p is " << p->first << "~" << p->second << ", start is " << start << ", len is " << len << endl;
ceph_abort();
}
p->second += len; // append to end
auto n = p;
++n;
if (pstart)
*pstart = p->first;
if (n != m.end() &&
start+len == n->first) { // combine with next, too!
p->second += n->second;
if (plen)
*plen = p->second;
m.erase(n);
} else {
if (plen)
*plen = p->second;
}
} else {
if (start+len == p->first) {
if (pstart)
*pstart = start;
if (plen)
*plen = len + p->second;
L psecond = p->second;
m.erase(p);
m[start] = len + psecond; // append to front
} else {
ceph_assert(p->first > start+len);
if (pstart)
*pstart = start;
if (plen)
*plen = len;
m[start] = len; // new interval
}
}
}
}
void swap(interval_set& other) {
m.swap(other.m);
std::swap(_size, other._size);
}
void erase(const iterator &i) {
_size -= i.get_len();
m.erase(i._iter);
}
void erase(T val) {
erase(val, 1);
}
void erase(T start, L len,
std::function<bool(T, L)> claim = {}) {
auto p = find_inc_m(start);
_size -= len;
ceph_assert(p != m.end());
ceph_assert(p->first <= start);
L before = start - p->first;
ceph_assert(p->second >= before+len);
L after = p->second - before - len;
if (before) {
if (claim && claim(p->first, before)) {
_size -= before;
m.erase(p);
} else {
p->second = before; // shorten bit before
}
} else {
m.erase(p);
}
if (after) {
if (claim && claim(start + len, after)) {
_size -= after;
} else {
m[start + len] = after;
}
}
}
void subtract(const interval_set &a) {
for (const auto& [start, len] : a.m) {
erase(start, len);
}
}
void insert(const interval_set &a) {
for (const auto& [start, len] : a.m) {
insert(start, len);
}
}
void intersection_of(const interval_set &a, const interval_set &b) {
ceph_assert(&a != this);
ceph_assert(&b != this);
clear();
const interval_set *s, *l;
if (a.size() < b.size()) {
s = &a;
l = &b;
} else {
s = &b;
l = &a;
}
if (!s->size())
return;
/*
* Use the lower_bound algorithm for larger size ratios
* where it performs better, but not for smaller size
* ratios where sequential search performs better.
*/
if (l->size() / s->size() >= 10) {
intersection_size_asym(*s, *l);
return;
}
auto pa = a.m.begin();
auto pb = b.m.begin();
auto mi = m.begin();
while (pa != a.m.end() && pb != b.m.end()) {
// passing?
if (pa->first + pa->second <= pb->first)
{ pa++; continue; }
if (pb->first + pb->second <= pa->first)
{ pb++; continue; }
if (*pa == *pb) {
do {
mi = m.insert(mi, *pa);
_size += pa->second;
++pa;
++pb;
} while (pa != a.m.end() && pb != b.m.end() && *pa == *pb);
continue;
}
T start = std::max(pa->first, pb->first);
T en = std::min(pa->first+pa->second, pb->first+pb->second);
ceph_assert(en > start);
mi = m.emplace_hint(mi, start, en - start);
_size += mi->second;
if (pa->first+pa->second > pb->first+pb->second)
pb++;
else
pa++;
}
}
void intersection_of(const interval_set& b) {
interval_set a;
swap(a);
intersection_of(a, b);
}
void union_of(const interval_set &a, const interval_set &b) {
ceph_assert(&a != this);
ceph_assert(&b != this);
clear();
//cout << "union_of" << endl;
// a
m = a.m;
_size = a._size;
// - (a*b)
interval_set ab;
ab.intersection_of(a, b);
subtract(ab);
// + b
insert(b);
return;
}
void union_of(const interval_set &b) {
interval_set a;
swap(a);
union_of(a, b);
}
void union_insert(T off, L len) {
interval_set a;
a.insert(off, len);
union_of(a);
}
bool subset_of(const interval_set &big) const {
if (!size())
return true;
if (size() > big.size())
return false;
if (range_end() > big.range_end())
return false;
/*
* Use the lower_bound algorithm for larger size ratios
* where it performs better, but not for smaller size
* ratios where sequential search performs better.
*/
if (big.size() / size() < 10)
return subset_size_sym(big);
for (const auto& [start, len] : m) {
if (!big.contains(start, len)) return false;
}
return true;
}
/*
* build a subset of @other, starting at or after @start, and including
* @len worth of values, skipping holes. e.g.,
* span_of([5~10,20~5], 8, 5) -> [8~2,20~3]
*/
void span_of(const interval_set &other, T start, L len) {
clear();
auto p = other.find_inc(start);
if (p == other.m.end())
return;
if (p->first < start) {
if (p->first + p->second < start)
return;
if (p->first + p->second < start + len) {
L howmuch = p->second - (start - p->first);
insert(start, howmuch);
len -= howmuch;
p++;
} else {
insert(start, len);
return;
}
}
while (p != other.m.end() && len > 0) {
if (p->second < len) {
insert(p->first, p->second);
len -= p->second;
p++;
} else {
insert(p->first, len);
return;
}
}
}
/*
* Move contents of m into another Map. Use that instead of
* encoding interval_set into bufferlist then decoding it back into Map.
*/
Map detach() && {
return std::move(m);
}
private:
// data
uint64_t _size = 0;
Map m; // map start -> len
};
} // namespace details
using laddr_interval_set_t = details::interval_set<laddr_t, extent_len_t>;
} // namespace crimson::os::seastore

View File

@ -316,7 +316,7 @@ BtreeLBAManager::_alloc_extents(
assert((info.key == L_ADDR_NULL) == (laddr_null));
if (!laddr_null) {
assert(info.key >= last_end);
last_end = info.key + info.len;
last_end = (info.key + info.len).checked_to_laddr();
}
}
#endif
@ -325,7 +325,8 @@ BtreeLBAManager::_alloc_extents(
total_len += info.len;
}
} else {
total_len = alloc_infos.back().key + alloc_infos.back().len - hint;
auto end = alloc_infos.back().key + alloc_infos.back().len;
total_len = end.get_byte_distance<extent_len_t>(hint);
}
struct state_t {
@ -381,7 +382,7 @@ BtreeLBAManager::_alloc_extents(
interruptible::ready_future_marker{},
seastar::stop_iteration::yes);
} else {
state.last_end = pos.get_key() + pos.get_val().len;
state.last_end = (pos.get_key() + pos.get_val().len).checked_to_laddr();
TRACET("{}~{}, hint={}, state: {}~{}, repeat ... -- {}",
t, addr, total_len, hint,
pos.get_key(), pos.get_val().len,
@ -431,7 +432,7 @@ BtreeLBAManager::_alloc_extents(
return iter.next(c).si_then([&state, &alloc_info](auto it) {
state.insert_iter = it;
if (alloc_info.key == L_ADDR_NULL) {
state.last_end += alloc_info.len;
state.last_end = (state.last_end + alloc_info.len).checked_to_laddr();
}
});
});

View File

@ -128,7 +128,7 @@ public:
assert(intermediate_key >= intermediate_base);
assert((intermediate_key == L_ADDR_NULL)
== (intermediate_base == L_ADDR_NULL));
return intermediate_key - intermediate_base;
return intermediate_key.get_byte_distance<extent_len_t>(intermediate_base);
}
extent_len_t get_intermediate_length() const final {
@ -465,7 +465,7 @@ public:
: L_ADDR_NULL;
auto remap_offset = remap.offset;
auto remap_len = remap.len;
auto remap_laddr = orig_laddr + remap_offset;
auto remap_laddr = (orig_laddr + remap_offset).checked_to_laddr();
ceph_assert(intermediate_base != L_ADDR_NULL);
ceph_assert(intermediate_key != L_ADDR_NULL);
ceph_assert(remap_len < orig_len);
@ -476,7 +476,7 @@ public:
" intermediate_base: {}, intermediate_key: {}", t,
remap_laddr, orig_paddr, remap_len,
intermediate_base, intermediate_key);
auto remapped_intermediate_key = intermediate_key + remap_offset;
auto remapped_intermediate_key = (intermediate_key + remap_offset).checked_to_laddr();
alloc_infos.emplace_back(
alloc_mapping_info_t::create_indirect(
remap_laddr,
@ -485,7 +485,7 @@ public:
}
fut = alloc_cloned_mappings(
t,
remaps.front().offset + orig_laddr,
(remaps.front().offset + orig_laddr).checked_to_laddr(),
std::move(alloc_infos)
).si_then([&orig_mapping](auto imappings) mutable {
std::vector<LBAMappingRef> mappings;
@ -504,7 +504,7 @@ public:
} else { // !orig_mapping->is_indirect()
fut = alloc_extents(
t,
remaps.front().offset + orig_laddr,
(remaps.front().offset + orig_laddr).checked_to_laddr(),
std::move(extents),
EXTENT_DEFAULT_REF_COUNT);
}

View File

@ -83,7 +83,7 @@ BtreeLBAMappingRef LBALeafNode::get_mapping(
this,
iter.get_offset(),
val,
lba_node_meta_t{laddr, laddr + val.len, 0});
lba_node_meta_t{laddr, (laddr + val.len).checked_to_laddr(), 0});
}
}

View File

@ -7,6 +7,7 @@
#include "crimson/common/log.h"
#include "crimson/os/seastore/object_data_handler.h"
#include "crimson/os/seastore/laddr_interval_set.h"
namespace {
seastar::logger& logger() {
@ -63,7 +64,7 @@ struct extent_to_write_t {
}
laddr_t get_end_addr() const {
return addr + len;
return (addr + len).checked_to_laddr();
}
static extent_to_write_t create_data(
@ -169,7 +170,7 @@ struct extent_to_remap_t {
nullptr, new_offset, new_len, p->get_key(), p->get_length(), b);
}
uint64_t laddr_start;
laddr_t laddr_start;
extent_len_t length;
std::optional<bufferlist> bl;
@ -180,7 +181,7 @@ private:
pin(std::move(pin)), new_offset(new_offset), new_len(new_len) {}
extent_to_remap_t(type_t type,
LBAMappingRef &&pin, extent_len_t new_offset, extent_len_t new_len,
uint64_t ori_laddr, extent_len_t ori_len, std::optional<bufferlist> b)
laddr_t ori_laddr, extent_len_t ori_len, std::optional<bufferlist> b)
: type(type),
pin(std::move(pin)), new_offset(new_offset), new_len(new_len),
laddr_start(ori_laddr), length(ori_len), bl(b) {}
@ -267,7 +268,7 @@ overwrite_ops_t prepare_ops_list(
ops.to_remap.push_back(extent_to_remap_t::create_remap2(
std::move(front.pin),
front.len,
back.addr - front.addr - front.len));
back.addr.get_byte_distance<extent_len_t>(front.addr) - front.len));
ops.to_remove.pop_front();
} else {
// prepare to_remap, happens in one or multiple extents
@ -288,13 +289,13 @@ overwrite_ops_t prepare_ops_list(
back.pin->get_key() + back.pin->get_length());
ops.to_remap.push_back(extent_to_remap_t::create_remap1(
std::move(back.pin),
back.addr - back.pin->get_key(),
back.addr.get_byte_distance<extent_len_t>(back.pin->get_key()),
back.len));
ops.to_remove.pop_back();
}
}
interval_set<uint64_t> pre_alloc_addr_removed, pre_alloc_addr_remapped;
laddr_interval_set_t pre_alloc_addr_removed, pre_alloc_addr_remapped;
if (delta_based_overwrite_max_extent_size) {
for (auto &r : ops.to_remove) {
if (r->is_data_stable() && !r->is_zero_reserved()) {
@ -321,7 +322,7 @@ overwrite_ops_t prepare_ops_list(
erased_num = std::erase_if(
ops.to_remove,
[&region, &to_remap](auto &r) {
interval_set<uint64_t> range;
laddr_interval_set_t range;
range.insert(r->get_key(), r->get_length());
if (range.contains(region.addr, region.len) && !r->is_clone()) {
to_remap.push_back(extent_to_remap_t::create_overwrite(
@ -337,12 +338,13 @@ overwrite_ops_t prepare_ops_list(
erased_num = std::erase_if(
ops.to_remap,
[&region, &to_remap](auto &r) {
interval_set<uint64_t> range;
laddr_interval_set_t range;
range.insert(r.pin->get_key(), r.pin->get_length());
if (range.contains(region.addr, region.len) && !r.pin->is_clone()) {
to_remap.push_back(extent_to_remap_t::create_overwrite(
region.addr - range.begin().get_start(), region.len,
std::move(r.pin), *region.to_write));
region.addr.get_byte_distance<
extent_len_t> (range.begin().get_start()),
region.len, std::move(r.pin), *region.to_write));
return true;
}
return false;
@ -519,7 +521,6 @@ ObjectDataHandler::write_ret do_insertions(
[ctx](auto &region) {
LOG_PREFIX(object_data_handler.cc::do_insertions);
if (region.is_data()) {
assert_aligned(region.addr);
assert_aligned(region.len);
ceph_assert(region.len == region.bl->length());
DEBUGT("allocating extent: {}~{}",
@ -544,7 +545,7 @@ ObjectDataHandler::write_ret do_insertions(
off);
}
iter.copy(extent->get_length(), extent->get_bptr().c_str());
off += extent->get_length();
off = (off + extent->get_length()).checked_to_laddr();
left -= extent->get_length();
}
return ObjectDataHandler::write_iertr::now();
@ -625,13 +626,16 @@ std::ostream& operator<<(
* left_paddr right_paddr
*/
struct overwrite_plan_t {
// addresses
// reserved data base of object data
laddr_t data_base;
// addresses about extents
laddr_t pin_begin;
laddr_t pin_end;
paddr_t left_paddr;
paddr_t right_paddr;
laddr_t data_begin;
laddr_t data_end;
laddr_offset_t data_begin;
laddr_offset_t data_end;
laddr_t aligned_data_begin;
laddr_t aligned_data_end;
@ -646,42 +650,43 @@ struct overwrite_plan_t {
public:
extent_len_t get_left_size() const {
return data_begin - pin_begin;
return data_begin.get_byte_distance<extent_len_t>(pin_begin);
}
extent_len_t get_left_extent_size() const {
return aligned_data_begin - pin_begin;
return aligned_data_begin.get_byte_distance<extent_len_t>(pin_begin);
}
extent_len_t get_left_alignment_size() const {
return data_begin - aligned_data_begin;
return data_begin.get_byte_distance<extent_len_t>(aligned_data_begin);
}
extent_len_t get_right_size() const {
return pin_end - data_end;
return pin_end.get_byte_distance<extent_len_t>(data_end);
}
extent_len_t get_right_extent_size() const {
return pin_end - aligned_data_end;
return pin_end.get_byte_distance<extent_len_t>(aligned_data_end);
}
extent_len_t get_right_alignment_size() const {
return aligned_data_end - data_end;
return aligned_data_end.get_byte_distance<extent_len_t>(data_end);
}
extent_len_t get_aligned_data_size() const {
return aligned_data_end - aligned_data_begin;
return aligned_data_end.get_byte_distance<extent_len_t>(aligned_data_begin);
}
extent_len_t get_pins_size() const {
return pin_end - pin_begin;
return pin_end.get_byte_distance<extent_len_t>(pin_begin);
}
friend std::ostream& operator<<(
std::ostream& out,
const overwrite_plan_t& overwrite_plan) {
return out << "overwrite_plan_t("
<< "pin_begin=" << overwrite_plan.pin_begin
<< "data_base=" << overwrite_plan.data_base
<< ", pin_begin=" << overwrite_plan.pin_begin
<< ", pin_end=" << overwrite_plan.pin_end
<< ", left_paddr=" << overwrite_plan.left_paddr
<< ", right_paddr=" << overwrite_plan.right_paddr
@ -697,18 +702,20 @@ public:
<< ")";
}
overwrite_plan_t(laddr_t offset,
overwrite_plan_t(laddr_t data_base,
objaddr_t offset,
extent_len_t len,
const lba_pin_list_t& pins,
extent_len_t block_size) :
data_base(data_base),
pin_begin(pins.front()->get_key()),
pin_end(pins.back()->get_key() + pins.back()->get_length()),
pin_end((pins.back()->get_key() + pins.back()->get_length()).checked_to_laddr()),
left_paddr(pins.front()->get_val()),
right_paddr(pins.back()->get_val()),
data_begin(offset),
data_end(offset + len),
aligned_data_begin(p2align((uint64_t)data_begin, (uint64_t)block_size)),
aligned_data_end(p2roundup((uint64_t)data_end, (uint64_t)block_size)),
data_begin(data_base + offset),
data_end(data_base + offset + len),
aligned_data_begin(data_begin.get_aligned_laddr()),
aligned_data_end(data_end.get_roundup_laddr()),
left_operation(overwrite_operation_t::UNKNOWN),
right_operation(overwrite_operation_t::UNKNOWN),
block_size(block_size),
@ -725,11 +732,6 @@ public:
private:
// refer to overwrite_plan_t description
void validate() const {
ceph_assert(pin_begin % block_size == 0);
ceph_assert(pin_end % block_size == 0);
ceph_assert(aligned_data_begin % block_size == 0);
ceph_assert(aligned_data_end % block_size == 0);
ceph_assert(pin_begin <= aligned_data_begin);
ceph_assert(aligned_data_begin <= data_begin);
ceph_assert(data_begin <= data_end);
@ -941,9 +943,9 @@ operate_ret operate_right(context_t ctx, LBAMappingRef &pin, const overwrite_pla
std::nullopt);
} else {
auto append_offset =
overwrite_plan.data_end
- right_pin_begin
+ pin->get_intermediate_offset();
overwrite_plan.data_end.get_byte_distance<
extent_len_t>(right_pin_begin)
+ pin->get_intermediate_offset();
return ctx.tm.read_pin<ObjectDataBlock>(
ctx.t, pin->duplicate()
).si_then([append_offset, append_len](auto right_extent) {
@ -973,9 +975,9 @@ operate_ret operate_right(context_t ctx, LBAMappingRef &pin, const overwrite_pla
std::nullopt);
} else {
auto append_offset =
overwrite_plan.data_end
- right_pin_begin
+ pin->get_intermediate_offset();
overwrite_plan.data_end.get_byte_distance<
extent_len_t>(right_pin_begin)
+ pin->get_intermediate_offset();
return ctx.tm.read_pin<ObjectDataBlock>(
ctx.t, pin->duplicate()
).si_then([append_offset, append_len,
@ -1081,14 +1083,14 @@ ObjectDataHandler::clear_ret ObjectDataHandler::trim_data_reservation(
extent_to_write_list_t(),
[ctx, size, &object_data, this](auto &pins, auto &to_write) {
LOG_PREFIX(ObjectDataHandler::trim_data_reservation);
DEBUGT("object_data: {}~{}",
ctx.t,
object_data.get_reserved_data_base(),
object_data.get_reserved_data_len());
auto data_base = object_data.get_reserved_data_base();
auto data_len = object_data.get_reserved_data_len();
DEBUGT("object_data: {}~{}", ctx.t, data_base, data_len);
laddr_t aligned_start = (data_base + size).get_aligned_laddr();
loffset_t aligned_length =
data_len - aligned_start.get_byte_distance<loffset_t>(data_base);
return ctx.tm.get_pins(
ctx.t,
object_data.get_reserved_data_base() + size,
object_data.get_reserved_data_len() - size
ctx.t, aligned_start, aligned_length
).si_then([ctx, size, &pins, &object_data, &to_write](auto _pins) {
_pins.swap(pins);
ceph_assert(pins.size());
@ -1101,8 +1103,8 @@ ObjectDataHandler::clear_ret ObjectDataHandler::trim_data_reservation(
ceph_assert(pin.get_key() >= object_data.get_reserved_data_base());
ceph_assert(
pin.get_key() <= object_data.get_reserved_data_base() + size);
auto pin_offset = pin.get_key() -
object_data.get_reserved_data_base();
auto pin_offset = pin.get_key().template get_byte_distance<extent_len_t>(
object_data.get_reserved_data_base());
if ((pin.get_key() == (object_data.get_reserved_data_base() + size)) ||
(pin.get_val().is_zero())) {
/* First pin is exactly at the boundary or is a zero pin. Either way,
@ -1126,7 +1128,7 @@ ObjectDataHandler::clear_ret ObjectDataHandler::trim_data_reservation(
pin.get_key(),
size - pin_offset));
to_write.push_back(extent_to_write_t::create_zero(
object_data.get_reserved_data_base() + roundup_size,
(object_data.get_reserved_data_base() + roundup_size).checked_to_laddr(),
object_data.get_reserved_data_len() - roundup_size));
return clear_iertr::now();
} else {
@ -1151,7 +1153,7 @@ ObjectDataHandler::clear_ret ObjectDataHandler::trim_data_reservation(
pin.get_key(),
bl));
to_write.push_back(extent_to_write_t::create_zero(
object_data.get_reserved_data_base() + roundup_size,
(object_data.get_reserved_data_base() + roundup_size).checked_to_laddr(),
object_data.get_reserved_data_len() - roundup_size));
return clear_iertr::now();
});
@ -1186,12 +1188,13 @@ ObjectDataHandler::clear_ret ObjectDataHandler::trim_data_reservation(
* optionally on the right.
*/
extent_to_write_list_t get_to_writes_with_zero_buffer(
laddr_t data_base,
const extent_len_t block_size,
laddr_t offset, extent_len_t len,
objaddr_t offset, extent_len_t len,
std::optional<bufferptr> &&headptr, std::optional<bufferptr> &&tailptr)
{
auto zero_left = p2roundup(offset, (laddr_t)block_size);
auto zero_right = p2align(offset + len, (laddr_t)block_size);
auto zero_left = p2roundup(offset, (objaddr_t)block_size);
auto zero_right = p2align(offset + len, (objaddr_t)block_size);
auto left = headptr ? (offset - headptr->length()) : offset;
auto right = tailptr ?
(offset + len + tailptr->length()) :
@ -1207,8 +1210,6 @@ extent_to_write_list_t get_to_writes_with_zero_buffer(
(!tailptr && (right == zero_right)));
assert(right > left);
assert((left % block_size) == 0);
assert((right % block_size) == 0);
// zero region too small for a reserved section,
// headptr and tailptr in same extent
@ -1225,7 +1226,8 @@ extent_to_write_list_t get_to_writes_with_zero_buffer(
assert(bl.length() % block_size == 0);
assert(bl.length() == (right - left));
extent_to_write_list_t ret;
ret.push_back(extent_to_write_t::create_data(left, bl));
ret.push_back(extent_to_write_t::create_data(
(data_base + left).checked_to_laddr(), bl));
return ret;
} else {
// reserved section between ends, headptr and tailptr in different extents
@ -1236,10 +1238,13 @@ extent_to_write_list_t get_to_writes_with_zero_buffer(
headbl.append_zero(zero_left - left - headbl.length());
assert(headbl.length() % block_size == 0);
assert(headbl.length() > 0);
ret.push_back(extent_to_write_t::create_data(left, headbl));
ret.push_back(extent_to_write_t::create_data(
(data_base + left).checked_to_laddr(), headbl));
}
// reserved zero region
ret.push_back(extent_to_write_t::create_zero(zero_left, zero_right - zero_left));
ret.push_back(extent_to_write_t::create_zero(
(data_base + zero_left).checked_to_laddr(),
zero_right - zero_left));
assert(ret.back().len % block_size == 0);
assert(ret.back().len > 0);
if (tailptr) {
@ -1248,7 +1253,8 @@ extent_to_write_list_t get_to_writes_with_zero_buffer(
tailbl.append_zero(right - zero_right - tailbl.length());
assert(tailbl.length() % block_size == 0);
assert(tailbl.length() > 0);
ret.push_back(extent_to_write_t::create_data(zero_right, tailbl));
ret.push_back(extent_to_write_t::create_data(
(data_base + zero_right).checked_to_laddr(), tailbl));
}
return ret;
}
@ -1270,7 +1276,8 @@ extent_to_write_list_t get_to_writes(laddr_t offset, bufferlist &bl)
ObjectDataHandler::write_ret ObjectDataHandler::overwrite(
context_t ctx,
laddr_t offset,
laddr_t data_base,
objaddr_t offset,
extent_len_t len,
std::optional<bufferlist> &&bl,
lba_pin_list_t &&_pins)
@ -1278,11 +1285,11 @@ ObjectDataHandler::write_ret ObjectDataHandler::overwrite(
if (bl.has_value()) {
assert(bl->length() == len);
}
overwrite_plan_t overwrite_plan(offset, len, _pins, ctx.tm.get_block_size());
overwrite_plan_t overwrite_plan(data_base, offset, len, _pins, ctx.tm.get_block_size());
return seastar::do_with(
std::move(_pins),
extent_to_write_list_t(),
[ctx, len, offset, overwrite_plan, bl=std::move(bl), this]
[ctx, data_base, len, offset, overwrite_plan, bl=std::move(bl), this]
(auto &pins, auto &to_write) mutable
{
LOG_PREFIX(ObjectDataHandler::overwrite);
@ -1297,7 +1304,7 @@ ObjectDataHandler::write_ret ObjectDataHandler::overwrite(
ctx,
pins.front(),
overwrite_plan
).si_then([ctx, len, offset, overwrite_plan, bl=std::move(bl),
).si_then([ctx, data_base, len, offset, overwrite_plan, bl=std::move(bl),
&to_write, &pins, this](auto p) mutable {
auto &[left_extent, headptr] = p;
if (left_extent) {
@ -1311,7 +1318,7 @@ ObjectDataHandler::write_ret ObjectDataHandler::overwrite(
ctx,
pins.back(),
overwrite_plan
).si_then([ctx, len, offset,
).si_then([ctx, data_base, len, offset,
pin_begin=overwrite_plan.pin_begin,
pin_end=overwrite_plan.pin_end,
bl=std::move(bl), headptr=std::move(headptr),
@ -1322,8 +1329,7 @@ ObjectDataHandler::write_ret ObjectDataHandler::overwrite(
bufferlist write_bl;
if (headptr) {
write_bl.append(*headptr);
write_offset -= headptr->length();
assert_aligned(write_offset);
write_offset = write_offset - headptr->length();
}
write_bl.claim_append(*bl);
if (tailptr) {
@ -1332,11 +1338,12 @@ ObjectDataHandler::write_ret ObjectDataHandler::overwrite(
}
splice_extent_to_write(
to_write,
get_to_writes(write_offset, write_bl));
get_to_writes((data_base + write_offset).checked_to_laddr(), write_bl));
} else {
splice_extent_to_write(
to_write,
get_to_writes_with_zero_buffer(
data_base,
ctx.tm.get_block_size(),
offset,
len,
@ -1388,14 +1395,20 @@ ObjectDataHandler::zero_ret ObjectDataHandler::zero(
object_data,
p2roundup(offset + len, ctx.tm.get_block_size())
).si_then([this, ctx, offset, len, &object_data] {
auto logical_offset = object_data.get_reserved_data_base() + offset;
auto data_base = object_data.get_reserved_data_base();
laddr_offset_t l_start = data_base + offset;
laddr_offset_t l_end = l_start + len;
laddr_t aligned_start = l_start.get_aligned_laddr();
loffset_t aligned_length =
l_end.get_roundup_laddr().get_byte_distance<
loffset_t>(aligned_start);
return ctx.tm.get_pins(
ctx.t,
logical_offset,
len
).si_then([this, ctx, logical_offset, len](auto pins) {
aligned_start,
aligned_length
).si_then([this, ctx, data_base, offset, len](auto pins) {
return overwrite(
ctx, logical_offset, len,
ctx, data_base, offset, len,
std::nullopt, std::move(pins));
});
});
@ -1423,15 +1436,21 @@ ObjectDataHandler::write_ret ObjectDataHandler::write(
object_data,
p2roundup(offset + bl.length(), ctx.tm.get_block_size())
).si_then([this, ctx, offset, &object_data, &bl] {
auto logical_offset = object_data.get_reserved_data_base() + offset;
auto data_base = object_data.get_reserved_data_base();
laddr_offset_t l_start = data_base + offset;
laddr_offset_t l_end = l_start + bl.length();
laddr_t aligned_start = l_start.get_aligned_laddr();
loffset_t aligned_length =
l_end.get_roundup_laddr().get_byte_distance<
loffset_t>(aligned_start);
return ctx.tm.get_pins(
ctx.t,
logical_offset,
bl.length()
).si_then([this, ctx,logical_offset, &bl](
aligned_start,
aligned_length
).si_then([this, ctx, offset, data_base, &bl](
auto pins) {
return overwrite(
ctx, logical_offset, bl.length(),
ctx, data_base, offset, bl.length(),
bufferlist(bl), std::move(pins));
});
});
@ -1459,17 +1478,21 @@ ObjectDataHandler::read_ret ObjectDataHandler::read(
ceph_assert(!object_data.is_null());
ceph_assert((obj_offset + len) <= object_data.get_reserved_data_len());
ceph_assert(len > 0);
laddr_t l_start =
laddr_offset_t l_start =
object_data.get_reserved_data_base() + obj_offset;
laddr_offset_t l_end = l_start + len;
laddr_t aligned_start = l_start.get_aligned_laddr();
loffset_t aligned_length =
l_end.get_roundup_laddr().get_byte_distance<
loffset_t>(aligned_start);
return ctx.tm.get_pins(
ctx.t,
l_start,
len
).si_then([FNAME, ctx, l_start, len, &ret](auto _pins) {
aligned_start,
aligned_length
).si_then([FNAME, ctx, l_start, l_end, &ret](auto _pins) {
// offset~len falls within reserved region and len > 0
ceph_assert(_pins.size() >= 1);
ceph_assert((*_pins.begin())->get_key() <= l_start);
auto l_end = l_start + len;
return seastar::do_with(
std::move(_pins),
l_start,
@ -1488,17 +1511,19 @@ ObjectDataHandler::read_ret ObjectDataHandler::read(
ceph_assert(l_current < l_end);
auto pin_len = pin->get_length();
assert(pin_len > 0);
laddr_t l_pin_end = pin_key + pin_len;
laddr_offset_t l_pin_end = pin_key + pin_len;
ceph_assert(l_current < l_pin_end);
laddr_t l_current_end = std::min(l_pin_end, l_end);
laddr_offset_t l_current_end = std::min(l_pin_end, l_end);
if (pin->get_val().is_zero()) {
DEBUGT("got {}~{} from zero-pin {}~{}",
ctx.t,
l_current,
l_current_end - l_current,
l_current_end.get_byte_distance<loffset_t>(l_current),
pin_key,
pin_len);
ret.append_zero(l_current_end - l_current);
ret.append_zero(
l_current_end.get_byte_distance<
extent_len_t>(l_current));
l_current = l_current_end;
return seastar::now();
}
@ -1515,7 +1540,7 @@ ObjectDataHandler::read_ret ObjectDataHandler::read(
DEBUGT("reading {}~{} from indirect-pin {}~{}, direct-pin {}~{}(off={})",
ctx.t,
l_current,
l_current_end - l_current,
l_current_end.get_byte_distance<extent_len_t>(l_current),
pin_key,
pin_len,
e_key,
@ -1527,14 +1552,16 @@ ObjectDataHandler::read_ret ObjectDataHandler::read(
DEBUGT("reading {}~{} from pin {}~{}",
ctx.t,
l_current,
l_current_end - l_current,
l_current_end.get_byte_distance<
extent_len_t>(l_current),
pin_key,
pin_len);
e_key = pin_key;
e_len = pin_len;
e_off = 0;
}
extent_len_t e_current_off = e_off + l_current - pin_key;
extent_len_t e_current_off = (l_current + e_off)
.template get_byte_distance<extent_len_t>(pin_key);
return ctx.tm.read_pin<ObjectDataBlock>(
ctx.t,
std::move(pin)
@ -1550,7 +1577,7 @@ ObjectDataHandler::read_ret ObjectDataHandler::read(
bufferptr(
extent->get_bptr(),
e_current_off,
l_current_end - l_current));
l_current_end.get_byte_distance<extent_len_t>(l_current)));
l_current = l_current_end;
return seastar::now();
}).handle_error_interruptible(
@ -1592,26 +1619,32 @@ ObjectDataHandler::fiemap_ret ObjectDataHandler::fiemap(
ceph_assert(!object_data.is_null());
ceph_assert((obj_offset + len) <= object_data.get_reserved_data_len());
ceph_assert(len > 0);
laddr_t l_start =
laddr_offset_t l_start =
object_data.get_reserved_data_base() + obj_offset;
laddr_offset_t l_end = l_start + len;
laddr_t aligned_start = l_start.get_aligned_laddr();
loffset_t aligned_length =
l_end.get_roundup_laddr().get_byte_distance<
loffset_t>(aligned_start);
return ctx.tm.get_pins(
ctx.t,
l_start,
len
aligned_start,
aligned_length
).si_then([l_start, len, &object_data, &ret](auto &&pins) {
ceph_assert(pins.size() >= 1);
ceph_assert((*pins.begin())->get_key() <= l_start);
for (auto &&i: pins) {
if (!(i->get_val().is_zero())) {
auto ret_left = std::max(i->get_key(), l_start);
auto ret_right = std::min(
laddr_offset_t ret_left = std::max(laddr_offset_t(i->get_key(), 0), l_start);
laddr_offset_t ret_right = std::min(
i->get_key() + i->get_length(),
l_start + len);
assert(ret_right > ret_left);
ret.emplace(
std::make_pair(
ret_left - object_data.get_reserved_data_base(),
ret_right - ret_left
ret_left.get_byte_distance<uint64_t>(
object_data.get_reserved_data_base()),
ret_right.get_byte_distance<uint64_t>(ret_left)
));
}
}
@ -1689,11 +1722,13 @@ ObjectDataHandler::clone_ret ObjectDataHandler::clone_extents(
return trans_intr::do_for_each(
pins,
[&last_pos, &object_data, ctx, data_base](auto &pin) {
auto offset = pin->get_key() - data_base;
auto offset = pin->get_key().template get_byte_distance<
extent_len_t>(data_base);
ceph_assert(offset == last_pos);
auto fut = TransactionManager::alloc_extent_iertr
::make_ready_future<LBAMappingRef>();
auto addr = object_data.get_reserved_data_base() + offset;
laddr_t addr = (object_data.get_reserved_data_base() + offset)
.checked_to_laddr();
if (pin->get_val().is_zero()) {
fut = ctx.tm.reserve_region(ctx.t, addr, pin->get_length());
} else {
@ -1711,7 +1746,7 @@ ObjectDataHandler::clone_ret ObjectDataHandler::clone_extents(
if (last_pos != object_data.get_reserved_data_len()) {
return ctx.tm.reserve_region(
ctx.t,
object_data.get_reserved_data_base() + last_pos,
(object_data.get_reserved_data_base() + last_pos).checked_to_laddr(),
object_data.get_reserved_data_len() - last_pos
).si_then([](auto) {
return seastar::now();

View File

@ -229,7 +229,8 @@ private:
/// Updates region [_offset, _offset + bl.length) to bl
write_ret overwrite(
context_t ctx, ///< [in] ctx
laddr_t offset, ///< [in] write offset
laddr_t data_base, ///< [in] data base laddr
objaddr_t offset, ///< [in] write offset
extent_len_t len, ///< [in] len to write, len == bl->length() if bl
std::optional<bufferlist> &&bl, ///< [in] buffer to write, empty for zeros
lba_pin_list_t &&pins ///< [in] set of pins overlapping above region

View File

@ -46,7 +46,7 @@ struct omap_node_meta_le_t {
struct omap_inner_key_t {
uint16_t key_off = 0;
uint16_t key_len = 0;
laddr_t laddr = 0;
laddr_t laddr = L_ADDR_MIN;
omap_inner_key_t() = default;
omap_inner_key_t(uint16_t off, uint16_t len, laddr_t addr)
@ -70,7 +70,7 @@ struct omap_inner_key_t {
struct omap_inner_key_le_t {
ceph_le16 key_off{0};
ceph_le16 key_len{0};
laddr_le_t laddr{0};
laddr_le_t laddr{L_ADDR_MIN};
omap_inner_key_le_t() = default;
omap_inner_key_le_t(const omap_inner_key_le_t &) = default;

View File

@ -82,8 +82,9 @@ public:
assert(default_metadata_offset);
assert(default_metadata_range);
uint64_t range_blocks = default_metadata_range / block_size;
return get_hint() + default_metadata_offset +
(((uint32_t)std::rand() % range_blocks) * block_size);
auto random_offset = default_metadata_offset +
(((uint32_t)std::rand() % range_blocks) * block_size);
return (get_hint() + random_offset).checked_to_laddr();
}
laddr_t get_data_hint() const {
return get_hint();

View File

@ -12,7 +12,7 @@ namespace crimson::os::seastore::onode {
void FLTreeOnode::Recorder::apply_value_delta(
ceph::bufferlist::const_iterator &bliter,
NodeExtentMutable &value,
laddr_t value_addr)
laddr_offset_t value_addr_offset)
{
LOG_PREFIX(FLTreeOnode::Recorder::apply_value_delta);
delta_op_t op;

View File

@ -66,7 +66,7 @@ struct FLTreeOnode final : Onode, Value {
void apply_value_delta(
ceph::bufferlist::const_iterator &bliter,
NodeExtentMutable &value,
laddr_t value_addr) final;
laddr_offset_t value_addr_offset) final;
void encode_update(NodeExtentMutable &payload_mut, delta_op_t op);
};

View File

@ -435,7 +435,7 @@ eagain_ifuture<Ref<Node>> Node::load_root(context_t c, RootNodeTracker& root_tra
assert(_super);
auto root_addr = _super->get_root_laddr();
assert(root_addr != L_ADDR_NULL);
TRACET("loading root_addr={:x} ...", c.t, root_addr);
TRACET("loading root_addr={} ...", c.t, root_addr);
return Node::load(c, root_addr, true
).si_then([c, _super = std::move(_super),
&root_tracker, FNAME](auto root) mutable {
@ -693,22 +693,22 @@ eagain_ifuture<Ref<Node>> Node::load(
eagain_iertr::pass_further{},
crimson::ct_error::input_output_error::assert_failure(
[FNAME, c, addr, expect_is_level_tail] {
ERRORT("EIO -- addr={:x}, is_level_tail={}",
ERRORT("EIO -- addr={}, is_level_tail={}",
c.t, addr, expect_is_level_tail);
}),
crimson::ct_error::invarg::assert_failure(
[FNAME, c, addr, expect_is_level_tail] {
ERRORT("EINVAL -- addr={:x}, is_level_tail={}",
ERRORT("EINVAL -- addr={}, is_level_tail={}",
c.t, addr, expect_is_level_tail);
}),
crimson::ct_error::enoent::assert_failure(
[FNAME, c, addr, expect_is_level_tail] {
ERRORT("ENOENT -- addr={:x}, is_level_tail={}",
ERRORT("ENOENT -- addr={}, is_level_tail={}",
c.t, addr, expect_is_level_tail);
}),
crimson::ct_error::erange::assert_failure(
[FNAME, c, addr, expect_is_level_tail] {
ERRORT("ERANGE -- addr={:x}, is_level_tail={}",
ERRORT("ERANGE -- addr={}, is_level_tail={}",
c.t, addr, expect_is_level_tail);
})
).si_then([FNAME, c, addr, expect_is_level_tail](auto extent)
@ -717,13 +717,13 @@ eagain_ifuture<Ref<Node>> Node::load(
auto header = extent->get_header();
auto field_type = header.get_field_type();
if (!field_type) {
ERRORT("load addr={:x}, is_level_tail={} error, "
ERRORT("load addr={}, is_level_tail={} error, "
"got invalid header -- {}",
c.t, addr, expect_is_level_tail, fmt::ptr(extent));
ceph_abort("fatal error");
}
if (header.get_is_level_tail() != expect_is_level_tail) {
ERRORT("load addr={:x}, is_level_tail={} error, "
ERRORT("load addr={}, is_level_tail={} error, "
"is_level_tail mismatch -- {}",
c.t, addr, expect_is_level_tail, fmt::ptr(extent));
ceph_abort("fatal error");
@ -732,7 +732,7 @@ eagain_ifuture<Ref<Node>> Node::load(
auto node_type = header.get_node_type();
if (node_type == node_type_t::LEAF) {
if (extent->get_length() != c.vb.get_leaf_node_size()) {
ERRORT("load addr={:x}, is_level_tail={} error, "
ERRORT("load addr={}, is_level_tail={} error, "
"leaf length mismatch -- {}",
c.t, addr, expect_is_level_tail, fmt::ptr(extent));
ceph_abort("fatal error");
@ -743,7 +743,7 @@ eagain_ifuture<Ref<Node>> Node::load(
new LeafNode(derived_ptr, std::move(impl)));
} else if (node_type == node_type_t::INTERNAL) {
if (extent->get_length() != c.vb.get_internal_node_size()) {
ERRORT("load addr={:x}, is_level_tail={} error, "
ERRORT("load addr={}, is_level_tail={} error, "
"internal length mismatch -- {}",
c.t, addr, expect_is_level_tail, fmt::ptr(extent));
ceph_abort("fatal error");
@ -1084,7 +1084,7 @@ eagain_ifuture<> InternalNode::apply_children_merge(
auto left_addr = left_child->impl->laddr();
auto& right_pos = right_child->parent_info().position;
auto right_addr = right_child->impl->laddr();
DEBUGT("apply {}'s child {} (was {:#x}) at pos({}), "
DEBUGT("apply {}'s child {} (was {}) at pos({}), "
"to merge with {} at pos({}), update_index={} ...",
c.t, get_name(), left_child->get_name(), origin_left_addr, left_pos,
right_child->get_name(), right_pos, update_index);
@ -1572,12 +1572,12 @@ eagain_ifuture<Ref<Node>> InternalNode::get_or_track_child(
return [this, position, child_addr, c, FNAME] {
auto found = tracked_child_nodes.find(position);
if (found != tracked_child_nodes.end()) {
TRACET("loaded child tracked {} at pos({}) addr={:x}",
TRACET("loaded child tracked {} at pos({}) addr={}",
c.t, found->second->get_name(), position, child_addr);
return eagain_iertr::make_ready_future<Ref<Node>>(found->second);
}
// the child is not loaded yet
TRACET("loading child at pos({}) addr={:x} ...",
TRACET("loading child at pos({}) addr={} ...",
c.t, position, child_addr);
bool level_tail = position.is_end();
return Node::load(c, child_addr, level_tail

View File

@ -173,7 +173,7 @@ class DeltaRecorderT final: public DeltaRecorder {
auto p_addr = reinterpret_cast<laddr_packed_t*>(
mut.get_write() + update_offset);
SUBDEBUG(seastore_onode,
"apply {:#x} to offset {:#x} ...",
"apply {} to offset {:#x} ...",
new_addr, update_offset);
layout_t::update_child_addr(mut, new_addr, p_addr);
break;
@ -526,12 +526,12 @@ class NodeExtentAccessorT {
crimson::ct_error::input_output_error::assert_failure(
[FNAME, c, alloc_size, l_to_discard = extent->get_laddr()] {
SUBERRORT(seastore_onode,
"EIO during allocate -- node_size={}, to_discard={:x}",
"EIO during allocate -- node_size={}, to_discard={}",
c.t, alloc_size, l_to_discard);
})
).si_then([this, c, FNAME] (auto fresh_extent) {
SUBDEBUGT(seastore_onode,
"update addr from {:#x} to {:#x} ...",
"update addr from {} to {} ...",
c.t, extent->get_laddr(), fresh_extent->get_laddr());
assert(fresh_extent);
assert(fresh_extent->is_initial_pending());
@ -555,14 +555,14 @@ class NodeExtentAccessorT {
[FNAME, c, l_to_discard = to_discard->get_laddr(),
l_fresh = fresh_extent->get_laddr()] {
SUBERRORT(seastore_onode,
"EIO during retire -- to_disgard={:x}, fresh={:x}",
"EIO during retire -- to_disgard={}, fresh={}",
c.t, l_to_discard, l_fresh);
}),
crimson::ct_error::enoent::assert_failure(
[FNAME, c, l_to_discard = to_discard->get_laddr(),
l_fresh = fresh_extent->get_laddr()] {
SUBERRORT(seastore_onode,
"ENOENT during retire -- to_disgard={:x}, fresh={:x}",
"ENOENT during retire -- to_disgard={}, fresh={}",
c.t, l_to_discard, l_fresh);
})
);
@ -582,11 +582,11 @@ class NodeExtentAccessorT {
eagain_iertr::pass_further{},
crimson::ct_error::input_output_error::assert_failure(
[FNAME, c, addr] {
SUBERRORT(seastore_onode, "EIO -- addr={:x}", c.t, addr);
SUBERRORT(seastore_onode, "EIO -- addr={}", c.t, addr);
}),
crimson::ct_error::enoent::assert_failure(
[FNAME, c, addr] {
SUBERRORT(seastore_onode, "ENOENT -- addr={:x}", c.t, addr);
SUBERRORT(seastore_onode, "ENOENT -- addr={}", c.t, addr);
})
#ifndef NDEBUG
).si_then([c] {

View File

@ -28,7 +28,7 @@ class DummySuper final: public Super {
laddr_t get_root_laddr() const override { return *p_root_laddr; }
void write_root_laddr(context_t c, laddr_t addr) override {
LOG_PREFIX(OTree::Dummy);
SUBDEBUGT(seastore_onode, "update root {:#x} ...", c.t, addr);
SUBDEBUGT(seastore_onode, "update root {} ...", c.t, addr);
*p_root_laddr = addr;
}
private:
@ -77,7 +77,7 @@ class DummyNodeExtentManager final: public NodeExtentManager {
read_iertr::future<NodeExtentRef> read_extent(
Transaction& t, laddr_t addr) override {
SUBTRACET(seastore_onode, "reading at {:#x} ...", t, addr);
SUBTRACET(seastore_onode, "reading at {} ...", t, addr);
if constexpr (SYNC) {
return read_extent_sync(t, addr);
} else {
@ -90,7 +90,7 @@ class DummyNodeExtentManager final: public NodeExtentManager {
alloc_iertr::future<NodeExtentRef> alloc_extent(
Transaction& t, laddr_t hint, extent_len_t len) override {
SUBTRACET(seastore_onode, "allocating {}B with hint {:#x} ...", t, len, hint);
SUBTRACET(seastore_onode, "allocating {}B with hint {} ...", t, len, hint);
if constexpr (SYNC) {
return alloc_extent_sync(t, len);
} else {
@ -104,7 +104,7 @@ class DummyNodeExtentManager final: public NodeExtentManager {
retire_iertr::future<> retire_extent(
Transaction& t, NodeExtentRef extent) override {
SUBTRACET(seastore_onode,
"retiring {}B at {:#x} -- {} ...",
"retiring {}B at {} -- {} ...",
t, extent->get_length(), extent->get_laddr(), *extent);
if constexpr (SYNC) {
return retire_extent_sync(t, extent);
@ -140,7 +140,7 @@ class DummyNodeExtentManager final: public NodeExtentManager {
assert(iter != allocate_map.end());
auto extent = iter->second;
SUBTRACET(seastore_onode,
"read {}B at {:#x} -- {}",
"read {}B at {} -- {}",
t, extent->get_length(), extent->get_laddr(), *extent);
assert(extent->get_laddr() == addr);
return read_iertr::make_ready_future<NodeExtentRef>(extent);
@ -150,14 +150,15 @@ class DummyNodeExtentManager final: public NodeExtentManager {
Transaction& t, extent_len_t len) {
assert(len % ALIGNMENT == 0);
auto r = ceph::buffer::create_aligned(len, ALIGNMENT);
auto addr = reinterpret_cast<laddr_t>(r->get_data());
auto addr = laddr_t::from_byte_offset(
reinterpret_cast<laddr_t::Unsigned>(r->get_data()));
auto bp = ceph::bufferptr(std::move(r));
auto extent = Ref<DummyNodeExtent>(new DummyNodeExtent(std::move(bp)));
extent->set_laddr(addr);
assert(allocate_map.find(extent->get_laddr()) == allocate_map.end());
allocate_map.insert({extent->get_laddr(), extent});
SUBDEBUGT(seastore_onode,
"allocated {}B at {:#x} -- {}",
"allocated {}B at {} -- {}",
t, extent->get_length(), extent->get_laddr(), *extent);
assert(extent->get_length() == len);
return alloc_iertr::make_ready_future<NodeExtentRef>(extent);
@ -172,13 +173,13 @@ class DummyNodeExtentManager final: public NodeExtentManager {
auto iter = allocate_map.find(addr);
assert(iter != allocate_map.end());
allocate_map.erase(iter);
SUBDEBUGT(seastore_onode, "retired {}B at {:#x}", t, len, addr);
SUBDEBUGT(seastore_onode, "retired {}B at {}", t, len, addr);
return retire_iertr::now();
}
getsuper_iertr::future<Super::URef> get_super_sync(
Transaction& t, RootNodeTracker& tracker) {
SUBTRACET(seastore_onode, "got root {:#x}", t, root_laddr);
SUBTRACET(seastore_onode, "got root {}", t, root_laddr);
return getsuper_iertr::make_ready_future<Super::URef>(
Super::URef(new DummySuper(t, tracker, &root_laddr)));
}

View File

@ -30,7 +30,7 @@ class SeastoreSuper final: public Super {
}
void write_root_laddr(context_t c, laddr_t addr) override {
LOG_PREFIX(OTree::Seastore);
SUBDEBUGT(seastore_onode, "update root {:#x} ...", c.t, addr);
SUBDEBUGT(seastore_onode, "update root {} ...", c.t, addr);
root_addr = addr;
tm.write_onode_root(c.t, addr);
}
@ -102,10 +102,10 @@ class SeastoreNodeExtentManager final: public TransactionManagerHandle {
read_iertr::future<NodeExtentRef> read_extent(
Transaction& t, laddr_t addr) override {
SUBTRACET(seastore_onode, "reading at {:#x} ...", t, addr);
SUBTRACET(seastore_onode, "reading at {} ...", t, addr);
if constexpr (INJECT_EAGAIN) {
if (trigger_eagain()) {
SUBDEBUGT(seastore_onode, "reading at {:#x}: trigger eagain", t, addr);
SUBDEBUGT(seastore_onode, "reading at {}: trigger eagain", t, addr);
t.test_set_conflict();
return read_iertr::make_ready_future<NodeExtentRef>();
}
@ -113,7 +113,7 @@ class SeastoreNodeExtentManager final: public TransactionManagerHandle {
return tm.read_extent<SeastoreNodeExtent>(t, addr
).si_then([addr, &t](auto&& e) -> read_iertr::future<NodeExtentRef> {
SUBTRACET(seastore_onode,
"read {}B at {:#x} -- {}",
"read {}B at {} -- {}",
t, e->get_length(), e->get_laddr(), *e);
assert(e->get_laddr() == addr);
std::ignore = addr;
@ -123,7 +123,7 @@ class SeastoreNodeExtentManager final: public TransactionManagerHandle {
alloc_iertr::future<NodeExtentRef> alloc_extent(
Transaction& t, laddr_t hint, extent_len_t len) override {
SUBTRACET(seastore_onode, "allocating {}B with hint {:#x} ...", t, len, hint);
SUBTRACET(seastore_onode, "allocating {}B with hint {} ...", t, len, hint);
if constexpr (INJECT_EAGAIN) {
if (trigger_eagain()) {
SUBDEBUGT(seastore_onode, "allocating {}B: trigger eagain", t, len);
@ -134,7 +134,7 @@ class SeastoreNodeExtentManager final: public TransactionManagerHandle {
return tm.alloc_non_data_extent<SeastoreNodeExtent>(t, hint, len
).si_then([len, &t](auto extent) {
SUBDEBUGT(seastore_onode,
"allocated {}B at {:#x} -- {}",
"allocated {}B at {} -- {}",
t, extent->get_length(), extent->get_laddr(), *extent);
if (!extent->is_initial_pending()) {
SUBERRORT(seastore_onode,
@ -157,12 +157,12 @@ class SeastoreNodeExtentManager final: public TransactionManagerHandle {
auto addr = extent->get_laddr();
auto len = extent->get_length();
SUBDEBUGT(seastore_onode,
"retiring {}B at {:#x} -- {} ...",
"retiring {}B at {} -- {} ...",
t, len, addr, *extent);
if constexpr (INJECT_EAGAIN) {
if (trigger_eagain()) {
SUBDEBUGT(seastore_onode,
"retiring {}B at {:#x} -- {} : trigger eagain",
"retiring {}B at {} -- {} : trigger eagain",
t, len, addr, *extent);
t.test_set_conflict();
return retire_iertr::now();
@ -170,7 +170,7 @@ class SeastoreNodeExtentManager final: public TransactionManagerHandle {
}
return tm.remove(t, extent).si_then([addr, len, &t] (unsigned cnt) {
assert(cnt == 0);
SUBTRACET(seastore_onode, "retired {}B at {:#x} ...", t, len, addr);
SUBTRACET(seastore_onode, "retired {}B at {} ...", t, len, addr);
});
}
@ -185,7 +185,7 @@ class SeastoreNodeExtentManager final: public TransactionManagerHandle {
}
}
return tm.read_onode_root(t).si_then([this, &t, &tracker](auto root_addr) {
SUBTRACET(seastore_onode, "got root {:#x}", t, root_addr);
SUBTRACET(seastore_onode, "got root {}", t, root_addr);
return Super::URef(new SeastoreSuper(t, tracker, root_addr, tm));
});
}

View File

@ -374,8 +374,8 @@ class NodeLayoutT final : public InternalNodeImpl, public LeafNodeImpl {
size += sizeof(laddr_t);
auto value_ptr = node_stage.get_end_p_laddr();
int offset = reinterpret_cast<const char*>(value_ptr) - p_start;
os << "\n tail value: 0x"
<< std::hex << value_ptr->value << std::dec
os << "\n tail value: "
<< laddr_t(value_ptr->value)
<< " " << size << "B"
<< " @" << offset << "B";
}
@ -845,7 +845,7 @@ class NodeLayoutT final : public InternalNodeImpl, public LeafNodeImpl {
const search_position_t& pos, laddr_t dst, laddr_t src) override {
if constexpr (NODE_TYPE == node_type_t::INTERNAL) {
LOG_PREFIX(OTree::Layout::replace_child_addr);
SUBDEBUG(seastore_onode, "update from {:#x} to {:#x} at pos({}) ...", src, dst, pos);
SUBDEBUG(seastore_onode, "update from {} to {} at pos({}) ...", src, dst, pos);
const laddr_packed_t* p_value;
if (pos.is_end()) {
assert(is_level_tail());
@ -924,8 +924,8 @@ class NodeLayoutT final : public InternalNodeImpl, public LeafNodeImpl {
// XXX: maybe also include the extent state
std::ostringstream sos;
sos << "Node" << NODE_TYPE << FIELD_TYPE
<< "@0x" << std::hex << extent.get_laddr()
<< "+" << extent.get_length() << std::dec
<< "@" << extent.get_laddr()
<< "+" << std::hex << extent.get_length() << std::dec
<< "Lv" << (unsigned)level()
<< (is_level_tail() ? "$" : "");
name = sos.str();

View File

@ -44,10 +44,10 @@ inline std::ostream& operator<<(std::ostream &os, const node_type_t& type) {
}
struct laddr_packed_t {
laddr_t value;
laddr_le_t value;
} __attribute__((packed));
inline std::ostream& operator<<(std::ostream& os, const laddr_packed_t& laddr) {
return os << "laddr_packed(0x" << std::hex << laddr.value << std::dec << ")";
return os << "laddr_packed(" << laddr_t(laddr.value) << ")";
}
using match_stat_t = int8_t;

View File

@ -46,9 +46,9 @@ static laddr_t get_lba_hint(shard_t shard, pool_t pool, crush_hash_t crush) {
// FIXME: It is possible that PGs from different pools share the same prefix
// if the mask 0xFF is not long enough, result in unexpected transaction
// conflicts.
return ((uint64_t)(shard & 0XFF)<<56 |
(uint64_t)(pool & 0xFF)<<48 |
(uint64_t)(crush )<<16);
return laddr_t::from_raw_uint((uint64_t)(shard & 0xFF)<<56 |
(uint64_t)(pool & 0xFF)<<48 |
(uint64_t)(crush )<<16);
}
struct node_offset_packed_t {

View File

@ -1443,7 +1443,7 @@ struct staged {
if constexpr (NODE_TYPE == node_type_t::LEAF) {
os << *value_ptr;
} else {
os << "0x" << std::hex << value_ptr->value << std::dec;
os << laddr_t(value_ptr->value);
}
os << " " << size << "B"
<< " @" << offset << "B";

View File

@ -22,7 +22,7 @@ const laddr_packed_t* internal_sub_items_t::insert_at(
auto p_insert = const_cast<char*>(p_shift_end) - size;
auto item = internal_sub_item_t{
snap_gen_t::from_key(key), laddr_packed_t{value}};
snap_gen_t::from_key(key), laddr_packed_t{laddr_le_t{value}}};
mut.copy_in_absolute(p_insert, item);
return &reinterpret_cast<internal_sub_item_t*>(p_insert)->value;
}
@ -79,7 +79,7 @@ void internal_sub_items_t::Appender<KT>::append(
{
p_append -= sizeof(internal_sub_item_t);
auto item = internal_sub_item_t{
snap_gen_t::from_key(key), laddr_packed_t{value}};
snap_gen_t::from_key(key), laddr_packed_t{laddr_le_t{value}}};
p_mut->copy_in_absolute(p_append, item);
p_value = &reinterpret_cast<internal_sub_item_t*>(p_append)->value;
}

View File

@ -138,7 +138,7 @@ void validate_tree_config(const tree_conf_t& conf)
#define _STAGE_T(NodeType) node_to_stage_t<typename NodeType::node_stage_t>
#define NXT_T(StageType) staged<typename StageType::next_param_t>
laddr_t i_value{0};
laddr_t i_value = L_ADDR_MIN;
auto insert_size_2 =
_STAGE_T(InternalNode0)::insert_size(key, i_value);
auto insert_size_0 =

View File

@ -141,7 +141,7 @@ class ValueDeltaRecorder {
/// Called by DeltaRecorderT to apply user-defined value delta.
virtual void apply_value_delta(ceph::bufferlist::const_iterator&,
NodeExtentMutable&,
laddr_t) = 0;
laddr_offset_t) = 0;
protected:
ValueDeltaRecorder(ceph::bufferlist& encoded) : encoded{encoded} {}

View File

@ -253,6 +253,8 @@ SeaStore::mount_ertr::future<> SeaStore::mount()
ceph_assert(seastar::this_shard_id() == primary_core);
return device->mount(
).safe_then([this] {
ceph_assert(device->get_sharded_device().get_block_size()
>= laddr_t::UNIT_SIZE);
auto &sec_devices = device->get_sharded_device().get_secondary_devices();
return crimson::do_for_each(sec_devices, [this](auto& device_entry) {
device_id_t id = device_entry.first;
@ -266,6 +268,8 @@ SeaStore::mount_ertr::future<> SeaStore::mount()
).then([this, magic, sec_dev = std::move(sec_dev)]() mutable {
return sec_dev->mount(
).safe_then([this, sec_dev=std::move(sec_dev), magic]() mutable {
ceph_assert(sec_dev->get_sharded_device().get_block_size()
>= laddr_t::UNIT_SIZE);
boost::ignore_unused(magic); // avoid clang warning;
assert(sec_dev->get_sharded_device().get_magic() == magic);
secondaries.emplace_back(std::move(sec_dev));

View File

@ -92,6 +92,15 @@ std::ostream& operator<<(std::ostream& out, segment_seq_printer_t seq)
}
}
std::ostream &operator<<(std::ostream &out, const laddr_t &laddr) {
return out << 'L' << std::hex << laddr.value << std::dec;
}
std::ostream &operator<<(std::ostream &out, const laddr_offset_t &laddr_offset) {
return out << laddr_offset.get_aligned_laddr()
<< "+" << std::hex << laddr_offset.get_offset() << std::dec;
}
std::ostream &operator<<(std::ostream &out, const pladdr_t &pladdr)
{
if (pladdr.is_laddr()) {

View File

@ -192,7 +192,7 @@ private:
std::ostream &operator<<(std::ostream &out, const segment_id_t&);
// ondisk type of segment_id_t
struct __attribute((packed)) segment_id_le_t {
struct __attribute__((packed)) segment_id_le_t {
ceph_le32 segment = ceph_le32(segment_id_t().segment);
segment_id_le_t(const segment_id_t id) :
@ -853,7 +853,7 @@ inline paddr_t paddr_t::block_relative_to(paddr_t rhs) const {
return as_res_paddr().block_relative_to(rhs.as_res_paddr());
}
struct __attribute((packed)) paddr_le_t {
struct __attribute__((packed)) paddr_le_t {
ceph_le64 internal_paddr =
ceph_le64(P_ADDR_NULL.internal_paddr);
@ -1006,33 +1006,249 @@ constexpr journal_seq_t JOURNAL_SEQ_MAX{
// JOURNAL_SEQ_NULL == JOURNAL_SEQ_MAX == journal_seq_t{}
constexpr journal_seq_t JOURNAL_SEQ_NULL = JOURNAL_SEQ_MAX;
// logical addr, see LBAManager, TransactionManager
using laddr_t = uint64_t;
constexpr laddr_t L_ADDR_MIN = std::numeric_limits<laddr_t>::min();
constexpr laddr_t L_ADDR_MAX = std::numeric_limits<laddr_t>::max();
constexpr laddr_t L_ADDR_NULL = L_ADDR_MAX;
constexpr laddr_t L_ADDR_ROOT = L_ADDR_MAX - 1;
constexpr laddr_t L_ADDR_LBAT = L_ADDR_MAX - 2;
// logical offset between two laddr_t
using loffset_t = uint64_t;
struct __attribute((packed)) laddr_le_t {
ceph_le64 laddr = ceph_le64(L_ADDR_NULL);
// logical offset within an extent
using extent_len_t = uint32_t;
constexpr extent_len_t EXTENT_LEN_MAX =
std::numeric_limits<extent_len_t>::max();
using extent_len_le_t = ceph_le32;
inline extent_len_le_t init_extent_len_le(extent_len_t len) {
return ceph_le32(len);
}
// logical addr, see LBAManager, TransactionManager
class laddr_t {
public:
// the type of underlying integer
using Unsigned = uint64_t;
static constexpr Unsigned RAW_VALUE_MAX =
std::numeric_limits<Unsigned>::max();
constexpr laddr_t() : laddr_t(RAW_VALUE_MAX) {}
// laddr_t is block aligned, one logical address represents one 4KiB block in disk
static constexpr unsigned UNIT_SHIFT = 12;
static constexpr unsigned UNIT_SIZE = 1 << UNIT_SHIFT; // 4096
static constexpr unsigned UNIT_MASK = UNIT_SIZE - 1;
static laddr_t from_byte_offset(Unsigned value) {
assert((value & UNIT_MASK) == 0);
return laddr_t(value >> UNIT_SHIFT);
}
static constexpr laddr_t from_raw_uint(Unsigned v) {
return laddr_t(v);
}
/// laddr_t works like primitive integer type, encode/decode it manually
void encode(::ceph::buffer::list::contiguous_appender& p) const {
p.append(reinterpret_cast<const char *>(&value), sizeof(Unsigned));
}
void bound_encode(size_t& p) const {
p += sizeof(Unsigned);
}
void decode(::ceph::buffer::ptr::const_iterator& p) {
assert(static_cast<std::size_t>(p.get_end() - p.get_pos()) >= sizeof(Unsigned));
memcpy((char *)&value, p.get_pos_add(sizeof(Unsigned)), sizeof(Unsigned));
}
// laddr_offset_t contains one base laddr and one block not aligned
// offset(< laddr_t::UNIT_SIZE). It is the return type of plus/minus
// overloads for laddr_t and loffset_t.
struct laddr_offset_t {
explicit laddr_offset_t(laddr_t base)
: base(base.value), offset(0) {}
laddr_offset_t(laddr_t base, extent_len_t offset)
: base(base.value), offset(offset) {
assert(offset < laddr_t::UNIT_SIZE);
}
laddr_t get_roundup_laddr() const {
if (offset == 0) {
return laddr_t(base);
} else {
assert(offset < laddr_t::UNIT_SIZE);
return laddr_t(base + 1);
}
}
laddr_t get_aligned_laddr() const { return laddr_t(base); }
extent_len_t get_offset() const {
assert(offset < laddr_t::UNIT_SIZE);
return offset;
}
laddr_t checked_to_laddr() const {
assert(offset == 0);
return laddr_t(base);
}
template<std::unsigned_integral U>
U get_byte_distance(const laddr_t &l) const {
assert(offset < UNIT_SIZE);
if (base >= l.value) {
Unsigned udiff = base - l.value;
assert(udiff <= (std::numeric_limits<U>::max() >> UNIT_SHIFT));
return (static_cast<U>(udiff) << UNIT_SHIFT) + offset;
} else { // base < l.value
Unsigned udiff = l.value - base;
assert(udiff <= (std::numeric_limits<U>::max() >> UNIT_SHIFT));
return (static_cast<U>(udiff) << UNIT_SHIFT) - offset;
}
}
template<std::unsigned_integral U>
U get_byte_distance(const laddr_offset_t &l) const {
assert(offset < UNIT_SIZE);
if (*this >= l) {
Unsigned udiff = base - l.base;
assert(udiff <= (std::numeric_limits<U>::max() >> UNIT_SHIFT));
return ((static_cast<U>(udiff) << UNIT_SHIFT) + offset) - l.offset;
} else { // *this < l
Unsigned udiff = l.base - base;
assert(udiff <= (std::numeric_limits<U>::max() >> UNIT_SHIFT));
return ((static_cast<U>(udiff) << UNIT_SHIFT) + l.offset) - offset;
}
}
friend bool operator==(const laddr_offset_t&, const laddr_offset_t&) = default;
friend auto operator<=>(const laddr_offset_t&, const laddr_offset_t&) = default;
friend std::ostream &operator<<(std::ostream&, const laddr_offset_t&);
friend laddr_offset_t operator+(const laddr_offset_t &laddr_offset,
const loffset_t &offset) {
// laddr_offset_t could access (laddr_t + loffset_t) overload.
return laddr_offset.get_aligned_laddr()
+ (laddr_offset.get_offset() + offset);
}
friend laddr_offset_t operator+(const loffset_t &offset,
const laddr_offset_t &loffset) {
return loffset + offset;
}
friend laddr_offset_t operator-(const laddr_offset_t &laddr_offset,
const loffset_t &offset) {
if (laddr_offset.get_offset() >= offset) {
return laddr_offset_t(
laddr_offset.get_aligned_laddr(),
laddr_offset.get_offset() - offset);
} else {
// laddr_offset_t could access (laddr_t - loffset_t) overload.
return laddr_offset.get_aligned_laddr()
- (offset - laddr_offset.get_offset());
}
}
friend class laddr_t;
private:
// use Unsigned here to avoid incomplete type of laddr_t
Unsigned base;
extent_len_t offset;
};
template<std::unsigned_integral U>
U get_byte_distance(const laddr_offset_t &l) const {
if (value <= l.base) {
Unsigned udiff = l.base - value;
assert(udiff <= (std::numeric_limits<U>::max() >> UNIT_SHIFT));
return (static_cast<U>(udiff) << UNIT_SHIFT) + l.offset;
} else { // value > l.base
Unsigned udiff = value - l.base;
assert(udiff <= (std::numeric_limits<U>::max() >> UNIT_SHIFT));
return (static_cast<U>(udiff) << UNIT_SHIFT) - l.offset;
}
}
template<std::unsigned_integral U>
U get_byte_distance(const laddr_t &l) const {
Unsigned diff = value > l.value
? value - l.value
: l.value - value;
assert(diff <= (std::numeric_limits<U>::max() >> UNIT_SHIFT));
return static_cast<U>(diff) << UNIT_SHIFT;
}
friend std::ostream &operator<<(std::ostream &, const laddr_t &);
friend bool operator==(const laddr_t&, const laddr_t&) = default;
friend bool operator==(const laddr_t &laddr,
const laddr_offset_t &laddr_offset) {
return laddr == laddr_offset.get_aligned_laddr()
&& 0 == laddr_offset.get_offset();
}
friend bool operator==(const laddr_offset_t &laddr_offset,
const laddr_t &laddr) {
return laddr_offset.get_aligned_laddr() == laddr
&& laddr_offset.get_offset() == 0;
}
friend auto operator<=>(const laddr_t&, const laddr_t&) = default;
friend auto operator<=>(const laddr_t &laddr,
const laddr_offset_t &laddr_offset) {
return laddr_offset_t(laddr, 0) <=> laddr_offset;
}
friend auto operator<=>(const laddr_offset_t &laddr_offset,
const laddr_t &laddr) {
return laddr_offset <=> laddr_offset_t(laddr, 0);
}
friend laddr_offset_t operator+(const laddr_t &laddr,
const loffset_t &offset) {
auto base = laddr;
base.value += offset >> laddr_t::UNIT_SHIFT;
assert(base.value >= laddr.value);
return laddr_offset_t(base, offset & laddr_t::UNIT_MASK);
}
friend laddr_offset_t operator+(const loffset_t &offset,
const laddr_t &laddr) {
return laddr + offset;
}
friend laddr_offset_t operator-(const laddr_t &laddr, loffset_t offset) {
auto base = laddr;
auto diff = (offset + laddr_t::UNIT_SIZE - 1) >> laddr_t::UNIT_SHIFT;
base.value -= diff;
assert(base.value <= laddr.value);
offset = (diff << laddr_t::UNIT_SHIFT) - offset;
return laddr_offset_t(base, offset);
}
friend struct laddr_le_t;
friend struct pladdr_le_t;
private:
// Prevent direct construction of laddr_t with an integer,
// always use laddr_t::from_raw_uint instead.
constexpr explicit laddr_t(Unsigned value) : value(value) {}
Unsigned value;
};
using laddr_offset_t = laddr_t::laddr_offset_t;
constexpr laddr_t L_ADDR_MAX = laddr_t::from_raw_uint(laddr_t::RAW_VALUE_MAX);
constexpr laddr_t L_ADDR_MIN = laddr_t::from_raw_uint(0);
constexpr laddr_t L_ADDR_NULL = L_ADDR_MAX;
constexpr laddr_t L_ADDR_ROOT = laddr_t::from_raw_uint(laddr_t::RAW_VALUE_MAX - 1);
constexpr laddr_t L_ADDR_LBAT = laddr_t::from_raw_uint(laddr_t::RAW_VALUE_MAX - 2);
struct __attribute__((packed)) laddr_le_t {
ceph_le64 laddr;
using orig_type = laddr_t;
laddr_le_t() = default;
laddr_le_t() : laddr_le_t(L_ADDR_NULL) {}
laddr_le_t(const laddr_le_t &) = default;
explicit laddr_le_t(const laddr_t &addr)
: laddr(ceph_le64(addr)) {}
: laddr(addr.value) {}
operator laddr_t() const {
return laddr_t(laddr);
}
laddr_le_t& operator=(laddr_t addr) {
ceph_le64 val;
val = addr;
val = addr.value;
laddr = val;
return *this;
}
bool operator==(const laddr_le_t&) const = default;
};
constexpr uint64_t PL_ADDR_NULL = std::numeric_limits<uint64_t>::max();
@ -1087,7 +1303,7 @@ enum class addr_type_t : uint8_t {
MAX=2 // or NONE
};
struct __attribute((packed)) pladdr_le_t {
struct __attribute__((packed)) pladdr_le_t {
ceph_le64 pladdr = ceph_le64(PL_ADDR_NULL);
addr_type_t addr_type = addr_type_t::MAX;
@ -1097,7 +1313,7 @@ struct __attribute((packed)) pladdr_le_t {
: pladdr(
ceph_le64(
addr.is_laddr() ?
std::get<0>(addr.pladdr) :
std::get<0>(addr.pladdr).value :
std::get<1>(addr.pladdr).internal_paddr)),
addr_type(
addr.is_laddr() ?
@ -1132,16 +1348,6 @@ struct min_max_t<paddr_t> {
static constexpr paddr_t null = P_ADDR_NULL;
};
// logical offset, see LBAManager, TransactionManager
using extent_len_t = uint32_t;
constexpr extent_len_t EXTENT_LEN_MAX =
std::numeric_limits<extent_len_t>::max();
using extent_len_le_t = ceph_le32;
inline extent_len_le_t init_extent_len_le(extent_len_t len) {
return ceph_le32(len);
}
using extent_ref_count_t = uint32_t;
constexpr extent_ref_count_t EXTENT_DEFAULT_REF_COUNT = 1;
@ -2680,6 +2886,7 @@ struct cache_stats_t {
WRITE_CLASS_DENC_BOUNDED(crimson::os::seastore::seastore_meta_t)
WRITE_CLASS_DENC_BOUNDED(crimson::os::seastore::segment_id_t)
WRITE_CLASS_DENC_BOUNDED(crimson::os::seastore::laddr_t)
WRITE_CLASS_DENC_BOUNDED(crimson::os::seastore::paddr_t)
WRITE_CLASS_DENC_BOUNDED(crimson::os::seastore::journal_seq_t)
WRITE_CLASS_DENC_BOUNDED(crimson::os::seastore::delta_info_t)
@ -2703,6 +2910,8 @@ template <> struct fmt::formatter<crimson::os::seastore::dirty_io_stats_printer_
template <> struct fmt::formatter<crimson::os::seastore::extent_types_t> : fmt::ostream_formatter {};
template <> struct fmt::formatter<crimson::os::seastore::journal_seq_t> : fmt::ostream_formatter {};
template <> struct fmt::formatter<crimson::os::seastore::journal_tail_delta_t> : fmt::ostream_formatter {};
template <> struct fmt::formatter<crimson::os::seastore::laddr_t> : fmt::ostream_formatter {};
template <> struct fmt::formatter<crimson::os::seastore::laddr_offset_t> : fmt::ostream_formatter {};
template <> struct fmt::formatter<crimson::os::seastore::laddr_list_t> : fmt::ostream_formatter {};
template <> struct fmt::formatter<crimson::os::seastore::omap_root_t> : fmt::ostream_formatter {};
template <> struct fmt::formatter<crimson::os::seastore::paddr_list_t> : fmt::ostream_formatter {};

View File

@ -585,7 +585,7 @@ TransactionManager::rewrite_logical_extent(
if (first_extent) {
fut = lba_manager->update_mapping(
t,
lextent->get_laddr() + off,
(lextent->get_laddr() + off).checked_to_laddr(),
lextent->get_length(),
lextent->get_paddr(),
nlextent->get_length(),
@ -599,7 +599,7 @@ TransactionManager::rewrite_logical_extent(
ceph_assert(refcount != 0);
fut = lba_manager->alloc_extent(
t,
lextent->get_laddr() + off,
(lextent->get_laddr() + off).checked_to_laddr(),
*nlextent,
refcount
).si_then([lextent, nlextent, off](auto mapping) {

View File

@ -348,7 +348,6 @@ public:
LOG_PREFIX(TransactionManager::alloc_non_data_extent);
SUBTRACET(seastore_tm, "{} len={}, placement_hint={}, laddr_hint={}",
t, T::TYPE, len, placement_hint, laddr_hint);
ceph_assert(is_aligned(laddr_hint, epm->get_block_size()));
auto ext = cache->alloc_new_non_data_extent<T>(
t,
len,
@ -388,7 +387,6 @@ public:
LOG_PREFIX(TransactionManager::alloc_data_extents);
SUBTRACET(seastore_tm, "{} len={}, placement_hint={}, laddr_hint={}",
t, T::TYPE, len, placement_hint, laddr_hint);
ceph_assert(is_aligned(laddr_hint, epm->get_block_size()));
auto exts = cache->alloc_new_data_extents<T>(
t,
len,
@ -534,7 +532,7 @@ public:
for (auto &remap : remaps) {
auto remap_offset = remap.offset;
auto remap_len = remap.len;
auto remap_laddr = original_laddr + remap_offset;
auto remap_laddr = (original_laddr + remap_offset).checked_to_laddr();
auto remap_paddr = original_paddr.add_offset(remap_offset);
ceph_assert(remap_len < original_len);
ceph_assert(remap_offset + remap_len <= original_len);
@ -582,7 +580,6 @@ public:
extent_len_t len) {
LOG_PREFIX(TransactionManager::reserve_region);
SUBDEBUGT(seastore_tm, "len={}, laddr_hint={}", t, len, hint);
ceph_assert(is_aligned(hint, epm->get_block_size()));
return lba_manager->reserve_region(
t,
hint,
@ -615,7 +612,6 @@ public:
LOG_PREFIX(TransactionManager::clone_pin);
SUBDEBUGT(seastore_tm, "len={}, laddr_hint={}, clone_offset {}",
t, mapping.get_length(), hint, intermediate_key);
ceph_assert(is_aligned(hint, epm->get_block_size()));
return lba_manager->clone_mapping(
t,
hint,

View File

@ -27,20 +27,20 @@ seastar::future<> TMDriver::write(
"write",
[this, offset, &ptr](auto& t)
{
return tm->remove(t, offset
return tm->remove(t, laddr_t::from_byte_offset(offset)
).discard_result().handle_error_interruptible(
crimson::ct_error::enoent::handle([](auto) { return seastar::now(); }),
crimson::ct_error::pass_further_all{}
).si_then([this, offset, &t, &ptr] {
logger().debug("dec_ref complete");
return tm->alloc_data_extents<TestBlock>(t, offset, ptr.length());
return tm->alloc_data_extents<TestBlock>(t, laddr_t::from_byte_offset(offset), ptr.length());
}).si_then([this, offset, &t, &ptr](auto extents) mutable {
boost::ignore_unused(offset); // avoid clang warning;
auto off = offset;
auto left = ptr.length();
size_t written = 0;
for (auto &ext : extents) {
assert(ext->get_laddr() == (size_t)off);
assert(ext->get_laddr() == laddr_t::from_byte_offset(off));
assert(ext->get_bptr().length() <= left);
ptr.copy_out(written, ext->get_length(), ext->get_bptr().c_str());
off += ext->get_length();
@ -111,17 +111,17 @@ seastar::future<bufferlist> TMDriver::read(
"read",
[=, &blret, this](auto& t)
{
return read_extents(t, offset, size
return read_extents(t, laddr_t::from_byte_offset(offset), size
).si_then([=, &blret](auto ext_list) {
size_t cur = offset;
auto cur = laddr_t::from_byte_offset(offset);
for (auto &i: ext_list) {
if (cur != i.first) {
assert(cur < i.first);
blret.append_zero(i.first - cur);
blret.append_zero(i.first.template get_byte_distance<size_t>(cur));
cur = i.first;
}
blret.append(i.second->get_bptr());
cur += i.second->get_bptr().length();
cur = (cur + i.second->get_bptr().length()).checked_to_laddr();
}
if (blret.length() != size) {
assert(blret.length() < size);

View File

@ -32,7 +32,7 @@ struct onode_item_t {
void initialize(Transaction& t, Onode& value) const {
auto &ftvalue = static_cast<FLTreeOnode&>(value);
ftvalue.update_onode_size(t, size);
auto oroot = omap_root_t(id, cnt_modify,
auto oroot = omap_root_t(laddr_t::from_raw_uint(id), cnt_modify,
value.get_metadata_hint(block_size));
ftvalue.update_omap_root(t, oroot);
validate(value);
@ -40,8 +40,8 @@ struct onode_item_t {
void validate(Onode& value) const {
auto& layout = value.get_layout();
ceph_assert(laddr_t(layout.size) == laddr_t{size});
ceph_assert(layout.omap_root.get(value.get_metadata_hint(block_size)).addr == id);
ceph_assert(uint64_t(layout.size) == uint64_t{size});
ceph_assert(layout.omap_root.get(value.get_metadata_hint(block_size)).addr == laddr_t::from_raw_uint(id));
ceph_assert(layout.omap_root.get(value.get_metadata_hint(block_size)).depth == cnt_modify);
}

View File

@ -127,7 +127,7 @@ TEST_F(a_basic_test_t, 1_basic_sizes)
value.payload_size = 8;
#define _STAGE_T(NodeType) node_to_stage_t<typename NodeType::node_stage_t>
#define NXT_T(StageType) staged<typename StageType::next_param_t>
laddr_t i_value{0};
laddr_t i_value = L_ADDR_MIN;
logger().info("\n"
"Bytes of a key-value insertion (full-string):\n"
" s-p-c, 'n'-'o', s-g => value_payload(8): typically internal 43B, leaf 59B\n"
@ -1047,8 +1047,8 @@ class DummyChildPool {
static Ref<DummyChild> create_new(
const std::set<ghobject_t>& keys, bool is_level_tail, DummyChildPool& pool) {
static laddr_t seed = 0;
return create(keys, is_level_tail, seed++, pool);
static uint64_t seed = 0;
return create(keys, is_level_tail, laddr_t::from_raw_uint(seed++), pool);
}
static eagain_ifuture<Ref<DummyChild>> create_initial(

View File

@ -137,7 +137,7 @@ class TestValue final : public Value {
void apply_value_delta(ceph::bufferlist::const_iterator& delta,
NodeExtentMutable& payload_mut,
laddr_t value_addr) override {
laddr_offset_t value_addr_offset) override {
delta_op_t op;
try {
ceph::decode(op, delta);
@ -159,13 +159,13 @@ class TestValue final : public Value {
break;
}
default:
logger().error("OTree::TestValue::Replay: got unknown op {} when replay {:#x}+{:#x}",
op, value_addr, payload_mut.get_length());
logger().error("OTree::TestValue::Replay: got unknown op {} when replay {}~{:#x}",
op, value_addr_offset, payload_mut.get_length());
ceph_abort();
}
} catch (buffer::error& e) {
logger().error("OTree::TestValue::Replay: got decode error {} when replay {:#x}+{:#x}",
e.what(), value_addr, payload_mut.get_length());
logger().error("OTree::TestValue::Replay: got decode error {} when replay {}~{:#x}",
e.what(), value_addr_offset, payload_mut.get_length());
ceph_abort();
}
}

View File

@ -378,14 +378,14 @@ TEST_F(lba_btree_test, basic)
run_async([this] {
constexpr unsigned total = 16<<10;
for (unsigned i = 0; i < total; i += 16) {
insert(i, 8);
insert(laddr_t::from_raw_uint(i), 8);
}
for (unsigned i = 0; i < total; i += 16) {
check_lower_bound(i);
check_lower_bound(i + 4);
check_lower_bound(i + 8);
check_lower_bound(i + 12);
check_lower_bound(laddr_t::from_raw_uint(i));
check_lower_bound(laddr_t::from_raw_uint(i + 4));
check_lower_bound(laddr_t::from_raw_uint(i + 8));
check_lower_bound(laddr_t::from_raw_uint(i + 12));
}
});
}
@ -500,7 +500,7 @@ struct btree_lba_manager_test : btree_test_base {
bottom->first + bottom->second.len <= addr)
++bottom;
auto top = t.mappings.lower_bound(addr + len);
auto top = t.mappings.lower_bound((addr + len).checked_to_laddr());
return std::make_pair(
bottom,
top
@ -665,7 +665,7 @@ struct btree_lba_manager_test : btree_test_base {
[=, &t, this](auto &) {
return lba_manager->scan_mappings(
*t.t,
0,
L_ADDR_MIN,
L_ADDR_MAX,
[iter=t.mappings.begin(), &t](auto l, auto p, auto len) mutable {
EXPECT_NE(iter, t.mappings.end());
@ -681,7 +681,7 @@ struct btree_lba_manager_test : btree_test_base {
TEST_F(btree_lba_manager_test, basic)
{
run_async([this] {
laddr_t laddr = 0x12345678 * block_size;
laddr_t laddr = laddr_t::from_byte_offset(0x12345678 * block_size);
{
// write initial mapping
auto t = create_transaction();
@ -701,7 +701,7 @@ TEST_F(btree_lba_manager_test, force_split)
auto t = create_transaction();
logger().debug("opened transaction");
for (unsigned j = 0; j < 5; ++j) {
alloc_mappings(t, 0, block_size);
alloc_mappings(t, L_ADDR_MIN, block_size);
if ((i % 10 == 0) && (j == 3)) {
check_mappings(t);
check_mappings();
@ -721,7 +721,7 @@ TEST_F(btree_lba_manager_test, force_split_merge)
auto t = create_transaction();
logger().debug("opened transaction");
for (unsigned j = 0; j < 5; ++j) {
auto rets = alloc_mappings(t, 0, block_size);
auto rets = alloc_mappings(t, L_ADDR_MIN, block_size);
// just to speed things up a bit
if ((i % 100 == 0) && (j == 3)) {
check_mappings(t);
@ -780,7 +780,7 @@ TEST_F(btree_lba_manager_test, single_transaction_split_merge)
{
auto t = create_transaction();
for (unsigned i = 0; i < 400; ++i) {
alloc_mappings(t, 0, block_size);
alloc_mappings(t, L_ADDR_MIN, block_size);
}
check_mappings(t);
submit_test_transaction(std::move(t));
@ -803,7 +803,7 @@ TEST_F(btree_lba_manager_test, single_transaction_split_merge)
{
auto t = create_transaction();
for (unsigned i = 0; i < 600; ++i) {
alloc_mappings(t, 0, block_size);
alloc_mappings(t, L_ADDR_MIN, block_size);
}
auto addresses = get_mapped_addresses(t);
for (unsigned i = 0; i != addresses.size(); ++i) {
@ -831,23 +831,23 @@ TEST_F(btree_lba_manager_test, split_merge_multi)
}
};
iterate([&](auto &t, auto idx) {
alloc_mappings(t, idx * block_size, block_size);
alloc_mappings(t, laddr_t::from_byte_offset(idx * block_size), block_size);
});
check_mappings();
iterate([&](auto &t, auto idx) {
if ((idx % 32) > 0) {
decref_mapping(t, idx * block_size);
decref_mapping(t, laddr_t::from_byte_offset(idx * block_size));
}
});
check_mappings();
iterate([&](auto &t, auto idx) {
if ((idx % 32) > 0) {
alloc_mappings(t, idx * block_size, block_size);
alloc_mappings(t, laddr_t::from_byte_offset(idx * block_size), block_size);
}
});
check_mappings();
iterate([&](auto &t, auto idx) {
decref_mapping(t, idx * block_size);
decref_mapping(t, laddr_t::from_byte_offset(idx * block_size));
});
check_mappings();
});

View File

@ -218,14 +218,14 @@ struct object_data_handler_test_t:
objaddr_t offset,
extent_len_t length) {
auto ret = with_trans_intr(t, [&](auto &t) {
return tm->get_pins(t, offset, length);
return tm->get_pins(t, laddr_t::from_byte_offset(offset), length);
}).unsafe_get();
return ret;
}
std::list<LBAMappingRef> get_mappings(objaddr_t offset, extent_len_t length) {
auto t = create_mutate_transaction();
auto ret = with_trans_intr(*t, [&](auto &t) {
return tm->get_pins(t, offset, length);
return tm->get_pins(t, laddr_t::from_byte_offset(offset), length);
}).unsafe_get();
return ret;
}
@ -297,7 +297,7 @@ struct object_data_handler_test_t:
"seastore_max_data_allocation_size", "8192").get();
}
laddr_t get_random_laddr(size_t block_size, laddr_t limit) {
objaddr_t get_random_write_offset(size_t block_size, objaddr_t limit) {
return block_size *
std::uniform_int_distribution<>(0, (limit / block_size) - 1)(gen);
}
@ -632,7 +632,7 @@ TEST_P(object_data_handler_test_t, remap_left) {
auto base = pins.front()->get_key();
int i = 0;
for (auto &pin : pins) {
EXPECT_EQ(pin->get_key() - base, res[i]);
EXPECT_EQ(pin->get_key().get_byte_distance<size_t>(base), res[i]);
i++;
}
read(0, 128<<10);
@ -666,7 +666,7 @@ TEST_P(object_data_handler_test_t, remap_right) {
auto base = pins.front()->get_key();
int i = 0;
for (auto &pin : pins) {
EXPECT_EQ(pin->get_key() - base, res[i]);
EXPECT_EQ(pin->get_key().get_byte_distance<size_t>(base), res[i]);
i++;
}
read(0, 128<<10);
@ -699,7 +699,7 @@ TEST_P(object_data_handler_test_t, remap_right_left) {
auto base = pins.front()->get_key();
int i = 0;
for (auto &pin : pins) {
EXPECT_EQ(pin->get_key() - base, res[i]);
EXPECT_EQ(pin->get_key().get_byte_distance<size_t>(base), res[i]);
i++;
}
enable_max_extent_size();
@ -730,7 +730,7 @@ TEST_P(object_data_handler_test_t, multiple_remap) {
auto base = pins.front()->get_key();
int i = 0;
for (auto &pin : pins) {
EXPECT_EQ(pin->get_key() - base, res[i]);
EXPECT_EQ(pin->get_key().get_byte_distance<size_t>(base), res[i]);
i++;
}
read(0, 128<<10);
@ -769,7 +769,7 @@ TEST_P(object_data_handler_test_t, random_overwrite) {
for (unsigned j = 0; j < 100; ++j) {
auto t = create_mutate_transaction();
for (unsigned k = 0; k < 2; ++k) {
write(*t, get_random_laddr(BSIZE, TOTAL), wsize,
write(*t, get_random_write_offset(BSIZE, TOTAL), wsize,
(char)((j*k) % std::numeric_limits<char>::max()));
}
submit_transaction(std::move(t));
@ -798,7 +798,7 @@ TEST_P(object_data_handler_test_t, overwrite_then_read_within_transaction) {
auto pins = get_mappings(*t, base, len);
assert(pins.size() == 1);
auto pin1 = remap_pin(*t, std::move(pins.front()), 4096, 8192);
auto ext = get_extent(*t, base + 4096, 4096 * 2);
auto ext = get_extent(*t, laddr_t::from_byte_offset(base + 4096), 4096 * 2);
ASSERT_TRUE(ext->is_exist_clean());
write(*t, base + 4096, 4096, 'y');
ASSERT_TRUE(ext->is_exist_mutation_pending());

View File

@ -66,9 +66,9 @@ struct transaction_manager_test_t :
: TMTestState(num_main_devices, num_cold_devices), gen(rd()) {
}
laddr_t get_random_laddr(size_t block_size, laddr_t limit) {
return block_size *
std::uniform_int_distribution<>(0, (limit / block_size) - 1)(gen);
laddr_t get_random_laddr(size_t block_size, size_t limit) {
return laddr_t::from_byte_offset(block_size *
std::uniform_int_distribution<>(0, (limit / block_size) - 1)(gen));
}
char get_random_contents() {
@ -254,8 +254,8 @@ struct transaction_manager_test_t :
EXPECT_EQ(addr, last);
break;
}
EXPECT_FALSE(iter->first - last > len);
last = iter->first + iter->second.desc.len;
EXPECT_FALSE(iter->first.get_byte_distance<extent_len_t>(last) > len);
last = (iter->first + iter->second.desc.len).checked_to_laddr();
++iter;
}
}
@ -719,7 +719,7 @@ struct transaction_manager_test_t :
[this, &overlay](auto &t) {
return lba_manager->scan_mappings(
t,
0,
L_ADDR_MIN,
L_ADDR_MAX,
[iter=overlay.begin(), &overlay](auto l, auto p, auto len) mutable {
EXPECT_NE(iter, overlay.end());
@ -830,9 +830,9 @@ struct transaction_manager_test_t :
auto t = create_transaction();
auto extent = alloc_extent(
t,
i * BSIZE,
laddr_t::from_byte_offset(i * BSIZE),
BSIZE);
ASSERT_EQ(i * BSIZE, extent->get_laddr());
ASSERT_EQ(laddr_t::from_byte_offset(i * BSIZE), extent->get_laddr());
submit_transaction(std::move(t));
}
@ -844,7 +844,7 @@ struct transaction_manager_test_t :
boost::make_counting_iterator(0lu),
boost::make_counting_iterator(BLOCKS),
[this, &t](auto i) {
return tm->read_extent<TestBlock>(t, i * BSIZE, BSIZE
return tm->read_extent<TestBlock>(t, laddr_t::from_byte_offset(i * BSIZE), BSIZE
).si_then([](auto) {
return seastar::now();
});
@ -870,9 +870,9 @@ struct transaction_manager_test_t :
auto t = create_transaction();
auto extent = alloc_extent(
t,
i * BSIZE,
laddr_t::from_byte_offset(i * BSIZE),
BSIZE);
ASSERT_EQ(i * BSIZE, extent->get_laddr());
ASSERT_EQ(laddr_t::from_byte_offset(i * BSIZE), extent->get_laddr());
if (try_submit_transaction(std::move(t)))
break;
}
@ -1180,7 +1180,7 @@ struct transaction_manager_test_t :
o_len - new_offset - new_len)
}
).si_then([this, new_offset, new_len, o_laddr, &t, &bl](auto ret) {
return tm->alloc_data_extents<TestBlock>(t, o_laddr + new_offset, new_len
return tm->alloc_data_extents<TestBlock>(t, (o_laddr + new_offset).checked_to_laddr(), new_len
).si_then([this, ret = std::move(ret), new_len,
new_offset, o_laddr, &t, &bl](auto extents) mutable {
assert(extents.size() == 1);
@ -1188,7 +1188,7 @@ struct transaction_manager_test_t :
ceph_assert(ret.size() == 2);
auto iter = bl.cbegin();
iter.copy(new_len, ext->get_bptr().c_str());
auto r_laddr = o_laddr + new_offset + new_len;
auto r_laddr = (o_laddr + new_offset + new_len).checked_to_laddr();
// old pins expired after alloc new extent, need to get it.
return tm->get_pin(t, o_laddr
).si_then([this, &t, ext = std::move(ext), r_laddr](auto lpin) mutable {
@ -1216,7 +1216,7 @@ struct transaction_manager_test_t :
o_len - new_offset - new_len)
}
).si_then([this, new_offset, new_len, o_laddr, &t, &bl](auto ret) {
return tm->alloc_data_extents<TestBlock>(t, o_laddr + new_offset, new_len
return tm->alloc_data_extents<TestBlock>(t, (o_laddr + new_offset).checked_to_laddr(), new_len
).si_then([this, ret = std::move(ret), new_offset, new_len,
o_laddr, &t, &bl](auto extents) mutable {
assert(extents.size() == 1);
@ -1224,7 +1224,7 @@ struct transaction_manager_test_t :
ceph_assert(ret.size() == 1);
auto iter = bl.cbegin();
iter.copy(new_len, ext->get_bptr().c_str());
auto r_laddr = o_laddr + new_offset + new_len;
auto r_laddr = (o_laddr + new_offset + new_len).checked_to_laddr();
return tm->get_pin(t, r_laddr
).si_then([ext = std::move(ext)](auto rpin) mutable {
return _overwrite_pin_iertr::make_ready_future<
@ -1247,7 +1247,7 @@ struct transaction_manager_test_t :
new_offset)
}
).si_then([this, new_offset, new_len, o_laddr, &t, &bl](auto ret) {
return tm->alloc_data_extents<TestBlock>(t, o_laddr + new_offset, new_len
return tm->alloc_data_extents<TestBlock>(t, (o_laddr + new_offset).checked_to_laddr(), new_len
).si_then([this, ret = std::move(ret), new_len, o_laddr, &t, &bl]
(auto extents) mutable {
assert(extents.size() == 1);
@ -1346,10 +1346,10 @@ struct transaction_manager_test_t :
void test_remap_pin() {
run_async([this] {
disable_max_extent_size();
constexpr size_t l_offset = 32 << 10;
constexpr size_t l_len = 32 << 10;
constexpr size_t r_offset = 64 << 10;
constexpr size_t r_len = 32 << 10;
laddr_t l_offset = laddr_t::from_byte_offset(32 << 10);
size_t l_len = 32 << 10;
laddr_t r_offset = laddr_t::from_byte_offset(64 << 10);
size_t r_len = 32 << 10;
{
auto t = create_transaction();
auto lext = alloc_extent(t, l_offset, l_len);
@ -1400,12 +1400,12 @@ struct transaction_manager_test_t :
void test_clone_and_remap_pin() {
run_async([this] {
disable_max_extent_size();
constexpr size_t l_offset = 32 << 10;
constexpr size_t l_len = 32 << 10;
constexpr size_t r_offset = 64 << 10;
constexpr size_t r_len = 32 << 10;
constexpr size_t l_clone_offset = 96 << 10;
constexpr size_t r_clone_offset = 128 << 10;
laddr_t l_offset = laddr_t::from_byte_offset(32 << 10);
size_t l_len = 32 << 10;
laddr_t r_offset = laddr_t::from_byte_offset(64 << 10);
size_t r_len = 32 << 10;
laddr_t l_clone_offset = laddr_t::from_byte_offset(96 << 10);
laddr_t r_clone_offset = laddr_t::from_byte_offset(128 << 10);
{
auto t = create_transaction();
auto lext = alloc_extent(t, l_offset, l_len);
@ -1455,12 +1455,12 @@ struct transaction_manager_test_t :
void test_overwrite_pin() {
run_async([this] {
disable_max_extent_size();
constexpr size_t m_offset = 8 << 10;
constexpr size_t m_len = 56 << 10;
constexpr size_t l_offset = 64 << 10;
constexpr size_t l_len = 64 << 10;
constexpr size_t r_offset = 128 << 10;
constexpr size_t r_len = 64 << 10;
laddr_t m_offset = laddr_t::from_byte_offset(8 << 10);
size_t m_len = 56 << 10;
laddr_t l_offset = laddr_t::from_byte_offset(64 << 10);
size_t l_len = 64 << 10;
laddr_t r_offset = laddr_t::from_byte_offset(128 << 10);
size_t r_len = 64 << 10;
{
auto t = create_transaction();
auto m_ext = alloc_extent(t, m_offset, m_len);
@ -1538,7 +1538,7 @@ struct transaction_manager_test_t :
run_async([this] {
disable_max_extent_size();
constexpr unsigned REMAP_NUM = 32;
constexpr size_t offset = 0;
constexpr laddr_t offset = L_ADDR_MIN;
constexpr size_t length = 256 << 10;
{
auto t = create_transaction();
@ -1575,7 +1575,8 @@ struct transaction_manager_test_t :
if (off == 0 || off >= 255) {
continue;
}
auto new_off = (off << 10) - last_pin->get_key();
auto new_off = laddr_t::from_byte_offset(off << 10)
.get_byte_distance<extent_len_t>(last_pin->get_key());
auto new_len = last_pin->get_length() - new_off;
//always remap right extent at new split_point
auto pin = remap_pin(t, std::move(last_pin), new_off, new_len);
@ -1620,7 +1621,7 @@ struct transaction_manager_test_t :
run_async([this] {
disable_max_extent_size();
constexpr unsigned REMAP_NUM = 32;
constexpr size_t offset = 0;
constexpr laddr_t offset = L_ADDR_MIN;
constexpr size_t length = 256 << 10;
{
auto t = create_transaction();
@ -1665,7 +1666,7 @@ struct transaction_manager_test_t :
auto end_off = split_points.front();
split_points.pop_front();
ASSERT_TRUE(start_off <= end_off);
if (((end_off << 10) == pin0->get_key() + pin0->get_length())
if ((laddr_t::from_byte_offset(end_off << 10) == pin0->get_key() + pin0->get_length())
|| (start_off == end_off)) {
if (split_points.empty() && empty_transaction) {
early_exit++;
@ -1674,7 +1675,8 @@ struct transaction_manager_test_t :
continue;
}
empty_transaction = false;
auto new_off = (start_off << 10) - last_rpin->get_key();
auto new_off = laddr_t::from_byte_offset(start_off << 10)
.get_byte_distance<extent_len_t>(last_rpin->get_key());
auto new_len = (end_off - start_off) << 10;
bufferlist bl;
bl.append(ceph::bufferptr(ceph::buffer::create(new_len, 0)));
@ -1766,13 +1768,13 @@ struct tm_random_block_device_test_t :
TEST_P(tm_random_block_device_test_t, scatter_allocation)
{
run_async([this] {
constexpr laddr_t ADDR = 0xFF * 4096;
laddr_t ADDR = laddr_t::from_byte_offset(0xFF * 4096);
epm->prefill_fragmented_devices();
auto t = create_transaction();
for (int i = 0; i < 1991; i++) {
auto extents = alloc_extents(t, ADDR + i * 16384, 16384, 'a');
auto extents = alloc_extents(t, (ADDR + i * 16384).checked_to_laddr(), 16384, 'a');
}
alloc_extents_deemed_fail(t, ADDR + 1991 * 16384, 16384, 'a');
alloc_extents_deemed_fail(t, (ADDR + 1991 * 16384).checked_to_laddr(), 16384, 'a');
check_mappings(t);
check();
submit_transaction(std::move(t));
@ -1782,9 +1784,9 @@ TEST_P(tm_random_block_device_test_t, scatter_allocation)
TEST_P(tm_single_device_test_t, basic)
{
constexpr laddr_t SIZE = 4096;
constexpr size_t SIZE = 4096;
run_async([this] {
constexpr laddr_t ADDR = 0xFF * SIZE;
laddr_t ADDR = laddr_t::from_byte_offset(0xFF * SIZE);
{
auto t = create_transaction();
auto extent = alloc_extent(
@ -1803,9 +1805,9 @@ TEST_P(tm_single_device_test_t, basic)
TEST_P(tm_single_device_test_t, mutate)
{
constexpr laddr_t SIZE = 4096;
constexpr size_t SIZE = 4096;
run_async([this] {
constexpr laddr_t ADDR = 0xFF * SIZE;
laddr_t ADDR = laddr_t::from_byte_offset(0xFF * SIZE);
{
auto t = create_transaction();
auto extent = alloc_extent(
@ -1841,10 +1843,10 @@ TEST_P(tm_single_device_test_t, mutate)
TEST_P(tm_single_device_test_t, allocate_lba_conflict)
{
constexpr laddr_t SIZE = 4096;
constexpr size_t SIZE = 4096;
run_async([this] {
constexpr laddr_t ADDR = 0xFF * SIZE;
constexpr laddr_t ADDR2 = 0xFE * SIZE;
laddr_t ADDR = laddr_t::from_byte_offset(0xFF * SIZE);
laddr_t ADDR2 = laddr_t::from_byte_offset(0xFE * SIZE);
auto t = create_transaction();
auto t2 = create_transaction();
@ -1874,14 +1876,14 @@ TEST_P(tm_single_device_test_t, allocate_lba_conflict)
TEST_P(tm_single_device_test_t, mutate_lba_conflict)
{
constexpr laddr_t SIZE = 4096;
constexpr size_t SIZE = 4096;
run_async([this] {
{
auto t = create_transaction();
for (unsigned i = 0; i < 300; ++i) {
auto extent = alloc_extent(
t,
laddr_t(i * SIZE),
laddr_t::from_byte_offset(i * SIZE),
SIZE);
}
check_mappings(t);
@ -1889,7 +1891,7 @@ TEST_P(tm_single_device_test_t, mutate_lba_conflict)
check();
}
constexpr laddr_t ADDR = 150 * SIZE;
laddr_t ADDR = laddr_t::from_byte_offset(150 * SIZE);
{
auto t = create_transaction();
auto t2 = create_transaction();
@ -1913,17 +1915,17 @@ TEST_P(tm_single_device_test_t, mutate_lba_conflict)
TEST_P(tm_single_device_test_t, concurrent_mutate_lba_no_conflict)
{
constexpr laddr_t SIZE = 4096;
constexpr size_t SIZE = 4096;
constexpr size_t NUM = 500;
constexpr laddr_t addr = 0;
constexpr laddr_t addr2 = SIZE * (NUM - 1);
run_async([this] {
laddr_t addr = L_ADDR_MIN;
laddr_t addr2 = laddr_t::from_byte_offset(SIZE * (NUM - 1));
run_async([this, addr, addr2] {
{
auto t = create_transaction();
for (unsigned i = 0; i < NUM; ++i) {
auto extent = alloc_extent(
t,
laddr_t(i * SIZE),
laddr_t::from_byte_offset(i * SIZE),
SIZE);
}
submit_transaction(std::move(t));
@ -1945,9 +1947,9 @@ TEST_P(tm_single_device_test_t, concurrent_mutate_lba_no_conflict)
TEST_P(tm_single_device_test_t, create_remove_same_transaction)
{
constexpr laddr_t SIZE = 4096;
constexpr size_t SIZE = 4096;
run_async([this] {
constexpr laddr_t ADDR = 0xFF * SIZE;
laddr_t ADDR = laddr_t::from_byte_offset(0xFF * SIZE);
{
auto t = create_transaction();
auto extent = alloc_extent(
@ -1976,14 +1978,14 @@ TEST_P(tm_single_device_test_t, create_remove_same_transaction)
TEST_P(tm_single_device_test_t, split_merge_read_same_transaction)
{
constexpr laddr_t SIZE = 4096;
constexpr size_t SIZE = 4096;
run_async([this] {
{
auto t = create_transaction();
for (unsigned i = 0; i < 300; ++i) {
auto extent = alloc_extent(
t,
laddr_t(i * SIZE),
laddr_t::from_byte_offset(i * SIZE),
SIZE);
}
check_mappings(t);
@ -1995,7 +1997,7 @@ TEST_P(tm_single_device_test_t, split_merge_read_same_transaction)
for (unsigned i = 0; i < 240; ++i) {
dec_ref(
t,
laddr_t(i * SIZE));
laddr_t::from_byte_offset(i * SIZE));
}
check_mappings(t);
submit_transaction(std::move(t));
@ -2006,9 +2008,9 @@ TEST_P(tm_single_device_test_t, split_merge_read_same_transaction)
TEST_P(tm_single_device_test_t, inc_dec_ref)
{
constexpr laddr_t SIZE = 4096;
constexpr size_t SIZE = 4096;
run_async([this] {
constexpr laddr_t ADDR = 0xFF * SIZE;
laddr_t ADDR = laddr_t::from_byte_offset(0xFF * SIZE);
{
auto t = create_transaction();
auto extent = alloc_extent(
@ -2053,16 +2055,16 @@ TEST_P(tm_single_device_test_t, inc_dec_ref)
TEST_P(tm_single_device_test_t, cause_lba_split)
{
constexpr laddr_t SIZE = 4096;
constexpr size_t SIZE = 4096;
run_async([this] {
for (unsigned i = 0; i < 200; ++i) {
auto t = create_transaction();
auto extent = alloc_extent(
t,
i * SIZE,
laddr_t::from_byte_offset(i * SIZE),
SIZE,
(char)(i & 0xFF));
ASSERT_EQ(i * SIZE, extent->get_laddr());
ASSERT_EQ(laddr_t::from_byte_offset(i * SIZE), extent->get_laddr());
submit_transaction(std::move(t));
}
check();
@ -2080,9 +2082,9 @@ TEST_P(tm_single_device_test_t, random_writes)
auto t = create_transaction();
auto extent = alloc_extent(
t,
i * BSIZE,
laddr_t::from_byte_offset(i * BSIZE),
BSIZE);
ASSERT_EQ(i * BSIZE, extent->get_laddr());
ASSERT_EQ(laddr_t::from_byte_offset(i * BSIZE), extent->get_laddr());
submit_transaction(std::move(t));
}
@ -2098,7 +2100,7 @@ TEST_P(tm_single_device_test_t, random_writes)
// pad out transaction
auto paddings = alloc_extents(
t,
TOTAL + (k * PADDING_SIZE),
laddr_t::from_byte_offset(TOTAL + (k * PADDING_SIZE)),
PADDING_SIZE);
for (auto &padding : paddings) {
dec_ref(t, padding->get_laddr());
@ -2131,7 +2133,7 @@ TEST_P(tm_single_device_test_t, find_hole_assert_trigger)
TEST_P(tm_single_device_intergrity_check_test_t, remap_lazy_read)
{
constexpr laddr_t offset = 0;
constexpr laddr_t offset = L_ADDR_MIN;
constexpr size_t length = 256 << 10;
run_async([this, offset] {
disable_max_extent_size();
@ -2184,7 +2186,7 @@ TEST_P(tm_single_device_test_t, invalid_lba_mapping_detect)
for (int i = 0; i < LEAF_NODE_CAPACITY; i++) {
auto extent = alloc_extent(
t,
i * 4096,
laddr_t::from_byte_offset(i * 4096),
4096,
'a');
}
@ -2193,12 +2195,12 @@ TEST_P(tm_single_device_test_t, invalid_lba_mapping_detect)
{
auto t = create_transaction();
auto pin = get_pin(t, (LEAF_NODE_CAPACITY - 1) * 4096);
auto pin = get_pin(t, laddr_t::from_byte_offset((LEAF_NODE_CAPACITY - 1) * 4096));
assert(pin->is_parent_viewable());
auto extent = alloc_extent(t, LEAF_NODE_CAPACITY * 4096, 4096, 'a');
auto extent = alloc_extent(t, laddr_t::from_byte_offset(LEAF_NODE_CAPACITY * 4096), 4096, 'a');
assert(!pin->is_parent_viewable());
pin = get_pin(t, LEAF_NODE_CAPACITY * 4096);
std::ignore = alloc_extent(t, (LEAF_NODE_CAPACITY + 1) * 4096, 4096, 'a');
pin = get_pin(t, laddr_t::from_byte_offset(LEAF_NODE_CAPACITY * 4096));
std::ignore = alloc_extent(t, laddr_t::from_byte_offset((LEAF_NODE_CAPACITY + 1) * 4096), 4096, 'a');
assert(pin->is_parent_viewable());
assert(pin->parent_modified());
pin->maybe_fix_pos();