summaryrefslogtreecommitdiff
path: root/src/include/CompatSet.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/include/CompatSet.h')
-rw-r--r--src/include/CompatSet.h34
1 files changed, 30 insertions, 4 deletions
diff --git a/src/include/CompatSet.h b/src/include/CompatSet.h
index 1c18d6193a9..b5bf450b97e 100644
--- a/src/include/CompatSet.h
+++ b/src/include/CompatSet.h
@@ -33,9 +33,11 @@ struct CompatSet {
uint64_t mask;
map <uint64_t,string> names;
- FeatureSet() : mask(0), names() {}
+ FeatureSet() : mask(1), names() {}
void insert(Feature f) {
- mask |= f.id;
+ assert(f.id > 0);
+ assert(f.id < 63);
+ mask |= (1<<f.id);
names[f.id] = f.name;
}
@@ -45,18 +47,42 @@ struct CompatSet {
void remove(uint64_t f) {
if (names.count(f)) {
names.erase(f);
- mask &= ~f;
+ mask &= ~(1<<f);
}
}
void encode(bufferlist& bl) const {
- ::encode(mask, bl);
+ /* See below, mask always has the lowest bit set in memory, but
+ * unset in the encoding */
+ ::encode(mask & (~(uint64_t)1), bl);
::encode(names, bl);
}
void decode(bufferlist::iterator& bl) {
::decode(mask, bl);
::decode(names, bl);
+ /**
+ * Previously, there was a bug where insert did
+ * mask |= f.id rather than mask |= (1 << f.id).
+ * In FeatureSets from those version, mask always
+ * has the lowest bit set. Since then, masks always
+ * have the lowest bit unset.
+ *
+ * When we encounter such a FeatureSet, we have to
+ * reconstruct the mask from the names map.
+ */
+ if (mask & 1) {
+ mask = 1;
+ map<uint64_t, string> temp_names;
+ temp_names.swap(names);
+ for (map<uint64_t, string>::iterator i = temp_names.begin();
+ i != temp_names.end();
+ ++i) {
+ insert(Feature(i->first, i->second));
+ }
+ } else {
+ mask |= 1;
+ }
}
void dump(Formatter *f) const {