Linux 4.13 compat: bio->bi_status and blk_status_t

Commit torvalds/linux@4e4cbee9.  The bio->bi_error field was
replaced with bio->bi_status which is an enum that describes
all possible error types.

Reviewed-by: Chunwei Chen <david.chen@osnexus.com>
Signed-off-by: Brian Behlendorf <behlendorf1@llnl.gov>
Closes #6351
This commit is contained in:
Brian Behlendorf 2017-07-23 19:37:12 -07:00 committed by GitHub
parent 7a8ed6b8b7
commit 36ba27e9e0
4 changed files with 120 additions and 6 deletions

View File

@ -22,3 +22,25 @@ AC_DEFUN([ZFS_AC_KERNEL_BIO_END_IO_T_ARGS], [
AC_MSG_RESULT(no) AC_MSG_RESULT(no)
]) ])
]) ])
dnl #
dnl # 4.13 API change
dnl # The bio->bi_error field was replaced with bio->bi_status which is an
dnl # enum which describes all possible error types.
dnl #
AC_DEFUN([ZFS_AC_KERNEL_BIO_BI_STATUS], [
AC_MSG_CHECKING([whether bio->bi_status exists])
ZFS_LINUX_TRY_COMPILE([
#include <linux/bio.h>
],[
struct bio bio __attribute__ ((unused));
blk_status_t status __attribute__ ((unused)) = BLK_STS_OK;
bio.bi_status = status;
],[
AC_MSG_RESULT(yes)
AC_DEFINE(HAVE_BIO_BI_STATUS, 1, [bio->bi_status exists])
],[
AC_MSG_RESULT(no)
])
])

View File

@ -30,6 +30,7 @@ AC_DEFUN([ZFS_AC_CONFIG_KERNEL], [
ZFS_AC_KERNEL_REQ_OP_FLUSH ZFS_AC_KERNEL_REQ_OP_FLUSH
ZFS_AC_KERNEL_BIO_BI_OPF ZFS_AC_KERNEL_BIO_BI_OPF
ZFS_AC_KERNEL_BIO_END_IO_T_ARGS ZFS_AC_KERNEL_BIO_END_IO_T_ARGS
ZFS_AC_KERNEL_BIO_BI_STATUS
ZFS_AC_KERNEL_BIO_RW_BARRIER ZFS_AC_KERNEL_BIO_RW_BARRIER
ZFS_AC_KERNEL_BIO_RW_DISCARD ZFS_AC_KERNEL_BIO_RW_DISCARD
ZFS_AC_KERNEL_BLK_QUEUE_BDI ZFS_AC_KERNEL_BLK_QUEUE_BDI

View File

@ -221,14 +221,104 @@ bio_set_flags_failfast(struct block_device *bdev, int *flags)
#define DISK_NAME_LEN 32 #define DISK_NAME_LEN 32
#endif /* DISK_NAME_LEN */ #endif /* DISK_NAME_LEN */
#ifdef HAVE_BIO_BI_STATUS
static inline int
bi_status_to_errno(blk_status_t status)
{
switch (status) {
case BLK_STS_OK:
return (0);
case BLK_STS_NOTSUPP:
return (EOPNOTSUPP);
case BLK_STS_TIMEOUT:
return (ETIMEDOUT);
case BLK_STS_NOSPC:
return (ENOSPC);
case BLK_STS_TRANSPORT:
return (ENOLINK);
case BLK_STS_TARGET:
return (EREMOTEIO);
case BLK_STS_NEXUS:
return (EBADE);
case BLK_STS_MEDIUM:
return (ENODATA);
case BLK_STS_PROTECTION:
return (EILSEQ);
case BLK_STS_RESOURCE:
return (ENOMEM);
case BLK_STS_AGAIN:
return (EAGAIN);
case BLK_STS_IOERR:
return (EIO);
default:
return (EIO);
}
}
static inline blk_status_t
errno_to_bi_status(int error)
{
switch (error) {
case 0:
return (BLK_STS_OK);
case EOPNOTSUPP:
return (BLK_STS_NOTSUPP);
case ETIMEDOUT:
return (BLK_STS_TIMEOUT);
case ENOSPC:
return (BLK_STS_NOSPC);
case ENOLINK:
return (BLK_STS_TRANSPORT);
case EREMOTEIO:
return (BLK_STS_TARGET);
case EBADE:
return (BLK_STS_NEXUS);
case ENODATA:
return (BLK_STS_MEDIUM);
case EILSEQ:
return (BLK_STS_PROTECTION);
case ENOMEM:
return (BLK_STS_RESOURCE);
case EAGAIN:
return (BLK_STS_AGAIN);
case EIO:
return (BLK_STS_IOERR);
default:
return (BLK_STS_IOERR);
}
}
#endif /* HAVE_BIO_BI_STATUS */
/* /*
* 4.3 API change * 4.3 API change
* The bio_endio() prototype changed slightly. These are helper * The bio_endio() prototype changed slightly. These are helper
* macro's to ensure the prototype and invocation are handled. * macro's to ensure the prototype and invocation are handled.
*/ */
#ifdef HAVE_1ARG_BIO_END_IO_T #ifdef HAVE_1ARG_BIO_END_IO_T
#ifdef HAVE_BIO_BI_STATUS
#define BIO_END_IO_ERROR(bio) bi_status_to_errno(bio->bi_status)
#define BIO_END_IO_PROTO(fn, x, z) static void fn(struct bio *x) #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); #define BIO_END_IO(bio, error) bio_set_bi_status(bio, error)
static inline void
bio_set_bi_status(struct bio *bio, int error)
{
ASSERT3S(error, <=, 0);
bio->bi_status = errno_to_bi_status(-error);
bio_endio(bio);
}
#else
#define BIO_END_IO_ERROR(bio) (-(bio->bi_error))
#define BIO_END_IO_PROTO(fn, x, z) static void fn(struct bio *x)
#define BIO_END_IO(bio, error) bio_set_bi_error(bio, error)
static inline void
bio_set_bi_error(struct bio *bio, int error)
{
ASSERT3S(error, <=, 0);
bio->bi_error = error;
bio_endio(bio);
}
#endif /* HAVE_BIO_BI_STATUS */
#else #else
#define BIO_END_IO_PROTO(fn, x, z) static void fn(struct bio *x, int z) #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); #define BIO_END_IO(bio, error) bio_endio(bio, error);

View File

@ -427,7 +427,7 @@ BIO_END_IO_PROTO(vdev_disk_physio_completion, bio, error)
if (dr->dr_error == 0) { if (dr->dr_error == 0) {
#ifdef HAVE_1ARG_BIO_END_IO_T #ifdef HAVE_1ARG_BIO_END_IO_T
dr->dr_error = -(bio->bi_error); dr->dr_error = BIO_END_IO_ERROR(bio);
#else #else
if (error) if (error)
dr->dr_error = -(error); dr->dr_error = -(error);
@ -618,15 +618,16 @@ retry:
return (error); return (error);
} }
BIO_END_IO_PROTO(vdev_disk_io_flush_completion, bio, rc) BIO_END_IO_PROTO(vdev_disk_io_flush_completion, bio, error)
{ {
zio_t *zio = bio->bi_private; zio_t *zio = bio->bi_private;
#ifdef HAVE_1ARG_BIO_END_IO_T #ifdef HAVE_1ARG_BIO_END_IO_T
int rc = bio->bi_error; zio->io_error = BIO_END_IO_ERROR(bio);
#else
zio->io_error = -error;
#endif #endif
zio->io_error = -rc; if (zio->io_error && (zio->io_error == EOPNOTSUPP))
if (rc && (rc == -EOPNOTSUPP))
zio->io_vd->vdev_nowritecache = B_TRUE; zio->io_vd->vdev_nowritecache = B_TRUE;
bio_put(bio); bio_put(bio);