LBAMapping pos,
LBAMapping mapping,
laddr_t laddr,
+ extent_len_t offset,
+ extent_len_t len,
bool updateref)
{
LOG_PREFIX(BtreeLBAManager::clone_mapping);
assert(pos.is_viewable());
assert(mapping.is_viewable());
- DEBUGT("pos={}, mapping={}, laddr={}, updateref={}",
- t, pos, mapping, laddr, updateref);
+ DEBUGT("pos={}, mapping={}, laddr={}, {}~{} updateref={}",
+ t, pos, mapping, laddr, offset, len, updateref);
+ assert(offset + len <= mapping.get_length());
struct state_t {
LBAMapping pos;
LBAMapping mapping;
laddr_t laddr;
+ extent_len_t offset;
extent_len_t len;
};
auto c = get_context(t);
return update_refcount_iertr::make_ready_future<
LBAMapping>(std::move(mapping));
}
- }).si_then([c, this, pos=std::move(pos),
- laddr](auto mapping) mutable {
- auto len = mapping.get_length();
+ }).si_then([c, this, pos=std::move(pos), len,
+ offset, laddr](auto mapping) mutable {
return seastar::do_with(
- state_t{std::move(pos), std::move(mapping), laddr, len},
+ state_t{std::move(pos), std::move(mapping), laddr, offset, len},
[this, c](auto &state) {
return with_btree<LBABtree>(
cache,
).si_then([&state, c, &btree]() mutable {
auto &cursor = state.pos.get_effective_cursor();
assert(state.laddr + state.len <= cursor.key);
+ auto inter_key = state.mapping.is_indirect()
+ ? state.mapping.get_intermediate_key()
+ : state.mapping.get_key();
+ inter_key = (inter_key + state.offset).checked_to_laddr();
return btree.insert(
c,
btree.make_partial_iter(c, cursor),
state.laddr,
- lba_map_val_t{
- state.len,
- state.mapping.is_indirect()
- ? state.mapping.get_intermediate_key()
- : state.mapping.get_key(),
- EXTENT_DEFAULT_REF_COUNT,
- 0});
+ lba_map_val_t{state.len, inter_key, EXTENT_DEFAULT_REF_COUNT, 0});
}).si_then([c, &state](auto p) {
auto &[iter, inserted] = p;
auto &leaf_node = *iter.get_leaf_node();
LBAMapping pos,
LBAMapping mapping,
laddr_t laddr,
+ extent_len_t offset,
+ extent_len_t len,
bool updateref) final;
#ifdef UNIT_TESTS_BUILT
using clone_mapping_iertr = alloc_extent_iertr;
using clone_mapping_ret = clone_mapping_iertr::future<clone_mapping_ret_t>;
/*
- * Clones "mapping" at the position "pos" with new laddr "laddr", if updateref
- * is true, update the refcount of the mapping "mapping"
+ * Clones (part of) "mapping" at the position "pos" with the new lba key "laddr".
*/
virtual clone_mapping_ret clone_mapping(
Transaction &t,
- LBAMapping pos,
- LBAMapping mapping,
- laddr_t laddr,
- bool updateref) = 0;
+ LBAMapping pos, // the destined position
+ LBAMapping mapping, // the mapping to be cloned
+ laddr_t laddr, // the new lba key of the cloned mapping
+ extent_len_t offset, // the offset of the part to be cloned,
+ // relative to the start of the mapping.
+ extent_len_t len, // the length of the part to be cloned
+ bool updateref // whether to update the refcount of the
+ // direct mapping
+ ) = 0;
virtual alloc_extent_ret reserve_region(
Transaction &t,
LBAMapping pos,
LBAMapping mapping,
laddr_t hint,
+ extent_len_t offset,
+ extent_len_t len,
bool updateref) {
LOG_PREFIX(TransactionManager::clone_pin);
SUBDEBUGT(seastore_tm, "{} clone to hint {} ... pos={}, updateref={}",
return seastar::do_with(
std::move(pos),
std::move(mapping),
- [FNAME, this, &t, hint, updateref](auto &pos, auto &mapping) {
+ [offset, len, FNAME, this, &t, hint, updateref](auto &pos, auto &mapping) {
return pos.refresh(
).si_then([&pos, &mapping](auto m) {
pos = std::move(m);
return mapping.refresh();
- }).si_then([FNAME, this, &pos, &t, hint, updateref](auto mapping) {
+ }).si_then([offset, len, FNAME, this, &pos,
+ &t, hint, updateref](auto mapping) {
return lba_manager->clone_mapping(
t,
std::move(pos),
std::move(mapping),
hint,
+ offset,
+ len,
updateref
).si_then([FNAME, &t](auto ret) {
SUBDEBUGT(seastore_tm, "cloned as {}", t, ret.cloned_mapping);
if (mapping.is_real()) {
ret = true;
}
+ auto len = mapping.get_length();
return clone_pin(
t, std::move(pos), std::move(mapping),
- (base + offset).checked_to_laddr(), updateref
+ (base + offset).checked_to_laddr(),
+ 0, len, updateref
).si_then([&offset, &pos, &mapping](auto ret) {
offset += ret.cloned_mapping.get_length();
return ret.cloned_mapping.next(
laddr_t offset) {
auto key = mapping.get_key();
auto pin = with_trans_intr(*(t.t), [&](auto &trans) {
+ auto len = mapping.get_length();
return tm->clone_pin(
trans,
std::move(pos),
std::move(mapping),
offset,
+ 0,
+ len,
true);
}).unsafe_get().cloned_mapping;
EXPECT_EQ(offset, pin.get_key());