{
dout(10) << "merge " << subs << dendl;
+ // see if _any_ of the source frags have stale fragstat or rstat
+ int stale_rstat = 0;
+ int stale_fragstat = 0;
+
for (list<CDir*>::iterator p = subs.begin(); p != subs.end(); p++) {
CDir *dir = *p;
dout(10) << " subfrag " << dir->get_frag() << " " << *dir << dendl;
if (dir->get_version() > get_version())
set_version(dir->get_version());
- if (fnode.fragstat.version == 0)
+ // *stat versions
+ if (fnode.fragstat.version < dir->fnode.fragstat.version)
fnode.fragstat.version = dir->fnode.fragstat.version;
- if (fnode.rstat.version == 0)
+ 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;
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;
+
init_fragment_pins();
}
nsubdirs += cur.nsubdirs - acc.nsubdirs;
}
+ void add(const frag_info_t& other) {
+ if (other.mtime > mtime)
+ mtime = other.mtime;
+ nfiles += other.nfiles;
+ nsubdirs += other.nsubdirs;
+ }
+
void encode(bufferlist &bl) const {
__u8 v = 1;
::encode(v, bl);