From: Jason Dillaman Date: Tue, 15 Mar 2016 20:20:20 +0000 (-0400) Subject: librbd: track if a mirror image resync has been requested X-Git-Tag: v10.1.0~70^2~1 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=d1a6c7c4c9ef86adfe19af656ce04bddc9d389fd;p=ceph.git librbd: track if a mirror image resync has been requested A secondary image will store its resync request to the primary image's journal. When the local rbd mirror process detects the flag being set, it can initiate a resync from the remote. Signed-off-by: Jason Dillaman --- diff --git a/src/librbd/Journal.cc b/src/librbd/Journal.cc index a775c5ac1662..ec000f986518 100644 --- a/src/librbd/Journal.cc +++ b/src/librbd/Journal.cc @@ -15,6 +15,7 @@ #include "common/errno.h" #include "common/Timer.h" #include "common/WorkQueue.h" +#include #define dout_subsys ceph_subsys_rbd #undef dout_prefix @@ -161,7 +162,8 @@ public: template int open_journaler(I *image_ctx, J *journaler, bool *initialized, - uint64_t *tag_class, journal::TagData *tag_data) { + journal::ImageClientMeta *client_meta, + journal::TagData *tag_data) { C_SaferCond init_ctx; journaler->init(&init_ctx); int r = init_ctx.wait(); @@ -184,19 +186,19 @@ int open_journaler(I *image_ctx, J *journaler, bool *initialized, return -EINVAL; } - librbd::journal::ImageClientMeta *image_client_meta = - boost::get(&client_data.client_meta); + journal::ImageClientMeta *image_client_meta = + boost::get(&client_data.client_meta); if (image_client_meta == nullptr) { return -EINVAL; } + *client_meta = *image_client_meta; C_SaferCond get_tags_ctx; Mutex lock("lock"); - *tag_class = image_client_meta->tag_class; uint64_t tag_tid; C_DecodeTags *tags_ctx = new C_DecodeTags( image_ctx->cct, &lock, &tag_tid, tag_data, &get_tags_ctx); - journaler->get_tags(*tag_class, &tags_ctx->tags, tags_ctx); + journaler->get_tags(client_meta->tag_class, &tags_ctx->tags, tags_ctx); r = get_tags_ctx.wait(); if (r < 0) { @@ -462,9 +464,9 @@ int Journal::get_tag_owner(I *image_ctx, std::string *mirror_uuid) { image_ctx->cct->_conf->rbd_journal_commit_age); bool initialized; - uint64_t tag_class; + journal::ImageClientMeta client_meta; journal::TagData tag_data; - int r = open_journaler(image_ctx, &journaler, &initialized, &tag_class, + int r = open_journaler(image_ctx, &journaler, &initialized, &client_meta, &tag_data); if (r >= 0) { *mirror_uuid = tag_data.mirror_uuid; @@ -485,34 +487,79 @@ int Journal::allocate_tag(I *image_ctx, const std::string &mirror_uuid) { image_ctx->cct->_conf->rbd_journal_commit_age); bool initialized; - uint64_t tag_class; + journal::ImageClientMeta client_meta; journal::TagData tag_data; - int r = open_journaler(image_ctx, &journaler, &initialized, &tag_class, + int r = open_journaler(image_ctx, &journaler, &initialized, &client_meta, &tag_data); - if (r >= 0) { - journal::TagData tag_data; - tag_data.mirror_uuid = mirror_uuid; + BOOST_SCOPE_EXIT_ALL(&journaler, &initialized) { + if (initialized) { + journaler.shut_down(); + } + }; - // TODO: inject current commit position into tag data - tag_data.predecessor_mirror_uuid = mirror_uuid; + if (r < 0) { + return r; + } - bufferlist tag_bl; - ::encode(tag_data, tag_bl); + // TODO: inject current commit position into tag data + tag_data.mirror_uuid = mirror_uuid; + tag_data.predecessor_mirror_uuid = mirror_uuid; - C_SaferCond allocate_tag_ctx; - cls::journal::Tag tag; - journaler.allocate_tag(tag_class, tag_bl, &tag, &allocate_tag_ctx); + bufferlist tag_bl; + ::encode(tag_data, tag_bl); - r = allocate_tag_ctx.wait(); - if (r < 0) { - lderr(cct) << "failed to allocate tag: " << cpp_strerror(r) << dendl; + C_SaferCond allocate_tag_ctx; + cls::journal::Tag tag; + journaler.allocate_tag(client_meta.tag_class, tag_bl, &tag, + &allocate_tag_ctx); + + r = allocate_tag_ctx.wait(); + if (r < 0) { + lderr(cct) << "failed to allocate tag: " << cpp_strerror(r) << dendl; + return r; + } + + return 0; +} + +template +int Journal::request_resync(I *image_ctx) { + CephContext *cct = image_ctx->cct; + ldout(cct, 20) << __func__ << dendl; + + Journaler journaler(image_ctx->md_ctx, image_ctx->id, IMAGE_CLIENT_ID, + image_ctx->cct->_conf->rbd_journal_commit_age); + + bool initialized; + journal::ImageClientMeta client_meta; + journal::TagData tag_data; + int r = open_journaler(image_ctx, &journaler, &initialized, &client_meta, + &tag_data); + BOOST_SCOPE_EXIT_ALL(&journaler, &initialized) { + if (initialized) { + journaler.shut_down(); } + }; + + if (r < 0) { + return r; } - if (initialized) { - journaler.shut_down(); + client_meta.resync_requested = true; + + journal::ClientData client_data(client_meta); + bufferlist client_data_bl; + ::encode(client_data, client_data_bl); + + C_SaferCond update_client_ctx; + journaler.update_client(client_data_bl, &update_client_ctx); + + r = update_client_ctx.wait(); + if (r < 0) { + lderr(cct) << "failed to update client: " << cpp_strerror(r) << dendl; + return r; } - return r; + return 0; } template @@ -972,8 +1019,8 @@ void Journal::handle_initialized(int r) { return; } - librbd::journal::ImageClientMeta *image_client_meta = - boost::get(&client_data.client_meta); + journal::ImageClientMeta *image_client_meta = + boost::get(&client_data.client_meta); if (image_client_meta == nullptr) { lderr(cct) << "failed to extract client meta data" << dendl; destroy_journaler(-EINVAL); diff --git a/src/librbd/Journal.h b/src/librbd/Journal.h index 871b8d047d03..065b202f2246 100644 --- a/src/librbd/Journal.h +++ b/src/librbd/Journal.h @@ -113,6 +113,7 @@ public: static int is_tag_owner(ImageCtxT *image_ctx, bool *is_tag_owner); static int get_tag_owner(ImageCtxT *image_ctx, std::string *mirror_uuid); static int allocate_tag(ImageCtxT *image_ctx, const std::string &mirror_uuid); + static int request_resync(ImageCtxT *image_ctx); bool is_journal_ready() const; bool is_journal_replaying() const; diff --git a/src/librbd/journal/Types.cc b/src/librbd/journal/Types.cc index 86d7ec127d33..86fc7e00ca36 100644 --- a/src/librbd/journal/Types.cc +++ b/src/librbd/journal/Types.cc @@ -324,14 +324,17 @@ void EventEntry::generate_test_instances(std::list &o) { void ImageClientMeta::encode(bufferlist& bl) const { ::encode(tag_class, bl); + ::encode(resync_requested, bl); } void ImageClientMeta::decode(__u8 version, bufferlist::iterator& it) { ::decode(tag_class, it); + ::decode(resync_requested, it); } void ImageClientMeta::dump(Formatter *f) const { f->dump_unsigned("tag_class", tag_class); + f->dump_bool("resync_requested", resync_requested); } void MirrorPeerSyncPoint::encode(bufferlist& bl) const { diff --git a/src/librbd/journal/Types.h b/src/librbd/journal/Types.h index b19850daa675..20803995b5df 100644 --- a/src/librbd/journal/Types.h +++ b/src/librbd/journal/Types.h @@ -308,6 +308,7 @@ struct ImageClientMeta { static const ClientMetaType TYPE = IMAGE_CLIENT_META_TYPE; uint64_t tag_class = 0; + bool resync_requested = false; ImageClientMeta() { } diff --git a/src/test/librbd/test_mock_Journal.cc b/src/test/librbd/test_mock_Journal.cc index 7c64611dc284..050a4d06a89a 100644 --- a/src/test/librbd/test_mock_Journal.cc +++ b/src/test/librbd/test_mock_Journal.cc @@ -90,6 +90,7 @@ struct MockJournaler { MOCK_METHOD1(flush_commit_position, void(Context*)); MOCK_METHOD2(get_cached_client, int(const std::string&, cls::journal::Client*)); + MOCK_METHOD2(update_client, void(const bufferlist &, Context *)); MOCK_METHOD3(get_tags, void(uint64_t, journal::Journaler::Tags*, Context*)); MOCK_METHOD1(start_replay, void(::journal::ReplayHandler *replay_handler)); @@ -153,6 +154,9 @@ struct MockJournalerProxy { cls::journal::Client* client) { return MockJournaler::get_instance().get_cached_client(client_id, client); } + void update_client(const bufferlist &client_data, Context *on_finish) { + MockJournaler::get_instance().update_client(client_data, on_finish); + } void get_tags(uint64_t tag_class, journal::Journaler::Tags *tags, Context *on_finish) {