java-topology/defects/ceph/patch/ceph-0001-osdmap-underfull-set.patch
russell@unturf.com ac82cff865 php-cluster: doctrine-orm-0001 + composer-0003 CWE-407 defects; count 668→670
doctrine-orm-0001: ClassMetadata::addSubClass in_array O(S²) subclasses list HIGH
  - src/Mapping/ClassMetadata.php addSubClass() scans plain $subClasses list
  - addSubClasses($parent->subClasses) called in doLoadMetadata: O(S²) per class
  - Fix: parallel $subClassesSet hash for O(1) membership; 500x at S=1000

composer-0003: InstalledRepository::getDependents in_array O(P²) needles list MEDIUM
  - needles array grows during foreach($packages) loop, in_array scan 3 sites
  - $packagesFoundSet already exists for cycle-detection but needles is separate
  - Fix: add $needlesSet = array_fill_keys($needles, true), mirror growth; 1000x at P=1000

cayley: CLEAN (confirmed -- map-based seen/pathMap throughout)
tinkerpop: CLEAN (confirmed -- existing CLEAN.md valid, sort ArrayList is query-plan-time only)
2026-03-29 19:51:31 -04:00

60 lines
2.6 KiB
Diff
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# UNDF: UNDF-2026-000000044
diff --git a/src/osd/OSDMap.cc b/src/osd/OSDMap.cc
--- a/src/osd/OSDMap.cc
+++ b/src/osd/OSDMap.cc
@@ -5818,6 +5818,8 @@ int OSDMap::calc_pg_upmaps(
while (max--) {
ldout(cct, 30) << "Top of loop #" << max+1 << dendl;
// build overfull and underfull
set<int> overfull;
set<int> more_overfull;
bool using_more_overfull = false;
vector<int> underfull;
vector<int> more_underfull;
fill_overfull_underfull(cct, deviation_osd, max_deviation,
overfull, more_overfull,
underfull, more_underfull);
+ // Pre-build O(1) lookup sets — underfull/more_underfull are read-only in
+ // the scan loops below, so unordered_set avoids O(N×U) std::find calls.
+ std::unordered_set<int> underfull_set(underfull.begin(), underfull.end());
+ std::unordered_set<int> more_underfull_set(more_underfull.begin(), more_underfull.end());
@@ -5979,8 +5981,7 @@ int OSDMap::calc_pg_upmaps(
for (auto& [deviation, osd] : deviation_osd) {
- if (std::find(underfull.begin(), underfull.end(), osd) ==
- underfull.end())
+ if (underfull_set.find(osd) == underfull_set.end())
break;
float target = osd_weight[osd] * pgs_per_weight;
diff --git a/src/crush/CrushWrapper.cc b/src/crush/CrushWrapper.cc
--- a/src/crush/CrushWrapper.cc
+++ b/src/crush/CrushWrapper.cc
@@ -4118,6 +4118,8 @@ int CrushWrapper::try_remap_rule(
for (int pos = 0; pos < fanout; ++pos) {
if (type > 0) {
// non-leaf: no change
} else {
// leaf
bool replaced = false;
if (overfull.count(*i)) {
+ // Build orig_set once per leaf slot — O(1) membership below
+ std::unordered_set<int> orig_set(orig.begin(), orig.end());
for (auto item : underfull) {
if (used.count(item)) continue;
if (!subtree_contains(from, item)) continue;
- if (std::find(orig.begin(), orig.end(), item) != orig.end()) {
+ if (orig_set.count(item)) {
ldout(cct, 20) << __func__ << " in orig " << orig << dendl;
continue;
}
@@ -4152,8 +4154,6 @@ int CrushWrapper::try_remap_rule(
if (!replaced) {
for (auto item : more_underfull) {
if (used.count(item)) continue;
if (!subtree_contains(from, item)) continue;
- if (std::find(orig.begin(), orig.end(), item) != orig.end()) {
+ if (orig_set.count(item)) {
ldout(cct, 20) << __func__ << " in orig " << orig << dendl;
continue;
}