aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ceph/mds_client.c
diff options
context:
space:
mode:
authorSage Weil <sage@newdream.net>2010-05-13 15:01:13 -0400
committerSage Weil <sage@newdream.net>2010-05-17 13:25:45 -0400
commitb4556396fac5b3f063d5b8ac54dc02f7612a75e1 (patch)
tree30f24bd81c4c007dd09fc625f202854803dd2628 /fs/ceph/mds_client.c
parente1518c7c0a67a75727f7285780dbef0ca7121cc9 (diff)
ceph: fix race between aborted requests and fill_trace
When we abort requests we need to prevent fill_trace et al from doing anything that relies on locks held by the VFS caller. This fixes a race between the reply handler and the abort code, ensuring that continue holding the dir mutex until the reply handler completes. Signed-off-by: Sage Weil <sage@newdream.net>
Diffstat (limited to 'fs/ceph/mds_client.c')
-rw-r--r--fs/ceph/mds_client.c11
1 files changed, 11 insertions, 0 deletions
diff --git a/fs/ceph/mds_client.c b/fs/ceph/mds_client.c
index b3b19f05b82..c0568fe3c0b 100644
--- a/fs/ceph/mds_client.c
+++ b/fs/ceph/mds_client.c
@@ -1181,6 +1181,7 @@ ceph_mdsc_create_request(struct ceph_mds_client *mdsc, int op, int mode)
1181 if (!req) 1181 if (!req)
1182 return ERR_PTR(-ENOMEM); 1182 return ERR_PTR(-ENOMEM);
1183 1183
1184 mutex_init(&req->r_fill_mutex);
1184 req->r_started = jiffies; 1185 req->r_started = jiffies;
1185 req->r_resend_mds = -1; 1186 req->r_resend_mds = -1;
1186 INIT_LIST_HEAD(&req->r_unsafe_dir_item); 1187 INIT_LIST_HEAD(&req->r_unsafe_dir_item);
@@ -1715,8 +1716,16 @@ int ceph_mdsc_do_request(struct ceph_mds_client *mdsc,
1715 err = le32_to_cpu(req->r_reply_info.head->result); 1716 err = le32_to_cpu(req->r_reply_info.head->result);
1716 } else if (err < 0) { 1717 } else if (err < 0) {
1717 dout("aborted request %lld with %d\n", req->r_tid, err); 1718 dout("aborted request %lld with %d\n", req->r_tid, err);
1719
1720 /*
1721 * ensure we aren't running concurrently with
1722 * ceph_fill_trace or ceph_readdir_prepopulate, which
1723 * rely on locks (dir mutex) held by our caller.
1724 */
1725 mutex_lock(&req->r_fill_mutex);
1718 req->r_err = err; 1726 req->r_err = err;
1719 req->r_aborted = true; 1727 req->r_aborted = true;
1728 mutex_unlock(&req->r_fill_mutex);
1720 1729
1721 if (req->r_locked_dir && 1730 if (req->r_locked_dir &&
1722 (req->r_op & CEPH_MDS_OP_WRITE)) { 1731 (req->r_op & CEPH_MDS_OP_WRITE)) {
@@ -1861,12 +1870,14 @@ static void handle_reply(struct ceph_mds_session *session, struct ceph_msg *msg)
1861 } 1870 }
1862 1871
1863 /* insert trace into our cache */ 1872 /* insert trace into our cache */
1873 mutex_lock(&req->r_fill_mutex);
1864 err = ceph_fill_trace(mdsc->client->sb, req, req->r_session); 1874 err = ceph_fill_trace(mdsc->client->sb, req, req->r_session);
1865 if (err == 0) { 1875 if (err == 0) {
1866 if (result == 0 && rinfo->dir_nr) 1876 if (result == 0 && rinfo->dir_nr)
1867 ceph_readdir_prepopulate(req, req->r_session); 1877 ceph_readdir_prepopulate(req, req->r_session);
1868 ceph_unreserve_caps(&req->r_caps_reservation); 1878 ceph_unreserve_caps(&req->r_caps_reservation);
1869 } 1879 }
1880 mutex_unlock(&req->r_fill_mutex);
1870 1881
1871 up_read(&mdsc->snap_rwsem); 1882 up_read(&mdsc->snap_rwsem);
1872out_err: 1883out_err: