From 89af63e3db3ba3f526fa6730c4bcafeb841d435a Mon Sep 17 00:00:00 2001 From: Sage Weil Date: Thu, 9 Sep 2010 15:53:10 -0700 Subject: [PATCH] mds: journal dirfrag accounted_{r,frag}stat on inode update When the inode sucks in the dir's updated frag info, we need to journal the dirfrag update as well. This ensures that any subsequent changes in the dirfrag will be reflected by the difference between rstat and accounted_rstat from the perspective of the journal contents (in case we fail/recover during that process). --- src/mds/CInode.cc | 110 ++++++++++++++++++++++++++++++++++++++-------- src/mds/CInode.h | 2 + 2 files changed, 93 insertions(+), 19 deletions(-) diff --git a/src/mds/CInode.cc b/src/mds/CInode.cc index 0f0fd4fb06d41..e5ef0527e0e2f 100644 --- a/src/mds/CInode.cc +++ b/src/mds/CInode.cc @@ -20,8 +20,11 @@ #include "MDS.h" #include "MDCache.h" +#include "MDLog.h" #include "Locker.h" +#include "events/EUpdate.h" + #include "osdc/Objecter.h" #include "snap.h" @@ -991,13 +994,14 @@ void CInode::encode_lock_state(int type, bufferlist& bl) frag_t fg = p->first; CDir *dir = p->second; if (is_auth() || dir->is_auth()) { + fnode_t *pf = dir->get_projected_fnode(); dout(15) << fg << " " << *dir << dendl; - dout(20) << fg << " fragstat " << dir->fnode.fragstat << dendl; - dout(20) << fg << " accounted_fragstat " << dir->fnode.accounted_fragstat << dendl; + dout(20) << fg << " fragstat " << pf->fragstat << dendl; + dout(20) << fg << " accounted_fragstat " << pf->accounted_fragstat << dendl; ::encode(fg, tmp); ::encode(dir->first, tmp); - ::encode(dir->fnode.fragstat, tmp); - ::encode(dir->fnode.accounted_fragstat, tmp); + ::encode(pf->fragstat, tmp); + ::encode(pf->accounted_fragstat, tmp); n++; } } @@ -1018,14 +1022,15 @@ void CInode::encode_lock_state(int type, bufferlist& bl) frag_t fg = p->first; CDir *dir = p->second; if (is_auth() || dir->is_auth()) { + fnode_t *pf = dir->get_projected_fnode(); dout(10) << fg << " " << *dir << dendl; - dout(10) << fg << " " << dir->fnode.rstat << dendl; - dout(10) << fg << " " << dir->fnode.rstat << dendl; + dout(10) << fg << " " << pf->rstat << dendl; + dout(10) << fg << " " << pf->rstat << dendl; dout(10) << fg << " " << dir->dirty_old_rstat << dendl; ::encode(fg, tmp); ::encode(dir->first, tmp); - ::encode(dir->fnode.rstat, tmp); - ::encode(dir->fnode.accounted_rstat, tmp); + ::encode(pf->rstat, tmp); + ::encode(pf->accounted_rstat, tmp); ::encode(dir->dirty_old_rstat, tmp); n++; } @@ -1053,6 +1058,18 @@ void CInode::encode_lock_state(int type, bufferlist& bl) } } +struct C_Inode_FragUpdate : public Context { + CInode *in; + CDir *dir; + Mutation *mut; + + C_Inode_FragUpdate(CInode *i, CDir *d, Mutation *m) : in(i), dir(d), mut(m) {} + void finish(int r) { + in->_finish_frag_update(dir, mut); + } +}; + + void CInode::decode_lock_state(int type, bufferlist& bl) { bufferlist::iterator p = bl.begin(); @@ -1175,12 +1192,35 @@ void CInode::decode_lock_state(int type, bufferlist& bl) << " on " << *dir << dendl; dir->first = fgfirst; - dout(10) << fg << " setting accounted_fragstat and setting dirty bit" << dendl; fnode_t *pf = dir->get_projected_fnode(); - pf->accounted_fragstat = fragstat; - pf->fragstat.version = fragstat.version; - assert(pf->fragstat == fragstat); - dir->_set_dirty_flag(); // bit of a hack + + if (pf->accounted_fragstat.version != fragstat.version) { + dout(10) << fg << " journaling accounted_fragstat update v" << fragstat.version << dendl; + + MDLog *mdlog = mdcache->mds->mdlog; + Mutation *mut = new Mutation; + mut->ls = mdlog->get_current_segment(); + EUpdate *le = new EUpdate(mdlog, "lock ifile accounted_fragstat update"); + mdlog->start_entry(le); + + pf = dir->project_fnode(); + pf->version = dir->pre_dirty(); + pf->accounted_fragstat = fragstat; + pf->fragstat.version = fragstat.version; + mut->add_projected_fnode(dir); + + le->metablob.add_dir_context(dir); + le->metablob.add_dir(dir, true); + + assert(!dir->is_frozen()); + mut->auth_pin(dir); + + mdlog->submit_entry(le, new C_Inode_FragUpdate(this, dir, mut)); + } else { + dout(10) << fg << " accounted_fragstat unchanged at v" << fragstat.version << dendl; + assert(pf->fragstat == fragstat); + assert(pf->accounted_fragstat == fragstat); + } } } } @@ -1231,13 +1271,36 @@ void CInode::decode_lock_state(int type, bufferlist& bl) dout(10) << fg << " first " << dir->first << " -> " << fgfirst << " on " << *dir << dendl; dir->first = fgfirst; - - dout(10) << fg << " resetting accounted_rstat and setting dirty bit" << dendl; + fnode_t *pf = dir->get_projected_fnode(); - pf->accounted_rstat = rstat; - pf->rstat.version = rstat.version; - dir->dirty_old_rstat.clear(); - dir->_set_dirty_flag(); // bit of a hack, FIXME? + + if (pf->accounted_rstat.version != rstat.version) { + dout(10) << fg << " journaling accounted_rstat update v" << rstat.version << dendl; + + MDLog *mdlog = mdcache->mds->mdlog; + Mutation *mut = new Mutation; + mut->ls = mdlog->get_current_segment(); + EUpdate *le = new EUpdate(mdlog, "lock inest accounted_rstat update"); + mdlog->start_entry(le); + + pf = dir->project_fnode(); + pf->version = dir->pre_dirty(); + pf->accounted_rstat = rstat; + pf->rstat.version = rstat.version; + mut->add_projected_fnode(dir); + + le->metablob.add_dir_context(dir); + le->metablob.add_dir(dir, true); + + assert(!dir->is_frozen()); + mut->auth_pin(dir); + + mdlog->submit_entry(le, new C_Inode_FragUpdate(this, dir, mut)); + } else { + dout(10) << fg << " accounted_rstat unchanged at v" << rstat.version << dendl; + assert(pf->rstat == rstat); + assert(pf->accounted_rstat == rstat); + } } } } @@ -1269,6 +1332,15 @@ void CInode::decode_lock_state(int type, bufferlist& bl) } } +void CInode::_finish_frag_update(CDir *dir, Mutation *mut) +{ + dout(10) << "_finish_frag_update on " << *dir << dendl; + mut->apply(); + mut->cleanup(); + delete mut; +} + + void CInode::clear_dirty_scattered(int type) { dout(10) << "clear_dirty_scattered " << type << " on " << *this << dendl; diff --git a/src/mds/CInode.h b/src/mds/CInode.h index 3b162b3baa089..8bd340dbd695c 100644 --- a/src/mds/CInode.h +++ b/src/mds/CInode.h @@ -601,6 +601,8 @@ public: void encode_lock_state(int type, bufferlist& bl); void decode_lock_state(int type, bufferlist& bl); + void _finish_frag_update(CDir *dir, Mutation *mut); + void clear_dirty_scattered(int type); void finish_scatter_gather_update(int type); -- 2.39.5