From: Jason Dillaman Date: Mon, 20 Apr 2015 16:12:05 +0000 (-0400) Subject: librados_test_stub: support AIO snapshot context X-Git-Tag: v9.0.2~225^2~10 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=12719478ad5265020b8d3322185bb786c8b51907;p=ceph.git librados_test_stub: support AIO snapshot context AIO operations can be executed with a different snapshot context from the IoCtx. librbd takes advantage of this capability to perform a deep object copyup. Signed-off-by: Jason Dillaman --- diff --git a/src/test/librados_test_stub/LibradosTestStub.cc b/src/test/librados_test_stub/LibradosTestStub.cc index fb0812043b72..4e1c0075ae76 100644 --- a/src/test/librados_test_stub/LibradosTestStub.cc +++ b/src/test/librados_test_stub/LibradosTestStub.cc @@ -395,7 +395,8 @@ void IoCtx::dup(const IoCtx& rhs) { int IoCtx::exec(const std::string& oid, const char *cls, const char *method, bufferlist& inbl, bufferlist& outbl) { TestIoCtxImpl *ctx = reinterpret_cast(io_ctx_impl); - return ctx->exec(oid, *get_class_handler(), cls, method, inbl, &outbl); + return ctx->exec(oid, *get_class_handler(), cls, method, inbl, &outbl, + ctx->get_snap_context()); } void IoCtx::from_rados_ioctx_t(rados_ioctx_t p, IoCtx &io) { @@ -548,12 +549,12 @@ int IoCtx::watch2(const std::string& o, uint64_t *handle, int IoCtx::write(const std::string& oid, bufferlist& bl, size_t len, uint64_t off) { TestIoCtxImpl *ctx = reinterpret_cast(io_ctx_impl); - return ctx->write(oid, bl, len, off); + return ctx->write(oid, bl, len, off, ctx->get_snap_context()); } int IoCtx::write_full(const std::string& oid, bufferlist& bl) { TestIoCtxImpl *ctx = reinterpret_cast(io_ctx_impl); - return ctx->write_full(oid, bl); + return ctx->write_full(oid, bl, ctx->get_snap_context()); } static int save_operation_result(int result, int *pval) { @@ -587,7 +588,7 @@ void ObjectOperation::exec(const char *cls, const char *method, TestObjectOperationImpl *o = reinterpret_cast(impl); o->ops.push_back(boost::bind(&TestIoCtxImpl::exec, _1, _2, boost::ref(*get_class_handler()), - cls, method, inbl, _3)); + cls, method, inbl, _3, _4)); } void ObjectOperation::set_op_flags2(int flags) { @@ -605,7 +606,7 @@ void ObjectReadOperation::list_snaps(snap_set_t *out_snaps, int *prval) { out_snaps); if (prval != NULL) { op = boost::bind(save_operation_result, - boost::bind(op, _1, _2, _3), prval); + boost::bind(op, _1, _2, _3, _4), prval); } o->ops.push_back(op); } @@ -623,7 +624,7 @@ void ObjectReadOperation::read(size_t off, uint64_t len, bufferlist *pbl, if (prval != NULL) { op = boost::bind(save_operation_result, - boost::bind(op, _1, _2, _3), prval); + boost::bind(op, _1, _2, _3, _4), prval); } o->ops.push_back(op); } @@ -642,7 +643,7 @@ void ObjectReadOperation::sparse_read(uint64_t off, uint64_t len, if (prval != NULL) { op = boost::bind(save_operation_result, - boost::bind(op, _1, _2, _3), prval); + boost::bind(op, _1, _2, _3, _4), prval); } o->ops.push_back(op); } @@ -683,12 +684,12 @@ void ObjectWriteOperation::truncate(uint64_t off) { void ObjectWriteOperation::write(uint64_t off, const bufferlist& bl) { TestObjectOperationImpl *o = reinterpret_cast(impl); o->ops.push_back(boost::bind(&TestIoCtxImpl::write, _1, _2, bl, bl.length(), - off)); + off, _4)); } void ObjectWriteOperation::write_full(const bufferlist& bl) { TestObjectOperationImpl *o = reinterpret_cast(impl); - o->ops.push_back(boost::bind(&TestIoCtxImpl::write_full, _1, _2, bl)); + o->ops.push_back(boost::bind(&TestIoCtxImpl::write_full, _1, _2, bl, _4)); } void ObjectWriteOperation::zero(uint64_t off, uint64_t len) { @@ -990,13 +991,13 @@ int cls_cxx_write(cls_method_context_t hctx, int ofs, int len, bufferlist *inbl) { librados::TestClassHandler::MethodContext *ctx = reinterpret_cast(hctx); - return ctx->io_ctx_impl->write(ctx->oid, *inbl, len, ofs); + return ctx->io_ctx_impl->write(ctx->oid, *inbl, len, ofs, ctx->snapc); } int cls_cxx_write_full(cls_method_context_t hctx, bufferlist *inbl) { librados::TestClassHandler::MethodContext *ctx = reinterpret_cast(hctx); - return ctx->io_ctx_impl->write_full(ctx->oid, *inbl); + return ctx->io_ctx_impl->write_full(ctx->oid, *inbl, ctx->snapc); } int cls_log(int level, const char *format, ...) { diff --git a/src/test/librados_test_stub/TestClassHandler.cc b/src/test/librados_test_stub/TestClassHandler.cc index c7a2e96fd887..e55770f4e43f 100644 --- a/src/test/librados_test_stub/TestClassHandler.cc +++ b/src/test/librados_test_stub/TestClassHandler.cc @@ -100,10 +100,12 @@ cls_method_cxx_call_t TestClassHandler::get_method(const std::string &cls, } TestClassHandler::SharedMethodContext TestClassHandler::get_method_context( - TestIoCtxImpl *io_ctx_impl, const std::string &oid) { + TestIoCtxImpl *io_ctx_impl, const std::string &oid, + const SnapContext &snapc) { SharedMethodContext ctx(new MethodContext()); ctx->io_ctx_impl = io_ctx_impl; ctx->oid = oid; + ctx->snapc = snapc; return ctx; } diff --git a/src/test/librados_test_stub/TestClassHandler.h b/src/test/librados_test_stub/TestClassHandler.h index d921d418463e..97062cec6917 100644 --- a/src/test/librados_test_stub/TestClassHandler.h +++ b/src/test/librados_test_stub/TestClassHandler.h @@ -5,6 +5,7 @@ #define CEPH_TEST_CLASS_HANDLER_H #include "objclass/objclass.h" +#include "common/snap_types.h" #include #include #include @@ -24,6 +25,7 @@ public: struct MethodContext { TestIoCtxImpl *io_ctx_impl; std::string oid; + SnapContext snapc; }; typedef boost::shared_ptr SharedMethodContext; @@ -47,7 +49,8 @@ public: cls_method_cxx_call_t get_method(const std::string &cls, const std::string &method); SharedMethodContext get_method_context(TestIoCtxImpl *io_ctx_impl, - const std::string &oid); + const std::string &oid, + const SnapContext &snapc); private: diff --git a/src/test/librados_test_stub/TestIoCtxImpl.cc b/src/test/librados_test_stub/TestIoCtxImpl.cc index f810906a19e6..36be941bdef2 100644 --- a/src/test/librados_test_stub/TestIoCtxImpl.cc +++ b/src/test/librados_test_stub/TestIoCtxImpl.cc @@ -88,11 +88,12 @@ void TestIoCtxImpl::aio_flush_async(AioCompletionImpl *c) { int TestIoCtxImpl::aio_operate(const std::string& oid, TestObjectOperationImpl &ops, AioCompletionImpl *c, SnapContext *snap_context, int flags) { - // TODO ignoring snap_context and flags for now + // TODO flags for now ops.get(); m_client->add_aio_operation(oid, true, boost::bind( &TestIoCtxImpl::execute_aio_operations, this, oid, &ops, - reinterpret_cast(NULL)), c); + reinterpret_cast(NULL), + snap_context != NULL ? *snap_context : m_snapc), c); return 0; } @@ -103,20 +104,21 @@ int TestIoCtxImpl::aio_operate_read(const std::string& oid, // TODO ignoring flags for now ops.get(); m_client->add_aio_operation(oid, true, boost::bind( - &TestIoCtxImpl::execute_aio_operations, this, oid, &ops, pbl), c); + &TestIoCtxImpl::execute_aio_operations, this, oid, &ops, pbl, m_snapc), c); return 0; } int TestIoCtxImpl::exec(const std::string& oid, TestClassHandler &handler, const char *cls, const char *method, - bufferlist& inbl, bufferlist* outbl) { + bufferlist& inbl, bufferlist* outbl, + const SnapContext &snapc) { cls_method_cxx_call_t call = handler.get_method(cls, method); if (call == NULL) { return -ENOSYS; } return (*call)(reinterpret_cast( - handler.get_method_context(this, oid).get()), &inbl, outbl); + handler.get_method_context(this, oid, snapc).get()), &inbl, outbl); } int TestIoCtxImpl::list_watchers(const std::string& o, @@ -141,7 +143,7 @@ int TestIoCtxImpl::operate(const std::string& oid, TestObjectOperationImpl &ops) ops.get(); m_client->add_aio_operation(oid, false, boost::bind( &TestIoCtxImpl::execute_aio_operations, this, oid, &ops, - reinterpret_cast(NULL)), comp); + reinterpret_cast(NULL), m_snapc), comp); comp->wait_for_safe(); int ret = comp->get_return_value(); @@ -155,7 +157,8 @@ int TestIoCtxImpl::operate_read(const std::string& oid, TestObjectOperationImpl ops.get(); m_client->add_aio_operation(oid, false, boost::bind( - &TestIoCtxImpl::execute_aio_operations, this, oid, &ops, pbl), comp); + &TestIoCtxImpl::execute_aio_operations, this, oid, &ops, pbl, + m_snapc), comp); comp->wait_for_complete(); int ret = comp->get_return_value(); @@ -229,7 +232,7 @@ int TestIoCtxImpl::tmap_update(const std::string& oid, bufferlist& cmdbl) { bufferlist out; ::encode(tmap_header, out); ::encode(tmap, out); - r = write_full(oid, out); + r = write_full(oid, out, m_snapc); return r; } @@ -244,10 +247,12 @@ int TestIoCtxImpl::watch(const std::string& o, uint64_t *handle, int TestIoCtxImpl::execute_aio_operations(const std::string& oid, TestObjectOperationImpl *ops, - bufferlist *pbl) { + bufferlist *pbl, + const SnapContext &snapc) { int ret = 0; - for (ObjectOperations::iterator it = ops->ops.begin(); it != ops->ops.end(); ++it) { - ret = (*it)(this, oid, pbl); + for (ObjectOperations::iterator it = ops->ops.begin(); + it != ops->ops.end(); ++it) { + ret = (*it)(this, oid, pbl, snapc); if (ret < 0) { break; } diff --git a/src/test/librados_test_stub/TestIoCtxImpl.h b/src/test/librados_test_stub/TestIoCtxImpl.h index d21fd667c05e..9c4e98067c90 100644 --- a/src/test/librados_test_stub/TestIoCtxImpl.h +++ b/src/test/librados_test_stub/TestIoCtxImpl.h @@ -18,7 +18,8 @@ class TestRadosClient; typedef boost::function ObjectOperationTestImpl; + bufferlist *, + const SnapContext &)> ObjectOperationTestImpl; typedef std::list ObjectOperations; struct TestObjectOperationImpl { @@ -74,7 +75,8 @@ public: virtual int create(const std::string& oid, bool exclusive) = 0; virtual int exec(const std::string& oid, TestClassHandler &handler, const char *cls, const char *method, - bufferlist& inbl, bufferlist* outbl); + bufferlist& inbl, bufferlist* outbl, + const SnapContext &snapc); virtual int list_snaps(const std::string& o, snap_set_t *out_snaps) = 0; virtual int list_watchers(const std::string& o, std::list *out_watchers); @@ -117,8 +119,9 @@ public: virtual int watch(const std::string& o, uint64_t *handle, librados::WatchCtx *ctx, librados::WatchCtx2 *ctx2); virtual int write(const std::string& oid, bufferlist& bl, size_t len, - uint64_t off) = 0; - virtual int write_full(const std::string& oid, bufferlist& bl) = 0; + uint64_t off, const SnapContext &snapc) = 0; + virtual int write_full(const std::string& oid, bufferlist& bl, + const SnapContext &snapc) = 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, @@ -129,8 +132,9 @@ protected: TestIoCtxImpl(const TestIoCtxImpl& rhs); virtual ~TestIoCtxImpl(); - int execute_aio_operations(const std::string& oid, TestObjectOperationImpl *ops, - bufferlist *pbl); + int execute_aio_operations(const std::string& oid, + TestObjectOperationImpl *ops, + bufferlist *pbl, const SnapContext &snapc); private: diff --git a/src/test/librados_test_stub/TestMemIoCtxImpl.cc b/src/test/librados_test_stub/TestMemIoCtxImpl.cc index 2e6518a174ef..e35416399974 100644 --- a/src/test/librados_test_stub/TestMemIoCtxImpl.cc +++ b/src/test/librados_test_stub/TestMemIoCtxImpl.cc @@ -45,7 +45,8 @@ int TestMemIoCtxImpl::aio_remove(const std::string& oid, AioCompletionImpl *c) { int TestMemIoCtxImpl::assert_exists(const std::string &oid) { RWLock::RLocker l(m_pool->file_lock); - TestMemRadosClient::SharedFile file = get_file(oid, false); + TestMemRadosClient::SharedFile file = get_file(oid, false, + get_snap_context()); if (file == NULL) { return -ENOENT; } @@ -58,7 +59,7 @@ int TestMemIoCtxImpl::create(const std::string& oid, bool exclusive) { } RWLock::WLocker l(m_pool->file_lock); - get_file(oid, true); + get_file(oid, true, get_snap_context()); return 0; } @@ -140,7 +141,7 @@ int TestMemIoCtxImpl::omap_get_vals(const std::string& oid, TestMemRadosClient::SharedFile file; { RWLock::RLocker l(m_pool->file_lock); - file = get_file(oid, false); + file = get_file(oid, false, get_snap_context()); if (file == NULL) { return -ENOENT; } @@ -180,7 +181,7 @@ int TestMemIoCtxImpl::omap_rm_keys(const std::string& oid, TestMemRadosClient::SharedFile file; { RWLock::WLocker l(m_pool->file_lock); - file = get_file(oid, true); + file = get_file(oid, true, get_snap_context()); if (file == NULL) { return -ENOENT; } @@ -203,7 +204,7 @@ int TestMemIoCtxImpl::omap_set(const std::string& oid, TestMemRadosClient::SharedFile file; { RWLock::WLocker l(m_pool->file_lock); - file = get_file(oid, true); + file = get_file(oid, true, get_snap_context()); if (file == NULL) { return -ENOENT; } @@ -225,7 +226,7 @@ int TestMemIoCtxImpl::read(const std::string& oid, size_t len, uint64_t off, TestMemRadosClient::SharedFile file; { RWLock::RLocker l(m_pool->file_lock); - file = get_file(oid, false); + file = get_file(oid, false, get_snap_context()); if (file == NULL) { return -ENOENT; } @@ -250,11 +251,12 @@ int TestMemIoCtxImpl::remove(const std::string& oid) { } RWLock::WLocker l(m_pool->file_lock); - TestMemRadosClient::SharedFile file = get_file(oid, false); + TestMemRadosClient::SharedFile file = get_file(oid, false, + get_snap_context()); if (file == NULL) { return -ENOENT; } - file = get_file(oid, true); + file = get_file(oid, true, get_snap_context()); RWLock::WLocker l2(file->lock); file->exists = false; @@ -340,7 +342,7 @@ int TestMemIoCtxImpl::sparse_read(const std::string& oid, uint64_t off, TestMemRadosClient::SharedFile file; { RWLock::RLocker l(m_pool->file_lock); - file = get_file(oid, false); + file = get_file(oid, false, get_snap_context()); if (file == NULL) { return -ENOENT; } @@ -367,7 +369,7 @@ int TestMemIoCtxImpl::stat(const std::string& oid, uint64_t *psize, TestMemRadosClient::SharedFile file; { RWLock::RLocker l(m_pool->file_lock); - file = get_file(oid, false); + file = get_file(oid, false, get_snap_context()); if (file == NULL) { return -ENOENT; } @@ -391,7 +393,7 @@ int TestMemIoCtxImpl::truncate(const std::string& oid, uint64_t size) { TestMemRadosClient::SharedFile file; { RWLock::WLocker l(m_pool->file_lock); - file = get_file(oid, true); + file = get_file(oid, true, get_snap_context()); } RWLock::WLocker l(file->lock); @@ -419,7 +421,7 @@ int TestMemIoCtxImpl::truncate(const std::string& oid, uint64_t size) { } int TestMemIoCtxImpl::write(const std::string& oid, bufferlist& bl, size_t len, - uint64_t off) { + uint64_t off, const SnapContext &snapc) { if (get_snap_read() != CEPH_NOSNAP) { return -EROFS; } @@ -427,7 +429,7 @@ int TestMemIoCtxImpl::write(const std::string& oid, bufferlist& bl, size_t len, TestMemRadosClient::SharedFile file; { RWLock::WLocker l(m_pool->file_lock); - file = get_file(oid, true); + file = get_file(oid, true, snapc); } RWLock::WLocker l(file->lock); @@ -443,7 +445,8 @@ int TestMemIoCtxImpl::write(const std::string& oid, bufferlist& bl, size_t len, return 0; } -int TestMemIoCtxImpl::write_full(const std::string& oid, bufferlist& bl) { +int TestMemIoCtxImpl::write_full(const std::string& oid, bufferlist& bl, + const SnapContext &snapc) { if (get_snap_read() != CEPH_NOSNAP) { return -EROFS; } @@ -451,7 +454,7 @@ int TestMemIoCtxImpl::write_full(const std::string& oid, bufferlist& bl) { TestMemRadosClient::SharedFile file; { RWLock::WLocker l(m_pool->file_lock); - file = get_file(oid, true); + file = get_file(oid, true, snapc); if (file == NULL) { return -ENOENT; } @@ -494,11 +497,11 @@ int TestMemIoCtxImpl::zero(const std::string& oid, uint64_t off, uint64_t len) { TestMemRadosClient::SharedFile file; { RWLock::WLocker l(m_pool->file_lock); - file = get_file(oid, false); + file = get_file(oid, false, get_snap_context()); if (!file) { return 0; } - file = get_file(oid, true); + file = get_file(oid, true, get_snap_context()); RWLock::RLocker l2(file->lock); if (len > 0 && off + len >= file->data.length()) { @@ -512,7 +515,7 @@ int TestMemIoCtxImpl::zero(const std::string& oid, uint64_t off, uint64_t len) { bufferlist bl; bl.append_zero(len); - return write(oid, bl, len, off); + return write(oid, bl, len, off, get_snap_context()); } void TestMemIoCtxImpl::append_clone(bufferlist& src, bufferlist* dest) { @@ -544,7 +547,7 @@ void TestMemIoCtxImpl::ensure_minimum_length(size_t len, bufferlist *bl) { } TestMemRadosClient::SharedFile TestMemIoCtxImpl::get_file( - const std::string &oid, bool write) { + const std::string &oid, bool write, const SnapContext &snapc) { assert(m_pool->file_lock.is_locked() || m_pool->file_lock.is_wlocked()); assert(!write || m_pool->file_lock.is_wlocked()); @@ -557,7 +560,6 @@ TestMemRadosClient::SharedFile TestMemIoCtxImpl::get_file( } if (write) { - const SnapContext &snapc = get_snap_context(); bool new_version = false; if (!file || !file->exists) { file = TestMemRadosClient::SharedFile(new TestMemRadosClient::File()); @@ -572,11 +574,13 @@ TestMemRadosClient::SharedFile TestMemIoCtxImpl::get_file( } } - uint64_t prev_size = file->data.length(); + bufferlist prev_data = file->data; file = TestMemRadosClient::SharedFile( new TestMemRadosClient::File(*file)); - if (prev_size > 0) { - file->snap_overlap.insert(0, prev_size); + file->data.clear(); + append_clone(prev_data, &file->data); + if (prev_data.length() > 0) { + file->snap_overlap.insert(0, prev_data.length()); } new_version = true; } diff --git a/src/test/librados_test_stub/TestMemIoCtxImpl.h b/src/test/librados_test_stub/TestMemIoCtxImpl.h index 68adf2105e0b..bde6ba0ed5f6 100644 --- a/src/test/librados_test_stub/TestMemIoCtxImpl.h +++ b/src/test/librados_test_stub/TestMemIoCtxImpl.h @@ -45,8 +45,9 @@ public: virtual int stat(const std::string& oid, uint64_t *psize, time_t *pmtime); virtual int truncate(const std::string& oid, uint64_t size); virtual int write(const std::string& oid, bufferlist& bl, size_t len, - uint64_t off); - virtual int write_full(const std::string& oid, bufferlist& bl); + uint64_t off, const SnapContext &snapc); + virtual int write_full(const std::string& oid, bufferlist& bl, + const SnapContext &snapc); virtual int xattr_get(const std::string& oid, std::map* attrset); virtual int xattr_set(const std::string& oid, const std::string &name, @@ -63,7 +64,8 @@ private: size_t clip_io(size_t off, size_t len, size_t bl_len); void ensure_minimum_length(size_t len, bufferlist *bl); - TestMemRadosClient::SharedFile get_file(const std::string &oid, bool write); + TestMemRadosClient::SharedFile get_file(const std::string &oid, bool write, + const SnapContext &snapc); };