]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
librbd: fix crash using clone of flattened image
authorJosh Durgin <josh.durgin@inktank.com>
Thu, 24 Jul 2014 22:29:40 +0000 (15:29 -0700)
committerJosh Durgin <josh.durgin@inktank.com>
Mon, 15 Sep 2014 18:36:14 +0000 (11:36 -0700)
The crash occurs due to ImageCtx->parent->parent being uninitialized,
since the inital open_parent() -> open_image(parent) ->
ictx_refresh(parent) occurs before ImageCtx->parent->snap_id is set,
so refresh_parent() is not called to open an ImageCtx for the parent
of the parent. This leaves the ImageCtx->parent->parent NULL, but the
rest of ImageCtx->parent updated to point at the correct parent snapshot.

Setting the parent->snap_id earlier has some unintended side effects
currently, so for now just call refresh_parent() during
open_parent(). This is the easily backportable version of the
fix. Further patches can clean up this whole initialization process.

Fixes: #8845
Backport: firefly, dumpling
Signed-off-by: Josh Durgin <josh.durgin@inktank.com>
(cherry picked from commit 2545e80d274b23b6715f4d8b1f4c6b96182996fb)

src/librbd/internal.cc
src/librbd/internal.h
src/test/pybind/test_rbd.py

index 138ed42164bdfcbc18f688d4c42158b4ceb07563..7394a9ac7d0b8dba9fefa5d6918ba629631ca938 100644 (file)
@@ -1269,6 +1269,19 @@ reprotect_and_return_err:
       return r;
     }
     ictx->parent->snap_set(ictx->parent->snap_name);
+    ictx->parent->parent_lock.get_write();
+    r = refresh_parent(ictx->parent);
+    if (r < 0) {
+      lderr(ictx->cct) << "error refreshing parent snapshot "
+                      << ictx->parent->id << " "
+                      << ictx->parent->snap_name << dendl;
+      ictx->parent->parent_lock.put_write();
+      ictx->parent->snap_lock.put_write();
+      close_image(ictx->parent);
+      ictx->parent = NULL;
+      return r;
+    }
+    ictx->parent->parent_lock.put_write();
     ictx->parent->snap_lock.put_write();
 
     return 0;
index 723a688cfb5b665c5dece0a562ffb7d392ef009c..6cf2ca96f4a32e3d546d108c8be262be0a6e795a 100644 (file)
@@ -114,6 +114,7 @@ namespace librbd {
                        bool *is_protected);
   int add_snap(ImageCtx *ictx, const char *snap_name);
   int rm_snap(ImageCtx *ictx, const char *snap_name);
+  int refresh_parent(ImageCtx *ictx);
   int ictx_check(ImageCtx *ictx);
   int ictx_refresh(ImageCtx *ictx);
   int copy(ImageCtx *ictx, IoCtx& dest_md_ctx, const char *destname,
index 6a57ff13c21b7c5edba9e5aad83a30a831832a90..c9efdff6c31c10b65de034adf0dfe3f1972ea9a2 100644 (file)
@@ -808,3 +808,31 @@ class TestClone(object):
                 after_flatten = clone2.read(IMG_SIZE / 2, 256)
                 eq(data, after_flatten)
         self.rbd.remove(ioctx, 'clone2')
+
+    def test_flatten_multi_level(self):
+        self.clone.create_snap('snap2')
+        self.clone.protect_snap('snap2')
+        self.rbd.clone(ioctx, 'clone', 'snap2', ioctx, 'clone3', features)
+        self.clone.flatten()
+        with Image(ioctx, 'clone3') as clone3:
+            clone3.flatten()
+        self.clone.unprotect_snap('snap2')
+        self.clone.remove_snap('snap2')
+        self.rbd.remove(ioctx, 'clone3')
+
+    def test_resize_flatten_multi_level(self):
+        self.clone.create_snap('snap2')
+        self.clone.protect_snap('snap2')
+        self.rbd.clone(ioctx, 'clone', 'snap2', ioctx, 'clone3', features)
+        self.clone.resize(1)
+        orig_data = self.image.read(0, 256)
+        with Image(ioctx, 'clone3') as clone3:
+            clone3_data = clone3.read(0, 256)
+            eq(orig_data, clone3_data)
+        self.clone.flatten()
+        with Image(ioctx, 'clone3') as clone3:
+            clone3_data = clone3.read(0, 256)
+            eq(orig_data, clone3_data)
+        self.rbd.remove(ioctx, 'clone3')
+        self.clone.unprotect_snap('snap2')
+        self.clone.remove_snap('snap2')