]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
mds: mark scatterlock stale if any auth dirfrags appear stale
authorSage Weil <sage@newdream.net>
Wed, 3 Nov 2010 04:51:15 +0000 (21:51 -0700)
committerSage Weil <sage@newdream.net>
Wed, 3 Nov 2010 04:51:15 +0000 (21:51 -0700)
The auth needs to move to MIX_STALE for the same reasons a replica does:
if, on scatter, any dirfrags have an old accounted_*stat, the lock needs to
be marked stale (or updated... TODO!).

Signed-off-by: Sage Weil <sage@newdream.net>
src/mds/CInode.cc
src/mds/CInode.h
src/mds/Locker.cc

index f16ea68b265b424159770e7db8db797bcaa16a32..bd258ecc38d5ddec53080da4d7ffba642fb204ef 100644 (file)
@@ -1492,6 +1492,48 @@ void CInode::clear_dirty_scattered(int type)
 }
 
 
+/*
+ * when we initially scatter a lock, we need to check if any of the dirfrags
+ * have out of date accounted_rstat/fragstat.  if so, mark the lock stale.
+ */
+void CInode::start_scatter(ScatterLock *lock)
+{
+  dout(10) << "start_scatter " << *lock << " on " << *this << dendl;
+  assert(is_auth());
+  inode_t *pi = get_projected_inode();
+
+  for (map<frag_t,CDir*>::iterator p = dirfrags.begin();
+       p != dirfrags.end();
+       p++) {
+    frag_t fg = p->first;
+    CDir *dir = p->second;
+    fnode_t *pf = dir->get_projected_fnode();
+    dout(20) << fg << " " << *dir << dendl;
+
+    switch (lock->get_type()) {
+    case CEPH_LOCK_IFILE:
+      if (pf->fragstat.version < pi->dirstat.version) {
+       dout(10) << fg << " stale dirstat on " << *dir << dendl;
+       lock->set_stale();
+      }
+      break;
+
+    case CEPH_LOCK_INEST:
+      if (pf->rstat.version < pi->rstat.version) {
+       dout(10) << fg << " stale rstat on " << *dir << dendl;
+       lock->set_stale();
+      }
+      break;
+    }
+  }
+}
+
+/*
+ * when we gather a lock, we need to assimilate dirfrag changes into the inode
+ * state.  it's possible we can't update the dirfrag accounted_rstat/fragstat
+ * because the frag is auth and frozen, or that the replica couldn't for the same
+ * reason.  hopefully it will get updated the next time the lock cycles.
+ */
 void CInode::finish_scatter_gather_update(int type)
 {
   dout(10) << "finish_scatter_gather_update " << type << " on " << *this << dendl;
index a7932fe911d2b86e9470f325fcf1b4a9ed5c12c3..5ca8bf3d430a8556b841d62563181bce62b4cb72 100644 (file)
@@ -707,6 +707,8 @@ public:
   void _finish_frag_update(CDir *dir, Mutation *mut);
 
   void clear_dirty_scattered(int type);
+
+  void start_scatter(ScatterLock *lock);
   void finish_scatter_gather_update(int type);
   void finish_scatter_gather_update_accounted(int type, Mutation *mut, EMetaBlob *metablob);
 
index c66779f883fccea74925709c3bb50504bb67645b..7ee23c86ba9afa12a532d68e2c01bdca3c3b5d3f 100644 (file)
@@ -560,6 +560,7 @@ void Locker::eval_gather(SimpleLock *lock, bool first, bool *pneed_issue, list<C
       case LOCK_TSYN_MIX:
       case LOCK_SYNC_MIX:
       case LOCK_EXCL_MIX:
+       in->start_scatter((ScatterLock *)lock);
        if (lock->get_parent()->is_replicated()) {
          bufferlist softdata;
          lock->encode_locked_state(softdata);
@@ -3673,11 +3674,13 @@ void Locker::scatter_mix(ScatterLock *lock, bool *need_issue)
   assert(lock->is_stable());
 
   if (lock->get_state() == LOCK_LOCK) {
+    in->start_scatter(lock);
     if (in->is_replicated()) {
       // data
+
       bufferlist softdata;
       lock->encode_locked_state(softdata);
-      
+
       // bcast to replicas
       send_lock_message(lock, LOCK_AC_MIX, softdata);
     }
@@ -3731,6 +3734,7 @@ void Locker::scatter_mix(ScatterLock *lock, bool *need_issue)
     if (gather)
       lock->get_parent()->auth_pin(lock);
     else {
+      in->start_scatter(lock);
       if (lock->is_stale())
         lock->set_state(LOCK_MIX_STALE);
       else