]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
mds: catrack last_created, clean up caching semantics, use either get_newest_snap...
authorSage Weil <sage@newdream.net>
Fri, 25 Jul 2008 22:17:43 +0000 (15:17 -0700)
committerSage Weil <sage@newdream.net>
Fri, 25 Jul 2008 23:02:41 +0000 (16:02 -0700)
src/mds/CInode.cc
src/mds/MDCache.cc
src/mds/Server.cc
src/mds/snap.cc
src/mds/snap.h

index 2f2f0d5a7ac173f1ad1813fb1f2d72d7cd69ef2f..5c913c107a716ca2b9ef68ecc0bb4c974c017c2c 100644 (file)
@@ -1124,7 +1124,7 @@ old_inode_t& CInode::cow_old_inode(snapid_t follows, inode_t *pi)
 
 void CInode::pre_cow_old_inode()
 {
-  snapid_t follows = find_snaprealm()->get_latest_snap();
+  snapid_t follows = find_snaprealm()->get_newest_snap();
   if (first <= follows)
     cow_old_inode(follows, get_projected_inode());
 }
index 4838bb4dc18fe6ac9da702dd67542e6e60185442..bbe6d16da75cfa55e05552f9408885e41906562d 100644 (file)
@@ -1046,7 +1046,7 @@ void MDCache::journal_cow_dentry(EMetaBlob *metablob, CDentry *dn, snapid_t foll
     CInode *in = dn->inode;
 
     if (follows == CEPH_NOSNAP || follows == 0)
-      follows = in->find_snaprealm()->get_latest_snap();
+      follows = in->find_snaprealm()->get_newest_snap();
 
     // already cloned?
     if (follows < in->first)
@@ -1066,7 +1066,7 @@ void MDCache::journal_cow_dentry(EMetaBlob *metablob, CDentry *dn, snapid_t foll
     }
   } else {
     if (follows == CEPH_NOSNAP)
-      follows = dn->dir->inode->find_snaprealm()->get_latest_snap();
+      follows = dn->dir->inode->find_snaprealm()->get_newest_snap();
     
     // already cloned?
     if (follows < dn->first)
@@ -1383,7 +1383,7 @@ void MDCache::predirty_journal_parents(Mutation *mut, EMetaBlob *blob,
     // rstat
     if (primary_dn) { 
       SnapRealm *prealm = parent->inode->find_snaprealm();
-      snapid_t latest = prealm->get_latest_snap();
+      snapid_t latest = prealm->get_newest_snap();
       
       snapid_t follows = cfollows;
       if (follows == CEPH_NOSNAP || follows == 0)
@@ -4761,7 +4761,8 @@ int MDCache::path_traverse(MDRequest *mdr, Message *req,     // who
       dout(10) << "traverse: snapdir" << dendl;
       snapid = CEPH_SNAPDIR;
       depth++;
-      assert(psnapdiri);
+      if (!psnapdiri)
+       return -EINVAL;
       *psnapdiri = cur;
       continue;
     }
index 28c58136ca3c1b3d1de385f14cf6059dd3938b47..ace8a8cd179780bca253a670aa62f12f9ac1e6d5 100644 (file)
@@ -1497,7 +1497,7 @@ CDentry* Server::rdlock_path_xlock_dentry(MDRequest *mdr, bool okexist, bool mus
     rdlocks.insert(&dn->lock);  // existing dn, rdlock
   wrlocks.insert(&dn->dir->inode->dirlock); // also, wrlock on dir mtime
   wrlocks.insert(&dn->dir->inode->nestlock); // also, wrlock on dir mtime
-  mds->locker->include_snap_rdlocks(rdlocks, mdr->ref);
+  mds->locker->include_snap_rdlocks(rdlocks, dn->dir->inode);
 
   if (!mds->locker->acquire_locks(mdr, rdlocks, wrlocks, xlocks))
     return 0;
@@ -2068,7 +2068,7 @@ void Server::handle_client_mknod(MDRequest *mdr)
   CDentry *dn = rdlock_path_xlock_dentry(mdr, false, false);
   if (!dn) return;
 
-  snapid_t follows = dn->dir->inode->find_snaprealm()->get_latest_snap();
+  snapid_t follows = dn->dir->inode->find_snaprealm()->get_last_created();
   mdr->now = g_clock.real_now();
 
   CInode *newi = prepare_new_inode(mdr, dn->dir);
@@ -2112,7 +2112,7 @@ void Server::handle_client_mkdir(MDRequest *mdr)
   if (!dn) return;
 
   // new inode
-  snapid_t follows = dn->dir->inode->find_snaprealm()->get_latest_snap();
+  snapid_t follows = dn->dir->inode->find_snaprealm()->get_last_created();
   mdr->now = g_clock.real_now();
 
   CInode *newi = prepare_new_inode(mdr, dn->dir);  
@@ -2160,7 +2160,7 @@ void Server::handle_client_symlink(MDRequest *mdr)
   if (!dn) return;
 
   mdr->now = g_clock.real_now();
-  snapid_t follows = dn->dir->inode->find_snaprealm()->get_latest_snap();
+  snapid_t follows = dn->dir->inode->find_snaprealm()->get_last_created();
 
   CInode *newi = prepare_new_inode(mdr, dn->dir);
   assert(newi);
@@ -2323,7 +2323,7 @@ void Server::_link_local(MDRequest *mdr, CDentry *dn, CInode *targeti)
   pi->ctime = mdr->now;
   pi->version = tipv;
 
-  snapid_t follows = dn->dir->inode->find_snaprealm()->get_latest_snap();
+  snapid_t follows = dn->dir->inode->find_snaprealm()->get_last_created();
   dn->first = follows+1;
 
   // log + wait
@@ -3663,7 +3663,7 @@ void Server::_rename_prepare(MDRequest *mdr,
       if (!destdn->is_null())
        mdcache->journal_cow_dentry(metablob, destdn);
       else
-       destdn->first = destdn->dir->inode->find_snaprealm()->get_latest_snap()+1;
+       destdn->first = destdn->dir->inode->find_snaprealm()->get_last_created()+1;
       metablob->add_remote_dentry(destdn, true, srcdn->get_remote_ino(), srcdn->get_remote_d_type());
       mdcache->journal_cow_dentry(metablob, srcdn->inode->get_parent_dn());
       ji = metablob->add_primary_dentry(srcdn->inode->get_parent_dn(), true, srcdn->inode, pi);
@@ -3671,16 +3671,18 @@ void Server::_rename_prepare(MDRequest *mdr,
       if (!destdn->is_null())
        mdcache->journal_cow_dentry(metablob, destdn);
       else
-       destdn->first = destdn->dir->inode->find_snaprealm()->get_latest_snap()+1;
+       destdn->first = destdn->dir->inode->find_snaprealm()->get_last_created()+1;
       metablob->add_primary_dentry(destdn, true, destdn->inode, pi); 
     }
   } else if (srcdn->is_primary()) {
     // project snap parent update?
     bufferlist snapbl;
-    if (destdn->is_auth() && srcdn->inode->snaprealm) {
+    if (!srcdn->inode->snaprealm)
+      srcdn->inode->open_snaprealm();
+    if (destdn->is_auth()) {
       SnapRealm *realm = srcdn->inode->snaprealm;
-      snapid_t oldlast = realm->parent->get_latest_snap();
-      snapid_t newlast = destdn->dir->inode->find_snaprealm()->get_latest_snap();
+      snapid_t oldlast = realm->parent->get_newest_snap();
+      snapid_t newlast = destdn->dir->inode->find_snaprealm()->get_last_created();
       snapid_t first = realm->current_parent_since;
 
       snapid_t old_since = realm->current_parent_since;
@@ -3701,7 +3703,7 @@ void Server::_rename_prepare(MDRequest *mdr,
     if (!destdn->is_null())
       mdcache->journal_cow_dentry(metablob, destdn);
     else
-      destdn->first = destdn->dir->inode->find_snaprealm()->get_latest_snap()+1;
+      destdn->first = destdn->dir->inode->find_snaprealm()->get_last_created()+1;
     ji = metablob->add_primary_dentry(destdn, true, srcdn->inode, pi, 0, &snapbl); 
   }
     
@@ -3808,10 +3810,10 @@ void Server::_rename_apply(MDRequest *mdr, CDentry *srcdn, CDentry *destdn, CDen
       destdn->inode->pop_and_dirty_projected_inode(mdr->ls);
 
     // snap parent update?
-    if (destdn->is_auth() && destdn->inode->snaprealm) {
+    if (destdn->inode->is_dir()) {
       SnapRealm *realm = destdn->inode->snaprealm;
-      snapid_t oldlast = srcdn->dir->inode->find_snaprealm()->get_latest_snap();
-      snapid_t newlast = destdn->dir->inode->find_snaprealm()->get_latest_snap();
+      snapid_t oldlast = srcdn->dir->inode->find_snaprealm()->get_newest_snap();
+      snapid_t newlast = destdn->dir->inode->find_snaprealm()->get_last_created();
       snapid_t first = realm->current_parent_since;
       
       if (oldlast >= realm->current_parent_since) {
@@ -4768,7 +4770,7 @@ void Server::handle_client_openc(MDRequest *mdr)
     
   // create inode.
   mdr->now = g_clock.real_now();
-  snapid_t follows = dn->dir->inode->find_snaprealm()->get_latest_snap();
+  snapid_t follows = dn->dir->inode->find_snaprealm()->get_last_created();
 
   CInode *in = prepare_new_inode(mdr, dn->dir);
   assert(in);
@@ -4997,11 +4999,14 @@ void Server::handle_client_mksnap(MDRequest *mdr)
   // project the snaprealm.. hack!
   bufferlist snapbl;
   snapid_t old_seq = diri->snaprealm->seq;
+  snapid_t old_lc = diri->snaprealm->last_created;
   diri->snaprealm->snaps[snapid] = info;
   diri->snaprealm->seq = snapid;
+  diri->snaprealm->last_created = snapid;
   diri->encode_snap_blob(snapbl);
   diri->snaprealm->snaps.erase(snapid);
   diri->snaprealm->seq = old_seq;
+  diri->snaprealm->last_created = old_lc;
   le->metablob.add_primary_dentry(diri->get_projected_parent_dn(), true, 0, pi, 0, &snapbl);
 
   mdlog->submit_entry(le, new C_MDS_mksnap_finish(mds, mdr, diri, info));
@@ -5020,6 +5025,7 @@ void Server::_mksnap_finish(MDRequest *mdr, CInode *diri, SnapInfo &info)
   snapid_t snapid = info.snapid;
   diri->snaprealm->snaps[snapid] = info;
   diri->snaprealm->seq = snapid;
+  diri->snaprealm->last_created = snapid;
   dout(10) << "snaprealm now " << *diri->snaprealm << dendl;
 
   bufferlist snapbl;
@@ -5049,8 +5055,10 @@ void Server::_mksnap_finish(MDRequest *mdr, CInode *diri, SnapInfo &info)
     dout(10) << " " << realm << " open_children are " << realm->open_children << dendl;
     for (set<SnapRealm*>::iterator p = realm->open_children.begin();
         p != realm->open_children.end();
-        p++)
+        p++) {
+      (*p)->invalidate_cached_snaps();
       q.push_back(*p);
+    }
   }
 
   // send
index 0999b88b72f54e89165e7d7dd021201a6d7216d5..d7f2378884964ad2decde9ff48e15d8e544afe3e 100644 (file)
@@ -57,10 +57,17 @@ bool SnapRealm::open_parents(MDRequest *mdr)
  * get list of snaps for this realm.  we must include parents' snaps
  * for the intervals during which they were our parent.
  */
-void SnapRealm::build_snap_set(set<snapid_t> &s, snapid_t first, snapid_t last)
+void SnapRealm::build_snap_set(set<snapid_t> &s,
+                              snapid_t& max_seq, snapid_t& max_last_created,
+                              snapid_t first, snapid_t last)
 {
   dout(10) << "build_snap_set [" << first << "," << last << "] on " << *this << dendl;
 
+  if (seq > max_seq)
+    max_seq = seq;
+  if (last_created > max_last_created)
+    max_last_created = last_created;
+
   // include my snaps within interval [first,last]
   for (map<snapid_t, SnapInfo>::iterator p = snaps.lower_bound(first); // first element >= first
        p != snaps.end() && p->first <= last;
@@ -76,39 +83,47 @@ void SnapRealm::build_snap_set(set<snapid_t> &s, snapid_t first, snapid_t last)
     assert(oldparent->snaprealm);
     
     snapid_t thru = MIN(last, p->first);
-    oldparent->snaprealm->build_snap_set(s, 
+    oldparent->snaprealm->build_snap_set(s, max_seq, max_last_created,
                                         MAX(first, p->second.first),
                                         thru);
   }
   if (current_parent_since <= last && parent)
-    parent->build_snap_set(s, current_parent_since, last);
+    parent->build_snap_set(s, max_seq, max_last_created, current_parent_since, last);
 }
 
 /*
  * build vector in reverse sorted order
  */
+void SnapRealm::check_cache()
+{
+  if (cached_seq >= seq)
+    return;
+
+  cached_snaps.clear();
+  cached_snap_vec.clear();
+  cached_last_created = last_created;
+  cached_seq = seq;
+  build_snap_set(cached_snaps, cached_seq, cached_last_created, 0, CEPH_NOSNAP);
+  
+  dout(10) << "check_cache " << cached_snaps
+          << " seq " << seq
+          << " cached_seq " << cached_seq
+          << " cached_last_created " << cached_last_created << ")" 
+          << dendl;
+}
+
 const set<snapid_t>& SnapRealm::get_snaps()
 {
-  if (cached_snaps.empty() || cached_snaps_seq < seq) {
-    cached_snaps.clear();
-    cached_snap_vec.clear();
-    build_snap_set(cached_snaps, 0, CEPH_NOSNAP);
-
-    dout(10) << "get_snaps " << cached_snaps
-            << " (seq " << seq << ")" 
-            << dendl;
-  } else {
-    dout(10) << "get_snaps " << cached_snaps
-            << " (seq " << seq << ")" 
-            << " (cached)"
-            << dendl;
-  }
+  check_cache();
+  dout(10) << "get_snaps " << cached_snaps
+          << " (seq " << seq << " cached_seq " << cached_seq << ")"
+          << dendl;
   return cached_snaps;
 }
 
 const vector<snapid_t>& SnapRealm::get_snap_vector()
 {
-  get_snaps();
+  check_cache();
 
   if (cached_snap_vec.empty()) {
     cached_snap_vec.resize(cached_snaps.size());
@@ -294,21 +309,21 @@ void SnapRealm::build_snap_trace(bufferlist& snapbl)
   SnapRealmInfo info;
   info.ino = inode->ino();
   info.seq = seq;
+  info.parent_since = current_parent_since;
 
   if (parent) {
     info.parent = parent->inode->ino();
     if (!past_parents.empty()) {
       snapid_t last = past_parents.rbegin()->first;
       set<snapid_t> past;
-      build_snap_set(past, 0, last);
+      snapid_t max_seq, max_last_created;
+      build_snap_set(past, max_seq, max_last_created, 0, last);
       info.prior_parent_snaps.reserve(past.size());
       for (set<snapid_t>::reverse_iterator p = past.rbegin(); p != past.rend(); p++)
        info.prior_parent_snaps.push_back(*p);
-      info.parent_since = last+1;
       dout(10) << "build_snap_trace prior_parent_snaps from [1," << last << "] "
               << info.prior_parent_snaps << dendl;
-    } else
-      info.parent_since = 1;
+    }
   } else 
     info.parent = 0;
 
index ec116724e278688c95f8c58226c6943921bc277e..5b03358b125a91d474672088face24ed99669dd7 100644 (file)
@@ -81,13 +81,16 @@ WRITE_CLASS_ENCODER(snaplink_t)
 
 struct SnapRealm {
   // realm state
-  snapid_t created, seq;
+  snapid_t created;                 // when this realm was created.
+  snapid_t last_created;            // last snap created in _this_ realm.
+  snapid_t seq;                     // basically, a version/seq # for changes to _this_ realm.
   snapid_t current_parent_since;
   map<snapid_t, SnapInfo> snaps;
   map<snapid_t, snaplink_t> past_parents;  // key is "last" (or NOSNAP)
 
   void encode(bufferlist& bl) const {
     ::encode(created, bl);
+    ::encode(last_created, bl);
     ::encode(seq, bl);
     ::encode(current_parent_since, bl);
     ::encode(snaps, bl);
@@ -95,6 +98,7 @@ struct SnapRealm {
   }
   void decode(bufferlist::iterator& p) {
     ::decode(created, p);
+    ::decode(last_created, p);
     ::decode(seq, p);
     ::decode(current_parent_since, p);
     ::decode(snaps, p);
@@ -109,8 +113,9 @@ struct SnapRealm {
   set<SnapRealm*> open_children;    // active children that are currently open
   map<snapid_t,SnapRealm*> open_past_parents;  // these are explicitly pinned.
 
-  // caches?
-  snapid_t cached_snaps_seq;
+  // cache
+  snapid_t cached_seq;           // max seq over self and all past+present parents.
+  snapid_t cached_last_created;  // max last_created over all past+present parents
   set<snapid_t> cached_snaps;
   vector<snapid_t> cached_snap_vec;
 
@@ -118,7 +123,7 @@ struct SnapRealm {
   map<int, xlist<Capability*> > client_caps;   // to identify clients who need snap notifications
 
   SnapRealm(MDCache *c, CInode *in) : 
-    created(0), seq(0),
+    created(0), last_created(0), seq(0),
     current_parent_since(1),
     mdcache(c), inode(in),
     parent(0)
@@ -134,7 +139,9 @@ struct SnapRealm {
   }
 
   bool open_parents(MDRequest *mdr);
-  void build_snap_set(set<snapid_t>& s, snapid_t first, snapid_t last);
+  void build_snap_set(set<snapid_t>& s, 
+                     snapid_t& max_seq, snapid_t& max_last_created,
+                     snapid_t first, snapid_t last);
   void get_snap_info(map<snapid_t,SnapInfo*>& infomap, snapid_t first=0, snapid_t last=CEPH_NOSNAP);
 
   void build_snap_trace(bufferlist& snapbl);
@@ -142,14 +149,22 @@ struct SnapRealm {
   const string& get_snapname(snapid_t snapid, inodeno_t atino);
   snapid_t resolve_snapname(const string &name, inodeno_t atino, snapid_t first=0, snapid_t last=CEPH_NOSNAP);
 
+  void check_cache();
   const set<snapid_t>& get_snaps();
   const vector<snapid_t>& get_snap_vector();
-  snapid_t get_latest_snap() {
-    const set<snapid_t> &snaps = get_snaps();
-    if (snaps.empty())
+  void invalidate_cached_snaps() {
+    cached_seq = 0;
+  }
+  snapid_t get_last_created() {
+    check_cache();
+    return cached_last_created;
+  }
+  snapid_t get_newest_snap() {
+    check_cache();
+    if (cached_snaps.empty())
       return 0;
     else
-      return *snaps.rbegin();
+      return *cached_snaps.rbegin();
   }
 
   void change_open_parent_to(SnapRealm *newp) {
@@ -174,6 +189,7 @@ WRITE_CLASS_ENCODER(SnapRealm)
 
 inline ostream& operator<<(ostream& out, const SnapRealm &realm) {
   out << "snaprealm(seq " << realm.seq
+      << " lc " << realm.last_created
       << " snaps=" << realm.snaps;
   if (realm.past_parents.size()) {
     out << " past_parents=(";