mirror_zfs/module/os/linux/zfs
Matthew Ahrens 7bcb7f0840
File incorrectly zeroed when receiving incremental stream that toggles -L
Background:

By increasing the recordsize property above the default of 128KB, a
filesystem may have "large" blocks.  By default, a send stream of such a
filesystem does not contain large WRITE records, instead it decreases
objects' block sizes to 128KB and splits the large blocks into 128KB
blocks, allowing the large-block filesystem to be received by a system
that does not support the `large_blocks` feature.  A send stream
generated by `zfs send -L` (or `--large-block`) preserves the large
block size on the receiving system, by using large WRITE records.

When receiving an incremental send stream for a filesystem with large
blocks, if the send stream's -L flag was toggled, a bug is encountered
in which the file's contents are incorrectly zeroed out.  The contents
of any blocks that were not modified by this send stream will be lost.
"Toggled" means that the previous send used `-L`, but this incremental
does not use `-L` (-L to no-L); or that the previous send did not use
`-L`, but this incremental does use `-L` (no-L to -L).

Changes:

This commit addresses the problem with several changes to the semantics
of zfs send/receive:

1. "-L to no-L" incrementals are rejected.  If the previous send used
`-L`, but this incremental does not use `-L`, the `zfs receive` will
fail with this error message:

    incremental send stream requires -L (--large-block), to match
    previous receive.

2. "no-L to -L" incrementals are handled correctly, preserving the
smaller (128KB) block size of any already-received files that used large
blocks on the sending system but were split by `zfs send` without the
`-L` flag.

3. A new send stream format flag is added, `SWITCH_TO_LARGE_BLOCKS`.
This feature indicates that we can correctly handle "no-L to -L"
incrementals.  This flag is currently not set on any send streams.  In
the future, we intend for incremental send streams of snapshots that
have large blocks to use `-L` by default, and these streams will also
have the `SWITCH_TO_LARGE_BLOCKS` feature set. This ensures that streams
from the default use of `zfs send` won't encounter the bug mentioned
above, because they can't be received by software with the bug.

Implementation notes:

To facilitate accessing the ZPL's generation number,
`zfs_space_delta_cb()` has been renamed to `zpl_get_file_info()` and
restructured to fill in a struct with ZPL-specific info including owner
and generation.

In the "no-L to -L" case, if this is a compressed send stream (from
`zfs send -cL`), large WRITE records that are being written to small
(128KB) blocksize files need to be decompressed so that they can be
written split up into multiple blocks.  The zio pipeline will recompress
each smaller block individually.

A new test case, `send-L_toggle`, is added, which tests the "no-L to -L"
case and verifies that we get an error for the "-L to no-L" case.

Reviewed-by: Paul Dagnelie <pcd@delphix.com>
Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov>
Signed-off-by: Matthew Ahrens <mahrens@delphix.com>
Closes #6224 
Closes #10383
2020-06-09 10:41:01 -07:00
..
abd_os.c Gang ABD Type 2020-05-20 18:06:09 -07:00
arc_os.c Don't ignore zfs_arc_max below allmem/32 2020-04-09 15:39:48 -07:00
Makefile.in Combine OS-independent ABD Code into Common Source File 2020-05-10 12:23:52 -07:00
mmp_os.c Add zfs_file_* interface, remove vnodes 2019-11-21 09:32:57 -08:00
policy.c Add zfs_file_* interface, remove vnodes 2019-11-21 09:32:57 -08:00
qat_compress.c Fix QAT allocation failure return value 2020-01-06 11:17:53 -08:00
qat_crypt.c QAT related bug fixes 2019-09-12 13:33:44 -07:00
qat.c QAT related bug fixes 2019-09-12 13:33:44 -07:00
spa_misc_os.c Make spa_history_zone platform-dependent in kernel 2020-03-02 09:43:30 -08:00
spa_stats.c Trim L2ARC 2020-06-09 10:15:08 -07:00
trace.c Enable use of DTRACE_PROBE* macros in "spl" module 2019-11-01 13:13:43 -07:00
vdev_disk.c Gang ABD Type 2020-05-20 18:06:09 -07:00
vdev_file.c Mark Linux fallocate extensions as specific to Linux 2019-11-30 15:40:22 -08:00
zfs_acl.c OpenZFS 6765 - zfs_zaccess_delete() comments do not accurately 2020-04-30 11:24:55 -07:00
zfs_ctldir.c Eliminate Linux specific inode usage from common code 2019-12-11 11:53:57 -08:00
zfs_debug.c Linux 5.6 compat: time_t 2020-02-27 09:31:02 -08:00
zfs_dir.c Add 'zfs wait' command 2020-04-01 10:02:06 -07:00
zfs_file_os.c Re-share zfsdev_getminor and zfs_onexit_fd_hold 2020-02-28 14:50:32 -08:00
zfs_ioctl_os.c Restore support for in-kernel ZFS ioctls 2020-06-08 13:57:22 -07:00
zfs_sysfs.c Persistent L2ARC 2020-04-10 10:33:35 -07:00
zfs_vfsops.c File incorrectly zeroed when receiving incremental stream that toggles -L 2020-06-09 10:41:01 -07:00
zfs_vnops.c OpenZFS 3254 - add support in zfs for aclmode=restricted 2020-04-30 11:23:59 -07:00
zfs_znode.c Make zfs_replay.c work on FreeBSD 2019-12-13 07:54:10 -08:00
zio_crypt.c Linux 4.14, 4.19, 5.0+ compat: SIMD save/restore 2019-10-24 10:17:33 -07:00
zpl_ctldir.c Eliminate Linux specific inode usage from common code 2019-12-11 11:53:57 -08:00
zpl_export.c Eliminate Linux specific inode usage from common code 2019-12-11 11:53:57 -08:00
zpl_file.c Eliminate Linux specific inode usage from common code 2019-12-11 11:53:57 -08:00
zpl_inode.c Linux 5.6 compat: timestamp_truncate() 2020-02-07 11:04:32 -08:00
zpl_super.c Eliminate Linux specific inode usage from common code 2019-12-11 11:53:57 -08:00
zpl_xattr.c Eliminate Linux specific inode usage from common code 2019-12-11 11:53:57 -08:00
zvol_os.c Connect dataset_kstats for FreeBSD 2020-06-05 17:17:02 -07:00