]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
* fixed scatter writebehind
authorsageweil <sageweil@29311d96-e01e-0410-9327-a35deaab8ce9>
Tue, 3 Jul 2007 22:56:48 +0000 (22:56 +0000)
committersageweil <sageweil@29311d96-e01e-0410-9327-a35deaab8ce9>
Tue, 3 Jul 2007 22:56:48 +0000 (22:56 +0000)
git-svn-id: https://ceph.svn.sf.net/svnroot/ceph@1471 29311d96-e01e-0410-9327-a35deaab8ce9

branches/sage/cephmds2/TODO
branches/sage/cephmds2/mds/Locker.cc
branches/sage/cephmds2/mds/Locker.h
branches/sage/cephmds2/mds/MDCache.cc
branches/sage/cephmds2/mds/MDCache.h
branches/sage/cephmds2/mds/Server.cc

index 3ec5548339cf3ed5b567f2767121f235d44aec10..b08cfdaffd15c42f4c55390246b2b9dd3c969090 100644 (file)
@@ -8,6 +8,12 @@ some smallish projects:
  - xml import/export?  
  - ?
 
+- pg monitor service
+ - to support statfs?
+ - general pg health
+ - some sort of (throttled) osd status reporting
+ - dynamic pg creation (eventually!)
+
 - SimpleMessenger
  - clean up/merge Messenger/Dispatcher interfaces
  - auto close idle connections
@@ -17,10 +23,6 @@ some smallish projects:
 - generalize monitor client?
  - throttle message resend attempts
 
-- paxos layer work
- - integrate leasing into paxos framework
- - carefully interface design...
-
 
 code cleanup
 - endian portability
@@ -29,7 +31,7 @@ code cleanup
 
 general kernel planning
 - soft consistency on lookup?
-
+- accurate reconstruction of (syscall) path?
 
 
 
@@ -48,66 +50,11 @@ sage mds
 
 - unlink needs to journal on witnesses (probably), since unlinked inodes may be in those journals
 
-/- make locks auth_pin for unstable states.
-/  - can locker *_eval() starve freezing?
-
-/- fix rename to delay the _apply.
-/  - need to fix locking vs migration first.
-/- rename_prep should create a subtree (auth,auth) so that cache expires are routed properly
-
-- then, mtimes:
-/  - avoid migration race concern (on auth).
-/  - writeback and dirty on gather.
-/    - cleaned up pv/pi makes writebehind play nice with concurrent updates.
-/    - should pin lock in LOCK state? (acdtually, gather)
-/  - scatterlock 'updated' flag.  
-    - on replica, clear only on sync | rescatter.
-  - make sure "dirty" scatterlock prevents journal expire.
-    - EMetaBlob map<inodeno_t,utime_t> dirty_scatter;
-      - mtime must be greater, or scatterlock must be !updated.
-
-/- fix slave op commit/abort logic:
-/ - recovering node needs to know what stray prepare ops committed
-/   - include with import_map
-/   - wait for explicit commit/abort from peer.
-/ - surviving node needs to 
-/   - wait for log to flush (commits to finish), then
-/   - for uncommitted master requests, 
-/     - remove failed from witnesses, waiting_on_slave, and
-/     - redispatch
-/     - somehow wait for needed peers to recover...
-/   - for uncommitted slave requests,
-/     - include with import_map, wait for explicit commit/abort from peer.
-
-/- make unlink/link behave with commit/abort recovery
-
-/- new thrashing test with
-/ - link, unlink, and rename (lots of hard links!)
-/ - directory renames
-
-- fix up writeback of dir inode mtime
-- revisit wrlocks, dir inode mtime updates.  esp in rename.
-  - if auth, pin and be happy.  decide early.
-  - make no attempt to dirty inodes until a gather
-/  - pin scattered inodes
-  - mtime will always get journaled...
-  -> so, just make sure v/pv/dirtyness is sane on recovery...
-  -> scatterlock should recover into scatter state, or whatever...
-
-
-- Q: locker vs migration
-  - maybe unstable lock states should auth_pin.  would simplify migration logic, and probably avoid a number of bugs.  basically, the freeze would have to wait for any in-progress lock gathers (not that long!).
-  - ...but does it play nice with wrlock?  and unfortuantely auth_pinning wrlocks would kill performance on updates at dir delegation points.
-  - ????
-
 - stray reintegration
 - stray purge on shutdown
   - need to export stray crap to another mds..
 - verify stray is empty on shutdown
 
-/- roll EAlloc into EMetaBlob (and maybe Purge)
-
 - dir complete flag on migration.. does it go into the EMetaBlob too?  can it be safely dropped?
 
 - journal+recovery
index d268fbc7779d8ea8b27fa5bd25f7676a726e58f9..2e12933beec9fc1f324183dc1ab97982809aea1d 100644 (file)
@@ -1422,14 +1422,17 @@ void Locker::scatter_eval_gather(ScatterLock *lock)
     // glockc -> lock?
     else if (lock->get_state() == LOCK_GLOCKC &&
             !lock->is_gathering() &&
-            !lock->is_wrlocked() &&
-            !lock->is_updated()) {
-      dout(7) << "scatter_eval finished lock gather/un-wrlock on " << *lock
+            !lock->is_wrlocked()) {
+      if (lock->is_updated()) {
+       scatter_writebehind(lock);
+      } else {
+       dout(7) << "scatter_eval finished lock gather/un-wrlock on " << *lock
              << " on " << *lock->get_parent() << endl;
-      lock->set_state(LOCK_LOCK);
-      //lock->get_parent()->put(CInode::PIN_SCATTERED);
-      lock->finish_waiters(ScatterLock::WAIT_XLOCK|ScatterLock::WAIT_STABLE);
-      lock->get_parent()->auth_unpin();
+       lock->set_state(LOCK_LOCK);
+       //lock->get_parent()->put(CInode::PIN_SCATTERED);
+       lock->finish_waiters(ScatterLock::WAIT_XLOCK|ScatterLock::WAIT_STABLE);
+       lock->get_parent()->auth_unpin();
+      }
     }
 
     // gSyncL -> sync?
@@ -1471,13 +1474,16 @@ void Locker::scatter_eval_gather(ScatterLock *lock)
     else if ((lock->get_state() == LOCK_GTEMPSYNCC ||
              lock->get_state() == LOCK_GTEMPSYNCL) &&
             !lock->is_gathering() &&
-            !lock->is_wrlocked() &&
-            !lock->is_updated()) {
-      dout(7) << "scatter_eval finished tempsync gather/un-wrlock on " << *lock
-             << " on " << *lock->get_parent() << endl;
-      lock->set_state(LOCK_TEMPSYNC);
-      lock->finish_waiters(ScatterLock::WAIT_RD|ScatterLock::WAIT_STABLE);
-      lock->get_parent()->auth_unpin();
+            !lock->is_wrlocked()) {
+      if (lock->is_updated()) {
+       scatter_writebehind(lock);
+      } else {
+       dout(7) << "scatter_eval finished tempsync gather/un-wrlock on " << *lock
+               << " on " << *lock->get_parent() << endl;
+       lock->set_state(LOCK_TEMPSYNC);
+       lock->finish_waiters(ScatterLock::WAIT_RD|ScatterLock::WAIT_STABLE);
+       lock->get_parent()->auth_unpin();
+      }
     }
 
 
@@ -1487,6 +1493,32 @@ void Locker::scatter_eval_gather(ScatterLock *lock)
   }
 }
 
+void Locker::scatter_writebehind(ScatterLock *lock)
+{
+  CInode *in = (CInode*)lock->get_parent();
+  dout(10) << "scatter_writebehind on " << *lock << " on " << *in << endl;
+
+  // journal write-behind.
+  inode_t *pi = in->project_inode();
+  pi->version = in->pre_dirty();
+  
+  EUpdate *le = new EUpdate("dir.mtime writebehind");
+  le->metablob.add_dir_context(in->get_parent_dn()->get_dir());
+  le->metablob.add_primary_dentry(in->get_parent_dn(), true, 0, pi);
+  
+  mds->mdlog->submit_entry(le);
+  mds->mdlog->wait_for_sync(new C_Locker_ScatterWB(this, lock));
+}
+
+void Locker::scatter_writebehind_finish(ScatterLock *lock)
+{
+  CInode *in = (CInode*)lock->get_parent();
+  dout(10) << "scatter_writebehind_finish on " << *lock << " on " << *in << endl;
+  in->pop_and_dirty_projected_inode();
+  lock->clear_updated();
+  scatter_eval_gather(lock);
+}
+
 void Locker::scatter_eval(ScatterLock *lock)
 {
   dout(10) << "scatter_eval " << *lock << " on " << *lock->get_parent() << endl;
@@ -1798,25 +1830,7 @@ void Locker::handle_scatter_lock(ScatterLock *lock, MLock *m)
       dout(7) << "handle_scatter_lock " << *lock << " on " << *lock->get_parent()
              << " from " << from << ", last one" 
              << endl;
-
-      if (lock->is_updated()) {
-       // journal write-behind.
-       CInode *in = (CInode*)lock->get_parent();
-       inode_t *pi = in->project_inode();
-       pi->version = in->pre_dirty();
-       
-       EUpdate *le = new EUpdate("dir.mtime writebehind");
-       le->metablob.add_dir_context(in->get_parent_dn()->get_dir());
-       le->metablob.add_primary_dentry(in->get_parent_dn(), true, 0, pi);
-       
-       mds->mdlog->submit_entry(le);
-       mds->mdlog->wait_for_sync(new C_Locker_GatherWB(this, lock));
-      }
-      else {
-       // WARNING: this is non-optimal, but simplest.
-       // just block the gather until we flush the writeback to the journal.
-       scatter_eval_gather(lock);
-      }
+      scatter_eval_gather(lock);
     }
     break;
 
@@ -1836,14 +1850,6 @@ void Locker::handle_scatter_lock(ScatterLock *lock, MLock *m)
   delete m;
 }
 
-void Locker::scatter_gather_writebehind(ScatterLock *lock)
-{
-  CInode *in = (CInode*)lock->get_parent();
-  dout(10) << "scatter_gather_writebehind on " << *lock << " on " << *in << endl;
-  in->pop_and_dirty_projected_inode();
-  lock->clear_updated();
-  scatter_eval_gather(lock);
-}
 
 
 
index f630acb79f77a4881383c7c298f9b2d5313bdafd..4aa5c22753b6d35ef398e7b45ea5ea544030860f 100644 (file)
@@ -122,16 +122,17 @@ protected:
   bool scatter_wrlock_start(ScatterLock *lock, MDRequest *mdr);
   void scatter_wrlock_finish(ScatterLock *lock, MDRequest *mdr);
 
-  class C_Locker_GatherWB : public Context {
+  void scatter_writebehind(ScatterLock *lock);
+  class C_Locker_ScatterWB : public Context {
     Locker *locker;
     ScatterLock *lock;
   public:
-    C_Locker_GatherWB(Locker *l, ScatterLock *sl) : locker(l), lock(sl) {}
+    C_Locker_ScatterWB(Locker *l, ScatterLock *sl) : locker(l), lock(sl) {}
     void finish(int r) { 
-      locker->scatter_gather_writebehind(lock); 
+      locker->scatter_writebehind_finish(lock); 
     }
   };
-  void scatter_gather_writebehind(ScatterLock *lock);
+  void scatter_writebehind_finish(ScatterLock *lock);
 
   // local
 protected:
index d031650d2f1ff6437ec15da05a5a08c6edf3d8b5..e6e0a482815448020a914ceb137d23d03194c996 100644 (file)
@@ -393,6 +393,8 @@ void MDCache::adjust_subtree_auth(CDir *dir, pair<int,int> auth)
 
     // i am now the subtree root.
     root = dir;
+
+    eval_subtree_root(dir);
   }
 
   // adjust export pins
@@ -402,17 +404,6 @@ void MDCache::adjust_subtree_auth(CDir *dir, pair<int,int> auth)
        ++p) 
     adjust_export_state(*p);
   
-  // evaluate subtree inode dirlock?
-  //  (we should scatter the dirlock on subtree bounds)
-  if (dir->inode->is_auth() &&
-      dir->inode->dirlock.is_stable()) {
-    // force the issue a bit
-    if (!dir->inode->is_frozen())
-      mds->locker->scatter_eval(&dir->inode->dirlock);
-    else
-      mds->locker->try_scatter_eval(&dir->inode->dirlock);  // ** may or may not be auth_pinned **
-  }
-
   show_subtrees();
 }
 
@@ -463,7 +454,6 @@ void MDCache::try_subtree_merge(CDir *dir)
        p != oldbounds.end();
        ++p) 
     try_subtree_merge_at(*p);
-  
 }
 
 void MDCache::try_subtree_merge_at(CDir *dir)
@@ -493,11 +483,27 @@ void MDCache::try_subtree_merge_at(CDir *dir)
     // we are no longer a subtree or bound
     subtrees.erase(dir);
     subtrees[parent].erase(dir);
+
+    eval_subtree_root(dir);
   } 
 
   show_subtrees(15);
 }
 
+void MDCache::eval_subtree_root(CDir *dir)
+{
+  // evaluate subtree inode dirlock?
+  //  (we should scatter the dirlock on subtree bounds)
+  if (dir->inode->is_auth() &&
+      dir->inode->dirlock.is_stable()) {
+    // force the issue a bit
+    if (!dir->inode->is_frozen())
+      mds->locker->scatter_eval(&dir->inode->dirlock);
+    else
+      mds->locker->try_scatter_eval(&dir->inode->dirlock);  // ** may or may not be auth_pinned **
+  }  
+}
+
 
 void MDCache::adjust_bounded_subtree_auth(CDir *dir, set<CDir*>& bounds, pair<int,int> auth)
 {
@@ -3590,12 +3596,12 @@ void MDCache::open_remote_ino_2(inodeno_t ino,
   while (1) {
     // inode?
     dout(10) << " " << i << ": " << anchortrace[i-1] << endl;
-    CInode *in = get_inode(anchortrace[i-1].ino);
+    in = get_inode(anchortrace[i-1].ino);
     if (in) break;
     i--;
     if (!i) {
-      CInode *in = get_inode(anchortrace[i].dirfrag.ino);
-      assert(in);
+      in = get_inode(anchortrace[i].dirfrag.ino);
+      assert(in);  // actually, we may need to open the root or a foreign stray inode, here.
       break;
     }
   }
index 7abbf4e387b2da845f8997eca9310c2818e2ef38..845c6917dc601c038c5d7fe838383b21d69ab39f 100644 (file)
@@ -239,6 +239,7 @@ public:
   void adjust_export_state(CDir *dir);
   void try_subtree_merge(CDir *root);
   void try_subtree_merge_at(CDir *root);
+  void eval_subtree_root(CDir *dir);
   CDir *get_subtree_root(CDir *dir);
   void remove_subtree(CDir *dir);
   void get_subtree_bounds(CDir *root, set<CDir*>& bounds);
index 3f263f1318ae6296306ffa94fb1960bd59381042..b5069df5ddd995310c5e8fbff94f074ff40229d8 100644 (file)
@@ -1222,6 +1222,8 @@ version_t Server::predirty_dn_diri(MDRequest *mdr, CDentry *dn, EMetaBlob *blob)
     // journal the mtime change anyway.
     inode_t *ji = blob->add_primary_dentry(diri->get_parent_dn(), true);    
     ji->ctime = ji->mtime = mdr->now;
+
+    dout(10) << "predirty_dn_diri (non-auth) ctime/mtime " << mdr->now << " on " << *diri << endl;
     
     blob->add_dirtied_inode_mtime(diri->ino(), mdr->now);
   }
@@ -1244,10 +1246,10 @@ void Server::dirty_dn_diri(CDentry *dn, version_t dirpv, utime_t mtime)
     diri->pop_and_dirty_projected_inode();
     dout(10) << "dirty_dn_diri ctime/mtime " << mtime << " v " << diri->inode.version << " on " << *diri << endl;
   } else {
-    dout(10) << "dirty_dn_diri ctime/mtime " << mtime << " (non-dirty) on " << *diri << endl;
     // dirlock scatterlock will propagate the update.
     diri->inode.ctime = diri->inode.mtime = mtime;
     diri->dirlock.set_updated();
+    dout(10) << "dirty_dn_diri (non-dirty) ctime/mtime " << mtime << " on " << *diri << endl;
   }
 }