+void CDir::assimilate_dirty_rstat_inodes()
+{
+ dout(10) << "assimilate_dirty_rstat_inodes" << dendl;
+ for (elist<CInode*>::iterator p = dirty_rstat_inodes.begin_use_current();
+ !p.end(); ++p) {
+ CInode *in = *p;
+ inode_t *pi = in->project_inode();
+ pi->version = in->pre_dirty();
+
+ inode->mdcache->project_rstat_inode_to_frag(in, this, 0, 0);
+ }
+ dout(10) << "assimilate_dirty_rstat_inodes done" << dendl;
+}
+
+void CDir::assimilate_dirty_rstat_inodes_finish(Mutation *mut, EMetaBlob *blob)
+{
+ dout(10) << "assimilate_dirty_rstat_inodes_finish" << dendl;
+ elist<CInode*>::iterator p = dirty_rstat_inodes.begin_use_current();
+ while (!p.end()) {
+ CInode *in = *p;
+ CDentry *dn = in->get_projected_parent_dn();
+ ++p;
+
+ mut->auth_pin(in);
+ mut->add_projected_inode(in);
+
+ in->clear_dirty_rstat();
+ blob->add_primary_dentry(dn, true, in);
+ }
+ assert(dirty_rstat_inodes.empty());
+}
+
+
/****************************************
dout(20) << fg << " " << *dir << dendl;
fnode_t *pf = dir->get_projected_fnode();
- if (dir->is_auth())
+ if (dir->is_auth()) {
pf = dir->project_fnode();
+ // first push any inodes with dirty rstat into this dirfrag
+ dir->assimilate_dirty_rstat_inodes();
+ }
+
if (pf->accounted_rstat.version == pi->rstat.version) {
dout(20) << fg << " rstat " << pf->rstat << dendl;
dout(20) << fg << " accounted_rstat " << pf->accounted_rstat << dendl;
mut->add_projected_fnode(dir);
metablob->add_dir(dir, true);
mut->auth_pin(dir);
+
+ dir->assimilate_dirty_rstat_inodes_finish(mut, metablob);
}
}
// nested ---------------------------------------------------------------
+void MDCache::project_rstat_inode_to_frag(CInode *cur, CDir *parent, snapid_t first, int linkunlink)
+{
+ CDentry *parentdn = cur->get_projected_parent_dn();
+ inode_t *curi = cur->get_projected_inode();
+
+ dout(20) << " frag head is [" << parent->first << ",head] " << dendl;
+ dout(20) << " inode update is [" << first << "," << cur->last << "]" << dendl;
+
+ /*
+ * FIXME. this incompletely propagates rstats to _old_ parents
+ * (i.e. shortly after a directory rename). but we need full
+ * blown hard link backpointers to make this work properly...
+ */
+ snapid_t floor = parentdn->first;
+ dout(20) << " floor of " << floor << " from parent dn " << *parentdn << dendl;
+
+ if (cur->last >= floor)
+ project_rstat_inode_to_frag(*curi, MAX(first, floor), cur->last, parent, linkunlink);
+
+ for (set<snapid_t>::iterator p = cur->dirty_old_rstats.begin();
+ p != cur->dirty_old_rstats.end();
+ p++) {
+ old_inode_t& old = cur->old_inodes[*p];
+ if (*p >= floor)
+ project_rstat_inode_to_frag(old.inode, MAX(old.first, floor), *p, parent);
+ }
+ cur->dirty_old_rstats.clear();
+}
+
void MDCache::project_rstat_inode_to_frag(inode_t& inode, snapid_t ofirst, snapid_t last,
CDir *parent, int linkunlink)
// rstat
- if (primary_dn) {
+ if (!primary_dn) {
+ // don't update parent this pass
+ } else if (!parent->inode->nestlock.can_wrlock(-1)) {
+ dout(20) << " unwritable parent nestlock " << parent->inode->nestlock
+ << ", marking dirty rstat on " << *cur << dendl;
+ cur->mark_dirty_rstat();
+ mds->locker->mark_updated_scatterlock(&parent->inode->nestlock);
+ } else {
SnapRealm *prealm = parent->inode->find_snaprealm();
snapid_t follows = cfollows;
if (cur->first > first)
first = cur->first;
- dout(20) << " frag head is [" << parent->first << ",head] " << dendl;
- dout(20) << " inode update is [" << first << "," << cur->last << "]" << dendl;
+ project_rstat_inode_to_frag(cur, parent, first, linkunlink);
- /*
- * FIXME. this incompletely propagates rstats to _old_ parents
- * (i.e. shortly after a directory rename). but we need full
- * blow hard link backpointers to make this work properly...
- */
- snapid_t floor = parentdn->first;
- dout(20) << " floor of " << floor << " from parent dn " << *parentdn << dendl;
-
- if (cur->last >= floor)
- project_rstat_inode_to_frag(*curi, MAX(first, floor), cur->last, parent, linkunlink);
-
- for (set<snapid_t>::iterator p = cur->dirty_old_rstats.begin();
- p != cur->dirty_old_rstats.end();
- p++) {
- old_inode_t& old = cur->old_inodes[*p];
- if (*p >= floor)
- project_rstat_inode_to_frag(old.inode, MAX(old.first, floor), *p, parent);
- }
- cur->dirty_old_rstats.clear();
+ cur->clear_dirty_rstat();
}
bool stop = false;