assert(ref->is_valid());
extents.insert(*ref);
- ceph_assert(!ref->primary_ref_list_hook.is_linked());
if (ref->is_dirty()) {
- intrusive_ptr_add_ref(&*ref);
- dirty.push_back(*ref);
+ add_to_dirty(ref);
+ } else {
+ ceph_assert(!ref->primary_ref_list_hook.is_linked());
}
logger().debug("add_extent: {}", *ref);
}
assert(ref->is_valid());
assert(!ref->primary_ref_list_hook.is_linked());
intrusive_ptr_add_ref(&*ref);
- dirty.push_front(*ref);
+ dirty.push_back(*ref);
}
void Cache::remove_extent(CachedExtentRef ref)
if (prev->is_dirty()) {
ceph_assert(prev->primary_ref_list_hook.is_linked());
- dirty.insert(dirty.iterator_to(*prev), *next);
- dirty.erase(dirty.iterator_to(*prev));
+ auto prev_it = dirty.iterator_to(*prev);
+ dirty.insert(prev_it, *next);
+ dirty.erase(prev_it);
intrusive_ptr_release(&*prev);
intrusive_ptr_add_ref(&*next);
+ } else {
+ add_to_dirty(next);
}
}
}
i->state = CachedExtent::extent_state_t::DIRTY;
if (i->version == 1) {
- add_to_dirty(i);
+ i->dirty_from = seq;
}
}
extent->apply_delta_and_adjust_crc(record_base, delta.bl);
assert(extent->last_committed_crc == delta.final_crc);
+ if (extent->version == 0) {
+ extent->dirty_from = journal_seq;
+ }
extent->version++;
mark_dirty(extent);
});
SegmentManager &segment_manager; ///< ref to segment_manager
RootBlockRef root; ///< ref to current root
ExtentIndex extents; ///< set of live extents
- CachedExtent::list dirty; ///< holds refs to dirty extents
+
+ /**
+ * dirty
+ *
+ * holds refs to dirty extents. Ordered by CachedExtent::dirty_from.
+ */
+ CachedExtent::list dirty;
/// alloc buffer for cached extent
bufferptr alloc_cache_buf(size_t size) {
// Points at current version while in state MUTATION_PENDING
CachedExtentRef prior_instance;
+ /**
+ * dirty_from
+ *
+ * When dirty, indiciates the oldest journal entry which mutates
+ * this extent.
+ */
+ journal_seq_t dirty_from;
+
public:
/**
* duplicate_for_write
out << "CachedExtent(addr=" << this
<< ", type=" << get_type()
<< ", version=" << version
+ << ", dirty_from=" << dirty_from
<< ", paddr=" << get_paddr()
<< ", state=" << state
<< ", last_committed_crc=" << last_committed_crc
return state != extent_state_t::INVALID;
}
+ /**
+ * get_dirty_from
+ *
+ * Return journal location of oldest relevant delta.
+ */
+ auto get_dirty_from() const { return dirty_from; }
+
+
/**
* get_paddr
*
CachedExtent(ceph::bufferptr &&ptr) : ptr(std::move(ptr)) {}
CachedExtent(const CachedExtent &other)
: state(other.state),
+ dirty_from(other.dirty_from),
ptr(other.ptr.c_str(), other.ptr.length()),
version(other.version),
poffset(other.poffset) {}
struct share_buffer_t {};
CachedExtent(const CachedExtent &other, share_buffer_t) :
state(other.state),
+ dirty_from(other.dirty_from),
ptr(other.ptr),
version(other.version),
poffset(other.poffset) {}