There is one new plugin (shec). When upgrading a cluster, there
must be a protection against the following scenario:
* the mon are upgraded but not the osd
* a new pool is created using plugin shec
* the osd fail to load the shec plugin because they have not been
upgraded
A feature bit is added : PLUGINS_V3. The monitor will only agree to
create an erasure code profile for the shec plugin if all OSDs
supports PLUGINS_V3. Once such an erasure code profile is stored in the
OSDMap, an OSD can only boot if it supports the PLUGINS_V3 feature,
which means it is able to load the shec plugin.
The monitors will only activate the PLUGINS_V3 feature if all monitors
in the quorum support it. It protects against the following scenario:
* the leader is upgraded the peons are not upgraded
* the leader creates a pool with plugin=shec because all OSD have
the PLUGINS_V3 feature
* the leader goes down and a non upgraded peon becomes the leader
* an old OSD tries to join the cluster
* the new leader will let the OSD boot because it does not contain
the logic that would excluded it
* the old OSD will fail when required to load the plugin shec
This is going to be needed each time new plugins are added, which is
impractical. A more generic plugin upgrade support should be added
instead, as described in http://tracker.ceph.com/issues/7291.
See also
9687150ceac9cc7e506bc227f430d4207a6d7489 for the PLUGINS_V2
implementation.
http://tracker.ceph.com/issues/10887 Fixes: #10887
Signed-off-by: Loic Dachary <ldachary@redhat.com>
#define CEPH_FEATURE_MON_METADATA (1ULL<<50)
#define CEPH_FEATURE_OSD_BITWISE_HOBJ_SORT (1ULL<<51) /* can sort objs bitwise */
#define CEPH_FEATURE_OSD_PROXY_WRITE_FEATURES (1ULL<<52)
+#define CEPH_FEATURE_ERASURE_CODE_PLUGINS_V3 (1ULL<<53)
#define CEPH_FEATURE_RESERVED2 (1ULL<<61) /* slow down, we are almost out... */
#define CEPH_FEATURE_RESERVED (1ULL<<62) /* DO NOT USE THIS ... last bit! */
CEPH_FEATURE_OSD_MIN_SIZE_RECOVERY | \
CEPH_FEATURE_MON_METADATA | \
CEPH_FEATURE_OSD_BITWISE_HOBJ_SORT | \
+ CEPH_FEATURE_ERASURE_CODE_PLUGINS_V3 | \
CEPH_FEATURE_OSD_PROXY_WRITE_FEATURES | \
0ULL)
compat.incompat.insert(CEPH_MON_FEATURE_INCOMPAT_OSD_ERASURE_CODES);
compat.incompat.insert(CEPH_MON_FEATURE_INCOMPAT_OSDMAP_ENC);
compat.incompat.insert(CEPH_MON_FEATURE_INCOMPAT_ERASURE_CODE_PLUGINS_V2);
+ compat.incompat.insert(CEPH_MON_FEATURE_INCOMPAT_ERASURE_CODE_PLUGINS_V3);
return compat;
}
if (quorum_features & CEPH_FEATURE_ERASURE_CODE_PLUGINS_V2) {
new_features.incompat.insert(CEPH_MON_FEATURE_INCOMPAT_ERASURE_CODE_PLUGINS_V2);
}
+ if (quorum_features & CEPH_FEATURE_ERASURE_CODE_PLUGINS_V3) {
+ new_features.incompat.insert(CEPH_MON_FEATURE_INCOMPAT_ERASURE_CODE_PLUGINS_V3);
+ }
if (new_features.compare(features) != 0) {
CompatSet diff = features.unsupported(new_features);
dout(1) << __func__ << " enabling new quorum features: " << diff << dendl;
if (features.incompat.contains(CEPH_MON_FEATURE_INCOMPAT_ERASURE_CODE_PLUGINS_V2)) {
required_features |= CEPH_FEATURE_ERASURE_CODE_PLUGINS_V2;
}
+ if (features.incompat.contains(CEPH_MON_FEATURE_INCOMPAT_ERASURE_CODE_PLUGINS_V3)) {
+ required_features |= CEPH_FEATURE_ERASURE_CODE_PLUGINS_V3;
+ }
dout(10) << __func__ << " required_features " << required_features << dendl;
}
#define CEPH_MON_FEATURE_INCOMPAT_OSD_ERASURE_CODES CompatSet::Feature(4, "support erasure code pools")
#define CEPH_MON_FEATURE_INCOMPAT_OSDMAP_ENC CompatSet::Feature(5, "new-style osdmap encoding")
#define CEPH_MON_FEATURE_INCOMPAT_ERASURE_CODE_PLUGINS_V2 CompatSet::Feature(6, "support isa/lrc erasure code")
+#define CEPH_MON_FEATURE_INCOMPAT_ERASURE_CODE_PLUGINS_V3 CompatSet::Feature(7, "support shec erasure code")
// make sure you add your feature to Monitor::get_supported_features
long parse_pos_long(const char *s, ostream *pss = NULL);
goto ignore;
}
+ if ((osdmap.get_features(CEPH_ENTITY_TYPE_OSD, NULL) &
+ CEPH_FEATURE_ERASURE_CODE_PLUGINS_V3) &&
+ !(m->get_connection()->get_features() & CEPH_FEATURE_ERASURE_CODE_PLUGINS_V3)) {
+ dout(0) << __func__ << " osdmap requires erasure code plugins v3 but osd at "
+ << m->get_orig_source_inst()
+ << " doesn't announce support -- ignore" << dendl;
+ goto ignore;
+ }
+
if (osdmap.test_flag(CEPH_OSDMAP_SORTBITWISE) &&
!(m->osd_features & CEPH_FEATURE_OSD_BITWISE_HOBJ_SORT)) {
mon->clog->info() << "disallowing boot of OSD "
if (err)
goto reply;
} else if (plugin == "shec") {
- if (!g_ceph_context->check_experimental_feature_enabled("shec", &ss)) {
- err = -EINVAL;
+ err = check_cluster_features(CEPH_FEATURE_ERASURE_CODE_PLUGINS_V3, ss);
+ if (err == -EAGAIN)
+ goto wait;
+ if (err)
goto reply;
- }
}
err = normalize_profile(profile_map, &ss);
if (err)
++p) {
const map<string,string> &profile = p->second;
map<string,string>::const_iterator plugin = profile.find("plugin");
- if (plugin != profile.end() && (plugin->second == "isa" ||
- plugin->second == "lrc"))
- features |= CEPH_FEATURE_ERASURE_CODE_PLUGINS_V2;
+ if (plugin != profile.end()) {
+ if (plugin->second == "isa" || plugin->second == "lrc")
+ features |= CEPH_FEATURE_ERASURE_CODE_PLUGINS_V2;
+ if (plugin->second == "shec")
+ features |= CEPH_FEATURE_ERASURE_CODE_PLUGINS_V3;
+ }
}
}
mask |= CEPH_FEATURE_OSDHASHPSPOOL | CEPH_FEATURE_OSD_CACHEPOOL;
export CEPH_MON="127.0.0.1:7101"
export CEPH_ARGS
CEPH_ARGS+="--fsid=$(uuidgen) --auth-supported=none "
- CEPH_ARGS+="--enable-experimental-unrecoverable-data-corrupting-features=shec "
CEPH_ARGS+="--mon-host=$CEPH_MON "
setup $dir || return 1
export CEPH_MON="127.0.0.1:7112"
export CEPH_ARGS
CEPH_ARGS+="--fsid=$(uuidgen) --auth-supported=none "
- CEPH_ARGS+="--enable-experimental-unrecoverable-data-corrupting-features=shec "
CEPH_ARGS+="--mon-host=$CEPH_MON "
local funcs=${@:-$(set | sed -n -e 's/^\(TEST_[0-9a-z_]*\) .*/\1/p')}
grep -q "unknown erasure code profile 'WRONG'" $dir/out || return 1
}
-function TEST_experimental_shec() {
- local dir=$1
- local id=$2
-
- run_mon $dir a || return 1
-
- local profile=shec-profile
-
- ! ./ceph osd erasure-code-profile set $profile plugin=shec > $dir/out 2>&1 || return 1
- grep "experimental feature 'shec'" $dir/out || return 1
- ! ./ceph osd erasure-code-profile ls | grep $profile || return 1
-}
-
function TEST_set_idempotent() {
local dir=$1
local id=$2