]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
kclient: fill_trace now uses d_splice_alias
authorSage Weil <sage@newdream.net>
Mon, 5 May 2008 22:27:01 +0000 (15:27 -0700)
committerSage Weil <sage@newdream.net>
Wed, 7 May 2008 19:38:28 +0000 (12:38 -0700)
src/kernel/dir.c
src/kernel/inode.c
src/kernel/super.c
src/kernel/super.h

index 752636e1c7799426f3155f99cdbecb6acf1d5336..0f7d3c8fb54a2fd86911ce3d1349d18cb78e7bf9 100644 (file)
@@ -263,28 +263,29 @@ struct dentry *ceph_do_lookup(struct super_block *sb, struct dentry *dentry,
        dget(dentry);                /* to match put_request below */
        req->r_last_dentry = dentry; /* use this dentry in fill_trace */
        err = ceph_mdsc_do_request(mdsc, req);
-       /* no trace? */
-       if (err == -ENOENT && req->r_reply_info.trace_numd == 0) {
-               dout(20, "ENOENT and no trace, dentry %p inode %p\n",
-                    dentry, dentry->d_inode);
-               ceph_init_dentry(dentry);
-               if (dentry->d_inode) {
-                       struct dentry *new = 
-                               d_alloc(dentry->d_parent, &dentry->d_name);
-                       d_drop(dentry);
-                       dentry = new;
-               } else {
-                       d_add(dentry, NULL);
-                       dentry = 0;
+       if (err == -ENOENT) {
+               /* no trace? */
+               if (req->r_reply_info.trace_numd == 0) {
+                       dout(20, "ENOENT and no trace, dentry %p inode %p\n",
+                            dentry, dentry->d_inode);
+                       ceph_init_dentry(dentry);
+                       if (dentry->d_inode) {
+                               req->r_last_dentry = d_alloc(dentry->d_parent,
+                                                            &dentry->d_name);
+                               d_drop(dentry);
+                       } else
+                               d_add(dentry, NULL);
                }
                err = 0;
-       } else if (err)
+       }
+       if (err)
                dentry = ERR_PTR(err);
+       else if (dentry != req->r_last_dentry)
+               dentry = req->r_last_dentry;   /* we got d_splice_alias'd */
        else
                dentry = 0;
        ceph_mdsc_put_request(req);  /* will dput(dentry) */
-       dout(20, "do_lookup result=%p %d\n", dentry,
-            dentry ? atomic_read(&dentry->d_count):0);
+       dout(20, "do_lookup result=%p\n", dentry);
        return dentry;
 }
 
@@ -448,20 +449,18 @@ static int ceph_link(struct dentry *old_dentry, struct inode *dir,
        dget(dentry);                /* to match put_request below */
        req->r_last_dentry = dentry; /* use this dentry in fill_trace */
        igrab(old_dentry->d_inode);
-       req->r_last_inode = old_dentry->d_inode;
 
        ceph_mdsc_lease_release(mdsc, dir, 0, CEPH_LOCK_ICONTENT);
        err = ceph_mdsc_do_request(mdsc, req);
        ceph_mdsc_put_request(req);
-       if (!err) {
-       /*
+       if (err)
+               d_drop(dentry);
+       else if (req->r_reply_info.trace_numd == 0) {
+               /* no trace */
                igrab(old_dentry->d_inode);
                inc_nlink(old_dentry->d_inode);
                d_instantiate(dentry, old_dentry->d_inode);
-       */
-       } else
-               d_drop(dentry);
-
+       }
        return err;
 }
 
index 9b67ffe59cf78be9c43c84a18190f960cba54b2f..97fb43f28f19d3b3685d3955a6c9bacb8761d0cd 100644 (file)
@@ -42,9 +42,7 @@ struct inode *ceph_get_inode(struct super_block *sb, __u64 ino)
        }
 
        ci = ceph_inode(inode);
-#if BITS_PER_LONG == 64
        ceph_set_ino(inode, ino);
-#endif
        ci->i_hashval = inode->i_ino;
 
        dout(30, "get_inode on %lu=%llx got %p\n", inode->i_ino, ino, inode);
@@ -84,8 +82,6 @@ int ceph_fill_inode(struct inode *inode, struct ceph_mds_reply_inode *info)
             inode, info->ino, inode->i_uid, inode->i_gid,
             inode->i_size, inode->i_mode, inode->i_nlink);
 
-       ceph_set_ino(inode, le64_to_cpu(info->ino));
-
        spin_lock(&inode->i_lock);
        dout(30, " su %d, blkbits %d, blocks %llu.  v %llu, had %llu\n",
             su, blkbits, blocks, le64_to_cpu(info->version), ci->i_version);
@@ -377,7 +373,7 @@ int ceph_fill_trace(struct super_block *sb, struct ceph_mds_request *req,
        struct ceph_mds_reply_info *rinfo = &req->r_reply_info;
        int err = 0;
        struct qstr dname;
-       struct dentry *dn = sb->s_root;
+       struct dentry *dn = sb->s_root, *realdn;
        struct dentry *parent = NULL;
        struct inode *in;
        struct ceph_mds_reply_inode *ininfo;
@@ -392,7 +388,8 @@ int ceph_fill_trace(struct super_block *sb, struct ceph_mds_request *req,
        ino = le64_to_cpu(rinfo->trace_in[0].in->ino);
        if (dn) {
                in = dn->d_inode;
-               /* trace should start at root, or have only 1 dentry */
+               /* trace should start at root, or have only 1 dentry
+                * (if it is in mds stray dir) */
                WARN_ON(ino != 1 && rinfo->trace_numd != 1);
        } else {
                /* first reply (i.e. mount) */
@@ -418,18 +415,24 @@ int ceph_fill_trace(struct super_block *sb, struct ceph_mds_request *req,
 
        dget(dn);
        for (d = 0; d < rinfo->trace_numd; d++) {
-               dout(10, "fill_trace dn %d/%d dn %p in %p\n",
-                    (d+1), rinfo->trace_numd,
-                    dn, dn->d_inode);
+               dname.name = rinfo->trace_dname[d];
+               dname.len = rinfo->trace_dname_len[d];
                parent = dn;
 
+               dout(10, "fill_trace %d/%d parent %p in %p d '%.*s'\n",
+                    (d+1), rinfo->trace_numd, parent, parent->d_inode,
+                    (int)dname.len, dname.name);
+
                /* dentry */
-               ininfo = rinfo->trace_in[d+1].in;
+               dn = 0;
                if (d == rinfo->trace_numd-1 && req->r_last_dentry) {
                        dn = req->r_last_dentry;
-                       dout(10, "fill_trace using provided dentry %p\n", dn);
+                       dout(10, "fill_trace provided dn %p '%.*s'\n", dn,
+                            dn->d_name.len, dn->d_name.name);
                        ceph_init_dentry(dn);  /* just in case */
                        req->r_last_dentry = NULL;
+
+                       /* rename? */
                        if (req->r_old_dentry) {
                                dout(10, " src %p '%.*s' dst %p '%.*s'\n",
                                     req->r_old_dentry,
@@ -448,23 +451,18 @@ int ceph_fill_trace(struct super_block *sb, struct ceph_mds_request *req,
                                dn = req->r_old_dentry;  /* use old_dentry */
                                req->r_old_dentry = 0;
                        }
-               } else {
-                       dname.name = rinfo->trace_dname[d];
-                       dname.len = rinfo->trace_dname_len[d];
+                       if (dn->d_parent != parent)
+                               dout(10, "warning: d_parent %p != %p\n",
+                                    dn->d_parent, parent);
+               }
+               
+               if (!dn) {
                        dname.hash = full_name_hash(dname.name, dname.len);
-retry_lookup:
+               retry_lookup:
                        dn = d_lookup(parent, &dname);
                        dout(10, "fill_trace d_lookup of '%.*s' got %p\n",
                             (int)dname.len, dname.name, dn);
-                       if (d+1 < rinfo->trace_numi &&
-                           dn && dn->d_inode &&
-                           ceph_ino(dn->d_inode) != le64_to_cpu(ininfo->ino)) {
-                               dout(10, "fill_trace dn points to wrong ino\n");
-                               d_delete(dn);
-                               goto retry_lookup; /* may drop, be neg */
-                       }
                        if (!dn) {
-                               dout(10, "fill_trace calling d_alloc\n");
                                dn = d_alloc(parent, &dname);
                                if (!dn) {
                                        derr(0, "d_alloc enomem\n");
@@ -474,63 +472,85 @@ retry_lookup:
                                ceph_init_dentry(dn);
                        }
                }
-               if (dn->d_parent == parent)
-                       ceph_update_dentry_lease(dn, rinfo->trace_dlease[d],
-                                                session, req->r_from_time);
+               BUG_ON(!dn);
 
-               /* inode */
+               /* null dentry? */
                if (d+1 == rinfo->trace_numi) {
-                       dout(10, "fill_trace has dentry but no inode\n");
-                       if (dn->d_inode)
-                               d_delete(dn);  /* is this right? */
-                       else
-                               d_instantiate(dn, NULL);
+                       dout(10, "fill_trace null dentry\n");
+                       if (dn->d_inode) {
+                               dout(20, "d_delete %p\n", dn);
+                               d_delete(dn);
+                               dput(dn);
+                               goto retry_lookup;
+                       }
+                       dout(20, "d_instantiate %p NULL\n", dn);
+                       d_instantiate(dn, NULL);
                        if (d_unhashed(dn))
                                d_rehash(dn);
                        in = 0;
+                       ceph_update_dentry_lease(dn, rinfo->trace_dlease[d],
+                                                session, req->r_from_time);
                        break;
                }
 
-               if (!dn->d_inode) {
-                       dout(10, "fill_trace attaching inode\n");
-                       if (req->r_last_inode && ceph_ino(req->r_last_inode) ==
-                           le64_to_cpu(ininfo->ino)) {
-                               in = req->r_last_inode;
-                               igrab(in);
-                               inc_nlink(in);
-                       } else {
-                               in = ceph_get_inode(dn->d_sb,
-                                                   le64_to_cpu(ininfo->ino));
-                               if (IS_ERR(in)) {
-                                       dout(30, "new_inode badness\n");
-                                       err = PTR_ERR(in);
-                                       d_delete(dn);
-                                       dn = NULL;
-                                       in = NULL;
-                                       break;
-                               }
+               /* attach proper inode */
+               ininfo = rinfo->trace_in[d+1].in;
+               if (dn->d_inode) {
+                       if (ceph_ino(dn->d_inode) != le64_to_cpu(ininfo->ino)) {
+                               dout(10, "dn %p wrong %p ino %llx\n",
+                                    dn, dn->d_inode, ceph_ino(dn->d_inode));
+                               d_delete(dn);
+                               dput(dn);
+                               goto retry_lookup;
                        }
-                       err = ceph_fill_inode(in, ininfo);
-                       if (err < 0) {
-                               dout(30, "ceph_fill_inode badness\n");
-                               iput(in);
+                       dout(10, "dn %p correct %p ino %llx\n",
+                            dn, dn->d_inode, ceph_ino(dn->d_inode));
+                       in = dn->d_inode;
+               } else {
+                       in = ceph_get_inode(dn->d_sb, le64_to_cpu(ininfo->ino));
+                       if (IS_ERR(in)) {
+                               derr(30, "get_inode badness\n");
+                               err = PTR_ERR(in);
                                d_delete(dn);
                                dn = NULL;
+                               in = NULL;
                                break;
                        }
-                       dout(10, "fill_trace d_instantiate\n");
-                       d_instantiate(dn, in);
-                       if (d_unhashed(dn))
-                               d_rehash(dn);
-                       dout(10, "ceph_fill_trace added dentry %p"
-                            " inode %llx\n", dn, ceph_ino(in));
-               } else {
-                       in = dn->d_inode;
-                       err = ceph_fill_inode(in, ininfo);
-                       if (err < 0) {
-                               dout(30, "ceph_fill_inode badness\n");
-                               break;
+                       /* d_splice_alias wants dn unhashed */
+                       if (!d_unhashed(dn)) {
+                               dout(20, "d_drop %p\n", dn);
+                               d_drop(dn);
                        }
+                       realdn = d_splice_alias(in, dn);
+                       if (realdn) {
+                               derr(10, "dn %p spliced with %p inode %p "
+                                    "ino %llx\n", dn, realdn, realdn->d_inode, 
+                                    ceph_ino(realdn->d_inode));
+                               if (dn == req->r_last_dentry) {
+                                       dput(dn);
+                                       req->r_last_dentry = realdn;
+                               }
+                               dn = realdn;
+                               ceph_init_dentry(dn);
+                       } else
+                               dout(10, "dn %p attached to %p ino %llx\n",
+                                    dn, dn->d_inode, ceph_ino(dn->d_inode));
+               }
+               if (dn->d_parent == parent)
+                       ceph_update_dentry_lease(dn, rinfo->trace_dlease[d],
+                                                session, req->r_from_time);
+               else
+                       derr(10, "sloppy tailing dentry %p, not doing lease\n",
+                            dn);
+               BUG_ON(d_unhashed(dn));
+               
+               err = ceph_fill_inode(in, ininfo);
+               if (err < 0) {
+                       derr(30, "ceph_fill_inode badness\n");
+                       iput(in);
+                       d_delete(dn);
+                       dn = NULL;
+                       break;
                }
                ceph_update_inode_lease(dn->d_inode, rinfo->trace_ilease[d+1],
                                        session, req->r_from_time);
index cea4b8a6d92c929c13b707c98ac6e3dd038e6eca..fc8b147bfeb91e1d19e92c7efa7b53ccbe282694 100644 (file)
@@ -196,7 +196,7 @@ static void ceph_destroy_inode(struct inode *inode)
 static void init_once(struct kmem_cache *cachep, void *foo)
 {
        struct ceph_inode_info *ci = foo;
-       dout(10, "init_once on %p\n", foo);
+       dout(10, "init_once on %p\n", &ci->vfs_inode);
        inode_init_once(&ci->vfs_inode);
 }
 
index b169898819eb6cd033accc62ef3bade09d62821e..53446f122f0c38e5ced41a7f3dd484689e519a14 100644 (file)
@@ -162,7 +162,7 @@ struct ceph_inode_frag_map_item {
 #define STATIC_CAPS 2
 
 struct ceph_inode_info {
-       u64 i_ceph_ino;
+       u64 i_ceph_ino;   /* make this ifdef away on 64 bit */
 
        u64 i_version;
        u64 i_time_warp_seq;