// did we import some dirty scatterlock data?
if (dirty_old_rstat.size() ||
- !(fnode.rstat == fnode.accounted_rstat))
+ !(fnode.rstat == fnode.accounted_rstat)) {
cache->mds->locker->mark_updated_scatterlock(&inode->nestlock);
- if (!(fnode.fragstat == fnode.accounted_fragstat))
+ ls->dirty_dirfrag_nest.push_back(&inode->item_dirty_dirfrag_nest);
+ }
+ if (!(fnode.fragstat == fnode.accounted_fragstat)) {
cache->mds->locker->mark_updated_scatterlock(&inode->filelock);
+ ls->dirty_dirfrag_dir.push_back(&inode->item_dirty_dirfrag_dir);
+ }
+ if (is_dirty_dft()) {
+ if (inode->dirfragtreelock.get_state() != LOCK_MIX &&
+ inode->dirfragtreelock.is_stable()) {
+ // clear stale dirtydft
+ state_clear(STATE_DIRTYDFT);
+ } else {
+ cache->mds->locker->mark_updated_scatterlock(&inode->dirfragtreelock);
+ ls->dirty_dirfrag_dirfragtree.push_back(&inode->item_dirty_dirfrag_dirfragtree);
+ }
+ }
}
static const unsigned STATE_STICKY = (1<<15); // sticky pin due to inode stickydirs
static const unsigned STATE_DNPINNEDFRAG = (1<<16); // dir is refragmenting
static const unsigned STATE_ASSIMRSTAT = (1<<17); // assimilating inode->frag rstats
+ static const unsigned STATE_DIRTYDFT = (1<<18); // dirty dirfragtree
// common states
static const unsigned STATE_CLEAN = 0;
// these state bits are preserved by an import/export
// ...except if the directory is hashed, in which case none of them are!
static const unsigned MASK_STATE_EXPORTED =
- (STATE_COMPLETE|STATE_DIRTY);
+ (STATE_COMPLETE|STATE_DIRTY|STATE_DIRTYDFT);
static const unsigned MASK_STATE_IMPORT_KEPT =
(
STATE_IMPORTING
bool is_complete() { return state & STATE_COMPLETE; }
bool is_exporting() { return state & STATE_EXPORTING; }
bool is_importing() { return state & STATE_IMPORTING; }
+ bool is_dirty_dft() { return state & STATE_DIRTYDFT; }
int get_dir_rep() { return dir_rep; }
bool is_rep() {
dirfragtree.swap(temp);
for (map<frag_t,CDir*>::iterator p = dirfrags.begin();
p != dirfrags.end();
- ++p)
+ ++p) {
if (!dirfragtree.is_leaf(p->first)) {
dout(10) << " forcing open dirfrag " << p->first << " to leaf (racing with split|merge)" << dendl;
dirfragtree.force_to_leaf(g_ceph_context, p->first);
}
+ if (p->second->is_auth())
+ p->second->state_clear(CDir::STATE_DIRTYDFT);
+ }
}
if (g_conf->mds_debug_frag)
verify_dirfrags();
case CEPH_LOCK_INEST:
finish_scatter_update(lock, dir, pi->rstat.version, pf->accounted_rstat.version);
break;
+
+ case CEPH_LOCK_IDFT:
+ dir->state_clear(CDir::STATE_DIRTYDFT);
+ break;
}
}
}
for (list<CDir*>::iterator p = info.resultfrags.begin();
p != info.resultfrags.end();
++p) {
- le->metablob.add_dir(*p, false);
+ if (diri->is_auth()) {
+ le->metablob.add_fragmented_dir(*p, false);
+ } else {
+ (*p)->state_set(CDir::STATE_DIRTYDFT);
+ le->metablob.add_fragmented_dir(*p, true);
+ }
}
// dft lock
- mds->locker->mark_updated_scatterlock(&diri->dirfragtreelock);
- mdr->ls->dirty_dirfrag_dirfragtree.push_back(&diri->item_dirty_dirfrag_dirfragtree);
- mdr->add_updated_lock(&diri->dirfragtreelock);
+ if (diri->is_auth()) {
+ // journal dirfragtree
+ inode_t *pi = diri->project_inode();
+ pi->version = diri->pre_dirty();
+ journal_dirty_inode(mdr, &le->metablob, diri);
+ } else {
+ mds->locker->mark_updated_scatterlock(&diri->dirfragtreelock);
+ mdr->ls->dirty_dirfrag_dirfragtree.push_back(&diri->item_dirty_dirfrag_dirfragtree);
+ mdr->add_updated_lock(&diri->dirfragtreelock);
+ }
/*
// filelock
dout(10) << "fragment_logged " << basedirfrag << " bits " << info.bits
<< " on " << *diri << dendl;
+ if (diri->is_auth())
+ diri->pop_and_dirty_projected_inode(mdr->ls);
+
+ mdr->apply(); // mark scatterlock
+
// store resulting frags
C_GatherBuilder gather(g_ceph_context, new C_MDC_FragmentStore(this, mdr));
mds->send_message_mds(notify, p->first);
}
- mdr->apply(); // mark scatterlock
mds->locker->drop_locks(mdr);
// unfreeze resulting frags
mds->locker->mark_updated_scatterlock(&in->filelock);
}
+ if (in->dirfragtreelock.is_dirty()) {
+ updated_scatterlocks.push_back(&in->dirfragtreelock);
+ mds->locker->mark_updated_scatterlock(&in->dirfragtreelock);
+ }
+
// adjust replica list
//assert(!in->is_replica(oldauth)); // not true on failed export
in->add_replica(oldauth, CInode::EXPORT_NONCE);
static const int STATE_DIRTY = (1<<2); // dirty due to THIS journal item, that is!
static const int STATE_NEW = (1<<3); // new directory
static const int STATE_IMPORTING = (1<<4); // importing directory
+ static const int STATE_DIRTYDFT = (1<<5); // dirty dirfragtree
//version_t dirv;
fnode_t fnode;
void mark_new() { state |= STATE_NEW; }
bool is_importing() { return state & STATE_IMPORTING; }
void mark_importing() { state |= STATE_IMPORTING; }
+ bool is_dirty_dft() { return state & STATE_DIRTYDFT; }
+ void mark_dirty_dft() { state |= STATE_DIRTYDFT; }
list<ceph::shared_ptr<fullbit> > &get_dfull() { return dfull; }
list<remotebit> &get_dremote() { return dremote; }
dirlump& add_import_dir(CDir *dir) {
// dirty=false would be okay in some cases
return add_dir(dir->dirfrag(), dir->get_projected_fnode(), dir->get_projected_version(),
- dir->is_dirty(), dir->is_complete(), false, true);
+ dir->is_dirty(), dir->is_complete(), false, true, dir->is_dirty_dft());
+ }
+ dirlump& add_fragmented_dir(CDir *dir, bool dirtydft) {
+ return add_dir(dir->dirfrag(), dir->get_projected_fnode(), dir->get_projected_version(),
+ false, false, false, false, dirtydft);
}
dirlump& add_dir(dirfrag_t df, fnode_t *pf, version_t pv, bool dirty,
- bool complete=false, bool isnew=false, bool importing=false) {
+ bool complete=false, bool isnew=false,
+ bool importing=false, bool dirty_dft=false) {
if (lump_map.count(df) == 0)
lump_order.push_back(df);
if (dirty) l.mark_dirty();
if (isnew) l.mark_new();
if (importing) l.mark_importing();
+ if (dirty_dft) l.mark_dirty_dft();
return l;
}
dout(10) << "EMetaBlob.replay clean fragstat on " << *dir << dendl;
}
}
+ if (lump.is_dirty_dft()) {
+ dout(10) << "EMetaBlob.replay dirty dirfragtree on " << *dir << dendl;
+ dir->state_set(CDir::STATE_DIRTYDFT);
+ mds->locker->mark_updated_scatterlock(&dir->inode->dirfragtreelock);
+ logseg->dirty_dirfrag_dirfragtree.push_back(&dir->inode->item_dirty_dirfrag_dirfragtree);
+ }
if (lump.is_new())
dir->mark_new(logseg);
if (lump.is_complete())