Files
mirror_zfs/include/sys
Alex Reece 463a8cfe2b Illumos 6844 - dnode_next_offset can detect fictional holes
6844 dnode_next_offset can detect fictional holes
Reviewed by: Matthew Ahrens <mahrens@delphix.com>
Reviewed by: George Wilson <george.wilson@delphix.com>
Reviewed by: Brian Behlendorf <behlendorf1@llnl.gov>

dnode_next_offset is used in a variety of places to iterate over the
holes or allocated blocks in a dnode. It operates under the premise that
it can iterate over the blockpointers of a dnode in open context while
holding only the dn_struct_rwlock as reader. Unfortunately, this premise
does not hold.

When we create the zio for a dbuf, we pass in the actual block pointer
in the indirect block above that dbuf. When we later zero the bp in
zio_write_compress, we are directly modifying the bp. The state of the
bp is now inconsistent from the perspective of dnode_next_offset: the bp
will appear to be a hole until zio_dva_allocate finally finishes filling
it in. In the meantime, dnode_next_offset can detect a hole in the dnode
when none exists.

I was able to experimentally demonstrate this behavior with the
following setup:
1. Create a file with 1 million dbufs.
2. Create a thread that randomly dirties L2 blocks by writing to the
first L0 block under them.
3. Observe dnode_next_offset, waiting for it to skip over a hole in the
middle of a file.
4. Do dnode_next_offset in a loop until we skip over such a non-existent
hole.

The fix is to ensure that it is valid to iterate over the indirect
blocks in a dnode while holding the dn_struct_rwlock by passing the zio
a copy of the BP and updating the actual BP in dbuf_write_ready while
holding the lock.

References:
  https://www.illumos.org/issues/6844
  https://github.com/openzfs/openzfs/pull/82
  DLPX-35372

Ported-by: Brian Behlendorf <behlendorf1@llnl.gov>
Closes #4548
2016-04-27 16:24:15 -07:00
..
2016-01-11 11:58:26 -08:00
2015-09-11 11:14:38 -07:00
2015-07-10 11:58:37 -07:00
2014-08-01 14:28:05 -07:00
2016-01-08 15:08:19 -08:00
2014-01-07 10:33:11 -08:00
2014-08-01 14:28:05 -07:00
2014-03-04 12:22:24 -08:00
2014-07-29 10:55:29 -07:00
2014-07-29 10:55:29 -07:00
2013-11-04 11:18:14 -08:00
2013-11-04 11:17:48 -08:00
2016-04-21 09:49:25 -07:00
2016-01-15 15:38:35 -08:00
2014-08-13 10:35:00 -07:00
2016-04-21 09:49:25 -07:00
2014-07-30 09:20:35 -07:00
2015-12-30 13:20:12 -08:00
2016-04-05 18:54:55 -07:00
2016-01-15 15:38:35 -08:00
2016-01-15 15:38:35 -08:00
2016-01-15 15:38:35 -08:00
2015-01-06 16:53:24 -08:00
2011-02-10 09:21:43 -08:00
2013-11-04 10:55:25 -08:00
2013-12-18 16:46:35 -08:00
2015-06-25 08:58:16 -07:00
2011-03-02 11:43:50 -08:00
2015-12-04 09:39:20 -08:00
2014-07-28 14:29:58 -07:00
2013-11-04 10:55:25 -08:00
2016-03-29 18:33:17 -07:00
2015-09-04 16:08:14 -07:00
2013-12-18 16:46:35 -08:00
2011-02-10 09:27:21 -08:00
2013-11-04 10:55:25 -08:00
2016-01-15 15:33:45 -08:00
2016-04-21 09:49:25 -07:00
2016-04-05 18:54:55 -07:00
2015-06-09 13:48:02 -07:00
2016-01-08 15:08:19 -08:00
2013-11-04 10:55:25 -08:00
2013-11-05 12:14:56 -08:00
2016-01-08 15:08:19 -08:00
2016-01-08 15:08:19 -08:00
2015-09-03 14:14:55 -07:00