diff --git a/src/librbd/AioRequest.cc b/src/librbd/AioRequest.cc index 3bbbab9ec6e..ea1df532d1e 100644 --- a/src/librbd/AioRequest.cc +++ b/src/librbd/AioRequest.cc @@ -24,21 +24,21 @@ namespace librbd { - AioRequest::AioRequest() : - m_ictx(NULL), - m_object_no(0), m_object_off(0), m_object_len(0), - m_snap_id(CEPH_NOSNAP), m_completion(NULL), m_parent_completion(NULL), - m_hide_enoent(false) {} AioRequest::AioRequest(ImageCtx *ictx, const std::string &oid, uint64_t objectno, uint64_t off, uint64_t len, - const ::SnapContext &snapc, librados::snap_t snap_id, + librados::snap_t snap_id, Context *completion, - bool hide_enoent) : - m_ictx(ictx), m_oid(oid), m_object_no(objectno), - m_object_off(off), m_object_len(len), m_snap_id(snap_id), - m_completion(completion), m_parent_completion(NULL), - m_hide_enoent(hide_enoent) { - m_snaps.insert(m_snaps.end(), snapc.snaps.begin(), snapc.snaps.end()); + bool hide_enoent) + : m_ictx(ictx), m_oid(oid), m_object_no(objectno), m_object_off(off), + m_object_len(len), m_snap_id(snap_id), m_completion(completion), + m_parent_completion(NULL), m_hide_enoent(hide_enoent) { + + Striper::extent_to_file(m_ictx->cct, &m_ictx->layout, m_object_no, + 0, m_ictx->layout.fl_object_size, m_parent_extents); + + RWLock::RLocker snap_locker(m_ictx->snap_lock); + RWLock::RLocker parent_locker(m_ictx->parent_lock); + compute_parent_extents(); } AioRequest::~AioRequest() { @@ -60,7 +60,34 @@ namespace librbd { } } - void AioRequest::read_from_parent(vector >& image_extents, + bool AioRequest::compute_parent_extents() { + assert(m_ictx->snap_lock.is_locked()); + assert(m_ictx->parent_lock.is_locked()); + + uint64_t parent_overlap; + int r = m_ictx->get_parent_overlap(m_snap_id, &parent_overlap); + if (r < 0) { + // NOTE: it's possible for a snapshot to be deleted while we are + // still reading from it + lderr(m_ictx->cct) << this << " compute_parent_extents: failed to " + << "retrieve parent overlap: " << cpp_strerror(r) + << dendl; + m_parent_extents.clear(); + return false; + } + + uint64_t object_overlap = + m_ictx->prune_parent_extents(m_parent_extents, parent_overlap); + if (object_overlap > 0) { + ldout(m_ictx->cct, 20) << this << " compute_parent_extents: " + << "overlap " << parent_overlap << " " + << "extents " << m_parent_extents << dendl; + return true; + } + return false; + } + + void AioRequest::read_from_parent(const vector >& parent_extents, bool block_completion) { assert(!m_parent_completion); @@ -74,9 +101,9 @@ namespace librbd { ldout(m_ictx->cct, 20) << "read_from_parent this = " << this << " parent completion " << m_parent_completion - << " extents " << image_extents + << " extents " << parent_extents << dendl; - int r = aio_read(m_ictx->parent, image_extents, NULL, &m_read_data, + int r = aio_read(m_ictx->parent, parent_extents, NULL, &m_read_data, m_parent_completion, 0); if (r < 0) { lderr(m_ictx->cct) << "read_from_parent " << this @@ -98,32 +125,21 @@ namespace librbd { AioRead::AioRead(ImageCtx *ictx, const std::string &oid, uint64_t objectno, uint64_t offset, uint64_t len, vector >& be, - const ::SnapContext &snapc, librados::snap_t snap_id, bool sparse, Context *completion, int op_flags) - : AioRequest(ictx, oid, objectno, offset, len, snapc, snap_id, completion, - false), - m_buffer_extents(be), m_tried_parent(false), - m_sparse(sparse), m_op_flags(op_flags), m_state(LIBRBD_AIO_READ_FLAT) { - RWLock::RLocker l(m_ictx->snap_lock); - RWLock::RLocker l2(m_ictx->parent_lock); - - Striper::extent_to_file(m_ictx->cct, &m_ictx->layout, - m_object_no, 0, m_ictx->layout.fl_object_size, - m_image_extents); + : AioRequest(ictx, oid, objectno, offset, len, snap_id, completion, false), + m_buffer_extents(be), m_tried_parent(false), m_sparse(sparse), + m_op_flags(op_flags), m_state(LIBRBD_AIO_READ_FLAT) { guard_read(); } void AioRead::guard_read() { - assert(m_ictx->snap_lock.is_locked()); + RWLock::RLocker snap_locker(m_ictx->snap_lock); + RWLock::RLocker parent_locker(m_ictx->parent_lock); - uint64_t image_overlap = 0; - m_ictx->get_parent_overlap(m_snap_id, &image_overlap); - uint64_t object_overlap = - m_ictx->prune_parent_extents(m_image_extents, image_overlap); - if (object_overlap) { + if (has_parent()) { ldout(m_ictx->cct, 20) << __func__ << " guarding read" << dendl; m_state = LIBRBD_AIO_READ_GUARD; } @@ -131,7 +147,8 @@ namespace librbd { bool AioRead::should_complete(int r) { - ldout(m_ictx->cct, 20) << "should_complete " << this << " " << m_oid << " " << m_object_off << "~" << m_object_len + ldout(m_ictx->cct, 20) << "should_complete " << this << " " << m_oid << " " + << m_object_off << "~" << m_object_len << " r = " << r << dendl; bool finished = true; @@ -154,25 +171,25 @@ namespace librbd { } // calculate reverse mapping onto the image - vector > image_extents; - Striper::extent_to_file(m_ictx->cct, &m_ictx->layout, - m_object_no, m_object_off, m_object_len, - image_extents); + vector > parent_extents; + Striper::extent_to_file(m_ictx->cct, &m_ictx->layout, m_object_no, + m_object_off, m_object_len, parent_extents); - uint64_t image_overlap = 0; - r = m_ictx->get_parent_overlap(m_snap_id, &image_overlap); - if (r < 0) { - assert(0 == "FIXME"); + uint64_t parent_overlap = 0; + uint64_t object_overlap = 0; + r = m_ictx->get_parent_overlap(m_snap_id, &parent_overlap); + if (r == 0) { + object_overlap = m_ictx->prune_parent_extents(parent_extents, + parent_overlap); } - uint64_t object_overlap = m_ictx->prune_parent_extents(image_extents, - image_overlap); - if (object_overlap) { + + if (object_overlap > 0) { m_tried_parent = true; if (is_copy_on_read(m_ictx, m_snap_id)) { m_state = LIBRBD_AIO_READ_COPYUP; } - read_from_parent(image_extents, true); + read_from_parent(parent_extents, true); finished = false; } } @@ -187,7 +204,8 @@ namespace librbd { } break; case LIBRBD_AIO_READ_COPYUP: - ldout(m_ictx->cct, 20) << "should_complete " << this << " READ_COPYUP" << dendl; + ldout(m_ictx->cct, 20) << "should_complete " << this << " READ_COPYUP" + << dendl; // This is the extra step for copy-on-read: kick off an asynchronous copyup. // It is different from copy-on-write as asynchronous copyup will finish // by itself so state won't go back to LIBRBD_AIO_READ_GUARD. @@ -201,25 +219,13 @@ namespace librbd { map::iterator it = m_ictx->copyup_list.find(m_object_no); if (it == m_ictx->copyup_list.end()) { - RWLock::RLocker l(m_ictx->snap_lock); - RWLock::RLocker l2(m_ictx->parent_lock); - if (m_ictx->parent == NULL) { - ldout(m_ictx->cct, 20) << "parent is gone; do nothing" << dendl; - break; - } - - // If parent still exists, overlap might also have changed. - uint64_t parent_overlap; - r = m_ictx->get_parent_overlap(CEPH_NOSNAP, &parent_overlap); - assert(r == 0); - - uint64_t newlen = m_ictx->prune_parent_extents( - m_image_extents, parent_overlap); - if (newlen != 0) { + RWLock::RLocker snap_locker(m_ictx->snap_lock); + RWLock::RLocker parent_locker(m_ictx->parent_lock); + if (compute_parent_extents()) { // create and kick off a CopyupRequest CopyupRequest *new_req = new CopyupRequest(m_ictx, m_oid, m_object_no, - m_image_extents); + m_parent_extents); m_ictx->copyup_list[m_object_no] = new_req; new_req->queue_send(); } @@ -227,7 +233,8 @@ namespace librbd { } break; case LIBRBD_AIO_READ_FLAT: - ldout(m_ictx->cct, 20) << "should_complete " << this << " READ_FLAT" << dendl; + ldout(m_ictx->cct, 20) << "should_complete " << this << " READ_FLAT" + << dendl; // The read content should be deposit in m_read_data break; default: @@ -239,7 +246,8 @@ namespace librbd { } int AioRead::send() { - ldout(m_ictx->cct, 20) << "send " << this << " " << m_oid << " " << m_object_off << "~" << m_object_len << dendl; + ldout(m_ictx->cct, 20) << "send " << this << " " << m_oid << " " + << m_object_off << "~" << m_object_len << dendl; // send read request to parent if the object doesn't exist locally if (!m_ictx->object_map.object_may_exist(m_object_no)) { @@ -267,24 +275,16 @@ namespace librbd { /** write **/ - AbstractWrite::AbstractWrite() - : m_state(LIBRBD_AIO_WRITE_FLAT), - m_parent_overlap(0), - m_snap_seq(0) {} AbstractWrite::AbstractWrite(ImageCtx *ictx, const std::string &oid, - uint64_t object_no, uint64_t object_off, uint64_t len, - vector >& objectx, - uint64_t object_overlap, - const ::SnapContext &snapc, librados::snap_t snap_id, - Context *completion, - bool hide_enoent) - : AioRequest(ictx, oid, object_no, object_off, len, snapc, snap_id, - completion, hide_enoent), + uint64_t object_no, uint64_t object_off, + uint64_t len, const ::SnapContext &snapc, + Context *completion, bool hide_enoent) + : AioRequest(ictx, oid, object_no, object_off, len, CEPH_NOSNAP, completion, + hide_enoent), m_state(LIBRBD_AIO_WRITE_FLAT), m_snap_seq(snapc.seq.val), m_entire_object(NULL) { - m_object_image_extents = objectx; - m_parent_overlap = object_overlap; + m_snaps.insert(m_snaps.end(), snapc.snaps.begin(), snapc.snaps.end()); } void AbstractWrite::guard_write() @@ -298,7 +298,8 @@ namespace librbd { bool AbstractWrite::should_complete(int r) { - ldout(m_ictx->cct, 20) << "write " << this << " " << m_oid << " " << m_object_off << "~" << m_object_len + ldout(m_ictx->cct, 20) << "write " << this << " " << m_oid << " " + << m_object_off << "~" << m_object_len << " should_complete: r = " << r << dendl; map::iterator it; @@ -326,48 +327,18 @@ namespace librbd { RWLock::RLocker l(m_ictx->snap_lock); RWLock::RLocker l2(m_ictx->parent_lock); - /* - * Parent may have disappeared; if so, recover by using - * send_copyup() to send the original write req (the copyup - * operation itself will be a no-op, since someone must have - * populated the child object while we weren't looking). - * Move to WRITE_FLAT state as we'll be done with the - * operation once the null copyup completes. - */ - - if (m_ictx->parent == NULL) { - ldout(m_ictx->cct, 20) << "parent is gone; do null copyup " << dendl; - m_state = LIBRBD_AIO_WRITE_FLAT; - send_copyup(); - finished = false; - break; - } - // If parent still exists, overlap might also have changed. - uint64_t parent_overlap; - r = m_ictx->get_parent_overlap(CEPH_NOSNAP, &parent_overlap); - assert(r == 0); - - uint64_t newlen = m_ictx->prune_parent_extents( - m_object_image_extents, parent_overlap); - - // copyup the entire object up to the overlap point, if any - if (newlen != 0) { - ldout(m_ictx->cct, 20) << "should_complete(" << this << ") overlap " - << parent_overlap << " newlen " - << newlen << " image_extents" - << m_object_image_extents << dendl; - + if (compute_parent_extents()) { m_state = LIBRBD_AIO_WRITE_COPYUP; - if (is_copy_on_read(m_ictx, m_snap_id)) { + if (is_copy_on_read(m_ictx, CEPH_NOSNAP)) { m_ictx->copyup_list_lock.Lock(); it = m_ictx->copyup_list.find(m_object_no); if (it == m_ictx->copyup_list.end()) { - // If it is not in the list, create a CopyupRequest and wait for it. + // If it is not in the list, create a CopyupRequest and wait CopyupRequest *new_req = new CopyupRequest(m_ictx, m_oid, m_object_no, - m_object_image_extents); + m_parent_extents); // make sure to wait on this CopyupRequest new_req->append_request(this); m_ictx->copyup_list[m_object_no] = new_req; @@ -381,12 +352,19 @@ namespace librbd { m_ictx->copyup_list_lock.Unlock(); } } else { - read_from_parent(m_object_image_extents, false); + read_from_parent(m_parent_extents, false); } } else { + /* + * Parent may have disappeared; if so, recover by using + * send_copyup() to send the original write req (the copyup + * operation itself will be a no-op, since someone must have + * populated the child object while we weren't looking). + * Move to WRITE_FLAT state as we'll be done with the + * operation once the null copyup completes. + */ ldout(m_ictx->cct, 20) << "should_complete(" << this << "): parent overlap now 0" << dendl; - m_object_image_extents.clear(); m_state = LIBRBD_AIO_WRITE_FLAT; send_copyup(); } @@ -430,7 +408,7 @@ namespace librbd { case LIBRBD_AIO_WRITE_ERROR: assert(r < 0); lderr(m_ictx->cct) << "WRITE_ERROR: " << cpp_strerror(r) - << dendl; + << dendl; break; default: @@ -536,7 +514,8 @@ namespace librbd { } void AbstractWrite::send_copyup() { - ldout(m_ictx->cct, 20) << "send_copyup " << this << " " << m_oid << " " << m_object_off << "~" << m_object_len << dendl; + ldout(m_ictx->cct, 20) << "send_copyup " << this << " " << m_oid << " " + << m_object_off << "~" << m_object_len << dendl; librados::ObjectWriteOperation op; if (!m_read_data.is_zero()) { op.exec("rbd", "copyup", m_read_data); diff --git a/src/librbd/AioRequest.h b/src/librbd/AioRequest.h index eda9a84a9c0..29bd880d7b7 100644 --- a/src/librbd/AioRequest.h +++ b/src/librbd/AioRequest.h @@ -27,10 +27,9 @@ namespace librbd { class AioRequest { public: - AioRequest(); AioRequest(ImageCtx *ictx, const std::string &oid, uint64_t objectno, uint64_t off, uint64_t len, - const ::SnapContext &snapc, librados::snap_t snap_id, + librados::snap_t snap_id, Context *completion, bool hide_enoent); virtual ~AioRequest(); @@ -39,8 +38,13 @@ namespace librbd { virtual bool should_complete(int r) = 0; virtual int send() = 0; + bool has_parent() const { + return !m_parent_extents.empty(); + } + protected: - void read_from_parent(vector >& image_extents, + bool compute_parent_extents(); + void read_from_parent(const vector >& image_extents, bool block_completion); ImageCtx *m_ictx; @@ -48,17 +52,17 @@ namespace librbd { uint64_t m_object_no, m_object_off, m_object_len; librados::snap_t m_snap_id; Context *m_completion; + std::vector > m_parent_extents; AioCompletion *m_parent_completion; ceph::bufferlist m_read_data; bool m_hide_enoent; - std::vector m_snaps; }; class AioRead : public AioRequest { public: AioRead(ImageCtx *ictx, const std::string &oid, uint64_t objectno, uint64_t offset, uint64_t len, - vector >& be, const ::SnapContext &snapc, + vector >& be, librados::snap_t snap_id, bool sparse, Context *completion, int op_flags); virtual ~AioRead() {} @@ -79,7 +83,6 @@ namespace librbd { bool m_tried_parent; bool m_sparse; int m_op_flags; - vector > m_image_extents; /** * Reads go through the following state machine to deal with @@ -108,22 +111,14 @@ namespace librbd { class AbstractWrite : public AioRequest { public: - AbstractWrite(); - AbstractWrite(ImageCtx *ictx, const std::string &oid, - uint64_t object_no, uint64_t object_off, uint64_t len, - vector >& objectx, uint64_t object_overlap, - const ::SnapContext &snapc, - librados::snap_t snap_id, - Context *completion, - bool hide_enoent); + AbstractWrite(ImageCtx *ictx, const std::string &oid, uint64_t object_no, + uint64_t object_off, uint64_t len, const ::SnapContext &snapc, + Context *completion, bool hide_enoent); virtual ~AbstractWrite() {} + virtual bool should_complete(int r); virtual int send(); - bool has_parent() const { - return !m_object_image_extents.empty(); - } - private: /** * Writes go through the following state machine to deal with @@ -134,7 +129,7 @@ namespace librbd { * . | * . \---> LIBRBD_AIO_WRITE_PRE * . | | - * . . . . . . | . . . . | . . . . . . . . . . . + * . . . . . . | . . . . | . . . . . . . . . . . * . | -or- | . * . | | v * . | \----------------> LIBRBD_AIO_WRITE_FLAT . . . @@ -150,7 +145,7 @@ namespace librbd { * . LIBRBD_AIO_WRITE_POST . * . | . * . v . - * . . . . . . . . . . . . . . > < . . . . . . . . . . . . . . + * . . . . . . . . . . . . . . > < . . . . . . . . . . . . . . * * The _PRE_REMOVE/_POST_REMOVE states are skipped if the object map * is disabled. The write starts in _WRITE_GUARD or _FLAT depending on @@ -167,10 +162,9 @@ namespace librbd { protected: write_state_d m_state; - vector > m_object_image_extents; - uint64_t m_parent_overlap; librados::ObjectWriteOperation m_write; uint64_t m_snap_seq; + std::vector m_snaps; ceph::bufferlist *m_entire_object; virtual void add_write_ops(librados::ObjectWriteOperation *wr) = 0; @@ -189,16 +183,10 @@ namespace librbd { class AioWrite : public AbstractWrite { public: - AioWrite(ImageCtx *ictx, const std::string &oid, - uint64_t object_no, uint64_t object_off, - vector >& objectx, uint64_t object_overlap, - const ceph::bufferlist &data, const ::SnapContext &snapc, - librados::snap_t snap_id, - Context *completion) - : AbstractWrite(ictx, oid, - object_no, object_off, data.length(), - objectx, object_overlap, - snapc, snap_id, + AioWrite(ImageCtx *ictx, const std::string &oid, uint64_t object_no, + uint64_t object_off, const ceph::bufferlist &data, + const ::SnapContext &snapc, Context *completion) + : AbstractWrite(ictx, oid, object_no, object_off, data.length(), snapc, completion, false), m_write_data(data), m_op_flags(0) { } @@ -220,16 +208,9 @@ namespace librbd { class AioRemove : public AbstractWrite { public: - AioRemove(ImageCtx *ictx, const std::string &oid, - uint64_t object_no, - vector >& objectx, uint64_t object_overlap, - const ::SnapContext &snapc, librados::snap_t snap_id, - Context *completion) - : AbstractWrite(ictx, oid, - object_no, 0, 0, - objectx, object_overlap, - snapc, snap_id, completion, - true), + AioRemove(ImageCtx *ictx, const std::string &oid, uint64_t object_no, + const ::SnapContext &snapc, Context *completion) + : AbstractWrite(ictx, oid, object_no, 0, 0, snapc, completion, true), m_object_state(OBJECT_NONEXISTENT) { } virtual ~AioRemove() {} @@ -269,16 +250,11 @@ namespace librbd { class AioTruncate : public AbstractWrite { public: - AioTruncate(ImageCtx *ictx, const std::string &oid, - uint64_t object_no, uint64_t object_off, - vector >& objectx, uint64_t object_overlap, - const ::SnapContext &snapc, librados::snap_t snap_id, - Context *completion) - : AbstractWrite(ictx, oid, - object_no, object_off, 0, - objectx, object_overlap, - snapc, snap_id, completion, - true) { + AioTruncate(ImageCtx *ictx, const std::string &oid, uint64_t object_no, + uint64_t object_off, const ::SnapContext &snapc, + Context *completion) + : AbstractWrite(ictx, oid, object_no, object_off, 0, snapc, completion, + true) { } virtual ~AioTruncate() {} @@ -294,16 +270,11 @@ namespace librbd { class AioZero : public AbstractWrite { public: - AioZero(ImageCtx *ictx, const std::string &oid, - uint64_t object_no, uint64_t object_off, uint64_t object_len, - vector >& objectx, uint64_t object_overlap, - const ::SnapContext &snapc, librados::snap_t snap_id, - Context *completion) - : AbstractWrite(ictx, oid, - object_no, object_off, object_len, - objectx, object_overlap, - snapc, snap_id, completion, - true) { + AioZero(ImageCtx *ictx, const std::string &oid, uint64_t object_no, + uint64_t object_off, uint64_t object_len, + const ::SnapContext &snapc, Context *completion) + : AbstractWrite(ictx, oid, object_no, object_off, object_len, snapc, + completion, true) { } virtual ~AioZero() {} diff --git a/src/librbd/AsyncFlattenRequest.cc b/src/librbd/AsyncFlattenRequest.cc index 87c2655641f..f6a3e154f4d 100644 --- a/src/librbd/AsyncFlattenRequest.cc +++ b/src/librbd/AsyncFlattenRequest.cc @@ -38,39 +38,17 @@ public: return -ERESTART; } - RWLock::RLocker l2(m_image_ctx.snap_lock); - uint64_t overlap; - { - RWLock::RLocker l3(m_image_ctx.parent_lock); + bufferlist bl; + string oid = m_image_ctx.get_object_name(m_object_no); + AioWrite *req = new AioWrite(&m_image_ctx, oid, m_object_no, 0, bl, m_snapc, + this); + if (!req->has_parent()) { // stop early if the parent went away - it just means - // another flatten finished first, so this one is useless. - if (!m_image_ctx.parent) { - return 1; - } - - // resize might have occurred while flatten is running - uint64_t parent_overlap; - int r = m_image_ctx.get_parent_overlap(CEPH_NOSNAP, &parent_overlap); - assert(r == 0); - overlap = min(m_image_ctx.size, parent_overlap); - } - - // map child object onto the parent - vector > objectx; - Striper::extent_to_file(cct, &m_image_ctx.layout, m_object_no, - 0, m_object_size, objectx); - uint64_t object_overlap = m_image_ctx.prune_parent_extents(objectx, overlap); - assert(object_overlap <= m_object_size); - if (object_overlap == 0) { - // resize shrunk image while flattening + // another flatten finished first or the image was resized + delete req; return 1; } - bufferlist bl; - string oid = m_image_ctx.get_object_name(m_object_no); - AioWrite *req = new AioWrite(&m_image_ctx, oid, m_object_no, 0, objectx, - object_overlap, bl, m_snapc, CEPH_NOSNAP, - this); int r = req->send(); assert(r == 0); return 0; diff --git a/src/librbd/AsyncTrimRequest.cc b/src/librbd/AsyncTrimRequest.cc index d3dcd811873..b474124c85c 100644 --- a/src/librbd/AsyncTrimRequest.cc +++ b/src/librbd/AsyncTrimRequest.cc @@ -251,14 +251,9 @@ bool AsyncTrimRequest::send_clean_boundary() { lost_exclusive_lock = true; } else { ::SnapContext snapc; - uint64_t parent_overlap; { RWLock::RLocker l2(m_image_ctx.snap_lock); snapc = m_image_ctx.snapc; - - RWLock::RLocker l3(m_image_ctx.parent_lock); - int r = m_image_ctx.get_parent_overlap(CEPH_NOSNAP, &parent_overlap); - assert(r == 0); } // discard the weird boundary, if any @@ -273,21 +268,13 @@ bool AsyncTrimRequest::send_clean_boundary() { ldout(cct, 20) << " ex " << *p << dendl; Context *req_comp = new C_ContextCompletion(*completion); - // reverse map this object extent onto the parent - vector > objectx; - Striper::extent_to_file(cct, &m_image_ctx.layout, p->objectno, 0, - m_image_ctx.layout.fl_object_size, objectx); - uint64_t object_overlap = - m_image_ctx.prune_parent_extents(objectx, parent_overlap); - AbstractWrite *req; if (p->offset == 0) { - req = new AioRemove(&m_image_ctx, p->oid.name, p->objectno, objectx, - object_overlap, snapc, CEPH_NOSNAP, req_comp); + req = new AioRemove(&m_image_ctx, p->oid.name, p->objectno, snapc, + req_comp); } else { - req = new AioTruncate(&m_image_ctx, p->oid.name, p->objectno, p->offset, - objectx, object_overlap, snapc, CEPH_NOSNAP, - req_comp); + req = new AioTruncate(&m_image_ctx, p->oid.name, p->objectno, + p->offset, snapc, req_comp); } int r = req->send(); if (r < 0) { diff --git a/src/librbd/LibrbdWriteback.cc b/src/librbd/LibrbdWriteback.cc index 694f2c739da..cd2e1de2aa8 100644 --- a/src/librbd/LibrbdWriteback.cc +++ b/src/librbd/LibrbdWriteback.cc @@ -157,30 +157,14 @@ namespace librbd { uint64_t trunc_size, __u32 trunc_seq, Context *oncommit) { - m_ictx->snap_lock.get_read(); - librados::snap_t snap_id = m_ictx->snap_id; - m_ictx->parent_lock.get_read(); - uint64_t overlap = 0; - m_ictx->get_parent_overlap(snap_id, &overlap); - m_ictx->parent_lock.put_read(); - m_ictx->snap_lock.put_read(); - 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); write_result_d *result = new write_result_d(oid.name, oncommit); m_writes[oid.name].push(result); ldout(m_ictx->cct, 20) << "write will wait for result " << result << dendl; C_OrderedWrite *req_comp = new C_OrderedWrite(m_ictx->cct, result, this); - AioWrite *req = new AioWrite(m_ictx, oid.name, - object_no, off, objectx, object_overlap, - bl, snapc, snap_id, - req_comp); + AioWrite *req = new AioWrite(m_ictx, oid.name, object_no, off, bl, snapc, + req_comp); req->send(); return ++m_tid; } diff --git a/src/librbd/internal.cc b/src/librbd/internal.cc index 64879a034fb..48c423867d2 100644 --- a/src/librbd/internal.cc +++ b/src/librbd/internal.cc @@ -3447,29 +3447,21 @@ reprotect_and_return_err: RWLock::RLocker md_locker(ictx->md_lock); uint64_t clip_len = len; - snapid_t snap_id; ::SnapContext snapc; - uint64_t overlap = 0; { // prevent image size from changing between computing clip and recording // pending async operation RWLock::RLocker snap_locker(ictx->snap_lock); + if (ictx->snap_id != CEPH_NOSNAP || ictx->read_only) { + return -EROFS; + } + r = clip_io(ictx, off, &clip_len); if (r < 0) { return r; } - snap_id = ictx->snap_id; snapc = ictx->snapc; - ictx->parent_lock.get_read(); - ictx->get_parent_overlap(ictx->snap_id, &overlap); - ictx->parent_lock.put_read(); - - if (snap_id != CEPH_NOSNAP || ictx->read_only) { - return -EROFS; - } - - ldout(cct, 20) << " parent overlap " << overlap << dendl; c->get(); c->init_time(ictx, AIO_TYPE_WRITE); @@ -3505,16 +3497,8 @@ reprotect_and_return_err: c->add_request(); ictx->write_to_cache(p->oid, bl, p->length, p->offset, req_comp, op_flags); } else { - // reverse map this object extent onto the parent - vector > objectx; - Striper::extent_to_file(ictx->cct, &ictx->layout, - p->objectno, 0, ictx->layout.fl_object_size, - objectx); - uint64_t object_overlap = ictx->prune_parent_extents(objectx, overlap); - AioWrite *req = new AioWrite(ictx, p->oid.name, p->objectno, p->offset, - objectx, object_overlap, - bl, snapc, snap_id, req_comp); + bl, snapc, req_comp); c->add_request(); req->set_op_flags(op_flags); @@ -3603,28 +3587,22 @@ reprotect_and_return_err: RWLock::RLocker md_locker(ictx->md_lock); uint64_t clip_len = len; - snapid_t snap_id; ::SnapContext snapc; - uint64_t overlap; { // prevent image size from changing between computing clip and recording // pending async operation RWLock::RLocker snap_locker(ictx->snap_lock); + if (ictx->snap_id != CEPH_NOSNAP || ictx->read_only) { + return -EROFS; + } + r = clip_io(ictx, off, &clip_len); if (r < 0) { return r; } // TODO: check for snap - snap_id = ictx->snap_id; snapc = ictx->snapc; - ictx->parent_lock.get_read(); - ictx->get_parent_overlap(ictx->snap_id, &overlap); - ictx->parent_lock.put_read(); - - if (snap_id != CEPH_NOSNAP || ictx->read_only) { - return -EROFS; - } c->get(); c->init_time(ictx, AIO_TYPE_DISCARD); @@ -3651,30 +3629,17 @@ reprotect_and_return_err: AbstractWrite *req; c->add_request(); - // reverse map this object extent onto the parent - vector > objectx; - uint64_t object_overlap = 0; - if (off < overlap) { // we might overlap... - Striper::extent_to_file(ictx->cct, &ictx->layout, - p->objectno, 0, ictx->layout.fl_object_size, - objectx); - object_overlap = ictx->prune_parent_extents(objectx, overlap); - } - if (p->offset == 0 && p->length == ictx->layout.fl_object_size) { - req = new AioRemove(ictx, p->oid.name, p->objectno, objectx, object_overlap, - snapc, snap_id, req_comp); + req = new AioRemove(ictx, p->oid.name, p->objectno, snapc, req_comp); } else if (p->offset + p->length == ictx->layout.fl_object_size) { - req = new AioTruncate(ictx, p->oid.name, p->objectno, p->offset, objectx, object_overlap, - snapc, snap_id, req_comp); + req = new AioTruncate(ictx, p->oid.name, p->objectno, p->offset, snapc, + req_comp); } else { if(ictx->cct->_conf->rbd_skip_partial_discard) { continue; - } else { - req = new AioZero(ictx, p->oid.name, p->objectno, p->offset, p->length, - objectx, object_overlap, - snapc, snap_id, req_comp); } + req = new AioZero(ictx, p->oid.name, p->objectno, p->offset, p->length, + snapc, req_comp); } r = req->send(); @@ -3791,7 +3756,6 @@ reprotect_and_return_err: } snap_t snap_id; - ::SnapContext snapc; map > object_extents; uint64_t buffer_ofs = 0; { @@ -3799,7 +3763,6 @@ reprotect_and_return_err: // pending async operation RWLock::RLocker snap_locker(ictx->snap_lock); snap_id = ictx->snap_id; - snapc = ictx->snapc; // map for (vector >::const_iterator p = @@ -3828,16 +3791,18 @@ reprotect_and_return_err: c->read_buf_len = buffer_ofs; c->read_bl = pbl; - for (map >::iterator p = object_extents.begin(); p != object_extents.end(); ++p) { - for (vector::iterator q = p->second.begin(); q != p->second.end(); ++q) { - ldout(ictx->cct, 20) << " oid " << q->oid << " " << q->offset << "~" << q->length - << " from " << q->buffer_extents << dendl; + for (map >::iterator p = object_extents.begin(); + p != object_extents.end(); ++p) { + for (vector::iterator q = p->second.begin(); + q != p->second.end(); ++q) { + ldout(ictx->cct, 20) << " oid " << q->oid << " " << q->offset << "~" + << q->length << " from " << q->buffer_extents + << dendl; C_AioRead *req_comp = new C_AioRead(ictx->cct, c); - AioRead *req = new AioRead(ictx, q->oid.name, - q->objectno, q->offset, q->length, - q->buffer_extents, snapc, - snap_id, true, req_comp, op_flags); + AioRead *req = new AioRead(ictx, q->oid.name, q->objectno, q->offset, + q->length, q->buffer_extents, snap_id, true, + req_comp, op_flags); req_comp->set_req(req); c->add_request();