]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
osd/SnapMapper: fix pacific legacy key conversion and introduce test 47108/head
authorManuel Lausch <manuel.lausch@1und1.de>
Thu, 30 Jun 2022 12:29:53 +0000 (14:29 +0200)
committerMatan Breizman <mbreizma@redhat.com>
Thu, 14 Jul 2022 20:33:37 +0000 (20:33 +0000)
Octopus modified the SnapMapper key format from

  <LEGACY_MAPPING_PREFIX><snapid>_<shardid>_<hobject_t::to_str()>

to

  <MAPPING_PREFIX><pool>_<snapid>_<shardid>_<hobject_t::to_str()>

When this change was introduced, 94ebe0ea also introduced a conversion
with a crucial bug which essentially destroyed legacy keys by mapping them
to

  <MAPPING_PREFIX><poolid>_<snapid>_

without the object-unique suffix.  This commit fixes this conversion going
forward, but a fix for existing clusters still needs to be developed.

Fixes: https://tracker.ceph.com/issues/56147
Signed-off-by: Manuel Lausch <manuel.lausch@1und1.de>
Signed-off-by: Matan Breizman <mbreizma@redhat.com>
src/osd/SnapMapper.cc
src/osd/SnapMapper.h
src/test/test_snap_mapper.cc

index 66d8a22857cd5c62bf022a76b7b94206f5a64c80..c2c5d9840e5bfdec96f1e2ae4576fe91d9859363 100644 (file)
@@ -650,6 +650,38 @@ bool SnapMapper::is_legacy_mapping(const string &to_test)
     LEGACY_MAPPING_PREFIX;
 }
 
+/* Octopus modified the SnapMapper key format from
+ *
+ *  <LEGACY_MAPPING_PREFIX><snapid>_<shardid>_<hobject_t::to_str()>
+ *
+ * to
+ *
+ *  <MAPPING_PREFIX><pool>_<snapid>_<shardid>_<hobject_t::to_str()>
+ *
+ * We can't reconstruct the new key format just from the value since the
+ * Mapping object contains an hobject rather than a ghobject. Instead,
+ * we exploit the fact that the new format is identical starting at <snapid>.
+ *
+ * Note that the original version of this conversion introduced in 94ebe0ea
+ * had a crucial bug which essentially destroyed legacy keys by mapping
+ * them to
+ *
+ *  <MAPPING_PREFIX><poolid>_<snapid>_
+ *
+ * without the object-unique suffix.
+ * See https://tracker.ceph.com/issues/56147
+ */
+std::string SnapMapper::convert_legacy_key(
+  const std::string& old_key,
+  const bufferlist& value)
+{
+  auto old = from_raw(make_pair(old_key, value));
+  std::string object_suffix = old_key.substr(
+    SnapMapper::LEGACY_MAPPING_PREFIX.length());
+  return SnapMapper::MAPPING_PREFIX + std::to_string(old.second.pool)
+    + "_" + object_suffix;
+}
+
 int SnapMapper::convert_legacy(
   CephContext *cct,
   ObjectStore *store,
@@ -671,13 +703,9 @@ int SnapMapper::convert_legacy(
   while (iter->valid()) {
     bool valid = SnapMapper::is_legacy_mapping(iter->key());
     if (valid) {
-      SnapMapper::Mapping m;
-      bufferlist bl(iter->value());
-      auto bp = bl.cbegin();
-      decode(m, bp);
       to_set.emplace(
-       SnapMapper::get_prefix(m.hoid.pool, m.snap),
-       bl);
+       convert_legacy_key(iter->key(), iter->value()),
+       iter->value());
       ++n;
       iter->next();
     }
index 3fbc2261a9df05038033fc6a99b0a04bf4ebc010..8571adb091c88f84548b728d1ab5f91bb8100ec6 100644 (file)
@@ -100,6 +100,7 @@ public:
  * particular snap will group under up to 8 prefixes.
  */
 class SnapMapper {
+  friend class MapperVerifier;
 public:
   CephContext* cct;
   struct object_snaps {
@@ -174,6 +175,10 @@ public:
     void run();
   };
 
+  static std::string convert_legacy_key(
+    const std::string& old_key,
+    const bufferlist& value);
+
   static int convert_legacy(
     CephContext *cct,
     ObjectStore *store,
index 9b6dbdd2b0c59db43f956656624755cb25aced15..181448071de4252562d8eb29a3c9b9ce6aab0418 100644 (file)
@@ -499,6 +499,21 @@ public:
     }
   }
 
+  std::pair<std::string, ceph::buffer::list> to_raw(
+    const std::pair<snapid_t, hobject_t> &to_map) {
+    return mapper->to_raw(to_map);
+  }
+
+  std::string to_legacy_raw_key(
+    const std::pair<snapid_t, hobject_t> &to_map) {
+    return mapper->to_legacy_raw_key(to_map);
+  }
+
+  std::string to_raw_key(
+    const std::pair<snapid_t, hobject_t> &to_map) {
+    return mapper->to_raw_key(to_map);
+  }
+
   void trim_snap() {
     std::lock_guard l{lock};
     if (snap_to_hobject.empty())
@@ -655,3 +670,19 @@ TEST_F(SnapMapperTest, MultiPG) {
   init(50);
   run();
 }
+
+TEST_F(SnapMapperTest, LegacyKeyConvertion) {
+    init(1);
+    auto obj = get_tester().random_hobject();
+    snapid_t snapid = random() % 10;
+    auto snap_obj = make_pair(snapid, obj);
+    auto raw = get_tester().to_raw(snap_obj);
+    std::string old_key = get_tester().to_legacy_raw_key(snap_obj);
+    std::string converted_key =
+      SnapMapper::convert_legacy_key(old_key, raw.second);
+    std::string new_key = get_tester().to_raw_key(snap_obj);
+    std::cout << "Converted: " << old_key << "\nTo:        " << converted_key
+             << "\nNew key:   " << new_key << std::endl;
+    ASSERT_EQ(converted_key, new_key);
+}
+