Skip to content
Snippets Groups Projects
Commit dd722d72 authored by Eric Mei's avatar Eric Mei
Browse files

branch: b1_6

fix a race condition of early reply release.
b=14274
r=nathan, andreas
parent 6e34800c
No related branches found
No related tags found
No related merge requests found
...@@ -284,7 +284,8 @@ struct ptlrpc_request { ...@@ -284,7 +284,8 @@ struct ptlrpc_request {
rq_no_resend:1, rq_waiting:1, rq_receiving_reply:1, rq_no_resend:1, rq_waiting:1, rq_receiving_reply:1,
rq_no_delay:1, rq_net_err:1, rq_early:1, rq_must_unlink:1, rq_no_delay:1, rq_net_err:1, rq_early:1, rq_must_unlink:1,
/* server-side flags */ /* server-side flags */
rq_packed_final:1; /* packed final reply */ rq_packed_final:1, /* packed final reply */
rq_sent_final:1; /* stop sending early replies */
enum rq_phase rq_phase; /* one of RQ_PHASE_* */ enum rq_phase rq_phase; /* one of RQ_PHASE_* */
atomic_t rq_refcount; /* client-side refcount for SENT race, atomic_t rq_refcount; /* client-side refcount for SENT race,
server-side refcounf for multiple replies */ server-side refcounf for multiple replies */
......
...@@ -378,6 +378,7 @@ static void ptlrpc_server_req_decref(struct ptlrpc_request *req) ...@@ -378,6 +378,7 @@ static void ptlrpc_server_req_decref(struct ptlrpc_request *req)
if (!atomic_dec_and_test(&req->rq_refcount)) if (!atomic_dec_and_test(&req->rq_refcount))
return; return;
LASSERT(list_empty(&req->rq_timed_list));
if (req != &rqbd->rqbd_req) { if (req != &rqbd->rqbd_req) {
/* NB request buffers use an embedded /* NB request buffers use an embedded
* req if the incoming req unlinked the * req if the incoming req unlinked the
...@@ -412,6 +413,7 @@ static void ptlrpc_server_free_request(struct ptlrpc_request *req) ...@@ -412,6 +413,7 @@ static void ptlrpc_server_free_request(struct ptlrpc_request *req)
if (req->rq_phase != RQ_PHASE_NEW) /* incorrect message magic */ if (req->rq_phase != RQ_PHASE_NEW) /* incorrect message magic */
DEBUG_REQ(D_INFO, req, "free req"); DEBUG_REQ(D_INFO, req, "free req");
spin_lock(&svc->srv_at_lock); spin_lock(&svc->srv_at_lock);
req->rq_sent_final = 1;
list_del_init(&req->rq_timed_list); list_del_init(&req->rq_timed_list);
spin_unlock(&svc->srv_at_lock); spin_unlock(&svc->srv_at_lock);
...@@ -614,6 +616,11 @@ static int ptlrpc_at_add_timed(struct ptlrpc_request *req) ...@@ -614,6 +616,11 @@ static int ptlrpc_at_add_timed(struct ptlrpc_request *req)
spin_lock(&svc->srv_at_lock); spin_lock(&svc->srv_at_lock);
if (unlikely(req->rq_sent_final)) {
spin_unlock(&svc->srv_at_lock);
return 0;
}
LASSERT(list_empty(&req->rq_timed_list)); LASSERT(list_empty(&req->rq_timed_list));
/* Add to sorted list. Presumably latest rpcs will have the latest /* Add to sorted list. Presumably latest rpcs will have the latest
deadlines, so search backward. */ deadlines, so search backward. */
...@@ -709,6 +716,12 @@ static int ptlrpc_at_send_early_reply(struct ptlrpc_request *req, ...@@ -709,6 +716,12 @@ static int ptlrpc_at_send_early_reply(struct ptlrpc_request *req,
reqcopy->rq_reqmsg = reqmsg; reqcopy->rq_reqmsg = reqmsg;
memcpy(reqmsg, req->rq_reqmsg, req->rq_reqlen); memcpy(reqmsg, req->rq_reqmsg, req->rq_reqlen);
if (req->rq_sent_final) {
CDEBUG(D_ADAPTTO, "x"LPU64": normal reply already sent out, "
"abort sending early reply\n", req->rq_xid);
GOTO(out, rc = 0);
}
/* Connection ref */ /* Connection ref */
reqcopy->rq_export = class_conn2export( reqcopy->rq_export = class_conn2export(
lustre_msg_get_handle(reqcopy->rq_reqmsg)); lustre_msg_get_handle(reqcopy->rq_reqmsg));
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment