From: Jason Dillaman Date: Thu, 9 Jul 2015 18:43:56 +0000 (-0400) Subject: librbd: re-use common logic between aio_write/discard X-Git-Tag: v10.0.1~52^2~25 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=44a49aa8991b1106bb6c54ec5379a32d1de6119b;p=ceph.git librbd: re-use common logic between aio_write/discard Signed-off-by: Jason Dillaman --- diff --git a/src/librbd/AioImageRequest.cc b/src/librbd/AioImageRequest.cc index 9f0a5d78ed8b..56fbc453ef31 100644 --- a/src/librbd/AioImageRequest.cc +++ b/src/librbd/AioImageRequest.cc @@ -7,6 +7,8 @@ #include "librbd/ImageCtx.h" #include "librbd/ImageWatcher.h" #include "librbd/internal.h" +#include "include/rados/librados.hpp" +#include "osdc/Striper.h" #define dout_subsys ceph_subsys_rbd #undef dout_prefix @@ -14,7 +16,7 @@ namespace librbd { -void AioImageRequest::read( +void AioImageRequest::aio_read( ImageCtx *ictx, AioCompletion *c, const std::vector > &extents, char *buf, bufferlist *pbl, int op_flags) { @@ -22,26 +24,26 @@ void AioImageRequest::read( req.send(); } -void AioImageRequest::read(ImageCtx *ictx, AioCompletion *c, uint64_t off, - size_t len, char *buf, bufferlist *pbl, - int op_flags) { +void AioImageRequest::aio_read(ImageCtx *ictx, AioCompletion *c, uint64_t off, + size_t len, char *buf, bufferlist *pbl, + int op_flags) { AioImageRead req(*ictx, c, off, len, buf, pbl, op_flags); req.send(); } -void AioImageRequest::write(ImageCtx *ictx, AioCompletion *c, uint64_t off, - size_t len, const char *buf, int op_flags) { +void AioImageRequest::aio_write(ImageCtx *ictx, AioCompletion *c, uint64_t off, + size_t len, const char *buf, int op_flags) { AioImageWrite req(*ictx, c, off, len, buf, op_flags); req.send(); } -void AioImageRequest::discard(ImageCtx *ictx, AioCompletion *c, uint64_t off, - uint64_t len) { +void AioImageRequest::aio_discard(ImageCtx *ictx, AioCompletion *c, + uint64_t off, uint64_t len) { AioImageDiscard req(*ictx, c, off, len); req.send(); } -void AioImageRequest::flush(ImageCtx *ictx, AioCompletion *c) { +void AioImageRequest::aio_flush(ImageCtx *ictx, AioCompletion *c) { AioImageFlush req(*ictx, c); req.send(); } @@ -60,11 +62,10 @@ void AioImageRequest::send() { return; } - execute_request(); + send_request(); } - -void AioImageRead::execute_request() { +void AioImageRead::send_request() { CephContext *cct = m_image_ctx.cct; if (m_image_ctx.object_cacher && m_image_ctx.readahead_max_bytes > 0 && @@ -141,7 +142,7 @@ void AioImageRead::execute_request() { m_image_ctx.perfcounter->inc(l_librbd_rd_bytes, buffer_ofs); } -void AioImageWrite::execute_request() { +void AbstractAioImageWrite::send_request() { CephContext *cct = m_image_ctx.cct; RWLock::RLocker md_locker(m_image_ctx.md_lock); @@ -164,125 +165,115 @@ void AioImageWrite::execute_request() { } snapc = m_image_ctx.snapc; - m_aio_comp->start_op(&m_image_ctx, AIO_TYPE_WRITE); + m_aio_comp->start_op(&m_image_ctx, AIO_TYPE_WRITE); // TODO use correct enum } assert(!m_image_ctx.image_watcher->is_lock_supported() || m_image_ctx.image_watcher->is_lock_owner()); - // map - vector extents; - if (m_len > 0) { + // map to object extents + ObjectExtents extents; + if (clip_len > 0) { Striper::file_to_extents(cct, m_image_ctx.format_string, &m_image_ctx.layout, m_off, clip_len, 0, extents); } - for (vector::iterator p = extents.begin(); - p != extents.end(); ++p) { - ldout(cct, 20) << " oid " << p->oid << " " << p->offset << "~" << p->length - << " from " << p->buffer_extents << dendl; - // assemble extent - bufferlist bl; - for (vector >::iterator q = - p->buffer_extents.begin(); - q != p->buffer_extents.end(); ++q) { - bl.append(m_buf + q->first, q->second); - } - - C_AioRequest *req_comp = new C_AioRequest(cct, m_aio_comp); - if (m_image_ctx.object_cacher) { - m_image_ctx.write_to_cache(p->oid, bl, p->length, p->offset, req_comp, - m_op_flags); - } else { - AioObjectWrite *req = new AioObjectWrite(&m_image_ctx, p->oid.name, - p->objectno, p->offset, bl, - snapc, req_comp); - - req->set_op_flags(m_op_flags); - req->send(); - } - } + send_object_requests(extents, snapc); + update_stats(clip_len); m_aio_comp->finish_adding_requests(cct); m_aio_comp->put(); - - m_image_ctx.perfcounter->inc(l_librbd_wr); - m_image_ctx.perfcounter->inc(l_librbd_wr_bytes, clip_len); } -void AioImageDiscard::execute_request() { +void AbstractAioImageWrite::send_object_requests( + const ObjectExtents &object_extents, const ::SnapContext &snapc) { CephContext *cct = m_image_ctx.cct; + for (ObjectExtents::const_iterator p = object_extents.begin(); + p != object_extents.end(); ++p) { + ldout(cct, 20) << " oid " << p->oid << " " << p->offset << "~" << p->length + << " from " << p->buffer_extents << dendl; + send_object_request(*p, snapc); + } +} - RWLock::RLocker md_locker(m_image_ctx.md_lock); +void AioImageWrite::send_object_request(const ObjectExtent &object_extent, + const ::SnapContext &snapc) { + CephContext *cct = m_image_ctx.cct; - uint64_t clip_len = m_len; - ::SnapContext snapc; - { - // prevent image size from changing between computing clip and recording - // pending async operation - RWLock::RLocker snap_locker(m_image_ctx.snap_lock); - if (m_image_ctx.snap_id != CEPH_NOSNAP || m_image_ctx.read_only) { - m_aio_comp->fail(cct, -EROFS); - return; - } + // assemble extent + bufferlist bl; + for (Extents::const_iterator q = object_extent.buffer_extents.begin(); + q != object_extent.buffer_extents.end(); ++q) { + bl.append(m_buf + q->first, q->second); + } - int r = clip_io(&m_image_ctx, m_off, &clip_len); - if (r < 0) { - m_aio_comp->fail(cct, r); - return; - } + C_AioRequest *req_comp = new C_AioRequest(cct, m_aio_comp); + if (m_image_ctx.object_cacher) { + m_image_ctx.write_to_cache(object_extent.oid, bl, object_extent.length, + object_extent.offset, req_comp, m_op_flags); + } else { + AioObjectWrite *req = new AioObjectWrite(&m_image_ctx, + object_extent.oid.name, + object_extent.objectno, + object_extent.offset, bl, + snapc, req_comp); - snapc = m_image_ctx.snapc; - m_aio_comp->start_op(&m_image_ctx, AIO_TYPE_DISCARD); + req->set_op_flags(m_op_flags); + req->send(); } +} - assert(!m_image_ctx.image_watcher->is_lock_supported() || - m_image_ctx.image_watcher->is_lock_owner()); - // map - vector extents; - if (m_len > 0) { - Striper::file_to_extents(cct, m_image_ctx.format_string, - &m_image_ctx.layout, m_off, clip_len, 0, extents); - } +void AioImageWrite::update_stats(size_t length) { + m_image_ctx.perfcounter->inc(l_librbd_wr); + m_image_ctx.perfcounter->inc(l_librbd_wr_bytes, length); +} - for (vector::iterator p = extents.begin(); - p != extents.end(); ++p) { - ldout(cct, 20) << " oid " << p->oid << " " << p->offset << "~" << p->length - << " from " << p->buffer_extents << dendl; - C_AioRequest *req_comp = new C_AioRequest(cct, m_aio_comp); - AioObjectRequest *req; - - if (p->length == m_image_ctx.layout.fl_object_size) { - req = new AioObjectRemove(&m_image_ctx, p->oid.name, p->objectno, snapc, - req_comp); - } else if (p->offset + p->length == m_image_ctx.layout.fl_object_size) { - req = new AioObjectTruncate(&m_image_ctx, p->oid.name, p->objectno, - p->offset, snapc, req_comp); - } else { - if(cct->_conf->rbd_skip_partial_discard) { - delete req_comp; - continue; - } - req = new AioObjectZero(&m_image_ctx, p->oid.name, p->objectno, p->offset, - p->length, snapc, req_comp); - } - req->send(); +void AioImageDiscard::send_object_requests(const ObjectExtents &object_extents, + const ::SnapContext &snapc) { + // discard from the cache first to ensure writeback won't recreate + if (m_image_ctx.object_cacher != NULL) { + Mutex::Locker cache_locker(m_image_ctx.cache_lock); + m_image_ctx.object_cacher->discard_set(m_image_ctx.object_set, + object_extents); } - if (m_image_ctx.object_cacher) { - Mutex::Locker l(m_image_ctx.cache_lock); - m_image_ctx.object_cacher->discard_set(m_image_ctx.object_set, extents); - } + AbstractAioImageWrite::send_object_requests(object_extents, snapc); +} - m_aio_comp->finish_adding_requests(cct); - m_aio_comp->put(); +void AioImageDiscard::send_object_request(const ObjectExtent &object_extent, + const ::SnapContext &snapc) { + CephContext *cct = m_image_ctx.cct; + + C_AioRequest *req_comp = new C_AioRequest(cct, m_aio_comp); + + AioObjectRequest *req; + if (object_extent.length == m_image_ctx.layout.fl_object_size) { + req = new AioObjectRemove(&m_image_ctx, object_extent.oid.name, + object_extent.objectno, snapc, req_comp); + } else if (object_extent.offset + object_extent.length == + m_image_ctx.layout.fl_object_size) { + req = new AioObjectTruncate(&m_image_ctx, object_extent.oid.name, + object_extent.objectno, object_extent.offset, + snapc, req_comp); + } else { + if(cct->_conf->rbd_skip_partial_discard) { + delete req_comp; + return; + } + req = new AioObjectZero(&m_image_ctx, object_extent.oid.name, + object_extent.objectno, object_extent.offset, + object_extent.length, snapc, req_comp); + } + req->send(); +} +void AioImageDiscard::update_stats(size_t length) { m_image_ctx.perfcounter->inc(l_librbd_discard); - m_image_ctx.perfcounter->inc(l_librbd_discard_bytes, clip_len); + m_image_ctx.perfcounter->inc(l_librbd_discard_bytes, length); } -void AioImageFlush::execute_request() { +void AioImageFlush::send_request() { CephContext *cct = m_image_ctx.cct; // TODO race condition between registering op and submitting to cache diff --git a/src/librbd/AioImageRequest.h b/src/librbd/AioImageRequest.h index 1d8586b201d4..db65839b5dd6 100644 --- a/src/librbd/AioImageRequest.h +++ b/src/librbd/AioImageRequest.h @@ -6,6 +6,8 @@ #include "include/int_types.h" #include "include/buffer.h" +#include "common/snap_types.h" +#include "osd/osd_types.h" #include #include @@ -16,29 +18,35 @@ class ImageCtx; class AioImageRequest { public: - AioImageRequest(ImageCtx &image_ctx, AioCompletion *aio_comp) - : m_image_ctx(image_ctx), m_aio_comp(aio_comp) {} + typedef std::vector > Extents; + virtual ~AioImageRequest() {} - static void read(ImageCtx *ictx, AioCompletion *c, - const std::vector > &extents, - char *buf, bufferlist *pbl, int op_flags); - static void read(ImageCtx *ictx, AioCompletion *c, uint64_t off, size_t len, - char *buf, bufferlist *pbl, int op_flags); - static void write(ImageCtx *ictx, AioCompletion *c, uint64_t off, size_t len, - const char *buf, int op_flags); - static void discard(ImageCtx *ictx, AioCompletion *c, uint64_t off, - uint64_t len); - static void flush(ImageCtx *ictx, AioCompletion *c); + static void aio_read(ImageCtx *ictx, AioCompletion *c, + const std::vector > &extents, + char *buf, bufferlist *pbl, int op_flags); + static void aio_read(ImageCtx *ictx, AioCompletion *c, uint64_t off, + size_t len, char *buf, bufferlist *pbl, int op_flags); + static void aio_write(ImageCtx *ictx, AioCompletion *c, uint64_t off, + size_t len, const char *buf, int op_flags); + static void aio_discard(ImageCtx *ictx, AioCompletion *c, uint64_t off, + uint64_t len); + static void aio_flush(ImageCtx *ictx, AioCompletion *c); - virtual bool is_write_op() const = 0; + virtual bool is_write_op() const { + return false; + } void send(); + protected: ImageCtx &m_image_ctx; AioCompletion *m_aio_comp; - virtual void execute_request() = 0; + AioImageRequest(ImageCtx &image_ctx, AioCompletion *aio_comp) + : m_image_ctx(image_ctx), m_aio_comp(aio_comp) {} + + virtual void send_request() = 0; virtual const char *get_request_type() const = 0; }; @@ -50,69 +58,91 @@ public: m_op_flags(op_flags) { m_image_extents.push_back(std::make_pair(off, len)); } + AioImageRead(ImageCtx &image_ctx, AioCompletion *aio_comp, - const std::vector > &image_extents, - char *buf, bufferlist *pbl, int op_flags) + const Extents &image_extents, char *buf, bufferlist *pbl, + int op_flags) : AioImageRequest(image_ctx, aio_comp), m_image_extents(image_extents), m_buf(buf), m_pbl(pbl), m_op_flags(op_flags) { } - virtual bool is_write_op() const { - return false; - } protected: - virtual void execute_request(); + virtual void send_request(); virtual const char *get_request_type() const { return "aio_read"; } private: - std::vector > m_image_extents; + Extents m_image_extents; char *m_buf; bufferlist *m_pbl; int m_op_flags; }; -class AioImageWrite : public AioImageRequest { +class AbstractAioImageWrite : public AioImageRequest { +public: + virtual bool is_write_op() const { + return true; + } + +protected: + typedef std::vector ObjectExtents; + + AbstractAioImageWrite(ImageCtx &image_ctx, AioCompletion *aio_comp, + uint64_t off, size_t len) + : AioImageRequest(image_ctx, aio_comp), m_off(off), m_len(len) { + } + + virtual void send_request(); + + virtual void send_object_requests(const ObjectExtents &object_extents, + const ::SnapContext &snapc); + virtual void send_object_request(const ObjectExtent &object_extent, + const ::SnapContext &snapc) = 0; + virtual void update_stats(size_t length) = 0; + +private: + uint64_t m_off; + size_t m_len; +}; + +class AioImageWrite : public AbstractAioImageWrite { public: AioImageWrite(ImageCtx &image_ctx, AioCompletion *aio_comp, uint64_t off, size_t len, const char *buf, int op_flags) - : AioImageRequest(image_ctx, aio_comp), m_off(off), m_len(len), m_buf(buf), + : AbstractAioImageWrite(image_ctx, aio_comp, off, len), m_buf(buf), m_op_flags(op_flags) { } - virtual bool is_write_op() const { - return true; - } protected: - virtual void execute_request(); virtual const char *get_request_type() const { return "aio_write"; } + + virtual void send_object_request(const ObjectExtent &object_extent, + const ::SnapContext &snapc); + virtual void update_stats(size_t length); private: - uint64_t m_off; - uint64_t m_len; const char *m_buf; int m_op_flags; }; -class AioImageDiscard : public AioImageRequest { +class AioImageDiscard : public AbstractAioImageWrite { public: AioImageDiscard(ImageCtx &image_ctx, AioCompletion *aio_comp, uint64_t off, uint64_t len) - : AioImageRequest(image_ctx, aio_comp), m_off(off), m_len(len) { + : AbstractAioImageWrite(image_ctx, aio_comp, off, len) { } - virtual bool is_write_op() const { - return true; - } protected: - virtual void execute_request(); virtual const char *get_request_type() const { return "aio_discard"; } -private: - uint64_t m_off; - uint64_t m_len; + + virtual void send_object_requests(const ObjectExtents &object_extents, + const ::SnapContext &snapc); + virtual void send_object_request(const ObjectExtent &object_extent, + const ::SnapContext &snapc); + virtual void update_stats(size_t length); }; class AioImageFlush : public AioImageRequest { @@ -121,11 +151,8 @@ public: : AioImageRequest(image_ctx, aio_comp) { } - virtual bool is_write_op() const { - return false; - } protected: - virtual void execute_request(); + virtual void send_request(); virtual const char *get_request_type() const { return "aio_flush"; } diff --git a/src/librbd/AioImageRequestWQ.cc b/src/librbd/AioImageRequestWQ.cc index bef86c0933e6..6d5fffde5a4e 100644 --- a/src/librbd/AioImageRequestWQ.cc +++ b/src/librbd/AioImageRequestWQ.cc @@ -89,7 +89,7 @@ void AioImageRequestWQ::aio_read(AioCompletion *c, uint64_t off, size_t len, queue(new AioImageRead(m_image_ctx, c, off, len, buf, pbl, op_flags), false); } else { - AioImageRequest::read(&m_image_ctx, c, off, len, buf, pbl, op_flags); + AioImageRequest::aio_read(&m_image_ctx, c, off, len, buf, pbl, op_flags); } } @@ -107,7 +107,7 @@ void AioImageRequestWQ::aio_write(AioCompletion *c, uint64_t off, size_t len, queue(new AioImageWrite(m_image_ctx, c, off, len, buf, op_flags), lock_required); } else { - AioImageRequest::write(&m_image_ctx, c, off, len, buf, op_flags); + AioImageRequest::aio_write(&m_image_ctx, c, off, len, buf, op_flags); } } @@ -125,7 +125,7 @@ void AioImageRequestWQ::aio_discard(AioCompletion *c, uint64_t off, queue(new AioImageDiscard(m_image_ctx, c, off, len), lock_required); } else { - AioImageRequest::discard(&m_image_ctx, c, off, len); + AioImageRequest::aio_discard(&m_image_ctx, c, off, len); } } @@ -139,7 +139,7 @@ void AioImageRequestWQ::aio_flush(AioCompletion *c) { if (m_image_ctx.non_blocking_aio || !writes_empty()) { queue(new AioImageFlush(m_image_ctx, c), false); } else { - AioImageRequest::flush(&m_image_ctx, c); + AioImageRequest::aio_flush(&m_image_ctx, c); } } diff --git a/src/librbd/AioObjectRequest.cc b/src/librbd/AioObjectRequest.cc index 95dda4b012eb..48e98371f9a5 100644 --- a/src/librbd/AioObjectRequest.cc +++ b/src/librbd/AioObjectRequest.cc @@ -273,8 +273,8 @@ namespace librbd { << " extents " << parent_extents << dendl; RWLock::RLocker owner_locker(m_ictx->parent->owner_lock); - AioImageRequest::read(m_ictx->parent, m_parent_completion, parent_extents, - NULL, &m_read_data, 0); + AioImageRequest::aio_read(m_ictx->parent, m_parent_completion, + parent_extents, NULL, &m_read_data, 0); } /** write **/ diff --git a/src/librbd/CopyupRequest.cc b/src/librbd/CopyupRequest.cc index 9ac6ca6f853c..eff12ff645aa 100644 --- a/src/librbd/CopyupRequest.cc +++ b/src/librbd/CopyupRequest.cc @@ -187,8 +187,8 @@ private: << ", extents " << m_image_extents << dendl; RWLock::RLocker owner_locker(m_ictx->parent->owner_lock); - AioImageRequest::read(m_ictx->parent, comp, m_image_extents, NULL, - &m_copyup_data, 0); + AioImageRequest::aio_read(m_ictx->parent, comp, m_image_extents, NULL, + &m_copyup_data, 0); } void CopyupRequest::queue_send() diff --git a/src/librbd/internal.cc b/src/librbd/internal.cc index 794102b62b63..a0c76070737d 100644 --- a/src/librbd/internal.cc +++ b/src/librbd/internal.cc @@ -2891,8 +2891,9 @@ reprotect_and_return_err: RWLock::RLocker owner_lock(m_dest->owner_lock); Context *ctx = new C_CopyWrite(m_throttle, m_bl); AioCompletion *comp = aio_create_completion_internal(ctx, rbd_ctx_cb); - AioImageRequest::write(m_dest, comp, m_offset, m_bl->length(), - m_bl->c_str(), LIBRADOS_OP_FLAG_FADVISE_DONTNEED); + AioImageRequest::aio_write(m_dest, comp, m_offset, m_bl->length(), + m_bl->c_str(), + LIBRADOS_OP_FLAG_FADVISE_DONTNEED); } private: SimpleThrottle *m_throttle; @@ -2945,7 +2946,8 @@ reprotect_and_return_err: bufferlist *bl = new bufferlist(); Context *ctx = new C_CopyRead(&throttle, dest, offset, bl); AioCompletion *comp = aio_create_completion_internal(ctx, rbd_ctx_cb); - AioImageRequest::read(src, comp, offset, len, NULL, bl, fadvise_flags); + AioImageRequest::aio_read(src, comp, offset, len, NULL, bl, + fadvise_flags); prog_ctx.update_progress(offset, src_size); } @@ -3473,7 +3475,7 @@ reprotect_and_return_err: Context *ctx = new C_SafeCond(&mylock, &cond, &done, &ret); AioCompletion *c = aio_create_completion_internal(ctx, rbd_ctx_cb); - AioImageRequest::read(ictx, c, off, read_len, NULL, &bl, 0); + AioImageRequest::aio_read(ictx, c, off, read_len, NULL, &bl, 0); mylock.Lock(); while (!done)