From: xie xingguo Date: Mon, 9 Mar 2020 05:52:51 +0000 (+0800) Subject: osd/OSDMap: stop encoding osd_state with >8 bits wide states only for old client X-Git-Tag: v15.1.1~20^2 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=054bcb934f9ee881f2afc538eeaa80931a03ffd6;p=ceph.git osd/OSDMap: stop encoding osd_state with >8 bits wide states only for old client In a8fb39b5 we extended Incremental's new_state to 32 bits wide instead of 8. However, if we intend to flip those > 8 bits wide flags only (e.g., the per-osd CEPH_OSD_NOOUT/NOIN flag), we'll end up encoding a zeroed new_state into the Incremental map, which'll be mis-interpreted as osd-down by old clients. Fix by skipping encoding osd_states with the extended(> 256) flags only. They simply can not be understood by those clients and will get ignored anyway. Signed-off-by: xie xingguo --- diff --git a/src/osd/OSDMap.cc b/src/osd/OSDMap.cc index a4adf503dd3..23903c29674 100644 --- a/src/osd/OSDMap.cc +++ b/src/osd/OSDMap.cc @@ -433,11 +433,21 @@ void OSDMap::Incremental::encode_client_old(ceph::buffer::list& bl) const encode(new_up_client, bl, 0); { // legacy is map - uint32_t n = new_state.size(); - encode(n, bl); + map os; for (auto p : new_state) { + // new_state may only inculde some new flags(e.g., CEPH_OSD_NOOUT) + // that an old client could not understand. + // skip those! + uint8_t s = p.second; + if (p.second != 0 && s == 0) + continue; + os[p.first] = s; + } + uint32_t n = os.size(); + encode(n, bl); + for (auto p : os) { encode(p.first, bl); - encode((uint8_t)p.second, bl); + encode(p.second, bl); } } encode(new_weight, bl); @@ -477,11 +487,21 @@ void OSDMap::Incremental::encode_classic(ceph::buffer::list& bl, uint64_t featur encode(old_pools, bl); encode(new_up_client, bl, features); { - uint32_t n = new_state.size(); - encode(n, bl); + map os; for (auto p : new_state) { + // new_state may only inculde some new flags(e.g., CEPH_OSD_NOOUT) + // that an old client could not understand. + // skip those! + uint8_t s = p.second; + if (p.second != 0 && s == 0) + continue; + os[p.first] = s; + } + uint32_t n = os.size(); + encode(n, bl); + for (auto p : os) { encode(p.first, bl); - encode((uint8_t)p.second, bl); + encode(p.second, bl); } } encode(new_weight, bl); @@ -585,11 +605,21 @@ void OSDMap::Incremental::encode(ceph::buffer::list& bl, uint64_t features) cons if (v >= 5) { encode(new_state, bl); } else { - uint32_t n = new_state.size(); - encode(n, bl); + map os; for (auto p : new_state) { - encode(p.first, bl); - encode((uint8_t)p.second, bl); + // new_state may only inculde some new flags(e.g., CEPH_OSD_NOOUT) + // that an old client could not understand. + // skip those! + uint8_t s = p.second; + if (p.second != 0 && s == 0) + continue; + os[p.first] = s; + } + uint32_t n = os.size(); + encode(n, bl); + for (auto p : os) { + encode(p.first, bl); + encode(p.second, bl); } } encode(new_weight, bl);