]> granicus.if.org Git - zfs/commitdiff
OpenZFS 9630 - add lzc_rename and lzc_destroy to libzfs_core
authorAndriy Gapon <avg@FreeBSD.org>
Wed, 27 Jun 2018 21:37:54 +0000 (00:37 +0300)
committerBrian Behlendorf <behlendorf1@llnl.gov>
Fri, 14 Dec 2018 17:49:45 +0000 (09:49 -0800)
Porting Notes:
* Additional changes to recv_rename_impl() were required due to
  encryption code not being merged in OpenZFS yet.
* libzfs_core python bindings (pyzfs) were updated to fully support
  both lzc_rename() and lzc_destroy()

Authored by: Andriy Gapon <avg@FreeBSD.org>
Reviewed by: Andy Stormont <astormont@racktopsystems.com>
Reviewed by: Matt Ahrens <matt@delphix.com>
Reviewed by: Serapheim Dimitropoulos <serapheim.dimitro@delphix.com>
Reviewed by: Brian Behlendorf <behlendorf1@llnl.gov>
Approved by: Dan McDonald <danmcd@joyent.com>
Ported-by: loli10K <ezomori.nozomu@gmail.com>
OpenZFS-issue: https://www.illumos.org/issues/9630
OpenZFS-commit: https://github.com/openzfs/openzfs/commit/049ba63
Closes #8207

contrib/pyzfs/libzfs_core/_libzfs_core.py
contrib/pyzfs/libzfs_core/bindings/libzfs_core.py
include/libzfs_core.h
lib/libzfs/libzfs_dataset.c
lib/libzfs/libzfs_sendrecv.c
lib/libzfs_core/libzfs_core.c
module/zfs/zfs_ioctl.c
tests/zfs-tests/cmd/libzfs_input_check/libzfs_input_check.c

index db207bf71e1fcb144bfa5d80010e36c7a3ec8568..157dc16e9a75419329a78152b15a8b031a8f843e 100644 (file)
@@ -1605,7 +1605,6 @@ def lzc_pool_checkpoint_discard(name):
     errors.lzc_pool_checkpoint_discard_translate_error(ret, name)
 
 
-@_uncommitted()
 def lzc_rename(source, target):
     '''
     Rename the ZFS dataset.
@@ -1621,12 +1620,11 @@ def lzc_rename(source, target):
     :raises FilesystemExists: if the target already exists.
     :raises PoolsDiffer: if the source and target belong to different pools.
     '''
-    ret = _lib.lzc_rename(source, target, _ffi.NULL, _ffi.NULL)
+    ret = _lib.lzc_rename(source, target)
     errors.lzc_rename_translate_error(ret, source, target)
 
 
-@_uncommitted()
-def lzc_destroy_one(name):
+def lzc_destroy(name):
     '''
     Destroy the ZFS dataset.
 
@@ -1635,16 +1633,10 @@ def lzc_destroy_one(name):
     :raises NameTooLong: if the dataset name is too long.
     :raises FilesystemNotFound: if the dataset does not exist.
     '''
-    ret = _lib.lzc_destroy_one(name, _ffi.NULL)
+    ret = _lib.lzc_destroy(name)
     errors.lzc_destroy_translate_error(ret, name)
 
 
-# As the extended API is not committed yet, the names of the new interfaces
-# are not settled down yet.
-# lzc_destroy() might make more sense as we do not have lzc_create_one().
-lzc_destroy = lzc_destroy_one
-
-
 @_uncommitted()
 def lzc_inherit(name, prop):
     '''
index b69c8d779aa861cc330b2081e687f70160ba9c22..658394a3fe5540a9144588b1a1377e5526a2080d 100644 (file)
@@ -129,9 +129,9 @@ CDEF = """
     int lzc_remap(const char *);
     int lzc_pool_checkpoint(const char *);
     int lzc_pool_checkpoint_discard(const char *);
+    int lzc_rename(const char *, const char *);
+    int lzc_destroy(const char *fsname);
 
-    int lzc_rename(const char *, const char *, nvlist_t *, char **);
-    int lzc_destroy_one(const char *fsname, nvlist_t *);
     int lzc_inherit(const char *fsname, const char *name, nvlist_t *);
     int lzc_set_props(const char *, nvlist_t *, nvlist_t *, nvlist_t *);
     int lzc_list (const char *, nvlist_t *);
index c22cbf18e2cc974b28a47fcea516ea471debab20..f84270d7eb440df4c1e3ad4676f7f384f31a2a72 100644 (file)
@@ -102,6 +102,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,
index 237933c371f0ed35b59dd1ea6748e7b2ed451a39..6445c9d7acf3509ce73d8aeed83eaeda279314d5 100644 (file)
@@ -3856,32 +3856,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));
index a05ccbe30960ee9babafb7b59e8c452a5813adc9..ae24454d7c792977884598b5709613fb1a3e9a43 100644 (file)
@@ -2294,7 +2294,7 @@ recv_open_grand_origin(zfs_handle_t *zhp)
 }
 
 static int
-recv_rename_impl(zfs_handle_t *zhp, zfs_cmd_t *zc)
+recv_rename_impl(zfs_handle_t *zhp, const char *name, const char *newname)
 {
        int err;
        zfs_handle_t *ozhp = NULL;
@@ -2304,7 +2304,7 @@ recv_rename_impl(zfs_handle_t *zhp, zfs_cmd_t *zc)
         * attempted to rename the dataset outside of its encryption root.
         * Force the dataset to become an encryption root and try again.
         */
-       err = ioctl(zhp->zfs_hdl->libzfs_fd, ZFS_IOC_RENAME, &zc);
+       err = lzc_rename(name, newname);
        if (err == EACCES) {
                ozhp = recv_open_grand_origin(zhp);
                if (ozhp == NULL) {
@@ -2317,7 +2317,7 @@ recv_rename_impl(zfs_handle_t *zhp, zfs_cmd_t *zc)
                if (err != 0)
                        goto out;
 
-               err = ioctl(zhp->zfs_hdl->libzfs_fd, ZFS_IOC_RENAME, &zc);
+               err = lzc_rename(name, newname);
        }
 
 out:
@@ -2331,7 +2331,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 = NULL;
        zfs_handle_t *zhp = NULL;
@@ -2351,19 +2350,13 @@ recv_rename(libzfs_handle_t *hdl, const char *name, const char *tryname,
        if (err)
                goto out;
 
-       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 = recv_rename_impl(zhp, &zc);
+               err = recv_rename_impl(zhp, name, newname);
                if (err == 0)
                        changelist_rename(clp, name, tryname);
        } else {
@@ -2375,13 +2368,12 @@ 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 = recv_rename_impl(zhp, &zc);
+               err = recv_rename_impl(zhp, name, newname);
                if (err == 0)
                        changelist_rename(clp, name, newname);
                if (err && flags->verbose) {
@@ -2461,7 +2453,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;
@@ -2484,17 +2475,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);
index f24581db83e080d938d99be35bf37683c8129988..1baec04a4077f7231b2fff15124996fb75f3209a 100644 (file)
@@ -316,6 +316,30 @@ 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.
  *
index 7c469246d98d66f50c1fec7b96459920cf1bef62..a71da28374729760eeeba52ae8b12bf783593786 100644 (file)
@@ -3785,7 +3785,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
@@ -3793,9 +3792,17 @@ 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, '@')) {
@@ -3917,8 +3924,11 @@ 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;
+       int err;
 
        /* "zfs rename" from and to ...%recv datasets should both fail */
        zc->zc_name[sizeof (zc->zc_name) - 1] = '\0';
@@ -3928,6 +3938,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 */
@@ -3936,7 +3952,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) {
+               if (ost == DMU_OST_ZFS) {
                        error = dmu_objset_find(zc->zc_name,
                            recursive_unmount, at + 1,
                            recursive ? DS_FIND_CHILDREN : 0);
index 3d5c7b64a20a546c73ca19e5668649e74be40246..88a18d8f0f6a288db756d6a4b03e3b0286b14562 100644 (file)
@@ -650,7 +650,6 @@ zfs_destroy(const char *dataset)
 
        (void) strlcpy(zc.zc_name, dataset, sizeof (zc.zc_name));
        zc.zc_name[sizeof (zc.zc_name) - 1] = '\0';
-       zc.zc_objset_type = DMU_OST_ZFS;
        err = ioctl(zfs_fd, ZFS_IOC_DESTROY, &zc);
 
        return (err == 0 ? 0 : errno);