From a5abd544ee2993a68930bcfebddc059af4ee7ee5 Mon Sep 17 00:00:00 2001 From: Yehuda Sadeh Date: Thu, 7 Jan 2010 15:36:32 -0800 Subject: [PATCH] --- yaml --- r: 188675 b: refs/heads/master c: 4baa75ef0ed29adae03fcbbaa9aca1511a5a8cc9 h: refs/heads/master i: 188673: 1b2bb07b53a7ee70f9f3876d69095a216b6a077b 188671: 29c5afa9813f13b8c5f4b4c8f6f96ac2b2556705 v: v3 --- [refs] | 2 +- trunk/fs/ceph/inode.c | 29 +++++++++++++++++++++++++++++ 2 files changed, 30 insertions(+), 1 deletion(-) diff --git a/[refs] b/[refs] index 4248570ba978..687683a3d3ac 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 6a4ef48103a78a46b80e07fcd8ac4edda0c7128f +refs/heads/master: 4baa75ef0ed29adae03fcbbaa9aca1511a5a8cc9 diff --git a/trunk/fs/ceph/inode.c b/trunk/fs/ceph/inode.c index 8774b2811597..518beb628f09 100644 --- a/trunk/fs/ceph/inode.c +++ b/trunk/fs/ceph/inode.c @@ -816,6 +816,33 @@ static struct dentry *splice_dentry(struct dentry *dn, struct inode *in, return dn; } +/* + * Set dentry's directory position based on the current dir's max, and + * order it in d_subdirs, so that dcache_readdir behaves. + */ +static void ceph_set_dentry_offset(struct dentry *dn) +{ + struct dentry *dir = dn->d_parent; + struct inode *inode = dn->d_parent->d_inode; + struct ceph_dentry_info *di; + + BUG_ON(!inode); + + di = ceph_dentry(dn); + + spin_lock(&inode->i_lock); + di->offset = ceph_inode(inode)->i_max_offset++; + spin_unlock(&inode->i_lock); + + spin_lock(&dcache_lock); + spin_lock(&dn->d_lock); + list_move_tail(&dir->d_subdirs, &dn->d_u.d_child); + dout("set_dentry_offset %p %lld (%p %p)\n", dn, di->offset, + dn->d_u.d_child.prev, dn->d_u.d_child.next); + spin_unlock(&dn->d_lock); + spin_unlock(&dcache_lock); +} + /* * Incorporate results into the local cache. This is either just * one inode, or a directory, dentry, and possibly linked-to inode (e.g., @@ -987,6 +1014,7 @@ int ceph_fill_trace(struct super_block *sb, struct ceph_mds_request *req, goto done; } req->r_dentry = dn; /* may have spliced */ + ceph_set_dentry_offset(dn); igrab(in); } else if (ceph_ino(in) == vino.ino && ceph_snap(in) == vino.snap) { @@ -1029,6 +1057,7 @@ int ceph_fill_trace(struct super_block *sb, struct ceph_mds_request *req, err = PTR_ERR(dn); goto done; } + ceph_set_dentry_offset(dn); req->r_dentry = dn; /* may have spliced */ igrab(in); rinfo->head->is_dentry = 1; /* fool notrace handlers */