]> git.proxmox.com Git - mirror_zfs.git/commitdiff
Linux 5.5 compat: blkg_tryget()
authorBrian Behlendorf <behlendorf1@llnl.gov>
Fri, 28 Feb 2020 16:58:39 +0000 (08:58 -0800)
committerGitHub <noreply@github.com>
Fri, 28 Feb 2020 16:58:39 +0000 (08:58 -0800)
Commit https://github.com/torvalds/linux/commit/9e8d42a0f accidentally
converted the static inline function blkg_tryget() to GPL-only for
kernels built with CONFIG_PREEMPT_RCU=y and CONFIG_BLK_CGROUP=y.

Resolve the build issue by providing our own equivalent functionality
when needed which uses rcu_read_lock_sched() internally as before.

Reviewed-by: Tony Hutter <hutter2@llnl.gov>
Signed-off-by: Brian Behlendorf <behlendorf1@llnl.gov>
Closes #9745
Closes #10072

config/kernel-bio.m4
module/os/linux/zfs/vdev_disk.c

index 75a4a6de4eb8b637a1850e7f991471eadafc1b89..afa1f1cabeb01f12f570f35f5ef2d036c1eb575a 100644 (file)
@@ -331,6 +331,44 @@ AC_DEFUN([ZFS_AC_KERNEL_BIO_CURRENT_BIO_LIST], [
        ])
 ])
 
+dnl #
+dnl # Linux 5.5 API,
+dnl #
+dnl # The Linux 5.5 kernel updated percpu_ref_tryget() which is inlined by
+dnl # blkg_tryget() to use rcu_read_lock() instead of rcu_read_lock_sched().
+dnl # As a side effect the function was converted to GPL-only.
+dnl #
+AC_DEFUN([ZFS_AC_KERNEL_SRC_BLKG_TRYGET], [
+       ZFS_LINUX_TEST_SRC([blkg_tryget], [
+               #include <linux/blk-cgroup.h>
+               #include <linux/bio.h>
+               #include <linux/fs.h>
+       ],[
+               struct blkcg_gq blkg __attribute__ ((unused));
+               bool rc __attribute__ ((unused));
+               rc = blkg_tryget(&blkg);
+       ], [], [$ZFS_META_LICENSE])
+])
+
+AC_DEFUN([ZFS_AC_KERNEL_BLKG_TRYGET], [
+       AC_MSG_CHECKING([whether blkg_tryget() is available])
+       ZFS_LINUX_TEST_RESULT([blkg_tryget], [
+               AC_MSG_RESULT(yes)
+               AC_DEFINE(HAVE_BLKG_TRYGET, 1, [blkg_tryget() is available])
+
+               AC_MSG_CHECKING([whether blkg_tryget() is GPL-only])
+               ZFS_LINUX_TEST_RESULT([blkg_tryget_license], [
+                       AC_MSG_RESULT(no)
+               ],[
+                       AC_MSG_RESULT(yes)
+                       AC_DEFINE(HAVE_BLKG_TRYGET_GPL_ONLY, 1,
+                           [blkg_tryget() GPL-only])
+               ])
+       ],[
+               AC_MSG_RESULT(no)
+       ])
+])
+
 AC_DEFUN([ZFS_AC_KERNEL_SRC_BIO], [
        ZFS_AC_KERNEL_SRC_REQ
        ZFS_AC_KERNEL_SRC_BIO_OPS
@@ -340,6 +378,7 @@ AC_DEFUN([ZFS_AC_KERNEL_SRC_BIO], [
        ZFS_AC_KERNEL_SRC_BIO_BVEC_ITER
        ZFS_AC_KERNEL_SRC_BIO_SUBMIT_BIO
        ZFS_AC_KERNEL_SRC_BIO_CURRENT_BIO_LIST
+       ZFS_AC_KERNEL_SRC_BLKG_TRYGET
 ])
 
 AC_DEFUN([ZFS_AC_KERNEL_BIO], [
@@ -360,4 +399,5 @@ AC_DEFUN([ZFS_AC_KERNEL_BIO], [
        ZFS_AC_KERNEL_BIO_BVEC_ITER
        ZFS_AC_KERNEL_BIO_SUBMIT_BIO
        ZFS_AC_KERNEL_BIO_CURRENT_BIO_LIST
+       ZFS_AC_KERNEL_BLKG_TRYGET
 ])
index cbe9e18316ed065c6c745c95e389b1a439f5adf4..66e408c6c98c54e85c3f5fa79f3cabd812f766e6 100644 (file)
@@ -456,6 +456,36 @@ vdev_submit_bio_impl(struct bio *bio)
 
 #ifdef HAVE_BIO_SET_DEV
 #if defined(CONFIG_BLK_CGROUP) && defined(HAVE_BIO_SET_DEV_GPL_ONLY)
+/*
+ * The Linux 5.5 kernel updated percpu_ref_tryget() which is inlined by
+ * blkg_tryget() to use rcu_read_lock() instead of rcu_read_lock_sched().
+ * As a side effect the function was converted to GPL-only.  Define our
+ * own version when needed which uses rcu_read_lock_sched().
+ */
+#if defined(HAVE_BLKG_TRYGET_GPL_ONLY)
+static inline bool
+vdev_blkg_tryget(struct blkcg_gq *blkg)
+{
+       struct percpu_ref *ref = &blkg->refcnt;
+       unsigned long __percpu *count;
+       bool rc;
+
+       rcu_read_lock_sched();
+
+       if (__ref_is_percpu(ref, &count)) {
+               this_cpu_inc(*count);
+               rc = true;
+       } else {
+               rc = atomic_long_inc_not_zero(&ref->count);
+       }
+
+       rcu_read_unlock_sched();
+
+       return (rc);
+}
+#elif defined(HAVE_BLKG_TRYGET)
+#define        vdev_blkg_tryget(bg)    blkg_tryget(bg)
+#endif
 /*
  * The Linux 5.0 kernel updated the bio_set_dev() macro so it calls the
  * GPL-only bio_associate_blkg() symbol thus inadvertently converting
@@ -470,7 +500,7 @@ vdev_bio_associate_blkg(struct bio *bio)
        ASSERT3P(q, !=, NULL);
        ASSERT3P(bio->bi_blkg, ==, NULL);
 
-       if (q->root_blkg && blkg_tryget(q->root_blkg))
+       if (q->root_blkg && vdev_blkg_tryget(q->root_blkg))
                bio->bi_blkg = q->root_blkg;
 }
 #define        bio_associate_blkg vdev_bio_associate_blkg