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);
}
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;
}
}
-struct Mapping {
- snapid_t snap;
- hobject_t hoid;
- explicit Mapping(const pair<snapid_t, hobject_t> &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<unsigned>(snap));
- return LEGACY_MAPPING_PREFIX + string(buf, len);
-}
-
string SnapMapper::get_prefix(int64_t pool, snapid_t snap)
{
char buf[100];
pair<snapid_t, hobject_t> SnapMapper::from_raw(
const pair<std::string, bufferlist> &image)
{
+ using ceph::decode;
Mapping map;
bufferlist bl(image.second);
auto bp = bl.cbegin();
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<unsigned>(snap));
+ return LEGACY_MAPPING_PREFIX + string(buf, len);
+}
+
+string SnapMapper::to_legacy_raw_key(
+ const pair<snapid_t, hobject_t> &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<string,bufferlist> 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;
+}
void decode(bufferlist::const_iterator &bp);
};
-private:
- MapCacher::MapCacher<std::string, bufferlist> backend;
+ struct Mapping {
+ snapid_t snap;
+ hobject_t hoid;
+ explicit Mapping(const pair<snapid_t, hobject_t> &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<std::string, bufferlist> 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<snapid_t, hobject_t> &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<snapid_t, hobject_t> &to_map);
static bool is_mapping(const std::string &to_test);
- std::pair<snapid_t, hobject_t> from_raw(
+ static std::pair<snapid_t, hobject_t> from_raw(
const std::pair<std::string, bufferlist> &image);
std::string to_object_key(const hobject_t &hoid);
); ///< @return error, -ENOENT if oid is not recorded
};
WRITE_CLASS_ENCODER(SnapMapper::object_snaps)
+WRITE_CLASS_ENCODER(SnapMapper::Mapping)
#endif
#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