aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ceph/inode.c
diff options
context:
space:
mode:
authorYehuda Sadeh <yehuda@hq.newdream.net>2010-01-07 18:36:32 -0500
committerSage Weil <sage@newdream.net>2010-01-14 15:23:14 -0500
commit4baa75ef0ed29adae03fcbbaa9aca1511a5a8cc9 (patch)
treef3ba17caa2a8738eff064b611c1d7bb0610f3037 /fs/ceph/inode.c
parent6a4ef48103a78a46b80e07fcd8ac4edda0c7128f (diff)
ceph: change dentry offset and position after splice_dentry
This fixes a bug, where we had the parent list have dentries with offsets that are not monotonically increasing, which caused the ceph dcache_readdir to skip entries. Signed-off-by: Yehuda Sadeh <yehuda@hq.newdream.net> Signed-off-by: Sage Weil <sage@newdream.net>
Diffstat (limited to 'fs/ceph/inode.c')
-rw-r--r--fs/ceph/inode.c29
1 files changed, 29 insertions, 0 deletions
diff --git a/fs/ceph/inode.c b/fs/ceph/inode.c
index 8774b2811597..518beb628f09 100644
--- a/fs/ceph/inode.c
+++ b/fs/ceph/inode.c
@@ -817,6 +817,33 @@ out:
817} 817}
818 818
819/* 819/*
820 * Set dentry's directory position based on the current dir's max, and
821 * order it in d_subdirs, so that dcache_readdir behaves.
822 */
823static void ceph_set_dentry_offset(struct dentry *dn)
824{
825 struct dentry *dir = dn->d_parent;
826 struct inode *inode = dn->d_parent->d_inode;
827 struct ceph_dentry_info *di;
828
829 BUG_ON(!inode);
830
831 di = ceph_dentry(dn);
832
833 spin_lock(&inode->i_lock);
834 di->offset = ceph_inode(inode)->i_max_offset++;
835 spin_unlock(&inode->i_lock);
836
837 spin_lock(&dcache_lock);
838 spin_lock(&dn->d_lock);
839 list_move_tail(&dir->d_subdirs, &dn->d_u.d_child);
840 dout("set_dentry_offset %p %lld (%p %p)\n", dn, di->offset,
841 dn->d_u.d_child.prev, dn->d_u.d_child.next);
842 spin_unlock(&dn->d_lock);
843 spin_unlock(&dcache_lock);
844}
845
846/*
820 * Incorporate results into the local cache. This is either just 847 * Incorporate results into the local cache. This is either just
821 * one inode, or a directory, dentry, and possibly linked-to inode (e.g., 848 * one inode, or a directory, dentry, and possibly linked-to inode (e.g.,
822 * after a lookup). 849 * after a lookup).
@@ -987,6 +1014,7 @@ int ceph_fill_trace(struct super_block *sb, struct ceph_mds_request *req,
987 goto done; 1014 goto done;
988 } 1015 }
989 req->r_dentry = dn; /* may have spliced */ 1016 req->r_dentry = dn; /* may have spliced */
1017 ceph_set_dentry_offset(dn);
990 igrab(in); 1018 igrab(in);
991 } else if (ceph_ino(in) == vino.ino && 1019 } else if (ceph_ino(in) == vino.ino &&
992 ceph_snap(in) == vino.snap) { 1020 ceph_snap(in) == vino.snap) {
@@ -1029,6 +1057,7 @@ int ceph_fill_trace(struct super_block *sb, struct ceph_mds_request *req,
1029 err = PTR_ERR(dn); 1057 err = PTR_ERR(dn);
1030 goto done; 1058 goto done;
1031 } 1059 }
1060 ceph_set_dentry_offset(dn);
1032 req->r_dentry = dn; /* may have spliced */ 1061 req->r_dentry = dn; /* may have spliced */
1033 igrab(in); 1062 igrab(in);
1034 rinfo->head->is_dentry = 1; /* fool notrace handlers */ 1063 rinfo->head->is_dentry = 1; /* fool notrace handlers */