summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYan, Zheng <zheng.z.yan@intel.com>2013-09-19 13:37:05 +0800
committerYan, Zheng <zheng.z.yan@intel.com>2013-10-05 11:31:11 +0800
commit2eb863de2594fdae02fa5ab3056038cc12348f0c (patch)
tree989a1d6e2cdf17ed2df507e865ac9776424c651d
parentf989396ea562144c7cbc9de5ca606b451a121f88 (diff)
downloadceph-2eb863de2594fdae02fa5ab3056038cc12348f0c.tar.gz
mds: properly update rstat/fragstat when fragmentating directory
The stale rstat/dirstat check in CDir::merge() is wrong. dirfrag's rstat/fragstat is stale if the accounted rstat/fragstat version isn't equal to inode's rstat/dirstat version. For CDir::split(), no need to worry about if the rstat/fragstat of the origin dirfrag is stale. If it's stale, the rstat/fragstat of the resulting dirfrags are stale too. Signed-off-by: Yan, Zheng <zheng.z.yan@intel.com>
-rw-r--r--src/mds/CDir.cc90
1 files changed, 46 insertions, 44 deletions
diff --git a/src/mds/CDir.cc b/src/mds/CDir.cc
index 1b3c7e63456..c478e4c4c01 100644
--- a/src/mds/CDir.cc
+++ b/src/mds/CDir.cc
@@ -786,8 +786,10 @@ void CDir::prepare_old_fragment(bool replay)
void CDir::prepare_new_fragment(bool replay)
{
- if (!replay && is_auth())
+ if (!replay && is_auth()) {
_freeze_dir();
+ mark_complete();
+ }
}
void CDir::finish_old_fragment(list<Context*>& waiters, bool replay)
@@ -856,11 +858,16 @@ void CDir::split(int bits, list<CDir*>& subs, list<Context*>& waiters, bool repl
double fac = 1.0 / (double)(1 << bits); // for scaling load vecs
- nest_info_t olddiff; // old += f - af;
- dout(10) << " rstat " << fnode.rstat << dendl;
- dout(10) << " accounted_rstat " << fnode.accounted_rstat << dendl;
- olddiff.add_delta(fnode.rstat, fnode.accounted_rstat);
- dout(10) << " olddiff " << olddiff << dendl;
+ dout(15) << " rstat " << fnode.rstat << dendl;
+ dout(15) << " accounted_rstat " << fnode.accounted_rstat << dendl;
+ nest_info_t rstatdiff;
+ rstatdiff.add_delta(fnode.accounted_rstat, fnode.rstat);
+ dout(15) << " fragstat " << fnode.fragstat << dendl;
+ dout(15) << " accounted_fragstat " << fnode.accounted_fragstat << dendl;
+ frag_info_t fragstatdiff;
+ bool touched_mtime;
+ fragstatdiff.add_delta(fnode.accounted_fragstat, fnode.fragstat, touched_mtime);
+ dout(10) << " rstatdiff " << rstatdiff << " fragstatdiff " << fragstatdiff << dendl;
prepare_old_fragment(replay);
@@ -905,27 +912,24 @@ void CDir::split(int bits, list<CDir*>& subs, list<Context*>& waiters, bool repl
f->steal_dentry(dn);
}
+ // FIXME: handle dirty old rstat
+
// fix up new frag fragstats
- bool stale_fragstat = fnode.fragstat.version != fnode.accounted_fragstat.version;
- bool stale_rstat = fnode.rstat.version != fnode.accounted_rstat.version;
for (int i=0; i<n; i++) {
- subfrags[i]->fnode.fragstat.version = fnode.fragstat.version;
- subfrags[i]->fnode.accounted_fragstat = subfrags[i]->fnode.fragstat;
- if (i == 0) {
- if (stale_fragstat)
- subfrags[0]->fnode.accounted_fragstat.version--;
- if (stale_rstat)
- subfrags[0]->fnode.accounted_rstat.version--;
- }
- dout(10) << " fragstat " << subfrags[i]->fnode.fragstat << " on " << *subfrags[i] << dendl;
+ CDir *f = subfrags[i];
+ f->fnode.rstat.version = fnode.rstat.version;
+ f->fnode.accounted_rstat = f->fnode.rstat;
+ f->fnode.fragstat.version = fnode.fragstat.version;
+ f->fnode.accounted_fragstat = f->fnode.fragstat;
+ dout(10) << " rstat " << f->fnode.rstat << " fragstat " << f->fnode.fragstat
+ << " on " << *f << dendl;
}
// give any outstanding frag stat differential to first frag
- // af[0] -= olddiff
- dout(10) << "giving olddiff " << olddiff << " to " << *subfrags[0] << dendl;
- nest_info_t zero;
- subfrags[0]->fnode.accounted_rstat.add_delta(zero, olddiff);
- dout(10) << " " << subfrags[0]->fnode.accounted_fragstat << dendl;
+ dout(10) << " giving rstatdiff " << rstatdiff << " fragstatdiff" << fragstatdiff
+ << " to " << *subfrags[0] << dendl;
+ subfrags[0]->fnode.accounted_rstat.add(rstatdiff);
+ subfrags[0]->fnode.accounted_fragstat.add(fragstatdiff);
finish_old_fragment(waiters, replay);
}
@@ -936,15 +940,23 @@ void CDir::merge(list<CDir*>& subs, list<Context*>& waiters, bool replay)
prepare_new_fragment(replay);
- // see if _any_ of the source frags have stale fragstat or rstat
- int stale_rstat = 0;
- int stale_fragstat = 0;
+ nest_info_t rstatdiff;
+ frag_info_t fragstatdiff;
+ bool touched_mtime;
+ version_t rstat_version = inode->get_projected_inode()->rstat.version;
+ version_t dirstat_version = inode->get_projected_inode()->dirstat.version;
for (list<CDir*>::iterator p = subs.begin(); p != subs.end(); ++p) {
CDir *dir = *p;
dout(10) << " subfrag " << dir->get_frag() << " " << *dir << dendl;
assert(!dir->is_auth() || dir->is_complete() || replay);
-
+
+ if (dir->fnode.accounted_rstat.version == rstat_version)
+ rstatdiff.add_delta(dir->fnode.accounted_rstat, dir->fnode.rstat);
+ if (dir->fnode.accounted_fragstat.version == dirstat_version)
+ fragstatdiff.add_delta(dir->fnode.accounted_fragstat, dir->fnode.fragstat,
+ touched_mtime);
+
dir->prepare_old_fragment(replay);
// steal dentries
@@ -964,21 +976,6 @@ void CDir::merge(list<CDir*>& subs, list<Context*>& waiters, bool replay)
if (dir->get_version() > get_version())
set_version(dir->get_version());
- // *stat versions
- if (fnode.fragstat.version < dir->fnode.fragstat.version)
- fnode.fragstat.version = dir->fnode.fragstat.version;
- if (fnode.rstat.version < dir->fnode.rstat.version)
- fnode.rstat.version = dir->fnode.rstat.version;
-
- if (dir->fnode.accounted_fragstat.version != dir->fnode.fragstat.version)
- stale_fragstat = 1;
- if (dir->fnode.accounted_rstat.version != dir->fnode.rstat.version)
- stale_rstat = 1;
-
- // sum accounted_*
- fnode.accounted_fragstat.add(dir->fnode.accounted_fragstat);
- fnode.accounted_rstat.add(dir->fnode.accounted_rstat, 1);
-
// merge state
state_set(dir->get_state() & MASK_STATE_FRAGMENT_KEPT);
dir_auth = dir->dir_auth;
@@ -987,9 +984,14 @@ void CDir::merge(list<CDir*>& subs, list<Context*>& waiters, bool replay)
inode->close_dirfrag(dir->get_frag());
}
- // offset accounted_* version by -1 if any source frag was stale
- fnode.accounted_fragstat.version = fnode.fragstat.version - stale_fragstat;
- fnode.accounted_rstat.version = fnode.rstat.version - stale_rstat;
+ // FIXME: merge dirty old rstat
+ fnode.rstat.version = rstat_version;
+ fnode.accounted_rstat = fnode.rstat;
+ fnode.accounted_rstat.add(rstatdiff);
+
+ fnode.fragstat.version = dirstat_version;
+ fnode.accounted_fragstat = fnode.fragstat;
+ fnode.accounted_fragstat.add(fragstatdiff);
init_fragment_pins();
}