From f3d42a7000884149d3be408b9d5f170a355dd9e6 Mon Sep 17 00:00:00 2001 From: Alex Zhuravlev Date: Fri, 11 Mar 2016 18:26:47 +0300 Subject: [PATCH] LU-7896: do not call lu_site_purge() for single object exceed first of all, this is expensive procedure including a global mutex and per-bucket spinlocks. also, all the threads observed exceed will be calling lu_site_purge() and essentially serialized on that. instead we can let other threads to skip the whole procedure. Change-Id: Ib5d213c70b5a2f259153ab24d7c3f5a3e97239df Signed-off-by: Alex Zhuravlev Reviewed-on: http://review.whamcloud.com/19082 Reviewed-by: Andreas Dilger Tested-by: Jenkins Tested-by: Maloo Reviewed-by: Mike Pershin Reviewed-by: Oleg Drokin --- lustre/include/lu_object.h | 8 +++++++- lustre/obdclass/lu_object.c | 24 ++++++++++++++++-------- 2 files changed, 23 insertions(+), 9 deletions(-) diff --git a/lustre/include/lu_object.h b/lustre/include/lu_object.h index 18f1ad6..e8e4cf4 100644 --- a/lustre/include/lu_object.h +++ b/lustre/include/lu_object.h @@ -729,8 +729,14 @@ static inline int lu_object_is_dying(const struct lu_object_header *h) void lu_object_put(const struct lu_env *env, struct lu_object *o); void lu_object_put_nocache(const struct lu_env *env, struct lu_object *o); void lu_object_unhash(const struct lu_env *env, struct lu_object *o); +int lu_site_purge_objects(const struct lu_env *env, struct lu_site *s, int nr, + int canblock); -int lu_site_purge(const struct lu_env *env, struct lu_site *s, int nr); +static inline int lu_site_purge(const struct lu_env *env, struct lu_site *s, + int nr) +{ + return lu_site_purge_objects(env, s, nr, 1); +} void lu_site_print(const struct lu_env *env, struct lu_site *s, void *cookie, lu_printer_t printer); diff --git a/lustre/obdclass/lu_object.c b/lustre/obdclass/lu_object.c index 5cce81b..f76917c 100644 --- a/lustre/obdclass/lu_object.c +++ b/lustre/obdclass/lu_object.c @@ -60,7 +60,7 @@ enum { LU_CACHE_PERCENT_DEFAULT = 20 }; -#define LU_CACHE_NR_MAX_ADJUST 128 +#define LU_CACHE_NR_MAX_ADJUST 512 #define LU_CACHE_NR_UNLIMITED -1 #define LU_CACHE_NR_DEFAULT LU_CACHE_NR_UNLIMITED #define LU_CACHE_NR_LDISKFS_LIMIT LU_CACHE_NR_UNLIMITED @@ -348,8 +348,11 @@ static void lu_object_free(const struct lu_env *env, struct lu_object *o) /** * Free \a nr objects from the cold end of the site LRU list. + * if canblock is 0, then don't block awaiting for another + * instance of lu_site_purge() to complete */ -int lu_site_purge(const struct lu_env *env, struct lu_site *s, int nr) +int lu_site_purge_objects(const struct lu_env *env, struct lu_site *s, + int nr, int canblock) { struct lu_object_header *h; struct lu_object_header *temp; @@ -379,7 +382,11 @@ int lu_site_purge(const struct lu_env *env, struct lu_site *s, int nr) * It doesn't make any sense to make purge threads parallel, that can * only bring troubles to us. See LU-5331. */ - mutex_lock(&s->ls_purge_mutex); + if (canblock != 0) + mutex_lock(&s->ls_purge_mutex); + else if (mutex_trylock(&s->ls_purge_mutex) == 0) + goto out; + did_sth = 0; cfs_hash_for_each_bucket(s->ls_obj_hash, &bd, i) { if (i < start) @@ -435,9 +442,10 @@ int lu_site_purge(const struct lu_env *env, struct lu_site *s, int nr) /* race on s->ls_purge_start, but nobody cares */ s->ls_purge_start = i % CFS_HASH_NBKT(s->ls_obj_hash); +out: return nr; } -EXPORT_SYMBOL(lu_site_purge); +EXPORT_SYMBOL(lu_site_purge_objects); /* * Object printing. @@ -665,11 +673,11 @@ static void lu_object_limit(const struct lu_env *env, size = cfs_hash_size_get(dev->ld_site->ls_obj_hash); nr = (__u64)lu_cache_nr; - if (size > nr) - lu_site_purge(env, dev->ld_site, - MIN(size - nr, LU_CACHE_NR_MAX_ADJUST)); + if (size <= nr) + return; - return; + lu_site_purge_objects(env, dev->ld_site, + MIN(size - nr, LU_CACHE_NR_MAX_ADJUST), 0); } static struct lu_object *lu_object_new(const struct lu_env *env, -- 1.8.3.1