Remove inconsistent use of EOPNOTSUPP
[zfs.git] / module / zfs / vdev_disk.c
index 6b410b1..51062ef 100644 (file)
@@ -91,6 +91,17 @@ bdev_capacity(struct block_device *bdev)
        return get_capacity(bdev->bd_disk);
 }
 
+static void
+vdev_disk_error(zio_t *zio)
+{
+#ifdef ZFS_DEBUG
+       printk("ZFS: zio error=%d type=%d offset=%llu size=%llu "
+           "flags=%x delay=%llu\n", zio->io_error, zio->io_type,
+           (u_longlong_t)zio->io_offset, (u_longlong_t)zio->io_size,
+           zio->io_flags, (u_longlong_t)zio->io_delay);
+#endif
+}
+
 static int
 vdev_disk_open(vdev_t *v, uint64_t *psize, uint64_t *ashift)
 {
@@ -231,7 +242,12 @@ vdev_disk_dio_put(dio_request_t *dr)
                vdev_disk_dio_free(dr);
 
                if (zio) {
+                       zio->io_delay = jiffies_to_msecs(
+                           jiffies_64 - zio->io_delay);
                        zio->io_error = error;
+                       ASSERT3S(zio->io_error, >=, 0);
+                       if (zio->io_error)
+                               vdev_disk_error(zio);
                        zio_interrupt(zio);
                }
        }
@@ -259,10 +275,10 @@ BIO_END_IO_PROTO(vdev_disk_physio_completion, bio, size, error)
 #endif /* HAVE_2ARGS_BIO_END_IO_T */
 
        if (error == 0 && !test_bit(BIO_UPTODATE, &bio->bi_flags))
-               error = EIO;
+               error = -EIO;
 
        if (dr->dr_error == 0)
-               dr->dr_error = error;
+               dr->dr_error = -error;
 
        /* Drop reference aquired by __vdev_disk_physio */
        rc = vdev_disk_dio_put(dr);
@@ -328,15 +344,13 @@ retry:
        if (dr == NULL)
                return ENOMEM;
 
+       if (zio && !(zio->io_flags & (ZIO_FLAG_IO_RETRY | ZIO_FLAG_TRYHARD)))
+                       bio_set_flags_failfast(bdev, &flags);
+
        dr->dr_zio = zio;
        dr->dr_rw = flags;
        block_size = vdev_bdev_block_size(bdev);
 
-#ifdef BIO_RW_FAILFAST
-       if (flags & (1 << BIO_RW_FAILFAST))
-               dr->dr_rw |= 1 << BIO_RW_FAILFAST;
-#endif /* BIO_RW_FAILFAST */
-
        /*
         * When the IO size exceeds the maximum bio size for the request
         * queue we are forced to break the IO in multiple bio's and wait
@@ -391,6 +405,8 @@ retry:
 
        /* Extra reference to protect dio_request during submit_bio */
        vdev_disk_dio_get(dr);
+       if (zio)
+               zio->io_delay = jiffies_64;
 
        /* Submit all bio's associated with this dio */
        for (i = 0; i < dr->dr_bio_count; i++)
@@ -420,6 +436,7 @@ int
 vdev_disk_physio(struct block_device *bdev, caddr_t kbuf,
                 size_t size, uint64_t offset, int flags)
 {
+       bio_set_flags_failfast(bdev, &flags);
        return __vdev_disk_physio(bdev, NULL, kbuf, size, offset, flags);
 }
 
@@ -429,11 +446,15 @@ BIO_END_IO_PROTO(vdev_disk_io_flush_completion, bio, size, rc)
 {
        zio_t *zio = bio->bi_private;
 
+       zio->io_delay = jiffies_to_msecs(jiffies_64 - zio->io_delay);
        zio->io_error = -rc;
        if (rc && (rc == -EOPNOTSUPP))
                zio->io_vd->vdev_nowritecache = B_TRUE;
 
        bio_put(bio);
+       ASSERT3S(zio->io_error, >=, 0);
+       if (zio->io_error)
+               vdev_disk_error(zio);
        zio_interrupt(zio);
 
        BIO_END_IO_RETURN(0);
@@ -456,6 +477,7 @@ vdev_disk_io_flush(struct block_device *bdev, zio_t *zio)
        bio->bi_end_io = vdev_disk_io_flush_completion;
        bio->bi_private = zio;
        bio->bi_bdev = bdev;
+       zio->io_delay = jiffies_64;
        submit_bio(WRITE_BARRIER, bio);
 
        return 0;
@@ -523,11 +545,6 @@ vdev_disk_io_start(zio_t *zio)
                return ZIO_PIPELINE_CONTINUE;
        }
 
-#ifdef BIO_RW_FAILFAST
-       if (zio->io_flags & (ZIO_FLAG_IO_RETRY | ZIO_FLAG_TRYHARD))
-               flags |= (1 << BIO_RW_FAILFAST);
-#endif /* BIO_RW_FAILFAST */
-
        error = __vdev_disk_physio(vd->vd_bdev, zio, zio->io_data,
                                   zio->io_size, zio->io_offset, flags);
        if (error) {