]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
Fix a crash when unmounting due to wrong dentry accounting. Don't allocate new dentri...
authorYehuda Sadeh-Weinraub <yehuda@yehuda.infit.com>
Thu, 10 Jan 2008 14:18:06 +0000 (16:18 +0200)
committerYehuda Sadeh-Weinraub <yehuda@yehuda.infit.com>
Thu, 10 Jan 2008 14:18:06 +0000 (16:18 +0200)
src/kernel/dir.c

index 7c5e5f803b1406cc324f6062c4ad22b885ae72e1..e973a8aa638d2d0a8a5cd954193b1b330fd8db90 100644 (file)
@@ -87,26 +87,34 @@ nextfrag:
                        dname.name = fi->rinfo.dir_dname[i];
                        dname.len = fi->rinfo.dir_dname_len[i];
                        dname.hash = full_name_hash(dname.name, dname.len);
-                       dn = d_alloc(parent, &dname);
-                       if (dn == NULL) {
-                               dout(30, "d_alloc badness\n");
-                               break; 
-                       }
-                       in = new_inode(parent->d_sb);
-                       if (in == NULL) {
-                               dout(30, "new_inode badness\n");
-                               d_delete(dn);
-                               break;
-                       }
-                       if (ceph_fill_inode(in, fi->rinfo.dir_in[i].in) < 0) {
-                               dout(30, "ceph_fill_inode badness\n");
-                               iput(in);
-                               d_delete(dn);
-                               break;
+
+                       dn = d_lookup(parent, &dname);
+                       dout(30, "calling d_lookup on parent=%p name=%s returned %p\n", parent, dname.name, dn);
+
+                       if (!dn) {
+                               dn = d_alloc(parent, &dname);
+                               if (dn == NULL) {
+                                       dout(30, "d_alloc badness\n");
+                                       break; 
+                               }
+                               in = new_inode(parent->d_sb);
+                               if (in == NULL) {
+                                       dout(30, "new_inode badness\n");
+                                       d_delete(dn);
+                                       break;
+                               }
+                               if (ceph_fill_inode(in, fi->rinfo.dir_in[i].in) < 0) {
+                                       dout(30, "ceph_fill_inode badness\n");
+                                       iput(in);
+                                       d_delete(dn);
+                                       break;
+                               }
+                               d_add(dn, in);
+                               dout(10, "dir_readdir added dentry %p inode %lu %d/%d\n",
+                                    dn, in->i_ino, i, fi->rinfo.dir_nr);
                        }
-                       d_add(dn, in);
-                       dout(10, "dir_readdir added dentry %p inode %lu %d/%d\n",
-                            dn, in->i_ino, i, fi->rinfo.dir_nr);
+
+                       dput(dn);
                }
        }       
        
@@ -146,6 +154,9 @@ const struct file_operations ceph_dir_fops = {
        .release = ceph_release,
 };
 
+struct dentry_operations ceph_dentry_ops = {
+       .d_revalidate = NULL,
+};
 
 
 static struct dentry *ceph_dir_lookup(struct inode *dir, struct dentry *dentry,
@@ -173,6 +184,12 @@ static struct dentry *ceph_dir_lookup(struct inode *dir, struct dentry *dentry,
                return ERR_PTR(err);
        err = le32_to_cpu(rinfo.head->result);
        dout(20, "dir_readdir result=%d\n", err);
+
+       /* if there was a previous inode associated with this dentry, now there isn't one */
+       if (err == -ENOENT) {
+               d_add(dentry, NULL);
+       }
+
        if (err < 0) 
                return ERR_PTR(err);