diff options
Diffstat (limited to 'usr/src/uts/common/fs/zfs/zio.c')
-rw-r--r-- | usr/src/uts/common/fs/zfs/zio.c | 29 |
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)); /* |