From 3d4b5dacb3053f39d79d59860a903a19e76b9318 Mon Sep 17 00:00:00 2001 From: Vitaly Fertman Date: Fri, 31 Jul 2020 21:16:43 +0300 Subject: [PATCH] LU-11518 ldlm: cancel LRU improvement Add @batch parameter to cancel LRU, which means if at least 1 lock is cancelled, try to cancel at least a batch locks. This functionality will be used in later patches. Limit the LRU cancel by 1 thread only, however, not for those which have the @max limit given (ELC), as LRU may be left not cleaned up in full. Signed-off-by: Vitaly Fertman Change-Id: Ide21c4a2b2209b8a721249466ea1e651c8532c8a HPE-bug-id: LUS-8678 Reviewed-on: https://es-gerrit.dev.cray.com/157067 Reviewed-by: Andriy Skulysh Reviewed-by: Alexey Lyashkov Tested-by: Alexander Lezhoev Reviewed-on: https://review.whamcloud.com/39561 Tested-by: jenkins Tested-by: Maloo Reviewed-by: Andreas Dilger Reviewed-by: Gu Zheng Reviewed-by: Oleg Drokin --- lustre/include/lustre_dlm.h | 13 +++++++++++++ lustre/ldlm/ldlm_request.c | 31 ++++++++++++++++++++++++++++--- lustre/ldlm/ldlm_resource.c | 1 + 3 files changed, 42 insertions(+), 3 deletions(-) diff --git a/lustre/include/lustre_dlm.h b/lustre/include/lustre_dlm.h index 5ad6c70..f38f36b 100644 --- a/lustre/include/lustre_dlm.h +++ b/lustre/include/lustre_dlm.h @@ -353,6 +353,14 @@ enum ldlm_ns_type { LDLM_NS_TYPE_MGT, /**< MGT namespace */ }; +enum ldlm_namespace_flags { + /** + * Flag to indicate the LRU cancel is in progress. + * Used to limit the process by 1 thread only. + */ + LDLM_LRU_CANCEL = 0 +}; + /** * LDLM Namespace. * @@ -538,6 +546,11 @@ struct ldlm_namespace { struct kobject ns_kobj; /* sysfs object */ struct completion ns_kobj_unregister; + + /** + * To avoid another ns_lock usage, a separate bitops field. + */ + unsigned long ns_flags; }; /** diff --git a/lustre/ldlm/ldlm_request.c b/lustre/ldlm/ldlm_request.c index 5522a80..74a1e73 100644 --- a/lustre/ldlm/ldlm_request.c +++ b/lustre/ldlm/ldlm_request.c @@ -1768,6 +1768,7 @@ ldlm_cancel_lru_policy(struct ldlm_namespace *ns, enum ldlm_lru_flags lru_flags) * redundant unused locks are canceled locally; * - also cancel locally unused aged locks; * - do not cancel more than \a max locks; + * - if some locks are cancelled, try to cancel at least \a batch locks * - GET the found locks and add them into the \a cancels list. * * A client lock can be added to the l_bl_ast list only when it is @@ -1792,7 +1793,8 @@ ldlm_cancel_lru_policy(struct ldlm_namespace *ns, enum ldlm_lru_flags lru_flags) * discard those pages. */ static int ldlm_prepare_lru_list(struct ldlm_namespace *ns, - struct list_head *cancels, int min, int max, + struct list_head *cancels, + int min, int max, int batch, enum ldlm_lru_flags lru_flags) { ldlm_cancel_lru_policy_t pf; @@ -1800,11 +1802,27 @@ static int ldlm_prepare_lru_list(struct ldlm_namespace *ns, int no_wait = lru_flags & LDLM_LRU_FLAG_NO_WAIT; ENTRY; + /* + * Let only 1 thread to proceed. However, not for those which have the + * @max limit given (ELC), as LRU may be left not cleaned up in full. + */ + if (max == 0) { + if (test_and_set_bit(LDLM_LRU_CANCEL, &ns->ns_flags)) + RETURN(0); + } else if (test_bit(LDLM_LRU_CANCEL, &ns->ns_flags)) + RETURN(0); + LASSERT(ergo(max, min <= max)); + /* No sense to give @batch for ELC */ + LASSERT(ergo(max, batch == 0)); if (!ns_connect_lru_resize(ns)) min = max_t(int, min, ns->ns_nr_unused - ns->ns_max_unused); + /* If at least 1 lock is to be cancelled, cancel at least @batch locks */ + if (min && min < batch) + min = batch; + pf = ldlm_cancel_lru_policy(ns, lru_flags); LASSERT(pf != NULL); @@ -1937,7 +1955,14 @@ static int ldlm_prepare_lru_list(struct ldlm_namespace *ns, unlock_res_and_lock(lock); lu_ref_del(&lock->l_reference, __FUNCTION__, current); added++; + /* Once a lock added, batch the requested amount */ + if (min == 0) + min = batch; } + + if (max == 0) + clear_bit(LDLM_LRU_CANCEL, &ns->ns_flags); + RETURN(added); } @@ -1948,7 +1973,7 @@ int ldlm_cancel_lru_local(struct ldlm_namespace *ns, struct list_head *cancels, { int added; - added = ldlm_prepare_lru_list(ns, cancels, min, max, lru_flags); + added = ldlm_prepare_lru_list(ns, cancels, min, max, 0, lru_flags); if (added <= 0) return added; @@ -1976,7 +2001,7 @@ int ldlm_cancel_lru(struct ldlm_namespace *ns, int min, * Just prepare the list of locks, do not actually cancel them yet. * Locks are cancelled later in a separate thread. */ - count = ldlm_prepare_lru_list(ns, &cancels, min, 0, lru_flags); + count = ldlm_prepare_lru_list(ns, &cancels, min, 0, 0, lru_flags); rc = ldlm_bl_to_thread_list(ns, NULL, &cancels, count, cancel_flags); if (rc == 0) RETURN(count); diff --git a/lustre/ldlm/ldlm_resource.c b/lustre/ldlm/ldlm_resource.c index a805e3f..e439ffb 100644 --- a/lustre/ldlm/ldlm_resource.c +++ b/lustre/ldlm/ldlm_resource.c @@ -913,6 +913,7 @@ struct ldlm_namespace *ldlm_namespace_new(struct obd_device *obd, char *name, ns->ns_stopping = 0; ns->ns_reclaim_start = 0; ns->ns_last_pos = &ns->ns_unused_list; + ns->ns_flags = 0; rc = ldlm_namespace_sysfs_register(ns); if (rc) { -- 1.8.3.1