]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
mds: journal dirfrag accounted_{r,frag}stat on inode update
authorSage Weil <sage@newdream.net>
Thu, 9 Sep 2010 22:53:10 +0000 (15:53 -0700)
committerSage Weil <sage@newdream.net>
Thu, 9 Sep 2010 23:40:44 +0000 (16:40 -0700)
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
src/mds/CInode.h

index 0f0fd4fb06d414d9da3b7edba0bb17856a3dbc80..e5ef0527e0e2f76d0378c0312946f9c9a5ae65a1 100644 (file)
 
 #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;
index 3b162b3baa0895d74bdc3ac0ae4efb4147c535cf..8bd340dbd695cb1e2f5f70cff0e18dffaceb8e51 100644 (file)
@@ -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);