Thanks! Added this to the testing branch. sage On Thu, 5 Dec 2013, Yan, Zheng wrote: > > > > -------- Original Message -------- > Subject: [PATCH] ceph: initialize inode before instantiating dentry > Date: Thu, 5 Dec 2013 13:45:36 +0800 > From: Yan, Zheng <zheng.z.yan@xxxxxxxxx> > To: <linux-kernel@xxxxxxxxxxxxxxx> > CC: <sage@xxxxxxxxxxx>, <dave@xxxxxxxxxxxxxxxxxx>, <malcolm@xxxxxxx>, "Yan, Zheng" <zheng.z.yan@xxxxxxxxx> > > From: "Yan, Zheng" <zheng.z.yan@xxxxxxxxx> > > commit b18825a7c8 (Put a small type field into struct dentry::d_flags) > put a type field into struct dentry::d_flags. __d_instantiate() set the > field by checking inode->i_mode. So we should initialize inode before > instantiating dentry when handling mds reply. > > Fixes: #6930 > Signed-off-by: Yan, Zheng <zheng.z.yan@xxxxxxxxx> > --- > fs/ceph/inode.c | 114 +++++++++++++++++++++----------------------------------- > 1 file changed, 43 insertions(+), 71 deletions(-) > > diff --git a/fs/ceph/inode.c b/fs/ceph/inode.c > index 9a8e396..c1a9367 100644 > --- a/fs/ceph/inode.c > +++ b/fs/ceph/inode.c > @@ -978,7 +978,6 @@ int ceph_fill_trace(struct super_block *sb, struct ceph_mds_request *req, > struct ceph_mds_reply_inode *ininfo; > struct ceph_vino vino; > struct ceph_fs_client *fsc = ceph_sb_to_client(sb); > - int i = 0; > int err = 0; > > dout("fill_trace %p is_dentry %d is_target %d\n", req, > @@ -1039,6 +1038,29 @@ int ceph_fill_trace(struct super_block *sb, struct ceph_mds_request *req, > } > } > > + if (rinfo->head->is_target) { > + vino.ino = le64_to_cpu(rinfo->targeti.in->ino); > + vino.snap = le64_to_cpu(rinfo->targeti.in->snapid); > + > + in = ceph_get_inode(sb, vino); > + if (IS_ERR(in)) { > + err = PTR_ERR(in); > + goto done; > + } > + req->r_target_inode = in; > + > + err = fill_inode(in, &rinfo->targeti, NULL, > + session, req->r_request_started, > + (le32_to_cpu(rinfo->head->result) == 0) ? > + req->r_fmode : -1, > + &req->r_caps_reservation); > + if (err < 0) { > + pr_err("fill_inode badness %p %llx.%llx\n", > + in, ceph_vinop(in)); > + goto done; > + } > + } > + > /* > * ignore null lease/binding on snapdir ENOENT, or else we > * will have trouble splicing in the virtual snapdir later > @@ -1108,7 +1130,6 @@ int ceph_fill_trace(struct super_block *sb, struct ceph_mds_request *req, > ceph_dentry(req->r_old_dentry)->offset); > > dn = req->r_old_dentry; /* use old_dentry */ > - in = dn->d_inode; > } > > /* null dentry? */ > @@ -1130,44 +1151,28 @@ int ceph_fill_trace(struct super_block *sb, struct ceph_mds_request *req, > } > > /* attach proper inode */ > - ininfo = rinfo->targeti.in; > - vino.ino = le64_to_cpu(ininfo->ino); > - vino.snap = le64_to_cpu(ininfo->snapid); > - in = dn->d_inode; > - if (!in) { > - in = ceph_get_inode(sb, vino); > - if (IS_ERR(in)) { > - pr_err("fill_trace bad get_inode " > - "%llx.%llx\n", vino.ino, vino.snap); > - err = PTR_ERR(in); > - d_drop(dn); > - goto done; > - } > + if (!dn->d_inode) { > + ihold(in); > dn = splice_dentry(dn, in, &have_lease, true); > if (IS_ERR(dn)) { > err = PTR_ERR(dn); > goto done; > } > req->r_dentry = dn; /* may have spliced */ > - ihold(in); > - } else if (ceph_ino(in) == vino.ino && > - ceph_snap(in) == vino.snap) { > - ihold(in); > - } else { > + } else if (dn->d_inode && dn->d_inode != in) { > dout(" %p links to %p %llx.%llx, not %llx.%llx\n", > - dn, in, ceph_ino(in), ceph_snap(in), > - vino.ino, vino.snap); > + dn, dn->d_inode, ceph_vinop(dn->d_inode), > + ceph_vinop(in)); > have_lease = false; > - in = NULL; > } > > if (have_lease) > update_dentry_lease(dn, rinfo->dlease, session, > req->r_request_started); > dout(" final dn %p\n", dn); > - i++; > - } else if ((req->r_op == CEPH_MDS_OP_LOOKUPSNAP || > - req->r_op == CEPH_MDS_OP_MKSNAP) && !req->r_aborted) { > + } else if (!req->r_aborted && > + (req->r_op == CEPH_MDS_OP_LOOKUPSNAP || > + req->r_op == CEPH_MDS_OP_MKSNAP)) { > struct dentry *dn = req->r_dentry; > > /* fill out a snapdir LOOKUPSNAP dentry */ > @@ -1177,52 +1182,15 @@ int ceph_fill_trace(struct super_block *sb, struct ceph_mds_request *req, > ininfo = rinfo->targeti.in; > vino.ino = le64_to_cpu(ininfo->ino); > vino.snap = le64_to_cpu(ininfo->snapid); > - in = ceph_get_inode(sb, vino); > - if (IS_ERR(in)) { > - pr_err("fill_inode get_inode badness %llx.%llx\n", > - vino.ino, vino.snap); > - err = PTR_ERR(in); > - d_delete(dn); > - goto done; > - } > dout(" linking snapped dir %p to dn %p\n", in, dn); > + ihold(in); > dn = splice_dentry(dn, in, NULL, true); > if (IS_ERR(dn)) { > err = PTR_ERR(dn); > goto done; > } > req->r_dentry = dn; /* may have spliced */ > - ihold(in); > - rinfo->head->is_dentry = 1; /* fool notrace handlers */ > } > - > - if (rinfo->head->is_target) { > - vino.ino = le64_to_cpu(rinfo->targeti.in->ino); > - vino.snap = le64_to_cpu(rinfo->targeti.in->snapid); > - > - if (in == NULL || ceph_ino(in) != vino.ino || > - ceph_snap(in) != vino.snap) { > - in = ceph_get_inode(sb, vino); > - if (IS_ERR(in)) { > - err = PTR_ERR(in); > - goto done; > - } > - } > - req->r_target_inode = in; > - > - err = fill_inode(in, > - &rinfo->targeti, NULL, > - session, req->r_request_started, > - (le32_to_cpu(rinfo->head->result) == 0) ? > - req->r_fmode : -1, > - &req->r_caps_reservation); > - if (err < 0) { > - pr_err("fill_inode badness %p %llx.%llx\n", > - in, ceph_vinop(in)); > - goto done; > - } > - } > - > done: > dout("fill_trace done err=%d\n", err); > return err; > @@ -1360,23 +1328,27 @@ retry_lookup: > } else { > in = ceph_get_inode(parent->d_sb, vino); > if (IS_ERR(in)) { > - dout("new_inode badness\n"); > - d_drop(dn); > - dput(dn); > err = PTR_ERR(in); > - goto out; > + d_drop(dn); > + goto next_item; > } > - dn = splice_dentry(dn, in, NULL, false); > - if (IS_ERR(dn)) > - dn = NULL; > } > > if (fill_inode(in, &rinfo->dir_in[i], NULL, session, > req->r_request_started, -1, > &req->r_caps_reservation) < 0) { > pr_err("fill_inode badness on %p\n", in); > + if (!dn->d_inode) > + iput(in); > + d_drop(dn); > goto next_item; > } > + > + if (!dn->d_inode) { > + dn = splice_dentry(dn, in, NULL, false); > + if (IS_ERR(dn)) > + dn = NULL; > + } > if (dn) > update_dentry_lease(dn, rinfo->dir_dlease[i], > req->r_session, > -- > 1.8.1.4 > > > > -- > To unsubscribe from this list: send the line "unsubscribe ceph-devel" in > the body of a message to majordomo@xxxxxxxxxxxxxxx > More majordomo info at http://vger.kernel.org/majordomo-info.html > > -- To unsubscribe from this list: send the line "unsubscribe ceph-devel" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html