summaryrefslogtreecommitdiff
path: root/usr/src/uts/common/fs/zfs/zio.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src/uts/common/fs/zfs/zio.c')
-rw-r--r--usr/src/uts/common/fs/zfs/zio.c29
1 files changed, 26 insertions, 3 deletions
diff --git a/usr/src/uts/common/fs/zfs/zio.c b/usr/src/uts/common/fs/zfs/zio.c
index f8a98f73f3..b32dffd79c 100644
--- a/usr/src/uts/common/fs/zfs/zio.c
+++ b/usr/src/uts/common/fs/zfs/zio.c
@@ -22,6 +22,7 @@
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2011, 2018 by Delphix. All rights reserved.
* Copyright (c) 2011 Nexenta Systems, Inc. All rights reserved.
+ * Copyright (c) 2013 by Saso Kiselkov. All rights reserved.
* Copyright (c) 2014 Integros [integros.com]
* Copyright (c) 2017, Intel Corporation.
* Copyright 2020 Joyent, Inc.
@@ -43,6 +44,7 @@
#include <sys/ddt.h>
#include <sys/blkptr.h>
#include <sys/zfeature.h>
+#include <sys/zfs_zone.h>
#include <sys/time.h>
#include <sys/dsl_scan.h>
#include <sys/metaslab_impl.h>
@@ -765,6 +767,7 @@ zio_create(zio_t *pio, spa_t *spa, uint64_t txg, const blkptr_t *bp,
zio->io_bookmark = *zb;
if (pio != NULL) {
+ zio->io_zoneid = pio->io_zoneid;
if (zio->io_metaslab_class == NULL)
zio->io_metaslab_class = pio->io_metaslab_class;
if (zio->io_logical == NULL)
@@ -772,6 +775,8 @@ zio_create(zio_t *pio, spa_t *spa, uint64_t txg, const blkptr_t *bp,
if (zio->io_child_type == ZIO_CHILD_GANG)
zio->io_gang_leader = pio->io_gang_leader;
zio_add_child(pio, zio);
+ } else {
+ zfs_zone_zio_init(zio);
}
return (zio);
@@ -4317,6 +4322,24 @@ zio_done(zio_t *zio)
}
}
+ /*
+ * When we have an error on a slog vdev, we must ensure that the
+ * zio is not suspended. Suspending the zio will cause dataset deletion
+ * or an attempt to remove the slog to hang. In both cases, the code
+ * might be trying to clean up the zil blocks on the slog, but because
+ * the slog is dead, the suspended zio causes this to hang indefinitely.
+ * The system properly switches over to using zils on regular storage
+ * when the slog dies.
+ *
+ * This is a reasonable point in the stack to detect that the vdev is
+ * a slog. The 'no_suspend' flag will propagate up to the logical zio
+ * via zio_notify_parent.
+ */
+ if (zio->io_error && vd != NULL && vd->vdev_islog &&
+ !vdev_accessible(vd, zio)) {
+ zio->io_reexecute |= ZIO_REEXECUTE_NO_SUSPEND;
+ }
+
if (zio->io_error && zio == lio) {
/*
* Determine whether zio should be reexecuted. This will
@@ -4361,7 +4384,7 @@ zio_done(zio_t *zio)
*/
zio_inherit_child_errors(zio, ZIO_CHILD_LOGICAL);
- if ((zio->io_error || zio->io_reexecute) &&
+ if ((zio->io_error || ZIO_SHOULD_REEXECUTE(zio)) &&
IO_IS_ALLOCATING(zio) && zio->io_gang_leader == zio &&
!(zio->io_flags & (ZIO_FLAG_IO_REWRITE | ZIO_FLAG_NOPWRITE)))
zio_dva_unallocate(zio, zio->io_gang_tree, bp);
@@ -4375,7 +4398,7 @@ zio_done(zio_t *zio)
(zio->io_reexecute & ZIO_REEXECUTE_SUSPEND))
zio->io_reexecute = 0;
- if (zio->io_reexecute) {
+ if (ZIO_SHOULD_REEXECUTE(zio)) {
/*
* This is a logical I/O that wants to reexecute.
*
@@ -4446,7 +4469,7 @@ zio_done(zio_t *zio)
}
ASSERT(zio->io_child_count == 0);
- ASSERT(zio->io_reexecute == 0);
+ ASSERT(!ZIO_SHOULD_REEXECUTE(zio));
ASSERT(zio->io_error == 0 || (zio->io_flags & ZIO_FLAG_CANFAIL));
/*