]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
librbd: allow to open an image without opening parent image 13130/head
authorRicardo Dias <rdias@suse.com>
Tue, 10 Jan 2017 15:11:19 +0000 (15:11 +0000)
committerRicardo Dias <rdias@suse.com>
Thu, 2 Feb 2017 15:14:49 +0000 (15:14 +0000)
Fixes: http://tracker.ceph.com/issues/18325
Signed-off-by: Ricardo Dias <rdias@suse.com>
(cherry picked from commit 61af1c25015de087a2423811548d975dd7d430b4)

Conflicts:
  src/librbd/ImageState.cc - added missing arg to RefreshRequest::create
  src/librbd/exclusive_lock/PostAcquireRequest.cc -
                                        deleted, does not exist in jewel
  src/librbd/image/OpenRequest.cc - added missing arg to
                                    RefreshRequest::create
  src/librbd/internal.cc - added missing arg to ImageState::open
  src/librbd/librbd.cc - added missing arg to ImageState::open
  src/test/librbd/exclusive_lock/test_mock_PostAcquireRequest.cc -
                                        deleted, does not exist in jewel
  src/test/rbd_mirror/image_replayer/test_mock_CreateImageRequest.cc -
                                        added missing arg to ImageState::open
  src/test/rbd_mirror/test_PoolWatcher.cc - added missing arg to
                                            ImageState::open

22 files changed:
src/librbd/ImageState.cc
src/librbd/ImageState.h
src/librbd/exclusive_lock/AcquireRequest.cc
src/librbd/image/OpenRequest.cc
src/librbd/image/OpenRequest.h
src/librbd/image/RefreshParentRequest.cc
src/librbd/image/RefreshRequest.cc
src/librbd/image/RefreshRequest.h
src/librbd/internal.cc
src/librbd/librbd.cc
src/test/librbd/exclusive_lock/test_mock_AcquireRequest.cc
src/test/librbd/image/test_mock_RefreshRequest.cc
src/test/librbd/test_fixture.cc
src/test/librbd/test_internal.cc
src/test/rbd_mirror/image_replayer/test_mock_CreateImageRequest.cc
src/test/rbd_mirror/test_ImageDeleter.cc
src/test/rbd_mirror/test_ImageReplayer.cc
src/test/rbd_mirror/test_PoolWatcher.cc
src/test/rbd_mirror/test_fixture.cc
src/tools/rbd_mirror/ImageDeleter.cc
src/tools/rbd_mirror/image_replayer/OpenImageRequest.cc
src/tools/rbd_mirror/image_replayer/OpenLocalImageRequest.cc

index 3204307276921f6392ee4ba923c08607a21ecf3c..28cf4274ef9ec02fc853d702ccf40dbe4b1f79b2 100644 (file)
@@ -234,7 +234,8 @@ ImageState<I>::ImageState(I *image_ctx)
   : m_image_ctx(image_ctx), m_state(STATE_UNINITIALIZED),
     m_lock(util::unique_lock_name("librbd::ImageState::m_lock", this)),
     m_last_refresh(0), m_refresh_seq(0),
-    m_update_watchers(new ImageUpdateWatchers(image_ctx->cct)) {
+    m_update_watchers(new ImageUpdateWatchers(image_ctx->cct)),
+    m_skip_open_parent_image(false) {
 }
 
 template <typename I>
@@ -244,19 +245,20 @@ ImageState<I>::~ImageState() {
 }
 
 template <typename I>
-int ImageState<I>::open() {
+int ImageState<I>::open(bool skip_open_parent) {
   C_SaferCond ctx;
-  open(&ctx);
+  open(skip_open_parent, &ctx);
   return ctx.wait();
 }
 
 template <typename I>
-void ImageState<I>::open(Context *on_finish) {
+void ImageState<I>::open(bool skip_open_parent, Context *on_finish) {
   CephContext *cct = m_image_ctx->cct;
   ldout(cct, 20) << __func__ << dendl;
 
   m_lock.Lock();
   assert(m_state == STATE_UNINITIALIZED);
+  m_skip_open_parent_image = skip_open_parent;
 
   Action action(ACTION_TYPE_OPEN);
   action.refresh_seq = m_refresh_seq;
@@ -555,7 +557,7 @@ void ImageState<I>::send_open_unlock() {
     *m_image_ctx, create_context_callback<
       ImageState<I>, &ImageState<I>::handle_open>(this));
   image::OpenRequest<I> *req = image::OpenRequest<I>::create(
-    m_image_ctx, ctx);
+    m_image_ctx, m_skip_open_parent_image, ctx);
 
   m_lock.Unlock();
   req->send();
@@ -620,7 +622,7 @@ void ImageState<I>::send_refresh_unlock() {
     *m_image_ctx, create_context_callback<
       ImageState<I>, &ImageState<I>::handle_refresh>(this));
   image::RefreshRequest<I> *req = image::RefreshRequest<I>::create(
-    *m_image_ctx, false, ctx);
+    *m_image_ctx, false, false, ctx);
 
   m_lock.Unlock();
   req->send();
index 412730e711688659c00afbf3b38dd9813592c199..b6e7ce63b4426d9134b1aa8b4fcc83d662c6272e 100644 (file)
@@ -25,8 +25,8 @@ public:
   ImageState(ImageCtxT *image_ctx);
   ~ImageState();
 
-  int open();
-  void open(Context *on_finish);
+  int open(bool skip_open_parent);
+  void open(bool skip_open_parent, Context *on_finish);
 
   int close();
   void close(Context *on_finish);
@@ -109,6 +109,8 @@ private:
 
   ImageUpdateWatchers *m_update_watchers;
 
+  bool m_skip_open_parent_image;
+
   bool is_transition_state() const;
   bool is_closed() const;
 
index 5a495805debd9d2efb03043b3c66bb26d0b30b9a..344a267db8f90a3e26969e10415311d1b78e943d 100644 (file)
@@ -189,7 +189,7 @@ Context *AcquireRequest<I>::send_refresh() {
   // ImageState is blocked waiting for lock to complete -- safe to directly
   // refresh
   image::RefreshRequest<I> *req = image::RefreshRequest<I>::create(
-    m_image_ctx, true, ctx);
+    m_image_ctx, true, false, ctx);
   req->send();
   return nullptr;
 }
index 36d740da76f495149e96631a77bb84fbd5d202c4..9fbd8bcb485e0d63b4b035a45a9aa8ab357b2b50 100644 (file)
@@ -30,8 +30,10 @@ using util::create_context_callback;
 using util::create_rados_ack_callback;
 
 template <typename I>
-OpenRequest<I>::OpenRequest(I *image_ctx, Context *on_finish)
-  : m_image_ctx(image_ctx), m_on_finish(on_finish), m_error_result(0),
+OpenRequest<I>::OpenRequest(I *image_ctx, bool skip_open_parent,
+                            Context *on_finish)
+  : m_image_ctx(image_ctx), m_skip_open_parent_image(skip_open_parent),
+    m_on_finish(on_finish), m_error_result(0),
     m_last_metadata_key(ImageCtx::METADATA_CONF_PREFIX) {
 }
 
@@ -373,7 +375,7 @@ void OpenRequest<I>::send_refresh() {
 
   using klass = OpenRequest<I>;
   RefreshRequest<I> *ctx = RefreshRequest<I>::create(
-    *m_image_ctx, false,
+    *m_image_ctx, false, m_skip_open_parent_image,
     create_context_callback<klass, &klass::handle_refresh>(this));
   ctx->send();
 }
index 627285b40ffd703bdc1c24d99cdfe39414ef95cf..04c255d9c796a465c56182d0ec2db5a7f04da97f 100644 (file)
@@ -19,8 +19,9 @@ namespace image {
 template <typename ImageCtxT = ImageCtx>
 class OpenRequest {
 public:
-  static OpenRequest *create(ImageCtxT *image_ctx, Context *on_finish) {
-    return new OpenRequest(image_ctx, on_finish);
+  static OpenRequest *create(ImageCtxT *image_ctx, bool skip_open_parent,
+                             Context *on_finish) {
+    return new OpenRequest(image_ctx, skip_open_parent, on_finish);
   }
 
   void send();
@@ -65,9 +66,10 @@ private:
    * @endverbatim
    */
 
-  OpenRequest(ImageCtxT *image_ctx, Context *on_finish);
+  OpenRequest(ImageCtxT *image_ctx, bool skip_open_parent, Context *on_finish);
 
   ImageCtxT *m_image_ctx;
+  bool m_skip_open_parent_image;
   Context *m_on_finish;
 
   bufferlist m_out_bl;
index a44124f391366202d41ba879d639d718ffad9dbd..28058abe7b557f620eddd7b850979920c02ccfe7 100644 (file)
@@ -120,7 +120,7 @@ void RefreshParentRequest<I>::send_open_parent() {
   Context *ctx = create_async_context_callback(
     m_child_image_ctx, create_context_callback<
       klass, &klass::handle_open_parent, false>(this));
-  OpenRequest<I> *req = OpenRequest<I>::create(m_parent_image_ctx, ctx);
+  OpenRequest<I> *req = OpenRequest<I>::create(m_parent_image_ctx, false, ctx);
   req->send();
 }
 
index 04b05fa55d3df8706436c286d6e1ff24e1df7827..70c43b97aacc3277cd884588f64ff562a66ec5c7 100644 (file)
@@ -28,8 +28,9 @@ using util::create_context_callback;
 
 template <typename I>
 RefreshRequest<I>::RefreshRequest(I &image_ctx, bool acquiring_lock,
-                                  Context *on_finish)
+                                  bool skip_open_parent, Context *on_finish)
   : m_image_ctx(image_ctx), m_acquiring_lock(acquiring_lock),
+    m_skip_open_parent_image(skip_open_parent),
     m_on_finish(create_async_context_callback(m_image_ctx, on_finish)),
     m_error_result(0), m_flush_aio(false), m_exclusive_lock(nullptr),
     m_object_map(nullptr), m_journal(nullptr), m_refresh_parent(nullptr) {
@@ -397,8 +398,8 @@ void RefreshRequest<I>::send_v2_refresh_parent() {
 
     parent_info parent_md;
     int r = get_parent_info(m_image_ctx.snap_id, &parent_md);
-    if (r < 0 ||
-        RefreshParentRequest<I>::is_refresh_required(m_image_ctx, parent_md)) {
+    if (!m_skip_open_parent_image && (r < 0 ||
+        RefreshParentRequest<I>::is_refresh_required(m_image_ctx, parent_md))) {
       CephContext *cct = m_image_ctx.cct;
       ldout(cct, 10) << this << " " << __func__ << dendl;
 
index 79b5d9e816d2ed98e30686982f9f5dbc7b4926f5..43275d705f7d325e54d59797e753808232da1a4e 100644 (file)
@@ -27,11 +27,13 @@ template<typename ImageCtxT = ImageCtx>
 class RefreshRequest {
 public:
   static RefreshRequest *create(ImageCtxT &image_ctx, bool acquiring_lock,
-                                Context *on_finish) {
-    return new RefreshRequest(image_ctx, acquiring_lock, on_finish);
+                                bool skip_open_parent, Context *on_finish) {
+    return new RefreshRequest(image_ctx, acquiring_lock, skip_open_parent,
+                              on_finish);
   }
 
-  RefreshRequest(ImageCtxT &image_ctx, bool acquiring_lock, Context *on_finish);
+  RefreshRequest(ImageCtxT &image_ctx, bool acquiring_lock,
+                 bool skip_open_parent, Context *on_finish);
   ~RefreshRequest();
 
   void send();
@@ -98,6 +100,7 @@ private:
 
   ImageCtxT &m_image_ctx;
   bool m_acquiring_lock;
+  bool m_skip_open_parent_image;
   Context *m_on_finish;
 
   int m_error_result;
index b7f7df633af0e929b51e50f36acdf49a22da9a7f..d5875d8dde21f5381f2e4ccda1fa4c6b1a50ebc4 100644 (file)
@@ -1422,7 +1422,7 @@ int mirror_image_disable_internal(ImageCtx *ictx, bool force,
 
     // make sure parent snapshot exists
     ImageCtx *p_imctx = new ImageCtx(p_name, "", p_snap_name, p_ioctx, true);
-    int r = p_imctx->state->open();
+    int r = p_imctx->state->open(false);
     if (r < 0) {
       lderr(cct) << "error opening parent image: "
                 << cpp_strerror(-r) << dendl;
@@ -1558,7 +1558,7 @@ int mirror_image_disable_internal(ImageCtx *ictx, bool force,
     }
 
     c_imctx = new ImageCtx(c_name, "", NULL, c_ioctx, false);
-    r = c_imctx->state->open();
+    r = c_imctx->state->open(false);
     if (r < 0) {
       lderr(cct) << "Error opening new image: " << cpp_strerror(r) << dendl;
       delete c_imctx;
@@ -1631,7 +1631,7 @@ int mirror_image_disable_internal(ImageCtx *ictx, bool force,
                   << dstname << dendl;
 
     ImageCtx *ictx = new ImageCtx(srcname, "", "", io_ctx, false);
-    int r = ictx->state->open();
+    int r = ictx->state->open(false);
     if (r < 0) {
       lderr(ictx->cct) << "error opening source image: " << cpp_strerror(r)
                       << dendl;
@@ -1971,7 +1971,7 @@ int mirror_image_disable_internal(ImageCtx *ictx, bool force,
       if (enable_mirroring) {
         ImageCtx *img_ctx = new ImageCtx("", ictx->id, nullptr,
             ictx->md_ctx, false);
-        r = img_ctx->state->open();
+        r = img_ctx->state->open(false);
         if (r < 0) {
           lderr(cct) << "error opening image: " << cpp_strerror(r) << dendl;
           delete img_ctx;
@@ -2268,7 +2268,7 @@ int mirror_image_disable_internal(ImageCtx *ictx, bool force,
     bool unknown_format = true;
     ImageCtx *ictx = new ImageCtx(
       (id.empty() ? name : std::string()), id, nullptr, io_ctx, false);
-    int r = ictx->state->open();
+    int r = ictx->state->open(true);
     if (r < 0) {
       ldout(cct, 2) << "error opening image: " << cpp_strerror(-r) << dendl;
       delete ictx;
@@ -2538,7 +2538,7 @@ int mirror_image_disable_internal(ImageCtx *ictx, bool force,
 
     ImageCtx *dest = new librbd::ImageCtx(destname, "", NULL,
                                          dest_md_ctx, false);
-    r = dest->state->open();
+    r = dest->state->open(false);
     if (r < 0) {
       delete dest;
       lderr(cct) << "failed to read newly created header" << dendl;
@@ -3603,7 +3603,7 @@ int mirror_image_disable_internal(ImageCtx *ictx, bool force,
         if ((features & RBD_FEATURE_JOURNALING) != 0) {
           ImageCtx *img_ctx = new ImageCtx("", img_pair.second, nullptr,
                                            io_ctx, false);
-          r = img_ctx->state->open();
+          r = img_ctx->state->open(false);
           if (r < 0) {
             lderr(cct) << "error opening image "<< img_pair.first << ": "
                        << cpp_strerror(r) << dendl;
@@ -3650,7 +3650,7 @@ int mirror_image_disable_internal(ImageCtx *ictx, bool force,
           }
         } else {
           ImageCtx *img_ctx = new ImageCtx("", img_id, nullptr, io_ctx, false);
-          r = img_ctx->state->open();
+          r = img_ctx->state->open(false);
           if (r < 0) {
             lderr(cct) << "error opening image id "<< img_id << ": "
                        << cpp_strerror(r) << dendl;
index f560b22d40a697f0bfa1bea67d0922372be42ad6..04bdb06aef2b6a88f89da64d0e4356af378b7b10 100644 (file)
@@ -103,7 +103,7 @@ struct C_OpenAfterCloseComplete : public Context {
   virtual void finish(int r) {
     ldout(ictx->cct, 20) << "C_OpenAfterCloseComplete::finish: r=" << r
                         << dendl;
-    ictx->state->open(new C_OpenComplete(ictx, comp, ictxp, true));
+    ictx->state->open(false, new C_OpenComplete(ictx, comp, ictxp, true));
   }
 };
 
@@ -213,7 +213,7 @@ namespace librbd {
       image.ctx = NULL;
     }
 
-    int r = ictx->state->open();
+    int r = ictx->state->open(false);
     if (r < 0) {
       delete ictx;
       tracepoint(librbd, open_image_exit, r);
@@ -236,7 +236,7 @@ namespace librbd {
       reinterpret_cast<ImageCtx*>(image.ctx)->state->close(
        new C_OpenAfterCloseComplete(ictx, get_aio_completion(c), &image.ctx));
     } else {
-      ictx->state->open(new C_OpenComplete(ictx, get_aio_completion(c),
+      ictx->state->open(false, new C_OpenComplete(ictx, get_aio_completion(c),
                                           &image.ctx));
     }
     tracepoint(librbd, aio_open_image_exit, 0);
@@ -255,7 +255,7 @@ namespace librbd {
       image.ctx = NULL;
     }
 
-    int r = ictx->state->open();
+    int r = ictx->state->open(false);
     if (r < 0) {
       delete ictx;
       tracepoint(librbd, open_image_exit, r);
@@ -278,7 +278,7 @@ namespace librbd {
       reinterpret_cast<ImageCtx*>(image.ctx)->state->close(
        new C_OpenAfterCloseComplete(ictx, get_aio_completion(c), &image.ctx));
     } else {
-      ictx->state->open(new C_OpenComplete(ictx, get_aio_completion(c),
+      ictx->state->open(false, new C_OpenComplete(ictx, get_aio_completion(c),
                                           &image.ctx));
     }
     tracepoint(librbd, aio_open_image_exit, 0);
@@ -1904,7 +1904,7 @@ extern "C" int rbd_open(rados_ioctx_t p, const char *name, rbd_image_t *image,
                                                false);
   tracepoint(librbd, open_image_enter, ictx, ictx->name.c_str(), ictx->id.c_str(), ictx->snap_name.c_str(), ictx->read_only);
 
-  int r = ictx->state->open();
+  int r = ictx->state->open(false);
   if (r < 0) {
     delete ictx;
   } else {
@@ -1925,7 +1925,7 @@ extern "C" int rbd_aio_open(rados_ioctx_t p, const char *name,
                                                false);
   librbd::RBD::AioCompletion *comp = (librbd::RBD::AioCompletion *)c;
   tracepoint(librbd, aio_open_image_enter, ictx, ictx->name.c_str(), ictx->id.c_str(), ictx->snap_name.c_str(), ictx->read_only, comp->pc);
-  ictx->state->open(new C_OpenComplete(ictx, get_aio_completion(comp), image));
+  ictx->state->open(false, new C_OpenComplete(ictx, get_aio_completion(comp), image));
   tracepoint(librbd, aio_open_image_exit, 0);
   return 0;
 }
@@ -1940,7 +1940,7 @@ extern "C" int rbd_open_read_only(rados_ioctx_t p, const char *name,
                                                true);
   tracepoint(librbd, open_image_enter, ictx, ictx->name.c_str(), ictx->id.c_str(), ictx->snap_name.c_str(), ictx->read_only);
 
-  int r = ictx->state->open();
+  int r = ictx->state->open(false);
   if (r < 0) {
     delete ictx;
   } else {
@@ -1961,7 +1961,8 @@ extern "C" int rbd_aio_open_read_only(rados_ioctx_t p, const char *name,
                                                true);
   librbd::RBD::AioCompletion *comp = (librbd::RBD::AioCompletion *)c;
   tracepoint(librbd, aio_open_image_enter, ictx, ictx->name.c_str(), ictx->id.c_str(), ictx->snap_name.c_str(), ictx->read_only, comp->pc);
-  ictx->state->open(new C_OpenComplete(ictx, get_aio_completion(comp), image));
+  ictx->state->open(false, new C_OpenComplete(ictx, get_aio_completion(comp),
+                                              image));
   tracepoint(librbd, aio_open_image_exit, 0);
   return 0;
 }
index 00f03cf96c0b6bcfbac8b87ed01343ca970a93bb..1c96cdba983b7d557913aa99aaef5fde54bc0dbd 100644 (file)
@@ -89,7 +89,7 @@ struct RefreshRequest<librbd::MockTestImageCtx> {
 
   static RefreshRequest *create(librbd::MockTestImageCtx &image_ctx,
                                 bool acquire_lock_refresh,
-                                Context *on_finish) {
+                                bool skip_open_parent, Context *on_finish) {
     EXPECT_TRUE(acquire_lock_refresh);
     assert(s_instance != nullptr);
     s_instance->on_finish = on_finish;
index 4076e253bba5e86d20587c69368f044119d63f23..6b0ff52ab53418495debb60d3955fb6c335b750f 100644 (file)
@@ -321,7 +321,7 @@ TEST_F(TestMockImageRefreshRequest, SuccessV1) {
   expect_init_layout(mock_image_ctx);
 
   C_SaferCond ctx;
-  MockRefreshRequest *req = new MockRefreshRequest(mock_image_ctx, false, &ctx);
+  MockRefreshRequest *req = new MockRefreshRequest(mock_image_ctx, false, false, &ctx);
   req->send();
 
   ASSERT_EQ(0, ctx.wait());
@@ -347,7 +347,7 @@ TEST_F(TestMockImageRefreshRequest, SuccessSnapshotV1) {
   expect_add_snap(mock_image_ctx, "snap", ictx->snap_ids.begin()->second);
 
   C_SaferCond ctx;
-  MockRefreshRequest *req = new MockRefreshRequest(mock_image_ctx, false, &ctx);
+  MockRefreshRequest *req = new MockRefreshRequest(mock_image_ctx, false, false, &ctx);
   req->send();
 
   ASSERT_EQ(0, ctx.wait());
@@ -374,7 +374,7 @@ TEST_F(TestMockImageRefreshRequest, SuccessV2) {
   }
 
   C_SaferCond ctx;
-  MockRefreshRequest *req = new MockRefreshRequest(mock_image_ctx, false, &ctx);
+  MockRefreshRequest *req = new MockRefreshRequest(mock_image_ctx, false, false, &ctx);
   req->send();
 
   ASSERT_EQ(0, ctx.wait());
@@ -405,7 +405,7 @@ TEST_F(TestMockImageRefreshRequest, SuccessSnapshotV2) {
   expect_add_snap(mock_image_ctx, "snap", ictx->snap_ids.begin()->second);
 
   C_SaferCond ctx;
-  MockRefreshRequest *req = new MockRefreshRequest(mock_image_ctx, false, &ctx);
+  MockRefreshRequest *req = new MockRefreshRequest(mock_image_ctx, false, false, &ctx);
   req->send();
 
   ASSERT_EQ(0, ctx.wait());
@@ -438,7 +438,7 @@ TEST_F(TestMockImageRefreshRequest, SuccessSetSnapshotV2) {
   expect_get_snap_id(mock_image_ctx, "snap", ictx->snap_ids.begin()->second);
 
   C_SaferCond ctx;
-  MockRefreshRequest *req = new MockRefreshRequest(mock_image_ctx, false, &ctx);
+  MockRefreshRequest *req = new MockRefreshRequest(mock_image_ctx, false, false, &ctx);
   req->send();
 
   ASSERT_EQ(0, ctx.wait());
@@ -488,7 +488,52 @@ TEST_F(TestMockImageRefreshRequest, SuccessChild) {
   expect_refresh_parent_finalize(mock_image_ctx, *mock_refresh_parent_request, 0);
 
   C_SaferCond ctx;
-  MockRefreshRequest *req = new MockRefreshRequest(mock_image_ctx, false, &ctx);
+  MockRefreshRequest *req = new MockRefreshRequest(mock_image_ctx, false, false, &ctx);
+  req->send();
+
+  ASSERT_EQ(0, ctx.wait());
+}
+
+TEST_F(TestMockImageRefreshRequest, SuccessChildDontOpenParent) {
+  REQUIRE_FEATURE(RBD_FEATURE_LAYERING);
+
+  librbd::ImageCtx *ictx;
+  librbd::ImageCtx *ictx2 = nullptr;
+  std::string clone_name = get_temp_image_name();
+
+  ASSERT_EQ(0, open_image(m_image_name, &ictx));
+  ASSERT_EQ(0, snap_create(*ictx, "snap"));
+  ASSERT_EQ(0, snap_protect(*ictx, "snap"));
+  BOOST_SCOPE_EXIT_ALL((&)) {
+    if (ictx2 != nullptr) {
+      close_image(ictx2);
+    }
+
+    librbd::NoOpProgressContext no_op;
+    ASSERT_EQ(0, librbd::remove(m_ioctx, clone_name, "", no_op));
+    ASSERT_EQ(0, ictx->operations->snap_unprotect("snap"));
+  };
+
+  int order = ictx->order;
+  ASSERT_EQ(0, librbd::clone(m_ioctx, m_image_name.c_str(), "snap", m_ioctx,
+                             clone_name.c_str(), ictx->features, &order, 0, 0));
+
+  ASSERT_EQ(0, open_image(clone_name, &ictx2));
+
+  MockRefreshImageCtx mock_image_ctx(*ictx2);
+  MockExclusiveLock mock_exclusive_lock;
+  expect_op_work_queue(mock_image_ctx);
+  expect_test_features(mock_image_ctx);
+
+  InSequence seq;
+  expect_get_mutable_metadata(mock_image_ctx, 0);
+  expect_get_flags(mock_image_ctx, 0);
+  if (ictx->test_features(RBD_FEATURE_EXCLUSIVE_LOCK)) {
+    expect_init_exclusive_lock(mock_image_ctx, mock_exclusive_lock, 0);
+  }
+
+  C_SaferCond ctx;
+  MockRefreshRequest *req = new MockRefreshRequest(mock_image_ctx, false, true, &ctx);
   req->send();
 
   ASSERT_EQ(0, ctx.wait());
@@ -544,7 +589,7 @@ TEST_F(TestMockImageRefreshRequest, DisableExclusiveLock) {
   expect_shut_down_exclusive_lock(mock_image_ctx, *mock_exclusive_lock, 0);
 
   C_SaferCond ctx;
-  MockRefreshRequest *req = new MockRefreshRequest(mock_image_ctx, false, &ctx);
+  MockRefreshRequest *req = new MockRefreshRequest(mock_image_ctx, false, false, &ctx);
   req->send();
 
   ASSERT_EQ(0, ctx.wait());
@@ -589,7 +634,7 @@ TEST_F(TestMockImageRefreshRequest, DisableExclusiveLockWhileAcquiringLock) {
   expect_refresh_parent_is_required(mock_refresh_parent_request, false);
 
   C_SaferCond ctx;
-  MockRefreshRequest *req = new MockRefreshRequest(mock_image_ctx, true, &ctx);
+  MockRefreshRequest *req = new MockRefreshRequest(mock_image_ctx, true, false, &ctx);
   req->send();
 
   ASSERT_EQ(-ERESTART, ctx.wait());
@@ -631,7 +676,7 @@ TEST_F(TestMockImageRefreshRequest, JournalDisabledByPolicy) {
   expect_journal_disabled(mock_journal_policy, true);
 
   C_SaferCond ctx;
-  MockRefreshRequest *req = new MockRefreshRequest(mock_image_ctx, false, &ctx);
+  MockRefreshRequest *req = new MockRefreshRequest(mock_image_ctx, false, false, &ctx);
   req->send();
 
   ASSERT_EQ(0, ctx.wait());
@@ -675,7 +720,7 @@ TEST_F(TestMockImageRefreshRequest, EnableJournalWithExclusiveLock) {
   expect_open_journal(mock_image_ctx, mock_journal, 0);
 
   C_SaferCond ctx;
-  MockRefreshRequest *req = new MockRefreshRequest(mock_image_ctx, false, &ctx);
+  MockRefreshRequest *req = new MockRefreshRequest(mock_image_ctx, false, false, &ctx);
   req->send();
 
   ASSERT_EQ(0, ctx.wait());
@@ -713,7 +758,7 @@ TEST_F(TestMockImageRefreshRequest, EnableJournalWithoutExclusiveLock) {
   expect_set_require_lock_on_read(mock_image_ctx);
 
   C_SaferCond ctx;
-  MockRefreshRequest *req = new MockRefreshRequest(mock_image_ctx, false, &ctx);
+  MockRefreshRequest *req = new MockRefreshRequest(mock_image_ctx, false, false, &ctx);
   req->send();
 
   ASSERT_EQ(0, ctx.wait());
@@ -757,7 +802,7 @@ TEST_F(TestMockImageRefreshRequest, DisableJournal) {
   expect_unblock_writes(mock_image_ctx);
 
   C_SaferCond ctx;
-  MockRefreshRequest *req = new MockRefreshRequest(mock_image_ctx, false, &ctx);
+  MockRefreshRequest *req = new MockRefreshRequest(mock_image_ctx, false, false, &ctx);
   req->send();
 
   ASSERT_EQ(0, ctx.wait());
@@ -793,7 +838,7 @@ TEST_F(TestMockImageRefreshRequest, EnableObjectMapWithExclusiveLock) {
   expect_open_object_map(mock_image_ctx, &mock_object_map, 0);
 
   C_SaferCond ctx;
-  MockRefreshRequest *req = new MockRefreshRequest(mock_image_ctx, false, &ctx);
+  MockRefreshRequest *req = new MockRefreshRequest(mock_image_ctx, false, false, &ctx);
   req->send();
 
   ASSERT_EQ(0, ctx.wait());
@@ -826,7 +871,7 @@ TEST_F(TestMockImageRefreshRequest, EnableObjectMapWithoutExclusiveLock) {
   expect_refresh_parent_is_required(mock_refresh_parent_request, false);
 
   C_SaferCond ctx;
-  MockRefreshRequest *req = new MockRefreshRequest(mock_image_ctx, false, &ctx);
+  MockRefreshRequest *req = new MockRefreshRequest(mock_image_ctx, false, false, &ctx);
   req->send();
 
   ASSERT_EQ(0, ctx.wait());
@@ -871,7 +916,7 @@ TEST_F(TestMockImageRefreshRequest, DisableObjectMap) {
   expect_close_object_map(mock_image_ctx, *mock_object_map, 0);
 
   C_SaferCond ctx;
-  MockRefreshRequest *req = new MockRefreshRequest(mock_image_ctx, false, &ctx);
+  MockRefreshRequest *req = new MockRefreshRequest(mock_image_ctx, false, false, &ctx);
   req->send();
 
   ASSERT_EQ(0, ctx.wait());
@@ -907,7 +952,7 @@ TEST_F(TestMockImageRefreshRequest, OpenObjectMapError) {
   expect_open_object_map(mock_image_ctx, mock_object_map, -EFBIG);
 
   C_SaferCond ctx;
-  MockRefreshRequest *req = new MockRefreshRequest(mock_image_ctx, false, &ctx);
+  MockRefreshRequest *req = new MockRefreshRequest(mock_image_ctx, false, false, &ctx);
   req->send();
 
   ASSERT_EQ(0, ctx.wait());
index a521a79deee86afc172538a3502f44ea3b547e3b..d3283c5cee2d703336e438519cbf051724db83a1 100644 (file)
@@ -60,7 +60,7 @@ int TestFixture::open_image(const std::string &image_name,
   *ictx = new librbd::ImageCtx(image_name.c_str(), "", NULL, m_ioctx, false);
   m_ictxs.insert(*ictx);
 
-  return (*ictx)->state->open();
+  return (*ictx)->state->open(false);
 }
 
 int TestFixture::snap_create(librbd::ImageCtx &ictx,
index 97c2dadf253caeac45d702828fd41c4e1ec4a613..cd7f56ba3b911c88500af0ba0258ab3d333df6a0 100644 (file)
@@ -81,7 +81,7 @@ TEST_F(TestInternal, OpenByID) {
    close_image(ictx);
 
    ictx = new librbd::ImageCtx("", id, nullptr, m_ioctx, true);
-   ASSERT_EQ(0, ictx->state->open());
+   ASSERT_EQ(0, ictx->state->open(false));
    ASSERT_EQ(ictx->name, m_image_name);
    close_image(ictx);
 }
index 81916522c1879a2837c3f6f2de58383c5e36ed77..798dc1d42951e2c6e8bd673bb0ae76dbc027d7fd 100644 (file)
@@ -198,7 +198,7 @@ public:
       librbd::ImageCtx *ictx = new librbd::ImageCtx(parent_image_ctx->name,
                                                    "", "", m_remote_io_ctx,
                                                     false);
-      ictx->state->open();
+      ictx->state->open(false);
       EXPECT_EQ(0, ictx->operations->snap_create(snap_name.c_str()));
       EXPECT_EQ(0, ictx->operations->snap_protect(snap_name.c_str()));
       ictx->state->close();
index 5480316e338f4b6531637c467062ca004f6f4a29..d3739eb43d11d6e1d6766941c4bca1c20454468b 100644 (file)
@@ -69,7 +69,7 @@ public:
     EXPECT_EQ(0, create_image(rbd, m_local_io_ctx, m_image_name, 1 << 20));
     ImageCtx *ictx = new ImageCtx(m_image_name, "", "", m_local_io_ctx,
                                   false);
-    EXPECT_EQ(0, ictx->state->open());
+    EXPECT_EQ(0, ictx->state->open(false));
     m_local_image_id = ictx->id;
 
     cls::rbd::MirrorImage mirror_image(GLOBAL_IMAGE_ID,
@@ -112,7 +112,7 @@ public:
     if (!ictx) {
       ictx = new ImageCtx("", m_local_image_id, "", m_local_io_ctx,
                           false);
-      r = ictx->state->open();
+      r = ictx->state->open(false);
       close = (r == 0);
     }
 
@@ -133,7 +133,7 @@ public:
     if (!ictx) {
       ictx = new ImageCtx("", m_local_image_id, "", m_local_io_ctx,
                           false);
-      EXPECT_EQ(0, ictx->state->open());
+      EXPECT_EQ(0, ictx->state->open(false));
       close = true;
     }
 
@@ -147,7 +147,7 @@ public:
   void create_snapshot(std::string snap_name="snap1", bool protect=false) {
     ImageCtx *ictx = new ImageCtx("", m_local_image_id, "", m_local_io_ctx,
                                   false);
-    EXPECT_EQ(0, ictx->state->open());
+    EXPECT_EQ(0, ictx->state->open(false));
     promote_image(ictx);
 
     EXPECT_EQ(0, ictx->operations->snap_create(snap_name.c_str()));
@@ -163,7 +163,7 @@ public:
   std::string create_clone() {
     ImageCtx *ictx = new ImageCtx("", m_local_image_id, "", m_local_io_ctx,
                                   false);
-    EXPECT_EQ(0, ictx->state->open());
+    EXPECT_EQ(0, ictx->state->open(false));
     promote_image(ictx);
 
     EXPECT_EQ(0, ictx->operations->snap_create("snap1"));
@@ -175,7 +175,7 @@ public:
     std::string clone_id;
     ImageCtx *ictx_clone = new ImageCtx("clone1", "", "", m_local_io_ctx,
                                         false);
-    EXPECT_EQ(0, ictx_clone->state->open());
+    EXPECT_EQ(0, ictx_clone->state->open(false));
     clone_id = ictx_clone->id;
     cls::rbd::MirrorImage mirror_image(GLOBAL_CLONE_IMAGE_ID,
                                 MirrorImageState::MIRROR_IMAGE_STATE_ENABLED);
@@ -193,7 +193,7 @@ public:
   void check_image_deleted() {
     ImageCtx *ictx = new ImageCtx("", m_local_image_id, "", m_local_io_ctx,
                                   false);
-    EXPECT_EQ(-ENOENT, ictx->state->open());
+    EXPECT_EQ(-ENOENT, ictx->state->open(false));
     delete ictx;
 
     cls::rbd::MirrorImage mirror_image;
@@ -417,7 +417,7 @@ TEST_F(TestImageDeleter, Delete_NonExistent_Image_Without_MirroringState) {
 TEST_F(TestImageDeleter, Fail_Delete_NonPrimary_Image) {
   ImageCtx *ictx = new ImageCtx("", m_local_image_id, "", m_local_io_ctx,
                                 false);
-  EXPECT_EQ(0, ictx->state->open());
+  EXPECT_EQ(0, ictx->state->open(false));
 
   m_deleter->schedule_image_delete(_rados, m_local_pool_id, m_local_image_id,
       m_image_name, GLOBAL_IMAGE_ID);
@@ -436,7 +436,7 @@ TEST_F(TestImageDeleter, Fail_Delete_NonPrimary_Image) {
 TEST_F(TestImageDeleter, Retry_Failed_Deletes) {
   ImageCtx *ictx = new ImageCtx("", m_local_image_id, "", m_local_io_ctx,
                                 false);
-  EXPECT_EQ(0, ictx->state->open());
+  EXPECT_EQ(0, ictx->state->open(false));
 
   m_deleter->set_failed_timer_interval(2);
 
@@ -464,7 +464,7 @@ TEST_F(TestImageDeleter, Retry_Failed_Deletes) {
 TEST_F(TestImageDeleter, Delete_Is_Idempotent) {
   ImageCtx *ictx = new ImageCtx("", m_local_image_id, "", m_local_io_ctx,
                                 false);
-  EXPECT_EQ(0, ictx->state->open());
+  EXPECT_EQ(0, ictx->state->open(false));
 
   m_deleter->schedule_image_delete(_rados, m_local_pool_id, m_local_image_id,
       m_image_name, GLOBAL_IMAGE_ID);
index 38b0b41aee78e4e23a2731f5f9fcf2a4094d9598..28682eecd26ad4edbb7a547cd526a69ace03bde4 100644 (file)
@@ -192,7 +192,7 @@ public:
   {
     librbd::ImageCtx *ictx = new librbd::ImageCtx(image_name.c_str(),
                                                  "", "", ioctx, readonly);
-    EXPECT_EQ(0, ictx->state->open());
+    EXPECT_EQ(0, ictx->state->open(false));
     *ictxp = ictx;
   }
 
index 2a2708ed686c329507cfd8c9702da0e57624989c..96e1b3d318176cc36c46f7fcf4f7805ed37c8502 100644 (file)
@@ -126,7 +126,7 @@ TestPoolWatcher() : m_lock("TestPoolWatcherLock"),
     {
       librbd::ImageCtx *ictx = new librbd::ImageCtx(parent_image_name.c_str(),
                                                    "", "", pioctx, false);
-      ictx->state->open();
+      ictx->state->open(false);
       EXPECT_EQ(0, ictx->operations->snap_create(snap_name.c_str()));
       EXPECT_EQ(0, ictx->operations->snap_protect(snap_name.c_str()));
       ictx->state->close();
index b1eb489d97aab04db73658d53604e606d7311895..361e553cf63be18e3a30ec13889d6e5132cc9e13 100644 (file)
@@ -79,7 +79,7 @@ int TestFixture::open_image(librados::IoCtx &io_ctx,
   *image_ctx = new librbd::ImageCtx(image_name.c_str(), "", NULL, io_ctx,
                                     false);
   m_image_ctxs.insert(*image_ctx);
-  return (*image_ctx)->state->open();
+  return (*image_ctx)->state->open(false);
 }
 
 int TestFixture::create_snap(librbd::ImageCtx *image_ctx, const char* snap_name,
index 0b0c775dba0d133f0d852a94ada066f2db58ea9e..d089768c60b571afe64e31b6f6b22b33b175b535 100644 (file)
@@ -330,7 +330,7 @@ bool ImageDeleter::process_image_delete() {
 
     ImageCtx *imgctx = new ImageCtx("", m_active_delete->local_image_id,
                                     nullptr, ioctx, false);
-    r = imgctx->state->open();
+    r = imgctx->state->open(false);
     if (r < 0) {
       derr << "error opening image id " << m_active_delete->local_image_id
            << ": " << cpp_strerror(r) << dendl;
index 9cf6af2b3219a13e36e2f3ad7cf5525d4d7b8091..32c0724ab619b376e167ab9470cc867713fe7d69 100644 (file)
@@ -44,7 +44,7 @@ void OpenImageRequest<I>::send_open_image() {
   Context *ctx = create_context_callback<
     OpenImageRequest<I>, &OpenImageRequest<I>::handle_open_image>(
       this);
-  (*m_image_ctx)->state->open(ctx);
+  (*m_image_ctx)->state->open(false, ctx);
 }
 
 template <typename I>
index 1d331f906a84084607f480e576a3c5626df6b521..b1ec3c74ec3ba661e80af2aa2b98184c15e25f8c 100644 (file)
@@ -99,7 +99,7 @@ void OpenLocalImageRequest<I>::send_open_image() {
   Context *ctx = create_context_callback<
     OpenLocalImageRequest<I>, &OpenLocalImageRequest<I>::handle_open_image>(
       this);
-  (*m_local_image_ctx)->state->open(ctx);
+  (*m_local_image_ctx)->state->open(false, ctx);
 }
 
 template <typename I>