]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
test/librbd: handle cmpext request in LibradosTestStub
authorwangzhengyong <wangzhengyong@cmss.chinamobile.com>
Mon, 12 Jun 2017 13:21:55 +0000 (21:21 +0800)
committerJason Dillaman <dillaman@redhat.com>
Wed, 26 Jul 2017 12:00:06 +0000 (08:00 -0400)
Signed-off-by: Zhengyong Wang <wangzhengyong@cmss.chinamobile.com>
src/test/librados_test_stub/LibradosTestStub.cc
src/test/librados_test_stub/TestIoCtxImpl.h
src/test/librados_test_stub/TestMemIoCtxImpl.cc
src/test/librados_test_stub/TestMemIoCtxImpl.h
src/test/librbd/io/test_mock_ImageRequest.cc

index 2a64837fbc317dab52f2b978ebc073f1540bc766..fd67877bf0dbb12aa49531185277d7f8c3880f33 100644 (file)
@@ -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<TestIoCtxImpl*>(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<TestObjectOperationImpl*>(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<TestObjectOperationImpl*>(impl);
 
index 04629d128ff0c6206a6c38724db47ad4bcdeef15..2ba13fdcd38042e8ebdf9c3ad92b76e40d813328 100644 (file)
@@ -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<std::string, bufferlist>* attrset) = 0;
   virtual int xattr_set(const std::string& oid, const std::string &name,
index ab4137ff12cc283f8e3b6e4b0acb043c38e683fd..908bad32fba9483948811e4e2be731a02a41642b 100644 (file)
@@ -5,6 +5,7 @@
 #include "test/librados_test_stub/TestMemRadosClient.h"
 #include "common/Clock.h"
 #include "common/RWLock.h"
+#include "include/err.h"
 #include <boost/algorithm/string/predicate.hpp>
 #include <boost/bind.hpp>
 #include <errno.h>
@@ -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<std::string, bufferlist>* attrset) {
   if (m_client->is_blacklisted()) {
index 9c9519f803b815f96a295baa19804215240777c7..9f63b7daee1bf71d9e133ad81e8520a9ac3c5739 100644 (file)
@@ -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<std::string, bufferlist>* attrset) override;
   int xattr_set(const std::string& oid, const std::string &name,
index 7a11c2c6ab1c63b7eb264575181be705e060bfdb..4aca8a8d9ce69c99119fb937355b3e6ff56cea4a 100644 (file)
@@ -97,6 +97,22 @@ struct ObjectRequest<librbd::MockTestImageCtx> : 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<librbd::MockTestImageCtx> MockImageDiscardRequest;
   typedef ImageFlushRequest<librbd::MockTestImageCtx> MockImageFlushRequest;
   typedef ImageWriteSameRequest<librbd::MockTestImageCtx> MockImageWriteSameRequest;
+  typedef ImageCompareAndWriteRequest<librbd::MockTestImageCtx> MockImageCompareAndWriteRequest;
   typedef ObjectRequest<librbd::MockTestImageCtx> MockObjectRequest;
   typedef ObjectReadRequest<librbd::MockTestImageCtx> 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