]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
mds: update dir parent pointer on rename
authorSage Weil <sage@newdream.net>
Tue, 25 Aug 2009 21:56:23 +0000 (14:56 -0700)
committerSage Weil <sage@newdream.net>
Tue, 25 Aug 2009 21:56:23 +0000 (14:56 -0700)
Maintain per-segment list and inode flag for this purpose.
Flush out changes on log segment trim.

Also remove from renamed list if we commit first frag (which also
writes a parent pointer each time).

src/TODO
src/mds/CDir.cc
src/mds/CDir.h
src/mds/CInode.cc
src/mds/CInode.h
src/mds/LogSegment.h
src/mds/Server.cc
src/mds/journal.cc
src/mds/mdstypes.h

index 7aa9c88187cc2f4bab690fc5caaef23057c1463a..494a9b5717c4930d0932298c71b6b477e72f0400 100644 (file)
--- a/src/TODO
+++ b/src/TODO
@@ -56,9 +56,6 @@ rados
 - security
 
 repair
-- repair metadata.. 
-/  - parent pointer on CDir objects
-  - update on dir rename commit
 - namespace reconstruction tool
 - repair pg (rebuild log)  (online or offline?  ./cosd --repair_pg 1.ef?)
 - repair file ioctl?
@@ -69,11 +66,6 @@ repair
 - data object 
   - path backpointers?
   - parent dir pointer?
-- cdir objects
-  - parent dir pointer
-    - update on rename?  or on cdir store?
-      on cdir store is sufficient if mdlog survives...
-  - or what the hell, full trace?
 - mds scrubbing
 
 kclient
index 5fef3e6846ee99c2bc8470d07fa05e5e45bd70d6..b491e979e51ecb7eb08b681287044e014a675b37 100644 (file)
@@ -1358,11 +1358,11 @@ public:
 
 class C_Dir_Committed : public Context {
   CDir *dir;
-  version_t version;
+  version_t version, last_renamed_version;
 public:
-  C_Dir_Committed(CDir *d, version_t v) : dir(d), version(v) { }
+  C_Dir_Committed(CDir *d, version_t v, version_t lrv) : dir(d), version(v), last_renamed_version(lrv) { }
   void finish(int r) {
-    dir->_committed(version);
+    dir->_committed(version, last_renamed_version);
   }
 };
 
@@ -1587,6 +1587,10 @@ void CDir::_commit(version_t want)
     _commit_partial(m, snaps);
   }
 
+  // update parent pointer while we're here.
+  //  NOTE: the pointer is ONLY required to be valid for the first frag.  we put the xattr
+  //        on other frags too because it can't hurt, but it won't necessarily be up to date
+  //        in that case!!
   inode->encode_parent_mutation(m);
 
   SnapContext snapc;
@@ -1596,7 +1600,7 @@ void CDir::_commit(version_t want)
                                                     cache->mds->mdsmap->get_metadata_pg_pool());
 
   cache->mds->objecter->mutate(oid, ol, m, snapc, g_clock.now(), 0,
-                              NULL, new C_Dir_Committed(this, get_version()) );
+                              NULL, new C_Dir_Committed(this, get_version(), inode->inode.last_renamed_version) );
 }
 
 
@@ -1605,10 +1609,19 @@ void CDir::_commit(version_t want)
  *
  * @param v version i just committed
  */
-void CDir::_committed(version_t v)
+void CDir::_committed(version_t v, version_t lrv)
 {
-  dout(10) << "_committed v " << v << " on " << *this << dendl;
+  dout(10) << "_committed v " << v << " (last renamed " << lrv << ") on " << *this << dendl;
   assert(is_auth());
+
+  // did we update the parent pointer too?
+  if (get_frag() == frag_t() &&     // only counts on first frag
+      inode->state_test(CInode::STATE_DIRTYPARENT) &&
+      lrv == inode->inode.last_renamed_version) {
+    inode->xlist_renamed_file.remove_myself();
+    inode->state_clear(CInode::STATE_DIRTYPARENT);
+    dout(10) << "_committed  stored parent pointer, removed from renamed_files list " << *inode << dendl;
+  }
   
   // take note.
   assert(v > committed_version);
index 25ecc4d36c4d70c9516b9383b7102d405d7b4cd3..fb342e255086ce979be43b1695ce68d82b4c32aa 100644 (file)
@@ -443,7 +443,7 @@ private:
   void _commit_full(ObjectOperation& m, const set<snapid_t> *snaps);
   void _commit_partial(ObjectOperation& m, const set<snapid_t> *snaps);
   void _encode_dentry(CDentry *dn, bufferlist& bl, const set<snapid_t> *snaps);
-  void _committed(version_t v);
+  void _committed(version_t v, version_t last_renamed_version);
   void wait_for_commit(Context *c, version_t v=0);
 
   // -- dirtyness --
index 6bcdb09ae12c42de85575c383db7b0e3ea84a5a5..6ddbb59769f3a5b5447a5603385c264792592b55 100644 (file)
@@ -101,6 +101,7 @@ ostream& operator<<(ostream& out, CInode& in)
   if (in.state_test(CInode::STATE_AMBIGUOUSAUTH)) out << " AMBIGAUTH";
   if (in.state_test(CInode::STATE_NEEDSRECOVER)) out << " needsrecover";
   if (in.state_test(CInode::STATE_RECOVERING)) out << " recovering";
+  if (in.state_test(CInode::STATE_DIRTYPARENT)) out << " dirtyparent";
   if (in.is_freezing_inode()) out << " FREEZING=" << in.auth_pin_freeze_allowance;
   if (in.is_frozen_inode()) out << " FROZEN";
 
@@ -736,10 +737,11 @@ void CInode::_fetched(bufferlist& bl, Context *fin)
 
 struct C_Inode_StoredParent : public Context {
   CInode *in;
+  version_t version;
   Context *fin;
-  C_Inode_StoredParent(CInode *i, Context *f) : in(i), fin(f) {}
+  C_Inode_StoredParent(CInode *i, version_t v, Context *f) : in(i), version(v), fin(f) {}
   void finish(int r) {
-    in->_stored_parent(fin);
+    in->_stored_parent(version, fin);
   }
 };
 
@@ -780,13 +782,20 @@ void CInode::store_parent(Context *fin)
                                                     mdcache->mds->mdsmap->get_metadata_pg_pool());
 
   mdcache->mds->objecter->mutate(oid, ol, m, snapc, g_clock.now(), 0,
-                                NULL, new C_Inode_StoredParent(this, fin) );
+                                NULL, new C_Inode_StoredParent(this, inode.last_renamed_version, fin) );
 
 }
 
-void CInode::_stored_parent(Context *fin)
+void CInode::_stored_parent(version_t v, Context *fin)
 {
-  dout(10) << "stored_parent" << dendl;
+  if (v == inode.last_renamed_version) {
+    dout(10) << "stored_parent committed v" << v << ", removing from list" << dendl;
+    xlist_renamed_file.remove_myself();
+    state_clear(STATE_DIRTYPARENT);
+  } else {
+    dout(10) << "stored_parent committed v" << v << " < " << inode.last_renamed_version
+            << ", renamed again, not removing from list" << dendl;
+  }
   if (fin) {
     fin->finish(0);
     delete fin;
index 0963a4b764022de37c98dc2072ed507b6d983b2f..695c7802d033e453612878b124a0a8ed676f738b 100644 (file)
@@ -124,6 +124,7 @@ public:
   static const int STATE_NEEDSRECOVER = (1<<11);
   static const int STATE_RECOVERING =   (1<<12);
   static const int STATE_PURGING =     (1<<13);
+  static const int STATE_DIRTYPARENT =  (1<<14);
 
   // -- waiters --
   static const __u64 WAIT_DIR         = (1<<0);
@@ -272,6 +273,7 @@ protected:
 public:
   xlist<CInode*>::item xlist_caps;
   xlist<CInode*>::item xlist_open_file;
+  xlist<CInode*>::item xlist_renamed_file;
   xlist<CInode*>::item xlist_dirty_dirfrag_dir;
   xlist<CInode*>::item xlist_dirty_dirfrag_nest;
   xlist<CInode*>::item xlist_dirty_dirfrag_dirfragtree;
@@ -312,7 +314,7 @@ private:
     parent(0),
     inode_auth(CDIR_AUTH_DEFAULT),
     replica_caps_wanted(0),
-    xlist_dirty(this), xlist_caps(this), xlist_open_file(this), 
+    xlist_dirty(this), xlist_caps(this), xlist_open_file(this), xlist_renamed_file(this), 
     xlist_dirty_dirfrag_dir(this), 
     xlist_dirty_dirfrag_nest(this), 
     xlist_dirty_dirfrag_dirfragtree(this), 
@@ -401,7 +403,7 @@ private:
   void _fetched(bufferlist& bl, Context *fin);  
 
   void store_parent(Context *fin);
-  void _stored_parent(Context *fin);
+  void _stored_parent(version_t v, Context *fin);
 
   void encode_parent_mutation(ObjectOperation& m);
 
index 0b765f8cd3b7bca67283aea9d477a5ff097a5bd1..0bfdbfe372a046cfd1e17e2f8453d088245c515b 100644 (file)
@@ -41,6 +41,7 @@ class LogSegment {
   xlist<CDentry*> dirty_dentries;
 
   xlist<CInode*>  open_files;
+  xlist<CInode*>  renamed_files;
   xlist<CInode*>  dirty_dirfrag_dir;
   xlist<CInode*>  dirty_dirfrag_nest;
   xlist<CInode*>  dirty_dirfrag_dirfragtree;
index 2f093689b2aa8bcea2f0b7af7f24ff76312bdda4..77becf9776105cce7570505ccca9cc723d1aaf69 100644 (file)
@@ -4246,6 +4246,7 @@ void Server::_rename_prepare(MDRequest *mdr,
 
   if (!silent) {
     if (pi) {
+      pi->last_renamed_version = pi->version;
       pi->ctime = mdr->now;
       if (linkmerge)
        pi->nlink--;
@@ -4456,7 +4457,15 @@ void Server::_rename_apply(MDRequest *mdr, CDentry *srcdn, CDentry *destdn, CDen
     }
 
     if (destdn->is_auth()) {
-      destdnl->get_inode()->pop_and_dirty_projected_inode(mdr->ls);
+      CInode *desti = destdnl->get_inode();
+      desti->pop_and_dirty_projected_inode(mdr->ls);
+
+      
+      if (desti->is_dir()) {
+       mdr->ls->renamed_files.push_back(&desti->xlist_renamed_file);
+       desti->state_set(CInode::STATE_DIRTYPARENT);
+       dout(10) << "added dir to logsegment renamed_files list " << *desti << dendl;
+      }
     }
 
     // snap parent update?
index e26f2d6f7db465033c8b6c851a7dfdd93f61219b..0df174473aa61dc2ba0ca95092b266ec358a25a0 100644 (file)
@@ -174,6 +174,15 @@ C_Gather *LogSegment::try_to_expire(MDS *mds)
     }
   }
 
+  // parent pointers on renamed dirs
+  for (xlist<CInode*>::iterator p = renamed_files.begin(); !p.end(); ++p) {
+    CInode *in = *p;
+    dout(10) << "try_to_expire waiting for dir parent pointer update on " << *in << dendl;
+    assert(in->state_test(CInode::STATE_DIRTYPARENT));
+    if (!gather) gather = new C_Gather;
+    in->store_parent(gather->new_sub());
+  }
+
   // slave updates
   for (xlist<MDSlaveUpdate*>::iterator p = slave_updates.begin(); !p.end(); ++p) {
     MDSlaveUpdate *su = *p;
index 42bdd122b790b19cdf8af7a5637a25b048fd1d2c..f585f5d6b9920c8cecf606d5c5a19dc21b4f4307 100644 (file)
@@ -356,12 +356,14 @@ struct inode_t {
   version_t file_data_version; // auth only
   version_t xattr_version;
 
+  version_t last_renamed_version;      // when i was last renamed
+
   inode_t() : ino(0), rdev(0),
              mode(0), uid(0), gid(0),
              nlink(0), anchored(false),
              size(0), truncate_seq(0), truncate_size(0), truncate_from(0),
              time_warp_seq(0),
-             version(0), file_data_version(0), xattr_version(0) { 
+             version(0), file_data_version(0), xattr_version(0), last_renamed_version(0) { 
     memset(&layout, 0, sizeof(layout));
   }
 
@@ -397,7 +399,7 @@ struct inode_t {
   }
 
   void encode(bufferlist &bl) const {
-    __u8 v = 1;
+    __u8 v = 2;
     ::encode(v, bl);
 
     ::encode(ino, bl);
@@ -428,6 +430,7 @@ struct inode_t {
     ::encode(version, bl);
     ::encode(file_data_version, bl);
     ::encode(xattr_version, bl);
+    ::encode(last_renamed_version, bl);
   }
   void decode(bufferlist::iterator &p) {
     __u8 v;
@@ -461,6 +464,8 @@ struct inode_t {
     ::decode(version, p);
     ::decode(file_data_version, p);
     ::decode(xattr_version, p);
+    if (v >= 2)
+      ::decode(last_renamed_version, p);
   }
 };
 WRITE_CLASS_ENCODER(inode_t)