aboutsummaryrefslogtreecommitdiffstats
path: root/net/ceph/osd_client.c
diff options
context:
space:
mode:
authorIlya Dryomov <ilya.dryomov@inktank.com>2014-02-03 06:56:33 -0500
committerSage Weil <sage@inktank.com>2014-02-07 13:45:53 -0500
commitff513ace9b772e75e337f8e058cc7f12816843fe (patch)
treec41312d8926e5f12f4f47426f46cce3da148c0a9 /net/ceph/osd_client.c
parent0bbfdfe8d25fcc1d5c2edb6b060fb0c5cf66aff9 (diff)
libceph: take map_sem for read in handle_reply()
Handling redirect replies requires both map_sem and request_mutex. Taking map_sem unconditionally near the top of handle_reply() avoids possible race conditions that arise from releasing request_mutex to be able to acquire map_sem in redirect reply case. (Lock ordering is: map_sem, request_mutex, crush_mutex.) Signed-off-by: Ilya Dryomov <ilya.dryomov@inktank.com> Reviewed-by: Sage Weil <sage@inktank.com>
Diffstat (limited to 'net/ceph/osd_client.c')
-rw-r--r--net/ceph/osd_client.c17
1 files changed, 11 insertions, 6 deletions
diff --git a/net/ceph/osd_client.c b/net/ceph/osd_client.c
index 2aa82b6bb305..0676f2b199d6 100644
--- a/net/ceph/osd_client.c
+++ b/net/ceph/osd_client.c
@@ -1687,6 +1687,7 @@ static void handle_reply(struct ceph_osd_client *osdc, struct ceph_msg *msg,
1687 osdmap_epoch = ceph_decode_32(&p); 1687 osdmap_epoch = ceph_decode_32(&p);
1688 1688
1689 /* lookup */ 1689 /* lookup */
1690 down_read(&osdc->map_sem);
1690 mutex_lock(&osdc->request_mutex); 1691 mutex_lock(&osdc->request_mutex);
1691 req = __lookup_request(osdc, tid); 1692 req = __lookup_request(osdc, tid);
1692 if (req == NULL) { 1693 if (req == NULL) {
@@ -1743,7 +1744,6 @@ static void handle_reply(struct ceph_osd_client *osdc, struct ceph_msg *msg,
1743 dout("redirect pool %lld\n", redir.oloc.pool); 1744 dout("redirect pool %lld\n", redir.oloc.pool);
1744 1745
1745 __unregister_request(osdc, req); 1746 __unregister_request(osdc, req);
1746 mutex_unlock(&osdc->request_mutex);
1747 1747
1748 req->r_target_oloc = redir.oloc; /* struct */ 1748 req->r_target_oloc = redir.oloc; /* struct */
1749 1749
@@ -1755,10 +1755,10 @@ static void handle_reply(struct ceph_osd_client *osdc, struct ceph_msg *msg,
1755 * successfully. In the future we might want to follow 1755 * successfully. In the future we might want to follow
1756 * original request's nofail setting here. 1756 * original request's nofail setting here.
1757 */ 1757 */
1758 err = ceph_osdc_start_request(osdc, req, true); 1758 err = __ceph_osdc_start_request(osdc, req, true);
1759 BUG_ON(err); 1759 BUG_ON(err);
1760 1760
1761 goto done; 1761 goto out_unlock;
1762 } 1762 }
1763 1763
1764 already_completed = req->r_got_reply; 1764 already_completed = req->r_got_reply;
@@ -1776,8 +1776,7 @@ static void handle_reply(struct ceph_osd_client *osdc, struct ceph_msg *msg,
1776 req->r_got_reply = 1; 1776 req->r_got_reply = 1;
1777 } else if ((flags & CEPH_OSD_FLAG_ONDISK) == 0) { 1777 } else if ((flags & CEPH_OSD_FLAG_ONDISK) == 0) {
1778 dout("handle_reply tid %llu dup ack\n", tid); 1778 dout("handle_reply tid %llu dup ack\n", tid);
1779 mutex_unlock(&osdc->request_mutex); 1779 goto out_unlock;
1780 goto done;
1781 } 1780 }
1782 1781
1783 dout("handle_reply tid %llu flags %d\n", tid, flags); 1782 dout("handle_reply tid %llu flags %d\n", tid, flags);
@@ -1792,6 +1791,7 @@ static void handle_reply(struct ceph_osd_client *osdc, struct ceph_msg *msg,
1792 __unregister_request(osdc, req); 1791 __unregister_request(osdc, req);
1793 1792
1794 mutex_unlock(&osdc->request_mutex); 1793 mutex_unlock(&osdc->request_mutex);
1794 up_read(&osdc->map_sem);
1795 1795
1796 if (!already_completed) { 1796 if (!already_completed) {
1797 if (req->r_unsafe_callback && 1797 if (req->r_unsafe_callback &&
@@ -1809,10 +1809,14 @@ static void handle_reply(struct ceph_osd_client *osdc, struct ceph_msg *msg,
1809 complete_request(req); 1809 complete_request(req);
1810 } 1810 }
1811 1811
1812done: 1812out:
1813 dout("req=%p req->r_linger=%d\n", req, req->r_linger); 1813 dout("req=%p req->r_linger=%d\n", req, req->r_linger);
1814 ceph_osdc_put_request(req); 1814 ceph_osdc_put_request(req);
1815 return; 1815 return;
1816out_unlock:
1817 mutex_unlock(&osdc->request_mutex);
1818 up_read(&osdc->map_sem);
1819 goto out;
1816 1820
1817bad_put: 1821bad_put:
1818 req->r_result = -EIO; 1822 req->r_result = -EIO;
@@ -1825,6 +1829,7 @@ bad_put:
1825 ceph_osdc_put_request(req); 1829 ceph_osdc_put_request(req);
1826bad_mutex: 1830bad_mutex:
1827 mutex_unlock(&osdc->request_mutex); 1831 mutex_unlock(&osdc->request_mutex);
1832 up_read(&osdc->map_sem);
1828bad: 1833bad:
1829 pr_err("corrupt osd_op_reply got %d %d\n", 1834 pr_err("corrupt osd_op_reply got %d %d\n",
1830 (int)msg->front.iov_len, le32_to_cpu(msg->hdr.front_len)); 1835 (int)msg->front.iov_len, le32_to_cpu(msg->hdr.front_len));