From 2f1ae2b26c6c7163a3b63ab61d04d5925be969da Mon Sep 17 00:00:00 2001 From: Lukas Wunner Date: Wed, 23 Sep 2015 17:55:15 +0200 Subject: [PATCH] Linux 4.3 compat: bio_end_io_t / BIO_UPTODATE Commit torvalds/linux@4246a0b63bd8f56a1469b12eafeb875b1041a451 ("block: add a bi_error field to struct bio") dropped the error argument from bio_end_io in favor of newly introduced bio->bi_error. This also replaces bio->bi_flags value BIO_UPTODATE. bio_end_io was a 3 argument function until Linux 2.6.24, which made it a 2 argument function, and now the prototype has changed yet again to a 1 argument function. Signed-off-by: Lukas Wunner Fixes #3799 --- config/kernel-bio-end-io-t-args.m4 | 32 ++++++++++++++++++++++++++---- include/linux/blkdev_compat.h | 11 ++++++---- module/zfs/vdev_disk.c | 22 +++++++++++++------- 3 files changed, 50 insertions(+), 15 deletions(-) diff --git a/config/kernel-bio-end-io-t-args.m4 b/config/kernel-bio-end-io-t-args.m4 index 407e55cd0103..b4dbb3a1dc13 100644 --- a/config/kernel-bio-end-io-t-args.m4 +++ b/config/kernel-bio-end-io-t-args.m4 @@ -7,20 +7,44 @@ dnl # that partial IO's are no longer possibe and the end_io callback dnl # should not check bi->bi_size. Finally, the return type was updated dnl # to void. dnl # +dnl # 4.3 API change +dnl # Error argument dropped from bio_end_io in favor of newly introduced +dnl # bio->bi_error. This also replaces bio->bi_flags value BIO_UPTODATE. +dnl # Introduced by torvalds/linux@4246a0b63bd8f56a1469b12eafeb875b1041a451 +dnl # ("block: add a bi_error field to struct bio"). +dnl # AC_DEFUN([ZFS_AC_KERNEL_BIO_END_IO_T_ARGS], [ - AC_MSG_CHECKING([whether bio_end_io_t wants 2 args]) + AC_MSG_CHECKING([whether bio_end_io_t wants 1 arg]) ZFS_LINUX_TRY_COMPILE([ #include - void wanted_end_io(struct bio *bio, int x) { return; } + void wanted_end_io(struct bio *bio) { return; } bio_end_io_t *end_io __attribute__ ((unused)) = wanted_end_io; ],[ ],[ AC_MSG_RESULT(yes) - AC_DEFINE(HAVE_2ARGS_BIO_END_IO_T, 1, - [bio_end_io_t wants 2 args]) + AC_DEFINE(HAVE_1ARG_BIO_END_IO_T, 1, + [bio_end_io_t wants 1 arg]) ],[ AC_MSG_RESULT(no) + AC_MSG_CHECKING([whether bio_end_io_t wants 2 args]) + ZFS_LINUX_TRY_COMPILE([ + #include + + void wanted_end_io(struct bio *bio, int x) { return; } + + bio_end_io_t *end_io __attribute__ ((unused)) = + wanted_end_io; + ],[ + ],[ + AC_MSG_RESULT(yes) + AC_DEFINE(HAVE_2ARGS_BIO_END_IO_T, 1, + [bio_end_io_t wants 2 args]) + ],[ + AC_MSG_RESULT(no) + AC_DEFINE(HAVE_3ARGS_BIO_END_IO_T, 1, + [bio_end_io_t wants 3 args]) + ]) ]) ]) diff --git a/include/linux/blkdev_compat.h b/include/linux/blkdev_compat.h index 162b315ea0c4..4d49b1e12300 100644 --- a/include/linux/blkdev_compat.h +++ b/include/linux/blkdev_compat.h @@ -182,20 +182,23 @@ bio_set_flags_failfast(struct block_device *bdev, int *flags) #endif /* DISK_NAME_LEN */ /* - * 2.6.24 API change, + * 2.6.24 and 4.3 API change, * The bio_end_io() prototype changed slightly. These are helper * macro's to ensure the prototype and return value are handled. */ -#ifdef HAVE_2ARGS_BIO_END_IO_T +#if defined(HAVE_1ARG_BIO_END_IO_T) +#define BIO_END_IO_PROTO(fn, x, y, z) static void fn(struct bio *x) +#define BIO_END_IO_RETURN(rc) return +#elif defined(HAVE_2ARGS_BIO_END_IO_T) #define BIO_END_IO_PROTO(fn, x, y, z) static void fn(struct bio *x, int z) #define BIO_END_IO_RETURN(rc) return -#else +#elif defined(HAVE_3ARGS_BIO_END_IO_T) #define BIO_END_IO_PROTO(fn, x, y, z) static int fn( \ struct bio *x, \ unsigned int y, \ int z) #define BIO_END_IO_RETURN(rc) return rc -#endif /* HAVE_2ARGS_BIO_END_IO_T */ +#endif /* HAVE_1ARG_BIO_END_IO_T */ /* * 2.6.38 - 2.6.x API, diff --git a/module/zfs/vdev_disk.c b/module/zfs/vdev_disk.c index e7e2b3b93f40..1d733bc31f82 100644 --- a/module/zfs/vdev_disk.c +++ b/module/zfs/vdev_disk.c @@ -429,16 +429,21 @@ BIO_END_IO_PROTO(vdev_disk_physio_completion, bio, size, error) dio_request_t *dr = bio->bi_private; int rc; -#ifndef HAVE_2ARGS_BIO_END_IO_T +#ifdef HAVE_3ARGS_BIO_END_IO_T if (BIO_BI_SIZE(bio)) return (1); -#endif /* HAVE_2ARGS_BIO_END_IO_T */ - - if (error == 0 && !test_bit(BIO_UPTODATE, &bio->bi_flags)) - error = (-EIO); +#endif - if (dr->dr_error == 0) - dr->dr_error = -error; + if (dr->dr_error == 0) { +#ifdef HAVE_1ARG_BIO_END_IO_T + dr->dr_error = -(bio->bi_error); +#else /* HAVE_2ARGS_BIO_END_IO_T || HAVE_3ARGS_BIO_END_IO_T */ + if (error) + dr->dr_error = -(error); + else if (!test_bit(BIO_UPTODATE, &bio->bi_flags)) + dr->dr_error = EIO; +#endif + } /* Drop reference aquired by __vdev_disk_physio */ rc = vdev_disk_dio_put(dr); @@ -627,6 +632,9 @@ vdev_disk_physio(struct block_device *bdev, caddr_t kbuf, BIO_END_IO_PROTO(vdev_disk_io_flush_completion, bio, size, rc) { zio_t *zio = bio->bi_private; +#ifdef HAVE_1ARG_BIO_END_IO_T + int rc = bio->bi_error; +#endif zio->io_delay = jiffies_64 - zio->io_delay; zio->io_error = -rc;