]> git.apps.os.sepia.ceph.com Git - ceph-ci.git/commitdiff
librbd: make writesame get all zeros with rbd_skip_partial_discard on
authorGui Hecheng <guihecheng@cmss.chinamobile.com>
Wed, 22 Feb 2017 09:24:33 +0000 (17:24 +0800)
committerGui Hecheng <guihecheng@cmss.chinamobile.com>
Thu, 23 Feb 2017 16:16:46 +0000 (00:16 +0800)
Now writesame tends to do a discard on all zero buffer, but
if rbd_skip_partial_discard is turned on, discard will not do any
zeroing work on partial discard, so we read random data while expecting
all zeros.
To fix it, we introduce the ImageCtx::skip_partial_discard and
pass an extra parameter to discard. Writesame will always pass false
and other discards will pass the ImageCtx::skip_partial_discard
which is set by the rbd_skip_partial_discard option.

Signed-off-by: Gui Hecheng <guihecheng@cmss.chinamobile.com>
24 files changed:
src/librbd/ImageCtx.cc
src/librbd/ImageCtx.h
src/librbd/cache/ImageCache.h
src/librbd/cache/ImageWriteback.cc
src/librbd/cache/ImageWriteback.h
src/librbd/cache/PassthroughImageCache.cc
src/librbd/cache/PassthroughImageCache.h
src/librbd/io/ImageRequest.cc
src/librbd/io/ImageRequest.h
src/librbd/io/ImageRequestWQ.cc
src/librbd/io/ImageRequestWQ.h
src/librbd/journal/Replay.cc
src/librbd/journal/Types.cc
src/librbd/journal/Types.h
src/librbd/librbd.cc
src/test/librbd/io/test_mock_ImageRequest.cc
src/test/librbd/journal/test_Entries.cc
src/test/librbd/journal/test_Replay.cc
src/test/librbd/journal/test_mock_Replay.cc
src/test/librbd/mock/cache/MockImageCache.h
src/test/librbd/test_internal.cc
src/test/rbd_mirror/image_sync/test_mock_ObjectCopyRequest.cc
src/test/rbd_mirror/test_ImageSync.cc
src/test/rbd_mirror/test_mock_ImageReplayer.cc

index d16e8c14a878ef45ee6915cad487b8bc400045a5..4d5dd3ae18c5d76c12d621305181b5b5c21c9f34 100644 (file)
@@ -971,7 +971,8 @@ struct C_InvalidateCache : public Context {
         "rbd_journal_max_payload_bytes", false)(
         "rbd_journal_max_concurrent_object_sets", false)(
         "rbd_mirroring_resync_after_disconnect", false)(
-        "rbd_mirroring_replay_delay", false);
+        "rbd_mirroring_replay_delay", false)(
+        "rbd_skip_partial_discard", false);
 
     md_config_t local_config_t;
     std::map<std::string, bufferlist> res;
@@ -1030,6 +1031,7 @@ struct C_InvalidateCache : public Context {
     ASSIGN_OPTION(journal_max_concurrent_object_sets);
     ASSIGN_OPTION(mirroring_resync_after_disconnect);
     ASSIGN_OPTION(mirroring_replay_delay);
+    ASSIGN_OPTION(skip_partial_discard);
   }
 
   ExclusiveLock<ImageCtx> *ImageCtx::create_exclusive_lock() {
index 0f089c1683118d02546e2cacdc4245f68106ddc0..76f38efb929ebe79b43a12ea2067c96db4b38250 100644 (file)
@@ -193,6 +193,7 @@ namespace librbd {
     int journal_max_concurrent_object_sets;
     bool mirroring_resync_after_disconnect;
     int mirroring_replay_delay;
+    bool skip_partial_discard;
 
     LibrbdAdminSocketHook *asok_hook;
 
index 02a6467aa60ea640b6e16e5723d22f22d02408c3..0a5d0263ee33e52b4a227423ef8f44fc3a694835 100644 (file)
@@ -28,7 +28,7 @@ struct ImageCache {
   virtual void aio_write(Extents&& image_extents, ceph::bufferlist&& bl,
                          int fadvise_flags, Context *on_finish) = 0;
   virtual void aio_discard(uint64_t offset, uint64_t length,
-                           Context *on_finish) = 0;
+                           bool skip_partial_discard, Context *on_finish) = 0;
   virtual void aio_flush(Context *on_finish) = 0;
   virtual void aio_writesame(uint64_t offset, uint64_t length,
                              ceph::bufferlist&& bl,
index 69b28c3d27481311d1de13b51d31387c990cc43c..83c3b5bb14bed7144ba18d794e8706198e61c30a 100644 (file)
@@ -53,7 +53,7 @@ void ImageWriteback<I>::aio_write(Extents &&image_extents,
 
 template <typename I>
 void ImageWriteback<I>::aio_discard(uint64_t offset, uint64_t length,
-                                    Context *on_finish) {
+                                    bool skip_partial_discard, Context *on_finish) {
   CephContext *cct = m_image_ctx.cct;
   ldout(cct, 20) << "offset=" << offset << ", "
                  << "length=" << length << ", "
@@ -61,7 +61,8 @@ void ImageWriteback<I>::aio_discard(uint64_t offset, uint64_t length,
 
   auto aio_comp = io::AioCompletion::create_and_start(on_finish, &m_image_ctx,
                                                       io::AIO_TYPE_DISCARD);
-  io::ImageDiscardRequest<I> req(m_image_ctx, aio_comp, offset, length);
+  io::ImageDiscardRequest<I> req(m_image_ctx, aio_comp, offset, length,
+                                 skip_partial_discard);
   req.set_bypass_image_cache();
   req.send();
 }
index 29ea713baa880fdb67e8cd480fa0e76b368dd826..1ffc450dfbbbd2d74b668129d06298c41faec85c 100644 (file)
@@ -30,7 +30,8 @@ public:
                 int fadvise_flags, Context *on_finish);
   void aio_write(Extents &&image_extents, ceph::bufferlist&& bl,
                  int fadvise_flags, Context *on_finish);
-  void aio_discard(uint64_t offset, uint64_t length, Context *on_finish);
+  void aio_discard(uint64_t offset, uint64_t length,
+                   bool skip_partial_discard, Context *on_finish);
   void aio_flush(Context *on_finish);
   void aio_writesame(uint64_t offset, uint64_t length,
                      ceph::bufferlist&& bl,
index 62f81aca329849f432ac3ab0906cabec160999f9..f892387acc8922931df844f6e9d215482477e28c 100644 (file)
@@ -45,13 +45,13 @@ void PassthroughImageCache<I>::aio_write(Extents &&image_extents,
 
 template <typename I>
 void PassthroughImageCache<I>::aio_discard(uint64_t offset, uint64_t length,
-                                           Context *on_finish) {
+                                           bool skip_partial_discard, Context *on_finish) {
   CephContext *cct = m_image_ctx.cct;
   ldout(cct, 20) << "offset=" << offset << ", "
                  << "length=" << length << ", "
                  << "on_finish=" << on_finish << dendl;
 
-  m_image_writeback.aio_discard(offset, length, on_finish);
+  m_image_writeback.aio_discard(offset, length, skip_partial_discard, on_finish);
 }
 
 template <typename I>
index 2abea0efb77708b12f08819513dee1392445ccbf..5210e7c619dc75a998ead09cb0b6db78ce239e79 100644 (file)
@@ -27,7 +27,7 @@ public:
   void aio_write(Extents&& image_extents, ceph::bufferlist&& bl,
                  int fadvise_flags, Context *on_finish) override;
   void aio_discard(uint64_t offset, uint64_t length,
-                   Context *on_finish) override;
+                   bool skip_partial_discard, Context *on_finish);
   void aio_flush(Context *on_finish) override;
   virtual void aio_writesame(uint64_t offset, uint64_t length,
                              ceph::bufferlist&& bl,
index ee9d9535b2a9696cdca8f4960acc55ec75f6d119..b66ad6efa04beb0c31c86dc6fcb3972f39144936 100644 (file)
@@ -130,8 +130,9 @@ void ImageRequest<I>::aio_write(I *ictx, AioCompletion *c,
 
 template <typename I>
 void ImageRequest<I>::aio_discard(I *ictx, AioCompletion *c,
-                                  uint64_t off, uint64_t len) {
-  ImageDiscardRequest<I> req(*ictx, c, off, len);
+                                  uint64_t off, uint64_t len,
+                                  bool skip_partial_discard) {
+  ImageDiscardRequest<I> req(*ictx, c, off, len, skip_partial_discard);
   req.send();
 }
 
@@ -505,7 +506,8 @@ uint64_t ImageDiscardRequest<I>::append_journal_event(
   assert(!this->m_image_extents.empty());
   for (auto &extent : this->m_image_extents) {
     journal::EventEntry event_entry(journal::AioDiscardEvent(extent.first,
-                                                             extent.second));
+                                                             extent.second,
+                                                             this->m_skip_partial_discard));
     tid = image_ctx.journal->append_io_event(std::move(event_entry),
                                              requests, extent.first,
                                              extent.second, synchronous);
@@ -520,7 +522,7 @@ template <typename I>
 void ImageDiscardRequest<I>::prune_object_extents(ObjectExtents &object_extents) {
   I &image_ctx = this->m_image_ctx;
   CephContext *cct = image_ctx.cct;
-  if (!cct->_conf->rbd_skip_partial_discard) {
+  if (!this->m_skip_partial_discard) {
     return;
   }
 
@@ -552,7 +554,8 @@ void ImageDiscardRequest<I>::send_image_cache_request() {
   aio_comp->set_request_count(this->m_image_extents.size());
   for (auto &extent : this->m_image_extents) {
     C_AioRequest *req_comp = new C_AioRequest(aio_comp);
-    image_ctx.image_cache->aio_discard(extent.first, extent.second, req_comp);
+    image_ctx.image_cache->aio_discard(extent.first, extent.second,
+                                       this->m_skip_partial_discard, req_comp);
   }
 }
 
index 4c8ae76f5bb49834a9bd4873718c67ff1a777acf..aeabd50bfbaed747b78bc1f9bd3eb0076cab3fe4 100644 (file)
@@ -35,7 +35,7 @@ public:
   static void aio_write(ImageCtxT *ictx, AioCompletion *c,
                         Extents &&image_extents, bufferlist &&bl, int op_flags);
   static void aio_discard(ImageCtxT *ictx, AioCompletion *c, uint64_t off,
-                          uint64_t len);
+                          uint64_t len, bool skip_partial_discard);
   static void aio_flush(ImageCtxT *ictx, AioCompletion *c);
   static void aio_writesame(ImageCtxT *ictx, AioCompletion *c, uint64_t off,
                             uint64_t len, bufferlist &&bl, int op_flags);
@@ -199,8 +199,9 @@ template <typename ImageCtxT = ImageCtx>
 class ImageDiscardRequest : public AbstractImageWriteRequest<ImageCtxT> {
 public:
   ImageDiscardRequest(ImageCtxT &image_ctx, AioCompletion *aio_comp,
-                      uint64_t off, uint64_t len)
-    : AbstractImageWriteRequest<ImageCtxT>(image_ctx, aio_comp, {{off, len}}) {
+                      uint64_t off, uint64_t len, bool skip_partial_discard)
+    : AbstractImageWriteRequest<ImageCtxT>(image_ctx, aio_comp, {{off, len}}),
+      m_skip_partial_discard(skip_partial_discard) {
   }
 
 protected:
@@ -229,6 +230,8 @@ protected:
   uint64_t append_journal_event(const ObjectRequests &requests,
                                 bool synchronous) override;
   void update_stats(size_t length) override;
+private:
+  bool m_skip_partial_discard;
 };
 
 template <typename ImageCtxT = ImageCtx>
index 1ce121df70c101f751e2dae7a4cc4f623c493f1a..7b7cbc63e2a71a596b9b254ebeb8728ec4f047ae 100644 (file)
@@ -69,7 +69,7 @@ ssize_t ImageRequestWQ::write(uint64_t off, uint64_t len,
   return len;
 }
 
-int ImageRequestWQ::discard(uint64_t off, uint64_t len) {
+int ImageRequestWQ::discard(uint64_t off, uint64_t len, bool skip_partial_discard) {
   CephContext *cct = m_image_ctx.cct;
   ldout(cct, 20) << "discard: ictx=" << &m_image_ctx << ", off=" << off << ", "
                  << "len = " << len << dendl;
@@ -84,7 +84,7 @@ int ImageRequestWQ::discard(uint64_t off, uint64_t len) {
 
   C_SaferCond cond;
   AioCompletion *c = AioCompletion::create(&cond);
-  aio_discard(c, off, len, false);
+  aio_discard(c, off, len, skip_partial_discard, false);
 
   r = cond.wait();
   if (r < 0) {
@@ -187,7 +187,8 @@ void ImageRequestWQ::aio_write(AioCompletion *c, uint64_t off, uint64_t len,
 }
 
 void ImageRequestWQ::aio_discard(AioCompletion *c, uint64_t off,
-                                 uint64_t len, bool native_async) {
+                                 uint64_t len, bool skip_partial_discard,
+                                 bool native_async) {
   c->init_time(&m_image_ctx, AIO_TYPE_DISCARD);
   CephContext *cct = m_image_ctx.cct;
   ldout(cct, 20) << "aio_discard: ictx=" << &m_image_ctx << ", "
@@ -204,10 +205,10 @@ void ImageRequestWQ::aio_discard(AioCompletion *c, uint64_t off,
 
   RWLock::RLocker owner_locker(m_image_ctx.owner_lock);
   if (m_image_ctx.non_blocking_aio || writes_blocked()) {
-    queue(new ImageDiscardRequest<>(m_image_ctx, c, off, len));
+    queue(new ImageDiscardRequest<>(m_image_ctx, c, off, len, skip_partial_discard));
   } else {
     c->start_op();
-    ImageRequest<>::aio_discard(&m_image_ctx, c, off, len);
+    ImageRequest<>::aio_discard(&m_image_ctx, c, off, len, skip_partial_discard);
     finish_in_flight_op();
   }
 }
index 103a4f8c19db58cf0e97f95dfb35cee337bc1c67..c4c7b9954e4e67925eed5c823aac2eea84975a8b 100644 (file)
@@ -28,7 +28,7 @@ public:
   ssize_t read(uint64_t off, uint64_t len, ReadResult &&read_result,
                int op_flags);
   ssize_t write(uint64_t off, uint64_t len, bufferlist &&bl, int op_flags);
-  int discard(uint64_t off, uint64_t len);
+  int discard(uint64_t off, uint64_t len, bool skip_partial_discard);
   ssize_t writesame(uint64_t off, uint64_t len, bufferlist &&bl, int op_flags);
 
   void aio_read(AioCompletion *c, uint64_t off, uint64_t len,
@@ -36,7 +36,7 @@ public:
   void aio_write(AioCompletion *c, uint64_t off, uint64_t len,
                  bufferlist &&bl, int op_flags, bool native_async=true);
   void aio_discard(AioCompletion *c, uint64_t off, uint64_t len,
-                   bool native_async=true);
+                   bool skip_partial_discard, bool native_async=true);
   void aio_flush(AioCompletion *c, bool native_async=true);
   void aio_writesame(AioCompletion *c, uint64_t off, uint64_t len,
                      bufferlist &&bl, int op_flags, bool native_async=true);
index ff4dfb0ff093cd662cc84e280e2d1112b79d8dcb..c3e9108165656a863a4ba51561c66114b06e55b1 100644 (file)
@@ -315,7 +315,7 @@ void Replay<I>::handle_event(const journal::AioDiscardEvent &event,
                                                io::AIO_TYPE_DISCARD,
                                                &flush_required);
   io::ImageRequest<I>::aio_discard(&m_image_ctx, aio_comp, event.offset,
-                                   event.length);
+                                   event.length, event.skip_partial_discard);
   if (flush_required) {
     m_lock.Lock();
     auto flush_comp = create_aio_flush_completion(nullptr);
index 2373e54859c36a1fd1a98a890afda0aee3f0b3ec..cef0dbfd13028d62ee93605b286514d83f213523 100644 (file)
@@ -71,16 +71,21 @@ private:
 void AioDiscardEvent::encode(bufferlist& bl) const {
   ::encode(offset, bl);
   ::encode(length, bl);
+  ::encode(skip_partial_discard, bl);
 }
 
 void AioDiscardEvent::decode(__u8 version, bufferlist::iterator& it) {
   ::decode(offset, it);
   ::decode(length, it);
+  if (version >= 5) {
+    ::decode(skip_partial_discard, it);
+  }
 }
 
 void AioDiscardEvent::dump(Formatter *f) const {
   f->dump_unsigned("offset", offset);
   f->dump_unsigned("length", length);
+  f->dump_bool("skip_partial_discard", skip_partial_discard);
 }
 
 uint32_t AioWriteEvent::get_fixed_size() {
@@ -335,7 +340,7 @@ EventType EventEntry::get_event_type() const {
 }
 
 void EventEntry::encode(bufferlist& bl) const {
-  ENCODE_START(4, 1, bl);
+  ENCODE_START(5, 1, bl);
   boost::apply_visitor(EncodeVisitor(bl), event);
   ENCODE_FINISH(bl);
   encode_metadata(bl);
@@ -434,7 +439,7 @@ void EventEntry::decode_metadata(bufferlist::iterator& it) {
 
 void EventEntry::generate_test_instances(std::list<EventEntry *> &o) {
   o.push_back(new EventEntry(AioDiscardEvent()));
-  o.push_back(new EventEntry(AioDiscardEvent(123, 345), utime_t(1, 1)));
+  o.push_back(new EventEntry(AioDiscardEvent(123, 345, false), utime_t(1, 1)));
 
   bufferlist bl;
   bl.append(std::string(32, '1'));
index 71505b814f99d0fb6493c2ae55ceb2b33d3b5336..e80d82586f4363636dd73745053c6b612c125f67 100644 (file)
@@ -50,11 +50,12 @@ struct AioDiscardEvent {
 
   uint64_t offset;
   uint64_t length;
+  bool skip_partial_discard;
 
-  AioDiscardEvent() : offset(0), length(0) {
+  AioDiscardEvent() : offset(0), length(0), skip_partial_discard(false) {
   }
-  AioDiscardEvent(uint64_t _offset, uint64_t _length)
-    : offset(_offset), length(_length) {
+  AioDiscardEvent(uint64_t _offset, uint64_t _length, bool _skip_partial_discard)
+    : offset(_offset), length(_length), skip_partial_discard(_skip_partial_discard) {
   }
 
   void encode(bufferlist& bl) const;
index 13f1d27f7e56d9a929def6a1a5968181584b7d29..51b93f14821ddb05256cca83d65762f8d3f074e0 100644 (file)
@@ -1331,7 +1331,7 @@ namespace librbd {
         tracepoint(librbd, discard_exit, -EINVAL);
         return -EINVAL;
     }
-    int r = ictx->io_work_queue->discard(ofs, len);
+    int r = ictx->io_work_queue->discard(ofs, len, ictx->skip_partial_discard);
     tracepoint(librbd, discard_exit, r);
     return r;
   }
@@ -1348,7 +1348,7 @@ namespace librbd {
     }
 
     if (mem_is_zero(bl.c_str(), bl.length())) {
-      int r = ictx->io_work_queue->discard(ofs, len);
+      int r = ictx->io_work_queue->discard(ofs, len, false);
       tracepoint(librbd, writesame_exit, r);
       return r;
     }
@@ -1393,7 +1393,7 @@ namespace librbd {
   {
     ImageCtx *ictx = (ImageCtx *)ctx;
     tracepoint(librbd, aio_discard_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, off, len, c->pc);
-    ictx->io_work_queue->aio_discard(get_aio_completion(c), off, len);
+    ictx->io_work_queue->aio_discard(get_aio_completion(c), off, len, ictx->skip_partial_discard);
     tracepoint(librbd, aio_discard_exit, 0);
     return 0;
   }
@@ -1456,7 +1456,7 @@ namespace librbd {
     }
 
     if (mem_is_zero(bl.c_str(), bl.length())) {
-      ictx->io_work_queue->aio_discard(get_aio_completion(c), off, len);
+      ictx->io_work_queue->aio_discard(get_aio_completion(c), off, len, false);
       tracepoint(librbd, aio_writesame_exit, 0);
       return 0;
     }
@@ -2944,7 +2944,7 @@ extern "C" int rbd_discard(rbd_image_t image, uint64_t ofs, uint64_t len)
 {
   librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
   tracepoint(librbd, discard_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, ofs, len);
-  int r = ictx->io_work_queue->discard(ofs, len);
+  int r = ictx->io_work_queue->discard(ofs, len, ictx->skip_partial_discard);
   tracepoint(librbd, discard_exit, r);
   return r;
 }
@@ -2962,7 +2962,7 @@ extern "C" ssize_t rbd_writesame(rbd_image_t image, uint64_t ofs, size_t len,
   }
 
   if (mem_is_zero(buf, data_len)) {
-    int r = ictx->io_work_queue->discard(ofs, len);
+    int r = ictx->io_work_queue->discard(ofs, len, false);
     tracepoint(librbd, writesame_exit, r);
     return r;
   }
@@ -3057,7 +3057,7 @@ extern "C" int rbd_aio_discard(rbd_image_t image, uint64_t off, uint64_t len,
   librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
   librbd::RBD::AioCompletion *comp = (librbd::RBD::AioCompletion *)c;
   tracepoint(librbd, aio_discard_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, off, len, comp->pc);
-  ictx->io_work_queue->aio_discard(get_aio_completion(comp), off, len);
+  ictx->io_work_queue->aio_discard(get_aio_completion(comp), off, len, ictx->skip_partial_discard);
   tracepoint(librbd, aio_discard_exit, 0);
   return 0;
 }
@@ -3159,7 +3159,7 @@ extern "C" int rbd_aio_writesame(rbd_image_t image, uint64_t off, size_t len,
   }
 
   if (mem_is_zero(buf, data_len)) {
-    ictx->io_work_queue->aio_discard(get_aio_completion(comp), off, len);
+    ictx->io_work_queue->aio_discard(get_aio_completion(comp), off, len, false);
     tracepoint(librbd, aio_writesame_exit, 0);
     return 0;
   }
index 0c0acd92619574d037fe97869a09f3b09432bf9b..3cb0ffcc5c31b36e31975e41fedf7303dde3b000 100644 (file)
@@ -246,7 +246,8 @@ TEST_F(TestMockIoImageRequest, AioDiscardJournalAppendDisabled) {
   C_SaferCond aio_comp_ctx;
   AioCompletion *aio_comp = AioCompletion::create_and_start(
     &aio_comp_ctx, ictx, AIO_TYPE_DISCARD);
-  MockImageDiscardRequest mock_aio_image_discard(mock_image_ctx, aio_comp, 0, 1);
+  MockImageDiscardRequest mock_aio_image_discard(mock_image_ctx, aio_comp,
+                                                 0, 1, ictx->skip_partial_discard);
   {
     RWLock::RLocker owner_locker(mock_image_ctx.owner_lock);
     mock_aio_image_discard.send();
index 3345394dda81b1301e6c959f5bdc377103b20543..33e162a0f5e6324963080fce7accc2ba75d7dde9 100644 (file)
@@ -175,7 +175,7 @@ TEST_F(TestJournalEntries, AioDiscard) {
   C_SaferCond cond_ctx;
   auto c = librbd::io::AioCompletion::create(&cond_ctx);
   c->get();
-  ictx->io_work_queue->aio_discard(c, 123, 234);
+  ictx->io_work_queue->aio_discard(c, 123, 234, cct->_conf->rbd_skip_partial_discard);
   ASSERT_EQ(0, c->wait_for_complete());
   c->put();
 
index 19ec52e5e8a5bf407b19647c6e74666716e3a41d..abdbbf99aa93b12a3a54f478c31566b384031a89 100644 (file)
@@ -143,7 +143,7 @@ TEST_F(TestJournalReplay, AioDiscardEvent) {
 
   // inject a discard operation into the journal
   inject_into_journal(ictx,
-                      librbd::journal::AioDiscardEvent(0, payload.size()));
+                      librbd::journal::AioDiscardEvent(0, payload.size(), ictx->skip_partial_discard));
   close_image(ictx);
 
   // re-open the journal so that it replays the new entry
@@ -170,9 +170,9 @@ TEST_F(TestJournalReplay, AioDiscardEvent) {
 
   // replay several envents and check the commit position
   inject_into_journal(ictx,
-                      librbd::journal::AioDiscardEvent(0, payload.size()));
+                      librbd::journal::AioDiscardEvent(0, payload.size(), ictx->cct->_conf->rbd_skip_partial_discard));
   inject_into_journal(ictx,
-                      librbd::journal::AioDiscardEvent(0, payload.size()));
+                      librbd::journal::AioDiscardEvent(0, payload.size(), ictx->cct->_conf->rbd_skip_partial_discard));
   close_image(ictx);
 
   ASSERT_EQ(0, open_image(m_image_name, &ictx));
@@ -183,7 +183,7 @@ TEST_F(TestJournalReplay, AioDiscardEvent) {
 
   // verify lock ordering constraints
   aio_comp = new librbd::io::AioCompletion();
-  ictx->io_work_queue->aio_discard(aio_comp, 0, read_payload.size());
+  ictx->io_work_queue->aio_discard(aio_comp, 0, read_payload.size(), ictx->cct->_conf->rbd_skip_partial_discard);
   ASSERT_EQ(0, aio_comp->wait_for_complete());
   aio_comp->release();
 }
index 9cbd6632e94a73fc60538982bf0330fa4ae455f7..62fc57e178ea7a90ba44f4f76006ff56f4ec8db4 100644 (file)
@@ -37,11 +37,12 @@ struct ImageRequest<MockReplayImageCtx> {
     s_instance->aio_write(c, image_extents, bl, op_flags);
   }
 
-  MOCK_METHOD3(aio_discard, void(AioCompletion *c, uint64_t off, uint64_t len));
+  MOCK_METHOD4(aio_discard, void(AioCompletion *c, uint64_t off, uint64_t len,
+                                 bool skip_partial_discard));
   static void aio_discard(MockReplayImageCtx *ictx, AioCompletion *c,
-                          uint64_t off, uint64_t len) {
+                          uint64_t off, uint64_t len, bool skip_partial_discard) {
     assert(s_instance != nullptr);
-    s_instance->aio_discard(c, off, len);
+    s_instance->aio_discard(c, off, len, skip_partial_discard);
   }
 
   MOCK_METHOD1(aio_flush, void(AioCompletion *c));
@@ -126,8 +127,8 @@ public:
 
   void expect_aio_discard(MockIoImageRequest &mock_io_image_request,
                           io::AioCompletion **aio_comp, uint64_t off,
-                          uint64_t len) {
-    EXPECT_CALL(mock_io_image_request, aio_discard(_, off, len))
+                          uint64_t len, bool skip_partial_discard) {
+    EXPECT_CALL(mock_io_image_request, aio_discard(_, off, len, skip_partial_discard))
                   .WillOnce(SaveArg<0>(aio_comp));
   }
 
@@ -337,9 +338,9 @@ TEST_F(TestMockJournalReplay, AioDiscard) {
   io::AioCompletion *aio_comp;
   C_SaferCond on_ready;
   C_SaferCond on_safe;
-  expect_aio_discard(mock_io_image_request, &aio_comp, 123, 456);
+  expect_aio_discard(mock_io_image_request, &aio_comp, 123, 456, ictx->skip_partial_discard);
   when_process(mock_journal_replay,
-               EventEntry{AioDiscardEvent(123, 456)},
+               EventEntry{AioDiscardEvent(123, 456, ictx->skip_partial_discard)},
                &on_ready, &on_safe);
 
   when_complete(mock_image_ctx, aio_comp, 0);
@@ -447,9 +448,9 @@ TEST_F(TestMockJournalReplay, IOError) {
   io::AioCompletion *aio_comp;
   C_SaferCond on_ready;
   C_SaferCond on_safe;
-  expect_aio_discard(mock_io_image_request, &aio_comp, 123, 456);
+  expect_aio_discard(mock_io_image_request, &aio_comp, 123, 456, ictx->skip_partial_discard);
   when_process(mock_journal_replay,
-               EventEntry{AioDiscardEvent(123, 456)},
+               EventEntry{AioDiscardEvent(123, 456, ictx->skip_partial_discard)},
                &on_ready, &on_safe);
 
   when_complete(mock_image_ctx, aio_comp, -EINVAL);
@@ -478,12 +479,12 @@ TEST_F(TestMockJournalReplay, SoftFlushIO) {
     io::AioCompletion *aio_comp;
     io::AioCompletion *flush_comp = nullptr;
     C_SaferCond on_ready;
-    expect_aio_discard(mock_io_image_request, &aio_comp, 123, 456);
+    expect_aio_discard(mock_io_image_request, &aio_comp, 123, 456, ictx->skip_partial_discard);
     if (i == io_count - 1) {
       expect_aio_flush(mock_io_image_request, &flush_comp);
     }
     when_process(mock_journal_replay,
-                 EventEntry{AioDiscardEvent(123, 456)},
+                 EventEntry{AioDiscardEvent(123, 456, ictx->skip_partial_discard)},
                  &on_ready, &on_safes[i]);
     when_complete(mock_image_ctx, aio_comp, 0);
     ASSERT_EQ(0, on_ready.wait());
@@ -555,9 +556,9 @@ TEST_F(TestMockJournalReplay, Flush) {
   io::AioCompletion *aio_comp = nullptr;
   C_SaferCond on_ready;
   C_SaferCond on_safe;
-  expect_aio_discard(mock_io_image_request, &aio_comp, 123, 456);
+  expect_aio_discard(mock_io_image_request, &aio_comp, 123, 456, ictx->skip_partial_discard);
   when_process(mock_journal_replay,
-               EventEntry{AioDiscardEvent(123, 456)},
+               EventEntry{AioDiscardEvent(123, 456, ictx->skip_partial_discard)},
                &on_ready, &on_safe);
 
   when_complete(mock_image_ctx, aio_comp, 0);
index 36ce5b71a7c854a0f535c438653c266de4e19681..8c5624c8659ffe0d445ab88d88fdbc56d34d846b 100644 (file)
@@ -28,7 +28,7 @@ struct MockImageCache {
     aio_write_mock(image_extents, bl, fadvise_flags, on_finish);
   }
 
-  MOCK_METHOD3(aio_discard, void(uint64_t, uint64_t, Context *));
+  MOCK_METHOD4(aio_discard, void(uint64_t, uint64_t, bool, Context *));
   MOCK_METHOD1(aio_flush, void(Context *));
   MOCK_METHOD5(aio_writesame_mock, void(uint64_t, uint64_t, ceph::bufferlist& bl,
                                         int, Context *));
index b9eb60db11ca47e23597e66f71cb8bc6a7a9eea8..fea96009931851f0d0ebbf2c244bd58e9ac150e6 100644 (file)
@@ -299,7 +299,7 @@ TEST_F(TestInternal, AioDiscardRequestsLock) {
   Context *ctx = new DummyContext();
   auto c = librbd::io::AioCompletion::create(ctx);
   c->get();
-  ictx->io_work_queue->aio_discard(c, 0, 256);
+  ictx->io_work_queue->aio_discard(c, 0, 256, false);
 
   bool is_owner;
   ASSERT_EQ(0, librbd::is_exclusive_lock_owner(ictx, &is_owner));
@@ -686,7 +686,7 @@ TEST_F(TestInternal, DiscardCopyup)
   read_bl.push_back(read_ptr);
 
   ASSERT_EQ(static_cast<int>(m_image_size - 64),
-            ictx2->io_work_queue->discard(32, m_image_size - 64));
+            ictx2->io_work_queue->discard(32, m_image_size - 64, false));
   ASSERT_EQ(0, librbd::snap_set(ictx2, "snap1"));
 
   {
index fe77cb01bc363e2f091dec2d39c780dae0df7826..d34f04187b4aba35addec9b1517f1f8f9c9f14d7 100644 (file)
@@ -487,7 +487,7 @@ TEST_F(TestMockImageSyncObjectCopyRequest, Trim) {
   // trim the object
   uint64_t trim_offset = rand() % one.range_end();
   ASSERT_LE(0, m_remote_image_ctx->io_work_queue->discard(
-    trim_offset, one.range_end() - trim_offset));
+    trim_offset, one.range_end() - trim_offset, m_remote_image_ctx->skip_partial_discard));
   ASSERT_EQ(0, create_snap("sync"));
 
   librbd::MockTestImageCtx mock_remote_image_ctx(*m_remote_image_ctx);
@@ -530,7 +530,7 @@ TEST_F(TestMockImageSyncObjectCopyRequest, Remove) {
 
   // remove the object
   uint64_t object_size = 1 << m_remote_image_ctx->order;
-  ASSERT_LE(0, m_remote_image_ctx->io_work_queue->discard(0, object_size));
+  ASSERT_LE(0, m_remote_image_ctx->io_work_queue->discard(0, object_size, m_remote_image_ctx->skip_partial_discard));
   ASSERT_EQ(0, create_snap("sync"));
   librbd::MockTestImageCtx mock_remote_image_ctx(*m_remote_image_ctx);
   librbd::MockTestImageCtx mock_local_image_ctx(*m_local_image_ctx);
index 51d48357b5e2fea67b6cf6f343bc1de13d291149..8947ddbc075d479e1376e026783252e728b1c9ca 100644 (file)
@@ -33,7 +33,7 @@ void scribble(librbd::ImageCtx *image_ctx, int num_ops, size_t max_size)
     uint64_t len = 1 + rand() % max_size;
 
     if (rand() % 4 == 0) {
-      ASSERT_EQ((int)len, image_ctx->io_work_queue->discard(off, len));
+      ASSERT_EQ((int)len, image_ctx->io_work_queue->discard(off, len, image_ctx->skip_partial_discard));
     } else {
       bufferlist bl;
       bl.append(std::string(len, '1'));
@@ -202,7 +202,7 @@ TEST_F(TestImageSync, Discard) {
   ASSERT_EQ(0, create_snap(m_remote_image_ctx, "snap", nullptr));
 
   ASSERT_EQ((int)len - 2, m_remote_image_ctx->io_work_queue->discard(off + 1,
-                                                                     len - 2));
+                                                                     len - 2, m_remote_image_ctx->skip_partial_discard));
   {
     RWLock::RLocker owner_locker(m_remote_image_ctx->owner_lock);
     ASSERT_EQ(0, m_remote_image_ctx->flush());
index 697f041949211cd4a9d3c8e4b47bab82ee59bca2..ee3e466a6d3cec3adc9f650bf1da5719c9643557 100644 (file)
@@ -847,7 +847,7 @@ TEST_F(TestMockImageReplayer, DelayedReplay) {
   // process with delay
   EXPECT_CALL(mock_replay_entry, get_data());
   librbd::journal::EventEntry event_entry(
-    librbd::journal::AioDiscardEvent(123, 345), ceph_clock_now());
+    librbd::journal::AioDiscardEvent(123, 345, false), ceph_clock_now());
   EXPECT_CALL(mock_local_replay, decode(_, _))
     .WillOnce(DoAll(SetArgPointee<1>(event_entry),
                     Return(0)));