This commit is contained in:
Attila Fülöp 2024-07-17 07:17:32 +08:00 committed by GitHub
commit ed10f01ab7
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 28 additions and 7 deletions

View File

@ -54,7 +54,7 @@ dmu_send(const char *tosnap, const char *fromsnap, boolean_t embedok,
const char *redactbook, int outfd, offset_t *off, const char *redactbook, int outfd, offset_t *off,
struct dmu_send_outparams *dsop); struct dmu_send_outparams *dsop);
int dmu_send_estimate_fast(struct dsl_dataset *ds, struct dsl_dataset *fromds, int dmu_send_estimate_fast(struct dsl_dataset *ds, struct dsl_dataset *fromds,
zfs_bookmark_phys_t *frombook, boolean_t stream_compressed, zfs_bookmark_phys_t *frombook, boolean_t compressok, boolean_t rawok,
boolean_t saved, uint64_t *sizep); boolean_t saved, uint64_t *sizep);
int dmu_send_obj(const char *pool, uint64_t tosnap, uint64_t fromsnap, int dmu_send_obj(const char *pool, uint64_t tosnap, uint64_t fromsnap,
boolean_t embedok, boolean_t large_block_ok, boolean_t compressok, boolean_t embedok, boolean_t large_block_ok, boolean_t compressok,

View File

@ -3009,16 +3009,21 @@ dmu_adjust_send_estimate_for_indirects(dsl_dataset_t *ds, uint64_t uncompressed,
int int
dmu_send_estimate_fast(dsl_dataset_t *origds, dsl_dataset_t *fromds, dmu_send_estimate_fast(dsl_dataset_t *origds, dsl_dataset_t *fromds,
zfs_bookmark_phys_t *frombook, boolean_t stream_compressed, zfs_bookmark_phys_t *frombook, boolean_t compressok, boolean_t rawok,
boolean_t saved, uint64_t *sizep) boolean_t saved, uint64_t *sizep)
{ {
int err; int err;
dsl_dataset_t *ds = origds; dsl_dataset_t *ds = origds;
ds_hold_flags_t dsflags;
uint64_t uncomp, comp; uint64_t uncomp, comp;
boolean_t owned = B_FALSE;
boolean_t stream_compressed = compressok || rawok;
ASSERT(dsl_pool_config_held(origds->ds_dir->dd_pool)); ASSERT(dsl_pool_config_held(origds->ds_dir->dd_pool));
ASSERT(fromds == NULL || frombook == NULL); ASSERT(fromds == NULL || frombook == NULL);
dsflags = (rawok) ? DS_HOLD_FLAG_NONE : DS_HOLD_FLAG_DECRYPT;
/* /*
* If this is a saved send we may actually be sending * If this is a saved send we may actually be sending
* from the %recv clone used for resuming. * from the %recv clone used for resuming.
@ -3056,10 +3061,22 @@ dmu_send_estimate_fast(dsl_dataset_t *origds, dsl_dataset_t *fromds,
} }
} }
/* tosnap must be a snapshot or the target of a saved send */ /*
if (!ds->ds_is_snapshot && ds == origds) * If we are sending a filesystem or volume, ensure
return (SET_ERROR(EINVAL)); * that it doesn't change by owning the dataset.
*/
if (!ds->ds_is_snapshot && ds == origds) {
char dsname[ZFS_MAX_DATASET_NAME_LEN];
dsl_dataset_name(ds, dsname);
err = dsl_dataset_own(ds->ds_dir->dd_pool, dsname, dsflags,
FTAG, &ds);
if (err != 0)
return (err);
owned = B_TRUE;
}
if (fromds != NULL) { if (fromds != NULL) {
uint64_t used; uint64_t used;
if (!fromds->ds_is_snapshot) { if (!fromds->ds_is_snapshot) {
@ -3097,6 +3114,10 @@ dmu_send_estimate_fast(dsl_dataset_t *origds, dsl_dataset_t *fromds,
out: out:
if (ds != origds) if (ds != origds)
dsl_dataset_rele(ds, FTAG); dsl_dataset_rele(ds, FTAG);
if (owned == B_TRUE)
dsl_dataset_disown(ds, dsflags, FTAG);
return (err); return (err);
} }

View File

@ -5678,7 +5678,7 @@ zfs_ioc_send(zfs_cmd_t *zc)
} }
error = dmu_send_estimate_fast(tosnap, fromsnap, NULL, error = dmu_send_estimate_fast(tosnap, fromsnap, NULL,
compressok || rawok, savedok, &zc->zc_objset_type); compressok, rawok, savedok, &zc->zc_objset_type);
if (fromsnap != NULL) if (fromsnap != NULL)
dsl_dataset_rele(fromsnap, FTAG); dsl_dataset_rele(fromsnap, FTAG);
@ -6849,7 +6849,7 @@ zfs_ioc_send_space(const char *snapname, nvlist_t *innvl, nvlist_t *outnvl)
} else { } else {
error = dmu_send_estimate_fast(tosnap, fromsnap, error = dmu_send_estimate_fast(tosnap, fromsnap,
(from && strchr(fromname, '#') != NULL ? &zbm : NULL), (from && strchr(fromname, '#') != NULL ? &zbm : NULL),
compressok || rawok, savedok, &space); compressok, rawok, savedok, &space);
space -= resume_bytes; space -= resume_bytes;
if (fromsnap != NULL) if (fromsnap != NULL)
dsl_dataset_rele(fromsnap, FTAG); dsl_dataset_rele(fromsnap, FTAG);