ZFS: add bookmark renaming
The feature is implemented as an extension of the existing ZFS_IOC_RENAME ioctl. Both the userland and the DSL interfaces support renaming only a single bookmark at a time. As of now, there is no ZCP interface to the new functionality. I am going to add it once the DSL interface passes a test of time. This change picks up support for zfs_ioc_namecheck_t::ENTITY_NAME that was added to ZoL as part of Redacted Send/Receive feature by Paul Dagnelie <pcd@delphix.com>. This is needed to allow a bookmark name in zc_name. Discussed with: mahrens Reviewed by: bcr (man page) Sponsored by: CyberSecure Differential Revision: https://reviews.freebsd.org/D21795
This commit is contained in:
parent
d60ac9d561
commit
912c3fe715
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=353037
@ -105,6 +105,9 @@
|
|||||||
.Ar snapshot snapshot
|
.Ar snapshot snapshot
|
||||||
.Nm
|
.Nm
|
||||||
.Cm rename
|
.Cm rename
|
||||||
|
.Ar bookmark bookmark
|
||||||
|
.Nm
|
||||||
|
.Cm rename
|
||||||
.Fl u
|
.Fl u
|
||||||
.Op Fl p
|
.Op Fl p
|
||||||
.Ar filesystem filesystem
|
.Ar filesystem filesystem
|
||||||
@ -2094,6 +2097,16 @@ Recursively rename the snapshots of all descendent datasets. Snapshots are the
|
|||||||
only dataset that can be renamed recursively.
|
only dataset that can be renamed recursively.
|
||||||
.It Xo
|
.It Xo
|
||||||
.Nm
|
.Nm
|
||||||
|
.Cm rename
|
||||||
|
.Ar bookmark bookmark
|
||||||
|
.Xc
|
||||||
|
.Pp
|
||||||
|
Renames the given bookmark.
|
||||||
|
Bookmarks can only be renamed within the parent file system or volume.
|
||||||
|
When renaming a bookmark, the parent file system or volume of the bookmark
|
||||||
|
does not need to be specified as part of the second argument.
|
||||||
|
.It Xo
|
||||||
|
.Nm
|
||||||
.Cm list
|
.Cm list
|
||||||
.Op Fl r Ns | Ns Fl d Ar depth
|
.Op Fl r Ns | Ns Fl d Ar depth
|
||||||
.Op Fl Hp
|
.Op Fl Hp
|
||||||
|
@ -284,6 +284,7 @@ get_usage(zfs_help_t idx)
|
|||||||
"<filesystem|volume|snapshot>\n"
|
"<filesystem|volume|snapshot>\n"
|
||||||
"\trename [-f] -p <filesystem|volume> <filesystem|volume>\n"
|
"\trename [-f] -p <filesystem|volume> <filesystem|volume>\n"
|
||||||
"\trename -r <snapshot> <snapshot>\n"
|
"\trename -r <snapshot> <snapshot>\n"
|
||||||
|
"\trename <bookmark> <bookmark>\n"
|
||||||
"\trename -u [-p] <filesystem> <filesystem>"));
|
"\trename -u [-p] <filesystem> <filesystem>"));
|
||||||
case HELP_ROLLBACK:
|
case HELP_ROLLBACK:
|
||||||
return (gettext("\trollback [-rRf] <snapshot>\n"));
|
return (gettext("\trollback [-rRf] <snapshot>\n"));
|
||||||
@ -3254,6 +3255,7 @@ zfs_do_list(int argc, char **argv)
|
|||||||
* zfs rename [-f] <fs | snap | vol> <fs | snap | vol>
|
* zfs rename [-f] <fs | snap | vol> <fs | snap | vol>
|
||||||
* zfs rename [-f] -p <fs | vol> <fs | vol>
|
* zfs rename [-f] -p <fs | vol> <fs | vol>
|
||||||
* zfs rename -r <snap> <snap>
|
* zfs rename -r <snap> <snap>
|
||||||
|
* zfs rename <bmark> <bmark>
|
||||||
* zfs rename -u [-p] <fs> <fs>
|
* zfs rename -u [-p] <fs> <fs>
|
||||||
*
|
*
|
||||||
* Renames the given dataset to another of the same type.
|
* Renames the given dataset to another of the same type.
|
||||||
@ -3270,6 +3272,7 @@ zfs_do_rename(int argc, char **argv)
|
|||||||
int ret = 0;
|
int ret = 0;
|
||||||
int types;
|
int types;
|
||||||
boolean_t parents = B_FALSE;
|
boolean_t parents = B_FALSE;
|
||||||
|
boolean_t bookmarks = B_FALSE;
|
||||||
char *snapshot = NULL;
|
char *snapshot = NULL;
|
||||||
|
|
||||||
/* check options */
|
/* check options */
|
||||||
@ -3320,7 +3323,7 @@ zfs_do_rename(int argc, char **argv)
|
|||||||
usage(B_FALSE);
|
usage(B_FALSE);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (flags.recurse && strchr(argv[0], '@') == 0) {
|
if (flags.recurse && strchr(argv[0], '@') == NULL) {
|
||||||
(void) fprintf(stderr, gettext("source dataset for recursive "
|
(void) fprintf(stderr, gettext("source dataset for recursive "
|
||||||
"rename must be a snapshot\n"));
|
"rename must be a snapshot\n"));
|
||||||
usage(B_FALSE);
|
usage(B_FALSE);
|
||||||
@ -3332,10 +3335,22 @@ zfs_do_rename(int argc, char **argv)
|
|||||||
usage(B_FALSE);
|
usage(B_FALSE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (strchr(argv[0], '#') != NULL)
|
||||||
|
bookmarks = B_TRUE;
|
||||||
|
|
||||||
|
if (bookmarks && (flags.nounmount || flags.recurse ||
|
||||||
|
flags.forceunmount || parents)) {
|
||||||
|
(void) fprintf(stderr, gettext("options are not supported "
|
||||||
|
"for renaming bookmarks\n"));
|
||||||
|
usage(B_FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
if (flags.nounmount)
|
if (flags.nounmount)
|
||||||
types = ZFS_TYPE_FILESYSTEM;
|
types = ZFS_TYPE_FILESYSTEM;
|
||||||
else if (parents)
|
else if (parents)
|
||||||
types = ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME;
|
types = ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME;
|
||||||
|
else if (bookmarks)
|
||||||
|
types = ZFS_TYPE_BOOKMARK;
|
||||||
else
|
else
|
||||||
types = ZFS_TYPE_DATASET;
|
types = ZFS_TYPE_DATASET;
|
||||||
|
|
||||||
|
@ -4291,17 +4291,18 @@ zfs_rename(zfs_handle_t *zhp, const char *source, const char *target,
|
|||||||
/*
|
/*
|
||||||
* Make sure the target name is valid
|
* Make sure the target name is valid
|
||||||
*/
|
*/
|
||||||
if (zhp->zfs_type == ZFS_TYPE_SNAPSHOT) {
|
if (zhp->zfs_type == ZFS_TYPE_SNAPSHOT ||
|
||||||
if ((strchr(target, '@') == NULL) ||
|
zhp->zfs_type == ZFS_TYPE_BOOKMARK) {
|
||||||
*target == '@') {
|
const char sep = zhp->zfs_type == ZFS_TYPE_SNAPSHOT ? '@' : '#';
|
||||||
|
|
||||||
|
if ((strchr(target, sep) == NULL) || *target == sep) {
|
||||||
/*
|
/*
|
||||||
* Snapshot target name is abbreviated,
|
* Snapshot target name is abbreviated,
|
||||||
* reconstruct full dataset name
|
* reconstruct full dataset name
|
||||||
*/
|
*/
|
||||||
(void) strlcpy(parent, zhp->zfs_name,
|
(void) strlcpy(parent, zhp->zfs_name, sizeof (parent));
|
||||||
sizeof (parent));
|
delim = strchr(parent, sep);
|
||||||
delim = strchr(parent, '@');
|
if (strchr(target, sep) == NULL)
|
||||||
if (strchr(target, '@') == NULL)
|
|
||||||
*(++delim) = '\0';
|
*(++delim) = '\0';
|
||||||
else
|
else
|
||||||
*delim = '\0';
|
*delim = '\0';
|
||||||
@ -4311,12 +4312,13 @@ zfs_rename(zfs_handle_t *zhp, const char *source, const char *target,
|
|||||||
/*
|
/*
|
||||||
* Make sure we're renaming within the same dataset.
|
* Make sure we're renaming within the same dataset.
|
||||||
*/
|
*/
|
||||||
delim = strchr(target, '@');
|
delim = strchr(target, sep);
|
||||||
if (strncmp(zhp->zfs_name, target, delim - target)
|
if (strncmp(zhp->zfs_name, target, delim - target)
|
||||||
!= 0 || zhp->zfs_name[delim - target] != '@') {
|
!= 0 || zhp->zfs_name[delim - target] != sep) {
|
||||||
zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
|
zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
|
||||||
"snapshots must be part of same "
|
"%s must be part of same dataset"),
|
||||||
"dataset"));
|
zhp->zfs_type == ZFS_TYPE_SNAPSHOT ?
|
||||||
|
"snapshots" : "bookmarks");
|
||||||
return (zfs_error(hdl, EZFS_CROSSTARGET,
|
return (zfs_error(hdl, EZFS_CROSSTARGET,
|
||||||
errbuf));
|
errbuf));
|
||||||
}
|
}
|
||||||
@ -4379,7 +4381,6 @@ zfs_rename(zfs_handle_t *zhp, const char *source, const char *target,
|
|||||||
flags.nounmount = B_TRUE;
|
flags.nounmount = B_TRUE;
|
||||||
}
|
}
|
||||||
if (flags.recurse) {
|
if (flags.recurse) {
|
||||||
|
|
||||||
parentname = zfs_strdup(zhp->zfs_hdl, zhp->zfs_name);
|
parentname = zfs_strdup(zhp->zfs_hdl, zhp->zfs_name);
|
||||||
if (parentname == NULL) {
|
if (parentname == NULL) {
|
||||||
ret = -1;
|
ret = -1;
|
||||||
@ -4392,7 +4393,8 @@ zfs_rename(zfs_handle_t *zhp, const char *source, const char *target,
|
|||||||
ret = -1;
|
ret = -1;
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
} else if (zhp->zfs_type != ZFS_TYPE_SNAPSHOT) {
|
} else if (zhp->zfs_type != ZFS_TYPE_SNAPSHOT &&
|
||||||
|
zhp->zfs_type != ZFS_TYPE_BOOKMARK) {
|
||||||
if ((cl = changelist_gather(zhp, ZFS_PROP_NAME,
|
if ((cl = changelist_gather(zhp, ZFS_PROP_NAME,
|
||||||
flags.nounmount ? CL_GATHER_DONT_UNMOUNT : 0,
|
flags.nounmount ? CL_GATHER_DONT_UNMOUNT : 0,
|
||||||
flags.forceunmount ? MS_FORCE : 0)) == NULL) {
|
flags.forceunmount ? MS_FORCE : 0)) == NULL) {
|
||||||
@ -4437,6 +4439,8 @@ zfs_rename(zfs_handle_t *zhp, const char *source, const char *target,
|
|||||||
"a child dataset already has a snapshot "
|
"a child dataset already has a snapshot "
|
||||||
"with the new name"));
|
"with the new name"));
|
||||||
(void) zfs_error(hdl, EZFS_EXISTS, errbuf);
|
(void) zfs_error(hdl, EZFS_EXISTS, errbuf);
|
||||||
|
} else if (errno == EINVAL) {
|
||||||
|
(void) zfs_error(hdl, EZFS_INVALIDNAME, errbuf);
|
||||||
} else {
|
} else {
|
||||||
(void) zfs_standard_error(zhp->zfs_hdl, errno, errbuf);
|
(void) zfs_standard_error(zhp->zfs_hdl, errno, errbuf);
|
||||||
}
|
}
|
||||||
|
@ -459,3 +459,108 @@ dsl_bookmark_destroy(nvlist_t *bmarks, nvlist_t *errors)
|
|||||||
fnvlist_free(dbda.dbda_success);
|
fnvlist_free(dbda.dbda_success);
|
||||||
return (rv);
|
return (rv);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
typedef struct dsl_bookmark_rename_arg {
|
||||||
|
const char *dbra_fsname;
|
||||||
|
const char *dbra_oldname;
|
||||||
|
const char *dbra_newname;
|
||||||
|
} dsl_bookmark_rename_arg_t;
|
||||||
|
|
||||||
|
static int
|
||||||
|
dsl_bookmark_rename_check(void *arg, dmu_tx_t *tx)
|
||||||
|
{
|
||||||
|
dsl_bookmark_rename_arg_t *dbra = arg;
|
||||||
|
dsl_pool_t *dp = dmu_tx_pool(tx);
|
||||||
|
dsl_dataset_t *ds;
|
||||||
|
zfs_bookmark_phys_t bmark_phys;
|
||||||
|
int error;
|
||||||
|
|
||||||
|
if (!spa_feature_is_enabled(dp->dp_spa, SPA_FEATURE_BOOKMARKS))
|
||||||
|
return (SET_ERROR(ENOTSUP));
|
||||||
|
|
||||||
|
/* Check validity and the full length of the new bookmark name. */
|
||||||
|
if (zfs_component_namecheck(dbra->dbra_newname, NULL, NULL))
|
||||||
|
return (SET_ERROR(EINVAL));
|
||||||
|
if (strlen(dbra->dbra_fsname) + strlen(dbra->dbra_newname) + 1 >=
|
||||||
|
ZFS_MAX_DATASET_NAME_LEN)
|
||||||
|
return (SET_ERROR(ENAMETOOLONG));
|
||||||
|
|
||||||
|
error = dsl_dataset_hold(dp, dbra->dbra_fsname, FTAG, &ds);
|
||||||
|
if (error != 0)
|
||||||
|
return (error);
|
||||||
|
if (ds->ds_is_snapshot) {
|
||||||
|
dsl_dataset_rele(ds, FTAG);
|
||||||
|
return (SET_ERROR(EINVAL));
|
||||||
|
}
|
||||||
|
error = dsl_dataset_bmark_lookup(ds, dbra->dbra_oldname, &bmark_phys);
|
||||||
|
if (error != 0) {
|
||||||
|
dsl_dataset_rele(ds, FTAG);
|
||||||
|
return (error);
|
||||||
|
}
|
||||||
|
|
||||||
|
error = dsl_dataset_bmark_lookup(ds, dbra->dbra_newname, &bmark_phys);
|
||||||
|
dsl_dataset_rele(ds, FTAG);
|
||||||
|
if (error == 0)
|
||||||
|
return (SET_ERROR(EEXIST));
|
||||||
|
if (error != ESRCH)
|
||||||
|
return (error);
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
dsl_bookmark_rename_sync(void *arg, dmu_tx_t *tx)
|
||||||
|
{
|
||||||
|
zfs_bookmark_phys_t bmark_phys;
|
||||||
|
dsl_bookmark_rename_arg_t *dbra = arg;
|
||||||
|
dsl_pool_t *dp = dmu_tx_pool(tx);
|
||||||
|
objset_t *mos;
|
||||||
|
dsl_dataset_t *ds;
|
||||||
|
uint64_t bmark_zapobj;
|
||||||
|
uint64_t int_size, num_ints;
|
||||||
|
matchtype_t mt = 0;
|
||||||
|
int error;
|
||||||
|
|
||||||
|
ASSERT(spa_feature_is_enabled(dp->dp_spa, SPA_FEATURE_BOOKMARKS));
|
||||||
|
VERIFY0(dsl_dataset_hold(dp, dbra->dbra_fsname, FTAG, &ds));
|
||||||
|
|
||||||
|
mos = ds->ds_dir->dd_pool->dp_meta_objset;
|
||||||
|
bmark_zapobj = ds->ds_bookmarks;
|
||||||
|
|
||||||
|
if (dsl_dataset_phys(ds)->ds_flags & DS_FLAG_CI_DATASET)
|
||||||
|
mt = MT_NORMALIZE;
|
||||||
|
|
||||||
|
VERIFY0(zap_length(mos, bmark_zapobj, dbra->dbra_oldname,
|
||||||
|
&int_size, &num_ints));
|
||||||
|
ASSERT3U(int_size, ==, sizeof (uint64_t));
|
||||||
|
VERIFY0(zap_lookup_norm(mos, bmark_zapobj, dbra->dbra_oldname, int_size,
|
||||||
|
num_ints, &bmark_phys, mt, NULL, 0, NULL));
|
||||||
|
VERIFY0(zap_remove_norm(mos, bmark_zapobj, dbra->dbra_oldname, mt, tx));
|
||||||
|
|
||||||
|
VERIFY0(zap_add(mos, bmark_zapobj, dbra->dbra_newname, int_size,
|
||||||
|
num_ints, &bmark_phys, tx));
|
||||||
|
|
||||||
|
spa_history_log_internal_ds(ds, "rename bookmark", tx,
|
||||||
|
"#%s -> #%s creation_txg=%llu",
|
||||||
|
dbra->dbra_oldname, dbra->dbra_newname,
|
||||||
|
(longlong_t)bmark_phys.zbm_creation_txg);
|
||||||
|
|
||||||
|
dsl_dataset_rele(ds, FTAG);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The bookmarks must all be in the same pool.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
dsl_bookmark_rename(const char *fsname, const char *oldbmark,
|
||||||
|
const char *newbmark)
|
||||||
|
{
|
||||||
|
dsl_bookmark_rename_arg_t dbra;
|
||||||
|
|
||||||
|
dbra.dbra_fsname = fsname;
|
||||||
|
dbra.dbra_oldname = oldbmark;
|
||||||
|
dbra.dbra_newname = newbmark;
|
||||||
|
|
||||||
|
return (dsl_sync_task(fsname, dsl_bookmark_rename_check,
|
||||||
|
dsl_bookmark_rename_sync, &dbra, 1, ZFS_SPACE_CHECK_NORMAL));
|
||||||
|
}
|
||||||
|
|
||||||
|
@ -41,6 +41,7 @@ int dsl_bookmark_create(nvlist_t *, nvlist_t *);
|
|||||||
int dsl_get_bookmarks(const char *, nvlist_t *, nvlist_t *);
|
int dsl_get_bookmarks(const char *, nvlist_t *, nvlist_t *);
|
||||||
int dsl_get_bookmarks_impl(dsl_dataset_t *, nvlist_t *, nvlist_t *);
|
int dsl_get_bookmarks_impl(dsl_dataset_t *, nvlist_t *, nvlist_t *);
|
||||||
int dsl_bookmark_destroy(nvlist_t *, nvlist_t *);
|
int dsl_bookmark_destroy(nvlist_t *, nvlist_t *);
|
||||||
|
int dsl_bookmark_rename(const char *fs, const char *from, const char *to);
|
||||||
int dsl_bookmark_lookup(struct dsl_pool *, const char *,
|
int dsl_bookmark_lookup(struct dsl_pool *, const char *,
|
||||||
struct dsl_dataset *, zfs_bookmark_phys_t *);
|
struct dsl_dataset *, zfs_bookmark_phys_t *);
|
||||||
|
|
||||||
|
@ -224,7 +224,8 @@ typedef int zfs_secpolicy_func_t(zfs_cmd_t *, nvlist_t *, cred_t *);
|
|||||||
typedef enum {
|
typedef enum {
|
||||||
NO_NAME,
|
NO_NAME,
|
||||||
POOL_NAME,
|
POOL_NAME,
|
||||||
DATASET_NAME
|
DATASET_NAME,
|
||||||
|
ENTITY_NAME
|
||||||
} zfs_ioc_namecheck_t;
|
} zfs_ioc_namecheck_t;
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
@ -922,8 +923,21 @@ static int
|
|||||||
zfs_secpolicy_rename(zfs_cmd_t *zc, nvlist_t *innvl, cred_t *cr)
|
zfs_secpolicy_rename(zfs_cmd_t *zc, nvlist_t *innvl, cred_t *cr)
|
||||||
{
|
{
|
||||||
char *at = NULL;
|
char *at = NULL;
|
||||||
|
char *pound;
|
||||||
int error;
|
int error;
|
||||||
|
|
||||||
|
if ((pound = strchr(zc->zc_name, '#')) != NULL) {
|
||||||
|
*pound = '\0';
|
||||||
|
error = zfs_secpolicy_write_perms(zc->zc_name,
|
||||||
|
ZFS_DELEG_PERM_RENAME, cr);
|
||||||
|
if (error == 0) {
|
||||||
|
error = zfs_secpolicy_write_perms(zc->zc_name,
|
||||||
|
ZFS_DELEG_PERM_BOOKMARK, cr);
|
||||||
|
}
|
||||||
|
*pound = '#';
|
||||||
|
return (error);
|
||||||
|
}
|
||||||
|
|
||||||
if ((zc->zc_cookie & 1) != 0) {
|
if ((zc->zc_cookie & 1) != 0) {
|
||||||
/*
|
/*
|
||||||
* This is recursive rename, so the starting snapshot might
|
* This is recursive rename, so the starting snapshot might
|
||||||
@ -4020,8 +4034,8 @@ recursive_unmount(const char *fsname, void *arg)
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* inputs:
|
* inputs:
|
||||||
* zc_name old name of dataset
|
* zc_name old name of dataset or bookmark
|
||||||
* zc_value new name of dataset
|
* zc_value new name of dataset or bookmark
|
||||||
* zc_cookie recursive flag (only valid for snapshots)
|
* zc_cookie recursive flag (only valid for snapshots)
|
||||||
*
|
*
|
||||||
* outputs: none
|
* outputs: none
|
||||||
@ -4032,7 +4046,7 @@ zfs_ioc_rename(zfs_cmd_t *zc)
|
|||||||
objset_t *os;
|
objset_t *os;
|
||||||
dmu_objset_type_t ost;
|
dmu_objset_type_t ost;
|
||||||
boolean_t recursive = zc->zc_cookie & 1;
|
boolean_t recursive = zc->zc_cookie & 1;
|
||||||
char *at;
|
char *pos, *pos2;
|
||||||
boolean_t allow_mounted = B_TRUE;
|
boolean_t allow_mounted = B_TRUE;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
@ -4040,9 +4054,34 @@ zfs_ioc_rename(zfs_cmd_t *zc)
|
|||||||
allow_mounted = (zc->zc_cookie & 2) != 0;
|
allow_mounted = (zc->zc_cookie & 2) != 0;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* "zfs rename" from and to ...%recv datasets should both fail */
|
|
||||||
zc->zc_name[sizeof (zc->zc_name) - 1] = '\0';
|
zc->zc_name[sizeof (zc->zc_name) - 1] = '\0';
|
||||||
zc->zc_value[sizeof (zc->zc_value) - 1] = '\0';
|
zc->zc_value[sizeof (zc->zc_value) - 1] = '\0';
|
||||||
|
|
||||||
|
pos = strchr(zc->zc_name, '#');
|
||||||
|
if (pos != NULL) {
|
||||||
|
/* Bookmarks must be in same fs. */
|
||||||
|
pos2 = strchr(zc->zc_value, '#');
|
||||||
|
if (pos2 == NULL)
|
||||||
|
return (SET_ERROR(EINVAL));
|
||||||
|
|
||||||
|
/* Recursive flag is not supported yet. */
|
||||||
|
if (recursive)
|
||||||
|
return (SET_ERROR(ENOTSUP));
|
||||||
|
|
||||||
|
*pos = '\0';
|
||||||
|
*pos2 = '\0';
|
||||||
|
if (strcmp(zc->zc_name, zc->zc_value) == 0) {
|
||||||
|
err = dsl_bookmark_rename(zc->zc_name,
|
||||||
|
pos + 1, pos2 + 1);
|
||||||
|
} else {
|
||||||
|
err = SET_ERROR(EXDEV);
|
||||||
|
}
|
||||||
|
*pos = '#';
|
||||||
|
*pos2 = '#';
|
||||||
|
return (err);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* "zfs rename" from and to ...%recv datasets should both fail */
|
||||||
if (dataset_namecheck(zc->zc_name, NULL, NULL) != 0 ||
|
if (dataset_namecheck(zc->zc_name, NULL, NULL) != 0 ||
|
||||||
dataset_namecheck(zc->zc_value, NULL, NULL) != 0 ||
|
dataset_namecheck(zc->zc_value, NULL, NULL) != 0 ||
|
||||||
strchr(zc->zc_name, '%') || strchr(zc->zc_value, '%'))
|
strchr(zc->zc_name, '%') || strchr(zc->zc_value, '%'))
|
||||||
@ -4054,28 +4093,30 @@ zfs_ioc_rename(zfs_cmd_t *zc)
|
|||||||
ost = dmu_objset_type(os);
|
ost = dmu_objset_type(os);
|
||||||
dmu_objset_rele(os, FTAG);
|
dmu_objset_rele(os, FTAG);
|
||||||
|
|
||||||
at = strchr(zc->zc_name, '@');
|
pos = strchr(zc->zc_name, '@');
|
||||||
if (at != NULL) {
|
if (pos != NULL) {
|
||||||
/* snaps must be in same fs */
|
/* Snapshots must be in same fs. */
|
||||||
int error;
|
pos2 = strchr(zc->zc_value, '@');
|
||||||
|
if (pos2 == NULL)
|
||||||
if (strncmp(zc->zc_name, zc->zc_value, at - zc->zc_name + 1))
|
return (SET_ERROR(EINVAL));
|
||||||
return (SET_ERROR(EXDEV));
|
*pos = '\0';
|
||||||
*at = '\0';
|
*pos2 = '\0';
|
||||||
if (ost == DMU_OST_ZFS && !allow_mounted) {
|
if (strcmp(zc->zc_name, zc->zc_value) != 0) {
|
||||||
error = dmu_objset_find(zc->zc_name,
|
err = SET_ERROR(EXDEV);
|
||||||
recursive_unmount, at + 1,
|
} else {
|
||||||
recursive ? DS_FIND_CHILDREN : 0);
|
if (ost == DMU_OST_ZFS && !allow_mounted) {
|
||||||
if (error != 0) {
|
err = dmu_objset_find(zc->zc_name,
|
||||||
*at = '@';
|
recursive_unmount, pos + 1,
|
||||||
return (error);
|
recursive ? DS_FIND_CHILDREN : 0);
|
||||||
|
}
|
||||||
|
if (err == 0) {
|
||||||
|
err = dsl_dataset_rename_snapshot(zc->zc_name,
|
||||||
|
pos + 1, pos2 + 1, recursive);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
error = dsl_dataset_rename_snapshot(zc->zc_name,
|
*pos = '@';
|
||||||
at + 1, strchr(zc->zc_value, '@') + 1, recursive);
|
*pos2 = '@';
|
||||||
*at = '@';
|
return (err);
|
||||||
|
|
||||||
return (error);
|
|
||||||
} else {
|
} else {
|
||||||
#ifdef illumos
|
#ifdef illumos
|
||||||
if (ost == DMU_OST_ZVOL)
|
if (ost == DMU_OST_ZVOL)
|
||||||
@ -6352,8 +6393,6 @@ zfs_ioctl_init(void)
|
|||||||
zfs_secpolicy_none);
|
zfs_secpolicy_none);
|
||||||
zfs_ioctl_register_dataset_modify(ZFS_IOC_DESTROY, zfs_ioc_destroy,
|
zfs_ioctl_register_dataset_modify(ZFS_IOC_DESTROY, zfs_ioc_destroy,
|
||||||
zfs_secpolicy_destroy);
|
zfs_secpolicy_destroy);
|
||||||
zfs_ioctl_register_dataset_modify(ZFS_IOC_RENAME, zfs_ioc_rename,
|
|
||||||
zfs_secpolicy_rename);
|
|
||||||
zfs_ioctl_register_dataset_modify(ZFS_IOC_RECV, zfs_ioc_recv,
|
zfs_ioctl_register_dataset_modify(ZFS_IOC_RECV, zfs_ioc_recv,
|
||||||
zfs_secpolicy_recv);
|
zfs_secpolicy_recv);
|
||||||
zfs_ioctl_register_dataset_modify(ZFS_IOC_PROMOTE, zfs_ioc_promote,
|
zfs_ioctl_register_dataset_modify(ZFS_IOC_PROMOTE, zfs_ioc_promote,
|
||||||
@ -6363,6 +6402,14 @@ zfs_ioctl_init(void)
|
|||||||
zfs_ioctl_register_dataset_modify(ZFS_IOC_SET_FSACL, zfs_ioc_set_fsacl,
|
zfs_ioctl_register_dataset_modify(ZFS_IOC_SET_FSACL, zfs_ioc_set_fsacl,
|
||||||
zfs_secpolicy_set_fsacl);
|
zfs_secpolicy_set_fsacl);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Not using zfs_ioctl_register_dataset_modify as DATASET_NAME check
|
||||||
|
* won't allow a bookmark name.
|
||||||
|
*/
|
||||||
|
zfs_ioctl_register_legacy(ZFS_IOC_RENAME, zfs_ioc_rename,
|
||||||
|
zfs_secpolicy_rename, ENTITY_NAME, B_TRUE,
|
||||||
|
POOL_CHECK_SUSPENDED | POOL_CHECK_READONLY);
|
||||||
|
|
||||||
zfs_ioctl_register_dataset_nolog(ZFS_IOC_SHARE, zfs_ioc_share,
|
zfs_ioctl_register_dataset_nolog(ZFS_IOC_SHARE, zfs_ioc_share,
|
||||||
zfs_secpolicy_share, POOL_CHECK_NONE);
|
zfs_secpolicy_share, POOL_CHECK_NONE);
|
||||||
zfs_ioctl_register_dataset_nolog(ZFS_IOC_SMB_ACL, zfs_ioc_smb_acl,
|
zfs_ioctl_register_dataset_nolog(ZFS_IOC_SMB_ACL, zfs_ioc_smb_acl,
|
||||||
@ -6392,7 +6439,8 @@ pool_status_check(const char *name, zfs_ioc_namecheck_t type,
|
|||||||
spa_t *spa;
|
spa_t *spa;
|
||||||
int error;
|
int error;
|
||||||
|
|
||||||
ASSERT(type == POOL_NAME || type == DATASET_NAME);
|
ASSERT(type == POOL_NAME || type == DATASET_NAME ||
|
||||||
|
type == ENTITY_NAME);
|
||||||
|
|
||||||
if (check & POOL_CHECK_NONE)
|
if (check & POOL_CHECK_NONE)
|
||||||
return (0);
|
return (0);
|
||||||
@ -6725,6 +6773,15 @@ zfsdev_ioctl(struct cdev *dev, u_long zcmd, caddr_t arg, int flag,
|
|||||||
vec->zvec_namecheck, vec->zvec_pool_check);
|
vec->zvec_namecheck, vec->zvec_pool_check);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case ENTITY_NAME:
|
||||||
|
if (entity_namecheck(zc->zc_name, NULL, NULL) != 0) {
|
||||||
|
error = SET_ERROR(EINVAL);
|
||||||
|
} else {
|
||||||
|
error = pool_status_check(zc->zc_name,
|
||||||
|
vec->zvec_namecheck, vec->zvec_pool_check);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
case NO_NAME:
|
case NO_NAME:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user