From: Jason Dillaman Date: Tue, 15 May 2018 19:55:04 +0000 (-0400) Subject: librbd: journal replay should no-op out-of-bounds IO X-Git-Tag: v14.0.0~95^2~13 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=9a1fcef5edbfdfc77293c4b60c9e038db49abf1f;p=ceph.git librbd: journal replay should no-op out-of-bounds IO Signed-off-by: Jason Dillaman --- diff --git a/src/librbd/journal/Replay.cc b/src/librbd/journal/Replay.cc index 2f33ab5e915..bd4942ad2f6 100644 --- a/src/librbd/journal/Replay.cc +++ b/src/librbd/journal/Replay.cc @@ -350,9 +350,12 @@ void Replay::handle_event(const journal::AioDiscardEvent &event, return; } - io::ImageRequest::aio_discard(&m_image_ctx, aio_comp, - {{event.offset, event.length}}, - event.skip_partial_discard, {}); + if (!clipped_io(event.offset, aio_comp)) { + io::ImageRequest::aio_discard(&m_image_ctx, aio_comp, + {{event.offset, event.length}}, + event.skip_partial_discard, {}); + } + if (flush_required) { m_lock.Lock(); auto flush_comp = create_aio_flush_completion(nullptr); @@ -381,9 +384,12 @@ void Replay::handle_event(const journal::AioWriteEvent &event, return; } - io::ImageRequest::aio_write(&m_image_ctx, aio_comp, - {{event.offset, event.length}}, - std::move(data), 0, {}); + if (!clipped_io(event.offset, aio_comp)) { + io::ImageRequest::aio_write(&m_image_ctx, aio_comp, + {{event.offset, event.length}}, + std::move(data), 0, {}); + } + if (flush_required) { m_lock.Lock(); auto flush_comp = create_aio_flush_completion(nullptr); @@ -431,9 +437,12 @@ void Replay::handle_event(const journal::AioWriteSameEvent &event, return; } - io::ImageRequest::aio_writesame(&m_image_ctx, aio_comp, - {{event.offset, event.length}}, - std::move(data), 0, {}); + if (!clipped_io(event.offset, aio_comp)) { + io::ImageRequest::aio_writesame(&m_image_ctx, aio_comp, + {{event.offset, event.length}}, + std::move(data), 0, {}); + } + if (flush_required) { m_lock.Lock(); auto flush_comp = create_aio_flush_completion(nullptr); @@ -459,11 +468,15 @@ void Replay::handle_event(const journal::AioWriteSameEvent &event, io::AIO_TYPE_COMPARE_AND_WRITE, &flush_required, {-EILSEQ}); - io::ImageRequest::aio_compare_and_write(&m_image_ctx, aio_comp, - {{event.offset, event.length}}, - std::move(cmp_data), - std::move(write_data), - nullptr, 0, {}); + + if (!clipped_io(event.offset, aio_comp)) { + io::ImageRequest::aio_compare_and_write(&m_image_ctx, aio_comp, + {{event.offset, event.length}}, + std::move(cmp_data), + std::move(write_data), + nullptr, 0, {}); + } + if (flush_required) { m_lock.Lock(); auto flush_comp = create_aio_flush_completion(nullptr); @@ -1126,6 +1139,29 @@ io::AioCompletion *Replay::create_aio_flush_completion(Context *on_safe) { return aio_comp; } +template +bool Replay::clipped_io(uint64_t image_offset, io::AioCompletion *aio_comp) { + CephContext *cct = m_image_ctx.cct; + + m_image_ctx.snap_lock.get_read(); + size_t image_size = m_image_ctx.size; + m_image_ctx.snap_lock.put_read(); + + if (image_offset >= image_size) { + // rbd-mirror image sync might race an IO event w/ associated resize between + // the point the peer is registered and the sync point is created, so no-op + // IO events beyond the current image extents since under normal conditions + // it wouldn't have been recorded in the journal + ldout(cct, 5) << ": no-op IO event beyond image size" << dendl; + aio_comp->get(); + aio_comp->unblock(); + aio_comp->put(); + return true; + } + + return false; +} + } // namespace journal } // namespace librbd diff --git a/src/librbd/journal/Replay.h b/src/librbd/journal/Replay.h index 4a4260cb9f0..3851ab49d2c 100644 --- a/src/librbd/journal/Replay.h +++ b/src/librbd/journal/Replay.h @@ -193,6 +193,8 @@ private: io::AioCompletion *create_aio_flush_completion(Context *on_safe); void handle_aio_completion(io::AioCompletion *aio_comp); + bool clipped_io(uint64_t image_offset, io::AioCompletion *aio_comp); + }; } // namespace journal