]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
rbd-replay: decode and replay discard IO operations
authorJason Dillaman <dillaman@redhat.com>
Mon, 18 Jul 2016 17:37:37 +0000 (13:37 -0400)
committerJason Dillaman <dillaman@redhat.com>
Tue, 19 Jul 2016 11:22:28 +0000 (07:22 -0400)
Fixes: http://tracker.ceph.com/issues/16707
Signed-off-by: Jason Dillaman <dillaman@redhat.com>
src/rbd_replay/ActionTypes.cc
src/rbd_replay/ActionTypes.h
src/rbd_replay/actions.cc
src/rbd_replay/actions.hpp
src/rbd_replay/ios.cc
src/rbd_replay/ios.hpp
src/rbd_replay/rbd-replay-prep.cc

index dc5388f241ede98c8e0316e37e2bd47a4a0a9d10..4e7a297a6c7cd6f0b28d49bc384d56780e772dce 100644 (file)
@@ -288,12 +288,18 @@ void ActionEntry::decode(__u8 version, bufferlist::iterator &it) {
   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;
@@ -330,12 +336,18 @@ void ActionEntry::generate_test_instances(std::list<ActionEntry *> &o) {
   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,
@@ -372,12 +384,18 @@ std::ostream &operator<<(std::ostream &out,
   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;
index 302b9e216ff49c721c3868167bf2fd67b6a75c86..b6dc43351e11122d6df876d9883dec1be221fa5e 100644 (file)
@@ -72,6 +72,8 @@ enum ActionType {
   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 {
@@ -170,6 +172,18 @@ struct WriteAction : public IoActionBase {
   }
 };
 
+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;
 
@@ -194,6 +208,18 @@ struct AioWriteAction : public IoActionBase {
   }
 };
 
+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;
 
@@ -272,8 +298,10 @@ typedef boost::variant<StartThreadAction,
                        StopThreadAction,
                        ReadAction,
                        WriteAction,
+                       DiscardAction,
                        AioReadAction,
                        AioWriteAction,
+                       AioDiscardAction,
                        OpenImageAction,
                        CloseImageAction,
                        AioOpenImageAction,
index 33c8de5a38d752d1079d19fcaa168aafffa4cf83..e596ec0dd50dc2ad0100a4ea2d290a672b905831 100644 (file)
@@ -57,6 +57,14 @@ struct ConstructVisitor : public boost::static_visitor<Action::ptr> {
     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));
   }
@@ -118,7 +126,6 @@ void ReadAction::perform(ActionCtx &worker) {
   worker.remove_pending(io);
 }
 
-
 void AioWriteAction::perform(ActionCtx &worker) {
   static const std::string fake_data(create_fake_data());
   dout(ACTION_LEVEL) << "Performing " << *this << dendl;
@@ -152,6 +159,31 @@ void WriteAction::perform(ActionCtx &worker) {
   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));
index eec655a3bd7e42e67e5928941c9bf299bfd6a76c..df5dde48459938c67a60031fd2da327b073c5d81 100644 (file)
@@ -251,6 +251,36 @@ protected:
 };
 
 
+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)
index f479e0dd9f8a7081d99d37ca9eee7c550bb06eed..db8470e9cf424100b8997d14ce0568a48d26bc8e 100644 (file)
@@ -111,6 +111,18 @@ void WriteIO::write_debug(std::ostream& out) const {
   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()),
@@ -135,6 +147,18 @@ void AioWriteIO::write_debug(std::ostream& out) const {
   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()),
index 7316bc1dcc82e44f197f8e4e7ba93c10675f8b43..5f19648b9e64b1e7a631fc5dd2784bd2457cfc7d 100644 (file)
@@ -186,6 +186,31 @@ private:
   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,
@@ -236,6 +261,31 @@ private:
   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,
index c887813a5565708e5214fc96823287ab0b265064..1ece6e9bd61ede60338894a800cb5132e0d3f519 100644 (file)
@@ -427,6 +427,21 @@ private:
       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"));
@@ -459,6 +474,21 @@ private:
       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);