Skip to content

Commit e8ba972

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 equivilant functionality when needed which uses rcu_read_lock_sched() internally as before. Signed-off-by: Brian Behlendorf <[email protected]> Issue #9745
1 parent 3d5ba1c commit e8ba972

File tree

2 files changed

+71
-1
lines changed

2 files changed

+71
-1
lines changed

config/kernel-bio.m4

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -331,6 +331,44 @@ AC_DEFUN([ZFS_AC_KERNEL_BIO_CURRENT_BIO_LIST], [
331331
])
332332
])
333333

334+
dnl #
335+
dnl # Linux 5.5 API,
336+
dnl #
337+
dnl # The Linux 5.5 kernel updated percpu_ref_tryget() which is inlined by
338+
dnl # blkg_tryget() to use rcu_read_lock() instead of rcu_read_lock_sched().
339+
dnl # As a side effect the function was converted to GPL-only.
340+
dnl #
341+
AC_DEFUN([ZFS_AC_KERNEL_SRC_BLKG_TRYGET], [
342+
ZFS_LINUX_TEST_SRC([blkg_tryget], [
343+
#include <linux/blk-cgroup.h>
344+
#include <linux/bio.h>
345+
#include <linux/fs.h>
346+
],[
347+
struct blkcg_gq blkg __attribute__ ((unused));
348+
bool rc __attribute__ ((unused));
349+
rc = blkg_tryget(&blkg);
350+
], [], [$ZFS_META_LICENSE])
351+
])
352+
353+
AC_DEFUN([ZFS_AC_KERNEL_BLKG_TRYGET], [
354+
AC_MSG_CHECKING([whether blkg_tryget() is available])
355+
ZFS_LINUX_TEST_RESULT([blkg_tryget], [
356+
AC_MSG_RESULT(yes)
357+
AC_DEFINE(HAVE_BLKG_TRYGET, 1, [blkg_tryget() is available])
358+
359+
AC_MSG_CHECKING([whether blkg_tryget() is GPL-only])
360+
ZFS_LINUX_TEST_RESULT([blkg_tryget_license], [
361+
AC_MSG_RESULT(no)
362+
],[
363+
AC_MSG_RESULT(yes)
364+
AC_DEFINE(HAVE_BLKG_TRYGET_GPL_ONLY, 1,
365+
[blkg_tryget() GPL-only])
366+
])
367+
],[
368+
AC_MSG_RESULT(no)
369+
])
370+
])
371+
334372
AC_DEFUN([ZFS_AC_KERNEL_SRC_BIO], [
335373
ZFS_AC_KERNEL_SRC_REQ
336374
ZFS_AC_KERNEL_SRC_BIO_OPS
@@ -340,6 +378,7 @@ AC_DEFUN([ZFS_AC_KERNEL_SRC_BIO], [
340378
ZFS_AC_KERNEL_SRC_BIO_BVEC_ITER
341379
ZFS_AC_KERNEL_SRC_BIO_SUBMIT_BIO
342380
ZFS_AC_KERNEL_SRC_BIO_CURRENT_BIO_LIST
381+
ZFS_AC_KERNEL_SRC_BLKG_TRYGET
343382
])
344383

345384
AC_DEFUN([ZFS_AC_KERNEL_BIO], [
@@ -360,4 +399,5 @@ AC_DEFUN([ZFS_AC_KERNEL_BIO], [
360399
ZFS_AC_KERNEL_BIO_BVEC_ITER
361400
ZFS_AC_KERNEL_BIO_SUBMIT_BIO
362401
ZFS_AC_KERNEL_BIO_CURRENT_BIO_LIST
402+
ZFS_AC_KERNEL_BLKG_TRYGET
363403
])

module/os/linux/zfs/vdev_disk.c

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

457457
#ifdef HAVE_BIO_SET_DEV
458458
#if defined(CONFIG_BLK_CGROUP) && defined(HAVE_BIO_SET_DEV_GPL_ONLY)
459+
/*
460+
* The Linux 5.5 kernel updated percpu_ref_tryget() which is inlined by
461+
* blkg_tryget() to use rcu_read_lock() instead of rcu_read_lock_sched().
462+
* As a side effect the function was converted to GPL-only. Define our
463+
* own version when needed which uses rcu_read_lock_sched().
464+
*/
465+
#if defined(HAVE_BLKG_TRYGET_GPL_ONLY)
466+
static inline bool
467+
vdev_blkg_tryget(struct blkcg_gq *blkg)
468+
{
469+
struct percpu_ref *ref = &blkg->refcnt;
470+
unsigned long __percpu *count;
471+
bool rc;
472+
473+
rcu_read_lock_sched();
474+
475+
if (__ref_is_percpu(ref, &count)) {
476+
this_cpu_inc(*count);
477+
rc = true;
478+
} else {
479+
rc = atomic_long_inc_not_zero(&ref->count);
480+
}
481+
482+
rcu_read_unlock_sched();
483+
484+
return (rc);
485+
}
486+
#elif defined(HAVE_BLKG_TRYGET)
487+
#define vdev_blkg_tryget(bg) blkg_tryget(bg)
488+
#endif
459489
/*
460490
* The Linux 5.0 kernel updated the bio_set_dev() macro so it calls the
461491
* GPL-only bio_associate_blkg() symbol thus inadvertently converting
@@ -470,7 +500,7 @@ vdev_bio_associate_blkg(struct bio *bio)
470500
ASSERT3P(q, !=, NULL);
471501
ASSERT3P(bio->bi_blkg, ==, NULL);
472502

473-
if (q->root_blkg && blkg_tryget(q->root_blkg))
503+
if (q->root_blkg && vdev_blkg_tryget(q->root_blkg))
474504
bio->bi_blkg = q->root_blkg;
475505
}
476506
#define bio_associate_blkg vdev_bio_associate_blkg

0 commit comments

Comments
 (0)