From: wangzhengyong Date: Mon, 12 Jun 2017 13:14:19 +0000 (+0800) Subject: librbd: add compare_and_write ImageRequest X-Git-Tag: v12.1.2~106^2~11 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=d201c850de292cb1882ad539c55dc8c13a591991;p=ceph.git librbd: add compare_and_write ImageRequest Signed-off-by: Zhengyong Wang --- diff --git a/src/librbd/cache/ImageCache.h b/src/librbd/cache/ImageCache.h index 0a5d0263ee33..f394a1a80a1e 100644 --- a/src/librbd/cache/ImageCache.h +++ b/src/librbd/cache/ImageCache.h @@ -33,6 +33,12 @@ struct ImageCache { virtual void aio_writesame(uint64_t offset, uint64_t length, ceph::bufferlist&& bl, int fadvise_flags, Context *on_finish) = 0; + virtual void aio_compare_and_write(Extents&& image_extents, + ceph::bufferlist&& cmp_bl, + ceph::bufferlist&& bl, + uint64_t *mismatch_offset, + int fadvise_flags, + Context *on_finish) = 0; /// internal state methods virtual void init(Context *on_finish) = 0; diff --git a/src/librbd/cache/ImageWriteback.cc b/src/librbd/cache/ImageWriteback.cc index cff7a531db29..d5c9c759c850 100644 --- a/src/librbd/cache/ImageWriteback.cc +++ b/src/librbd/cache/ImageWriteback.cc @@ -98,6 +98,27 @@ void ImageWriteback::aio_writesame(uint64_t offset, uint64_t length, req.send(); } +template +void ImageWriteback::aio_compare_and_write(Extents &&image_extents, + ceph::bufferlist&& cmp_bl, + ceph::bufferlist&& bl, + uint64_t *mismatch_offset, + int fadvise_flags, + Context *on_finish) { + CephContext *cct = m_image_ctx.cct; + ldout(cct, 20) << "image_extents=" << image_extents << ", " + << "on_finish=" << on_finish << dendl; + + auto aio_comp = io::AioCompletion::create_and_start(on_finish, &m_image_ctx, + io::AIO_TYPE_COMPARE_AND_WRITE); + io::ImageCompareAndWriteRequest req(m_image_ctx, aio_comp, + std::move(image_extents), + std::move(cmp_bl), std::move(bl), + mismatch_offset, fadvise_flags, {}); + req.set_bypass_image_cache(); + req.send(); +} + } // namespace cache } // namespace librbd diff --git a/src/librbd/cache/ImageWriteback.h b/src/librbd/cache/ImageWriteback.h index 1ffc450dfbbb..9bc9b5e6d26d 100644 --- a/src/librbd/cache/ImageWriteback.h +++ b/src/librbd/cache/ImageWriteback.h @@ -36,7 +36,11 @@ public: void aio_writesame(uint64_t offset, uint64_t length, ceph::bufferlist&& bl, int fadvise_flags, Context *on_finish); - + void aio_compare_and_write(Extents &&image_extents, + ceph::bufferlist&& cmp_bl, + ceph::bufferlist&& bl, + uint64_t *mismatch_offset, + int fadvise_flags, Context *on_finish); private: ImageCtxT &m_image_ctx; diff --git a/src/librbd/cache/PassthroughImageCache.cc b/src/librbd/cache/PassthroughImageCache.cc index f892387acc89..5b22fc7a6ced 100644 --- a/src/librbd/cache/PassthroughImageCache.cc +++ b/src/librbd/cache/PassthroughImageCache.cc @@ -76,6 +76,22 @@ void PassthroughImageCache::aio_writesame(uint64_t offset, uint64_t length, on_finish); } +template +void PassthroughImageCache::aio_compare_and_write(Extents &&image_extents, + bufferlist&& cmp_bl, + bufferlist&& bl, + uint64_t *mismatch_offset, + int fadvise_flags, + Context *on_finish) { + CephContext *cct = m_image_ctx.cct; + ldout(cct, 20) << "image_extents=" << image_extents << ", " + << "on_finish=" << on_finish << dendl; + + m_image_writeback.aio_compare_and_write( + std::move(image_extents), std::move(cmp_bl), std::move(bl), mismatch_offset, + fadvise_flags, on_finish); +} + template void PassthroughImageCache::init(Context *on_finish) { CephContext *cct = m_image_ctx.cct; diff --git a/src/librbd/cache/PassthroughImageCache.h b/src/librbd/cache/PassthroughImageCache.h index 089430c7b5b8..2dbe94dbe79b 100644 --- a/src/librbd/cache/PassthroughImageCache.h +++ b/src/librbd/cache/PassthroughImageCache.h @@ -32,6 +32,10 @@ public: void aio_writesame(uint64_t offset, uint64_t length, ceph::bufferlist&& bl, int fadvise_flags, Context *on_finish) override; + void aio_compare_and_write(Extents&& image_extents, + ceph::bufferlist&& cmp_bl, ceph::bufferlist&& bl, + uint64_t *mismatch_offset,int fadvise_flags, + Context *on_finish) override; /// internal state methods void init(Context *on_finish) override; diff --git a/src/librbd/io/ImageRequest.cc b/src/librbd/io/ImageRequest.cc index 8afd6556a32c..86ea5536addd 100644 --- a/src/librbd/io/ImageRequest.cc +++ b/src/librbd/io/ImageRequest.cc @@ -197,6 +197,21 @@ void ImageRequest::aio_writesame(I *ictx, AioCompletion *c, req.send(); } +template +void ImageRequest::aio_compare_and_write(I *ictx, AioCompletion *c, + Extents &&image_extents, + bufferlist &&cmp_bl, + bufferlist &&bl, + uint64_t *mismatch_offset, + int op_flags, + const ZTracer::Trace &parent_trace) { + ImageCompareAndWriteRequest req(*ictx, c, std::move(image_extents), + std::move(cmp_bl), std::move(bl), + mismatch_offset, op_flags, parent_trace); + req.send(); +} + + template void ImageRequest::send() { I &image_ctx = this->m_image_ctx; @@ -206,7 +221,7 @@ void ImageRequest::send() { CephContext *cct = image_ctx.cct; AioCompletion *aio_comp = this->m_aio_comp; ldout(cct, 20) << get_request_type() << ": ictx=" << &image_ctx << ", " - << "completion=" << aio_comp << dendl; + << "completion=" << aio_comp << dendl; aio_comp->get(); int r = clip_request(); @@ -404,7 +419,11 @@ void AbstractImageWriteRequest::send_request() { image_ctx.journal->is_journal_appending()); } - prune_object_extents(object_extents); + int ret = prune_object_extents(object_extents); + if (ret < 0) { + aio_comp->fail(ret); + return; + } if (!object_extents.empty()) { uint64_t journal_tid = 0; @@ -583,11 +602,11 @@ uint64_t ImageDiscardRequest::append_journal_event( } template -void ImageDiscardRequest::prune_object_extents(ObjectExtents &object_extents) { +int ImageDiscardRequest::prune_object_extents(ObjectExtents &object_extents) { I &image_ctx = this->m_image_ctx; CephContext *cct = image_ctx.cct; if (!this->m_skip_partial_discard) { - return; + return 0; } for (auto p = object_extents.begin(); p != object_extents.end(); ) { @@ -600,6 +619,8 @@ void ImageDiscardRequest::prune_object_extents(ObjectExtents &object_extents) ++p; } } + + return 0; } template @@ -876,6 +897,104 @@ void ImageWriteSameRequest::update_stats(size_t length) { image_ctx.perfcounter->inc(l_librbd_ws_bytes, length); } +template +uint64_t ImageCompareAndWriteRequest::append_journal_event( + const ObjectRequests &requests, bool synchronous) { + + I &image_ctx = this->m_image_ctx; + + uint64_t tid = 0; + assert(this->m_image_extents.size() == 1); + auto &extent = this->m_image_extents.front(); + journal::EventEntry event_entry(journal::AioCompareAndWriteEvent(extent.first, + extent.second, + m_cmp_bl, m_bl)); + tid = image_ctx.journal->append_io_event(std::move(event_entry), + requests, extent.first, + extent.second, synchronous); + + AioCompletion *aio_comp = this->m_aio_comp; + aio_comp->associate_journal_event(tid); + + return tid; +} + +template +void ImageCompareAndWriteRequest::send_object_cache_requests( + const ObjectExtents &object_extents, uint64_t journal_tid) { + I &image_ctx = this->m_image_ctx; + + if (image_ctx.object_cacher != NULL) { + Mutex::Locker cache_locker(image_ctx.cache_lock); + image_ctx.object_cacher->discard_set(image_ctx.object_set, + object_extents); + } +} + +template +void ImageCompareAndWriteRequest::assemble_extent( + const ObjectExtent &object_extent, bufferlist *bl) { + for (auto q = object_extent.buffer_extents.begin(); + q != object_extent.buffer_extents.end(); ++q) { + bufferlist sub_bl; + sub_bl.substr_of(m_bl, q->first, q->second); + bl->claim_append(sub_bl); + } +} + +template +void ImageCompareAndWriteRequest::send_image_cache_request() { + I &image_ctx = this->m_image_ctx; + assert(image_ctx.image_cache != nullptr); + + AioCompletion *aio_comp = this->m_aio_comp; + aio_comp->set_request_count(1); + C_AioRequest *req_comp = new C_AioRequest(aio_comp); + image_ctx.image_cache->aio_compare_and_write( + std::move(this->m_image_extents), std::move(m_cmp_bl), std::move(m_bl), + m_mismatch_offset, m_op_flags, req_comp); +} + +template +ObjectRequestHandle *ImageCompareAndWriteRequest::create_object_request( + const ObjectExtent &object_extent, + const ::SnapContext &snapc, + Context *on_finish) { + I &image_ctx = this->m_image_ctx; + + bufferlist bl; + assemble_extent(object_extent, &bl); + ObjectRequest *req = ObjectRequest::create_compare_and_write( + &image_ctx, object_extent.oid.name, + object_extent.objectno, object_extent.offset, + m_cmp_bl, bl, snapc, m_mismatch_offset, + m_op_flags, this->m_trace, on_finish); + return req; +} + +template +void ImageCompareAndWriteRequest::update_stats(size_t length) { + I &image_ctx = this->m_image_ctx; + image_ctx.perfcounter->inc(l_librbd_cmp); + image_ctx.perfcounter->inc(l_librbd_cmp_bytes, length); +} + +template +int ImageCompareAndWriteRequest::prune_object_extents(ObjectExtents &object_extents) { + if (object_extents.size() > 1) + return -EINVAL; + + I &image_ctx = this->m_image_ctx; + uint64_t sector_size = 512ULL; + uint64_t su = image_ctx.layout.stripe_unit; + ObjectExtent object_extent = object_extents.front(); + if (object_extent.offset % sector_size + object_extent.length > sector_size || + (su != 0 && (object_extent.offset % su + object_extent.length > su))) + return -EINVAL; + + return 0; +} + } // namespace io } // namespace librbd @@ -886,3 +1005,4 @@ template class librbd::io::ImageWriteRequest; template class librbd::io::ImageDiscardRequest; template class librbd::io::ImageFlushRequest; template class librbd::io::ImageWriteSameRequest; +template class librbd::io::ImageCompareAndWriteRequest; diff --git a/src/librbd/io/ImageRequest.h b/src/librbd/io/ImageRequest.h index de19f490c6f2..93538f6e3e72 100644 --- a/src/librbd/io/ImageRequest.h +++ b/src/librbd/io/ImageRequest.h @@ -73,6 +73,11 @@ public: uint64_t len, bufferlist &&bl, int op_flags, const ZTracer::Trace &parent_trace); + static void aio_compare_and_write(ImageCtxT *ictx, AioCompletion *c, + Extents &&image_extents, bufferlist &&cmp_bl, + bufferlist &&bl, uint64_t *mismatch_offset, + int op_flags, const ZTracer::Trace &parent_trace); + virtual bool is_write_op() const { return false; } @@ -171,7 +176,8 @@ protected: void send_request() override; - virtual void prune_object_extents(ObjectExtents &object_extents) { + virtual int prune_object_extents(ObjectExtents &object_extents) { + return 0; } virtual uint32_t get_object_cache_request_count(bool journaling) const { return 0; @@ -264,7 +270,7 @@ protected: return "aio_discard"; } - void prune_object_extents(ObjectExtents &object_extents) override; + int prune_object_extents(ObjectExtents &object_extents) override; void send_image_cache_request() override; @@ -357,6 +363,53 @@ private: int m_op_flags; }; +template +class ImageCompareAndWriteRequest : public AbstractImageWriteRequest { +public: + using typename ImageRequest::ObjectRequests; + using typename AbstractImageWriteRequest::ObjectExtents; + + ImageCompareAndWriteRequest(ImageCtxT &image_ctx, AioCompletion *aio_comp, + Extents &&image_extents, bufferlist &&cmp_bl, + bufferlist &&bl, uint64_t *mismatch_offset, + int op_flags, const ZTracer::Trace &parent_trace) + : AbstractImageWriteRequest( + image_ctx, aio_comp, std::move(image_extents), "compare_and_write", parent_trace), + m_cmp_bl(std::move(cmp_bl)), m_bl(std::move(bl)), + m_mismatch_offset(mismatch_offset), m_op_flags(op_flags) { + } + +protected: + void send_image_cache_request() override; + + void send_object_cache_requests(const ObjectExtents &object_extents, + uint64_t journal_tid) override; + + void assemble_extent(const ObjectExtent &object_extent, bufferlist *bl); + + ObjectRequestHandle *create_object_request(const ObjectExtent &object_extent, + const ::SnapContext &snapc, + Context *on_finish) override; + + uint64_t append_journal_event(const ObjectRequests &requests, + bool synchronous) override; + void update_stats(size_t length) override; + + aio_type_t get_aio_type() const override { + return AIO_TYPE_COMPARE_AND_WRITE; + } + const char *get_request_type() const override { + return "aio_compare_and_write"; + } + + int prune_object_extents(ObjectExtents &object_extents) override; +private: + bufferlist m_cmp_bl; + bufferlist m_bl; + uint64_t *m_mismatch_offset; + int m_op_flags; +}; + } // namespace io } // namespace librbd @@ -367,5 +420,6 @@ extern template class librbd::io::ImageWriteRequest; extern template class librbd::io::ImageDiscardRequest; extern template class librbd::io::ImageFlushRequest; extern template class librbd::io::ImageWriteSameRequest; +extern template class librbd::io::ImageCompareAndWriteRequest; #endif // CEPH_LIBRBD_IO_IMAGE_REQUEST_H