diff options
author | Yan, Zheng <zheng.z.yan@intel.com> | 2013-02-18 03:38:14 -0500 |
---|---|---|
committer | Sage Weil <sage@inktank.com> | 2013-05-02 00:14:33 -0400 |
commit | a8673d61ad77ddf2118599507bd40cc345e95368 (patch) | |
tree | 0b8688fee3c2f6c7c35db75d42edd806df689d1d /fs/ceph/inode.c | |
parent | 964266cce94cee7e4aca42994fcda206c111e917 (diff) |
ceph: use I_COMPLETE inode flag instead of D_COMPLETE flag
commit c6ffe10015 moved the flag that tracks if the dcache contents
for a directory are complete to dentry. The problem is there are
lots of places that use ceph_dir_{set,clear,test}_complete() while
holding i_ceph_lock. but ceph_dir_{set,clear,test}_complete() may
sleep because they call dput().
This patch basically reverts that commit. For ceph_d_prune(), it's
called with both the dentry to prune and the parent dentry are
locked. So it's safe to access the parent dentry's d_inode and
clear I_COMPLETE flag.
Signed-off-by: Yan, Zheng <zheng.z.yan@intel.com>
Reviewed-by: Greg Farnum <greg@inktank.com>
Reviewed-by: Sage Weil <sage@inktank.com>
Diffstat (limited to 'fs/ceph/inode.c')
-rw-r--r-- | fs/ceph/inode.c | 30 |
1 files changed, 13 insertions, 17 deletions
diff --git a/fs/ceph/inode.c b/fs/ceph/inode.c index 851814d951cd..be2f262b822d 100644 --- a/fs/ceph/inode.c +++ b/fs/ceph/inode.c | |||
@@ -561,7 +561,6 @@ static int fill_inode(struct inode *inode, | |||
561 | struct ceph_inode_info *ci = ceph_inode(inode); | 561 | struct ceph_inode_info *ci = ceph_inode(inode); |
562 | int i; | 562 | int i; |
563 | int issued = 0, implemented; | 563 | int issued = 0, implemented; |
564 | int updating_inode = 0; | ||
565 | struct timespec mtime, atime, ctime; | 564 | struct timespec mtime, atime, ctime; |
566 | u32 nsplits; | 565 | u32 nsplits; |
567 | struct ceph_buffer *xattr_blob = NULL; | 566 | struct ceph_buffer *xattr_blob = NULL; |
@@ -601,7 +600,6 @@ static int fill_inode(struct inode *inode, | |||
601 | (ci->i_version & ~1) >= le64_to_cpu(info->version)) | 600 | (ci->i_version & ~1) >= le64_to_cpu(info->version)) |
602 | goto no_change; | 601 | goto no_change; |
603 | 602 | ||
604 | updating_inode = 1; | ||
605 | issued = __ceph_caps_issued(ci, &implemented); | 603 | issued = __ceph_caps_issued(ci, &implemented); |
606 | issued |= implemented | __ceph_caps_dirty(ci); | 604 | issued |= implemented | __ceph_caps_dirty(ci); |
607 | 605 | ||
@@ -717,6 +715,17 @@ static int fill_inode(struct inode *inode, | |||
717 | ceph_vinop(inode), inode->i_mode); | 715 | ceph_vinop(inode), inode->i_mode); |
718 | } | 716 | } |
719 | 717 | ||
718 | /* set dir completion flag? */ | ||
719 | if (S_ISDIR(inode->i_mode) && | ||
720 | ci->i_files == 0 && ci->i_subdirs == 0 && | ||
721 | ceph_snap(inode) == CEPH_NOSNAP && | ||
722 | (le32_to_cpu(info->cap.caps) & CEPH_CAP_FILE_SHARED) && | ||
723 | (issued & CEPH_CAP_FILE_EXCL) == 0 && | ||
724 | (ci->i_ceph_flags & CEPH_I_COMPLETE) == 0) { | ||
725 | dout(" marking %p complete (empty)\n", inode); | ||
726 | ci->i_ceph_flags |= CEPH_I_COMPLETE; | ||
727 | ci->i_max_offset = 2; | ||
728 | } | ||
720 | no_change: | 729 | no_change: |
721 | spin_unlock(&ci->i_ceph_lock); | 730 | spin_unlock(&ci->i_ceph_lock); |
722 | 731 | ||
@@ -767,19 +776,6 @@ no_change: | |||
767 | __ceph_get_fmode(ci, cap_fmode); | 776 | __ceph_get_fmode(ci, cap_fmode); |
768 | } | 777 | } |
769 | 778 | ||
770 | /* set dir completion flag? */ | ||
771 | if (S_ISDIR(inode->i_mode) && | ||
772 | updating_inode && /* didn't jump to no_change */ | ||
773 | ci->i_files == 0 && ci->i_subdirs == 0 && | ||
774 | ceph_snap(inode) == CEPH_NOSNAP && | ||
775 | (le32_to_cpu(info->cap.caps) & CEPH_CAP_FILE_SHARED) && | ||
776 | (issued & CEPH_CAP_FILE_EXCL) == 0 && | ||
777 | !ceph_dir_test_complete(inode)) { | ||
778 | dout(" marking %p complete (empty)\n", inode); | ||
779 | ceph_dir_set_complete(inode); | ||
780 | ci->i_max_offset = 2; | ||
781 | } | ||
782 | |||
783 | /* update delegation info? */ | 779 | /* update delegation info? */ |
784 | if (dirinfo) | 780 | if (dirinfo) |
785 | ceph_fill_dirfrag(inode, dirinfo); | 781 | ceph_fill_dirfrag(inode, dirinfo); |
@@ -861,7 +857,7 @@ static void ceph_set_dentry_offset(struct dentry *dn) | |||
861 | di = ceph_dentry(dn); | 857 | di = ceph_dentry(dn); |
862 | 858 | ||
863 | spin_lock(&ci->i_ceph_lock); | 859 | spin_lock(&ci->i_ceph_lock); |
864 | if (!ceph_dir_test_complete(inode)) { | 860 | if ((ceph_inode(inode)->i_ceph_flags & CEPH_I_COMPLETE) == 0) { |
865 | spin_unlock(&ci->i_ceph_lock); | 861 | spin_unlock(&ci->i_ceph_lock); |
866 | return; | 862 | return; |
867 | } | 863 | } |
@@ -1066,7 +1062,7 @@ int ceph_fill_trace(struct super_block *sb, struct ceph_mds_request *req, | |||
1066 | * d_move() puts the renamed dentry at the end of | 1062 | * d_move() puts the renamed dentry at the end of |
1067 | * d_subdirs. We need to assign it an appropriate | 1063 | * d_subdirs. We need to assign it an appropriate |
1068 | * directory offset so we can behave when holding | 1064 | * directory offset so we can behave when holding |
1069 | * D_COMPLETE. | 1065 | * I_COMPLETE. |
1070 | */ | 1066 | */ |
1071 | ceph_set_dentry_offset(req->r_old_dentry); | 1067 | ceph_set_dentry_offset(req->r_old_dentry); |
1072 | dout("dn %p gets new offset %lld\n", req->r_old_dentry, | 1068 | dout("dn %p gets new offset %lld\n", req->r_old_dentry, |