]> 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 19:59:13 +0000 (12:59 -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 9fc1cc3671ce96d623774bcf4d15068e8cb5bc44..afa466025327e154be8816f156dbeb47a8ee0130 100644 (file)
@@ -1275,6 +1275,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 6fb1af4617573566e9cec061125c85ca7fd34263..1e9fd9a67a029b7cc01664d9f61aae35c3dc230d 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 bb53081d794518394b3b2862a8bc7435394809d2..2525732671f7a95b99ce07ef8564997a6ba64edf 100644 (file)
@@ -815,3 +815,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')