From f0dda9e48de107e87a2389fb3d9095c2efa0aa79 Mon Sep 17 00:00:00 2001 From: Bobi Jam Date: Mon, 16 Jul 2012 19:27:09 +0800 Subject: [PATCH] LU-1626 lov: fix lov request set finish check race When several lov_request callbacks are called, if one of them is the last lov_request in the set, lov_finished_set() checks for all of them will return true, while the following action is supposed be called only once for the set, in this case the assumption is broke and the lov request set's refcount is wrong. This patch fixed another glitch, in qos_remedy_create(), when we use OST pool, the ost_idx value does not initialied correctly. Signed-off-by: Bobi Jam Change-Id: Id3ff1777b2146630b2d693e046038fcc6f465309 Reviewed-on: http://review.whamcloud.com/3402 Tested-by: Hudson Tested-by: Maloo Reviewed-by: Fan Yong Reviewed-by: wangdi Reviewed-by: Oleg Drokin --- lustre/lov/lov_internal.h | 3 ++- lustre/lov/lov_obd.c | 2 +- lustre/lov/lov_qos.c | 5 +++-- lustre/lov/lov_request.c | 15 +++++++++++---- 4 files changed, 17 insertions(+), 8 deletions(-) diff --git a/lustre/lov/lov_internal.h b/lustre/lov/lov_internal.h index 4aafdef..8d01397 100644 --- a/lustre/lov/lov_internal.h +++ b/lustre/lov/lov_internal.h @@ -77,6 +77,7 @@ struct lov_request_set { int set_count; int set_completes; int set_success; + cfs_atomic_t set_finish_checked; struct llog_cookie *set_cookies; int set_cookie_sent; struct obd_trans_info *set_oti; @@ -193,7 +194,7 @@ int qos_remedy_create(struct lov_request_set *set, struct lov_request *req); /* lov_request.c */ void lov_set_add_req(struct lov_request *req, struct lov_request_set *set); -int lov_finished_set(struct lov_request_set *set); +int lov_set_finished(struct lov_request_set *set, int idempotent); void lov_update_set(struct lov_request_set *set, struct lov_request *req, int rc); int lov_update_common_set(struct lov_request_set *set, diff --git a/lustre/lov/lov_obd.c b/lustre/lov/lov_obd.c index 673e18b..7c0d735 100644 --- a/lustre/lov/lov_obd.c +++ b/lustre/lov/lov_obd.c @@ -1173,7 +1173,7 @@ static int lov_create(struct obd_export *exp, struct obdo *src_oa, /* osc_create have timeout equ obd_timeout/2 so waiting don't be * longer then this */ - l_wait_event(set->set_waitq, lov_finished_set(set), &lwi); + l_wait_event(set->set_waitq, lov_set_finished(set, 1), &lwi); /* we not have ptlrpc set for assign set->interpret and should * be call interpret function himself. calling from cb_create_update diff --git a/lustre/lov/lov_qos.c b/lustre/lov/lov_qos.c index c1f8c96..49ffcf4 100644 --- a/lustre/lov/lov_qos.c +++ b/lustre/lov/lov_qos.c @@ -534,7 +534,7 @@ int qos_remedy_create(struct lov_request_set *set, struct lov_request *req) { struct lov_stripe_md *lsm = set->set_oi->oi_md; struct lov_obd *lov = &set->set_exp->exp_obd->u.lov; - unsigned ost_idx = 0, ost_count; + unsigned ost_idx, ost_count; struct pool_desc *pool; struct ost_pool *osts = NULL; int i, rc = -EIO; @@ -546,7 +546,8 @@ int qos_remedy_create(struct lov_request_set *set, struct lov_request *req) cfs_down_read(&pool_tgt_rw_sem(pool)); osts = &(pool->pool_obds); ost_count = osts->op_count; - for (i = 0; i < ost_count; i++, ost_idx = osts->op_array[i]) { + for (i = 0, ost_idx = osts->op_array[0]; i < ost_count; + i++, ost_idx = osts->op_array[i]) { rc = lov_check_and_create_object(lov, ost_idx, lsm, req, set->set_oti); if (rc == 0) diff --git a/lustre/lov/lov_request.c b/lustre/lov/lov_request.c index 12b1b2e..b931326 100644 --- a/lustre/lov/lov_request.c +++ b/lustre/lov/lov_request.c @@ -59,6 +59,7 @@ static void lov_init_set(struct lov_request_set *set) set->set_count = 0; set->set_completes = 0; set->set_success = 0; + cfs_atomic_set(&set->set_finish_checked, 0); set->set_cookies = 0; CFS_INIT_LIST_HEAD(&set->set_list); cfs_atomic_set(&set->set_refcount, 1); @@ -99,11 +100,17 @@ void lov_finish_set(struct lov_request_set *set) EXIT; } -int lov_finished_set(struct lov_request_set *set) +int lov_set_finished(struct lov_request_set *set, int idempotent) { CDEBUG(D_INFO, "check set %d/%d\n", set->set_completes, set->set_count); - return set->set_completes == set->set_count; + if (set->set_completes == set->set_count) { + if (idempotent) + return 1; + if (cfs_atomic_inc_return(&set->set_finish_checked) == 1) + return 1; + } + return 0; } void lov_update_set(struct lov_request_set *set, @@ -727,7 +734,7 @@ int cb_create_update(void *cookie, int rc) rc = -ENOTCONN; rc= lov_update_create_set(lovreq->rq_rqset, lovreq, rc); - if (lov_finished_set(lovreq->rq_rqset)) + if (lov_set_finished(lovreq->rq_rqset, 0)) lov_put_reqset(lovreq->rq_rqset); return rc; } @@ -1653,7 +1660,7 @@ out_update: out: if (lovreq->rq_rqset->set_oi->oi_flags & OBD_STATFS_PTLRPCD && - lov_finished_set(lovreq->rq_rqset)) { + lov_set_finished(lovreq->rq_rqset, 0)) { lov_statfs_interpret(NULL, lovreq->rq_rqset, lovreq->rq_rqset->set_success != lovreq->rq_rqset->set_count); -- 1.8.3.1