]> granicus.if.org Git - zfs/commitdiff
OpenZFS 8264 - want support for promoting datasets in libzfs_core
authorGiuseppe Di Natale <dinatale2@users.noreply.github.com>
Mon, 26 Jun 2017 23:56:09 +0000 (16:56 -0700)
committerBrian Behlendorf <behlendorf1@llnl.gov>
Mon, 26 Jun 2017 23:56:09 +0000 (16:56 -0700)
Authored by: Andrew Stormont <astormont@racktopsystems.com>
Reviewed by: Andriy Gapon <avg@FreeBSD.org>
Reviewed by: Matthew Ahrens <mahrens@delphix.com>
Reviewed by: Dan McDonald <danmcd@kebe.com>
Approved by: Dan McDonald <danmcd@kebe.com>
Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov>
Ported-by: Giuseppe Di Natale <dinatale2@llnl.gov>
OpenZFS-issue: https://www.illumos.org/issues/8264
OpenZFS-commit: https://github.com/openzfs/openzfs/commit/a4b8c9a
Closes #6254

include/libzfs_core.h
lib/libzfs/libzfs_dataset.c
lib/libzfs_core/libzfs_core.c
module/zfs/zfs_ioctl.c

index f71d4b20575b72e6016a25739f950bdd9f72d611..cf7ea38370d81aed1ed17fbc02fc21a596d0a68c 100644 (file)
@@ -22,6 +22,7 @@
 /*
  * Copyright (c) 2012, 2014 by Delphix. All rights reserved.
  * Copyright (c) 2017 Datto Inc.
+ * Copyright 2017 RackTop Systems.
  */
 
 #ifndef        _LIBZFS_CORE_H
@@ -50,6 +51,7 @@ enum lzc_dataset_type {
 int lzc_snapshot(nvlist_t *, nvlist_t *, nvlist_t **);
 int lzc_create(const char *, enum lzc_dataset_type, nvlist_t *);
 int lzc_clone(const char *, const char *, nvlist_t *);
+int lzc_promote(const char *, char *, int);
 int lzc_destroy_snaps(nvlist_t *, boolean_t, nvlist_t **);
 int lzc_bookmark(nvlist_t *, nvlist_t **);
 int lzc_get_bookmarks(const char *, nvlist_t *, nvlist_t **);
index f1346b69c6f43316a46ac07328d733982643c900..bc630919a6a6870f5f908b3564dcad7a0087426f 100644 (file)
@@ -29,6 +29,7 @@
  * Copyright (c) 2013 Steven Hartland. All rights reserved.
  * Copyright 2016 Nexenta Systems, Inc.
  * Copyright 2016 Igor Kozhukhov <ikozhukhov@gmail.com>
+ * Copyright 2017 RackTop Systems.
  */
 
 #include <ctype.h>
@@ -3731,8 +3732,7 @@ int
 zfs_promote(zfs_handle_t *zhp)
 {
        libzfs_handle_t *hdl = zhp->zfs_hdl;
-       zfs_cmd_t zc = {"\0"};
-       char parent[MAXPATHLEN];
+       char snapname[ZFS_MAX_DATASET_NAME_LEN];
        int ret;
        char errbuf[1024];
 
@@ -3745,31 +3745,25 @@ zfs_promote(zfs_handle_t *zhp)
                return (zfs_error(hdl, EZFS_BADTYPE, errbuf));
        }
 
-       (void) strlcpy(parent, zhp->zfs_dmustats.dds_origin, sizeof (parent));
-       if (parent[0] == '\0') {
+       if (zhp->zfs_dmustats.dds_origin[0] == '\0') {
                zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
                    "not a cloned filesystem"));
                return (zfs_error(hdl, EZFS_BADTYPE, errbuf));
        }
 
-       (void) strlcpy(zc.zc_value, zhp->zfs_dmustats.dds_origin,
-           sizeof (zc.zc_value));
-       (void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name));
-       ret = zfs_ioctl(hdl, ZFS_IOC_PROMOTE, &zc);
+       ret = lzc_promote(zhp->zfs_name, snapname, sizeof (snapname));
 
        if (ret != 0) {
-               int save_errno = errno;
-
-               switch (save_errno) {
+               switch (ret) {
                case EEXIST:
                        /* There is a conflicting snapshot name. */
                        zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
                            "conflicting snapshot '%s' from parent '%s'"),
-                           zc.zc_string, parent);
+                           snapname, zhp->zfs_dmustats.dds_origin);
                        return (zfs_error(hdl, EZFS_EXISTS, errbuf));
 
                default:
-                       return (zfs_standard_error(hdl, save_errno, errbuf));
+                       return (zfs_standard_error(hdl, ret, errbuf));
                }
        }
        return (ret);
index 8e36d84598155228c3c2c564a3452e7e0210d999..8142f2c632a55bf040783e66c3500c5c43f508c4 100644 (file)
@@ -23,6 +23,7 @@
  * Copyright (c) 2012, 2014 by Delphix. All rights reserved.
  * Copyright (c) 2013 Steven Hartland. All rights reserved.
  * Copyright (c) 2017 Datto Inc.
+ * Copyright 2017 RackTop Systems.
  */
 
 /*
@@ -206,6 +207,28 @@ lzc_clone(const char *fsname, const char *origin,
        return (error);
 }
 
+int
+lzc_promote(const char *fsname, char *snapnamebuf, int snapnamelen)
+{
+       /*
+        * The promote ioctl is still legacy, so we need to construct our
+        * own zfs_cmd_t rather than using lzc_ioctl().
+        */
+       zfs_cmd_t zc = { "\0" };
+
+       ASSERT3S(g_refcount, >, 0);
+       VERIFY3S(g_fd, !=, -1);
+
+       (void) strlcpy(zc.zc_name, fsname, sizeof (zc.zc_name));
+       if (ioctl(g_fd, ZFS_IOC_PROMOTE, &zc) != 0) {
+               int error = errno;
+               if (error == EEXIST && snapnamebuf != NULL)
+                       (void) strlcpy(snapnamebuf, zc.zc_string, snapnamelen);
+               return (error);
+       }
+       return (0);
+}
+
 /*
  * Creates snapshots.
  *
@@ -333,7 +356,7 @@ lzc_exists(const char *dataset)
 {
        /*
         * The objset_stats ioctl is still legacy, so we need to construct our
-        * own zfs_cmd_t rather than using zfsc_ioctl().
+        * own zfs_cmd_t rather than using lzc_ioctl().
         */
        zfs_cmd_t zc = {"\0"};
 
index 4fda36c7f047a742c199064e3e397b2b2a8722aa..8cdfe31a2f7f1e087f28cf390a012d46b27a511d 100644 (file)
@@ -35,6 +35,7 @@
  * Copyright (c) 2016 Actifio, Inc. All rights reserved.
  * Copyright (c) 2017, loli10K <ezomori.nozomu@gmail.com>. All rights reserved.
  * Copyright (c) 2017 Datto Inc.
+ * Copyright 2017 RackTop Systems.
  */
 
 /*
@@ -4963,7 +4964,6 @@ zfs_ioc_pool_reopen(zfs_cmd_t *zc)
 /*
  * inputs:
  * zc_name     name of filesystem
- * zc_value    name of origin snapshot
  *
  * outputs:
  * zc_string   name of conflicting snapshot, if there is one
@@ -4971,16 +4971,49 @@ zfs_ioc_pool_reopen(zfs_cmd_t *zc)
 static int
 zfs_ioc_promote(zfs_cmd_t *zc)
 {
+       dsl_pool_t *dp;
+       dsl_dataset_t *ds, *ods;
+       char origin[ZFS_MAX_DATASET_NAME_LEN];
        char *cp;
+       int error;
+
+       error = dsl_pool_hold(zc->zc_name, FTAG, &dp);
+       if (error != 0)
+               return (error);
+
+       error = dsl_dataset_hold(dp, zc->zc_name, FTAG, &ds);
+       if (error != 0) {
+               dsl_pool_rele(dp, FTAG);
+               return (error);
+       }
+
+       if (!dsl_dir_is_clone(ds->ds_dir)) {
+               dsl_dataset_rele(ds, FTAG);
+               dsl_pool_rele(dp, FTAG);
+               return (SET_ERROR(EINVAL));
+       }
+
+       error = dsl_dataset_hold_obj(dp,
+           dsl_dir_phys(ds->ds_dir)->dd_origin_obj, FTAG, &ods);
+       if (error != 0) {
+               dsl_dataset_rele(ds, FTAG);
+               dsl_pool_rele(dp, FTAG);
+               return (error);
+       }
+
+       dsl_dataset_name(ods, origin);
+       dsl_dataset_rele(ods, FTAG);
+       dsl_dataset_rele(ds, FTAG);
+       dsl_pool_rele(dp, FTAG);
 
        /*
         * We don't need to unmount *all* the origin fs's snapshots, but
         * it's easier.
         */
-       cp = strchr(zc->zc_value, '@');
+       cp = strchr(origin, '@');
        if (cp)
                *cp = '\0';
-       (void) dmu_objset_find(zc->zc_value,
+       (void) dmu_objset_find(origin,
            zfs_unmount_snap_cb, NULL, DS_FIND_SNAPSHOTS);
        return (dsl_dataset_promote(zc->zc_name, zc->zc_string));
 }