OpenZFS on Linux and FreeBSD
Go to file
George Wilson 07ce5d7390 OpenZFS 8857 - zio_remove_child() panic due to already destroyed parent zio
PROBLEM
=======
It's possible for a parent zio to complete even though it has children
which have not completed. This can result in the following panic:
    > $C
    ffffff01809128c0 vpanic()
    ffffff01809128e0 mutex_panic+0x58(fffffffffb94c904, ffffff597dde7f80)
    ffffff0180912950 mutex_vector_enter+0x347(ffffff597dde7f80)
    ffffff01809129b0 zio_remove_child+0x50(ffffff597dde7c58, ffffff32bd901ac0,
    ffffff3373370908)
    ffffff0180912a40 zio_done+0x390(ffffff32bd901ac0)
    ffffff0180912a70 zio_execute+0x78(ffffff32bd901ac0)
    ffffff0180912b30 taskq_thread+0x2d0(ffffff33bae44140)
    ffffff0180912b40 thread_start+8()
    > ::status
    debugging crash dump vmcore.2 (64-bit) from batfs0390
    operating system: 5.11 joyent_20170911T171900Z (i86pc)
    image uuid: (not set)
    panic message: mutex_enter: bad mutex, lp=ffffff597dde7f80
    owner=ffffff3c59b39480 thread=ffffff0180912c40
    dump content: kernel pages only
The problem is that dbuf_prefetch along with l2arc can create a zio tree
which confuses the parent zio and allows it to complete with while children
still exist. Here's the scenario:
    zio tree:
        pio
         |--- lio
The parent zio, pio, has entered the zio_done stage and begins to check its
children to see there are still some that have not completed. In zio_done(),
the children are checked in the following order:
    zio_wait_for_children(zio, ZIO_CHILD_VDEV, ZIO_WAIT_DONE)
    zio_wait_for_children(zio, ZIO_CHILD_GANG, ZIO_WAIT_DONE)
    zio_wait_for_children(zio, ZIO_CHILD_DDT, ZIO_WAIT_DONE)
    zio_wait_for_children(zio, ZIO_CHILD_LOGICAL, ZIO_WAIT_DONE)
If pio, finds any child which has not completed then it stops executing and
goes to sleep. Each call to zio_wait_for_children() will grab the io_lock
while checking the particular child.
In this scenario, the pio has completed the first call to
zio_wait_for_children() to check for any ZIO_CHILD_VDEV children. Since
the only zio in the zio tree right now is the logical zio, lio, then it
completes that call and prepares to check the next child type.
In the meantime, the lio completes and in its callback creates a child vdev
zio, cio. The zio tree looks like this:
    zio tree:
        pio
         |--- lio
         |--- cio
The lio then grabs the parent's io_lock and removes itself.
    zio tree:
        pio
         |--- cio
The pio continues to run but has already completed its check for ZIO_CHILD_VDEV
and will erroneously complete. When the child zio, cio, completes it will panic
the system trying to reference the parent zio which has been destroyed.
SOLUTION
========
The fix is to rework the zio_wait_for_children() logic to accept a bitfield
for all the children types that it's interested in checking. The
io_lock will is held the entire time we check all the children types. Since
the function now accepts a bitfield, a simple ZIO_CHILD_BIT() macro is provided
to allow for the conversion between a ZIO_CHILD type and the bitfield used by
the zio_wiat_for_children logic.

Authored by: George Wilson <george.wilson@delphix.com>
Reviewed by: Matthew Ahrens <mahrens@delphix.com>
Reviewed by: Andriy Gapon <avg@FreeBSD.org>
Reviewed by: Youzhong Yang <youzhong@gmail.com>
Reviewed by: Brian Behlendorf <behlendorf1@llnl.gov>
Approved by: Dan McDonald <danmcd@omniti.com>
Ported-by: Giuseppe Di Natale <dinatale2@llnl.gov>

OpenZFS-issue: https://www.illumos.org/issues/8857
OpenZFS-commit: https://github.com/openzfs/openzfs/commit/862ff6d99c
Issue #5918
Closes #7168
2018-03-14 16:10:37 -07:00
.github Update codecov.yml 2018-03-14 16:10:36 -07:00
cmd 'zfs receive' fails with "dataset is busy" 2018-03-14 16:10:37 -07:00
config Linux 4.16 compat: inode_set_iversion() 2018-03-14 16:10:36 -07:00
contrib contrib/initramfs: add missing conf.d/zfs 2018-03-14 16:10:37 -07:00
etc Use /sbin/openrc-run for openrc init scripts 2018-01-30 10:27:30 -06:00
include OpenZFS 8857 - zio_remove_child() panic due to already destroyed parent zio 2018-03-14 16:10:37 -07:00
lib 'zfs receive' fails with "dataset is busy" 2018-03-14 16:10:37 -07:00
man Fix zdb -R decompression 2018-03-14 16:10:36 -07:00
module OpenZFS 8857 - zio_remove_child() panic due to already destroyed parent zio 2018-03-14 16:10:37 -07:00
rpm Fix systemd_ RPM macros usage on Debian-based distributions 2018-03-14 16:10:36 -07:00
scripts Extend zloop.sh for automated testing 2018-01-30 10:27:31 -06:00
tests Handle zap_add() failures in mixed case mode 2018-03-14 16:10:37 -07:00
udev Fix spelling 2017-01-03 11:31:18 -06:00
.gitignore Add configure option to enable gcov analysis 2018-03-14 16:10:36 -07:00
.gitmodules Add zimport.sh compatibility test script 2014-02-21 12:10:31 -08:00
AUTHORS Add a missing > to AUTHORS 2014-09-02 14:18:53 -07:00
COPYRIGHT Update ZED copyright boilerplate 2015-05-11 15:07:00 -07:00
DISCLAIMER Fix minor typos and update marketing copy. 2013-03-21 12:51:06 -07:00
META Tag zfs-0.7.6 2018-02-01 10:02:58 -08:00
Makefile.am Add support for "--enable-code-coverage" option 2018-03-14 16:10:36 -07:00
OPENSOLARIS.LICENSE Add CDDL license file 2008-12-01 14:49:34 -08:00
README.markdown Update codecov.yml 2018-03-14 16:10:36 -07:00
TEST Retire filebench testing 2017-06-01 06:24:28 -07:00
autogen.sh build: do not call boilerplate ourself 2013-04-02 10:55:20 -07:00
configure.ac Add support for "--enable-code-coverage" option 2018-03-14 16:10:36 -07:00
copy-builtin Allow c99 when building ZFS in the kernel tree 2017-03-27 12:31:15 -07:00
zfs-script-config.sh.in zpool iostat/status -c improvements 2017-06-05 10:52:15 -07:00
zfs.release.in Move zfs.release generation to configure step 2012-07-12 12:22:51 -07:00

README.markdown

img

ZFS on Linux is an advanced file system and volume manager which was originally developed for Solaris and is now maintained by the OpenZFS community.

codecov

Official Resources

Installation

Full documentation for installing ZoL on your favorite Linux distribution can be found at our site.

Contribute & Develop

We have a separate document with contribution guidelines.