#include "librbd/ImageCtx.h"
#include "librbd/ImageState.h"
#include "librbd/Operations.h"
+#include "osdc/Striper.h"
#include "test/librados_test_stub/MockTestMemIoCtxImpl.h"
#include "test/librbd/mock/MockImageCtx.h"
#include "tools/rbd_mirror/image_sync/SnapshotCreateRequest.h"
ASSERT_EQ(0, open_image(m_local_io_ctx, m_image_name, &m_local_image_ctx));
}
+ void expect_test_features(librbd::MockImageCtx &mock_image_ctx,
+ uint64_t features, bool enabled) {
+ EXPECT_CALL(mock_image_ctx, test_features(features))
+ .WillOnce(Return(enabled));
+ }
+
void expect_set_size(librbd::MockImageCtx &mock_image_ctx, int r) {
EXPECT_CALL(get_mock_io_ctx(mock_image_ctx.md_ctx),
exec(mock_image_ctx.header_oid, _, StrEq("rbd"), StrEq("set_size"), _, _, _))
}))));
}
+ void expect_object_map_resize(librbd::MockImageCtx &mock_image_ctx,
+ librados::snap_t snap_id, int r) {
+ std::string oid(librbd::ObjectMap::object_map_name(mock_image_ctx.id,
+ snap_id));
+ EXPECT_CALL(get_mock_io_ctx(mock_image_ctx.md_ctx),
+ exec(oid, _, StrEq("rbd"), StrEq("object_map_resize"), _, _, _))
+ .WillOnce(Return(r));
+ }
+
static void inject_snap(librbd::MockImageCtx &mock_image_ctx,
uint64_t snap_id, const std::string &snap_name) {
mock_image_ctx.snap_ids[snap_name] = snap_id;
InSequence seq;
expect_set_size(mock_local_image_ctx, 0);
expect_snap_create(mock_local_image_ctx, "snap1", 10, 0);
+ expect_test_features(mock_local_image_ctx, RBD_FEATURE_OBJECT_MAP, false);
C_SaferCond ctx;
MockSnapshotCreateRequest *request = create_request(mock_local_image_ctx,
InSequence seq;
expect_snap_create(mock_local_image_ctx, "snap1", 10, 0);
+ expect_test_features(mock_local_image_ctx, RBD_FEATURE_OBJECT_MAP, false);
C_SaferCond ctx;
MockSnapshotCreateRequest *request = create_request(mock_local_image_ctx,
ASSERT_EQ(-EINVAL, ctx.wait());
}
+TEST_F(TestMockImageSyncSnapshotCreateRequest, ResizeObjectMap) {
+ librbd::MockImageCtx mock_local_image_ctx(*m_local_image_ctx);
+
+ InSequence seq;
+ expect_snap_create(mock_local_image_ctx, "snap1", 10, 0);
+ expect_test_features(mock_local_image_ctx, RBD_FEATURE_OBJECT_MAP, true);
+ expect_object_map_resize(mock_local_image_ctx, 10, 0);
+
+ C_SaferCond ctx;
+ MockSnapshotCreateRequest *request = create_request(mock_local_image_ctx,
+ "snap1",
+ m_local_image_ctx->size,
+ &ctx);
+ request->send();
+ ASSERT_EQ(0, ctx.wait());
+}
+
+TEST_F(TestMockImageSyncSnapshotCreateRequest, ResizeObjectMapError) {
+ librbd::MockImageCtx mock_local_image_ctx(*m_local_image_ctx);
+
+ InSequence seq;
+ expect_snap_create(mock_local_image_ctx, "snap1", 10, 0);
+ expect_test_features(mock_local_image_ctx, RBD_FEATURE_OBJECT_MAP, true);
+ expect_object_map_resize(mock_local_image_ctx, 10, -EINVAL);
+
+ C_SaferCond ctx;
+ MockSnapshotCreateRequest *request = create_request(mock_local_image_ctx,
+ "snap1",
+ m_local_image_ctx->size,
+ &ctx);
+ request->send();
+ ASSERT_EQ(-EINVAL, ctx.wait());
+}
+
} // namespace image_sync
} // namespace mirror
} // namespace rbd
#include "SnapshotCreateRequest.h"
#include "common/errno.h"
#include "cls/rbd/cls_rbd_client.h"
+#include "librbd/ObjectMap.h"
#include "librbd/Operations.h"
#include "librbd/Utils.h"
+#include "osdc/Striper.h"
#define dout_subsys ceph_subsys_rbd_mirror
#undef dout_prefix
}
template <typename I>
void SnapshotCreateRequest<I>::send_create_object_map() {
- // TODO
- if (true) {
+ CephContext *cct = m_local_image_ctx->cct;
+
+ if (!m_local_image_ctx->test_features(RBD_FEATURE_OBJECT_MAP)) {
finish(0);
return;
}
- CephContext *cct = m_local_image_ctx->cct;
- ldout(cct, 20) << dendl;
+ m_local_image_ctx->snap_lock.get_read();
+ auto snap_it = m_local_image_ctx->snap_ids.find(m_snap_name);
+ if (snap_it == m_local_image_ctx->snap_ids.end()) {
+ lderr(cct) << "failed to locate snap: " << m_snap_name << dendl;
+ m_local_image_ctx->snap_lock.put_read();
+ finish(-ENOENT);
+ return;
+ }
+ librados::snap_t local_snap_id = snap_it->second;
+ m_local_image_ctx->snap_lock.put_read();
+
+ std::string object_map_oid(librbd::ObjectMap::object_map_name(
+ m_local_image_ctx->id, local_snap_id));
+ uint64_t object_count = Striper::get_num_objects(m_local_image_ctx->layout,
+ m_size);
+ ldout(cct, 20) << ": "
+ << "object_map_oid=" << object_map_oid << ", "
+ << "object_count=" << object_count << dendl;
+
+ // initialize an empty object map of the correct size (object sync
+ // will populate the object map)
+ librados::ObjectWriteOperation op;
+ librbd::cls_client::object_map_resize(&op, object_count, OBJECT_NONEXISTENT);
+ librados::AioCompletion *comp = create_rados_safe_callback<
+ SnapshotCreateRequest<I>,
+ &SnapshotCreateRequest<I>::handle_create_object_map>(this);
+ int r = m_local_image_ctx->md_ctx.aio_operate(object_map_oid, comp, &op);
+ assert(r == 0);
+ comp->release();
}
template <typename I>