From e70d48933ca2509350b664e8c4e772c1c24ba1d5 Mon Sep 17 00:00:00 2001 From: wangzhengyong Date: Mon, 12 Jun 2017 21:18:29 +0800 Subject: [PATCH] librbd: add compare_and_write/aio_compare_and_write API Signed-off-by: Zhengyong Wang --- src/include/rbd/librbd.h | 10 ++++ src/include/rbd/librbd.hpp | 5 ++ src/librbd/io/AioCompletion.cc | 2 + src/librbd/librbd.cc | 94 ++++++++++++++++++++++++++++++++++ src/tracing/librbd.tp | 65 +++++++++++++++++++++++ 5 files changed, 176 insertions(+) diff --git a/src/include/rbd/librbd.h b/src/include/rbd/librbd.h index dca8f42370413..9a21c4af5daaa 100644 --- a/src/include/rbd/librbd.h +++ b/src/include/rbd/librbd.h @@ -701,6 +701,11 @@ CEPH_RBD_API ssize_t rbd_write2(rbd_image_t image, uint64_t ofs, size_t len, CEPH_RBD_API int rbd_discard(rbd_image_t image, uint64_t ofs, uint64_t len); CEPH_RBD_API ssize_t rbd_writesame(rbd_image_t image, uint64_t ofs, size_t len, const char *buf, size_t data_len, int op_flags); +CEPH_RBD_API ssize_t rbd_compare_and_write(rbd_image_t image, uint64_t ofs, + size_t len, const char *cmp_buf, + const char *buf, uint64_t *mismatch_off, + int op_flags); + CEPH_RBD_API int rbd_aio_write(rbd_image_t image, uint64_t off, size_t len, const char *buf, rbd_completion_t c); @@ -726,6 +731,11 @@ CEPH_RBD_API int rbd_aio_discard(rbd_image_t image, uint64_t off, uint64_t len, CEPH_RBD_API int rbd_aio_writesame(rbd_image_t image, uint64_t off, size_t len, const char *buf, size_t data_len, rbd_completion_t c, int op_flags); +CEPH_RBD_API ssize_t rbd_aio_compare_and_write(rbd_image_t image, + uint64_t off, size_t len, + const char *cmp_buf, const char *buf, + rbd_completion_t c, uint64_t *mismatch_off, + int op_flags); CEPH_RBD_API int rbd_aio_create_completion(void *cb_arg, rbd_callback_t complete_cb, diff --git a/src/include/rbd/librbd.hpp b/src/include/rbd/librbd.hpp index b8e7456920531..bbf4270bc245d 100644 --- a/src/include/rbd/librbd.hpp +++ b/src/include/rbd/librbd.hpp @@ -376,6 +376,8 @@ public: ssize_t write2(uint64_t ofs, size_t len, ceph::bufferlist& bl, int op_flags); int discard(uint64_t ofs, uint64_t len); ssize_t writesame(uint64_t ofs, size_t len, ceph::bufferlist &bl, int op_flags); + ssize_t compare_and_write(uint64_t ofs, size_t len, ceph::bufferlist &cmp_bl, + ceph::bufferlist& bl, uint64_t *mismatch_off, int op_flags); int aio_write(uint64_t off, size_t len, ceph::bufferlist& bl, RBD::AioCompletion *c); /* @param op_flags see librados.h constants beginning with LIBRADOS_OP_FLAG */ @@ -383,6 +385,9 @@ public: RBD::AioCompletion *c, int op_flags); int aio_writesame(uint64_t off, size_t len, ceph::bufferlist& bl, RBD::AioCompletion *c, int op_flags); + int aio_compare_and_write(uint64_t off, size_t len, ceph::bufferlist& cmp_bl, + ceph::bufferlist& bl, RBD::AioCompletion *c, + uint64_t *mismatch_off, int op_flags); /** * read async from image * diff --git a/src/librbd/io/AioCompletion.cc b/src/librbd/io/AioCompletion.cc index cc40e8ffbe1af..1dc6280959c2e 100644 --- a/src/librbd/io/AioCompletion.cc +++ b/src/librbd/io/AioCompletion.cc @@ -74,6 +74,8 @@ void AioCompletion::complete() { ictx->perfcounter->tinc(l_librbd_aio_flush_latency, elapsed); break; case AIO_TYPE_WRITESAME: ictx->perfcounter->tinc(l_librbd_ws_latency, elapsed); break; + case AIO_TYPE_COMPARE_AND_WRITE: + ictx->perfcounter->tinc(l_librbd_cmp_latency, elapsed); break; default: lderr(cct) << "completed invalid aio_type: " << aio_type << dendl; break; diff --git a/src/librbd/librbd.cc b/src/librbd/librbd.cc index 1d5920fccb308..542dd28ab38d1 100644 --- a/src/librbd/librbd.cc +++ b/src/librbd/librbd.cc @@ -1636,6 +1636,29 @@ namespace librbd { return r; } + ssize_t Image::compare_and_write(uint64_t ofs, size_t len, + ceph::bufferlist &cmp_bl, ceph::bufferlist& bl, + uint64_t *mismatch_off, int op_flags) + { + ImageCtx *ictx = (ImageCtx *)ctx; + tracepoint(librbd, compare_and_write_enter, ictx, ictx->name.c_str(), + ictx->snap_name.c_str(), + ictx->read_only, ofs, len, cmp_bl.length() < len ? NULL : cmp_bl.c_str(), + bl.length() < len ? NULL : bl.c_str(), op_flags); + + if (bl.length() < len) { + tracepoint(librbd, write_exit, -EINVAL); + return -EINVAL; + } + + int r = ictx->io_work_queue->compare_and_write(ofs, len, bufferlist{cmp_bl}, + bufferlist{bl}, mismatch_off, + op_flags); + + tracepoint(librbd, compare_and_write_exit, r); + + return r; + } int Image::aio_write(uint64_t off, size_t len, bufferlist& bl, RBD::AioCompletion *c) { @@ -1745,6 +1768,30 @@ namespace librbd { return 0; } + int Image::aio_compare_and_write(uint64_t off, size_t len, + ceph::bufferlist& cmp_bl, ceph::bufferlist& bl, + RBD::AioCompletion *c, uint64_t *mismatch_off, + int op_flags) + { + ImageCtx *ictx = (ImageCtx *)ctx; + tracepoint(librbd, aio_compare_and_write_enter, ictx, ictx->name.c_str(), + ictx->snap_name.c_str(), + ictx->read_only, off, len, cmp_bl.length() < len ? NULL : cmp_bl.c_str(), + bl.length() < len ? NULL : bl.c_str(), c->pc, op_flags); + + if (bl.length() < len) { + tracepoint(librbd, compare_and_write_exit, -EINVAL); + return -EINVAL; + } + + ictx->io_work_queue->aio_compare_and_write(get_aio_completion(c), off, len, + bufferlist{cmp_bl}, bufferlist{bl}, + mismatch_off, op_flags, false); + + tracepoint(librbd, aio_compare_and_write_exit, 0); + + return 0; + } int Image::invalidate_cache() { @@ -3547,6 +3594,30 @@ extern "C" ssize_t rbd_writesame(rbd_image_t image, uint64_t ofs, size_t len, return r; } +extern "C" ssize_t rbd_compare_and_write(rbd_image_t image, + uint64_t ofs, size_t len, + const char *cmp_buf, + const char *buf, + uint64_t *mismatch_off, + int op_flags) +{ + librbd::ImageCtx *ictx = (librbd::ImageCtx *)image; + tracepoint(librbd, compare_and_write_enter, ictx, ictx->name.c_str(), + ictx->snap_name.c_str(), ictx->read_only, ofs, + len, cmp_buf, buf, op_flags); + + bufferlist cmp_bl; + cmp_bl.push_back(create_write_raw(ictx, cmp_buf, len)); + bufferlist bl; + bl.push_back(create_write_raw(ictx, buf, len)); + + int r = ictx->io_work_queue->compare_and_write(ofs, len, std::move(cmp_bl), + std::move(bl), mismatch_off, + op_flags); + tracepoint(librbd, compare_and_write_exit, r); + return r; +} + extern "C" int rbd_aio_create_completion(void *cb_arg, rbd_callback_t complete_cb, rbd_completion_t *c) @@ -3745,6 +3816,29 @@ extern "C" int rbd_aio_writesame(rbd_image_t image, uint64_t off, size_t len, return 0; } +extern "C" ssize_t rbd_aio_compare_and_write(rbd_image_t image, uint64_t off, + size_t len, const char *cmp_buf, + const char *buf, rbd_completion_t c, + uint64_t *mismatch_off, + int op_flags) +{ + librbd::ImageCtx *ictx = (librbd::ImageCtx *)image; + librbd::RBD::AioCompletion *comp = (librbd::RBD::AioCompletion *)c; + tracepoint(librbd, aio_compare_and_write_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), + ictx->read_only, off, len, cmp_buf, buf, comp->pc, op_flags); + + bufferlist cmp_bl; + cmp_bl.push_back(create_write_raw(ictx, cmp_buf, len)); + bufferlist bl; + bl.push_back(create_write_raw(ictx, buf, len)); + ictx->io_work_queue->aio_compare_and_write(get_aio_completion(comp), off, len, + std::move(cmp_bl), std::move(bl), + mismatch_off, op_flags, false); + + tracepoint(librbd, aio_compare_and_write_exit, 0); + return 0; +} + extern "C" int rbd_invalidate_cache(rbd_image_t image) { librbd::ImageCtx *ictx = (librbd::ImageCtx *)image; diff --git a/src/tracing/librbd.tp b/src/tracing/librbd.tp index f8c77142a7842..5b8d396613144 100644 --- a/src/tracing/librbd.tp +++ b/src/tracing/librbd.tp @@ -204,6 +204,37 @@ TRACEPOINT_EVENT(librbd, writesame_exit, ) ) +TRACEPOINT_EVENT(librbd, compare_and_write_enter, + TP_ARGS( + void*, imagectx, + const char*, name, + const char*, snap_name, + char, read_only, + uint64_t, off, + size_t, len, + const char*, cmp_buf, + const char*, buf, + int, op_flags), + TP_FIELDS( + ctf_integer_hex(void*, imagectx, imagectx) + ctf_string(name, name) + ctf_string(snap_name, snap_name) + ctf_integer(char, read_only, read_only) + ctf_integer(uint64_t, off, off) + ceph_ctf_sequence(unsigned char, cmp_buf, cmp_buf, size_t, len) + ceph_ctf_sequence(unsigned char, buf, buf, size_t, len) + ctf_integer(int, op_flags, op_flags) + ) +) + +TRACEPOINT_EVENT(librbd, compare_and_write_exit, + TP_ARGS( + ssize_t, retval), + TP_FIELDS( + ctf_integer(ssize_t, retval, retval) + ) +) + TRACEPOINT_EVENT(librbd, open_image_by_id_enter, TP_ARGS( void*, imagectx, @@ -1159,6 +1190,40 @@ TRACEPOINT_EVENT(librbd, aio_writesame_exit, ) ) +TRACEPOINT_EVENT(librbd, aio_compare_and_write_enter, + TP_ARGS( + void*, imagectx, + const char*, name, + const char*, snap_name, + char, read_only, + uint64_t, off, + size_t, len, + const char*, cmp_buf, + const char*, buf, + const void*, completion, + int, op_flags), + TP_FIELDS( + ctf_integer_hex(void*, imagectx, imagectx) + ctf_string(name, name) + ctf_string(snap_name, snap_name) + ctf_integer(char, read_only, read_only) + ctf_integer(uint64_t, off, off) + ctf_integer(size_t, len, len) + ceph_ctf_sequence(unsigned char, cmp_buf, cmp_buf, size_t, len) + ceph_ctf_sequence(unsigned char, buf, buf, size_t, len) + ctf_integer_hex(const void*, completion, completion) + ctf_integer(int, op_flags, op_flags) + ) +) +TRACEPOINT_EVENT(librbd, aio_compare_and_write_exit, + TP_ARGS( + int, retval), + TP_FIELDS( + ctf_integer(int, retval, retval) + ) +) + + TRACEPOINT_EVENT(librbd, clone_enter, TP_ARGS( const char*, parent_pool_name, -- 2.39.5