#pragma once
#include <map>
+#include <algorithm>
#include <seastar/core/future.hh>
#include <seastar/core/shared_future.hh>
#include "include/types.h"
#include "crimson/common/type_helpers.h"
+#include "crimson/common/smp_helpers.h"
#include "crimson/osd/osd_operation.h"
#include "osd/osd_types.h"
namespace crimson::osd {
class PG;
+/**
+ * PGShardMapping
+ *
+ * Maps pgs to shards.
+ */
+class PGShardMapping {
+public:
+ /// Returns mapping if present, NULL_CORE otherwise
+ core_id_t get_pg_mapping(spg_t pgid) {
+ auto iter = pg_to_core.find(pgid);
+ ceph_assert_always(iter == pg_to_core.end() || iter->second != NULL_CORE);
+ return iter == pg_to_core.end() ? NULL_CORE : iter->second;
+ }
+
+ /// Returns mapping for pgid, creates new one if it doesn't already exist
+ core_id_t maybe_create_pg(spg_t pgid) {
+ auto [insert_iter, inserted] = pg_to_core.emplace(pgid, NULL_CORE);
+ if (!inserted) {
+ ceph_assert_always(insert_iter->second != NULL_CORE);
+ return insert_iter->second;
+ } else {
+ ceph_assert_always(core_to_num_pgs.size() > 0);
+ auto core_iter = std::min_element(
+ core_to_num_pgs.begin(),
+ core_to_num_pgs.end(),
+ [](const auto &left, const auto &right) {
+ return left.second < right.second;
+ });
+ ceph_assert_always(core_to_num_pgs.end() != core_iter);
+ insert_iter->second = core_iter->first;
+ core_iter->second++;
+ return insert_iter->second;
+ }
+ }
+
+ /// Remove pgid
+ void remove_pg(spg_t pgid) {
+ auto iter = pg_to_core.find(pgid);
+ ceph_assert_always(iter != pg_to_core.end());
+ ceph_assert_always(iter->second != NULL_CORE);
+ auto count_iter = core_to_num_pgs.find(iter->second);
+ ceph_assert_always(count_iter != core_to_num_pgs.end());
+ ceph_assert_always(count_iter->second > 0);
+ --(count_iter->second);
+ pg_to_core.erase(iter);
+ }
+
+ /// Map to cores in [min_core_mapping, core_mapping_limit)
+ PGShardMapping(core_id_t min_core_mapping, core_id_t core_mapping_limit) {
+ ceph_assert_always(min_core_mapping < core_mapping_limit);
+ for (auto i = min_core_mapping; i != core_mapping_limit; ++i) {
+ core_to_num_pgs.emplace(i, 0);
+ }
+ }
+private:
+ std::map<core_id_t, unsigned> core_to_num_pgs;
+ std::map<spg_t, core_id_t> pg_to_core;
+};
+
+/**
+ * PGMap
+ *
+ * Maps spg_t to PG instance within a shard. Handles dealing with waiting
+ * on pg creation.
+ */
class PGMap {
struct PGCreationState : BlockerT<PGCreationState> {
static constexpr const char * type_name = "PGCreation";