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

branch: b1_6

server do not repost buffer before all requests are finished.
b=17228
r=wangdi
r=nathan
parent d9188dd4
No related branches found
No related tags found
No related merge requests found
...@@ -386,41 +386,32 @@ failed: ...@@ -386,41 +386,32 @@ failed:
return NULL; return NULL;
} }
static void ptlrpc_server_req_decref(struct ptlrpc_request *req) /**
* to actually free the request, must be called without holding svc_lock.
* note it's caller's responsibility to unlink req->rq_list.
*/
static void ptlrpc_server_free_request(struct ptlrpc_request *req)
{ {
struct ptlrpc_request_buffer_desc *rqbd = req->rq_rqbd; LASSERT(atomic_read(&req->rq_refcount) == 0);
LASSERT(list_empty(&req->rq_timed_list));
if (!atomic_dec_and_test(&req->rq_refcount))
return;
/* DEBUG_REQ() assumes the reply state of a request with a valid /* DEBUG_REQ() assumes the reply state of a request with a valid
* ref will not be destroyed until that reference is dropped. */ * ref will not be destroyed until that reference is dropped. */
ptlrpc_req_drop_rs(req); ptlrpc_req_drop_rs(req);
LASSERT(list_empty(&req->rq_timed_list)); if (req != &req->rq_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
* MD; this isn't one of them! */ * MD; this isn't one of them! */
OBD_FREE(req, sizeof(*req)); OBD_FREE(req, sizeof(*req));
} else {
struct ptlrpc_service *svc = rqbd->rqbd_service;
/* schedule request buffer for re-use.
* NB I can only do this after I've disposed of their
* reqs; particularly the embedded req */
spin_lock(&svc->srv_lock);
list_add_tail(&rqbd->rqbd_list, &svc->srv_idle_rqbds);
spin_unlock(&svc->srv_lock);
} }
} }
static void __ptlrpc_server_free_request(struct ptlrpc_request *req) /**
{ * drop a reference count of the request. if it reaches 0, we either
list_del(&req->rq_list); * put it into history list, or free it immediately.
ptlrpc_server_req_decref(req); */
} static void ptlrpc_server_drop_request(struct ptlrpc_request *req)
static void ptlrpc_server_free_request(struct ptlrpc_request *req)
{ {
struct ptlrpc_request_buffer_desc *rqbd = req->rq_rqbd; struct ptlrpc_request_buffer_desc *rqbd = req->rq_rqbd;
struct ptlrpc_service *svc = rqbd->rqbd_service; struct ptlrpc_service *svc = rqbd->rqbd_service;
...@@ -428,12 +419,8 @@ static void ptlrpc_server_free_request(struct ptlrpc_request *req) ...@@ -428,12 +419,8 @@ static void ptlrpc_server_free_request(struct ptlrpc_request *req)
struct list_head *tmp; struct list_head *tmp;
struct list_head *nxt; struct list_head *nxt;
if (req->rq_phase != RQ_PHASE_NEW) /* incorrect message magic */ if (!atomic_dec_and_test(&req->rq_refcount))
DEBUG_REQ(D_INFO, req, "free req"); return;
spin_lock(&svc->srv_at_lock);
req->rq_sent_final = 1;
list_del_init(&req->rq_timed_list);
spin_unlock(&svc->srv_at_lock);
spin_lock(&svc->srv_lock); spin_lock(&svc->srv_lock);
...@@ -476,19 +463,49 @@ static void ptlrpc_server_free_request(struct ptlrpc_request *req) ...@@ -476,19 +463,49 @@ static void ptlrpc_server_free_request(struct ptlrpc_request *req)
req = list_entry(rqbd->rqbd_reqs.next, req = list_entry(rqbd->rqbd_reqs.next,
struct ptlrpc_request, struct ptlrpc_request,
rq_list); rq_list);
__ptlrpc_server_free_request(req); list_del(&req->rq_list);
ptlrpc_server_free_request(req);
} }
spin_lock(&svc->srv_lock); spin_lock(&svc->srv_lock);
/*
* now all reqs including the embedded req has been
* disposed, schedule request buffer for re-use.
*/
LASSERT(atomic_read(&rqbd->rqbd_req.rq_refcount) == 0);
list_add_tail(&rqbd->rqbd_list, &svc->srv_idle_rqbds);
} }
spin_unlock(&svc->srv_lock);
} else if (req->rq_reply_state && req->rq_reply_state->rs_prealloc) { } else if (req->rq_reply_state && req->rq_reply_state->rs_prealloc) {
/* If we are low on memory, we are not interested in /* If we are low on memory, we are not interested in history */
history */ list_del(&req->rq_list);
list_del_init(&req->rq_history_list); list_del_init(&req->rq_history_list);
__ptlrpc_server_free_request(req); spin_unlock(&svc->srv_lock);
ptlrpc_server_free_request(req);
} else {
spin_unlock(&svc->srv_lock);
} }
}
spin_unlock(&svc->srv_lock); /**
* to finish a request: stop sending more early replies, and release
* the request. should be called after we finished handling the request.
*/
static void ptlrpc_server_finish_request(struct ptlrpc_request *req)
{
struct ptlrpc_service *svc = req->rq_rqbd->rqbd_service;
if (req->rq_phase != RQ_PHASE_NEW) /* incorrect message magic */
DEBUG_REQ(D_INFO, req, "free req");
spin_lock(&svc->srv_at_lock);
req->rq_sent_final = 1;
list_del_init(&req->rq_timed_list);
spin_unlock(&svc->srv_at_lock);
ptlrpc_server_drop_request(req);
} }
/* This function makes sure dead exports are evicted in a timely manner. /* This function makes sure dead exports are evicted in a timely manner.
...@@ -850,8 +867,8 @@ static int ptlrpc_at_check_timed(struct ptlrpc_service *svc) ...@@ -850,8 +867,8 @@ static int ptlrpc_at_check_timed(struct ptlrpc_service *svc)
at_get(&svc->srv_at_estimate), delay); at_get(&svc->srv_at_estimate), delay);
} }
/* ptlrpc_server_free_request may delete an entry out of the work /* ptlrpc_server_finish_request may delete an entry out of
list */ * the work list */
spin_lock(&svc->srv_at_lock); spin_lock(&svc->srv_at_lock);
while (!list_empty(&work_list)) { while (!list_empty(&work_list)) {
rq = list_entry(work_list.next, struct ptlrpc_request, rq = list_entry(work_list.next, struct ptlrpc_request,
...@@ -865,7 +882,7 @@ static int ptlrpc_at_check_timed(struct ptlrpc_service *svc) ...@@ -865,7 +882,7 @@ static int ptlrpc_at_check_timed(struct ptlrpc_service *svc)
if (ptlrpc_at_send_early_reply(rq, at_extra) == 0) if (ptlrpc_at_send_early_reply(rq, at_extra) == 0)
ptlrpc_at_add_timed(rq); ptlrpc_at_add_timed(rq);
ptlrpc_server_req_decref(rq); ptlrpc_server_drop_request(rq);
spin_lock(&svc->srv_at_lock); spin_lock(&svc->srv_at_lock);
} }
spin_unlock(&svc->srv_at_lock); spin_unlock(&svc->srv_at_lock);
...@@ -970,7 +987,7 @@ err_req: ...@@ -970,7 +987,7 @@ err_req:
svc->srv_n_queued_reqs--; svc->srv_n_queued_reqs--;
svc->srv_n_active_reqs++; svc->srv_n_active_reqs++;
spin_unlock(&svc->srv_lock); spin_unlock(&svc->srv_lock);
ptlrpc_server_free_request(req); ptlrpc_server_finish_request(req);
RETURN(1); RETURN(1);
} }
...@@ -1126,7 +1143,7 @@ put_conn: ...@@ -1126,7 +1143,7 @@ put_conn:
work_end.tv_sec - request->rq_arrival_time.tv_sec); work_end.tv_sec - request->rq_arrival_time.tv_sec);
} }
ptlrpc_server_free_request(request); ptlrpc_server_finish_request(request);
RETURN(1); RETURN(1);
} }
...@@ -1687,7 +1704,7 @@ int ptlrpc_unregister_service(struct ptlrpc_service *service) ...@@ -1687,7 +1704,7 @@ int ptlrpc_unregister_service(struct ptlrpc_service *service)
list_del(&req->rq_list); list_del(&req->rq_list);
service->srv_n_queued_reqs--; service->srv_n_queued_reqs--;
service->srv_n_active_reqs++; service->srv_n_active_reqs++;
ptlrpc_server_free_request(req); ptlrpc_server_finish_request(req);
} }
while (!list_empty(&service->srv_request_queue)) { while (!list_empty(&service->srv_request_queue)) {
struct ptlrpc_request *req = struct ptlrpc_request *req =
...@@ -1698,7 +1715,7 @@ int ptlrpc_unregister_service(struct ptlrpc_service *service) ...@@ -1698,7 +1715,7 @@ int ptlrpc_unregister_service(struct ptlrpc_service *service)
list_del(&req->rq_list); list_del(&req->rq_list);
service->srv_n_queued_reqs--; service->srv_n_queued_reqs--;
service->srv_n_active_reqs++; service->srv_n_active_reqs++;
ptlrpc_server_free_request(req); ptlrpc_server_finish_request(req);
} }
LASSERT(service->srv_n_queued_reqs == 0); LASSERT(service->srv_n_queued_reqs == 0);
LASSERT(service->srv_n_active_reqs == 0); LASSERT(service->srv_n_active_reqs == 0);
......
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