]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
mds: projected_parent on inode to allow concurrent rename and inode updates (due...
authorSage Weil <sage@newdream.net>
Thu, 28 Feb 2008 17:50:13 +0000 (09:50 -0800)
committerSage Weil <sage@newdream.net>
Thu, 28 Feb 2008 17:50:13 +0000 (09:50 -0800)
The problem is that a cap update would give a new mtime mid-rename.  Locker would pre-dirty the inode and _old_ parent dentry, and when it went to apply the projected update, it would have a pv from the old dentry and use it to dirty the new parent dentry.  Now, rename sets projected_parent in _rename_prepare and clears it via CDir::link_inode, and pre_dirty follows that pointer when present.

src/mds/CInode.cc
src/mds/CInode.h
src/mds/Server.cc

index a5db68f70b2f37bcebfab8330de6879956ae4a93..a358a7aaf2c185b3aa12671961e561701f70d305 100644 (file)
@@ -407,7 +407,10 @@ void CInode::name_stray_dentry(string& dname)
 version_t CInode::pre_dirty()
 {    
   assert(parent);
-  return parent->pre_dirty();
+  if (projected_parent)
+    return projected_parent->pre_dirty();
+  else
+    return parent->pre_dirty();
 }
 
 void CInode::_mark_dirty(LogSegment *ls)
index 9c4ac07b152201b1a686646177f12cd85ecb85b8..5f77210cae371038a789cfe8fbe39897d3a7e72d 100644 (file)
@@ -191,6 +191,7 @@ public:
   // parent dentries in cache
   CDentry         *parent;             // primary link
   set<CDentry*>    remote_parents;     // if hard linked
+  CDentry         *projected_parent;   // for in-progress rename
 
   pair<int,int> inode_auth;
 
@@ -236,7 +237,8 @@ public:
     last_journaled(0), last_open_journaled(0), 
     //hack_accessed(true),
     stickydir_ref(0),
-    parent(0), inode_auth(CDIR_AUTH_DEFAULT),
+    parent(0), projected_parent(0),
+    inode_auth(CDIR_AUTH_DEFAULT),
     replica_caps_wanted(0),
     xlist_dirty(this), xlist_open_file(this), 
     xlist_dirty_inode_mtime(this), xlist_purging_inode(this),
@@ -505,6 +507,10 @@ public:
   void set_primary_parent(CDentry *p) {
     assert(parent == 0);
     parent = p;
+    if (projected_parent) {
+      assert(projected_parent == p);
+      projected_parent = 0;
+    }
   }
   void remove_primary_parent(CDentry *dn) {
     assert(dn == parent);
index 0634e012d041988d0eec829bc75ed64f0efb05dc..43a281183fe7b4f369e441420cb2f22f9bda8082 100644 (file)
@@ -3130,6 +3130,7 @@ void Server::_rename_prepare(MDRequest *mdr,
     if (destdn->is_auth())
       ipv = mdr->more()->pvmap[destdn] = destdn->pre_dirty(destdn->inode->inode.version);
     ji = metablob->add_primary_dentry(destdn, true, destdn->inode); 
+    destdn->inode->projected_parent = destdn;
     
     // do src dentry
     metablob->add_dir_context(srcdn->dir);
@@ -3148,6 +3149,7 @@ void Server::_rename_prepare(MDRequest *mdr,
       if (straydn->is_auth())
        ipv = mdr->more()->pvmap[straydn] = straydn->pre_dirty(destdn->inode->inode.version);
       ji = metablob->add_primary_dentry(straydn, true, destdn->inode);
+      destdn->inode->projected_parent = straydn;
     } 
     else if (destdn->is_remote()) {
       // remote.
@@ -3197,6 +3199,7 @@ void Server::_rename_prepare(MDRequest *mdr,
        mdr->more()->pvmap[destdn] = destdn->pre_dirty(siv+1);
       }
       metablob->add_primary_dentry(destdn, true, srcdn->inode); 
+      srcdn->inode->projected_parent = destdn;
 
     } else {
       assert(srcdn->is_remote());