summaryrefslogtreecommitdiffstats
path: root/fs/ceph/caps.c
diff options
context:
space:
mode:
authorYan, Zheng <zheng.z.yan@intel.com>2013-04-12 04:11:10 -0400
committerSage Weil <sage@inktank.com>2013-05-02 00:18:53 -0400
commit37505d5768b9389a5ef7bc1efa465d4484a5462e (patch)
tree208daa8785fe4847061a1dafee58ff32b5b861e6 /fs/ceph/caps.c
parent26be88087ae8a04a5b576aa2f490597b649fc132 (diff)
ceph: take i_mutex before getting Fw cap
There is deadlock as illustrated bellow. The fix is taking i_mutex before getting Fw cap reference. write truncate MDS --------------------- -------------------- -------------- get Fw cap lock i_mutex lock i_mutex (blocked) request setattr.size -> <- revoke Fw cap Signed-off-by: Yan, Zheng <zheng.z.yan@intel.com> Reviewed-by: Alex Elder <elder@inktank.com> Reviewed-by: Sage Weil <sage@inktank.com>
Diffstat (limited to 'fs/ceph/caps.c')
-rw-r--r--fs/ceph/caps.c13
1 files changed, 7 insertions, 6 deletions
diff --git a/fs/ceph/caps.c b/fs/ceph/caps.c
index f9563108d189..da0f9b8a3bcb 100644
--- a/fs/ceph/caps.c
+++ b/fs/ceph/caps.c
@@ -2052,6 +2052,13 @@ static int try_get_cap_refs(struct ceph_inode_info *ci, int need, int want,
2052 goto out; 2052 goto out;
2053 } 2053 }
2054 2054
2055 /* finish pending truncate */
2056 while (ci->i_truncate_pending) {
2057 spin_unlock(&ci->i_ceph_lock);
2058 __ceph_do_pending_vmtruncate(inode, !(need & CEPH_CAP_FILE_WR));
2059 spin_lock(&ci->i_ceph_lock);
2060 }
2061
2055 if (need & CEPH_CAP_FILE_WR) { 2062 if (need & CEPH_CAP_FILE_WR) {
2056 if (endoff >= 0 && endoff > (loff_t)ci->i_max_size) { 2063 if (endoff >= 0 && endoff > (loff_t)ci->i_max_size) {
2057 dout("get_cap_refs %p endoff %llu > maxsize %llu\n", 2064 dout("get_cap_refs %p endoff %llu > maxsize %llu\n",
@@ -2073,12 +2080,6 @@ static int try_get_cap_refs(struct ceph_inode_info *ci, int need, int want,
2073 } 2080 }
2074 have = __ceph_caps_issued(ci, &implemented); 2081 have = __ceph_caps_issued(ci, &implemented);
2075 2082
2076 /*
2077 * disallow writes while a truncate is pending
2078 */
2079 if (ci->i_truncate_pending)
2080 have &= ~CEPH_CAP_FILE_WR;
2081
2082 if ((have & need) == need) { 2083 if ((have & need) == need) {
2083 /* 2084 /*
2084 * Look at (implemented & ~have & not) so that we keep waiting 2085 * Look at (implemented & ~have & not) so that we keep waiting