It still uses sync open/close in replay, which can be improved later.
Signed-off-by: Mykola Golub <mgolub@mirantis.com>
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);
}
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);
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
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<uint32_t>(type) << ")";
break;
typedef std::vector<Dependency> 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 {
}
};
+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<ActionType>(-1);
AioWriteAction,
OpenImageAction,
CloseImageAction,
+ AioOpenImageAction,
+ AioCloseImageAction,
UnknownAction> Action;
class ActionEntry {
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();
}
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());
+}
}
};
+class AioOpenImageAction : public TypedAction<action::AioOpenImageAction> {
+public:
+ AioOpenImageAction(const action::AioOpenImageAction &action)
+ : TypedAction<action::AioOpenImageAction>(action) {
+ }
+
+ virtual void perform(ActionCtx &ctx);
+
+protected:
+ virtual const char *get_action_name() const {
+ return "AioOpenImageAction";
+ }
+};
+
+
+class AioCloseImageAction : public TypedAction<action::AioCloseImageAction> {
+public:
+ AioCloseImageAction(const action::AioCloseImageAction &action)
+ : TypedAction<action::AioCloseImageAction>(action) {
+ }
+
+ virtual void perform(ActionCtx &ctx);
+
+protected:
+ virtual const char *get_action_name() const {
+ return "AioCloseImageAction";
+ }
+};
+
}
#endif
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;
+}
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
boost::shared_ptr<CloseImageIO> io(boost::dynamic_pointer_cast<CloseImageIO>(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<string, string> 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"));