aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBrian Behlendorf <[email protected]>2010-09-27 15:30:14 -0700
committerBrian Behlendorf <[email protected]>2010-10-12 14:55:00 -0700
commitd148e95156b98ac226013d24962d1afa4a51c712 (patch)
tree9c9226706d3dfe376197f9855d79a00a4043b1d6
parent398f129ca36b211b19b98ca16aff1d7e91ee2949 (diff)
Fix negative zio->io_error which must be positive.
All the upper layers of zfs expect zio->io_error to be positive. I was careful but I missed one instance in vdev_disk_physio_completion() which could return a negative error. To ensure all cases are always caught I had additionally added an ASSERT() to check this before zio_interpret(). Finally, as a debugging aid when zfs is build with --enable-debug all errors from the backing block devices will be reported to the console with an error message like this: ZFS: zio error=5 type=1 offset=4217856 size=8192 flags=60440
-rw-r--r--module/zfs/vdev_disk.c21
1 files changed, 19 insertions, 2 deletions
diff --git a/module/zfs/vdev_disk.c b/module/zfs/vdev_disk.c
index 6b410b1b6..9ae8fbc18 100644
--- a/module/zfs/vdev_disk.c
+++ b/module/zfs/vdev_disk.c
@@ -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\n", zio->io_error, zio->io_type,
+ (u_longlong_t)zio->io_offset, (u_longlong_t)zio->io_size,
+ zio->io_flags);
+#endif
+}
+
static int
vdev_disk_open(vdev_t *v, uint64_t *psize, uint64_t *ashift)
{
@@ -232,6 +243,9 @@ vdev_disk_dio_put(dio_request_t *dr)
if (zio) {
zio->io_error = error;
+ ASSERT3S(zio->io_error, >=, 0);
+ if (zio->io_error)
+ vdev_disk_error(zio);
zio_interrupt(zio);
}
}
@@ -259,10 +273,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);
@@ -434,6 +448,9 @@ BIO_END_IO_PROTO(vdev_disk_io_flush_completion, bio, size, rc)
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);