From 800ffd4711863e1067a693f1283bccf4edddf2a2 Mon Sep 17 00:00:00 2001 From: James Simmons Date: Thu, 31 Aug 2017 16:17:42 -0400 Subject: [PATCH] LU-8541 ldlm: don't use jiffies as sysfs parameter The ldlm sysfs file handles lru_max_age in jiffies which is wrong since jiffies are not consistent across machine since HZ is configurable at compile time. Talking to most users they thought lru_max_age was in seconds which is incorrect. The best way to fix this is to move lru_max_age to millisecs since most systems lustre deals with sets HZ to 1000. To make it clear it is in milliseconds print out lru_max_age with "ms". Since users tend to think in seconds allow passing in seconds besides milliseconds and internally converting them to nanaseconds. Since we have to support milliseconds move to ktime_t since we can't use time64_t. Unfortunately, this makes a relatively large patch, but I could not find a way to split it up some more without breaking atomicity of the change. Change-Id: I0b1814fd9d903767f62fe141d2c95845b75fb95a Signed-off-by: James Simmons Reviewed-on: https://review.whamcloud.com/28370 Reviewed-by: Andreas Dilger Tested-by: Jenkins Tested-by: Maloo Reviewed-by: Dmitry Eremin Reviewed-by: Oleg Drokin --- libcfs/autoconf/lustre-libcfs.m4 | 20 ++++++++++ libcfs/include/libcfs/linux/linux-time.h | 7 ++++ lustre/include/lustre_dlm.h | 11 +++--- lustre/ldlm/ldlm_internal.h | 6 +-- lustre/ldlm/ldlm_lock.c | 7 ++-- lustre/ldlm/ldlm_lockd.c | 6 +-- lustre/ldlm/ldlm_reclaim.c | 66 ++++++++++++++++---------------- lustre/ldlm/ldlm_request.c | 26 ++++++------- lustre/ldlm/ldlm_resource.c | 23 ++++++++--- lustre/ofd/ofd_dev.c | 2 +- lustre/tests/sanity.sh | 2 +- 11 files changed, 109 insertions(+), 67 deletions(-) diff --git a/libcfs/autoconf/lustre-libcfs.m4 b/libcfs/autoconf/lustre-libcfs.m4 index f61f728..f9447df 100644 --- a/libcfs/autoconf/lustre-libcfs.m4 +++ b/libcfs/autoconf/lustre-libcfs.m4 @@ -367,6 +367,25 @@ ktime_after, [ ]) # LIBCFS_KTIME_AFTER # +# Kernel version 3.12 introduced ktime_before +# See linux commit 67cb9366ff5f99868100198efba5ca88aaa6ad25 +# +AC_DEFUN([LIBCFS_KTIME_BEFORE],[ +LB_CHECK_COMPILE([does function 'ktime_before' exist], +ktime_before, [ + #include +],[ + ktime_t start = ktime_set(0, 0); + ktime_t end = start; + + ktime_before(start, end); +],[ + AC_DEFINE(HAVE_KTIME_BEFORE, 1, + [ktime_before is available]) +]) +]) # LIBCFS_KTIME_BEFORE + +# # FC19 3.12 kernel struct shrinker change # AC_DEFUN([LIBCFS_SHRINKER_COUNT],[ @@ -766,6 +785,7 @@ LIBCFS_KTIME_GET_TS64 LIBCFS_KERNEL_PARAM_OPS LIBCFS_KTIME_ADD LIBCFS_KTIME_AFTER +LIBCFS_KTIME_BEFORE LIBCFS_SHRINKER_COUNT # 3.17 LIBCFS_HLIST_ADD_AFTER diff --git a/libcfs/include/libcfs/linux/linux-time.h b/libcfs/include/libcfs/linux/linux-time.h index a217929..6a391e2 100644 --- a/libcfs/include/libcfs/linux/linux-time.h +++ b/libcfs/include/libcfs/linux/linux-time.h @@ -154,6 +154,13 @@ static inline bool ktime_after(const ktime_t cmp1, const ktime_t cmp2) } #endif /* !HAVE_KTIME_AFTER */ +#ifndef HAVE_KTIME_BEFORE +static inline bool ktime_before(const ktime_t cmp1, const ktime_t cmp2) +{ + return cmp1.tv64 < cmp2.tv64; +} +#endif /* !HAVE_KTIME_BEFORE */ + #ifndef HAVE_KTIME_GET_TS64 void ktime_get_ts64(struct timespec64 *ts); #endif /* HAVE_KTIME_GET_TS */ diff --git a/lustre/include/lustre_dlm.h b/lustre/include/lustre_dlm.h index 62382da..17b51ae 100644 --- a/lustre/include/lustre_dlm.h +++ b/lustre/include/lustre_dlm.h @@ -62,7 +62,7 @@ extern struct kset *ldlm_svc_kset; #define OBD_LDLM_DEVICENAME "ldlm" #define LDLM_DEFAULT_LRU_SIZE (100 * num_online_cpus()) -#define LDLM_DEFAULT_MAX_ALIVE (cfs_time_seconds(3900)) /* 65 min */ +#define LDLM_DEFAULT_MAX_ALIVE 3900 /* 3900 seconds ~65 min */ #define LDLM_CTIME_AGE_LIMIT (10) #define LDLM_DEFAULT_PARALLEL_AST_LIMIT 1024 @@ -423,8 +423,10 @@ struct ldlm_namespace { * controlled by available memory on this client and on server. */ unsigned int ns_max_unused; + /** Maximum allowed age (last used time) for locks in the LRU */ - unsigned int ns_max_age; + ktime_t ns_max_age; + /** * Server only: number of times we evicted clients due to lack of reply * to ASTs. @@ -819,10 +821,9 @@ struct ldlm_lock { time64_t l_last_activity; /** - * Time last used by e.g. being matched by lock match. - * Jiffies. Should be converted to time if needed. + * Time, in nanoseconds, last used by e.g. being matched by lock match. */ - cfs_time_t l_last_used; + ktime_t l_last_used; /** Originally requested extent for the extent lock. */ struct ldlm_extent l_req_extent; diff --git a/lustre/ldlm/ldlm_internal.h b/lustre/ldlm/ldlm_internal.h index 0ee5520..8ef4709 100644 --- a/lustre/ldlm/ldlm_internal.h +++ b/lustre/ldlm/ldlm_internal.h @@ -162,9 +162,9 @@ void ldlm_discard_bl_list(struct list_head *bl_list); int ldlm_run_ast_work(struct ldlm_namespace *ns, struct list_head *rpc_list, ldlm_desc_ast_t ast_type); int ldlm_work_gl_ast_lock(struct ptlrpc_request_set *rqset, void *opaq); -int ldlm_lock_remove_from_lru_check(struct ldlm_lock *lock, - cfs_time_t last_use); -#define ldlm_lock_remove_from_lru(lock) ldlm_lock_remove_from_lru_check(lock, 0) +int ldlm_lock_remove_from_lru_check(struct ldlm_lock *lock, ktime_t last_use); +#define ldlm_lock_remove_from_lru(lock) \ + ldlm_lock_remove_from_lru_check(lock, ktime_set(0, 0)) int ldlm_lock_remove_from_lru_nolock(struct ldlm_lock *lock); void ldlm_lock_add_to_lru_nolock(struct ldlm_lock *lock); void ldlm_lock_add_to_lru(struct ldlm_lock *lock); diff --git a/lustre/ldlm/ldlm_lock.c b/lustre/ldlm/ldlm_lock.c index a480054..8d427ec 100644 --- a/lustre/ldlm/ldlm_lock.c +++ b/lustre/ldlm/ldlm_lock.c @@ -255,7 +255,7 @@ int ldlm_lock_remove_from_lru_nolock(struct ldlm_lock *lock) * otherwise, the lock hasn't been in the LRU list. * \retval 1 the lock was in LRU list and removed. */ -int ldlm_lock_remove_from_lru_check(struct ldlm_lock *lock, cfs_time_t last_use) +int ldlm_lock_remove_from_lru_check(struct ldlm_lock *lock, ktime_t last_use) { struct ldlm_namespace *ns = ldlm_lock_to_ns(lock); int rc = 0; @@ -267,7 +267,8 @@ int ldlm_lock_remove_from_lru_check(struct ldlm_lock *lock, cfs_time_t last_use) } spin_lock(&ns->ns_lock); - if (last_use == 0 || last_use == lock->l_last_used) + if (!ktime_compare(last_use, ktime_set(0, 0)) || + !ktime_compare(last_use, lock->l_last_used)) rc = ldlm_lock_remove_from_lru_nolock(lock); spin_unlock(&ns->ns_lock); @@ -281,7 +282,7 @@ void ldlm_lock_add_to_lru_nolock(struct ldlm_lock *lock) { struct ldlm_namespace *ns = ldlm_lock_to_ns(lock); - lock->l_last_used = cfs_time_current(); + lock->l_last_used = ktime_get(); LASSERT(list_empty(&lock->l_lru)); LASSERT(lock->l_resource->lr_type != LDLM_FLOCK); list_add_tail(&lock->l_lru, &ns->ns_unused_list); diff --git a/lustre/ldlm/ldlm_lockd.c b/lustre/ldlm/ldlm_lockd.c index 2209253..3e80cb2 100644 --- a/lustre/ldlm/ldlm_lockd.c +++ b/lustre/ldlm/ldlm_lockd.c @@ -1946,9 +1946,9 @@ static void ldlm_handle_gl_callback(struct ptlrpc_request *req, lock_res_and_lock(lock); if (lock->l_granted_mode == LCK_PW && !lock->l_readers && !lock->l_writers && - cfs_time_after(cfs_time_current(), - cfs_time_add(lock->l_last_used, - cfs_time_seconds(10)))) { + ktime_after(ktime_get(), + ktime_add(lock->l_last_used, + ktime_set(10, 0)))) { unlock_res_and_lock(lock); if (ldlm_bl_to_thread_lock(ns, NULL, lock)) ldlm_handle_bl_callback(ns, NULL, lock); diff --git a/lustre/ldlm/ldlm_reclaim.c b/lustre/ldlm/ldlm_reclaim.c index b551ea2..cf4c87f 100644 --- a/lustre/ldlm/ldlm_reclaim.c +++ b/lustre/ldlm/ldlm_reclaim.c @@ -63,8 +63,8 @@ __u64 ldlm_lock_limit_mb; struct percpu_counter ldlm_granted_total; static atomic_t ldlm_nr_reclaimer; -static cfs_duration_t ldlm_last_reclaim_age; -static cfs_time_t ldlm_last_reclaim_time; +static s64 ldlm_last_reclaim_age_ns; +static ktime_t ldlm_last_reclaim_time; struct ldlm_reclaim_cb_data { struct list_head rcd_rpc_list; @@ -73,7 +73,7 @@ struct ldlm_reclaim_cb_data { int rcd_cursor; int rcd_start; bool rcd_skip; - cfs_duration_t rcd_age; + s64 rcd_age_ns; struct cfs_hash_bd *rcd_prev_bd; }; @@ -143,9 +143,9 @@ static int ldlm_reclaim_lock_cb(struct cfs_hash *hs, struct cfs_hash_bd *bd, continue; if (!OBD_FAIL_CHECK(OBD_FAIL_LDLM_WATERMARK_LOW) && - cfs_time_before(cfs_time_current(), - cfs_time_add(lock->l_last_used, - data->rcd_age))) + ktime_before(ktime_get(), + ktime_add_ns(lock->l_last_used, + data->rcd_age_ns))) continue; if (!ldlm_is_ast_sent(lock)) { @@ -177,7 +177,7 @@ static int ldlm_reclaim_lock_cb(struct cfs_hash *hs, struct cfs_hash_bd *bd, * \param[out] count count of lock still to be revoked */ static void ldlm_reclaim_res(struct ldlm_namespace *ns, int *count, - cfs_duration_t age, bool skip) + s64 age_ns, bool skip) { struct ldlm_reclaim_cb_data data; int idx, type, start; @@ -201,7 +201,7 @@ static void ldlm_reclaim_res(struct ldlm_namespace *ns, int *count, INIT_LIST_HEAD(&data.rcd_rpc_list); data.rcd_added = 0; data.rcd_total = *count; - data.rcd_age = age; + data.rcd_age_ns = age_ns; data.rcd_skip = skip; data.rcd_prev_bd = NULL; start = ns->ns_reclaim_start % CFS_HASH_NBKT(ns->ns_rs_hash); @@ -222,20 +222,22 @@ static void ldlm_reclaim_res(struct ldlm_namespace *ns, int *count, } #define LDLM_RECLAIM_BATCH 512 -#define LDLM_RECLAIM_AGE_MIN cfs_time_seconds(300) -#define LDLM_RECLAIM_AGE_MAX (LDLM_DEFAULT_MAX_ALIVE * 3 / 4) +#define LDLM_RECLAIM_AGE_MIN (300 * NSEC_PER_SEC) +#define LDLM_RECLAIM_AGE_MAX (LDLM_DEFAULT_MAX_ALIVE * NSEC_PER_SEC * 3 / 4) -static inline cfs_duration_t ldlm_reclaim_age(void) +static inline s64 ldlm_reclaim_age(void) { - cfs_duration_t age; - - age = ldlm_last_reclaim_age + - cfs_time_sub(cfs_time_current(), ldlm_last_reclaim_time); - if (age > LDLM_RECLAIM_AGE_MAX) - age = LDLM_RECLAIM_AGE_MAX; - else if (age < (LDLM_RECLAIM_AGE_MIN * 2)) - age = LDLM_RECLAIM_AGE_MIN; - return age; + s64 age_ns = ldlm_last_reclaim_age_ns; + ktime_t now = ktime_get(); + ktime_t diff; + + diff = ktime_sub(now, ldlm_last_reclaim_time); + age_ns += ktime_to_ns(diff); + if (age_ns > LDLM_RECLAIM_AGE_MAX) + age_ns = LDLM_RECLAIM_AGE_MAX; + else if (age_ns < (LDLM_RECLAIM_AGE_MIN * 2)) + age_ns = LDLM_RECLAIM_AGE_MIN; + return age_ns; } /** @@ -249,7 +251,7 @@ static void ldlm_reclaim_ns(void) int count = LDLM_RECLAIM_BATCH; int ns_nr, nr_processed; enum ldlm_side ns_cli = LDLM_NAMESPACE_SERVER; - cfs_duration_t age; + s64 age_ns; bool skip = true; ENTRY; @@ -258,7 +260,7 @@ static void ldlm_reclaim_ns(void) return; } - age = ldlm_reclaim_age(); + age_ns = ldlm_reclaim_age(); again: nr_processed = 0; ns_nr = ldlm_namespace_nr_read(ns_cli); @@ -274,21 +276,21 @@ again: ldlm_namespace_move_to_active_locked(ns, ns_cli); mutex_unlock(ldlm_namespace_lock(ns_cli)); - ldlm_reclaim_res(ns, &count, age, skip); + ldlm_reclaim_res(ns, &count, age_ns, skip); ldlm_namespace_put(ns); nr_processed++; } - if (count > 0 && age > LDLM_RECLAIM_AGE_MIN) { - age >>= 1; - if (age < (LDLM_RECLAIM_AGE_MIN * 2)) - age = LDLM_RECLAIM_AGE_MIN; + if (count > 0 && age_ns > LDLM_RECLAIM_AGE_MIN) { + age_ns >>= 1; + if (age_ns < (LDLM_RECLAIM_AGE_MIN * 2)) + age_ns = LDLM_RECLAIM_AGE_MIN; skip = false; goto again; } - ldlm_last_reclaim_age = age; - ldlm_last_reclaim_time = cfs_time_current(); + ldlm_last_reclaim_age_ns = age_ns; + ldlm_last_reclaim_time = ktime_get(); out: atomic_add_unless(&ldlm_nr_reclaimer, -1, 0); EXIT; @@ -299,7 +301,7 @@ void ldlm_reclaim_add(struct ldlm_lock *lock) if (!ldlm_lock_reclaimable(lock)) return; percpu_counter_add(&ldlm_granted_total, 1); - lock->l_last_used = cfs_time_current(); + lock->l_last_used = ktime_get(); } void ldlm_reclaim_del(struct ldlm_lock *lock) @@ -367,8 +369,8 @@ int ldlm_reclaim_setup(void) ldlm_lock_limit = ldlm_ratio2locknr(LDLM_WM_RATIO_HIGH_DEFAULT); ldlm_lock_limit_mb = ldlm_locknr2mb(ldlm_lock_limit); - ldlm_last_reclaim_age = LDLM_RECLAIM_AGE_MAX; - ldlm_last_reclaim_time = cfs_time_current(); + ldlm_last_reclaim_age_ns = LDLM_RECLAIM_AGE_MAX; + ldlm_last_reclaim_time = ktime_get(); #ifdef HAVE_PERCPU_COUNTER_INIT_GFP_FLAG return percpu_counter_init(&ldlm_granted_total, 0, GFP_KERNEL); diff --git a/lustre/ldlm/ldlm_request.c b/lustre/ldlm/ldlm_request.c index 37c2db0..fb67a1e 100644 --- a/lustre/ldlm/ldlm_request.c +++ b/lustre/ldlm/ldlm_request.c @@ -1502,10 +1502,10 @@ static enum ldlm_policy_res ldlm_cancel_lrur_policy(struct ldlm_namespace *ns, int unused, int added, int count) { - cfs_time_t cur = cfs_time_current(); + ktime_t cur = ktime_get(); struct ldlm_pool *pl = &ns->ns_pool; - __u64 slv, lvf, lv; - cfs_time_t la; + u64 slv, lvf, lv; + s64 la; /* Stop LRU processing when we reach past @count or have checked all * locks in LRU. */ @@ -1513,15 +1513,15 @@ static enum ldlm_policy_res ldlm_cancel_lrur_policy(struct ldlm_namespace *ns, return LDLM_POLICY_KEEP_LOCK; /* Despite of the LV, It doesn't make sense to keep the lock which - * is unused for ns_max_age time. */ - if (cfs_time_after(cfs_time_current(), - cfs_time_add(lock->l_last_used, ns->ns_max_age))) + * is unused for ns_max_age time. + */ + if (ktime_after(ktime_get(), + ktime_add(lock->l_last_used, ns->ns_max_age))) return LDLM_POLICY_CANCEL_LOCK; slv = ldlm_pool_get_slv(pl); lvf = ldlm_pool_get_lvf(pl); - la = cfs_duration_sec(cfs_time_sub(cur, - lock->l_last_used)); + la = ktime_to_ns(ktime_sub(cur, lock->l_last_used)) / NSEC_PER_SEC; lv = lvf * la * unused; /* Inform pool about current CLV to see it via proc. */ @@ -1585,8 +1585,8 @@ static enum ldlm_policy_res ldlm_cancel_aged_policy(struct ldlm_namespace *ns, int count) { if ((added >= count) && - cfs_time_before(cfs_time_current(), - cfs_time_add(lock->l_last_used, ns->ns_max_age))) + ktime_before(ktime_get(), + ktime_add(lock->l_last_used, ns->ns_max_age))) return LDLM_POLICY_KEEP_LOCK; return LDLM_POLICY_CANCEL_LOCK; @@ -1719,7 +1719,7 @@ static int ldlm_prepare_lru_list(struct ldlm_namespace *ns, while (!list_empty(&ns->ns_unused_list)) { enum ldlm_policy_res result; - cfs_time_t last_use = 0; + ktime_t last_use = ktime_set(0, 0); /* all unused locks */ if (remained-- <= 0) @@ -1739,13 +1739,11 @@ static int ldlm_prepare_lru_list(struct ldlm_namespace *ns, continue; last_use = lock->l_last_used; - if (last_use == cfs_time_current()) - continue; /* Somebody is already doing CANCEL. No need for this * lock in LRU, do not traverse it again. */ if (!ldlm_is_canceling(lock)) - break; + break; ldlm_lock_remove_from_lru_nolock(lock); } diff --git a/lustre/ldlm/ldlm_resource.c b/lustre/ldlm/ldlm_resource.c index 5cb58f5..31ee704 100644 --- a/lustre/ldlm/ldlm_resource.c +++ b/lustre/ldlm/ldlm_resource.c @@ -407,7 +407,7 @@ static ssize_t lru_max_age_show(struct kobject *kobj, struct attribute *attr, struct ldlm_namespace *ns = container_of(kobj, struct ldlm_namespace, ns_kobj); - return sprintf(buf, "%u\n", ns->ns_max_age); + return sprintf(buf, "%lld\n", ktime_to_ms(ns->ns_max_age)); } static ssize_t lru_max_age_store(struct kobject *kobj, struct attribute *attr, @@ -415,14 +415,27 @@ static ssize_t lru_max_age_store(struct kobject *kobj, struct attribute *attr, { struct ldlm_namespace *ns = container_of(kobj, struct ldlm_namespace, ns_kobj); - unsigned long tmp; + int scale = NSEC_PER_MSEC; + unsigned long long tmp; + char *buf; int err; - err = kstrtoul(buffer, 10, &tmp); + /* Did the user ask in seconds or milliseconds. Default is in ms */ + buf = strstr(buffer, "ms"); + if (!buf) { + buf = strchr(buffer, 's'); + if (buf) + scale = NSEC_PER_SEC; + } + + if (buf) + *buf = '\0'; + + err = kstrtoull(buffer, 10, &tmp); if (err != 0) return -EINVAL; - ns->ns_max_age = tmp; + ns->ns_max_age = ktime_set(0, tmp * scale); return count; } @@ -940,7 +953,7 @@ struct ldlm_namespace *ldlm_namespace_new(struct obd_device *obd, char *name, ns->ns_max_parallel_ast = LDLM_DEFAULT_PARALLEL_AST_LIMIT; ns->ns_nr_unused = 0; ns->ns_max_unused = LDLM_DEFAULT_LRU_SIZE; - ns->ns_max_age = LDLM_DEFAULT_MAX_ALIVE; + ns->ns_max_age = ktime_set(LDLM_DEFAULT_MAX_ALIVE, 0); ns->ns_ctime_age_limit = LDLM_CTIME_AGE_LIMIT; ns->ns_timeouts = 0; ns->ns_orig_connect_flags = 0; diff --git a/lustre/ofd/ofd_dev.c b/lustre/ofd/ofd_dev.c index 17ce15f..3bb3d59 100644 --- a/lustre/ofd/ofd_dev.c +++ b/lustre/ofd/ofd_dev.c @@ -2432,7 +2432,7 @@ static void ofd_prolong_extent_locks(struct tgt_session_info *tsi, LDLM_LOCK_PUT(lock); RETURN_EXIT; } - lock->l_last_used = cfs_time_current(); + lock->l_last_used = ktime_get(); LDLM_LOCK_PUT(lock); } } diff --git a/lustre/tests/sanity.sh b/lustre/tests/sanity.sh index 43bf632..a136f4b 100755 --- a/lustre/tests/sanity.sh +++ b/lustre/tests/sanity.sh @@ -8972,7 +8972,7 @@ test_124c() { echo "unused=$unused, max_age=$max_age, recalc_p=$recalc_p" # set lru_max_age to 1 sec - $LCTL set_param $nsdir.lru_max_age=1000 # jiffies + $LCTL set_param $nsdir.lru_max_age=1000 # milliseconds echo "sleep $((recalc_p * 2)) seconds..." sleep $((recalc_p * 2)) -- 1.8.3.1