diff --git a/config/kernel-bio.m4 b/config/kernel-bio.m4 index 1d715b2de6..df5e9de3be 100644 --- a/config/kernel-bio.m4 +++ b/config/kernel-bio.m4 @@ -191,6 +191,24 @@ AC_DEFUN([ZFS_AC_KERNEL_SRC_BIO_SET_DEV], [ ], [], [ZFS_META_LICENSE]) ]) +dnl # +dnl # Linux 5.16 API +dnl # +dnl # bio_set_dev is no longer a helper macro and is now an inline function, +dnl # meaning that the function it calls internally can no longer be overridden +dnl # by our code +dnl # +AC_DEFUN([ZFS_AC_KERNEL_SRC_BIO_SET_DEV_MACRO], [ + ZFS_LINUX_TEST_SRC([bio_set_dev_macro], [ + #include + #include + ],[ + #ifndef bio_set_dev + #error Not a macro + #endif + ], [], [ZFS_META_LICENSE]) +]) + AC_DEFUN([ZFS_AC_KERNEL_BIO_SET_DEV], [ AC_MSG_CHECKING([whether bio_set_dev() is available]) ZFS_LINUX_TEST_RESULT([bio_set_dev], [ @@ -205,6 +223,15 @@ AC_DEFUN([ZFS_AC_KERNEL_BIO_SET_DEV], [ AC_DEFINE(HAVE_BIO_SET_DEV_GPL_ONLY, 1, [bio_set_dev() GPL-only]) ]) + + AC_MSG_CHECKING([whether bio_set_dev() is a macro]) + ZFS_LINUX_TEST_RESULT([bio_set_dev_macro], [ + AC_MSG_RESULT(yes) + AC_DEFINE(HAVE_BIO_SET_DEV_MACRO, 1, + [bio_set_dev() is a macro]) + ],[ + AC_MSG_RESULT(no) + ]) ],[ AC_MSG_RESULT(no) ]) @@ -434,6 +461,7 @@ AC_DEFUN([ZFS_AC_KERNEL_SRC_BIO], [ ZFS_AC_KERNEL_SRC_BLKG_TRYGET ZFS_AC_KERNEL_SRC_BIO_BDEV_DISK ZFS_AC_KERNEL_SRC_BDEV_SUBMIT_BIO_RETURNS_VOID + ZFS_AC_KERNEL_SRC_BIO_SET_DEV_MACRO ]) AC_DEFUN([ZFS_AC_KERNEL_BIO], [ diff --git a/module/os/linux/zfs/vdev_disk.c b/module/os/linux/zfs/vdev_disk.c index bcec4c6ba0..0e884f426a 100644 --- a/module/os/linux/zfs/vdev_disk.c +++ b/module/os/linux/zfs/vdev_disk.c @@ -493,6 +493,7 @@ vdev_blkg_tryget(struct blkcg_gq *blkg) #elif defined(HAVE_BLKG_TRYGET) #define vdev_blkg_tryget(bg) blkg_tryget(bg) #endif +#ifdef HAVE_BIO_SET_DEV_MACRO /* * The Linux 5.0 kernel updated the bio_set_dev() macro so it calls the * GPL-only bio_associate_blkg() symbol thus inadvertently converting @@ -514,7 +515,30 @@ vdev_bio_associate_blkg(struct bio *bio) if (q->root_blkg && vdev_blkg_tryget(q->root_blkg)) bio->bi_blkg = q->root_blkg; } + #define bio_associate_blkg vdev_bio_associate_blkg +#else +static inline void +vdev_bio_set_dev(struct bio *bio, struct block_device *bdev) +{ +#if defined(HAVE_BIO_BDEV_DISK) + struct request_queue *q = bdev->bd_disk->queue; +#else + struct request_queue *q = bio->bi_disk->queue; +#endif + bio_clear_flag(bio, BIO_REMAPPED); + if (bio->bi_bdev != bdev) + bio_clear_flag(bio, BIO_THROTTLED); + bio->bi_bdev = bdev; + + ASSERT3P(q, !=, NULL); + ASSERT3P(bio->bi_blkg, ==, NULL); + + if (q->root_blkg && vdev_blkg_tryget(q->root_blkg)) + bio->bi_blkg = q->root_blkg; +} +#define bio_set_dev vdev_bio_set_dev +#endif #endif #else /*