Skip to content

Commit 2fcab87

Browse files
committed
Linux 5.5 compat: blkg_tryget()
Commit torvalds/linux@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 <[email protected]> Signed-off-by: Brian Behlendorf <[email protected]> Closes openzfs#9745 Closes openzfs#10072
1 parent 9bb3d57 commit 2fcab87

File tree

3 files changed

+70
-1
lines changed

3 files changed

+70
-1
lines changed

config/kernel-blkg-tryget.m4

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
dnl #
2+
dnl # Linux 5.5 API,
3+
dnl #
4+
dnl # The Linux 5.5 kernel updated percpu_ref_tryget() which is inlined by
5+
dnl # blkg_tryget() to use rcu_read_lock() instead of rcu_read_lock_sched().
6+
dnl # As a side effect the function was converted to GPL-only.
7+
dnl #
8+
AC_DEFUN([ZFS_AC_KERNEL_SRC_BLKG_TRYGET], [
9+
ZFS_LINUX_TEST_SRC([blkg_tryget], [
10+
#include <linux/blk-cgroup.h>
11+
#include <linux/bio.h>
12+
#include <linux/fs.h>
13+
],[
14+
struct blkcg_gq blkg __attribute__ ((unused));
15+
bool rc __attribute__ ((unused));
16+
rc = blkg_tryget(&blkg);
17+
], [], [$ZFS_META_LICENSE])
18+
])
19+
20+
AC_DEFUN([ZFS_AC_KERNEL_BLKG_TRYGET], [
21+
AC_MSG_CHECKING([whether blkg_tryget() is available])
22+
ZFS_LINUX_TEST_RESULT([blkg_tryget], [
23+
AC_MSG_RESULT(yes)
24+
AC_DEFINE(HAVE_BLKG_TRYGET, 1, [blkg_tryget() is available])
25+
26+
AC_MSG_CHECKING([whether blkg_tryget() is GPL-only])
27+
ZFS_LINUX_TEST_RESULT([blkg_tryget_license], [
28+
AC_MSG_RESULT(no)
29+
],[
30+
AC_MSG_RESULT(yes)
31+
AC_DEFINE(HAVE_BLKG_TRYGET_GPL_ONLY, 1,
32+
[blkg_tryget() GPL-only])
33+
])
34+
],[
35+
AC_MSG_RESULT(no)
36+
])
37+
])

config/kernel.m4

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ AC_DEFUN([ZFS_AC_KERNEL_TEST_SRC], [
7070
ZFS_AC_KERNEL_SRC_BIO_BI_STATUS
7171
ZFS_AC_KERNEL_SRC_BIO_RW_BARRIER
7272
ZFS_AC_KERNEL_SRC_BIO_RW_DISCARD
73+
ZFS_AC_KERNEL_SRC_BLKG_TRYGET
7374
ZFS_AC_KERNEL_SRC_BLK_QUEUE_BDI
7475
ZFS_AC_KERNEL_SRC_BLK_QUEUE_DISCARD
7576
ZFS_AC_KERNEL_SRC_BLK_QUEUE_SECURE_ERASE
@@ -186,6 +187,7 @@ AC_DEFUN([ZFS_AC_KERNEL_TEST_RESULT], [
186187
ZFS_AC_KERNEL_BIO_BI_STATUS
187188
ZFS_AC_KERNEL_BIO_RW_BARRIER
188189
ZFS_AC_KERNEL_BIO_RW_DISCARD
190+
ZFS_AC_KERNEL_BLKG_TRYGET
189191
ZFS_AC_KERNEL_BLK_QUEUE_BDI
190192
ZFS_AC_KERNEL_BLK_QUEUE_DISCARD
191193
ZFS_AC_KERNEL_BLK_QUEUE_SECURE_ERASE

module/zfs/vdev_disk.c

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -473,6 +473,36 @@ vdev_submit_bio_impl(struct bio *bio)
473473

474474
#ifdef HAVE_BIO_SET_DEV
475475
#if defined(CONFIG_BLK_CGROUP) && defined(HAVE_BIO_SET_DEV_GPL_ONLY)
476+
/*
477+
* The Linux 5.5 kernel updated percpu_ref_tryget() which is inlined by
478+
* blkg_tryget() to use rcu_read_lock() instead of rcu_read_lock_sched().
479+
* As a side effect the function was converted to GPL-only. Define our
480+
* own version when needed which uses rcu_read_lock_sched().
481+
*/
482+
#if defined(HAVE_BLKG_TRYGET_GPL_ONLY)
483+
static inline bool
484+
vdev_blkg_tryget(struct blkcg_gq *blkg)
485+
{
486+
struct percpu_ref *ref = &blkg->refcnt;
487+
unsigned long __percpu *count;
488+
bool rc;
489+
490+
rcu_read_lock_sched();
491+
492+
if (__ref_is_percpu(ref, &count)) {
493+
this_cpu_inc(*count);
494+
rc = true;
495+
} else {
496+
rc = atomic_long_inc_not_zero(&ref->count);
497+
}
498+
499+
rcu_read_unlock_sched();
500+
501+
return (rc);
502+
}
503+
#elif defined(HAVE_BLKG_TRYGET)
504+
#define vdev_blkg_tryget(bg) blkg_tryget(bg)
505+
#endif
476506
/*
477507
* The Linux 5.0 kernel updated the bio_set_dev() macro so it calls the
478508
* GPL-only bio_associate_blkg() symbol thus inadvertently converting
@@ -487,7 +517,7 @@ vdev_bio_associate_blkg(struct bio *bio)
487517
ASSERT3P(q, !=, NULL);
488518
ASSERT3P(bio->bi_blkg, ==, NULL);
489519

490-
if (q->root_blkg && blkg_tryget(q->root_blkg))
520+
if (q->root_blkg && vdev_blkg_tryget(q->root_blkg))
491521
bio->bi_blkg = q->root_blkg;
492522
}
493523
#define bio_associate_blkg vdev_bio_associate_blkg

0 commit comments

Comments
 (0)