From f430589660caeb227f23be85629c4a822061c896 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_endio in favor of newly introduced bio->bi_error. This also replaces bio->bi_flags value BIO_UPTODATE. bio_endio 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. Support for pre 2.6.24 kernels was already dropped with 37f9dac592bf ("zvol processing should use struct bio") which assumed the 2 argument version in zvol_request(). Remaining code to support the 3 argument version is hereby removed. Signed-off-by: Lukas Wunner Fixes #3799 --- config/kernel-bio-end-io-t-args.m4 | 20 +++++++++---------- include/linux/blkdev_compat.h | 21 +++++++++----------- module/zfs/vdev_disk.c | 31 +++++++++++++++--------------- module/zfs/zvol.c | 2 +- 4 files changed, 34 insertions(+), 40 deletions(-) diff --git a/config/kernel-bio-end-io-t-args.m4 b/config/kernel-bio-end-io-t-args.m4 index 407e55cd0103..c8c520f1ba82 100644 --- a/config/kernel-bio-end-io-t-args.m4 +++ b/config/kernel-bio-end-io-t-args.m4 @@ -1,25 +1,23 @@ dnl # -dnl # 2.6.24 API change -dnl # Size argument dropped from bio_endio and bi_end_io, because the -dnl # bi_end_io is only called once now when the request is complete. -dnl # There is no longer any need for a size argument. This also means -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 # 4.3 API change +dnl # Error argument dropped from bio_endio 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) ]) diff --git a/include/linux/blkdev_compat.h b/include/linux/blkdev_compat.h index 162b315ea0c4..868b89c55cbb 100644 --- a/include/linux/blkdev_compat.h +++ b/include/linux/blkdev_compat.h @@ -182,20 +182,17 @@ bio_set_flags_failfast(struct block_device *bdev, int *flags) #endif /* DISK_NAME_LEN */ /* - * 2.6.24 API change, - * The bio_end_io() prototype changed slightly. These are helper - * macro's to ensure the prototype and return value are handled. + * 4.3 API change + * The bio_endio() prototype changed slightly. These are helper + * macro's to ensure the prototype and invocation are handled. */ -#ifdef 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 +#ifdef HAVE_1ARG_BIO_END_IO_T +#define BIO_END_IO_PROTO(fn, x, z) static void fn(struct bio *x) +#define BIO_END_IO(bio, error) bio->bi_error = error; bio_endio(bio); #else -#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 */ +#define BIO_END_IO_PROTO(fn, x, z) static void fn(struct bio *x, int z) +#define BIO_END_IO(bio, error) bio_endio(bio, error); +#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..eac0f296ecf1 100644 --- a/module/zfs/vdev_disk.c +++ b/module/zfs/vdev_disk.c @@ -424,21 +424,21 @@ vdev_disk_dio_put(dio_request_t *dr) return (rc); } -BIO_END_IO_PROTO(vdev_disk_physio_completion, bio, size, error) +BIO_END_IO_PROTO(vdev_disk_physio_completion, bio, error) { dio_request_t *dr = bio->bi_private; int rc; -#ifndef HAVE_2ARGS_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); - - 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 + 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); @@ -446,8 +446,6 @@ BIO_END_IO_PROTO(vdev_disk_physio_completion, bio, size, error) /* Wake up synchronous waiter this is the last outstanding bio */ if ((rc == 1) && vdev_disk_dio_is_sync(dr)) complete(&dr->dr_comp); - - BIO_END_IO_RETURN(0); } static inline unsigned long @@ -624,9 +622,12 @@ vdev_disk_physio(struct block_device *bdev, caddr_t kbuf, return (__vdev_disk_physio(bdev, NULL, kbuf, size, offset, flags)); } -BIO_END_IO_PROTO(vdev_disk_io_flush_completion, bio, size, rc) +BIO_END_IO_PROTO(vdev_disk_io_flush_completion, bio, 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; @@ -638,8 +639,6 @@ BIO_END_IO_PROTO(vdev_disk_io_flush_completion, bio, size, rc) if (zio->io_error) vdev_disk_error(zio); zio_interrupt(zio); - - BIO_END_IO_RETURN(0); } static int diff --git a/module/zfs/zvol.c b/module/zfs/zvol.c index 37c39d19ad58..c81f02a3907b 100644 --- a/module/zfs/zvol.c +++ b/module/zfs/zvol.c @@ -752,7 +752,7 @@ zvol_request(struct request_queue *q, struct bio *bio) out2: generic_end_io_acct(rw, &zv->zv_disk->part0, start); out1: - bio_endio(bio, -error); + BIO_END_IO(bio, -error); spl_fstrans_unmark(cookie); #ifdef HAVE_MAKE_REQUEST_FN_RET_INT return (0);