test/librbd: handle cmpext request in LibradosTestStub

Signed-off-by: Zhengyong Wang <wangzhengyong@cmss.chinamobile.com>
This commit is contained in:
wangzhengyong 2017-06-12 21:21:55 +08:00 committed by Jason Dillaman
parent e70d48933c
commit 5891b57a6f
5 changed files with 102 additions and 1 deletions

View 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);

View 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,

View 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()) {

View 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,

View 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