case ACTION_TYPE_WRITE:
action = WriteAction();
break;
+ case ACTION_TYPE_DISCARD:
+ action = DiscardAction();
+ break;
case ACTION_TYPE_AIO_READ:
action = AioReadAction();
break;
case ACTION_TYPE_AIO_WRITE:
action = AioWriteAction();
break;
+ case ACTION_TYPE_AIO_DISCARD:
+ action = AioDiscardAction();
+ break;
case ACTION_TYPE_OPEN_IMAGE:
action = OpenImageAction();
break;
o.push_back(new ActionEntry(WriteAction()));
o.push_back(new ActionEntry(WriteAction(1, 123456789, dependencies, 3, 4,
5)));
+ o.push_back(new ActionEntry(DiscardAction()));
+ o.push_back(new ActionEntry(DiscardAction(1, 123456789, dependencies, 3, 4,
+ 5)));
o.push_back(new ActionEntry(AioReadAction()));
o.push_back(new ActionEntry(AioReadAction(1, 123456789, dependencies, 3, 4,
5)));
o.push_back(new ActionEntry(AioWriteAction()));
o.push_back(new ActionEntry(AioWriteAction(1, 123456789, dependencies, 3, 4,
5)));
+ o.push_back(new ActionEntry(AioDiscardAction()));
+ o.push_back(new ActionEntry(AioDiscardAction(1, 123456789, dependencies, 3, 4,
+ 5)));
o.push_back(new ActionEntry(OpenImageAction()));
o.push_back(new ActionEntry(OpenImageAction(1, 123456789, dependencies, 3,
case ACTION_TYPE_WRITE:
out << "Write";
break;
+ case ACTION_TYPE_DISCARD:
+ out << "Discard";
+ break;
case ACTION_TYPE_AIO_READ:
out << "AioRead";
break;
case ACTION_TYPE_AIO_WRITE:
out << "AioWrite";
break;
+ case ACTION_TYPE_AIO_DISCARD:
+ out << "AioDiscard";
+ break;
case ACTION_TYPE_OPEN_IMAGE:
out << "OpenImage";
break;
ACTION_TYPE_CLOSE_IMAGE = 7,
ACTION_TYPE_AIO_OPEN_IMAGE = 8,
ACTION_TYPE_AIO_CLOSE_IMAGE = 9,
+ ACTION_TYPE_DISCARD = 10,
+ ACTION_TYPE_AIO_DISCARD = 11
};
struct ActionBase {
}
};
+struct DiscardAction : public IoActionBase {
+ static const ActionType ACTION_TYPE = ACTION_TYPE_DISCARD;
+
+ DiscardAction() {
+ }
+ DiscardAction(action_id_t id, thread_id_t thread_id,
+ const Dependencies &dependencies, imagectx_id_t imagectx_id,
+ uint64_t offset, uint64_t length)
+ : IoActionBase(id, thread_id, dependencies, imagectx_id, offset, length) {
+ }
+};
+
struct AioReadAction : public IoActionBase {
static const ActionType ACTION_TYPE = ACTION_TYPE_AIO_READ;
}
};
+struct AioDiscardAction : public IoActionBase {
+ static const ActionType ACTION_TYPE = ACTION_TYPE_AIO_DISCARD;
+
+ AioDiscardAction() {
+ }
+ AioDiscardAction(action_id_t id, thread_id_t thread_id,
+ const Dependencies &dependencies, imagectx_id_t imagectx_id,
+ uint64_t offset, uint64_t length)
+ : IoActionBase(id, thread_id, dependencies, imagectx_id, offset, length) {
+ }
+};
+
struct OpenImageAction : public ImageActionBase {
static const ActionType ACTION_TYPE = ACTION_TYPE_OPEN_IMAGE;
StopThreadAction,
ReadAction,
WriteAction,
+ DiscardAction,
AioReadAction,
AioWriteAction,
+ AioDiscardAction,
OpenImageAction,
CloseImageAction,
AioOpenImageAction,
return Action::ptr(new AioWriteAction(action));
}
+ inline Action::ptr operator()(const action::DiscardAction &action) const {
+ return Action::ptr(new DiscardAction(action));
+ }
+
+ inline Action::ptr operator()(const action::AioDiscardAction &action) const {
+ return Action::ptr(new AioDiscardAction(action));
+ }
+
inline Action::ptr operator()(const action::OpenImageAction &action) const {
return Action::ptr(new OpenImageAction(action));
}
worker.remove_pending(io);
}
-
void AioWriteAction::perform(ActionCtx &worker) {
static const std::string fake_data(create_fake_data());
dout(ACTION_LEVEL) << "Performing " << *this << dendl;
worker.remove_pending(io);
}
+void AioDiscardAction::perform(ActionCtx &worker) {
+ dout(ACTION_LEVEL) << "Performing " << *this << dendl;
+ librbd::Image *image = worker.get_image(m_action.imagectx_id);
+ PendingIO::ptr io(new PendingIO(pending_io_id(), worker));
+ worker.add_pending(io);
+ if (worker.readonly()) {
+ worker.remove_pending(io);
+ } else {
+ int r = image->aio_discard(m_action.offset, m_action.length, &io->completion());
+ assertf(r >= 0, "id = %d, r = %d", id(), r);
+ }
+}
+
+void DiscardAction::perform(ActionCtx &worker) {
+ dout(ACTION_LEVEL) << "Performing " << *this << dendl;
+ librbd::Image *image = worker.get_image(m_action.imagectx_id);
+ PendingIO::ptr io(new PendingIO(pending_io_id(), worker));
+ worker.add_pending(io);
+ if (!worker.readonly()) {
+ ssize_t r = image->discard(m_action.offset, m_action.length);
+ assertf(r >= 0, "id = %d, r = %d", id(), r);
+ }
+ worker.remove_pending(io);
+}
+
void OpenImageAction::perform(ActionCtx &worker) {
dout(ACTION_LEVEL) << "Performing " << *this << dendl;
PendingIO::ptr io(new PendingIO(pending_io_id(), worker));
};
+class AioDiscardAction : public TypedAction<action::AioDiscardAction> {
+public:
+ explicit AioDiscardAction(const action::AioDiscardAction &action)
+ : TypedAction<action::AioDiscardAction>(action) {
+ }
+
+ virtual void perform(ActionCtx &ctx);
+
+protected:
+ virtual const char *get_action_name() const {
+ return "AioDiscardAction";
+ }
+};
+
+
+class DiscardAction : public TypedAction<action::DiscardAction> {
+public:
+ explicit DiscardAction(const action::DiscardAction &action)
+ : TypedAction<action::DiscardAction>(action) {
+ }
+
+ virtual void perform(ActionCtx &ctx);
+
+protected:
+ virtual const char *get_action_name() const {
+ return "DiscardAction";
+ }
+};
+
+
class OpenImageAction : public TypedAction<action::OpenImageAction> {
public:
explicit OpenImageAction(const action::OpenImageAction &action)
out << ", imagectx=" << m_imagectx << ", offset=" << m_offset << ", length=" << m_length << "]";
}
+void DiscardIO::encode(bufferlist &bl) const {
+ action::Action action((action::DiscardAction(
+ ionum(), thread_id(), convert_dependencies(start_time(), dependencies()),
+ m_imagectx, m_offset, m_length)));
+ ::encode(action, bl);
+}
+
+void DiscardIO::write_debug(std::ostream& out) const {
+ write_debug_base(out, "discard");
+ out << ", imagectx=" << m_imagectx << ", offset=" << m_offset << ", length=" << m_length << "]";
+}
+
void AioReadIO::encode(bufferlist &bl) const {
action::Action action((action::AioReadAction(
ionum(), thread_id(), convert_dependencies(start_time(), dependencies()),
out << ", imagectx=" << m_imagectx << ", offset=" << m_offset << ", length=" << m_length << "]";
}
+void AioDiscardIO::encode(bufferlist &bl) const {
+ action::Action action((action::AioDiscardAction(
+ ionum(), thread_id(), convert_dependencies(start_time(), dependencies()),
+ m_imagectx, m_offset, m_length)));
+ ::encode(action, bl);
+}
+
+void AioDiscardIO::write_debug(std::ostream& out) const {
+ write_debug_base(out, "aio discard");
+ out << ", imagectx=" << m_imagectx << ", offset=" << m_offset << ", length=" << m_length << "]";
+}
+
void OpenImageIO::encode(bufferlist &bl) const {
action::Action action((action::OpenImageAction(
ionum(), thread_id(), convert_dependencies(start_time(), dependencies()),
uint64_t m_length;
};
+class DiscardIO : public IO {
+public:
+ DiscardIO(action_id_t ionum,
+ uint64_t start_time,
+ thread_id_t thread_id,
+ const io_set_t& deps,
+ imagectx_id_t imagectx,
+ uint64_t offset,
+ uint64_t length)
+ : IO(ionum, start_time, thread_id, deps),
+ m_imagectx(imagectx),
+ m_offset(offset),
+ m_length(length) {
+ }
+
+ virtual void encode(bufferlist &bl) const;
+
+ void write_debug(std::ostream& out) const;
+
+private:
+ imagectx_id_t m_imagectx;
+ uint64_t m_offset;
+ uint64_t m_length;
+};
+
class AioReadIO : public IO {
public:
AioReadIO(action_id_t ionum,
uint64_t m_length;
};
+class AioDiscardIO : public IO {
+public:
+ AioDiscardIO(action_id_t ionum,
+ uint64_t start_time,
+ thread_id_t thread_id,
+ const io_set_t& deps,
+ imagectx_id_t imagectx,
+ uint64_t offset,
+ uint64_t length)
+ : IO(ionum, start_time, thread_id, deps),
+ m_imagectx(imagectx),
+ m_offset(offset),
+ m_length(length) {
+ }
+
+ virtual void encode(bufferlist &bl) const;
+
+ void write_debug(std::ostream& out) const;
+
+private:
+ imagectx_id_t m_imagectx;
+ uint64_t m_offset;
+ uint64_t m_length;
+};
+
class OpenImageIO : public IO {
public:
OpenImageIO(action_id_t ionum,
ios->push_back(io);
} else if (strcmp(event_name, "librbd:write_exit") == 0) {
completed(thread->latest_io());
+ } else if (strcmp(event_name, "librbd:discard_enter") == 0) {
+ string name(fields.string("name"));
+ string snap_name(fields.string("snap_name"));
+ bool readonly = fields.int64("read_only");
+ uint64_t offset = fields.uint64("off");
+ uint64_t length = fields.uint64("len");
+ imagectx_id_t imagectx = fields.uint64("imagectx");
+ require_image(ts, thread, imagectx, name, snap_name, readonly, ios);
+ action_id_t ionum = next_id();
+ IO::ptr io(new DiscardIO(ionum, ts, threadID, m_recent_completions,
+ imagectx, offset, length));
+ thread->issued_io(io, &m_latest_ios);
+ ios->push_back(io);
+ } else if (strcmp(event_name, "librbd:discard_exit") == 0) {
+ completed(thread->latest_io());
} else if (strcmp(event_name, "librbd:aio_read_enter") == 0 ||
strcmp(event_name, "librbd:aio_read2_enter") == 0) {
string name(fields.string("name"));
thread->issued_io(io, &m_latest_ios);
ios->push_back(io);
m_pending_ios[completion] = io;
+ } else if (strcmp(event_name, "librbd:aio_discard_enter") == 0) {
+ string name(fields.string("name"));
+ string snap_name(fields.string("snap_name"));
+ bool readonly = fields.int64("read_only");
+ uint64_t offset = fields.uint64("off");
+ uint64_t length = fields.uint64("len");
+ uint64_t completion = fields.uint64("completion");
+ imagectx_id_t imagectx = fields.uint64("imagectx");
+ require_image(ts, thread, imagectx, name, snap_name, readonly, ios);
+ action_id_t ionum = next_id();
+ IO::ptr io(new AioDiscardIO(ionum, ts, threadID, m_recent_completions,
+ imagectx, offset, length));
+ thread->issued_io(io, &m_latest_ios);
+ ios->push_back(io);
+ m_pending_ios[completion] = io;
} else if (strcmp(event_name, "librbd:aio_complete_enter") == 0) {
uint64_t completion = fields.uint64("completion");
map<uint64_t, IO::ptr>::iterator itr = m_pending_ios.find(completion);