From 5dd9f1a17cc187bb0697ea47493998a7c43aed01 Mon Sep 17 00:00:00 2001 From: Sage Weil Date: Thu, 28 Feb 2008 09:50:13 -0800 Subject: [PATCH] mds: projected_parent on inode to allow concurrent rename and inode updates (due to cap changes) 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 | 5 ++++- src/mds/CInode.h | 8 +++++++- src/mds/Server.cc | 3 +++ 3 files changed, 14 insertions(+), 2 deletions(-) diff --git a/src/mds/CInode.cc b/src/mds/CInode.cc index a5db68f70b2f3..a358a7aaf2c18 100644 --- a/src/mds/CInode.cc +++ b/src/mds/CInode.cc @@ -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) diff --git a/src/mds/CInode.h b/src/mds/CInode.h index 9c4ac07b15220..5f77210cae371 100644 --- a/src/mds/CInode.h +++ b/src/mds/CInode.h @@ -191,6 +191,7 @@ public: // parent dentries in cache CDentry *parent; // primary link set remote_parents; // if hard linked + CDentry *projected_parent; // for in-progress rename pair 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); diff --git a/src/mds/Server.cc b/src/mds/Server.cc index 0634e012d0419..43a281183fe7b 100644 --- a/src/mds/Server.cc +++ b/src/mds/Server.cc @@ -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()); -- 2.39.5