crimson/os/seastore/transaction_manager: implement remap_pin

Signed-off-by: Xinyu Huang <xinyu.huang@intel.com>
This commit is contained in:
Xinyu Huang 2023-04-21 15:52:24 +00:00
parent cf6e46e57a
commit 55d33b69b0

View File

@ -291,6 +291,125 @@ public:
});
}
/**
* remap_pin
*
* Remap original extent to new extents.
* Return the pins of new extent.
*/
struct remap_entry {
extent_len_t offset;
extent_len_t len;
remap_entry(extent_len_t _offset, extent_len_t _len) {
offset = _offset;
len = _len;
}
};
using remap_pin_iertr = base_iertr;
template <std::size_t N>
using remap_pin_ret = remap_pin_iertr::future<std::array<LBAMappingRef, N>>;
template <typename T, std::size_t N>
remap_pin_ret<N> remap_pin(
Transaction &t,
LBAMappingRef &&pin,
std::array<remap_entry, N> remaps) {
#ifndef NDEBUG
std::sort(remaps.begin(), remaps.end(),
[](remap_entry x, remap_entry y) {
return x.offset < y.offset;
});
auto original_len = pin->get_length();
extent_len_t total_remap_len = 0;
extent_len_t last_offset = 0;
extent_len_t last_len = 0;
for (auto &remap : remaps) {
auto remap_offset = remap.offset;
auto remap_len = remap.len;
total_remap_len += remap.len;
ceph_assert(remap_offset >= (last_offset + last_len));
last_offset = remap_offset;
last_len = remap_len;
}
ceph_assert(total_remap_len < original_len);
#endif
// FIXME: paddr can be absolute and pending
ceph_assert(pin->get_val().is_absolute());
return cache->get_extent_if_cached(
t, pin->get_val(), T::TYPE
).si_then([this, &t, remaps,
original_laddr = pin->get_key(),
original_paddr = pin->get_val(),
original_len = pin->get_length()](auto ext) {
std::optional<ceph::bufferptr> original_bptr;
LOG_PREFIX(TransactionManager::remap_pin);
SUBDEBUGT(seastore_tm,
"original laddr: {}, original paddr: {}, original length: {},"
" remap to {} extents",
t, original_laddr, original_paddr, original_len, remaps.size());
if (ext) {
// FIXME: cannot and will not remap a dirty extent for now.
ceph_assert(!ext->is_dirty());
ceph_assert(!ext->is_mutable());
ceph_assert(ext->get_length() == original_len);
original_bptr = ext->get_bptr();
}
return seastar::do_with(
std::array<LBAMappingRef, N>(),
0,
std::move(original_bptr),
std::vector<remap_entry>(remaps.begin(), remaps.end()),
[this, &t, original_laddr, original_paddr, original_len]
(auto &ret, auto &count, auto &original_bptr, auto &remaps) {
return dec_ref(t, original_laddr
).si_then([this, &t, &original_bptr, &ret, &count, &remaps,
original_laddr, original_paddr, original_len](auto) {
return trans_intr::do_for_each(
remaps.begin(),
remaps.end(),
[this, &t, &original_bptr, &ret, &count,
original_laddr, original_paddr, original_len](auto &remap) {
LOG_PREFIX(TransactionManager::remap_pin);
auto remap_offset = remap.offset;
auto remap_len = remap.len;
auto remap_laddr = original_laddr + remap_offset;
auto remap_paddr = original_paddr.add_offset(remap_offset);
ceph_assert(remap_len < original_len);
ceph_assert(remap_offset + remap_len <= original_len);
ceph_assert(remap_len != 0);
ceph_assert(remap_offset % cache->get_block_size() == 0);
ceph_assert(remap_len % cache->get_block_size() == 0);
SUBDEBUGT(seastore_tm,
"remap laddr: {}, remap paddr: {}, remap length: {}", t,
remap_laddr, remap_paddr, remap_len);
return alloc_remapped_extent<T>(
t,
remap_laddr,
remap_paddr,
remap_len,
original_laddr,
std::move(original_bptr)
).si_then([&ret, &count, remap_laddr](auto &&npin) {
ceph_assert(npin->get_key() == remap_laddr);
ret[count++] = std::move(npin);
});
});
}).handle_error_interruptible(
remap_pin_iertr::pass_further{},
crimson::ct_error::assert_all{
"TransactionManager::remap_pin hit invalid error"
}
).si_then([&ret, &count] {
ceph_assert(count == N);
return remap_pin_iertr::make_ready_future<
std::array<LBAMappingRef, N>>(std::move(ret));
});
});
});
}
/**
* map_existing_extent
*