aboutsummaryrefslogtreecommitdiffstats
path: root/net/ceph
diff options
context:
space:
mode:
authorAlex Elder <elder@inktank.com>2013-04-01 17:12:14 -0400
committerSage Weil <sage@inktank.com>2013-05-02 00:17:54 -0400
commitace6d3a96f00c271b3f337adcde8e8cbe39c3820 (patch)
treecb93ac34e892b61ee9303e051384bb64ed925caa /net/ceph
parent25d71cb92d8eb48df9cbd8cc4bb28e88ee8e88d9 (diff)
libceph: drop ceph_osd_request->r_con_filling_msg
A field in an osd request keeps track of whether a connection is currently filling the request's reply message. This patch gets rid of that field. An osd request includes two messages--a request and a reply--and they're both associated with the connection that existed to its the target osd at the time the request was created. An osd request can be dropped early, even when it's in flight. And at that time both messages are released. It's possible the reply message has been supplied to its connection to receive an incoming response message at the time the osd request gets dropped. So ceph_osdc_release_request() revokes that message from the connection before releasing it so things get cleaned up properly. Previously this may have caused a problem, because the connection that a message was associated with might have gone away before the revoke request. And to avoid any problems using that connection, the osd client held a reference to it when it supplies its response message. However since this commit: 38941f80 libceph: have messages point to their connection all messages hold a reference to the connection they are associated with whenever the connection is actively operating on the message (i.e. while the message is queued to send or sending, and when it data is being received into it). And if a message has no connection associated with it, ceph_msg_revoke_incoming() won't do anything when asked to revoke it. As a result, there is no need to keep an additional reference to the connection associated with a message when we hand the message to the messenger when it calls our alloc_msg() method to receive something. If the connection *were* operating on it, it would have its own reference, and if not, there's no work to be done when we need to revoke it. So get rid of the osd request's r_con_filling_msg field. This resolves: http://tracker.ceph.com/issues/4647 Signed-off-by: Alex Elder <elder@inktank.com> Reviewed-by: Josh Durgin <josh.durgin@inktank.com>
Diffstat (limited to 'net/ceph')
-rw-r--r--net/ceph/osd_client.c29
1 files changed, 5 insertions, 24 deletions
diff --git a/net/ceph/osd_client.c b/net/ceph/osd_client.c
index ca79cad50840..e0887923e5ab 100644
--- a/net/ceph/osd_client.c
+++ b/net/ceph/osd_client.c
@@ -91,15 +91,10 @@ void ceph_osdc_release_request(struct kref *kref)
91 91
92 if (req->r_request) 92 if (req->r_request)
93 ceph_msg_put(req->r_request); 93 ceph_msg_put(req->r_request);
94 if (req->r_con_filling_msg) { 94 if (req->r_reply) {
95 dout("%s revoking msg %p from con %p\n", __func__,
96 req->r_reply, req->r_con_filling_msg);
97 ceph_msg_revoke_incoming(req->r_reply); 95 ceph_msg_revoke_incoming(req->r_reply);
98 req->r_con_filling_msg->ops->put(req->r_con_filling_msg);
99 req->r_con_filling_msg = NULL;
100 }
101 if (req->r_reply)
102 ceph_msg_put(req->r_reply); 96 ceph_msg_put(req->r_reply);
97 }
103 98
104 if (req->r_data_in.type == CEPH_OSD_DATA_TYPE_PAGES && 99 if (req->r_data_in.type == CEPH_OSD_DATA_TYPE_PAGES &&
105 req->r_data_in.own_pages) { 100 req->r_data_in.own_pages) {
@@ -1353,16 +1348,6 @@ static void handle_reply(struct ceph_osd_client *osdc, struct ceph_msg *msg,
1353 for (i = 0; i < numops; i++) 1348 for (i = 0; i < numops; i++)
1354 req->r_reply_op_result[i] = ceph_decode_32(&p); 1349 req->r_reply_op_result[i] = ceph_decode_32(&p);
1355 1350
1356 /*
1357 * if this connection filled our message, drop our reference now, to
1358 * avoid a (safe but slower) revoke later.
1359 */
1360 if (req->r_con_filling_msg == con && req->r_reply == msg) {
1361 dout(" dropping con_filling_msg ref %p\n", con);
1362 req->r_con_filling_msg = NULL;
1363 con->ops->put(con);
1364 }
1365
1366 if (!req->r_got_reply) { 1351 if (!req->r_got_reply) {
1367 unsigned int bytes; 1352 unsigned int bytes;
1368 1353
@@ -2199,13 +2184,10 @@ static struct ceph_msg *get_reply(struct ceph_connection *con,
2199 goto out; 2184 goto out;
2200 } 2185 }
2201 2186
2202 if (req->r_con_filling_msg) { 2187 if (req->r_reply->con)
2203 dout("%s revoking msg %p from old con %p\n", __func__, 2188 dout("%s revoking msg %p from old con %p\n", __func__,
2204 req->r_reply, req->r_con_filling_msg); 2189 req->r_reply, req->r_reply->con);
2205 ceph_msg_revoke_incoming(req->r_reply); 2190 ceph_msg_revoke_incoming(req->r_reply);
2206 req->r_con_filling_msg->ops->put(req->r_con_filling_msg);
2207 req->r_con_filling_msg = NULL;
2208 }
2209 2191
2210 if (front > req->r_reply->front.iov_len) { 2192 if (front > req->r_reply->front.iov_len) {
2211 pr_warning("get_reply front %d > preallocated %d\n", 2193 pr_warning("get_reply front %d > preallocated %d\n",
@@ -2236,7 +2218,6 @@ static struct ceph_msg *get_reply(struct ceph_connection *con,
2236 } 2218 }
2237 } 2219 }
2238 *skip = 0; 2220 *skip = 0;
2239 req->r_con_filling_msg = con->ops->get(con);
2240 dout("get_reply tid %lld %p\n", tid, m); 2221 dout("get_reply tid %lld %p\n", tid, m);
2241 2222
2242out: 2223out: