diff --git a/src/client/ObjecterWriteback.h b/src/client/ObjecterWriteback.h index 8b5a2684da8..1aa5e4932df 100644 --- a/src/client/ObjecterWriteback.h +++ b/src/client/ObjecterWriteback.h @@ -19,6 +19,10 @@ class ObjecterWriteback : public WritebackHandler { trunc_size, trunc_seq, onfinish); } + virtual bool may_copy_on_write(const object_t& oid, uint64_t read_off, uint64_t read_len, snapid_t snapid) { + return false; + } + virtual tid_t write(const object_t& oid, const object_locator_t& oloc, uint64_t off, uint64_t len, const SnapContext& snapc, const bufferlist &bl, utime_t mtime, uint64_t trunc_size, diff --git a/src/librbd/LibrbdWriteback.cc b/src/librbd/LibrbdWriteback.cc index 944d784c5f7..e732c9e4fc3 100644 --- a/src/librbd/LibrbdWriteback.cc +++ b/src/librbd/LibrbdWriteback.cc @@ -86,6 +86,29 @@ namespace librbd { return ++m_tid; } + bool LibrbdWriteback::may_copy_on_write(const object_t& oid, uint64_t read_off, uint64_t read_len, snapid_t snapid) + { + m_ictx->snap_lock.Lock(); + librados::snap_t snap_id = m_ictx->snap_id; + m_ictx->parent_lock.Lock(); + uint64_t overlap = 0; + m_ictx->get_parent_overlap(snap_id, &overlap); + m_ictx->parent_lock.Unlock(); + m_ictx->snap_lock.Unlock(); + + uint64_t object_no = oid_to_object_no(oid.name, m_ictx->object_prefix); + + // reverse map this object extent onto the parent + vector > objectx; + Striper::extent_to_file(m_ictx->cct, &m_ictx->layout, + object_no, 0, m_ictx->layout.fl_object_size, + objectx); + uint64_t object_overlap = m_ictx->prune_parent_extents(objectx, overlap); + bool may = object_overlap > 0; + ldout(m_ictx->cct, 10) << "may_copy_on_write " << oid << " " << read_off << "~" << read_len << " = " << may << dendl; + return may; + } + tid_t LibrbdWriteback::write(const object_t& oid, const object_locator_t& oloc, uint64_t off, uint64_t len, diff --git a/src/librbd/LibrbdWriteback.h b/src/librbd/LibrbdWriteback.h index b7bb8a9e588..b054dbc5950 100644 --- a/src/librbd/LibrbdWriteback.h +++ b/src/librbd/LibrbdWriteback.h @@ -26,6 +26,9 @@ namespace librbd { bufferlist *pbl, uint64_t trunc_size, __u32 trunc_seq, Context *onfinish); + // Determine whether a read to this extent could be affected by a write-triggered copy-on-write + virtual bool may_copy_on_write(const object_t& oid, uint64_t read_off, uint64_t read_len, snapid_t snapid); + // Note that oloc, trunc_size, and trunc_seq are ignored virtual tid_t write(const object_t& oid, const object_locator_t& oloc, uint64_t off, uint64_t len, const SnapContext& snapc, diff --git a/src/osdc/WritebackHandler.h b/src/osdc/WritebackHandler.h index 8a00927063b..a9a035ca52f 100644 --- a/src/osdc/WritebackHandler.h +++ b/src/osdc/WritebackHandler.h @@ -16,6 +16,18 @@ class WritebackHandler { uint64_t off, uint64_t len, snapid_t snapid, bufferlist *pbl, uint64_t trunc_size, __u32 trunc_seq, Context *onfinish) = 0; + /** + * check if a given extent read result may change due to a write + * + * Check if the content we see at the given read offset may change due to a write to + * this object. + * + * @param oid object + * @param read_off read offset + * @param read_len read length + * @param snapid read snapid + */ + virtual bool may_copy_on_write(const object_t& oid, uint64_t read_off, uint64_t read_len, snapid_t snapid) = 0; virtual tid_t write(const object_t& oid, const object_locator_t& oloc, uint64_t off, uint64_t len, const SnapContext& snapc, const bufferlist &bl, utime_t mtime, uint64_t trunc_size,