From 94ebe0eab968068c29fdffa1bfe68c72122db633 Mon Sep 17 00:00:00 2001 From: Sage Weil Date: Thu, 6 Jun 2019 14:37:07 -0500 Subject: [PATCH] osd: adjust snapmapper keys on first start as octopus Convert snapmapper keys to the new form the first time we start up running octopus. This is an incompat feature--once you start as octopus you can't go back. Signed-off-by: Sage Weil --- src/osd/OSD.cc | 12 +++++ src/osd/SnapMapper.cc | 110 ++++++++++++++++++++++++++++++------------ src/osd/SnapMapper.h | 39 +++++++++++++-- src/osd/osd_types.h | 1 + 4 files changed, 127 insertions(+), 35 deletions(-) diff --git a/src/osd/OSD.cc b/src/osd/OSD.cc index f85d33cead1a9..7c1aaacab179c 100644 --- a/src/osd/OSD.cc +++ b/src/osd/OSD.cc @@ -198,6 +198,7 @@ CompatSet OSD::get_osd_initial_compat_set() { ceph_osd_feature_incompat.insert(CEPH_OSD_FEATURE_INCOMPAT_MISSING); ceph_osd_feature_incompat.insert(CEPH_OSD_FEATURE_INCOMPAT_FASTINFO); ceph_osd_feature_incompat.insert(CEPH_OSD_FEATURE_INCOMPAT_RECOVERY_DELETES); + ceph_osd_feature_incompat.insert(CEPH_OSD_FEATURE_INCOMPAT_SNAPMAPPER2); return CompatSet(ceph_osd_feature_compat, ceph_osd_feature_ro_compat, ceph_osd_feature_incompat); } @@ -2849,6 +2850,17 @@ int OSD::init() initial = get_osd_initial_compat_set(); diff = superblock.compat_features.unsupported(initial); if (superblock.compat_features.merge(initial)) { + // Are we adding SNAPMAPPER2? + if (diff.incompat.contains(CEPH_OSD_FEATURE_INCOMPAT_SNAPMAPPER2)) { + dout(1) << __func__ << " upgrade snap_mapper (first start as octopus)" + << dendl; + auto ch = service.meta_ch; + auto hoid = make_snapmapper_oid(); + unsigned max = cct->_conf->osd_target_transaction_size; + r = SnapMapper::convert_legacy(cct, store, ch, hoid, max); + if (r < 0) + goto out; + } // We need to persist the new compat_set before we // do anything else dout(5) << "Upgrading superblock adding: " << diff << dendl; diff --git a/src/osd/SnapMapper.cc b/src/osd/SnapMapper.cc index e745fff23f6db..968caff370b2e 100644 --- a/src/osd/SnapMapper.cc +++ b/src/osd/SnapMapper.cc @@ -85,37 +85,6 @@ int OSDriver::get_next( } } -struct Mapping { - snapid_t snap; - hobject_t hoid; - explicit Mapping(const pair &in) - : snap(in.first), hoid(in.second) {} - Mapping() : snap(0) {} - void encode(bufferlist &bl) const { - ENCODE_START(1, 1, bl); - encode(snap, bl); - encode(hoid, bl); - ENCODE_FINISH(bl); - } - void decode(bufferlist::const_iterator &bl) { - DECODE_START(1, bl); - decode(snap, bl); - decode(hoid, bl); - DECODE_FINISH(bl); - } -}; -WRITE_CLASS_ENCODER(Mapping) - -string SnapMapper::get_legacy_prefix(snapid_t snap) -{ - char buf[100]; - int len = snprintf( - buf, sizeof(buf), - "%.*X_", - (int)(sizeof(snap)*2), static_cast(snap)); - return LEGACY_MAPPING_PREFIX + string(buf, len); -} - string SnapMapper::get_prefix(int64_t pool, snapid_t snap) { char buf[100]; @@ -146,6 +115,7 @@ pair SnapMapper::to_raw( pair SnapMapper::from_raw( const pair &image) { + using ceph::decode; Mapping map; bufferlist bl(image.second); auto bp = bl.cbegin(); @@ -428,3 +398,81 @@ int SnapMapper::get_snaps( snaps->swap(out.snaps); return 0; } + + +// ------------------------------------- +// legacy conversion/support + +string SnapMapper::get_legacy_prefix(snapid_t snap) +{ + char buf[100]; + int len = snprintf( + buf, sizeof(buf), + "%.*X_", + (int)(sizeof(snap)*2), static_cast(snap)); + return LEGACY_MAPPING_PREFIX + string(buf, len); +} + +string SnapMapper::to_legacy_raw_key( + const pair &in) +{ + return get_legacy_prefix(in.first) + shard_prefix + in.second.to_str(); +} + +bool SnapMapper::is_legacy_mapping(const string &to_test) +{ + return to_test.substr(0, LEGACY_MAPPING_PREFIX.size()) == + LEGACY_MAPPING_PREFIX; +} + +int SnapMapper::convert_legacy( + CephContext *cct, + ObjectStore *store, + ObjectStore::CollectionHandle& ch, + ghobject_t hoid, + unsigned max) +{ + uint64_t n = 0; + + ObjectMap::ObjectMapIterator iter = store->get_omap_iterator(ch, hoid); + if (!iter) { + return -EIO; + } + + auto start = ceph::mono_clock::now(); + + iter->upper_bound(SnapMapper::LEGACY_MAPPING_PREFIX); + map to_set; + 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); + ++n; + iter->next(); + } + if (!valid || !iter->valid() || to_set.size() >= max) { + ObjectStore::Transaction t; + t.omap_setkeys(ch->cid, hoid, to_set); + int r = store->queue_transaction(ch, std::move(t)); + ceph_assert(r == 0); + to_set.clear(); + if (!valid) { + break; + } + dout(10) << __func__ << " converted " << n << " keys" << dendl; + } + } + + auto end = ceph::mono_clock::now(); + + dout(1) << __func__ << " converted " << n << " keys in " + << timespan_str(end - start) << dendl; +#warning fixme remove old keys + return 0; +} diff --git a/src/osd/SnapMapper.h b/src/osd/SnapMapper.h index 2a9236c1f90e8..d8899b12f3469 100644 --- a/src/osd/SnapMapper.h +++ b/src/osd/SnapMapper.h @@ -111,16 +111,46 @@ public: void decode(bufferlist::const_iterator &bp); }; -private: - MapCacher::MapCacher backend; + struct Mapping { + snapid_t snap; + hobject_t hoid; + explicit Mapping(const pair &in) + : snap(in.first), hoid(in.second) {} + Mapping() : snap(0) {} + void encode(bufferlist &bl) const { + ENCODE_START(1, 1, bl); + encode(snap, bl); + encode(hoid, bl); + ENCODE_FINISH(bl); + } + void decode(bufferlist::const_iterator &bl) { + DECODE_START(1, bl); + decode(snap, bl); + decode(hoid, bl); + DECODE_FINISH(bl); + } + }; static const std::string LEGACY_MAPPING_PREFIX; static const std::string MAPPING_PREFIX; static const std::string OBJECT_PREFIX; + static int convert_legacy( + CephContext *cct, + ObjectStore *store, + ObjectStore::CollectionHandle& ch, + ghobject_t hoid, + unsigned max); + +private: + MapCacher::MapCacher backend; + static std::string get_legacy_prefix(snapid_t snap); - static std::string get_prefix(int64_t pool, snapid_t snap); + std::string to_legacy_raw_key( + const std::pair &to_map); + static bool is_legacy_mapping(const std::string &to_test); + static std::string get_prefix(int64_t pool, snapid_t snap); std::string to_raw_key( const std::pair &to_map); @@ -129,7 +159,7 @@ private: static bool is_mapping(const std::string &to_test); - std::pair from_raw( + static std::pair from_raw( const std::pair &image); std::string to_object_key(const hobject_t &hoid); @@ -234,5 +264,6 @@ public: ); ///< @return error, -ENOENT if oid is not recorded }; WRITE_CLASS_ENCODER(SnapMapper::object_snaps) +WRITE_CLASS_ENCODER(SnapMapper::Mapping) #endif diff --git a/src/osd/osd_types.h b/src/osd/osd_types.h index 12042f2a400b0..46b4c88117d8f 100644 --- a/src/osd/osd_types.h +++ b/src/osd/osd_types.h @@ -68,6 +68,7 @@ #define CEPH_OSD_FEATURE_INCOMPAT_MISSING CompatSet::Feature(14, "explicit missing set") #define CEPH_OSD_FEATURE_INCOMPAT_FASTINFO CompatSet::Feature(15, "fastinfo pg attr") #define CEPH_OSD_FEATURE_INCOMPAT_RECOVERY_DELETES CompatSet::Feature(16, "deletes in missing set") +#define CEPH_OSD_FEATURE_INCOMPAT_SNAPMAPPER2 CompatSet::Feature(17, "new snapmapper key structure") /// pool priority range set by user -- 2.39.5