void merge(const std::vector<CDir*>& subs, MDSContext::vec& waiters, bool replay);
bool should_split() const {
- return (int)get_frag_size() > g_conf()->mds_bal_split_size;
+ return g_conf()->mds_bal_split_size > 0 &&
+ (int)get_frag_size() > g_conf()->mds_bal_split_size;
}
bool should_split_fast() const;
bool should_merge() const {
- return (int)get_frag_size() < g_conf()->mds_bal_merge_size;
+ return get_frag() != frag_t() &&
+ (int)get_frag_size() < g_conf()->mds_bal_merge_size;
}
mds_authority_t authority() const override;
!dir->inode->is_stray()) { // not straydir
// split
- if (g_conf()->mds_bal_split_size > 0 && (dir->should_split() || hot)) {
+ if (dir->should_split() || hot) {
if (split_pending.count(dir->dirfrag()) == 0) {
queue_split(dir, false);
} else {
void MDBalancer::hit_dir(CDir *dir, int type, int who, double amount)
{
+ if (dir->inode->is_stray())
+ return;
// hit me
double v = dir->pop_me.get(type).hit(amount);
void queue_split(const CDir *dir, bool fast);
void queue_merge(CDir *dir);
+ bool is_fragment_pending(dirfrag_t df) {
+ return split_pending.count(df) || merge_pending.count(df);
+ }
/**
* Based on size and configuration, decide whether to issue a queue_split
populate_mydir();
}
+void MDCache::advance_stray() {
+ // check whether the directory has been fragmented
+ if (stray_fragmenting_index >= 0) {
+ auto&& dfs = strays[stray_fragmenting_index]->get_dirfrags();
+ bool any_fragmenting = false;
+ for (const auto& dir : dfs) {
+ if (dir->state_test(CDir::STATE_FRAGMENTING) ||
+ mds->balancer->is_fragment_pending(dir->dirfrag())) {
+ any_fragmenting = true;
+ break;
+ }
+ }
+ if (!any_fragmenting)
+ stray_fragmenting_index = -1;
+ }
+
+ for (int i = 1; i < NUM_STRAY; i++){
+ stray_index = (stray_index + i) % NUM_STRAY;
+ if (stray_index != stray_fragmenting_index)
+ break;
+ }
+
+ if (stray_fragmenting_index == -1 && is_open()) {
+ // Fragment later stray dir in advance. We don't choose past
+ // stray dir because in-flight requests may still use it.
+ stray_fragmenting_index = (stray_index + 3) % NUM_STRAY;
+ auto&& dfs = strays[stray_fragmenting_index]->get_dirfrags();
+ bool any_fragmenting = false;
+ for (const auto& dir : dfs) {
+ if (dir->should_split()) {
+ mds->balancer->queue_split(dir, true);
+ any_fragmenting = true;
+ } else if (dir->should_merge()) {
+ mds->balancer->queue_merge(dir);
+ any_fragmenting = true;
+ }
+ }
+ if (!any_fragmenting)
+ stray_fragmenting_index = -1;
+ }
+
+ dout(10) << "advance_stray to index " << stray_index
+ << " fragmenting index " << stray_fragmenting_index << dendl;
+}
+
void MDCache::populate_mydir()
{
ceph_assert(myin);
return cache_size() > cache_memory_limit*cache_health_threshold;
}
- void advance_stray() {
- stray_index = (stray_index+1)%NUM_STRAY;
- }
+ void advance_stray();
/**
* Call this when you know that a CDentry is ready to be passed
bool readonly = false;
int stray_index = 0;
+ int stray_fragmenting_index = -1;
set<CInode*> base_inodes;
logger->set(l_mdl_seg, segments.size());
// Adjust to next stray dir
- dout(10) << "Advancing to next stray directory on mds " << mds->get_nodeid()
- << dendl;
mds->mdcache->advance_stray();
}