]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
* fixed client cache bug with relinking
authorsageweil <sageweil@29311d96-e01e-0410-9327-a35deaab8ce9>
Wed, 27 Jun 2007 22:58:26 +0000 (22:58 +0000)
committersageweil <sageweil@29311d96-e01e-0410-9327-a35deaab8ce9>
Wed, 27 Jun 2007 22:58:26 +0000 (22:58 +0000)
git-svn-id: https://ceph.svn.sf.net/svnroot/ceph@1451 29311d96-e01e-0410-9327-a35deaab8ce9

branches/sage/cephmds2/client/Client.cc
branches/sage/cephmds2/client/Client.h

index 8b65c76c1ebab017441b72be019fb1fdb757c5a1..c53c6b1693a5d03bc64e43951303e479084d238a 100644 (file)
@@ -301,7 +301,7 @@ Inode* Client::insert_inode(Dir *dir, InodeStat *st, const string& dname)
         dout(12) << " had ino " << in->inode.ino
                  << " linked at wrong position, unlinking"
                  << endl;
-        dn = relink(in->dn, dir, dname);
+        dn = relink(dir, dname, in);
       } else {
         // link
         dout(12) << " had ino " << in->inode.ino
index 6b1eb75298c63db1ae2652c15d973a1bc589fc71..2289803ea9594455dbb45921c0a9c5654185b5e9 100644 (file)
@@ -274,7 +274,7 @@ class Inode {
   Dir *open_dir() {
     if (!dir) {
       if (dn) dn->get();      // pin dentry
-      get();
+      get();                  // pin inode
       dir = new Dir(this);
     }
     return dir;
@@ -448,7 +448,7 @@ protected:
     
     delete in->dir;
     in->dir = 0;
-    put_inode(in);
+    put_inode(in);               // unpin inode
   }
 
   int get_cache_size() { return lru.lru_get_size(); }
@@ -468,6 +468,8 @@ protected:
     in->dn = dn;
     in->get();
 
+    if (in->dir) dn->get();  // dir -> dn pin
+
     lru.lru_insert_mid(dn);    // mid or top?
     return dn;
   }
@@ -476,6 +478,7 @@ protected:
     Inode *in = dn->inode;
 
     // unlink from inode
+    if (dn->inode->dir) dn->put();        // dir -> dn pin
     dn->inode = 0;
     in->dn = 0;
     put_inode(in);
@@ -491,29 +494,37 @@ protected:
     delete dn;
   }
 
-  Dentry *relink(Dentry *dn, Dir *dir, const string& name) {
-    // first link new dn to dir
-    /*
-    char *oldname = (char*)dn->name;
-    dn->name = new char[name.length()+1];
-    strcpy((char*)dn->name, name.c_str());
-    dir->dentries[dn->name] = dn;
-    */
-    //cout << "relink dir " << dir->parent_inode->inode.ino << " '" << name << "' -> inode " << dn->inode->inode.ino << endl;
+  Dentry *relink(Dir *dir, const string& name, Inode *in) {
+    Dentry *olddn = in->dn;
+    Dir *olddir = olddn->dir;  // note: might == dir!
 
-    dir->dentries[name] = dn;
+    // newdn, attach to inode.  don't touch inode ref.
+    Dentry *newdn = new Dentry;
+    newdn->name = name;
+    newdn->inode = in;
+    newdn->dir = dir;
+    in->dn = newdn;
 
-    // unlink from old dir
-    dn->dir->dentries.erase(dn->name);
-    //delete[] oldname;
-    if (dn->dir->is_empty()) 
-      close_dir(dn->dir);
+    if (in->dir) { // dir -> dn pin
+      newdn->get();
+      olddn->put();
+    }
 
-    // fix up dn
-    dn->name = name;
-    dn->dir = dir;
+    // unlink old dn from dir
+    olddir->dentries.erase(olddn->name);
+    olddn->inode = 0;
+    olddn->dir = 0;
+    lru.lru_remove(olddn);
+    
+    // link new dn to dir
+    dir->dentries[name] = newdn;
+    lru.lru_insert_mid(newdn);
+    
+    // olddir now empty?  (remember, olddir might == dir)
+    if (olddir->is_empty()) 
+      close_dir(olddir);
 
-    return dn;
+    return newdn;
   }
 
   // move dentry to top of lru