dsl_dataset: rename dmu_objset_clone* to dsl_dataset_clone*

And make its check and sync functions visible, so I can hook them up to
zcp_synctask. Rename not strictly necessary, but it definitely looks
more like a dsl_dataset thing than a dmu_objset thing, to the extent
that those things even have a meaningful distinction.

Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov>
Reviewed-by: Alexander Motin <mav@FreeBSD.org>
Signed-off-by: Rob Norris <robn@despairlabs.com>
Sponsored-by: https://despairlabs.com/sponsor/
Closes #17426
This commit is contained in:
Rob Norris 2025-06-05 16:23:22 +10:00 committed by Brian Behlendorf
parent ba227e2cc2
commit 560e3170ef
6 changed files with 115 additions and 114 deletions

View File

@ -4916,7 +4916,7 @@ ztest_dsl_dataset_promote_busy(ztest_ds_t *zd, uint64_t id)
fatal(B_FALSE, "dmu_take_snapshot(%s) = %d", snap1name, error); fatal(B_FALSE, "dmu_take_snapshot(%s) = %d", snap1name, error);
} }
error = dmu_objset_clone(clone1name, snap1name); error = dsl_dataset_clone(clone1name, snap1name);
if (error) { if (error) {
if (error == ENOSPC) { if (error == ENOSPC) {
ztest_record_enospc(FTAG); ztest_record_enospc(FTAG);
@ -4943,7 +4943,7 @@ ztest_dsl_dataset_promote_busy(ztest_ds_t *zd, uint64_t id)
fatal(B_FALSE, "dmu_open_snapshot(%s) = %d", snap3name, error); fatal(B_FALSE, "dmu_open_snapshot(%s) = %d", snap3name, error);
} }
error = dmu_objset_clone(clone2name, snap3name); error = dsl_dataset_clone(clone2name, snap3name);
if (error) { if (error) {
if (error == ENOSPC) { if (error == ENOSPC) {
ztest_record_enospc(FTAG); ztest_record_enospc(FTAG);
@ -6334,13 +6334,13 @@ ztest_dmu_snapshot_hold(ztest_ds_t *zd, uint64_t id)
fatal(B_FALSE, "dmu_objset_snapshot(%s) = %d", fullname, error); fatal(B_FALSE, "dmu_objset_snapshot(%s) = %d", fullname, error);
} }
error = dmu_objset_clone(clonename, fullname); error = dsl_dataset_clone(clonename, fullname);
if (error) { if (error) {
if (error == ENOSPC) { if (error == ENOSPC) {
ztest_record_enospc("dmu_objset_clone"); ztest_record_enospc("dsl_dataset_clone");
goto out; goto out;
} }
fatal(B_FALSE, "dmu_objset_clone(%s) = %d", clonename, error); fatal(B_FALSE, "dsl_dataset_clone(%s) = %d", clonename, error);
} }
error = dsl_destroy_snapshot(fullname, B_TRUE); error = dsl_destroy_snapshot(fullname, B_TRUE);

View File

@ -360,7 +360,6 @@ void dmu_objset_evict_dbufs(objset_t *os);
int dmu_objset_create(const char *name, dmu_objset_type_t type, uint64_t flags, int dmu_objset_create(const char *name, dmu_objset_type_t type, uint64_t flags,
struct dsl_crypto_params *dcp, dmu_objset_create_sync_func_t func, struct dsl_crypto_params *dcp, dmu_objset_create_sync_func_t func,
void *arg); void *arg);
int dmu_objset_clone(const char *name, const char *origin);
int dsl_destroy_snapshots_nvl(struct nvlist *snaps, boolean_t defer, int dsl_destroy_snapshots_nvl(struct nvlist *snaps, boolean_t defer,
struct nvlist *errlist); struct nvlist *errlist);
int dmu_objset_snapshot_one(const char *fsname, const char *snapname); int dmu_objset_snapshot_one(const char *fsname, const char *snapname);

View File

@ -276,6 +276,12 @@ dsl_dataset_phys(dsl_dataset_t *ds)
return ((dsl_dataset_phys_t *)ds->ds_dbuf->db_data); return ((dsl_dataset_phys_t *)ds->ds_dbuf->db_data);
} }
typedef struct dsl_dataset_clone_arg_t {
const char *ddca_clone;
const char *ddca_origin;
cred_t *ddca_cred;
} dsl_dataset_clone_arg_t;
typedef struct dsl_dataset_promote_arg { typedef struct dsl_dataset_promote_arg {
const char *ddpa_clonename; const char *ddpa_clonename;
dsl_dataset_t *ddpa_clone; dsl_dataset_t *ddpa_clone;
@ -364,6 +370,9 @@ uint64_t dsl_dataset_create_sync_dd(dsl_dir_t *dd, dsl_dataset_t *origin,
void dsl_dataset_snapshot_sync(void *arg, dmu_tx_t *tx); void dsl_dataset_snapshot_sync(void *arg, dmu_tx_t *tx);
int dsl_dataset_snapshot_check(void *arg, dmu_tx_t *tx); int dsl_dataset_snapshot_check(void *arg, dmu_tx_t *tx);
int dsl_dataset_snapshot(nvlist_t *snaps, nvlist_t *props, nvlist_t *errors); int dsl_dataset_snapshot(nvlist_t *snaps, nvlist_t *props, nvlist_t *errors);
void dsl_dataset_clone_sync(void *arg, dmu_tx_t *tx);
int dsl_dataset_clone_check(void *arg, dmu_tx_t *tx);
int dsl_dataset_clone(const char *clone, const char *origin);
void dsl_dataset_promote_sync(void *arg, dmu_tx_t *tx); void dsl_dataset_promote_sync(void *arg, dmu_tx_t *tx);
int dsl_dataset_promote_check(void *arg, dmu_tx_t *tx); int dsl_dataset_promote_check(void *arg, dmu_tx_t *tx);
int dsl_dataset_promote(const char *name, char *conflsnap); int dsl_dataset_promote(const char *name, char *conflsnap);

View File

@ -1383,112 +1383,6 @@ dmu_objset_create(const char *name, dmu_objset_type_t type, uint64_t flags,
return (rv); return (rv);
} }
typedef struct dmu_objset_clone_arg {
const char *doca_clone;
const char *doca_origin;
cred_t *doca_cred;
} dmu_objset_clone_arg_t;
static int
dmu_objset_clone_check(void *arg, dmu_tx_t *tx)
{
dmu_objset_clone_arg_t *doca = arg;
dsl_dir_t *pdd;
const char *tail;
int error;
dsl_dataset_t *origin;
dsl_pool_t *dp = dmu_tx_pool(tx);
if (strchr(doca->doca_clone, '@') != NULL)
return (SET_ERROR(EINVAL));
if (strlen(doca->doca_clone) >= ZFS_MAX_DATASET_NAME_LEN)
return (SET_ERROR(ENAMETOOLONG));
error = dsl_dir_hold(dp, doca->doca_clone, FTAG, &pdd, &tail);
if (error != 0)
return (error);
if (tail == NULL) {
dsl_dir_rele(pdd, FTAG);
return (SET_ERROR(EEXIST));
}
error = dsl_fs_ss_limit_check(pdd, 1, ZFS_PROP_FILESYSTEM_LIMIT, NULL,
doca->doca_cred);
if (error != 0) {
dsl_dir_rele(pdd, FTAG);
return (SET_ERROR(EDQUOT));
}
error = dsl_dataset_hold(dp, doca->doca_origin, FTAG, &origin);
if (error != 0) {
dsl_dir_rele(pdd, FTAG);
return (error);
}
/* You can only clone snapshots, not the head datasets. */
if (!origin->ds_is_snapshot) {
dsl_dataset_rele(origin, FTAG);
dsl_dir_rele(pdd, FTAG);
return (SET_ERROR(EINVAL));
}
dsl_dataset_rele(origin, FTAG);
dsl_dir_rele(pdd, FTAG);
return (0);
}
static void
dmu_objset_clone_sync(void *arg, dmu_tx_t *tx)
{
dmu_objset_clone_arg_t *doca = arg;
dsl_pool_t *dp = dmu_tx_pool(tx);
dsl_dir_t *pdd;
const char *tail;
dsl_dataset_t *origin, *ds;
uint64_t obj;
char namebuf[ZFS_MAX_DATASET_NAME_LEN];
VERIFY0(dsl_dir_hold(dp, doca->doca_clone, FTAG, &pdd, &tail));
VERIFY0(dsl_dataset_hold(dp, doca->doca_origin, FTAG, &origin));
obj = dsl_dataset_create_sync(pdd, tail, origin, 0,
doca->doca_cred, NULL, tx);
VERIFY0(dsl_dataset_hold_obj(pdd->dd_pool, obj, FTAG, &ds));
dsl_dataset_name(origin, namebuf);
spa_history_log_internal_ds(ds, "clone", tx,
"origin=%s (%llu)", namebuf, (u_longlong_t)origin->ds_object);
dsl_dataset_rele(ds, FTAG);
dsl_dataset_rele(origin, FTAG);
dsl_dir_rele(pdd, FTAG);
}
int
dmu_objset_clone(const char *clone, const char *origin)
{
dmu_objset_clone_arg_t doca;
cred_t *cr = CRED();
crhold(cr);
doca.doca_clone = clone;
doca.doca_origin = origin;
doca.doca_cred = cr;
int rv = dsl_sync_task(clone,
dmu_objset_clone_check, dmu_objset_clone_sync, &doca,
6, ZFS_SPACE_CHECK_NORMAL);
if (rv == 0)
zvol_create_minor(clone);
crfree(cr);
return (rv);
}
int int
dmu_objset_snapshot_one(const char *fsname, const char *snapname) dmu_objset_snapshot_one(const char *fsname, const char *snapname)
{ {
@ -3165,7 +3059,6 @@ EXPORT_SYMBOL(dmu_objset_rele_flags);
EXPORT_SYMBOL(dmu_objset_disown); EXPORT_SYMBOL(dmu_objset_disown);
EXPORT_SYMBOL(dmu_objset_from_ds); EXPORT_SYMBOL(dmu_objset_from_ds);
EXPORT_SYMBOL(dmu_objset_create); EXPORT_SYMBOL(dmu_objset_create);
EXPORT_SYMBOL(dmu_objset_clone);
EXPORT_SYMBOL(dmu_objset_stats); EXPORT_SYMBOL(dmu_objset_stats);
EXPORT_SYMBOL(dmu_objset_fast_stat); EXPORT_SYMBOL(dmu_objset_fast_stat);
EXPORT_SYMBOL(dmu_objset_spa); EXPORT_SYMBOL(dmu_objset_spa);

View File

@ -3320,6 +3320,106 @@ dsl_dataset_rollback(const char *fsname, const char *tosnap, void *owner,
1, ZFS_SPACE_CHECK_RESERVED)); 1, ZFS_SPACE_CHECK_RESERVED));
} }
int
dsl_dataset_clone_check(void *arg, dmu_tx_t *tx)
{
dsl_dataset_clone_arg_t *ddca = arg;
dsl_dir_t *pdd;
const char *tail;
int error;
dsl_dataset_t *origin;
dsl_pool_t *dp = dmu_tx_pool(tx);
if (strchr(ddca->ddca_clone, '@') != NULL)
return (SET_ERROR(EINVAL));
if (strlen(ddca->ddca_clone) >= ZFS_MAX_DATASET_NAME_LEN)
return (SET_ERROR(ENAMETOOLONG));
error = dsl_dir_hold(dp, ddca->ddca_clone, FTAG, &pdd, &tail);
if (error != 0)
return (error);
if (tail == NULL) {
dsl_dir_rele(pdd, FTAG);
return (SET_ERROR(EEXIST));
}
error = dsl_fs_ss_limit_check(pdd, 1, ZFS_PROP_FILESYSTEM_LIMIT, NULL,
ddca->ddca_cred);
if (error != 0) {
dsl_dir_rele(pdd, FTAG);
return (SET_ERROR(EDQUOT));
}
error = dsl_dataset_hold(dp, ddca->ddca_origin, FTAG, &origin);
if (error != 0) {
dsl_dir_rele(pdd, FTAG);
return (error);
}
/* You can only clone snapshots, not the head datasets. */
if (!origin->ds_is_snapshot) {
dsl_dataset_rele(origin, FTAG);
dsl_dir_rele(pdd, FTAG);
return (SET_ERROR(EINVAL));
}
dsl_dataset_rele(origin, FTAG);
dsl_dir_rele(pdd, FTAG);
return (0);
}
void
dsl_dataset_clone_sync(void *arg, dmu_tx_t *tx)
{
dsl_dataset_clone_arg_t *ddca = arg;
dsl_pool_t *dp = dmu_tx_pool(tx);
dsl_dir_t *pdd;
const char *tail;
dsl_dataset_t *origin, *ds;
uint64_t obj;
char namebuf[ZFS_MAX_DATASET_NAME_LEN];
VERIFY0(dsl_dir_hold(dp, ddca->ddca_clone, FTAG, &pdd, &tail));
VERIFY0(dsl_dataset_hold(dp, ddca->ddca_origin, FTAG, &origin));
obj = dsl_dataset_create_sync(pdd, tail, origin, 0,
ddca->ddca_cred, NULL, tx);
VERIFY0(dsl_dataset_hold_obj(pdd->dd_pool, obj, FTAG, &ds));
dsl_dataset_name(origin, namebuf);
spa_history_log_internal_ds(ds, "clone", tx,
"origin=%s (%llu)", namebuf, (u_longlong_t)origin->ds_object);
dsl_dataset_rele(ds, FTAG);
dsl_dataset_rele(origin, FTAG);
dsl_dir_rele(pdd, FTAG);
}
int
dsl_dataset_clone(const char *clone, const char *origin)
{
dsl_dataset_clone_arg_t ddca;
cred_t *cr = CRED();
crhold(cr);
ddca.ddca_clone = clone;
ddca.ddca_origin = origin;
ddca.ddca_cred = cr;
int rv = dsl_sync_task(clone,
dsl_dataset_clone_check, dsl_dataset_clone_sync, &ddca,
6, ZFS_SPACE_CHECK_NORMAL);
if (rv == 0)
zvol_create_minor(clone);
crfree(cr);
return (rv);
}
struct promotenode { struct promotenode {
list_node_t link; list_node_t link;
dsl_dataset_t *ds; dsl_dataset_t *ds;

View File

@ -3730,7 +3730,7 @@ zfs_ioc_clone(const char *fsname, nvlist_t *innvl, nvlist_t *outnvl)
if (dataset_namecheck(origin_name, NULL, NULL) != 0) if (dataset_namecheck(origin_name, NULL, NULL) != 0)
return (SET_ERROR(EINVAL)); return (SET_ERROR(EINVAL));
error = dmu_objset_clone(fsname, origin_name); error = dsl_dataset_clone(fsname, origin_name);
/* /*
* It would be nice to do this atomically. * It would be nice to do this atomically.