aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ceph
diff options
context:
space:
mode:
authorYan, Zheng <zheng.z.yan@intel.com>2013-10-31 04:44:14 -0400
committerYan, Zheng <zheng.z.yan@intel.com>2014-01-21 00:29:32 -0500
commit4fe59789adc93b2573b0417ac93136805521902e (patch)
treeeab5cc55b2785c1617ba21478a82f47dd2663ad4 /fs/ceph
parentfc12c80aa57ee90385dc90e4263ec1a66200ba76 (diff)
ceph: handle cap export race in try_flush_caps()
auth cap may change after releasing the i_ceph_lock Signed-off-by: Yan, Zheng <zheng.z.yan@intel.com>
Diffstat (limited to 'fs/ceph')
-rw-r--r--fs/ceph/caps.c16
1 files changed, 8 insertions, 8 deletions
diff --git a/fs/ceph/caps.c b/fs/ceph/caps.c
index 80dad0d491a3..101209930d5c 100644
--- a/fs/ceph/caps.c
+++ b/fs/ceph/caps.c
@@ -1735,13 +1735,12 @@ ack:
1735/* 1735/*
1736 * Try to flush dirty caps back to the auth mds. 1736 * Try to flush dirty caps back to the auth mds.
1737 */ 1737 */
1738static int try_flush_caps(struct inode *inode, struct ceph_mds_session *session, 1738static int try_flush_caps(struct inode *inode, unsigned *flush_tid)
1739 unsigned *flush_tid)
1740{ 1739{
1741 struct ceph_mds_client *mdsc = ceph_sb_to_client(inode->i_sb)->mdsc; 1740 struct ceph_mds_client *mdsc = ceph_sb_to_client(inode->i_sb)->mdsc;
1742 struct ceph_inode_info *ci = ceph_inode(inode); 1741 struct ceph_inode_info *ci = ceph_inode(inode);
1743 int unlock_session = session ? 0 : 1;
1744 int flushing = 0; 1742 int flushing = 0;
1743 struct ceph_mds_session *session = NULL;
1745 1744
1746retry: 1745retry:
1747 spin_lock(&ci->i_ceph_lock); 1746 spin_lock(&ci->i_ceph_lock);
@@ -1755,13 +1754,14 @@ retry:
1755 int want = __ceph_caps_wanted(ci); 1754 int want = __ceph_caps_wanted(ci);
1756 int delayed; 1755 int delayed;
1757 1756
1758 if (!session) { 1757 if (!session || session != cap->session) {
1759 spin_unlock(&ci->i_ceph_lock); 1758 spin_unlock(&ci->i_ceph_lock);
1759 if (session)
1760 mutex_unlock(&session->s_mutex);
1760 session = cap->session; 1761 session = cap->session;
1761 mutex_lock(&session->s_mutex); 1762 mutex_lock(&session->s_mutex);
1762 goto retry; 1763 goto retry;
1763 } 1764 }
1764 BUG_ON(session != cap->session);
1765 if (cap->session->s_state < CEPH_MDS_SESSION_OPEN) 1765 if (cap->session->s_state < CEPH_MDS_SESSION_OPEN)
1766 goto out; 1766 goto out;
1767 1767
@@ -1780,7 +1780,7 @@ retry:
1780out: 1780out:
1781 spin_unlock(&ci->i_ceph_lock); 1781 spin_unlock(&ci->i_ceph_lock);
1782out_unlocked: 1782out_unlocked:
1783 if (session && unlock_session) 1783 if (session)
1784 mutex_unlock(&session->s_mutex); 1784 mutex_unlock(&session->s_mutex);
1785 return flushing; 1785 return flushing;
1786} 1786}
@@ -1865,7 +1865,7 @@ int ceph_fsync(struct file *file, loff_t start, loff_t end, int datasync)
1865 return ret; 1865 return ret;
1866 mutex_lock(&inode->i_mutex); 1866 mutex_lock(&inode->i_mutex);
1867 1867
1868 dirty = try_flush_caps(inode, NULL, &flush_tid); 1868 dirty = try_flush_caps(inode, &flush_tid);
1869 dout("fsync dirty caps are %s\n", ceph_cap_string(dirty)); 1869 dout("fsync dirty caps are %s\n", ceph_cap_string(dirty));
1870 1870
1871 /* 1871 /*
@@ -1900,7 +1900,7 @@ int ceph_write_inode(struct inode *inode, struct writeback_control *wbc)
1900 1900
1901 dout("write_inode %p wait=%d\n", inode, wait); 1901 dout("write_inode %p wait=%d\n", inode, wait);
1902 if (wait) { 1902 if (wait) {
1903 dirty = try_flush_caps(inode, NULL, &flush_tid); 1903 dirty = try_flush_caps(inode, &flush_tid);
1904 if (dirty) 1904 if (dirty)
1905 err = wait_event_interruptible(ci->i_cap_wq, 1905 err = wait_event_interruptible(ci->i_cap_wq,
1906 caps_are_flushed(inode, flush_tid)); 1906 caps_are_flushed(inode, flush_tid));