]> git.apps.os.sepia.ceph.com Git - ceph-ci.git/commitdiff
librbd: invoke new parent class API methods
authorJason Dillaman <dillaman@redhat.com>
Tue, 21 Aug 2018 01:48:20 +0000 (21:48 -0400)
committerJason Dillaman <dillaman@redhat.com>
Wed, 19 Sep 2018 12:05:29 +0000 (08:05 -0400)
If the OSDs don't support the new methods, revert to the legacy
class API methods.

Signed-off-by: Jason Dillaman <dillaman@redhat.com>
src/librbd/image/RefreshRequest.cc
src/librbd/image/RefreshRequest.h
src/test/librbd/image/test_mock_RefreshRequest.cc

index 6c1218b94a92411c3f8a3af5450d8f5e2893dfef..d9178fc3b2d2261ef21084b4350c923569e697b8 100644 (file)
@@ -423,10 +423,16 @@ template <typename I>
 void RefreshRequest<I>::send_v2_get_parent() {
   // NOTE: remove support when Mimic is EOLed
   CephContext *cct = m_image_ctx.cct;
-  ldout(cct, 10) << this << " " << __func__ << dendl;
+  ldout(cct, 10) << this << " " << __func__ << ": legacy=" << m_legacy_parent
+                 << dendl;
 
   librados::ObjectReadOperation op;
-  cls_client::get_parent_start(&op, CEPH_NOSNAP);
+  if (!m_legacy_parent) {
+    cls_client::parent_get_start(&op);
+    cls_client::parent_overlap_get_start(&op, CEPH_NOSNAP);
+  } else {
+    cls_client::get_parent_start(&op, CEPH_NOSNAP);
+  }
 
   auto aio_comp = create_rados_callback<
     RefreshRequest<I>, &RefreshRequest<I>::handle_v2_get_parent>(this);
@@ -442,13 +448,41 @@ Context *RefreshRequest<I>::handle_v2_get_parent(int *result) {
   CephContext *cct = m_image_ctx.cct;
   ldout(cct, 10) << this << " " << __func__ << ": r=" << *result << dendl;
 
-  if (*result == 0) {
-    auto it = m_out_bl.cbegin();
+  auto it = m_out_bl.cbegin();
+  if (!m_legacy_parent) {
+    cls::rbd::ParentImageSpec parent_image_spec;
+    if (*result == 0) {
+      *result = cls_client::parent_get_finish(&it, &parent_image_spec);
+
+      m_parent_md.spec = {};
+      if (*result == 0) {
+        m_parent_md.spec.pool_id = parent_image_spec.pool_id;
+        m_parent_md.spec.image_id = parent_image_spec.image_id;
+        m_parent_md.spec.snap_id = parent_image_spec.snap_id;
+      }
+    }
+
+    std::optional<uint64_t> parent_overlap;
+    if (*result == 0) {
+      *result = cls_client::parent_overlap_get_finish(&it, &parent_overlap);
+    }
+
+    if (*result == 0 && parent_overlap) {
+      m_parent_md.overlap = *parent_overlap;
+      m_head_parent_overlap = true;
+    }
+  } else if (*result == 0) {
     *result = cls_client::get_parent_finish(&it, &m_parent_md.spec,
                                             &m_parent_md.overlap);
+    m_head_parent_overlap = true;
   }
 
-  if (*result < 0) {
+  if (*result == -EOPNOTSUPP && !m_legacy_parent) {
+    ldout(cct, 10) << "retrying using legacy parent method" << dendl;
+    m_legacy_parent = true;
+    send_v2_get_parent();
+    return nullptr;
+  } if (*result < 0) {
     lderr(cct) << "failed to retrieve parent: " << cpp_strerror(*result)
                << dendl;
     return m_on_finish;
@@ -622,8 +656,14 @@ void RefreshRequest<I>::send_v2_get_snapshots() {
     } else {
       cls_client::snapshot_get_start(&op, snap_id);
     }
+
+    if (m_legacy_parent) {
+      cls_client::get_parent_start(&op, snap_id);
+    } else {
+      cls_client::parent_overlap_get_start(&op, snap_id);
+    }
+
     cls_client::get_flags_start(&op, snap_id);
-    cls_client::get_parent_start(&op, snap_id);
     cls_client::get_protection_status_start(&op, snap_id);
   }
 
@@ -672,13 +712,22 @@ Context *RefreshRequest<I>::handle_v2_get_snapshots(int *result) {
       *result = cls_client::snapshot_get_finish(&it, &m_snap_infos[i]);
     }
 
-    if (*result >= 0) {
-      *result = cls_client::get_flags_finish(&it, &m_snap_flags[i]);
+    if (*result == 0) {
+      if (m_legacy_parent) {
+        *result = cls_client::get_parent_finish(&it, &m_snap_parents[i].spec,
+                                                &m_snap_parents[i].overlap);
+      } else {
+        std::optional<uint64_t> parent_overlap;
+        *result = cls_client::parent_overlap_get_finish(&it, &parent_overlap);
+        if (*result == 0 && parent_overlap && m_parent_md.spec.pool_id > -1) {
+          m_snap_parents[i].spec = m_parent_md.spec;
+          m_snap_parents[i].overlap = *parent_overlap;
+        }
+      }
     }
 
     if (*result >= 0) {
-      *result = cls_client::get_parent_finish(&it, &m_snap_parents[i].spec,
-                                              &m_snap_parents[i].overlap);
+      *result = cls_client::get_flags_finish(&it, &m_snap_flags[i]);
     }
 
     if (*result >= 0) {
@@ -1202,6 +1251,12 @@ void RefreshRequest<I>::apply() {
       m_image_ctx.object_prefix = std::move(m_object_prefix);
       m_image_ctx.init_layout();
     } else {
+      // HEAD revision doesn't have a defined overlap so it's only
+      // applicable to snapshots
+      if (!m_head_parent_overlap) {
+        m_parent_md = {};
+      }
+
       m_image_ctx.features = m_features;
       m_image_ctx.flags = m_flags;
       m_image_ctx.op_features = m_op_features;
index 1d982425dbab196a44e70aa6bf7cafcb18c691bf..1fa380fc7c33a971e0400d85d30bc1e6bfe410a7 100644 (file)
@@ -57,7 +57,10 @@ private:
    *                v                                         v
    *            V2_GET_METADATA                            <apply>
    *                |                                         |
-   *                v                                         |
+   *                |     -EOPNOTSUPP                         |
+   *                |  * * *                                  |
+   *                |  *   *                                  |
+   *                v  v   *                                  |
    *            V2_GET_PARENT                                 |
    *                |                                         |
    *                v (skip if not enabled)                   |
@@ -129,6 +132,7 @@ private:
 
   bufferlist m_out_bl;
 
+  bool m_legacy_parent = false;
   bool m_legacy_snapshot = false;
 
   uint8_t m_order = 0;
@@ -143,6 +147,7 @@ private:
 
   std::string m_object_prefix;
   ParentInfo m_parent_md;
+  bool m_head_parent_overlap = false;
   cls::rbd::GroupSpec m_group_spec;
 
   ::SnapContext m_snapc;
index d3dcf5e0e5cf8701e55f7501f0e9e045ab5b1029..2b5c8422e7763e6417af5b9a93e0cef117565c75 100644 (file)
@@ -209,9 +209,40 @@ public:
       EXPECT_CALL(get_mock_io_ctx(mock_image_ctx.md_ctx),
                   exec(mock_image_ctx.header_oid, _, StrEq("lock"), StrEq("get_info"), _, _, _))
                     .WillOnce(DoDefault());
-      EXPECT_CALL(get_mock_io_ctx(mock_image_ctx.md_ctx),
-                  exec(mock_image_ctx.header_oid, _, StrEq("rbd"), StrEq("get_parent"), _, _, _))
-                    .WillOnce(DoDefault());
+    }
+  }
+
+  void expect_parent_overlap_get(MockRefreshImageCtx &mock_image_ctx, int r) {
+    auto& expect = EXPECT_CALL(get_mock_io_ctx(mock_image_ctx.md_ctx),
+                               exec(mock_image_ctx.header_oid, _, StrEq("rbd"),
+                               StrEq("parent_overlap_get"), _, _, _));
+    if (r < 0) {
+      expect.WillOnce(Return(r));
+    } else {
+      expect.WillOnce(DoDefault());
+    }
+  }
+
+  void expect_get_parent(MockRefreshImageCtx &mock_image_ctx, int r) {
+    auto& expect = EXPECT_CALL(get_mock_io_ctx(mock_image_ctx.md_ctx),
+                               exec(mock_image_ctx.header_oid, _, StrEq("rbd"),
+                                    StrEq("parent_get"), _, _, _));
+    if (r < 0) {
+      expect.WillOnce(Return(r));
+    } else {
+      expect.WillOnce(DoDefault());
+      expect_parent_overlap_get(mock_image_ctx, 0);
+    }
+  }
+
+  void expect_get_parent_legacy(MockRefreshImageCtx &mock_image_ctx, int r) {
+    auto& expect = EXPECT_CALL(get_mock_io_ctx(mock_image_ctx.md_ctx),
+                               exec(mock_image_ctx.header_oid, _, StrEq("rbd"),
+                                    StrEq("get_parent"), _, _, _));
+    if (r < 0) {
+      expect.WillOnce(Return(r));
+    } else {
+      expect.WillOnce(DoDefault());
     }
   }
 
@@ -270,17 +301,22 @@ public:
     }
   }
 
-  void expect_get_snapshots(MockRefreshImageCtx &mock_image_ctx, int r) {
+  void expect_get_snapshots(MockRefreshImageCtx &mock_image_ctx,
+                            bool legacy_parent, int r) {
     auto &expect = EXPECT_CALL(get_mock_io_ctx(mock_image_ctx.md_ctx),
                                exec(mock_image_ctx.header_oid, _, StrEq("rbd"), StrEq("snapshot_get"), _, _, _));
     if (r < 0) {
       expect.WillOnce(Return(r));
     } else {
       expect.WillOnce(DoDefault());
+      if (legacy_parent) {
+        EXPECT_CALL(get_mock_io_ctx(mock_image_ctx.md_ctx),
+                    exec(mock_image_ctx.header_oid, _, StrEq("rbd"), StrEq("get_parent"), _, _, _))
+                      .WillOnce(DoDefault());
+      } else {
+        expect_parent_overlap_get(mock_image_ctx, 0);
+      }
       expect_get_flags(mock_image_ctx, 0);
-      EXPECT_CALL(get_mock_io_ctx(mock_image_ctx.md_ctx),
-                  exec(mock_image_ctx.header_oid, _, StrEq("rbd"), StrEq("get_parent"), _, _, _))
-                    .WillOnce(DoDefault());
       EXPECT_CALL(get_mock_io_ctx(mock_image_ctx.md_ctx),
                   exec(mock_image_ctx.header_oid, _, StrEq("rbd"), StrEq("get_protection_status"), _, _, _))
                     .WillOnce(DoDefault());
@@ -300,10 +336,10 @@ public:
       EXPECT_CALL(get_mock_io_ctx(mock_image_ctx.md_ctx),
                   exec(mock_image_ctx.header_oid, _, StrEq("rbd"), StrEq("get_snapshot_timestamp"), _, _, _))
                     .WillOnce(DoDefault());
-      expect_get_flags(mock_image_ctx, 0);
       EXPECT_CALL(get_mock_io_ctx(mock_image_ctx.md_ctx),
                   exec(mock_image_ctx.header_oid, _, StrEq("rbd"), StrEq("get_parent"), _, _, _))
                     .WillOnce(DoDefault());
+      expect_get_flags(mock_image_ctx, 0);
       EXPECT_CALL(get_mock_io_ctx(mock_image_ctx.md_ctx),
                   exec(mock_image_ctx.header_oid, _, StrEq("rbd"), StrEq("get_protection_status"), _, _, _))
                     .WillOnce(DoDefault());
@@ -507,6 +543,7 @@ TEST_F(TestMockImageRefreshRequest, SuccessV2) {
 
   InSequence seq;
   expect_get_mutable_metadata(mock_image_ctx, ictx->features, 0);
+  expect_get_parent(mock_image_ctx, 0);
   expect_get_metadata(mock_image_ctx, 0);
   expect_apply_metadata(mock_image_ctx, 0);
   expect_get_group(mock_image_ctx, 0);
@@ -537,10 +574,11 @@ TEST_F(TestMockImageRefreshRequest, SuccessSnapshotV2) {
 
   InSequence seq;
   expect_get_mutable_metadata(mock_image_ctx, ictx->features, 0);
+  expect_get_parent(mock_image_ctx, 0);
   expect_get_metadata(mock_image_ctx, 0);
   expect_apply_metadata(mock_image_ctx, 0);
   expect_get_group(mock_image_ctx, 0);
-  expect_get_snapshots(mock_image_ctx, 0);
+  expect_get_snapshots(mock_image_ctx, false, 0);
   expect_refresh_parent_is_required(mock_refresh_parent_request, false);
   if (ictx->test_features(RBD_FEATURE_EXCLUSIVE_LOCK)) {
     expect_init_exclusive_lock(mock_image_ctx, mock_exclusive_lock, 0);
@@ -569,10 +607,12 @@ TEST_F(TestMockImageRefreshRequest, SuccessLegacySnapshotV2) {
 
   InSequence seq;
   expect_get_mutable_metadata(mock_image_ctx, ictx->features, 0);
+  expect_get_parent(mock_image_ctx, -EOPNOTSUPP);
+  expect_get_parent_legacy(mock_image_ctx, 0);
   expect_get_metadata(mock_image_ctx, 0);
   expect_apply_metadata(mock_image_ctx, 0);
   expect_get_group(mock_image_ctx, 0);
-  expect_get_snapshots(mock_image_ctx, -EOPNOTSUPP);
+  expect_get_snapshots(mock_image_ctx, true, -EOPNOTSUPP);
   expect_get_snapshots_legacy(mock_image_ctx, 0);
   expect_refresh_parent_is_required(mock_refresh_parent_request, false);
   if (ictx->test_features(RBD_FEATURE_EXCLUSIVE_LOCK)) {
@@ -605,10 +645,11 @@ TEST_F(TestMockImageRefreshRequest, SuccessSetSnapshotV2) {
 
   InSequence seq;
   expect_get_mutable_metadata(mock_image_ctx, ictx->features, 0);
+  expect_get_parent(mock_image_ctx, 0);
   expect_get_metadata(mock_image_ctx, 0);
   expect_apply_metadata(mock_image_ctx, 0);
   expect_get_group(mock_image_ctx, 0);
-  expect_get_snapshots(mock_image_ctx, 0);
+  expect_get_snapshots(mock_image_ctx, false, 0);
   expect_refresh_parent_is_required(mock_refresh_parent_request, false);
   if (ictx->test_features(RBD_FEATURE_OBJECT_MAP)) {
     expect_open_object_map(mock_image_ctx, &mock_object_map, 0);
@@ -657,6 +698,7 @@ TEST_F(TestMockImageRefreshRequest, SuccessChild) {
 
   InSequence seq;
   expect_get_mutable_metadata(mock_image_ctx, ictx2->features, 0);
+  expect_get_parent(mock_image_ctx, 0);
   expect_get_metadata(mock_image_ctx, 0);
   expect_apply_metadata(mock_image_ctx, 0);
   expect_get_op_features(mock_image_ctx, RBD_OPERATION_FEATURE_CLONE_CHILD, 0);
@@ -709,6 +751,7 @@ TEST_F(TestMockImageRefreshRequest, SuccessChildDontOpenParent) {
 
   InSequence seq;
   expect_get_mutable_metadata(mock_image_ctx, ictx2->features, 0);
+  expect_get_parent(mock_image_ctx, 0);
   expect_get_metadata(mock_image_ctx, 0);
   expect_apply_metadata(mock_image_ctx, 0);
   expect_get_op_features(mock_image_ctx, RBD_OPERATION_FEATURE_CLONE_CHILD, 0);
@@ -740,6 +783,7 @@ TEST_F(TestMockImageRefreshRequest, SuccessOpFeatures) {
 
   InSequence seq;
   expect_get_mutable_metadata(mock_image_ctx, mock_image_ctx.features, 0);
+  expect_get_parent(mock_image_ctx, 0);
   expect_get_metadata(mock_image_ctx, 0);
   expect_apply_metadata(mock_image_ctx, 0);
   expect_get_op_features(mock_image_ctx, 4096, 0);
@@ -809,6 +853,7 @@ TEST_F(TestMockImageRefreshRequest, DisableExclusiveLock) {
   // and journaling were never enabled (or active)
   InSequence seq;
   expect_get_mutable_metadata(mock_image_ctx, ictx->features, 0);
+  expect_get_parent(mock_image_ctx, 0);
   expect_get_metadata(mock_image_ctx, 0);
   expect_apply_metadata(mock_image_ctx, 0);
   expect_get_group(mock_image_ctx, 0);
@@ -863,6 +908,7 @@ TEST_F(TestMockImageRefreshRequest, DisableExclusiveLockWhileAcquiringLock) {
   // and journaling were never enabled (or active)
   InSequence seq;
   expect_get_mutable_metadata(mock_image_ctx, ictx->features, 0);
+  expect_get_parent(mock_image_ctx, 0);
   expect_get_metadata(mock_image_ctx, 0);
   expect_apply_metadata(mock_image_ctx, 0);
   expect_get_group(mock_image_ctx, 0);
@@ -907,6 +953,7 @@ TEST_F(TestMockImageRefreshRequest, JournalDisabledByPolicy) {
 
   InSequence seq;
   expect_get_mutable_metadata(mock_image_ctx, ictx->features, 0);
+  expect_get_parent(mock_image_ctx, 0);
   expect_get_metadata(mock_image_ctx, 0);
   expect_apply_metadata(mock_image_ctx, 0);
   expect_get_group(mock_image_ctx, 0);
@@ -956,6 +1003,7 @@ TEST_F(TestMockImageRefreshRequest, EnableJournalWithExclusiveLock) {
   // journal should be immediately opened if exclusive lock owned
   InSequence seq;
   expect_get_mutable_metadata(mock_image_ctx, ictx->features, 0);
+  expect_get_parent(mock_image_ctx, 0);
   expect_get_metadata(mock_image_ctx, 0);
   expect_apply_metadata(mock_image_ctx, 0);
   expect_get_group(mock_image_ctx, 0);
@@ -1004,6 +1052,7 @@ TEST_F(TestMockImageRefreshRequest, EnableJournalWithoutExclusiveLock) {
   // do not open the journal if exclusive lock is not owned
   InSequence seq;
   expect_get_mutable_metadata(mock_image_ctx, ictx->features, 0);
+  expect_get_parent(mock_image_ctx, 0);
   expect_get_metadata(mock_image_ctx, 0);
   expect_apply_metadata(mock_image_ctx, 0);
   expect_get_group(mock_image_ctx, 0);
@@ -1050,6 +1099,7 @@ TEST_F(TestMockImageRefreshRequest, DisableJournal) {
   // verify journal is closed if feature disabled
   InSequence seq;
   expect_get_mutable_metadata(mock_image_ctx, ictx->features, 0);
+  expect_get_parent(mock_image_ctx, 0);
   expect_get_metadata(mock_image_ctx, 0);
   expect_apply_metadata(mock_image_ctx, 0);
   expect_get_group(mock_image_ctx, 0);
@@ -1096,6 +1146,7 @@ TEST_F(TestMockImageRefreshRequest, EnableObjectMapWithExclusiveLock) {
   // object map should be immediately opened if exclusive lock owned
   InSequence seq;
   expect_get_mutable_metadata(mock_image_ctx, ictx->features, 0);
+  expect_get_parent(mock_image_ctx, 0);
   expect_get_metadata(mock_image_ctx, 0);
   expect_apply_metadata(mock_image_ctx, 0);
   expect_get_group(mock_image_ctx, 0);
@@ -1135,6 +1186,7 @@ TEST_F(TestMockImageRefreshRequest, EnableObjectMapWithoutExclusiveLock) {
   // do not open the object map if exclusive lock is not owned
   InSequence seq;
   expect_get_mutable_metadata(mock_image_ctx, ictx->features, 0);
+  expect_get_parent(mock_image_ctx, 0);
   expect_get_metadata(mock_image_ctx, 0);
   expect_apply_metadata(mock_image_ctx, 0);
   expect_get_group(mock_image_ctx, 0);
@@ -1185,6 +1237,7 @@ TEST_F(TestMockImageRefreshRequest, DisableObjectMap) {
   // verify object map is closed if feature disabled
   InSequence seq;
   expect_get_mutable_metadata(mock_image_ctx, ictx->features, 0);
+  expect_get_parent(mock_image_ctx, 0);
   expect_get_metadata(mock_image_ctx, 0);
   expect_apply_metadata(mock_image_ctx, 0);
   expect_get_group(mock_image_ctx, 0);
@@ -1226,6 +1279,7 @@ TEST_F(TestMockImageRefreshRequest, OpenObjectMapError) {
   // object map should be immediately opened if exclusive lock owned
   InSequence seq;
   expect_get_mutable_metadata(mock_image_ctx, ictx->features, 0);
+  expect_get_parent(mock_image_ctx, 0);
   expect_get_metadata(mock_image_ctx, 0);
   expect_apply_metadata(mock_image_ctx, 0);
   expect_get_group(mock_image_ctx, 0);
@@ -1254,6 +1308,7 @@ TEST_F(TestMockImageRefreshRequest, ApplyMetadataError) {
 
   InSequence seq;
   expect_get_mutable_metadata(mock_image_ctx, ictx->features, 0);
+  expect_get_parent(mock_image_ctx, 0);
   expect_get_metadata(mock_image_ctx, 0);
   expect_apply_metadata(mock_image_ctx, -EINVAL);
   expect_get_group(mock_image_ctx, 0);