MFV r342469: 9630 add lzc_rename and lzc_destroy to libzfs_core

illumos/illumos-gate@049ba636fa
049ba636fa

https://www.illumos.org/issues/9630
  Rename and destroy are very useful operations that deserve to be in
  libzfs_core.  And they are not hard to implement too.

MFC after:	2 weeks
Relnotes:	maybe
This commit is contained in:
Andriy Gapon 2018-12-26 10:37:41 +00:00
commit f050611e7f
5 changed files with 79 additions and 37 deletions

View File

@ -3647,32 +3647,34 @@ zfs_create(libzfs_handle_t *hdl, const char *path, zfs_type_t type,
int
zfs_destroy(zfs_handle_t *zhp, boolean_t defer)
{
zfs_cmd_t zc = { 0 };
int error;
if (zhp->zfs_type != ZFS_TYPE_SNAPSHOT && defer)
return (EINVAL);
if (zhp->zfs_type == ZFS_TYPE_BOOKMARK) {
nvlist_t *nv = fnvlist_alloc();
fnvlist_add_boolean(nv, zhp->zfs_name);
int error = lzc_destroy_bookmarks(nv, NULL);
error = lzc_destroy_bookmarks(nv, NULL);
fnvlist_free(nv);
if (error != 0) {
return (zfs_standard_error_fmt(zhp->zfs_hdl, errno,
return (zfs_standard_error_fmt(zhp->zfs_hdl, error,
dgettext(TEXT_DOMAIN, "cannot destroy '%s'"),
zhp->zfs_name));
}
return (0);
}
(void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name));
if (ZFS_IS_VOLUME(zhp)) {
zc.zc_objset_type = DMU_OST_ZVOL;
if (zhp->zfs_type == ZFS_TYPE_SNAPSHOT) {
nvlist_t *nv = fnvlist_alloc();
fnvlist_add_boolean(nv, zhp->zfs_name);
error = lzc_destroy_snaps(nv, defer, NULL);
fnvlist_free(nv);
} else {
zc.zc_objset_type = DMU_OST_ZFS;
error = lzc_destroy(zhp->zfs_name);
}
zc.zc_defer_destroy = defer;
if (zfs_ioctl(zhp->zfs_hdl, ZFS_IOC_DESTROY, &zc) != 0 &&
errno != ENOENT) {
if (error != 0 && error != ENOENT) {
return (zfs_standard_error_fmt(zhp->zfs_hdl, errno,
dgettext(TEXT_DOMAIN, "cannot destroy '%s'"),
zhp->zfs_name));

View File

@ -2140,7 +2140,6 @@ recv_rename(libzfs_handle_t *hdl, const char *name, const char *tryname,
int baselen, char *newname, recvflags_t *flags)
{
static int seq;
zfs_cmd_t zc = { 0 };
int err;
prop_changelist_t *clp;
zfs_handle_t *zhp;
@ -2157,19 +2156,13 @@ recv_rename(libzfs_handle_t *hdl, const char *name, const char *tryname,
if (err)
return (err);
zc.zc_objset_type = DMU_OST_ZFS;
(void) strlcpy(zc.zc_name, name, sizeof (zc.zc_name));
if (tryname) {
(void) strcpy(newname, tryname);
(void) strlcpy(zc.zc_value, tryname, sizeof (zc.zc_value));
if (flags->verbose) {
(void) printf("attempting rename %s to %s\n",
zc.zc_name, zc.zc_value);
name, newname);
}
err = ioctl(hdl->libzfs_fd, ZFS_IOC_RENAME, &zc);
err = lzc_rename(name, newname);
if (err == 0)
changelist_rename(clp, name, tryname);
} else {
@ -2181,13 +2174,11 @@ recv_rename(libzfs_handle_t *hdl, const char *name, const char *tryname,
(void) snprintf(newname, ZFS_MAX_DATASET_NAME_LEN,
"%.*srecv-%u-%u", baselen, name, getpid(), seq);
(void) strlcpy(zc.zc_value, newname, sizeof (zc.zc_value));
if (flags->verbose) {
(void) printf("failed - trying rename %s to %s\n",
zc.zc_name, zc.zc_value);
name, newname);
}
err = ioctl(hdl->libzfs_fd, ZFS_IOC_RENAME, &zc);
err = lzc_rename(name, newname);
if (err == 0)
changelist_rename(clp, name, newname);
if (err && flags->verbose) {
@ -2212,7 +2203,6 @@ static int
recv_destroy(libzfs_handle_t *hdl, const char *name, int baselen,
char *newname, recvflags_t *flags)
{
zfs_cmd_t zc = { 0 };
int err = 0;
prop_changelist_t *clp;
zfs_handle_t *zhp;
@ -2235,17 +2225,20 @@ recv_destroy(libzfs_handle_t *hdl, const char *name, int baselen,
if (err)
return (err);
zc.zc_objset_type = DMU_OST_ZFS;
zc.zc_defer_destroy = defer;
(void) strlcpy(zc.zc_name, name, sizeof (zc.zc_name));
if (flags->verbose)
(void) printf("attempting destroy %s\n", zc.zc_name);
err = ioctl(hdl->libzfs_fd, ZFS_IOC_DESTROY, &zc);
(void) printf("attempting destroy %s\n", name);
if (zhp->zfs_type == ZFS_TYPE_SNAPSHOT) {
nvlist_t *nv = fnvlist_alloc();
fnvlist_add_boolean(nv, name);
err = lzc_destroy_snaps(nv, defer, NULL);
fnvlist_free(nv);
} else {
err = lzc_destroy(name);
}
if (err == 0) {
if (flags->verbose)
(void) printf("success\n");
changelist_remove(clp, zc.zc_name);
changelist_remove(clp, name);
}
(void) changelist_postfix(clp);

View File

@ -296,6 +296,34 @@ lzc_remap(const char *fsname)
return (error);
}
int
lzc_rename(const char *source, const char *target)
{
zfs_cmd_t zc = { 0 };
int error;
ASSERT3S(g_refcount, >, 0);
VERIFY3S(g_fd, !=, -1);
(void) strlcpy(zc.zc_name, source, sizeof (zc.zc_name));
(void) strlcpy(zc.zc_value, target, sizeof (zc.zc_value));
error = ioctl(g_fd, ZFS_IOC_RENAME, &zc);
if (error != 0)
error = errno;
return (error);
}
int
lzc_destroy(const char *fsname)
{
int error;
nvlist_t *args = fnvlist_alloc();
error = lzc_ioctl(ZFS_IOC_DESTROY, fsname, args, NULL);
nvlist_free(args);
return (error);
}
/*
* Creates snapshots.
*

View File

@ -91,6 +91,9 @@ boolean_t lzc_exists(const char *);
int lzc_rollback(const char *, char *, int);
int lzc_rollback_to(const char *, const char *);
int lzc_rename(const char *, const char *);
int lzc_destroy(const char *);
int lzc_channel_program(const char *, const char *, uint64_t,
uint64_t, nvlist_t *, nvlist_t **);
int lzc_channel_program_nosync(const char *, const char *, uint64_t,

View File

@ -3840,7 +3840,6 @@ zfs_ioc_pool_discard_checkpoint(const char *poolname, nvlist_t *innvl,
/*
* inputs:
* zc_name name of dataset to destroy
* zc_objset_type type of objset
* zc_defer_destroy mark for deferred destroy
*
* outputs: none
@ -3848,16 +3847,24 @@ zfs_ioc_pool_discard_checkpoint(const char *poolname, nvlist_t *innvl,
static int
zfs_ioc_destroy(zfs_cmd_t *zc)
{
objset_t *os;
dmu_objset_type_t ost;
int err;
if (zc->zc_objset_type == DMU_OST_ZFS)
err = dmu_objset_hold(zc->zc_name, FTAG, &os);
if (err != 0)
return (err);
ost = dmu_objset_type(os);
dmu_objset_rele(os, FTAG);
if (ost == DMU_OST_ZFS)
zfs_unmount_snap(zc->zc_name);
if (strchr(zc->zc_name, '@'))
err = dsl_destroy_snapshot(zc->zc_name, zc->zc_defer_destroy);
else
err = dsl_destroy_head(zc->zc_name);
if (zc->zc_objset_type == DMU_OST_ZVOL && err == 0)
if (ost == DMU_OST_ZVOL && err == 0)
#ifdef __FreeBSD__
zvol_remove_minors(zc->zc_name);
#else
@ -4016,9 +4023,12 @@ recursive_unmount(const char *fsname, void *arg)
static int
zfs_ioc_rename(zfs_cmd_t *zc)
{
objset_t *os;
dmu_objset_type_t ost;
boolean_t recursive = zc->zc_cookie & 1;
char *at;
boolean_t allow_mounted = B_TRUE;
int err;
#ifdef __FreeBSD__
allow_mounted = (zc->zc_cookie & 2) != 0;
@ -4032,6 +4042,12 @@ zfs_ioc_rename(zfs_cmd_t *zc)
strchr(zc->zc_name, '%') || strchr(zc->zc_value, '%'))
return (SET_ERROR(EINVAL));
err = dmu_objset_hold(zc->zc_name, FTAG, &os);
if (err != 0)
return (err);
ost = dmu_objset_type(os);
dmu_objset_rele(os, FTAG);
at = strchr(zc->zc_name, '@');
if (at != NULL) {
/* snaps must be in same fs */
@ -4040,7 +4056,7 @@ zfs_ioc_rename(zfs_cmd_t *zc)
if (strncmp(zc->zc_name, zc->zc_value, at - zc->zc_name + 1))
return (SET_ERROR(EXDEV));
*at = '\0';
if (zc->zc_objset_type == DMU_OST_ZFS && !allow_mounted) {
if (ost == DMU_OST_ZFS && !allow_mounted) {
error = dmu_objset_find(zc->zc_name,
recursive_unmount, at + 1,
recursive ? DS_FIND_CHILDREN : 0);
@ -4056,7 +4072,7 @@ zfs_ioc_rename(zfs_cmd_t *zc)
return (error);
} else {
#ifdef illumos
if (zc->zc_objset_type == DMU_OST_ZVOL)
if (ost == DMU_OST_ZVOL)
(void) zvol_remove_minor(zc->zc_name);
#endif
return (dsl_dir_rename(zc->zc_name, zc->zc_value));