From 9c2fb0b29cec8a02c0c080da7596c2c99921d47d Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Wed, 12 Dec 2018 17:49:53 +1100 Subject: [PATCH] LU-9679 osc: convert oe_refc to kref oe_refc is used like a kref, so make it one. As cl_object_put() needs an 'env', we cannot quite use kref_put() as intended. Maybe that can be fixed one day. This requires kref_read() to be provided for older kernels. The original Linux-commit also converted oe_users to a refcount_t but that was later reverted. Linux-Commit: 35ea2a7c694b ("lustre: osc: convert oe_refc and oe_users to kref and refcount_") Signed-off-by: Mr NeilBrown Change-Id: I42fd17c4261b85b273387936b97fce463273e2b8 Reviewed-on: https://review.whamcloud.com/37601 Tested-by: jenkins Tested-by: Maloo Reviewed-by: James Simmons Reviewed-by: Shaun Tancheff Reviewed-by: Oleg Drokin --- libcfs/autoconf/lustre-libcfs.m4 | 17 +++++++++ libcfs/include/libcfs/linux/linux-misc.h | 7 ++++ lustre/include/lustre_osc.h | 2 +- lustre/osc/osc_cache.c | 61 ++++++++++++++++++++------------ 4 files changed, 63 insertions(+), 24 deletions(-) diff --git a/libcfs/autoconf/lustre-libcfs.m4 b/libcfs/autoconf/lustre-libcfs.m4 index 4db29eb..5992d2a 100644 --- a/libcfs/autoconf/lustre-libcfs.m4 +++ b/libcfs/autoconf/lustre-libcfs.m4 @@ -750,6 +750,22 @@ LB_CHECK_LINUX_HEADER([linux/sched/signal.h], [ ]) # LIBCFS_SCHED_HEADERS # +# Kernel version 4.11-rc1 commit 2c935bc57221cc2edc787c72ea0e2d30cdcd3d5e +# introduce kref_read +# +AC_DEFUN([LIBCFS_KREF_READ], [ +LB_CHECK_COMPILE([if 'kref_read' exists], +kref_read, [ + #include +],[ + kref_read(NULL); +],[ + AC_DEFINE(HAVE_KREF_READ, 1, + [kref_read() is available]) +]) +]) LIBCFS_KREF_READ + +# # Kernel version 4.11-rc1 commit da20420f83ea0fbcf3d03afda08d971ea1d8a356 # introduced rht_bucket_var # @@ -1245,6 +1261,7 @@ LIBCFS_REFCOUNT_T # 4.11 LIBCFS_RHASHTABLE_LOOKUP_GET_INSERT_FAST LIBCFS_SCHED_HEADERS +LIBCFS_KREF_READ LIBCFS_RHT_BUCKET_VAR # 4.12 LIBCFS_HAVE_PROCESSOR_HEADER diff --git a/libcfs/include/libcfs/linux/linux-misc.h b/libcfs/include/libcfs/linux/linux-misc.h index 87bfda1..7a4c83b 100644 --- a/libcfs/include/libcfs/linux/linux-misc.h +++ b/libcfs/include/libcfs/linux/linux-misc.h @@ -99,6 +99,13 @@ int cfs_apply_workqueue_attrs(struct workqueue_struct *wq, int kstrtobool_from_user(const char __user *s, size_t count, bool *res); #endif /* HAVE_KSTRTOBOOL_FROM_USER */ +#ifndef HAVE_KREF_READ +static inline int kref_read(const struct kref *kref) +{ + return atomic_read(&kref->refcount); +} +#endif /* HAVE_KREF_READ */ + void cfs_arch_init(void); #ifndef container_of_safe diff --git a/lustre/include/lustre_osc.h b/lustre/include/lustre_osc.h index 6995aec..cd7561c 100644 --- a/lustre/include/lustre_osc.h +++ b/lustre/include/lustre_osc.h @@ -887,7 +887,7 @@ struct osc_extent { /** osc_object of this extent */ struct osc_object *oe_obj; /** refcount, removed from red-black tree if reaches zero. */ - atomic_t oe_refc; + struct kref oe_refc; /** busy if non-zero */ atomic_t oe_users; /** link list of osc_object's oo_{hp|urgent|locking}_exts. */ diff --git a/lustre/osc/osc_cache.c b/lustre/osc/osc_cache.c index 5a829cd..3214339 100644 --- a/lustre/osc/osc_cache.c +++ b/lustre/osc/osc_cache.c @@ -110,7 +110,7 @@ static const char *oes_strings[] = { /* ----- extent part 0 ----- */ \ __ext, EXTPARA(__ext), \ /* ----- part 1 ----- */ \ - atomic_read(&__ext->oe_refc), \ + kref_read(&__ext->oe_refc), \ atomic_read(&__ext->oe_users), \ list_empty_marker(&__ext->oe_link), \ oes_strings[__ext->oe_state], ext_flags(__ext, __buf), \ @@ -186,10 +186,10 @@ static int osc_extent_sanity_check0(struct osc_extent *ext, if (ext->oe_state >= OES_STATE_MAX) GOTO(out, rc = 10); - if (atomic_read(&ext->oe_refc) <= 0) + if (kref_read(&ext->oe_refc) <= 0) GOTO(out, rc = 20); - if (atomic_read(&ext->oe_refc) < atomic_read(&ext->oe_users)) + if (kref_read(&ext->oe_refc) < atomic_read(&ext->oe_users)) GOTO(out, rc = 30); switch (ext->oe_state) { @@ -329,7 +329,7 @@ static struct osc_extent *osc_extent_alloc(struct osc_object *obj) RB_CLEAR_NODE(&ext->oe_node); ext->oe_obj = obj; cl_object_get(osc2cl(obj)); - atomic_set(&ext->oe_refc, 1); + kref_init(&ext->oe_refc); atomic_set(&ext->oe_users, 0); INIT_LIST_HEAD(&ext->oe_link); ext->oe_state = OES_INV; @@ -340,35 +340,50 @@ static struct osc_extent *osc_extent_alloc(struct osc_object *obj) return ext; } -static void osc_extent_free(struct osc_extent *ext) +static void osc_extent_free(struct kref *kref) { + struct osc_extent *ext = container_of(kref, struct osc_extent, + oe_refc); + + LASSERT(list_empty(&ext->oe_link)); + LASSERT(atomic_read(&ext->oe_users) == 0); + LASSERT(ext->oe_state == OES_INV); + LASSERT(RB_EMPTY_NODE(&ext->oe_node)); + + if (ext->oe_dlmlock) { + lu_ref_del(&ext->oe_dlmlock->l_reference, + "osc_extent", ext); + LDLM_LOCK_PUT(ext->oe_dlmlock); + ext->oe_dlmlock = NULL; + } +#if 0 + /* If/When cl_object_put drops the need for 'env', + * this code can be enabled, and matching code in + * osc_extent_put removed. + */ + cl_object_put(osc2cl(ext->oe_obj)); + OBD_SLAB_FREE_PTR(ext, osc_extent_kmem); +#endif } static struct osc_extent *osc_extent_get(struct osc_extent *ext) { - LASSERT(atomic_read(&ext->oe_refc) >= 0); - atomic_inc(&ext->oe_refc); + LASSERT(kref_read(&ext->oe_refc) >= 0); + kref_get(&ext->oe_refc); return ext; } static void osc_extent_put(const struct lu_env *env, struct osc_extent *ext) { - LASSERT(atomic_read(&ext->oe_refc) > 0); - if (atomic_dec_and_test(&ext->oe_refc)) { - LASSERT(list_empty(&ext->oe_link)); - LASSERT(atomic_read(&ext->oe_users) == 0); - LASSERT(ext->oe_state == OES_INV); - LASSERT(RB_EMPTY_NODE(&ext->oe_node)); - - if (ext->oe_dlmlock != NULL) { - lu_ref_del(&ext->oe_dlmlock->l_reference, - "osc_extent", ext); - LDLM_LOCK_RELEASE(ext->oe_dlmlock); - ext->oe_dlmlock = NULL; - } + LASSERT(kref_read(&ext->oe_refc) > 0); + if (kref_put(&ext->oe_refc, osc_extent_free)) { + /* This should be in osc_extent_free(), but + * while we need to pass 'env' it cannot be. + */ cl_object_put(env, osc2cl(ext->oe_obj)); - osc_extent_free(ext); + + OBD_SLAB_FREE_PTR(ext, osc_extent_kmem); } } @@ -379,9 +394,9 @@ static void osc_extent_put(const struct lu_env *env, struct osc_extent *ext) */ static void osc_extent_put_trust(struct osc_extent *ext) { - LASSERT(atomic_read(&ext->oe_refc) > 1); + LASSERT(kref_read(&ext->oe_refc) > 1); assert_osc_object_is_locked(ext->oe_obj); - atomic_dec(&ext->oe_refc); + osc_extent_put(NULL, ext); } /** -- 1.8.3.1