]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
librbd: prevent copyup during image shrink operations 3607/head
authorJason Dillaman <dillaman@redhat.com>
Tue, 3 Feb 2015 11:07:00 +0000 (06:07 -0500)
committerJason Dillaman <dillaman@redhat.com>
Tue, 3 Feb 2015 11:07:11 +0000 (06:07 -0500)
If a cloned image was shrunk, it was possible for a copyup
to be performed on objects outside of the new image range.
Resize now pre-shrinks the parent overlap to disable copyup
when removing objects.

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

index ba9ae71eb3a949e2f00026556d8cc1601610fdd5..a5da41edbefd5dbba916f0dba9585c3c7837079e 100644 (file)
@@ -249,15 +249,18 @@ namespace librbd {
   protected:
     virtual void add_write_ops(librados::ObjectWriteOperation *wr) {
       if (has_parent()) {
-       m_object_state = OBJECT_EXISTS;
        wr->truncate(0);
       } else {
-       m_object_state = OBJECT_PENDING;
        wr->remove();
       }
     }
 
     virtual void pre_object_map_update(uint8_t *new_state) {
+      if (has_parent()) {
+       m_object_state = OBJECT_EXISTS;
+      } else {
+       m_object_state = OBJECT_PENDING;
+      }
       *new_state = m_object_state;
     }
 
index af2a3cdf8dccf27ab3fb3e8faed38ee453922a86..8b161d50daa8ffc2c59461649bdc55bb107949f9 100644 (file)
@@ -27,6 +27,12 @@ bool AsyncResizeRequest::should_complete(int r)
     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;
   }
 
@@ -92,6 +98,13 @@ void AsyncResizeRequest::send_trim_image() {
     // update in-memory size to clip concurrent IO operations
     RWLock::WLocker l(m_image_ctx.md_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;
+    }
   }
 
   AsyncTrimRequest *req = new AsyncTrimRequest(m_image_ctx,
index 0e72a101e7ffae72be4f73d56680372323bc06d8..6884abf003936c0f7d66e57e55ff393143abfbdf 100644 (file)
@@ -19,7 +19,8 @@ public:
                     ProgressContext &prog_ctx)
     : AsyncRequest(image_ctx, on_finish),
       m_original_size(original_size), m_new_size(new_size),
-      m_prog_ctx(prog_ctx)
+      m_prog_ctx(prog_ctx), m_original_parent_overlap(0),
+      m_new_parent_overlap(0)
   {
   }
 
@@ -60,6 +61,8 @@ protected:
   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;
 
   virtual bool should_complete(int r);
 
index f179fa83302900f15edbdd2f6c52b868e7875665..6b2be6389cc49253ec6cb4710ea815493bfb9dea 100644 (file)
@@ -187,6 +187,9 @@ bool ObjectMap::aio_update(uint64_t start_object_no, uint64_t end_object_no,
   assert(start_object_no < end_object_no);
   
   CephContext *cct = m_image_ctx.cct;
+  ldout(cct, 20) << &m_image_ctx << " aio_update: start=" << start_object_no
+                << ", end=" << end_object_no << ", new_state="
+                << static_cast<uint32_t>(new_state) << dendl;
   if (end_object_no > object_map.size()) {
     ldout(cct, 20) << "skipping update of invalid object map" << dendl;
     return false;
@@ -319,7 +322,8 @@ void ObjectMap::UpdateRequest::send() {
 
   ldout(cct, 20) << &m_image_ctx << " updating on-disk object map: ["
                 << m_start_object_no << "," << m_end_object_no << ") = "
-                << (m_current_state ? stringify(*m_current_state) : "")
+                << (m_current_state ?
+                      stringify(static_cast<uint32_t>(*m_current_state)) : "")
                 << "->" << static_cast<uint32_t>(m_new_state)
                 << dendl;