]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
librbd: queue multiple resize requests
authorJason Dillaman <dillaman@redhat.com>
Tue, 10 Mar 2015 01:30:17 +0000 (21:30 -0400)
committerJosh Durgin <jdurgin@redhat.com>
Tue, 10 Mar 2015 22:41:46 +0000 (15:41 -0700)
Only allow a single resize request to be executed concurrently.

Signed-off-by: Jason Dillaman <dillaman@redhat.com>
src/librbd/AsyncResizeRequest.cc
src/librbd/AsyncResizeRequest.h
src/librbd/ImageCtx.h

index d79832939595d10e1b6be82402f446a549b01c5f..7459f2c3ad2332e2bb067882cb34838b169178a7 100644 (file)
 namespace librbd
 {
 
-bool AsyncResizeRequest::should_complete(int r)
+AsyncResizeRequest::AsyncResizeRequest(ImageCtx &image_ctx, Context *on_finish,
+                                      uint64_t original_size,
+                                       uint64_t new_size,
+                                      ProgressContext &prog_ctx)
+  : AsyncRequest(image_ctx, on_finish),
+    m_original_size(original_size), m_new_size(new_size),
+    m_prog_ctx(prog_ctx), m_original_parent_overlap(0),
+    m_new_parent_overlap(0), m_xlist_item(this)
 {
+  RWLock::WLocker l(m_image_ctx.snap_lock);
+  m_image_ctx.async_resize_reqs.push_back(&m_xlist_item);
+}
+
+AsyncResizeRequest::~AsyncResizeRequest() {
+  AsyncResizeRequest *next_req = NULL;
+  {
+    RWLock::WLocker l(m_image_ctx.snap_lock);
+    assert(m_xlist_item.remove_myself());
+    if (!m_image_ctx.async_resize_reqs.empty()) {
+      next_req = m_image_ctx.async_resize_reqs.front();
+    }
+  }
+
+  if (next_req != NULL) {
+    next_req->send();
+  }
+}
+
+bool AsyncResizeRequest::should_complete(int r) {
   CephContext *cct = m_image_ctx.cct;
   ldout(cct, 5) << this << " should_complete: " << " r=" << r << dendl;
 
@@ -81,8 +108,20 @@ bool AsyncResizeRequest::should_complete(int r)
 }
 
 void AsyncResizeRequest::send() {
+  {
+    RWLock::RLocker l(m_image_ctx.snap_lock);
+    assert(!m_image_ctx.async_resize_reqs.empty());
+
+    // only allow a single concurrent resize request
+    if (m_image_ctx.async_resize_reqs.front() != this) {
+      return;
+    }
+  }
+
   CephContext *cct = m_image_ctx.cct;
-  if (m_original_size == m_new_size) {
+  if (is_canceled()) {
+    complete(-ERESTART);
+  } else if (m_original_size == m_new_size) {
     ldout(cct, 2) << this << " no change in size (" << m_original_size
                  << " -> " << m_new_size << ")" << dendl;
     m_state = STATE_FINISHED;
index a341a3ae684414cd2ca0b1a8371bc50ffb9d4b2c..de6a49b0ee9894372a9bad3894a0f437e28b177e 100644 (file)
@@ -4,6 +4,7 @@
 #define CEPH_LIBRBD_ASYNC_RESIZE_REQUEST_H
 
 #include "librbd/AsyncRequest.h"
+#include "include/xlist.h"
 
 namespace librbd
 {
@@ -16,17 +17,12 @@ class AsyncResizeRequest : public AsyncRequest
 public:
   AsyncResizeRequest(ImageCtx &image_ctx, Context *on_finish,
                     uint64_t original_size, uint64_t new_size,
-                    ProgressContext &prog_ctx)
-    : AsyncRequest(image_ctx, on_finish),
-      m_original_size(original_size), m_new_size(new_size),
-      m_prog_ctx(prog_ctx), m_original_parent_overlap(0),
-      m_new_parent_overlap(0)
-  {
-  }
+                    ProgressContext &prog_ctx);
+  virtual ~AsyncResizeRequest();
 
   virtual void send();
 
-protected:
+private:
   /**
    * Resize goes through the following state machine to resize the image
    * and update the object map:
@@ -74,6 +70,8 @@ protected:
   uint64_t m_original_parent_overlap;
   uint64_t m_new_parent_overlap;
 
+  xlist<AsyncResizeRequest *>::item m_xlist_item;
+
   virtual bool should_complete(int r);
 
   void send_flush();
index a35e40b54b4b3a2bd6ab74d11653ce02199d21ae..7cb6e3a00c6221c17330a6aa7268e93b85c0c99a 100644 (file)
@@ -38,6 +38,7 @@ namespace librbd {
 
   class AsyncOperation;
   class AsyncRequest;
+  class AsyncResizeRequest;
   class CopyupRequest;
   class ImageWatcher;
 
@@ -89,7 +90,7 @@ namespace librbd {
     RWLock parent_lock; // protects parent_md and parent
     Mutex refresh_lock; // protects refresh_seq and last_refresh
     RWLock object_map_lock; // protects object map updates and object_map itself
-    Mutex async_ops_lock; // protects async_ops
+    Mutex async_ops_lock; // protects async_ops and async_requests
     Mutex copyup_list_lock; // protects copyup_waiting_list
 
     unsigned extra_read_flags;
@@ -127,6 +128,8 @@ namespace librbd {
 
     atomic_t async_request_seq;
 
+    xlist<AsyncResizeRequest*> async_resize_reqs;
+
     /**
      * Either image_name or image_id must be set.
      * If id is not known, pass the empty std::string,