]> granicus.if.org Git - zfs/blobdiff - lib/libzfs/libzfs_util.c
OpenZFS 9166 - zfs storage pool checkpoint
[zfs] / lib / libzfs / libzfs_util.c
index c281f9eb3239cdf35efc150bc0b14e672d270fa6..a19b34415dbd81cd3febea95ad8859b6c26f192a 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, 2014 by Delphix. All rights reserved.
+ * Copyright (c) 2018, Joyent, Inc. All rights reserved.
+ * Copyright (c) 2011, 2017 by Delphix. All rights reserved.
  * Copyright 2016 Igor Kozhukhov <ikozhukhov@gmail.com>
+ * Copyright (c) 2017 Datto Inc.
  */
 
 /*
@@ -246,6 +247,9 @@ libzfs_error_description(libzfs_handle_t *hdl)
        case EZFS_POSTSPLIT_ONLINE:
                return (dgettext(TEXT_DOMAIN, "disk was split from this pool "
                    "into a new one"));
+       case EZFS_SCRUB_PAUSED:
+               return (dgettext(TEXT_DOMAIN, "scrub is paused; "
+                   "use 'zpool scrub' to resume"));
        case EZFS_SCRUBBING:
                return (dgettext(TEXT_DOMAIN, "currently scrubbing; "
                    "use 'zpool scrub -s' to cancel current scrub"));
@@ -257,6 +261,25 @@ libzfs_error_description(libzfs_handle_t *hdl)
                return (dgettext(TEXT_DOMAIN, "invalid diff data"));
        case EZFS_POOLREADONLY:
                return (dgettext(TEXT_DOMAIN, "pool is read-only"));
+       case EZFS_NO_PENDING:
+               return (dgettext(TEXT_DOMAIN, "operation is not "
+                   "in progress"));
+       case EZFS_CHECKPOINT_EXISTS:
+               return (dgettext(TEXT_DOMAIN, "checkpoint exists"));
+       case EZFS_DISCARDING_CHECKPOINT:
+               return (dgettext(TEXT_DOMAIN, "currently discarding "
+                   "checkpoint"));
+       case EZFS_NO_CHECKPOINT:
+               return (dgettext(TEXT_DOMAIN, "checkpoint does not exist"));
+       case EZFS_DEVRM_IN_PROGRESS:
+               return (dgettext(TEXT_DOMAIN, "device removal in progress"));
+       case EZFS_VDEV_TOO_BIG:
+               return (dgettext(TEXT_DOMAIN, "device exceeds supported size"));
+       case EZFS_ACTIVE_POOL:
+               return (dgettext(TEXT_DOMAIN, "pool is imported on a "
+                   "different host"));
+       case EZFS_CRYPTOFAILED:
+               return (dgettext(TEXT_DOMAIN, "encryption failure"));
        case EZFS_UNKNOWN:
                return (dgettext(TEXT_DOMAIN, "unknown error"));
        default:
@@ -419,6 +442,9 @@ zfs_standard_error_fmt(libzfs_handle_t *hdl, int error, const char *fmt, ...)
                    "pool I/O is currently suspended"));
                zfs_verror(hdl, EZFS_POOLUNAVAIL, fmt, ap);
                break;
+       case EREMOTEIO:
+               zfs_verror(hdl, EZFS_ACTIVE_POOL, fmt, ap);
+               break;
        default:
                zfs_error_aux(hdl, strerror(error));
                zfs_verror(hdl, EZFS_UNKNOWN, fmt, ap);
@@ -470,6 +496,11 @@ zpool_standard_error_fmt(libzfs_handle_t *hdl, int error, const char *fmt, ...)
                zfs_verror(hdl, EZFS_BUSY, fmt, ap);
                break;
 
+       /* There is no pending operation to cancel */
+       case ENOTACTIVE:
+               zfs_verror(hdl, EZFS_NO_PENDING, fmt, ap);
+               break;
+
        case ENXIO:
                zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
                    "one or more devices is currently unavailable"));
@@ -507,7 +538,24 @@ zpool_standard_error_fmt(libzfs_handle_t *hdl, int error, const char *fmt, ...)
                    "block size out of range or does not match"));
                zfs_verror(hdl, EZFS_BADPROP, fmt, ap);
                break;
-
+       case EREMOTEIO:
+               zfs_verror(hdl, EZFS_ACTIVE_POOL, fmt, ap);
+               break;
+       case ZFS_ERR_CHECKPOINT_EXISTS:
+               zfs_verror(hdl, EZFS_CHECKPOINT_EXISTS, fmt, ap);
+               break;
+       case ZFS_ERR_DISCARDING_CHECKPOINT:
+               zfs_verror(hdl, EZFS_DISCARDING_CHECKPOINT, fmt, ap);
+               break;
+       case ZFS_ERR_NO_CHECKPOINT:
+               zfs_verror(hdl, EZFS_NO_CHECKPOINT, fmt, ap);
+               break;
+       case ZFS_ERR_DEVRM_IN_PROGRESS:
+               zfs_verror(hdl, EZFS_DEVRM_IN_PROGRESS, fmt, ap);
+               break;
+       case ZFS_ERR_VDEV_TOO_BIG:
+               zfs_verror(hdl, EZFS_VDEV_TOO_BIG, fmt, ap);
+               break;
        default:
                zfs_error_aux(hdl, strerror(error));
                zfs_verror(hdl, EZFS_UNKNOWN, fmt, ap);
@@ -623,9 +671,14 @@ zfs_nicenum_format(uint64_t num, char *buf, size_t buflen,
        if (format == ZFS_NICENUM_RAW) {
                snprintf(buf, buflen, "%llu", (u_longlong_t)num);
                return;
+       } else if (format == ZFS_NICENUM_RAWTIME && num > 0) {
+               snprintf(buf, buflen, "%llu", (u_longlong_t)num);
+               return;
+       } else if (format == ZFS_NICENUM_RAWTIME && num == 0) {
+               snprintf(buf, buflen, "%s", "-");
+               return;
        }
 
-
        while (n >= k_unit[format] && index < units_len[format]) {
                n /= k_unit[format];
                index++;
@@ -633,7 +686,7 @@ zfs_nicenum_format(uint64_t num, char *buf, size_t buflen,
 
        u = units[format][index];
 
-       /* Don't print 0ns times */
+       /* Don't print zero latencies since they're invalid */
        if ((format == ZFS_NICENUM_TIME) && (num == 0)) {
                (void) snprintf(buf, buflen, "-");
        } else if ((index == 0) || ((num %
@@ -945,13 +998,14 @@ libzfs_load_module(const char *module)
                                load = 0;
                }
 
-               if (load && libzfs_run_process("/sbin/modprobe", argv, 0))
-                       return (ENOEXEC);
-       }
+               if (load) {
+                       if (libzfs_run_process("/sbin/modprobe", argv, 0))
+                               return (ENOEXEC);
 
-       /* Module loading is synchronous it must be available */
-       if (!libzfs_module_loaded(module))
-               return (ENXIO);
+                       if (!libzfs_module_loaded(module))
+                               return (ENXIO);
+               }
+       }
 
        /*
         * Device creation by udev is asynchronous and waiting may be
@@ -1033,6 +1087,10 @@ libzfs_init(void)
        libzfs_mnttab_init(hdl);
        fletcher_4_init();
 
+       if (getenv("ZFS_PROP_DEBUG") != NULL) {
+               hdl->libzfs_prop_debug = B_TRUE;
+       }
+
        return (hdl);
 }
 
@@ -1050,7 +1108,6 @@ libzfs_fini(libzfs_handle_t *hdl)
                (void) fclose(hdl->libzfs_sharetab);
        zfs_uninit_libshare(hdl);
        zpool_free_handles(hdl);
-       libzfs_fru_clear(hdl, B_TRUE);
        namespace_clear(hdl);
        libzfs_mnttab_fini(hdl);
        libzfs_core_fini();
@@ -1782,6 +1839,7 @@ zprop_parse_value(libzfs_handle_t *hdl, nvpair_t *elem, int prop,
        const char *propname;
        char *value;
        boolean_t isnone = B_FALSE;
+       boolean_t isauto = B_FALSE;
        int err = 0;
 
        if (type == ZFS_TYPE_POOL) {
@@ -1823,8 +1881,9 @@ zprop_parse_value(libzfs_handle_t *hdl, nvpair_t *elem, int prop,
                        (void) nvpair_value_string(elem, &value);
                        if (strcmp(value, "none") == 0) {
                                isnone = B_TRUE;
-                       } else if (zfs_nicestrtonum(hdl, value, ivalp)
-                           != 0) {
+                       } else if (strcmp(value, "auto") == 0) {
+                               isauto = B_TRUE;
+                       } else if (zfs_nicestrtonum(hdl, value, ivalp) != 0) {
                                goto error;
                        }
                } else if (datatype == DATA_TYPE_UINT64) {
@@ -1854,6 +1913,31 @@ zprop_parse_value(libzfs_handle_t *hdl, nvpair_t *elem, int prop,
                    prop == ZFS_PROP_SNAPSHOT_LIMIT)) {
                        *ivalp = UINT64_MAX;
                }
+
+               /*
+                * Special handling for setting 'refreservation' to 'auto'.  Use
+                * UINT64_MAX to tell the caller to use zfs_fix_auto_resv().
+                * 'auto' is only allowed on volumes.
+                */
+               if (isauto) {
+                       switch (prop) {
+                       case ZFS_PROP_REFRESERVATION:
+                               if ((type & ZFS_TYPE_VOLUME) == 0) {
+                                       zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
+                                           "'%s=auto' only allowed on "
+                                           "volumes"), nvpair_name(elem));
+                                       goto error;
+                               }
+                               *ivalp = UINT64_MAX;
+                               break;
+                       default:
+                               zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
+                                   "'auto' is invalid value for '%s'"),
+                                   nvpair_name(elem));
+                               goto error;
+                       }
+               }
+
                break;
 
        case PROP_TYPE_INDEX: