]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
bugfixes, EOpen works with logsegments
authorsageweil <sageweil@29311d96-e01e-0410-9327-a35deaab8ce9>
Fri, 5 Oct 2007 15:44:21 +0000 (15:44 +0000)
committersageweil <sageweil@29311d96-e01e-0410-9327-a35deaab8ce9>
Fri, 5 Oct 2007 15:44:21 +0000 (15:44 +0000)
* try_to_expire does teh right thing with open files
* dirlock on base inodes never scattered
* trim more aggressive about base inodes when max==0

git-svn-id: https://ceph.svn.sf.net/svnroot/ceph@1886 29311d96-e01e-0410-9327-a35deaab8ce9

14 files changed:
branches/sage/mds/TODO
branches/sage/mds/mds/CInode.cc
branches/sage/mds/mds/CInode.h
branches/sage/mds/mds/Locker.cc
branches/sage/mds/mds/LogSegment.h
branches/sage/mds/mds/MDCache.cc
branches/sage/mds/mds/ScatterLock.h
branches/sage/mds/mds/Server.cc
branches/sage/mds/mds/events/EAnchor.h
branches/sage/mds/mds/events/EAnchorClient.h
branches/sage/mds/mds/events/EOpen.h
branches/sage/mds/mds/events/EUpdate.h
branches/sage/mds/mds/journal.cc
branches/sage/mds/mds/mdstypes.h

index 256a7cc134f8ab403fe62371b2df155da67ce5c3..a857bd7195ad4bf72527059dddd05e530f8eee18 100644 (file)
@@ -84,6 +84,9 @@ mds bugs
 
 - verify once-per-segment jouranl context is working...
 
+- open file rejournaling vs capped log...
+  - open files vs shutdown in general!  need to export any caps on replicated metadata
+
 mds cleanup
 - fix freeze_* interface to pull waiters _outside_
 - get rid of replicate objects for replicate_to .. encode to bufferlists directly
@@ -93,6 +96,8 @@ mds
   - fix path_traverse
   - fix reconnect/rejoin open file weirdness
 
+- export caps to auth on unlinked inodes
+
 - stray reintegration
 - stray purge on shutdown
   - need to export stray crap to another mds..
index d447d6f0d1f368b70328b9cfda19bbdde788cb02..05ad442aa83a7978afaceefb8a3365fc8afa40f8 100644 (file)
@@ -64,8 +64,7 @@ ostream& operator<<(ostream& out, CInode& in)
   
   out << " v" << in.get_version();
 
-  if (in.state_test(CInode::STATE_AMBIGUOUSAUTH))
-    out << " AMBIGAUTH";
+  if (in.state_test(CInode::STATE_AMBIGUOUSAUTH)) out << " AMBIGAUTH";
   if (in.is_freezing_inode()) out << " FREEZING";
   if (in.is_frozen_inode()) out << " FROZEN";
 
@@ -607,10 +606,15 @@ bool CInode::is_freezing()
 
 void CInode::add_waiter(int tag, Context *c) 
 {
+  dout(10) << "add_waiter tag " << tag 
+          << " !ambig " << !state_test(STATE_AMBIGUOUSAUTH)
+          << " !frozen " << !is_frozen_inode()
+          << " !freezing " << !is_freezing_inode()
+          << dendl;
   // wait on the directory?
   //  make sure its not the inode that is explicitly ambiguous|freezing|frozen
-  if ((tag & WAIT_SINGLEAUTH) && !state_test(STATE_AMBIGUOUSAUTH) ||
-      (tag & WAIT_UNFREEZE) && !state_test(STATE_FROZEN|STATE_FREEZING)) {
+  if (((tag & WAIT_SINGLEAUTH) && !state_test(STATE_AMBIGUOUSAUTH)) ||
+      ((tag & WAIT_UNFREEZE) && !is_frozen_inode() && !is_freezing_inode())) {
     parent->dir->add_waiter(tag, c);
     return;
   }
index cce2b43058f568a19c574d6546f1d8baa5ae7af1..acb600ea04afff4d2337646010d083894e292744 100644 (file)
@@ -104,7 +104,6 @@ class CInode : public MDSCacheObject {
   static const int WAIT_UNANCHORED  = (1<<3);
   static const int WAIT_CAPS        = (1<<4);
   static const int WAIT_FROZEN      = (1<<5);
-  static const int WAIT_UNFREEZE    = (1<<6);
   
   static const int WAIT_AUTHLOCK_OFFSET = 5;
   static const int WAIT_LINKLOCK_OFFSET = 5 + SimpleLock::WAIT_BITS;
@@ -197,7 +196,7 @@ protected:
   // LogSegment xlists i (may) belong to
   xlist<CInode*>::item xlist_dirty;
 public:
-  xlist<CInode*>::item xlist_opened_files;
+  xlist<CInode*>::item xlist_open_file;
   xlist<CInode*>::item xlist_dirty_inode_mtime;
   xlist<CInode*>::item xlist_purging_inode;
 
@@ -228,7 +227,7 @@ private:
     stickydir_ref(0),
     parent(0), force_auth(CDIR_AUTH_DEFAULT),
     replica_caps_wanted(0),
-    xlist_dirty(this), xlist_opened_files(this), 
+    xlist_dirty(this), xlist_open_file(this), 
     xlist_dirty_inode_mtime(this), xlist_purging_inode(this),
     auth_pins(0), nested_auth_pins(0),
     versionlock(this, LOCK_OTYPE_IVERSION, WAIT_VERSIONLOCK_OFFSET),
@@ -257,6 +256,7 @@ private:
   
   bool is_root() { return inode.ino == MDS_INO_ROOT; }
   bool is_stray() { return MDS_INO_IS_STRAY(inode.ino); }
+  bool is_base() { return inode.ino < MDS_INO_BASE; }
 
   // note: this overloads MDSCacheObject
   bool is_ambiguous_auth() {
index ad5d021b612d700f3a2da3210736ea00e3de2632..5a605fb3ecc9e9c9bd7e54c9ea978779f9ad20fc 100644 (file)
@@ -720,6 +720,8 @@ void Locker::handle_client_file_caps(MClientFileCaps *m)
   if (cap->is_null()) {
     dout(7) << " cap for client" << client << " is now null, removing from " << *in << dendl;
     in->remove_client_cap(client);
+    if (!in->is_any_caps()) 
+      in->xlist_open_file.remove_myself();  // unpin logsegment
     if (!in->is_auth())
       request_inode_file_caps(in);
 
@@ -1594,7 +1596,8 @@ void Locker::scatter_eval(ScatterLock *lock)
   assert(lock->get_parent()->is_auth());
   assert(lock->is_stable());
 
-  if (((CInode*)lock->get_parent())->has_subtree_root_dirfrag()) {
+  CInode *in = (CInode*)lock->get_parent();
+  if (in->has_subtree_root_dirfrag() && !in->is_base()) {
     // i _should_ be scattered.
     if (!lock->is_rdlocked() &&
        !lock->is_xlocked()) {
index 58511c66db9049d35462e3863c5a2f89ee54a0dd..7579add569d506eef7cb6d8079db7f8b3512ca69 100644 (file)
@@ -37,7 +37,7 @@ class LogSegment {
   xlist<CInode*>  dirty_inodes;
   xlist<CDentry*> dirty_dentries;
 
-  xlist<CInode*>  opened_files;
+  xlist<CInode*>  open_files;
   xlist<CInode*>  dirty_inode_mtimes;
 
   //xlist<CInode*>  purging_inodes;
index 646f719327ba98bf7e344adf73a1f78e86e4b929..df5cd916df0a76f9e67e28df7eb83ab08ef3b2f4 100644 (file)
@@ -2895,6 +2895,22 @@ bool MDCache::trim(int max)
       p = n;
     } 
   }
+  if (max == 0) {
+    for (set<CInode*>::iterator p = base_inodes.begin();
+        p != base_inodes.end();
+        ++p) {
+      CInode *in = *p;
+      list<CDir*> ls;
+      in->get_dirfrags(ls);
+      for (list<CDir*>::iterator p = ls.begin(); p != ls.end(); ++p) {
+       CDir *dir = *p;
+       if (dir->get_num_ref() == 0) 
+         trim_dirfrag(dir, 0, expiremap);
+      }
+      if (in->get_num_ref() == 0)
+       trim_inode(0, in, 0, expiremap);
+    }
+  }
 
   // send!
   send_expire_messages(expiremap);
@@ -6039,7 +6055,7 @@ void MDCache::show_subtrees(int dbl)
     return;  // i won't print anything.
 
   if (subtrees.empty()) {
-    dout(dbl) << "no subtrees" << dendl;
+    dout(dbl) << "show_subtrees - no subtrees" << dendl;
     return;
   }
 
@@ -6049,7 +6065,8 @@ void MDCache::show_subtrees(int dbl)
        p != base_inodes.end();
        ++p) 
     (*p)->get_dirfrags(basefrags);
-  dout(15) << "show_subtrees, base dirfrags " << basefrags << dendl;
+  //dout(15) << "show_subtrees, base dirfrags " << basefrags << dendl;
+  dout(15) << "show_subtrees" << dendl;
 
   // queue stuff
   list<pair<CDir*,int> > q;
index f93034d0b8829b164d1bec5b96609835cddeb233..0645622aee56d790504358398c79225264c88467 100644 (file)
@@ -166,6 +166,8 @@ public:
       out << " x=" << get_xlocked_by();
     if (is_wrlocked()) 
       out << " wr=" << get_num_wrlocks();
+    if (updated)
+      out << " updated";
     out << ")";
   }
 
index 4df9347319371956746f865a56501243b540638d..2e40d323d01736bfa65093e2996a6af220384b20 100644 (file)
@@ -3685,14 +3685,17 @@ void Server::journal_opens()
   EOpen *le = 0;
 
   // check queued inodes
+  LogSegment *ls = mdlog->get_current_segment();
   for (set<CInode*>::iterator p = journal_open_queue.begin();
        p != journal_open_queue.end();
        ++p) {
-    (*p)->put(CInode::PIN_BATCHOPENJOURNAL);
-    if ((*p)->is_any_caps()) {
+    CInode *in = *p;
+    in->put(CInode::PIN_BATCHOPENJOURNAL);
+    if (in->is_any_caps()) {
       if (!le) le = new EOpen(mdlog);
-      le->add_inode(*p);
-      (*p)->last_open_journaled = mds->mdlog->get_write_pos();
+      le->add_inode(in);
+      in->last_open_journaled = mds->mdlog->get_write_pos();
+      ls->open_files.push_back(&in->xlist_open_file);
     }
   }
   journal_open_queue.clear();
index 5de43f1ba19aa846fc5965bbd0cc19205516ce8f..97a21a36734bef39c0d894cfed6e7dc2b8ac7c66 100644 (file)
@@ -73,8 +73,6 @@ protected:
     if (reqmds >= 0) out << " by mds" << reqmds;
   }  
 
-  bool has_expired(MDS *mds);
-  void expire(MDS *mds, Context *c);
   void update_segment();
   void replay(MDS *mds);  
 };
index 7cd36453e17b998623c865430fd9b994b16dc861..21f78369cae72a956981892574114c81977ddcad 100644 (file)
@@ -49,8 +49,6 @@ protected:
     if (atid) out << " atid " << atid;
   }  
 
-  bool has_expired(MDS *mds);
-  void expire(MDS *mds, Context *c);
   void replay(MDS *mds);
   
 };
index b96892678023bc5928256b0edef19d97f8a54b1e..fccc3650707a8ff0fcee8d7dcd65bbc0f95b117e 100644 (file)
@@ -46,8 +46,6 @@ public:
     metablob._decode(bl, off);
   }
 
-  bool has_expired(MDS *mds);
-  void expire(MDS *mds, Context *c);
   void update_segment();
   void replay(MDS *mds);
 };
index ba0a4863f0daf9e5631f3c89eb5fedf6f12c857d..de965429f9bdd5a7df47695b50fabdf86208be31 100644 (file)
@@ -43,8 +43,6 @@ public:
     metablob._decode(bl, off);
   }
 
-  bool has_expired(MDS *mds);
-  void expire(MDS *mds, Context *c);
   void update_segment();
   void replay(MDS *mds);
 };
index 7d843a99a0311039145e53fe98f75fd0956da530..243acc037f7408e577fcc2c50828165260a8457e 100644 (file)
@@ -87,10 +87,10 @@ C_Gather *LogSegment::try_to_expire(MDS *mds)
         ++p) {
       CDir *dir = *p;
       if (dir->can_auth_pin()) {
-       dout(10) << " committing " << *dir << dendl;
+       dout(10) << "try_to_expire committing " << *dir << dendl;
        dir->commit(0, gather->new_sub());
       } else {
-       dout(10) << " waiting for unfreeze on " << *dir << dendl;
+       dout(10) << "try_to_expire waiting for unfreeze on " << *dir << dendl;
        dir->add_waiter(CDir::WAIT_UNFREEZE, gather->new_sub());
       }
     }
@@ -98,21 +98,34 @@ C_Gather *LogSegment::try_to_expire(MDS *mds)
 
   // dirty non-auth mtimes
   for (xlist<CInode*>::iterator p = dirty_inode_mtimes.begin(); !p.end(); ++p) {
-    dout(10) << " waiting for dirlock mtime flush on " << *p << dendl;
+    dout(10) << "try_to_expire waiting for dirlock mtime flush on " << *p << dendl;
     if (!gather) gather = new C_Gather;
     (*p)->dirlock.add_waiter(SimpleLock::WAIT_STABLE, gather->new_sub());
   }
+  
+  // open files
+  if (!open_files.empty()) {
+    assert(!mds->mdlog->is_capped()); // hmm FIXME
+    for (xlist<CInode*>::iterator p = open_files.begin(); !p.end(); ++p) {
+      dout(20) << "try_to_expire requeueing open file " << **p << dendl;
+      mds->server->queue_journal_open(*p);
+    }
+    if (!gather) gather = new C_Gather;
+    mds->server->add_journal_open_waiter(gather->new_sub());
+    mds->server->maybe_journal_opens();
+    dout(10) << "try_to_expire waiting for open files to rejournal" << dendl;
+  }
 
   // idalloc
   if (allocv > mds->idalloc->get_committed_version()) {
-    dout(10) << " saving idalloc table, need " << allocv << dendl;
+    dout(10) << "try_to_expire saving idalloc table, need " << allocv << dendl;
     if (!gather) gather = new C_Gather;
     mds->idalloc->save(gather->new_sub(), allocv);
   }
 
   // clientmap
   if (clientmapv > mds->clientmap.get_committed()) {
-    dout(10) << " saving clientmap, need " << clientmapv << dendl;
+    dout(10) << "try_to_expire saving clientmap, need " << clientmapv << dendl;
     if (!gather) gather = new C_Gather;
     mds->clientmap.save(gather->new_sub(), clientmapv);
   }
@@ -123,21 +136,20 @@ C_Gather *LogSegment::try_to_expire(MDS *mds)
        ++p) {
     if (!gather) gather = new C_Gather;
     assert(!mds->anchorclient->has_committed(*p));
-    dout(10) << " anchor transaction " << *p 
+    dout(10) << "try_to_expire anchor transaction " << *p 
             << " pending commit (not yet acked), waiting" << dendl;
     mds->anchorclient->wait_for_ack(*p, gather->new_sub());
   }
   
   // anchortable
   if (anchortablev > mds->anchortable->get_committed_version()) {
-    dout(10) << " saving anchor table, need " << anchortablev << dendl;
+    dout(10) << "try_to_expire waiting for anchor table to save, need " << anchortablev << dendl;
     if (!gather) gather = new C_Gather;
     mds->anchortable->save(gather->new_sub());
   }
 
   // FIXME client requests...?
   // audit handling of anchor transactions?
-  // open files?
 
   return gather;
 }
@@ -796,44 +808,6 @@ void EUpdate::replay(MDS *mds)
 // ------------------------
 // EOpen
 
-bool EOpen::has_expired(MDS *mds)
-{
-  for (list<inodeno_t>::iterator p = inos.begin(); p != inos.end(); ++p) {
-    CInode *in = mds->mdcache->get_inode(*p);
-    if (in &&
-       in->is_any_caps() &&
-       !(in->last_open_journaled > get_start_off() ||
-         in->last_open_journaled == 0)) {
-      dout(10) << "EOpen.has_expired still refer to caps on " << *in << dendl;
-      return false;
-    }
-  }
-  return true;
-}
-
-void EOpen::expire(MDS *mds, Context *c)
-{
-  dout(10) << "EOpen.expire " << dendl;
-  
-  if (mds->mdlog->is_capped()) {
-    dout(0) << "uh oh, log is capped, but i have unexpired opens." << dendl;
-    assert(0);
-  }
-
-  for (list<inodeno_t>::iterator p = inos.begin(); p != inos.end(); ++p) {
-    CInode *in = mds->mdcache->get_inode(*p);
-    if (!in) continue;
-    if (!in->is_any_caps()) continue;
-    
-    dout(10) << "EOpen.expire " << in->ino()
-            << " last_open_journaled " << in->last_open_journaled << dendl;
-
-    mds->server->queue_journal_open(in);
-  }
-  mds->server->add_journal_open_waiter(c);
-  mds->server->maybe_journal_opens();
-}
-
 void EOpen::update_segment()
 {
   // ??
index a3112223f1028cea5af47ba694ac7782580b44ea..3992c7a61b7ac2eaedebddb1f16629e2074771e9 100644 (file)
@@ -433,16 +433,16 @@ class MDSCacheObject {
   unsigned state;     // state bits
 
  public:
-  unsigned get_state() { return state; }
+  unsigned get_state() const { return state; }
+  unsigned state_test(unsigned mask) const { return (state & mask); }
   void state_clear(unsigned mask) { state &= ~mask; }
   void state_set(unsigned mask) { state |= mask; }
-  unsigned state_test(unsigned mask) { return state & mask; }
   void state_reset(unsigned s) { state = s; }
 
-  bool is_auth() { return state_test(STATE_AUTH); }
-  bool is_dirty() { return state_test(STATE_DIRTY); }
-  bool is_clean() { return !is_dirty(); }
-  bool is_rejoining() { return state_test(STATE_REJOINING); }
+  bool is_auth() const { return state_test(STATE_AUTH); }
+  bool is_dirty() const { return state_test(STATE_DIRTY); }
+  bool is_clean() const { return !is_dirty(); }
+  bool is_rejoining() const { return state_test(STATE_REJOINING); }
 
   // --------------------------------------------
   // authority