]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
librbd: update size / parent overlap after resize completes
authorJason Dillaman <dillaman@redhat.com>
Tue, 10 Mar 2015 01:45:06 +0000 (21:45 -0400)
committerJosh Durgin <jdurgin@redhat.com>
Tue, 10 Mar 2015 22:41:46 +0000 (15:41 -0700)
Update the in-memory image metadata for size and parent
overlap after updating the on-disk image metadata. Also
schedule an image refresh in case multiple resizes are
enqueued -- since ictx_refresh isn't async.

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

index 7459f2c3ad2332e2bb067882cb34838b169178a7..914e85f60e07103ef96fd805ed72c479dc16de88 100644 (file)
@@ -22,11 +22,12 @@ AsyncResizeRequest::AsyncResizeRequest(ImageCtx &image_ctx, Context *on_finish,
                                       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)
+    m_prog_ctx(prog_ctx), 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);
+  compute_parent_overlap();
 }
 
 AsyncResizeRequest::~AsyncResizeRequest() {
@@ -36,6 +37,7 @@ AsyncResizeRequest::~AsyncResizeRequest() {
     assert(m_xlist_item.remove_myself());
     if (!m_image_ctx.async_resize_reqs.empty()) {
       next_req = m_image_ctx.async_resize_reqs.front();
+      next_req->compute_parent_overlap();
     }
   }
 
@@ -50,16 +52,6 @@ bool AsyncResizeRequest::should_complete(int r) {
 
   if (r < 0) {
     lderr(cct) << "resize encountered an error: " << cpp_strerror(r) << dendl;
-    RWLock::WLocker l(m_image_ctx.snap_lock);
-    if (m_image_ctx.size == m_new_size) {
-      m_image_ctx.size = m_original_size;
-    }
-
-    RWLock::WLocker l2(m_image_ctx.parent_lock);
-    if (m_image_ctx.parent != NULL &&
-       m_image_ctx.parent_md.overlap == m_new_parent_overlap) {
-      m_image_ctx.parent_md.overlap = m_original_parent_overlap;
-    }
     return true;
   }
 
@@ -87,12 +79,16 @@ bool AsyncResizeRequest::should_complete(int r) {
   case STATE_UPDATE_HEADER:
     ldout(cct, 5) << "UPDATE_HEADER" << dendl;
     if (send_shrink_object_map()) {
+      update_size_and_overlap();
+      increment_refresh_seq();
       return true;
     }
     break;
 
   case STATE_SHRINK_OBJECT_MAP:
     ldout(cct, 5) << "SHRINK_OBJECT_MAP" << dendl;
+    update_size_and_overlap();
+    increment_refresh_seq();
     return true;
 
   case STATE_FINISHED:
@@ -143,19 +139,6 @@ void AsyncResizeRequest::send_flush() {
                             << " new_size=" << m_new_size << dendl;
   m_state = STATE_FLUSH;
 
-  {
-    // update in-memory size to clip concurrent IO operations
-    RWLock::WLocker l(m_image_ctx.snap_lock);
-    m_image_ctx.size = m_new_size;
-
-    RWLock::WLocker l2(m_image_ctx.parent_lock);
-    if (m_image_ctx.parent != NULL) {
-      m_original_parent_overlap = m_image_ctx.parent_md.overlap;
-      m_new_parent_overlap = MIN(m_new_size, m_original_parent_overlap);
-      m_image_ctx.parent_md.overlap = m_new_parent_overlap;
-    }
-  }
-
   // with clipping adjusted, ensure that write / copy-on-read operations won't
   // (re-)create objects that we just removed
   m_image_ctx.flush_async_operations(create_callback_context());
@@ -222,8 +205,7 @@ bool AsyncResizeRequest::send_shrink_object_map() {
   bool lost_exclusive_lock = false;
   {
     RWLock::RLocker l(m_image_ctx.owner_lock);
-    if (!m_image_ctx.object_map.enabled() ||
-       m_new_size > m_original_size) {
+    if (!m_image_ctx.object_map.enabled() || m_new_size > m_original_size) {
       return true;
     }
 
@@ -258,16 +240,12 @@ void AsyncResizeRequest::send_update_header() {
   m_state = STATE_UPDATE_HEADER;
 
   {
-    RWLock::RLocker l(m_image_ctx.owner_lock); 
+    RWLock::RLocker l(m_image_ctx.owner_lock);
     if (m_image_ctx.image_watcher->is_lock_supported() &&
        !m_image_ctx.image_watcher->is_lock_owner()) {
       ldout(m_image_ctx.cct, 1) << "lost exclusive lock during header update" << dendl;
       lost_exclusive_lock = true;
     } else {
-      m_image_ctx.snap_lock.get_write();
-      m_image_ctx.size = m_new_size;
-      m_image_ctx.snap_lock.put_write();
-
       librados::ObjectWriteOperation op;
       if (m_image_ctx.old_format) {
        // rewrite header
@@ -296,4 +274,29 @@ void AsyncResizeRequest::send_update_header() {
   }
 }
 
+void AsyncResizeRequest::compute_parent_overlap() {
+  RWLock::RLocker l2(m_image_ctx.parent_lock);
+  if (m_image_ctx.parent == NULL) {
+    m_new_parent_overlap = 0;
+  } else {
+    m_new_parent_overlap = MIN(m_new_size, m_image_ctx.parent_md.overlap);
+  }
+}
+
+void AsyncResizeRequest::increment_refresh_seq() {
+  m_image_ctx.refresh_lock.Lock();
+  ++m_image_ctx.refresh_seq;
+  m_image_ctx.refresh_lock.Unlock();
+}
+
+void AsyncResizeRequest::update_size_and_overlap() {
+  RWLock::WLocker snap_locker(m_image_ctx.snap_lock);
+  m_image_ctx.size = m_new_size;
+
+  RWLock::WLocker parent_locker(m_image_ctx.parent_lock);
+  if (m_image_ctx.parent != NULL && m_new_size < m_original_size) {
+    m_image_ctx.parent_md.overlap = m_new_parent_overlap;
+  }
+}
+
 } // namespace librbd
index 655b2135a9c66305c8a93ed65115f1f1d1333d36..5ac83512fb475020b8b1706b08ef5ebdd9b18a50 100644 (file)
@@ -79,7 +79,6 @@ private:
   uint64_t m_original_size;
   uint64_t m_new_size;
   ProgressContext &m_prog_ctx;
-  uint64_t m_original_parent_overlap;
   uint64_t m_new_parent_overlap;
 
   xlist<AsyncResizeRequest *>::item m_xlist_item;
@@ -93,6 +92,10 @@ private:
   bool send_shrink_object_map();
   void send_update_header();
 
+  void compute_parent_overlap();
+  void increment_refresh_seq();
+  void update_size_and_overlap();
+
 };
 
 } // namespace librbd