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>
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,
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();
}
* particular snap will group under up to 8 prefixes.
*/
class SnapMapper {
+ friend class MapperVerifier;
public:
CephContext* cct;
struct object_snaps {
void run();
};
+ static std::string convert_legacy_key(
+ const std::string& old_key,
+ const bufferlist& value);
+
static int convert_legacy(
CephContext *cct,
ObjectStore *store,
}
}
+ 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())
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);
+}
+