DEBUGT("start with {} allocated extents",
t, extents.size());
std::vector<write_info_t> writes;
- writes.reserve(extents.size());
for (auto& ex : extents) {
auto paddr = ex->get_paddr();
assert(paddr.is_absolute());
auto& stats = t.get_ool_write_stats();
stats.extents.num += 1;
stats.extents.bytes += ex->get_length();
- stats.num_records += 1;
-
ex->prepare_write();
- extent_len_t offset = 0;
+
bufferptr bp;
if (can_inplace_rewrite(t, ex)) {
assert(ex->is_logical());
auto r = ex->template cast<LogicalCachedExtent>()->get_modified_region();
ceph_assert(r.has_value());
- offset = p2align(r->offset, rbm->get_block_size());
+ extent_len_t offset = p2align(r->offset, rbm->get_block_size());
extent_len_t len =
p2roundup(r->offset + r->len, rbm->get_block_size()) - offset;
bp = ceph::bufferptr(ex->get_bptr(), offset, len);
+ paddr = ex->get_paddr() + offset;
} else {
bp = ex->get_bptr();
auto& trans_stats = get_by_src(w_stats.stats_by_src, t.get_src());
- ++(trans_stats.num_records);
trans_stats.data_bytes += ex->get_length();
w_stats.data_bytes += ex->get_length();
}
- writes.push_back(write_info_t{paddr + offset, std::move(bp), rbm});
if (ex->is_initial_pending()) {
t.mark_allocated_extent_ool(ex);
} else {
ceph_assert("impossible");
}
+
+ // TODO : allocate a consecutive address based on a transaction
+ if (writes.size() != 0 &&
+ writes.back().offset + writes.back().bp.length() == paddr) {
+ // We can write both the currrent extent and the previous one at once
+ // if the extents are located in a row
+ if (writes.back().mergeable_bps.size() == 0) {
+ writes.back().mergeable_bps.push_back(writes.back().bp);
+ }
+ writes.back().mergeable_bps.push_back(ex->get_bptr());
+ } else {
+ // Write a single extent in the existing way
+ write_info_t w_info;
+ w_info.offset = paddr;
+ w_info.rbm = rbm;
+ w_info.bp = bp;
+ writes.push_back(w_info);
+ }
+ TRACE("current extent: base off {} len {},\
+ maybe-merged current extent: base off {} len {}",
+ paddr, ex->get_length(), writes.back().offset, writes.back().bp.length());
+ }
+
+ for (auto &w : writes) {
+ if (w.mergeable_bps.size() > 0) {
+ extent_len_t len = 0;
+ for (auto &b : w.mergeable_bps) {
+ len += b.length();
+ }
+ w.bp = ceph::bufferptr(ceph::buffer::create_page_aligned(len));
+ extent_len_t cursor = 0;
+ for (auto &b : w.mergeable_bps) {
+ w.bp.copy_in(cursor, b.length(), b.c_str());
+ cursor += b.length();
+ }
+ w.mergeable_bps.clear();
+ }
}
return trans_intr::make_interruptible(
seastar::do_with(std::move(writes),
- [](auto& writes) {
+ [&t, this](auto& writes) {
+ auto& stats = t.get_ool_write_stats();
+ stats.num_records += writes.size();
+ auto& trans_stats = get_by_src(w_stats.stats_by_src, t.get_src());
+ trans_stats.num_records += writes.size();
return crimson::do_for_each(writes,
[](auto& info) {
return info.rbm->write(info.offset, info.bp