]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
librbd: finish write request early 32113/head
authorlixiaoy1 <xiaoyan.li@intel.com>
Mon, 9 Dec 2019 14:56:56 +0000 (09:56 -0500)
committerlixiaoy1 <xiaoyan.li@intel.com>
Tue, 10 Dec 2019 10:20:06 +0000 (05:20 -0500)
Finish write requests if the image is read-only or length is 0.

Signed-off-by: Li, Xiaoyan <xiaoyan.li@intel.com>
src/librbd/io/ImageRequest.cc
src/librbd/io/ImageRequest.h
src/test/librbd/io/test_mock_ImageRequest.cc

index dc2acce5df0112f4e4c35dcc26b96ffd3e33e284..977182eacd1c53426c4bbaa1dd3164d8f8f89f56 100644 (file)
@@ -219,7 +219,6 @@ void ImageRequest<I>::aio_compare_and_write(I *ictx, AioCompletion *c,
   req.send();
 }
 
-
 template <typename I>
 void ImageRequest<I>::send() {
   I &image_ctx = this->m_image_ctx;
@@ -237,6 +236,10 @@ void ImageRequest<I>::send() {
     return;
   }
 
+  if (finish_request_early()) {
+    return;
+  }
+
   if (m_bypass_image_cache || m_image_ctx.image_cache == nullptr) {
     update_timestamp();
     send_request();
@@ -407,6 +410,27 @@ void ImageReadRequest<I>::send_image_cache_request() {
                                   req_comp);
 }
 
+template <typename I>
+bool AbstractImageWriteRequest<I>::finish_request_early() {
+  AioCompletion *aio_comp = this->m_aio_comp;
+  {
+    std::shared_lock image_locker{this->m_image_ctx.image_lock};
+    if (this->m_image_ctx.snap_id != CEPH_NOSNAP || this->m_image_ctx.read_only) {
+      aio_comp->fail(-EROFS);
+      return true;
+    }
+  }
+  uint64_t total_bytes = 0;
+  for (auto& image_extent : this->m_image_extents) {
+    total_bytes += image_extent.second;
+  }
+  if (total_bytes == 0) {
+    aio_comp->set_request_count(0);
+    return true;
+  }
+  return false;
+}
+
 template <typename I>
 void AbstractImageWriteRequest<I>::send_request() {
   I &image_ctx = this->m_image_ctx;
@@ -420,10 +444,6 @@ void AbstractImageWriteRequest<I>::send_request() {
     // prevent image size from changing between computing clip and recording
     // pending async operation
     std::shared_lock image_locker{image_ctx.image_lock};
-    if (image_ctx.snap_id != CEPH_NOSNAP || image_ctx.read_only) {
-      aio_comp->fail(-EROFS);
-      return;
-    }
 
     snapc = image_ctx.snapc;
     journaling = (image_ctx.journal != nullptr &&
index f62a6796209501fcd0076c73adc43f84ce5918ad..e5a04597d3e7df46e3a05edebd03119950c636c1 100644 (file)
@@ -83,7 +83,9 @@ protected:
     m_trace.event("start");
   }
 
-
+  virtual bool finish_request_early() {
+    return false;
+  }
   virtual int clip_request();
   virtual void update_timestamp();
   virtual void send_request() = 0;
@@ -138,6 +140,7 @@ protected:
   }
 
   void send_request() override;
+  bool finish_request_early() override;
 
   virtual int prune_object_extents(
       LightweightObjectExtents* object_extents) const {
index c63e2c99540ffcece04632cd77ec0e33a15fe176..2dab0ebe4b64cad87f0f02069da200a38e4931da 100644 (file)
@@ -173,6 +173,38 @@ TEST_F(TestMockIoImageRequest, AioWriteModifyTimestamp) {
   ASSERT_EQ(0, aio_comp_ctx_2.wait());
 }
 
+TEST_F(TestMockIoImageRequest, AioWriteEarlyFinish) {
+  librbd::ImageCtx *ictx;
+  ASSERT_EQ(0, open_image(m_image_name, &ictx));
+
+  MockTestImageCtx mock_image_ctx(*ictx);
+
+  C_SaferCond aio_comp_ctx_1, aio_comp_ctx_2;
+  AioCompletion *aio_comp_1 = AioCompletion::create_and_start(
+    &aio_comp_ctx_1, ictx, AIO_TYPE_WRITE);
+  AioCompletion *aio_comp_2 = AioCompletion::create_and_start(
+    &aio_comp_ctx_2, ictx, AIO_TYPE_WRITE);
+
+  bufferlist bl;
+  MockImageWriteRequest mock_aio_image_write_1(mock_image_ctx, aio_comp_1,
+                                             {{0, 0}}, std::move(bl), 0, {});
+  {
+    std::shared_lock owner_locker{mock_image_ctx.owner_lock};
+    mock_aio_image_write_1.send();
+  }
+  ASSERT_EQ(0, aio_comp_ctx_1.wait());
+
+  mock_image_ctx.snap_id = 123;
+  bl.append("1");
+  MockImageWriteRequest mock_aio_image_write_2(mock_image_ctx, aio_comp_2,
+                                             {{0, 1}}, std::move(bl), 0, {});
+  {
+    std::shared_lock owner_locker{mock_image_ctx.owner_lock};
+    mock_aio_image_write_2.send();
+  }
+  ASSERT_EQ(-EROFS, aio_comp_ctx_2.wait());
+}
+
 TEST_F(TestMockIoImageRequest, AioReadAccessTimestamp) {
   REQUIRE_FORMAT_V2();