]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
mds: refragment dirs when inode dirfragtree updates from journal
authorSage Weil <sage.weil@dreamhost.com>
Wed, 23 Feb 2011 21:01:08 +0000 (13:01 -0800)
committerSage Weil <sage.weil@dreamhost.com>
Wed, 23 Feb 2011 21:01:08 +0000 (13:01 -0800)
Force dir fragmentation specified by dirfragtree when replayed from
the journal.

Example:
 mds0 is auth for /foo, mds1 is auth for /foo/bar.
 mds1 fragments /foo/bar.  journals etc.
 mds0 gets fragment notify and the in-memory inode's dirfragtree changes.
 mds0 journals the /foo/bar inode for some random reason.
 mds0 imports /foo/bar.

On replay, mds0 refragments upon first mention of the new fragtree in the
journal, so that the dirfragtree <-> dir frags always match.  Confusion is
avoided when we, say, import /foo/bar.

Signed-off-by: Sage Weil <sage.weil@dreamhost.com>
src/include/frag.h
src/mds/CInode.cc
src/mds/CInode.h
src/mds/events/EMetaBlob.h
src/mds/journal.cc

index 14afb948781b34e777864f2a7bd3084ad26908df..866c60b4d4cc7c0e579486fd168f29d3947ce710 100644 (file)
@@ -495,6 +495,13 @@ public:
 };
 WRITE_CLASS_ENCODER(fragtree_t)
 
+inline bool operator==(const fragtree_t& l, const fragtree_t& r) {
+  return l._splits == r._splits;
+}
+inline bool operator!=(const fragtree_t& l, const fragtree_t& r) {
+  return l._splits != r._splits;
+}
+
 inline std::ostream& operator<<(std::ostream& out, fragtree_t& ft)
 {
   out << "fragtree_t(";
index 4ecdddd85bcf12f6a33645ebc8d0caa7da9fef56..772024db6bb9cb8a6d0f64b3cb6806b98c54bc52 100644 (file)
@@ -473,6 +473,27 @@ void CInode::verify_dirfrags()
   assert(!bad);
 }
 
+void CInode::force_dirfrags()
+{
+  bool bad = false;
+  for (map<frag_t,CDir*>::iterator p = dirfrags.begin(); p != dirfrags.end(); ++p) {
+    if (!dirfragtree.is_leaf(p->first)) {
+      dout(0) << "have open dirfrag " << p->first << " but not leaf in " << dirfragtree
+             << ": " << *p->second << dendl;
+      bad = true;
+    }
+  }
+
+  if (bad) {
+    list<frag_t> leaves;
+    dirfragtree.get_leaves(leaves);
+    for (list<frag_t>::iterator p = leaves.begin(); p != leaves.end(); ++p)
+      mdcache->get_force_dirfrag(dirfrag_t(ino(),*p));
+  }
+
+  verify_dirfrags();
+}
+
 CDir *CInode::get_approx_dirfrag(frag_t fg)
 {
   CDir *dir = get_dirfrag(fg);
index 2cf264c627c51ec4048cd134c5c2234631462639..cb3242a5864fd8e6baef8012c6830ffac866a2f7 100644 (file)
@@ -380,6 +380,7 @@ public:
   void close_dirfrags();
   bool has_subtree_root_dirfrag();
 
+  void force_dirfrags();
   void verify_dirfrags();
 
   void get_stickydirs();
index eacbafb7d0e18690c2a1dc0cf8241bd234016a4e..9ab124fa5e527d39d6bc38106a234af585b06a81 100644 (file)
@@ -133,24 +133,7 @@ public:
       ::decode(dirty, bl);
     }
 
-    void update_inode(CInode *in) {
-      in->inode = inode;
-      in->xattrs = xattrs;
-      if (in->inode.is_dir()) {
-       in->dirfragtree = dirfragtree;
-       delete in->default_layout;
-       in->default_layout = dir_layout;
-       dir_layout = NULL;
-       /*
-        * we can do this before linking hte inode bc the split_at would
-        * be a no-op.. we have no children (namely open snaprealms) to
-        * divy up 
-        */
-       in->decode_snap_blob(snapbl);  
-      } else if (in->inode.is_symlink()) {
-       in->symlink = symlink;
-      }
-    }
+    void update_inode(CInode *in);
 
     void print(ostream& out) {
       out << " fullbit dn " << dn << " [" << dnfirst << "," << dnlast << "] dnv " << dnv
index eb4fbd8407a441c33b8bb8f0286f4057b08b232d..e25521c1aca0b499797ef8eb945cf1c8f9bbb076 100644 (file)
@@ -360,6 +360,30 @@ void EMetaBlob::update_segment(LogSegment *ls)
     //    ls->last_client_tid[client_reqs.rbegin()->client] = client_reqs.rbegin()->tid);
 }
 
+void EMetaBlob::fullbit::update_inode(CInode *in)
+{
+  in->inode = inode;
+  in->xattrs = xattrs;
+  if (in->inode.is_dir()) {
+    if (!(in->dirfragtree == dirfragtree)) {
+      in->dirfragtree = dirfragtree;
+      in->force_dirfrags();
+    }
+
+    delete in->default_layout;
+    in->default_layout = dir_layout;
+    dir_layout = NULL;
+    /*
+     * we can do this before linking hte inode bc the split_at would
+     * be a no-op.. we have no children (namely open snaprealms) to
+     * divy up 
+     */
+    in->decode_snap_blob(snapbl);  
+  } else if (in->inode.is_symlink()) {
+    in->symlink = symlink;
+  }
+}
+
 void EMetaBlob::replay(MDS *mds, LogSegment *logseg)
 {
   dout(10) << "EMetaBlob.replay " << lump_map.size() << " dirlumps by " << client_name << dendl;