* New OSD daemon command dump_scrub_reservations which reveals the
scrub reservations that are held for local (primary) and remote (replica) PGs.
+* Ceph will now issue a health warning if a RADOS pool as a ``pg_num``
+ value that is not a power of two. This can be fixed by adjusting
+ the pool to a nearby power of two::
+
+ ceph osd pool set <pool-name> pg_num <new-pg-num>
+
+ Alternatively, the warning can be silenced with::
+
+ ceph config set global mon_warn_on_pool_pg_num_not_power_of_two false
+
* The ``pg_autoscale_mode`` is now set to ``on`` by default for newly
created pools, which means that Ceph will automatically manage the
number of PGs. To change this behavior, or to learn more about PG
Please refer to :ref:`choosing-number-of-placement-groups` for more
information.
+POOL_PG_NUM_NOT_POWER_OF_TWO
+____________________________
+
+One or more pools has a ``pg_num`` value that is not a power of two.
+Although this is not strictly incorrect, it does lead to a less
+balanced distribution of data because some PGs have roughly twice as
+much data as others.
+
+This is easily corrected by setting the ``pg_num`` value for the
+affected pool(s) to a nearby power of two::
+
+ ceph osd pool set <pool-name> pg_num <value>
+
+This health warning can be disabled with::
+
+ ceph config set global mon_warn_on_pool_pg_num_not_power_of_two false
+
POOL_TOO_FEW_PGS
________________
.add_service("mgr")
.set_description("issue POOL_APP_NOT_ENABLED health warning if pool has not application enabled"),
+ Option("mon_warn_on_pool_pg_num_not_power_of_two", Option::TYPE_BOOL, Option::LEVEL_DEV)
+ .set_default(true)
+ .add_service("mon")
+ .set_description("issue POOL_PG_NUM_NOT_POWER_OF_TWO warning if pool has a non-power-of-two pg_num value"),
+
Option("mon_warn_on_misplaced", Option::TYPE_BOOL, Option::LEVEL_ADVANCED)
.set_default(false)
.add_service("mgr")
// health
health_check_map_t next;
- tmp.check_health(&next);
+ tmp.check_health(g_ceph_context, &next);
encode_health(next, t);
}
}
}
-void OSDMap::check_health(health_check_map_t *checks) const
+void OSDMap::check_health(CephContext *cct,
+ health_check_map_t *checks) const
{
int num_osds = get_num_osds();
d.detail.swap(nearfull_detail);
}
}
+
+ // POOL_PG_NUM_NOT_POWER_OF_TWO
+ if (cct->_conf.get_val<bool>("mon_warn_on_pool_pg_num_not_power_of_two")) {
+ list<string> detail;
+ for (auto it : get_pools()) {
+ if (!isp2(it.second.get_pg_num_target())) {
+ ostringstream ss;
+ ss << "pool '" << get_pool_name(it.first)
+ << "' pg_num " << it.second.get_pg_num_target()
+ << " is not a power of two";
+ detail.push_back(ss.str());
+ }
+ }
+ if (!detail.empty()) {
+ ostringstream ss;
+ ss << detail.size() << " pool(s) have non-power-of-two pg_num";
+ auto& d = checks->add("POOL_PG_NUM_NOT_POWER_OF_TWO", HEALTH_WARN,
+ ss.str(), detail.size());
+ d.detail.swap(detail);
+ }
+ }
}
int OSDMap::parse_osd_id_list(const vector<string>& ls, set<int> *out,
static void generate_test_instances(std::list<OSDMap*>& o);
bool check_new_blacklist_entries() const { return new_blacklist_entries; }
- void check_health(health_check_map_t *checks) const;
+ void check_health(CephContext *cct, health_check_map_t *checks) const;
int parse_osd_id_list(const std::vector<std::string>& ls,
std::set<int> *out,
if (health) {
health_check_map_t checks;
- osdmap.check_health(&checks);
+ osdmap.check_health(g_ceph_context, &checks);
JSONFormatter jf(true);
jf.dump_object("checks", checks);
jf.flush(cout);