]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
mds: make cache track nested anchors
authorSage Weil <sage@newdream.net>
Tue, 27 May 2008 19:39:31 +0000 (12:39 -0700)
committerSage Weil <sage@newdream.net>
Tue, 27 May 2008 19:39:31 +0000 (12:39 -0700)
src/mds/CDentry.cc
src/mds/CDentry.h
src/mds/CDir.cc
src/mds/CDir.h
src/mds/CInode.cc
src/mds/CInode.h
src/mds/MDCache.cc

index 7be4c032915f96b15f75d4ad9ff2461037ab989c..ab8002af9c7c5e942541d67ed79b1eb6983cb16a 100644 (file)
@@ -326,6 +326,14 @@ bool CDentry::is_frozen()
 }
 
 
+void CDentry::adjust_nested_anchors(int by)
+{
+  nested_anchors += by;
+  dout(20) << "adjust_nested_anchors by " << by << " -> " << nested_anchors << dendl;
+  assert(nested_anchors >= 0);
+  dir->adjust_nested_anchors(by);
+}
+
 // ----------------------------
 // locking
 
index 6805330e1fe5153aff5ed4c61b91978b9256a5ab..55f2a49c117239c06907f080921e0477fe9a6da1 100644 (file)
@@ -92,6 +92,7 @@ class CDentry : public MDSCacheObject, public LRUObject {
   off_t dir_offset;   
 
   int auth_pins, nested_auth_pins;
+  int nested_anchors;
 
   friend class Migrator;
   friend class Locker;
@@ -117,7 +118,7 @@ public:
     version(0), projected_version(0),
     xlist_dirty(this),
     dir_offset(0),
-    auth_pins(0), nested_auth_pins(0),
+    auth_pins(0), nested_auth_pins(0), nested_anchors(0),
     lock(this, CEPH_LOCK_DN, WAIT_LOCK_OFFSET) { }
   CDentry(const string& n, CInode *in) :
     name(n),
@@ -126,7 +127,7 @@ public:
     version(0), projected_version(0),
     xlist_dirty(this),
     dir_offset(0),
-    auth_pins(0), nested_auth_pins(0),
+    auth_pins(0), nested_auth_pins(0), nested_anchors(0),
     lock(this, CEPH_LOCK_DN, WAIT_LOCK_OFFSET) { }
   CDentry(const string& n, inodeno_t ino, unsigned char dt, CInode *in=0) :
     name(n),
@@ -135,7 +136,7 @@ public:
     version(0), projected_version(0),
     xlist_dirty(this),
     dir_offset(0),
-    auth_pins(0), nested_auth_pins(0),
+    auth_pins(0), nested_auth_pins(0), nested_anchors(0),
     lock(this, CEPH_LOCK_DN, WAIT_LOCK_OFFSET) { }
 
   CInode *get_inode() const { return inode; }
@@ -169,6 +170,7 @@ public:
   void adjust_nested_auth_pins(int by);
   bool is_frozen();
   
+  void adjust_nested_anchors(int by);
 
   // dentry type is primary || remote || null
   // inode ptr is required for primary, optional for remote, undefined for null
index 16b8b9b0ef180a342b1b02ad3b21e19f3c8e362c..f8f72e8a830b8c16890e12e0bd677e13d1abc0fd 100644 (file)
@@ -75,6 +75,8 @@ ostream& operator<<(ostream& out, CDir& dir)
   
   if (dir.get_cum_auth_pins())
     out << " ap=" << dir.get_auth_pins() << "+" << dir.get_nested_auth_pins();
+  if (dir.get_nested_anchors())
+    out << " na=" << dir.get_nested_anchors();
 
   out << " state=" << dir.get_state();
   if (dir.state_test(CDir::STATE_COMPLETE)) out << "|complete";
@@ -157,6 +159,8 @@ CDir::CDir(CInode *in, frag_t fg, MDCache *mdcache, bool auth) :
   nested_auth_pins = 0;
   request_pins = 0;
 
+  nested_anchors = 0;
+
   //hack_num_accessed = -1;
   
   dir_rep = REP_NONE;
@@ -359,6 +363,9 @@ void CDir::link_inode_work( CDentry *dn, CInode *in)
   // adjust auth pin count
   if (in->auth_pins + in->nested_auth_pins)
     dn->adjust_nested_auth_pins(in->auth_pins + in->nested_auth_pins);
+
+  if (in->inode.anchored + in->nested_anchors)
+    dn->adjust_nested_anchors(in->nested_anchors + in->inode.anchored);
 }
 
 void CDir::unlink_inode( CDentry *dn )
@@ -442,6 +449,9 @@ void CDir::unlink_inode_work( CDentry *dn )
     if (in->auth_pins + in->nested_auth_pins)
       dn->adjust_nested_auth_pins(0 - (in->auth_pins + in->nested_auth_pins));
     
+    if (in->inode.anchored + in->nested_anchors)
+      dn->adjust_nested_anchors(0 - (in->nested_anchors + in->inode.anchored));
+
     // detach inode
     in->remove_primary_parent(dn);
     dn->inode = 0;
@@ -514,6 +524,7 @@ void CDir::steal_dentry(CDentry *dn)
   }
 
   nested_auth_pins += dn->auth_pins + dn->nested_auth_pins;
+  nested_anchors += dn->nested_anchors;
   if (dn->is_dirty()) 
     num_dirty++;
 
@@ -1564,6 +1575,13 @@ void CDir::adjust_nested_auth_pins(int inc)
   inode->adjust_nested_auth_pins(inc);
 }
 
+void CDir::adjust_nested_anchors(int by)
+{
+  nested_anchors += by;
+  dout(20) << "adjust_nested_anchors by " << by << " -> " << nested_anchors << dendl;
+  assert(nested_anchors >= 0);
+  inode->adjust_nested_anchors(by);
+}
 
 
 /*****************************************************************************
index 386cf50ae4f0aee15137a8a7070b3189bc0a91a2..5e87f83af261d11349c09400c4ac4ee5e43b9836 100644 (file)
@@ -214,6 +214,8 @@ protected:
   int nested_auth_pins;
   int request_pins;
 
+  int nested_anchors;
+
   // cache control  (defined for authority; hints for replicas)
   int      dir_rep;
   set<int> dir_rep_by;      // if dir_rep == REP_LIST
@@ -446,6 +448,9 @@ public:
   void auth_unpin();
   void adjust_nested_auth_pins(int inc);
 
+  int get_nested_anchors() { return nested_anchors; }
+  void adjust_nested_anchors(int by);
+
   // -- freezing --
   bool freeze_tree();
   void _freeze_tree();
index 026e164adbb1ac2c0877fbbde984c9bb138a3659..897e6aabc58f3c6f7e9d94372fdfbda86c9be89d 100644 (file)
@@ -576,7 +576,12 @@ void CInode::decode_lock_state(int type, bufferlist& bl)
     ::decode(tm, p);
     if (inode.ctime < tm) inode.ctime = tm;
     ::decode(inode.nlink, p);
-    ::decode(inode.anchored, p);
+    {
+      bool was_anchored = inode.anchored;
+      ::decode(inode.anchored, p);
+      if (was_anchored != inode.anchored)
+       parent->adjust_nested_anchors((int)inode.anchored - (int)was_anchored);
+    }
     break;
 
   case CEPH_LOCK_IDFT:
@@ -826,7 +831,14 @@ void CInode::adjust_nested_auth_pins(int a)
   parent->adjust_nested_auth_pins(a);
 }
 
-
+void CInode::adjust_nested_anchors(int by)
+{
+  nested_anchors += by;
+  dout(20) << "adjust_nested_anchors by " << by << " -> " << nested_anchors << dendl;
+  assert(nested_anchors >= 0);
+  if (parent)
+    parent->adjust_nested_anchors(by);
+}
 
 // authority
 
@@ -898,7 +910,10 @@ void CInode::decode_import(bufferlist::iterator& p,
                           LogSegment *ls)
 {
   utime_t old_mtime = inode.mtime;
+  bool was_anchored = inode.anchored;
   ::decode(inode, p);
+  if (was_anchored != inode.anchored)
+    parent->adjust_nested_anchors((int)inode.anchored - (int)was_anchored);
   if (old_mtime > inode.mtime) {
     assert(dirlock.is_updated());
     inode.mtime = old_mtime;     // preserve our mtime, if it is larger
index 0f5673b714db714866b8ebccf69557a15027af48..cd766104e41de9e8fd45d75297b0bd84964e8b0f 100644 (file)
@@ -116,7 +116,6 @@ class CInode : public MDSCacheObject {
   static const int WAIT_DIRLOCK_OFFSET         = 4 + 3*SimpleLock::WAIT_BITS; // same
   static const int WAIT_VERSIONLOCK_OFFSET     = 4 + 4*SimpleLock::WAIT_BITS;
   static const int WAIT_XATTRLOCK_OFFSET       = 4 + 5*SimpleLock::WAIT_BITS;
-  static const int WAIT_NESTEDLOCK_OFFSET      = 4 + 6*SimpleLock::WAIT_BITS;
 
   static const int WAIT_ANY_MASK       = (0xffffffff);
 
@@ -229,6 +228,9 @@ private:
 public:
   int auth_pin_freeze_allowance;
 
+private:
+  int nested_anchors;   // _NOT_ including me!
+
  public:
   inode_load_vec_t pop;
 
@@ -255,6 +257,7 @@ public:
     xlist_dirty_dirfrag_dir(this), 
     xlist_purging_inode(this),
     auth_pins(0), nested_auth_pins(0),
+    nested_anchors(0),
     versionlock(this, CEPH_LOCK_IVERSION, WAIT_VERSIONLOCK_OFFSET),
     authlock(this, CEPH_LOCK_IAUTH, WAIT_AUTHLOCK_OFFSET),
     linklock(this, CEPH_LOCK_ILINK, WAIT_LINKLOCK_OFFSET),
@@ -501,6 +504,7 @@ public:
   void auth_pin();
   void auth_unpin();
 
+  void adjust_nested_anchors(int by);
 
   // -- freeze --
   bool is_freezing_inode() { return state_test(STATE_FREEZING); }
@@ -614,6 +618,8 @@ class CInodeDiscover {
   int get_replica_nonce() { return replica_nonce; }
 
   void update_inode(CInode *in) {
+    if (in->parent && inode.anchored != in->inode.anchored)
+      in->parent->adjust_nested_anchors((int)inode.anchored - (int)in->inode.anchored);
     in->inode = inode;
     in->symlink = symlink;
     in->dirfragtree = dirfragtree;
index 1826b07fdf1229160e3d75be9e12fb5fe75cf0e3..93899951077f81f0a7b2ba38695f091bad7dc178 100644 (file)
@@ -4777,6 +4777,21 @@ void MDCache::anchor_create(MDRequest *mdr, CInode *in, Context *onfinish)
     return;
   }
 
+  // rdlock path
+  set<SimpleLock*> rdlocks = mdr->rdlocks;
+  set<SimpleLock*> wrlocks = mdr->wrlocks;
+  set<SimpleLock*> xlocks = mdr->xlocks;
+
+  CDentry *dn = in->get_parent_dn();
+  while (dn) {
+    rdlocks.insert(&dn->lock);
+    dn = dn->get_dir()->get_inode()->get_parent_dn();
+  }
+  if (!mds->locker->acquire_locks(mdr, rdlocks, wrlocks, xlocks)) {
+   dout(7) << "anchor_create waiting for locks  " << *in << dendl;
+   return;
+  }
+
   // wait
   in->add_waiter(CInode::WAIT_ANCHORED, onfinish);
 
@@ -4851,17 +4866,20 @@ public:
 
 void MDCache::_anchor_prepared(CInode *in, version_t atid, bool add)
 {
-  dout(10) << "_anchor_create_prepared " << *in << " atid " << atid << dendl;
-  assert(in->inode.anchored == false);
+  dout(10) << "_anchor_prepared " << *in << " atid " << atid 
+          << " " << (add ? "create":"destroy") << dendl;
+  assert(in->inode.anchored == !add);
 
   // update the logged inode copy
   inode_t *pi = in->project_inode();
   if (add) {
     pi->anchored = true;
     pi->dirstat.ranchors++;
+    in->parent->adjust_nested_anchors(1);
   } else {
     pi->anchored = false;
     pi->dirstat.ranchors--;
+    in->parent->adjust_nested_anchors(-1);
   }
   pi->version = in->pre_dirty();