]> git.proxmox.com Git - mirror_zfs.git/blobdiff - lib/libzfs/libzfs_dataset.c
Make createtxg and guid properties public
[mirror_zfs.git] / lib / libzfs / libzfs_dataset.c
index 3ff96f0c65eb33e95487fd1610b698104a4804d5..f1346b69c6f43316a46ac07328d733982643c900 100644 (file)
 /*
  * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
  * Copyright (c) 2013, Joyent, Inc. All rights reserved.
- * Copyright (c) 2011, 2015 by Delphix. All rights reserved.
+ * Copyright (c) 2011, 2016 by Delphix. All rights reserved.
  * Copyright (c) 2012 DEY Storage Systems, Inc.  All rights reserved.
  * Copyright (c) 2012 Pawel Jakub Dawidek <pawel@dawidek.net>.
  * Copyright (c) 2013 Martin Matuska. All rights reserved.
  * Copyright (c) 2013 Steven Hartland. All rights reserved.
- * Copyright 2013 Nexenta Systems, Inc. All rights reserved.
+ * Copyright 2016 Nexenta Systems, Inc.
+ * Copyright 2016 Igor Kozhukhov <ikozhukhov@gmail.com>
  */
 
 #include <ctype.h>
@@ -80,8 +81,12 @@ zfs_type_to_name(zfs_type_t type)
                return (dgettext(TEXT_DOMAIN, "snapshot"));
        case ZFS_TYPE_VOLUME:
                return (dgettext(TEXT_DOMAIN, "volume"));
+       case ZFS_TYPE_POOL:
+               return (dgettext(TEXT_DOMAIN, "pool"));
+       case ZFS_TYPE_BOOKMARK:
+               return (dgettext(TEXT_DOMAIN, "bookmark"));
        default:
-               break;
+               assert(!"unhandled zfs_type_t");
        }
 
        return (NULL);
@@ -100,7 +105,7 @@ zfs_validate_name(libzfs_handle_t *hdl, const char *path, int type,
        char what;
 
        (void) zfs_prop_get_table();
-       if (dataset_namecheck(path, &why, &what) != 0) {
+       if (entity_namecheck(path, &why, &what) != 0) {
                if (hdl != NULL) {
                        switch (why) {
                        case NAME_ERR_TOOLONG:
@@ -129,9 +134,10 @@ zfs_validate_name(libzfs_handle_t *hdl, const char *path, int type,
                                    "'%c' in name"), what);
                                break;
 
-                       case NAME_ERR_MULTIPLE_AT:
+                       case NAME_ERR_MULTIPLE_DELIMITERS:
                                zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
-                                   "multiple '@' delimiters in name"));
+                                   "multiple '@' and/or '#' delimiters in "
+                                   "name"));
                                break;
 
                        case NAME_ERR_NOLETTER:
@@ -148,7 +154,10 @@ zfs_validate_name(libzfs_handle_t *hdl, const char *path, int type,
                                zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
                                    "reserved disk name"));
                                break;
+
                        default:
+                               zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
+                                   "(%d) not defined"), why);
                                break;
                        }
                }
@@ -159,7 +168,7 @@ zfs_validate_name(libzfs_handle_t *hdl, const char *path, int type,
        if (!(type & ZFS_TYPE_SNAPSHOT) && strchr(path, '@') != NULL) {
                if (hdl != NULL)
                        zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
-                           "snapshot delimiter '@' in filesystem name"));
+                           "snapshot delimiter '@' is not expected here"));
                return (0);
        }
 
@@ -170,6 +179,20 @@ zfs_validate_name(libzfs_handle_t *hdl, const char *path, int type,
                return (0);
        }
 
+       if (!(type & ZFS_TYPE_BOOKMARK) && strchr(path, '#') != NULL) {
+               if (hdl != NULL)
+                       zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
+                           "bookmark delimiter '#' is not expected here"));
+               return (0);
+       }
+
+       if (type == ZFS_TYPE_BOOKMARK && strchr(path, '#') == NULL) {
+               if (hdl != NULL)
+                       zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
+                           "missing '#' delimiter in bookmark name"));
+               return (0);
+       }
+
        if (modifying && strchr(path, '%') != NULL) {
                if (hdl != NULL)
                        zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
@@ -610,8 +633,36 @@ make_bookmark_handle(zfs_handle_t *parent, const char *path,
        return (zhp);
 }
 
+struct zfs_open_bookmarks_cb_data {
+       const char *path;
+       zfs_handle_t *zhp;
+};
+
+static int
+zfs_open_bookmarks_cb(zfs_handle_t *zhp, void *data)
+{
+       struct zfs_open_bookmarks_cb_data *dp = data;
+
+       /*
+        * Is it the one we are looking for?
+        */
+       if (strcmp(dp->path, zfs_get_name(zhp)) == 0) {
+               /*
+                * We found it.  Save it and let the caller know we are done.
+                */
+               dp->zhp = zhp;
+               return (EEXIST);
+       }
+
+       /*
+        * Not found.  Close the handle and ask for another one.
+        */
+       zfs_close(zhp);
+       return (0);
+}
+
 /*
- * Opens the given snapshot, filesystem, or volume.   The 'types'
+ * Opens the given snapshot, bookmark, filesystem, or volume.   The 'types'
  * argument is a mask of acceptable types.  The function will print an
  * appropriate error message and return NULL if it can't be opened.
  */
@@ -620,6 +671,7 @@ zfs_open(libzfs_handle_t *hdl, const char *path, int types)
 {
        zfs_handle_t *zhp;
        char errbuf[1024];
+       char *bookp;
 
        (void) snprintf(errbuf, sizeof (errbuf),
            dgettext(TEXT_DOMAIN, "cannot open '%s'"), path);
@@ -627,20 +679,68 @@ zfs_open(libzfs_handle_t *hdl, const char *path, int types)
        /*
         * Validate the name before we even try to open it.
         */
-       if (!zfs_validate_name(hdl, path, ZFS_TYPE_DATASET, B_FALSE)) {
-               zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
-                   "invalid dataset name"));
+       if (!zfs_validate_name(hdl, path, types, B_FALSE)) {
                (void) zfs_error(hdl, EZFS_INVALIDNAME, errbuf);
                return (NULL);
        }
 
        /*
-        * Try to get stats for the dataset, which will tell us if it exists.
+        * Bookmarks needs to be handled separately.
         */
-       errno = 0;
-       if ((zhp = make_dataset_handle(hdl, path)) == NULL) {
-               (void) zfs_standard_error(hdl, errno, errbuf);
-               return (NULL);
+       bookp = strchr(path, '#');
+       if (bookp == NULL) {
+               /*
+                * Try to get stats for the dataset, which will tell us if it
+                * exists.
+                */
+               errno = 0;
+               if ((zhp = make_dataset_handle(hdl, path)) == NULL) {
+                       (void) zfs_standard_error(hdl, errno, errbuf);
+                       return (NULL);
+               }
+       } else {
+               char dsname[ZFS_MAX_DATASET_NAME_LEN];
+               zfs_handle_t *pzhp;
+               struct zfs_open_bookmarks_cb_data cb_data = {path, NULL};
+
+               /*
+                * We need to cut out '#' and everything after '#'
+                * to get the parent dataset name only.
+                */
+               assert(bookp - path < sizeof (dsname));
+               (void) strncpy(dsname, path, bookp - path);
+               dsname[bookp - path] = '\0';
+
+               /*
+                * Create handle for the parent dataset.
+                */
+               errno = 0;
+               if ((pzhp = make_dataset_handle(hdl, dsname)) == NULL) {
+                       (void) zfs_standard_error(hdl, errno, errbuf);
+                       return (NULL);
+               }
+
+               /*
+                * Iterate bookmarks to find the right one.
+                */
+               errno = 0;
+               if ((zfs_iter_bookmarks(pzhp, zfs_open_bookmarks_cb,
+                   &cb_data) == 0) && (cb_data.zhp == NULL)) {
+                       (void) zfs_error(hdl, EZFS_NOENT, errbuf);
+                       zfs_close(pzhp);
+                       return (NULL);
+               }
+               if (cb_data.zhp == NULL) {
+                       (void) zfs_standard_error(hdl, errno, errbuf);
+                       zfs_close(pzhp);
+                       return (NULL);
+               }
+               zhp = cb_data.zhp;
+
+               /*
+                * Cleanup.
+                */
+               zfs_close(pzhp);
        }
 
        if (!(types & zhp->zfs_type)) {
@@ -674,15 +774,13 @@ typedef struct mnttab_node {
 static int
 libzfs_mnttab_cache_compare(const void *arg1, const void *arg2)
 {
-       const mnttab_node_t *mtn1 = arg1;
-       const mnttab_node_t *mtn2 = arg2;
+       const mnttab_node_t *mtn1 = (const mnttab_node_t *)arg1;
+       const mnttab_node_t *mtn2 = (const mnttab_node_t *)arg2;
        int rv;
 
        rv = strcmp(mtn1->mtn_mt.mnt_special, mtn2->mtn_mt.mnt_special);
 
-       if (rv == 0)
-               return (0);
-       return (rv > 0 ? 1 : -1);
+       return (AVL_ISIGN(rv));
 }
 
 void
@@ -737,7 +835,8 @@ libzfs_mnttab_fini(libzfs_handle_t *hdl)
        void *cookie = NULL;
        mnttab_node_t *mtn;
 
-       while ((mtn = avl_destroy_nodes(&hdl->libzfs_mnttab_cache, &cookie))) {
+       while ((mtn = avl_destroy_nodes(&hdl->libzfs_mnttab_cache, &cookie))
+           != NULL) {
                free(mtn->mtn_mt.mnt_special);
                free(mtn->mtn_mt.mnt_mountp);
                free(mtn->mtn_mt.mnt_fstype);
@@ -815,7 +914,8 @@ libzfs_mnttab_remove(libzfs_handle_t *hdl, const char *fsname)
        mnttab_node_t *ret;
 
        find.mtn_mt.mnt_special = (char *)fsname;
-       if ((ret = avl_find(&hdl->libzfs_mnttab_cache, (void *)&find, NULL))) {
+       if ((ret = avl_find(&hdl->libzfs_mnttab_cache, (void *)&find, NULL))
+           != NULL) {
                avl_remove(&hdl->libzfs_mnttab_cache, ret);
                free(ret->mtn_mt.mnt_special);
                free(ret->mtn_mt.mnt_mountp);
@@ -946,7 +1046,9 @@ zfs_valid_proplist(libzfs_handle_t *hdl, zfs_type_t type, nvlist_t *nvl,
                        }
 
                        if (uqtype != ZFS_PROP_USERQUOTA &&
-                           uqtype != ZFS_PROP_GROUPQUOTA) {
+                           uqtype != ZFS_PROP_GROUPQUOTA &&
+                           uqtype != ZFS_PROP_USEROBJQUOTA &&
+                           uqtype != ZFS_PROP_GROUPOBJQUOTA) {
                                zfs_error_aux(hdl,
                                    dgettext(TEXT_DOMAIN, "'%s' is readonly"),
                                    propname);
@@ -1071,7 +1173,7 @@ zfs_valid_proplist(libzfs_handle_t *hdl, zfs_type_t type, nvlist_t *nvl,
                         */
                        if (intval < SPA_MINBLOCKSIZE ||
                            intval > maxbs || !ISP2(intval)) {
-                               zfs_nicenum(maxbs, buf, sizeof (buf));
+                               zfs_nicebytes(maxbs, buf, sizeof (buf));
                                zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
                                    "'%s' must be power of 2 from 512B "
                                    "to %s"), propname, buf);
@@ -1162,7 +1264,12 @@ badlabel:
                                            "component of '%s' is too long"),
                                            propname);
                                        break;
+
                                default:
+                                       zfs_error_aux(hdl,
+                                           dgettext(TEXT_DOMAIN,
+                                           "(%d) not defined"),
+                                           why);
                                        break;
                                }
                                (void) zfs_error(hdl, EZFS_BADPROP, errbuf);
@@ -1282,12 +1389,15 @@ badlabel:
                        }
 
                        break;
+
                case ZFS_PROP_UTF8ONLY:
                        chosen_utf = (int)intval;
                        break;
+
                case ZFS_PROP_NORMALIZE:
                        chosen_normal = (int)intval;
                        break;
+
                default:
                        break;
                }
@@ -1318,7 +1428,7 @@ badlabel:
 
                        case ZFS_PROP_VOLSIZE:
                                if (intval % blocksize != 0) {
-                                       zfs_nicenum(blocksize, buf,
+                                       zfs_nicebytes(blocksize, buf,
                                            sizeof (buf));
                                        zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
                                            "'%s' must be a multiple of "
@@ -1338,6 +1448,7 @@ badlabel:
                                        goto error;
                                }
                                break;
+
                        default:
                                break;
                        }
@@ -1479,6 +1590,12 @@ zfs_setprop_error(libzfs_handle_t *hdl, zfs_prop_t prop, int err,
                            "property setting is not allowed on "
                            "bootable datasets"));
                        (void) zfs_error(hdl, EZFS_NOTSUP, errbuf);
+               } else if (prop == ZFS_PROP_CHECKSUM ||
+                   prop == ZFS_PROP_DEDUP) {
+                       (void) zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
+                           "property setting is not allowed on "
+                           "root pools"));
+                       (void) zfs_error(hdl, EZFS_NOTSUP, errbuf);
                } else {
                        (void) zfs_standard_error(hdl, err, errbuf);
                }
@@ -1572,7 +1689,7 @@ zfs_prop_set_list(zfs_handle_t *zhp, nvlist_t *props)
        char errbuf[1024];
        libzfs_handle_t *hdl = zhp->zfs_hdl;
        nvlist_t *nvl;
-       int nvl_len;
+       int nvl_len = 0;
        int added_resv = 0;
        zfs_prop_t prop = 0;
        nvpair_t *elem;
@@ -1602,7 +1719,6 @@ zfs_prop_set_list(zfs_handle_t *zhp, nvlist_t *props)
         * Check how many properties we're setting and allocate an array to
         * store changelist pointers for postfix().
         */
-       nvl_len = 0;
        for (elem = nvlist_next_nvpair(nvl, NULL);
            elem != NULL;
            elem = nvlist_next_nvpair(nvl, elem))
@@ -1623,8 +1739,9 @@ zfs_prop_set_list(zfs_handle_t *zhp, nvlist_t *props)
                 * its canmount property to 'on' or 'noauto'.  We only use
                 * the changelist logic to unmount when setting canmount=off.
                 */
-               if (!(prop == ZFS_PROP_CANMOUNT &&
-                   fnvpair_value_uint64(elem) != ZFS_CANMOUNT_OFF)) {
+               if (prop != ZFS_PROP_CANMOUNT ||
+                   (fnvpair_value_uint64(elem) == ZFS_CANMOUNT_OFF &&
+                   zfs_is_mounted(zhp, NULL))) {
                        cls[cl_idx] = changelist_gather(zhp, prop, 0, 0);
                        if (cls[cl_idx] == NULL)
                                goto error;
@@ -1911,9 +2028,9 @@ zfs_unset_recvd_props_mode(zfs_handle_t *zhp, uint64_t *cookie)
  * zfs_prop_get_int() are built using this interface.
  *
  * Certain properties can be overridden using 'mount -o'.  In this case, scan
- * the contents of the /etc/mtab entry, searching for the appropriate options.
- * If they differ from the on-disk values, report the current values and mark
- * the source "temporary".
+ * the contents of the /proc/self/mounts entry, searching for the
+ * appropriate options. If they differ from the on-disk values, report the
+ * current values and mark the source "temporary".
  */
 static int
 get_numeric_property(zfs_handle_t *zhp, zfs_prop_t prop, zprop_source_t *src,
@@ -1933,9 +2050,9 @@ get_numeric_property(zfs_handle_t *zhp, zfs_prop_t prop, zprop_source_t *src,
         * the property is valid for the snapshot's head dataset type.
         */
        if (zhp->zfs_type == ZFS_TYPE_SNAPSHOT &&
-               !zfs_prop_valid_for_type(prop, zhp->zfs_head_type, B_TRUE)) {
-                       *val = zfs_prop_default_numeric(prop);
-                       return (-1);
+           !zfs_prop_valid_for_type(prop, zhp->zfs_head_type, B_TRUE)) {
+               *val = zfs_prop_default_numeric(prop);
+               return (-1);
        }
 
        switch (prop) {
@@ -1978,14 +2095,16 @@ get_numeric_property(zfs_handle_t *zhp, zfs_prop_t prop, zprop_source_t *src,
                mntopt_on = MNTOPT_NBMAND;
                mntopt_off = MNTOPT_NONBMAND;
                break;
+
        default:
                break;
        }
 
        /*
         * Because looking up the mount options is potentially expensive
-        * (iterating over all of /etc/mtab), we defer its calculation until
-        * we're looking up a property which requires its presence.
+        * (iterating over all of /proc/self/mounts), we defer its
+        * calculation until we're looking up a property which requires
+        * its presence.
         */
        if (!zhp->zfs_mntcheck &&
            (mntopt_on != NULL || prop == ZFS_PROP_MOUNTED)) {
@@ -2094,11 +2213,15 @@ get_numeric_property(zfs_handle_t *zhp, zfs_prop_t prop, zprop_source_t *src,
                        /*
                         * If we tried to use a default value for a
                         * readonly property, it means that it was not
-                        * present.
+                        * present.  Note this only applies to "truly"
+                        * readonly properties, not set-once properties
+                        * like volblocksize.
                         */
                        if (zfs_prop_readonly(prop) &&
+                           !zfs_prop_setonce(prop) &&
                            *source != NULL && (*source)[0] == '\0') {
                                *source = NULL;
+                               return (-1);
                        }
                        break;
 
@@ -2264,6 +2387,11 @@ zfs_get_clones_nvl(zfs_handle_t *zhp)
                        (void) strsep(&cp, "/@");
                        root = zfs_open(zhp->zfs_hdl, pool,
                            ZFS_TYPE_FILESYSTEM);
+                       if (root == NULL) {
+                               nvlist_free(nv);
+                               nvlist_free(value);
+                               return (NULL);
+                       }
 
                        (void) get_clones_cb(root, &gca);
                }
@@ -2332,7 +2460,7 @@ zfs_prop_get(zfs_handle_t *zhp, zfs_prop_t prop, char *propbuf, size_t proplen,
                            strftime(propbuf, proplen, "%a %b %e %k:%M %Y",
                            &t) == 0)
                                (void) snprintf(propbuf, proplen, "%llu",
-                                   (u_longlong_t) val);
+                                   (u_longlong_t)val);
                }
                break;
 
@@ -2441,7 +2569,7 @@ zfs_prop_get(zfs_handle_t *zhp, zfs_prop_t prop, char *propbuf, size_t proplen,
                                (void) snprintf(propbuf, proplen, "%llu",
                                    (u_longlong_t)val);
                        else
-                               zfs_nicenum(val, propbuf, proplen);
+                               zfs_nicebytes(val, propbuf, proplen);
                }
                break;
 
@@ -2567,6 +2695,7 @@ zfs_prop_get(zfs_handle_t *zhp, zfs_prop_t prop, char *propbuf, size_t proplen,
                break;
 
        case ZFS_PROP_GUID:
+       case ZFS_PROP_CREATETXG:
                /*
                 * GUIDs are stored as numbers, but they are identifiers.
                 * We don't want them to be pretty printed, because pretty
@@ -2577,6 +2706,22 @@ zfs_prop_get(zfs_handle_t *zhp, zfs_prop_t prop, char *propbuf, size_t proplen,
                (void) snprintf(propbuf, proplen, "%llu", (u_longlong_t)val);
                break;
 
+       case ZFS_PROP_REFERENCED:
+       case ZFS_PROP_AVAILABLE:
+       case ZFS_PROP_USED:
+       case ZFS_PROP_USEDSNAP:
+       case ZFS_PROP_USEDDS:
+       case ZFS_PROP_USEDREFRESERV:
+       case ZFS_PROP_USEDCHILD:
+               if (get_numeric_property(zhp, prop, src, &source, &val) != 0)
+                       return (-1);
+               if (literal)
+                       (void) snprintf(propbuf, proplen, "%llu",
+                           (u_longlong_t)val);
+               else
+                       zfs_nicebytes(val, propbuf, proplen);
+               break;
+
        default:
                switch (zfs_prop_get_type(prop)) {
                case PROP_TYPE_NUMBER:
@@ -2625,7 +2770,7 @@ uint64_t
 zfs_prop_get_int(zfs_handle_t *zhp, zfs_prop_t prop)
 {
        char *source;
-       uint64_t val;
+       uint64_t val = 0;
 
        (void) get_numeric_property(zhp, prop, NULL, &source, &val);
 
@@ -2732,8 +2877,12 @@ userquota_propname_decode(const char *propname, boolean_t zoned,
                return (EINVAL);
        *typep = type;
 
-       isuser = (type == ZFS_PROP_USERQUOTA || type == ZFS_PROP_USERUSED);
-       isgroup = (type == ZFS_PROP_GROUPQUOTA || type == ZFS_PROP_GROUPUSED);
+       isuser = (type == ZFS_PROP_USERQUOTA || type == ZFS_PROP_USERUSED ||
+           type == ZFS_PROP_USEROBJQUOTA ||
+           type == ZFS_PROP_USEROBJUSED);
+       isgroup = (type == ZFS_PROP_GROUPQUOTA || type == ZFS_PROP_GROUPUSED ||
+           type == ZFS_PROP_GROUPOBJQUOTA ||
+           type == ZFS_PROP_GROUPOBJUSED);
 
        cp = strchr(propname, '@') + 1;
 
@@ -2866,8 +3015,12 @@ zfs_prop_get_userquota(zfs_handle_t *zhp, const char *propname,
                (void) snprintf(propbuf, proplen, "%llu",
                    (u_longlong_t)propvalue);
        } else if (propvalue == 0 &&
-           (type == ZFS_PROP_USERQUOTA || type == ZFS_PROP_GROUPQUOTA)) {
+           (type == ZFS_PROP_USERQUOTA || type == ZFS_PROP_GROUPQUOTA ||
+           type == ZFS_PROP_USEROBJQUOTA || type == ZFS_PROP_GROUPOBJQUOTA)) {
                (void) strlcpy(propbuf, "none", proplen);
+       } else if (type == ZFS_PROP_USERQUOTA || type == ZFS_PROP_GROUPQUOTA ||
+           type == ZFS_PROP_USERUSED || type == ZFS_PROP_GROUPUSED) {
+               zfs_nicebytes(propvalue, propbuf, proplen);
        } else {
                zfs_nicenum(propvalue, propbuf, proplen);
        }
@@ -2924,7 +3077,7 @@ zfs_prop_get_written(zfs_handle_t *zhp, const char *propname,
                (void) snprintf(propbuf, proplen, "%llu",
                    (u_longlong_t)propvalue);
        } else {
-               zfs_nicenum(propvalue, propbuf, proplen);
+               zfs_nicebytes(propvalue, propbuf, proplen);
        }
 
        return (0);
@@ -2939,6 +3092,15 @@ zfs_get_name(const zfs_handle_t *zhp)
        return (zhp->zfs_name);
 }
 
+/*
+ * Returns the name of the parent pool for the given zfs handle.
+ */
+const char *
+zfs_get_pool_name(const zfs_handle_t *zhp)
+{
+       return (zhp->zpool_hdl->zpool_name);
+}
+
 /*
  * Returns the type of the given zfs handle.
  */
@@ -3129,7 +3291,7 @@ create_parents(libzfs_handle_t *hdl, char *target, int prefixlen)
         * up to the prefixlen-long one.
         */
        for (cp = target + prefixlen + 1;
-           (cp = strchr(cp, '/')); *cp = '/', cp++) {
+           (cp = strchr(cp, '/')) != NULL; *cp = '/', cp++) {
 
                *cp = '\0';
 
@@ -3208,7 +3370,8 @@ zfs_create(libzfs_handle_t *hdl, const char *path, zfs_type_t type,
        uint64_t blocksize = zfs_prop_default_numeric(ZFS_PROP_VOLBLOCKSIZE);
        char errbuf[1024];
        uint64_t zoned;
-       dmu_objset_type_t ost;
+       enum lzc_dataset_type ost;
+       zpool_handle_t *zpool_handle;
 
        (void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN,
            "cannot create '%s'"), path);
@@ -3235,9 +3398,9 @@ zfs_create(libzfs_handle_t *hdl, const char *path, zfs_type_t type,
        }
 
        if (type == ZFS_TYPE_VOLUME)
-               ost = DMU_OST_ZVOL;
+               ost = LZC_DATSET_TYPE_ZVOL;
        else
-               ost = DMU_OST_ZFS;
+               ost = LZC_DATSET_TYPE_ZFS;
 
        /* open zpool handle for prop validation */
        char pool_path[ZFS_MAX_DATASET_NAME_LEN];
@@ -3248,7 +3411,8 @@ zfs_create(libzfs_handle_t *hdl, const char *path, zfs_type_t type,
        if (p != NULL)
                *p = '\0';
 
-       zpool_handle_t *zpool_handle = zpool_open(hdl, pool_path);
+       if ((zpool_handle = zpool_open(hdl, pool_path)) == NULL)
+               return (-1);
 
        if (props && (props = zfs_valid_proplist(hdl, type, props,
            zoned, NULL, zpool_handle, errbuf)) == 0) {
@@ -3647,6 +3811,8 @@ zfs_snapshot_nvl(libzfs_handle_t *hdl, nvlist_t *snaps, nvlist_t *props)
        char errbuf[1024];
        nvpair_t *elem;
        nvlist_t *errors;
+       zpool_handle_t *zpool_hdl;
+       char pool[ZFS_MAX_DATASET_NAME_LEN];
 
        (void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN,
            "cannot create snapshots "));
@@ -3669,11 +3835,12 @@ zfs_snapshot_nvl(libzfs_handle_t *hdl, nvlist_t *snaps, nvlist_t *props)
         * get pool handle for prop validation. assumes all snaps are in the
         * same pool, as does lzc_snapshot (below).
         */
-       char pool[ZFS_MAX_DATASET_NAME_LEN];
        elem = nvlist_next_nvpair(snaps, NULL);
        (void) strlcpy(pool, nvpair_name(elem), sizeof (pool));
        pool[strcspn(pool, "/@")] = '\0';
-       zpool_handle_t *zpool_hdl = zpool_open(hdl, pool);
+       zpool_hdl = zpool_open(hdl, pool);
+       if (zpool_hdl == NULL)
+               return (-1);
 
        if (props != NULL &&
            (props = zfs_valid_proplist(hdl, ZFS_TYPE_SNAPSHOT,
@@ -3896,7 +4063,7 @@ int
 zfs_rename(zfs_handle_t *zhp, const char *target, boolean_t recursive,
     boolean_t force_unmount)
 {
-       int ret;
+       int ret = 0;
        zfs_cmd_t zc = {"\0"};
        char *delim;
        prop_changelist_t *cl = NULL;
@@ -4324,6 +4491,13 @@ zfs_userspace(zfs_handle_t *zhp, zfs_userquota_prop_t type,
                if (zfs_ioctl(hdl, ZFS_IOC_USERSPACE_MANY, &zc) != 0) {
                        char errbuf[1024];
 
+                       if ((errno == ENOTSUP &&
+                           (type == ZFS_PROP_USEROBJUSED ||
+                           type == ZFS_PROP_GROUPOBJUSED ||
+                           type == ZFS_PROP_USEROBJQUOTA ||
+                           type == ZFS_PROP_GROUPOBJQUOTA)))
+                               break;
+
                        (void) snprintf(errbuf, sizeof (errbuf),
                            dgettext(TEXT_DOMAIN,
                            "cannot get used/quota for %s"), zc.zc_name);