// Maximum number of concurrent stray files to purge
OPTION(mds_max_purge_files, OPT_U32, 64)
// Maximum number of concurrent RADOS ops to issue in purging
-OPTION(mds_max_purge_ops, OPT_U32, 256)
+OPTION(mds_max_purge_ops, OPT_U32, 8192)
+// Maximum number of concurrent RADOS ops to issue in purging, scaled by PG count
+OPTION(mds_max_purge_ops_per_pg, OPT_FLOAT, 0.5)
// If true, compact leveldb store on mount
OPTION(osd_compact_leveldb_on_mount, OPT_BOOL, false)
// Calculate how much of the ops allowance is available, allowing
// for the case where the limit is currently being exceeded.
uint32_t ops_avail;
- if (ops_in_flight <= g_conf->mds_max_purge_ops) {
- ops_avail = g_conf->mds_max_purge_ops - ops_in_flight;
+ if (ops_in_flight <= max_purge_ops) {
+ ops_avail = max_purge_ops - ops_in_flight;
} else {
ops_avail = 0;
}
num_strays(0), num_strays_purging(0), num_strays_delayed(0)
{
assert(mds != NULL);
-
- assert(g_conf->mds_max_purge_ops >= g_conf->filer_max_purge_ops);
+ update_op_limit();
}
eval_stray(dn);
}
+
+const char** StrayManager::get_tracked_conf_keys() const
+{
+ static const char* KEYS[] = {
+ "mds_max_purge_ops",
+ NULL
+ };
+ return KEYS;
+}
+
+
+// Subscribe to the per-PG ops throttle config event, and do a cool calculation
+// of (throttle * pg_num / (mds_num))
+void StrayManager::handle_conf_change(const struct md_config_t *conf,
+ const std::set <std::string> &changed)
+{
+ if (changed.count("mds_max_purge_ops")) {
+ update_op_limit();
+ }
+}
+
+
+void StrayManager::update_op_limit()
+{
+ const OSDMap *osdmap = mds->objecter->get_osdmap_read();
+
+ // Number of PGs across all data pools
+ uint64_t pg_count = 0;
+ const std::set<int64_t> &data_pools = mds->mdsmap->get_data_pools();
+ for (std::set<int64_t>::iterator i = data_pools.begin();
+ i != data_pools.end(); ++i) {
+ pg_count += osdmap->get_pg_num(*i);
+ }
+
+ mds->objecter->put_osdmap_read();
+
+ uint64_t mds_count = mds->mdsmap->get_max_mds();
+
+ // Work out a limit based on n_pgs / n_mdss, multiplied by the user's
+ // preference for how many ops per PG
+ max_purge_ops = uint64_t(((double)pg_count / (double)mds_count) * g_conf->mds_max_purge_ops_per_pg);
+
+ // User may also specify a hard limit, apply this if so.
+ if (g_conf->mds_max_purge_ops) {
+ max_purge_ops = MIN(max_purge_ops, g_conf->mds_max_purge_ops);
+ }
+}
+
class CInode;
class CDentry;
-class StrayManager
+class StrayManager : public md_config_obs_t
{
protected:
class QueuedStray {
uint64_t ops_in_flight;
uint64_t files_purging;
+ // Dynamic op limit per MDS based on PG count
+ uint64_t max_purge_ops;
+
// Statistics
uint64_t num_strays;
uint64_t num_strays_purging;
void notify_stray_created();
void notify_stray_removed();
void abort_queue();
+
+ void update_op_limit();
+ virtual const char** get_tracked_conf_keys() const;
+ virtual void handle_conf_change(const struct md_config_t *conf,
+ const std::set <std::string> &changed);
};
#endif // STRAY_MANAGER_H