Whamcloud - gitweb
LU-9679 osc: convert oe_refc to kref 01/37601/9
authorNeilBrown <neilb@suse.com>
Wed, 12 Dec 2018 06:49:53 +0000 (17:49 +1100)
committerOleg Drokin <green@whamcloud.com>
Tue, 14 Apr 2020 08:09:08 +0000 (08:09 +0000)
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 <neilb@suse.com>
Change-Id: I42fd17c4261b85b273387936b97fce463273e2b8
Reviewed-on: https://review.whamcloud.com/37601
Tested-by: jenkins <devops@whamcloud.com>
Tested-by: Maloo <maloo@whamcloud.com>
Reviewed-by: James Simmons <jsimmons@infradead.org>
Reviewed-by: Shaun Tancheff <shaun.tancheff@hpe.com>
Reviewed-by: Oleg Drokin <green@whamcloud.com>
libcfs/autoconf/lustre-libcfs.m4
libcfs/include/libcfs/linux/linux-misc.h
lustre/include/lustre_osc.h
lustre/osc/osc_cache.c

index 4db29eb..5992d2a 100644 (file)
@@ -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 <linux/kref.h>
+],[
+       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
index 87bfda1..7a4c83b 100644 (file)
@@ -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
index 6995aec..cd7561c 100644 (file)
@@ -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. */
index 5a829cd..3214339 100644 (file)
@@ -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);
 }
 
 /**