From: Mykola Golub Date: Wed, 20 Jan 2016 20:28:26 +0000 (+0200) Subject: rbd-replay: async open/close calls support X-Git-Tag: v10.0.4~149^2 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=fe4e18026d3667d8bc3126d8b108fa5f68fae263;p=ceph.git rbd-replay: async open/close calls support It still uses sync open/close in replay, which can be improved later. Signed-off-by: Mykola Golub --- diff --git a/src/rbd_replay/ActionTypes.cc b/src/rbd_replay/ActionTypes.cc index 36ed3ca02c72..e879384343a9 100644 --- a/src/rbd_replay/ActionTypes.cc +++ b/src/rbd_replay/ActionTypes.cc @@ -218,6 +218,32 @@ void OpenImageAction::dump(Formatter *f) const { f->dump_bool("read_only", read_only); } +void AioOpenImageAction::encode(bufferlist &bl) const { + ImageActionBase::encode(bl); + ::encode(name, bl); + ::encode(snap_name, bl); + ::encode(read_only, bl); +} + +void AioOpenImageAction::decode(__u8 version, bufferlist::iterator &it) { + ImageActionBase::decode(version, it); + if (byte_swap_required(version)) { + decode_big_endian_string(name, it); + decode_big_endian_string(snap_name, it); + } else { + ::decode(name, it); + ::decode(snap_name, it); + } + ::decode(read_only, it); +} + +void AioOpenImageAction::dump(Formatter *f) const { + ImageActionBase::dump(f); + f->dump_string("name", name); + f->dump_string("snap_name", snap_name); + f->dump_bool("read_only", read_only); +} + void UnknownAction::encode(bufferlist &bl) const { assert(false); } @@ -274,6 +300,12 @@ void ActionEntry::decode(__u8 version, bufferlist::iterator &it) { case ACTION_TYPE_CLOSE_IMAGE: action = CloseImageAction(); break; + case ACTION_TYPE_AIO_OPEN_IMAGE: + action = AioOpenImageAction(); + break; + case ACTION_TYPE_AIO_CLOSE_IMAGE: + action = AioCloseImageAction(); + break; } boost::apply_visitor(DecodeVisitor(version, it), action); @@ -311,6 +343,13 @@ void ActionEntry::generate_test_instances(std::list &o) { true))); o.push_back(new ActionEntry(CloseImageAction())); o.push_back(new ActionEntry(CloseImageAction(1, 123456789, dependencies, 3))); + + o.push_back(new ActionEntry(AioOpenImageAction())); + o.push_back(new ActionEntry(AioOpenImageAction(1, 123456789, dependencies, 3, + "image_name", "snap_name", + true))); + o.push_back(new ActionEntry(AioCloseImageAction())); + o.push_back(new ActionEntry(AioCloseImageAction(1, 123456789, dependencies, 3))); } } // namespace action @@ -345,6 +384,12 @@ std::ostream &operator<<(std::ostream &out, case ACTION_TYPE_CLOSE_IMAGE: out << "CloseImage"; break; + case ACTION_TYPE_AIO_OPEN_IMAGE: + out << "AioOpenImage"; + break; + case ACTION_TYPE_AIO_CLOSE_IMAGE: + out << "AioCloseImage"; + break; default: out << "Unknown (" << static_cast(type) << ")"; break; diff --git a/src/rbd_replay/ActionTypes.h b/src/rbd_replay/ActionTypes.h index fcceca859ceb..302b9e216ff4 100644 --- a/src/rbd_replay/ActionTypes.h +++ b/src/rbd_replay/ActionTypes.h @@ -62,14 +62,16 @@ WRITE_CLASS_ENCODER(Dependency); typedef std::vector Dependencies; enum ActionType { - ACTION_TYPE_START_THREAD = 0, - ACTION_TYPE_STOP_THREAD = 1, - ACTION_TYPE_READ = 2, - ACTION_TYPE_WRITE = 3, - ACTION_TYPE_AIO_READ = 4, - ACTION_TYPE_AIO_WRITE = 5, - ACTION_TYPE_OPEN_IMAGE = 6, - ACTION_TYPE_CLOSE_IMAGE = 7 + ACTION_TYPE_START_THREAD = 0, + ACTION_TYPE_STOP_THREAD = 1, + ACTION_TYPE_READ = 2, + ACTION_TYPE_WRITE = 3, + ACTION_TYPE_AIO_READ = 4, + ACTION_TYPE_AIO_WRITE = 5, + ACTION_TYPE_OPEN_IMAGE = 6, + ACTION_TYPE_CLOSE_IMAGE = 7, + ACTION_TYPE_AIO_OPEN_IMAGE = 8, + ACTION_TYPE_AIO_CLOSE_IMAGE = 9, }; struct ActionBase { @@ -225,6 +227,39 @@ struct CloseImageAction : public ImageActionBase { } }; +struct AioOpenImageAction : public ImageActionBase { + static const ActionType ACTION_TYPE = ACTION_TYPE_AIO_OPEN_IMAGE; + + std::string name; + std::string snap_name; + bool read_only; + + AioOpenImageAction() : read_only(false) { + } + AioOpenImageAction(action_id_t id, thread_id_t thread_id, + const Dependencies &dependencies, imagectx_id_t imagectx_id, + const std::string &name, const std::string &snap_name, + bool read_only) + : ImageActionBase(id, thread_id, dependencies, imagectx_id), + name(name), snap_name(snap_name), read_only(read_only) { + } + + void encode(bufferlist &bl) const; + void decode(__u8 version, bufferlist::iterator &it); + void dump(Formatter *f) const; +}; + +struct AioCloseImageAction : public ImageActionBase { + static const ActionType ACTION_TYPE = ACTION_TYPE_AIO_CLOSE_IMAGE; + + AioCloseImageAction() { + } + AioCloseImageAction(action_id_t id, thread_id_t thread_id, + const Dependencies &dependencies, imagectx_id_t imagectx_id) + : ImageActionBase(id, thread_id, dependencies, imagectx_id) { + } +}; + struct UnknownAction { static const ActionType ACTION_TYPE = static_cast(-1); @@ -241,6 +276,8 @@ typedef boost::variant Action; class ActionEntry { diff --git a/src/rbd_replay/actions.cc b/src/rbd_replay/actions.cc index 7726d08706db..33c8de5a38d7 100644 --- a/src/rbd_replay/actions.cc +++ b/src/rbd_replay/actions.cc @@ -65,6 +65,14 @@ struct ConstructVisitor : public boost::static_visitor { return Action::ptr(new CloseImageAction(action)); } + inline Action::ptr operator()(const action::AioOpenImageAction &action) const { + return Action::ptr(new AioOpenImageAction(action)); + } + + inline Action::ptr operator()(const action::AioCloseImageAction &action) const { + return Action::ptr(new AioCloseImageAction(action)); + } + inline Action::ptr operator()(const action::UnknownAction &action) const { return Action::ptr(); } @@ -175,3 +183,35 @@ void CloseImageAction::perform(ActionCtx &worker) { worker.set_action_complete(pending_io_id()); } +void AioOpenImageAction::perform(ActionCtx &worker) { + dout(ACTION_LEVEL) << "Performing " << *this << dendl; + // TODO: Make it async + PendingIO::ptr io(new PendingIO(pending_io_id(), worker)); + worker.add_pending(io); + librbd::Image *image = new librbd::Image(); + librbd::RBD *rbd = worker.rbd(); + rbd_loc name(worker.map_image_name(m_action.name, m_action.snap_name)); + int r; + if (m_action.read_only || worker.readonly()) { + r = rbd->open_read_only(*worker.ioctx(), *image, name.image.c_str(), name.snap.c_str()); + } else { + r = rbd->open(*worker.ioctx(), *image, name.image.c_str(), name.snap.c_str()); + } + if (r) { + cerr << "Unable to open image '" << m_action.name + << "' with snap '" << m_action.snap_name + << "' (mapped to '" << name.str() + << "') and readonly " << m_action.read_only + << ": (" << -r << ") " << strerror(-r) << std::endl; + exit(1); + } + worker.put_image(m_action.imagectx_id, image); + worker.remove_pending(io); +} + +void AioCloseImageAction::perform(ActionCtx &worker) { + dout(ACTION_LEVEL) << "Performing " << *this << dendl; + // TODO: Make it async + worker.erase_image(m_action.imagectx_id); + worker.set_action_complete(pending_io_id()); +} diff --git a/src/rbd_replay/actions.hpp b/src/rbd_replay/actions.hpp index ea46a883362e..9f0acec90c3e 100644 --- a/src/rbd_replay/actions.hpp +++ b/src/rbd_replay/actions.hpp @@ -280,6 +280,35 @@ protected: } }; +class AioOpenImageAction : public TypedAction { +public: + AioOpenImageAction(const action::AioOpenImageAction &action) + : TypedAction(action) { + } + + virtual void perform(ActionCtx &ctx); + +protected: + virtual const char *get_action_name() const { + return "AioOpenImageAction"; + } +}; + + +class AioCloseImageAction : public TypedAction { +public: + AioCloseImageAction(const action::AioCloseImageAction &action) + : TypedAction(action) { + } + + virtual void perform(ActionCtx &ctx); + +protected: + virtual const char *get_action_name() const { + return "AioCloseImageAction"; + } +}; + } #endif diff --git a/src/rbd_replay/ios.cc b/src/rbd_replay/ios.cc index 7437bed88978..52d885ac9b59 100644 --- a/src/rbd_replay/ios.cc +++ b/src/rbd_replay/ios.cc @@ -158,3 +158,27 @@ void CloseImageIO::write_debug(std::ostream& out) const { write_debug_base(out, "close image"); out << ", imagectx=" << m_imagectx; } + +void AioOpenImageIO::encode(bufferlist &bl) const { + action::Action action((action::AioOpenImageAction( + ionum(), thread_id(), convert_dependencies(start_time(), dependencies()), + m_imagectx, m_name, m_snap_name, m_readonly))); + ::encode(action, bl); +} + +void AioOpenImageIO::write_debug(std::ostream& out) const { + write_debug_base(out, "aio open image"); + out << ", imagectx=" << m_imagectx << ", name='" << m_name << "', snap_name='" << m_snap_name << "', readonly=" << m_readonly; +} + +void AioCloseImageIO::encode(bufferlist &bl) const { + action::Action action((action::AioCloseImageAction( + ionum(), thread_id(), convert_dependencies(start_time(), dependencies()), + m_imagectx))); + ::encode(action, bl); +} + +void AioCloseImageIO::write_debug(std::ostream& out) const { + write_debug_base(out, "aio close image"); + out << ", imagectx=" << m_imagectx; +} diff --git a/src/rbd_replay/ios.hpp b/src/rbd_replay/ios.hpp index 218717b746f7..e6c0bf5fd52d 100644 --- a/src/rbd_replay/ios.hpp +++ b/src/rbd_replay/ios.hpp @@ -291,6 +291,61 @@ private: imagectx_id_t m_imagectx; }; +class AioOpenImageIO : public IO { +public: + AioOpenImageIO(action_id_t ionum, + uint64_t start_time, + thread_id_t thread_id, + const io_set_t& deps, + imagectx_id_t imagectx, + const std::string& name, + const std::string& snap_name, + bool readonly) + : IO(ionum, start_time, thread_id, deps), + m_imagectx(imagectx), + m_name(name), + m_snap_name(snap_name), + m_readonly(readonly) { + } + + virtual void encode(bufferlist &bl) const; + + imagectx_id_t imagectx() const { + return m_imagectx; + } + + void write_debug(std::ostream& out) const; + +private: + imagectx_id_t m_imagectx; + std::string m_name; + std::string m_snap_name; + bool m_readonly; +}; + +class AioCloseImageIO : public IO { +public: + AioCloseImageIO(action_id_t ionum, + uint64_t start_time, + thread_id_t thread_id, + const io_set_t& deps, + imagectx_id_t imagectx) + : IO(ionum, start_time, thread_id, deps), + m_imagectx(imagectx) { + } + + virtual void encode(bufferlist &bl) const; + + imagectx_id_t imagectx() const { + return m_imagectx; + } + + void write_debug(std::ostream& out) const; + +private: + imagectx_id_t m_imagectx; +}; + } #endif diff --git a/src/rbd_replay/rbd-replay-prep.cc b/src/rbd_replay/rbd-replay-prep.cc index 61cff592cf27..647a5e380631 100644 --- a/src/rbd_replay/rbd-replay-prep.cc +++ b/src/rbd_replay/rbd-replay-prep.cc @@ -372,6 +372,29 @@ private: boost::shared_ptr io(boost::dynamic_pointer_cast(thread->latest_io())); assert(io); m_open_images.erase(io->imagectx()); + } else if (strcmp(event_name, "librbd:aio_open_image_enter") == 0) { + string name(fields.string("name")); + string snap_name(fields.string("snap_name")); + bool readonly = fields.uint64("read_only"); + imagectx_id_t imagectx = fields.uint64("imagectx"); + uint64_t completion = fields.uint64("completion"); + action_id_t ionum = next_id(); + pair aname(map_image_snap(name, snap_name)); + IO::ptr io(new AioOpenImageIO(ionum, ts, threadID, m_recent_completions, + imagectx, aname.first, aname.second, + readonly)); + thread->issued_io(io, &m_latest_ios); + ios->push_back(io); + m_pending_ios[completion] = io; + } else if (strcmp(event_name, "librbd:aio_close_image_enter") == 0) { + imagectx_id_t imagectx = fields.uint64("imagectx"); + uint64_t completion = fields.uint64("completion"); + action_id_t ionum = next_id(); + IO::ptr io(new AioCloseImageIO(ionum, ts, threadID, m_recent_completions, + imagectx)); + thread->issued_io(io, &m_latest_ios); + ios->push_back(thread->latest_io()); + m_pending_ios[completion] = io; } else if (strcmp(event_name, "librbd:read_enter") == 0 || strcmp(event_name, "librbd:read2_enter") == 0) { string name(fields.string("name"));