]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
mds: handle freeze completion delayed by frozen inode
authorSage Weil <sage@newdream.net>
Thu, 28 Apr 2011 00:07:54 +0000 (17:07 -0700)
committerSage Weil <sage@newdream.net>
Thu, 28 Apr 2011 00:07:54 +0000 (17:07 -0700)
We can't complete a freeze_tree if we are not a subtree and the parent
inode is frozen.  If that's the case, we were just doing nothing on the
auth_unpin, but that means the freeze_tree would never complete.

Instead, retake an auth_pin (on behalf of the parent) and release it when
the parent inode unfreezes.

Signed-off-by: Sage Weil <sage@newdream.net>
src/mds/CDir.cc
src/mds/CDir.h

index 364fddd01ff0575b2a7aa004b847b550ffdb58f9..ece3404024b54fc78147e7a0b86ce5f246aff5a7 100644 (file)
@@ -2498,6 +2498,45 @@ CDir *CDir::get_frozen_tree_root()
   }
 }
 
+struct C_Dir_AuthUnpin : public Context {
+  CDir *dir;
+  C_Dir_AuthUnpin(CDir *d) : dir(d) {}
+  void finish(int r) {
+    dir->auth_unpin(dir->get_inode());
+  }
+};
+
+void CDir::maybe_finish_freeze()
+{
+  if (auth_pins != 1 || dir_auth_pins != 0)
+    return;
+
+  // we can freeze the _dir_ even with nested pins...
+  if (state_test(STATE_FREEZINGDIR)) {
+    _freeze_dir();
+    auth_unpin(this);
+    finish_waiting(WAIT_FROZEN);
+  }
+
+  if (nested_auth_pins != 0)
+    return;
+
+  if (state_test(STATE_FREEZINGTREE)) {
+    if (!is_subtree_root() && inode->is_frozen()) {
+      dout(10) << "maybe_finish_freeze !subtree root and frozen inode, waiting for unfreeze on " << inode << dendl;
+      // retake an auth_pin...
+      auth_pin(inode);
+      // and release it when the parent inode unfreezes
+      inode->add_waiter(WAIT_UNFREEZE, new C_Dir_AuthUnpin(this));
+      return;
+    }
+
+    _freeze_tree();
+    auth_unpin(this);
+    finish_waiting(WAIT_FROZEN);
+  }
+}
+
 
 
 // FREEZE DIR
index 4389193e214da549bfe249757fa707ef9914de89..94942dd8109fe960981dc01181b2c22f7472871f 100644 (file)
@@ -571,26 +571,7 @@ public:
   void _freeze_dir();
   void unfreeze_dir();
 
-  void maybe_finish_freeze() {
-    if (auth_pins != 1 ||
-       dir_auth_pins != 0)
-      return;
-    // we can freeze the _dir_ even with nested pins...
-    if (state_test(STATE_FREEZINGDIR)) {
-      _freeze_dir();
-      auth_unpin(this);
-      finish_waiting(WAIT_FROZEN);
-    }
-    if (nested_auth_pins != 0) 
-      return;
-    if (!is_subtree_root() && inode->is_frozen())
-      return;
-    if (state_test(STATE_FREEZINGTREE)) {
-      _freeze_tree();
-      auth_unpin(this);
-      finish_waiting(WAIT_FROZEN);
-    }
-  }
+  void maybe_finish_freeze();
 
   bool is_freezing() { return is_freezing_tree() || is_freezing_dir(); }
   bool is_freezing_tree();