From: Gui Hecheng Date: Wed, 22 Feb 2017 09:24:33 +0000 (+0800) Subject: librbd: make writesame get all zeros with rbd_skip_partial_discard on X-Git-Tag: v12.0.1~250^2~2 X-Git-Url: http://git.apps.os.sepia.ceph.com/?a=commitdiff_plain;h=6d024c5dae648b4958685a9f0df3e193e2759723;p=ceph-ci.git librbd: make writesame get all zeros with rbd_skip_partial_discard on Now writesame tends to do a discard on all zero buffer, but if rbd_skip_partial_discard is turned on, discard will not do any zeroing work on partial discard, so we read random data while expecting all zeros. To fix it, we introduce the ImageCtx::skip_partial_discard and pass an extra parameter to discard. Writesame will always pass false and other discards will pass the ImageCtx::skip_partial_discard which is set by the rbd_skip_partial_discard option. Signed-off-by: Gui Hecheng --- diff --git a/src/librbd/ImageCtx.cc b/src/librbd/ImageCtx.cc index d16e8c14a87..4d5dd3ae18c 100644 --- a/src/librbd/ImageCtx.cc +++ b/src/librbd/ImageCtx.cc @@ -971,7 +971,8 @@ struct C_InvalidateCache : public Context { "rbd_journal_max_payload_bytes", false)( "rbd_journal_max_concurrent_object_sets", false)( "rbd_mirroring_resync_after_disconnect", false)( - "rbd_mirroring_replay_delay", false); + "rbd_mirroring_replay_delay", false)( + "rbd_skip_partial_discard", false); md_config_t local_config_t; std::map res; @@ -1030,6 +1031,7 @@ struct C_InvalidateCache : public Context { ASSIGN_OPTION(journal_max_concurrent_object_sets); ASSIGN_OPTION(mirroring_resync_after_disconnect); ASSIGN_OPTION(mirroring_replay_delay); + ASSIGN_OPTION(skip_partial_discard); } ExclusiveLock *ImageCtx::create_exclusive_lock() { diff --git a/src/librbd/ImageCtx.h b/src/librbd/ImageCtx.h index 0f089c16831..76f38efb929 100644 --- a/src/librbd/ImageCtx.h +++ b/src/librbd/ImageCtx.h @@ -193,6 +193,7 @@ namespace librbd { int journal_max_concurrent_object_sets; bool mirroring_resync_after_disconnect; int mirroring_replay_delay; + bool skip_partial_discard; LibrbdAdminSocketHook *asok_hook; diff --git a/src/librbd/cache/ImageCache.h b/src/librbd/cache/ImageCache.h index 02a6467aa60..0a5d0263ee3 100644 --- a/src/librbd/cache/ImageCache.h +++ b/src/librbd/cache/ImageCache.h @@ -28,7 +28,7 @@ struct ImageCache { virtual void aio_write(Extents&& image_extents, ceph::bufferlist&& bl, int fadvise_flags, Context *on_finish) = 0; virtual void aio_discard(uint64_t offset, uint64_t length, - Context *on_finish) = 0; + bool skip_partial_discard, Context *on_finish) = 0; virtual void aio_flush(Context *on_finish) = 0; virtual void aio_writesame(uint64_t offset, uint64_t length, ceph::bufferlist&& bl, diff --git a/src/librbd/cache/ImageWriteback.cc b/src/librbd/cache/ImageWriteback.cc index 69b28c3d274..83c3b5bb14b 100644 --- a/src/librbd/cache/ImageWriteback.cc +++ b/src/librbd/cache/ImageWriteback.cc @@ -53,7 +53,7 @@ void ImageWriteback::aio_write(Extents &&image_extents, template void ImageWriteback::aio_discard(uint64_t offset, uint64_t length, - Context *on_finish) { + bool skip_partial_discard, Context *on_finish) { CephContext *cct = m_image_ctx.cct; ldout(cct, 20) << "offset=" << offset << ", " << "length=" << length << ", " @@ -61,7 +61,8 @@ void ImageWriteback::aio_discard(uint64_t offset, uint64_t length, auto aio_comp = io::AioCompletion::create_and_start(on_finish, &m_image_ctx, io::AIO_TYPE_DISCARD); - io::ImageDiscardRequest req(m_image_ctx, aio_comp, offset, length); + io::ImageDiscardRequest req(m_image_ctx, aio_comp, offset, length, + skip_partial_discard); req.set_bypass_image_cache(); req.send(); } diff --git a/src/librbd/cache/ImageWriteback.h b/src/librbd/cache/ImageWriteback.h index 29ea713baa8..1ffc450dfbb 100644 --- a/src/librbd/cache/ImageWriteback.h +++ b/src/librbd/cache/ImageWriteback.h @@ -30,7 +30,8 @@ public: int fadvise_flags, Context *on_finish); void aio_write(Extents &&image_extents, ceph::bufferlist&& bl, int fadvise_flags, Context *on_finish); - void aio_discard(uint64_t offset, uint64_t length, Context *on_finish); + void aio_discard(uint64_t offset, uint64_t length, + bool skip_partial_discard, Context *on_finish); void aio_flush(Context *on_finish); void aio_writesame(uint64_t offset, uint64_t length, ceph::bufferlist&& bl, diff --git a/src/librbd/cache/PassthroughImageCache.cc b/src/librbd/cache/PassthroughImageCache.cc index 62f81aca329..f892387acc8 100644 --- a/src/librbd/cache/PassthroughImageCache.cc +++ b/src/librbd/cache/PassthroughImageCache.cc @@ -45,13 +45,13 @@ void PassthroughImageCache::aio_write(Extents &&image_extents, template void PassthroughImageCache::aio_discard(uint64_t offset, uint64_t length, - Context *on_finish) { + bool skip_partial_discard, Context *on_finish) { CephContext *cct = m_image_ctx.cct; ldout(cct, 20) << "offset=" << offset << ", " << "length=" << length << ", " << "on_finish=" << on_finish << dendl; - m_image_writeback.aio_discard(offset, length, on_finish); + m_image_writeback.aio_discard(offset, length, skip_partial_discard, on_finish); } template diff --git a/src/librbd/cache/PassthroughImageCache.h b/src/librbd/cache/PassthroughImageCache.h index 2abea0efb77..5210e7c619d 100644 --- a/src/librbd/cache/PassthroughImageCache.h +++ b/src/librbd/cache/PassthroughImageCache.h @@ -27,7 +27,7 @@ public: void aio_write(Extents&& image_extents, ceph::bufferlist&& bl, int fadvise_flags, Context *on_finish) override; void aio_discard(uint64_t offset, uint64_t length, - Context *on_finish) override; + bool skip_partial_discard, Context *on_finish); void aio_flush(Context *on_finish) override; virtual void aio_writesame(uint64_t offset, uint64_t length, ceph::bufferlist&& bl, diff --git a/src/librbd/io/ImageRequest.cc b/src/librbd/io/ImageRequest.cc index ee9d9535b2a..b66ad6efa04 100644 --- a/src/librbd/io/ImageRequest.cc +++ b/src/librbd/io/ImageRequest.cc @@ -130,8 +130,9 @@ void ImageRequest::aio_write(I *ictx, AioCompletion *c, template void ImageRequest::aio_discard(I *ictx, AioCompletion *c, - uint64_t off, uint64_t len) { - ImageDiscardRequest req(*ictx, c, off, len); + uint64_t off, uint64_t len, + bool skip_partial_discard) { + ImageDiscardRequest req(*ictx, c, off, len, skip_partial_discard); req.send(); } @@ -505,7 +506,8 @@ uint64_t ImageDiscardRequest::append_journal_event( assert(!this->m_image_extents.empty()); for (auto &extent : this->m_image_extents) { journal::EventEntry event_entry(journal::AioDiscardEvent(extent.first, - extent.second)); + extent.second, + this->m_skip_partial_discard)); tid = image_ctx.journal->append_io_event(std::move(event_entry), requests, extent.first, extent.second, synchronous); @@ -520,7 +522,7 @@ template void ImageDiscardRequest::prune_object_extents(ObjectExtents &object_extents) { I &image_ctx = this->m_image_ctx; CephContext *cct = image_ctx.cct; - if (!cct->_conf->rbd_skip_partial_discard) { + if (!this->m_skip_partial_discard) { return; } @@ -552,7 +554,8 @@ void ImageDiscardRequest::send_image_cache_request() { aio_comp->set_request_count(this->m_image_extents.size()); for (auto &extent : this->m_image_extents) { C_AioRequest *req_comp = new C_AioRequest(aio_comp); - image_ctx.image_cache->aio_discard(extent.first, extent.second, req_comp); + image_ctx.image_cache->aio_discard(extent.first, extent.second, + this->m_skip_partial_discard, req_comp); } } diff --git a/src/librbd/io/ImageRequest.h b/src/librbd/io/ImageRequest.h index 4c8ae76f5bb..aeabd50bfba 100644 --- a/src/librbd/io/ImageRequest.h +++ b/src/librbd/io/ImageRequest.h @@ -35,7 +35,7 @@ public: static void aio_write(ImageCtxT *ictx, AioCompletion *c, Extents &&image_extents, bufferlist &&bl, int op_flags); static void aio_discard(ImageCtxT *ictx, AioCompletion *c, uint64_t off, - uint64_t len); + uint64_t len, bool skip_partial_discard); static void aio_flush(ImageCtxT *ictx, AioCompletion *c); static void aio_writesame(ImageCtxT *ictx, AioCompletion *c, uint64_t off, uint64_t len, bufferlist &&bl, int op_flags); @@ -199,8 +199,9 @@ template class ImageDiscardRequest : public AbstractImageWriteRequest { public: ImageDiscardRequest(ImageCtxT &image_ctx, AioCompletion *aio_comp, - uint64_t off, uint64_t len) - : AbstractImageWriteRequest(image_ctx, aio_comp, {{off, len}}) { + uint64_t off, uint64_t len, bool skip_partial_discard) + : AbstractImageWriteRequest(image_ctx, aio_comp, {{off, len}}), + m_skip_partial_discard(skip_partial_discard) { } protected: @@ -229,6 +230,8 @@ protected: uint64_t append_journal_event(const ObjectRequests &requests, bool synchronous) override; void update_stats(size_t length) override; +private: + bool m_skip_partial_discard; }; template diff --git a/src/librbd/io/ImageRequestWQ.cc b/src/librbd/io/ImageRequestWQ.cc index 1ce121df70c..7b7cbc63e2a 100644 --- a/src/librbd/io/ImageRequestWQ.cc +++ b/src/librbd/io/ImageRequestWQ.cc @@ -69,7 +69,7 @@ ssize_t ImageRequestWQ::write(uint64_t off, uint64_t len, return len; } -int ImageRequestWQ::discard(uint64_t off, uint64_t len) { +int ImageRequestWQ::discard(uint64_t off, uint64_t len, bool skip_partial_discard) { CephContext *cct = m_image_ctx.cct; ldout(cct, 20) << "discard: ictx=" << &m_image_ctx << ", off=" << off << ", " << "len = " << len << dendl; @@ -84,7 +84,7 @@ int ImageRequestWQ::discard(uint64_t off, uint64_t len) { C_SaferCond cond; AioCompletion *c = AioCompletion::create(&cond); - aio_discard(c, off, len, false); + aio_discard(c, off, len, skip_partial_discard, false); r = cond.wait(); if (r < 0) { @@ -187,7 +187,8 @@ void ImageRequestWQ::aio_write(AioCompletion *c, uint64_t off, uint64_t len, } void ImageRequestWQ::aio_discard(AioCompletion *c, uint64_t off, - uint64_t len, bool native_async) { + uint64_t len, bool skip_partial_discard, + bool native_async) { c->init_time(&m_image_ctx, AIO_TYPE_DISCARD); CephContext *cct = m_image_ctx.cct; ldout(cct, 20) << "aio_discard: ictx=" << &m_image_ctx << ", " @@ -204,10 +205,10 @@ void ImageRequestWQ::aio_discard(AioCompletion *c, uint64_t off, RWLock::RLocker owner_locker(m_image_ctx.owner_lock); if (m_image_ctx.non_blocking_aio || writes_blocked()) { - queue(new ImageDiscardRequest<>(m_image_ctx, c, off, len)); + queue(new ImageDiscardRequest<>(m_image_ctx, c, off, len, skip_partial_discard)); } else { c->start_op(); - ImageRequest<>::aio_discard(&m_image_ctx, c, off, len); + ImageRequest<>::aio_discard(&m_image_ctx, c, off, len, skip_partial_discard); finish_in_flight_op(); } } diff --git a/src/librbd/io/ImageRequestWQ.h b/src/librbd/io/ImageRequestWQ.h index 103a4f8c19d..c4c7b9954e4 100644 --- a/src/librbd/io/ImageRequestWQ.h +++ b/src/librbd/io/ImageRequestWQ.h @@ -28,7 +28,7 @@ public: ssize_t read(uint64_t off, uint64_t len, ReadResult &&read_result, int op_flags); ssize_t write(uint64_t off, uint64_t len, bufferlist &&bl, int op_flags); - int discard(uint64_t off, uint64_t len); + int discard(uint64_t off, uint64_t len, bool skip_partial_discard); ssize_t writesame(uint64_t off, uint64_t len, bufferlist &&bl, int op_flags); void aio_read(AioCompletion *c, uint64_t off, uint64_t len, @@ -36,7 +36,7 @@ public: void aio_write(AioCompletion *c, uint64_t off, uint64_t len, bufferlist &&bl, int op_flags, bool native_async=true); void aio_discard(AioCompletion *c, uint64_t off, uint64_t len, - bool native_async=true); + bool skip_partial_discard, bool native_async=true); void aio_flush(AioCompletion *c, bool native_async=true); void aio_writesame(AioCompletion *c, uint64_t off, uint64_t len, bufferlist &&bl, int op_flags, bool native_async=true); diff --git a/src/librbd/journal/Replay.cc b/src/librbd/journal/Replay.cc index ff4dfb0ff09..c3e91081656 100644 --- a/src/librbd/journal/Replay.cc +++ b/src/librbd/journal/Replay.cc @@ -315,7 +315,7 @@ void Replay::handle_event(const journal::AioDiscardEvent &event, io::AIO_TYPE_DISCARD, &flush_required); io::ImageRequest::aio_discard(&m_image_ctx, aio_comp, event.offset, - event.length); + event.length, event.skip_partial_discard); if (flush_required) { m_lock.Lock(); auto flush_comp = create_aio_flush_completion(nullptr); diff --git a/src/librbd/journal/Types.cc b/src/librbd/journal/Types.cc index 2373e54859c..cef0dbfd130 100644 --- a/src/librbd/journal/Types.cc +++ b/src/librbd/journal/Types.cc @@ -71,16 +71,21 @@ private: void AioDiscardEvent::encode(bufferlist& bl) const { ::encode(offset, bl); ::encode(length, bl); + ::encode(skip_partial_discard, bl); } void AioDiscardEvent::decode(__u8 version, bufferlist::iterator& it) { ::decode(offset, it); ::decode(length, it); + if (version >= 5) { + ::decode(skip_partial_discard, it); + } } void AioDiscardEvent::dump(Formatter *f) const { f->dump_unsigned("offset", offset); f->dump_unsigned("length", length); + f->dump_bool("skip_partial_discard", skip_partial_discard); } uint32_t AioWriteEvent::get_fixed_size() { @@ -335,7 +340,7 @@ EventType EventEntry::get_event_type() const { } void EventEntry::encode(bufferlist& bl) const { - ENCODE_START(4, 1, bl); + ENCODE_START(5, 1, bl); boost::apply_visitor(EncodeVisitor(bl), event); ENCODE_FINISH(bl); encode_metadata(bl); @@ -434,7 +439,7 @@ void EventEntry::decode_metadata(bufferlist::iterator& it) { void EventEntry::generate_test_instances(std::list &o) { o.push_back(new EventEntry(AioDiscardEvent())); - o.push_back(new EventEntry(AioDiscardEvent(123, 345), utime_t(1, 1))); + o.push_back(new EventEntry(AioDiscardEvent(123, 345, false), utime_t(1, 1))); bufferlist bl; bl.append(std::string(32, '1')); diff --git a/src/librbd/journal/Types.h b/src/librbd/journal/Types.h index 71505b814f9..e80d82586f4 100644 --- a/src/librbd/journal/Types.h +++ b/src/librbd/journal/Types.h @@ -50,11 +50,12 @@ struct AioDiscardEvent { uint64_t offset; uint64_t length; + bool skip_partial_discard; - AioDiscardEvent() : offset(0), length(0) { + AioDiscardEvent() : offset(0), length(0), skip_partial_discard(false) { } - AioDiscardEvent(uint64_t _offset, uint64_t _length) - : offset(_offset), length(_length) { + AioDiscardEvent(uint64_t _offset, uint64_t _length, bool _skip_partial_discard) + : offset(_offset), length(_length), skip_partial_discard(_skip_partial_discard) { } void encode(bufferlist& bl) const; diff --git a/src/librbd/librbd.cc b/src/librbd/librbd.cc index 13f1d27f7e5..51b93f14821 100644 --- a/src/librbd/librbd.cc +++ b/src/librbd/librbd.cc @@ -1331,7 +1331,7 @@ namespace librbd { tracepoint(librbd, discard_exit, -EINVAL); return -EINVAL; } - int r = ictx->io_work_queue->discard(ofs, len); + int r = ictx->io_work_queue->discard(ofs, len, ictx->skip_partial_discard); tracepoint(librbd, discard_exit, r); return r; } @@ -1348,7 +1348,7 @@ namespace librbd { } if (mem_is_zero(bl.c_str(), bl.length())) { - int r = ictx->io_work_queue->discard(ofs, len); + int r = ictx->io_work_queue->discard(ofs, len, false); tracepoint(librbd, writesame_exit, r); return r; } @@ -1393,7 +1393,7 @@ namespace librbd { { ImageCtx *ictx = (ImageCtx *)ctx; tracepoint(librbd, aio_discard_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, off, len, c->pc); - ictx->io_work_queue->aio_discard(get_aio_completion(c), off, len); + ictx->io_work_queue->aio_discard(get_aio_completion(c), off, len, ictx->skip_partial_discard); tracepoint(librbd, aio_discard_exit, 0); return 0; } @@ -1456,7 +1456,7 @@ namespace librbd { } if (mem_is_zero(bl.c_str(), bl.length())) { - ictx->io_work_queue->aio_discard(get_aio_completion(c), off, len); + ictx->io_work_queue->aio_discard(get_aio_completion(c), off, len, false); tracepoint(librbd, aio_writesame_exit, 0); return 0; } @@ -2944,7 +2944,7 @@ extern "C" int rbd_discard(rbd_image_t image, uint64_t ofs, uint64_t len) { librbd::ImageCtx *ictx = (librbd::ImageCtx *)image; tracepoint(librbd, discard_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, ofs, len); - int r = ictx->io_work_queue->discard(ofs, len); + int r = ictx->io_work_queue->discard(ofs, len, ictx->skip_partial_discard); tracepoint(librbd, discard_exit, r); return r; } @@ -2962,7 +2962,7 @@ extern "C" ssize_t rbd_writesame(rbd_image_t image, uint64_t ofs, size_t len, } if (mem_is_zero(buf, data_len)) { - int r = ictx->io_work_queue->discard(ofs, len); + int r = ictx->io_work_queue->discard(ofs, len, false); tracepoint(librbd, writesame_exit, r); return r; } @@ -3057,7 +3057,7 @@ extern "C" int rbd_aio_discard(rbd_image_t image, uint64_t off, uint64_t len, librbd::ImageCtx *ictx = (librbd::ImageCtx *)image; librbd::RBD::AioCompletion *comp = (librbd::RBD::AioCompletion *)c; tracepoint(librbd, aio_discard_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, off, len, comp->pc); - ictx->io_work_queue->aio_discard(get_aio_completion(comp), off, len); + ictx->io_work_queue->aio_discard(get_aio_completion(comp), off, len, ictx->skip_partial_discard); tracepoint(librbd, aio_discard_exit, 0); return 0; } @@ -3159,7 +3159,7 @@ extern "C" int rbd_aio_writesame(rbd_image_t image, uint64_t off, size_t len, } if (mem_is_zero(buf, data_len)) { - ictx->io_work_queue->aio_discard(get_aio_completion(comp), off, len); + ictx->io_work_queue->aio_discard(get_aio_completion(comp), off, len, false); tracepoint(librbd, aio_writesame_exit, 0); return 0; } diff --git a/src/test/librbd/io/test_mock_ImageRequest.cc b/src/test/librbd/io/test_mock_ImageRequest.cc index 0c0acd92619..3cb0ffcc5c3 100644 --- a/src/test/librbd/io/test_mock_ImageRequest.cc +++ b/src/test/librbd/io/test_mock_ImageRequest.cc @@ -246,7 +246,8 @@ TEST_F(TestMockIoImageRequest, AioDiscardJournalAppendDisabled) { C_SaferCond aio_comp_ctx; AioCompletion *aio_comp = AioCompletion::create_and_start( &aio_comp_ctx, ictx, AIO_TYPE_DISCARD); - MockImageDiscardRequest mock_aio_image_discard(mock_image_ctx, aio_comp, 0, 1); + MockImageDiscardRequest mock_aio_image_discard(mock_image_ctx, aio_comp, + 0, 1, ictx->skip_partial_discard); { RWLock::RLocker owner_locker(mock_image_ctx.owner_lock); mock_aio_image_discard.send(); diff --git a/src/test/librbd/journal/test_Entries.cc b/src/test/librbd/journal/test_Entries.cc index 3345394dda8..33e162a0f5e 100644 --- a/src/test/librbd/journal/test_Entries.cc +++ b/src/test/librbd/journal/test_Entries.cc @@ -175,7 +175,7 @@ TEST_F(TestJournalEntries, AioDiscard) { C_SaferCond cond_ctx; auto c = librbd::io::AioCompletion::create(&cond_ctx); c->get(); - ictx->io_work_queue->aio_discard(c, 123, 234); + ictx->io_work_queue->aio_discard(c, 123, 234, cct->_conf->rbd_skip_partial_discard); ASSERT_EQ(0, c->wait_for_complete()); c->put(); diff --git a/src/test/librbd/journal/test_Replay.cc b/src/test/librbd/journal/test_Replay.cc index 19ec52e5e8a..abdbbf99aa9 100644 --- a/src/test/librbd/journal/test_Replay.cc +++ b/src/test/librbd/journal/test_Replay.cc @@ -143,7 +143,7 @@ TEST_F(TestJournalReplay, AioDiscardEvent) { // inject a discard operation into the journal inject_into_journal(ictx, - librbd::journal::AioDiscardEvent(0, payload.size())); + librbd::journal::AioDiscardEvent(0, payload.size(), ictx->skip_partial_discard)); close_image(ictx); // re-open the journal so that it replays the new entry @@ -170,9 +170,9 @@ TEST_F(TestJournalReplay, AioDiscardEvent) { // replay several envents and check the commit position inject_into_journal(ictx, - librbd::journal::AioDiscardEvent(0, payload.size())); + librbd::journal::AioDiscardEvent(0, payload.size(), ictx->cct->_conf->rbd_skip_partial_discard)); inject_into_journal(ictx, - librbd::journal::AioDiscardEvent(0, payload.size())); + librbd::journal::AioDiscardEvent(0, payload.size(), ictx->cct->_conf->rbd_skip_partial_discard)); close_image(ictx); ASSERT_EQ(0, open_image(m_image_name, &ictx)); @@ -183,7 +183,7 @@ TEST_F(TestJournalReplay, AioDiscardEvent) { // verify lock ordering constraints aio_comp = new librbd::io::AioCompletion(); - ictx->io_work_queue->aio_discard(aio_comp, 0, read_payload.size()); + ictx->io_work_queue->aio_discard(aio_comp, 0, read_payload.size(), ictx->cct->_conf->rbd_skip_partial_discard); ASSERT_EQ(0, aio_comp->wait_for_complete()); aio_comp->release(); } diff --git a/src/test/librbd/journal/test_mock_Replay.cc b/src/test/librbd/journal/test_mock_Replay.cc index 9cbd6632e94..62fc57e178e 100644 --- a/src/test/librbd/journal/test_mock_Replay.cc +++ b/src/test/librbd/journal/test_mock_Replay.cc @@ -37,11 +37,12 @@ struct ImageRequest { s_instance->aio_write(c, image_extents, bl, op_flags); } - MOCK_METHOD3(aio_discard, void(AioCompletion *c, uint64_t off, uint64_t len)); + MOCK_METHOD4(aio_discard, void(AioCompletion *c, uint64_t off, uint64_t len, + bool skip_partial_discard)); static void aio_discard(MockReplayImageCtx *ictx, AioCompletion *c, - uint64_t off, uint64_t len) { + uint64_t off, uint64_t len, bool skip_partial_discard) { assert(s_instance != nullptr); - s_instance->aio_discard(c, off, len); + s_instance->aio_discard(c, off, len, skip_partial_discard); } MOCK_METHOD1(aio_flush, void(AioCompletion *c)); @@ -126,8 +127,8 @@ public: void expect_aio_discard(MockIoImageRequest &mock_io_image_request, io::AioCompletion **aio_comp, uint64_t off, - uint64_t len) { - EXPECT_CALL(mock_io_image_request, aio_discard(_, off, len)) + uint64_t len, bool skip_partial_discard) { + EXPECT_CALL(mock_io_image_request, aio_discard(_, off, len, skip_partial_discard)) .WillOnce(SaveArg<0>(aio_comp)); } @@ -337,9 +338,9 @@ TEST_F(TestMockJournalReplay, AioDiscard) { io::AioCompletion *aio_comp; C_SaferCond on_ready; C_SaferCond on_safe; - expect_aio_discard(mock_io_image_request, &aio_comp, 123, 456); + expect_aio_discard(mock_io_image_request, &aio_comp, 123, 456, ictx->skip_partial_discard); when_process(mock_journal_replay, - EventEntry{AioDiscardEvent(123, 456)}, + EventEntry{AioDiscardEvent(123, 456, ictx->skip_partial_discard)}, &on_ready, &on_safe); when_complete(mock_image_ctx, aio_comp, 0); @@ -447,9 +448,9 @@ TEST_F(TestMockJournalReplay, IOError) { io::AioCompletion *aio_comp; C_SaferCond on_ready; C_SaferCond on_safe; - expect_aio_discard(mock_io_image_request, &aio_comp, 123, 456); + expect_aio_discard(mock_io_image_request, &aio_comp, 123, 456, ictx->skip_partial_discard); when_process(mock_journal_replay, - EventEntry{AioDiscardEvent(123, 456)}, + EventEntry{AioDiscardEvent(123, 456, ictx->skip_partial_discard)}, &on_ready, &on_safe); when_complete(mock_image_ctx, aio_comp, -EINVAL); @@ -478,12 +479,12 @@ TEST_F(TestMockJournalReplay, SoftFlushIO) { io::AioCompletion *aio_comp; io::AioCompletion *flush_comp = nullptr; C_SaferCond on_ready; - expect_aio_discard(mock_io_image_request, &aio_comp, 123, 456); + expect_aio_discard(mock_io_image_request, &aio_comp, 123, 456, ictx->skip_partial_discard); if (i == io_count - 1) { expect_aio_flush(mock_io_image_request, &flush_comp); } when_process(mock_journal_replay, - EventEntry{AioDiscardEvent(123, 456)}, + EventEntry{AioDiscardEvent(123, 456, ictx->skip_partial_discard)}, &on_ready, &on_safes[i]); when_complete(mock_image_ctx, aio_comp, 0); ASSERT_EQ(0, on_ready.wait()); @@ -555,9 +556,9 @@ TEST_F(TestMockJournalReplay, Flush) { io::AioCompletion *aio_comp = nullptr; C_SaferCond on_ready; C_SaferCond on_safe; - expect_aio_discard(mock_io_image_request, &aio_comp, 123, 456); + expect_aio_discard(mock_io_image_request, &aio_comp, 123, 456, ictx->skip_partial_discard); when_process(mock_journal_replay, - EventEntry{AioDiscardEvent(123, 456)}, + EventEntry{AioDiscardEvent(123, 456, ictx->skip_partial_discard)}, &on_ready, &on_safe); when_complete(mock_image_ctx, aio_comp, 0); diff --git a/src/test/librbd/mock/cache/MockImageCache.h b/src/test/librbd/mock/cache/MockImageCache.h index 36ce5b71a7c..8c5624c8659 100644 --- a/src/test/librbd/mock/cache/MockImageCache.h +++ b/src/test/librbd/mock/cache/MockImageCache.h @@ -28,7 +28,7 @@ struct MockImageCache { aio_write_mock(image_extents, bl, fadvise_flags, on_finish); } - MOCK_METHOD3(aio_discard, void(uint64_t, uint64_t, Context *)); + MOCK_METHOD4(aio_discard, void(uint64_t, uint64_t, bool, Context *)); MOCK_METHOD1(aio_flush, void(Context *)); MOCK_METHOD5(aio_writesame_mock, void(uint64_t, uint64_t, ceph::bufferlist& bl, int, Context *)); diff --git a/src/test/librbd/test_internal.cc b/src/test/librbd/test_internal.cc index b9eb60db11c..fea96009931 100644 --- a/src/test/librbd/test_internal.cc +++ b/src/test/librbd/test_internal.cc @@ -299,7 +299,7 @@ TEST_F(TestInternal, AioDiscardRequestsLock) { Context *ctx = new DummyContext(); auto c = librbd::io::AioCompletion::create(ctx); c->get(); - ictx->io_work_queue->aio_discard(c, 0, 256); + ictx->io_work_queue->aio_discard(c, 0, 256, false); bool is_owner; ASSERT_EQ(0, librbd::is_exclusive_lock_owner(ictx, &is_owner)); @@ -686,7 +686,7 @@ TEST_F(TestInternal, DiscardCopyup) read_bl.push_back(read_ptr); ASSERT_EQ(static_cast(m_image_size - 64), - ictx2->io_work_queue->discard(32, m_image_size - 64)); + ictx2->io_work_queue->discard(32, m_image_size - 64, false)); ASSERT_EQ(0, librbd::snap_set(ictx2, "snap1")); { diff --git a/src/test/rbd_mirror/image_sync/test_mock_ObjectCopyRequest.cc b/src/test/rbd_mirror/image_sync/test_mock_ObjectCopyRequest.cc index fe77cb01bc3..d34f04187b4 100644 --- a/src/test/rbd_mirror/image_sync/test_mock_ObjectCopyRequest.cc +++ b/src/test/rbd_mirror/image_sync/test_mock_ObjectCopyRequest.cc @@ -487,7 +487,7 @@ TEST_F(TestMockImageSyncObjectCopyRequest, Trim) { // trim the object uint64_t trim_offset = rand() % one.range_end(); ASSERT_LE(0, m_remote_image_ctx->io_work_queue->discard( - trim_offset, one.range_end() - trim_offset)); + trim_offset, one.range_end() - trim_offset, m_remote_image_ctx->skip_partial_discard)); ASSERT_EQ(0, create_snap("sync")); librbd::MockTestImageCtx mock_remote_image_ctx(*m_remote_image_ctx); @@ -530,7 +530,7 @@ TEST_F(TestMockImageSyncObjectCopyRequest, Remove) { // remove the object uint64_t object_size = 1 << m_remote_image_ctx->order; - ASSERT_LE(0, m_remote_image_ctx->io_work_queue->discard(0, object_size)); + ASSERT_LE(0, m_remote_image_ctx->io_work_queue->discard(0, object_size, m_remote_image_ctx->skip_partial_discard)); ASSERT_EQ(0, create_snap("sync")); librbd::MockTestImageCtx mock_remote_image_ctx(*m_remote_image_ctx); librbd::MockTestImageCtx mock_local_image_ctx(*m_local_image_ctx); diff --git a/src/test/rbd_mirror/test_ImageSync.cc b/src/test/rbd_mirror/test_ImageSync.cc index 51d48357b5e..8947ddbc075 100644 --- a/src/test/rbd_mirror/test_ImageSync.cc +++ b/src/test/rbd_mirror/test_ImageSync.cc @@ -33,7 +33,7 @@ void scribble(librbd::ImageCtx *image_ctx, int num_ops, size_t max_size) uint64_t len = 1 + rand() % max_size; if (rand() % 4 == 0) { - ASSERT_EQ((int)len, image_ctx->io_work_queue->discard(off, len)); + ASSERT_EQ((int)len, image_ctx->io_work_queue->discard(off, len, image_ctx->skip_partial_discard)); } else { bufferlist bl; bl.append(std::string(len, '1')); @@ -202,7 +202,7 @@ TEST_F(TestImageSync, Discard) { ASSERT_EQ(0, create_snap(m_remote_image_ctx, "snap", nullptr)); ASSERT_EQ((int)len - 2, m_remote_image_ctx->io_work_queue->discard(off + 1, - len - 2)); + len - 2, m_remote_image_ctx->skip_partial_discard)); { RWLock::RLocker owner_locker(m_remote_image_ctx->owner_lock); ASSERT_EQ(0, m_remote_image_ctx->flush()); diff --git a/src/test/rbd_mirror/test_mock_ImageReplayer.cc b/src/test/rbd_mirror/test_mock_ImageReplayer.cc index 697f0419492..ee3e466a6d3 100644 --- a/src/test/rbd_mirror/test_mock_ImageReplayer.cc +++ b/src/test/rbd_mirror/test_mock_ImageReplayer.cc @@ -847,7 +847,7 @@ TEST_F(TestMockImageReplayer, DelayedReplay) { // process with delay EXPECT_CALL(mock_replay_entry, get_data()); librbd::journal::EventEntry event_entry( - librbd::journal::AioDiscardEvent(123, 345), ceph_clock_now()); + librbd::journal::AioDiscardEvent(123, 345, false), ceph_clock_now()); EXPECT_CALL(mock_local_replay, decode(_, _)) .WillOnce(DoAll(SetArgPointee<1>(event_entry), Return(0)));