]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
mds: open snaprealm parents during path_traverse. once parents are all open, set...
authorSage Weil <sage@newdream.net>
Sat, 26 Jul 2008 04:26:45 +0000 (21:26 -0700)
committerSage Weil <sage@newdream.net>
Sat, 26 Jul 2008 04:26:45 +0000 (21:26 -0700)
src/TODO
src/mds/CDir.cc
src/mds/MDCache.cc
src/mds/snap.cc
src/mds/snap.h

index 03139d05b527b5101449b323f9f57e0e8a5ebe5c..12ab9208fe77b3f89aea233332dc7f51efb49c71 100644 (file)
--- a/src/TODO
+++ b/src/TODO
@@ -25,22 +25,22 @@ snapshots
   - snap collections
   - garbage collection
 
+mds
+- migrator import/export of versioned dentries, inodes... drop them on export...
+/- pin/unpin open_past_parents.
+/- call open_parents() where needed.
+  - what about during recovery?  e.g. client reconnected caps...
+- resolve/rejoin vs snapshots!
 - client reconnect vs snaps
+- mds server ops
+  - link rollback
+  - rename rollback
 
 - hard link backpointers
   - anchor source dir
   - build snaprealm for any hardlinked file
   - include snaps for all (primary+remote) parents
 
-- migrator import/export of versioned dentries, inodes... drop them on export...
-
-/- pin/unpin open_past_parents.
-- call open_parents() where needed.
-
-- mds server ops
-  - link rollback
-  - rename rollback
-
 
 
 userspace client
index 3c5629decb7afb7652e5c86778c3e9c09f75b380..ec4a15d4c52e4b42ff4421cc5263feed6222ac17 100644 (file)
@@ -1047,16 +1047,19 @@ void CDir::_fetched(bufferlist &bl)
   
   int32_t n;
   ::decode(n, p);
-
   snapid_t got_newest_seq;
   ::decode(got_newest_seq, p);
+
+  // purge stale snaps?
+  //  * only if we have past_parents open!
+  const set<snapid_t> *snaps = 0;
   SnapRealm *realm = inode->find_snaprealm();
-  const set<snapid_t>& snaps = realm->get_snaps();
-  bool purge_stale = false;
-  if (got_newest_seq < realm->get_newest_seq()) {
+  if (!realm->have_past_parents_open()) {
+    dout(10) << " no snap purge, one or more past parents NOT open" << dendl;
+  } else if (got_newest_seq < realm->get_newest_seq()) {
+    snaps = &realm->get_snaps();
     dout(10) << " got newest_seq " << got_newest_seq << " < " << realm->get_newest_seq()
-            << ", will purge stale entries using snaps " << snaps << dendl;
-    purge_stale = true;
+            << ", snap purge based on " << *snaps << dendl;
   }
 
   //int num_new_inodes_loaded = 0;
@@ -1079,9 +1082,9 @@ void CDir::_fetched(bufferlist &bl)
             << dendl;
 
     bool stale = false;
-    if (purge_stale && last != CEPH_NOSNAP) {
-      set<snapid_t>::const_iterator p = snaps.lower_bound(first);
-      if (p == snaps.end() || *p > last) {
+    if (snaps && last != CEPH_NOSNAP) {
+      set<snapid_t>::const_iterator p = snaps->lower_bound(first);
+      if (p == snaps->end() || *p > last) {
        dout(10) << " skipping stale dentry on [" << first << "," << last << "]" << dendl;
        stale = true;
       }
@@ -1178,8 +1181,8 @@ void CDir::_fetched(bufferlist &bl)
          in->xattrs.swap(xattrs);
          in->decode_snap_blob(snapbl);
          in->old_inodes.swap(old_inodes);
-         if (purge_stale)
-           in->purge_stale_snap_data(snaps);
+         if (snaps)
+           in->purge_stale_snap_data(*snaps);
 
          // add 
          cache->add_inode( in );
@@ -1358,8 +1361,17 @@ void CDir::_commit(version_t want)
   int32_t n = num_head_items + num_snap_items;
   ::encode(n, bl);
 
-  const set<snapid_t>& snaps = inode->find_snaprealm()->get_snaps();
-  snapid_t newest_seq = inode->find_snaprealm()->get_newest_seq();
+  // snap purge?
+  const set<snapid_t> *snaps = 0;
+  snapid_t newest_seq = 0;
+  SnapRealm *realm = inode->find_snaprealm();
+  if (realm->have_past_parents_open()) {
+    snaps = &realm->get_snaps();
+    newest_seq = realm->get_newest_seq();
+    dout(10) << " snap purge based on " << *snaps << dendl;
+  } else {
+    dout(10) << " no snap purge, one or more past parents NOT open" << dendl;
+  }
   ::encode(newest_seq, bl);
 
   map_t::iterator p = items.begin();
@@ -1370,9 +1382,9 @@ void CDir::_commit(version_t want)
     if (dn->is_null()) 
       continue;  // skip negative entries
 
-    if (dn->last != CEPH_NOSNAP) {
-      set<snapid_t>::const_iterator p = snaps.lower_bound(dn->first);
-      if (p == snaps.end() || *p > dn->last) {
+    if (snaps && dn->last != CEPH_NOSNAP) {
+      set<snapid_t>::const_iterator p = snaps->lower_bound(dn->first);
+      if (p == snaps->end() || *p > dn->last) {
        dout(10) << " purging " << *dn << dendl;
        remove_dentry(dn);
        continue;
@@ -1420,8 +1432,8 @@ void CDir::_commit(version_t want)
       in->encode_snap_blob(snapbl);
       ::encode(snapbl, bl);
 
-      if (in->is_multiversion())
-       in->purge_stale_snap_data(snaps);
+      if (in->is_multiversion() && snaps)
+       in->purge_stale_snap_data(*snaps);
       ::encode(in->old_inodes, bl);
     }
   }
index cd1eb4cdc32fea7931c2571ed6f18664a8bc0768..8bd428352fe1473b91b5628e9b94915bdaba2226 100644 (file)
@@ -4837,6 +4837,12 @@ int MDCache::path_traverse(MDRequest *mdr, Message *req,     // who
     }
 
 
+    // make sure snaprealm parents are open...
+    if (cur->snaprealm && !cur->snaprealm->open && mdr &&
+       !cur->snaprealm->open_parents(mdr))
+      return 1;
+
+
     // dentry
     CDentry *dn = curdir->lookup(path[depth], snapid);
 
index 50d33ef70c2996e42b22efdf5e926d65acc15d8c..79ec9c8ccc3e95acecacc0103e4cba796293574f 100644 (file)
                                                  << ".cache.snaprealm(" << inode->ino() \
                                                  << " seq " << seq << " " << this << ") "
 
-bool SnapRealm::open_parents(MDRequest *mdr)
+bool SnapRealm::open_parents(MDRequest *mdr, snapid_t first, snapid_t last)
 {
-  dout(10) << "open_parents" << dendl;
+  dout(10) << "open_parents [" << first << "," << last << "]" << dendl;
+  if (open)
+    return true;
 
   // make sure my current parents' parents are open...
   if (parent) {
-    dout(10) << " parent is " << *parent
+    dout(10) << " current parent [" << current_parent_since << ",head] is " << *parent
             << " on " << *parent->inode << dendl;
-    if (!parent->open_parents(mdr))
+    if (last >= current_parent_since &&
+       !parent->open_parents(mdr, MAX(first, current_parent_since), last))
       return false;
   }
 
   // and my past parents too!
-  for (map<snapid_t, snaplink_t>::iterator p = past_parents.begin();
+  assert(past_parents.size() >= open_past_parents.size());
+  if (past_parents.size() > open_past_parents.size()) {
+    for (map<snapid_t, snaplink_t>::iterator p = past_parents.begin();
+        p != past_parents.end();
+        p++) {    
+      dout(10) << " past_parent [" << p->second.first << "," << p->first << "] is "
+              << p->second.ino << dendl;
+      CInode *parent = mdcache->get_inode(p->second.ino);
+      if (!parent) {
+       mdcache->open_remote_ino(p->second.ino, mdr, 
+                                new C_MDS_RetryRequest(mdcache, mdr));
+       return false;
+      }
+      assert(parent->snaprealm);  // hmm!
+      if (!open_past_parents.count(p->second.ino)) {
+       open_past_parents[p->second.ino] = parent->snaprealm;
+       parent->get(CInode::PIN_PASTSNAPPARENT);
+      }
+      if (!parent->snaprealm->open_parents(mdr, p->second.first, p->first))
+       return false;
+    }
+  }
+
+  open = true;
+  return true;
+}
+
+bool SnapRealm::have_past_parents_open(snapid_t first, snapid_t last)
+{
+  dout(10) << "have_past_parents_open [" << first << "," << last << "]" << dendl;
+  for (map<snapid_t, snaplink_t>::iterator p = past_parents.lower_bound(first);
        p != past_parents.end();
-       p++) {    
-    CInode *parent = mdcache->get_inode(p->second.ino);
-    if (!parent) {
-      mdcache->open_remote_ino(p->second.ino, mdr, 
-                              new C_MDS_RetryRequest(mdcache, mdr));
+       p++) {
+    if (p->second.first > last)
+      break;
+    dout(10) << " past parent [" << p->second.first << "," << p->first << "] was "
+            << p->second.ino << dendl;
+    if (open_past_parents.count(p->second.ino) == 0) {
+      dout(10) << " past parent " << p->second.ino << " is not open" << dendl;
       return false;
     }
-    assert(parent->snaprealm);  // hmm!
-    if (!open_past_parents.count(p->second.ino)) {
-      open_past_parents[p->second.ino] = parent->snaprealm;
-      parent->get(CInode::PIN_PASTSNAPPARENT);
-    }
+    if (!open_past_parents[p->second.ino]->have_past_parents_open(MAX(first, p->second.first),
+                                                                 MIN(last, p->first)))
+      return false;
   }
   return true;
 }
index 0e1c31821d37e6b81709181a98377337faf31691..c29fa9344905279f145244c854a4fbeda6a06904 100644 (file)
@@ -109,6 +109,7 @@ struct SnapRealm {
   MDCache *mdcache;
   CInode *inode;
 
+  bool open;                        // set to true once all past_parents are opened
   SnapRealm *parent;
   set<SnapRealm*> open_children;    // active children that are currently open
   map<inodeno_t,SnapRealm*> open_past_parents;  // these are explicitly pinned.
@@ -126,7 +127,7 @@ struct SnapRealm {
     created(0), last_created(0), seq(0),
     current_parent_since(1),
     mdcache(c), inode(in),
-    parent(0)
+    open(false), parent(0)
   { }
 
   bool exists(const string &name) {
@@ -138,7 +139,8 @@ struct SnapRealm {
     return false;
   }
 
-  bool open_parents(MDRequest *mdr);
+  bool open_parents(MDRequest *mdr, snapid_t first=1, snapid_t last=CEPH_NOSNAP);
+  bool have_past_parents_open(snapid_t first=1, snapid_t last=CEPH_NOSNAP);
   void close_parents();
 
   void build_snap_set(set<snapid_t>& s,