]> git.apps.os.sepia.ceph.com Git - ceph-ci.git/commitdiff
librbd: add WriteSameRequest
authorYuan Lu <yuan.y.lu@intel.com>
Thu, 23 Apr 2020 06:03:45 +0000 (14:03 +0800)
committerYuan Lu <yuan.y.lu@intel.com>
Wed, 6 May 2020 05:11:56 +0000 (13:11 +0800)
Signed-off-by: Peterson, Scott <scott.d.peterson@intel.com>
Signed-off-by: Li, Xiaoyan <xiaoyan.li@intel.com>
Signed-off-by: Lu, Yuan <yuan.y.lu@intel.com>
Signed-off-by: Chamarthy, Mahati <mahati.chamarthy@intel.com>
src/librbd/cache/rwl/Request.cc
src/librbd/cache/rwl/Request.h

index e2e911c8082b174785994003781640afa7592b5d..8dc6f4c531df60c9823f296fbafd91879c07885f 100644 (file)
@@ -113,7 +113,7 @@ C_WriteRequest<T>::C_WriteRequest(T &rwl, const utime_t arrived, io::Extents &&i
                                   bufferlist&& bl, const int fadvise_flags, ceph::mutex &lock,
                                   PerfCounters *perfcounter, Context *user_req)
   : C_BlockIORequest<T>(rwl, arrived, std::move(image_extents), std::move(bl), fadvise_flags, user_req),
-    m_lock(lock), m_perfcounter(perfcounter) {
+    m_perfcounter(perfcounter), m_lock(lock) {
   ldout(rwl.get_context(), 99) << this << dendl;
 }
 
@@ -187,6 +187,11 @@ void C_WriteRequest<T>::setup_buffer_resources(
   bytes_dirtied = bytes_cached;
 }
 
+template <typename T>
+std::shared_ptr<WriteLogOperation> C_WriteRequest<T>::create_operation(uint64_t offset, uint64_t len) {
+  return std::make_shared<WriteLogOperation>(*op_set, offset, len, rwl.get_context());
+}
+
 template <typename T>
 void C_WriteRequest<T>::setup_log_operations(DeferredContexts &on_exit) {
   GenericWriteLogEntries log_entries;
@@ -224,9 +229,8 @@ void C_WriteRequest<T>::setup_log_operations(DeferredContexts &on_exit) {
     uint64_t buffer_offset = 0;
     for (auto &extent : this->image_extents) {
       /* operation->on_write_persist connected to m_prior_log_entries_persisted Gather */
-      auto operation =
-        std::make_shared<WriteLogOperation>(*op_set, extent.first, extent.second, rwl.get_context());
-      op_set->operations.emplace_back(operation);
+      auto operation = this->create_operation(extent.first, extent.second);
+      this->op_set->operations.emplace_back(operation);
 
       /* A WS is also a write */
       ldout(rwl.get_context(), 20) << "write_req=" << *this << " op_set=" << op_set.get()
@@ -311,7 +315,7 @@ void C_WriteRequest<T>::dispatch()
   this->m_dispatched_time = now;
 
   ldout(cct, 15) << "write_req=" << this << " cell=" << this->get_cell() << dendl;
-  setup_log_operations(on_exit);
+  this->setup_log_operations(on_exit);
 
   bool append_deferred = false;
   if (!op_set->persist_on_flush &&
@@ -561,6 +565,63 @@ std::ostream &operator<<(std::ostream &os,
   return os;
 };
 
+template <typename T>
+C_WriteSameRequest<T>::C_WriteSameRequest(T &rwl, const utime_t arrived, io::Extents &&image_extents,
+                                          bufferlist&& bl, const int fadvise_flags, ceph::mutex &lock,
+                                          PerfCounters *perfcounter, Context *user_req)
+  : C_WriteRequest<T>(rwl, arrived, std::move(image_extents), std::move(bl), fadvise_flags, lock, perfcounter, user_req) {
+  ldout(rwl.get_context(), 20) << this << dendl;
+}
+
+template <typename T>
+C_WriteSameRequest<T>::~C_WriteSameRequest() {
+   ldout(rwl.get_context(), 20) << this << dendl;
+}
+
+template <typename T>
+void C_WriteSameRequest<T>::update_req_stats(utime_t &now) {
+  /* Write same stats excluded from most write stats
+   * because the read phase will make them look like slow writes in
+   * those histograms. */
+  ldout(rwl.get_context(), 20) << this << dendl;
+  utime_t comp_latency = now - this->m_arrived_time;
+  this->m_perfcounter->tinc(l_librbd_rwl_ws_latency, comp_latency);
+}
+
+/* Write sames will allocate one buffer, the size of the repeating pattern */
+template <typename T>
+void C_WriteSameRequest<T>::setup_buffer_resources(
+    uint64_t &bytes_cached, uint64_t &bytes_dirtied, uint64_t &bytes_allocated,
+    uint64_t &number_lanes, uint64_t &number_log_entries,
+    uint64_t &number_unpublished_reserves) {
+  ldout(rwl.get_context(), 20) << this << dendl;
+  ceph_assert(this->image_extents.size() == 1);
+  bytes_dirtied += this->image_extents[0].second;
+  auto pattern_length = this->bl.length();
+  this->m_resources.buffers.emplace_back();
+  struct WriteBufferAllocation &buffer = this->m_resources.buffers.back();
+  buffer.allocation_size = MIN_WRITE_ALLOC_SIZE;
+  buffer.allocated = false;
+  bytes_cached += pattern_length;
+  if (pattern_length > buffer.allocation_size) {
+    buffer.allocation_size = pattern_length;
+  }
+}
+
+template <typename T>
+std::shared_ptr<WriteLogOperation> C_WriteSameRequest<T>::create_operation(uint64_t offset, uint64_t len) {
+  ceph_assert(this->image_extents.size() == 1);
+  return std::make_shared<WriteSameLogOperation>(*this->op_set.get(), offset, len,
+                                                 this->bl.length(), rwl.get_context());
+}
+
+template <typename T>
+std::ostream &operator<<(std::ostream &os,
+                         const C_WriteSameRequest<T> &req) {
+  os << (C_WriteRequest<T>&)req;
+  return os;
+};
+
 std::ostream &operator<<(std::ostream &os,
                          const BlockGuardReqState &r) {
   os << "barrier=" << r.barrier << ", "
index 76a209bbe4f3c3ff5e9f01af0e0f55b8cf730686..c77ac448f8fd060bf40a7d3acf52b3003997e1a8 100644 (file)
@@ -153,6 +153,8 @@ public:
 
   void dispatch() override;
 
+  virtual std::shared_ptr<WriteLogOperation> create_operation(uint64_t offset, uint64_t len);
+
   virtual void setup_log_operations(DeferredContexts &on_exit);
 
   bool append_write_request(std::shared_ptr<SyncPoint> sync_point);
@@ -165,6 +167,7 @@ public:
 
 protected:
   using C_BlockIORequest<T>::m_resources;
+  PerfCounters *m_perfcounter = nullptr;
   /* Plain writes will allocate one buffer per request extent */
   void setup_buffer_resources(
       uint64_t &bytes_cached, uint64_t &bytes_dirtied, uint64_t &bytes_allocated,
@@ -176,7 +179,6 @@ private:
   std::atomic<int> m_appended = {0};
   bool m_queued = false;
   ceph::mutex &m_lock;
-  PerfCounters *m_perfcounter = nullptr;
   template <typename U>
   friend std::ostream &operator<<(std::ostream &os,
                                   const C_WriteRequest<U> &req);
@@ -300,6 +302,40 @@ private:
                                   const C_DiscardRequest<U> &req);
 };
 
+/**
+ * This is the custodian of the BlockGuard cell for this write same.
+ *
+ * A writesame allocates and persists a data buffer like a write, but the
+ * data buffer is usually much shorter than the write same.
+ */
+template <typename T>
+class C_WriteSameRequest : public C_WriteRequest<T> {
+public:
+  using C_BlockIORequest<T>::rwl;
+  C_WriteSameRequest(T &rwl, const utime_t arrived, io::Extents &&image_extents,
+                     bufferlist&& bl, const int fadvise_flags, ceph::mutex &lock,
+                     PerfCounters *perfcounter, Context *user_req);
+
+  ~C_WriteSameRequest() override;
+
+  void update_req_stats(utime_t &now) override;
+
+  void setup_buffer_resources(
+      uint64_t &bytes_cached, uint64_t &bytes_dirtied, uint64_t &bytes_allocated,
+      uint64_t &number_lanes, uint64_t &number_log_entries,
+      uint64_t &number_unpublished_reserves) override;
+
+  std::shared_ptr<WriteLogOperation> create_operation(uint64_t offset, uint64_t len) override;
+
+  const char *get_name() const override {
+    return "C_WriteSameRequest";
+  }
+
+  template<typename U>
+  friend std::ostream &operator<<(std::ostream &os,
+                                  const C_WriteSameRequest<U> &req);
+};
+
 struct BlockGuardReqState {
   bool barrier = false; /* This is a barrier request */
   bool current_barrier = false; /* This is the currently active barrier */