}));
}
+ void expect_dir_get_name(librados::IoCtx &io_ctx,
+ const std::string &image_name, int r) {
+ bufferlist bl;
+ encode(image_name, bl);
+
+ EXPECT_CALL(get_mock_io_ctx(io_ctx),
+ exec(RBD_DIRECTORY, _, StrEq("rbd"), StrEq("dir_get_name"), _, _, _))
+ .WillOnce(DoAll(WithArg<5>(Invoke([bl](bufferlist *out_bl) {
+ *out_bl = bl;
+ })),
+ Return(r)));
+ }
+
void expect_mirror_image_get(librados::IoCtx &io_ctx,
cls::rbd::MirrorImageState state,
const std::string &global_id, int r) {
MockGetMirrorImageIdRequest mock_get_mirror_image_id_request;
expect_get_mirror_image_id(mock_get_mirror_image_id_request, "local image id",
0);
+ expect_dir_get_name(m_local_io_ctx, "local image name", 0);
expect_mirror_image_get(m_local_io_ctx, cls::rbd::MIRROR_IMAGE_STATE_ENABLED,
"global image id", 0);
expect_get_tag_owner(mock_journal, "local image id", "remote mirror uuid", 0);
std::string local_image_id;
+ std::string local_image_name;
std::string tag_owner;
C_SaferCond ctx;
auto req = MockPrepareLocalImageRequest::create(m_local_io_ctx,
"global image id",
&local_image_id,
+ &local_image_name,
&tag_owner,
m_threads->work_queue,
&ctx);
ASSERT_EQ(0, ctx.wait());
ASSERT_EQ(std::string("local image id"), local_image_id);
+ ASSERT_EQ(std::string("local image name"), local_image_name);
ASSERT_EQ(std::string("remote mirror uuid"), tag_owner);
}
expect_get_mirror_image_id(mock_get_mirror_image_id_request, "", -EINVAL);
std::string local_image_id;
+ std::string local_image_name;
std::string tag_owner;
C_SaferCond ctx;
auto req = MockPrepareLocalImageRequest::create(m_local_io_ctx,
"global image id",
&local_image_id,
+ &local_image_name,
&tag_owner,
m_threads->work_queue,
&ctx);
ASSERT_EQ(-EINVAL, ctx.wait());
}
+TEST_F(TestMockImageReplayerPrepareLocalImageRequest, DirGetNameError) {
+ InSequence seq;
+ MockGetMirrorImageIdRequest mock_get_mirror_image_id_request;
+ expect_get_mirror_image_id(mock_get_mirror_image_id_request, "local image id",
+ 0);
+ expect_dir_get_name(m_local_io_ctx, "", -ENOENT);
+
+ std::string local_image_id;
+ std::string local_image_name;
+ std::string tag_owner;
+ C_SaferCond ctx;
+ auto req = MockPrepareLocalImageRequest::create(m_local_io_ctx,
+ "global image id",
+ &local_image_id,
+ &local_image_name,
+ &tag_owner,
+ m_threads->work_queue,
+ &ctx);
+ req->send();
+
+ ASSERT_EQ(-ENOENT, ctx.wait());
+}
+
TEST_F(TestMockImageReplayerPrepareLocalImageRequest, MirrorImageError) {
InSequence seq;
MockGetMirrorImageIdRequest mock_get_mirror_image_id_request;
expect_get_mirror_image_id(mock_get_mirror_image_id_request, "local image id",
0);
+ expect_dir_get_name(m_local_io_ctx, "local image name", 0);
expect_mirror_image_get(m_local_io_ctx, cls::rbd::MIRROR_IMAGE_STATE_DISABLED,
"", -EINVAL);
std::string local_image_id;
+ std::string local_image_name;
std::string tag_owner;
C_SaferCond ctx;
auto req = MockPrepareLocalImageRequest::create(m_local_io_ctx,
"global image id",
&local_image_id,
+ &local_image_name,
&tag_owner,
m_threads->work_queue,
&ctx);
MockGetMirrorImageIdRequest mock_get_mirror_image_id_request;
expect_get_mirror_image_id(mock_get_mirror_image_id_request, "local image id",
0);
+ expect_dir_get_name(m_local_io_ctx, "local image name", 0);
expect_mirror_image_get(m_local_io_ctx, cls::rbd::MIRROR_IMAGE_STATE_ENABLED,
"global image id", 0);
-ENOENT);
std::string local_image_id;
+ std::string local_image_name;
std::string tag_owner;
C_SaferCond ctx;
auto req = MockPrepareLocalImageRequest::create(m_local_io_ctx,
"global image id",
&local_image_id,
+ &local_image_name,
&tag_owner,
m_threads->work_queue,
&ctx);
struct PrepareLocalImageRequest<librbd::MockTestImageCtx> {
static PrepareLocalImageRequest* s_instance;
std::string *local_image_id = nullptr;
+ std::string *local_image_name = nullptr;
std::string *tag_owner = nullptr;
Context *on_finish = nullptr;
static PrepareLocalImageRequest* create(librados::IoCtx &,
const std::string &global_image_id,
std::string *local_image_id,
+ std::string *local_image_name,
std::string *tag_owner,
MockContextWQ *work_queue,
Context *on_finish) {
assert(s_instance != nullptr);
s_instance->local_image_id = local_image_id;
+ s_instance->local_image_name = local_image_name;
s_instance->tag_owner = tag_owner;
s_instance->on_finish = on_finish;
return s_instance;
void expect_send(MockPrepareLocalImageRequest &mock_request,
const std::string &local_image_id,
+ const std::string &local_image_name,
const std::string &tag_owner,
int r) {
EXPECT_CALL(mock_request, send())
- .WillOnce(Invoke([&mock_request, local_image_id, tag_owner, r]() {
+ .WillOnce(Invoke([&mock_request, local_image_id, local_image_name, tag_owner, r]() {
if (r == 0) {
*mock_request.local_image_id = local_image_id;
+ *mock_request.local_image_name = local_image_name;
*mock_request.tag_owner = tag_owner;
}
mock_request.on_finish->complete(r);
InSequence seq;
expect_send(mock_prepare_local_image_request, mock_local_image_ctx.id,
- "remote mirror uuid", 0);
+ mock_local_image_ctx.name, "remote mirror uuid", 0);
expect_send(mock_prepare_remote_image_request, "remote mirror uuid",
m_remote_image_ctx->id, 0);
EXPECT_CALL(mock_remote_journaler, construct());
InSequence seq;
expect_send(mock_prepare_local_image_request, mock_local_image_ctx.id,
- "", 0);
+ mock_local_image_ctx.name, "", 0);
expect_send(mock_prepare_remote_image_request, "remote mirror uuid",
"remote image id", 0);
EXPECT_CALL(mock_remote_journaler, construct());
expect_get_or_send_update(mock_replay_status_formatter);
InSequence seq;
- expect_send(mock_prepare_local_image_request, "", "", -ENOENT);
+ expect_send(mock_prepare_local_image_request, "", "", "", -ENOENT);
expect_send(mock_prepare_remote_image_request, "remote mirror uuid",
m_remote_image_ctx->id, 0);
EXPECT_CALL(mock_remote_journaler, construct());
InSequence seq;
expect_send(mock_prepare_local_image_request, mock_local_image_ctx.id,
- "remote mirror uuid", -EINVAL);
+ mock_local_image_ctx.name, "remote mirror uuid", -EINVAL);
create_image_replayer(mock_threads);
InSequence seq;
expect_send(mock_prepare_local_image_request, mock_local_image_ctx.id,
- "remote mirror uuid", 0);
+ mock_local_image_ctx.name, "remote mirror uuid", 0);
expect_send(mock_prepare_remote_image_request, "remote mirror uuid",
"", -ENOENT);
expect_trash_move(mock_image_deleter, "global image id", false, 0);
InSequence seq;
expect_send(mock_prepare_local_image_request, mock_local_image_ctx.id,
- "some other mirror uuid", 0);
+ mock_local_image_ctx.name, "some other mirror uuid", 0);
expect_send(mock_prepare_remote_image_request, "remote mirror uuid",
"", -ENOENT);
InSequence seq;
expect_send(mock_prepare_local_image_request, mock_local_image_ctx.id,
- "remote mirror uuid", 0);
+ mock_local_image_ctx.name, "remote mirror uuid", 0);
expect_send(mock_prepare_remote_image_request, "remote mirror uuid",
m_remote_image_ctx->id, -EINVAL);
InSequence seq;
expect_send(mock_prepare_local_image_request, mock_local_image_ctx.id,
- "remote mirror uuid", 0);
+ mock_local_image_ctx.name, "remote mirror uuid", 0);
expect_send(mock_prepare_remote_image_request, "remote mirror uuid",
m_remote_image_ctx->id, 0);
EXPECT_CALL(mock_remote_journaler, construct());
InSequence seq;
expect_send(mock_prepare_local_image_request, mock_local_image_ctx.id,
- "remote mirror uuid", 0);
+ mock_local_image_ctx.name, "remote mirror uuid", 0);
expect_send(mock_prepare_remote_image_request, "remote mirror uuid",
m_remote_image_ctx->id, 0);
EXPECT_CALL(mock_remote_journaler, construct());
InSequence seq;
expect_send(mock_prepare_local_image_request, mock_local_image_ctx.id,
- "remote mirror uuid", 0);
+ mock_local_image_ctx.name, "remote mirror uuid", 0);
expect_send(mock_prepare_remote_image_request, "remote mirror uuid",
m_remote_image_ctx->id, 0);
EXPECT_CALL(mock_remote_journaler, construct());
InSequence seq;
expect_send(mock_prepare_local_image_request, mock_local_image_ctx.id,
- "remote mirror uuid", 0);
+ mock_local_image_ctx.name, "remote mirror uuid", 0);
expect_send(mock_prepare_remote_image_request, "remote mirror uuid",
m_remote_image_ctx->id, 0);
EXPECT_CALL(mock_remote_journaler, construct());
InSequence seq;
expect_send(mock_prepare_local_image_request, mock_local_image_ctx.id,
- "remote mirror uuid", 0);
+ mock_local_image_ctx.name, "remote mirror uuid", 0);
expect_send(mock_prepare_remote_image_request, "remote mirror uuid",
m_remote_image_ctx->id, 0);
EXPECT_CALL(mock_remote_journaler, construct());
InSequence seq;
expect_send(mock_prepare_local_image_request, mock_local_image_ctx.id,
- "remote mirror uuid", 0);
+ mock_local_image_ctx.name, "remote mirror uuid", 0);
expect_send(mock_prepare_remote_image_request, "remote mirror uuid",
m_remote_image_ctx->id, 0);
EXPECT_CALL(mock_remote_journaler, construct());
m_local(local),
m_local_mirror_uuid(local_mirror_uuid),
m_local_pool_id(local_pool_id),
- m_global_image_id(global_image_id),
+ m_global_image_id(global_image_id), m_local_image_name(global_image_id),
m_lock("rbd::mirror::ImageReplayer " + stringify(local_pool_id) + " " +
global_image_id),
m_progress_cxt(this),
Context *ctx = create_context_callback<
ImageReplayer, &ImageReplayer<I>::handle_prepare_local_image>(this);
auto req = PrepareLocalImageRequest<I>::create(
- *m_local_ioctx, m_global_image_id, &m_local_image_id,
+ *m_local_ioctx, m_global_image_id, &m_local_image_id, &m_local_image_name,
&m_local_image_tag_owner, m_threads->work_queue, ctx);
req->send();
}
} else if (r < 0) {
on_start_fail(r, "error preparing local image for replay");
return;
+ } else {
+ reregister_admin_socket_hook();
}
// local image doesn't exist or is non-primary
return;
}
- on_name_changed();
-
update_mirror_image_status(false, boost::none);
init_remote_journaler();
}
dout(20) << dendl;
assert(r == 0);
- on_name_changed();
+ {
+ RWLock::RLocker snap_locker(m_local_image_ctx->snap_lock);
+ m_local_image_name = m_local_image_ctx->name;
+ }
+
+ reregister_admin_socket_hook();
// attempt to process the next event
handle_replay_ready();
return;
}
- dout(20) << "registered asok hook: " << m_name << dendl;
+ dout(15) << "registered asok hook: " << m_name << dendl;
asok_hook = new ImageReplayerAdminSocketHook<I>(g_ceph_context, m_name,
this);
int r = asok_hook->register_commands();
template <typename I>
void ImageReplayer<I>::unregister_admin_socket_hook() {
- dout(20) << dendl;
+ dout(15) << dendl;
AdminSocketHook *asok_hook = nullptr;
{
}
template <typename I>
-void ImageReplayer<I>::on_name_changed() {
+void ImageReplayer<I>::reregister_admin_socket_hook() {
{
Mutex::Locker locker(m_lock);
- std::string name = m_local_ioctx->get_pool_name() + "/" +
- m_local_image_ctx->name;
+ auto name = m_local_ioctx->get_pool_name() + "/" + m_local_image_name;
if (m_name == name) {
return;
}
int64_t m_local_pool_id;
std::string m_local_image_id;
std::string m_global_image_id;
+ std::string m_local_image_name;
std::string m_name;
mutable Mutex m_lock;
void register_admin_socket_hook();
void unregister_admin_socket_hook();
-
- void on_name_changed();
+ void reregister_admin_socket_hook();
};
} // namespace mirror
return;
}
+ get_local_image_name();
+}
+
+template <typename I>
+void PrepareLocalImageRequest<I>::get_local_image_name() {
+ dout(20) << dendl;
+
+ librados::ObjectReadOperation op;
+ librbd::cls_client::dir_get_name_start(&op, *m_local_image_id);
+
+ m_out_bl.clear();
+ librados::AioCompletion *aio_comp = create_rados_callback<
+ PrepareLocalImageRequest<I>,
+ &PrepareLocalImageRequest<I>::handle_get_local_image_name>(this);
+ int r = m_io_ctx.aio_operate(RBD_DIRECTORY, aio_comp, &op, &m_out_bl);
+ assert(r == 0);
+ aio_comp->release();
+}
+
+template <typename I>
+void PrepareLocalImageRequest<I>::handle_get_local_image_name(int r) {
+ dout(20) << "r=" << r << dendl;
+
+ if (r == 0) {
+ bufferlist::iterator it = m_out_bl.begin();
+ r = librbd::cls_client::dir_get_name_finish(&it, m_local_image_name);
+ }
+
+ if (r < 0) {
+ if (r != -ENOENT) {
+ derr << "failed to retrieve image name: " << cpp_strerror(r) << dendl;
+ }
+ finish(r);
+ return;
+ }
+
get_mirror_state();
}
static PrepareLocalImageRequest *create(librados::IoCtx &io_ctx,
const std::string &global_image_id,
std::string *local_image_id,
+ std::string *local_image_name,
std::string *tag_owner,
ContextWQ *work_queue,
Context *on_finish) {
return new PrepareLocalImageRequest(io_ctx, global_image_id, local_image_id,
- tag_owner, work_queue, on_finish);
+ local_image_name, tag_owner, work_queue,
+ on_finish);
}
PrepareLocalImageRequest(librados::IoCtx &io_ctx,
const std::string &global_image_id,
std::string *local_image_id,
+ std::string *local_image_name,
std::string *tag_owner,
ContextWQ *work_queue,
Context *on_finish)
: m_io_ctx(io_ctx), m_global_image_id(global_image_id),
- m_local_image_id(local_image_id), m_tag_owner(tag_owner),
- m_work_queue(work_queue), m_on_finish(on_finish) {
+ m_local_image_id(local_image_id), m_local_image_name(local_image_name),
+ m_tag_owner(tag_owner), m_work_queue(work_queue), m_on_finish(on_finish) {
}
void send();
* GET_LOCAL_IMAGE_ID
* |
* v
+ * GET_LOCAL_IMAGE_NAME
+ * |
+ * v
* GET_MIRROR_STATE
* |
* v
librados::IoCtx &m_io_ctx;
std::string m_global_image_id;
std::string *m_local_image_id;
+ std::string *m_local_image_name;
std::string *m_tag_owner;
ContextWQ *m_work_queue;
Context *m_on_finish;
void get_local_image_id();
void handle_get_local_image_id(int r);
+ void get_local_image_name();
+ void handle_get_local_image_name(int r);
+
void get_mirror_state();
void handle_get_mirror_state(int r);