mirror of
https://git.proxmox.com/git/mirror_zfs.git
synced 2026-05-22 02:27:36 +03:00
Implement a new type of zfs receive: corrective receive (-c)
This type of recv is used to heal corrupted data when a replica of the data already exists (in the form of a send file for example). With the provided send stream, corrective receive will read from disk blocks described by the WRITE records. When any of the reads come back with ECKSUM we use the data from the corresponding WRITE record to rewrite the corrupted block. Reviewed-by: Paul Dagnelie <pcd@delphix.com> Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov> Reviewed-by: Paul Zuchowski <pzuchowski@datto.com> Signed-off-by: Alek Pinchuk <apinchuk@axcient.com> Closes #9372
This commit is contained in:
@@ -181,6 +181,7 @@
|
||||
<elf-symbol name='lzc_receive_resumable' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
|
||||
<elf-symbol name='lzc_receive_with_cmdprops' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
|
||||
<elf-symbol name='lzc_receive_with_header' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
|
||||
<elf-symbol name='lzc_receive_with_heal' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
|
||||
<elf-symbol name='lzc_redact' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
|
||||
<elf-symbol name='lzc_release' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
|
||||
<elf-symbol name='lzc_rename' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
|
||||
@@ -1741,6 +1742,26 @@
|
||||
<parameter type-id='8341348b' name='begin_record'/>
|
||||
<return type-id='95e97e5e'/>
|
||||
</function-decl>
|
||||
<function-decl name='lzc_receive_with_heal' mangled-name='lzc_receive_with_heal' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='lzc_receive_with_heal'>
|
||||
<parameter type-id='80f4b756' name='snapname'/>
|
||||
<parameter type-id='5ce45b60' name='props'/>
|
||||
<parameter type-id='5ce45b60' name='cmdprops'/>
|
||||
<parameter type-id='ae3e8ca6' name='wkeydata'/>
|
||||
<parameter type-id='3502e3ff' name='wkeylen'/>
|
||||
<parameter type-id='80f4b756' name='origin'/>
|
||||
<parameter type-id='c19b74c3' name='force'/>
|
||||
<parameter type-id='c19b74c3' name='heal'/>
|
||||
<parameter type-id='c19b74c3' name='resumable'/>
|
||||
<parameter type-id='c19b74c3' name='raw'/>
|
||||
<parameter type-id='95e97e5e' name='input_fd'/>
|
||||
<parameter type-id='8341348b' name='begin_record'/>
|
||||
<parameter type-id='95e97e5e' name='cleanup_fd'/>
|
||||
<parameter type-id='5d6479ae' name='read_bytes'/>
|
||||
<parameter type-id='5d6479ae' name='errflags'/>
|
||||
<parameter type-id='5d6479ae' name='action_handle'/>
|
||||
<parameter type-id='857bb57e' name='errors'/>
|
||||
<return type-id='95e97e5e'/>
|
||||
</function-decl>
|
||||
<function-decl name='lzc_receive_one' mangled-name='lzc_receive_one' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='lzc_receive_one'>
|
||||
<parameter type-id='80f4b756' name='snapname'/>
|
||||
<parameter type-id='5ce45b60' name='props'/>
|
||||
|
||||
@@ -22,10 +22,10 @@
|
||||
/*
|
||||
* Copyright (c) 2012, 2020 by Delphix. All rights reserved.
|
||||
* Copyright (c) 2013 Steven Hartland. All rights reserved.
|
||||
* Copyright (c) 2017 Datto Inc.
|
||||
* Copyright 2017 RackTop Systems.
|
||||
* Copyright (c) 2017 Open-E, Inc. All Rights Reserved.
|
||||
* Copyright (c) 2019, 2020 by Christian Schwarz. All rights reserved.
|
||||
* Copyright (c) 2019 Datto Inc.
|
||||
*/
|
||||
|
||||
/*
|
||||
@@ -986,7 +986,7 @@ recv_read(int fd, void *buf, int ilen)
|
||||
static int
|
||||
recv_impl(const char *snapname, nvlist_t *recvdprops, nvlist_t *localprops,
|
||||
uint8_t *wkeydata, uint_t wkeylen, const char *origin, boolean_t force,
|
||||
boolean_t resumable, boolean_t raw, int input_fd,
|
||||
boolean_t heal, boolean_t resumable, boolean_t raw, int input_fd,
|
||||
const dmu_replay_record_t *begin_record, uint64_t *read_bytes,
|
||||
uint64_t *errflags, nvlist_t **errors)
|
||||
{
|
||||
@@ -1041,7 +1041,7 @@ recv_impl(const char *snapname, nvlist_t *recvdprops, nvlist_t *localprops,
|
||||
/*
|
||||
* All receives with a payload should use the new interface.
|
||||
*/
|
||||
if (resumable || raw || wkeydata != NULL || payload) {
|
||||
if (resumable || heal || raw || wkeydata != NULL || payload) {
|
||||
nvlist_t *outnvl = NULL;
|
||||
nvlist_t *innvl = fnvlist_alloc();
|
||||
|
||||
@@ -1081,6 +1081,8 @@ recv_impl(const char *snapname, nvlist_t *recvdprops, nvlist_t *localprops,
|
||||
if (resumable)
|
||||
fnvlist_add_boolean(innvl, "resumable");
|
||||
|
||||
if (heal)
|
||||
fnvlist_add_boolean(innvl, "heal");
|
||||
|
||||
error = lzc_ioctl(ZFS_IOC_RECV_NEW, fsname, innvl, &outnvl);
|
||||
|
||||
@@ -1180,7 +1182,7 @@ lzc_receive(const char *snapname, nvlist_t *props, const char *origin,
|
||||
boolean_t force, boolean_t raw, int fd)
|
||||
{
|
||||
return (recv_impl(snapname, props, NULL, NULL, 0, origin, force,
|
||||
B_FALSE, raw, fd, NULL, NULL, NULL, NULL));
|
||||
B_FALSE, B_FALSE, raw, fd, NULL, NULL, NULL, NULL));
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1194,7 +1196,7 @@ lzc_receive_resumable(const char *snapname, nvlist_t *props, const char *origin,
|
||||
boolean_t force, boolean_t raw, int fd)
|
||||
{
|
||||
return (recv_impl(snapname, props, NULL, NULL, 0, origin, force,
|
||||
B_TRUE, raw, fd, NULL, NULL, NULL, NULL));
|
||||
B_FALSE, B_TRUE, raw, fd, NULL, NULL, NULL, NULL));
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1217,7 +1219,7 @@ lzc_receive_with_header(const char *snapname, nvlist_t *props,
|
||||
return (EINVAL);
|
||||
|
||||
return (recv_impl(snapname, props, NULL, NULL, 0, origin, force,
|
||||
resumable, raw, fd, begin_record, NULL, NULL, NULL));
|
||||
B_FALSE, resumable, raw, fd, begin_record, NULL, NULL, NULL));
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1247,7 +1249,7 @@ lzc_receive_one(const char *snapname, nvlist_t *props,
|
||||
{
|
||||
(void) action_handle, (void) cleanup_fd;
|
||||
return (recv_impl(snapname, props, NULL, NULL, 0, origin, force,
|
||||
resumable, raw, input_fd, begin_record,
|
||||
B_FALSE, resumable, raw, input_fd, begin_record,
|
||||
read_bytes, errflags, errors));
|
||||
}
|
||||
|
||||
@@ -1269,7 +1271,27 @@ lzc_receive_with_cmdprops(const char *snapname, nvlist_t *props,
|
||||
{
|
||||
(void) action_handle, (void) cleanup_fd;
|
||||
return (recv_impl(snapname, props, cmdprops, wkeydata, wkeylen, origin,
|
||||
force, resumable, raw, input_fd, begin_record,
|
||||
force, B_FALSE, resumable, raw, input_fd, begin_record,
|
||||
read_bytes, errflags, errors));
|
||||
}
|
||||
|
||||
/*
|
||||
* Like lzc_receive_with_cmdprops, but allows the caller to pass an additional
|
||||
* 'heal' argument.
|
||||
*
|
||||
* The heal arguments tells us to heal the provided snapshot using the provided
|
||||
* send stream
|
||||
*/
|
||||
int lzc_receive_with_heal(const char *snapname, nvlist_t *props,
|
||||
nvlist_t *cmdprops, uint8_t *wkeydata, uint_t wkeylen, const char *origin,
|
||||
boolean_t force, boolean_t heal, boolean_t resumable, boolean_t raw,
|
||||
int input_fd, const dmu_replay_record_t *begin_record, int cleanup_fd,
|
||||
uint64_t *read_bytes, uint64_t *errflags, uint64_t *action_handle,
|
||||
nvlist_t **errors)
|
||||
{
|
||||
(void) action_handle, (void) cleanup_fd;
|
||||
return (recv_impl(snapname, props, cmdprops, wkeydata, wkeylen, origin,
|
||||
force, heal, resumable, raw, input_fd, begin_record,
|
||||
read_bytes, errflags, errors));
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user