mirror of
https://git.proxmox.com/git/mirror_zfs.git
synced 2026-05-22 02:27:36 +03:00
zfs should optionally send holds
Add -h switch to zfs send command to send dataset holds. If holds are present in the stream, zfs receive will create them on the target dataset, unless the zfs receive -h option is used to skip receive of holds. Reviewed-by: Alek Pinchuk <apinchuk@datto.com> Reviewed-by: loli10K <ezomori.nozomu@gmail.com> Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov> Reviewed by: Paul Dagnelie <pcd@delphix.com> Signed-off-by: Paul Zuchowski <pzuchowski@datto.com> Closes #7513
This commit is contained in:
committed by
Brian Behlendorf
parent
e73ab1b38c
commit
9c5e88b1de
@@ -1282,7 +1282,6 @@ dmu_send(const char *tosnap, const char *fromsnap, boolean_t embedok,
|
||||
err = dsl_pool_hold(tosnap, FTAG, &dp);
|
||||
if (err != 0)
|
||||
return (err);
|
||||
|
||||
if (strchr(tosnap, '@') == NULL && spa_writeable(dp->dp_spa)) {
|
||||
/*
|
||||
* We are sending a filesystem or volume. Ensure
|
||||
|
||||
@@ -83,6 +83,7 @@ dsl_dataset_user_hold_check(void *arg, dmu_tx_t *tx)
|
||||
{
|
||||
dsl_dataset_user_hold_arg_t *dduha = arg;
|
||||
dsl_pool_t *dp = dmu_tx_pool(tx);
|
||||
nvlist_t *tmp_holds;
|
||||
|
||||
if (spa_version(dp->dp_spa) < SPA_VERSION_USERREFS)
|
||||
return (SET_ERROR(ENOTSUP));
|
||||
@@ -90,6 +91,26 @@ dsl_dataset_user_hold_check(void *arg, dmu_tx_t *tx)
|
||||
if (!dmu_tx_is_syncing(tx))
|
||||
return (0);
|
||||
|
||||
/*
|
||||
* Ensure the list has no duplicates by copying name/values from
|
||||
* non-unique dduha_holds to unique tmp_holds, and comparing counts.
|
||||
*/
|
||||
tmp_holds = fnvlist_alloc();
|
||||
for (nvpair_t *pair = nvlist_next_nvpair(dduha->dduha_holds, NULL);
|
||||
pair != NULL; pair = nvlist_next_nvpair(dduha->dduha_holds, pair)) {
|
||||
size_t len = strlen(nvpair_name(pair)) +
|
||||
strlen(fnvpair_value_string(pair));
|
||||
char *nameval = kmem_zalloc(len + 2, KM_SLEEP);
|
||||
(void) strcpy(nameval, nvpair_name(pair));
|
||||
(void) strcat(nameval, "@");
|
||||
(void) strcat(nameval, fnvpair_value_string(pair));
|
||||
fnvlist_add_string(tmp_holds, nameval, "");
|
||||
kmem_free(nameval, len + 2);
|
||||
}
|
||||
size_t tmp_count = fnvlist_num_pairs(tmp_holds);
|
||||
fnvlist_free(tmp_holds);
|
||||
if (tmp_count != fnvlist_num_pairs(dduha->dduha_holds))
|
||||
return (SET_ERROR(EEXIST));
|
||||
for (nvpair_t *pair = nvlist_next_nvpair(dduha->dduha_holds, NULL);
|
||||
pair != NULL; pair = nvlist_next_nvpair(dduha->dduha_holds, pair)) {
|
||||
dsl_dataset_t *ds;
|
||||
@@ -312,7 +333,8 @@ dsl_dataset_user_hold(nvlist_t *holds, minor_t cleanup_minor, nvlist_t *errlist)
|
||||
return (0);
|
||||
|
||||
dduha.dduha_holds = holds;
|
||||
dduha.dduha_chkholds = fnvlist_alloc();
|
||||
/* chkholds can have non-unique name */
|
||||
VERIFY(0 == nvlist_alloc(&dduha.dduha_chkholds, 0, KM_SLEEP));
|
||||
dduha.dduha_errlist = errlist;
|
||||
dduha.dduha_minor = cleanup_minor;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user