aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ceph/inode.c
diff options
context:
space:
mode:
authorSage Weil <sage@newdream.net>2010-05-04 01:08:02 -0400
committerSage Weil <sage@newdream.net>2010-05-17 18:25:28 -0400
commit1cd3935bedccf592d44343890251452a6dd74fc4 (patch)
treeb088e425d19dbca7d7702e9f1bfa0b2dfa85eba0 /fs/ceph/inode.c
parent1b7facc41b42c2ab904b2f88b64b1f8ca0ca6cb7 (diff)
ceph: set dn offset when spliced
We want to assign an offset when the dentry goes from null to linked, which is always done by splice_dentry(). Notably, we should NOT assign an offset when a dentry is first created and is still null. BUG if we try to splice a non-null dentry (we shouldn't). Signed-off-by: Sage Weil <sage@newdream.net>
Diffstat (limited to 'fs/ceph/inode.c')
-rw-r--r--fs/ceph/inode.c71
1 files changed, 37 insertions, 34 deletions
diff --git a/fs/ceph/inode.c b/fs/ceph/inode.c
index aa22a0bce52f..1bcf98bd0255 100644
--- a/fs/ceph/inode.c
+++ b/fs/ceph/inode.c
@@ -804,6 +804,37 @@ out_unlock:
804} 804}
805 805
806/* 806/*
807 * Set dentry's directory position based on the current dir's max, and
808 * order it in d_subdirs, so that dcache_readdir behaves.
809 */
810static void ceph_set_dentry_offset(struct dentry *dn)
811{
812 struct dentry *dir = dn->d_parent;
813 struct inode *inode = dn->d_parent->d_inode;
814 struct ceph_dentry_info *di;
815
816 BUG_ON(!inode);
817
818 di = ceph_dentry(dn);
819
820 spin_lock(&inode->i_lock);
821 if ((ceph_inode(inode)->i_ceph_flags & CEPH_I_COMPLETE) == 0) {
822 spin_unlock(&inode->i_lock);
823 return;
824 }
825 di->offset = ceph_inode(inode)->i_max_offset++;
826 spin_unlock(&inode->i_lock);
827
828 spin_lock(&dcache_lock);
829 spin_lock(&dn->d_lock);
830 list_move_tail(&dir->d_subdirs, &dn->d_u.d_child);
831 dout("set_dentry_offset %p %lld (%p %p)\n", dn, di->offset,
832 dn->d_u.d_child.prev, dn->d_u.d_child.next);
833 spin_unlock(&dn->d_lock);
834 spin_unlock(&dcache_lock);
835}
836
837/*
807 * splice a dentry to an inode. 838 * splice a dentry to an inode.
808 * caller must hold directory i_mutex for this to be safe. 839 * caller must hold directory i_mutex for this to be safe.
809 * 840 *
@@ -816,6 +847,8 @@ static struct dentry *splice_dentry(struct dentry *dn, struct inode *in,
816{ 847{
817 struct dentry *realdn; 848 struct dentry *realdn;
818 849
850 BUG_ON(dn->d_inode);
851
819 /* dn must be unhashed */ 852 /* dn must be unhashed */
820 if (!d_unhashed(dn)) 853 if (!d_unhashed(dn))
821 d_drop(dn); 854 d_drop(dn);
@@ -837,48 +870,17 @@ static struct dentry *splice_dentry(struct dentry *dn, struct inode *in,
837 dn = realdn; 870 dn = realdn;
838 } else { 871 } else {
839 BUG_ON(!ceph_dentry(dn)); 872 BUG_ON(!ceph_dentry(dn));
840
841 dout("dn %p attached to %p ino %llx.%llx\n", 873 dout("dn %p attached to %p ino %llx.%llx\n",
842 dn, dn->d_inode, ceph_vinop(dn->d_inode)); 874 dn, dn->d_inode, ceph_vinop(dn->d_inode));
843 } 875 }
844 if ((!prehash || *prehash) && d_unhashed(dn)) 876 if ((!prehash || *prehash) && d_unhashed(dn))
845 d_rehash(dn); 877 d_rehash(dn);
878 ceph_set_dentry_offset(dn);
846out: 879out:
847 return dn; 880 return dn;
848} 881}
849 882
850/* 883/*
851 * Set dentry's directory position based on the current dir's max, and
852 * order it in d_subdirs, so that dcache_readdir behaves.
853 */
854static void ceph_set_dentry_offset(struct dentry *dn)
855{
856 struct dentry *dir = dn->d_parent;
857 struct inode *inode = dn->d_parent->d_inode;
858 struct ceph_dentry_info *di;
859
860 BUG_ON(!inode);
861
862 di = ceph_dentry(dn);
863
864 spin_lock(&inode->i_lock);
865 if ((ceph_inode(inode)->i_ceph_flags & CEPH_I_COMPLETE) == 0) {
866 spin_unlock(&inode->i_lock);
867 return;
868 }
869 di->offset = ceph_inode(inode)->i_max_offset++;
870 spin_unlock(&inode->i_lock);
871
872 spin_lock(&dcache_lock);
873 spin_lock(&dn->d_lock);
874 list_move_tail(&dir->d_subdirs, &dn->d_u.d_child);
875 dout("set_dentry_offset %p %lld (%p %p)\n", dn, di->offset,
876 dn->d_u.d_child.prev, dn->d_u.d_child.next);
877 spin_unlock(&dn->d_lock);
878 spin_unlock(&dcache_lock);
879}
880
881/*
882 * Incorporate results into the local cache. This is either just 884 * Incorporate results into the local cache. This is either just
883 * one inode, or a directory, dentry, and possibly linked-to inode (e.g., 885 * one inode, or a directory, dentry, and possibly linked-to inode (e.g.,
884 * after a lookup). 886 * after a lookup).
@@ -1030,6 +1032,9 @@ int ceph_fill_trace(struct super_block *sb, struct ceph_mds_request *req,
1030 ceph_invalidate_dentry_lease(dn); 1032 ceph_invalidate_dentry_lease(dn);
1031 1033
1032 /* take overwritten dentry's readdir offset */ 1034 /* take overwritten dentry's readdir offset */
1035 dout("dn %p gets %p offset %lld (old offset %lld)\n",
1036 req->r_old_dentry, dn, ceph_dentry(dn)->offset,
1037 ceph_dentry(req->r_old_dentry)->offset);
1033 ceph_dentry(req->r_old_dentry)->offset = 1038 ceph_dentry(req->r_old_dentry)->offset =
1034 ceph_dentry(dn)->offset; 1039 ceph_dentry(dn)->offset;
1035 1040
@@ -1074,7 +1079,6 @@ int ceph_fill_trace(struct super_block *sb, struct ceph_mds_request *req,
1074 goto done; 1079 goto done;
1075 } 1080 }
1076 req->r_dentry = dn; /* may have spliced */ 1081 req->r_dentry = dn; /* may have spliced */
1077 ceph_set_dentry_offset(dn);
1078 igrab(in); 1082 igrab(in);
1079 } else if (ceph_ino(in) == vino.ino && 1083 } else if (ceph_ino(in) == vino.ino &&
1080 ceph_snap(in) == vino.snap) { 1084 ceph_snap(in) == vino.snap) {
@@ -1117,7 +1121,6 @@ int ceph_fill_trace(struct super_block *sb, struct ceph_mds_request *req,
1117 err = PTR_ERR(dn); 1121 err = PTR_ERR(dn);
1118 goto done; 1122 goto done;
1119 } 1123 }
1120 ceph_set_dentry_offset(dn);
1121 req->r_dentry = dn; /* may have spliced */ 1124 req->r_dentry = dn; /* may have spliced */
1122 igrab(in); 1125 igrab(in);
1123 rinfo->head->is_dentry = 1; /* fool notrace handlers */ 1126 rinfo->head->is_dentry = 1; /* fool notrace handlers */