summaryrefslogtreecommitdiff
path: root/cddl/contrib/opensolaris/lib
diff options
context:
space:
mode:
authorAndriy Gapon <avg@FreeBSD.org>2017-10-01 16:11:07 +0000
committerAndriy Gapon <avg@FreeBSD.org>2017-10-01 16:11:07 +0000
commitbda88d07d98950af3d4b808389bd6ed940e75de2 (patch)
tree23129537484d4877bf645ab1ade8ece8d4dc08c9 /cddl/contrib/opensolaris/lib
parentcfd6fd5ad186dcb66d4014e811dc7d9a4f7348bc (diff)
parentbdc44f62ffc094e160e2b416de5b8684a766b874 (diff)
Notes
Diffstat (limited to 'cddl/contrib/opensolaris/lib')
-rw-r--r--cddl/contrib/opensolaris/lib/libzfs/common/libzfs_dataset.c94
-rw-r--r--cddl/contrib/opensolaris/lib/libzfs/common/libzfs_impl.h1
-rw-r--r--cddl/contrib/opensolaris/lib/libzfs/common/libzfs_util.c4
-rw-r--r--cddl/contrib/opensolaris/lib/libzfs_core/common/libzfs_core.c63
-rw-r--r--cddl/contrib/opensolaris/lib/libzfs_core/common/libzfs_core.h5
-rw-r--r--cddl/contrib/opensolaris/lib/libzpool/common/kernel.c1
-rw-r--r--cddl/contrib/opensolaris/lib/libzpool/common/sys/zfs_context.h6
7 files changed, 164 insertions, 10 deletions
diff --git a/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_dataset.c b/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_dataset.c
index de78b5479240..e05f910a1fc9 100644
--- a/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_dataset.c
+++ b/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_dataset.c
@@ -2355,6 +2355,74 @@ zfs_get_clones_nvl(zfs_handle_t *zhp)
}
/*
+ * Accepts a property and value and checks that the value
+ * matches the one found by the channel program. If they are
+ * not equal, print both of them.
+ */
+void
+zcp_check(zfs_handle_t *zhp, zfs_prop_t prop, uint64_t intval,
+ const char *strval)
+{
+ if (!zhp->zfs_hdl->libzfs_prop_debug)
+ return;
+ int error;
+ char *poolname = zhp->zpool_hdl->zpool_name;
+ const char *program =
+ "args = ...\n"
+ "ds = args['dataset']\n"
+ "prop = args['property']\n"
+ "value, setpoint = zfs.get_prop(ds, prop)\n"
+ "return {value=value, setpoint=setpoint}\n";
+ nvlist_t *outnvl;
+ nvlist_t *retnvl;
+ nvlist_t *argnvl = fnvlist_alloc();
+
+ fnvlist_add_string(argnvl, "dataset", zhp->zfs_name);
+ fnvlist_add_string(argnvl, "property", zfs_prop_to_name(prop));
+
+ error = lzc_channel_program(poolname, program,
+ 10 * 1000 * 1000, 10 * 1024 * 1024, argnvl, &outnvl);
+
+ if (error == 0) {
+ retnvl = fnvlist_lookup_nvlist(outnvl, "return");
+ if (zfs_prop_get_type(prop) == PROP_TYPE_NUMBER) {
+ int64_t ans;
+ error = nvlist_lookup_int64(retnvl, "value", &ans);
+ if (error != 0) {
+ (void) fprintf(stderr, "zcp check error: %u\n",
+ error);
+ return;
+ }
+ if (ans != intval) {
+ (void) fprintf(stderr,
+ "%s: zfs found %lld, but zcp found %lld\n",
+ zfs_prop_to_name(prop),
+ (longlong_t)intval, (longlong_t)ans);
+ }
+ } else {
+ char *str_ans;
+ error = nvlist_lookup_string(retnvl, "value", &str_ans);
+ if (error != 0) {
+ (void) fprintf(stderr, "zcp check error: %u\n",
+ error);
+ return;
+ }
+ if (strcmp(strval, str_ans) != 0) {
+ (void) fprintf(stderr,
+ "%s: zfs found %s, but zcp found %s\n",
+ zfs_prop_to_name(prop),
+ strval, str_ans);
+ }
+ }
+ } else {
+ (void) fprintf(stderr,
+ "zcp check failed, channel program error: %u\n", error);
+ }
+ nvlist_free(argnvl);
+ nvlist_free(outnvl);
+}
+
+/*
* Retrieve a property from the given object. If 'literal' is specified, then
* numbers are left as exact values. Otherwise, numbers are converted to a
* human-readable form.
@@ -2400,6 +2468,7 @@ zfs_prop_get(zfs_handle_t *zhp, zfs_prop_t prop, char *propbuf, size_t proplen,
&t) == 0)
(void) snprintf(propbuf, proplen, "%llu", val);
}
+ zcp_check(zhp, prop, val, NULL);
break;
case ZFS_PROP_MOUNTPOINT:
@@ -2468,7 +2537,7 @@ zfs_prop_get(zfs_handle_t *zhp, zfs_prop_t prop, char *propbuf, size_t proplen,
/* 'legacy' or 'none' */
(void) strlcpy(propbuf, str, proplen);
}
-
+ zcp_check(zhp, prop, NULL, propbuf);
break;
case ZFS_PROP_ORIGIN:
@@ -2476,6 +2545,7 @@ zfs_prop_get(zfs_handle_t *zhp, zfs_prop_t prop, char *propbuf, size_t proplen,
if (str == NULL)
return (-1);
(void) strlcpy(propbuf, str, proplen);
+ zcp_check(zhp, prop, NULL, str);
break;
case ZFS_PROP_CLONES:
@@ -2490,7 +2560,6 @@ zfs_prop_get(zfs_handle_t *zhp, zfs_prop_t prop, char *propbuf, size_t proplen,
if (get_numeric_property(zhp, prop, src, &source, &val) != 0)
return (-1);
-
/*
* If quota or reservation is 0, we translate this into 'none'
* (unless literal is set), and indicate that it's the default
@@ -2509,6 +2578,7 @@ zfs_prop_get(zfs_handle_t *zhp, zfs_prop_t prop, char *propbuf, size_t proplen,
else
zfs_nicenum(val, propbuf, proplen);
}
+ zcp_check(zhp, prop, val, NULL);
break;
case ZFS_PROP_FILESYSTEM_LIMIT:
@@ -2533,6 +2603,8 @@ zfs_prop_get(zfs_handle_t *zhp, zfs_prop_t prop, char *propbuf, size_t proplen,
} else {
zfs_nicenum(val, propbuf, proplen);
}
+
+ zcp_check(zhp, prop, val, NULL);
break;
case ZFS_PROP_REFRATIO:
@@ -2542,6 +2614,7 @@ zfs_prop_get(zfs_handle_t *zhp, zfs_prop_t prop, char *propbuf, size_t proplen,
(void) snprintf(propbuf, proplen, "%llu.%02llux",
(u_longlong_t)(val / 100),
(u_longlong_t)(val % 100));
+ zcp_check(zhp, prop, val, NULL);
break;
case ZFS_PROP_TYPE:
@@ -2562,6 +2635,7 @@ zfs_prop_get(zfs_handle_t *zhp, zfs_prop_t prop, char *propbuf, size_t proplen,
abort();
}
(void) snprintf(propbuf, proplen, "%s", str);
+ zcp_check(zhp, prop, NULL, propbuf);
break;
case ZFS_PROP_MOUNTED:
@@ -2587,6 +2661,7 @@ zfs_prop_get(zfs_handle_t *zhp, zfs_prop_t prop, char *propbuf, size_t proplen,
* consumers.
*/
(void) strlcpy(propbuf, zhp->zfs_name, proplen);
+ zcp_check(zhp, prop, NULL, propbuf);
break;
case ZFS_PROP_MLSLABEL:
@@ -2640,26 +2715,33 @@ zfs_prop_get(zfs_handle_t *zhp, zfs_prop_t prop, char *propbuf, size_t proplen,
if (get_numeric_property(zhp, prop, src, &source, &val) != 0)
return (-1);
(void) snprintf(propbuf, proplen, "%llu", (u_longlong_t)val);
+ zcp_check(zhp, prop, val, NULL);
break;
default:
switch (zfs_prop_get_type(prop)) {
case PROP_TYPE_NUMBER:
if (get_numeric_property(zhp, prop, src,
- &source, &val) != 0)
+ &source, &val) != 0) {
return (-1);
- if (literal)
+ }
+
+ if (literal) {
(void) snprintf(propbuf, proplen, "%llu",
(u_longlong_t)val);
- else
+ } else {
zfs_nicenum(val, propbuf, proplen);
+ }
+ zcp_check(zhp, prop, val, NULL);
break;
case PROP_TYPE_STRING:
str = getprop_string(zhp, prop, &source);
if (str == NULL)
return (-1);
+
(void) strlcpy(propbuf, str, proplen);
+ zcp_check(zhp, prop, NULL, str);
break;
case PROP_TYPE_INDEX:
@@ -2668,7 +2750,9 @@ zfs_prop_get(zfs_handle_t *zhp, zfs_prop_t prop, char *propbuf, size_t proplen,
return (-1);
if (zfs_prop_index_to_string(prop, val, &strval) != 0)
return (-1);
+
(void) strlcpy(propbuf, strval, proplen);
+ zcp_check(zhp, prop, NULL, strval);
break;
default:
diff --git a/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_impl.h b/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_impl.h
index ded3d88237b0..c934cff70506 100644
--- a/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_impl.h
+++ b/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_impl.h
@@ -79,6 +79,7 @@ struct libzfs_handle {
libzfs_fru_t **libzfs_fru_hash;
libzfs_fru_t *libzfs_fru_list;
char libzfs_chassis_id[256];
+ boolean_t libzfs_prop_debug;
};
#define ZFSSHARE_MISS 0x01 /* Didn't find entry in cache */
diff --git a/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_util.c b/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_util.c
index a2ae8b043be2..621de6776488 100644
--- a/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_util.c
+++ b/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_util.c
@@ -678,6 +678,10 @@ libzfs_init(void)
zpool_feature_init();
libzfs_mnttab_init(hdl);
+ if (getenv("ZFS_PROP_DEBUG") != NULL) {
+ hdl->libzfs_prop_debug = B_TRUE;
+ }
+
return (hdl);
}
diff --git a/cddl/contrib/opensolaris/lib/libzfs_core/common/libzfs_core.c b/cddl/contrib/opensolaris/lib/libzfs_core/common/libzfs_core.c
index c38c8c64ee1d..d4ae7824c574 100644
--- a/cddl/contrib/opensolaris/lib/libzfs_core/common/libzfs_core.c
+++ b/cddl/contrib/opensolaris/lib/libzfs_core/common/libzfs_core.c
@@ -20,7 +20,7 @@
*/
/*
- * Copyright (c) 2012, 2014 by Delphix. All rights reserved.
+ * Copyright (c) 2012, 2016 by Delphix. All rights reserved.
* Copyright (c) 2013 Steven Hartland. All rights reserved.
* Copyright (c) 2014 Integros [integros.com]
* Copyright 2017 RackTop Systems.
@@ -174,7 +174,15 @@ lzc_ioctl(zfs_ioc_t ioc, const char *name,
}
while (ioctl(g_fd, ioc, &zc) != 0) {
- if (errno == ENOMEM && resultp != NULL) {
+ /*
+ * If ioctl exited with ENOMEM, we retry the ioctl after
+ * increasing the size of the destination nvlist.
+ *
+ * Channel programs that exit with ENOMEM probably ran over the
+ * lua memory sandbox; they should not be retried.
+ */
+ if (errno == ENOMEM && resultp != NULL &&
+ ioc != ZFS_IOC_CHANNEL_PROGRAM) {
free((void *)(uintptr_t)zc.zc_nvlist_dst);
zc.zc_nvlist_dst_size *= 2;
zc.zc_nvlist_dst = (uint64_t)(uintptr_t)
@@ -904,3 +912,54 @@ lzc_destroy_bookmarks(nvlist_t *bmarks, nvlist_t **errlist)
return (error);
}
+
+/*
+ * Executes a channel program.
+ *
+ * If this function returns 0 the channel program was successfully loaded and
+ * ran without failing. Note that individual commands the channel program ran
+ * may have failed and the channel program is responsible for reporting such
+ * errors through outnvl if they are important.
+ *
+ * This method may also return:
+ *
+ * EINVAL The program contains syntax errors, or an invalid memory or time
+ * limit was given. No part of the channel program was executed.
+ * If caused by syntax errors, 'outnvl' contains information about the
+ * errors.
+ *
+ * EDOM The program was executed, but encountered a runtime error, such as
+ * calling a function with incorrect arguments, invoking the error()
+ * function directly, failing an assert() command, etc. Some portion
+ * of the channel program may have executed and committed changes.
+ * Information about the failure can be found in 'outnvl'.
+ *
+ * ENOMEM The program fully executed, but the output buffer was not large
+ * enough to store the returned value. No output is returned through
+ * 'outnvl'.
+ *
+ * ENOSPC The program was terminated because it exceeded its memory usage
+ * limit. Some portion of the channel program may have executed and
+ * committed changes to disk. No output is returned through 'outnvl'.
+ *
+ * ETIMEDOUT The program was terminated because it exceeded its Lua instruction
+ * limit. Some portion of the channel program may have executed and
+ * committed changes to disk. No output is returned through 'outnvl'.
+ */
+int
+lzc_channel_program(const char *pool, const char *program, uint64_t instrlimit,
+ uint64_t memlimit, nvlist_t *argnvl, nvlist_t **outnvl)
+{
+ int error;
+ nvlist_t *args;
+
+ args = fnvlist_alloc();
+ fnvlist_add_string(args, ZCP_ARG_PROGRAM, program);
+ fnvlist_add_nvlist(args, ZCP_ARG_ARGLIST, argnvl);
+ fnvlist_add_uint64(args, ZCP_ARG_INSTRLIMIT, instrlimit);
+ fnvlist_add_uint64(args, ZCP_ARG_MEMLIMIT, memlimit);
+ error = lzc_ioctl(ZFS_IOC_CHANNEL_PROGRAM, pool, args, outnvl);
+ fnvlist_free(args);
+
+ return (error);
+}
diff --git a/cddl/contrib/opensolaris/lib/libzfs_core/common/libzfs_core.h b/cddl/contrib/opensolaris/lib/libzfs_core/common/libzfs_core.h
index ea0e752e3524..234dda4a194c 100644
--- a/cddl/contrib/opensolaris/lib/libzfs_core/common/libzfs_core.h
+++ b/cddl/contrib/opensolaris/lib/libzfs_core/common/libzfs_core.h
@@ -20,7 +20,7 @@
*/
/*
- * Copyright (c) 2012, 2014 by Delphix. All rights reserved.
+ * Copyright (c) 2012, 2016 by Delphix. All rights reserved.
* Copyright (c) 2013 by Martin Matuska <mm@FreeBSD.org>. All rights reserved.
* Copyright 2017 RackTop Systems.
*/
@@ -86,6 +86,9 @@ boolean_t lzc_exists(const char *);
int lzc_rollback(const char *, char *, int);
int lzc_rollback_to(const char *, const char *);
+int lzc_channel_program(const char *, const char *, uint64_t, uint64_t,
+ nvlist_t *, nvlist_t **);
+
#ifdef __cplusplus
}
#endif
diff --git a/cddl/contrib/opensolaris/lib/libzpool/common/kernel.c b/cddl/contrib/opensolaris/lib/libzpool/common/kernel.c
index ab1b839975ab..1d43c8d7253c 100644
--- a/cddl/contrib/opensolaris/lib/libzpool/common/kernel.c
+++ b/cddl/contrib/opensolaris/lib/libzpool/common/kernel.c
@@ -738,6 +738,7 @@ vpanic(const char *fmt, va_list adx)
char buf[512];
(void) vsnprintf(buf, 512, fmt, adx);
assfail(buf, NULL, 0);
+ abort(); /* necessary to make vpanic meet noreturn requirements */
}
void
diff --git a/cddl/contrib/opensolaris/lib/libzpool/common/sys/zfs_context.h b/cddl/contrib/opensolaris/lib/libzpool/common/sys/zfs_context.h
index f11174ffa521..ad1aced2769b 100644
--- a/cddl/contrib/opensolaris/lib/libzpool/common/sys/zfs_context.h
+++ b/cddl/contrib/opensolaris/lib/libzpool/common/sys/zfs_context.h
@@ -66,6 +66,7 @@ extern "C" {
#include <fsshare.h>
#include <pthread.h>
#include <sched.h>
+#include <setjmp.h>
#include <sys/debug.h>
#include <sys/note.h>
#include <sys/types.h>
@@ -126,8 +127,8 @@ extern void dprintf_setup(int *argc, char **argv);
extern void cmn_err(int, const char *, ...);
extern void vcmn_err(int, const char *, __va_list);
-extern void panic(const char *, ...);
-extern void vpanic(const char *, __va_list);
+extern void panic(const char *, ...) __NORETURN;
+extern void vpanic(const char *, __va_list) __NORETURN;
#define fm_panic panic
@@ -349,6 +350,7 @@ extern void cv_broadcast(kcondvar_t *cv);
#define KM_SLEEP UMEM_NOFAIL
#define KM_PUSHPAGE KM_SLEEP
#define KM_NOSLEEP UMEM_DEFAULT
+#define KM_NORMALPRI 0 /* not needed with UMEM_DEFAULT */
#define KMC_NODEBUG UMC_NODEBUG
#define KMC_NOTOUCH 0 /* not needed for userland caches */
#define KM_NODEBUG 0