diff --git a/lustre/ChangeLog b/lustre/ChangeLog index 1189c6a9d134adf8f0465ef4fc4a5a660e4ee93e..611ac96cf897b750c6dcc09a683db29c21d0ed5a 100644 --- a/lustre/ChangeLog +++ b/lustre/ChangeLog @@ -277,6 +277,15 @@ Description: 35% write performance drop with ldiskfs2 when quotas are on Details : Enable ext3 journalled quota by default to improve performance when quotas are turned on. +Severity : normal +Bugzilla : 13843 +Description: Client eviction while running blogbench +Details : A lot of unlink operations with concurrent I/O can lead to a + deadlock causing evictions. To address the problem, the number of + oustanding OST_DESTROY requests is now throttled to + max_rpcs_in_flight per OSC and LDLM_FL_DISCARD_DATA blocking + callbacks are processed in priority. + -------------------------------------------------------------------------------- 2007-12-07 Cluster File Systems, Inc. <info@clusterfs.com> diff --git a/lustre/include/obd.h b/lustre/include/obd.h index 660137357b7ff6de6efefab0501f5490c68fe3ff..a846bdb923f2664f26ddddc9484ed3d9d655fac7 100644 --- a/lustre/include/obd.h +++ b/lustre/include/obd.h @@ -390,6 +390,10 @@ struct client_obd { struct obd_histogram cl_read_offset_hist; struct obd_histogram cl_write_offset_hist; + /* number of in flight destroy rpcs is limited to max_rpcs_in_flight */ + atomic_t cl_destroy_in_flight; + cfs_waitq_t cl_destroy_waitq; + struct mdc_rpc_lock *cl_rpc_lock; struct mdc_rpc_lock *cl_setattr_lock; struct mdc_rpc_lock *cl_close_lock; diff --git a/lustre/ldlm/ldlm_lib.c b/lustre/ldlm/ldlm_lib.c index fc318262c9ad2428f5a3a1f4597906cb268aa67f..4a48b01c561d41876bfcff937c033bee24ef0d02 100644 --- a/lustre/ldlm/ldlm_lib.c +++ b/lustre/ldlm/ldlm_lib.c @@ -265,6 +265,8 @@ int client_obd_setup(struct obd_device *obddev, obd_count len, void *buf) spin_lock_init(&cli->cl_write_page_hist.oh_lock); spin_lock_init(&cli->cl_read_offset_hist.oh_lock); spin_lock_init(&cli->cl_write_offset_hist.oh_lock); + cfs_waitq_init(&cli->cl_destroy_waitq); + atomic_set(&cli->cl_destroy_in_flight, 0); #ifdef ENABLE_CHECKSUM cli->cl_checksum = 1; #endif diff --git a/lustre/osc/osc_request.c b/lustre/osc/osc_request.c index 2d428bc3b941fd885b82e51796c85f95c1d0f47b..823eaca68223e5a196899455f0be9c6f5fd2b7a0 100644 --- a/lustre/osc/osc_request.c +++ b/lustre/osc/osc_request.c @@ -570,6 +570,34 @@ static int osc_resource_get_unused(struct obd_export *exp, __u64 objid, RETURN(count); } +static int osc_destroy_interpret(struct ptlrpc_request *req, void *data, + int rc) +{ + struct client_obd *cli = &req->rq_import->imp_obd->u.cli; + + atomic_dec(&cli->cl_destroy_in_flight); + cfs_waitq_signal(&cli->cl_destroy_waitq); + return 0; +} + +static int osc_can_send_destroy(struct client_obd *cli) +{ + if (atomic_inc_return(&cli->cl_destroy_in_flight) <= + cli->cl_max_rpcs_in_flight) { + /* The destroy request can be sent */ + return 1; + } + if (atomic_dec_return(&cli->cl_destroy_in_flight) < + cli->cl_max_rpcs_in_flight) { + /* + * The counter has been modified between the two atomic + * operations. + */ + cfs_waitq_signal(&cli->cl_destroy_waitq); + } + return 0; +} + /* Destroy requests can be async always on the client, and we don't even really * care about the return code since the client cannot do anything at all about * a destroy failure. @@ -589,6 +617,7 @@ static int osc_destroy(struct obd_export *exp, struct obdo *oa, struct ost_body *body; int size[3] = { sizeof(struct ptlrpc_body), sizeof(*body), 0 }; int count, bufcount = 2; + struct client_obd *cli = &exp->exp_obd->u.cli; ENTRY; if (!oa) { @@ -606,6 +635,7 @@ static int osc_destroy(struct obd_export *exp, struct obdo *oa, RETURN(-ENOMEM); req->rq_request_portal = OST_IO_PORTAL; /* bug 7198 */ + req->rq_interpret_reply = osc_destroy_interpret; ptlrpc_at_set_req_timeout(req); body = lustre_msg_buf(req->rq_reqmsg, REQ_REC_OFF, sizeof(*body)); @@ -618,6 +648,18 @@ static int osc_destroy(struct obd_export *exp, struct obdo *oa, memcpy(&body->oa, oa, sizeof(*oa)); ptlrpc_req_set_repsize(req, 2, size); + if (!osc_can_send_destroy(cli)) { + struct l_wait_info lwi = { 0 }; + + /* + * Wait until the number of on-going destroy RPCs drops + * under max_rpc_in_flight + */ + l_wait_event_exclusive(cli->cl_destroy_waitq, + osc_can_send_destroy(cli), &lwi); + } + + /* Do not wait for response */ ptlrpcd_add_req(req); RETURN(0); }