mirror of
https://git.proxmox.com/git/mirror_zfs.git
synced 2026-05-22 18:40:43 +03:00
Enforce "-F" flag on resuming recv of full/newfs on existing dataset
When receiving full/newfs on existing dataset, then it should be done with "-F" flag. Its enforced for initial receive in checks done in zfs_receive_one function of libzfs. Similarly, on resuming full/newfs recv on existing dataset, it should be done with "-F" flag. When dataset doesn't exist, then full/new recv is done on newly created dataset and it's marked INCONSISTENT. But when receiving on existing dataset, recv is first done on %recv and its marked INCONSISTENT. Existing dataset is not marked INCONSISTENT. Resume of full/newfs receive with dataset not INCONSISTENT indicates that its resuming newfs on existing dataset. So, enforce "-F" flag in this case. Also return an error from dmu_recv_resume_begin_check() in zfs kernel, when its resuming full/newfs recv without force. Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov> Reviewed-by: Chunwei Chen <david.chen@nutanix.com> Signed-off-by: Jitendra Patidar <jitendra.patidar@nutanix.com> Closes #13856 Closes #13857
This commit is contained in:
@@ -4638,6 +4638,33 @@ zfs_receive_one(libzfs_handle_t *hdl, int infd, const char *tosnap,
|
||||
goto out;
|
||||
}
|
||||
|
||||
/*
|
||||
* When receiving full/newfs on existing dataset, then it
|
||||
* should be done with "-F" flag. Its enforced for initial
|
||||
* receive in previous checks in this function.
|
||||
* Similarly, on resuming full/newfs recv on existing dataset,
|
||||
* it should be done with "-F" flag.
|
||||
*
|
||||
* When dataset doesn't exist, then full/newfs recv is done on
|
||||
* newly created dataset and it's marked INCONSISTENT. But
|
||||
* When receiving on existing dataset, recv is first done on
|
||||
* %recv and its marked INCONSISTENT. Existing dataset is not
|
||||
* marked INCONSISTENT.
|
||||
* Resume of full/newfs receive with dataset not INCONSISTENT
|
||||
* indicates that its resuming newfs on existing dataset. So,
|
||||
* enforce "-F" flag in this case.
|
||||
*/
|
||||
if (stream_resumingnewfs &&
|
||||
!zfs_prop_get_int(zhp, ZFS_PROP_INCONSISTENT) &&
|
||||
!flags->force) {
|
||||
zfs_close(zhp);
|
||||
zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
|
||||
"Resuming recv on existing destination '%s'\n"
|
||||
"must specify -F to overwrite it"), name);
|
||||
err = zfs_error(hdl, EZFS_RESUME_EXISTS, errbuf);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (stream_wantsnewfs &&
|
||||
zhp->zfs_dmustats.dds_origin[0]) {
|
||||
zfs_close(zhp);
|
||||
@@ -5078,6 +5105,19 @@ zfs_receive_one(libzfs_handle_t *hdl, int infd, const char *tosnap,
|
||||
"be updated."));
|
||||
(void) zfs_error(hdl, EZFS_BADSTREAM, errbuf);
|
||||
break;
|
||||
case ZFS_ERR_RESUME_EXISTS:
|
||||
cp = strchr(destsnap, '@');
|
||||
if (newfs) {
|
||||
/* it's the containing fs that exists */
|
||||
*cp = '\0';
|
||||
}
|
||||
zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
|
||||
"Resuming recv on existing dataset without force"));
|
||||
(void) zfs_error_fmt(hdl, EZFS_RESUME_EXISTS,
|
||||
dgettext(TEXT_DOMAIN, "cannot resume recv %s"),
|
||||
destsnap);
|
||||
*cp = '@';
|
||||
break;
|
||||
case EBUSY:
|
||||
if (hastoken) {
|
||||
zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
|
||||
|
||||
@@ -304,6 +304,9 @@ libzfs_error_description(libzfs_handle_t *hdl)
|
||||
case EZFS_NOT_USER_NAMESPACE:
|
||||
return (dgettext(TEXT_DOMAIN, "the provided file "
|
||||
"was not a user namespace file"));
|
||||
case EZFS_RESUME_EXISTS:
|
||||
return (dgettext(TEXT_DOMAIN, "Resuming recv on existing "
|
||||
"dataset without force"));
|
||||
case EZFS_UNKNOWN:
|
||||
return (dgettext(TEXT_DOMAIN, "unknown error"));
|
||||
default:
|
||||
|
||||
Reference in New Issue
Block a user