_handle_osd_map() computes start = superblock.get_newest_map() + 1. A
freshly created OSD has get_newest_map() == 0, so start stays 1. When
such an OSD joins a cluster whose oldest map is already trimmed past
epoch 1, the gap [start, first - 1] is entirely below the trim lower
bound, so neither osdmap_subscribe guard above fires, and start stays 1.
store_maps() then stores only [first..last], but committed_osd_maps()
iterates from start=1 and calls get_local_map(1), which reads the
never-stored osdmap.1, hits ENOENT, and aborts. The OSD crash-loops
without ever activating a PG.
Clamp start to first in that case: the maps below first are gone, and
first is a full map, so it's a valid starting point. Classic OSD does
the same unconditionally via
start = std::max(superblock.get_newest_map() + 1, first).
Signed-off-by: Kefu Chai <k.chai@proxmox.com>
co_return co_await get_shard_services().osdmap_subscribe(
m->cluster_osdmap_trim_lower_bound - 1, true);
}
+ start = first;
}
ceph::os::Transaction t;