From 5891b57a6f76951660fde9689a607e689121882c Mon Sep 17 00:00:00 2001 From: wangzhengyong Date: Mon, 12 Jun 2017 21:21:55 +0800 Subject: [PATCH] test/librbd: handle cmpext request in LibradosTestStub Signed-off-by: Zhengyong Wang --- .../librados_test_stub/LibradosTestStub.cc | 16 ++++++ src/test/librados_test_stub/TestIoCtxImpl.h | 1 + .../librados_test_stub/TestMemIoCtxImpl.cc | 32 ++++++++++- .../librados_test_stub/TestMemIoCtxImpl.h | 1 + src/test/librbd/io/test_mock_ImageRequest.cc | 53 +++++++++++++++++++ 5 files changed, 102 insertions(+), 1 deletion(-) diff --git a/src/test/librados_test_stub/LibradosTestStub.cc b/src/test/librados_test_stub/LibradosTestStub.cc index 2a64837fbc317..fd67877bf0dbb 100644 --- a/src/test/librados_test_stub/LibradosTestStub.cc +++ b/src/test/librados_test_stub/LibradosTestStub.cc @@ -689,6 +689,12 @@ int IoCtx::writesame(const std::string& oid, bufferlist& bl, size_t len, ctx->get_snap_context())); } +int IoCtx::cmpext(const std::string& oid, uint64_t off, bufferlist& cmp_bl) { + TestIoCtxImpl *ctx = reinterpret_cast(io_ctx_impl); + return ctx->execute_operation( + oid, boost::bind(&TestIoCtxImpl::cmpext, _1, _2, off, cmp_bl)); +} + int IoCtx::application_enable(const std::string& app_name, bool force) { return 0; } @@ -765,6 +771,16 @@ size_t ObjectOperation::size() { return o->ops.size(); } +void ObjectOperation::cmpext(uint64_t off, bufferlist& cmp_bl, int *prval) { + TestObjectOperationImpl *o = reinterpret_cast(impl); + ObjectOperationTestImpl op = boost::bind(&TestIoCtxImpl::cmpext, _1, _2, off, cmp_bl); + if (prval != NULL) { + op = boost::bind(save_operation_result, + boost::bind(op, _1, _2, _3, _4), prval); + } + o->ops.push_back(op); +} + void ObjectReadOperation::list_snaps(snap_set_t *out_snaps, int *prval) { TestObjectOperationImpl *o = reinterpret_cast(impl); diff --git a/src/test/librados_test_stub/TestIoCtxImpl.h b/src/test/librados_test_stub/TestIoCtxImpl.h index 04629d128ff0c..2ba13fdcd3804 100644 --- a/src/test/librados_test_stub/TestIoCtxImpl.h +++ b/src/test/librados_test_stub/TestIoCtxImpl.h @@ -147,6 +147,7 @@ public: const SnapContext &snapc) = 0; virtual int writesame(const std::string& oid, bufferlist& bl, size_t len, uint64_t off, const SnapContext &snapc) = 0; + virtual int cmpext(const std::string& oid, uint64_t off, bufferlist& cmp_bl) = 0; virtual int xattr_get(const std::string& oid, std::map* attrset) = 0; virtual int xattr_set(const std::string& oid, const std::string &name, diff --git a/src/test/librados_test_stub/TestMemIoCtxImpl.cc b/src/test/librados_test_stub/TestMemIoCtxImpl.cc index ab4137ff12cc2..908bad32fba94 100644 --- a/src/test/librados_test_stub/TestMemIoCtxImpl.cc +++ b/src/test/librados_test_stub/TestMemIoCtxImpl.cc @@ -5,6 +5,7 @@ #include "test/librados_test_stub/TestMemRadosClient.h" #include "common/Clock.h" #include "common/RWLock.h" +#include "include/err.h" #include #include #include @@ -557,7 +558,6 @@ int TestMemIoCtxImpl::writesame(const std::string& oid, bufferlist& bl, size_t l return -EBLACKLISTED; } - if (len == 0 || (len % bl.length())) { return -EINVAL; } @@ -585,6 +585,36 @@ int TestMemIoCtxImpl::writesame(const std::string& oid, bufferlist& bl, size_t l return 0; } +int TestMemIoCtxImpl::cmpext(const std::string& oid, uint64_t off, + bufferlist& cmp_bl) { + if (get_snap_read() != CEPH_NOSNAP) { + return -EROFS; + } else if (m_client->is_blacklisted()) { + return -EBLACKLISTED; + } + + if (cmp_bl.length() == 0) { + return -EINVAL; + } + + TestMemCluster::SharedFile file; + { + RWLock::WLocker l(m_pool->file_lock); + file = get_file(oid, true, get_snap_context()); + } + + RWLock::RLocker l(file->lock); + size_t len = cmp_bl.length(); + ensure_minimum_length(off + len, &file->data); + if (len > 0 && off <= len) { + for (uint64_t p = off; p < len; p++) { + if (file->data[p] != cmp_bl[p]) + return -MAX_ERRNO - p; + } + } + return 0; +} + int TestMemIoCtxImpl::xattr_get(const std::string& oid, std::map* attrset) { if (m_client->is_blacklisted()) { diff --git a/src/test/librados_test_stub/TestMemIoCtxImpl.h b/src/test/librados_test_stub/TestMemIoCtxImpl.h index 9c9519f803b81..9f63b7daee1bf 100644 --- a/src/test/librados_test_stub/TestMemIoCtxImpl.h +++ b/src/test/librados_test_stub/TestMemIoCtxImpl.h @@ -57,6 +57,7 @@ public: const SnapContext &snapc) override; int writesame(const std::string& oid, bufferlist& bl, size_t len, uint64_t off, const SnapContext &snapc) override; + int cmpext(const std::string& oid, uint64_t off, bufferlist& cmp_bl) override; int xattr_get(const std::string& oid, std::map* attrset) override; int xattr_set(const std::string& oid, const std::string &name, diff --git a/src/test/librbd/io/test_mock_ImageRequest.cc b/src/test/librbd/io/test_mock_ImageRequest.cc index 7a11c2c6ab1c6..4aca8a8d9ce69 100644 --- a/src/test/librbd/io/test_mock_ImageRequest.cc +++ b/src/test/librbd/io/test_mock_ImageRequest.cc @@ -97,6 +97,22 @@ struct ObjectRequest : public ObjectRequestHandle { return s_instance; } + static ObjectRequest* create_compare_and_write(librbd::MockTestImageCtx *ictx, + const std::string &oid, + uint64_t object_no, + uint64_t object_off, + const ceph::bufferlist &cmp_data, + const ceph::bufferlist &write_data, + const ::SnapContext &snapc, + uint64_t *mismatch_offset, + int op_flags, + const ZTracer::Trace &parent_trace, + Context *completion) { + assert(s_instance != nullptr); + s_instance->on_finish = completion; + return s_instance; + } + ObjectRequest() { assert(s_instance == nullptr); s_instance = this; @@ -168,6 +184,7 @@ struct TestMockIoImageRequest : public TestMockFixture { typedef ImageDiscardRequest MockImageDiscardRequest; typedef ImageFlushRequest MockImageFlushRequest; typedef ImageWriteSameRequest MockImageWriteSameRequest; + typedef ImageCompareAndWriteRequest MockImageCompareAndWriteRequest; typedef ObjectRequest MockObjectRequest; typedef ObjectReadRequest MockObjectReadRequest; @@ -334,5 +351,41 @@ TEST_F(TestMockIoImageRequest, AioWriteSameJournalAppendDisabled) { ASSERT_EQ(0, aio_comp_ctx.wait()); } +TEST_F(TestMockIoImageRequest, AioCompareAndWriteJournalAppendDisabled) { + REQUIRE_FEATURE(RBD_FEATURE_JOURNALING); + + librbd::ImageCtx *ictx; + ASSERT_EQ(0, open_image(m_image_name, &ictx)); + + MockObjectRequest mock_aio_object_request; + MockTestImageCtx mock_image_ctx(*ictx); + MockJournal mock_journal; + mock_image_ctx.journal = &mock_journal; + + InSequence seq; + expect_is_journal_appending(mock_journal, false); + expect_object_request_send(mock_image_ctx, mock_aio_object_request, 0); + + C_SaferCond aio_comp_ctx; + AioCompletion *aio_comp = AioCompletion::create_and_start( + &aio_comp_ctx, ictx, AIO_TYPE_COMPARE_AND_WRITE); + + bufferlist cmp_bl; + cmp_bl.append("1"); + bufferlist write_bl; + write_bl.append("1"); + uint64_t mismatch_offset; + MockImageCompareAndWriteRequest mock_aio_image_write(mock_image_ctx, aio_comp, + {{0, 1}}, std::move(cmp_bl), + std::move(write_bl), + &mismatch_offset, + 0, {}); + { + RWLock::RLocker owner_locker(mock_image_ctx.owner_lock); + mock_aio_image_write.send(); + } + ASSERT_EQ(0, aio_comp_ctx.wait()); +} + } // namespace io } // namespace librbd -- 2.39.5