Always refuse receving non-resume stream when resume state exists
This fixes a hole in the situation where the resume state is left from receiving a new dataset and, so, the state is set on the dataset itself (as opposed to %recv child). Additionally, distinguish incremental and resume streams in error messages. Reviewed-by: Matt Ahrens <matt@delphix.com> Reviewed-by: Tom Caputi <tcaputi@datto.com> Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov> Signed-off-by: Andriy Gapon <avg@FreeBSD.org> Closes #9252
This commit is contained in:
parent
1a504d27df
commit
ebeb6f23bf
|
@ -4598,11 +4598,18 @@ zfs_receive_one(libzfs_handle_t *hdl, int infd, const char *tosnap,
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
/*
|
/*
|
||||||
* if the fs does not exist, look for it based on the
|
* If the fs does not exist, look for it based on the
|
||||||
* fromsnap GUID
|
* fromsnap GUID.
|
||||||
*/
|
*/
|
||||||
(void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN,
|
if (resuming) {
|
||||||
"cannot receive incremental stream"));
|
(void) snprintf(errbuf, sizeof (errbuf),
|
||||||
|
dgettext(TEXT_DOMAIN,
|
||||||
|
"cannot receive resume stream"));
|
||||||
|
} else {
|
||||||
|
(void) snprintf(errbuf, sizeof (errbuf),
|
||||||
|
dgettext(TEXT_DOMAIN,
|
||||||
|
"cannot receive incremental stream"));
|
||||||
|
}
|
||||||
|
|
||||||
(void) strcpy(name, destsnap);
|
(void) strcpy(name, destsnap);
|
||||||
*strchr(name, '@') = '\0';
|
*strchr(name, '@') = '\0';
|
||||||
|
|
|
@ -350,21 +350,25 @@ recv_begin_check_existing_impl(dmu_recv_begin_arg_t *drba, dsl_dataset_t *ds,
|
||||||
boolean_t raw = (featureflags & DMU_BACKUP_FEATURE_RAW) != 0;
|
boolean_t raw = (featureflags & DMU_BACKUP_FEATURE_RAW) != 0;
|
||||||
boolean_t embed = (featureflags & DMU_BACKUP_FEATURE_EMBED_DATA) != 0;
|
boolean_t embed = (featureflags & DMU_BACKUP_FEATURE_EMBED_DATA) != 0;
|
||||||
|
|
||||||
/* temporary clone name must not exist */
|
/* Temporary clone name must not exist. */
|
||||||
error = zap_lookup(dp->dp_meta_objset,
|
error = zap_lookup(dp->dp_meta_objset,
|
||||||
dsl_dir_phys(ds->ds_dir)->dd_child_dir_zapobj, recv_clone_name,
|
dsl_dir_phys(ds->ds_dir)->dd_child_dir_zapobj, recv_clone_name,
|
||||||
8, 1, &val);
|
8, 1, &val);
|
||||||
if (error != ENOENT)
|
if (error != ENOENT)
|
||||||
return (error == 0 ? SET_ERROR(EBUSY) : error);
|
return (error == 0 ? SET_ERROR(EBUSY) : error);
|
||||||
|
|
||||||
/* new snapshot name must not exist */
|
/* Resume state must not be set. */
|
||||||
|
if (dsl_dataset_has_resume_receive_state(ds))
|
||||||
|
return (SET_ERROR(EBUSY));
|
||||||
|
|
||||||
|
/* New snapshot name must not exist. */
|
||||||
error = zap_lookup(dp->dp_meta_objset,
|
error = zap_lookup(dp->dp_meta_objset,
|
||||||
dsl_dataset_phys(ds)->ds_snapnames_zapobj,
|
dsl_dataset_phys(ds)->ds_snapnames_zapobj,
|
||||||
drba->drba_cookie->drc_tosnap, 8, 1, &val);
|
drba->drba_cookie->drc_tosnap, 8, 1, &val);
|
||||||
if (error != ENOENT)
|
if (error != ENOENT)
|
||||||
return (error == 0 ? SET_ERROR(EEXIST) : error);
|
return (error == 0 ? SET_ERROR(EEXIST) : error);
|
||||||
|
|
||||||
/* must not have children if receiving a ZVOL */
|
/* Must not have children if receiving a ZVOL. */
|
||||||
error = zap_count(dp->dp_meta_objset,
|
error = zap_count(dp->dp_meta_objset,
|
||||||
dsl_dir_phys(ds->ds_dir)->dd_child_dir_zapobj, &children);
|
dsl_dir_phys(ds->ds_dir)->dd_child_dir_zapobj, &children);
|
||||||
if (error != 0)
|
if (error != 0)
|
||||||
|
|
Loading…
Reference in New Issue