overwrite_plan_t(laddr_t offset,
extent_len_t len,
const lba_pin_list_t& pins,
- extent_len_t block_size) :
+ extent_len_t block_size,
+ Transaction& t) :
pin_begin(pins.front()->get_key()),
pin_end(pins.back()->get_key() + pins.back()->get_length()),
left_paddr(pins.front()->get_val()),
right_operation(overwrite_operation_t::UNKNOWN),
block_size(block_size) {
validate();
- evaluate_operations();
+ evaluate_operations(t);
assert(left_operation != overwrite_operation_t::UNKNOWN);
assert(right_operation != overwrite_operation_t::UNKNOWN);
}
* original extent into at most three parts: origin-left, part-to-be-modified
* and origin-right.
*/
- void evaluate_operations() {
+ void evaluate_operations(Transaction& t) {
auto actual_write_size = get_pins_size();
auto aligned_data_size = get_aligned_data_size();
auto left_ext_size = get_left_extent_size();
auto right_ext_size = get_right_extent_size();
+ auto can_merge = [](Transaction& t, paddr_t paddr) {
+ CachedExtentRef ext;
+ if (paddr.is_relative() || paddr.is_delayed()) {
+ return true;
+ } else if (t.get_extent(paddr, &ext) ==
+ Transaction::get_extent_ret::PRESENT) {
+ // FIXME: there is no need to lookup the cache if the pin can
+ // be associated with the extent state
+ if (ext->is_mutable()) {
+ return true;
+ }
+ }
+ return false;
+ };
if (left_paddr.is_zero()) {
actual_write_size -= left_ext_size;
left_ext_size = 0;
left_operation = overwrite_operation_t::OVERWRITE_ZERO;
- // FIXME: left_paddr can be absolute and pending
- } else if (left_paddr.is_relative() ||
- left_paddr.is_delayed()) {
+ } else if (can_merge(t, left_paddr)) {
aligned_data_size += left_ext_size;
left_ext_size = 0;
left_operation = overwrite_operation_t::MERGE_EXISTING;
actual_write_size -= right_ext_size;
right_ext_size = 0;
right_operation = overwrite_operation_t::OVERWRITE_ZERO;
- // FIXME: right_paddr can be absolute and pending
- } else if (right_paddr.is_relative() ||
- right_paddr.is_delayed()) {
+ } else if (can_merge(t, right_paddr)) {
aligned_data_size += right_ext_size;
right_ext_size = 0;
right_operation = overwrite_operation_t::MERGE_EXISTING;
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(offset, len, _pins, ctx.tm.get_block_size(), ctx.t);
return seastar::do_with(
std::move(_pins),
extent_to_write_list_t(),