From 0f48cd0b9856fe1ea920b8abab3579ded0b9511e Mon Sep 17 00:00:00 2001 From: Alexander Zarochentsev Date: Sun, 31 May 2020 19:29:25 +0300 Subject: [PATCH] LU-11290 ldlm: page discard speedup Improving check_and_discard_cb, allowing to cache negative result of dlm lock lookup and avoid excessive osc_dlm_lock_at_pgoff() calls. HPE-bug-id: LUS-6432 Change-Id: I253f944bf430b06d0e1a300d22e5d9b2e97412bf Signed-off-by: Alexander Zarochentsev Reviewed-on: https://review.whamcloud.com/39327 Tested-by: jenkins Tested-by: Maloo Reviewed-by: Vitaly Fertman Reviewed-by: Andrew Perepechko Reviewed-by: Oleg Drokin --- lustre/include/lustre_dlm.h | 1 + lustre/include/lustre_osc.h | 5 +++++ lustre/ldlm/ldlm_lock.c | 8 ++++++-- lustre/osc/osc_cache.c | 50 +++++++++++++++++++++++++++++++++------------ lustre/osc/osc_lock.c | 3 +++ 5 files changed, 52 insertions(+), 15 deletions(-) diff --git a/lustre/include/lustre_dlm.h b/lustre/include/lustre_dlm.h index 65e91fe..1bcd224 100644 --- a/lustre/include/lustre_dlm.h +++ b/lustre/include/lustre_dlm.h @@ -1013,6 +1013,7 @@ enum ldlm_match_flags { LDLM_MATCH_UNREF = BIT(0), LDLM_MATCH_AST = BIT(1), LDLM_MATCH_AST_ANY = BIT(2), + LDLM_MATCH_RIGHT = BIT(3), }; /** diff --git a/lustre/include/lustre_osc.h b/lustre/include/lustre_osc.h index f41ecb7..6432a59 100644 --- a/lustre/include/lustre_osc.h +++ b/lustre/include/lustre_osc.h @@ -169,6 +169,7 @@ struct osc_thread_info { */ pgoff_t oti_next_index; pgoff_t oti_fn_index; /* first non-overlapped index */ + pgoff_t oti_ng_index; /* negative lock caching */ struct cl_sync_io oti_anchor; struct cl_req_attr oti_req_attr; struct lu_buf oti_ladvise_buf; @@ -231,6 +232,10 @@ enum osc_dap_flags { * check ast data is present, requested to cancel cb */ OSC_DAP_FL_AST = BIT(2), + /** + * look at right region for the desired lock + */ + OSC_DAP_FL_RIGHT = BIT(3), }; /* diff --git a/lustre/ldlm/ldlm_lock.c b/lustre/ldlm/ldlm_lock.c index 546f351..dcb6448 100644 --- a/lustre/ldlm/ldlm_lock.c +++ b/lustre/ldlm/ldlm_lock.c @@ -1199,8 +1199,9 @@ static int lock_matches(struct ldlm_lock *lock, struct ldlm_match_data *data) switch (lock->l_resource->lr_type) { case LDLM_EXTENT: - if (lpol->l_extent.start > data->lmd_policy->l_extent.start || - lpol->l_extent.end < data->lmd_policy->l_extent.end) + if (!(data->lmd_match & LDLM_MATCH_RIGHT) && + (lpol->l_extent.start > data->lmd_policy->l_extent.start || + lpol->l_extent.end < data->lmd_policy->l_extent.end)) return INTERVAL_ITER_CONT; if (unlikely(match == LCK_GROUP) && @@ -1286,6 +1287,9 @@ struct ldlm_lock *search_itree(struct ldlm_resource *res, data->lmd_lock = NULL; + if (data->lmd_match & LDLM_MATCH_RIGHT) + ext.end = OBD_OBJECT_EOF; + for (idx = 0; idx < LCK_MODE_NUM; idx++) { struct ldlm_interval_tree *tree = &res->lr_itree[idx]; diff --git a/lustre/osc/osc_cache.c b/lustre/osc/osc_cache.c index a477ebd..364a71f 100644 --- a/lustre/osc/osc_cache.c +++ b/lustre/osc/osc_cache.c @@ -3117,28 +3117,51 @@ static bool check_and_discard_cb(const struct lu_env *env, struct cl_io *io, { struct osc_thread_info *info = osc_env_info(env); struct osc_object *osc = cbdata; + struct cl_page *page = ops->ops_cl.cpl_page; pgoff_t index; + bool discard = false; index = osc_index(ops); - if (index >= info->oti_fn_index) { - struct ldlm_lock *tmp; - struct cl_page *page = ops->ops_cl.cpl_page; + /* negative lock caching */ + if (index < info->oti_ng_index) { + discard = true; + } else if (index >= info->oti_fn_index) { + struct ldlm_lock *tmp; /* refresh non-overlapped index */ tmp = osc_dlmlock_at_pgoff(env, osc, index, - OSC_DAP_FL_TEST_LOCK | OSC_DAP_FL_AST); + OSC_DAP_FL_TEST_LOCK | + OSC_DAP_FL_AST | OSC_DAP_FL_RIGHT); if (tmp != NULL) { __u64 end = tmp->l_policy_data.l_extent.end; - /* Cache the first-non-overlapped index so as to skip - * all pages within [index, oti_fn_index). This is safe - * because if tmp lock is canceled, it will discard - * these pages. */ - info->oti_fn_index = cl_index(osc2cl(osc), end + 1); - if (end == OBD_OBJECT_EOF) - info->oti_fn_index = CL_PAGE_EOF; + __u64 start = tmp->l_policy_data.l_extent.start; + + /* no lock covering this page */ + if (index < cl_index(osc2cl(osc), start)) { + /* no lock at @index, first lock at @start */ + info->oti_ng_index = cl_index(osc2cl(osc), + start); + discard = true; + } else { + /* Cache the first-non-overlapped index so as to + * skip all pages within [index, oti_fn_index). + * This is safe because if tmp lock is canceled, + * it will discard these pages. + */ + info->oti_fn_index = cl_index(osc2cl(osc), + end + 1); + if (end == OBD_OBJECT_EOF) + info->oti_fn_index = CL_PAGE_EOF; + } LDLM_LOCK_PUT(tmp); - } else if (cl_page_own(env, io, page) == 0) { - /* discard the page */ + } else { + info->oti_ng_index = CL_PAGE_EOF; + discard = true; + } + } + + if (discard) { + if (cl_page_own(env, io, page) == 0) { cl_page_discard(env, io, page); cl_page_disown(env, io, page); } else { @@ -3201,6 +3224,7 @@ int osc_lock_discard_pages(const struct lu_env *env, struct osc_object *osc, cb = discard ? osc_discard_cb : check_and_discard_cb; info->oti_fn_index = info->oti_next_index = start; + info->oti_ng_index = 0; osc_page_gang_lookup(env, io, osc, info->oti_next_index, end, cb, osc); diff --git a/lustre/osc/osc_lock.c b/lustre/osc/osc_lock.c index f3ed624..62da056 100644 --- a/lustre/osc/osc_lock.c +++ b/lustre/osc/osc_lock.c @@ -1294,6 +1294,9 @@ struct ldlm_lock *osc_obj_dlmlock_at_pgoff(const struct lu_env *env, if (dap_flags & OSC_DAP_FL_CANCELING) match_flags |= LDLM_MATCH_UNREF; + if (dap_flags & OSC_DAP_FL_RIGHT) + match_flags |= LDLM_MATCH_RIGHT; + /* * It is fine to match any group lock since there could be only one * with a uniq gid and it conflicts with all other lock modes too -- 1.8.3.1