[Midnightbsd-cvs] src [10229] trunk/cddl/contrib/opensolaris/lib/pyzfs/common/ioctl.c: sync with freebsd
laffer1 at midnightbsd.org
laffer1 at midnightbsd.org
Sat Jun 2 12:07:31 EDT 2018
Revision: 10229
http://svnweb.midnightbsd.org/src/?rev=10229
Author: laffer1
Date: 2018-06-02 12:07:30 -0400 (Sat, 02 Jun 2018)
Log Message:
-----------
sync with freebsd
Modified Paths:
--------------
trunk/cddl/contrib/opensolaris/common/avl/avl.c
trunk/cddl/contrib/opensolaris/common/ctf/ctf_create.c
trunk/cddl/contrib/opensolaris/common/ctf/ctf_decl.c
trunk/cddl/contrib/opensolaris/common/ctf/ctf_error.c
trunk/cddl/contrib/opensolaris/common/ctf/ctf_hash.c
trunk/cddl/contrib/opensolaris/common/ctf/ctf_impl.h
trunk/cddl/contrib/opensolaris/common/ctf/ctf_labels.c
trunk/cddl/contrib/opensolaris/common/ctf/ctf_lookup.c
trunk/cddl/contrib/opensolaris/common/ctf/ctf_open.c
trunk/cddl/contrib/opensolaris/common/ctf/ctf_types.c
trunk/cddl/contrib/opensolaris/common/ctf/ctf_util.c
trunk/cddl/contrib/opensolaris/head/assert.h
trunk/cddl/contrib/opensolaris/head/atomic.h
trunk/cddl/contrib/opensolaris/head/libintl.h
trunk/cddl/contrib/opensolaris/head/nlist.h
trunk/cddl/contrib/opensolaris/head/note.h
trunk/cddl/contrib/opensolaris/head/stdio_ext.h
trunk/cddl/contrib/opensolaris/head/storclass.h
trunk/cddl/contrib/opensolaris/head/syms.h
trunk/cddl/contrib/opensolaris/head/synch.h
trunk/cddl/contrib/opensolaris/head/thread.h
trunk/cddl/contrib/opensolaris/lib/libctf/common/ctf_lib.c
trunk/cddl/contrib/opensolaris/lib/libctf/common/ctf_subr.c
trunk/cddl/contrib/opensolaris/lib/libctf/common/libctf.h
trunk/cddl/contrib/opensolaris/lib/libdtrace/common/drti.c
trunk/cddl/contrib/opensolaris/lib/libdtrace/common/dt_aggregate.c
trunk/cddl/contrib/opensolaris/lib/libdtrace/common/dt_as.c
trunk/cddl/contrib/opensolaris/lib/libdtrace/common/dt_as.h
trunk/cddl/contrib/opensolaris/lib/libdtrace/common/dt_buf.c
trunk/cddl/contrib/opensolaris/lib/libdtrace/common/dt_buf.h
trunk/cddl/contrib/opensolaris/lib/libdtrace/common/dt_cc.c
trunk/cddl/contrib/opensolaris/lib/libdtrace/common/dt_cg.c
trunk/cddl/contrib/opensolaris/lib/libdtrace/common/dt_consume.c
trunk/cddl/contrib/opensolaris/lib/libdtrace/common/dt_decl.c
trunk/cddl/contrib/opensolaris/lib/libdtrace/common/dt_decl.h
trunk/cddl/contrib/opensolaris/lib/libdtrace/common/dt_dis.c
trunk/cddl/contrib/opensolaris/lib/libdtrace/common/dt_dof.c
trunk/cddl/contrib/opensolaris/lib/libdtrace/common/dt_dof.h
trunk/cddl/contrib/opensolaris/lib/libdtrace/common/dt_error.c
trunk/cddl/contrib/opensolaris/lib/libdtrace/common/dt_errtags.h
trunk/cddl/contrib/opensolaris/lib/libdtrace/common/dt_grammar.y
trunk/cddl/contrib/opensolaris/lib/libdtrace/common/dt_handle.c
trunk/cddl/contrib/opensolaris/lib/libdtrace/common/dt_ident.c
trunk/cddl/contrib/opensolaris/lib/libdtrace/common/dt_ident.h
trunk/cddl/contrib/opensolaris/lib/libdtrace/common/dt_impl.h
trunk/cddl/contrib/opensolaris/lib/libdtrace/common/dt_inttab.c
trunk/cddl/contrib/opensolaris/lib/libdtrace/common/dt_inttab.h
trunk/cddl/contrib/opensolaris/lib/libdtrace/common/dt_lex.l
trunk/cddl/contrib/opensolaris/lib/libdtrace/common/dt_link.c
trunk/cddl/contrib/opensolaris/lib/libdtrace/common/dt_list.c
trunk/cddl/contrib/opensolaris/lib/libdtrace/common/dt_list.h
trunk/cddl/contrib/opensolaris/lib/libdtrace/common/dt_map.c
trunk/cddl/contrib/opensolaris/lib/libdtrace/common/dt_module.c
trunk/cddl/contrib/opensolaris/lib/libdtrace/common/dt_module.h
trunk/cddl/contrib/opensolaris/lib/libdtrace/common/dt_open.c
trunk/cddl/contrib/opensolaris/lib/libdtrace/common/dt_options.c
trunk/cddl/contrib/opensolaris/lib/libdtrace/common/dt_parser.c
trunk/cddl/contrib/opensolaris/lib/libdtrace/common/dt_parser.h
trunk/cddl/contrib/opensolaris/lib/libdtrace/common/dt_pcb.c
trunk/cddl/contrib/opensolaris/lib/libdtrace/common/dt_pcb.h
trunk/cddl/contrib/opensolaris/lib/libdtrace/common/dt_pid.c
trunk/cddl/contrib/opensolaris/lib/libdtrace/common/dt_pid.h
trunk/cddl/contrib/opensolaris/lib/libdtrace/common/dt_pragma.c
trunk/cddl/contrib/opensolaris/lib/libdtrace/common/dt_print.c
trunk/cddl/contrib/opensolaris/lib/libdtrace/common/dt_printf.c
trunk/cddl/contrib/opensolaris/lib/libdtrace/common/dt_printf.h
trunk/cddl/contrib/opensolaris/lib/libdtrace/common/dt_proc.c
trunk/cddl/contrib/opensolaris/lib/libdtrace/common/dt_proc.h
trunk/cddl/contrib/opensolaris/lib/libdtrace/common/dt_program.c
trunk/cddl/contrib/opensolaris/lib/libdtrace/common/dt_program.h
trunk/cddl/contrib/opensolaris/lib/libdtrace/common/dt_provider.c
trunk/cddl/contrib/opensolaris/lib/libdtrace/common/dt_provider.h
trunk/cddl/contrib/opensolaris/lib/libdtrace/common/dt_regset.c
trunk/cddl/contrib/opensolaris/lib/libdtrace/common/dt_regset.h
trunk/cddl/contrib/opensolaris/lib/libdtrace/common/dt_string.c
trunk/cddl/contrib/opensolaris/lib/libdtrace/common/dt_string.h
trunk/cddl/contrib/opensolaris/lib/libdtrace/common/dt_strtab.c
trunk/cddl/contrib/opensolaris/lib/libdtrace/common/dt_strtab.h
trunk/cddl/contrib/opensolaris/lib/libdtrace/common/dt_subr.c
trunk/cddl/contrib/opensolaris/lib/libdtrace/common/dt_work.c
trunk/cddl/contrib/opensolaris/lib/libdtrace/common/dt_xlator.c
trunk/cddl/contrib/opensolaris/lib/libdtrace/common/dt_xlator.h
trunk/cddl/contrib/opensolaris/lib/libdtrace/common/dtrace.h
trunk/cddl/contrib/opensolaris/lib/libdtrace/i386/dt_isadep.c
trunk/cddl/contrib/opensolaris/lib/libdtrace/sparc/dt_isadep.c
trunk/cddl/contrib/opensolaris/lib/libgen/common/gmatch.c
trunk/cddl/contrib/opensolaris/lib/libnvpair/libnvpair.c
trunk/cddl/contrib/opensolaris/lib/libnvpair/libnvpair.h
trunk/cddl/contrib/opensolaris/lib/libnvpair/nvpair_alloc_system.c
trunk/cddl/contrib/opensolaris/lib/libuutil/common/libuutil.h
trunk/cddl/contrib/opensolaris/lib/libuutil/common/libuutil_common.h
trunk/cddl/contrib/opensolaris/lib/libuutil/common/libuutil_impl.h
trunk/cddl/contrib/opensolaris/lib/libuutil/common/uu_alloc.c
trunk/cddl/contrib/opensolaris/lib/libuutil/common/uu_avl.c
trunk/cddl/contrib/opensolaris/lib/libuutil/common/uu_dprintf.c
trunk/cddl/contrib/opensolaris/lib/libuutil/common/uu_ident.c
trunk/cddl/contrib/opensolaris/lib/libuutil/common/uu_list.c
trunk/cddl/contrib/opensolaris/lib/libuutil/common/uu_misc.c
trunk/cddl/contrib/opensolaris/lib/libuutil/common/uu_open.c
trunk/cddl/contrib/opensolaris/lib/libuutil/common/uu_pname.c
trunk/cddl/contrib/opensolaris/lib/libuutil/common/uu_string.c
trunk/cddl/contrib/opensolaris/lib/libuutil/common/uu_strtoint.c
trunk/cddl/contrib/opensolaris/lib/libzfs/common/libzfs.h
trunk/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_changelist.c
trunk/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_compat.c
trunk/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_compat.h
trunk/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_config.c
trunk/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_dataset.c
trunk/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_diff.c
trunk/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_fru.c
trunk/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_impl.h
trunk/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_import.c
trunk/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_iter.c
trunk/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_mount.c
trunk/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_pool.c
trunk/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_sendrecv.c
trunk/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_status.c
trunk/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_util.c
trunk/cddl/contrib/opensolaris/lib/libzfs_core/common/libzfs_core.c
trunk/cddl/contrib/opensolaris/lib/libzfs_core/common/libzfs_core.h
trunk/cddl/contrib/opensolaris/lib/libzfs_core/common/libzfs_core_compat.c
trunk/cddl/contrib/opensolaris/lib/libzfs_core/common/libzfs_core_compat.h
trunk/cddl/contrib/opensolaris/lib/libzpool/common/kernel.c
trunk/cddl/contrib/opensolaris/lib/libzpool/common/sys/zfs_context.h
trunk/cddl/contrib/opensolaris/lib/libzpool/common/taskq.c
trunk/cddl/contrib/opensolaris/lib/libzpool/common/util.c
trunk/cddl/contrib/opensolaris/lib/pyzfs/common/allow.py
trunk/cddl/contrib/opensolaris/lib/pyzfs/common/ioctl.c
Added Paths:
-----------
trunk/cddl/contrib/opensolaris/common/util/
trunk/cddl/contrib/opensolaris/common/util/strtolctype.h
trunk/cddl/contrib/opensolaris/lib/libcmdutils/
trunk/cddl/contrib/opensolaris/lib/libcmdutils/common/
trunk/cddl/contrib/opensolaris/lib/libcmdutils/common/nicenum.c
trunk/cddl/contrib/opensolaris/lib/libcmdutils/libcmdutils.h
trunk/cddl/contrib/opensolaris/lib/libdtrace/common/dt_pq.c
trunk/cddl/contrib/opensolaris/lib/libdtrace/common/dt_pq.h
trunk/cddl/contrib/opensolaris/lib/libdtrace/mips/
trunk/cddl/contrib/opensolaris/lib/libdtrace/mips/dt_isadep.c
trunk/cddl/contrib/opensolaris/lib/libdtrace/powerpc/
trunk/cddl/contrib/opensolaris/lib/libdtrace/powerpc/dt_isadep.c
trunk/cddl/contrib/opensolaris/lib/libnvpair/nvpair_json.c
Property Changed:
----------------
trunk/cddl/contrib/opensolaris/lib/libdtrace/common/dt_grammar.y
trunk/cddl/contrib/opensolaris/lib/libdtrace/common/dt_lex.l
trunk/cddl/contrib/opensolaris/lib/pyzfs/common/allow.py
Modified: trunk/cddl/contrib/opensolaris/common/avl/avl.c
===================================================================
--- trunk/cddl/contrib/opensolaris/common/avl/avl.c 2018-06-02 16:07:17 UTC (rev 10228)
+++ trunk/cddl/contrib/opensolaris/common/avl/avl.c 2018-06-02 16:07:30 UTC (rev 10229)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*
* CDDL HEADER START
*
Modified: trunk/cddl/contrib/opensolaris/common/ctf/ctf_create.c
===================================================================
--- trunk/cddl/contrib/opensolaris/common/ctf/ctf_create.c 2018-06-02 16:07:17 UTC (rev 10228)
+++ trunk/cddl/contrib/opensolaris/common/ctf/ctf_create.c 2018-06-02 16:07:30 UTC (rev 10229)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*
* CDDL HEADER START
*
@@ -24,13 +25,15 @@
* Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
+/*
+ * Copyright (c) 2013, Joyent, Inc. All rights reserved.
+ */
-#pragma ident "%Z%%M% %I% %E% SMI"
-
#include <sys/sysmacros.h>
#include <sys/param.h>
#include <sys/mman.h>
#include <ctf_impl.h>
+#include <sys/debug.h>
/*
* This static string is used as the template for initially populating a
@@ -63,7 +66,7 @@
cts.cts_name = _CTF_SECTION;
cts.cts_type = SHT_PROGBITS;
cts.cts_flags = 0;
- cts.cts_data = &hdr;
+ cts.cts_data = (void *)&hdr;
cts.cts_size = sizeof (hdr);
cts.cts_entsize = 1;
cts.cts_offset = 0;
@@ -167,6 +170,51 @@
}
/*
+ * Only types of dyanmic CTF containers contain reference counts. These
+ * containers are marked RD/WR. Because of that we basically make this a no-op
+ * for compatability with non-dynamic CTF sections. This is also a no-op for
+ * types which are not dynamic types. It is the responsibility of the caller to
+ * make sure it is a valid type. We help that caller out on debug builds.
+ *
+ * Note that the reference counts are not maintained for types that are not
+ * within this container. In other words if we have a type in a parent, that
+ * will not have its reference count increased. On the flip side, the parent
+ * will not be allowed to remove dynamic types if it has children.
+ */
+static void
+ctf_ref_inc(ctf_file_t *fp, ctf_id_t tid)
+{
+ ctf_dtdef_t *dtd = ctf_dtd_lookup(fp, tid);
+
+ if (dtd == NULL)
+ return;
+
+ if (!(fp->ctf_flags & LCTF_RDWR))
+ return;
+
+ dtd->dtd_ref++;
+}
+
+/*
+ * Just as with ctf_ref_inc, this is a no-op on non-writeable containers and the
+ * caller should ensure that this is already a valid type.
+ */
+static void
+ctf_ref_dec(ctf_file_t *fp, ctf_id_t tid)
+{
+ ctf_dtdef_t *dtd = ctf_dtd_lookup(fp, tid);
+
+ if (dtd == NULL)
+ return;
+
+ if (!(fp->ctf_flags & LCTF_RDWR))
+ return;
+
+ ASSERT(dtd->dtd_ref >= 1);
+ dtd->dtd_ref--;
+}
+
+/*
* If the specified CTF container is writable and has been modified, reload
* this container with the updated type definitions. In order to make this
* code and the rest of libctf as simple as possible, we perform updates by
@@ -180,6 +228,10 @@
* ctf_bufopen() will return a new ctf_file_t, but we want to keep the fp
* constant for the caller, so after ctf_bufopen() returns, we use bcopy to
* swap the interior of the old and new ctf_file_t's, and then free the old.
+ *
+ * Note that the lists of dynamic types stays around and the resulting container
+ * is still writeable. Furthermore, the reference counts that are on the dtd's
+ * are still valid.
*/
int
ctf_update(ctf_file_t *fp)
@@ -432,6 +484,7 @@
ctf_dtdef_t *p, **q = &fp->ctf_dthash[h];
ctf_dmdef_t *dmd, *nmd;
size_t len;
+ int kind, i;
for (p = *q; p != NULL; p = p->dtd_hash) {
if (p != dtd)
@@ -443,7 +496,8 @@
if (p != NULL)
*q = p->dtd_hash;
- switch (CTF_INFO_KIND(dtd->dtd_data.ctt_info)) {
+ kind = CTF_INFO_KIND(dtd->dtd_data.ctt_info);
+ switch (kind) {
case CTF_K_STRUCT:
case CTF_K_UNION:
case CTF_K_ENUM:
@@ -454,14 +508,33 @@
ctf_free(dmd->dmd_name, len);
fp->ctf_dtstrlen -= len;
}
+ if (kind != CTF_K_ENUM)
+ ctf_ref_dec(fp, dmd->dmd_type);
nmd = ctf_list_next(dmd);
ctf_free(dmd, sizeof (ctf_dmdef_t));
}
break;
case CTF_K_FUNCTION:
+ ctf_ref_dec(fp, dtd->dtd_data.ctt_type);
+ for (i = 0; i < CTF_INFO_VLEN(dtd->dtd_data.ctt_info); i++)
+ if (dtd->dtd_u.dtu_argv[i] != 0)
+ ctf_ref_dec(fp, dtd->dtd_u.dtu_argv[i]);
ctf_free(dtd->dtd_u.dtu_argv, sizeof (ctf_id_t) *
CTF_INFO_VLEN(dtd->dtd_data.ctt_info));
break;
+ case CTF_K_ARRAY:
+ ctf_ref_dec(fp, dtd->dtd_u.dtu_arr.ctr_contents);
+ ctf_ref_dec(fp, dtd->dtd_u.dtu_arr.ctr_index);
+ break;
+ case CTF_K_TYPEDEF:
+ ctf_ref_dec(fp, dtd->dtd_data.ctt_type);
+ break;
+ case CTF_K_POINTER:
+ case CTF_K_VOLATILE:
+ case CTF_K_CONST:
+ case CTF_K_RESTRICT:
+ ctf_ref_dec(fp, dtd->dtd_data.ctt_type);
+ break;
}
if (dtd->dtd_name) {
@@ -495,7 +568,9 @@
* Discard all of the dynamic type definitions that have been added to the
* container since the last call to ctf_update(). We locate such types by
* scanning the list and deleting elements that have type IDs greater than
- * ctf_dtoldid, which is set by ctf_update(), above.
+ * ctf_dtoldid, which is set by ctf_update(), above. Note that to work properly
+ * with our reference counting schemes, we must delete the dynamic list in
+ * reverse.
*/
int
ctf_discard(ctf_file_t *fp)
@@ -508,11 +583,11 @@
if (!(fp->ctf_flags & LCTF_DIRTY))
return (0); /* no update required */
- for (dtd = ctf_list_next(&fp->ctf_dtdefs); dtd != NULL; dtd = ntd) {
- if (dtd->dtd_type <= fp->ctf_dtoldid)
+ for (dtd = ctf_list_prev(&fp->ctf_dtdefs); dtd != NULL; dtd = ntd) {
+ ntd = ctf_list_prev(dtd);
+ if (CTF_TYPE_TO_INDEX(dtd->dtd_type) <= fp->ctf_dtoldid)
continue; /* skip types that have been committed */
- ntd = ctf_list_next(dtd);
ctf_dtd_delete(fp, dtd);
}
@@ -614,6 +689,8 @@
if ((type = ctf_add_generic(fp, flag, NULL, &dtd)) == CTF_ERR)
return (CTF_ERR); /* errno is set for us */
+ ctf_ref_inc(fp, ref);
+
dtd->dtd_data.ctt_info = CTF_TYPE_INFO(kind, flag, 0);
dtd->dtd_data.ctt_type = (ushort_t)ref;
@@ -645,10 +722,21 @@
{
ctf_dtdef_t *dtd;
ctf_id_t type;
+ ctf_file_t *fpd;
if (arp == NULL)
return (ctf_set_errno(fp, EINVAL));
+ fpd = fp;
+ if (ctf_lookup_by_id(&fpd, arp->ctr_contents) == NULL &&
+ ctf_dtd_lookup(fp, arp->ctr_contents) == NULL)
+ return (ctf_set_errno(fp, ECTF_BADID));
+
+ fpd = fp;
+ if (ctf_lookup_by_id(&fpd, arp->ctr_index) == NULL &&
+ ctf_dtd_lookup(fp, arp->ctr_index) == NULL)
+ return (ctf_set_errno(fp, ECTF_BADID));
+
if ((type = ctf_add_generic(fp, flag, NULL, &dtd)) == CTF_ERR)
return (CTF_ERR); /* errno is set for us */
@@ -655,6 +743,8 @@
dtd->dtd_data.ctt_info = CTF_TYPE_INFO(CTF_K_ARRAY, flag, 0);
dtd->dtd_data.ctt_size = 0;
dtd->dtd_u.dtu_arr = *arp;
+ ctf_ref_inc(fp, arp->ctr_contents);
+ ctf_ref_inc(fp, arp->ctr_index);
return (type);
}
@@ -662,6 +752,7 @@
int
ctf_set_array(ctf_file_t *fp, ctf_id_t type, const ctf_arinfo_t *arp)
{
+ ctf_file_t *fpd;
ctf_dtdef_t *dtd = ctf_dtd_lookup(fp, type);
if (!(fp->ctf_flags & LCTF_RDWR))
@@ -670,8 +761,22 @@
if (dtd == NULL || CTF_INFO_KIND(dtd->dtd_data.ctt_info) != CTF_K_ARRAY)
return (ctf_set_errno(fp, ECTF_BADID));
+ fpd = fp;
+ if (ctf_lookup_by_id(&fpd, arp->ctr_contents) == NULL &&
+ ctf_dtd_lookup(fp, arp->ctr_contents) == NULL)
+ return (ctf_set_errno(fp, ECTF_BADID));
+
+ fpd = fp;
+ if (ctf_lookup_by_id(&fpd, arp->ctr_index) == NULL &&
+ ctf_dtd_lookup(fp, arp->ctr_index) == NULL)
+ return (ctf_set_errno(fp, ECTF_BADID));
+
+ ctf_ref_dec(fp, dtd->dtd_u.dtu_arr.ctr_contents);
+ ctf_ref_dec(fp, dtd->dtd_u.dtu_arr.ctr_index);
fp->ctf_flags |= LCTF_DIRTY;
dtd->dtd_u.dtu_arr = *arp;
+ ctf_ref_inc(fp, arp->ctr_contents);
+ ctf_ref_inc(fp, arp->ctr_index);
return (0);
}
@@ -683,7 +788,9 @@
ctf_dtdef_t *dtd;
ctf_id_t type;
uint_t vlen;
+ int i;
ctf_id_t *vdat = NULL;
+ ctf_file_t *fpd;
if (ctc == NULL || (ctc->ctc_flags & ~CTF_FUNC_VARARG) != 0 ||
(ctc->ctc_argc != 0 && argv == NULL))
@@ -696,6 +803,18 @@
if (vlen > CTF_MAX_VLEN)
return (ctf_set_errno(fp, EOVERFLOW));
+ fpd = fp;
+ if (ctf_lookup_by_id(&fpd, ctc->ctc_return) == NULL &&
+ ctf_dtd_lookup(fp, ctc->ctc_return) == NULL)
+ return (ctf_set_errno(fp, ECTF_BADID));
+
+ for (i = 0; i < ctc->ctc_argc; i++) {
+ fpd = fp;
+ if (ctf_lookup_by_id(&fpd, argv[i]) == NULL &&
+ ctf_dtd_lookup(fp, argv[i]) == NULL)
+ return (ctf_set_errno(fp, ECTF_BADID));
+ }
+
if (vlen != 0 && (vdat = ctf_alloc(sizeof (ctf_id_t) * vlen)) == NULL)
return (ctf_set_errno(fp, EAGAIN));
@@ -707,6 +826,10 @@
dtd->dtd_data.ctt_info = CTF_TYPE_INFO(CTF_K_FUNCTION, flag, vlen);
dtd->dtd_data.ctt_type = (ushort_t)ctc->ctc_return;
+ ctf_ref_inc(fp, ctc->ctc_return);
+ for (i = 0; i < ctc->ctc_argc; i++)
+ ctf_ref_inc(fp, argv[i]);
+
bcopy(argv, vdat, sizeof (ctf_id_t) * ctc->ctc_argc);
if (ctc->ctc_flags & CTF_FUNC_VARARG)
vdat[vlen - 1] = 0; /* add trailing zero to indicate varargs */
@@ -825,8 +948,11 @@
{
ctf_dtdef_t *dtd;
ctf_id_t type;
+ ctf_file_t *fpd;
- if (ref == CTF_ERR || ref < 0 || ref > CTF_MAX_TYPE)
+ fpd = fp;
+ if (ref == CTF_ERR || (ctf_lookup_by_id(&fpd, ref) == NULL &&
+ ctf_dtd_lookup(fp, ref) == NULL))
return (ctf_set_errno(fp, EINVAL));
if ((type = ctf_add_generic(fp, flag, name, &dtd)) == CTF_ERR)
@@ -834,6 +960,7 @@
dtd->dtd_data.ctt_info = CTF_TYPE_INFO(CTF_K_TYPEDEF, flag, 0);
dtd->dtd_data.ctt_type = (ushort_t)ref;
+ ctf_ref_inc(fp, ref);
return (type);
}
@@ -1008,10 +1135,49 @@
if (s != NULL)
fp->ctf_dtstrlen += strlen(s) + 1;
+ ctf_ref_inc(fp, type);
fp->ctf_flags |= LCTF_DIRTY;
return (0);
}
+/*
+ * This removes a type from the dynamic section. This will fail if the type is
+ * referenced by another type. Note that the CTF ID is never reused currently by
+ * CTF. Note that if this container is a parent container then we just outright
+ * refuse to remove the type. There currently is no notion of searching for the
+ * ctf_dtdef_t in parent containers. If there is, then this constraint could
+ * become finer grained.
+ */
+int
+ctf_delete_type(ctf_file_t *fp, ctf_id_t type)
+{
+ ctf_file_t *fpd;
+ ctf_dtdef_t *dtd = ctf_dtd_lookup(fp, type);
+
+ if (!(fp->ctf_flags & LCTF_RDWR))
+ return (ctf_set_errno(fp, ECTF_RDONLY));
+
+ /*
+ * We want to give as useful an errno as possible. That means that we
+ * want to distinguish between a type which does not exist and one for
+ * which the type is not dynamic.
+ */
+ fpd = fp;
+ if (ctf_lookup_by_id(&fpd, type) == NULL &&
+ ctf_dtd_lookup(fp, type) == NULL)
+ return (CTF_ERR); /* errno is set for us */
+
+ if (dtd == NULL)
+ return (ctf_set_errno(fp, ECTF_NOTDYN));
+
+ if (dtd->dtd_ref != 0 || fp->ctf_refcnt > 1)
+ return (ctf_set_errno(fp, ECTF_REFERENCED));
+
+ ctf_dtd_delete(fp, dtd);
+ fp->ctf_flags |= LCTF_DIRTY;
+ return (0);
+}
+
static int
enumcmp(const char *name, int value, void *arg)
{
@@ -1103,6 +1269,9 @@
ctf_hash_t *hp;
ctf_helem_t *hep;
+ if (dst_fp == src_fp)
+ return (src_type);
+
if (!(dst_fp->ctf_flags & LCTF_RDWR))
return (ctf_set_errno(dst_fp, ECTF_RDONLY));
@@ -1145,10 +1314,13 @@
* unless dst_type is a forward declaration and src_type is a struct,
* union, or enum (i.e. the definition of the previous forward decl).
*/
- if (dst_type != CTF_ERR && dst_kind != kind && (
- dst_kind != CTF_K_FORWARD || (kind != CTF_K_ENUM &&
- kind != CTF_K_STRUCT && kind != CTF_K_UNION)))
- return (ctf_set_errno(dst_fp, ECTF_CONFLICT));
+ if (dst_type != CTF_ERR && dst_kind != kind) {
+ if (dst_kind != CTF_K_FORWARD || (kind != CTF_K_ENUM &&
+ kind != CTF_K_STRUCT && kind != CTF_K_UNION))
+ return (ctf_set_errno(dst_fp, ECTF_CONFLICT));
+ else
+ dst_type = CTF_ERR;
+ }
/*
* If the non-empty name was not found in the appropriate hash, search
@@ -1157,15 +1329,28 @@
* we are looking for. This is necessary to permit ctf_add_type() to
* operate recursively on entities such as a struct that contains a
* pointer member that refers to the same struct type.
+ *
+ * In the case of integer and floating point types, we match using the
+ * type encoding as well - else we may incorrectly return a bitfield
+ * type, for instance.
*/
if (dst_type == CTF_ERR && name[0] != '\0') {
for (dtd = ctf_list_prev(&dst_fp->ctf_dtdefs); dtd != NULL &&
- dtd->dtd_type > dst_fp->ctf_dtoldid;
+ CTF_TYPE_TO_INDEX(dtd->dtd_type) > dst_fp->ctf_dtoldid;
dtd = ctf_list_prev(dtd)) {
- if (CTF_INFO_KIND(dtd->dtd_data.ctt_info) == kind &&
- dtd->dtd_name != NULL &&
- strcmp(dtd->dtd_name, name) == 0)
- return (dtd->dtd_type);
+ if (CTF_INFO_KIND(dtd->dtd_data.ctt_info) != kind ||
+ dtd->dtd_name == NULL ||
+ strcmp(dtd->dtd_name, name) != 0)
+ continue;
+ if (kind == CTF_K_INTEGER || kind == CTF_K_FLOAT) {
+ if (ctf_type_encoding(src_fp, src_type,
+ &src_en) != 0)
+ continue;
+ if (bcmp(&src_en, &dtd->dtd_u.dtu_enc,
+ sizeof (ctf_encoding_t)) != 0)
+ continue;
+ }
+ return (dtd->dtd_type);
}
}
@@ -1313,6 +1498,14 @@
if (errs)
return (CTF_ERR); /* errno is set for us */
+
+ /*
+ * Now that we know that we can't fail, we go through and bump
+ * all the reference counts on the member types.
+ */
+ for (dmd = ctf_list_next(&dtd->dtd_u.dtu_members);
+ dmd != NULL; dmd = ctf_list_next(dmd))
+ ctf_ref_inc(dst_fp, dmd->dmd_type);
break;
}
Modified: trunk/cddl/contrib/opensolaris/common/ctf/ctf_decl.c
===================================================================
--- trunk/cddl/contrib/opensolaris/common/ctf/ctf_decl.c 2018-06-02 16:07:17 UTC (rev 10228)
+++ trunk/cddl/contrib/opensolaris/common/ctf/ctf_decl.c 2018-06-02 16:07:30 UTC (rev 10229)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*
* CDDL HEADER START
*
Modified: trunk/cddl/contrib/opensolaris/common/ctf/ctf_error.c
===================================================================
--- trunk/cddl/contrib/opensolaris/common/ctf/ctf_error.c 2018-06-02 16:07:17 UTC (rev 10228)
+++ trunk/cddl/contrib/opensolaris/common/ctf/ctf_error.c 2018-06-02 16:07:30 UTC (rev 10229)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*
* CDDL HEADER START
*
@@ -23,9 +24,10 @@
* Copyright 2003 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
+/*
+ * Copyright (c) 2012, Joyent, Inc.
+ */
-#pragma ident "%Z%%M% %I% %E% SMI"
-
#include <ctf_impl.h>
static const char *const _ctf_errlist[] = {
@@ -73,6 +75,8 @@
"Limit on number of dynamic types reached", /* ECTF_FULL */
"Duplicate member name definition", /* ECTF_DUPMEMBER */
"Conflicting type is already defined", /* ECTF_CONFLICT */
+ "Type has outstanding references", /* ECTF_REFERENCED */
+ "Type is not a dynamic type" /* ECTF_NOTDYN */
};
static const int _ctf_nerr = sizeof (_ctf_errlist) / sizeof (_ctf_errlist[0]);
Modified: trunk/cddl/contrib/opensolaris/common/ctf/ctf_hash.c
===================================================================
--- trunk/cddl/contrib/opensolaris/common/ctf/ctf_hash.c 2018-06-02 16:07:17 UTC (rev 10228)
+++ trunk/cddl/contrib/opensolaris/common/ctf/ctf_hash.c 2018-06-02 16:07:30 UTC (rev 10229)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*
* CDDL HEADER START
*
Modified: trunk/cddl/contrib/opensolaris/common/ctf/ctf_impl.h
===================================================================
--- trunk/cddl/contrib/opensolaris/common/ctf/ctf_impl.h 2018-06-02 16:07:17 UTC (rev 10228)
+++ trunk/cddl/contrib/opensolaris/common/ctf/ctf_impl.h 2018-06-02 16:07:30 UTC (rev 10229)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*
* CDDL HEADER START
*
@@ -24,12 +25,13 @@
* Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
+/*
+ * Copyright (c) 2012, Joyent, Inc. All rights reserved.
+ */
#ifndef _CTF_IMPL_H
#define _CTF_IMPL_H
-#pragma ident "%Z%%M% %I% %E% SMI"
-
#include <sys/types.h>
#include <sys/errno.h>
#include <sys/sysmacros.h>
@@ -149,6 +151,7 @@
char *dtd_name; /* name associated with definition (if any) */
ctf_id_t dtd_type; /* type identifier for this definition */
ctf_type_t dtd_data; /* type node (see <sys/ctf.h>) */
+ int dtd_ref; /* recfount for dyanmic types */
union {
ctf_list_t dtu_members; /* struct, union, or enum */
ctf_arinfo_t dtu_arr; /* array */
@@ -269,7 +272,9 @@
ECTF_DTFULL, /* CTF type is full (no more members allowed) */
ECTF_FULL, /* CTF container is full */
ECTF_DUPMEMBER, /* duplicate member name definition */
- ECTF_CONFLICT /* conflicting type definition present */
+ ECTF_CONFLICT, /* conflicting type definition present */
+ ECTF_REFERENCED, /* type has outstanding references */
+ ECTF_NOTDYN /* type is not a dynamic type */
};
extern ssize_t ctf_get_ctt_size(const ctf_file_t *, const ctf_type_t *,
Modified: trunk/cddl/contrib/opensolaris/common/ctf/ctf_labels.c
===================================================================
--- trunk/cddl/contrib/opensolaris/common/ctf/ctf_labels.c 2018-06-02 16:07:17 UTC (rev 10228)
+++ trunk/cddl/contrib/opensolaris/common/ctf/ctf_labels.c 2018-06-02 16:07:30 UTC (rev 10229)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*
* CDDL HEADER START
*
Modified: trunk/cddl/contrib/opensolaris/common/ctf/ctf_lookup.c
===================================================================
--- trunk/cddl/contrib/opensolaris/common/ctf/ctf_lookup.c 2018-06-02 16:07:17 UTC (rev 10228)
+++ trunk/cddl/contrib/opensolaris/common/ctf/ctf_lookup.c 2018-06-02 16:07:30 UTC (rev 10229)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*
* CDDL HEADER START
*
Modified: trunk/cddl/contrib/opensolaris/common/ctf/ctf_open.c
===================================================================
--- trunk/cddl/contrib/opensolaris/common/ctf/ctf_open.c 2018-06-02 16:07:17 UTC (rev 10228)
+++ trunk/cddl/contrib/opensolaris/common/ctf/ctf_open.c 2018-06-02 16:07:30 UTC (rev 10229)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*
* CDDL HEADER START
*
@@ -24,9 +25,10 @@
* Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
+/*
+ * Copyright (c) 2013, Joyent, Inc. All rights reserved.
+ */
-#pragma ident "%Z%%M% %I% %E% SMI"
-
#include <ctf_impl.h>
#include <sys/mman.h>
#include <sys/zmod.h>
@@ -787,6 +789,92 @@
}
/*
+ * Dupliate a ctf_file_t and its underlying section information into a new
+ * container. This works by copying the three ctf_sect_t's of the original
+ * container if they exist and passing those into ctf_bufopen. To copy those, we
+ * mmap anonymous memory with ctf_data_alloc and bcopy the data across. It's not
+ * the cheapest thing, but it's what we've got.
+ */
+ctf_file_t *
+ctf_dup(ctf_file_t *ofp)
+{
+ ctf_file_t *fp;
+ ctf_sect_t ctfsect, symsect, strsect;
+ ctf_sect_t *ctp, *symp, *strp;
+ void *cbuf, *symbuf, *strbuf;
+ int err;
+
+ cbuf = symbuf = strbuf = NULL;
+ /*
+ * The ctfsect isn't allowed to not exist, but the symbol and string
+ * section might not. We only need to copy the data of the section, not
+ * the name, as ctf_bufopen will take care of that.
+ */
+ bcopy(&ofp->ctf_data, &ctfsect, sizeof (ctf_sect_t));
+ cbuf = ctf_data_alloc(ctfsect.cts_size);
+ if (cbuf == NULL) {
+ (void) ctf_set_errno(ofp, ECTF_MMAP);
+ return (NULL);
+ }
+
+ bcopy(ctfsect.cts_data, cbuf, ctfsect.cts_size);
+ ctf_data_protect(cbuf, ctfsect.cts_size);
+ ctfsect.cts_data = cbuf;
+ ctfsect.cts_offset = 0;
+ ctp = &ctfsect;
+
+ if (ofp->ctf_symtab.cts_data != NULL) {
+ bcopy(&ofp->ctf_symtab, &symsect, sizeof (ctf_sect_t));
+ symbuf = ctf_data_alloc(symsect.cts_size);
+ if (symbuf == NULL) {
+ (void) ctf_set_errno(ofp, ECTF_MMAP);
+ goto err;
+ }
+ bcopy(symsect.cts_data, symbuf, symsect.cts_size);
+ ctf_data_protect(symbuf, symsect.cts_size);
+ symsect.cts_data = symbuf;
+ symsect.cts_offset = 0;
+ symp = &symsect;
+ } else {
+ symp = NULL;
+ }
+
+ if (ofp->ctf_strtab.cts_data != NULL) {
+ bcopy(&ofp->ctf_strtab, &strsect, sizeof (ctf_sect_t));
+ strbuf = ctf_data_alloc(strsect.cts_size);
+ if (strbuf == NULL) {
+ (void) ctf_set_errno(ofp, ECTF_MMAP);
+ goto err;
+ }
+ bcopy(strsect.cts_data, strbuf, strsect.cts_size);
+ ctf_data_protect(strbuf, strsect.cts_size);
+ strsect.cts_data = strbuf;
+ strsect.cts_offset = 0;
+ strp = &strsect;
+ } else {
+ strp = NULL;
+ }
+
+ fp = ctf_bufopen(ctp, symp, strp, &err);
+ if (fp == NULL) {
+ (void) ctf_set_errno(ofp, err);
+ goto err;
+ }
+
+ fp->ctf_flags |= LCTF_MMAP;
+
+ return (fp);
+
+err:
+ ctf_data_free(cbuf, ctfsect.cts_size);
+ if (symbuf != NULL)
+ ctf_data_free(symbuf, symsect.cts_size);
+ if (strbuf != NULL)
+ ctf_data_free(strbuf, strsect.cts_size);
+ return (NULL);
+}
+
+/*
* Close the specified CTF container and free associated data structures. Note
* that ctf_close() is a reference counted operation: if the specified file is
* the parent of other active containers, its reference count will be greater
@@ -810,8 +898,12 @@
if (fp->ctf_parent != NULL)
ctf_close(fp->ctf_parent);
- for (dtd = ctf_list_next(&fp->ctf_dtdefs); dtd != NULL; dtd = ntd) {
- ntd = ctf_list_next(dtd);
+ /*
+ * Note, to work properly with reference counting on the dynamic
+ * section, we must delete the list in reverse.
+ */
+ for (dtd = ctf_list_prev(&fp->ctf_dtdefs); dtd != NULL; dtd = ntd) {
+ ntd = ctf_list_prev(dtd);
ctf_dtd_delete(fp, dtd);
}
Modified: trunk/cddl/contrib/opensolaris/common/ctf/ctf_types.c
===================================================================
--- trunk/cddl/contrib/opensolaris/common/ctf/ctf_types.c 2018-06-02 16:07:17 UTC (rev 10228)
+++ trunk/cddl/contrib/opensolaris/common/ctf/ctf_types.c 2018-06-02 16:07:30 UTC (rev 10229)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*
* CDDL HEADER START
*
@@ -25,8 +26,6 @@
* Use is subject to license terms.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
-
#include <ctf_impl.h>
ssize_t
@@ -199,8 +198,9 @@
* Lookup the given type ID and print a string name for it into buf. Return
* the actual number of bytes (not including \0) needed to format the name.
*/
-ssize_t
-ctf_type_lname(ctf_file_t *fp, ctf_id_t type, char *buf, size_t len)
+static ssize_t
+ctf_type_qlname(ctf_file_t *fp, ctf_id_t type, char *buf, size_t len,
+ const char *qname)
{
ctf_decl_t cd;
ctf_decl_node_t *cdp;
@@ -255,6 +255,8 @@
case CTF_K_INTEGER:
case CTF_K_FLOAT:
case CTF_K_TYPEDEF:
+ if (qname != NULL)
+ ctf_decl_sprintf(&cd, "%s`", qname);
ctf_decl_sprintf(&cd, "%s", name);
break;
case CTF_K_POINTER:
@@ -268,13 +270,22 @@
break;
case CTF_K_STRUCT:
case CTF_K_FORWARD:
- ctf_decl_sprintf(&cd, "struct %s", name);
+ ctf_decl_sprintf(&cd, "struct ");
+ if (qname != NULL)
+ ctf_decl_sprintf(&cd, "%s`", qname);
+ ctf_decl_sprintf(&cd, "%s", name);
break;
case CTF_K_UNION:
- ctf_decl_sprintf(&cd, "union %s", name);
+ ctf_decl_sprintf(&cd, "union ");
+ if (qname != NULL)
+ ctf_decl_sprintf(&cd, "%s`", qname);
+ ctf_decl_sprintf(&cd, "%s", name);
break;
case CTF_K_ENUM:
- ctf_decl_sprintf(&cd, "enum %s", name);
+ ctf_decl_sprintf(&cd, "enum ");
+ if (qname != NULL)
+ ctf_decl_sprintf(&cd, "%s`", qname);
+ ctf_decl_sprintf(&cd, "%s", name);
break;
case CTF_K_VOLATILE:
ctf_decl_sprintf(&cd, "volatile");
@@ -301,6 +312,12 @@
return (cd.cd_len);
}
+ssize_t
+ctf_type_lname(ctf_file_t *fp, ctf_id_t type, char *buf, size_t len)
+{
+ return (ctf_type_qlname(fp, type, buf, len, NULL));
+}
+
/*
* Lookup the given type ID and print a string name for it into buf. If buf
* is too small, return NULL: the ECTF_NAMELEN error is set on 'fp' for us.
@@ -308,10 +325,19 @@
char *
ctf_type_name(ctf_file_t *fp, ctf_id_t type, char *buf, size_t len)
{
- ssize_t rv = ctf_type_lname(fp, type, buf, len);
+ ssize_t rv = ctf_type_qlname(fp, type, buf, len, NULL);
return (rv >= 0 && rv < len ? buf : NULL);
}
+char *
+ctf_type_qname(ctf_file_t *fp, ctf_id_t type, char *buf, size_t len,
+ const char *qname)
+{
+ ssize_t rv = ctf_type_qlname(fp, type, buf, len, qname);
+ return (rv >= 0 && rv < len ? buf : NULL);
+}
+
+
/*
* Resolve the type down to a base type node, and then return the size
* of the type storage in bytes.
Modified: trunk/cddl/contrib/opensolaris/common/ctf/ctf_util.c
===================================================================
--- trunk/cddl/contrib/opensolaris/common/ctf/ctf_util.c 2018-06-02 16:07:17 UTC (rev 10228)
+++ trunk/cddl/contrib/opensolaris/common/ctf/ctf_util.c 2018-06-02 16:07:30 UTC (rev 10229)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*
* CDDL HEADER START
*
Added: trunk/cddl/contrib/opensolaris/common/util/strtolctype.h
===================================================================
--- trunk/cddl/contrib/opensolaris/common/util/strtolctype.h (rev 0)
+++ trunk/cddl/contrib/opensolaris/common/util/strtolctype.h 2018-06-02 16:07:30 UTC (rev 10229)
@@ -0,0 +1,80 @@
+/* $MidnightBSD$ */
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+/* Copyright (c) 1988 AT&T */
+/* All Rights Reserved */
+
+#ifndef _COMMON_UTIL_CTYPE_H
+#define _COMMON_UTIL_CTYPE_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * This header file contains a collection of macros that the strtou?ll?
+ * functions in common/util use to test characters. What we need is a kernel
+ * version of ctype.h.
+ *
+ * NOTE: These macros are used within several DTrace probe context functions.
+ * They must not be altered to make function calls or perform actions not
+ * safe in probe context.
+ */
+
+#if defined(illumos) && (defined(_KERNEL) || defined(_BOOT))
+
+#define isalnum(ch) (isalpha(ch) || isdigit(ch))
+#define isalpha(ch) (isupper(ch) || islower(ch))
+#define isdigit(ch) ((ch) >= '0' && (ch) <= '9')
+#define islower(ch) ((ch) >= 'a' && (ch) <= 'z')
+#define isspace(ch) (((ch) == ' ') || ((ch) == '\r') || ((ch) == '\n') || \
+ ((ch) == '\t') || ((ch) == '\f'))
+#define isupper(ch) ((ch) >= 'A' && (ch) <= 'Z')
+#define isxdigit(ch) (isdigit(ch) || ((ch) >= 'a' && (ch) <= 'f') || \
+ ((ch) >= 'A' && (ch) <= 'F'))
+
+#endif /* _KERNEL || _BOOT */
+
+#define DIGIT(x) \
+ (isdigit(x) ? (x) - '0' : islower(x) ? (x) + 10 - 'a' : (x) + 10 - 'A')
+
+#define MBASE ('z' - 'a' + 1 + 10)
+
+/*
+ * The following macro is a version of isalnum() that limits alphabetic
+ * characters to the ranges a-z and A-Z; locale dependent characters will not
+ * return 1. The members of a-z and A-Z are assumed to be in ascending order
+ * and contiguous.
+ */
+#define lisalnum(x) \
+ (isdigit(x) || ((x) >= 'a' && (x) <= 'z') || ((x) >= 'A' && (x) <= 'Z'))
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _COMMON_UTIL_CTYPE_H */
Property changes on: trunk/cddl/contrib/opensolaris/common/util/strtolctype.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Modified: trunk/cddl/contrib/opensolaris/head/assert.h
===================================================================
--- trunk/cddl/contrib/opensolaris/head/assert.h 2018-06-02 16:07:17 UTC (rev 10228)
+++ trunk/cddl/contrib/opensolaris/head/assert.h 2018-06-02 16:07:30 UTC (rev 10229)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*
* CDDL HEADER START
*
Modified: trunk/cddl/contrib/opensolaris/head/atomic.h
===================================================================
--- trunk/cddl/contrib/opensolaris/head/atomic.h 2018-06-02 16:07:17 UTC (rev 10228)
+++ trunk/cddl/contrib/opensolaris/head/atomic.h 2018-06-02 16:07:30 UTC (rev 10229)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*
* CDDL HEADER START
*
Modified: trunk/cddl/contrib/opensolaris/head/libintl.h
===================================================================
--- trunk/cddl/contrib/opensolaris/head/libintl.h 2018-06-02 16:07:17 UTC (rev 10228)
+++ trunk/cddl/contrib/opensolaris/head/libintl.h 2018-06-02 16:07:30 UTC (rev 10229)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*
* CDDL HEADER START
*
@@ -19,6 +20,8 @@
* CDDL HEADER END
*/
/*
+ * Copyright 2014 Garrett D'Amore <garrett at damore.org>
+ *
* Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -27,8 +30,6 @@
#ifndef _LIBINTL_H
#define _LIBINTL_H
-#pragma ident "%Z%%M% %I% %E% SMI"
-
#include <sys/isa_defs.h>
#ifdef __cplusplus
@@ -64,7 +65,6 @@
#define __GNU_GETTEXT_SUPPORTED_REVISION(m) \
((((m) == 0) || ((m) == 1)) ? 1 : -1)
-#ifdef __STDC__
extern char *dcgettext(const char *, const char *, const int);
extern char *dgettext(const char *, const char *);
extern char *gettext(const char *);
@@ -91,33 +91,6 @@
extern wchar_t mcfiller(void);
extern int mcwrap(void);
-#else
-extern char *dcgettext();
-extern char *dgettext();
-extern char *gettext();
-extern char *textdomain();
-extern char *bindtextdomain();
-
-/*
- * LI18NUX 2000 Globalization Specification Version 1.0
- * with Amendment 2
- */
-extern char *dcngettext();
-extern char *dngettext();
-extern char *ngettext();
-extern char *bind_textdomain_codeset();
-
-/* Word handling functions --- requires dynamic linking */
-/* Warning: these are experimental and subject to change. */
-extern int wdinit();
-extern int wdchkind();
-extern int wdbindf();
-extern wchar_t *wddelim();
-extern wchar_t mcfiller();
-extern int mcwrap();
-
-#endif
-
#ifdef __cplusplus
}
#endif
Modified: trunk/cddl/contrib/opensolaris/head/nlist.h
===================================================================
--- trunk/cddl/contrib/opensolaris/head/nlist.h 2018-06-02 16:07:17 UTC (rev 10228)
+++ trunk/cddl/contrib/opensolaris/head/nlist.h 2018-06-02 16:07:30 UTC (rev 10229)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*
* CDDL HEADER START
*
@@ -19,6 +20,9 @@
*
* CDDL HEADER END
*/
+/*
+ * Copyright 2014 Garrett D'Amore <garrett at damore.org>
+ */
/* Copyright (c) 1988 AT&T */
/* All Rights Reserved */
@@ -26,8 +30,6 @@
#ifndef _NLIST_H
#define _NLIST_H
-#pragma ident "%Z%%M% %I% %E% SMI" /* SVr4.0 1.8.2.4 */
-
#ifdef __cplusplus
extern "C" {
#endif
@@ -41,11 +43,7 @@
char n_numaux; /* number of aux. entries */
};
-#if defined(__STDC__)
extern int nlist(const char *, struct nlist *);
-#else /* __STDC__ */
-extern int nlist();
-#endif /* __STDC__ */
#ifdef __cplusplus
}
Modified: trunk/cddl/contrib/opensolaris/head/note.h
===================================================================
--- trunk/cddl/contrib/opensolaris/head/note.h 2018-06-02 16:07:17 UTC (rev 10228)
+++ trunk/cddl/contrib/opensolaris/head/note.h 2018-06-02 16:07:30 UTC (rev 10229)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*
* CDDL HEADER START
*
Modified: trunk/cddl/contrib/opensolaris/head/stdio_ext.h
===================================================================
--- trunk/cddl/contrib/opensolaris/head/stdio_ext.h 2018-06-02 16:07:17 UTC (rev 10228)
+++ trunk/cddl/contrib/opensolaris/head/stdio_ext.h 2018-06-02 16:07:30 UTC (rev 10229)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*
* CDDL HEADER START
*
Modified: trunk/cddl/contrib/opensolaris/head/storclass.h
===================================================================
--- trunk/cddl/contrib/opensolaris/head/storclass.h 2018-06-02 16:07:17 UTC (rev 10228)
+++ trunk/cddl/contrib/opensolaris/head/storclass.h 2018-06-02 16:07:30 UTC (rev 10229)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*
* CDDL HEADER START
*
Modified: trunk/cddl/contrib/opensolaris/head/syms.h
===================================================================
--- trunk/cddl/contrib/opensolaris/head/syms.h 2018-06-02 16:07:17 UTC (rev 10228)
+++ trunk/cddl/contrib/opensolaris/head/syms.h 2018-06-02 16:07:30 UTC (rev 10229)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*
* CDDL HEADER START
*
Modified: trunk/cddl/contrib/opensolaris/head/synch.h
===================================================================
--- trunk/cddl/contrib/opensolaris/head/synch.h 2018-06-02 16:07:17 UTC (rev 10228)
+++ trunk/cddl/contrib/opensolaris/head/synch.h 2018-06-02 16:07:30 UTC (rev 10229)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*
* CDDL HEADER START
*
@@ -20,6 +21,7 @@
*/
/*
+ * Copyright 2014 Garrett D'Amore <garrett at damore.org>
* Copyright (c) 1992, 2010, Oracle and/or its affiliates. All rights reserved.
*/
@@ -86,7 +88,6 @@
cond_t writercv; /* used only to indicate ownership */
} rwlock_t;
-#ifdef __STDC__
int _lwp_mutex_lock(lwp_mutex_t *);
int _lwp_mutex_unlock(lwp_mutex_t *);
int _lwp_mutex_trylock(lwp_mutex_t *);
@@ -127,50 +128,6 @@
int sema_post(sema_t *);
int sema_trywait(sema_t *);
-#else /* __STDC__ */
-
-int _lwp_mutex_lock();
-int _lwp_mutex_unlock();
-int _lwp_mutex_trylock();
-int _lwp_cond_wait();
-int _lwp_cond_timedwait();
-int _lwp_cond_reltimedwait();
-int _lwp_cond_signal();
-int _lwp_cond_broadcast();
-int _lwp_sema_init();
-int _lwp_sema_wait();
-int _lwp_sema_trywait();
-int _lwp_sema_post();
-int cond_init();
-int cond_destroy();
-int cond_wait();
-int cond_timedwait();
-int cond_reltimedwait();
-int cond_signal();
-int cond_broadcast();
-int mutex_init();
-int mutex_destroy();
-int mutex_consistent();
-int mutex_lock();
-int mutex_trylock();
-int mutex_unlock();
-int rwlock_init();
-int rwlock_destroy();
-int rw_rdlock();
-int rw_wrlock();
-int rw_unlock();
-int rw_tryrdlock();
-int rw_trywrlock();
-int sema_init();
-int sema_destroy();
-int sema_wait();
-int sema_timedwait();
-int sema_reltimedwait();
-int sema_post();
-int sema_trywait();
-
-#endif /* __STDC__ */
-
#endif /* _ASM */
/* "Magic numbers" tagging synchronization object types */
@@ -238,8 +195,6 @@
#ifndef _ASM
-#ifdef __STDC__
-
/*
* The *_held() functions apply equally well to Solaris threads
* and to Posix threads synchronization objects, but the formal
@@ -252,21 +207,8 @@
int _rw_write_held(void *); /* rwlock_t or pthread_rwlock_t */
int _mutex_held(void *); /* mutex_t or pthread_mutex_t */
-#else /* __STDC__ */
-
-int _sema_held();
-int _rw_read_held();
-int _rw_write_held();
-int _mutex_held();
-
-#endif /* __STDC__ */
-
/* Pause API */
-#ifdef __STDC__
void smt_pause(void);
-#else /* __STDC__ */
-void smt_pause();
-#endif /* __STDC__ */
#endif /* _ASM */
Modified: trunk/cddl/contrib/opensolaris/head/thread.h
===================================================================
--- trunk/cddl/contrib/opensolaris/head/thread.h 2018-06-02 16:07:17 UTC (rev 10228)
+++ trunk/cddl/contrib/opensolaris/head/thread.h 2018-06-02 16:07:30 UTC (rev 10229)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*
* CDDL HEADER START
*
@@ -20,6 +21,8 @@
*/
/*
+ * Copyright 2014 Garrett D'Amore <garrett at damore.org>
+ *
* Copyright 2007 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -27,8 +30,6 @@
#ifndef _THREAD_H
#define _THREAD_H
-#pragma ident "%Z%%M% %I% %E% SMI"
-
#include <pthread.h>
#include <pthread_np.h>
#include <assert.h>
Added: trunk/cddl/contrib/opensolaris/lib/libcmdutils/common/nicenum.c
===================================================================
--- trunk/cddl/contrib/opensolaris/lib/libcmdutils/common/nicenum.c (rev 0)
+++ trunk/cddl/contrib/opensolaris/lib/libcmdutils/common/nicenum.c 2018-06-02 16:07:30 UTC (rev 10229)
@@ -0,0 +1,131 @@
+/* $MidnightBSD$ */
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright 2017 Jason king
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/debug.h>
+#include "libcmdutils.h"
+
+/* The largest suffix that can fit, aka an exabyte (2^60 / 10^18) */
+#define INDEX_MAX (6)
+
+/* Verify INDEX_MAX fits */
+CTASSERT(INDEX_MAX * 10 < sizeof (uint64_t) * 8);
+
+void
+nicenum_scale(uint64_t n, size_t units, char *buf, size_t buflen,
+ uint32_t flags)
+{
+ uint64_t divamt = 1024;
+ uint64_t divisor = 1;
+ int index = 0;
+ int rc = 0;
+ char u;
+
+ if (units == 0)
+ units = 1;
+
+ if (n > 0) {
+ n *= units;
+ if (n < units)
+ goto overflow;
+ }
+
+ if (flags & NN_DIVISOR_1000)
+ divamt = 1000;
+
+ /*
+ * This tries to find the suffix S(n) such that
+ * S(n) <= n < S(n+1), where S(n) = 2^(n*10) | 10^(3*n)
+ * (i.e. 1024/1000, 1,048,576/1,000,000, etc). Stop once S(n)
+ * is the largest prefix supported (i.e. don't bother computing
+ * and checking S(n+1). Since INDEX_MAX should be the largest
+ * suffix that fits (currently an exabyte), S(INDEX_MAX + 1) is
+ * never checked as it would overflow.
+ */
+ while (index < INDEX_MAX) {
+ uint64_t newdiv = divisor * divamt;
+
+ /* CTASSERT() guarantee these never trip */
+ VERIFY3U(newdiv, >=, divamt);
+ VERIFY3U(newdiv, >=, divisor);
+
+ if (n < newdiv)
+ break;
+
+ divisor = newdiv;
+ index++;
+ }
+
+ u = " KMGTPE"[index];
+
+ if (index == 0) {
+ rc = snprintf(buf, buflen, "%llu", n);
+ } else if (n % divisor == 0) {
+ /*
+ * If this is an even multiple of the base, always display
+ * without any decimal precision.
+ */
+ rc = snprintf(buf, buflen, "%llu%c", n / divisor, u);
+ } else {
+ /*
+ * We want to choose a precision that reflects the best choice
+ * for fitting in 5 characters. This can get rather tricky
+ * when we have numbers that are very close to an order of
+ * magnitude. For example, when displaying 10239 (which is
+ * really 9.999K), we want only a single place of precision
+ * for 10.0K. We could develop some complex heuristics for
+ * this, but it's much easier just to try each combination
+ * in turn.
+ */
+ int i;
+ for (i = 2; i >= 0; i--) {
+ if ((rc = snprintf(buf, buflen, "%.*f%c", i,
+ (double)n / divisor, u)) <= 5)
+ break;
+ }
+ }
+
+ if (rc + 1 > buflen || rc < 0)
+ goto overflow;
+
+ return;
+
+overflow:
+ /* prefer a more verbose message if possible */
+ if (buflen > 10)
+ (void) strlcpy(buf, "<overflow>", buflen);
+ else
+ (void) strlcpy(buf, "??", buflen);
+}
+
+void
+nicenum(uint64_t num, char *buf, size_t buflen)
+{
+ nicenum_scale(num, 1, buf, buflen, 0);
+}
Property changes on: trunk/cddl/contrib/opensolaris/lib/libcmdutils/common/nicenum.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/cddl/contrib/opensolaris/lib/libcmdutils/libcmdutils.h
===================================================================
--- trunk/cddl/contrib/opensolaris/lib/libcmdutils/libcmdutils.h (rev 0)
+++ trunk/cddl/contrib/opensolaris/lib/libcmdutils/libcmdutils.h 2018-06-02 16:07:30 UTC (rev 10229)
@@ -0,0 +1,236 @@
+/* $MidnightBSD$ */
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+/*
+ * Copyright (c) 2013 RackTop Systems.
+ */
+/*
+ * Copyright 2017 Joyent, Inc.
+ */
+
+/*
+ * Declarations for the functions in libcmdutils.
+ */
+
+#ifndef _LIBCMDUTILS_H
+#define _LIBCMDUTILS_H
+
+#ifdef illumos
+#if !defined(_LP64) && \
+ !((_FILE_OFFSET_BITS == 64) || defined(_LARGEFILE64_SOURCE))
+#error "libcmdutils.h can only be used in a largefile compilation environment"
+#endif
+#endif
+
+/*
+ * This is a private header file. Applications should not directly include
+ * this file.
+ */
+
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <libintl.h>
+#include <string.h>
+#include <dirent.h>
+#ifdef illumos
+#include <attr.h>
+#endif
+#include <sys/avl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/mman.h>
+#include <libnvpair.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* extended system attribute support */
+#define _NOT_SATTR 0
+#define _RO_SATTR 1
+#define _RW_SATTR 2
+
+#define MAXMAPSIZE (1024*1024*8) /* map at most 8MB */
+#define SMALLFILESIZE (32*1024) /* don't use mmap on little file */
+
+/* Type used for a node containing a device id and inode number */
+
+#if defined(_LP64) || (_FILE_OFFSET_BITS == 64)
+typedef struct tree_node {
+ dev_t node_dev;
+ ino_t node_ino;
+ avl_node_t avl_link;
+} tree_node_t;
+#else
+typedef struct tree_node {
+ dev_t node_dev;
+ ino64_t node_ino;
+ avl_node_t avl_link;
+} tree_node_t;
+#endif
+
+ /* extended system attribute support */
+
+/* Determine if a file is the name of an extended system attribute file */
+extern int sysattr_type(char *);
+
+/* Determine if the underlying file system supports system attributes */
+extern int sysattr_support(char *, int);
+
+/* Copies the content of the source file to the target file */
+#if defined(_LP64) || (_FILE_OFFSET_BITS == 64)
+extern int writefile(int, int, char *, char *, char *, char *,
+ struct stat *, struct stat *);
+#else
+extern int writefile(int, int, char *, char *, char *, char *,
+ struct stat64 *, struct stat64 *);
+#endif
+
+/* Gets file descriptors of the source and target attribute files */
+extern int get_attrdirs(int, int, char *, int *, int *);
+
+/* Move extended attribute and extended system attribute */
+extern int mv_xattrs(char *, char *, char *, int, int);
+
+/* Returns non default extended system attribute list */
+extern nvlist_t *sysattr_list(char *, int, char *);
+
+
+
+ /* avltree */
+
+/*
+ * Used to compare two nodes. We are attempting to match the 1st
+ * argument (node) against the 2nd argument (a node which
+ * is already in the search tree).
+ */
+
+extern int tnode_compare(const void *, const void *);
+
+/*
+ * Used to add a single node (containing the input device id and
+ * inode number) to the specified search tree. The calling
+ * application must set the tree pointer to NULL before calling
+ * add_tnode() for the first time.
+ */
+#if defined(_LP64) || (_FILE_OFFSET_BITS == 64)
+extern int add_tnode(avl_tree_t **, dev_t, ino_t);
+#else
+extern int add_tnode(avl_tree_t **, dev_t, ino64_t);
+#endif
+
+/*
+ * Used to destroy a whole tree (all nodes) without rebalancing.
+ * The calling application is responsible for setting the tree
+ * pointer to NULL upon return.
+ */
+extern void destroy_tree(avl_tree_t *);
+
+
+
+ /* user/group id helpers */
+
+/*
+ * Used to get the next available user id in given range.
+ */
+extern int findnextuid(uid_t, uid_t, uid_t *);
+
+/*
+ * Used to get the next available group id in given range.
+ */
+extern int findnextgid(gid_t, gid_t, gid_t *);
+
+
+
+ /* dynamic string utilities */
+
+typedef struct custr custr_t;
+
+/*
+ * Allocate and free a "custr_t" dynamic string object. Returns 0 on success
+ * and -1 otherwise.
+ */
+extern int custr_alloc(custr_t **);
+extern void custr_free(custr_t *);
+
+/*
+ * Allocate a "custr_t" dynamic string object that operates on a fixed external
+ * buffer.
+ */
+extern int custr_alloc_buf(custr_t **, void *, size_t);
+
+/*
+ * Append a single character, or a NUL-terminated string of characters, to a
+ * dynamic string. Returns 0 on success and -1 otherwise. The dynamic string
+ * will be unmodified if the function returns -1.
+ */
+extern int custr_appendc(custr_t *, char);
+extern int custr_append(custr_t *, const char *);
+
+/*
+ * Append a format string and arguments as though the contents were being parsed
+ * through snprintf. Returns 0 on success and -1 otherwise. The dynamic string
+ * will be unmodified if the function returns -1.
+ */
+extern int custr_append_printf(custr_t *, const char *, ...);
+extern int custr_append_vprintf(custr_t *, const char *, va_list);
+
+/*
+ * Determine the length in bytes, not including the NUL terminator, of the
+ * dynamic string.
+ */
+extern size_t custr_len(custr_t *);
+
+/*
+ * Clear the contents of a dynamic string. Does not free the underlying
+ * memory.
+ */
+extern void custr_reset(custr_t *);
+
+/*
+ * Retrieve a const pointer to a NUL-terminated string version of the contents
+ * of the dynamic string. Storage for this string should not be freed, and
+ * the pointer will be invalidated by any mutations to the dynamic string.
+ */
+extern const char *custr_cstr(custr_t *str);
+
+#define NN_DIVISOR_1000 (1U << 0)
+
+/* Minimum size for the output of nicenum, including NULL */
+#define NN_NUMBUF_SZ (6)
+
+void nicenum(uint64_t, char *, size_t);
+void nicenum_scale(uint64_t, size_t, char *, size_t, uint32_t);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _LIBCMDUTILS_H */
Property changes on: trunk/cddl/contrib/opensolaris/lib/libcmdutils/libcmdutils.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Modified: trunk/cddl/contrib/opensolaris/lib/libctf/common/ctf_lib.c
===================================================================
--- trunk/cddl/contrib/opensolaris/lib/libctf/common/ctf_lib.c 2018-06-02 16:07:17 UTC (rev 10228)
+++ trunk/cddl/contrib/opensolaris/lib/libctf/common/ctf_lib.c 2018-06-02 16:07:30 UTC (rev 10229)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*
* CDDL HEADER START
*
@@ -34,7 +35,7 @@
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
-#if defined(sun)
+#ifdef illumos
#include <dlfcn.h>
#else
#include <zlib.h>
@@ -41,7 +42,7 @@
#endif
#include <gelf.h>
-#if defined(sun)
+#ifdef illumos
#ifdef _LP64
static const char *_libctf_zlib = "/usr/lib/64/libz.so";
#else
@@ -58,7 +59,7 @@
static size_t _PAGESIZE;
static size_t _PAGEMASK;
-#if defined(sun)
+#ifdef illumos
#pragma init(_libctf_init)
#else
void _libctf_init(void) __attribute__ ((constructor));
@@ -66,7 +67,7 @@
void
_libctf_init(void)
{
-#if defined(sun)
+#ifdef illumos
const char *p = getenv("LIBCTF_DECOMPRESSOR");
if (p != NULL)
@@ -87,7 +88,7 @@
void *
ctf_zopen(int *errp)
{
-#if defined(sun)
+#ifdef illumos
ctf_dprintf("decompressing CTF data using %s\n", _libctf_zlib);
if (zlib.z_dlp != NULL)
@@ -216,6 +217,7 @@
{
ctf_sect_t ctfsect, symsect, strsect;
ctf_file_t *fp = NULL;
+ size_t shstrndx, shnum;
struct stat64 st;
ssize_t nbytes;
@@ -273,16 +275,15 @@
*/
if (nbytes >= (ssize_t) sizeof (Elf32_Ehdr) &&
bcmp(&hdr.e32.e_ident[EI_MAG0], ELFMAG, SELFMAG) == 0) {
-#ifdef _BIG_ENDIAN
+#if BYTE_ORDER == _BIG_ENDIAN
uchar_t order = ELFDATA2MSB;
#else
uchar_t order = ELFDATA2LSB;
#endif
- GElf_Half i, n;
GElf_Shdr *sp;
void *strs_map;
- size_t strs_mapsz;
+ size_t strs_mapsz, i;
char *strs;
if (hdr.e32.e_ident[EI_DATA] != order)
@@ -298,11 +299,38 @@
ehdr_to_gelf(&e32, &hdr.e64);
}
- if (hdr.e64.e_shstrndx >= hdr.e64.e_shnum)
+ shnum = hdr.e64.e_shnum;
+ shstrndx = hdr.e64.e_shstrndx;
+
+ /* Extended ELF sections */
+ if ((shstrndx == SHN_XINDEX) || (shnum == 0)) {
+ if (hdr.e32.e_ident[EI_CLASS] == ELFCLASS32) {
+ Elf32_Shdr x32;
+
+ if (pread64(fd, &x32, sizeof (x32),
+ hdr.e64.e_shoff) != sizeof (x32))
+ return (ctf_set_open_errno(errp,
+ errno));
+
+ shnum = x32.sh_size;
+ shstrndx = x32.sh_link;
+ } else {
+ Elf64_Shdr x64;
+
+ if (pread64(fd, &x64, sizeof (x64),
+ hdr.e64.e_shoff) != sizeof (x64))
+ return (ctf_set_open_errno(errp,
+ errno));
+
+ shnum = x64.sh_size;
+ shstrndx = x64.sh_link;
+ }
+ }
+
+ if (shstrndx >= shnum)
return (ctf_set_open_errno(errp, ECTF_CORRUPT));
- n = hdr.e64.e_shnum;
- nbytes = sizeof (GElf_Shdr) * n;
+ nbytes = sizeof (GElf_Shdr) * shnum;
if ((sp = malloc(nbytes)) == NULL)
return (ctf_set_open_errno(errp, errno));
@@ -314,7 +342,7 @@
if (hdr.e32.e_ident[EI_CLASS] == ELFCLASS32) {
Elf32_Shdr *sp32;
- nbytes = sizeof (Elf32_Shdr) * n;
+ nbytes = sizeof (Elf32_Shdr) * shnum;
if ((sp32 = malloc(nbytes)) == NULL || pread64(fd,
sp32, nbytes, hdr.e64.e_shoff) != nbytes) {
@@ -322,7 +350,7 @@
return (ctf_set_open_errno(errp, errno));
}
- for (i = 0; i < n; i++)
+ for (i = 0; i < shnum; i++)
shdr_to_gelf(&sp32[i], &sp[i]);
free(sp32);
@@ -336,14 +364,14 @@
* Now mmap the section header strings section so that we can
* perform string comparison on the section names.
*/
- strs_mapsz = sp[hdr.e64.e_shstrndx].sh_size +
- (sp[hdr.e64.e_shstrndx].sh_offset & ~_PAGEMASK);
+ strs_mapsz = sp[shstrndx].sh_size +
+ (sp[shstrndx].sh_offset & ~_PAGEMASK);
strs_map = mmap64(NULL, strs_mapsz, PROT_READ, MAP_PRIVATE,
- fd, sp[hdr.e64.e_shstrndx].sh_offset & _PAGEMASK);
+ fd, sp[shstrndx].sh_offset & _PAGEMASK);
strs = (char *)strs_map +
- (sp[hdr.e64.e_shstrndx].sh_offset & ~_PAGEMASK);
+ (sp[shstrndx].sh_offset & ~_PAGEMASK);
if (strs_map == MAP_FAILED) {
free(sp);
@@ -354,15 +382,15 @@
* Iterate over the section header array looking for the CTF
* section and symbol table. The strtab is linked to symtab.
*/
- for (i = 0; i < n; i++) {
+ for (i = 0; i < shnum; i++) {
const GElf_Shdr *shp = &sp[i];
const GElf_Shdr *lhp = &sp[shp->sh_link];
- if (shp->sh_link >= hdr.e64.e_shnum)
+ if (shp->sh_link >= shnum)
continue; /* corrupt sh_link field */
- if (shp->sh_name >= sp[hdr.e64.e_shstrndx].sh_size ||
- lhp->sh_name >= sp[hdr.e64.e_shstrndx].sh_size)
+ if (shp->sh_name >= sp[shstrndx].sh_size ||
+ lhp->sh_name >= sp[shstrndx].sh_size)
continue; /* corrupt sh_name field */
if (shp->sh_type == SHT_PROGBITS &&
Modified: trunk/cddl/contrib/opensolaris/lib/libctf/common/ctf_subr.c
===================================================================
--- trunk/cddl/contrib/opensolaris/lib/libctf/common/ctf_subr.c 2018-06-02 16:07:17 UTC (rev 10228)
+++ trunk/cddl/contrib/opensolaris/lib/libctf/common/ctf_subr.c 2018-06-02 16:07:30 UTC (rev 10229)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*
* CDDL HEADER START
*
Modified: trunk/cddl/contrib/opensolaris/lib/libctf/common/libctf.h
===================================================================
--- trunk/cddl/contrib/opensolaris/lib/libctf/common/libctf.h 2018-06-02 16:07:17 UTC (rev 10228)
+++ trunk/cddl/contrib/opensolaris/lib/libctf/common/libctf.h 2018-06-02 16:07:30 UTC (rev 10229)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*
* CDDL HEADER START
*
Modified: trunk/cddl/contrib/opensolaris/lib/libdtrace/common/drti.c
===================================================================
--- trunk/cddl/contrib/opensolaris/lib/libdtrace/common/drti.c 2018-06-02 16:07:17 UTC (rev 10228)
+++ trunk/cddl/contrib/opensolaris/lib/libdtrace/common/drti.c 2018-06-02 16:07:30 UTC (rev 10229)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*
* CDDL HEADER START
*
@@ -20,6 +21,7 @@
*/
/*
* Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2013 Voxer Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -55,13 +57,13 @@
*/
static const char *devnamep = "/dev/dtrace/helper";
-#if defined(sun)
+#ifdef illumos
static const char *olddevname = "/devices/pseudo/dtrace at 0:helper";
#endif
static const char *modname; /* Name of this load object */
static int gen; /* DOF helper generation */
-#if defined(sun)
+#ifdef illumos
extern dof_hdr_t __SUNW_dof; /* DOF defined in the .SUNW_dof section */
#endif
static boolean_t dof_init_debug = B_FALSE; /* From DTRACE_DOF_INIT_DEBUG */
@@ -89,7 +91,7 @@
va_end(ap);
}
-#if !defined(sun)
+#ifndef illumos
static void
fixsymbol(Elf *e, Elf_Data *data, size_t idx, int nprobes, char *buf,
dof_sec_t *sec, int *fixedprobes, char *dofstrtab)
@@ -119,7 +121,7 @@
}
#endif
-#if defined(sun)
+#ifdef illumos
#pragma init(dtrace_dof_init)
#else
static void dtrace_dof_init(void) __attribute__ ((constructor));
@@ -128,7 +130,7 @@
static void
dtrace_dof_init(void)
{
-#if defined(sun)
+#ifdef illumos
dof_hdr_t *dof = &__SUNW_dof;
#else
dof_hdr_t *dof = NULL;
@@ -140,26 +142,29 @@
#endif
dof_helper_t dh;
Link_map *lmp;
-#if defined(sun)
+#ifdef illumos
Lmid_t lmid;
#else
u_long lmid = 0;
- dof_sec_t *sec;
+ dof_sec_t *sec, *secstart, *dofstrtab, *dofprobes;
+ dof_provider_t *dofprovider;
size_t i;
#endif
int fd;
const char *p;
-#if !defined(sun)
+#ifndef illumos
Elf *e;
Elf_Scn *scn = NULL;
- Elf_Data *symtabdata = NULL, *dynsymdata = NULL;
+ Elf_Data *symtabdata = NULL, *dynsymdata = NULL, *dofdata = NULL;
+ dof_hdr_t *dof_next = NULL;
GElf_Shdr shdr;
int efd, nprobes;
char *s;
+ char *dofstrtabraw;
size_t shstridx, symtabidx = 0, dynsymidx = 0;
- unsigned char *dofstrtab = NULL;
unsigned char *buf;
- int fixedprobes = 0;
+ int fixedprobes;
+ uint64_t aligned_filesz;
#endif
if (getenv("DTRACE_DOF_INIT_DISABLE") != NULL)
@@ -173,7 +178,7 @@
return;
}
-#if defined(sun)
+#ifdef illumos
if (dlinfo(RTLD_SELF, RTLD_DI_LMID, &lmid) == -1) {
dprintf(1, "couldn't discover link map ID\n");
return;
@@ -185,7 +190,7 @@
modname = lmp->l_name;
else
modname++;
-#if !defined(sun)
+#ifndef illumos
elf_version(EV_CURRENT);
if ((efd = open(lmp->l_name, O_RDONLY, 0)) < 0) {
dprintf(1, "couldn't open file for reading\n");
@@ -209,7 +214,8 @@
} else if (shdr.sh_type == SHT_PROGBITS) {
s = elf_strptr(e, shstridx, shdr.sh_name);
if (s && strcmp(s, ".SUNW_dof") == 0) {
- dof = elf_getdata(scn, NULL)->d_buf;
+ dofdata = elf_getdata(scn, NULL);
+ dof = dofdata->d_buf;
}
}
}
@@ -219,6 +225,12 @@
close(efd);
return;
}
+
+ while ((char *) dof < (char *) dofdata->d_buf + dofdata->d_size) {
+ fixedprobes = 0;
+ aligned_filesz = (shdr.sh_addralign == 0 ? dof->dofh_filesz :
+ roundup2(dof->dofh_filesz, shdr.sh_addralign));
+ dof_next = (void *) ((char *) dof + aligned_filesz);
#endif
if (dof->dofh_ident[DOF_ID_MAG0] != DOF_MAG_MAG0 ||
@@ -247,7 +259,7 @@
if ((fd = open64(devnamep, O_RDWR)) < 0) {
dprintf(1, "failed to open helper device %s", devnamep);
-#if defined(sun)
+#ifdef illumos
/*
* If the device path wasn't explicitly set, try again with
* the old device path.
@@ -290,53 +302,73 @@
* We are assuming the number of probes is less than the number of
* symbols (libc can have 4k symbols, for example).
*/
- sec = (dof_sec_t *)(dof + 1);
+ secstart = sec = (dof_sec_t *)(dof + 1);
buf = (char *)dof;
for (i = 0; i < dof->dofh_secnum; i++, sec++) {
- if (sec->dofs_type == DOF_SECT_STRTAB)
- dofstrtab = (unsigned char *)(buf + sec->dofs_offset);
- else if (sec->dofs_type == DOF_SECT_PROBES && dofstrtab)
+ if (sec->dofs_type != DOF_SECT_PROVIDER)
+ continue;
+
+ dofprovider = (void *) (buf + sec->dofs_offset);
+ dofstrtab = secstart + dofprovider->dofpv_strtab;
+ dofprobes = secstart + dofprovider->dofpv_probes;
+
+ if (dofstrtab->dofs_type != DOF_SECT_STRTAB) {
+ fprintf(stderr, "WARNING: expected STRTAB section, but got %d\n",
+ dofstrtab->dofs_type);
break;
-
+ }
+ if (dofprobes->dofs_type != DOF_SECT_PROBES) {
+ fprintf(stderr, "WARNING: expected PROBES section, but got %d\n",
+ dofprobes->dofs_type);
+ break;
+ }
+
+ dprintf(1, "found provider %p\n", dofprovider);
+ dofstrtabraw = (char *)(buf + dofstrtab->dofs_offset);
+ nprobes = dofprobes->dofs_size / dofprobes->dofs_entsize;
+ fixsymbol(e, symtabdata, symtabidx, nprobes, buf, dofprobes, &fixedprobes,
+ dofstrtabraw);
+ if (fixedprobes != nprobes) {
+ /*
+ * If we haven't fixed all the probes using the
+ * symtab section, look inside the dynsym
+ * section.
+ */
+ fixsymbol(e, dynsymdata, dynsymidx, nprobes, buf, dofprobes,
+ &fixedprobes, dofstrtabraw);
+ }
+ if (fixedprobes != nprobes) {
+ fprintf(stderr, "WARNING: number of probes "
+ "fixed does not match the number of "
+ "defined probes (%d != %d, "
+ "respectively)\n", fixedprobes, nprobes);
+ fprintf(stderr, "WARNING: some probes might "
+ "not fire or your program might crash\n");
+ }
}
- nprobes = sec->dofs_size / sec->dofs_entsize;
- fixsymbol(e, symtabdata, symtabidx, nprobes, buf, sec, &fixedprobes,
- dofstrtab);
- if (fixedprobes != nprobes) {
- /*
- * If we haven't fixed all the probes using the
- * symtab section, look inside the dynsym
- * section.
- */
- fixsymbol(e, dynsymdata, dynsymidx, nprobes, buf, sec,
- &fixedprobes, dofstrtab);
- }
- if (fixedprobes != nprobes) {
- fprintf(stderr, "WARNING: number of probes "
- "fixed does not match the number of "
- "defined probes (%d != %d, "
- "respectively)\n", fixedprobes, nprobes);
- fprintf(stderr, "WARNING: some probes might "
- "not fire or your program might crash\n");
- }
#endif
if ((gen = ioctl(fd, DTRACEHIOC_ADDDOF, &dh)) == -1)
dprintf(1, "DTrace ioctl failed for DOF at %p", dof);
else {
dprintf(1, "DTrace ioctl succeeded for DOF at %p\n", dof);
-#if !defined(sun)
+#ifndef illumos
gen = dh.gen;
#endif
}
(void) close(fd);
-#if !defined(sun)
+
+#ifndef illumos
+ /* End of while loop */
+ dof = dof_next;
+ }
+
elf_end(e);
(void) close(efd);
#endif
}
-#if defined(sun)
+#ifdef illumos
#pragma fini(dtrace_dof_fini)
#else
static void dtrace_dof_fini(void) __attribute__ ((destructor));
Modified: trunk/cddl/contrib/opensolaris/lib/libdtrace/common/dt_aggregate.c
===================================================================
--- trunk/cddl/contrib/opensolaris/lib/libdtrace/common/dt_aggregate.c 2018-06-02 16:07:17 UTC (rev 10228)
+++ trunk/cddl/contrib/opensolaris/lib/libdtrace/common/dt_aggregate.c 2018-06-02 16:07:30 UTC (rev 10229)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*
* CDDL HEADER START
*
@@ -25,7 +26,8 @@
*/
/*
- * Copyright (c) 2011, Joyent, Inc. All rights reserved.
+ * Copyright (c) 2013, Joyent, Inc. All rights reserved.
+ * Copyright (c) 2012 by Delphix. All rights reserved.
*/
#include <stdlib.h>
@@ -34,7 +36,7 @@
#include <unistd.h>
#include <dt_impl.h>
#include <assert.h>
-#if defined(sun)
+#ifdef illumos
#include <alloca.h>
#else
#include <sys/sysctl.h>
@@ -452,7 +454,7 @@
buf->dtbd_cpu = cpu;
-#if defined(sun)
+#ifdef illumos
if (dt_ioctl(dtp, DTRACEIOC_AGGSNAP, buf) == -1) {
#else
if (dt_ioctl(dtp, DTRACEIOC_AGGSNAP, &buf) == -1) {
@@ -894,34 +896,15 @@
caddr_t rdata = rh->dtahe_data.dtada_data;
dtrace_recdesc_t *lrec, *rrec;
int64_t *laddr, *raddr;
- int rval, i;
+ int rval;
- if ((rval = dt_aggregate_hashcmp(lhs, rhs)) != 0)
- return (rval);
+ assert(lagg->dtagd_nrecs == ragg->dtagd_nrecs);
- if (lagg->dtagd_nrecs > ragg->dtagd_nrecs)
- return (DT_GREATERTHAN);
+ lrec = &lagg->dtagd_rec[lagg->dtagd_nrecs - 1];
+ rrec = &ragg->dtagd_rec[ragg->dtagd_nrecs - 1];
- if (lagg->dtagd_nrecs < ragg->dtagd_nrecs)
- return (DT_LESSTHAN);
+ assert(lrec->dtrd_action == rrec->dtrd_action);
- for (i = 0; i < lagg->dtagd_nrecs; i++) {
- lrec = &lagg->dtagd_rec[i];
- rrec = &ragg->dtagd_rec[i];
-
- if (lrec->dtrd_offset < rrec->dtrd_offset)
- return (DT_LESSTHAN);
-
- if (lrec->dtrd_offset > rrec->dtrd_offset)
- return (DT_GREATERTHAN);
-
- if (lrec->dtrd_action < rrec->dtrd_action)
- return (DT_LESSTHAN);
-
- if (lrec->dtrd_action > rrec->dtrd_action)
- return (DT_GREATERTHAN);
- }
-
laddr = (int64_t *)(uintptr_t)(ldata + lrec->dtrd_offset);
raddr = (int64_t *)(uintptr_t)(rdata + rrec->dtrd_offset);
@@ -1319,6 +1302,231 @@
}
static int
+dt_aggregate_total(dtrace_hdl_t *dtp, boolean_t clear)
+{
+ dt_ahashent_t *h;
+ dtrace_aggdata_t **total;
+ dtrace_aggid_t max = DTRACE_AGGVARIDNONE, id;
+ dt_aggregate_t *agp = &dtp->dt_aggregate;
+ dt_ahash_t *hash = &agp->dtat_hash;
+ uint32_t tflags;
+
+ tflags = DTRACE_A_TOTAL | DTRACE_A_HASNEGATIVES | DTRACE_A_HASPOSITIVES;
+
+ /*
+ * If we need to deliver per-aggregation totals, we're going to take
+ * three passes over the aggregate: one to clear everything out and
+ * determine our maximum aggregation ID, one to actually total
+ * everything up, and a final pass to assign the totals to the
+ * individual elements.
+ */
+ for (h = hash->dtah_all; h != NULL; h = h->dtahe_nextall) {
+ dtrace_aggdata_t *aggdata = &h->dtahe_data;
+
+ if ((id = dt_aggregate_aggvarid(h)) > max)
+ max = id;
+
+ aggdata->dtada_total = 0;
+ aggdata->dtada_flags &= ~tflags;
+ }
+
+ if (clear || max == DTRACE_AGGVARIDNONE)
+ return (0);
+
+ total = dt_zalloc(dtp, (max + 1) * sizeof (dtrace_aggdata_t *));
+
+ if (total == NULL)
+ return (-1);
+
+ for (h = hash->dtah_all; h != NULL; h = h->dtahe_nextall) {
+ dtrace_aggdata_t *aggdata = &h->dtahe_data;
+ dtrace_aggdesc_t *agg = aggdata->dtada_desc;
+ dtrace_recdesc_t *rec;
+ caddr_t data;
+ int64_t val, *addr;
+
+ rec = &agg->dtagd_rec[agg->dtagd_nrecs - 1];
+ data = aggdata->dtada_data;
+ addr = (int64_t *)(uintptr_t)(data + rec->dtrd_offset);
+
+ switch (rec->dtrd_action) {
+ case DTRACEAGG_STDDEV:
+ val = dt_stddev((uint64_t *)addr, 1);
+ break;
+
+ case DTRACEAGG_SUM:
+ case DTRACEAGG_COUNT:
+ val = *addr;
+ break;
+
+ case DTRACEAGG_AVG:
+ val = addr[0] ? (addr[1] / addr[0]) : 0;
+ break;
+
+ default:
+ continue;
+ }
+
+ if (total[agg->dtagd_varid] == NULL) {
+ total[agg->dtagd_varid] = aggdata;
+ aggdata->dtada_flags |= DTRACE_A_TOTAL;
+ } else {
+ aggdata = total[agg->dtagd_varid];
+ }
+
+ if (val > 0)
+ aggdata->dtada_flags |= DTRACE_A_HASPOSITIVES;
+
+ if (val < 0) {
+ aggdata->dtada_flags |= DTRACE_A_HASNEGATIVES;
+ val = -val;
+ }
+
+ if (dtp->dt_options[DTRACEOPT_AGGZOOM] != DTRACEOPT_UNSET) {
+ val = (int64_t)((long double)val *
+ (1 / DTRACE_AGGZOOM_MAX));
+
+ if (val > aggdata->dtada_total)
+ aggdata->dtada_total = val;
+ } else {
+ aggdata->dtada_total += val;
+ }
+ }
+
+ /*
+ * And now one final pass to set everyone's total.
+ */
+ for (h = hash->dtah_all; h != NULL; h = h->dtahe_nextall) {
+ dtrace_aggdata_t *aggdata = &h->dtahe_data, *t;
+ dtrace_aggdesc_t *agg = aggdata->dtada_desc;
+
+ if ((t = total[agg->dtagd_varid]) == NULL || aggdata == t)
+ continue;
+
+ aggdata->dtada_total = t->dtada_total;
+ aggdata->dtada_flags |= (t->dtada_flags & tflags);
+ }
+
+ dt_free(dtp, total);
+
+ return (0);
+}
+
+static int
+dt_aggregate_minmaxbin(dtrace_hdl_t *dtp, boolean_t clear)
+{
+ dt_ahashent_t *h;
+ dtrace_aggdata_t **minmax;
+ dtrace_aggid_t max = DTRACE_AGGVARIDNONE, id;
+ dt_aggregate_t *agp = &dtp->dt_aggregate;
+ dt_ahash_t *hash = &agp->dtat_hash;
+
+ for (h = hash->dtah_all; h != NULL; h = h->dtahe_nextall) {
+ dtrace_aggdata_t *aggdata = &h->dtahe_data;
+
+ if ((id = dt_aggregate_aggvarid(h)) > max)
+ max = id;
+
+ aggdata->dtada_minbin = 0;
+ aggdata->dtada_maxbin = 0;
+ aggdata->dtada_flags &= ~DTRACE_A_MINMAXBIN;
+ }
+
+ if (clear || max == DTRACE_AGGVARIDNONE)
+ return (0);
+
+ minmax = dt_zalloc(dtp, (max + 1) * sizeof (dtrace_aggdata_t *));
+
+ if (minmax == NULL)
+ return (-1);
+
+ for (h = hash->dtah_all; h != NULL; h = h->dtahe_nextall) {
+ dtrace_aggdata_t *aggdata = &h->dtahe_data;
+ dtrace_aggdesc_t *agg = aggdata->dtada_desc;
+ dtrace_recdesc_t *rec;
+ caddr_t data;
+ int64_t *addr;
+ int minbin = -1, maxbin = -1, i;
+ int start = 0, size;
+
+ rec = &agg->dtagd_rec[agg->dtagd_nrecs - 1];
+ size = rec->dtrd_size / sizeof (int64_t);
+ data = aggdata->dtada_data;
+ addr = (int64_t *)(uintptr_t)(data + rec->dtrd_offset);
+
+ switch (rec->dtrd_action) {
+ case DTRACEAGG_LQUANTIZE:
+ /*
+ * For lquantize(), we always display the entire range
+ * of the aggregation when aggpack is set.
+ */
+ start = 1;
+ minbin = start;
+ maxbin = size - 1 - start;
+ break;
+
+ case DTRACEAGG_QUANTIZE:
+ for (i = start; i < size; i++) {
+ if (!addr[i])
+ continue;
+
+ if (minbin == -1)
+ minbin = i - start;
+
+ maxbin = i - start;
+ }
+
+ if (minbin == -1) {
+ /*
+ * If we have no data (e.g., due to a clear()
+ * or negative increments), we'll use the
+ * zero bucket as both our min and max.
+ */
+ minbin = maxbin = DTRACE_QUANTIZE_ZEROBUCKET;
+ }
+
+ break;
+
+ default:
+ continue;
+ }
+
+ if (minmax[agg->dtagd_varid] == NULL) {
+ minmax[agg->dtagd_varid] = aggdata;
+ aggdata->dtada_flags |= DTRACE_A_MINMAXBIN;
+ aggdata->dtada_minbin = minbin;
+ aggdata->dtada_maxbin = maxbin;
+ continue;
+ }
+
+ if (minbin < minmax[agg->dtagd_varid]->dtada_minbin)
+ minmax[agg->dtagd_varid]->dtada_minbin = minbin;
+
+ if (maxbin > minmax[agg->dtagd_varid]->dtada_maxbin)
+ minmax[agg->dtagd_varid]->dtada_maxbin = maxbin;
+ }
+
+ /*
+ * And now one final pass to set everyone's minbin and maxbin.
+ */
+ for (h = hash->dtah_all; h != NULL; h = h->dtahe_nextall) {
+ dtrace_aggdata_t *aggdata = &h->dtahe_data, *mm;
+ dtrace_aggdesc_t *agg = aggdata->dtada_desc;
+
+ if ((mm = minmax[agg->dtagd_varid]) == NULL || aggdata == mm)
+ continue;
+
+ aggdata->dtada_minbin = mm->dtada_minbin;
+ aggdata->dtada_maxbin = mm->dtada_maxbin;
+ aggdata->dtada_flags |= DTRACE_A_MINMAXBIN;
+ }
+
+ dt_free(dtp, minmax);
+
+ return (0);
+}
+
+static int
dt_aggregate_walk_sorted(dtrace_hdl_t *dtp,
dtrace_aggregate_f *func, void *arg,
int (*sfunc)(const void *, const void *))
@@ -1327,7 +1535,24 @@
dt_ahashent_t *h, **sorted;
dt_ahash_t *hash = &agp->dtat_hash;
size_t i, nentries = 0;
+ int rval = -1;
+ agp->dtat_flags &= ~(DTRACE_A_TOTAL | DTRACE_A_MINMAXBIN);
+
+ if (dtp->dt_options[DTRACEOPT_AGGHIST] != DTRACEOPT_UNSET) {
+ agp->dtat_flags |= DTRACE_A_TOTAL;
+
+ if (dt_aggregate_total(dtp, B_FALSE) != 0)
+ return (-1);
+ }
+
+ if (dtp->dt_options[DTRACEOPT_AGGPACK] != DTRACEOPT_UNSET) {
+ agp->dtat_flags |= DTRACE_A_MINMAXBIN;
+
+ if (dt_aggregate_minmaxbin(dtp, B_FALSE) != 0)
+ return (-1);
+ }
+
for (h = hash->dtah_all; h != NULL; h = h->dtahe_nextall)
nentries++;
@@ -1334,7 +1559,7 @@
sorted = dt_alloc(dtp, nentries * sizeof (dt_ahashent_t *));
if (sorted == NULL)
- return (-1);
+ goto out;
for (h = hash->dtah_all, i = 0; h != NULL; h = h->dtahe_nextall)
sorted[i++] = h;
@@ -1358,14 +1583,20 @@
for (i = 0; i < nentries; i++) {
h = sorted[i];
- if (dt_aggwalk_rval(dtp, h, func(&h->dtahe_data, arg)) == -1) {
- dt_free(dtp, sorted);
- return (-1);
- }
+ if (dt_aggwalk_rval(dtp, h, func(&h->dtahe_data, arg)) == -1)
+ goto out;
}
+ rval = 0;
+out:
+ if (agp->dtat_flags & DTRACE_A_TOTAL)
+ (void) dt_aggregate_total(dtp, B_TRUE);
+
+ if (agp->dtat_flags & DTRACE_A_MINMAXBIN)
+ (void) dt_aggregate_minmaxbin(dtp, B_TRUE);
+
dt_free(dtp, sorted);
- return (0);
+ return (rval);
}
int
@@ -1888,6 +2119,8 @@
{
dt_print_aggdata_t pd;
+ bzero(&pd, sizeof (pd));
+
pd.dtpa_dtp = dtp;
pd.dtpa_fp = fp;
pd.dtpa_allunprint = 1;
Modified: trunk/cddl/contrib/opensolaris/lib/libdtrace/common/dt_as.c
===================================================================
--- trunk/cddl/contrib/opensolaris/lib/libdtrace/common/dt_as.c 2018-06-02 16:07:17 UTC (rev 10228)
+++ trunk/cddl/contrib/opensolaris/lib/libdtrace/common/dt_as.c 2018-06-02 16:07:30 UTC (rev 10229)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*
* CDDL HEADER START
*
@@ -23,9 +24,11 @@
* Copyright 2005 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
+/*
+ * Copyright (c) 2013 by Delphix. All rights reserved.
+ * Copyright (c) 2013 Joyent, Inc. All rights reserved.
+ */
-#pragma ident "%Z%%M% %I% %E% SMI"
-
#include <sys/types.h>
#include <strings.h>
#include <stdlib.h>
@@ -125,7 +128,7 @@
dvp->dtdv_flags |= DIFV_F_MOD;
bzero(&dn, sizeof (dn));
- dt_node_type_assign(&dn, idp->di_ctfp, idp->di_type);
+ dt_node_type_assign(&dn, idp->di_ctfp, idp->di_type, B_FALSE);
dt_node_diftype(pcb->pcb_hdl, &dn, &dvp->dtdv_type);
idp->di_flags &= ~(DT_IDFLG_DIFR | DT_IDFLG_DIFW);
Modified: trunk/cddl/contrib/opensolaris/lib/libdtrace/common/dt_as.h
===================================================================
--- trunk/cddl/contrib/opensolaris/lib/libdtrace/common/dt_as.h 2018-06-02 16:07:17 UTC (rev 10228)
+++ trunk/cddl/contrib/opensolaris/lib/libdtrace/common/dt_as.h 2018-06-02 16:07:30 UTC (rev 10229)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*
* CDDL HEADER START
*
Modified: trunk/cddl/contrib/opensolaris/lib/libdtrace/common/dt_buf.c
===================================================================
--- trunk/cddl/contrib/opensolaris/lib/libdtrace/common/dt_buf.c 2018-06-02 16:07:17 UTC (rev 10228)
+++ trunk/cddl/contrib/opensolaris/lib/libdtrace/common/dt_buf.c 2018-06-02 16:07:30 UTC (rev 10229)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*
* CDDL HEADER START
*
Modified: trunk/cddl/contrib/opensolaris/lib/libdtrace/common/dt_buf.h
===================================================================
--- trunk/cddl/contrib/opensolaris/lib/libdtrace/common/dt_buf.h 2018-06-02 16:07:17 UTC (rev 10228)
+++ trunk/cddl/contrib/opensolaris/lib/libdtrace/common/dt_buf.h 2018-06-02 16:07:30 UTC (rev 10229)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*
* CDDL HEADER START
*
Modified: trunk/cddl/contrib/opensolaris/lib/libdtrace/common/dt_cc.c
===================================================================
--- trunk/cddl/contrib/opensolaris/lib/libdtrace/common/dt_cc.c 2018-06-02 16:07:17 UTC (rev 10228)
+++ trunk/cddl/contrib/opensolaris/lib/libdtrace/common/dt_cc.c 2018-06-02 16:07:30 UTC (rev 10229)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*
* CDDL HEADER START
*
@@ -21,8 +22,8 @@
/*
* Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2011, Joyent Inc. All rights reserved.
- * Copyright (c) 2011 by Delphix. All rights reserved.
+ * Copyright (c) 2013, Joyent Inc. All rights reserved.
+ * Copyright (c) 2012 by Delphix. All rights reserved.
*/
/*
@@ -663,64 +664,76 @@
static void
dt_action_trace(dtrace_hdl_t *dtp, dt_node_t *dnp, dtrace_stmtdesc_t *sdp)
{
+ int ctflib;
+
dtrace_actdesc_t *ap = dt_stmt_action(dtp, sdp);
+ boolean_t istrace = (dnp->dn_ident->di_id == DT_ACT_TRACE);
+ const char *act = istrace ? "trace" : "print";
if (dt_node_is_void(dnp->dn_args)) {
- dnerror(dnp->dn_args, D_TRACE_VOID,
- "trace( ) may not be applied to a void expression\n");
+ dnerror(dnp->dn_args, istrace ? D_TRACE_VOID : D_PRINT_VOID,
+ "%s( ) may not be applied to a void expression\n", act);
}
- if (dt_node_is_dynamic(dnp->dn_args)) {
- dnerror(dnp->dn_args, D_TRACE_DYN,
- "trace( ) may not be applied to a dynamic expression\n");
+ if (dt_node_resolve(dnp->dn_args, DT_IDENT_XLPTR) != NULL) {
+ dnerror(dnp->dn_args, istrace ? D_TRACE_DYN : D_PRINT_DYN,
+ "%s( ) may not be applied to a translated pointer\n", act);
}
+ if (dnp->dn_args->dn_kind == DT_NODE_AGG) {
+ dnerror(dnp->dn_args, istrace ? D_TRACE_AGG : D_PRINT_AGG,
+ "%s( ) may not be applied to an aggregation%s\n", act,
+ istrace ? "" : " -- did you mean printa()?");
+ }
+
dt_cg(yypcb, dnp->dn_args);
- ap->dtad_difo = dt_as(yypcb);
- ap->dtad_kind = DTRACEACT_DIFEXPR;
-}
-/*
- * The print() action behaves identically to trace(), except that it stores the
- * CTF type of the argument (if present) within the DOF for the DIFEXPR action.
- * To do this, we set the 'dtsd_strdata' to point to the fully-qualified CTF
- * type ID for the result of the DIF action. We use the ID instead of the name
- * to handles complex types like arrays and function pointers that can't be
- * resolved by ctf_type_lookup(). This is later processed by
- * dtrace_dof_create() and turned into a reference into the string table so
- * that we can get the type information when we process the data after the
- * fact.
- */
-static void
-dt_action_print(dtrace_hdl_t *dtp, dt_node_t *dnp, dtrace_stmtdesc_t *sdp)
-{
- dtrace_actdesc_t *ap = dt_stmt_action(dtp, sdp);
- dt_node_t *dret;
- size_t len;
- dt_module_t *dmp;
+ /*
+ * The print() action behaves identically to trace(), except that it
+ * stores the CTF type of the argument (if present) within the DOF for
+ * the DIFEXPR action. To do this, we set the 'dtsd_strdata' to point
+ * to the fully-qualified CTF type ID for the result of the DIF
+ * action. We use the ID instead of the name to handles complex types
+ * like arrays and function pointers that can't be resolved by
+ * ctf_type_lookup(). This is later processed by dtrace_dof_create()
+ * and turned into a reference into the string table so that we can
+ * get the type information when we process the data after the fact. In
+ * the case where we are referring to userland CTF data, we also need to
+ * to identify which ctf container in question we care about and encode
+ * that within the name.
+ */
+ if (dnp->dn_ident->di_id == DT_ACT_PRINT) {
+ dt_node_t *dret;
+ size_t n;
+ dt_module_t *dmp;
- if (dt_node_is_void(dnp->dn_args)) {
- dnerror(dnp->dn_args, D_PRINT_VOID,
- "print( ) may not be applied to a void expression\n");
- }
+ dret = yypcb->pcb_dret;
+ dmp = dt_module_lookup_by_ctf(dtp, dret->dn_ctfp);
- if (dt_node_is_dynamic(dnp->dn_args)) {
- dnerror(dnp->dn_args, D_PRINT_DYN,
- "print( ) may not be applied to a dynamic expression\n");
+ n = snprintf(NULL, 0, "%s`%ld", dmp->dm_name, dret->dn_type) + 1;
+ if (dmp->dm_pid != 0) {
+ ctflib = dt_module_getlibid(dtp, dmp, dret->dn_ctfp);
+ assert(ctflib >= 0);
+ n = snprintf(NULL, 0, "%s`%d`%ld", dmp->dm_name,
+ ctflib, dret->dn_type) + 1;
+ } else {
+ n = snprintf(NULL, 0, "%s`%ld", dmp->dm_name,
+ dret->dn_type) + 1;
+ }
+ sdp->dtsd_strdata = dt_alloc(dtp, n);
+ if (sdp->dtsd_strdata == NULL)
+ longjmp(yypcb->pcb_jmpbuf, EDT_NOMEM);
+ (void) snprintf(sdp->dtsd_strdata, n, "%s`%ld", dmp->dm_name,
+ dret->dn_type);
+ if (dmp->dm_pid != 0) {
+ (void) snprintf(sdp->dtsd_strdata, n, "%s`%d`%ld",
+ dmp->dm_name, ctflib, dret->dn_type);
+ } else {
+ (void) snprintf(sdp->dtsd_strdata, n, "%s`%ld",
+ dmp->dm_name, dret->dn_type);
+ }
}
- dt_cg(yypcb, dnp->dn_args);
-
- dret = yypcb->pcb_dret;
- dmp = dt_module_lookup_by_ctf(dtp, dret->dn_ctfp);
-
- len = snprintf(NULL, 0, "%s`%ld", dmp->dm_name, dret->dn_type) + 1;
- sdp->dtsd_strdata = dt_alloc(dtp, len);
- if (sdp->dtsd_strdata == NULL)
- longjmp(yypcb->pcb_jmpbuf, EDT_NOMEM);
- (void) snprintf(sdp->dtsd_strdata, len, "%s`%ld", dmp->dm_name,
- dret->dn_type);
-
ap->dtad_difo = dt_as(yypcb);
ap->dtad_kind = DTRACEACT_DIFEXPR;
}
@@ -1145,6 +1158,9 @@
case DT_ACT_PANIC:
dt_action_panic(dtp, dnp->dn_expr, sdp);
break;
+ case DT_ACT_PRINT:
+ dt_action_trace(dtp, dnp->dn_expr, sdp);
+ break;
case DT_ACT_PRINTA:
dt_action_printa(dtp, dnp->dn_expr, sdp);
break;
@@ -1181,9 +1197,6 @@
case DT_ACT_TRACE:
dt_action_trace(dtp, dnp->dn_expr, sdp);
break;
- case DT_ACT_PRINT:
- dt_action_print(dtp, dnp->dn_expr, sdp);
- break;
case DT_ACT_TRACEMEM:
dt_action_tracemem(dtp, dnp->dn_expr, sdp);
break;
@@ -1876,7 +1889,7 @@
char **argv = malloc(sizeof (char *) * (argc + 5));
FILE *ofp = tmpfile();
-#if defined(sun)
+#ifdef illumos
char ipath[20], opath[20]; /* big enough for /dev/fd/ + INT_MAX + \0 */
#endif
char verdef[32]; /* big enough for -D__SUNW_D_VERSION=0x%08x + \0 */
@@ -1886,7 +1899,7 @@
int wstat, estat;
pid_t pid;
-#if defined(sun)
+#ifdef illumos
off64_t off;
#else
off_t off = 0;
@@ -1917,7 +1930,7 @@
(void) fseeko64(ifp, off, SEEK_SET);
}
-#if defined(sun)
+#ifdef illumos
(void) snprintf(ipath, sizeof (ipath), "/dev/fd/%d", fileno(ifp));
(void) snprintf(opath, sizeof (opath), "/dev/fd/%d", fileno(ofp));
#endif
@@ -1928,7 +1941,7 @@
"-D__SUNW_D_VERSION=0x%08x", dtp->dt_vmax);
argv[argc++] = verdef;
-#if defined(sun)
+#ifdef illumos
switch (dtp->dt_stdcmode) {
case DT_STDC_XA:
case DT_STDC_XT:
@@ -1970,7 +1983,7 @@
}
if (pid == 0) {
-#if !defined(sun)
+#ifndef illumos
if (isatty(fileno(ifp)) == 0)
lseek(fileno(ifp), off, SEEK_SET);
dup2(fileno(ifp), 0);
@@ -2277,12 +2290,15 @@
dt_dprintf("skipping library %s, already processed "
"library with the same name: %s", dp->d_name,
dld->dtld_library);
+ (void) fclose(fp);
continue;
}
dtp->dt_filetag = fname;
- if (dt_lib_depend_add(dtp, &dtp->dt_lib_dep, fname) != 0)
+ if (dt_lib_depend_add(dtp, &dtp->dt_lib_dep, fname) != 0) {
+ (void) fclose(fp);
return (-1); /* preserve dt_errno */
+ }
rv = dt_compile(dtp, DT_CTX_DPROG,
DTRACE_PROBESPEC_NAME, NULL,
@@ -2290,8 +2306,10 @@
if (rv != NULL && dtp->dt_errno &&
(dtp->dt_errno != EDT_COMPILER ||
- dtp->dt_errtag != dt_errtag(D_PRAGMA_DEPEND)))
+ dtp->dt_errtag != dt_errtag(D_PRAGMA_DEPEND))) {
+ (void) fclose(fp);
return (-1); /* preserve dt_errno */
+ }
if (dtp->dt_errno)
dt_dprintf("error parsing library %s: %s\n",
@@ -2559,7 +2577,8 @@
}
out:
- if (context != DT_CTX_DTYPE && DT_TREEDUMP_PASS(dtp, 3))
+ if (context != DT_CTX_DTYPE && yypcb->pcb_root != NULL &&
+ DT_TREEDUMP_PASS(dtp, 3))
dt_node_printr(yypcb->pcb_root, stderr, 0);
if (dtp->dt_cdefs_fd != -1 && (ftruncate64(dtp->dt_cdefs_fd, 0) == -1 ||
Modified: trunk/cddl/contrib/opensolaris/lib/libdtrace/common/dt_cg.c
===================================================================
--- trunk/cddl/contrib/opensolaris/lib/libdtrace/common/dt_cg.c 2018-06-02 16:07:17 UTC (rev 10228)
+++ trunk/cddl/contrib/opensolaris/lib/libdtrace/common/dt_cg.c 2018-06-02 16:07:30 UTC (rev 10229)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*
* CDDL HEADER START
*
@@ -19,12 +20,15 @@
*
* CDDL HEADER END
*/
+
/*
* Copyright 2005 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
+/*
+ * Copyright (c) 2012 by Delphix. All rights reserved.
+ */
#include <sys/types.h>
#include <sys/sysmacros.h>
@@ -193,9 +197,6 @@
ssize_t size;
int sreg;
- if ((sreg = dt_regset_alloc(drp)) == -1)
- longjmp(yypcb->pcb_jmpbuf, EDT_NOREG);
-
type = ctf_type_resolve(ctfp, dnp->dn_type);
kind = ctf_type_kind(ctfp, type);
assert(kind == CTF_K_POINTER || kind == CTF_K_ARRAY);
@@ -212,6 +213,7 @@
if ((size = ctf_type_size(ctfp, type)) == 1)
return; /* multiply or divide by one can be omitted */
+ sreg = dt_regset_alloc(drp);
dt_cg_setx(dlp, sreg, size);
instr = DIF_INSTR_FMT(op, dreg, sreg, dreg);
dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr));
@@ -251,10 +253,8 @@
assert(dnp->dn_op == DT_TOK_PTR || dnp->dn_op == DT_TOK_DOT);
r1 = dnp->dn_left->dn_reg;
+ r2 = dt_regset_alloc(drp);
- if ((r2 = dt_regset_alloc(drp)) == -1)
- longjmp(yypcb->pcb_jmpbuf, EDT_NOREG);
-
/*
* On little-endian architectures, ctm_offset counts from the right so
* ctm_offset % NBBY itself is the amount we want to shift right to
@@ -356,10 +356,9 @@
"bits %u\n", m.ctm_offset, m.ctm_type, e.cte_bits);
}
- if ((r1 = dt_regset_alloc(drp)) == -1 ||
- (r2 = dt_regset_alloc(drp)) == -1 ||
- (r3 = dt_regset_alloc(drp)) == -1)
- longjmp(yypcb->pcb_jmpbuf, EDT_NOREG);
+ r1 = dt_regset_alloc(drp);
+ r2 = dt_regset_alloc(drp);
+ r3 = dt_regset_alloc(drp);
/*
* Compute shifts and masks. We need to compute "shift" as the amount
@@ -423,8 +422,7 @@
size = dt_node_type_size(src);
if (src->dn_flags & DT_NF_REF) {
- if ((reg = dt_regset_alloc(drp)) == -1)
- longjmp(yypcb->pcb_jmpbuf, EDT_NOREG);
+ reg = dt_regset_alloc(drp);
dt_cg_setx(dlp, reg, size);
instr = DIF_INSTR_COPYS(src->dn_reg, reg, dst->dn_reg);
dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr));
@@ -474,30 +472,58 @@
size_t dstsize = dt_node_type_size(dst);
dif_instr_t instr;
- int reg, n;
+ int rg;
- if (dt_node_is_scalar(dst) && (dstsize < srcsize ||
- (src->dn_flags & DT_NF_SIGNED) ^ (dst->dn_flags & DT_NF_SIGNED))) {
- if ((reg = dt_regset_alloc(drp)) == -1)
- longjmp(yypcb->pcb_jmpbuf, EDT_NOREG);
+ if (!dt_node_is_scalar(dst))
+ return; /* not a scalar */
+ if (dstsize == srcsize &&
+ ((src->dn_flags ^ dst->dn_flags) & DT_NF_SIGNED) != 0)
+ return; /* not narrowing or changing signed-ness */
+ if (dstsize > srcsize && (src->dn_flags & DT_NF_SIGNED) == 0)
+ return; /* nothing to do in this case */
- if (dstsize < srcsize)
- n = sizeof (uint64_t) * NBBY - dstsize * NBBY;
- else
- n = sizeof (uint64_t) * NBBY - srcsize * NBBY;
+ rg = dt_regset_alloc(drp);
- dt_cg_setx(dlp, reg, n);
+ if (dstsize > srcsize) {
+ int n = sizeof (uint64_t) * NBBY - srcsize * NBBY;
+ int s = (dstsize - srcsize) * NBBY;
- instr = DIF_INSTR_FMT(DIF_OP_SLL,
- src->dn_reg, reg, dst->dn_reg);
+ dt_cg_setx(dlp, rg, n);
+
+ instr = DIF_INSTR_FMT(DIF_OP_SLL, src->dn_reg, rg, dst->dn_reg);
dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr));
- instr = DIF_INSTR_FMT((dst->dn_flags & DT_NF_SIGNED) ?
- DIF_OP_SRA : DIF_OP_SRL, dst->dn_reg, reg, dst->dn_reg);
+ if ((dst->dn_flags & DT_NF_SIGNED) || n == s) {
+ instr = DIF_INSTR_FMT(DIF_OP_SRA,
+ dst->dn_reg, rg, dst->dn_reg);
+ dt_irlist_append(dlp,
+ dt_cg_node_alloc(DT_LBL_NONE, instr));
+ } else {
+ dt_cg_setx(dlp, rg, s);
+ instr = DIF_INSTR_FMT(DIF_OP_SRA,
+ dst->dn_reg, rg, dst->dn_reg);
+ dt_irlist_append(dlp,
+ dt_cg_node_alloc(DT_LBL_NONE, instr));
+ dt_cg_setx(dlp, rg, n - s);
+ instr = DIF_INSTR_FMT(DIF_OP_SRL,
+ dst->dn_reg, rg, dst->dn_reg);
+ dt_irlist_append(dlp,
+ dt_cg_node_alloc(DT_LBL_NONE, instr));
+ }
+ } else if (dstsize != sizeof (uint64_t)) {
+ int n = sizeof (uint64_t) * NBBY - dstsize * NBBY;
+ dt_cg_setx(dlp, rg, n);
+
+ instr = DIF_INSTR_FMT(DIF_OP_SLL, src->dn_reg, rg, dst->dn_reg);
dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr));
- dt_regset_free(drp, reg);
+
+ instr = DIF_INSTR_FMT((dst->dn_flags & DT_NF_SIGNED) ?
+ DIF_OP_SRA : DIF_OP_SRL, dst->dn_reg, rg, dst->dn_reg);
+ dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr));
}
+
+ dt_regset_free(drp, rg);
}
/*
@@ -523,8 +549,7 @@
for (dnp = args; dnp != NULL; dnp = dnp->dn_list)
dt_cg_node(dnp, dlp, drp);
- dt_irlist_append(dlp,
- dt_cg_node_alloc(DT_LBL_NONE, DIF_INSTR_FLUSHTS));
+ dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, DIF_INSTR_FLUSHTS));
for (dnp = args; dnp != NULL; dnp = dnp->dn_list, i++) {
dtrace_diftype_t t;
@@ -538,17 +563,18 @@
dt_cg_typecast(dnp, &isp->dis_args[i], dlp, drp);
isp->dis_args[i].dn_reg = -1;
- if (t.dtdt_flags & DIF_TF_BYREF)
+ if (t.dtdt_flags & DIF_TF_BYREF) {
op = DIF_OP_PUSHTR;
- else
+ if (t.dtdt_size != 0) {
+ reg = dt_regset_alloc(drp);
+ dt_cg_setx(dlp, reg, t.dtdt_size);
+ } else {
+ reg = DIF_REG_R0;
+ }
+ } else {
op = DIF_OP_PUSHTV;
-
- if (t.dtdt_size != 0) {
- if ((reg = dt_regset_alloc(drp)) == -1)
- longjmp(yypcb->pcb_jmpbuf, EDT_NOREG);
- dt_cg_setx(dlp, reg, t.dtdt_size);
- } else
reg = DIF_REG_R0;
+ }
instr = DIF_INSTR_PUSHTS(op, t.dtdt_kind, reg, dnp->dn_reg);
dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr));
@@ -629,9 +655,7 @@
dt_cg_node(dnp->dn_child, dlp, drp);
dnp->dn_reg = dnp->dn_child->dn_reg;
- if ((reg = dt_regset_alloc(drp)) == -1)
- longjmp(yypcb->pcb_jmpbuf, EDT_NOREG);
-
+ reg = dt_regset_alloc(drp);
dt_cg_setx(dlp, reg, size);
instr = DIF_INSTR_FMT(op, dnp->dn_reg, reg, dnp->dn_reg);
@@ -688,9 +712,7 @@
dt_cg_node(dnp->dn_child, dlp, drp);
dnp->dn_reg = dnp->dn_child->dn_reg;
- if ((nreg = dt_regset_alloc(drp)) == -1)
- longjmp(yypcb->pcb_jmpbuf, EDT_NOREG);
-
+ nreg = dt_regset_alloc(drp);
dt_cg_setx(dlp, nreg, size);
instr = DIF_INSTR_FMT(op, dnp->dn_reg, nreg, nreg);
dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr));
@@ -1008,9 +1030,7 @@
* set it to the size of our data structure, and then replace
* it with the result of an allocs of the specified size.
*/
- if ((r1 = dt_regset_alloc(drp)) == -1)
- longjmp(yypcb->pcb_jmpbuf, EDT_NOREG);
-
+ r1 = dt_regset_alloc(drp);
dt_cg_setx(dlp, r1,
ctf_type_size(dxp->dx_dst_ctfp, dxp->dx_dst_base));
@@ -1054,8 +1074,7 @@
* and add r1 to it before storing the result.
*/
if (ctm.ctm_offset != 0) {
- if ((r2 = dt_regset_alloc(drp)) == -1)
- longjmp(yypcb->pcb_jmpbuf, EDT_NOREG);
+ r2 = dt_regset_alloc(drp);
/*
* Add the member offset rounded down to the
@@ -1142,8 +1161,7 @@
dt_cg_arglist(dnp->dn_ident, dnp->dn_args, dlp, drp);
- if ((dnp->dn_reg = dt_regset_alloc(drp)) == -1)
- longjmp(yypcb->pcb_jmpbuf, EDT_NOREG);
+ dnp->dn_reg = dt_regset_alloc(drp);
if (dnp->dn_ident->di_flags & DT_IDFLG_TLS)
op = DIF_OP_LDTAA;
@@ -1273,9 +1291,7 @@
if ((size = dt_node_type_size(dnp)) == sizeof (uint64_t))
return;
- if ((reg = dt_regset_alloc(drp)) == -1)
- longjmp(yypcb->pcb_jmpbuf, EDT_NOREG);
-
+ reg = dt_regset_alloc(drp);
assert(size < sizeof (uint64_t));
n = sizeof (uint64_t) * NBBY - size * NBBY;
@@ -1372,6 +1388,162 @@
typs->dn_value = ctf_type_size(dtt.dtt_ctfp, dtt.dtt_type);
}
+typedef struct dt_xlmemb {
+ dt_ident_t *dtxl_idp; /* translated ident */
+ dt_irlist_t *dtxl_dlp; /* instruction list */
+ dt_regset_t *dtxl_drp; /* register set */
+ int dtxl_sreg; /* location of the translation input */
+ int dtxl_dreg; /* location of our allocated buffer */
+} dt_xlmemb_t;
+
+/*ARGSUSED*/
+static int
+dt_cg_xlate_member(const char *name, ctf_id_t type, ulong_t off, void *arg)
+{
+ dt_xlmemb_t *dx = arg;
+ dt_ident_t *idp = dx->dtxl_idp;
+ dt_irlist_t *dlp = dx->dtxl_dlp;
+ dt_regset_t *drp = dx->dtxl_drp;
+
+ dt_node_t *mnp;
+ dt_xlator_t *dxp;
+
+ int reg, treg;
+ uint32_t instr;
+ size_t size;
+
+ /* Generate code for the translation. */
+ dxp = idp->di_data;
+ mnp = dt_xlator_member(dxp, name);
+
+ /* If there's no translator for the given member, skip it. */
+ if (mnp == NULL)
+ return (0);
+
+ dxp->dx_ident->di_flags |= DT_IDFLG_CGREG;
+ dxp->dx_ident->di_id = dx->dtxl_sreg;
+
+ dt_cg_node(mnp->dn_membexpr, dlp, drp);
+
+ dxp->dx_ident->di_flags &= ~DT_IDFLG_CGREG;
+ dxp->dx_ident->di_id = 0;
+
+ treg = mnp->dn_membexpr->dn_reg;
+
+ /* Compute the offset into our buffer and store the result there. */
+ reg = dt_regset_alloc(drp);
+
+ dt_cg_setx(dlp, reg, off / NBBY);
+ instr = DIF_INSTR_FMT(DIF_OP_ADD, dx->dtxl_dreg, reg, reg);
+ dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr));
+
+ size = ctf_type_size(mnp->dn_membexpr->dn_ctfp,
+ mnp->dn_membexpr->dn_type);
+ if (dt_node_is_scalar(mnp->dn_membexpr)) {
+ /*
+ * Copying scalars is simple.
+ */
+ switch (size) {
+ case 1:
+ instr = DIF_INSTR_STORE(DIF_OP_STB, treg, reg);
+ break;
+ case 2:
+ instr = DIF_INSTR_STORE(DIF_OP_STH, treg, reg);
+ break;
+ case 4:
+ instr = DIF_INSTR_STORE(DIF_OP_STW, treg, reg);
+ break;
+ case 8:
+ instr = DIF_INSTR_STORE(DIF_OP_STX, treg, reg);
+ break;
+ default:
+ xyerror(D_UNKNOWN, "internal error -- unexpected "
+ "size: %lu\n", (ulong_t)size);
+ }
+
+ dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr));
+
+ } else if (dt_node_is_string(mnp->dn_membexpr)) {
+ int szreg;
+
+ /*
+ * Use the copys instruction for strings.
+ */
+ szreg = dt_regset_alloc(drp);
+ dt_cg_setx(dlp, szreg, size);
+ instr = DIF_INSTR_COPYS(treg, szreg, reg);
+ dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr));
+ dt_regset_free(drp, szreg);
+ } else {
+ int szreg;
+
+ /*
+ * If it's anything else then we'll just bcopy it.
+ */
+ szreg = dt_regset_alloc(drp);
+ dt_cg_setx(dlp, szreg, size);
+ dt_irlist_append(dlp,
+ dt_cg_node_alloc(DT_LBL_NONE, DIF_INSTR_FLUSHTS));
+ instr = DIF_INSTR_PUSHTS(DIF_OP_PUSHTV, DIF_TYPE_CTF,
+ DIF_REG_R0, treg);
+ dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr));
+ instr = DIF_INSTR_PUSHTS(DIF_OP_PUSHTV, DIF_TYPE_CTF,
+ DIF_REG_R0, reg);
+ dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr));
+ instr = DIF_INSTR_PUSHTS(DIF_OP_PUSHTV, DIF_TYPE_CTF,
+ DIF_REG_R0, szreg);
+ dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr));
+ instr = DIF_INSTR_CALL(DIF_SUBR_BCOPY, szreg);
+ dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr));
+ dt_regset_free(drp, szreg);
+ }
+
+ dt_regset_free(drp, reg);
+ dt_regset_free(drp, treg);
+
+ return (0);
+}
+
+/*
+ * If we're expanding a translated type, we create an appropriately sized
+ * buffer with alloca() and then translate each member into it.
+ */
+static int
+dt_cg_xlate_expand(dt_node_t *dnp, dt_ident_t *idp, dt_irlist_t *dlp,
+ dt_regset_t *drp)
+{
+ dt_xlmemb_t dlm;
+ uint32_t instr;
+ int dreg;
+ size_t size;
+
+ dreg = dt_regset_alloc(drp);
+ size = ctf_type_size(dnp->dn_ident->di_ctfp, dnp->dn_ident->di_type);
+
+ /* Call alloca() to create the buffer. */
+ dt_cg_setx(dlp, dreg, size);
+
+ dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, DIF_INSTR_FLUSHTS));
+
+ instr = DIF_INSTR_PUSHTS(DIF_OP_PUSHTV, DIF_TYPE_CTF, DIF_REG_R0, dreg);
+ dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr));
+
+ instr = DIF_INSTR_CALL(DIF_SUBR_ALLOCA, dreg);
+ dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr));
+
+ /* Generate the translation for each member. */
+ dlm.dtxl_idp = idp;
+ dlm.dtxl_dlp = dlp;
+ dlm.dtxl_drp = drp;
+ dlm.dtxl_sreg = dnp->dn_reg;
+ dlm.dtxl_dreg = dreg;
+ (void) ctf_member_iter(dnp->dn_ident->di_ctfp,
+ dnp->dn_ident->di_type, dt_cg_xlate_member,
+ &dlm);
+
+ return (dreg);
+}
+
static void
dt_cg_node(dt_node_t *dnp, dt_irlist_t *dlp, dt_regset_t *drp)
{
@@ -1384,7 +1556,6 @@
dt_ident_t *idp;
ssize_t stroff;
uint_t op;
- int reg;
switch (dnp->dn_op) {
case DT_TOK_COMMA:
@@ -1586,7 +1757,16 @@
dt_cg_node(dnp->dn_child, dlp, drp);
dnp->dn_reg = dnp->dn_child->dn_reg;
- if (!(dnp->dn_flags & DT_NF_REF)) {
+ if (dt_node_is_dynamic(dnp->dn_child)) {
+ int reg;
+ idp = dt_node_resolve(dnp->dn_child, DT_IDENT_XLPTR);
+ assert(idp != NULL);
+ reg = dt_cg_xlate_expand(dnp, idp, dlp, drp);
+
+ dt_regset_free(drp, dnp->dn_child->dn_reg);
+ dnp->dn_reg = reg;
+
+ } else if (!(dnp->dn_flags & DT_NF_REF)) {
uint_t ubit = dnp->dn_flags & DT_NF_USERLAND;
/*
@@ -1622,10 +1802,7 @@
case DT_TOK_SIZEOF: {
size_t size = dt_node_sizeof(dnp->dn_child);
-
- if ((dnp->dn_reg = dt_regset_alloc(drp)) == -1)
- longjmp(yypcb->pcb_jmpbuf, EDT_NOREG);
-
+ dnp->dn_reg = dt_regset_alloc(drp);
assert(size != 0);
dt_cg_setx(dlp, dnp->dn_reg, size);
break;
@@ -1650,8 +1827,7 @@
assert(dxp->dx_ident->di_flags & DT_IDFLG_CGREG);
assert(dxp->dx_ident->di_id != 0);
- if ((dnp->dn_reg = dt_regset_alloc(drp)) == -1)
- longjmp(yypcb->pcb_jmpbuf, EDT_NOREG);
+ dnp->dn_reg = dt_regset_alloc(drp);
if (dxp->dx_arg == -1) {
instr = DIF_INSTR_MOV(
@@ -1735,9 +1911,10 @@
}
if (m.ctm_offset != 0) {
- if ((reg = dt_regset_alloc(drp)) == -1)
- longjmp(yypcb->pcb_jmpbuf, EDT_NOREG);
+ int reg;
+ reg = dt_regset_alloc(drp);
+
/*
* If the offset is not aligned on a byte boundary, it
* is a bit-field member and we will extract the value
@@ -1782,8 +1959,7 @@
break;
case DT_TOK_STRING:
- if ((dnp->dn_reg = dt_regset_alloc(drp)) == -1)
- longjmp(yypcb->pcb_jmpbuf, EDT_NOREG);
+ dnp->dn_reg = dt_regset_alloc(drp);
assert(dnp->dn_kind == DT_NODE_STRING);
stroff = dt_strtab_insert(yypcb->pcb_strtab, dnp->dn_string);
@@ -1806,8 +1982,7 @@
*/
if (dnp->dn_kind == DT_NODE_VAR &&
(dnp->dn_ident->di_flags & DT_IDFLG_CGREG)) {
- if ((dnp->dn_reg = dt_regset_alloc(drp)) == -1)
- longjmp(yypcb->pcb_jmpbuf, EDT_NOREG);
+ dnp->dn_reg = dt_regset_alloc(drp);
instr = DIF_INSTR_MOV(dnp->dn_ident->di_id,
dnp->dn_reg);
dt_irlist_append(dlp,
@@ -1848,12 +2023,10 @@
dt_cg_arglist(dnp->dn_ident, dnp->dn_args, dlp, drp);
- if ((dnp->dn_reg = dt_regset_alloc(drp)) == -1)
- longjmp(yypcb->pcb_jmpbuf, EDT_NOREG);
+ dnp->dn_reg = dt_regset_alloc(drp);
+ instr = DIF_INSTR_CALL(dnp->dn_ident->di_id,
+ dnp->dn_reg);
- instr = DIF_INSTR_CALL(
- dnp->dn_ident->di_id, dnp->dn_reg);
-
dt_irlist_append(dlp,
dt_cg_node_alloc(DT_LBL_NONE, instr));
@@ -1880,8 +2053,7 @@
break;
}
- if ((dnp->dn_reg = dt_regset_alloc(drp)) == -1)
- longjmp(yypcb->pcb_jmpbuf, EDT_NOREG);
+ dnp->dn_reg = dt_regset_alloc(drp);
if (dnp->dn_ident->di_flags & DT_IDFLG_LOCAL)
op = DIF_OP_LDLS;
@@ -1911,9 +2083,7 @@
dtrace_errmsg(dtp, dtrace_errno(dtp)));
}
- if ((dnp->dn_reg = dt_regset_alloc(drp)) == -1)
- longjmp(yypcb->pcb_jmpbuf, EDT_NOREG);
-
+ dnp->dn_reg = dt_regset_alloc(drp);
dt_cg_xsetx(dlp, dnp->dn_ident,
DT_LBL_NONE, dnp->dn_reg, sym.st_value);
@@ -1933,9 +2103,7 @@
break;
case DT_TOK_INT:
- if ((dnp->dn_reg = dt_regset_alloc(drp)) == -1)
- longjmp(yypcb->pcb_jmpbuf, EDT_NOREG);
-
+ dnp->dn_reg = dt_regset_alloc(drp);
dt_cg_setx(dlp, dnp->dn_reg, dnp->dn_value);
break;
@@ -1950,6 +2118,7 @@
{
dif_instr_t instr;
dt_xlator_t *dxp;
+ dt_ident_t *idp;
if (pcb->pcb_regs == NULL && (pcb->pcb_regs =
dt_regset_create(pcb->pcb_hdl->dt_conf.dtc_difintregs)) == NULL)
@@ -1976,9 +2145,9 @@
assert(pcb->pcb_dret == NULL);
pcb->pcb_dret = dnp;
- if (dt_node_is_dynamic(dnp)) {
+ if (dt_node_resolve(dnp, DT_IDENT_XLPTR) != NULL) {
dnerror(dnp, D_CG_DYN, "expression cannot evaluate to result "
- "of dynamic type\n");
+ "of a translated pointer\n");
}
/*
@@ -1994,6 +2163,14 @@
}
dt_cg_node(dnp, &pcb->pcb_ir, pcb->pcb_regs);
+
+ if ((idp = dt_node_resolve(dnp, DT_IDENT_XLSOU)) != NULL) {
+ int reg = dt_cg_xlate_expand(dnp, idp,
+ &pcb->pcb_ir, pcb->pcb_regs);
+ dt_regset_free(pcb->pcb_regs, dnp->dn_reg);
+ dnp->dn_reg = reg;
+ }
+
instr = DIF_INSTR_RET(dnp->dn_reg);
dt_regset_free(pcb->pcb_regs, dnp->dn_reg);
dt_irlist_append(&pcb->pcb_ir, dt_cg_node_alloc(DT_LBL_NONE, instr));
@@ -2003,4 +2180,7 @@
dxp->dx_ident->di_id = 0;
dxp->dx_ident->di_flags &= ~DT_IDFLG_CGREG;
}
+
+ dt_regset_free(pcb->pcb_regs, 0);
+ dt_regset_assert_free(pcb->pcb_regs);
}
Modified: trunk/cddl/contrib/opensolaris/lib/libdtrace/common/dt_consume.c
===================================================================
--- trunk/cddl/contrib/opensolaris/lib/libdtrace/common/dt_consume.c 2018-06-02 16:07:17 UTC (rev 10228)
+++ trunk/cddl/contrib/opensolaris/lib/libdtrace/common/dt_consume.c 2018-06-02 16:07:30 UTC (rev 10229)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*
* CDDL HEADER START
*
@@ -24,8 +25,8 @@
*/
/*
- * Copyright (c) 2011, Joyent, Inc. All rights reserved.
- * Copyright (c) 2011 by Delphix. All rights reserved.
+ * Copyright (c) 2013, Joyent, Inc. All rights reserved.
+ * Copyright (c) 2012 by Delphix. All rights reserved.
*/
#include <stdlib.h>
@@ -35,11 +36,12 @@
#include <limits.h>
#include <assert.h>
#include <ctype.h>
-#if defined(sun)
+#ifdef illumos
#include <alloca.h>
#endif
#include <dt_impl.h>
-#if !defined(sun)
+#include <dt_pq.h>
+#ifndef illumos
#include <libproc_compat.h>
#endif
@@ -58,6 +60,25 @@
return (x);
}
+static int
+dt_ndigits(long long val)
+{
+ int rval = 1;
+ long long cmp = 10;
+
+ if (val < 0) {
+ val = val == INT64_MIN ? INT64_MAX : -val;
+ rval++;
+ }
+
+ while (val > cmp && cmp > 0) {
+ rval++;
+ cmp *= 10;
+ }
+
+ return (rval < 4 ? 4 : rval);
+}
+
/*
* 128-bit arithmetic functions needed to support the stddev() aggregating
* action.
@@ -362,12 +383,17 @@
int64_t norm_avg;
uint64_t diff[2];
+ if (data[0] == 0)
+ return (0);
+
/*
* The standard approximation for standard deviation is
* sqrt(average(x**2) - average(x)**2), i.e. the square root
* of the average of the squares minus the square of the average.
+ * When normalizing, we should divide the sum of x**2 by normal**2.
*/
dt_divide_128(data + 2, normal, avg_of_squares);
+ dt_divide_128(avg_of_squares, normal, avg_of_squares);
dt_divide_128(avg_of_squares, data[0], avg_of_squares);
norm_avg = (int64_t)data[1] / (int64_t)normal / (int64_t)data[0];
@@ -443,17 +469,8 @@
offs += epd->dtepd_size;
do {
- if (offs >= buf->dtbd_size) {
- /*
- * We're at the end -- maybe. If the oldest
- * record is non-zero, we need to wrap.
- */
- if (buf->dtbd_oldest != 0) {
- offs = 0;
- } else {
- goto out;
- }
- }
+ if (offs >= buf->dtbd_size)
+ goto out;
next = *(uint32_t *)((uintptr_t)buf->dtbd_data + offs);
@@ -495,7 +512,125 @@
return (DTRACE_CONSUME_NEXT);
}
-int
+static void
+dt_quantize_total(dtrace_hdl_t *dtp, int64_t datum, long double *total)
+{
+ long double val = dt_fabsl((long double)datum);
+
+ if (dtp->dt_options[DTRACEOPT_AGGZOOM] == DTRACEOPT_UNSET) {
+ *total += val;
+ return;
+ }
+
+ /*
+ * If we're zooming in on an aggregation, we want the height of the
+ * highest value to be approximately 95% of total bar height -- so we
+ * adjust up by the reciprocal of DTRACE_AGGZOOM_MAX when comparing to
+ * our highest value.
+ */
+ val *= 1 / DTRACE_AGGZOOM_MAX;
+
+ if (*total < val)
+ *total = val;
+}
+
+static int
+dt_print_quanthdr(dtrace_hdl_t *dtp, FILE *fp, int width)
+{
+ return (dt_printf(dtp, fp, "\n%*s %41s %-9s\n",
+ width ? width : 16, width ? "key" : "value",
+ "------------- Distribution -------------", "count"));
+}
+
+static int
+dt_print_quanthdr_packed(dtrace_hdl_t *dtp, FILE *fp, int width,
+ const dtrace_aggdata_t *aggdata, dtrace_actkind_t action)
+{
+ int min = aggdata->dtada_minbin, max = aggdata->dtada_maxbin;
+ int minwidth, maxwidth, i;
+
+ assert(action == DTRACEAGG_QUANTIZE || action == DTRACEAGG_LQUANTIZE);
+
+ if (action == DTRACEAGG_QUANTIZE) {
+ if (min != 0 && min != DTRACE_QUANTIZE_ZEROBUCKET)
+ min--;
+
+ if (max < DTRACE_QUANTIZE_NBUCKETS - 1)
+ max++;
+
+ minwidth = dt_ndigits(DTRACE_QUANTIZE_BUCKETVAL(min));
+ maxwidth = dt_ndigits(DTRACE_QUANTIZE_BUCKETVAL(max));
+ } else {
+ maxwidth = 8;
+ minwidth = maxwidth - 1;
+ max++;
+ }
+
+ if (dt_printf(dtp, fp, "\n%*s %*s .",
+ width, width > 0 ? "key" : "", minwidth, "min") < 0)
+ return (-1);
+
+ for (i = min; i <= max; i++) {
+ if (dt_printf(dtp, fp, "-") < 0)
+ return (-1);
+ }
+
+ return (dt_printf(dtp, fp, ". %*s | count\n", -maxwidth, "max"));
+}
+
+/*
+ * We use a subset of the Unicode Block Elements (U+2588 through U+258F,
+ * inclusive) to represent aggregations via UTF-8 -- which are expressed via
+ * 3-byte UTF-8 sequences.
+ */
+#define DTRACE_AGGUTF8_FULL 0x2588
+#define DTRACE_AGGUTF8_BASE 0x258f
+#define DTRACE_AGGUTF8_LEVELS 8
+
+#define DTRACE_AGGUTF8_BYTE0(val) (0xe0 | ((val) >> 12))
+#define DTRACE_AGGUTF8_BYTE1(val) (0x80 | (((val) >> 6) & 0x3f))
+#define DTRACE_AGGUTF8_BYTE2(val) (0x80 | ((val) & 0x3f))
+
+static int
+dt_print_quantline_utf8(dtrace_hdl_t *dtp, FILE *fp, int64_t val,
+ uint64_t normal, long double total)
+{
+ uint_t len = 40, i, whole, partial;
+ long double f = (dt_fabsl((long double)val) * len) / total;
+ const char *spaces = " ";
+
+ whole = (uint_t)f;
+ partial = (uint_t)((f - (long double)(uint_t)f) *
+ (long double)DTRACE_AGGUTF8_LEVELS);
+
+ if (dt_printf(dtp, fp, "|") < 0)
+ return (-1);
+
+ for (i = 0; i < whole; i++) {
+ if (dt_printf(dtp, fp, "%c%c%c",
+ DTRACE_AGGUTF8_BYTE0(DTRACE_AGGUTF8_FULL),
+ DTRACE_AGGUTF8_BYTE1(DTRACE_AGGUTF8_FULL),
+ DTRACE_AGGUTF8_BYTE2(DTRACE_AGGUTF8_FULL)) < 0)
+ return (-1);
+ }
+
+ if (partial != 0) {
+ partial = DTRACE_AGGUTF8_BASE - (partial - 1);
+
+ if (dt_printf(dtp, fp, "%c%c%c",
+ DTRACE_AGGUTF8_BYTE0(partial),
+ DTRACE_AGGUTF8_BYTE1(partial),
+ DTRACE_AGGUTF8_BYTE2(partial)) < 0)
+ return (-1);
+
+ i++;
+ }
+
+ return (dt_printf(dtp, fp, "%s %-9lld\n", spaces + i,
+ (long long)val / normal));
+}
+
+static int
dt_print_quantline(dtrace_hdl_t *dtp, FILE *fp, int64_t val,
uint64_t normal, long double total, char positives, char negatives)
{
@@ -513,6 +648,11 @@
if (!negatives) {
if (positives) {
+ if (dtp->dt_encoding == DT_ENCODING_UTF8) {
+ return (dt_print_quantline_utf8(dtp, fp, val,
+ normal, total));
+ }
+
f = (dt_fabsl((long double)val) * len) / total;
depth = (uint_t)(f + 0.5);
} else {
@@ -555,6 +695,73 @@
}
}
+/*
+ * As with UTF-8 printing of aggregations, we use a subset of the Unicode
+ * Block Elements (U+2581 through U+2588, inclusive) to represent our packed
+ * aggregation.
+ */
+#define DTRACE_AGGPACK_BASE 0x2581
+#define DTRACE_AGGPACK_LEVELS 8
+
+static int
+dt_print_packed(dtrace_hdl_t *dtp, FILE *fp,
+ long double datum, long double total)
+{
+ static boolean_t utf8_checked = B_FALSE;
+ static boolean_t utf8;
+ char *ascii = "__xxxxXX";
+ char *neg = "vvvvVV";
+ unsigned int len;
+ long double val;
+
+ if (!utf8_checked) {
+ char *term;
+
+ /*
+ * We want to determine if we can reasonably emit UTF-8 for our
+ * packed aggregation. To do this, we will check for terminals
+ * that are known to be primitive to emit UTF-8 on these.
+ */
+ utf8_checked = B_TRUE;
+
+ if (dtp->dt_encoding == DT_ENCODING_ASCII) {
+ utf8 = B_FALSE;
+ } else if (dtp->dt_encoding == DT_ENCODING_UTF8) {
+ utf8 = B_TRUE;
+ } else if ((term = getenv("TERM")) != NULL &&
+ (strcmp(term, "sun") == 0 ||
+ strcmp(term, "sun-color") == 0 ||
+ strcmp(term, "dumb") == 0)) {
+ utf8 = B_FALSE;
+ } else {
+ utf8 = B_TRUE;
+ }
+ }
+
+ if (datum == 0)
+ return (dt_printf(dtp, fp, " "));
+
+ if (datum < 0) {
+ len = strlen(neg);
+ val = dt_fabsl(datum * (len - 1)) / total;
+ return (dt_printf(dtp, fp, "%c", neg[(uint_t)(val + 0.5)]));
+ }
+
+ if (utf8) {
+ int block = DTRACE_AGGPACK_BASE + (unsigned int)(((datum *
+ (DTRACE_AGGPACK_LEVELS - 1)) / total) + 0.5);
+
+ return (dt_printf(dtp, fp, "%c%c%c",
+ DTRACE_AGGUTF8_BYTE0(block),
+ DTRACE_AGGUTF8_BYTE1(block),
+ DTRACE_AGGUTF8_BYTE2(block)));
+ }
+
+ len = strlen(ascii);
+ val = (datum * (len - 1)) / total;
+ return (dt_printf(dtp, fp, "%c", ascii[(uint_t)(val + 0.5)]));
+}
+
int
dt_print_quantize(dtrace_hdl_t *dtp, FILE *fp, const void *addr,
size_t size, uint64_t normal)
@@ -572,9 +779,9 @@
if (first_bin == DTRACE_QUANTIZE_NBUCKETS - 1) {
/*
- * There isn't any data. This is possible if (and only if)
- * negative increment values have been used. In this case,
- * we'll print the buckets around 0.
+ * There isn't any data. This is possible if the aggregation
+ * has been clear()'d or if negative increment values have been
+ * used. Regardless, we'll print the buckets around 0.
*/
first_bin = DTRACE_QUANTIZE_ZEROBUCKET - 1;
last_bin = DTRACE_QUANTIZE_ZEROBUCKET + 1;
@@ -592,11 +799,10 @@
for (i = first_bin; i <= last_bin; i++) {
positives |= (data[i] > 0);
negatives |= (data[i] < 0);
- total += dt_fabsl((long double)data[i]);
+ dt_quantize_total(dtp, data[i], &total);
}
- if (dt_printf(dtp, fp, "\n%16s %41s %-9s\n", "value",
- "------------- Distribution -------------", "count") < 0)
+ if (dt_print_quanthdr(dtp, fp, 0) < 0)
return (-1);
for (i = first_bin; i <= last_bin; i++) {
@@ -613,6 +819,48 @@
}
int
+dt_print_quantize_packed(dtrace_hdl_t *dtp, FILE *fp, const void *addr,
+ size_t size, const dtrace_aggdata_t *aggdata)
+{
+ const int64_t *data = addr;
+ long double total = 0, count = 0;
+ int min = aggdata->dtada_minbin, max = aggdata->dtada_maxbin, i;
+ int64_t minval, maxval;
+
+ if (size != DTRACE_QUANTIZE_NBUCKETS * sizeof (uint64_t))
+ return (dt_set_errno(dtp, EDT_DMISMATCH));
+
+ if (min != 0 && min != DTRACE_QUANTIZE_ZEROBUCKET)
+ min--;
+
+ if (max < DTRACE_QUANTIZE_NBUCKETS - 1)
+ max++;
+
+ minval = DTRACE_QUANTIZE_BUCKETVAL(min);
+ maxval = DTRACE_QUANTIZE_BUCKETVAL(max);
+
+ if (dt_printf(dtp, fp, " %*lld :", dt_ndigits(minval),
+ (long long)minval) < 0)
+ return (-1);
+
+ for (i = min; i <= max; i++) {
+ dt_quantize_total(dtp, data[i], &total);
+ count += data[i];
+ }
+
+ for (i = min; i <= max; i++) {
+ if (dt_print_packed(dtp, fp, data[i], total) < 0)
+ return (-1);
+ }
+
+ if (dt_printf(dtp, fp, ": %*lld | %lld\n",
+ -dt_ndigits(maxval), (long long)maxval, (long long)count) < 0)
+ return (-1);
+
+ return (0);
+}
+
+int
dt_print_lquantize(dtrace_hdl_t *dtp, FILE *fp, const void *addr,
size_t size, uint64_t normal)
{
@@ -659,7 +907,7 @@
for (i = first_bin; i <= last_bin; i++) {
positives |= (data[i] > 0);
negatives |= (data[i] < 0);
- total += dt_fabsl((long double)data[i]);
+ dt_quantize_total(dtp, data[i], &total);
}
if (dt_printf(dtp, fp, "\n%16s %41s %-9s\n", "value",
@@ -671,8 +919,7 @@
int err;
if (i == 0) {
- (void) snprintf(c, sizeof (c), "< %d",
- base / (uint32_t)normal);
+ (void) snprintf(c, sizeof (c), "< %d", base);
err = dt_printf(dtp, fp, "%16s ", c);
} else if (i == levels + 1) {
(void) snprintf(c, sizeof (c), ">= %d",
@@ -691,7 +938,60 @@
return (0);
}
+/*ARGSUSED*/
int
+dt_print_lquantize_packed(dtrace_hdl_t *dtp, FILE *fp, const void *addr,
+ size_t size, const dtrace_aggdata_t *aggdata)
+{
+ const int64_t *data = addr;
+ long double total = 0, count = 0;
+ int min, max, base, err;
+ uint64_t arg;
+ uint16_t step, levels;
+ char c[32];
+ unsigned int i;
+
+ if (size < sizeof (uint64_t))
+ return (dt_set_errno(dtp, EDT_DMISMATCH));
+
+ arg = *data++;
+ size -= sizeof (uint64_t);
+
+ base = DTRACE_LQUANTIZE_BASE(arg);
+ step = DTRACE_LQUANTIZE_STEP(arg);
+ levels = DTRACE_LQUANTIZE_LEVELS(arg);
+
+ if (size != sizeof (uint64_t) * (levels + 2))
+ return (dt_set_errno(dtp, EDT_DMISMATCH));
+
+ min = 0;
+ max = levels + 1;
+
+ if (min == 0) {
+ (void) snprintf(c, sizeof (c), "< %d", base);
+ err = dt_printf(dtp, fp, "%8s :", c);
+ } else {
+ err = dt_printf(dtp, fp, "%8d :", base + (min - 1) * step);
+ }
+
+ if (err < 0)
+ return (-1);
+
+ for (i = min; i <= max; i++) {
+ dt_quantize_total(dtp, data[i], &total);
+ count += data[i];
+ }
+
+ for (i = min; i <= max; i++) {
+ if (dt_print_packed(dtp, fp, data[i], total) < 0)
+ return (-1);
+ }
+
+ (void) snprintf(c, sizeof (c), ">= %d", base + (levels * step));
+ return (dt_printf(dtp, fp, ": %-8s | %lld\n", c, (long long)count));
+}
+
+int
dt_print_llquantize(dtrace_hdl_t *dtp, FILE *fp, const void *addr,
size_t size, uint64_t normal)
{
@@ -748,7 +1048,7 @@
for (i = first_bin; i <= last_bin; i++) {
positives |= (data[i] > 0);
negatives |= (data[i] < 0);
- total += dt_fabsl((long double)data[i]);
+ dt_quantize_total(dtp, data[i], &total);
}
if (dt_printf(dtp, fp, "\n%16s %41s %-9s\n", "value",
@@ -831,7 +1131,7 @@
}
/*ARGSUSED*/
-int
+static int
dt_print_bytes(dtrace_hdl_t *dtp, FILE *fp, caddr_t addr,
size_t nbytes, int width, int quiet, int forceraw)
{
@@ -884,10 +1184,12 @@
if (j != nbytes)
break;
- if (quiet)
+ if (quiet) {
return (dt_printf(dtp, fp, "%s", c));
- else
- return (dt_printf(dtp, fp, " %-*s", width, c));
+ } else {
+ return (dt_printf(dtp, fp, " %s%*s",
+ width < 0 ? " " : "", width, c));
+ }
}
break;
@@ -1801,11 +2103,84 @@
static int
dt_print_datum(dtrace_hdl_t *dtp, FILE *fp, dtrace_recdesc_t *rec,
- caddr_t addr, size_t size, uint64_t normal)
+ caddr_t addr, size_t size, const dtrace_aggdata_t *aggdata,
+ uint64_t normal, dt_print_aggdata_t *pd)
{
- int err;
+ int err, width;
dtrace_actkind_t act = rec->dtrd_action;
+ boolean_t packed = pd->dtpa_agghist || pd->dtpa_aggpack;
+ dtrace_aggdesc_t *agg = aggdata->dtada_desc;
+ static struct {
+ size_t size;
+ int width;
+ int packedwidth;
+ } *fmt, fmttab[] = {
+ { sizeof (uint8_t), 3, 3 },
+ { sizeof (uint16_t), 5, 5 },
+ { sizeof (uint32_t), 8, 8 },
+ { sizeof (uint64_t), 16, 16 },
+ { 0, -50, 16 }
+ };
+
+ if (packed && pd->dtpa_agghisthdr != agg->dtagd_varid) {
+ dtrace_recdesc_t *r;
+
+ width = 0;
+
+ /*
+ * To print our quantization header for either an agghist or
+ * aggpack aggregation, we need to iterate through all of our
+ * of our records to determine their width.
+ */
+ for (r = rec; !DTRACEACT_ISAGG(r->dtrd_action); r++) {
+ for (fmt = fmttab; fmt->size &&
+ fmt->size != r->dtrd_size; fmt++)
+ continue;
+
+ width += fmt->packedwidth + 1;
+ }
+
+ if (pd->dtpa_agghist) {
+ if (dt_print_quanthdr(dtp, fp, width) < 0)
+ return (-1);
+ } else {
+ if (dt_print_quanthdr_packed(dtp, fp,
+ width, aggdata, r->dtrd_action) < 0)
+ return (-1);
+ }
+
+ pd->dtpa_agghisthdr = agg->dtagd_varid;
+ }
+
+ if (pd->dtpa_agghist && DTRACEACT_ISAGG(act)) {
+ char positives = aggdata->dtada_flags & DTRACE_A_HASPOSITIVES;
+ char negatives = aggdata->dtada_flags & DTRACE_A_HASNEGATIVES;
+ int64_t val;
+
+ assert(act == DTRACEAGG_SUM || act == DTRACEAGG_COUNT);
+ val = (long long)*((uint64_t *)addr);
+
+ if (dt_printf(dtp, fp, " ") < 0)
+ return (-1);
+
+ return (dt_print_quantline(dtp, fp, val, normal,
+ aggdata->dtada_total, positives, negatives));
+ }
+
+ if (pd->dtpa_aggpack && DTRACEACT_ISAGG(act)) {
+ switch (act) {
+ case DTRACEAGG_QUANTIZE:
+ return (dt_print_quantize_packed(dtp,
+ fp, addr, size, aggdata));
+ case DTRACEAGG_LQUANTIZE:
+ return (dt_print_lquantize_packed(dtp,
+ fp, addr, size, aggdata));
+ default:
+ break;
+ }
+ }
+
switch (act) {
case DTRACEACT_STACK:
return (dt_print_stack(dtp, fp, NULL, addr,
@@ -1847,28 +2222,33 @@
break;
}
+ for (fmt = fmttab; fmt->size && fmt->size != size; fmt++)
+ continue;
+
+ width = packed ? fmt->packedwidth : fmt->width;
+
switch (size) {
case sizeof (uint64_t):
- err = dt_printf(dtp, fp, " %16lld",
+ err = dt_printf(dtp, fp, " %*lld", width,
/* LINTED - alignment */
(long long)*((uint64_t *)addr) / normal);
break;
case sizeof (uint32_t):
/* LINTED - alignment */
- err = dt_printf(dtp, fp, " %8d", *((uint32_t *)addr) /
+ err = dt_printf(dtp, fp, " %*d", width, *((uint32_t *)addr) /
(uint32_t)normal);
break;
case sizeof (uint16_t):
/* LINTED - alignment */
- err = dt_printf(dtp, fp, " %5d", *((uint16_t *)addr) /
+ err = dt_printf(dtp, fp, " %*d", width, *((uint16_t *)addr) /
(uint32_t)normal);
break;
case sizeof (uint8_t):
- err = dt_printf(dtp, fp, " %3d", *((uint8_t *)addr) /
+ err = dt_printf(dtp, fp, " %*d", width, *((uint8_t *)addr) /
(uint32_t)normal);
break;
default:
- err = dt_print_bytes(dtp, fp, addr, size, 50, 0, 0);
+ err = dt_print_bytes(dtp, fp, addr, size, width, 0, 0);
break;
}
@@ -1889,6 +2269,9 @@
caddr_t addr;
size_t size;
+ pd->dtpa_agghist = (aggdata->dtada_flags & DTRACE_A_TOTAL);
+ pd->dtpa_aggpack = (aggdata->dtada_flags & DTRACE_A_MINMAXBIN);
+
/*
* Iterate over each record description in the key, printing the traced
* data, skipping the first datum (the tuple member created by the
@@ -1905,7 +2288,8 @@
break;
}
- if (dt_print_datum(dtp, fp, rec, addr, size, 1) < 0)
+ if (dt_print_datum(dtp, fp, rec, addr,
+ size, aggdata, 1, pd) < 0)
return (-1);
if (dt_buffered_flush(dtp, NULL, rec, aggdata,
@@ -1928,7 +2312,8 @@
assert(DTRACEACT_ISAGG(act));
normal = aggdata->dtada_normal;
- if (dt_print_datum(dtp, fp, rec, addr, size, normal) < 0)
+ if (dt_print_datum(dtp, fp, rec, addr,
+ size, aggdata, normal, pd) < 0)
return (-1);
if (dt_buffered_flush(dtp, NULL, rec, aggdata,
@@ -1939,8 +2324,10 @@
agg->dtagd_flags |= DTRACE_AGD_PRINTED;
}
- if (dt_printf(dtp, fp, "\n") < 0)
- return (-1);
+ if (!pd->dtpa_agghist && !pd->dtpa_aggpack) {
+ if (dt_printf(dtp, fp, "\n") < 0)
+ return (-1);
+ }
if (dt_buffered_flush(dtp, NULL, NULL, aggdata,
DTRACE_BUFDATA_AGGFORMAT | DTRACE_BUFDATA_AGGLAST) < 0)
@@ -2014,26 +2401,27 @@
}
static int
-dt_consume_cpu(dtrace_hdl_t *dtp, FILE *fp, int cpu, dtrace_bufdesc_t *buf,
+dt_consume_cpu(dtrace_hdl_t *dtp, FILE *fp, int cpu,
+ dtrace_bufdesc_t *buf, boolean_t just_one,
dtrace_consume_probe_f *efunc, dtrace_consume_rec_f *rfunc, void *arg)
{
dtrace_epid_t id;
- size_t offs, start = buf->dtbd_oldest, end = buf->dtbd_size;
+ size_t offs;
int flow = (dtp->dt_options[DTRACEOPT_FLOWINDENT] != DTRACEOPT_UNSET);
int quiet = (dtp->dt_options[DTRACEOPT_QUIET] != DTRACEOPT_UNSET);
int rval, i, n;
- dtrace_epid_t last = DTRACE_EPIDNONE;
uint64_t tracememsize = 0;
dtrace_probedata_t data;
uint64_t drops;
- caddr_t addr;
bzero(&data, sizeof (data));
data.dtpda_handle = dtp;
data.dtpda_cpu = cpu;
+ data.dtpda_flow = dtp->dt_flow;
+ data.dtpda_indent = dtp->dt_indent;
+ data.dtpda_prefix = dtp->dt_prefix;
-again:
- for (offs = start; offs < end; ) {
+ for (offs = buf->dtbd_oldest; offs < buf->dtbd_size; ) {
dtrace_eprobedesc_t *epd;
/*
@@ -2068,7 +2456,8 @@
}
if (flow)
- (void) dt_flowindent(dtp, &data, last, buf, offs);
+ (void) dt_flowindent(dtp, &data, dtp->dt_last_epid,
+ buf, offs);
rval = (*efunc)(&data, arg);
@@ -2087,6 +2476,7 @@
return (dt_set_errno(dtp, EDT_BADRVAL));
for (i = 0; i < epd->dtepd_nrecs; i++) {
+ caddr_t addr;
dtrace_recdesc_t *rec = &epd->dtepd_rec[i];
dtrace_actkind_t act = rec->dtrd_action;
@@ -2406,7 +2796,7 @@
}
n = dt_print_bytes(dtp, fp, addr,
- tracememsize, 33, quiet, 1);
+ tracememsize, -33, quiet, 1);
tracememsize = 0;
@@ -2439,7 +2829,7 @@
break;
default:
n = dt_print_bytes(dtp, fp, addr,
- rec->dtrd_size, 33, quiet, 0);
+ rec->dtrd_size, -33, quiet, 0);
break;
}
@@ -2458,14 +2848,16 @@
rval = (*rfunc)(&data, NULL, arg);
nextepid:
offs += epd->dtepd_size;
- last = id;
+ dtp->dt_last_epid = id;
+ if (just_one) {
+ buf->dtbd_oldest = offs;
+ break;
+ }
}
- if (buf->dtbd_oldest != 0 && start == buf->dtbd_oldest) {
- end = buf->dtbd_oldest;
- start = 0;
- goto again;
- }
+ dtp->dt_flow = data.dtpda_flow;
+ dtp->dt_indent = data.dtpda_indent;
+ dtp->dt_prefix = data.dtpda_prefix;
if ((drops = buf->dtbd_drops) == 0)
return (0);
@@ -2478,6 +2870,131 @@
return (dt_handle_cpudrop(dtp, cpu, DTRACEDROP_PRINCIPAL, drops));
}
+/*
+ * Reduce memory usage by shrinking the buffer if it's no more than half full.
+ * Note, we need to preserve the alignment of the data at dtbd_oldest, which is
+ * only 4-byte aligned.
+ */
+static void
+dt_realloc_buf(dtrace_hdl_t *dtp, dtrace_bufdesc_t *buf, int cursize)
+{
+ uint64_t used = buf->dtbd_size - buf->dtbd_oldest;
+ if (used < cursize / 2) {
+ int misalign = buf->dtbd_oldest & (sizeof (uint64_t) - 1);
+ char *newdata = dt_alloc(dtp, used + misalign);
+ if (newdata == NULL)
+ return;
+ bzero(newdata, misalign);
+ bcopy(buf->dtbd_data + buf->dtbd_oldest,
+ newdata + misalign, used);
+ dt_free(dtp, buf->dtbd_data);
+ buf->dtbd_oldest = misalign;
+ buf->dtbd_size = used + misalign;
+ buf->dtbd_data = newdata;
+ }
+}
+
+/*
+ * If the ring buffer has wrapped, the data is not in order. Rearrange it
+ * so that it is. Note, we need to preserve the alignment of the data at
+ * dtbd_oldest, which is only 4-byte aligned.
+ */
+static int
+dt_unring_buf(dtrace_hdl_t *dtp, dtrace_bufdesc_t *buf)
+{
+ int misalign;
+ char *newdata, *ndp;
+
+ if (buf->dtbd_oldest == 0)
+ return (0);
+
+ misalign = buf->dtbd_oldest & (sizeof (uint64_t) - 1);
+ newdata = ndp = dt_alloc(dtp, buf->dtbd_size + misalign);
+
+ if (newdata == NULL)
+ return (-1);
+
+ assert(0 == (buf->dtbd_size & (sizeof (uint64_t) - 1)));
+
+ bzero(ndp, misalign);
+ ndp += misalign;
+
+ bcopy(buf->dtbd_data + buf->dtbd_oldest, ndp,
+ buf->dtbd_size - buf->dtbd_oldest);
+ ndp += buf->dtbd_size - buf->dtbd_oldest;
+
+ bcopy(buf->dtbd_data, ndp, buf->dtbd_oldest);
+
+ dt_free(dtp, buf->dtbd_data);
+ buf->dtbd_oldest = 0;
+ buf->dtbd_data = newdata;
+ buf->dtbd_size += misalign;
+
+ return (0);
+}
+
+static void
+dt_put_buf(dtrace_hdl_t *dtp, dtrace_bufdesc_t *buf)
+{
+ dt_free(dtp, buf->dtbd_data);
+ dt_free(dtp, buf);
+}
+
+/*
+ * Returns 0 on success, in which case *cbp will be filled in if we retrieved
+ * data, or NULL if there is no data for this CPU.
+ * Returns -1 on failure and sets dt_errno.
+ */
+static int
+dt_get_buf(dtrace_hdl_t *dtp, int cpu, dtrace_bufdesc_t **bufp)
+{
+ dtrace_optval_t size;
+ dtrace_bufdesc_t *buf = dt_zalloc(dtp, sizeof (*buf));
+ int error, rval;
+
+ if (buf == NULL)
+ return (-1);
+
+ (void) dtrace_getopt(dtp, "bufsize", &size);
+ buf->dtbd_data = dt_alloc(dtp, size);
+ if (buf->dtbd_data == NULL) {
+ dt_free(dtp, buf);
+ return (-1);
+ }
+ buf->dtbd_size = size;
+ buf->dtbd_cpu = cpu;
+
+#ifdef illumos
+ if (dt_ioctl(dtp, DTRACEIOC_BUFSNAP, buf) == -1) {
+#else
+ if (dt_ioctl(dtp, DTRACEIOC_BUFSNAP, &buf) == -1) {
+#endif
+ /*
+ * If we failed with ENOENT, it may be because the
+ * CPU was unconfigured -- this is okay. Any other
+ * error, however, is unexpected.
+ */
+ if (errno == ENOENT) {
+ *bufp = NULL;
+ rval = 0;
+ } else
+ rval = dt_set_errno(dtp, errno);
+
+ dt_put_buf(dtp, buf);
+ return (rval);
+ }
+
+ error = dt_unring_buf(dtp, buf);
+ if (error != 0) {
+ dt_put_buf(dtp, buf);
+ return (error);
+ }
+ dt_realloc_buf(dtp, buf, size);
+
+ *bufp = buf;
+ return (0);
+}
+
typedef struct dt_begin {
dtrace_consume_probe_f *dtbgn_probefunc;
dtrace_consume_rec_f *dtbgn_recfunc;
@@ -2490,7 +3007,7 @@
static int
dt_consume_begin_probe(const dtrace_probedata_t *data, void *arg)
{
- dt_begin_t *begin = (dt_begin_t *)arg;
+ dt_begin_t *begin = arg;
dtrace_probedesc_t *pd = data->dtpda_pdesc;
int r1 = (strcmp(pd->dtpd_provider, "dtrace") == 0);
@@ -2515,7 +3032,7 @@
dt_consume_begin_record(const dtrace_probedata_t *data,
const dtrace_recdesc_t *rec, void *arg)
{
- dt_begin_t *begin = (dt_begin_t *)arg;
+ dt_begin_t *begin = arg;
return (begin->dtbgn_recfunc(data, rec, begin->dtbgn_arg));
}
@@ -2541,7 +3058,7 @@
}
static int
-dt_consume_begin(dtrace_hdl_t *dtp, FILE *fp, dtrace_bufdesc_t *buf,
+dt_consume_begin(dtrace_hdl_t *dtp, FILE *fp,
dtrace_consume_probe_f *pf, dtrace_consume_rec_f *rf, void *arg)
{
/*
@@ -2565,34 +3082,20 @@
* first pass, and that we only process ERROR enablings _not_ induced
* by BEGIN enablings in the second pass.
*/
+
dt_begin_t begin;
processorid_t cpu = dtp->dt_beganon;
- dtrace_bufdesc_t nbuf;
-#if !defined(sun)
- dtrace_bufdesc_t *pbuf;
-#endif
int rval, i;
static int max_ncpus;
- dtrace_optval_t size;
+ dtrace_bufdesc_t *buf;
dtp->dt_beganon = -1;
-#if defined(sun)
- if (dt_ioctl(dtp, DTRACEIOC_BUFSNAP, buf) == -1) {
-#else
- if (dt_ioctl(dtp, DTRACEIOC_BUFSNAP, &buf) == -1) {
-#endif
- /*
- * We really don't expect this to fail, but it is at least
- * technically possible for this to fail with ENOENT. In this
- * case, we just drive on...
- */
- if (errno == ENOENT)
- return (0);
+ if (dt_get_buf(dtp, cpu, &buf) != 0)
+ return (-1);
+ if (buf == NULL)
+ return (0);
- return (dt_set_errno(dtp, errno));
- }
-
if (!dtp->dt_stopped || buf->dtbd_cpu != dtp->dt_endedon) {
/*
* This is the simple case. We're either not stopped, or if
@@ -2599,7 +3102,10 @@
* we are, we actually processed any END probes on another
* CPU. We can simply consume this buffer and return.
*/
- return (dt_consume_cpu(dtp, fp, cpu, buf, pf, rf, arg));
+ rval = dt_consume_cpu(dtp, fp, cpu, buf, B_FALSE,
+ pf, rf, arg);
+ dt_put_buf(dtp, buf);
+ return (rval);
}
begin.dtbgn_probefunc = pf;
@@ -2616,61 +3122,41 @@
dtp->dt_errhdlr = dt_consume_begin_error;
dtp->dt_errarg = &begin;
- rval = dt_consume_cpu(dtp, fp, cpu, buf, dt_consume_begin_probe,
- dt_consume_begin_record, &begin);
+ rval = dt_consume_cpu(dtp, fp, cpu, buf, B_FALSE,
+ dt_consume_begin_probe, dt_consume_begin_record, &begin);
dtp->dt_errhdlr = begin.dtbgn_errhdlr;
dtp->dt_errarg = begin.dtbgn_errarg;
- if (rval != 0)
+ if (rval != 0) {
+ dt_put_buf(dtp, buf);
return (rval);
+ }
- /*
- * Now allocate a new buffer. We'll use this to deal with every other
- * CPU.
- */
- bzero(&nbuf, sizeof (dtrace_bufdesc_t));
- (void) dtrace_getopt(dtp, "bufsize", &size);
- if ((nbuf.dtbd_data = malloc(size)) == NULL)
- return (dt_set_errno(dtp, EDT_NOMEM));
-
if (max_ncpus == 0)
max_ncpus = dt_sysconf(dtp, _SC_CPUID_MAX) + 1;
for (i = 0; i < max_ncpus; i++) {
- nbuf.dtbd_cpu = i;
-
+ dtrace_bufdesc_t *nbuf;
if (i == cpu)
continue;
-#if defined(sun)
- if (dt_ioctl(dtp, DTRACEIOC_BUFSNAP, &nbuf) == -1) {
-#else
- pbuf = &nbuf;
- if (dt_ioctl(dtp, DTRACEIOC_BUFSNAP, &pbuf) == -1) {
-#endif
- /*
- * If we failed with ENOENT, it may be because the
- * CPU was unconfigured -- this is okay. Any other
- * error, however, is unexpected.
- */
- if (errno == ENOENT)
- continue;
-
- free(nbuf.dtbd_data);
-
- return (dt_set_errno(dtp, errno));
+ if (dt_get_buf(dtp, i, &nbuf) != 0) {
+ dt_put_buf(dtp, buf);
+ return (-1);
}
+ if (nbuf == NULL)
+ continue;
- if ((rval = dt_consume_cpu(dtp, fp,
- i, &nbuf, pf, rf, arg)) != 0) {
- free(nbuf.dtbd_data);
+ rval = dt_consume_cpu(dtp, fp, i, nbuf, B_FALSE,
+ pf, rf, arg);
+ dt_put_buf(dtp, nbuf);
+ if (rval != 0) {
+ dt_put_buf(dtp, buf);
return (rval);
}
}
- free(nbuf.dtbd_data);
-
/*
* Okay -- we're done with the other buffers. Now we want to
* reconsume the first buffer -- but this time we're looking for
@@ -2685,8 +3171,8 @@
dtp->dt_errhdlr = dt_consume_begin_error;
dtp->dt_errarg = &begin;
- rval = dt_consume_cpu(dtp, fp, cpu, buf, dt_consume_begin_probe,
- dt_consume_begin_record, &begin);
+ rval = dt_consume_cpu(dtp, fp, cpu, buf, B_FALSE,
+ dt_consume_begin_probe, dt_consume_begin_record, &begin);
dtp->dt_errhdlr = begin.dtbgn_errhdlr;
dtp->dt_errarg = begin.dtbgn_errarg;
@@ -2694,11 +3180,32 @@
return (rval);
}
+/* ARGSUSED */
+static uint64_t
+dt_buf_oldest(void *elem, void *arg)
+{
+ dtrace_bufdesc_t *buf = elem;
+ size_t offs = buf->dtbd_oldest;
+
+ while (offs < buf->dtbd_size) {
+ dtrace_rechdr_t *dtrh =
+ /* LINTED - alignment */
+ (dtrace_rechdr_t *)(buf->dtbd_data + offs);
+ if (dtrh->dtrh_epid == DTRACE_EPIDNONE) {
+ offs += sizeof (dtrace_epid_t);
+ } else {
+ return (DTRACE_RECORD_LOAD_TIMESTAMP(dtrh));
+ }
+ }
+
+ /* There are no records left; use the time the buffer was retrieved. */
+ return (buf->dtbd_timestamp);
+}
+
int
dtrace_consume(dtrace_hdl_t *dtp, FILE *fp,
dtrace_consume_probe_f *pf, dtrace_consume_rec_f *rf, void *arg)
{
- dtrace_bufdesc_t *buf = &dtp->dt_buf;
dtrace_optval_t size;
static int max_ncpus;
int i, rval;
@@ -2726,79 +3233,158 @@
if (rf == NULL)
rf = (dtrace_consume_rec_f *)dt_nullrec;
- if (buf->dtbd_data == NULL) {
- (void) dtrace_getopt(dtp, "bufsize", &size);
- if ((buf->dtbd_data = malloc(size)) == NULL)
- return (dt_set_errno(dtp, EDT_NOMEM));
-
- buf->dtbd_size = size;
- }
-
- /*
- * If we have just begun, we want to first process the CPU that
- * executed the BEGIN probe (if any).
- */
- if (dtp->dt_active && dtp->dt_beganon != -1) {
- buf->dtbd_cpu = dtp->dt_beganon;
- if ((rval = dt_consume_begin(dtp, fp, buf, pf, rf, arg)) != 0)
+ if (dtp->dt_options[DTRACEOPT_TEMPORAL] == DTRACEOPT_UNSET) {
+ /*
+ * The output will not be in the order it was traced. Rather,
+ * we will consume all of the data from each CPU's buffer in
+ * turn. We apply special handling for the records from BEGIN
+ * and END probes so that they are consumed first and last,
+ * respectively.
+ *
+ * If we have just begun, we want to first process the CPU that
+ * executed the BEGIN probe (if any).
+ */
+ if (dtp->dt_active && dtp->dt_beganon != -1 &&
+ (rval = dt_consume_begin(dtp, fp, pf, rf, arg)) != 0)
return (rval);
- }
- for (i = 0; i < max_ncpus; i++) {
- buf->dtbd_cpu = i;
+ for (i = 0; i < max_ncpus; i++) {
+ dtrace_bufdesc_t *buf;
- /*
- * If we have stopped, we want to process the CPU on which the
- * END probe was processed only _after_ we have processed
- * everything else.
- */
- if (dtp->dt_stopped && (i == dtp->dt_endedon))
- continue;
-
-#if defined(sun)
- if (dt_ioctl(dtp, DTRACEIOC_BUFSNAP, buf) == -1) {
-#else
- if (dt_ioctl(dtp, DTRACEIOC_BUFSNAP, &buf) == -1) {
-#endif
/*
- * If we failed with ENOENT, it may be because the
- * CPU was unconfigured -- this is okay. Any other
- * error, however, is unexpected.
+ * If we have stopped, we want to process the CPU on
+ * which the END probe was processed only _after_ we
+ * have processed everything else.
*/
- if (errno == ENOENT)
+ if (dtp->dt_stopped && (i == dtp->dt_endedon))
continue;
- return (dt_set_errno(dtp, errno));
+ if (dt_get_buf(dtp, i, &buf) != 0)
+ return (-1);
+ if (buf == NULL)
+ continue;
+
+ dtp->dt_flow = 0;
+ dtp->dt_indent = 0;
+ dtp->dt_prefix = NULL;
+ rval = dt_consume_cpu(dtp, fp, i,
+ buf, B_FALSE, pf, rf, arg);
+ dt_put_buf(dtp, buf);
+ if (rval != 0)
+ return (rval);
}
+ if (dtp->dt_stopped) {
+ dtrace_bufdesc_t *buf;
- if ((rval = dt_consume_cpu(dtp, fp, i, buf, pf, rf, arg)) != 0)
+ if (dt_get_buf(dtp, dtp->dt_endedon, &buf) != 0)
+ return (-1);
+ if (buf == NULL)
+ return (0);
+
+ rval = dt_consume_cpu(dtp, fp, dtp->dt_endedon,
+ buf, B_FALSE, pf, rf, arg);
+ dt_put_buf(dtp, buf);
return (rval);
- }
+ }
+ } else {
+ /*
+ * The output will be in the order it was traced (or for
+ * speculations, when it was committed). We retrieve a buffer
+ * from each CPU and put it into a priority queue, which sorts
+ * based on the first entry in the buffer. This is sufficient
+ * because entries within a buffer are already sorted.
+ *
+ * We then consume records one at a time, always consuming the
+ * oldest record, as determined by the priority queue. When
+ * we reach the end of the time covered by these buffers,
+ * we need to stop and retrieve more records on the next pass.
+ * The kernel tells us the time covered by each buffer, in
+ * dtbd_timestamp. The first buffer's timestamp tells us the
+ * time covered by all buffers, as subsequently retrieved
+ * buffers will cover to a more recent time.
+ */
- if (!dtp->dt_stopped)
- return (0);
+ uint64_t *drops = alloca(max_ncpus * sizeof (uint64_t));
+ uint64_t first_timestamp = 0;
+ uint_t cookie = 0;
+ dtrace_bufdesc_t *buf;
- buf->dtbd_cpu = dtp->dt_endedon;
+ bzero(drops, max_ncpus * sizeof (uint64_t));
-#if defined(sun)
- if (dt_ioctl(dtp, DTRACEIOC_BUFSNAP, buf) == -1) {
-#else
- if (dt_ioctl(dtp, DTRACEIOC_BUFSNAP, &buf) == -1) {
-#endif
+ if (dtp->dt_bufq == NULL) {
+ dtp->dt_bufq = dt_pq_init(dtp, max_ncpus * 2,
+ dt_buf_oldest, NULL);
+ if (dtp->dt_bufq == NULL) /* ENOMEM */
+ return (-1);
+ }
+
+ /* Retrieve data from each CPU. */
+ (void) dtrace_getopt(dtp, "bufsize", &size);
+ for (i = 0; i < max_ncpus; i++) {
+ dtrace_bufdesc_t *buf;
+
+ if (dt_get_buf(dtp, i, &buf) != 0)
+ return (-1);
+ if (buf != NULL) {
+ if (first_timestamp == 0)
+ first_timestamp = buf->dtbd_timestamp;
+ assert(buf->dtbd_timestamp >= first_timestamp);
+
+ dt_pq_insert(dtp->dt_bufq, buf);
+ drops[i] = buf->dtbd_drops;
+ buf->dtbd_drops = 0;
+ }
+ }
+
+ /* Consume records. */
+ for (;;) {
+ dtrace_bufdesc_t *buf = dt_pq_pop(dtp->dt_bufq);
+ uint64_t timestamp;
+
+ if (buf == NULL)
+ break;
+
+ timestamp = dt_buf_oldest(buf, dtp);
+ assert(timestamp >= dtp->dt_last_timestamp);
+ dtp->dt_last_timestamp = timestamp;
+
+ if (timestamp == buf->dtbd_timestamp) {
+ /*
+ * We've reached the end of the time covered
+ * by this buffer. If this is the oldest
+ * buffer, we must do another pass
+ * to retrieve more data.
+ */
+ dt_put_buf(dtp, buf);
+ if (timestamp == first_timestamp &&
+ !dtp->dt_stopped)
+ break;
+ continue;
+ }
+
+ if ((rval = dt_consume_cpu(dtp, fp,
+ buf->dtbd_cpu, buf, B_TRUE, pf, rf, arg)) != 0)
+ return (rval);
+ dt_pq_insert(dtp->dt_bufq, buf);
+ }
+
+ /* Consume drops. */
+ for (i = 0; i < max_ncpus; i++) {
+ if (drops[i] != 0) {
+ int error = dt_handle_cpudrop(dtp, i,
+ DTRACEDROP_PRINCIPAL, drops[i]);
+ if (error != 0)
+ return (error);
+ }
+ }
+
/*
- * This _really_ shouldn't fail, but it is strictly speaking
- * possible for this to return ENOENT if the CPU that called
- * the END enabling somehow managed to become unconfigured.
- * It's unclear how the user can possibly expect anything
- * rational to happen in this case -- the state has been thrown
- * out along with the unconfigured CPU -- so we'll just drive
- * on...
+ * Reduce memory usage by re-allocating smaller buffers
+ * for the "remnants".
*/
- if (errno == ENOENT)
- return (0);
-
- return (dt_set_errno(dtp, errno));
+ while (buf = dt_pq_walk(dtp->dt_bufq, &cookie))
+ dt_realloc_buf(dtp, buf, buf->dtbd_size);
}
- return (dt_consume_cpu(dtp, fp, dtp->dt_endedon, buf, pf, rf, arg));
+ return (0);
}
Modified: trunk/cddl/contrib/opensolaris/lib/libdtrace/common/dt_decl.c
===================================================================
--- trunk/cddl/contrib/opensolaris/lib/libdtrace/common/dt_decl.c 2018-06-02 16:07:17 UTC (rev 10228)
+++ trunk/cddl/contrib/opensolaris/lib/libdtrace/common/dt_decl.c 2018-06-02 16:07:30 UTC (rev 10229)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*
* CDDL HEADER START
*
@@ -21,6 +22,8 @@
*/
/*
* Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+ * Copyright (c) 2013 by Delphix. All rights reserved.
+ * Copyright (c) 2013 Joyent, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -254,11 +257,6 @@
ddp->dd_kind = kind;
ddp->dd_name = name;
- if (name != NULL && strchr(name, '`') != NULL) {
- xyerror(D_DECL_SCOPE, "D scoping operator may not be used "
- "in a type name\n");
- }
-
return (dt_decl_check(ddp));
}
@@ -783,7 +781,7 @@
yyintdecimal = 0;
dnp = dt_node_int(value);
- dt_node_type_assign(dnp, dsp->ds_ctfp, dsp->ds_type);
+ dt_node_type_assign(dnp, dsp->ds_ctfp, dsp->ds_type, B_FALSE);
if ((inp = malloc(sizeof (dt_idnode_t))) == NULL)
longjmp(yypcb->pcb_jmpbuf, EDT_NOMEM);
@@ -825,6 +823,8 @@
char *name;
int rv;
+ tip->dtt_flags = 0;
+
/*
* Based on our current #include depth and decl stack depth, determine
* which dynamic CTF module and scope to use when adding any new types.
@@ -832,6 +832,9 @@
dmp = yypcb->pcb_idepth ? dtp->dt_cdefs : dtp->dt_ddefs;
flag = yypcb->pcb_dstack.ds_next ? CTF_ADD_NONROOT : CTF_ADD_ROOT;
+ if (ddp->dd_attr & DT_DA_USER)
+ tip->dtt_flags = DTT_FL_USER;
+
/*
* If we have already cached a CTF type for this decl, then we just
* return the type information for the cached type.
Modified: trunk/cddl/contrib/opensolaris/lib/libdtrace/common/dt_decl.h
===================================================================
--- trunk/cddl/contrib/opensolaris/lib/libdtrace/common/dt_decl.h 2018-06-02 16:07:17 UTC (rev 10228)
+++ trunk/cddl/contrib/opensolaris/lib/libdtrace/common/dt_decl.h 2018-06-02 16:07:30 UTC (rev 10229)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*
* CDDL HEADER START
*
@@ -23,12 +24,14 @@
* Copyright 2005 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
+/*
+ * Copyright (c) 2013 by Delphix. All rights reserved.
+ * Copyright (c) 2013 Joyent, Inc. All rights reserved.
+ */
#ifndef _DT_DECL_H
#define _DT_DECL_H
-#pragma ident "%Z%%M% %I% %E% SMI"
-
#include <sys/types.h>
#include <libctf.h>
#include <dtrace.h>
@@ -59,6 +62,7 @@
#define DT_DA_RESTRICT 0x0040 /* qualify type as restrict */
#define DT_DA_VOLATILE 0x0080 /* qualify type as volatile */
#define DT_DA_PAREN 0x0100 /* parenthesis tag */
+#define DT_DA_USER 0x0200 /* user-land type specifier */
typedef enum dt_dclass {
DT_DC_DEFAULT, /* no storage class specified */
Modified: trunk/cddl/contrib/opensolaris/lib/libdtrace/common/dt_dis.c
===================================================================
--- trunk/cddl/contrib/opensolaris/lib/libdtrace/common/dt_dis.c 2018-06-02 16:07:17 UTC (rev 10228)
+++ trunk/cddl/contrib/opensolaris/lib/libdtrace/common/dt_dis.c 2018-06-02 16:07:30 UTC (rev 10229)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*
* CDDL HEADER START
*
@@ -19,12 +20,16 @@
*
* CDDL HEADER END
*/
+
/*
* Copyright 2005 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
+/*
+ * Copyright (c) 2013 by Delphix. All rights reserved.
+ * Copyright (c) 2013 Joyent, Inc. All rights reserved.
+ */
#include <strings.h>
#include <stdio.h>
@@ -212,12 +217,22 @@
{
static const char *const tnames[] = { "D type", "string" };
uint_t type = DIF_INSTR_TYPE(in);
+ const char *pad;
- (void) fprintf(fp, "%-4s DT_TYPE(%u), %%r%u, %%r%u",
- name, type, DIF_INSTR_R2(in), DIF_INSTR_RS(in));
+ if (DIF_INSTR_OP(in) == DIF_OP_PUSHTV) {
+ (void) fprintf(fp, "%-4s DT_TYPE(%u), %%r%u",
+ name, type, DIF_INSTR_RS(in));
+ pad = "\t\t";
+ } else {
+ (void) fprintf(fp, "%-4s DT_TYPE(%u), %%r%u, %%r%u",
+ name, type, DIF_INSTR_R2(in), DIF_INSTR_RS(in));
+ pad = "\t";
+ }
- if (type < sizeof (tnames) / sizeof (tnames[0]))
- (void) fprintf(fp, "\t! DT_TYPE(%u) = %s", type, tnames[type]);
+ if (type < sizeof (tnames) / sizeof (tnames[0])) {
+ (void) fprintf(fp, "%s! DT_TYPE(%u) = %s", pad,
+ type, tnames[type]);
+ }
}
static void
@@ -299,9 +314,10 @@
(void) snprintf(ckind, sizeof (ckind), "0x%x", t->dtdt_ckind);
}
- if (t->dtdt_flags & DIF_TF_BYREF) {
- (void) snprintf(buf, len, "%s (%s) by ref (size %lu)",
- kind, ckind, (ulong_t)t->dtdt_size);
+ if (t->dtdt_flags & (DIF_TF_BYREF | DIF_TF_BYUREF)) {
+ (void) snprintf(buf, len, "%s (%s) by %sref (size %lu)",
+ kind, ckind, (t->dtdt_flags & DIF_TF_BYUREF) ? "user " : "",
+ (ulong_t)t->dtdt_size);
} else {
(void) snprintf(buf, len, "%s (%s) (size %lu)",
kind, ckind, (ulong_t)t->dtdt_size);
Modified: trunk/cddl/contrib/opensolaris/lib/libdtrace/common/dt_dof.c
===================================================================
--- trunk/cddl/contrib/opensolaris/lib/libdtrace/common/dt_dof.c 2018-06-02 16:07:17 UTC (rev 10228)
+++ trunk/cddl/contrib/opensolaris/lib/libdtrace/common/dt_dof.c 2018-06-02 16:07:30 UTC (rev 10229)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*
* CDDL HEADER START
*
@@ -22,15 +23,16 @@
/*
* Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2011 by Delphix. All rights reserved.
+ * Copyright (c) 2013, Joyent, Inc. All rights reserved.
*/
#include <sys/types.h>
-#if defined(sun)
+#ifdef illumos
#include <sys/sysmacros.h>
#endif
#include <strings.h>
-#if defined(sun)
+#ifdef illumos
#include <alloca.h>
#endif
#include <assert.h>
@@ -486,7 +488,7 @@
return (0);
}
-static void
+static int
dof_add_provider(dt_dof_t *ddo, const dt_provider_t *pvp)
{
dtrace_hdl_t *dtp = ddo->ddo_hdl;
@@ -497,8 +499,12 @@
size_t sz;
id_t i;
- if (pvp->pv_flags & DT_PROVIDER_IMPL)
- return; /* ignore providers that are exported by dtrace(7D) */
+ if (pvp->pv_flags & DT_PROVIDER_IMPL) {
+ /*
+ * ignore providers that are exported by dtrace(7D)
+ */
+ return (0);
+ }
nxr = dt_popcb(pvp->pv_xrefs, pvp->pv_xrmax);
dofs = alloca(sizeof (dof_secidx_t) * (nxr + 1));
@@ -525,6 +531,9 @@
(void) dt_idhash_iter(pvp->pv_probes, dof_add_probe, ddo);
+ if (dt_buf_len(&ddo->ddo_probes) == 0)
+ return (dt_set_errno(dtp, EDT_NOPROBES));
+
dofpv.dofpv_probes = dof_add_lsect(ddo, NULL, DOF_SECT_PROBES,
sizeof (uint64_t), 0, sizeof (dof_probe_t),
dt_buf_len(&ddo->ddo_probes));
@@ -579,6 +588,8 @@
sizeof (dof_secidx_t), 0, sizeof (dof_secidx_t),
sizeof (dof_secidx_t) * (nxr + 1));
}
+
+ return (0);
}
static int
@@ -822,8 +833,10 @@
*/
if (flags & DTRACE_D_PROBES) {
for (pvp = dt_list_next(&dtp->dt_provlist);
- pvp != NULL; pvp = dt_list_next(pvp))
- dof_add_provider(ddo, pvp);
+ pvp != NULL; pvp = dt_list_next(pvp)) {
+ if (dof_add_provider(ddo, pvp) != 0)
+ return (NULL);
+ }
}
/*
Modified: trunk/cddl/contrib/opensolaris/lib/libdtrace/common/dt_dof.h
===================================================================
--- trunk/cddl/contrib/opensolaris/lib/libdtrace/common/dt_dof.h 2018-06-02 16:07:17 UTC (rev 10228)
+++ trunk/cddl/contrib/opensolaris/lib/libdtrace/common/dt_dof.h 2018-06-02 16:07:30 UTC (rev 10229)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*
* CDDL HEADER START
*
Modified: trunk/cddl/contrib/opensolaris/lib/libdtrace/common/dt_error.c
===================================================================
--- trunk/cddl/contrib/opensolaris/lib/libdtrace/common/dt_error.c 2018-06-02 16:07:17 UTC (rev 10228)
+++ trunk/cddl/contrib/opensolaris/lib/libdtrace/common/dt_error.c 2018-06-02 16:07:30 UTC (rev 10229)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*
* CDDL HEADER START
*
@@ -18,11 +19,17 @@
*
* CDDL HEADER END
*/
+
/*
* Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
+/*
+ * Copyright (c) 2012 by Delphix. All rights reserved.
+ * Copyright (c) 2013, Joyent, Inc. All rights reserved.
+ */
+
#include <string.h>
#include <strings.h>
#include <dt_impl.h>
@@ -37,7 +44,6 @@
{ EDT_VERSREDUCED, "Requested version conflicts with earlier setting" },
{ EDT_CTF, "Unexpected libctf error" },
{ EDT_COMPILER, "Error in D program compilation" },
- { EDT_NOREG, "Insufficient registers to generate code" },
{ EDT_NOTUPREG, "Insufficient tuple registers to generate code" },
{ EDT_NOMEM, "Memory allocation failure" },
{ EDT_INT2BIG, "Integer constant table limit exceeded" },
@@ -105,7 +111,9 @@
{ EDT_BADSTACKPC, "Invalid stack program counter size" },
{ EDT_BADAGGVAR, "Invalid aggregation variable identifier" },
{ EDT_OVERSION, "Client requested deprecated version of library" },
- { EDT_ENABLING_ERR, "Failed to enable probe" }
+ { EDT_ENABLING_ERR, "Failed to enable probe" },
+ { EDT_NOPROBES, "No probe sites found for declared provider" },
+ { EDT_CANTLOAD, "Failed to load module" },
};
static const int _dt_nerr = sizeof (_dt_errlist) / sizeof (_dt_errlist[0]);
@@ -138,7 +146,7 @@
return (dtp->dt_errno);
}
-#if defined(sun)
+#ifdef illumos
int
dt_set_errno(dtrace_hdl_t *dtp, int err)
{
Modified: trunk/cddl/contrib/opensolaris/lib/libdtrace/common/dt_errtags.h
===================================================================
--- trunk/cddl/contrib/opensolaris/lib/libdtrace/common/dt_errtags.h 2018-06-02 16:07:17 UTC (rev 10228)
+++ trunk/cddl/contrib/opensolaris/lib/libdtrace/common/dt_errtags.h 2018-06-02 16:07:30 UTC (rev 10229)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*
* CDDL HEADER START
*
@@ -26,7 +27,7 @@
/*
* Copyright (c) 2011, Joyent, Inc. All rights reserved.
- * Copyright (c) 2011 by Delphix. All rights reserved.
+ * Copyright (c) 2012 by Delphix. All rights reserved.
*/
#ifndef _DT_ERRTAGS_H
@@ -190,8 +191,10 @@
D_PRINTA_AGGPROTO, /* printa() aggregation mismatch */
D_TRACE_VOID, /* trace() argument has void type */
D_TRACE_DYN, /* trace() argument has dynamic type */
+ D_TRACE_AGG, /* trace() argument is an aggregation */
D_PRINT_VOID, /* print() argument has void type */
D_PRINT_DYN, /* print() argument has dynamic type */
+ D_PRINT_AGG, /* print() argument is an aggregation */
D_TRACEMEM_ADDR, /* tracemem() address bad type */
D_TRACEMEM_SIZE, /* tracemem() size bad type */
D_TRACEMEM_ARGS, /* tracemem() illegal number of args */
@@ -260,6 +263,7 @@
D_LLQUANT_FACTOREVEN, /* llquantize() bad # steps/factor */
D_LLQUANT_FACTORSMALL, /* llquantize() magnitude too small */
D_LLQUANT_MAGTOOBIG, /* llquantize() high mag too large */
+ D_NOREG, /* no available internal registers */
D_PRINTM_ADDR, /* printm() memref bad type */
D_PRINTM_SIZE, /* printm() size bad type */
D_PRINTT_ADDR, /* printt() typeref bad type */
Modified: trunk/cddl/contrib/opensolaris/lib/libdtrace/common/dt_grammar.y
===================================================================
--- trunk/cddl/contrib/opensolaris/lib/libdtrace/common/dt_grammar.y 2018-06-02 16:07:17 UTC (rev 10228)
+++ trunk/cddl/contrib/opensolaris/lib/libdtrace/common/dt_grammar.y 2018-06-02 16:07:30 UTC (rev 10229)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
%{
/*
* CDDL HEADER START
@@ -23,9 +24,11 @@
* Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
+/*
+ * Copyright (c) 2013 by Delphix. All rights reserved.
+ * Copyright (c) 2013, Joyent, Inc. All rights reserved.
+ */
-#pragma ident "%Z%%M% %I% %E% SMI"
-
#include <dt_impl.h>
#define OP1(op, c) dt_node_op1(op, c)
@@ -102,6 +105,7 @@
%token DT_KEY_TYPEDEF
%token DT_KEY_UNION
%token DT_KEY_UNSIGNED
+%token DT_KEY_USERLAND
%token DT_KEY_VOID
%token DT_KEY_VOLATILE
%token DT_KEY_WHILE
@@ -204,6 +208,8 @@
%type <l_tok> unary_operator
%type <l_tok> struct_or_union
+%type <l_str> dtrace_keyword_ident
+
%%
dtrace_program: d_expression DT_TOK_EOF { return (dt_node_root($1)); }
@@ -388,6 +394,9 @@
| postfix_expression DT_TOK_DOT DT_TOK_TNAME {
$$ = OP2(DT_TOK_DOT, $1, dt_node_ident($3));
}
+ | postfix_expression DT_TOK_DOT dtrace_keyword_ident {
+ $$ = OP2(DT_TOK_DOT, $1, dt_node_ident($3));
+ }
| postfix_expression DT_TOK_PTR DT_TOK_IDENT {
$$ = OP2(DT_TOK_PTR, $1, dt_node_ident($3));
}
@@ -394,6 +403,9 @@
| postfix_expression DT_TOK_PTR DT_TOK_TNAME {
$$ = OP2(DT_TOK_PTR, $1, dt_node_ident($3));
}
+ | postfix_expression DT_TOK_PTR dtrace_keyword_ident {
+ $$ = OP2(DT_TOK_PTR, $1, dt_node_ident($3));
+ }
| postfix_expression DT_TOK_ADDADD {
$$ = OP1(DT_TOK_POSTINC, $1);
}
@@ -408,6 +420,10 @@
DT_TOK_TNAME DT_TOK_RPAR {
$$ = dt_node_offsetof($3, $5);
}
+ | DT_TOK_OFFSETOF DT_TOK_LPAR type_name DT_TOK_COMMA
+ dtrace_keyword_ident DT_TOK_RPAR {
+ $$ = dt_node_offsetof($3, $5);
+ }
| DT_TOK_XLATE DT_TOK_LT type_name DT_TOK_GT
DT_TOK_LPAR expression DT_TOK_RPAR {
$$ = OP2(DT_TOK_XLATE, dt_node_type($3), $6);
@@ -633,6 +649,7 @@
| DT_KEY_DOUBLE { $$ = dt_decl_spec(CTF_K_FLOAT, DUP("double")); }
| DT_KEY_SIGNED { $$ = dt_decl_attr(DT_DA_SIGNED); }
| DT_KEY_UNSIGNED { $$ = dt_decl_attr(DT_DA_UNSIGNED); }
+ | DT_KEY_USERLAND { $$ = dt_decl_attr(DT_DA_USER); }
| DT_KEY_STRING {
$$ = dt_decl_spec(CTF_K_TYPEDEF, DUP("string"));
}
@@ -831,4 +848,15 @@
| parameter_type_list { $$ = $1; }
;
+dtrace_keyword_ident:
+ DT_KEY_PROBE { $$ = DUP("probe"); }
+ | DT_KEY_PROVIDER { $$ = DUP("provider"); }
+ | DT_KEY_SELF { $$ = DUP("self"); }
+ | DT_KEY_STRING { $$ = DUP("string"); }
+ | DT_TOK_STRINGOF { $$ = DUP("stringof"); }
+ | DT_KEY_USERLAND { $$ = DUP("userland"); }
+ | DT_TOK_XLATE { $$ = DUP("xlate"); }
+ | DT_KEY_XLATOR { $$ = DUP("translator"); }
+ ;
+
%%
Property changes on: trunk/cddl/contrib/opensolaris/lib/libdtrace/common/dt_grammar.y
___________________________________________________________________
Added: mnbsd:nokeywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Modified: trunk/cddl/contrib/opensolaris/lib/libdtrace/common/dt_handle.c
===================================================================
--- trunk/cddl/contrib/opensolaris/lib/libdtrace/common/dt_handle.c 2018-06-02 16:07:17 UTC (rev 10228)
+++ trunk/cddl/contrib/opensolaris/lib/libdtrace/common/dt_handle.c 2018-06-02 16:07:30 UTC (rev 10229)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*
* CDDL HEADER START
*
@@ -31,7 +32,7 @@
#include <errno.h>
#include <unistd.h>
#include <assert.h>
-#if defined(sun)
+#ifdef illumos
#include <alloca.h>
#endif
Modified: trunk/cddl/contrib/opensolaris/lib/libdtrace/common/dt_ident.c
===================================================================
--- trunk/cddl/contrib/opensolaris/lib/libdtrace/common/dt_ident.c 2018-06-02 16:07:17 UTC (rev 10228)
+++ trunk/cddl/contrib/opensolaris/lib/libdtrace/common/dt_ident.c 2018-06-02 16:07:30 UTC (rev 10229)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*
* CDDL HEADER START
*
@@ -22,22 +23,24 @@
/*
* Copyright 2007 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
+ * Copyright (c) 2013 by Delphix. All rights reserved.
+ * Copyright (c) 2013 Joyent, Inc. All rights reserved.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
-#if defined(sun)
+#ifdef illumos
#include <sys/sysmacros.h>
#endif
#include <strings.h>
#include <stdlib.h>
-#if defined(sun)
+#ifdef illumos
#include <alloca.h>
#endif
#include <assert.h>
#include <errno.h>
#include <ctype.h>
-#if defined(sun)
+#ifdef illumos
#include <sys/procfs_isa.h>
#endif
#include <limits.h>
@@ -104,7 +107,7 @@
}
}
- dt_node_type_assign(dnp, idp->di_ctfp, idp->di_type);
+ dt_node_type_assign(dnp, idp->di_ctfp, idp->di_type, B_FALSE);
}
/*
@@ -163,7 +166,7 @@
if (argc != 0)
isp->dis_args[argc - 1].dn_list = NULL;
- dt_node_type_assign(dnp, idp->di_ctfp, idp->di_type);
+ dt_node_type_assign(dnp, idp->di_ctfp, idp->di_type, B_FALSE);
} else {
dt_idcook_sign(dnp, idp, argc, args,
@@ -304,7 +307,7 @@
}
dt_node_type_assign(&isp->dis_args[i],
- dtt.dtt_ctfp, dtt.dtt_type);
+ dtt.dtt_ctfp, dtt.dtt_type, B_FALSE);
}
}
@@ -391,7 +394,9 @@
dt_node_type_assign(dnp,
prp->pr_argv[ap->dn_value].dtt_ctfp,
- prp->pr_argv[ap->dn_value].dtt_type);
+ prp->pr_argv[ap->dn_value].dtt_type,
+ prp->pr_argv[ap->dn_value].dtt_flags & DTT_FL_USER ?
+ B_TRUE : B_FALSE);
} else if ((dxp = dt_xlator_lookup(dtp,
nnp, xnp, DT_XLATE_FUZZY)) != NULL || (
@@ -419,7 +424,8 @@
dnp->dn_ident->di_ctfp = xidp->di_ctfp;
dnp->dn_ident->di_type = xidp->di_type;
- dt_node_type_assign(dnp, DT_DYN_CTFP(dtp), DT_DYN_TYPE(dtp));
+ dt_node_type_assign(dnp, DT_DYN_CTFP(dtp), DT_DYN_TYPE(dtp),
+ B_FALSE);
} else {
xyerror(D_ARGS_XLATOR, "translator for %s[%lld] from %s to %s "
@@ -465,7 +471,7 @@
idp->di_ctfp = dtt.dtt_ctfp;
idp->di_type = dtt.dtt_type;
- dt_node_type_assign(dnp, idp->di_ctfp, idp->di_type);
+ dt_node_type_assign(dnp, idp->di_ctfp, idp->di_type, B_FALSE);
}
/*ARGSUSED*/
@@ -487,7 +493,7 @@
idp->di_type = dtt.dtt_type;
}
- dt_node_type_assign(dnp, idp->di_ctfp, idp->di_type);
+ dt_node_type_assign(dnp, idp->di_ctfp, idp->di_type, B_FALSE);
}
/*ARGSUSED*/
@@ -495,7 +501,7 @@
dt_idcook_thaw(dt_node_t *dnp, dt_ident_t *idp, int argc, dt_node_t *args)
{
if (idp->di_ctfp != NULL && idp->di_type != CTF_ERR)
- dt_node_type_assign(dnp, idp->di_ctfp, idp->di_type);
+ dt_node_type_assign(dnp, idp->di_ctfp, idp->di_type, B_FALSE);
}
static void
Modified: trunk/cddl/contrib/opensolaris/lib/libdtrace/common/dt_ident.h
===================================================================
--- trunk/cddl/contrib/opensolaris/lib/libdtrace/common/dt_ident.h 2018-06-02 16:07:17 UTC (rev 10228)
+++ trunk/cddl/contrib/opensolaris/lib/libdtrace/common/dt_ident.h 2018-06-02 16:07:30 UTC (rev 10229)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*
* CDDL HEADER START
*
Modified: trunk/cddl/contrib/opensolaris/lib/libdtrace/common/dt_impl.h
===================================================================
--- trunk/cddl/contrib/opensolaris/lib/libdtrace/common/dt_impl.h 2018-06-02 16:07:17 UTC (rev 10228)
+++ trunk/cddl/contrib/opensolaris/lib/libdtrace/common/dt_impl.h 2018-06-02 16:07:30 UTC (rev 10229)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*
* CDDL HEADER START
*
@@ -25,8 +26,8 @@
*/
/*
- * Copyright (c) 2011, Joyent, Inc. All rights reserved.
- * Copyright (c) 2011 by Delphix. All rights reserved.
+ * Copyright (c) 2013, Joyent, Inc. All rights reserved.
+ * Copyright (c) 2012 by Delphix. All rights reserved.
*/
#ifndef _DT_IMPL_H
@@ -34,7 +35,7 @@
#include <sys/param.h>
#include <sys/objfs.h>
-#if !defined(sun)
+#ifndef illumos
#include <sys/bitmap.h>
#include <sys/utsname.h>
#include <sys/ioccom.h>
@@ -45,7 +46,7 @@
#include <libctf.h>
#include <dtrace.h>
#include <gelf.h>
-#if defined(sun)
+#ifdef illumos
#include <synch.h>
#endif
@@ -64,6 +65,7 @@
#include <dt_proc.h>
#include <dt_dof.h>
#include <dt_pcb.h>
+#include <dt_pq.h>
struct dt_module; /* see below */
struct dt_pfdict; /* see <dt_printf.h> */
@@ -141,10 +143,14 @@
GElf_Addr dm_bss_va; /* virtual address of BSS */
GElf_Xword dm_bss_size; /* size in bytes of BSS */
dt_idhash_t *dm_extern; /* external symbol definitions */
-#if !defined(sun)
+#ifndef illumos
caddr_t dm_reloc_offset; /* Symbol relocation offset. */
uintptr_t *dm_sec_offsets;
#endif
+ pid_t dm_pid; /* pid for this module */
+ uint_t dm_nctflibs; /* number of ctf children libraries */
+ ctf_file_t **dm_libctfp; /* process library ctf pointers */
+ char **dm_libctfn; /* names of process ctf containers */
} dt_module_t;
#define DT_DM_LOADED 0x1 /* module symbol and type data is loaded */
@@ -188,6 +194,9 @@
dtrace_aggvarid_t dtpa_id; /* aggregation variable of interest */
FILE *dtpa_fp; /* file pointer */
int dtpa_allunprint; /* print only unprinted aggregations */
+ int dtpa_agghist; /* print aggregation as histogram */
+ int dtpa_agghisthdr; /* aggregation histogram hdr printed */
+ int dtpa_aggpack; /* pack quantized aggregations */
} dt_print_aggdata_t;
typedef struct dt_dirpath {
@@ -239,6 +248,7 @@
uint_t dt_provbuckets; /* number of provider hash buckets */
uint_t dt_nprovs; /* number of providers in hash and list */
dt_proc_hash_t *dt_procs; /* hash table of grabbed process handles */
+ char **dt_proc_env; /* additional environment variables */
dt_intdesc_t dt_ints[6]; /* cached integer type descriptions */
ctf_id_t dt_type_func; /* cached CTF identifier for function type */
ctf_id_t dt_type_fptr; /* cached CTF identifier for function pointer */
@@ -257,7 +267,7 @@
int dt_maxstrdata; /* max strdata ID */
char **dt_strdata; /* pointer to strdata array */
dt_aggregate_t dt_aggregate; /* aggregate */
- dtrace_bufdesc_t dt_buf; /* staging buffer */
+ dt_pq_t *dt_bufq; /* CPU-specific data queue */
struct dt_pfdict *dt_pfdict; /* dictionary of printf conversions */
dt_version_t dt_vmax; /* optional ceiling on program API binding */
dtrace_attribute_t dt_amin; /* optional floor on program attributes */
@@ -281,12 +291,13 @@
uint_t dt_linktype; /* dtrace link output file type (see below) */
uint_t dt_xlatemode; /* dtrace translator linking mode (see below) */
uint_t dt_stdcmode; /* dtrace stdc compatibility mode (see below) */
+ uint_t dt_encoding; /* dtrace output encoding (see below) */
uint_t dt_treedump; /* dtrace tree debug bitmap (see below) */
uint64_t dt_options[DTRACEOPT_MAX]; /* dtrace run-time options */
int dt_version; /* library version requested by client */
int dt_ctferr; /* error resulting from last CTF failure */
int dt_errno; /* error resulting from last failed operation */
-#if !defined(sun)
+#ifndef illumos
const char *dt_errfile;
int dt_errline;
#endif
@@ -295,7 +306,7 @@
int dt_fterr; /* saved errno from failed open of dt_ftfd */
int dt_cdefs_fd; /* file descriptor for C CTF debugging cache */
int dt_ddefs_fd; /* file descriptor for D CTF debugging cache */
-#if defined(sun)
+#ifdef illumos
int dt_stdout_fd; /* file descriptor for saved stdout */
#else
FILE *dt_freopen_fp; /* file pointer for freopened stdout */
@@ -326,6 +337,11 @@
struct utsname dt_uts; /* uname(2) information for system */
dt_list_t dt_lib_dep; /* scratch linked-list of lib dependencies */
dt_list_t dt_lib_dep_sorted; /* dependency sorted library list */
+ dtrace_flowkind_t dt_flow; /* flow kind */
+ const char *dt_prefix; /* recommended flow prefix */
+ int dt_indent; /* recommended flow indent */
+ dtrace_epid_t dt_last_epid; /* most recently consumed EPID */
+ uint64_t dt_last_timestamp; /* most recently consumed timestamp */
};
/*
@@ -367,6 +383,14 @@
#define DT_STDC_XT 3 /* ISO C + K&R C compat with ISO: __STDC__=0 */
/*
+ * Values for the dt_encoding property, which is used to force a particular
+ * character encoding (overriding default behavior and/or automatic detection).
+ */
+#define DT_ENCODING_UNSET 0
+#define DT_ENCODING_ASCII 1
+#define DT_ENCODING_UTF8 2
+
+/*
* Macro to test whether a given pass bit is set in the dt_treedump bit-vector.
* If the bit for pass 'p' is set, the D compiler displays the parse tree for
* the program by printing it to stderr at the end of compiler pass 'p'.
@@ -461,7 +485,6 @@
EDT_VERSREDUCED, /* requested API version has been reduced */
EDT_CTF, /* libctf called failed (dt_ctferr has more) */
EDT_COMPILER, /* error in D program compilation */
- EDT_NOREG, /* register allocation failure */
EDT_NOTUPREG, /* tuple register allocation failure */
EDT_NOMEM, /* memory allocation failure */
EDT_INT2BIG, /* integer limit exceeded */
@@ -529,7 +552,9 @@
EDT_BADSTACKPC, /* invalid stack program counter size */
EDT_BADAGGVAR, /* invalid aggregation variable identifier */
EDT_OVERSION, /* client is requesting deprecated version */
- EDT_ENABLING_ERR /* failed to enable probe */
+ EDT_ENABLING_ERR, /* failed to enable probe */
+ EDT_NOPROBES, /* no probes sites for declared provider */
+ EDT_CANTLOAD /* failed to load a module */
};
/*
@@ -572,7 +597,7 @@
extern char *dt_cpp_add_arg(dtrace_hdl_t *, const char *);
extern char *dt_cpp_pop_arg(dtrace_hdl_t *);
-#if defined(sun)
+#ifdef illumos
extern int dt_set_errno(dtrace_hdl_t *, int);
#else
int _dt_set_errno(dtrace_hdl_t *, int, const char *, int);
@@ -582,7 +607,7 @@
extern void dt_set_errmsg(dtrace_hdl_t *, const char *, const char *,
const char *, int, const char *, va_list);
-#if defined(sun)
+#ifdef illumos
extern int dt_ioctl(dtrace_hdl_t *, int, void *);
#else
extern int dt_ioctl(dtrace_hdl_t *, u_long, void *);
Modified: trunk/cddl/contrib/opensolaris/lib/libdtrace/common/dt_inttab.c
===================================================================
--- trunk/cddl/contrib/opensolaris/lib/libdtrace/common/dt_inttab.c 2018-06-02 16:07:17 UTC (rev 10228)
+++ trunk/cddl/contrib/opensolaris/lib/libdtrace/common/dt_inttab.c 2018-06-02 16:07:30 UTC (rev 10229)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*
* CDDL HEADER START
*
Modified: trunk/cddl/contrib/opensolaris/lib/libdtrace/common/dt_inttab.h
===================================================================
--- trunk/cddl/contrib/opensolaris/lib/libdtrace/common/dt_inttab.h 2018-06-02 16:07:17 UTC (rev 10228)
+++ trunk/cddl/contrib/opensolaris/lib/libdtrace/common/dt_inttab.h 2018-06-02 16:07:30 UTC (rev 10229)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*
* CDDL HEADER START
*
Modified: trunk/cddl/contrib/opensolaris/lib/libdtrace/common/dt_lex.l
===================================================================
--- trunk/cddl/contrib/opensolaris/lib/libdtrace/common/dt_lex.l 2018-06-02 16:07:17 UTC (rev 10228)
+++ trunk/cddl/contrib/opensolaris/lib/libdtrace/common/dt_lex.l 2018-06-02 16:07:30 UTC (rev 10229)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
%{
/*
* CDDL HEADER START
@@ -23,6 +24,10 @@
/*
* Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
*/
+/*
+ * Copyright (c) 2013 by Delphix. All rights reserved.
+ * Copyright (c) 2013, Joyent, Inc. All rights reserved.
+ */
#include <string.h>
#include <stdlib.h>
@@ -40,7 +45,7 @@
* We need to undefine lex's input and unput macros so that references to these
* call the functions provided at the end of this source file.
*/
-#if defined(sun)
+#ifdef illumos
#undef input
#undef unput
#else
@@ -75,7 +80,7 @@
#endif
static int id_or_type(const char *);
-#if defined(sun)
+#ifdef illumos
static int input(void);
static void unput(int);
#endif
@@ -93,13 +98,17 @@
%}
%e 1500 /* maximum nodes */
-%p 3700 /* maximum positions */
+%p 4900 /* maximum positions */
%n 600 /* maximum states */
+%a 3000 /* maximum transitions */
%s S0 S1 S2 S3 S4
RGX_AGG "@"[a-zA-Z_][0-9a-zA-Z_]*
RGX_PSPEC [-$:a-zA-Z_.?*\\\[\]!][-$:0-9a-zA-Z_.`?*\\\[\]!]*
+RGX_ALTIDENT [a-zA-Z_][0-9a-zA-Z_]*
+RGX_LMID LM[0-9a-fA-F]+`
+RGX_MOD_IDENT [a-zA-Z_`][0-9a-z.A-Z_`]*`
RGX_IDENT [a-zA-Z_`][0-9a-zA-Z_`]*
RGX_INT ([0-9]+|0[xX][0-9A-Fa-f]+)[uU]?[lL]?[lL]?
RGX_FP ([0-9]+("."?)[0-9]*|"."[0-9]+)((e|E)("+"|-)?[0-9]+)?[fFlL]?
@@ -169,6 +178,7 @@
<S0>typedef return (DT_KEY_TYPEDEF);
<S0>union return (DT_KEY_UNION);
<S0>unsigned return (DT_KEY_UNSIGNED);
+<S0>userland return (DT_KEY_USERLAND);
<S0>void return (DT_KEY_VOID);
<S0>volatile return (DT_KEY_VOLATILE);
<S0>while return (DT_KEY_WHILE);
@@ -347,7 +357,9 @@
return (DT_TOK_INT);
}
-<S0>{RGX_IDENT} {
+<S0>{RGX_IDENT} |
+<S0>{RGX_MOD_IDENT}{RGX_IDENT} |
+<S0>{RGX_MOD_IDENT} {
return (id_or_type(yytext));
}
@@ -729,9 +741,10 @@
yypcb = pcb;
yylineno = 1;
yypragma = NULL;
-#if defined(sun)
+#ifdef illumos
yysptr = yysbuf;
#endif
+ YY_FLUSH_BUFFER;
}
/*
@@ -827,7 +840,7 @@
return (ttok);
}
-#if defined(sun)
+#ifdef illumos
static int
input(void)
{
@@ -869,4 +882,4 @@
*yysptr++ = c;
yytchar = c;
}
-#endif
+#endif /* illumos */
Property changes on: trunk/cddl/contrib/opensolaris/lib/libdtrace/common/dt_lex.l
___________________________________________________________________
Added: mnbsd:nokeywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Modified: trunk/cddl/contrib/opensolaris/lib/libdtrace/common/dt_link.c
===================================================================
--- trunk/cddl/contrib/opensolaris/lib/libdtrace/common/dt_link.c 2018-06-02 16:07:17 UTC (rev 10228)
+++ trunk/cddl/contrib/opensolaris/lib/libdtrace/common/dt_link.c 2018-06-02 16:07:30 UTC (rev 10229)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*
* CDDL HEADER START
*
@@ -30,7 +31,7 @@
#include <elf.h>
#include <sys/types.h>
-#if defined(sun)
+#ifdef illumos
#include <sys/sysmacros.h>
#else
#define P2ROUNDUP(x, align) (-(-(x) & -(align)))
@@ -38,7 +39,7 @@
#include <unistd.h>
#include <strings.h>
-#if defined(sun)
+#ifdef illumos
#include <alloca.h>
#endif
#include <limits.h>
@@ -47,7 +48,7 @@
#include <stdio.h>
#include <fcntl.h>
#include <errno.h>
-#if defined(sun)
+#ifdef illumos
#include <wait.h>
#else
#include <sys/wait.h>
@@ -242,8 +243,14 @@
/* XXX */
printf("%s:%s(%d): DOODAD\n",__FUNCTION__,__FILE__,__LINE__);
#elif defined(__powerpc__)
-/* XXX */
-printf("%s:%s(%d): DOODAD\n",__FUNCTION__,__FILE__,__LINE__);
+ /*
+ * Add 4 bytes to hit the low half of this 64-bit
+ * big-endian address.
+ */
+ rel->r_offset = s->dofs_offset +
+ dofr[j].dofr_offset + 4;
+ rel->r_info = ELF32_R_INFO(count + dep->de_global,
+ R_PPC_REL32);
#elif defined(__sparc)
/*
* Add 4 bytes to hit the low half of this 64-bit
@@ -423,7 +430,10 @@
#elif defined(__mips__)
/* XXX */
#elif defined(__powerpc__)
-/* XXX */
+ rel->r_offset = s->dofs_offset +
+ dofr[j].dofr_offset;
+ rel->r_info = ELF64_R_INFO(count + dep->de_global,
+ R_PPC64_REL64);
#elif defined(__i386) || defined(__amd64)
rel->r_offset = s->dofs_offset +
dofr[j].dofr_offset;
@@ -824,12 +834,84 @@
return (0);
}
#elif defined(__powerpc__)
+/* The sentinel is 'xor r3,r3,r3'. */
+#define DT_OP_XOR_R3 0x7c631a78
+
+#define DT_OP_NOP 0x60000000
+#define DT_OP_BLR 0x4e800020
+
+/* This captures all forms of branching to address. */
+#define DT_IS_BRANCH(inst) ((inst & 0xfc000000) == 0x48000000)
+#define DT_IS_BL(inst) (DT_IS_BRANCH(inst) && (inst & 0x01))
+
/* XXX */
static int
dt_modtext(dtrace_hdl_t *dtp, char *p, int isenabled, GElf_Rela *rela,
uint32_t *off)
{
-printf("%s:%s(%d): DOODAD\n",__FUNCTION__,__FILE__,__LINE__);
+ uint32_t *ip;
+
+ if ((rela->r_offset & (sizeof (uint32_t) - 1)) != 0)
+ return (-1);
+
+ /*LINTED*/
+ ip = (uint32_t *)(p + rela->r_offset);
+
+ /*
+ * We only know about some specific relocation types.
+ */
+ if (GELF_R_TYPE(rela->r_info) != R_PPC_REL24 &&
+ GELF_R_TYPE(rela->r_info) != R_PPC_PLTREL24)
+ return (-1);
+
+ /*
+ * We may have already processed this object file in an earlier linker
+ * invocation. Check to see if the present instruction sequence matches
+ * the one we would install below.
+ */
+ if (isenabled) {
+ if (ip[0] == DT_OP_XOR_R3) {
+ (*off) += sizeof (ip[0]);
+ return (0);
+ }
+ } else {
+ if (ip[0] == DT_OP_NOP) {
+ (*off) += sizeof (ip[0]);
+ return (0);
+ }
+ }
+
+ /*
+ * We only expect branch to address instructions.
+ */
+ if (!DT_IS_BRANCH(ip[0])) {
+ dt_dprintf("found %x instead of a branch instruction at %llx\n",
+ ip[0], (u_longlong_t)rela->r_offset);
+ return (-1);
+ }
+
+ if (isenabled) {
+ /*
+ * It would necessarily indicate incorrect usage if an is-
+ * enabled probe were tail-called so flag that as an error.
+ * It's also potentially (very) tricky to handle gracefully,
+ * but could be done if this were a desired use scenario.
+ */
+ if (!DT_IS_BL(ip[0])) {
+ dt_dprintf("tail call to is-enabled probe at %llx\n",
+ (u_longlong_t)rela->r_offset);
+ return (-1);
+ }
+
+ ip[0] = DT_OP_XOR_R3;
+ (*off) += sizeof (ip[0]);
+ } else {
+ if (DT_IS_BL(ip[0]))
+ ip[0] = DT_OP_NOP;
+ else
+ ip[0] = DT_OP_BLR;
+ }
+
return (0);
}
@@ -1528,7 +1610,7 @@
return (dt_link_error(dtp, elf, fd, bufs,
"failed to allocate space for probe"));
}
-#if !defined(sun)
+#ifndef illumos
/*
* Our linker doesn't understand the SUNW_IGNORE ndx and
* will try to use this relocation when we build the
@@ -1539,10 +1621,17 @@
* the executable file as the symbol is going to be
* change from UND to ABS.
*/
- rela.r_offset = 0;
- rela.r_info = 0;
- rela.r_addend = 0;
- (void) gelf_update_rela(data_rel, i, &rela);
+ if (shdr_rel.sh_type == SHT_RELA) {
+ rela.r_offset = 0;
+ rela.r_info = 0;
+ rela.r_addend = 0;
+ (void) gelf_update_rela(data_rel, i, &rela);
+ } else {
+ GElf_Rel rel;
+ rel.r_offset = 0;
+ rel.r_info = 0;
+ (void) gelf_update_rel(data_rel, i, &rel);
+ }
#endif
mod = 1;
@@ -1555,7 +1644,7 @@
* already been processed by an earlier link
* invocation.
*/
-#if !defined(sun)
+#ifndef illumos
#define SHN_SUNW_IGNORE SHN_ABS
#endif
if (rsym.st_shndx != SHN_SUNW_IGNORE) {
@@ -1571,7 +1660,7 @@
(void) elf_end(elf);
(void) close(fd);
-#if !defined(sun)
+#ifndef illumos
if (nsym > 0)
#endif
while ((pair = bufs) != NULL) {
@@ -1592,7 +1681,7 @@
dtrace_program_link(dtrace_hdl_t *dtp, dtrace_prog_t *pgp, uint_t dflags,
const char *file, int objc, char *const objv[])
{
-#if !defined(sun)
+#ifndef illumos
char tfile[PATH_MAX];
Elf *e;
Elf_Scn *scn;
@@ -1615,7 +1704,7 @@
size_t len;
int eprobes = 0, ret = 0;
-#if !defined(sun)
+#ifndef illumos
if (access(file, R_OK) == 0) {
fprintf(stderr, "dtrace: target object (%s) already exists. "
"Please remove the target\ndtrace: object and rebuild all "
@@ -1693,7 +1782,7 @@
if ((dof = dtrace_dof_create(dtp, pgp, dflags)) == NULL)
return (-1); /* errno is set for us */
-#if defined(sun)
+#ifdef illumos
/*
* Create a temporary file and then unlink it if we're going to
* combine it with drti.o later. We can still refer to it in child
@@ -1737,12 +1826,12 @@
}
-#if defined(sun)
+#ifdef illumos
if (!dtp->dt_lazyload)
(void) unlink(file);
#endif
-#if defined(sun)
+#ifdef illumos
if (dtp->dt_oflags & DTRACE_O_LP64)
status = dump_elf64(dtp, dof, fd);
else
@@ -1758,7 +1847,7 @@
}
if (!dtp->dt_lazyload) {
-#if defined(sun)
+#ifdef illumos
const char *fmt = "%s -o %s -r -Blocal -Breduce /dev/fd/%d %s";
if (dtp->dt_oflags & DTRACE_O_LP64) {
@@ -1783,7 +1872,7 @@
* Arches which default to 64-bit need to explicitly use
* the 32-bit library path.
*/
- int use_32 = !(dtp->dt_oflags & DTRACE_O_LP64);
+ int use_32 = (dtp->dt_oflags & DTRACE_O_ILP32);
#else
/*
* Arches which are 32-bit only just use the normal
@@ -1798,9 +1887,7 @@
len = snprintf(&tmp, 1, fmt, dtp->dt_ld_path, file, tfile,
drti) + 1;
-#if !defined(sun)
len *= 2;
-#endif
cmd = alloca(len);
(void) snprintf(cmd, len, fmt, dtp->dt_ld_path, file,
@@ -1826,8 +1913,7 @@
file, dtp->dt_ld_path, WEXITSTATUS(status));
goto done;
}
-#if !defined(sun)
-#define BROKEN_LIBELF
+#ifndef illumos
/*
* FreeBSD's ld(1) is not instructed to interpret and add
* correctly the SUNW_dof section present in tfile.
@@ -1851,9 +1937,6 @@
/*
* Add the string '.SUWN_dof' to the shstrtab section.
*/
-#ifdef BROKEN_LIBELF
- elf_flagelf(e, ELF_C_SET, ELF_F_LAYOUT);
-#endif
elf_getshdrstrndx(e, &stridx);
scn = elf_getscn(e, stridx);
gelf_getshdr(scn, &shdr);
@@ -1865,54 +1948,6 @@
loc = shdr.sh_size;
shdr.sh_size += data->d_size;
gelf_update_shdr(scn, &shdr);
-#ifdef BROKEN_LIBELF
- off = shdr.sh_offset;
- rc = shdr.sh_offset + shdr.sh_size;
- gelf_getehdr(e, &ehdr);
- if (ehdr.e_shoff > off) {
- off = ehdr.e_shoff + ehdr.e_shnum * ehdr.e_shentsize;
- rc = roundup(rc, 8);
- ehdr.e_shoff = rc;
- gelf_update_ehdr(e, &ehdr);
- rc += ehdr.e_shnum * ehdr.e_shentsize;
- }
- for (;;) {
- scn0 = NULL;
- scn = NULL;
- while ((scn = elf_nextscn(e, scn)) != NULL) {
- gelf_getshdr(scn, &shdr);
- if (shdr.sh_type == SHT_NOBITS ||
- shdr.sh_offset < off)
- continue;
- /* Find the immediately adjcent section. */
- if (scn0 == NULL ||
- shdr.sh_offset < shdr0.sh_offset) {
- scn0 = scn;
- gelf_getshdr(scn0, &shdr0);
- }
- }
- if (scn0 == NULL)
- break;
- /* Load section data to work around another bug */
- elf_getdata(scn0, NULL);
- /* Update section header, assure section alignment */
- off = shdr0.sh_offset + shdr0.sh_size;
- rc = roundup(rc, shdr0.sh_addralign);
- shdr0.sh_offset = rc;
- gelf_update_shdr(scn0, &shdr0);
- rc += shdr0.sh_size;
- }
- if (elf_update(e, ELF_C_WRITE) < 0) {
- ret = dt_link_error(dtp, NULL, -1, NULL,
- "failed to add append the shstrtab section: %s",
- elf_errmsg(elf_errno()));
- elf_end(e);
- close(efd);
- goto done;
- }
- elf_end(e);
- e = elf_begin(efd, ELF_C_RDWR, NULL);
-#endif
/*
* Construct the .SUNW_dof section.
*/
@@ -1965,7 +2000,7 @@
done:
dtrace_dof_destroy(dtp, dof);
-#if !defined(sun)
+#ifndef illumos
unlink(tfile);
#endif
return (ret);
Modified: trunk/cddl/contrib/opensolaris/lib/libdtrace/common/dt_list.c
===================================================================
--- trunk/cddl/contrib/opensolaris/lib/libdtrace/common/dt_list.c 2018-06-02 16:07:17 UTC (rev 10228)
+++ trunk/cddl/contrib/opensolaris/lib/libdtrace/common/dt_list.c 2018-06-02 16:07:30 UTC (rev 10229)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*
* CDDL HEADER START
*
Modified: trunk/cddl/contrib/opensolaris/lib/libdtrace/common/dt_list.h
===================================================================
--- trunk/cddl/contrib/opensolaris/lib/libdtrace/common/dt_list.h 2018-06-02 16:07:17 UTC (rev 10228)
+++ trunk/cddl/contrib/opensolaris/lib/libdtrace/common/dt_list.h 2018-06-02 16:07:30 UTC (rev 10229)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*
* CDDL HEADER START
*
Modified: trunk/cddl/contrib/opensolaris/lib/libdtrace/common/dt_map.c
===================================================================
--- trunk/cddl/contrib/opensolaris/lib/libdtrace/common/dt_map.c 2018-06-02 16:07:17 UTC (rev 10228)
+++ trunk/cddl/contrib/opensolaris/lib/libdtrace/common/dt_map.c 2018-06-02 16:07:30 UTC (rev 10229)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*
* CDDL HEADER START
*
@@ -39,7 +40,7 @@
static int
dt_strdata_add(dtrace_hdl_t *dtp, dtrace_recdesc_t *rec, void ***data, int *max)
{
- int maxformat;
+ int maxformat, rval;
dtrace_fmtdesc_t fmt;
void *result;
@@ -63,8 +64,9 @@
return (dt_set_errno(dtp, EDT_NOMEM));
if (dt_ioctl(dtp, DTRACEIOC_FORMAT, &fmt) == -1) {
+ rval = dt_set_errno(dtp, errno);
free(fmt.dtfd_string);
- return (dt_set_errno(dtp, errno));
+ return (rval);
}
while (rec->dtrd_format > (maxformat = *max)) {
@@ -155,7 +157,7 @@
enabled->dtepd_epid = id;
enabled->dtepd_nrecs = 1;
-#if defined(sun)
+#ifdef illumos
if (dt_ioctl(dtp, DTRACEIOC_EPROBE, enabled) == -1) {
#else
if (dt_ioctl(dtp, DTRACEIOC_EPROBE, &enabled) == -1) {
@@ -179,7 +181,7 @@
if ((enabled = nenabled) == NULL)
return (dt_set_errno(dtp, EDT_NOMEM));
-#if defined(sun)
+#ifdef illumos
rval = dt_ioctl(dtp, DTRACEIOC_EPROBE, enabled);
#else
rval = dt_ioctl(dtp, DTRACEIOC_EPROBE, &enabled);
@@ -355,7 +357,7 @@
agg->dtagd_id = id;
agg->dtagd_nrecs = 1;
-#if defined(sun)
+#ifdef illumos
if (dt_ioctl(dtp, DTRACEIOC_AGGDESC, agg) == -1) {
#else
if (dt_ioctl(dtp, DTRACEIOC_AGGDESC, &agg) == -1) {
@@ -378,7 +380,7 @@
if ((agg = nagg) == NULL)
return (dt_set_errno(dtp, EDT_NOMEM));
-#if defined(sun)
+#ifdef illumos
rval = dt_ioctl(dtp, DTRACEIOC_AGGDESC, agg);
#else
rval = dt_ioctl(dtp, DTRACEIOC_AGGDESC, &agg);
Modified: trunk/cddl/contrib/opensolaris/lib/libdtrace/common/dt_module.c
===================================================================
--- trunk/cddl/contrib/opensolaris/lib/libdtrace/common/dt_module.c 2018-06-02 16:07:17 UTC (rev 10228)
+++ trunk/cddl/contrib/opensolaris/lib/libdtrace/common/dt_module.c 2018-06-02 16:07:30 UTC (rev 10229)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*
* CDDL HEADER START
*
@@ -22,9 +23,13 @@
/*
* Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
*/
+/*
+ * Copyright (c) 2013, Joyent, Inc. All rights reserved.
+ * Copyright (c) 2016, Pedro Giffuni. All rights reserved.
+ */
#include <sys/types.h>
-#if defined(sun)
+#ifdef illumos
#include <sys/modctl.h>
#include <sys/kobj.h>
#include <sys/kobj_impl.h>
@@ -38,7 +43,7 @@
#endif
#include <unistd.h>
-#if defined(sun)
+#ifdef illumos
#include <project.h>
#endif
#include <strings.h>
@@ -48,8 +53,9 @@
#include <assert.h>
#include <errno.h>
#include <dirent.h>
-#if !defined(sun)
+#ifndef illumos
#include <fcntl.h>
+#include <libproc_compat.h>
#endif
#include <dt_strtab.h>
@@ -462,6 +468,9 @@
dt_module_t *
dt_module_create(dtrace_hdl_t *dtp, const char *name)
{
+ long pid;
+ char *eptr;
+ dt_ident_t *idp;
uint_t h = dt_strtab_hash(name, NULL) % dtp->dt_modbuckets;
dt_module_t *dmp;
@@ -485,6 +494,32 @@
else
dmp->dm_ops = &dt_modops_32;
+ /*
+ * Modules for userland processes are special. They always refer to a
+ * specific process and have a copy of their CTF data from a specific
+ * instant in time. Any dt_module_t that begins with 'pid' is a module
+ * for a specific process, much like how any probe description that
+ * begins with 'pid' is special. pid123 refers to process 123. A module
+ * that is just 'pid' refers specifically to pid$target. This is
+ * generally done as D does not currently allow for macros to be
+ * evaluated when working with types.
+ */
+ if (strncmp(dmp->dm_name, "pid", 3) == 0) {
+ errno = 0;
+ if (dmp->dm_name[3] == '\0') {
+ idp = dt_idhash_lookup(dtp->dt_macros, "target");
+ if (idp != NULL && idp->di_id != 0)
+ dmp->dm_pid = idp->di_id;
+ } else {
+ pid = strtol(dmp->dm_name + 3, &eptr, 10);
+ if (errno == 0 && *eptr == '\0')
+ dmp->dm_pid = (pid_t)pid;
+ else
+ dt_dprintf("encountered malformed pid "
+ "module: %s\n", dmp->dm_name);
+ }
+ }
+
return (dmp);
}
@@ -539,7 +574,7 @@
if (sp == NULL || (dp = elf_getdata(sp, NULL)) == NULL)
return (0);
-#if defined(sun)
+#ifdef illumos
ctsp->cts_data = dp->d_buf;
#else
if ((ctsp->cts_data = malloc(dp->d_size)) == NULL)
@@ -554,6 +589,159 @@
return (0);
}
+typedef struct dt_module_cb_arg {
+ struct ps_prochandle *dpa_proc;
+ dtrace_hdl_t *dpa_dtp;
+ dt_module_t *dpa_dmp;
+ uint_t dpa_count;
+} dt_module_cb_arg_t;
+
+/* ARGSUSED */
+static int
+dt_module_load_proc_count(void *arg, const prmap_t *prmap, const char *obj)
+{
+ ctf_file_t *fp;
+ dt_module_cb_arg_t *dcp = arg;
+
+ /* Try to grab a ctf container if it exists */
+ fp = Pname_to_ctf(dcp->dpa_proc, obj);
+ if (fp != NULL)
+ dcp->dpa_count++;
+ return (0);
+}
+
+/* ARGSUSED */
+static int
+dt_module_load_proc_build(void *arg, const prmap_t *prmap, const char *obj)
+{
+ ctf_file_t *fp;
+ char buf[MAXPATHLEN], *p;
+ dt_module_cb_arg_t *dcp = arg;
+ int count = dcp->dpa_count;
+ Lmid_t lmid;
+
+ fp = Pname_to_ctf(dcp->dpa_proc, obj);
+ if (fp == NULL)
+ return (0);
+ fp = ctf_dup(fp);
+ if (fp == NULL)
+ return (0);
+ dcp->dpa_dmp->dm_libctfp[count] = fp;
+ /*
+ * While it'd be nice to simply use objname here, because of our prior
+ * actions we'll always get a resolved object name to its on disk file.
+ * Like the pid provider, we need to tell a bit of a lie here. The type
+ * that the user thinks of is in terms of the libraries they requested,
+ * eg. libc.so.1, they don't care about the fact that it's
+ * libc_hwcap.so.1.
+ */
+ (void) Pobjname(dcp->dpa_proc, prmap->pr_vaddr, buf, sizeof (buf));
+ if ((p = strrchr(buf, '/')) == NULL)
+ p = buf;
+ else
+ p++;
+
+ /*
+ * If for some reason we can't find a link map id for this module, which
+ * would be really quite weird. We instead just say the link map id is
+ * zero.
+ */
+ if (Plmid(dcp->dpa_proc, prmap->pr_vaddr, &lmid) != 0)
+ lmid = 0;
+
+ if (lmid == 0)
+ dcp->dpa_dmp->dm_libctfn[count] = strdup(p);
+ else
+ (void) asprintf(&dcp->dpa_dmp->dm_libctfn[count],
+ "LM%x`%s", lmid, p);
+ if (dcp->dpa_dmp->dm_libctfn[count] == NULL)
+ return (1);
+ ctf_setspecific(fp, dcp->dpa_dmp);
+ dcp->dpa_count++;
+ return (0);
+}
+
+/*
+ * We've been asked to load data that belongs to another process. As such we're
+ * going to pgrab it at this instant, load everything that we might ever care
+ * about, and then drive on. The reason for this is that the process that we're
+ * interested in might be changing. As long as we have grabbed it, then this
+ * can't be a problem for us.
+ *
+ * For now, we're actually going to punt on most things and just try to get CTF
+ * data, nothing else. Basically this is only useful as a source of type
+ * information, we can't go and do the stacktrace lookups, etc.
+ */
+static int
+dt_module_load_proc(dtrace_hdl_t *dtp, dt_module_t *dmp)
+{
+ struct ps_prochandle *p;
+ dt_module_cb_arg_t arg;
+
+ /*
+ * Note that on success we do not release this hold. We must hold this
+ * for our life time.
+ */
+ p = dt_proc_grab(dtp, dmp->dm_pid, 0, PGRAB_RDONLY | PGRAB_FORCE);
+ if (p == NULL) {
+ dt_dprintf("failed to grab pid: %d\n", (int)dmp->dm_pid);
+ return (dt_set_errno(dtp, EDT_CANTLOAD));
+ }
+ dt_proc_lock(dtp, p);
+
+ arg.dpa_proc = p;
+ arg.dpa_dtp = dtp;
+ arg.dpa_dmp = dmp;
+ arg.dpa_count = 0;
+ if (Pobject_iter_resolved(p, dt_module_load_proc_count, &arg) != 0) {
+ dt_dprintf("failed to iterate objects\n");
+ dt_proc_unlock(dtp, p);
+ dt_proc_release(dtp, p);
+ return (dt_set_errno(dtp, EDT_CANTLOAD));
+ }
+
+ if (arg.dpa_count == 0) {
+ dt_dprintf("no ctf data present\n");
+ dt_proc_unlock(dtp, p);
+ dt_proc_release(dtp, p);
+ return (dt_set_errno(dtp, EDT_CANTLOAD));
+ }
+
+ dmp->dm_libctfp = calloc(arg.dpa_count, sizeof (ctf_file_t *));
+ if (dmp->dm_libctfp == NULL) {
+ dt_proc_unlock(dtp, p);
+ dt_proc_release(dtp, p);
+ return (dt_set_errno(dtp, EDT_NOMEM));
+ }
+
+ dmp->dm_libctfn = calloc(arg.dpa_count, sizeof (char *));
+ if (dmp->dm_libctfn == NULL) {
+ free(dmp->dm_libctfp);
+ dt_proc_unlock(dtp, p);
+ dt_proc_release(dtp, p);
+ return (dt_set_errno(dtp, EDT_NOMEM));
+ }
+
+ dmp->dm_nctflibs = arg.dpa_count;
+
+ arg.dpa_count = 0;
+ if (Pobject_iter_resolved(p, dt_module_load_proc_build, &arg) != 0) {
+ dt_proc_unlock(dtp, p);
+ dt_module_unload(dtp, dmp);
+ dt_proc_release(dtp, p);
+ return (dt_set_errno(dtp, EDT_CANTLOAD));
+ }
+ assert(arg.dpa_count == dmp->dm_nctflibs);
+ dt_dprintf("loaded %d ctf modules for pid %d\n", arg.dpa_count,
+ (int)dmp->dm_pid);
+
+ dt_proc_unlock(dtp, p);
+ dt_proc_release(dtp, p);
+ dmp->dm_flags |= DT_DM_LOADED;
+
+ return (0);
+}
+
int
dt_module_load(dtrace_hdl_t *dtp, dt_module_t *dmp)
{
@@ -560,6 +748,9 @@
if (dmp->dm_flags & DT_DM_LOADED)
return (0); /* module is already loaded */
+ if (dmp->dm_pid != 0)
+ return (dt_module_load_proc(dtp, dmp));
+
dmp->dm_ctdata.cts_name = ".SUNW_ctf";
dmp->dm_ctdata.cts_type = SHT_PROGBITS;
dmp->dm_ctdata.cts_flags = 0;
@@ -610,8 +801,8 @@
dmp->dm_nsymbuckets = _dtrace_strbuckets;
dmp->dm_symfree = 1; /* first free element is index 1 */
- dmp->dm_symbuckets = malloc(sizeof (uint_t) * dmp->dm_nsymbuckets);
- dmp->dm_symchains = malloc(sizeof (dt_sym_t) * dmp->dm_nsymelems + 1);
+ dmp->dm_symbuckets = calloc(dmp->dm_nsymbuckets, sizeof (uint_t));
+ dmp->dm_symchains = calloc(dmp->dm_nsymelems + 1, sizeof (dt_sym_t));
if (dmp->dm_symbuckets == NULL || dmp->dm_symchains == NULL) {
dt_module_unload(dtp, dmp);
@@ -618,9 +809,6 @@
return (dt_set_errno(dtp, EDT_NOMEM));
}
- bzero(dmp->dm_symbuckets, sizeof (uint_t) * dmp->dm_nsymbuckets);
- bzero(dmp->dm_symchains, sizeof (dt_sym_t) * dmp->dm_nsymelems + 1);
-
/*
* Iterate over the symbol table data buffer and insert each symbol
* name into the name hash if the name and type are valid. Then
@@ -645,6 +833,14 @@
return (0);
}
+int
+dt_module_hasctf(dtrace_hdl_t *dtp, dt_module_t *dmp)
+{
+ if (dmp->dm_pid != 0 && dmp->dm_nctflibs > 0)
+ return (1);
+ return (dt_module_getctf(dtp, dmp) != NULL);
+}
+
ctf_file_t *
dt_module_getctf(dtrace_hdl_t *dtp, dt_module_t *dmp)
{
@@ -718,10 +914,12 @@
void
dt_module_unload(dtrace_hdl_t *dtp, dt_module_t *dmp)
{
+ int i;
+
ctf_close(dmp->dm_ctfp);
dmp->dm_ctfp = NULL;
-#if !defined(sun)
+#ifndef illumos
if (dmp->dm_ctdata.cts_data != NULL) {
free(dmp->dm_ctdata.cts_data);
}
@@ -733,6 +931,17 @@
}
#endif
+ if (dmp->dm_libctfp != NULL) {
+ for (i = 0; i < dmp->dm_nctflibs; i++) {
+ ctf_close(dmp->dm_libctfp[i]);
+ free(dmp->dm_libctfn[i]);
+ }
+ free(dmp->dm_libctfp);
+ free(dmp->dm_libctfn);
+ dmp->dm_libctfp = NULL;
+ dmp->dm_nctflibs = 0;
+ }
+
bzero(&dmp->dm_ctdata, sizeof (ctf_sect_t));
bzero(&dmp->dm_symtab, sizeof (ctf_sect_t));
bzero(&dmp->dm_strtab, sizeof (ctf_sect_t));
@@ -778,6 +987,8 @@
(void) elf_end(dmp->dm_elf);
dmp->dm_elf = NULL;
+ dmp->dm_pid = 0;
+
dmp->dm_flags &= ~DT_DM_LOADED;
}
@@ -866,6 +1077,34 @@
return ("32-bit");
}
+/* ARGSUSED */
+int
+dt_module_getlibid(dtrace_hdl_t *dtp, dt_module_t *dmp, const ctf_file_t *fp)
+{
+ int i;
+
+ for (i = 0; i < dmp->dm_nctflibs; i++) {
+ if (dmp->dm_libctfp[i] == fp)
+ return (i);
+ }
+
+ return (-1);
+}
+
+/* ARGSUSED */
+ctf_file_t *
+dt_module_getctflib(dtrace_hdl_t *dtp, dt_module_t *dmp, const char *name)
+{
+ int i;
+
+ for (i = 0; i < dmp->dm_nctflibs; i++) {
+ if (strcmp(dmp->dm_libctfn[i], name) == 0)
+ return (dmp->dm_libctfp[i]);
+ }
+
+ return (NULL);
+}
+
/*
* Update our module cache by adding an entry for the specified module 'name'.
* We create the dt_module_t and populate it using /system/object/<name>/.
@@ -874,7 +1113,7 @@
* including the path.
*/
static void
-#if defined(sun)
+#ifdef illumos
dt_module_update(dtrace_hdl_t *dtp, const char *name)
#else
dt_module_update(dtrace_hdl_t *dtp, struct kld_file_stat *k_stat)
@@ -891,7 +1130,7 @@
Elf_Data *dp;
Elf_Scn *sp;
-#if defined(sun)
+#ifdef illumos
(void) snprintf(fname, sizeof (fname),
"%s/%s/object", OBJFS_ROOT, name);
#else
@@ -970,13 +1209,13 @@
#if defined(__FreeBSD__)
if (sh.sh_size == 0)
continue;
- if (is_elf_obj && (sh.sh_type == SHT_PROGBITS ||
- sh.sh_type == SHT_NOBITS)) {
+ if (sh.sh_type == SHT_PROGBITS || sh.sh_type == SHT_NOBITS) {
alignmask = sh.sh_addralign - 1;
mapbase += alignmask;
mapbase &= ~alignmask;
sh.sh_addr = mapbase;
- dmp->dm_sec_offsets[elf_ndxscn(sp)] = sh.sh_addr;
+ if (is_elf_obj)
+ dmp->dm_sec_offsets[elf_ndxscn(sp)] = sh.sh_addr;
mapbase += sh.sh_size;
}
#endif
@@ -1001,7 +1240,7 @@
}
dmp->dm_flags |= DT_DM_KERNEL;
-#if defined(sun)
+#ifdef illumos
dmp->dm_modid = (int)OBJFS_MODID(st.st_ino);
#else
/*
@@ -1024,7 +1263,7 @@
}
}
#endif
-#endif
+#endif /* illumos */
if (dmp->dm_info.objfs_info_primary)
dmp->dm_flags |= DT_DM_PRIMARY;
@@ -1050,7 +1289,7 @@
dmp != NULL; dmp = dt_list_next(dmp))
dt_module_unload(dtp, dmp);
-#if defined(sun)
+#ifdef illumos
/*
* Open /system/object and attempt to create a libdtrace module for
* each kernel module that is loaded on the current system.
@@ -1090,11 +1329,11 @@
dt_idhash_lookup(dtp->dt_macros, "pid")->di_id = getpid();
dt_idhash_lookup(dtp->dt_macros, "pgid")->di_id = getpgid(0);
dt_idhash_lookup(dtp->dt_macros, "ppid")->di_id = getppid();
-#if defined(sun)
+#ifdef illumos
dt_idhash_lookup(dtp->dt_macros, "projid")->di_id = getprojid();
#endif
dt_idhash_lookup(dtp->dt_macros, "sid")->di_id = getsid(0);
-#if defined(sun)
+#ifdef illumos
dt_idhash_lookup(dtp->dt_macros, "taskid")->di_id = gettaskid();
#endif
dt_idhash_lookup(dtp->dt_macros, "uid")->di_id = getuid();
@@ -1294,8 +1533,10 @@
dt_module_t *dmp;
int found = 0;
ctf_id_t id;
- uint_t n;
+ uint_t n, i;
int justone;
+ ctf_file_t *fp;
+ char *buf, *p, *q;
uint_t mask = 0; /* mask of dt_module flags to match */
uint_t bits = 0; /* flag bits that must be present */
@@ -1310,7 +1551,6 @@
return (-1); /* dt_errno is set for us */
n = 1;
justone = 1;
-
} else {
if (object == DTRACE_OBJ_KMODS)
mask = bits = DT_DM_KERNEL;
@@ -1334,7 +1574,7 @@
* module. If our search was scoped to only one module then
* return immediately leaving dt_errno unmodified.
*/
- if (dt_module_getctf(dtp, dmp) == NULL) {
+ if (dt_module_hasctf(dtp, dmp) == 0) {
if (justone)
return (-1);
continue;
@@ -1346,13 +1586,38 @@
* 'tip' and keep going in the hope that we will locate the
* underlying structure definition. Otherwise just return.
*/
- if ((id = ctf_lookup_by_name(dmp->dm_ctfp, name)) != CTF_ERR) {
+ if (dmp->dm_pid == 0) {
+ id = ctf_lookup_by_name(dmp->dm_ctfp, name);
+ fp = dmp->dm_ctfp;
+ } else {
+ if ((p = strchr(name, '`')) != NULL) {
+ buf = strdup(name);
+ if (buf == NULL)
+ return (dt_set_errno(dtp, EDT_NOMEM));
+ p = strchr(buf, '`');
+ if ((q = strchr(p + 1, '`')) != NULL)
+ p = q;
+ *p = '\0';
+ fp = dt_module_getctflib(dtp, dmp, buf);
+ if (fp == NULL || (id = ctf_lookup_by_name(fp,
+ p + 1)) == CTF_ERR)
+ id = CTF_ERR;
+ free(buf);
+ } else {
+ for (i = 0; i < dmp->dm_nctflibs; i++) {
+ fp = dmp->dm_libctfp[i];
+ id = ctf_lookup_by_name(fp, name);
+ if (id != CTF_ERR)
+ break;
+ }
+ }
+ }
+ if (id != CTF_ERR) {
tip->dtt_object = dmp->dm_name;
- tip->dtt_ctfp = dmp->dm_ctfp;
+ tip->dtt_ctfp = fp;
tip->dtt_type = id;
-
- if (ctf_type_kind(dmp->dm_ctfp, ctf_type_resolve(
- dmp->dm_ctfp, id)) != CTF_K_FORWARD)
+ if (ctf_type_kind(fp, ctf_type_resolve(fp, id)) !=
+ CTF_K_FORWARD)
return (0);
found++;
@@ -1374,6 +1639,7 @@
tip->dtt_object = NULL;
tip->dtt_ctfp = NULL;
tip->dtt_type = CTF_ERR;
+ tip->dtt_flags = 0;
if ((dmp = dt_module_lookup_by_name(dtp, sip->dts_object)) == NULL)
return (dt_set_errno(dtp, EDT_NOMOD));
Modified: trunk/cddl/contrib/opensolaris/lib/libdtrace/common/dt_module.h
===================================================================
--- trunk/cddl/contrib/opensolaris/lib/libdtrace/common/dt_module.h 2018-06-02 16:07:17 UTC (rev 10228)
+++ trunk/cddl/contrib/opensolaris/lib/libdtrace/common/dt_module.h 2018-06-02 16:07:30 UTC (rev 10229)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*
* CDDL HEADER START
*
@@ -23,12 +24,13 @@
* Copyright 2004 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
+/*
+ * Copyright (c) 2013, Joyent, Inc. All rights reserved.
+ */
#ifndef _DT_MODULE_H
#define _DT_MODULE_H
-#pragma ident "%Z%%M% %I% %E% SMI"
-
#include <dt_impl.h>
#ifdef __cplusplus
@@ -43,11 +45,16 @@
extern dt_module_t *dt_module_lookup_by_name(dtrace_hdl_t *, const char *);
extern dt_module_t *dt_module_lookup_by_ctf(dtrace_hdl_t *, ctf_file_t *);
+extern int dt_module_hasctf(dtrace_hdl_t *, dt_module_t *);
extern ctf_file_t *dt_module_getctf(dtrace_hdl_t *, dt_module_t *);
extern dt_ident_t *dt_module_extern(dtrace_hdl_t *, dt_module_t *,
const char *, const dtrace_typeinfo_t *);
extern const char *dt_module_modelname(dt_module_t *);
+extern int dt_module_getlibid(dtrace_hdl_t *, dt_module_t *,
+ const ctf_file_t *);
+extern ctf_file_t *dt_module_getctflib(dtrace_hdl_t *, dt_module_t *,
+ const char *);
#ifdef __cplusplus
}
Modified: trunk/cddl/contrib/opensolaris/lib/libdtrace/common/dt_open.c
===================================================================
--- trunk/cddl/contrib/opensolaris/lib/libdtrace/common/dt_open.c 2018-06-02 16:07:17 UTC (rev 10228)
+++ trunk/cddl/contrib/opensolaris/lib/libdtrace/common/dt_open.c 2018-06-02 16:07:30 UTC (rev 10229)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*
* CDDL HEADER START
*
@@ -21,12 +22,12 @@
/*
* Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2011, Joyent, Inc. All rights reserved.
- * Copyright (c) 2011 by Delphix. All rights reserved.
+ * Copyright (c) 2013, Joyent, Inc. All rights reserved.
+ * Copyright (c) 2012 by Delphix. All rights reserved.
*/
#include <sys/types.h>
-#if defined(sun)
+#ifdef illumos
#include <sys/modctl.h>
#include <sys/systeminfo.h>
#endif
@@ -34,7 +35,7 @@
#include <libelf.h>
#include <strings.h>
-#if defined(sun)
+#ifdef illumos
#include <alloca.h>
#endif
#include <limits.h>
@@ -55,7 +56,7 @@
#include <dt_printf.h>
#include <dt_string.h>
#include <dt_provider.h>
-#if !defined(sun)
+#ifndef illumos
#include <sys/sysctl.h>
#include <string.h>
#endif
@@ -92,7 +93,7 @@
/*
* The version number should be increased for every customer visible release
- * of Solaris. The major number should be incremented when a fundamental
+ * of DTrace. The major number should be incremented when a fundamental
* change has been made that would affect all consumers, and would reflect
* sweeping changes to DTrace or the D language. The minor number should be
* incremented when a change is introduced that could break scripts that had
@@ -121,8 +122,13 @@
#define DT_VERS_1_8 DT_VERSION_NUMBER(1, 8, 0)
#define DT_VERS_1_8_1 DT_VERSION_NUMBER(1, 8, 1)
#define DT_VERS_1_9 DT_VERSION_NUMBER(1, 9, 0)
-#define DT_VERS_LATEST DT_VERS_1_9
-#define DT_VERS_STRING "Sun D 1.9"
+#define DT_VERS_1_9_1 DT_VERSION_NUMBER(1, 9, 1)
+#define DT_VERS_1_10 DT_VERSION_NUMBER(1, 10, 0)
+#define DT_VERS_1_11 DT_VERSION_NUMBER(1, 11, 0)
+#define DT_VERS_1_12 DT_VERSION_NUMBER(1, 12, 0)
+#define DT_VERS_1_12_1 DT_VERSION_NUMBER(1, 12, 1)
+#define DT_VERS_LATEST DT_VERS_1_12_1
+#define DT_VERS_STRING "Sun D 1.12.1"
const dt_version_t _dtrace_versions[] = {
DT_VERS_1_0, /* D API 1.0.0 (PSARC 2001/466) Solaris 10 FCS */
@@ -143,6 +149,11 @@
DT_VERS_1_8, /* D API 1.8 */
DT_VERS_1_8_1, /* D API 1.8.1 */
DT_VERS_1_9, /* D API 1.9 */
+ DT_VERS_1_9_1, /* D API 1.9.1 */
+ DT_VERS_1_10, /* D API 1.10 */
+ DT_VERS_1_11, /* D API 1.11 */
+ DT_VERS_1_12, /* D API 1.12 */
+ DT_VERS_1_12_1, /* D API 1.12.1 */
0
};
@@ -149,7 +160,7 @@
/*
* Global variables that are formatted on FreeBSD based on the kernel file name.
*/
-#if !defined(sun)
+#ifndef illumos
static char curthread_str[MAXPATHLEN];
static char intmtx_str[MAXPATHLEN];
static char threadmtx_str[MAXPATHLEN];
@@ -231,7 +242,7 @@
{ "curthread", DT_IDENT_SCALAR, 0, DIF_VAR_CURTHREAD,
{ DTRACE_STABILITY_STABLE, DTRACE_STABILITY_PRIVATE,
DTRACE_CLASS_COMMON }, DT_VERS_1_0,
-#if defined(sun)
+#ifdef illumos
&dt_idops_type, "genunix`kthread_t *" },
#else
&dt_idops_type, curthread_str },
@@ -273,6 +284,8 @@
&dt_idops_func, "uint64_t(uint64_t)" },
{ "htons", DT_IDENT_FUNC, 0, DIF_SUBR_HTONS, DT_ATTR_EVOLCMN, DT_VERS_1_3,
&dt_idops_func, "uint16_t(uint16_t)" },
+{ "getf", DT_IDENT_FUNC, 0, DIF_SUBR_GETF, DT_ATTR_STABCMN, DT_VERS_1_10,
+ &dt_idops_func, "file_t *(int)" },
{ "gid", DT_IDENT_SCALAR, 0, DIF_VAR_GID, DT_ATTR_STABCMN, DT_VERS_1_0,
&dt_idops_type, "gid_t" },
{ "id", DT_IDENT_SCALAR, 0, DIF_VAR_ID, DT_ATTR_STABCMN, DT_VERS_1_0,
@@ -280,13 +293,13 @@
{ "index", DT_IDENT_FUNC, 0, DIF_SUBR_INDEX, DT_ATTR_STABCMN, DT_VERS_1_1,
&dt_idops_func, "int(const char *, const char *, [int])" },
{ "inet_ntoa", DT_IDENT_FUNC, 0, DIF_SUBR_INET_NTOA, DT_ATTR_STABCMN,
-#if defined(sun)
+#ifdef illumos
DT_VERS_1_5, &dt_idops_func, "string(ipaddr_t *)" },
#else
DT_VERS_1_5, &dt_idops_func, "string(in_addr_t *)" },
#endif
{ "inet_ntoa6", DT_IDENT_FUNC, 0, DIF_SUBR_INET_NTOA6, DT_ATTR_STABCMN,
-#if defined(sun)
+#ifdef illumos
DT_VERS_1_5, &dt_idops_func, "string(in6_addr_t *)" },
#else
DT_VERS_1_5, &dt_idops_func, "string(struct in6_addr *)" },
@@ -295,6 +308,8 @@
DT_VERS_1_5, &dt_idops_func, "string(int, void *)" },
{ "ipl", DT_IDENT_SCALAR, 0, DIF_VAR_IPL, DT_ATTR_STABCMN, DT_VERS_1_0,
&dt_idops_type, "uint_t" },
+{ "json", DT_IDENT_FUNC, 0, DIF_SUBR_JSON, DT_ATTR_STABCMN, DT_VERS_1_11,
+ &dt_idops_func, "string(const char *, const char *)" },
{ "jstack", DT_IDENT_ACTFUNC, 0, DT_ACT_JSTACK, DT_ATTR_STABCMN, DT_VERS_1_0,
&dt_idops_func, "stack(...)" },
{ "lltostr", DT_IDENT_FUNC, 0, DIF_SUBR_LLTOSTR, DT_ATTR_STABCMN, DT_VERS_1_0,
@@ -309,6 +324,10 @@
&dt_idops_func, "void(@)" },
{ "memref", DT_IDENT_FUNC, 0, DIF_SUBR_MEMREF, DT_ATTR_STABCMN, DT_VERS_1_1,
&dt_idops_func, "uintptr_t *(void *, size_t)" },
+#ifndef illumos
+{ "memstr", DT_IDENT_FUNC, 0, DIF_SUBR_MEMSTR, DT_ATTR_STABCMN, DT_VERS_1_0,
+ &dt_idops_func, "string(void *, char, size_t)" },
+#endif
{ "min", DT_IDENT_AGGFUNC, 0, DTRACEAGG_MIN, DT_ATTR_STABCMN, DT_VERS_1_0,
&dt_idops_func, "void(@)" },
{ "mod", DT_IDENT_ACTFUNC, 0, DT_ACT_MOD, DT_ATTR_STABCMN,
@@ -319,7 +338,7 @@
{ "msgsize", DT_IDENT_FUNC, 0, DIF_SUBR_MSGSIZE,
DT_ATTR_STABCMN, DT_VERS_1_0,
&dt_idops_func, "size_t(mblk_t *)" },
-#if defined(sun)
+#ifdef illumos
{ "mutex_owned", DT_IDENT_FUNC, 0, DIF_SUBR_MUTEX_OWNED,
DT_ATTR_EVOLCMN, DT_VERS_1_0,
&dt_idops_func, "int(genunix`kmutex_t *)" },
@@ -390,7 +409,7 @@
&dt_idops_func, "int()" },
{ "rindex", DT_IDENT_FUNC, 0, DIF_SUBR_RINDEX, DT_ATTR_STABCMN, DT_VERS_1_1,
&dt_idops_func, "int(const char *, const char *, [int])" },
-#if defined(sun)
+#ifdef illumos
{ "rw_iswriter", DT_IDENT_FUNC, 0, DIF_SUBR_RW_ISWRITER,
DT_ATTR_EVOLCMN, DT_VERS_1_0,
&dt_idops_func, "int(genunix`krwlock_t *)" },
@@ -442,11 +461,13 @@
&dt_idops_func, "string(const char *, const char *)" },
{ "strtok", DT_IDENT_FUNC, 0, DIF_SUBR_STRTOK, DT_ATTR_STABCMN, DT_VERS_1_1,
&dt_idops_func, "string(const char *, const char *)" },
+{ "strtoll", DT_IDENT_FUNC, 0, DIF_SUBR_STRTOLL, DT_ATTR_STABCMN, DT_VERS_1_11,
+ &dt_idops_func, "int64_t(const char *, [int])" },
{ "substr", DT_IDENT_FUNC, 0, DIF_SUBR_SUBSTR, DT_ATTR_STABCMN, DT_VERS_1_1,
&dt_idops_func, "string(const char *, int, [int])" },
{ "sum", DT_IDENT_AGGFUNC, 0, DTRACEAGG_SUM, DT_ATTR_STABCMN, DT_VERS_1_0,
&dt_idops_func, "void(@)" },
-#if !defined(sun)
+#ifndef illumos
{ "sx_isexclusive", DT_IDENT_FUNC, 0, DIF_SUBR_SX_ISEXCLUSIVE,
DT_ATTR_EVOLCMN, DT_VERS_1_0,
&dt_idops_func, sxlock_str },
@@ -481,22 +502,16 @@
DT_VERS_1_0, &dt_idops_func, "void(...)" },
{ "typeref", DT_IDENT_FUNC, 0, DIF_SUBR_TYPEREF, DT_ATTR_STABCMN, DT_VERS_1_1,
&dt_idops_func, "uintptr_t *(void *, size_t, string, size_t)" },
-#if defined(sun)
{ "uaddr", DT_IDENT_ACTFUNC, 0, DT_ACT_UADDR, DT_ATTR_STABCMN,
DT_VERS_1_2, &dt_idops_func, "_usymaddr(uintptr_t)" },
-#endif
{ "ucaller", DT_IDENT_SCALAR, 0, DIF_VAR_UCALLER, DT_ATTR_STABCMN,
DT_VERS_1_2, &dt_idops_type, "uint64_t" },
-#if defined(sun)
{ "ufunc", DT_IDENT_ACTFUNC, 0, DT_ACT_USYM, DT_ATTR_STABCMN,
DT_VERS_1_2, &dt_idops_func, "_usymaddr(uintptr_t)" },
-#endif
{ "uid", DT_IDENT_SCALAR, 0, DIF_VAR_UID, DT_ATTR_STABCMN, DT_VERS_1_0,
&dt_idops_type, "uid_t" },
-#if defined(sun)
{ "umod", DT_IDENT_ACTFUNC, 0, DT_ACT_UMOD, DT_ATTR_STABCMN,
DT_VERS_1_2, &dt_idops_func, "_usymaddr(uintptr_t)" },
-#endif
{ "uregs", DT_IDENT_ARRAY, 0, DIF_VAR_UREGS, DT_ATTR_STABCMN, DT_VERS_1_0,
&dt_idops_regs, NULL },
{ "ustack", DT_IDENT_ACTFUNC, 0, DT_ACT_USTACK, DT_ATTR_STABCMN, DT_VERS_1_0,
@@ -504,10 +519,8 @@
{ "ustackdepth", DT_IDENT_SCALAR, 0, DIF_VAR_USTACKDEPTH,
DT_ATTR_STABCMN, DT_VERS_1_2,
&dt_idops_type, "uint32_t" },
-#if defined(sun)
{ "usym", DT_IDENT_ACTFUNC, 0, DT_ACT_USYM, DT_ATTR_STABCMN,
DT_VERS_1_2, &dt_idops_func, "_usymaddr(uintptr_t)" },
-#endif
{ "vtimestamp", DT_IDENT_SCALAR, 0, DIF_VAR_VTIMESTAMP,
DT_ATTR_STABCMN, DT_VERS_1_0,
&dt_idops_type, "uint64_t" },
@@ -514,12 +527,12 @@
{ "walltimestamp", DT_IDENT_SCALAR, 0, DIF_VAR_WALLTIMESTAMP,
DT_ATTR_STABCMN, DT_VERS_1_0,
&dt_idops_type, "int64_t" },
-#if defined(sun)
+#ifdef illumos
{ "zonename", DT_IDENT_SCALAR, 0, DIF_VAR_ZONENAME,
DT_ATTR_STABCMN, DT_VERS_1_0, &dt_idops_type, "string" },
#endif
-#if !defined(sun)
+#ifndef illumos
{ "cpu", DT_IDENT_SCALAR, 0, DIF_VAR_CPU,
DT_ATTR_STABCMN, DT_VERS_1_6_3, &dt_idops_type, "int" },
#endif
@@ -763,7 +776,7 @@
{ DTRACE_STABILITY_UNSTABLE, DTRACE_STABILITY_UNSTABLE, DTRACE_CLASS_COMMON },
};
-#if defined(sun)
+#ifdef illumos
const char *_dtrace_defcpp = "/usr/ccs/lib/cpp"; /* default cpp(1) to invoke */
const char *_dtrace_defld = "/usr/ccs/bin/ld"; /* default ld(1) to invoke */
#else
@@ -772,7 +785,7 @@
#endif
const char *_dtrace_libdir = "/usr/lib/dtrace"; /* default library directory */
-#if defined(sun)
+#ifdef illumos
const char *_dtrace_provdir = "/dev/dtrace/provider"; /* provider directory */
#else
const char *_dtrace_provdir = "/dev/dtrace"; /* provider directory */
@@ -797,7 +810,7 @@
uint_t df_size; /* size of df_fds[] */
} dt_fdlist_t;
-#if defined(sun)
+#ifdef illumos
#pragma init(_dtrace_init)
#else
void _dtrace_init(void) __attribute__ ((constructor));
@@ -833,7 +846,7 @@
dt_provmod_t *prov;
char path[PATH_MAX];
int fd;
-#if defined(sun)
+#ifdef illumos
struct dirent *dp, *ep;
DIR *dirp;
@@ -880,7 +893,7 @@
}
(void) closedir(dirp);
-#else
+#else /* !illumos */
char *p;
char *p1;
char *p_providers = NULL;
@@ -965,7 +978,7 @@
}
if (p_providers != NULL)
free(p_providers);
-#endif
+#endif /* illumos */
}
static void
@@ -982,7 +995,7 @@
*provmod = NULL;
}
-#if defined(sun)
+#ifdef illumos
static const char *
dt_get_sysinfo(int cmd, char *buf, size_t len)
{
@@ -1084,8 +1097,18 @@
dtfd = open("/dev/dtrace/dtrace", O_RDWR);
err = errno; /* save errno from opening dtfd */
-
-#if defined(sun)
+#if defined(__FreeBSD__)
+ /*
+ * Automatically load the 'dtraceall' module if we couldn't open the
+ * char device.
+ */
+ if (err == ENOENT && modfind("dtraceall") < 0) {
+ kldload("dtraceall"); /* ignore the error */
+ dtfd = open("/dev/dtrace/dtrace", O_RDWR);
+ err = errno;
+ }
+#endif
+#ifdef illumos
ftfd = open("/dev/dtrace/provider/fasttrap", O_RDWR);
#else
ftfd = open("/dev/dtrace/fasttrap", O_RDWR);
@@ -1127,15 +1150,16 @@
bzero(dtp, sizeof (dtrace_hdl_t));
dtp->dt_oflags = flags;
-#if defined(sun)
+#ifdef illumos
dtp->dt_prcmode = DT_PROC_STOP_PREINIT;
#else
- dtp->dt_prcmode = DT_PROC_STOP_MAIN;
+ dtp->dt_prcmode = DT_PROC_STOP_POSTINIT;
#endif
dtp->dt_linkmode = DT_LINK_KERNEL;
dtp->dt_linktype = DT_LTYP_ELF;
dtp->dt_xlatemode = DT_XL_STATIC;
dtp->dt_stdcmode = DT_STDC_XA;
+ dtp->dt_encoding = DT_ENCODING_UNSET;
dtp->dt_version = version;
dtp->dt_fd = dtfd;
dtp->dt_ftfd = ftfd;
@@ -1142,7 +1166,7 @@
dtp->dt_fterr = fterr;
dtp->dt_cdefs_fd = -1;
dtp->dt_ddefs_fd = -1;
-#if defined(sun)
+#ifdef illumos
dtp->dt_stdout_fd = -1;
#else
dtp->dt_freopen_fp = NULL;
@@ -1174,7 +1198,7 @@
dtp->dt_cpp_argv[0] = (char *)strbasename(dtp->dt_cpp_path);
-#if defined(sun)
+#ifdef illumos
(void) snprintf(isadef, sizeof (isadef), "-D__SUNW_D_%u",
(uint_t)(sizeof (void *) * NBBY));
@@ -1214,7 +1238,7 @@
return (set_open_errno(dtp, errp, EDT_NOMEM));
#endif
-#if defined(sun)
+#ifdef illumos
#ifdef __x86
/*
* On x86 systems, __i386 is defined for <sys/isa_defs.h> for 32-bit
@@ -1254,7 +1278,7 @@
* 'kern.bootfile' sysctl value tells us exactly which file is being
* used as the kernel.
*/
-#if !defined(sun)
+#ifndef illumos
{
char bootfile[MAXPATHLEN];
char *p;
@@ -1616,7 +1640,7 @@
(void) close(dtp->dt_cdefs_fd);
if (dtp->dt_ddefs_fd != -1)
(void) close(dtp->dt_ddefs_fd);
-#if defined(sun)
+#ifdef illumos
if (dtp->dt_stdout_fd != -1)
(void) close(dtp->dt_stdout_fd);
#else
@@ -1630,7 +1654,6 @@
dt_strdata_destroy(dtp);
dt_buffered_destroy(dtp);
dt_aggregate_destroy(dtp);
- free(dtp->dt_buf.dtbd_data);
dt_pfdict_destroy(dtp);
dt_provmod_destroy(&dtp->dt_provmod);
dt_dof_fini(dtp);
Modified: trunk/cddl/contrib/opensolaris/lib/libdtrace/common/dt_options.c
===================================================================
--- trunk/cddl/contrib/opensolaris/lib/libdtrace/common/dt_options.c 2018-06-02 16:07:17 UTC (rev 10228)
+++ trunk/cddl/contrib/opensolaris/lib/libdtrace/common/dt_options.c 2018-06-02 16:07:30 UTC (rev 10229)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*
* CDDL HEADER START
*
@@ -24,7 +25,10 @@
* Use is subject to license terms.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
+/*
+ * Copyright (c) 2013, Joyent, Inc. All rights reserved.
+ * Copyright (c) 2012 by Delphix. All rights reserved.
+ */
#include <sys/resource.h>
#include <sys/mman.h>
@@ -35,7 +39,7 @@
#include <stdlib.h>
#include <unistd.h>
#include <limits.h>
-#if defined(sun)
+#ifdef illumos
#include <alloca.h>
#endif
#include <errno.h>
@@ -336,6 +340,23 @@
/*ARGSUSED*/
static int
+dt_opt_encoding(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
+{
+ if (arg == NULL)
+ return (dt_set_errno(dtp, EDT_BADOPTVAL));
+
+ if (strcmp(arg, "ascii") == 0)
+ dtp->dt_encoding = DT_ENCODING_ASCII;
+ else if (strcmp(arg, "utf8") == 0)
+ dtp->dt_encoding = DT_ENCODING_UTF8;
+ else
+ return (dt_set_errno(dtp, EDT_BADOPTVAL));
+
+ return (0);
+}
+
+/*ARGSUSED*/
+static int
dt_opt_evaltime(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
{
if (arg == NULL)
@@ -368,6 +389,61 @@
return (0);
}
+static int
+dt_opt_setenv(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
+{
+ char **p;
+ char *var;
+ int i;
+
+ /*
+ * We can't effectively set environment variables from #pragma lines
+ * since the processes have already been spawned.
+ */
+ if (dtp->dt_pcb != NULL)
+ return (dt_set_errno(dtp, EDT_BADOPTCTX));
+
+ if (arg == NULL)
+ return (dt_set_errno(dtp, EDT_BADOPTVAL));
+
+ if (!option && strchr(arg, '=') != NULL)
+ return (dt_set_errno(dtp, EDT_BADOPTVAL));
+
+ for (i = 1, p = dtp->dt_proc_env; *p != NULL; i++, p++)
+ continue;
+
+ for (p = dtp->dt_proc_env; *p != NULL; p++) {
+ var = strchr(*p, '=');
+ if (var == NULL)
+ var = *p + strlen(*p);
+ if (strncmp(*p, arg, var - *p) == 0) {
+ dt_free(dtp, *p);
+ *p = dtp->dt_proc_env[i - 1];
+ dtp->dt_proc_env[i - 1] = NULL;
+ i--;
+ }
+ }
+
+ if (option) {
+ if ((var = strdup(arg)) == NULL)
+ return (dt_set_errno(dtp, EDT_NOMEM));
+
+ if ((p = dt_alloc(dtp, sizeof (char *) * (i + 1))) == NULL) {
+ dt_free(dtp, var);
+ return (dt_set_errno(dtp, EDT_NOMEM));
+ }
+
+ bcopy(dtp->dt_proc_env, p, sizeof (char *) * i);
+ dt_free(dtp, dtp->dt_proc_env);
+ dtp->dt_proc_env = p;
+
+ dtp->dt_proc_env[i - 1] = var;
+ dtp->dt_proc_env[i] = NULL;
+ }
+
+ return (0);
+}
+
/*ARGSUSED*/
static int
dt_opt_stdc(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
@@ -411,7 +487,6 @@
return (0);
}
-
/*ARGSUSED*/
static int
dt_opt_tree(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
@@ -797,7 +872,7 @@
bzero(&hdr, sizeof (dof_hdr_t));
hdr.dofh_loadsz = sizeof (dof_hdr_t);
-#if defined(sun)
+#ifdef illumos
if (dt_ioctl(dtp, DTRACEIOC_DOFGET, &hdr) == -1)
#else
dof = &hdr;
@@ -815,7 +890,7 @@
for (i = 0; i < DTRACEOPT_MAX; i++)
dtp->dt_options[i] = DTRACEOPT_UNSET;
-#if defined(sun)
+#ifdef illumos
if (dt_ioctl(dtp, DTRACEIOC_DOFGET, dof) == -1)
#else
if (dt_ioctl(dtp, DTRACEIOC_DOFGET, &dof) == -1)
@@ -848,30 +923,6 @@
return (0);
}
-/*ARGSUSED*/
-static int
-dt_opt_preallocate(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
-{
- dtrace_optval_t size;
- void *p;
-
- if (arg == NULL || dt_optval_parse(arg, &size) != 0)
- return (dt_set_errno(dtp, EDT_BADOPTVAL));
-
- if (size > SIZE_MAX)
- size = SIZE_MAX;
-
- if ((p = dt_zalloc(dtp, size)) == NULL) {
- do {
- size /= 2;
- } while ((p = dt_zalloc(dtp, size)) == NULL);
- }
-
- dt_free(dtp, p);
-
- return (0);
-}
-
typedef struct dt_option {
const char *o_name;
int (*o_func)(dtrace_hdl_t *, const char *, uintptr_t);
@@ -896,6 +947,7 @@
{ "define", dt_opt_cpp_opts, (uintptr_t)"-D" },
{ "droptags", dt_opt_droptags },
{ "empty", dt_opt_cflags, DTRACE_C_EMPTY },
+ { "encoding", dt_opt_encoding },
{ "errtags", dt_opt_cflags, DTRACE_C_ETAGS },
{ "evaltime", dt_opt_evaltime },
{ "incdir", dt_opt_cpp_opts, (uintptr_t)"-I" },
@@ -910,8 +962,8 @@
{ "linktype", dt_opt_linktype },
{ "nolibs", dt_opt_cflags, DTRACE_C_NOLIBS },
{ "pgmax", dt_opt_pgmax },
- { "preallocate", dt_opt_preallocate },
{ "pspec", dt_opt_cflags, DTRACE_C_PSPEC },
+ { "setenv", dt_opt_setenv, 1 },
{ "stdc", dt_opt_stdc },
{ "strip", dt_opt_dflags, DTRACE_D_STRIP },
{ "syslibdir", dt_opt_syslibdir },
@@ -920,6 +972,7 @@
{ "udefs", dt_opt_invcflags, DTRACE_C_UNODEF },
{ "undef", dt_opt_cpp_opts, (uintptr_t)"-U" },
{ "unodefs", dt_opt_cflags, DTRACE_C_UNODEF },
+ { "unsetenv", dt_opt_setenv, 0 },
{ "verbose", dt_opt_cflags, DTRACE_C_DIFV },
{ "version", dt_opt_version },
{ "zdefs", dt_opt_cflags, DTRACE_C_ZDEFS },
@@ -947,6 +1000,7 @@
{ "statusrate", dt_opt_rate, DTRACEOPT_STATUSRATE },
{ "strsize", dt_opt_strsize, DTRACEOPT_STRSIZE },
{ "ustackframes", dt_opt_runtime, DTRACEOPT_USTACKFRAMES },
+ { "temporal", dt_opt_runtime, DTRACEOPT_TEMPORAL },
{ NULL, NULL, 0 }
};
@@ -954,11 +1008,14 @@
* Dynamic run-time options.
*/
static const dt_option_t _dtrace_drtoptions[] = {
+ { "agghist", dt_opt_runtime, DTRACEOPT_AGGHIST },
+ { "aggpack", dt_opt_runtime, DTRACEOPT_AGGPACK },
{ "aggrate", dt_opt_rate, DTRACEOPT_AGGRATE },
{ "aggsortkey", dt_opt_runtime, DTRACEOPT_AGGSORTKEY },
{ "aggsortkeypos", dt_opt_runtime, DTRACEOPT_AGGSORTKEYPOS },
{ "aggsortpos", dt_opt_runtime, DTRACEOPT_AGGSORTPOS },
{ "aggsortrev", dt_opt_runtime, DTRACEOPT_AGGSORTREV },
+ { "aggzoom", dt_opt_runtime, DTRACEOPT_AGGZOOM },
{ "flowindent", dt_opt_runtime, DTRACEOPT_FLOWINDENT },
{ "quiet", dt_opt_runtime, DTRACEOPT_QUIET },
{ "rawbytes", dt_opt_runtime, DTRACEOPT_RAWBYTES },
Modified: trunk/cddl/contrib/opensolaris/lib/libdtrace/common/dt_parser.c
===================================================================
--- trunk/cddl/contrib/opensolaris/lib/libdtrace/common/dt_parser.c 2018-06-02 16:07:17 UTC (rev 10228)
+++ trunk/cddl/contrib/opensolaris/lib/libdtrace/common/dt_parser.c 2018-06-02 16:07:30 UTC (rev 10229)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*
* CDDL HEADER START
*
@@ -22,7 +23,8 @@
/*
* Copyright 2006 Sun Microsystems, Inc. All rights reserved.
- * Copyright (c) 2011, Joyent Inc. All rights reserved.
+ * Copyright (c) 2013, Joyent Inc. All rights reserved.
+ * Copyright (c) 2013 by Delphix. All rights reserved.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
@@ -96,11 +98,12 @@
*/
#include <sys/param.h>
+#include <sys/sysmacros.h>
#include <limits.h>
#include <setjmp.h>
#include <strings.h>
#include <assert.h>
-#if defined(sun)
+#ifdef illumos
#include <alloca.h>
#endif
#include <stdlib.h>
@@ -195,7 +198,7 @@
{
static const char delimiters[] = " \t\n\r\v\f*`";
dtrace_hdl_t *dtp = yypcb->pcb_hdl;
- const char *p, *q, *end, *obj;
+ const char *p, *q, *r, *end, *obj;
for (p = s, end = s + strlen(s); *p != '\0'; p = q) {
while (isspace(*p))
@@ -223,8 +226,23 @@
bcopy(s, type, (size_t)(p - s));
bcopy(q + 1, type + (size_t)(p - s), strlen(q + 1) + 1);
- if (strchr(q + 1, '`') != NULL)
- return (dt_set_errno(dtp, EDT_BADSCOPE));
+ /*
+ * There may be at most three delimeters. The second
+ * delimeter is usually used to distinguish the type
+ * within a given module, however, there could be a link
+ * map id on the scene in which case that delimeter
+ * would be the third. We determine presence of the lmid
+ * if it rouglhly meets the from LM[0-9]
+ */
+ if ((r = strchr(q + 1, '`')) != NULL &&
+ ((r = strchr(r + 1, '`')) != NULL)) {
+ if (strchr(r + 1, '`') != NULL)
+ return (dt_set_errno(dtp,
+ EDT_BADSCOPE));
+ if (q[1] != 'L' || q[2] != 'M')
+ return (dt_set_errno(dtp,
+ EDT_BADSCOPE));
+ }
return (dtrace_lookup_by_type(dtp, object, type, tip));
}
@@ -254,6 +272,7 @@
ctf_file_t *ctfp = tip->dtt_ctfp;
ctf_id_t type = tip->dtt_type;
ctf_id_t base = ctf_type_resolve(ctfp, type);
+ uint_t bflags = tip->dtt_flags;
dt_module_t *dmp;
ctf_id_t ptr;
@@ -285,6 +304,7 @@
tip->dtt_object = dmp->dm_name;
tip->dtt_ctfp = dmp->dm_ctfp;
tip->dtt_type = ptr;
+ tip->dtt_flags = bflags;
return (0);
}
@@ -388,7 +408,7 @@
dt_node_promote(dt_node_t *lp, dt_node_t *rp, dt_node_t *dnp)
{
dt_type_promote(lp, rp, &dnp->dn_ctfp, &dnp->dn_type);
- dt_node_type_assign(dnp, dnp->dn_ctfp, dnp->dn_type);
+ dt_node_type_assign(dnp, dnp->dn_ctfp, dnp->dn_type, B_FALSE);
dt_node_attr_assign(dnp, dt_attr_min(lp->dn_attr, rp->dn_attr));
}
@@ -657,7 +677,8 @@
}
void
-dt_node_type_assign(dt_node_t *dnp, ctf_file_t *fp, ctf_id_t type)
+dt_node_type_assign(dt_node_t *dnp, ctf_file_t *fp, ctf_id_t type,
+ boolean_t user)
{
ctf_id_t base = ctf_type_resolve(fp, type);
uint_t kind = ctf_type_kind(fp, base);
@@ -689,6 +710,9 @@
type == DT_DYN_TYPE(yypcb->pcb_hdl))
dnp->dn_flags |= DT_NF_REF;
+ if (user)
+ dnp->dn_flags |= DT_NF_USERLAND;
+
dnp->dn_flags |= DT_NF_COOKED;
dnp->dn_ctfp = fp;
dnp->dn_type = type;
@@ -726,6 +750,7 @@
dt_node_type_size(const dt_node_t *dnp)
{
ctf_id_t base;
+ dtrace_hdl_t *dtp = yypcb->pcb_hdl;
if (dnp->dn_kind == DT_NODE_STRING)
return (strlen(dnp->dn_string) + 1);
@@ -738,6 +763,20 @@
if (ctf_type_kind(dnp->dn_ctfp, base) == CTF_K_FORWARD)
return (0);
+ /*
+ * Here we have a 32-bit user pointer that is being used with a 64-bit
+ * kernel. When we're using it and its tagged as a userland reference --
+ * then we need to keep it as a 32-bit pointer. However, if we are
+ * referring to it as a kernel address, eg. being used after a copyin()
+ * then we need to make sure that we actually return the kernel's size
+ * of a pointer, 8 bytes.
+ */
+ if (ctf_type_kind(dnp->dn_ctfp, base) == CTF_K_POINTER &&
+ ctf_getmodel(dnp->dn_ctfp) == CTF_MODEL_ILP32 &&
+ !(dnp->dn_flags & DT_NF_USERLAND) &&
+ dtp->dt_conf.dtc_ctfmodel == CTF_MODEL_LP64)
+ return (8);
+
return (ctf_type_size(dnp->dn_ctfp, dnp->dn_type));
}
@@ -1224,7 +1263,7 @@
if (value <= dtp->dt_ints[i].did_limit) {
dt_node_type_assign(dnp,
dtp->dt_ints[i].did_ctfp,
- dtp->dt_ints[i].did_type);
+ dtp->dt_ints[i].did_type, B_FALSE);
/*
* If a prefix character is present in macro text, add
@@ -1259,7 +1298,7 @@
dnp = dt_node_alloc(DT_NODE_STRING);
dnp->dn_op = DT_TOK_STRING;
dnp->dn_string = string;
- dt_node_type_assign(dnp, DT_STR_CTFP(dtp), DT_STR_TYPE(dtp));
+ dt_node_type_assign(dnp, DT_STR_CTFP(dtp), DT_STR_TYPE(dtp), B_FALSE);
return (dnp);
}
@@ -1335,8 +1374,9 @@
dnp = dt_node_alloc(DT_NODE_TYPE);
dnp->dn_op = DT_TOK_IDENT;
dnp->dn_string = name;
- dt_node_type_assign(dnp, dtt.dtt_ctfp, dtt.dtt_type);
+ dt_node_type_assign(dnp, dtt.dtt_ctfp, dtt.dtt_type, dtt.dtt_flags);
+
if (dtt.dtt_ctfp == dtp->dt_cdefs->dm_ctfp ||
dtt.dtt_ctfp == dtp->dt_ddefs->dm_ctfp)
dt_node_attr_assign(dnp, _dtrace_defattr);
@@ -1579,7 +1619,8 @@
bzero(&idn, sizeof (dt_node_t));
if (idp != NULL && idp->di_type != CTF_ERR)
- dt_node_type_assign(&idn, idp->di_ctfp, idp->di_type);
+ dt_node_type_assign(&idn, idp->di_ctfp, idp->di_type,
+ B_FALSE);
else if (idp != NULL)
(void) dt_ident_cook(&idn, idp, NULL);
@@ -1789,7 +1830,7 @@
}
bzero(&dn, sizeof (dn));
- dt_node_type_assign(&dn, dtt.dtt_ctfp, ctm.ctm_type);
+ dt_node_type_assign(&dn, dtt.dtt_ctfp, ctm.ctm_type, B_FALSE);
if (dn.dn_flags & DT_NF_BITFIELD) {
xyerror(D_OFFSETOF_BITFIELD,
@@ -1845,7 +1886,8 @@
}
dt_node_type_assign(cp, dtp->dt_ddefs->dm_ctfp,
- ctf_lookup_by_name(dtp->dt_ddefs->dm_ctfp, "size_t"));
+ ctf_lookup_by_name(dtp->dt_ddefs->dm_ctfp, "size_t"),
+ B_FALSE);
cp->dn_kind = DT_NODE_INT;
cp->dn_op = DT_TOK_INT;
@@ -1862,6 +1904,38 @@
return (dnp);
}
+/*
+ * If an integer constant is being cast to another integer type, we can
+ * perform the cast as part of integer constant folding in this pass. We must
+ * take action when the integer is being cast to a smaller type or if it is
+ * changing signed-ness. If so, we first shift rp's bits bits high (losing
+ * excess bits if narrowing) and then shift them down with either a logical
+ * shift (unsigned) or arithmetic shift (signed).
+ */
+static void
+dt_cast(dt_node_t *lp, dt_node_t *rp)
+{
+ size_t srcsize = dt_node_type_size(rp);
+ size_t dstsize = dt_node_type_size(lp);
+
+ if (dstsize < srcsize) {
+ int n = (sizeof (uint64_t) - dstsize) * NBBY;
+ rp->dn_value <<= n;
+ rp->dn_value >>= n;
+ } else if (dstsize > srcsize) {
+ int n = (sizeof (uint64_t) - srcsize) * NBBY;
+ int s = (dstsize - srcsize) * NBBY;
+
+ rp->dn_value <<= n;
+ if (rp->dn_flags & DT_NF_SIGNED) {
+ rp->dn_value = (intmax_t)rp->dn_value >> s;
+ rp->dn_value >>= n - s;
+ } else {
+ rp->dn_value >>= n;
+ }
+ }
+}
+
dt_node_t *
dt_node_op2(int op, dt_node_t *lp, dt_node_t *rp)
{
@@ -1891,17 +1965,17 @@
case DT_TOK_LOR:
dnp->dn_value = l || r;
dt_node_type_assign(dnp,
- DT_INT_CTFP(dtp), DT_INT_TYPE(dtp));
+ DT_INT_CTFP(dtp), DT_INT_TYPE(dtp), B_FALSE);
break;
case DT_TOK_LXOR:
dnp->dn_value = (l != 0) ^ (r != 0);
dt_node_type_assign(dnp,
- DT_INT_CTFP(dtp), DT_INT_TYPE(dtp));
+ DT_INT_CTFP(dtp), DT_INT_TYPE(dtp), B_FALSE);
break;
case DT_TOK_LAND:
dnp->dn_value = l && r;
dt_node_type_assign(dnp,
- DT_INT_CTFP(dtp), DT_INT_TYPE(dtp));
+ DT_INT_CTFP(dtp), DT_INT_TYPE(dtp), B_FALSE);
break;
case DT_TOK_BOR:
dnp->dn_value = l | r;
@@ -1918,12 +1992,12 @@
case DT_TOK_EQU:
dnp->dn_value = l == r;
dt_node_type_assign(dnp,
- DT_INT_CTFP(dtp), DT_INT_TYPE(dtp));
+ DT_INT_CTFP(dtp), DT_INT_TYPE(dtp), B_FALSE);
break;
case DT_TOK_NEQ:
dnp->dn_value = l != r;
dt_node_type_assign(dnp,
- DT_INT_CTFP(dtp), DT_INT_TYPE(dtp));
+ DT_INT_CTFP(dtp), DT_INT_TYPE(dtp), B_FALSE);
break;
case DT_TOK_LT:
dt_node_promote(lp, rp, dnp);
@@ -1932,7 +2006,7 @@
else
dnp->dn_value = l < r;
dt_node_type_assign(dnp,
- DT_INT_CTFP(dtp), DT_INT_TYPE(dtp));
+ DT_INT_CTFP(dtp), DT_INT_TYPE(dtp), B_FALSE);
break;
case DT_TOK_LE:
dt_node_promote(lp, rp, dnp);
@@ -1941,7 +2015,7 @@
else
dnp->dn_value = l <= r;
dt_node_type_assign(dnp,
- DT_INT_CTFP(dtp), DT_INT_TYPE(dtp));
+ DT_INT_CTFP(dtp), DT_INT_TYPE(dtp), B_FALSE);
break;
case DT_TOK_GT:
dt_node_promote(lp, rp, dnp);
@@ -1950,7 +2024,7 @@
else
dnp->dn_value = l > r;
dt_node_type_assign(dnp,
- DT_INT_CTFP(dtp), DT_INT_TYPE(dtp));
+ DT_INT_CTFP(dtp), DT_INT_TYPE(dtp), B_FALSE);
break;
case DT_TOK_GE:
dt_node_promote(lp, rp, dnp);
@@ -1959,7 +2033,7 @@
else
dnp->dn_value = l >= r;
dt_node_type_assign(dnp,
- DT_INT_CTFP(dtp), DT_INT_TYPE(dtp));
+ DT_INT_CTFP(dtp), DT_INT_TYPE(dtp), B_FALSE);
break;
case DT_TOK_LSH:
dnp->dn_value = l << r;
@@ -2011,32 +2085,9 @@
}
}
- /*
- * If an integer constant is being cast to another integer type, we can
- * perform the cast as part of integer constant folding in this pass.
- * We must take action when the integer is being cast to a smaller type
- * or if it is changing signed-ness. If so, we first shift rp's bits
- * bits high (losing excess bits if narrowing) and then shift them down
- * with either a logical shift (unsigned) or arithmetic shift (signed).
- */
if (op == DT_TOK_LPAR && rp->dn_kind == DT_NODE_INT &&
dt_node_is_integer(lp)) {
- size_t srcsize = dt_node_type_size(rp);
- size_t dstsize = dt_node_type_size(lp);
-
- if ((dstsize < srcsize) || ((lp->dn_flags & DT_NF_SIGNED) ^
- (rp->dn_flags & DT_NF_SIGNED))) {
- int n = dstsize < srcsize ?
- (sizeof (uint64_t) * NBBY - dstsize * NBBY) :
- (sizeof (uint64_t) * NBBY - srcsize * NBBY);
-
- rp->dn_value <<= n;
- if (lp->dn_flags & DT_NF_SIGNED)
- rp->dn_value = (intmax_t)rp->dn_value >> n;
- else
- rp->dn_value = rp->dn_value >> n;
- }
-
+ dt_cast(lp, rp);
dt_node_type_propagate(lp, rp);
dt_node_attr_assign(rp, dt_attr_min(lp->dn_attr, rp->dn_attr));
dt_node_free(lp);
@@ -2223,7 +2274,7 @@
* until we have successfully cooked the right-hand expression, below.
*/
dnp = dt_node_alloc(DT_NODE_INLINE);
- dt_node_type_assign(dnp, dtt.dtt_ctfp, dtt.dtt_type);
+ dt_node_type_assign(dnp, dtt.dtt_ctfp, dtt.dtt_type, B_FALSE);
dt_node_attr_assign(dnp, _dtrace_defattr);
if (dt_node_is_void(dnp)) {
@@ -2378,7 +2429,8 @@
dnp->dn_membexpr = expr;
if (ddp != NULL)
- dt_node_type_assign(dnp, dtt.dtt_ctfp, dtt.dtt_type);
+ dt_node_type_assign(dnp, dtt.dtt_ctfp, dtt.dtt_type,
+ dtt.dtt_flags);
return (dnp);
}
@@ -2409,10 +2461,10 @@
}
bzero(&sn, sizeof (sn));
- dt_node_type_assign(&sn, src.dtt_ctfp, src.dtt_type);
+ dt_node_type_assign(&sn, src.dtt_ctfp, src.dtt_type, B_FALSE);
bzero(&dn, sizeof (dn));
- dt_node_type_assign(&dn, dst.dtt_ctfp, dst.dtt_type);
+ dt_node_type_assign(&dn, dst.dtt_ctfp, dst.dtt_type, B_FALSE);
if (dt_xlator_lookup(dtp, &sn, &dn, DT_XLATE_EXACT) != NULL) {
xyerror(D_XLATE_REDECL,
@@ -2658,7 +2710,7 @@
attr = dt_ident_cook(dnp, idp, NULL);
else {
dt_node_type_assign(dnp,
- DT_DYN_CTFP(dtp), DT_DYN_TYPE(dtp));
+ DT_DYN_CTFP(dtp), DT_DYN_TYPE(dtp), B_FALSE);
attr = idp->di_attr;
}
@@ -2734,7 +2786,8 @@
dnp->dn_ident = idp;
dnp->dn_flags |= DT_NF_LVALUE;
- dt_node_type_assign(dnp, dtt.dtt_ctfp, dtt.dtt_type);
+ dt_node_type_assign(dnp, dtt.dtt_ctfp, dtt.dtt_type,
+ dtt.dtt_flags);
dt_node_attr_assign(dnp, _dtrace_symattr);
if (uref) {
@@ -2782,7 +2835,7 @@
attr = dt_ident_cook(dnp, idp, NULL);
else {
dt_node_type_assign(dnp,
- DT_DYN_CTFP(dtp), DT_DYN_TYPE(dtp));
+ DT_DYN_CTFP(dtp), DT_DYN_TYPE(dtp), B_FALSE);
attr = idp->di_attr;
}
@@ -2885,7 +2938,8 @@
xyerror(D_TYPE_ERR, "failed to lookup int64_t\n");
dt_ident_type_assign(cp->dn_ident, dtt.dtt_ctfp, dtt.dtt_type);
- dt_node_type_assign(cp, dtt.dtt_ctfp, dtt.dtt_type);
+ dt_node_type_assign(cp, dtt.dtt_ctfp, dtt.dtt_type,
+ dtt.dtt_flags);
}
if (cp->dn_kind == DT_NODE_VAR)
@@ -2895,7 +2949,7 @@
case DT_TOK_DEREF:
/*
* If the deref operator is applied to a translated pointer,
- * we can just set our output type to the base translation.
+ * we set our output type to the output of the translation.
*/
if ((idp = dt_node_resolve(cp, DT_IDENT_XLPTR)) != NULL) {
dt_xlator_t *dxp = idp->di_data;
@@ -2902,7 +2956,8 @@
dnp->dn_ident = &dxp->dx_souid;
dt_node_type_assign(dnp,
- DT_DYN_CTFP(dtp), DT_DYN_TYPE(dtp));
+ dnp->dn_ident->di_ctfp, dnp->dn_ident->di_type,
+ cp->dn_flags & DT_NF_USERLAND);
break;
}
@@ -2922,7 +2977,8 @@
"cannot dereference non-pointer type\n");
}
- dt_node_type_assign(dnp, cp->dn_ctfp, type);
+ dt_node_type_assign(dnp, cp->dn_ctfp, type,
+ cp->dn_flags & DT_NF_USERLAND);
base = ctf_type_resolve(cp->dn_ctfp, type);
kind = ctf_type_kind(cp->dn_ctfp, base);
@@ -2979,7 +3035,8 @@
xyerror(D_OP_SCALAR, "operator %s requires an operand "
"of scalar type\n", opstr(dnp->dn_op));
}
- dt_node_type_assign(dnp, DT_INT_CTFP(dtp), DT_INT_TYPE(dtp));
+ dt_node_type_assign(dnp, DT_INT_CTFP(dtp), DT_INT_TYPE(dtp),
+ B_FALSE);
break;
case DT_TOK_ADDROF:
@@ -3012,10 +3069,8 @@
dt_node_type_name(cp, n, sizeof (n)));
}
- dt_node_type_assign(dnp, dtt.dtt_ctfp, dtt.dtt_type);
-
- if (cp->dn_flags & DT_NF_USERLAND)
- dnp->dn_flags |= DT_NF_USERLAND;
+ dt_node_type_assign(dnp, dtt.dtt_ctfp, dtt.dtt_type,
+ cp->dn_flags & DT_NF_USERLAND);
break;
case DT_TOK_SIZEOF:
@@ -3030,7 +3085,8 @@
}
dt_node_type_assign(dnp, dtp->dt_ddefs->dm_ctfp,
- ctf_lookup_by_name(dtp->dt_ddefs->dm_ctfp, "size_t"));
+ ctf_lookup_by_name(dtp->dt_ddefs->dm_ctfp, "size_t"),
+ B_FALSE);
break;
case DT_TOK_STRINGOF:
@@ -3040,7 +3096,8 @@
"cannot apply stringof to a value of type %s\n",
dt_node_type_name(cp, n, sizeof (n)));
}
- dt_node_type_assign(dnp, DT_STR_CTFP(dtp), DT_STR_TYPE(dtp));
+ dt_node_type_assign(dnp, DT_STR_CTFP(dtp), DT_STR_TYPE(dtp),
+ cp->dn_flags & DT_NF_USERLAND);
break;
case DT_TOK_PREINC:
@@ -3078,6 +3135,31 @@
return (dnp);
}
+static void
+dt_assign_common(dt_node_t *dnp)
+{
+ dt_node_t *lp = dnp->dn_left;
+ dt_node_t *rp = dnp->dn_right;
+ int op = dnp->dn_op;
+
+ if (rp->dn_kind == DT_NODE_INT)
+ dt_cast(lp, rp);
+
+ if (!(lp->dn_flags & DT_NF_LVALUE)) {
+ xyerror(D_OP_LVAL, "operator %s requires modifiable "
+ "lvalue as an operand\n", opstr(op));
+ /* see K&R[A7.17] */
+ }
+
+ if (!(lp->dn_flags & DT_NF_WRITABLE)) {
+ xyerror(D_OP_WRITE, "operator %s can only be applied "
+ "to a writable variable\n", opstr(op));
+ }
+
+ dt_node_type_propagate(lp, dnp); /* see K&R[A7.17] */
+ dt_node_attr_assign(dnp, dt_attr_min(lp->dn_attr, rp->dn_attr));
+}
+
static dt_node_t *
dt_cook_op2(dt_node_t *dnp, uint_t idflags)
{
@@ -3208,7 +3290,8 @@
"of scalar type\n", opstr(op));
}
- dt_node_type_assign(dnp, DT_INT_CTFP(dtp), DT_INT_TYPE(dtp));
+ dt_node_type_assign(dnp, DT_INT_CTFP(dtp), DT_INT_TYPE(dtp),
+ B_FALSE);
dt_node_attr_assign(dnp, dt_attr_min(lp->dn_attr, rp->dn_attr));
break;
@@ -3252,7 +3335,8 @@
rp->dn_op = DT_TOK_INT;
rp->dn_value = (intmax_t)val;
- dt_node_type_assign(rp, lp->dn_ctfp, lp->dn_type);
+ dt_node_type_assign(rp, lp->dn_ctfp, lp->dn_type,
+ B_FALSE);
dt_node_attr_assign(rp, _dtrace_symattr);
}
@@ -3284,7 +3368,8 @@
dt_node_type_name(rp, n2, sizeof (n2)));
}
- dt_node_type_assign(dnp, DT_INT_CTFP(dtp), DT_INT_TYPE(dtp));
+ dt_node_type_assign(dnp, DT_INT_CTFP(dtp), DT_INT_TYPE(dtp),
+ B_FALSE);
dt_node_attr_assign(dnp, dt_attr_min(lp->dn_attr, rp->dn_attr));
break;
@@ -3332,7 +3417,7 @@
dt_node_type_name(rp, n2, sizeof (n2)));
}
- dt_node_type_assign(dnp, ctfp, type);
+ dt_node_type_assign(dnp, ctfp, type, B_FALSE);
dt_node_attr_assign(dnp, dt_attr_min(lp->dn_attr, rp->dn_attr));
if (uref)
@@ -3473,7 +3558,7 @@
*/
if (lp->dn_kind == DT_NODE_VAR &&
dt_ident_unref(lp->dn_ident)) {
- dt_node_type_assign(lp, ctfp, type);
+ dt_node_type_assign(lp, ctfp, type, B_FALSE);
dt_ident_type_assign(lp->dn_ident, ctfp, type);
if (uref) {
@@ -3556,19 +3641,7 @@
}
}
asgn_common:
- if (!(lp->dn_flags & DT_NF_LVALUE)) {
- xyerror(D_OP_LVAL, "operator %s requires modifiable "
- "lvalue as an operand\n", opstr(op));
- /* see K&R[A7.17] */
- }
-
- if (!(lp->dn_flags & DT_NF_WRITABLE)) {
- xyerror(D_OP_WRITE, "operator %s can only be applied "
- "to a writable variable\n", opstr(op));
- }
-
- dt_node_type_propagate(lp, dnp); /* see K&R[A7.17] */
- dt_node_attr_assign(dnp, dt_attr_min(lp->dn_attr, rp->dn_attr));
+ dt_assign_common(dnp);
break;
case DT_TOK_PTR:
@@ -3699,7 +3772,7 @@
type = ctf_type_resolve(ctfp, m.ctm_type);
kind = ctf_type_kind(ctfp, type);
- dt_node_type_assign(dnp, ctfp, m.ctm_type);
+ dt_node_type_assign(dnp, ctfp, m.ctm_type, B_FALSE);
dt_node_attr_assign(dnp, lp->dn_attr);
if (op == DT_TOK_PTR && (kind != CTF_K_ARRAY ||
@@ -3825,7 +3898,8 @@
}
dnp->dn_ident = dt_xlator_ident(dxp, lp->dn_ctfp, lp->dn_type);
- dt_node_type_assign(dnp, DT_DYN_CTFP(dtp), DT_DYN_TYPE(dtp));
+ dt_node_type_assign(dnp, DT_DYN_CTFP(dtp), DT_DYN_TYPE(dtp),
+ B_FALSE);
dt_node_attr_assign(dnp,
dt_attr_min(rp->dn_attr, dnp->dn_ident->di_attr));
break;
@@ -3873,6 +3947,14 @@
dt_node_type_propagate(lp, dnp); /* see K&R[A7.5] */
dt_node_attr_assign(dnp, dt_attr_min(lp->dn_attr, rp->dn_attr));
+
+ /*
+ * If it's a pointer then should be able to (attempt to)
+ * assign to it.
+ */
+ if (lkind == CTF_K_POINTER)
+ dnp->dn_flags |= DT_NF_WRITABLE;
+
break;
}
@@ -3982,7 +4064,7 @@
"used in a conditional context\n");
}
- dt_node_type_assign(dnp, ctfp, type);
+ dt_node_type_assign(dnp, ctfp, type, B_FALSE);
dt_node_attr_assign(dnp, dt_attr_min(dnp->dn_expr->dn_attr,
dt_attr_min(lp->dn_attr, rp->dn_attr)));
@@ -4015,7 +4097,8 @@
dt_node_attr_assign(dnp, dt_ident_cook(dnp,
dnp->dn_ident, &dnp->dn_aggtup));
} else {
- dt_node_type_assign(dnp, DT_DYN_CTFP(dtp), DT_DYN_TYPE(dtp));
+ dt_node_type_assign(dnp, DT_DYN_CTFP(dtp), DT_DYN_TYPE(dtp),
+ B_FALSE);
dt_node_attr_assign(dnp, dnp->dn_ident->di_attr);
}
@@ -4217,7 +4300,8 @@
}
(void) dt_node_cook(mnp, DT_IDFLG_REF);
- dt_node_type_assign(mnp, dxp->dx_dst_ctfp, ctm.ctm_type);
+ dt_node_type_assign(mnp, dxp->dx_dst_ctfp, ctm.ctm_type,
+ B_FALSE);
attr = dt_attr_min(attr, mnp->dn_attr);
if (dt_node_is_argcompat(mnp, mnp->dn_membexpr) == 0) {
@@ -4236,7 +4320,7 @@
dxp->dx_souid.di_attr = attr;
dxp->dx_ptrid.di_attr = attr;
- dt_node_type_assign(dnp, DT_DYN_CTFP(dtp), DT_DYN_TYPE(dtp));
+ dt_node_type_assign(dnp, DT_DYN_CTFP(dtp), DT_DYN_TYPE(dtp), B_FALSE);
dt_node_attr_assign(dnp, _dtrace_defattr);
return (dnp);
@@ -4529,7 +4613,9 @@
ctf_type_resolve(dnp->dn_ctfp, dnp->dn_type));
}
- tp->dtdt_flags = (dnp->dn_flags & DT_NF_REF) ? DIF_TF_BYREF : 0;
+ tp->dtdt_flags = (dnp->dn_flags & DT_NF_REF) ?
+ (dnp->dn_flags & DT_NF_USERLAND) ? DIF_TF_BYUREF :
+ DIF_TF_BYREF : 0;
tp->dtdt_pad = 0;
tp->dtdt_size = ctf_type_size(dnp->dn_ctfp, dnp->dn_type);
}
Modified: trunk/cddl/contrib/opensolaris/lib/libdtrace/common/dt_parser.h
===================================================================
--- trunk/cddl/contrib/opensolaris/lib/libdtrace/common/dt_parser.h 2018-06-02 16:07:17 UTC (rev 10228)
+++ trunk/cddl/contrib/opensolaris/lib/libdtrace/common/dt_parser.h 2018-06-02 16:07:30 UTC (rev 10229)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*
* CDDL HEADER START
*
@@ -22,12 +23,14 @@
* Copyright 2007 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
+/*
+ * Copyright (c) 2013 by Delphix. All rights reserved.
+ * Copyright (c) 2013 Joyent, Inc. All rights reserved.
+ */
#ifndef _DT_PARSER_H
#define _DT_PARSER_H
-#pragma ident "%Z%%M% %I% %E% SMI"
-
#include <sys/types.h>
#include <sys/dtrace.h>
@@ -223,7 +226,7 @@
extern void dt_node_link_free(dt_node_t **);
extern void dt_node_attr_assign(dt_node_t *, dtrace_attribute_t);
-extern void dt_node_type_assign(dt_node_t *, ctf_file_t *, ctf_id_t);
+extern void dt_node_type_assign(dt_node_t *, ctf_file_t *, ctf_id_t, boolean_t);
extern void dt_node_type_propagate(const dt_node_t *, dt_node_t *);
extern const char *dt_node_type_name(const dt_node_t *, char *, size_t);
extern size_t dt_node_type_size(const dt_node_t *);
Modified: trunk/cddl/contrib/opensolaris/lib/libdtrace/common/dt_pcb.c
===================================================================
--- trunk/cddl/contrib/opensolaris/lib/libdtrace/common/dt_pcb.c 2018-06-02 16:07:17 UTC (rev 10228)
+++ trunk/cddl/contrib/opensolaris/lib/libdtrace/common/dt_pcb.c 2018-06-02 16:07:30 UTC (rev 10229)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*
* CDDL HEADER START
*
Modified: trunk/cddl/contrib/opensolaris/lib/libdtrace/common/dt_pcb.h
===================================================================
--- trunk/cddl/contrib/opensolaris/lib/libdtrace/common/dt_pcb.h 2018-06-02 16:07:17 UTC (rev 10228)
+++ trunk/cddl/contrib/opensolaris/lib/libdtrace/common/dt_pcb.h 2018-06-02 16:07:30 UTC (rev 10229)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*
* CDDL HEADER START
*
Modified: trunk/cddl/contrib/opensolaris/lib/libdtrace/common/dt_pid.c
===================================================================
--- trunk/cddl/contrib/opensolaris/lib/libdtrace/common/dt_pid.c 2018-06-02 16:07:17 UTC (rev 10228)
+++ trunk/cddl/contrib/opensolaris/lib/libdtrace/common/dt_pid.c 2018-06-02 16:07:30 UTC (rev 10229)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*
* CDDL HEADER START
*
@@ -23,6 +24,9 @@
* Copyright 2010 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
+/*
+ * Copyright (c) 2013, Joyent, Inc. All rights reserved.
+ */
#include <assert.h>
#include <strings.h>
@@ -30,19 +34,21 @@
#include <stdio.h>
#include <errno.h>
#include <ctype.h>
-#if defined(sun)
+#ifdef illumos
#include <alloca.h>
#endif
#include <libgen.h>
#include <stddef.h>
+#include <sys/sysmacros.h>
#include <dt_impl.h>
#include <dt_program.h>
#include <dt_pid.h>
#include <dt_string.h>
-#if !defined(sun)
+#ifndef illumos
#include <libproc_compat.h>
#endif
+#include <dt_module.h>
typedef struct dt_pid_probe {
dtrace_hdl_t *dpp_dtp;
@@ -69,7 +75,7 @@
static void
dt_pid_objname(char *buf, size_t len, Lmid_t lmid, const char *obj)
{
-#if defined(sun)
+#ifdef illumos
if (lmid == LM_ID_BASE)
(void) strncpy(buf, obj, len);
else
@@ -121,7 +127,7 @@
int isdash = strcmp("-", func) == 0;
pid_t pid;
-#if defined(sun)
+#ifdef illumos
pid = Pstatus(pp->dpp_pr)->pr_pid;
#else
pid = proc_getpid(pp->dpp_pr);
@@ -265,7 +271,7 @@
if (obj == NULL)
return (0);
-#if defined(sun)
+#ifdef illumos
(void) Plmid(pp->dpp_pr, pmp->pr_vaddr, &pp->dpp_lmid);
#endif
@@ -274,7 +280,7 @@
pp->dpp_obj = obj;
else
pp->dpp_obj++;
-#if defined(sun)
+#ifdef illumos
if (Pxlookup_by_name(pp->dpp_pr, pp->dpp_lmid, obj, ".stret1", &sym,
NULL) == 0)
pp->dpp_stret[0] = sym.st_value;
@@ -332,7 +338,7 @@
GELF_ST_INFO(STB_LOCAL, STT_FUNC);
sym.st_other = 0;
sym.st_value = 0;
-#if defined(sun)
+#ifdef illumos
sym.st_size = Pstatus(pp->dpp_pr)->pr_dmodel ==
PR_MODEL_ILP32 ? -1U : -1ULL;
#else
@@ -399,7 +405,7 @@
if (gmatch(obj, pp->dpp_mod))
return (dt_pid_per_mod(pp, pmp, obj));
-#if defined(sun)
+#ifdef illumos
(void) Plmid(pp->dpp_pr, pmp->pr_vaddr, &pp->dpp_lmid);
#else
pp->dpp_lmid = 0;
@@ -413,7 +419,7 @@
if (gmatch(pp->dpp_obj, pp->dpp_mod))
return (dt_pid_per_mod(pp, pmp, obj));
-#if defined(sun)
+#ifdef illumos
(void) Plmid(pp->dpp_pr, pmp->pr_vaddr, &pp->dpp_lmid);
#endif
@@ -429,7 +435,7 @@
dt_pid_fix_mod(dtrace_probedesc_t *pdp, struct ps_prochandle *P)
{
char m[MAXPATHLEN];
-#if defined(sun)
+#ifdef illumos
Lmid_t lmid = PR_LMID_EVERY;
#else
Lmid_t lmid = 0;
@@ -437,7 +443,7 @@
const char *obj;
const prmap_t *pmp;
-#if defined(sun)
+#ifdef illumos
/*
* Pick apart the link map from the library name.
*/
@@ -465,7 +471,7 @@
if ((pmp = Plmid_to_map(P, lmid, obj)) == NULL)
return (NULL);
-#if defined(sun)
+#ifdef illumos
(void) Pobjname(P, pmp->pr_vaddr, m, sizeof (m));
if ((obj = strrchr(m, '/')) == NULL)
obj = &m[0];
@@ -566,7 +572,7 @@
{
struct ps_prochandle *P = data;
GElf_Sym sym;
-#if defined(sun)
+#ifdef illumos
prsyminfo_t sip;
#endif
dof_helper_t dh;
@@ -604,13 +610,13 @@
dh.dofhp_addr = (e_type == ET_EXEC) ? 0 : pmp->pr_vaddr;
dt_pid_objname(dh.dofhp_mod, sizeof (dh.dofhp_mod),
-#if defined(sun)
+#ifdef illumos
sip.prs_lmid, mname);
#else
0, mname);
#endif
-#if defined(sun)
+#ifdef illumos
if (fd == -1 &&
(fd = pr_open(P, "/dev/dtrace/helper", O_RDWR, 0)) < 0) {
dt_dprintf("pr_open of helper device failed: %s\n",
@@ -623,7 +629,7 @@
#endif
}
-#if defined(sun)
+#ifdef illumos
if (fd != -1)
(void) pr_close(P, fd);
#endif
@@ -639,13 +645,13 @@
int ret = 0;
assert(DT_MUTEX_HELD(&dpr->dpr_lock));
-#if defined(sun)
+#ifdef illumos
(void) Pupdate_maps(P);
if (Pobject_iter(P, dt_pid_usdt_mapping, P) != 0) {
ret = -1;
(void) dt_pid_error(dtp, pcb, dpr, NULL, D_PROC_USDT,
"failed to instantiate probes for pid %d: %s",
-#if defined(sun)
+#ifdef illumos
(int)Pstatus(P)->pr_pid, strerror(errno));
#else
(int)proc_getpid(P), strerror(errno));
@@ -827,3 +833,170 @@
return (ret);
}
+
+/*
+ * libdtrace has a backroom deal with us to ask us for type information on
+ * behalf of pid provider probes when fasttrap doesn't return any type
+ * information. Instead we'll look up the module and see if there is type
+ * information available. However, if there is no type information available due
+ * to a lack of CTF data, then we want to make sure that DTrace still carries on
+ * in face of that. As such we don't have a meaningful exit code about failure.
+ * We emit information about why we failed to the dtrace debug log so someone
+ * can figure it out by asking nicely for DTRACE_DEBUG.
+ */
+void
+dt_pid_get_types(dtrace_hdl_t *dtp, const dtrace_probedesc_t *pdp,
+ dtrace_argdesc_t *adp, int *nargs)
+{
+ dt_module_t *dmp;
+ ctf_file_t *fp;
+ ctf_funcinfo_t f;
+ ctf_id_t argv[32];
+ GElf_Sym sym;
+#ifdef illumos
+ prsyminfo_t si;
+#else
+ void *si;
+#endif
+ struct ps_prochandle *p;
+ int i, args;
+ char buf[DTRACE_ARGTYPELEN];
+ const char *mptr;
+ char *eptr;
+ int ret = 0;
+ int argc = sizeof (argv) / sizeof (ctf_id_t);
+ Lmid_t lmid;
+
+ /* Set up a potential outcome */
+ args = *nargs;
+ *nargs = 0;
+
+ /*
+ * If we don't have an entry or return probe then we can just stop right
+ * now as we don't have arguments for offset probes.
+ */
+ if (strcmp(pdp->dtpd_name, "entry") != 0 &&
+ strcmp(pdp->dtpd_name, "return") != 0)
+ return;
+
+ dmp = dt_module_create(dtp, pdp->dtpd_provider);
+ if (dmp == NULL) {
+ dt_dprintf("failed to find module for %s\n",
+ pdp->dtpd_provider);
+ return;
+ }
+ if (dt_module_load(dtp, dmp) != 0) {
+ dt_dprintf("failed to load module for %s\n",
+ pdp->dtpd_provider);
+ return;
+ }
+
+ /*
+ * We may be working with a module that doesn't have ctf. If that's the
+ * case then we just return now and move on with life.
+ */
+ fp = dt_module_getctflib(dtp, dmp, pdp->dtpd_mod);
+ if (fp == NULL) {
+ dt_dprintf("no ctf container for %s\n",
+ pdp->dtpd_mod);
+ return;
+ }
+ p = dt_proc_grab(dtp, dmp->dm_pid, 0, PGRAB_RDONLY | PGRAB_FORCE);
+ if (p == NULL) {
+ dt_dprintf("failed to grab pid\n");
+ return;
+ }
+ dt_proc_lock(dtp, p);
+
+ /*
+ * Check to see if the D module has a link map ID and separate that out
+ * for properly interrogating libproc.
+ */
+ if ((mptr = strchr(pdp->dtpd_mod, '`')) != NULL) {
+ if (strlen(pdp->dtpd_mod) < 3) {
+ dt_dprintf("found weird modname with linkmap, "
+ "aborting: %s\n", pdp->dtpd_mod);
+ goto out;
+ }
+ if (pdp->dtpd_mod[0] != 'L' || pdp->dtpd_mod[1] != 'M') {
+ dt_dprintf("missing leading 'LM', "
+ "aborting: %s\n", pdp->dtpd_mod);
+ goto out;
+ }
+ errno = 0;
+ lmid = strtol(pdp->dtpd_mod + 2, &eptr, 16);
+ if (errno == ERANGE || eptr != mptr) {
+ dt_dprintf("failed to parse out lmid, aborting: %s\n",
+ pdp->dtpd_mod);
+ goto out;
+ }
+ mptr++;
+ } else {
+ mptr = pdp->dtpd_mod;
+ lmid = 0;
+ }
+
+ if (Pxlookup_by_name(p, lmid, mptr, pdp->dtpd_func,
+ &sym, &si) != 0) {
+ dt_dprintf("failed to find function %s in %s`%s\n",
+ pdp->dtpd_func, pdp->dtpd_provider, pdp->dtpd_mod);
+ goto out;
+ }
+#ifdef illumos
+ if (ctf_func_info(fp, si.prs_id, &f) == CTF_ERR) {
+ dt_dprintf("failed to get ctf information for %s in %s`%s\n",
+ pdp->dtpd_func, pdp->dtpd_provider, pdp->dtpd_mod);
+ goto out;
+ }
+#endif
+
+ (void) snprintf(buf, sizeof (buf), "%s`%s", pdp->dtpd_provider,
+ pdp->dtpd_mod);
+
+ if (strcmp(pdp->dtpd_name, "return") == 0) {
+ if (args < 2)
+ goto out;
+
+ bzero(adp, sizeof (dtrace_argdesc_t));
+ adp->dtargd_ndx = 0;
+ adp->dtargd_id = pdp->dtpd_id;
+ adp->dtargd_mapping = adp->dtargd_ndx;
+ /*
+ * We explicitly leave out the library here, we only care that
+ * it is some int. We are assuming that there is no ctf
+ * container in here that is lying about what an int is.
+ */
+ (void) snprintf(adp->dtargd_native, DTRACE_ARGTYPELEN,
+ "user %s`%s", pdp->dtpd_provider, "int");
+ adp++;
+ bzero(adp, sizeof (dtrace_argdesc_t));
+ adp->dtargd_ndx = 1;
+ adp->dtargd_id = pdp->dtpd_id;
+ adp->dtargd_mapping = adp->dtargd_ndx;
+ ret = snprintf(adp->dtargd_native, DTRACE_ARGTYPELEN,
+ "userland ");
+ (void) ctf_type_qname(fp, f.ctc_return, adp->dtargd_native +
+ ret, DTRACE_ARGTYPELEN - ret, buf);
+ *nargs = 2;
+#ifdef illumos
+ } else {
+ if (ctf_func_args(fp, si.prs_id, argc, argv) == CTF_ERR)
+ goto out;
+
+ *nargs = MIN(args, f.ctc_argc);
+ for (i = 0; i < *nargs; i++, adp++) {
+ bzero(adp, sizeof (dtrace_argdesc_t));
+ adp->dtargd_ndx = i;
+ adp->dtargd_id = pdp->dtpd_id;
+ adp->dtargd_mapping = adp->dtargd_ndx;
+ ret = snprintf(adp->dtargd_native, DTRACE_ARGTYPELEN,
+ "userland ");
+ (void) ctf_type_qname(fp, argv[i], adp->dtargd_native +
+ ret, DTRACE_ARGTYPELEN - ret, buf);
+ }
+#endif
+ }
+out:
+ dt_proc_unlock(dtp, p);
+ dt_proc_release(dtp, p);
+}
Modified: trunk/cddl/contrib/opensolaris/lib/libdtrace/common/dt_pid.h
===================================================================
--- trunk/cddl/contrib/opensolaris/lib/libdtrace/common/dt_pid.h 2018-06-02 16:07:17 UTC (rev 10228)
+++ trunk/cddl/contrib/opensolaris/lib/libdtrace/common/dt_pid.h 2018-06-02 16:07:30 UTC (rev 10229)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*
* CDDL HEADER START
*
@@ -24,12 +25,13 @@
* Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
+/*
+ * Copyright (c) 2013, Joyent, Inc. All rights reserved.
+ */
#ifndef _DT_PID_H
#define _DT_PID_H
-#pragma ident "%Z%%M% %I% %E% SMI"
-
#include <libproc.h>
#include <sys/fasttrap.h>
#include <dt_impl.h>
@@ -57,6 +59,9 @@
extern int dt_pid_create_glob_offset_probes(struct ps_prochandle *,
dtrace_hdl_t *, fasttrap_probe_spec_t *, const GElf_Sym *, const char *);
+extern void dt_pid_get_types(dtrace_hdl_t *, const dtrace_probedesc_t *,
+ dtrace_argdesc_t *, int *);
+
#ifdef __cplusplus
}
#endif
Added: trunk/cddl/contrib/opensolaris/lib/libdtrace/common/dt_pq.c
===================================================================
--- trunk/cddl/contrib/opensolaris/lib/libdtrace/common/dt_pq.c (rev 0)
+++ trunk/cddl/contrib/opensolaris/lib/libdtrace/common/dt_pq.c 2018-06-02 16:07:30 UTC (rev 10229)
@@ -0,0 +1,158 @@
+/* $MidnightBSD$ */
+/*
+ * CDDL HEADER START
+ *
+ * This file and its contents are supplied under the terms of the
+ * Common Development and Distribution License ("CDDL"), version 1.0.
+ * You may only use this file in accordance with the terms of version
+ * 1.0 of the CDDL.
+ *
+ * A full copy of the text of the CDDL should have accompanied this
+ * source. A copy of the CDDL is also available via the Internet at
+ * http://www.illumos.org/license/CDDL.
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright (c) 2012 by Delphix. All rights reserved.
+ */
+
+#include <dtrace.h>
+#include <dt_impl.h>
+#include <dt_pq.h>
+#include <assert.h>
+
+/*
+ * Create a new priority queue.
+ *
+ * size is the maximum number of items that will be stored in the priority
+ * queue at one time.
+ */
+dt_pq_t *
+dt_pq_init(dtrace_hdl_t *dtp, uint_t size, dt_pq_value_f value_cb, void *cb_arg)
+{
+ dt_pq_t *p;
+ assert(size > 1);
+
+ if ((p = dt_zalloc(dtp, sizeof (dt_pq_t))) == NULL)
+ return (NULL);
+
+ p->dtpq_items = dt_zalloc(dtp, size * sizeof (p->dtpq_items[0]));
+ if (p->dtpq_items == NULL) {
+ dt_free(dtp, p);
+ return (NULL);
+ }
+
+ p->dtpq_hdl = dtp;
+ p->dtpq_size = size;
+ p->dtpq_last = 1;
+ p->dtpq_value = value_cb;
+ p->dtpq_arg = cb_arg;
+
+ return (p);
+}
+
+void
+dt_pq_fini(dt_pq_t *p)
+{
+ dtrace_hdl_t *dtp = p->dtpq_hdl;
+
+ dt_free(dtp, p->dtpq_items);
+ dt_free(dtp, p);
+}
+
+static uint64_t
+dt_pq_getvalue(dt_pq_t *p, uint_t index)
+{
+ void *item = p->dtpq_items[index];
+ return (p->dtpq_value(item, p->dtpq_arg));
+}
+
+void
+dt_pq_insert(dt_pq_t *p, void *item)
+{
+ uint_t i;
+
+ assert(p->dtpq_last < p->dtpq_size);
+
+ i = p->dtpq_last++;
+ p->dtpq_items[i] = item;
+
+ while (i > 1 && dt_pq_getvalue(p, i) < dt_pq_getvalue(p, i / 2)) {
+ void *tmp = p->dtpq_items[i];
+ p->dtpq_items[i] = p->dtpq_items[i / 2];
+ p->dtpq_items[i / 2] = tmp;
+ i /= 2;
+ }
+}
+
+/*
+ * Return elements from the priority queue. *cookie should be zero when first
+ * called. Returns NULL when there are no more elements.
+ */
+void *
+dt_pq_walk(dt_pq_t *p, uint_t *cookie)
+{
+ (*cookie)++;
+ if (*cookie >= p->dtpq_last)
+ return (NULL);
+
+ return (p->dtpq_items[*cookie]);
+}
+
+void *
+dt_pq_pop(dt_pq_t *p)
+{
+ uint_t i = 1;
+ void *ret;
+
+ assert(p->dtpq_last > 0);
+
+ if (p->dtpq_last == 1)
+ return (NULL);
+
+ ret = p->dtpq_items[1];
+
+ p->dtpq_last--;
+ p->dtpq_items[1] = p->dtpq_items[p->dtpq_last];
+ p->dtpq_items[p->dtpq_last] = NULL;
+
+ for (;;) {
+ uint_t lc = i * 2;
+ uint_t rc = i * 2 + 1;
+ uint_t c;
+ uint64_t v;
+ void *tmp;
+
+ if (lc >= p->dtpq_last)
+ break;
+
+ if (rc >= p->dtpq_last) {
+ c = lc;
+ v = dt_pq_getvalue(p, lc);
+ } else {
+ uint64_t lv = dt_pq_getvalue(p, lc);
+ uint64_t rv = dt_pq_getvalue(p, rc);
+
+ if (lv < rv) {
+ c = lc;
+ v = lv;
+ } else {
+ c = rc;
+ v = rv;
+ }
+ }
+
+ if (v >= dt_pq_getvalue(p, i))
+ break;
+
+ tmp = p->dtpq_items[i];
+ p->dtpq_items[i] = p->dtpq_items[c];
+ p->dtpq_items[c] = tmp;
+
+ i = c;
+ }
+
+ return (ret);
+}
Property changes on: trunk/cddl/contrib/opensolaris/lib/libdtrace/common/dt_pq.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/cddl/contrib/opensolaris/lib/libdtrace/common/dt_pq.h
===================================================================
--- trunk/cddl/contrib/opensolaris/lib/libdtrace/common/dt_pq.h (rev 0)
+++ trunk/cddl/contrib/opensolaris/lib/libdtrace/common/dt_pq.h 2018-06-02 16:07:30 UTC (rev 10229)
@@ -0,0 +1,52 @@
+/* $MidnightBSD$ */
+/*
+ * CDDL HEADER START
+ *
+ * This file and its contents are supplied under the terms of the
+ * Common Development and Distribution License ("CDDL"), version 1.0.
+ * You may only use this file in accordance with the terms of version
+ * 1.0 of the CDDL.
+ *
+ * A full copy of the text of the CDDL should have accompanied this
+ * source. A copy of the CDDL is also available via the Internet at
+ * http://www.illumos.org/license/CDDL.
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright (c) 2012 by Delphix. All rights reserved.
+ */
+
+#ifndef _DT_PQ_H
+#define _DT_PQ_H
+
+#include <dtrace.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef uint64_t (*dt_pq_value_f)(void *, void *);
+
+typedef struct dt_pq {
+ dtrace_hdl_t *dtpq_hdl; /* dtrace handle */
+ void **dtpq_items; /* array of elements */
+ uint_t dtpq_size; /* count of allocated elements */
+ uint_t dtpq_last; /* next free slot */
+ dt_pq_value_f dtpq_value; /* callback to get the value */
+ void *dtpq_arg; /* callback argument */
+} dt_pq_t;
+
+extern dt_pq_t *dt_pq_init(dtrace_hdl_t *, uint_t size, dt_pq_value_f, void *);
+extern void dt_pq_fini(dt_pq_t *);
+
+extern void dt_pq_insert(dt_pq_t *, void *);
+extern void *dt_pq_pop(dt_pq_t *);
+extern void *dt_pq_walk(dt_pq_t *, uint_t *);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _DT_PQ_H */
Property changes on: trunk/cddl/contrib/opensolaris/lib/libdtrace/common/dt_pq.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Modified: trunk/cddl/contrib/opensolaris/lib/libdtrace/common/dt_pragma.c
===================================================================
--- trunk/cddl/contrib/opensolaris/lib/libdtrace/common/dt_pragma.c 2018-06-02 16:07:17 UTC (rev 10228)
+++ trunk/cddl/contrib/opensolaris/lib/libdtrace/common/dt_pragma.c 2018-06-02 16:07:30 UTC (rev 10229)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*
* CDDL HEADER START
*
@@ -28,7 +29,7 @@
#include <assert.h>
#include <strings.h>
-#if defined(sun)
+#ifdef illumos
#include <alloca.h>
#endif
#include <fcntl.h>
Modified: trunk/cddl/contrib/opensolaris/lib/libdtrace/common/dt_print.c
===================================================================
--- trunk/cddl/contrib/opensolaris/lib/libdtrace/common/dt_print.c 2018-06-02 16:07:17 UTC (rev 10228)
+++ trunk/cddl/contrib/opensolaris/lib/libdtrace/common/dt_print.c 2018-06-02 16:07:30 UTC (rev 10229)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*
* CDDL HEADER START
*
@@ -167,7 +168,7 @@
* to the lowest 'size' bytes in 'value', and we need to shift based on
* the offset from the end of the data, not the offset of the start.
*/
-#ifdef _BIG_ENDIAN
+#if BYTE_ORDER == _BIG_ENDIAN
buf += sizeof (value) - size;
off += ep->cte_bits;
#endif
@@ -178,7 +179,7 @@
* Offsets are counted from opposite ends on little- and
* big-endian machines.
*/
-#ifdef _BIG_ENDIAN
+#if BYTE_ORDER == _BIG_ENDIAN
shift = NBBY - shift;
#endif
@@ -647,12 +648,16 @@
dt_printarg_t pa;
ctf_id_t id;
dt_module_t *dmp;
+ ctf_file_t *ctfp;
+ int libid;
/*
* Split the fully-qualified type ID (module`id). This should
* always be the format, but if for some reason we don't find the
* expected value, return 0 to fall back to the generic trace()
- * behavior.
+ * behavior. In the case of userland CTF modules this will actually be
+ * of the format (module`lib`id). This is due to the fact that those
+ * modules have multiple CTF containers which `lib` identifies.
*/
for (s = typename; *s != '\0' && *s != '`'; s++)
;
@@ -663,6 +668,20 @@
object = alloca(s - typename + 1);
bcopy(typename, object, s - typename);
object[s - typename] = '\0';
+ dmp = dt_module_lookup_by_name(dtp, object);
+ if (dmp == NULL)
+ return (0);
+
+ if (dmp->dm_pid != 0) {
+ libid = atoi(s + 1);
+ s = strchr(s + 1, '`');
+ if (s == NULL || libid > dmp->dm_nctflibs)
+ return (0);
+ ctfp = dmp->dm_libctfp[libid];
+ } else {
+ ctfp = dt_module_getctf(dtp, dmp);
+ }
+
id = atoi(s + 1);
/*
@@ -670,16 +689,13 @@
* wrong and we can't resolve the ID, bail out and let trace() do the
* work.
*/
- dmp = dt_module_lookup_by_name(dtp, object);
- if (dmp == NULL || ctf_type_kind(dt_module_getctf(dtp, dmp),
- id) == CTF_ERR) {
+ if (ctfp == NULL || ctf_type_kind(ctfp, id) == CTF_ERR)
return (0);
- }
/* setup the print structure and kick off the main print routine */
pa.pa_dtp = dtp;
pa.pa_addr = addr;
- pa.pa_ctfp = dt_module_getctf(dtp, dmp);
+ pa.pa_ctfp = ctfp;
pa.pa_nest = 0;
pa.pa_depth = 0;
pa.pa_file = fp;
Modified: trunk/cddl/contrib/opensolaris/lib/libdtrace/common/dt_printf.c
===================================================================
--- trunk/cddl/contrib/opensolaris/lib/libdtrace/common/dt_printf.c 2018-06-02 16:07:17 UTC (rev 10228)
+++ trunk/cddl/contrib/opensolaris/lib/libdtrace/common/dt_printf.c 2018-06-02 16:07:30 UTC (rev 10229)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*
* CDDL HEADER START
*
@@ -21,10 +22,11 @@
/*
* Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2011, Joyent, Inc. All rights reserved.
+ * Copyright (c) 2013, Joyent, Inc. All rights reserved.
+ * Copyright (c) 2013 by Delphix. All rights reserved.
*/
-#if defined(sun)
+#ifdef illumos
#include <sys/sysmacros.h>
#else
#define ABS(a) ((a) < 0 ? -(a) : (a))
@@ -32,7 +34,7 @@
#include <string.h>
#include <strings.h>
#include <stdlib.h>
-#if defined(sun)
+#ifdef illumos
#include <alloca.h>
#endif
#include <assert.h>
@@ -161,7 +163,7 @@
pfcheck_dint(dt_pfargv_t *pfv, dt_pfargd_t *pfd, dt_node_t *dnp)
{
if (dnp->dn_flags & DT_NF_SIGNED)
- pfd->pfd_flags |= DT_PFCONV_SIGNED;
+ pfd->pfd_fmt[strlen(pfd->pfd_fmt) - 1] = 'i';
else
pfd->pfd_fmt[strlen(pfd->pfd_fmt) - 1] = 'u';
@@ -466,7 +468,7 @@
* Below, we turn this into the canonical adb/mdb /[yY] format,
* "1973 Dec 3 17:20:00".
*/
-#if defined(sun)
+#ifdef illumos
(void) ctime_r(&sec, src, sizeof (src));
#else
(void) ctime_r(&sec, src);
@@ -517,7 +519,7 @@
char buf[256];
struct servent *sv, res;
-#if defined(sun)
+#ifdef illumos
if ((sv = getservbyport_r(port, NULL, &res, buf, sizeof (buf))) != NULL)
#else
if (getservbyport_r(port, NULL, &res, buf, sizeof (buf), &sv) > 0)
@@ -543,7 +545,7 @@
s[size] = '\0';
if (strchr(s, ':') == NULL && inet_pton(AF_INET, s, inetaddr) != -1) {
-#if defined(sun)
+#ifdef illumos
if ((host = gethostbyaddr_r(inetaddr, NS_INADDRSZ,
AF_INET, &res, buf, sizeof (buf), &e)) != NULL)
#else
@@ -664,7 +666,7 @@
{ "hu", "u", "unsigned short", pfcheck_type, pfprint_uint },
{ "hx", "x", "short", pfcheck_xshort, pfprint_uint },
{ "hX", "X", "short", pfcheck_xshort, pfprint_uint },
-{ "i", "i", pfproto_xint, pfcheck_dint, pfprint_dint },
+{ "i", "i", pfproto_xint, pfcheck_xint, pfprint_sint },
{ "I", "s", pfproto_cstr, pfcheck_str, pfprint_inetaddr },
{ "k", "s", "stack", pfcheck_stack, pfprint_stack },
{ "lc", "lc", "int", pfcheck_type, pfprint_sint }, /* a.k.a. wint_t */
@@ -693,8 +695,13 @@
{ "S", "s", pfproto_cstr, pfcheck_str, pfprint_estr },
{ "T", "s", "int64_t", pfcheck_time, pfprint_time822 },
{ "u", "u", pfproto_xint, pfcheck_xint, pfprint_uint },
+#ifdef illumos
{ "wc", "wc", "int", pfcheck_type, pfprint_sint }, /* a.k.a. wchar_t */
{ "ws", "ws", pfproto_wstr, pfcheck_wstr, pfprint_wstr },
+#else
+{ "wc", "lc", "int", pfcheck_type, pfprint_sint }, /* a.k.a. wchar_t */
+{ "ws", "ls", pfproto_wstr, pfcheck_wstr, pfprint_wstr },
+#endif
{ "x", "x", pfproto_xint, pfcheck_xint, pfprint_uint },
{ "X", "X", pfproto_xint, pfcheck_xint, pfprint_uint },
{ "Y", "s", "int64_t", pfcheck_time, pfprint_time },
@@ -1069,7 +1076,7 @@
xyerror(D_TYPE_ERR, "failed to lookup agg type %s\n", aggtype);
bzero(&aggnode, sizeof (aggnode));
- dt_node_type_assign(&aggnode, dtt.dtt_ctfp, dtt.dtt_type);
+ dt_node_type_assign(&aggnode, dtt.dtt_ctfp, dtt.dtt_type, B_FALSE);
for (i = 0, j = 0; i < pfv->pfv_argc; i++, pfd = pfd->pfd_next) {
const dt_pfconv_t *pfc = pfd->pfd_conv;
@@ -1342,6 +1349,7 @@
dtrace_aggdesc_t *agg;
caddr_t lim = (caddr_t)buf + len, limit;
char format[64] = "%";
+ size_t ret;
int i, aggrec, curagg = -1;
uint64_t normal;
@@ -1373,7 +1381,9 @@
int prec = pfd->pfd_prec;
int rval;
+ const char *start;
char *f = format + 1; /* skip initial '%' */
+ size_t fmtsz = sizeof(format) - 1;
const dtrace_recdesc_t *rec;
dt_pfprint_f *func;
caddr_t addr;
@@ -1530,6 +1540,7 @@
break;
}
+ start = f;
if (pfd->pfd_flags & DT_PFCONV_ALT)
*f++ = '#';
if (pfd->pfd_flags & DT_PFCONV_ZPAD)
@@ -1542,6 +1553,7 @@
*f++ = '\'';
if (pfd->pfd_flags & DT_PFCONV_SPACE)
*f++ = ' ';
+ fmtsz -= f - start;
/*
* If we're printing a stack and DT_PFCONV_LEFT is set, we
@@ -1552,13 +1564,20 @@
if (func == pfprint_stack && (pfd->pfd_flags & DT_PFCONV_LEFT))
width = 0;
- if (width != 0)
- f += snprintf(f, sizeof (format), "%d", ABS(width));
+ if (width != 0) {
+ ret = snprintf(f, fmtsz, "%d", ABS(width));
+ f += ret;
+ fmtsz = MAX(0, fmtsz - ret);
+ }
- if (prec > 0)
- f += snprintf(f, sizeof (format), ".%d", prec);
+ if (prec > 0) {
+ ret = snprintf(f, fmtsz, ".%d", prec);
+ f += ret;
+ fmtsz = MAX(0, fmtsz - ret);
+ }
- (void) strcpy(f, pfd->pfd_fmt);
+ if (strlcpy(f, pfd->pfd_fmt, fmtsz) >= fmtsz)
+ return (dt_set_errno(dtp, EDT_COMPILER));
pfd->pfd_rec = rec;
if (func(dtp, fp, format, pfd, addr, size, normal) < 0)
@@ -1651,7 +1670,7 @@
if (rval == -1 || fp == NULL)
return (rval);
-#if defined(sun)
+#ifdef illumos
if (pfd->pfd_preflen != 0 &&
strcmp(pfd->pfd_prefix, DT_FREOPEN_RESTORE) == 0) {
/*
@@ -1733,7 +1752,7 @@
}
(void) fclose(nfp);
-#else
+#else /* !illumos */
/*
* The 'standard output' (which is not necessarily stdout)
* treatment on FreeBSD is implemented differently than on
@@ -1808,7 +1827,7 @@
/* Remember that the output has been redirected to the new file. */
dtp->dt_freopen_fp = nfp;
-#endif
+#endif /* illumos */
return (rval);
}
Modified: trunk/cddl/contrib/opensolaris/lib/libdtrace/common/dt_printf.h
===================================================================
--- trunk/cddl/contrib/opensolaris/lib/libdtrace/common/dt_printf.h 2018-06-02 16:07:17 UTC (rev 10228)
+++ trunk/cddl/contrib/opensolaris/lib/libdtrace/common/dt_printf.h 2018-06-02 16:07:30 UTC (rev 10229)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*
* CDDL HEADER START
*
Modified: trunk/cddl/contrib/opensolaris/lib/libdtrace/common/dt_proc.c
===================================================================
--- trunk/cddl/contrib/opensolaris/lib/libdtrace/common/dt_proc.c 2018-06-02 16:07:17 UTC (rev 10228)
+++ trunk/cddl/contrib/opensolaris/lib/libdtrace/common/dt_proc.c 2018-06-02 16:07:30 UTC (rev 10229)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*
* CDDL HEADER START
*
@@ -77,7 +78,7 @@
*/
#include <sys/wait.h>
-#if defined(sun)
+#ifdef illumos
#include <sys/lwp.h>
#endif
#include <strings.h>
@@ -89,7 +90,7 @@
#include <dt_pid.h>
#include <dt_impl.h>
-#if !defined(sun)
+#ifndef illumos
#include <sys/syscall.h>
#include <libproc_compat.h>
#define SYS_forksys SYS_fork
@@ -143,7 +144,7 @@
static void
dt_proc_bpmatch(dtrace_hdl_t *dtp, dt_proc_t *dpr)
{
-#if defined(sun)
+#ifdef illumos
const lwpstatus_t *psp = &Pstatus(dpr->dpr_proc)->pr_lwp;
#else
unsigned long pc;
@@ -152,7 +153,7 @@
assert(DT_MUTEX_HELD(&dpr->dpr_lock));
-#if !defined(sun)
+#ifndef illumos
proc_regget(dpr->dpr_proc, REG_PC, &pc);
proc_bkptregadj(&pc);
#endif
@@ -159,7 +160,7 @@
for (dbp = dt_list_next(&dpr->dpr_bps);
dbp != NULL; dbp = dt_list_next(dbp)) {
-#if defined(sun)
+#ifdef illumos
if (psp->pr_reg[R_PC] == dbp->dbp_addr)
break;
#else
@@ -170,7 +171,7 @@
if (dbp == NULL) {
dt_dprintf("pid %d: spurious breakpoint wakeup for %lx\n",
-#if defined(sun)
+#ifdef illumos
(int)dpr->dpr_pid, (ulong_t)psp->pr_reg[R_PC]);
#else
(int)dpr->dpr_pid, pc);
@@ -342,7 +343,7 @@
}
(void) dt_proc_bpcreate(dpr, rdn.u.bptaddr,
-#if defined(sun)
+#ifdef illumos
(dt_bkpt_f *)dt_proc_rdevent, (void *)evname);
#else
/* XXX ugly */
@@ -357,7 +358,7 @@
static void
dt_proc_attach(dt_proc_t *dpr, int exec)
{
-#if defined(sun)
+#ifdef illumos
const pstatus_t *psp = Pstatus(dpr->dpr_proc);
#endif
rd_err_e err;
@@ -366,23 +367,23 @@
assert(DT_MUTEX_HELD(&dpr->dpr_lock));
if (exec) {
-#if defined(sun)
+#ifdef illumos
if (psp->pr_lwp.pr_errno != 0)
return; /* exec failed: nothing needs to be done */
#endif
dt_proc_bpdestroy(dpr, B_FALSE);
-#if defined(sun)
+#ifdef illumos
Preset_maps(dpr->dpr_proc);
#endif
}
if ((dpr->dpr_rtld = Prd_agent(dpr->dpr_proc)) != NULL &&
(err = rd_event_enable(dpr->dpr_rtld, B_TRUE)) == RD_OK) {
-#if defined(sun)
+#ifdef illumos
dt_proc_rdwatch(dpr, RD_PREINIT, "RD_PREINIT");
#endif
dt_proc_rdwatch(dpr, RD_POSTINIT, "RD_POSTINIT");
-#if defined(sun)
+#ifdef illumos
dt_proc_rdwatch(dpr, RD_DLACTIVITY, "RD_DLACTIVITY");
#endif
} else {
@@ -507,7 +508,7 @@
struct ps_prochandle *P = dpr->dpr_proc;
int pid = dpr->dpr_pid;
-#if defined(sun)
+#ifdef illumos
int pfd = Pctlfd(P);
const long wstop = PCWSTOP;
@@ -529,7 +530,7 @@
*/
(void) pthread_mutex_lock(&dpr->dpr_lock);
-#if defined(sun)
+#ifdef illumos
(void) Punsetflags(P, PR_ASYNC); /* require synchronous mode */
(void) Psetflags(P, PR_BPTADJ); /* always adjust eip on x86 */
(void) Punsetflags(P, PR_FORK); /* do not inherit on fork */
@@ -562,7 +563,7 @@
* If PR_KLC is set, we created the process; otherwise we grabbed it.
* Check for an appropriate stop request and wait for dt_proc_continue.
*/
-#if defined(sun)
+#ifdef illumos
if (Pstatus(P)->pr_flags & PR_KLC)
#else
if (proc_getflags(P) & PR_KLC)
@@ -590,7 +591,7 @@
while (!dpr->dpr_quit) {
const lwpstatus_t *psp;
-#if defined(sun)
+#ifdef illumos
if (write(pfd, &wstop, sizeof (wstop)) == -1 && errno == EINTR)
continue; /* check dpr_quit and continue waiting */
#else
@@ -602,7 +603,7 @@
(void) pthread_mutex_lock(&dpr->dpr_lock);
-#if defined(sun)
+#ifdef illumos
pwait_locked:
if (Pstopstatus(P, PCNULL, 0) == -1 && errno == EINTR) {
(void) pthread_mutex_unlock(&dpr->dpr_lock);
@@ -612,7 +613,7 @@
switch (Pstate(P)) {
case PS_STOP:
-#if defined(sun)
+#ifdef illumos
psp = &Pstatus(P)->pr_lwp;
#else
psp = proc_getlwpstatus(P);
@@ -661,7 +662,7 @@
break;
case PS_LOST:
-#if defined(sun)
+#ifdef illumos
if (Preopen(P) == 0)
goto pwait_locked;
#endif
@@ -734,7 +735,7 @@
dt_proc_lookup(dtrace_hdl_t *dtp, struct ps_prochandle *P, int remove)
{
dt_proc_hash_t *dph = dtp->dt_procs;
-#if defined(sun)
+#ifdef illumos
pid_t pid = Pstatus(P)->pr_pid;
#else
pid_t pid = proc_getpid(P);
@@ -772,7 +773,7 @@
* an external debugger and we were waiting in dt_proc_waitrun().
* Leave the process in this condition using PRELEASE_HANG.
*/
-#if defined(sun)
+#ifdef illumos
if (!(Pstatus(dpr->dpr_proc)->pr_flags & (PR_KLC | PR_RLC))) {
#else
if (!(proc_getflags(dpr->dpr_proc) & (PR_KLC | PR_RLC))) {
@@ -779,7 +780,7 @@
#endif
dt_dprintf("abandoning pid %d\n", (int)dpr->dpr_pid);
rflag = PRELEASE_HANG;
-#if defined(sun)
+#ifdef illumos
} else if (Pstatus(dpr->dpr_proc)->pr_flags & PR_KLC) {
#else
} else if (proc_getflags(dpr->dpr_proc) & PR_KLC) {
@@ -808,7 +809,7 @@
*/
(void) pthread_mutex_lock(&dpr->dpr_lock);
dpr->dpr_quit = B_TRUE;
-#if defined(sun)
+#ifdef illumos
(void) _lwp_kill(dpr->dpr_tid, SIGCANCEL);
#else
pthread_kill(dpr->dpr_tid, SIGTHR);
@@ -880,7 +881,7 @@
(void) sigfillset(&nset);
(void) sigdelset(&nset, SIGABRT); /* unblocked for assert() */
-#if defined(sun)
+#ifdef illumos
(void) sigdelset(&nset, SIGCANCEL); /* see dt_proc_destroy() */
#else
(void) sigdelset(&nset, SIGUSR1); /* see dt_proc_destroy() */
@@ -912,7 +913,7 @@
* small amount of useful information to help figure it out.
*/
if (dpr->dpr_done) {
-#if defined(sun)
+#ifdef illumos
const psinfo_t *prp = Ppsinfo(dpr->dpr_proc);
int stat = prp ? prp->pr_wstat : 0;
int pid = dpr->dpr_pid;
@@ -963,7 +964,7 @@
(void) pthread_mutex_init(&dpr->dpr_lock, NULL);
(void) pthread_cond_init(&dpr->dpr_cv, NULL);
-#if defined(sun)
+#ifdef illumos
if ((dpr->dpr_proc = Pcreate(file, argv, &err, NULL, 0)) == NULL) {
#else
if ((err = proc_create(file, argv, pcf, child_arg,
@@ -974,7 +975,7 @@
}
dpr->dpr_hdl = dtp;
-#if defined(sun)
+#ifdef illumos
dpr->dpr_pid = Pstatus(dpr->dpr_proc)->pr_pid;
#else
dpr->dpr_pid = proc_getpid(dpr->dpr_proc);
@@ -1039,7 +1040,7 @@
(void) pthread_mutex_init(&dpr->dpr_lock, NULL);
(void) pthread_cond_init(&dpr->dpr_cv, NULL);
-#if defined(sun)
+#ifdef illumos
if ((dpr->dpr_proc = Pgrab(pid, flags, &err)) == NULL) {
#else
if ((err = proc_attach(pid, flags, &dpr->dpr_proc)) != 0) {
@@ -1174,7 +1175,7 @@
struct ps_prochandle *P = dt_proc_create(dtp, file, argv, pcf, child_arg);
if (P != NULL && idp != NULL && idp->di_id == 0) {
-#if defined(sun)
+#ifdef illumos
idp->di_id = Pstatus(P)->pr_pid; /* $target = created pid */
#else
idp->di_id = proc_getpid(P); /* $target = created pid */
Modified: trunk/cddl/contrib/opensolaris/lib/libdtrace/common/dt_proc.h
===================================================================
--- trunk/cddl/contrib/opensolaris/lib/libdtrace/common/dt_proc.h 2018-06-02 16:07:17 UTC (rev 10228)
+++ trunk/cddl/contrib/opensolaris/lib/libdtrace/common/dt_proc.h 2018-06-02 16:07:30 UTC (rev 10229)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*
* CDDL HEADER START
*
Modified: trunk/cddl/contrib/opensolaris/lib/libdtrace/common/dt_program.c
===================================================================
--- trunk/cddl/contrib/opensolaris/lib/libdtrace/common/dt_program.c 2018-06-02 16:07:17 UTC (rev 10228)
+++ trunk/cddl/contrib/opensolaris/lib/libdtrace/common/dt_program.c 2018-06-02 16:07:30 UTC (rev 10229)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*
* CDDL HEADER START
*
@@ -30,7 +31,7 @@
#include <errno.h>
#include <assert.h>
#include <ctype.h>
-#if defined(sun)
+#ifdef illumos
#include <alloca.h>
#endif
Modified: trunk/cddl/contrib/opensolaris/lib/libdtrace/common/dt_program.h
===================================================================
--- trunk/cddl/contrib/opensolaris/lib/libdtrace/common/dt_program.h 2018-06-02 16:07:17 UTC (rev 10228)
+++ trunk/cddl/contrib/opensolaris/lib/libdtrace/common/dt_program.h 2018-06-02 16:07:30 UTC (rev 10229)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*
* CDDL HEADER START
*
Modified: trunk/cddl/contrib/opensolaris/lib/libdtrace/common/dt_provider.c
===================================================================
--- trunk/cddl/contrib/opensolaris/lib/libdtrace/common/dt_provider.c 2018-06-02 16:07:17 UTC (rev 10228)
+++ trunk/cddl/contrib/opensolaris/lib/libdtrace/common/dt_provider.c 2018-06-02 16:07:30 UTC (rev 10229)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*
* CDDL HEADER START
*
@@ -23,11 +24,12 @@
* Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
+/*
+ * Copyright (c) 2013, Joyent, Inc. All rights reserved.
+ */
-#pragma ident "%Z%%M% %I% %E% SMI"
-
#include <sys/types.h>
-#if defined(sun)
+#ifdef illumos
#include <sys/sysmacros.h>
#endif
@@ -35,7 +37,7 @@
#include <limits.h>
#include <strings.h>
#include <stdlib.h>
-#if defined(sun)
+#ifdef illumos
#include <alloca.h>
#endif
#include <unistd.h>
@@ -45,6 +47,8 @@
#include <dt_module.h>
#include <dt_string.h>
#include <dt_list.h>
+#include <dt_pid.h>
+#include <dtrace.h>
static dt_provider_t *
dt_provider_insert(dtrace_hdl_t *dtp, dt_provider_t *pvp, uint_t h)
@@ -273,6 +277,21 @@
nc++;
/*
+ * The pid provider believes in giving the kernel a break. No reason to
+ * give the kernel all the ctf containers that we're keeping ourselves
+ * just to get it back from it. So if we're coming from a pid provider
+ * probe and the kernel gave us no argument information we'll get some
+ * here. If for some crazy reason the kernel knows about our userland
+ * types then we just ignore this.
+ */
+ if (xc == 0 && nc == 0 &&
+ strncmp(pvp->pv_desc.dtvd_name, "pid", 3) == 0) {
+ nc = adc;
+ dt_pid_get_types(dtp, pdp, adv, &nc);
+ xc = nc;
+ }
+
+ /*
* Now that we have discovered the number of native and translated
* arguments from the argument descriptions, allocate a new probe ident
* and corresponding dt_probe_t and hash it into the provider.
@@ -318,7 +337,8 @@
dtt.dtt_type = CTF_ERR;
} else {
dt_node_type_assign(prp->pr_nargv[adp->dtargd_mapping],
- dtt.dtt_ctfp, dtt.dtt_type);
+ dtt.dtt_ctfp, dtt.dtt_type,
+ dtt.dtt_flags & DTT_FL_USER ? B_TRUE : B_FALSE);
}
if (dtt.dtt_type != CTF_ERR && (adp->dtargd_xlate[0] == '\0' ||
@@ -337,7 +357,7 @@
dtt.dtt_type = CTF_ERR;
} else {
dt_node_type_assign(prp->pr_xargv[i],
- dtt.dtt_ctfp, dtt.dtt_type);
+ dtt.dtt_ctfp, dtt.dtt_type, B_FALSE);
}
prp->pr_mapping[i] = adp->dtargd_mapping;
@@ -638,7 +658,7 @@
bzero(dnp, sizeof (dt_node_t));
dnp->dn_kind = DT_NODE_TYPE;
- dt_node_type_assign(dnp, dtt.dtt_ctfp, dtt.dtt_type);
+ dt_node_type_assign(dnp, dtt.dtt_ctfp, dtt.dtt_type, B_FALSE);
dt_node_attr_assign(dnp, _dtrace_defattr);
return (dnp);
Modified: trunk/cddl/contrib/opensolaris/lib/libdtrace/common/dt_provider.h
===================================================================
--- trunk/cddl/contrib/opensolaris/lib/libdtrace/common/dt_provider.h 2018-06-02 16:07:17 UTC (rev 10228)
+++ trunk/cddl/contrib/opensolaris/lib/libdtrace/common/dt_provider.h 2018-06-02 16:07:30 UTC (rev 10229)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*
* CDDL HEADER START
*
Modified: trunk/cddl/contrib/opensolaris/lib/libdtrace/common/dt_regset.c
===================================================================
--- trunk/cddl/contrib/opensolaris/lib/libdtrace/common/dt_regset.c 2018-06-02 16:07:17 UTC (rev 10228)
+++ trunk/cddl/contrib/opensolaris/lib/libdtrace/common/dt_regset.c 2018-06-02 16:07:30 UTC (rev 10229)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*
* CDDL HEADER START
*
@@ -19,12 +20,16 @@
*
* CDDL HEADER END
*/
+
/*
* Copyright 2003 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
+/*
+ * Copyright (c) 2012 by Delphix. All rights reserved.
+ * Copyright (c) 2016 Pedro Giffuni. All rights reserved.
+ */
#include <sys/types.h>
#include <sys/bitmap.h>
@@ -33,18 +38,18 @@
#include <stdlib.h>
#include <dt_regset.h>
+#include <dt_impl.h>
dt_regset_t *
-dt_regset_create(ulong_t size)
+dt_regset_create(ulong_t nregs)
{
- ulong_t n = BT_BITOUL(size + 1); /* + 1 for %r0 */
+ ulong_t n = BT_BITOUL(nregs);
dt_regset_t *drp = malloc(sizeof (dt_regset_t));
if (drp == NULL)
return (NULL);
- drp->dr_bitmap = malloc(sizeof (ulong_t) * n);
- drp->dr_size = size + 1;
+ drp->dr_bitmap = calloc(n, sizeof (ulong_t));
if (drp->dr_bitmap == NULL) {
dt_regset_destroy(drp);
@@ -51,7 +56,8 @@
return (NULL);
}
- bzero(drp->dr_bitmap, sizeof (ulong_t) * n);
+ drp->dr_size = nregs;
+
return (drp);
}
@@ -68,6 +74,25 @@
bzero(drp->dr_bitmap, sizeof (ulong_t) * BT_BITOUL(drp->dr_size));
}
+void
+dt_regset_assert_free(dt_regset_t *drp)
+{
+ int reg;
+ boolean_t fail = B_FALSE;
+ for (reg = 0; reg < drp->dr_size; reg++) {
+ if (BT_TEST(drp->dr_bitmap, reg) != 0) {
+ dt_dprintf("%%r%d was left allocated\n", reg);
+ fail = B_TRUE;
+ }
+ }
+
+ /*
+ * We set this during dtest runs to check for register leaks.
+ */
+ if (fail && getenv("DTRACE_DEBUG_REGSET") != NULL)
+ abort();
+}
+
int
dt_regset_alloc(dt_regset_t *drp)
{
@@ -95,13 +120,15 @@
}
}
- return (-1); /* no available registers */
+ xyerror(D_NOREG, "Insufficient registers to generate code");
+ /*NOTREACHED*/
+ return (-1);
}
void
dt_regset_free(dt_regset_t *drp, int reg)
{
- assert(reg > 0 && reg < drp->dr_size);
+ assert(reg >= 0 && reg < drp->dr_size);
assert(BT_TEST(drp->dr_bitmap, reg) != 0);
BT_CLEAR(drp->dr_bitmap, reg);
}
Modified: trunk/cddl/contrib/opensolaris/lib/libdtrace/common/dt_regset.h
===================================================================
--- trunk/cddl/contrib/opensolaris/lib/libdtrace/common/dt_regset.h 2018-06-02 16:07:17 UTC (rev 10228)
+++ trunk/cddl/contrib/opensolaris/lib/libdtrace/common/dt_regset.h 2018-06-02 16:07:30 UTC (rev 10229)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*
* CDDL HEADER START
*
@@ -19,16 +20,19 @@
*
* CDDL HEADER END
*/
+
/*
* Copyright 2003 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
+/*
+ * Copyright (c) 2012 by Delphix. All rights reserved.
+ */
+
#ifndef _DT_REGSET_H
#define _DT_REGSET_H
-#pragma ident "%Z%%M% %I% %E% SMI"
-
#include <sys/types.h>
#ifdef __cplusplus
@@ -45,6 +49,7 @@
extern void dt_regset_reset(dt_regset_t *);
extern int dt_regset_alloc(dt_regset_t *);
extern void dt_regset_free(dt_regset_t *, int);
+extern void dt_regset_assert_free(dt_regset_t *);
#ifdef __cplusplus
}
Modified: trunk/cddl/contrib/opensolaris/lib/libdtrace/common/dt_string.c
===================================================================
--- trunk/cddl/contrib/opensolaris/lib/libdtrace/common/dt_string.c 2018-06-02 16:07:17 UTC (rev 10228)
+++ trunk/cddl/contrib/opensolaris/lib/libdtrace/common/dt_string.c 2018-06-02 16:07:30 UTC (rev 10229)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*
* CDDL HEADER START
*
Modified: trunk/cddl/contrib/opensolaris/lib/libdtrace/common/dt_string.h
===================================================================
--- trunk/cddl/contrib/opensolaris/lib/libdtrace/common/dt_string.h 2018-06-02 16:07:17 UTC (rev 10228)
+++ trunk/cddl/contrib/opensolaris/lib/libdtrace/common/dt_string.h 2018-06-02 16:07:30 UTC (rev 10229)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*
* CDDL HEADER START
*
Modified: trunk/cddl/contrib/opensolaris/lib/libdtrace/common/dt_strtab.c
===================================================================
--- trunk/cddl/contrib/opensolaris/lib/libdtrace/common/dt_strtab.c 2018-06-02 16:07:17 UTC (rev 10228)
+++ trunk/cddl/contrib/opensolaris/lib/libdtrace/common/dt_strtab.c 2018-06-02 16:07:30 UTC (rev 10229)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*
* CDDL HEADER START
*
@@ -24,6 +25,10 @@
* Use is subject to license terms.
*/
+/*
+ * Portions Copyright 2016 Pedro Giffuni. All rights reserved.
+ */
+
#pragma ident "%Z%%M% %I% %E% SMI"
#include <sys/types.h>
@@ -70,12 +75,11 @@
return (NULL);
bzero(sp, sizeof (dt_strtab_t));
- sp->str_hash = malloc(nbuckets * sizeof (dt_strhash_t *));
+ sp->str_hash = calloc(nbuckets, sizeof (dt_strhash_t *));
if (sp->str_hash == NULL)
goto err;
- bzero(sp->str_hash, nbuckets * sizeof (dt_strhash_t *));
sp->str_hashsz = nbuckets;
sp->str_bufs = NULL;
sp->str_ptr = NULL;
Modified: trunk/cddl/contrib/opensolaris/lib/libdtrace/common/dt_strtab.h
===================================================================
--- trunk/cddl/contrib/opensolaris/lib/libdtrace/common/dt_strtab.h 2018-06-02 16:07:17 UTC (rev 10228)
+++ trunk/cddl/contrib/opensolaris/lib/libdtrace/common/dt_strtab.h 2018-06-02 16:07:30 UTC (rev 10229)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*
* CDDL HEADER START
*
Modified: trunk/cddl/contrib/opensolaris/lib/libdtrace/common/dt_subr.c
===================================================================
--- trunk/cddl/contrib/opensolaris/lib/libdtrace/common/dt_subr.c 2018-06-02 16:07:17 UTC (rev 10228)
+++ trunk/cddl/contrib/opensolaris/lib/libdtrace/common/dt_subr.c 2018-06-02 16:07:30 UTC (rev 10229)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*
* CDDL HEADER START
*
@@ -21,10 +22,11 @@
/*
* Copyright 2010 Sun Microsystems, Inc. All rights reserved.
+ * Copyright (c) 2012 by Delphix. All rights reserved.
* Use is subject to license terms.
*/
-#if defined(sun)
+#ifdef illumos
#include <sys/sysmacros.h>
#endif
#include <sys/isa_defs.h>
@@ -37,7 +39,7 @@
#include <stdio.h>
#include <errno.h>
#include <ctype.h>
-#if defined(sun)
+#ifdef illumos
#include <alloca.h>
#else
#include <sys/sysctl.h>
@@ -476,7 +478,7 @@
}
int
-#if defined(sun)
+#ifdef illumos
dt_ioctl(dtrace_hdl_t *dtp, int val, void *arg)
#else
dt_ioctl(dtrace_hdl_t *dtp, u_long val, void *arg)
@@ -484,7 +486,7 @@
{
const dtrace_vector_t *v = dtp->dt_vector;
-#if !defined(sun)
+#ifndef illumos
/* Avoid sign extension. */
val &= 0xffffffff;
#endif
@@ -505,7 +507,7 @@
const dtrace_vector_t *v = dtp->dt_vector;
if (v == NULL) {
-#if defined(sun)
+#ifdef illumos
return (p_online(cpu, P_STATUS));
#else
int maxid = 0;
@@ -582,7 +584,7 @@
va_list ap;
int n;
-#if !defined(sun)
+#ifndef illumos
/*
* On FreeBSD, check if output is currently being re-directed
* to another file. If so, output to that file instead of the
@@ -617,8 +619,8 @@
size_t avail;
/*
- * It's not legal to use buffered ouput if there is not a
- * handler for buffered output.
+ * Using buffered output is not allowed if a handler has
+ * not been installed.
*/
if (dtp->dt_bufhdlr == NULL) {
va_end(ap);
@@ -678,6 +680,7 @@
dtp->dt_buffered_offs += needed;
assert(dtp->dt_buffered_buf[dtp->dt_buffered_offs] == '\0');
+ va_end(ap);
return (0);
}
@@ -732,11 +735,6 @@
{
void *data;
- if (size > 16 * 1024 * 1024) {
- (void) dt_set_errno(dtp, EDT_NOMEM);
- return (NULL);
- }
-
if ((data = malloc(size)) == NULL)
(void) dt_set_errno(dtp, EDT_NOMEM);
else
@@ -750,11 +748,6 @@
{
void *data;
- if (size > 16 * 1024 * 1024) {
- (void) dt_set_errno(dtp, EDT_NOMEM);
- return (NULL);
- }
-
if ((data = malloc(size)) == NULL)
(void) dt_set_errno(dtp, EDT_NOMEM);
@@ -853,7 +846,7 @@
return (popc + dt_popc(bp[maxw] & ((1UL << maxb) - 1)));
}
-#if defined(sun)
+#ifdef illumos
struct _rwlock;
struct _lwp_mutex;
@@ -875,7 +868,7 @@
int
dt_mutex_held(pthread_mutex_t *lock)
{
-#if defined(sun)
+#ifdef illumos
extern int _mutex_held(struct _lwp_mutex *);
return (_mutex_held((struct _lwp_mutex *)lock));
#else
Modified: trunk/cddl/contrib/opensolaris/lib/libdtrace/common/dt_work.c
===================================================================
--- trunk/cddl/contrib/opensolaris/lib/libdtrace/common/dt_work.c 2018-06-02 16:07:17 UTC (rev 10228)
+++ trunk/cddl/contrib/opensolaris/lib/libdtrace/common/dt_work.c 2018-06-02 16:07:30 UTC (rev 10229)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*
* CDDL HEADER START
*
@@ -82,7 +83,7 @@
return; /* sleep duration has already past */
}
-#if defined(sun)
+#ifdef illumos
tv.tv_sec = (earliest - now) / NANOSEC;
tv.tv_nsec = (earliest - now) % NANOSEC;
@@ -184,7 +185,7 @@
{
dtrace_enable_io_t args;
void *dof;
- int err;
+ int error, r;
if (dtp->dt_active)
return (dt_set_errno(dtp, EINVAL));
@@ -206,11 +207,12 @@
args.dof = dof;
args.n_matched = 0;
- err = dt_ioctl(dtp, DTRACEIOC_ENABLE, &args);
+ r = dt_ioctl(dtp, DTRACEIOC_ENABLE, &args);
+ error = errno;
dtrace_dof_destroy(dtp, dof);
- if (err == -1 && (errno != ENOTTY || dtp->dt_vector == NULL))
- return (dt_set_errno(dtp, errno));
+ if (r == -1 && (error != ENOTTY || dtp->dt_vector == NULL))
+ return (dt_set_errno(dtp, error));
if (dt_ioctl(dtp, DTRACEIOC_GO, &dtp->dt_beganon) == -1) {
if (errno == EACCES)
Modified: trunk/cddl/contrib/opensolaris/lib/libdtrace/common/dt_xlator.c
===================================================================
--- trunk/cddl/contrib/opensolaris/lib/libdtrace/common/dt_xlator.c 2018-06-02 16:07:17 UTC (rev 10228)
+++ trunk/cddl/contrib/opensolaris/lib/libdtrace/common/dt_xlator.c 2018-06-02 16:07:30 UTC (rev 10229)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*
* CDDL HEADER START
*
@@ -23,9 +24,11 @@
* Copyright 2005 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
+/*
+ * Copyright (c) 2013 by Delphix. All rights reserved.
+ * Copyright (c) 2013 Joyent, Inc. All rights reserved.
+ */
-#pragma ident "%Z%%M% %I% %E% SMI"
-
#include <strings.h>
#include <assert.h>
@@ -69,7 +72,7 @@
enp->dn_op = DT_TOK_XLATE;
enp->dn_xlator = dxp;
enp->dn_xmember = mnp;
- dt_node_type_assign(enp, dxp->dx_dst_ctfp, type);
+ dt_node_type_assign(enp, dxp->dx_dst_ctfp, type, B_FALSE);
/*
* For the member itself, we use a DT_NODE_MEMBER as usual with the
@@ -83,7 +86,7 @@
mnp->dn_membname = strdup(name);
mnp->dn_membexpr = enp;
- dt_node_type_assign(mnp, dxp->dx_dst_ctfp, type);
+ dt_node_type_assign(mnp, dxp->dx_dst_ctfp, type, B_FALSE);
if (mnp->dn_membname == NULL)
return (dt_set_errno(dtp, EDT_NOMEM));
@@ -318,7 +321,8 @@
for (dxp = dt_list_next(&dtp->dt_xlators); dxp != NULL;
dxp = dt_list_next(dxp)) {
- dt_node_type_assign(&xn, dxp->dx_src_ctfp, dxp->dx_src_type);
+ dt_node_type_assign(&xn, dxp->dx_src_ctfp, dxp->dx_src_type,
+ B_FALSE);
if (ctf_type_compat(dxp->dx_dst_ctfp, dxp->dx_dst_base,
dst_ctfp, dst_base) && dt_node_is_argcompat(src, &xn))
goto out;
Modified: trunk/cddl/contrib/opensolaris/lib/libdtrace/common/dt_xlator.h
===================================================================
--- trunk/cddl/contrib/opensolaris/lib/libdtrace/common/dt_xlator.h 2018-06-02 16:07:17 UTC (rev 10228)
+++ trunk/cddl/contrib/opensolaris/lib/libdtrace/common/dt_xlator.h 2018-06-02 16:07:30 UTC (rev 10229)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*
* CDDL HEADER START
*
Modified: trunk/cddl/contrib/opensolaris/lib/libdtrace/common/dtrace.h
===================================================================
--- trunk/cddl/contrib/opensolaris/lib/libdtrace/common/dtrace.h 2018-06-02 16:07:17 UTC (rev 10228)
+++ trunk/cddl/contrib/opensolaris/lib/libdtrace/common/dtrace.h 2018-06-02 16:07:30 UTC (rev 10229)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*
* CDDL HEADER START
*
@@ -25,7 +26,8 @@
*/
/*
- * Copyright (c) 2011, Joyent, Inc. All rights reserved.
+ * Copyright (c) 2013 by Delphix. All rights reserved.
+ * Copyright (c) 2013, Joyent, Inc. All rights reserved.
*/
#ifndef _DTRACE_H
@@ -36,7 +38,7 @@
#include <stdio.h>
#include <gelf.h>
#include <libproc.h>
-#if !defined(sun)
+#ifndef illumos
#include <rtld_db.h>
#endif
@@ -356,7 +358,13 @@
#define DTRACE_A_PERCPU 0x0001
#define DTRACE_A_KEEPDELTA 0x0002
#define DTRACE_A_ANONYMOUS 0x0004
+#define DTRACE_A_TOTAL 0x0008
+#define DTRACE_A_MINMAXBIN 0x0010
+#define DTRACE_A_HASNEGATIVES 0x0020
+#define DTRACE_A_HASPOSITIVES 0x0040
+#define DTRACE_AGGZOOM_MAX 0.95 /* height of max bar */
+
#define DTRACE_AGGWALK_ERROR -1 /* error while processing */
#define DTRACE_AGGWALK_NEXT 0 /* proceed to next element */
#define DTRACE_AGGWALK_ABORT 1 /* abort aggregation walk */
@@ -376,6 +384,10 @@
caddr_t dtada_delta; /* delta data, if available */
caddr_t *dtada_percpu; /* per CPU data, if avail */
caddr_t *dtada_percpu_delta; /* per CPU delta, if avail */
+ int64_t dtada_total; /* per agg total, if avail */
+ uint16_t dtada_minbin; /* minimum bin, if avail */
+ uint16_t dtada_maxbin; /* maximum bin, if avail */
+ uint32_t dtada_flags; /* flags */
};
typedef int dtrace_aggregate_f(const dtrace_aggdata_t *, void *);
@@ -495,8 +507,11 @@
const char *dtt_object; /* object containing type */
ctf_file_t *dtt_ctfp; /* CTF container handle */
ctf_id_t dtt_type; /* CTF type identifier */
+ uint_t dtt_flags; /* Misc. flags */
} dtrace_typeinfo_t;
+#define DTT_FL_USER 0x1 /* user type */
+
extern int dtrace_lookup_by_type(dtrace_hdl_t *, const char *, const char *,
dtrace_typeinfo_t *);
@@ -540,7 +555,7 @@
* entry point to obtain a library handle.
*/
struct dtrace_vector {
-#if defined(sun)
+#ifdef illumos
int (*dtv_ioctl)(void *, int, void *);
#else
int (*dtv_ioctl)(void *, u_long, void *);
@@ -591,7 +606,7 @@
}
#endif
-#if !defined(sun)
+#ifndef illumos
#define _SC_CPUID_MAX _SC_NPROCESSORS_CONF
#define _SC_NPROCESSORS_MAX _SC_NPROCESSORS_CONF
#endif
Modified: trunk/cddl/contrib/opensolaris/lib/libdtrace/i386/dt_isadep.c
===================================================================
--- trunk/cddl/contrib/opensolaris/lib/libdtrace/i386/dt_isadep.c 2018-06-02 16:07:17 UTC (rev 10228)
+++ trunk/cddl/contrib/opensolaris/lib/libdtrace/i386/dt_isadep.c 2018-06-02 16:07:30 UTC (rev 10229)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*
* CDDL HEADER START
*
@@ -24,6 +25,10 @@
* Use is subject to license terms.
*/
+/*
+ * Copyright (c) 2012 by Delphix. All rights reserved.
+ */
+
#include <stdlib.h>
#include <assert.h>
#include <errno.h>
@@ -35,7 +40,7 @@
#include <dis_tables.h>
-#if !defined(sun)
+#ifndef illumos
#define PR_MODEL_ILP32 1
#define PR_MODEL_LP64 2
#include <libproc_compat.h>
@@ -84,7 +89,7 @@
{
ulong_t i;
int size;
-#if defined(sun)
+#ifdef illumos
pid_t pid = Pstatus(P)->pr_pid;
char dmodel = Pstatus(P)->pr_dmodel;
#else
@@ -140,7 +145,7 @@
uint8_t *text;
ulong_t i, end;
int size;
-#if defined(sun)
+#ifdef illumos
pid_t pid = Pstatus(P)->pr_pid;
char dmodel = Pstatus(P)->pr_dmodel;
#else
@@ -301,7 +306,7 @@
uint8_t *text;
ulong_t i;
int size;
-#if defined(sun)
+#ifdef illumos
pid_t pid = Pstatus(P)->pr_pid;
char dmodel = Pstatus(P)->pr_dmodel;
#else
@@ -384,7 +389,7 @@
uint8_t *text;
int size;
ulong_t i, end = symp->st_size;
-#if defined(sun)
+#ifdef illumos
pid_t pid = Pstatus(P)->pr_pid;
char dmodel = Pstatus(P)->pr_dmodel;
#else
@@ -525,7 +530,8 @@
* another debugger attached to this process. The original instruction
* can't be recovered so this must fail.
*/
- if (x86dis.d86_len == 1 && instr[0] == FASTTRAP_INSTR)
+ if (x86dis.d86_len == 1 &&
+ (uchar_t)x86dis.d86_bytes[0] == FASTTRAP_INSTR)
return (-1);
return (x86dis.d86_len);
Added: trunk/cddl/contrib/opensolaris/lib/libdtrace/mips/dt_isadep.c
===================================================================
--- trunk/cddl/contrib/opensolaris/lib/libdtrace/mips/dt_isadep.c (rev 0)
+++ trunk/cddl/contrib/opensolaris/lib/libdtrace/mips/dt_isadep.c 2018-06-02 16:07:30 UTC (rev 10229)
@@ -0,0 +1,76 @@
+/* $MidnightBSD$ */
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <stdlib.h>
+#include <assert.h>
+#include <errno.h>
+#include <string.h>
+#include <libgen.h>
+
+#include <dt_impl.h>
+#include <dt_pid.h>
+
+/*ARGSUSED*/
+int
+dt_pid_create_entry_probe(struct ps_prochandle *P, dtrace_hdl_t *dtp,
+ fasttrap_probe_spec_t *ftp, const GElf_Sym *symp)
+{
+
+ dt_dprintf("%s: unimplemented\n", __func__);
+ return (DT_PROC_ERR);
+}
+
+int
+dt_pid_create_return_probe(struct ps_prochandle *P, dtrace_hdl_t *dtp,
+ fasttrap_probe_spec_t *ftp, const GElf_Sym *symp, uint64_t *stret)
+{
+
+ dt_dprintf("%s: unimplemented\n", __func__);
+ return (DT_PROC_ERR);
+}
+
+/*ARGSUSED*/
+int
+dt_pid_create_offset_probe(struct ps_prochandle *P, dtrace_hdl_t *dtp,
+ fasttrap_probe_spec_t *ftp, const GElf_Sym *symp, ulong_t off)
+{
+
+ dt_dprintf("%s: unimplemented\n", __func__);
+ return (DT_PROC_ERR);
+}
+
+/*ARGSUSED*/
+int
+dt_pid_create_glob_offset_probes(struct ps_prochandle *P, dtrace_hdl_t *dtp,
+ fasttrap_probe_spec_t *ftp, const GElf_Sym *symp, const char *pattern)
+{
+
+ dt_dprintf("%s: unimplemented\n", __func__);
+ return (DT_PROC_ERR);
+}
Property changes on: trunk/cddl/contrib/opensolaris/lib/libdtrace/mips/dt_isadep.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/cddl/contrib/opensolaris/lib/libdtrace/powerpc/dt_isadep.c
===================================================================
--- trunk/cddl/contrib/opensolaris/lib/libdtrace/powerpc/dt_isadep.c (rev 0)
+++ trunk/cddl/contrib/opensolaris/lib/libdtrace/powerpc/dt_isadep.c 2018-06-02 16:07:30 UTC (rev 10229)
@@ -0,0 +1,198 @@
+/* $MidnightBSD$ */
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <stdlib.h>
+#include <assert.h>
+#include <errno.h>
+#include <string.h>
+#include <libgen.h>
+
+#include <dt_impl.h>
+#include <dt_pid.h>
+
+#include <libproc_compat.h>
+
+/*ARGSUSED*/
+int
+dt_pid_create_entry_probe(struct ps_prochandle *P, dtrace_hdl_t *dtp,
+ fasttrap_probe_spec_t *ftp, const GElf_Sym *symp)
+{
+ ftp->ftps_type = DTFTP_ENTRY;
+ ftp->ftps_pc = (uintptr_t)symp->st_value;
+ ftp->ftps_size = (size_t)symp->st_size;
+ ftp->ftps_noffs = 1;
+ ftp->ftps_offs[0] = 0;
+
+ if (ioctl(dtp->dt_ftfd, FASTTRAPIOC_MAKEPROBE, ftp) != 0) {
+ dt_dprintf("fasttrap probe creation ioctl failed: %s\n",
+ strerror(errno));
+ return (dt_set_errno(dtp, errno));
+ }
+
+ return (1);
+}
+
+int
+dt_pid_create_return_probe(struct ps_prochandle *P, dtrace_hdl_t *dtp,
+ fasttrap_probe_spec_t *ftp, const GElf_Sym *symp, uint64_t *stret)
+{
+
+ uintptr_t temp;
+ uint32_t *text;
+ int i;
+ int srdepth = 0;
+
+ if ((text = malloc(symp->st_size + 4)) == NULL) {
+ dt_dprintf("mr sparkle: malloc() failed\n");
+ return (DT_PROC_ERR);
+ }
+
+ if (Pread(P, text, symp->st_size, symp->st_value) != symp->st_size) {
+ dt_dprintf("mr sparkle: Pread() failed\n");
+ free(text);
+ return (DT_PROC_ERR);
+ }
+
+ /*
+ * Leave a dummy instruction in the last slot to simplify edge
+ * conditions.
+ */
+ text[symp->st_size / 4] = 0;
+
+ ftp->ftps_type = DTFTP_RETURN;
+ ftp->ftps_pc = symp->st_value;
+ ftp->ftps_size = symp->st_size;
+ ftp->ftps_noffs = 0;
+
+ for (i = 0; i < symp->st_size / 4; i++) {
+
+ if ((text[i] & 0xfc000001) != 0x48000000 &&
+ text[i] != 0x4e800020)
+ continue;
+
+ /*
+ * Check for a jump within this function. If it's outside this
+ * function then it's a tail-call, so a return point.
+ */
+ if ((text[i] & 0xfc000000) == 0x48000000) {
+ temp = (text[i] & 0x03fffffc);
+ /* Bit 30 denotes an absolute address. */
+ if (!(text[i] & 0x02)) {
+ temp += symp->st_value + i * 4;
+ }
+ else {
+ /* Sign extend the absolute address. */
+ if (temp & 0x02000000) {
+ temp |= (UINTPTR_MAX - 0x03ffffff);
+ }
+ }
+ if (temp >= symp->st_value &&
+ temp <= (symp->st_value + symp->st_size))
+ continue;
+ }
+ dt_dprintf("return at offset %x\n", i * 4);
+ ftp->ftps_offs[ftp->ftps_noffs++] = i * 4;
+ }
+
+ free(text);
+ if (ftp->ftps_noffs > 0) {
+ if (ioctl(dtp->dt_ftfd, FASTTRAPIOC_MAKEPROBE, ftp) != 0) {
+ dt_dprintf("fasttrap probe creation ioctl failed: %s\n",
+ strerror(errno));
+ return (dt_set_errno(dtp, errno));
+ }
+ }
+
+
+ return (ftp->ftps_noffs);
+}
+
+/*ARGSUSED*/
+int
+dt_pid_create_offset_probe(struct ps_prochandle *P, dtrace_hdl_t *dtp,
+ fasttrap_probe_spec_t *ftp, const GElf_Sym *symp, ulong_t off)
+{
+ if (off & 0x3)
+ return (DT_PROC_ALIGN);
+
+ ftp->ftps_type = DTFTP_OFFSETS;
+ ftp->ftps_pc = (uintptr_t)symp->st_value;
+ ftp->ftps_size = (size_t)symp->st_size;
+ ftp->ftps_noffs = 1;
+ ftp->ftps_offs[0] = off;
+
+ if (ioctl(dtp->dt_ftfd, FASTTRAPIOC_MAKEPROBE, ftp) != 0) {
+ dt_dprintf("fasttrap probe creation ioctl failed: %s\n",
+ strerror(errno));
+ return (dt_set_errno(dtp, errno));
+ }
+
+ return (1);
+}
+
+/*ARGSUSED*/
+int
+dt_pid_create_glob_offset_probes(struct ps_prochandle *P, dtrace_hdl_t *dtp,
+ fasttrap_probe_spec_t *ftp, const GElf_Sym *symp, const char *pattern)
+{
+ ulong_t i;
+
+ ftp->ftps_type = DTFTP_OFFSETS;
+ ftp->ftps_pc = (uintptr_t)symp->st_value;
+ ftp->ftps_size = (size_t)symp->st_size;
+ ftp->ftps_noffs = 0;
+
+ /*
+ * If we're matching against everything, just iterate through each
+ * instruction in the function, otherwise look for matching offset
+ * names by constructing the string and comparing it against the
+ * pattern.
+ */
+ if (strcmp("*", pattern) == 0) {
+ for (i = 0; i < symp->st_size; i += 4) {
+ ftp->ftps_offs[ftp->ftps_noffs++] = i;
+ }
+ } else {
+ char name[sizeof (i) * 2 + 1];
+
+ for (i = 0; i < symp->st_size; i += 4) {
+ (void) sprintf(name, "%lx", i);
+ if (gmatch(name, pattern))
+ ftp->ftps_offs[ftp->ftps_noffs++] = i;
+ }
+ }
+
+ if (ioctl(dtp->dt_ftfd, FASTTRAPIOC_MAKEPROBE, ftp) != 0) {
+ dt_dprintf("fasttrap probe creation ioctl failed: %s\n",
+ strerror(errno));
+ return (dt_set_errno(dtp, errno));
+ }
+
+ return (ftp->ftps_noffs);
+}
Property changes on: trunk/cddl/contrib/opensolaris/lib/libdtrace/powerpc/dt_isadep.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Modified: trunk/cddl/contrib/opensolaris/lib/libdtrace/sparc/dt_isadep.c
===================================================================
--- trunk/cddl/contrib/opensolaris/lib/libdtrace/sparc/dt_isadep.c 2018-06-02 16:07:17 UTC (rev 10228)
+++ trunk/cddl/contrib/opensolaris/lib/libdtrace/sparc/dt_isadep.c 2018-06-02 16:07:30 UTC (rev 10229)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*
* CDDL HEADER START
*
Modified: trunk/cddl/contrib/opensolaris/lib/libgen/common/gmatch.c
===================================================================
--- trunk/cddl/contrib/opensolaris/lib/libgen/common/gmatch.c 2018-06-02 16:07:17 UTC (rev 10228)
+++ trunk/cddl/contrib/opensolaris/lib/libgen/common/gmatch.c 2018-06-02 16:07:30 UTC (rev 10229)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*
* CDDL HEADER START
*
@@ -29,7 +30,7 @@
#pragma ident "%Z%%M% %I% %E% SMI"
-#if defined(sun)
+#ifdef illumos
#pragma weak gmatch = _gmatch
#include "gen_synonyms.h"
@@ -38,7 +39,7 @@
#include <libgen.h>
#include <stdlib.h>
#include <limits.h>
-#if defined(sun)
+#ifdef illumos
#include <widec.h>
#include "_range.h"
#else
Modified: trunk/cddl/contrib/opensolaris/lib/libnvpair/libnvpair.c
===================================================================
--- trunk/cddl/contrib/opensolaris/lib/libnvpair/libnvpair.c 2018-06-02 16:07:17 UTC (rev 10228)
+++ trunk/cddl/contrib/opensolaris/lib/libnvpair/libnvpair.c 2018-06-02 16:07:30 UTC (rev 10229)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*
* CDDL HEADER START
*
@@ -26,7 +27,7 @@
#include <solaris.h>
#include <inttypes.h>
#include <unistd.h>
-#include <strings.h>
+#include <string.h>
#include <libintl.h>
#include <stdarg.h>
#include "libnvpair.h"
@@ -210,7 +211,7 @@
NVLIST_PRTFUNC(uint32, uint32_t, uint32_t, "0x%x")
NVLIST_PRTFUNC(int64, int64_t, longlong_t, "%lld")
NVLIST_PRTFUNC(uint64, uint64_t, u_longlong_t, "0x%llx")
-NVLIST_PRTFUNC(double, double, double, "0x%llf")
+NVLIST_PRTFUNC(double, double, double, "0x%f")
NVLIST_PRTFUNC(string, char *, char *, "%s")
NVLIST_PRTFUNC(hrtime, hrtime_t, hrtime_t, "0x%llx")
@@ -793,6 +794,7 @@
{
nvpair_t *elem = NULL;
boolean_t bool_value;
+ boolean_t *bool_array_value;
nvlist_t *nvlist_value;
nvlist_t **nvlist_array_value;
uint_t i, count;
@@ -853,6 +855,16 @@
NVP(elem, string, char *, char *, "'%s'");
break;
+ case DATA_TYPE_BOOLEAN_ARRAY:
+ (void) nvpair_value_boolean_array(elem,
+ &bool_array_value, &count);
+ for (i = 0; i < count; i++) {
+ (void) printf("%*s%s[%d]: %s\n", indent, "",
+ nvpair_name(elem), i,
+ bool_array_value[i] ? "true" : "false");
+ }
+ break;
+
case DATA_TYPE_BYTE_ARRAY:
NVPA(elem, byte_array, uchar_t, int, "%u");
break;
@@ -1217,7 +1229,8 @@
break;
}
case DATA_TYPE_BOOLEAN_VALUE: {
- boolean_t val, val_arg;
+ int32_t val_arg;
+ boolean_t val;
/* scanf boolean_t from value and check for match */
sr = sscanf(value, "%"SCNi32, &val_arg);
@@ -1228,7 +1241,8 @@
break;
}
case DATA_TYPE_BOOLEAN_ARRAY: {
- boolean_t *val_array, val_arg;
+ boolean_t *val_array;
+ int32_t val_arg;
/* check indexed value of array for match */
sr = sscanf(value, "%"SCNi32, &val_arg);
Modified: trunk/cddl/contrib/opensolaris/lib/libnvpair/libnvpair.h
===================================================================
--- trunk/cddl/contrib/opensolaris/lib/libnvpair/libnvpair.h 2018-06-02 16:07:17 UTC (rev 10228)
+++ trunk/cddl/contrib/opensolaris/lib/libnvpair/libnvpair.h 2018-06-02 16:07:30 UTC (rev 10229)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*
* CDDL HEADER START
*
@@ -20,6 +21,7 @@
*/
/*
* Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, Joyent, Inc. All rights reserved.
*/
#ifndef _LIBNVPAIR_H
@@ -46,6 +48,7 @@
char **);
extern void nvlist_print(FILE *, nvlist_t *);
+extern int nvlist_print_json(FILE *, nvlist_t *);
extern void dump_nvlist(nvlist_t *, int);
/*
Modified: trunk/cddl/contrib/opensolaris/lib/libnvpair/nvpair_alloc_system.c
===================================================================
--- trunk/cddl/contrib/opensolaris/lib/libnvpair/nvpair_alloc_system.c 2018-06-02 16:07:17 UTC (rev 10228)
+++ trunk/cddl/contrib/opensolaris/lib/libnvpair/nvpair_alloc_system.c 2018-06-02 16:07:30 UTC (rev 10229)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*
* CDDL HEADER START
*
Added: trunk/cddl/contrib/opensolaris/lib/libnvpair/nvpair_json.c
===================================================================
--- trunk/cddl/contrib/opensolaris/lib/libnvpair/nvpair_json.c (rev 0)
+++ trunk/cddl/contrib/opensolaris/lib/libnvpair/nvpair_json.c 2018-06-02 16:07:30 UTC (rev 10229)
@@ -0,0 +1,404 @@
+/* $MidnightBSD$ */
+/*
+ * This file and its contents are supplied under the terms of the
+ * Common Development and Distribution License ("CDDL"), version 1.0.
+ * You may only use this file in accordance with the terms of version
+ * 1.0 of the CDDL.
+ *
+ * A full copy of the text of the CDDL should have accompanied this
+ * source. A copy of the CDDL is also available via the Internet at
+ * http://www.illumos.org/license/CDDL.
+ */
+/*
+ * Copyright (c) 2014, Joyent, Inc.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <strings.h>
+#include <wchar.h>
+#include <sys/debug.h>
+
+#include "libnvpair.h"
+
+#define FPRINTF(fp, ...) \
+ do { \
+ if (fprintf(fp, __VA_ARGS__) < 0) \
+ return (-1); \
+ } while (0)
+
+/*
+ * When formatting a string for JSON output we must escape certain characters,
+ * as described in RFC4627. This applies to both member names and
+ * DATA_TYPE_STRING values.
+ *
+ * This function will only operate correctly if the following conditions are
+ * met:
+ *
+ * 1. The input String is encoded in the current locale.
+ *
+ * 2. The current locale includes the Basic Multilingual Plane (plane 0)
+ * as defined in the Unicode standard.
+ *
+ * The output will be entirely 7-bit ASCII (as a subset of UTF-8) with all
+ * representable Unicode characters included in their escaped numeric form.
+ */
+static int
+nvlist_print_json_string(FILE *fp, const char *input)
+{
+ mbstate_t mbr;
+ wchar_t c;
+ size_t sz;
+
+ bzero(&mbr, sizeof (mbr));
+
+ FPRINTF(fp, "\"");
+ while ((sz = mbrtowc(&c, input, MB_CUR_MAX, &mbr)) > 0) {
+ switch (c) {
+ case '"':
+ FPRINTF(fp, "\\\"");
+ break;
+ case '\n':
+ FPRINTF(fp, "\\n");
+ break;
+ case '\r':
+ FPRINTF(fp, "\\r");
+ break;
+ case '\\':
+ FPRINTF(fp, "\\\\");
+ break;
+ case '\f':
+ FPRINTF(fp, "\\f");
+ break;
+ case '\t':
+ FPRINTF(fp, "\\t");
+ break;
+ case '\b':
+ FPRINTF(fp, "\\b");
+ break;
+ default:
+ if ((c >= 0x00 && c <= 0x1f) ||
+ (c > 0x7f && c <= 0xffff)) {
+ /*
+ * Render both Control Characters and Unicode
+ * characters in the Basic Multilingual Plane
+ * as JSON-escaped multibyte characters.
+ */
+ FPRINTF(fp, "\\u%04x", (int)(0xffff & c));
+ } else if (c >= 0x20 && c <= 0x7f) {
+ /*
+ * Render other 7-bit ASCII characters directly
+ * and drop other, unrepresentable characters.
+ */
+ FPRINTF(fp, "%c", (int)(0xff & c));
+ }
+ break;
+ }
+ input += sz;
+ }
+
+ if (sz == (size_t)-1 || sz == (size_t)-2) {
+ /*
+ * We last read an invalid multibyte character sequence,
+ * so return an error.
+ */
+ return (-1);
+ }
+
+ FPRINTF(fp, "\"");
+ return (0);
+}
+
+/*
+ * Dump a JSON-formatted representation of an nvlist to the provided FILE *.
+ * This routine does not output any new-lines or additional whitespace other
+ * than that contained in strings, nor does it call fflush(3C).
+ */
+int
+nvlist_print_json(FILE *fp, nvlist_t *nvl)
+{
+ nvpair_t *curr;
+ boolean_t first = B_TRUE;
+
+ FPRINTF(fp, "{");
+
+ for (curr = nvlist_next_nvpair(nvl, NULL); curr;
+ curr = nvlist_next_nvpair(nvl, curr)) {
+ data_type_t type = nvpair_type(curr);
+
+ if (!first)
+ FPRINTF(fp, ",");
+ else
+ first = B_FALSE;
+
+ if (nvlist_print_json_string(fp, nvpair_name(curr)) == -1)
+ return (-1);
+ FPRINTF(fp, ":");
+
+ switch (type) {
+ case DATA_TYPE_STRING: {
+ char *string = fnvpair_value_string(curr);
+ if (nvlist_print_json_string(fp, string) == -1)
+ return (-1);
+ break;
+ }
+
+ case DATA_TYPE_BOOLEAN: {
+ FPRINTF(fp, "true");
+ break;
+ }
+
+ case DATA_TYPE_BOOLEAN_VALUE: {
+ FPRINTF(fp, "%s", fnvpair_value_boolean_value(curr) ==
+ B_TRUE ? "true" : "false");
+ break;
+ }
+
+ case DATA_TYPE_BYTE: {
+ FPRINTF(fp, "%hhu", fnvpair_value_byte(curr));
+ break;
+ }
+
+ case DATA_TYPE_INT8: {
+ FPRINTF(fp, "%hhd", fnvpair_value_int8(curr));
+ break;
+ }
+
+ case DATA_TYPE_UINT8: {
+ FPRINTF(fp, "%hhu", fnvpair_value_uint8_t(curr));
+ break;
+ }
+
+ case DATA_TYPE_INT16: {
+ FPRINTF(fp, "%hd", fnvpair_value_int16(curr));
+ break;
+ }
+
+ case DATA_TYPE_UINT16: {
+ FPRINTF(fp, "%hu", fnvpair_value_uint16(curr));
+ break;
+ }
+
+ case DATA_TYPE_INT32: {
+ FPRINTF(fp, "%d", fnvpair_value_int32(curr));
+ break;
+ }
+
+ case DATA_TYPE_UINT32: {
+ FPRINTF(fp, "%u", fnvpair_value_uint32(curr));
+ break;
+ }
+
+ case DATA_TYPE_INT64: {
+ FPRINTF(fp, "%lld",
+ (long long)fnvpair_value_int64(curr));
+ break;
+ }
+
+ case DATA_TYPE_UINT64: {
+ FPRINTF(fp, "%llu",
+ (unsigned long long)fnvpair_value_uint64(curr));
+ break;
+ }
+
+ case DATA_TYPE_HRTIME: {
+ hrtime_t val;
+ VERIFY0(nvpair_value_hrtime(curr, &val));
+ FPRINTF(fp, "%llu", (unsigned long long)val);
+ break;
+ }
+
+ case DATA_TYPE_DOUBLE: {
+ double val;
+ VERIFY0(nvpair_value_double(curr, &val));
+ FPRINTF(fp, "%f", val);
+ break;
+ }
+
+ case DATA_TYPE_NVLIST: {
+ if (nvlist_print_json(fp,
+ fnvpair_value_nvlist(curr)) == -1)
+ return (-1);
+ break;
+ }
+
+ case DATA_TYPE_STRING_ARRAY: {
+ char **val;
+ uint_t valsz, i;
+ VERIFY0(nvpair_value_string_array(curr, &val, &valsz));
+ FPRINTF(fp, "[");
+ for (i = 0; i < valsz; i++) {
+ if (i > 0)
+ FPRINTF(fp, ",");
+ if (nvlist_print_json_string(fp, val[i]) == -1)
+ return (-1);
+ }
+ FPRINTF(fp, "]");
+ break;
+ }
+
+ case DATA_TYPE_NVLIST_ARRAY: {
+ nvlist_t **val;
+ uint_t valsz, i;
+ VERIFY0(nvpair_value_nvlist_array(curr, &val, &valsz));
+ FPRINTF(fp, "[");
+ for (i = 0; i < valsz; i++) {
+ if (i > 0)
+ FPRINTF(fp, ",");
+ if (nvlist_print_json(fp, val[i]) == -1)
+ return (-1);
+ }
+ FPRINTF(fp, "]");
+ break;
+ }
+
+ case DATA_TYPE_BOOLEAN_ARRAY: {
+ boolean_t *val;
+ uint_t valsz, i;
+ VERIFY0(nvpair_value_boolean_array(curr, &val, &valsz));
+ FPRINTF(fp, "[");
+ for (i = 0; i < valsz; i++) {
+ if (i > 0)
+ FPRINTF(fp, ",");
+ FPRINTF(fp, val[i] == B_TRUE ?
+ "true" : "false");
+ }
+ FPRINTF(fp, "]");
+ break;
+ }
+
+ case DATA_TYPE_BYTE_ARRAY: {
+ uchar_t *val;
+ uint_t valsz, i;
+ VERIFY0(nvpair_value_byte_array(curr, &val, &valsz));
+ FPRINTF(fp, "[");
+ for (i = 0; i < valsz; i++) {
+ if (i > 0)
+ FPRINTF(fp, ",");
+ FPRINTF(fp, "%hhu", val[i]);
+ }
+ FPRINTF(fp, "]");
+ break;
+ }
+
+ case DATA_TYPE_UINT8_ARRAY: {
+ uint8_t *val;
+ uint_t valsz, i;
+ VERIFY0(nvpair_value_uint8_array(curr, &val, &valsz));
+ FPRINTF(fp, "[");
+ for (i = 0; i < valsz; i++) {
+ if (i > 0)
+ FPRINTF(fp, ",");
+ FPRINTF(fp, "%hhu", val[i]);
+ }
+ FPRINTF(fp, "]");
+ break;
+ }
+
+ case DATA_TYPE_INT8_ARRAY: {
+ int8_t *val;
+ uint_t valsz, i;
+ VERIFY0(nvpair_value_int8_array(curr, &val, &valsz));
+ FPRINTF(fp, "[");
+ for (i = 0; i < valsz; i++) {
+ if (i > 0)
+ FPRINTF(fp, ",");
+ FPRINTF(fp, "%hhd", val[i]);
+ }
+ FPRINTF(fp, "]");
+ break;
+ }
+
+ case DATA_TYPE_UINT16_ARRAY: {
+ uint16_t *val;
+ uint_t valsz, i;
+ VERIFY0(nvpair_value_uint16_array(curr, &val, &valsz));
+ FPRINTF(fp, "[");
+ for (i = 0; i < valsz; i++) {
+ if (i > 0)
+ FPRINTF(fp, ",");
+ FPRINTF(fp, "%hu", val[i]);
+ }
+ FPRINTF(fp, "]");
+ break;
+ }
+
+ case DATA_TYPE_INT16_ARRAY: {
+ int16_t *val;
+ uint_t valsz, i;
+ VERIFY0(nvpair_value_int16_array(curr, &val, &valsz));
+ FPRINTF(fp, "[");
+ for (i = 0; i < valsz; i++) {
+ if (i > 0)
+ FPRINTF(fp, ",");
+ FPRINTF(fp, "%hd", val[i]);
+ }
+ FPRINTF(fp, "]");
+ break;
+ }
+
+ case DATA_TYPE_UINT32_ARRAY: {
+ uint32_t *val;
+ uint_t valsz, i;
+ VERIFY0(nvpair_value_uint32_array(curr, &val, &valsz));
+ FPRINTF(fp, "[");
+ for (i = 0; i < valsz; i++) {
+ if (i > 0)
+ FPRINTF(fp, ",");
+ FPRINTF(fp, "%u", val[i]);
+ }
+ FPRINTF(fp, "]");
+ break;
+ }
+
+ case DATA_TYPE_INT32_ARRAY: {
+ int32_t *val;
+ uint_t valsz, i;
+ VERIFY0(nvpair_value_int32_array(curr, &val, &valsz));
+ FPRINTF(fp, "[");
+ for (i = 0; i < valsz; i++) {
+ if (i > 0)
+ FPRINTF(fp, ",");
+ FPRINTF(fp, "%d", val[i]);
+ }
+ FPRINTF(fp, "]");
+ break;
+ }
+
+ case DATA_TYPE_UINT64_ARRAY: {
+ uint64_t *val;
+ uint_t valsz, i;
+ VERIFY0(nvpair_value_uint64_array(curr, &val, &valsz));
+ FPRINTF(fp, "[");
+ for (i = 0; i < valsz; i++) {
+ if (i > 0)
+ FPRINTF(fp, ",");
+ FPRINTF(fp, "%llu",
+ (unsigned long long)val[i]);
+ }
+ FPRINTF(fp, "]");
+ break;
+ }
+
+ case DATA_TYPE_INT64_ARRAY: {
+ int64_t *val;
+ uint_t valsz, i;
+ VERIFY0(nvpair_value_int64_array(curr, &val, &valsz));
+ FPRINTF(fp, "[");
+ for (i = 0; i < valsz; i++) {
+ if (i > 0)
+ FPRINTF(fp, ",");
+ FPRINTF(fp, "%lld", (long long)val[i]);
+ }
+ FPRINTF(fp, "]");
+ break;
+ }
+
+ case DATA_TYPE_UNKNOWN:
+ return (-1);
+ }
+ }
+
+ FPRINTF(fp, "}");
+ return (0);
+}
Property changes on: trunk/cddl/contrib/opensolaris/lib/libnvpair/nvpair_json.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Modified: trunk/cddl/contrib/opensolaris/lib/libuutil/common/libuutil.h
===================================================================
--- trunk/cddl/contrib/opensolaris/lib/libuutil/common/libuutil.h 2018-06-02 16:07:17 UTC (rev 10228)
+++ trunk/cddl/contrib/opensolaris/lib/libuutil/common/libuutil.h 2018-06-02 16:07:30 UTC (rev 10229)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*
* CDDL HEADER START
*
Modified: trunk/cddl/contrib/opensolaris/lib/libuutil/common/libuutil_common.h
===================================================================
--- trunk/cddl/contrib/opensolaris/lib/libuutil/common/libuutil_common.h 2018-06-02 16:07:17 UTC (rev 10228)
+++ trunk/cddl/contrib/opensolaris/lib/libuutil/common/libuutil_common.h 2018-06-02 16:07:30 UTC (rev 10229)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*
* CDDL HEADER START
*
Modified: trunk/cddl/contrib/opensolaris/lib/libuutil/common/libuutil_impl.h
===================================================================
--- trunk/cddl/contrib/opensolaris/lib/libuutil/common/libuutil_impl.h 2018-06-02 16:07:17 UTC (rev 10228)
+++ trunk/cddl/contrib/opensolaris/lib/libuutil/common/libuutil_impl.h 2018-06-02 16:07:30 UTC (rev 10229)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*
* CDDL HEADER START
*
Modified: trunk/cddl/contrib/opensolaris/lib/libuutil/common/uu_alloc.c
===================================================================
--- trunk/cddl/contrib/opensolaris/lib/libuutil/common/uu_alloc.c 2018-06-02 16:07:17 UTC (rev 10228)
+++ trunk/cddl/contrib/opensolaris/lib/libuutil/common/uu_alloc.c 2018-06-02 16:07:30 UTC (rev 10229)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*
* CDDL HEADER START
*
Modified: trunk/cddl/contrib/opensolaris/lib/libuutil/common/uu_avl.c
===================================================================
--- trunk/cddl/contrib/opensolaris/lib/libuutil/common/uu_avl.c 2018-06-02 16:07:17 UTC (rev 10228)
+++ trunk/cddl/contrib/opensolaris/lib/libuutil/common/uu_avl.c 2018-06-02 16:07:30 UTC (rev 10229)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*
* CDDL HEADER START
*
@@ -128,6 +129,7 @@
pp->uap_next->uap_prev = pp->uap_prev;
pp->uap_prev->uap_next = pp->uap_next;
(void) pthread_mutex_unlock(&uu_apool_list_lock);
+ (void) pthread_mutex_destroy(&pp->uap_lock);
pp->uap_prev = NULL;
pp->uap_next = NULL;
uu_free(pp);
Modified: trunk/cddl/contrib/opensolaris/lib/libuutil/common/uu_dprintf.c
===================================================================
--- trunk/cddl/contrib/opensolaris/lib/libuutil/common/uu_dprintf.c 2018-06-02 16:07:17 UTC (rev 10228)
+++ trunk/cddl/contrib/opensolaris/lib/libuutil/common/uu_dprintf.c 2018-06-02 16:07:30 UTC (rev 10229)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*
* CDDL HEADER START
*
Modified: trunk/cddl/contrib/opensolaris/lib/libuutil/common/uu_ident.c
===================================================================
--- trunk/cddl/contrib/opensolaris/lib/libuutil/common/uu_ident.c 2018-06-02 16:07:17 UTC (rev 10228)
+++ trunk/cddl/contrib/opensolaris/lib/libuutil/common/uu_ident.c 2018-06-02 16:07:30 UTC (rev 10229)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*
* CDDL HEADER START
*
Modified: trunk/cddl/contrib/opensolaris/lib/libuutil/common/uu_list.c
===================================================================
--- trunk/cddl/contrib/opensolaris/lib/libuutil/common/uu_list.c 2018-06-02 16:07:17 UTC (rev 10228)
+++ trunk/cddl/contrib/opensolaris/lib/libuutil/common/uu_list.c 2018-06-02 16:07:30 UTC (rev 10229)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*
* CDDL HEADER START
*
Modified: trunk/cddl/contrib/opensolaris/lib/libuutil/common/uu_misc.c
===================================================================
--- trunk/cddl/contrib/opensolaris/lib/libuutil/common/uu_misc.c 2018-06-02 16:07:17 UTC (rev 10228)
+++ trunk/cddl/contrib/opensolaris/lib/libuutil/common/uu_misc.c 2018-06-02 16:07:30 UTC (rev 10229)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*
* CDDL HEADER START
*
Modified: trunk/cddl/contrib/opensolaris/lib/libuutil/common/uu_open.c
===================================================================
--- trunk/cddl/contrib/opensolaris/lib/libuutil/common/uu_open.c 2018-06-02 16:07:17 UTC (rev 10228)
+++ trunk/cddl/contrib/opensolaris/lib/libuutil/common/uu_open.c 2018-06-02 16:07:30 UTC (rev 10229)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*
* CDDL HEADER START
*
Modified: trunk/cddl/contrib/opensolaris/lib/libuutil/common/uu_pname.c
===================================================================
--- trunk/cddl/contrib/opensolaris/lib/libuutil/common/uu_pname.c 2018-06-02 16:07:17 UTC (rev 10228)
+++ trunk/cddl/contrib/opensolaris/lib/libuutil/common/uu_pname.c 2018-06-02 16:07:30 UTC (rev 10229)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*
* CDDL HEADER START
*
Modified: trunk/cddl/contrib/opensolaris/lib/libuutil/common/uu_string.c
===================================================================
--- trunk/cddl/contrib/opensolaris/lib/libuutil/common/uu_string.c 2018-06-02 16:07:17 UTC (rev 10228)
+++ trunk/cddl/contrib/opensolaris/lib/libuutil/common/uu_string.c 2018-06-02 16:07:30 UTC (rev 10229)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*
* CDDL HEADER START
*
Modified: trunk/cddl/contrib/opensolaris/lib/libuutil/common/uu_strtoint.c
===================================================================
--- trunk/cddl/contrib/opensolaris/lib/libuutil/common/uu_strtoint.c 2018-06-02 16:07:17 UTC (rev 10228)
+++ trunk/cddl/contrib/opensolaris/lib/libuutil/common/uu_strtoint.c 2018-06-02 16:07:30 UTC (rev 10229)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*
* CDDL HEADER START
*
Modified: trunk/cddl/contrib/opensolaris/lib/libzfs/common/libzfs.h
===================================================================
--- trunk/cddl/contrib/opensolaris/lib/libzfs/common/libzfs.h 2018-06-02 16:07:17 UTC (rev 10228)
+++ trunk/cddl/contrib/opensolaris/lib/libzfs/common/libzfs.h 2018-06-02 16:07:30 UTC (rev 10229)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*
* CDDL HEADER START
*
@@ -21,13 +22,13 @@
/*
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
- * Copyright 2011 Nexenta Systems, Inc. All rights reserved.
- * Copyright (c) 2011 Pawel Jakub Dawidek <pawel at dawidek.net>.
- * All rights reserved.
- * Copyright (c) 2012 by Delphix. All rights reserved.
+ * Copyright (c) 2011 Pawel Jakub Dawidek. All rights reserved.
+ * Copyright (c) 2011, 2015 by Delphix. All rights reserved.
* Copyright (c) 2012, Joyent, Inc. All rights reserved.
* Copyright (c) 2012 Martin Matuska <mm at FreeBSD.org>. All rights reserved.
* Copyright (c) 2013 Steven Hartland. All rights reserved.
+ * Copyright (c) 2014 Integros [integros.com]
+ * Copyright 2016 Nexenta Systems, Inc.
*/
#ifndef _LIBZFS_H
@@ -42,6 +43,7 @@
#include <sys/fs/zfs.h>
#include <sys/avl.h>
#include <sys/zfs_ioctl.h>
+#include <libzfs_core.h>
#ifdef __cplusplus
extern "C" {
@@ -50,8 +52,6 @@
/*
* Miscellaneous ZFS constants
*/
-#define ZFS_MAXNAMELEN MAXNAMELEN
-#define ZPOOL_MAXNAMELEN MAXNAMELEN
#define ZFS_MAXPROPLEN MAXPATHLEN
#define ZPOOL_MAXPROPLEN MAXPATHLEN
@@ -193,6 +193,7 @@
extern int libzfs_errno(libzfs_handle_t *);
extern const char *libzfs_error_action(libzfs_handle_t *);
extern const char *libzfs_error_description(libzfs_handle_t *);
+extern int zfs_standard_error(libzfs_handle_t *, int, const char *);
extern void libzfs_mnttab_init(libzfs_handle_t *);
extern void libzfs_mnttab_fini(libzfs_handle_t *);
extern void libzfs_mnttab_cache(libzfs_handle_t *, boolean_t);
@@ -213,6 +214,7 @@
extern const char *zpool_state_to_name(vdev_state_t, vdev_aux_t);
extern const char *zpool_pool_state_to_name(pool_state_t);
extern void zpool_free_handles(libzfs_handle_t *);
+extern int zpool_nextboot(libzfs_handle_t *, uint64_t, uint64_t, const char *);
/*
* Iterate over all active pools in the system.
@@ -219,6 +221,7 @@
*/
typedef int (*zpool_iter_f)(zpool_handle_t *, void *);
extern int zpool_iter(libzfs_handle_t *, zpool_iter_f, void *);
+extern boolean_t zpool_skip_pool(const char *);
/*
* Functions to create and destroy pools
@@ -269,7 +272,7 @@
*/
extern int zpool_set_prop(zpool_handle_t *, const char *, const char *);
extern int zpool_get_prop(zpool_handle_t *, zpool_prop_t, char *,
- size_t proplen, zprop_source_t *);
+ size_t proplen, zprop_source_t *, boolean_t);
extern uint64_t zpool_get_prop_int(zpool_handle_t *, zpool_prop_t,
zprop_source_t *);
@@ -324,8 +327,9 @@
ZPOOL_STATUS_VERSION_OLDER, /* older legacy on-disk version */
ZPOOL_STATUS_FEAT_DISABLED, /* supported features are disabled */
ZPOOL_STATUS_RESILVERING, /* device being resilvered */
- ZPOOL_STATUS_OFFLINE_DEV, /* device online */
+ ZPOOL_STATUS_OFFLINE_DEV, /* device offline */
ZPOOL_STATUS_REMOVED_DEV, /* removed device */
+ ZPOOL_STATUS_NON_NATIVE_ASHIFT, /* (e.g. 512e dev with ashift of 9) */
/*
* Finally, the following indicates a healthy pool.
@@ -408,6 +412,7 @@
extern zfs_type_t zfs_get_type(const zfs_handle_t *);
extern const char *zfs_get_name(const zfs_handle_t *);
extern zpool_handle_t *zfs_get_pool_handle(const zfs_handle_t *);
+extern const char *zfs_get_pool_name(const zfs_handle_t *);
/*
* Property management functions. Some functions are shared with the kernel,
@@ -423,10 +428,11 @@
extern boolean_t zfs_prop_align_right(zfs_prop_t);
extern nvlist_t *zfs_valid_proplist(libzfs_handle_t *, zfs_type_t,
- nvlist_t *, uint64_t, zfs_handle_t *, const char *);
+ nvlist_t *, uint64_t, zfs_handle_t *, zpool_handle_t *, const char *);
extern const char *zfs_prop_to_name(zfs_prop_t);
extern int zfs_prop_set(zfs_handle_t *, const char *, const char *);
+extern int zfs_prop_set_list(zfs_handle_t *, nvlist_t *);
extern int zfs_prop_get(zfs_handle_t *, zfs_prop_t, char *, size_t,
zprop_source_t *, char *, size_t, boolean_t);
extern int zfs_prop_get_recvd(zfs_handle_t *, const char *, char *, size_t,
@@ -462,7 +468,8 @@
boolean_t pl_fixed;
} zprop_list_t;
-extern int zfs_expand_proplist(zfs_handle_t *, zprop_list_t **, boolean_t);
+extern int zfs_expand_proplist(zfs_handle_t *, zprop_list_t **, boolean_t,
+ boolean_t);
extern void zfs_prune_proplist(zfs_handle_t *, uint8_t *);
#define ZFS_MOUNTPOINT_NONE "none"
@@ -535,6 +542,7 @@
extern int zfs_iter_snapshots(zfs_handle_t *, boolean_t, zfs_iter_f, void *);
extern int zfs_iter_snapshots_sorted(zfs_handle_t *, zfs_iter_f, void *);
extern int zfs_iter_snapspec(zfs_handle_t *, const char *, zfs_iter_f, void *);
+extern int zfs_iter_bookmarks(zfs_handle_t *, zfs_iter_f, void *);
typedef struct get_all_cb {
zfs_handle_t **cb_handles;
@@ -603,6 +611,12 @@
/* show progress (ie. -v) */
boolean_t progress;
+
+ /* large blocks (>128K) are permitted */
+ boolean_t largeblock;
+
+ /* WRITE_EMBEDDED records of type DATA are permitted */
+ boolean_t embed_data;
} sendflags_t;
typedef boolean_t (snapfilter_cb_t)(zfs_handle_t *, void *);
@@ -609,6 +623,11 @@
extern int zfs_send(zfs_handle_t *, const char *, const char *,
sendflags_t *, int, snapfilter_cb_t, void *, nvlist_t **);
+extern int zfs_send_one(zfs_handle_t *, const char *, int, enum lzc_send_flags);
+extern int zfs_send_resume(libzfs_handle_t *, sendflags_t *, int outfd,
+ const char *);
+extern nvlist_t *zfs_send_resume_token_to_nvlist(libzfs_handle_t *hdl,
+ const char *token);
extern int zfs_promote(zfs_handle_t *);
extern int zfs_hold(zfs_handle_t *, const char *, const char *,
@@ -649,6 +668,12 @@
/* set "canmount=off" on all modified filesystems */
boolean_t canmountoff;
+ /*
+ * Mark the file systems as "resumable" and do not destroy them if the
+ * receive is interrupted
+ */
+ boolean_t resumable;
+
/* byteswap flag is used internally; callers need not specify */
boolean_t byteswap;
@@ -656,8 +681,8 @@
boolean_t nomount;
} recvflags_t;
-extern int zfs_receive(libzfs_handle_t *, const char *, recvflags_t *,
- int, avl_tree_t *);
+extern int zfs_receive(libzfs_handle_t *, const char *, nvlist_t *,
+ recvflags_t *, int, avl_tree_t *);
typedef enum diff_flags {
ZFS_DIFF_PARSEABLE = 0x1,
@@ -678,6 +703,7 @@
extern boolean_t zfs_dataset_exists(libzfs_handle_t *, const char *,
zfs_type_t);
extern int zfs_spa_version(zfs_handle_t *, int *);
+extern boolean_t zfs_bookmark_exists(const char *path);
/*
* Mount support functions.
@@ -776,10 +802,10 @@
extern boolean_t libzfs_fru_notself(libzfs_handle_t *, const char *);
extern int zpool_fru_set(zpool_handle_t *, uint64_t, const char *);
-#ifndef sun
+#ifndef illumos
extern int zmount(const char *, const char *, int, char *, char *, int, char *,
int);
-#endif /* !sun */
+#endif
#ifdef __cplusplus
}
Modified: trunk/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_changelist.c
===================================================================
--- trunk/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_changelist.c 2018-06-02 16:07:17 UTC (rev 10228)
+++ trunk/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_changelist.c 2018-06-02 16:07:30 UTC (rev 10229)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*
* CDDL HEADER START
*
@@ -24,9 +25,10 @@
* Use is subject to license terms.
*
* Portions Copyright 2007 Ramprakash Jelari
- *
* Copyright (c) 2011 Pawel Jakub Dawidek <pawel at dawidek.net>.
* All rights reserved.
+ * Copyright (c) 2014, 2015 by Delphix. All rights reserved.
+ * Copyright 2016 Igor Kozhukhov <ikozhukhov at gmail.com>
*/
#include <libintl.h>
@@ -136,6 +138,9 @@
case ZFS_PROP_SHARESMB:
(void) zfs_unshare_smb(cn->cn_handle, NULL);
break;
+
+ default:
+ break;
}
}
}
@@ -293,7 +298,7 @@
changelist_rename(prop_changelist_t *clp, const char *src, const char *dst)
{
prop_changenode_t *cn;
- char newname[ZFS_MAXNAMELEN];
+ char newname[ZFS_MAX_DATASET_NAME_LEN];
for (cn = uu_list_first(clp->cl_list); cn != NULL;
cn = uu_list_next(clp->cl_list, cn)) {
Modified: trunk/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_compat.c
===================================================================
--- trunk/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_compat.c 2018-06-02 16:07:17 UTC (rev 10228)
+++ trunk/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_compat.c 2018-06-02 16:07:30 UTC (rev 10229)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*
* CDDL HEADER SART
*
@@ -72,16 +73,32 @@
if (zfs_ioctl_version == ZFS_IOCVER_UNDEF)
zfs_ioctl_version = get_zfs_ioctl_version();
- if (zfs_ioctl_version == ZFS_IOCVER_LZC)
- cflag = ZFS_CMD_COMPAT_LZC;
- else if (zfs_ioctl_version == ZFS_IOCVER_DEADMAN)
- cflag = ZFS_CMD_COMPAT_DEADMAN;
-
- /*
- * If vfs.zfs.version.ioctl is not defined, assume we have v28
- * compatible binaries and use vfs.zfs.version.spa to test for v15
- */
- if (zfs_ioctl_version < ZFS_IOCVER_DEADMAN) {
+ if (zfs_ioctl_version >= ZFS_IOCVER_DEADMAN) {
+ switch (zfs_ioctl_version) {
+ case ZFS_IOCVER_INLANES:
+ cflag = ZFS_CMD_COMPAT_INLANES;
+ break;
+ case ZFS_IOCVER_RESUME:
+ cflag = ZFS_CMD_COMPAT_RESUME;
+ break;
+ case ZFS_IOCVER_EDBP:
+ cflag = ZFS_CMD_COMPAT_EDBP;
+ break;
+ case ZFS_IOCVER_ZCMD:
+ cflag = ZFS_CMD_COMPAT_ZCMD;
+ break;
+ case ZFS_IOCVER_LZC:
+ cflag = ZFS_CMD_COMPAT_LZC;
+ break;
+ case ZFS_IOCVER_DEADMAN:
+ cflag = ZFS_CMD_COMPAT_DEADMAN;
+ break;
+ }
+ } else {
+ /*
+ * If vfs.zfs.version.ioctl is not defined, assume we have v28
+ * compatible binaries and use vfs.zfs.version.spa to test for v15
+ */
cflag = ZFS_CMD_COMPAT_V28;
if (zfs_spa_version < 0)
Modified: trunk/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_compat.h
===================================================================
--- trunk/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_compat.h 2018-06-02 16:07:17 UTC (rev 10228)
+++ trunk/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_compat.h 2018-06-02 16:07:30 UTC (rev 10229)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*
* CDDL HEADER SART
*
Modified: trunk/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_config.c
===================================================================
--- trunk/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_config.c 2018-06-02 16:07:17 UTC (rev 10228)
+++ trunk/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_config.c 2018-06-02 16:07:30 UTC (rev 10229)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*
* CDDL HEADER START
*
@@ -26,6 +27,8 @@
/*
* Copyright (c) 2012 by Delphix. All rights reserved.
+ * Copyright (c) 2015 by Syneto S.R.L. All rights reserved.
+ * Copyright 2016 Nexenta Systems, Inc.
*/
/*
@@ -246,8 +249,9 @@
config = zpool_get_config(zhp, NULL);
}
- verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_FEATURE_STATS,
- &features) == 0);
+ if (nvlist_lookup_nvlist(config, ZPOOL_CONFIG_FEATURE_STATS,
+ &features) != 0)
+ return (NULL);
return (features);
}
@@ -316,8 +320,7 @@
verify(nvlist_lookup_uint64(config,
ZPOOL_CONFIG_POOL_TXG, &newtxg) == 0);
- if (zhp->zpool_old_config != NULL)
- nvlist_free(zhp->zpool_old_config);
+ nvlist_free(zhp->zpool_old_config);
if (oldtxg != newtxg) {
nvlist_free(zhp->zpool_config);
@@ -337,33 +340,47 @@
}
/*
- * If the __ZFS_POOL_RESTRICT environment variable is set we only iterate over
- * pools it lists.
+ * The following environment variables are undocumented
+ * and should be used for testing purposes only:
*
- * This is an undocumented feature for use during testing only.
+ * __ZFS_POOL_EXCLUDE - don't iterate over the pools it lists
+ * __ZFS_POOL_RESTRICT - iterate only over the pools it lists
*
* This function returns B_TRUE if the pool should be skipped
* during iteration.
*/
-static boolean_t
-check_restricted(const char *poolname)
+boolean_t
+zpool_skip_pool(const char *poolname)
{
static boolean_t initialized = B_FALSE;
- static char *restricted = NULL;
+ static const char *exclude = NULL;
+ static const char *restricted = NULL;
const char *cur, *end;
- int len, namelen;
+ int len;
+ int namelen = strlen(poolname);
if (!initialized) {
initialized = B_TRUE;
+ exclude = getenv("__ZFS_POOL_EXCLUDE");
restricted = getenv("__ZFS_POOL_RESTRICT");
}
+ if (exclude != NULL) {
+ cur = exclude;
+ do {
+ end = strchr(cur, ' ');
+ len = (NULL == end) ? strlen(cur) : (end - cur);
+ if (len == namelen && 0 == strncmp(cur, poolname, len))
+ return (B_TRUE);
+ cur += (len + 1);
+ } while (NULL != end);
+ }
+
if (NULL == restricted)
return (B_FALSE);
cur = restricted;
- namelen = strlen(poolname);
do {
end = strchr(cur, ' ');
len = (NULL == end) ? strlen(cur) : (end - cur);
@@ -401,7 +418,7 @@
for (cn = uu_avl_first(hdl->libzfs_ns_avl); cn != NULL;
cn = uu_avl_next(hdl->libzfs_ns_avl, cn)) {
- if (check_restricted(cn->cn_name))
+ if (zpool_skip_pool(cn->cn_name))
continue;
if (zpool_open_silent(hdl, cn->cn_name, &zhp) != 0) {
@@ -439,7 +456,7 @@
for (cn = uu_avl_first(hdl->libzfs_ns_avl); cn != NULL;
cn = uu_avl_next(hdl->libzfs_ns_avl, cn)) {
- if (check_restricted(cn->cn_name))
+ if (zpool_skip_pool(cn->cn_name))
continue;
if ((zhp = make_dataset_handle(hdl, cn->cn_name)) == NULL)
Modified: trunk/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_dataset.c
===================================================================
--- trunk/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_dataset.c 2018-06-02 16:07:17 UTC (rev 10228)
+++ trunk/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_dataset.c 2018-06-02 16:07:30 UTC (rev 10229)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*
* CDDL HEADER START
*
@@ -21,13 +22,15 @@
/*
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2013 by Delphix. All rights reserved.
+ * Copyright (c) 2013, Joyent, Inc. All rights reserved.
+ * Copyright (c) 2011, 2016 by Delphix. All rights reserved.
* Copyright (c) 2012 DEY Storage Systems, Inc. All rights reserved.
- * Copyright 2012 Nexenta Systems, Inc. All rights reserved.
- * Copyright (c) 2011-2012 Pawel Jakub Dawidek <pawel at dawidek.net>.
- * All rights reserved.
- * Copyright (c) 2012 Martin Matuska <mm at FreeBSD.org>. All rights reserved.
+ * Copyright (c) 2011-2012 Pawel Jakub Dawidek. All rights reserved.
+ * Copyright (c) 2013 Martin Matuska. All rights reserved.
* Copyright (c) 2013 Steven Hartland. All rights reserved.
+ * Copyright (c) 2014 Integros [integros.com]
+ * Copyright 2016 Igor Kozhukhov <ikozhukhov at gmail.com>
+ * Copyright 2016 Nexenta Systems, Inc.
*/
#include <ctype.h>
@@ -77,6 +80,12 @@
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:
+ assert(!"unhandled zfs_type_t");
}
return (NULL);
@@ -83,49 +92,6 @@
}
/*
- * Given a path and mask of ZFS types, return a string describing this dataset.
- * This is used when we fail to open a dataset and we cannot get an exact type.
- * We guess what the type would have been based on the path and the mask of
- * acceptable types.
- */
-static const char *
-path_to_str(const char *path, int types)
-{
- /*
- * When given a single type, always report the exact type.
- */
- if (types == ZFS_TYPE_SNAPSHOT)
- return (dgettext(TEXT_DOMAIN, "snapshot"));
- if (types == ZFS_TYPE_FILESYSTEM)
- return (dgettext(TEXT_DOMAIN, "filesystem"));
- if (types == ZFS_TYPE_VOLUME)
- return (dgettext(TEXT_DOMAIN, "volume"));
-
- /*
- * The user is requesting more than one type of dataset. If this is the
- * case, consult the path itself. If we're looking for a snapshot, and
- * a '@' is found, then report it as "snapshot". Otherwise, remove the
- * snapshot attribute and try again.
- */
- if (types & ZFS_TYPE_SNAPSHOT) {
- if (strchr(path, '@') != NULL)
- return (dgettext(TEXT_DOMAIN, "snapshot"));
- return (path_to_str(path, types & ~ZFS_TYPE_SNAPSHOT));
- }
-
- /*
- * The user has requested either filesystems or volumes.
- * We have no way of knowing a priori what type this would be, so always
- * report it as "filesystem" or "volume", our two primitive types.
- */
- if (types & ZFS_TYPE_FILESYSTEM)
- return (dgettext(TEXT_DOMAIN, "filesystem"));
-
- assert(types & ZFS_TYPE_VOLUME);
- return (dgettext(TEXT_DOMAIN, "volume"));
-}
-
-/*
* Validate a ZFS path. This is used even before trying to open the dataset, to
* provide a more meaningful error message. We call zfs_error_aux() to
* explain exactly why the name was not valid.
@@ -186,6 +152,11 @@
zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
"reserved disk name"));
break;
+
+ default:
+ zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
+ "(%d) not defined"), why);
+ break;
}
}
@@ -295,7 +266,7 @@
int len;
zpool_handle_t *zph;
- len = strcspn(zhp->zfs_name, "/@") + 1;
+ len = strcspn(zhp->zfs_name, "/@#") + 1;
pool_name = zfs_alloc(zhp->zfs_hdl, len);
(void) strlcpy(pool_name, zhp->zfs_name, len);
@@ -579,6 +550,70 @@
return (zhp);
}
+boolean_t
+zfs_bookmark_exists(const char *path)
+{
+ nvlist_t *bmarks;
+ nvlist_t *props;
+ char fsname[ZFS_MAX_DATASET_NAME_LEN];
+ char *bmark_name;
+ char *pound;
+ int err;
+ boolean_t rv;
+
+
+ (void) strlcpy(fsname, path, sizeof (fsname));
+ pound = strchr(fsname, '#');
+ if (pound == NULL)
+ return (B_FALSE);
+
+ *pound = '\0';
+ bmark_name = pound + 1;
+ props = fnvlist_alloc();
+ err = lzc_get_bookmarks(fsname, props, &bmarks);
+ nvlist_free(props);
+ if (err != 0) {
+ nvlist_free(bmarks);
+ return (B_FALSE);
+ }
+
+ rv = nvlist_exists(bmarks, bmark_name);
+ nvlist_free(bmarks);
+ return (rv);
+}
+
+zfs_handle_t *
+make_bookmark_handle(zfs_handle_t *parent, const char *path,
+ nvlist_t *bmark_props)
+{
+ zfs_handle_t *zhp = calloc(sizeof (zfs_handle_t), 1);
+
+ if (zhp == NULL)
+ return (NULL);
+
+ /* Fill in the name. */
+ zhp->zfs_hdl = parent->zfs_hdl;
+ (void) strlcpy(zhp->zfs_name, path, sizeof (zhp->zfs_name));
+
+ /* Set the property lists. */
+ if (nvlist_dup(bmark_props, &zhp->zfs_props, 0) != 0) {
+ free(zhp);
+ return (NULL);
+ }
+
+ /* Set the types. */
+ zhp->zfs_head_type = parent->zfs_head_type;
+ zhp->zfs_type = ZFS_TYPE_BOOKMARK;
+
+ if ((zhp->zpool_hdl = zpool_handle(zhp)) == NULL) {
+ nvlist_free(zhp->zfs_props);
+ free(zhp);
+ return (NULL);
+ }
+
+ return (zhp);
+}
+
/*
* Opens the given snapshot, filesystem, or volume. The 'types'
* argument is a mask of acceptable types. The function will print an
@@ -704,7 +739,8 @@
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);
@@ -776,7 +812,8 @@
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);
@@ -825,7 +862,8 @@
*/
nvlist_t *
zfs_valid_proplist(libzfs_handle_t *hdl, zfs_type_t type, nvlist_t *nvl,
- uint64_t zoned, zfs_handle_t *zhp, const char *errbuf)
+ uint64_t zoned, zfs_handle_t *zhp, zpool_handle_t *zpool_hdl,
+ const char *errbuf)
{
nvpair_t *elem;
uint64_t intval;
@@ -1015,24 +1053,39 @@
break;
}
+ case ZFS_PROP_VOLBLOCKSIZE:
case ZFS_PROP_RECORDSIZE:
- case ZFS_PROP_VOLBLOCKSIZE:
- /* must be power of two within SPA_{MIN,MAX}BLOCKSIZE */
+ {
+ int maxbs = SPA_MAXBLOCKSIZE;
+ if (zpool_hdl != NULL) {
+ maxbs = zpool_get_prop_int(zpool_hdl,
+ ZPOOL_PROP_MAXBLOCKSIZE, NULL);
+ }
+ /*
+ * Volumes are limited to a volblocksize of 128KB,
+ * because they typically service workloads with
+ * small random writes, which incur a large performance
+ * penalty with large blocks.
+ */
+ if (prop == ZFS_PROP_VOLBLOCKSIZE)
+ maxbs = SPA_OLD_MAXBLOCKSIZE;
+ /*
+ * The value must be a power of two between
+ * SPA_MINBLOCKSIZE and maxbs.
+ */
if (intval < SPA_MINBLOCKSIZE ||
- intval > SPA_MAXBLOCKSIZE || !ISP2(intval)) {
+ intval > maxbs || !ISP2(intval)) {
zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
- "'%s' must be power of 2 from %u "
- "to %uk"), propname,
- (uint_t)SPA_MINBLOCKSIZE,
- (uint_t)SPA_MAXBLOCKSIZE >> 10);
+ "'%s' must be power of 2 from 512B "
+ "to %uKB"), propname, maxbs >> 10);
(void) zfs_error(hdl, EZFS_BADPROP, errbuf);
goto error;
}
break;
-
+ }
case ZFS_PROP_MLSLABEL:
{
-#ifdef sun
+#ifdef illumos
/*
* Verify the mlslabel string and convert to
* internal hex label string.
@@ -1081,11 +1134,11 @@
"invalid mlslabel '%s'"), strval);
(void) zfs_error(hdl, EZFS_BADPROP, errbuf);
m_label_free(new_sl); /* OK if null */
-#else /* !sun */
+#else /* !illumos */
zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
"mlslabel is not supported on FreeBSD"));
(void) zfs_error(hdl, EZFS_BADPROP, errbuf);
-#endif /* !sun */
+#endif /* illumos */
goto error;
}
@@ -1112,6 +1165,13 @@
"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);
goto error;
@@ -1230,12 +1290,17 @@
}
break;
+
case ZFS_PROP_UTF8ONLY:
chosen_utf = (int)intval;
break;
+
case ZFS_PROP_NORMALIZE:
chosen_normal = (int)intval;
break;
+
+ default:
+ break;
}
/*
@@ -1284,6 +1349,9 @@
goto error;
}
break;
+
+ default:
+ break;
}
}
}
@@ -1323,6 +1391,7 @@
uint64_t old_reservation;
uint64_t new_reservation;
zfs_prop_t resv_prop;
+ nvlist_t *props;
/*
* If this is an existing volume, and someone is setting the volsize,
@@ -1332,16 +1401,25 @@
if (zfs_which_resv_prop(zhp, &resv_prop) < 0)
return (-1);
old_reservation = zfs_prop_get_int(zhp, resv_prop);
- if ((zvol_volsize_to_reservation(old_volsize, zhp->zfs_props) !=
- old_reservation) || nvlist_lookup_uint64(nvl,
- zfs_prop_to_name(resv_prop), &new_reservation) != ENOENT) {
+
+ props = fnvlist_alloc();
+ fnvlist_add_uint64(props, zfs_prop_to_name(ZFS_PROP_VOLBLOCKSIZE),
+ zfs_prop_get_int(zhp, ZFS_PROP_VOLBLOCKSIZE));
+
+ if ((zvol_volsize_to_reservation(old_volsize, props) !=
+ old_reservation) || nvlist_exists(nvl,
+ zfs_prop_to_name(resv_prop))) {
+ fnvlist_free(props);
return (0);
}
if (nvlist_lookup_uint64(nvl, zfs_prop_to_name(ZFS_PROP_VOLSIZE),
- &new_volsize) != 0)
+ &new_volsize) != 0) {
+ fnvlist_free(props);
return (-1);
- new_reservation = zvol_volsize_to_reservation(new_volsize,
- zhp->zfs_props);
+ }
+ new_reservation = zvol_volsize_to_reservation(new_volsize, props);
+ fnvlist_free(props);
+
if (nvlist_add_uint64(nvl, zfs_prop_to_name(resv_prop),
new_reservation) != 0) {
(void) no_memory(zhp->zfs_hdl);
@@ -1400,11 +1478,19 @@
break;
case ERANGE:
- if (prop == ZFS_PROP_COMPRESSION) {
+ case EDOM:
+ if (prop == ZFS_PROP_COMPRESSION ||
+ prop == ZFS_PROP_RECORDSIZE) {
(void) zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
"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);
}
@@ -1440,15 +1526,10 @@
int
zfs_prop_set(zfs_handle_t *zhp, const char *propname, const char *propval)
{
- zfs_cmd_t zc = { 0 };
int ret = -1;
- prop_changelist_t *cl = NULL;
char errbuf[1024];
libzfs_handle_t *hdl = zhp->zfs_hdl;
- nvlist_t *nvl = NULL, *realprops;
- zfs_prop_t prop;
- boolean_t do_prefix = B_TRUE;
- int added_resv;
+ nvlist_t *nvl = NULL;
(void) snprintf(errbuf, sizeof (errbuf),
dgettext(TEXT_DOMAIN, "cannot set property for '%s'"),
@@ -1460,79 +1541,150 @@
goto error;
}
- if ((realprops = zfs_valid_proplist(hdl, zhp->zfs_type, nvl,
- zfs_prop_get_int(zhp, ZFS_PROP_ZONED), zhp, errbuf)) == NULL)
- goto error;
+ ret = zfs_prop_set_list(zhp, nvl);
+error:
nvlist_free(nvl);
- nvl = realprops;
+ return (ret);
+}
- prop = zfs_name_to_prop(propname);
- /* We don't support those properties on FreeBSD. */
- switch (prop) {
- case ZFS_PROP_DEVICES:
- case ZFS_PROP_ISCSIOPTIONS:
- case ZFS_PROP_XATTR:
- case ZFS_PROP_VSCAN:
- case ZFS_PROP_NBMAND:
- case ZFS_PROP_MLSLABEL:
- (void) snprintf(errbuf, sizeof (errbuf),
- "property '%s' not supported on FreeBSD", propname);
- ret = zfs_error(hdl, EZFS_PERM, errbuf);
- goto error;
- }
- if (prop == ZFS_PROP_VOLSIZE) {
- if ((added_resv = zfs_add_synthetic_resv(zhp, nvl)) == -1)
- goto error;
- }
+/*
+ * Given an nvlist of property names and values, set the properties for the
+ * given dataset.
+ */
+int
+zfs_prop_set_list(zfs_handle_t *zhp, nvlist_t *props)
+{
+ zfs_cmd_t zc = { 0 };
+ int ret = -1;
+ prop_changelist_t **cls = NULL;
+ int cl_idx;
+ char errbuf[1024];
+ libzfs_handle_t *hdl = zhp->zfs_hdl;
+ nvlist_t *nvl;
+ int nvl_len;
+ int added_resv = 0;
- if ((cl = changelist_gather(zhp, prop, 0, 0)) == NULL)
- goto error;
+ (void) snprintf(errbuf, sizeof (errbuf),
+ dgettext(TEXT_DOMAIN, "cannot set property for '%s'"),
+ zhp->zfs_name);
- if (prop == ZFS_PROP_MOUNTPOINT && changelist_haszonedchild(cl)) {
- zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
- "child dataset with inherited mountpoint is used "
- "in a non-global zone"));
- ret = zfs_error(hdl, EZFS_ZONED, errbuf);
+ if ((nvl = zfs_valid_proplist(hdl, zhp->zfs_type, props,
+ zfs_prop_get_int(zhp, ZFS_PROP_ZONED), zhp, zhp->zpool_hdl,
+ errbuf)) == NULL)
goto error;
- }
/*
- * We don't want to unmount & remount the dataset when changing
- * its canmount property to 'on' or 'noauto'. We only use
- * the changelist logic to unmount when setting canmount=off.
+ * We have to check for any extra properties which need to be added
+ * before computing the length of the nvlist.
*/
- if (prop == ZFS_PROP_CANMOUNT) {
- uint64_t idx;
- int err = zprop_string_to_index(prop, propval, &idx,
- ZFS_TYPE_DATASET);
- if (err == 0 && idx != ZFS_CANMOUNT_OFF)
- do_prefix = B_FALSE;
+ for (nvpair_t *elem = nvlist_next_nvpair(nvl, NULL);
+ elem != NULL;
+ elem = nvlist_next_nvpair(nvl, elem)) {
+ if (zfs_name_to_prop(nvpair_name(elem)) == ZFS_PROP_VOLSIZE &&
+ (added_resv = zfs_add_synthetic_resv(zhp, nvl)) == -1) {
+ goto error;
+ }
}
-
- if (do_prefix && (ret = changelist_prefix(cl)) != 0)
+ /*
+ * Check how many properties we're setting and allocate an array to
+ * store changelist pointers for postfix().
+ */
+ nvl_len = 0;
+ for (nvpair_t *elem = nvlist_next_nvpair(nvl, NULL);
+ elem != NULL;
+ elem = nvlist_next_nvpair(nvl, elem))
+ nvl_len++;
+ if ((cls = calloc(nvl_len, sizeof (prop_changelist_t *))) == NULL)
goto error;
+ cl_idx = 0;
+ for (nvpair_t *elem = nvlist_next_nvpair(nvl, NULL);
+ elem != NULL;
+ elem = nvlist_next_nvpair(nvl, elem)) {
+
+ zfs_prop_t prop = zfs_name_to_prop(nvpair_name(elem));
+
+ assert(cl_idx < nvl_len);
+ /*
+ * We don't want to unmount & remount the dataset when changing
+ * 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 &&
+ zfs_is_mounted(zhp, NULL))) {
+ cls[cl_idx] = changelist_gather(zhp, prop, 0, 0);
+ if (cls[cl_idx] == NULL)
+ goto error;
+ }
+
+ if (prop == ZFS_PROP_MOUNTPOINT &&
+ changelist_haszonedchild(cls[cl_idx])) {
+ zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
+ "child dataset with inherited mountpoint is used "
+ "in a non-global zone"));
+ ret = zfs_error(hdl, EZFS_ZONED, errbuf);
+ goto error;
+ }
+
+ /* We don't support those properties on FreeBSD. */
+ switch (prop) {
+ case ZFS_PROP_DEVICES:
+ case ZFS_PROP_ISCSIOPTIONS:
+ case ZFS_PROP_XATTR:
+ case ZFS_PROP_VSCAN:
+ case ZFS_PROP_NBMAND:
+ case ZFS_PROP_MLSLABEL:
+ (void) snprintf(errbuf, sizeof (errbuf),
+ "property '%s' not supported on FreeBSD",
+ nvpair_name(elem));
+ ret = zfs_error(hdl, EZFS_PERM, errbuf);
+ goto error;
+ }
+
+ if (cls[cl_idx] != NULL &&
+ (ret = changelist_prefix(cls[cl_idx])) != 0)
+ goto error;
+
+ cl_idx++;
+ }
+ assert(cl_idx == nvl_len);
+
/*
- * Execute the corresponding ioctl() to set this property.
+ * Execute the corresponding ioctl() to set this list of properties.
*/
(void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name));
- if (zcmd_write_src_nvlist(hdl, &zc, nvl) != 0)
+ if ((ret = zcmd_write_src_nvlist(hdl, &zc, nvl)) != 0 ||
+ (ret = zcmd_alloc_dst_nvlist(hdl, &zc, 0)) != 0)
goto error;
ret = zfs_ioctl(hdl, ZFS_IOC_SET_PROP, &zc);
if (ret != 0) {
- zfs_setprop_error(hdl, prop, errno, errbuf);
+ /* Get the list of unset properties back and report them. */
+ nvlist_t *errorprops = NULL;
+ if (zcmd_read_dst_nvlist(hdl, &zc, &errorprops) != 0)
+ goto error;
+ for (nvpair_t *elem = nvlist_next_nvpair(nvl, NULL);
+ elem != NULL;
+ elem = nvlist_next_nvpair(nvl, elem)) {
+ zfs_prop_t prop = zfs_name_to_prop(nvpair_name(elem));
+ zfs_setprop_error(hdl, prop, errno, errbuf);
+ }
+ nvlist_free(errorprops);
+
if (added_resv && errno == ENOSPC) {
/* clean up the volsize property we tried to set */
uint64_t old_volsize = zfs_prop_get_int(zhp,
ZFS_PROP_VOLSIZE);
nvlist_free(nvl);
+ nvl = NULL;
zcmd_free_nvlists(&zc);
+
if (nvlist_alloc(&nvl, NV_UNIQUE_NAME, 0) != 0)
goto error;
if (nvlist_add_uint64(nvl,
@@ -1544,8 +1696,13 @@
(void) zfs_ioctl(hdl, ZFS_IOC_SET_PROP, &zc);
}
} else {
- if (do_prefix)
- ret = changelist_postfix(cl);
+ for (cl_idx = 0; cl_idx < nvl_len; cl_idx++) {
+ if (cls[cl_idx] != NULL) {
+ int clp_err = changelist_postfix(cls[cl_idx]);
+ if (clp_err != 0)
+ ret = clp_err;
+ }
+ }
/*
* Refresh the statistics so the new property value
@@ -1558,8 +1715,13 @@
error:
nvlist_free(nvl);
zcmd_free_nvlists(&zc);
- if (cl)
- changelist_free(cl);
+ if (cls != NULL) {
+ for (cl_idx = 0; cl_idx < nvl_len; cl_idx++) {
+ if (cls[cl_idx] != NULL)
+ changelist_free(cls[cl_idx]);
+ }
+ free(cls);
+ }
return (ret);
}
@@ -1690,22 +1852,21 @@
return (value);
}
-static char *
+static const char *
getprop_string(zfs_handle_t *zhp, zfs_prop_t prop, char **source)
{
nvlist_t *nv;
- char *value;
+ const char *value;
*source = NULL;
if (nvlist_lookup_nvlist(zhp->zfs_props,
zfs_prop_to_name(prop), &nv) == 0) {
- verify(nvlist_lookup_string(nv, ZPROP_VALUE, &value) == 0);
+ value = fnvlist_lookup_string(nv, ZPROP_VALUE);
(void) nvlist_lookup_string(nv, ZPROP_SOURCE, source);
} else {
verify(!zhp->zfs_props_table ||
zhp->zfs_props_table[prop] == B_TRUE);
- if ((value = (char *)zfs_prop_default_string(prop)) == NULL)
- value = "";
+ value = zfs_prop_default_string(prop);
*source = "";
}
@@ -1789,6 +1950,9 @@
mntopt_on = MNTOPT_NBMAND;
mntopt_off = MNTOPT_NONBMAND;
break;
+
+ default:
+ break;
}
/*
@@ -1846,6 +2010,10 @@
case ZFS_PROP_REFQUOTA:
case ZFS_PROP_RESERVATION:
case ZFS_PROP_REFRESERVATION:
+ case ZFS_PROP_FILESYSTEM_LIMIT:
+ case ZFS_PROP_SNAPSHOT_LIMIT:
+ case ZFS_PROP_FILESYSTEM_COUNT:
+ case ZFS_PROP_SNAPSHOT_COUNT:
*val = getprop_uint64(zhp, prop, source);
if (*source == NULL) {
@@ -1880,11 +2048,14 @@
zcmd_free_nvlists(&zc);
return (-1);
}
- if (zplprops)
- nvlist_free(zplprops);
+ nvlist_free(zplprops);
zcmd_free_nvlists(&zc);
break;
+ case ZFS_PROP_INCONSISTENT:
+ *val = zhp->zfs_dmustats.dds_inconsistent;
+ break;
+
default:
switch (zfs_prop_get_type(prop)) {
case PROP_TYPE_NUMBER:
@@ -1898,6 +2069,7 @@
if (zfs_prop_readonly(prop) &&
*source != NULL && (*source)[0] == '\0') {
*source = NULL;
+ return (-1);
}
break;
@@ -2000,7 +2172,7 @@
uint64_t numclones;
nvlist_t *value;
const char *origin;
- char buf[ZFS_MAXNAMELEN];
+ char buf[ZFS_MAX_DATASET_NAME_LEN];
};
int
@@ -2055,7 +2227,7 @@
if (gca.numclones != 0) {
zfs_handle_t *root;
- char pool[ZFS_MAXNAMELEN];
+ char pool[ZFS_MAX_DATASET_NAME_LEN];
char *cp = pool;
/* get the pool name */
@@ -2099,7 +2271,7 @@
{
char *source = NULL;
uint64_t val;
- char *str;
+ const char *str;
const char *strval;
boolean_t received = zfs_is_recvd_props_mode(zhp);
@@ -2169,8 +2341,8 @@
}
if ((zpool_get_prop(zhp->zpool_hdl,
- ZPOOL_PROP_ALTROOT, buf, MAXPATHLEN, NULL)) ||
- (strcmp(root, "-") == 0))
+ ZPOOL_PROP_ALTROOT, buf, MAXPATHLEN, NULL,
+ B_FALSE)) || (strcmp(root, "-") == 0))
root[0] = '\0';
/*
* Special case an alternate root of '/'. This will
@@ -2204,14 +2376,10 @@
break;
case ZFS_PROP_ORIGIN:
- (void) strlcpy(propbuf, getprop_string(zhp, prop, &source),
- proplen);
- /*
- * If there is no parent at all, return failure to indicate that
- * it doesn't apply to this dataset.
- */
- if (propbuf[0] == '\0')
+ str = getprop_string(zhp, prop, &source);
+ if (str == NULL)
return (-1);
+ (void) strlcpy(propbuf, str, proplen);
break;
case ZFS_PROP_CLONES:
@@ -2247,6 +2415,30 @@
}
break;
+ case ZFS_PROP_FILESYSTEM_LIMIT:
+ case ZFS_PROP_SNAPSHOT_LIMIT:
+ case ZFS_PROP_FILESYSTEM_COUNT:
+ case ZFS_PROP_SNAPSHOT_COUNT:
+
+ if (get_numeric_property(zhp, prop, src, &source, &val) != 0)
+ return (-1);
+
+ /*
+ * If limit is UINT64_MAX, we translate this into 'none' (unless
+ * literal is set), and indicate that it's the default value.
+ * Otherwise, we print the number nicely and indicate that it's
+ * set locally.
+ */
+ if (literal) {
+ (void) snprintf(propbuf, proplen, "%llu",
+ (u_longlong_t)val);
+ } else if (val == UINT64_MAX) {
+ (void) strlcpy(propbuf, "none", proplen);
+ } else {
+ zfs_nicenum(val, propbuf, proplen);
+ }
+ break;
+
case ZFS_PROP_REFRATIO:
case ZFS_PROP_COMPRESSRATIO:
if (get_numeric_property(zhp, prop, src, &source, &val) != 0)
@@ -2267,6 +2459,9 @@
case ZFS_TYPE_SNAPSHOT:
str = "snapshot";
break;
+ case ZFS_TYPE_BOOKMARK:
+ str = "bookmark";
+ break;
default:
abort();
}
@@ -2300,7 +2495,7 @@
case ZFS_PROP_MLSLABEL:
{
-#ifdef sun
+#ifdef illumos
m_label_t *new_sl = NULL;
char *ascii = NULL; /* human readable label */
@@ -2334,9 +2529,9 @@
(void) strlcpy(propbuf, ascii, proplen);
free(ascii);
-#else /* !sun */
+#else /* !illumos */
propbuf[0] = '\0';
-#endif /* !sun */
+#endif /* illumos */
}
break;
@@ -2365,8 +2560,10 @@
break;
case PROP_TYPE_STRING:
- (void) strlcpy(propbuf,
- getprop_string(zhp, prop, &source), proplen);
+ str = getprop_string(zhp, prop, &source);
+ if (str == NULL)
+ return (-1);
+ (void) strlcpy(propbuf, str, proplen);
break;
case PROP_TYPE_INDEX:
@@ -2446,7 +2643,7 @@
idmap_id_to_numeric_domain_rid(uid_t id, boolean_t isuser,
char **domainp, idmap_rid_t *ridp)
{
-#ifdef sun
+#ifdef illumos
idmap_get_handle_t *get_hdl = NULL;
idmap_stat status;
int err = EINVAL;
@@ -2471,9 +2668,10 @@
if (get_hdl)
idmap_get_destroy(get_hdl);
return (err);
-#else /* !sun */
+#else /* !illumos */
assert(!"invalid code path");
-#endif /* !sun */
+ return (EINVAL); // silence compiler warning
+#endif /* illumos */
}
/*
@@ -2491,7 +2689,7 @@
boolean_t isuser;
domain[0] = '\0';
-
+ *ridp = 0;
/* Figure out the property type ({user|group}{quota|space}) */
for (type = 0; type < ZFS_NUM_USERQUOTA_PROPS; type++) {
if (strncmp(propname, zfs_userquota_prop_prefixes[type],
@@ -2508,43 +2706,69 @@
cp = strchr(propname, '@') + 1;
if (strchr(cp, '@')) {
-#ifdef sun
+#ifdef illumos
/*
* It's a SID name (eg "user at domain") that needs to be
* turned into S-1-domainID-RID.
*/
- directory_error_t e;
+ int flag = 0;
+ idmap_stat stat, map_stat;
+ uid_t pid;
+ idmap_rid_t rid;
+ idmap_get_handle_t *gh = NULL;
+
+ stat = idmap_get_create(&gh);
+ if (stat != IDMAP_SUCCESS) {
+ idmap_get_destroy(gh);
+ return (ENOMEM);
+ }
if (zoned && getzoneid() == GLOBAL_ZONEID)
return (ENOENT);
if (isuser) {
- e = directory_sid_from_user_name(NULL,
- cp, &numericsid);
+ stat = idmap_getuidbywinname(cp, NULL, flag, &pid);
+ if (stat < 0)
+ return (ENOENT);
+ stat = idmap_get_sidbyuid(gh, pid, flag, &numericsid,
+ &rid, &map_stat);
} else {
- e = directory_sid_from_group_name(NULL,
- cp, &numericsid);
+ stat = idmap_getgidbywinname(cp, NULL, flag, &pid);
+ if (stat < 0)
+ return (ENOENT);
+ stat = idmap_get_sidbygid(gh, pid, flag, &numericsid,
+ &rid, &map_stat);
}
- if (e != NULL) {
- directory_error_free(e);
+ if (stat < 0) {
+ idmap_get_destroy(gh);
return (ENOENT);
}
+ stat = idmap_get_mappings(gh);
+ idmap_get_destroy(gh);
+
+ if (stat < 0) {
+ return (ENOENT);
+ }
if (numericsid == NULL)
return (ENOENT);
cp = numericsid;
+ *ridp = rid;
/* will be further decoded below */
-#else /* !sun */
+#else /* !illumos */
return (ENOENT);
-#endif /* !sun */
+#endif /* illumos */
}
if (strncmp(cp, "S-1-", 4) == 0) {
/* It's a numeric SID (eg "S-1-234-567-89") */
(void) strlcpy(domain, cp, domainlen);
- cp = strrchr(domain, '-');
- *cp = '\0';
- cp++;
-
errno = 0;
- *ridp = strtoull(cp, &end, 10);
+ if (*ridp == 0) {
+ cp = strrchr(domain, '-');
+ *cp = '\0';
+ cp++;
+ *ridp = strtoull(cp, &end, 10);
+ } else {
+ end = "";
+ }
if (numericsid) {
free(numericsid);
numericsid = NULL;
@@ -2718,6 +2942,15 @@
}
/*
+ * 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.
*/
zfs_type_t
@@ -2779,7 +3012,7 @@
boolean_t accept_ancestor, int *prefixlen)
{
zfs_cmd_t zc = { 0 };
- char parent[ZFS_MAXNAMELEN];
+ char parent[ZFS_MAX_DATASET_NAME_LEN];
char *slash;
zfs_handle_t *zhp;
char errbuf[1024];
@@ -2907,7 +3140,7 @@
* up to the prefixlen-long one.
*/
for (cp = target + prefixlen + 1;
- cp = strchr(cp, '/'); *cp = '/', cp++) {
+ (cp = strchr(cp, '/')) != NULL; *cp = '/', cp++) {
*cp = '\0';
@@ -2959,7 +3192,7 @@
{
int prefix;
char *path_copy;
- int rc;
+ int rc = 0;
if (check_parents(hdl, path, NULL, B_TRUE, &prefix) != 0)
return (-1);
@@ -2986,7 +3219,7 @@
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;
(void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN,
"cannot create '%s'"), path);
@@ -3013,13 +3246,27 @@
}
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];
+ (void) strlcpy(pool_path, path, sizeof (pool_path));
+
+ /* truncate pool_path at first slash */
+ char *p = strchr(pool_path, '/');
+ if (p != NULL)
+ *p = '\0';
+
+ zpool_handle_t *zpool_handle = zpool_open(hdl, pool_path);
+
if (props && (props = zfs_valid_proplist(hdl, type, props,
- zoned, NULL, errbuf)) == 0)
+ zoned, NULL, zpool_handle, errbuf)) == 0) {
+ zpool_close(zpool_handle);
return (-1);
+ }
+ zpool_close(zpool_handle);
if (type == ZFS_TYPE_VOLUME) {
/*
@@ -3073,7 +3320,7 @@
/* check for failure */
if (ret != 0) {
- char parent[ZFS_MAXNAMELEN];
+ char parent[ZFS_MAX_DATASET_NAME_LEN];
(void) parent_name(path, parent, sizeof (parent));
switch (errno) {
@@ -3087,15 +3334,6 @@
"parent '%s' is not a filesystem"), parent);
return (zfs_error(hdl, EZFS_BADTYPE, errbuf));
- case EDOM:
- zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
- "volume block size must be power of 2 from "
- "%u to %uk"),
- (uint_t)SPA_MINBLOCKSIZE,
- (uint_t)SPA_MAXBLOCKSIZE >> 10);
-
- return (zfs_error(hdl, EZFS_BADPROP, errbuf));
-
case ENOTSUP:
zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
"pool must be upgraded to set this "
@@ -3129,6 +3367,19 @@
{
zfs_cmd_t zc = { 0 };
+ 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);
+ fnvlist_free(nv);
+ if (error != 0) {
+ return (zfs_standard_error_fmt(zhp->zfs_hdl, errno,
+ 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)) {
@@ -3159,7 +3410,7 @@
zfs_check_snap_cb(zfs_handle_t *zhp, void *arg)
{
struct destroydata *dd = arg;
- char name[ZFS_MAXNAMELEN];
+ char name[ZFS_MAX_DATASET_NAME_LEN];
int rv = 0;
(void) snprintf(name, sizeof (name),
@@ -3204,12 +3455,14 @@
zfs_destroy_snaps_nvl(libzfs_handle_t *hdl, nvlist_t *snaps, boolean_t defer)
{
int ret;
- nvlist_t *errlist;
+ nvlist_t *errlist = NULL;
ret = lzc_destroy_snaps(snaps, defer, &errlist);
- if (ret == 0)
+ if (ret == 0) {
+ nvlist_free(errlist);
return (0);
+ }
if (nvlist_empty(errlist)) {
char errbuf[1024];
@@ -3237,6 +3490,7 @@
}
}
+ nvlist_free(errlist);
return (ret);
}
@@ -3246,7 +3500,7 @@
int
zfs_clone(zfs_handle_t *zhp, const char *target, nvlist_t *props)
{
- char parent[ZFS_MAXNAMELEN];
+ char parent[ZFS_MAX_DATASET_NAME_LEN];
int ret;
char errbuf[1024];
libzfs_handle_t *hdl = zhp->zfs_hdl;
@@ -3277,7 +3531,7 @@
type = ZFS_TYPE_FILESYSTEM;
}
if ((props = zfs_valid_proplist(hdl, type, props, zoned,
- zhp, errbuf)) == NULL)
+ zhp, zhp->zpool_hdl, errbuf)) == NULL)
return (-1);
}
@@ -3376,16 +3630,19 @@
zfs_snapshot_cb(zfs_handle_t *zhp, void *arg)
{
snapdata_t *sd = arg;
- char name[ZFS_MAXNAMELEN];
+ char name[ZFS_MAX_DATASET_NAME_LEN];
int rv = 0;
- (void) snprintf(name, sizeof (name),
- "%s@%s", zfs_get_name(zhp), sd->sd_snapname);
+ if (zfs_prop_get_int(zhp, ZFS_PROP_INCONSISTENT) == 0) {
+ (void) snprintf(name, sizeof (name),
+ "%s@%s", zfs_get_name(zhp), sd->sd_snapname);
- fnvlist_add_boolean(sd->sd_nvl, name);
+ fnvlist_add_boolean(sd->sd_nvl, name);
- rv = zfs_iter_filesystems(zhp, zfs_snapshot_cb, sd);
+ rv = zfs_iter_filesystems(zhp, zfs_snapshot_cb, sd);
+ }
zfs_close(zhp);
+
return (rv);
}
@@ -3418,11 +3675,23 @@
}
}
+ /*
+ * 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);
+
if (props != NULL &&
(props = zfs_valid_proplist(hdl, ZFS_TYPE_SNAPSHOT,
- props, B_FALSE, NULL, errbuf)) == NULL) {
+ props, B_FALSE, NULL, zpool_hdl, errbuf)) == NULL) {
+ zpool_close(zpool_hdl);
return (-1);
}
+ zpool_close(zpool_hdl);
ret = lzc_snapshot(snaps, props, &errors);
@@ -3464,7 +3733,7 @@
{
int ret;
snapdata_t sd = { 0 };
- char fsname[ZFS_MAXNAMELEN];
+ char fsname[ZFS_MAX_DATASET_NAME_LEN];
char *cp;
zfs_handle_t *zhp;
char errbuf[1024];
@@ -3508,45 +3777,44 @@
const char *cb_target; /* the snapshot */
uint64_t cb_create; /* creation time reference */
boolean_t cb_error;
- boolean_t cb_dependent;
boolean_t cb_force;
} rollback_data_t;
static int
-rollback_destroy(zfs_handle_t *zhp, void *data)
+rollback_destroy_dependent(zfs_handle_t *zhp, void *data)
{
rollback_data_t *cbp = data;
+ prop_changelist_t *clp;
- if (!cbp->cb_dependent) {
- if (strcmp(zhp->zfs_name, cbp->cb_target) != 0 &&
- zfs_get_type(zhp) == ZFS_TYPE_SNAPSHOT &&
- zfs_prop_get_int(zhp, ZFS_PROP_CREATETXG) >
- cbp->cb_create) {
+ /* We must destroy this clone; first unmount it */
+ clp = changelist_gather(zhp, ZFS_PROP_NAME, 0,
+ cbp->cb_force ? MS_FORCE: 0);
+ if (clp == NULL || changelist_prefix(clp) != 0) {
+ cbp->cb_error = B_TRUE;
+ zfs_close(zhp);
+ return (0);
+ }
+ if (zfs_destroy(zhp, B_FALSE) != 0)
+ cbp->cb_error = B_TRUE;
+ else
+ changelist_remove(clp, zhp->zfs_name);
+ (void) changelist_postfix(clp);
+ changelist_free(clp);
- cbp->cb_dependent = B_TRUE;
- cbp->cb_error |= zfs_iter_dependents(zhp, B_FALSE,
- rollback_destroy, cbp);
- cbp->cb_dependent = B_FALSE;
+ zfs_close(zhp);
+ return (0);
+}
- cbp->cb_error |= zfs_destroy(zhp, B_FALSE);
- }
- } else {
- /* We must destroy this clone; first unmount it */
- prop_changelist_t *clp;
+static int
+rollback_destroy(zfs_handle_t *zhp, void *data)
+{
+ rollback_data_t *cbp = data;
- clp = changelist_gather(zhp, ZFS_PROP_NAME, 0,
- cbp->cb_force ? MS_FORCE: 0);
- if (clp == NULL || changelist_prefix(clp) != 0) {
- cbp->cb_error = B_TRUE;
- zfs_close(zhp);
- return (0);
- }
- if (zfs_destroy(zhp, B_FALSE) != 0)
- cbp->cb_error = B_TRUE;
- else
- changelist_remove(clp, zhp->zfs_name);
- (void) changelist_postfix(clp);
- changelist_free(clp);
+ if (zfs_prop_get_int(zhp, ZFS_PROP_CREATETXG) > cbp->cb_create) {
+ cbp->cb_error |= zfs_iter_dependents(zhp, B_FALSE,
+ rollback_destroy_dependent, cbp);
+
+ cbp->cb_error |= zfs_destroy(zhp, B_FALSE);
}
zfs_close(zhp);
@@ -3557,8 +3825,8 @@
* Given a dataset, rollback to a specific snapshot, discarding any
* data changes since then and making it the active dataset.
*
- * Any snapshots more recent than the target are destroyed, along with
- * their dependents.
+ * Any snapshots and bookmarks more recent than the target are
+ * destroyed, along with their dependents (i.e. clones).
*/
int
zfs_rollback(zfs_handle_t *zhp, zfs_handle_t *snap, boolean_t force)
@@ -3565,9 +3833,8 @@
{
rollback_data_t cb = { 0 };
int err;
- zfs_cmd_t zc = { 0 };
boolean_t restore_resv = 0;
- uint64_t old_volsize, new_volsize;
+ uint64_t old_volsize = 0, new_volsize;
zfs_prop_t resv_prop;
assert(zhp->zfs_type == ZFS_TYPE_FILESYSTEM ||
@@ -3579,7 +3846,8 @@
cb.cb_force = force;
cb.cb_target = snap->zfs_name;
cb.cb_create = zfs_prop_get_int(snap, ZFS_PROP_CREATETXG);
- (void) zfs_iter_children(zhp, rollback_destroy, &cb);
+ (void) zfs_iter_snapshots(zhp, B_FALSE, rollback_destroy, &cb);
+ (void) zfs_iter_bookmarks(zhp, rollback_destroy, &cb);
if (cb.cb_error)
return (-1);
@@ -3597,13 +3865,6 @@
(old_volsize == zfs_prop_get_int(zhp, resv_prop));
}
- (void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name));
-
- if (ZFS_IS_VOLUME(zhp))
- zc.zc_objset_type = DMU_OST_ZVOL;
- else
- zc.zc_objset_type = DMU_OST_ZFS;
-
/*
* We rely on zfs_iter_children() to verify that there are no
* newer snapshots for the given dataset. Therefore, we can
@@ -3610,9 +3871,9 @@
* simply pass the name on to the ioctl() call. There is still
* an unlikely race condition where the user has taken a
* snapshot since we verified that this was the most recent.
- *
*/
- if ((err = zfs_ioctl(zhp->zfs_hdl, ZFS_IOC_ROLLBACK, &zc)) != 0) {
+ err = lzc_rollback(zhp->zfs_name, NULL, 0);
+ if (err != 0) {
(void) zfs_standard_error_fmt(zhp->zfs_hdl, errno,
dgettext(TEXT_DOMAIN, "cannot rollback '%s'"),
zhp->zfs_name);
@@ -3645,13 +3906,13 @@
zfs_rename(zfs_handle_t *zhp, const char *source, const char *target,
renameflags_t flags)
{
- int ret;
+ int ret = 0;
zfs_cmd_t zc = { 0 };
char *delim;
prop_changelist_t *cl = NULL;
zfs_handle_t *zhrp = NULL;
char *parentname = NULL;
- char parent[ZFS_MAXNAMELEN];
+ char parent[ZFS_MAX_DATASET_NAME_LEN];
char property[ZFS_MAXPROPLEN];
libzfs_handle_t *hdl = zhp->zfs_hdl;
char errbuf[1024];
@@ -3764,7 +4025,6 @@
strcmp(property, "none") == 0)) {
flags.nounmount = B_TRUE;
}
-
if (flags.recurse) {
parentname = zfs_strdup(zhp->zfs_hdl, zhp->zfs_name);
@@ -3779,8 +4039,7 @@
ret = -1;
goto error;
}
-
- } else {
+ } else if (zhp->zfs_type != ZFS_TYPE_SNAPSHOT) {
if ((cl = changelist_gather(zhp, ZFS_PROP_NAME,
flags.nounmount ? CL_GATHER_DONT_UNMOUNT : 0,
flags.forceunmount ? MS_FORCE : 0)) == NULL) {
@@ -3792,6 +4051,7 @@
"child dataset with inherited mountpoint is used "
"in a non-global zone"));
(void) zfs_error(hdl, EZFS_ZONED, errbuf);
+ ret = -1;
goto error;
}
@@ -3832,10 +4092,10 @@
* On failure, we still want to remount any filesystems that
* were previously mounted, so we don't alter the system state.
*/
- if (!flags.recurse)
+ if (cl != NULL)
(void) changelist_postfix(cl);
} else {
- if (!flags.recurse) {
+ if (cl != NULL) {
changelist_rename(cl, zfs_get_name(zhp), target);
ret = changelist_postfix(cl);
}
@@ -3842,13 +4102,13 @@
}
error:
- if (parentname) {
+ if (parentname != NULL) {
free(parentname);
}
- if (zhrp) {
+ if (zhrp != NULL) {
zfs_close(zhrp);
}
- if (cl) {
+ if (cl != NULL) {
changelist_free(cl);
}
return (ret);
@@ -3883,7 +4143,8 @@
* of the RECEIVED column.
*/
int
-zfs_expand_proplist(zfs_handle_t *zhp, zprop_list_t **plp, boolean_t received)
+zfs_expand_proplist(zfs_handle_t *zhp, zprop_list_t **plp, boolean_t received,
+ boolean_t literal)
{
libzfs_handle_t *hdl = zhp->zfs_hdl;
zprop_list_t *entry;
@@ -3945,18 +4206,18 @@
* Now go through and check the width of any non-fixed columns
*/
for (entry = *plp; entry != NULL; entry = entry->pl_next) {
- if (entry->pl_fixed)
+ if (entry->pl_fixed && !literal)
continue;
if (entry->pl_prop != ZPROP_INVAL) {
if (zfs_prop_get(zhp, entry->pl_prop,
- buf, sizeof (buf), NULL, NULL, 0, B_FALSE) == 0) {
+ buf, sizeof (buf), NULL, NULL, 0, literal) == 0) {
if (strlen(buf) > entry->pl_width)
entry->pl_width = strlen(buf);
}
if (received && zfs_prop_get_recvd(zhp,
zfs_prop_to_name(entry->pl_prop),
- buf, sizeof (buf), B_FALSE) == 0)
+ buf, sizeof (buf), literal) == 0)
if (strlen(buf) > entry->pl_recvd_width)
entry->pl_recvd_width = strlen(buf);
} else {
@@ -3969,7 +4230,7 @@
}
if (received && zfs_prop_get_recvd(zhp,
entry->pl_user_prop,
- buf, sizeof (buf), B_FALSE) == 0)
+ buf, sizeof (buf), literal) == 0)
if (strlen(buf) > entry->pl_recvd_width)
entry->pl_recvd_width = strlen(buf);
}
@@ -4029,7 +4290,7 @@
}
}
-#ifdef sun
+#ifdef illumos
static int
zfs_smb_acl_mgmt(libzfs_handle_t *hdl, char *dataset, char *path,
zfs_smb_acl_op_t cmd, char *resource1, char *resource2)
@@ -4045,7 +4306,7 @@
if (cmd == ZFS_SMB_ACL_RENAME) {
if (nvlist_alloc(&nvlist, NV_UNIQUE_NAME, 0) != 0) {
(void) no_memory(hdl);
- return (NULL);
+ return (0);
}
}
@@ -4076,8 +4337,7 @@
return (-1);
}
error = ioctl(hdl->libzfs_fd, ZFS_IOC_SMB_ACL, &zc);
- if (nvlist)
- nvlist_free(nvlist);
+ nvlist_free(nvlist);
return (error);
}
@@ -4111,7 +4371,7 @@
return (zfs_smb_acl_mgmt(hdl, dataset, path, ZFS_SMB_ACL_RENAME,
oldname, newname));
}
-#endif /* sun */
+#endif /* illumos */
int
zfs_userspace(zfs_handle_t *zhp, zfs_userquota_prop_t type,
@@ -4166,7 +4426,7 @@
zfs_hold_one(zfs_handle_t *zhp, void *arg)
{
struct holdarg *ha = arg;
- char name[ZFS_MAXNAMELEN];
+ char name[ZFS_MAX_DATASET_NAME_LEN];
int rv = 0;
(void) snprintf(name, sizeof (name),
@@ -4285,7 +4545,7 @@
zfs_release_one(zfs_handle_t *zhp, void *arg)
{
struct holdarg *ha = arg;
- char name[ZFS_MAXNAMELEN];
+ char name[ZFS_MAX_DATASET_NAME_LEN];
int rv = 0;
nvlist_t *existing_holds;
@@ -4414,7 +4674,7 @@
zc.zc_nvlist_dst_size = nvsz;
zc.zc_nvlist_dst = (uintptr_t)nvbuf;
- (void) strlcpy(zc.zc_name, zhp->zfs_name, ZFS_MAXNAMELEN);
+ (void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name));
if (ioctl(hdl->libzfs_fd, ZFS_IOC_GET_FSACL, &zc) != 0) {
(void) snprintf(errbuf, sizeof (errbuf),
@@ -4606,7 +4866,7 @@
dgettext(TEXT_DOMAIN, "cannot jail '%s'"), zhp->zfs_name);
} else {
(void) snprintf(errbuf, sizeof (errbuf),
- dgettext(TEXT_DOMAIN, "cannot jail '%s'"), zhp->zfs_name);
+ dgettext(TEXT_DOMAIN, "cannot unjail '%s'"), zhp->zfs_name);
}
switch (zhp->zfs_type) {
Modified: trunk/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_diff.c
===================================================================
--- trunk/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_diff.c 2018-06-02 16:07:17 UTC (rev 10228)
+++ trunk/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_diff.c 2018-06-02 16:07:30 UTC (rev 10229)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*
* CDDL HEADER START
*
@@ -21,6 +22,10 @@
/*
* Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright 2015 Nexenta Systems, Inc. All rights reserved.
+ * Copyright (c) 2015 by Delphix. All rights reserved.
+ * Copyright 2016 Joyent, Inc.
+ * Copyright 2016 Igor Kozhukhov <ikozhukhov at gmail.com>
*/
/*
@@ -51,15 +56,6 @@
#define ZDIFF_REMOVED '-'
#define ZDIFF_RENAMED 'R'
-static boolean_t
-do_name_cmp(const char *fpath, const char *tpath)
-{
- char *fname, *tname;
- fname = strrchr(fpath, '/') + 1;
- tname = strrchr(tpath, '/') + 1;
- return (strcmp(fname, tname) == 0);
-}
-
typedef struct differ_info {
zfs_handle_t *zhp;
char *fromsnap;
@@ -135,12 +131,13 @@
static void
stream_bytes(FILE *fp, const char *string)
{
- while (*string) {
- if (*string > ' ' && *string != '\\' && *string < '\177')
- (void) fprintf(fp, "%c", *string++);
- else {
- (void) fprintf(fp, "\\%03hho",
- (unsigned char)*string++);
+ char c;
+
+ while ((c = *string++) != '\0') {
+ if (c > ' ' && c != '\\' && c < '\177') {
+ (void) fprintf(fp, "%c", c);
+ } else {
+ (void) fprintf(fp, "\\%03o", (uint8_t)c);
}
}
}
@@ -257,7 +254,6 @@
write_inuse_diffs_one(FILE *fp, differ_info_t *di, uint64_t dobj)
{
struct zfs_stat fsb, tsb;
- boolean_t same_name;
mode_t fmode, tmode;
char fobjname[MAXPATHLEN], tobjname[MAXPATHLEN];
int fobjerr, tobjerr;
@@ -318,7 +314,6 @@
if (fmode != tmode && fsb.zs_gen == tsb.zs_gen)
tsb.zs_gen++; /* Force a generational difference */
- same_name = do_name_cmp(fobjname, tobjname);
/* Simple modification or no change */
if (fsb.zs_gen == tsb.zs_gen) {
@@ -329,7 +324,7 @@
if (change) {
print_link_change(fp, di, change,
change > 0 ? fobjname : tobjname, &tsb);
- } else if (same_name) {
+ } else if (strcmp(fobjname, tobjname) == 0) {
print_file(fp, di, ZDIFF_MODIFIED, fobjname, &tsb);
} else {
print_rename(fp, di, fobjname, tobjname, &tsb);
@@ -350,7 +345,7 @@
int err;
for (o = dr->ddr_first; o <= dr->ddr_last; o++) {
- if (err = write_inuse_diffs_one(fp, di, o))
+ if ((err = write_inuse_diffs_one(fp, di, o)) != 0)
return (err);
}
return (0);
@@ -494,7 +489,7 @@
(void) strlcat(fullpath, ZDIFF_SHARESDIR, MAXPATHLEN);
if (stat64(fullpath, &sb) != 0) {
-#ifdef sun
+#ifdef illumos
(void) snprintf(di->errbuf, sizeof (di->errbuf),
dgettext(TEXT_DOMAIN, "Cannot stat %s"), fullpath);
return (zfs_error(di->zhp->zfs_hdl, EZFS_DIFF, di->errbuf));
@@ -614,7 +609,7 @@
* not the same dataset name, might be okay if
* tosnap is a clone of a fromsnap descendant.
*/
- char origin[ZFS_MAXNAMELEN];
+ char origin[ZFS_MAX_DATASET_NAME_LEN];
zprop_source_t src;
zfs_handle_t *zhp;
@@ -624,9 +619,12 @@
zhp = zfs_open(hdl, di->ds, ZFS_TYPE_FILESYSTEM);
while (zhp != NULL) {
- (void) zfs_prop_get(zhp, ZFS_PROP_ORIGIN,
- origin, sizeof (origin), &src, NULL, 0, B_FALSE);
-
+ if (zfs_prop_get(zhp, ZFS_PROP_ORIGIN, origin,
+ sizeof (origin), &src, NULL, 0, B_FALSE) != 0) {
+ (void) zfs_close(zhp);
+ zhp = NULL;
+ break;
+ }
if (strncmp(origin, fromsnap, fsnlen) == 0)
break;
Modified: trunk/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_fru.c
===================================================================
--- trunk/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_fru.c 2018-06-02 16:07:17 UTC (rev 10228)
+++ trunk/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_fru.c 2018-06-02 16:07:30 UTC (rev 10229)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*
* CDDL HEADER START
*
@@ -282,7 +283,7 @@
if (hdl->libzfs_fru_hash == NULL &&
(hdl->libzfs_fru_hash =
- calloc(ZFS_FRU_HASH_SIZE * sizeof (void *), 1)) == NULL)
+ calloc(ZFS_FRU_HASH_SIZE, sizeof (void *))) == NULL)
return;
/*
Modified: trunk/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_impl.h
===================================================================
--- trunk/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_impl.h 2018-06-02 16:07:17 UTC (rev 10228)
+++ trunk/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_impl.h 2018-06-02 16:07:30 UTC (rev 10229)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*
* CDDL HEADER SART
*
@@ -21,9 +22,8 @@
/*
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2011 Pawel Jakub Dawidek <pawel at dawidek.net>.
- * All rights reserved.
- * Copyright (c) 2012 by Delphix. All rights reserved.
+ * Copyright (c) 2011 Pawel Jakub Dawidek. All rights reserved.
+ * Copyright (c) 2011, 2015 by Delphix. All rights reserved.
* Copyright (c) 2013 Martin Matuska <mm at FreeBSD.org>. All rights reserved.
*/
@@ -30,11 +30,11 @@
#ifndef _LIBZFS_IMPL_H
#define _LIBZFS_IMPL_H
-#include <sys/dmu.h>
#include <sys/fs/zfs.h>
-#include <sys/zfs_ioctl.h>
#include <sys/spa.h>
#include <sys/nvpair.h>
+#include <sys/dmu.h>
+#include <sys/zfs_ioctl.h>
#include <libshare.h>
#include <libuutil.h>
@@ -87,7 +87,7 @@
struct zfs_handle {
libzfs_handle_t *zfs_hdl;
zpool_handle_t *zpool_hdl;
- char zfs_name[ZFS_MAXNAMELEN];
+ char zfs_name[ZFS_MAX_DATASET_NAME_LEN];
zfs_type_t zfs_type; /* type including snapshot */
zfs_type_t zfs_head_type; /* type excluding snapshot */
dmu_objset_stats_t zfs_dmustats;
@@ -108,7 +108,7 @@
struct zpool_handle {
libzfs_handle_t *zpool_hdl;
zpool_handle_t *zpool_next;
- char zpool_name[ZPOOL_MAXNAMELEN];
+ char zpool_name[ZFS_MAX_DATASET_NAME_LEN];
int zpool_state;
size_t zpool_config_size;
nvlist_t *zpool_config;
@@ -191,6 +191,8 @@
boolean_t isa_child_of(const char *dataset, const char *parent);
zfs_handle_t *make_dataset_handle(libzfs_handle_t *, const char *);
+zfs_handle_t *make_bookmark_handle(zfs_handle_t *, const char *,
+ nvlist_t *props);
int zpool_open_silent(libzfs_handle_t *, const char *, zpool_handle_t **);
Modified: trunk/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_import.c
===================================================================
--- trunk/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_import.c 2018-06-02 16:07:17 UTC (rev 10228)
+++ trunk/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_import.c 2018-06-02 16:07:30 UTC (rev 10229)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*
* CDDL HEADER START
*
@@ -18,10 +19,12 @@
*
* CDDL HEADER END
*/
+
/*
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
- * Copyright 2011 Nexenta Systems, Inc. All rights reserved.
- * Copyright (c) 2012 by Delphix. All rights reserved.
+ * Copyright (c) 2012, 2015 by Delphix. All rights reserved.
+ * Copyright 2015 RackTop Systems.
+ * Copyright 2016 Nexenta Systems, Inc.
*/
/*
@@ -94,6 +97,7 @@
static char *
get_devid(const char *path)
{
+#ifdef have_devid
int fd;
ddi_devid_t devid;
char *minor, *ret;
@@ -113,6 +117,9 @@
(void) close(fd);
return (ret);
+#else
+ return (NULL);
+#endif
}
@@ -194,8 +201,10 @@
if ((devid = get_devid(best->ne_name)) == NULL) {
(void) nvlist_remove_all(nv, ZPOOL_CONFIG_DEVID);
} else {
- if (nvlist_add_string(nv, ZPOOL_CONFIG_DEVID, devid) != 0)
+ if (nvlist_add_string(nv, ZPOOL_CONFIG_DEVID, devid) != 0) {
+ devid_str_free(devid);
return (-1);
+ }
devid_str_free(devid);
}
@@ -432,12 +441,12 @@
pool_entry_t *pe;
vdev_entry_t *ve;
config_entry_t *ce;
- nvlist_t *ret = NULL, *config = NULL, *tmp, *nvtop, *nvroot;
+ nvlist_t *ret = NULL, *config = NULL, *tmp = NULL, *nvtop, *nvroot;
nvlist_t **spares, **l2cache;
uint_t i, nspares, nl2cache;
boolean_t config_seen;
uint64_t best_txg;
- char *name, *hostname;
+ char *name, *hostname = NULL;
uint64_t guid;
uint_t children = 0;
nvlist_t **child = NULL;
@@ -661,8 +670,10 @@
nvlist_add_uint64(holey,
ZPOOL_CONFIG_ID, c) != 0 ||
nvlist_add_uint64(holey,
- ZPOOL_CONFIG_GUID, 0ULL) != 0)
+ ZPOOL_CONFIG_GUID, 0ULL) != 0) {
+ nvlist_free(holey);
goto nomem;
+ }
child[c] = holey;
}
}
@@ -854,6 +865,7 @@
/*
* Given a file descriptor, read the label information and return an nvlist
* describing the configuration, if there is one.
+ * Return 0 on success, or -1 on failure
*/
int
zpool_read_label(int fd, nvlist_t **config)
@@ -866,7 +878,7 @@
*config = NULL;
if (fstat64(fd, &statbuf) == -1)
- return (0);
+ return (-1);
size = P2ALIGN_TYPED(statbuf.st_size, sizeof (vdev_label_t), uint64_t);
if ((label = malloc(sizeof (vdev_label_t))) == NULL)
@@ -900,7 +912,8 @@
free(label);
*config = NULL;
- return (0);
+ errno = ENOENT;
+ return (-1);
}
typedef struct rdsk_node {
@@ -948,7 +961,7 @@
return (rv > 0 ? 1 : -1);
}
-#ifdef sun
+#ifdef illumos
static void
check_one_slice(avl_tree_t *r, char *diskname, uint_t partno,
diskaddr_t size, uint_t blksz)
@@ -971,12 +984,12 @@
(node = avl_find(r, &tmpnode, NULL)))
node->rn_nozpool = B_TRUE;
}
-#endif /* sun */
+#endif /* illumos */
static void
nozpool_all_slices(avl_tree_t *r, const char *sname)
{
-#ifdef sun
+#ifdef illumos
char diskname[MAXNAMELEN];
char *ptr;
int i;
@@ -992,13 +1005,13 @@
ptr[0] = 'p';
for (i = 0; i <= FD_NUMPART; i++)
check_one_slice(r, diskname, i, 0, 1);
-#endif /* sun */
+#endif /* illumos */
}
+#ifdef illumos
static void
check_slices(avl_tree_t *r, int fd, const char *sname)
{
-#ifdef sun
struct extvtoc vtoc;
struct dk_gpt *gpt;
char diskname[MAXNAMELEN];
@@ -1028,8 +1041,8 @@
check_one_slice(r, diskname, i, 0, 1);
efi_free(gpt);
}
-#endif /* sun */
}
+#endif /* illumos */
static void
zpool_open_func(void *arg)
@@ -1059,6 +1072,7 @@
return;
}
/* this file is too small to hold a zpool */
+#ifdef illumos
if (S_ISREG(statbuf.st_mode) &&
statbuf.st_size < SPA_MINDEVSIZE) {
(void) close(fd);
@@ -1070,8 +1084,14 @@
*/
check_slices(rn->rn_avl, fd, rn->rn_name);
}
+#else /* !illumos */
+ if (statbuf.st_size < SPA_MINDEVSIZE) {
+ (void) close(fd);
+ return;
+ }
+#endif /* illumos */
- if ((zpool_read_label(fd, &config)) != 0) {
+ if ((zpool_read_label(fd, &config)) != 0 && errno == ENOMEM) {
(void) close(fd);
(void) no_memory(rn->rn_hdl);
return;
@@ -1078,17 +1098,11 @@
}
(void) close(fd);
-
rn->rn_config = config;
- if (config != NULL) {
- assert(rn->rn_nozpool == B_FALSE);
- }
}
/*
- * Given a file descriptor, clear (zero) the label information. This function
- * is used in the appliance stack as part of the ZFS sysevent module and
- * to implement the "zpool labelclear" command.
+ * Given a file descriptor, clear (zero) the label information.
*/
int
zpool_clear_label(int fd)
@@ -1107,8 +1121,10 @@
for (l = 0; l < VDEV_LABELS; l++) {
if (pwrite64(fd, label, sizeof (vdev_label_t),
- label_offset(size, l)) != sizeof (vdev_label_t))
+ label_offset(size, l)) != sizeof (vdev_label_t)) {
+ free(label);
return (-1);
+ }
}
free(label);
@@ -1126,7 +1142,6 @@
zpool_find_import_impl(libzfs_handle_t *hdl, importargs_t *iarg)
{
int i, dirs = iarg->paths;
- DIR *dirp = NULL;
struct dirent64 *dp;
char path[MAXPATHLEN];
char *end, **dir = iarg->path;
@@ -1154,8 +1169,10 @@
*/
for (i = 0; i < dirs; i++) {
tpool_t *t;
- char *rdsk;
+ char rdsk[MAXPATHLEN];
int dfd;
+ boolean_t config_failed = B_FALSE;
+ DIR *dirp;
/* use realpath to normalize the path */
if (realpath(dir[i], path) == 0) {
@@ -1168,18 +1185,22 @@
*end = 0;
pathleft = &path[sizeof (path)] - end;
+#ifdef illumos
/*
* Using raw devices instead of block devices when we're
* reading the labels skips a bunch of slow operations during
* close(2) processing, so we replace /dev/dsk with /dev/rdsk.
*/
- if (strcmp(path, "/dev/dsk/") == 0)
- rdsk = "/dev/";
+ if (strcmp(path, ZFS_DISK_ROOTD) == 0)
+ (void) strlcpy(rdsk, ZFS_RDISK_ROOTD, sizeof (rdsk));
else
- rdsk = path;
+#endif
+ (void) strlcpy(rdsk, path, sizeof (rdsk));
if ((dfd = open64(rdsk, O_RDONLY)) < 0 ||
(dirp = fdopendir(dfd)) == NULL) {
+ if (dfd >= 0)
+ (void) close(dfd);
zfs_error_aux(hdl, strerror(errno));
(void) zfs_error_fmt(hdl, EZFS_BADPATH,
dgettext(TEXT_DOMAIN, "cannot open '%s'"),
@@ -1261,7 +1282,7 @@
cookie = NULL;
while ((slice = avl_destroy_nodes(&slice_cache,
&cookie)) != NULL) {
- if (slice->rn_config != NULL) {
+ if (slice->rn_config != NULL && !config_failed) {
nvlist_t *config = slice->rn_config;
boolean_t matched = B_TRUE;
@@ -1282,13 +1303,16 @@
}
if (!matched) {
nvlist_free(config);
- config = NULL;
- continue;
+ } else {
+ /*
+ * use the non-raw path for the config
+ */
+ (void) strlcpy(end, slice->rn_name,
+ pathleft);
+ if (add_config(hdl, &pools, path,
+ config) != 0)
+ config_failed = B_TRUE;
}
- /* use the non-raw path for the config */
- (void) strlcpy(end, slice->rn_name, pathleft);
- if (add_config(hdl, &pools, path, config) != 0)
- goto error;
}
free(slice->rn_name);
free(slice);
@@ -1296,7 +1320,9 @@
avl_destroy(&slice_cache);
(void) closedir(dirp);
- dirp = NULL;
+
+ if (config_failed)
+ goto error;
}
ret = get_configs(hdl, &pools, iarg->can_be_active);
@@ -1308,8 +1334,7 @@
venext = ve->ve_next;
for (ce = ve->ve_configs; ce != NULL; ce = cenext) {
cenext = ce->ce_next;
- if (ce->ce_config)
- nvlist_free(ce->ce_config);
+ nvlist_free(ce->ce_config);
free(ce);
}
free(ve);
@@ -1319,14 +1344,10 @@
for (ne = pools.names; ne != NULL; ne = nenext) {
nenext = ne->ne_next;
- if (ne->ne_name)
- free(ne->ne_name);
+ free(ne->ne_name);
free(ne);
}
- if (dirp)
- (void) closedir(dirp);
-
return (ret);
}
@@ -1415,21 +1436,15 @@
elem = NULL;
while ((elem = nvlist_next_nvpair(raw, elem)) != NULL) {
- verify(nvpair_value_nvlist(elem, &src) == 0);
+ src = fnvpair_value_nvlist(elem);
- verify(nvlist_lookup_string(src, ZPOOL_CONFIG_POOL_NAME,
- &name) == 0);
+ name = fnvlist_lookup_string(src, ZPOOL_CONFIG_POOL_NAME);
if (poolname != NULL && strcmp(poolname, name) != 0)
continue;
- verify(nvlist_lookup_uint64(src, ZPOOL_CONFIG_POOL_GUID,
- &this_guid) == 0);
- if (guid != 0) {
- verify(nvlist_lookup_uint64(src, ZPOOL_CONFIG_POOL_GUID,
- &this_guid) == 0);
- if (guid != this_guid)
- continue;
- }
+ this_guid = fnvlist_lookup_uint64(src, ZPOOL_CONFIG_POOL_GUID);
+ if (guid != 0 && guid != this_guid)
+ continue;
if (pool_active(hdl, name, this_guid, &active) != 0) {
nvlist_free(raw);
@@ -1577,7 +1592,7 @@
*inuse = B_FALSE;
- if (zpool_read_label(fd, &config) != 0) {
+ if (zpool_read_label(fd, &config) != 0 && errno == ENOMEM) {
(void) no_memory(hdl);
return (-1);
}
@@ -1606,10 +1621,17 @@
* its state to active.
*/
if (pool_active(hdl, name, guid, &isactive) == 0 && isactive &&
- (zhp = zpool_open_canfail(hdl, name)) != NULL &&
- zpool_get_prop_int(zhp, ZPOOL_PROP_READONLY, NULL))
- stateval = POOL_STATE_ACTIVE;
+ (zhp = zpool_open_canfail(hdl, name)) != NULL) {
+ if (zpool_get_prop_int(zhp, ZPOOL_PROP_READONLY, NULL))
+ stateval = POOL_STATE_ACTIVE;
+ /*
+ * All we needed the zpool handle for is the
+ * readonly prop check.
+ */
+ zpool_close(zhp);
+ }
+
ret = B_TRUE;
break;
@@ -1683,9 +1705,9 @@
cb.cb_type = ZPOOL_CONFIG_SPARES;
if (zpool_iter(hdl, find_aux, &cb) == 1) {
name = (char *)zpool_get_name(cb.cb_zhp);
- ret = TRUE;
+ ret = B_TRUE;
} else {
- ret = FALSE;
+ ret = B_FALSE;
}
break;
@@ -1699,9 +1721,9 @@
cb.cb_type = ZPOOL_CONFIG_L2CACHE;
if (zpool_iter(hdl, find_aux, &cb) == 1) {
name = (char *)zpool_get_name(cb.cb_zhp);
- ret = TRUE;
+ ret = B_TRUE;
} else {
- ret = FALSE;
+ ret = B_FALSE;
}
break;
Modified: trunk/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_iter.c
===================================================================
--- trunk/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_iter.c 2018-06-02 16:07:17 UTC (rev 10228)
+++ trunk/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_iter.c 2018-06-02 16:07:30 UTC (rev 10229)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*
* CDDL HEADER START
*
@@ -21,10 +22,9 @@
/*
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
- * Copyright 2010 Nexenta Systems, Inc. All rights reserved.
- * Copyright (c) 2012 by Delphix. All rights reserved.
- * Copyright (c) 2012 Pawel Jakub Dawidek <pawel at dawidek.net>.
- * All rights reserved.
+ * Copyright (c) 2013, 2015 by Delphix. All rights reserved.
+ * Copyright (c) 2012 Pawel Jakub Dawidek. All rights reserved.
+ * Copyright 2014 Nexenta Systems, Inc. All rights reserved.
*/
#include <stdio.h>
@@ -146,7 +146,8 @@
zfs_handle_t *nzhp;
int ret;
- if (zhp->zfs_type == ZFS_TYPE_SNAPSHOT)
+ if (zhp->zfs_type == ZFS_TYPE_SNAPSHOT ||
+ zhp->zfs_type == ZFS_TYPE_BOOKMARK)
return (0);
zc.zc_simple = simple;
@@ -173,6 +174,56 @@
}
/*
+ * Iterate over all bookmarks
+ */
+int
+zfs_iter_bookmarks(zfs_handle_t *zhp, zfs_iter_f func, void *data)
+{
+ zfs_handle_t *nzhp;
+ nvlist_t *props = NULL;
+ nvlist_t *bmarks = NULL;
+ int err;
+
+ if ((zfs_get_type(zhp) & (ZFS_TYPE_SNAPSHOT | ZFS_TYPE_BOOKMARK)) != 0)
+ return (0);
+
+ /* Setup the requested properties nvlist. */
+ props = fnvlist_alloc();
+ fnvlist_add_boolean(props, zfs_prop_to_name(ZFS_PROP_GUID));
+ fnvlist_add_boolean(props, zfs_prop_to_name(ZFS_PROP_CREATETXG));
+ fnvlist_add_boolean(props, zfs_prop_to_name(ZFS_PROP_CREATION));
+
+ if ((err = lzc_get_bookmarks(zhp->zfs_name, props, &bmarks)) != 0)
+ goto out;
+
+ for (nvpair_t *pair = nvlist_next_nvpair(bmarks, NULL);
+ pair != NULL; pair = nvlist_next_nvpair(bmarks, pair)) {
+ char name[ZFS_MAX_DATASET_NAME_LEN];
+ char *bmark_name;
+ nvlist_t *bmark_props;
+
+ bmark_name = nvpair_name(pair);
+ bmark_props = fnvpair_value_nvlist(pair);
+
+ (void) snprintf(name, sizeof (name), "%s#%s", zhp->zfs_name,
+ bmark_name);
+
+ nzhp = make_bookmark_handle(zhp, name, bmark_props);
+ if (nzhp == NULL)
+ continue;
+
+ if ((err = func(nzhp, data)) != 0)
+ goto out;
+ }
+
+out:
+ fnvlist_free(props);
+ fnvlist_free(bmarks);
+
+ return (err);
+}
+
+/*
* Routines for dealing with the sorted snapshot functionality
*/
typedef struct zfs_node {
@@ -264,7 +315,8 @@
} snapspec_arg_t;
static int
-snapspec_cb(zfs_handle_t *zhp, void *arg) {
+snapspec_cb(zfs_handle_t *zhp, void *arg)
+{
snapspec_arg_t *ssa = arg;
char *shortsnapname;
int err = 0;
@@ -334,7 +386,7 @@
* exists.
*/
if (ssa.ssa_last[0] != '\0') {
- char snapname[ZFS_MAXNAMELEN];
+ char snapname[ZFS_MAX_DATASET_NAME_LEN];
(void) snprintf(snapname, sizeof (snapname),
"%s@%s", zfs_get_name(fs_zhp),
ssa.ssa_last);
@@ -354,7 +406,7 @@
ret = ENOENT;
}
} else {
- char snapname[ZFS_MAXNAMELEN];
+ char snapname[ZFS_MAX_DATASET_NAME_LEN];
zfs_handle_t *snap_zhp;
(void) snprintf(snapname, sizeof (snapname), "%s@%s",
zfs_get_name(fs_zhp), comma_separated);
@@ -406,13 +458,13 @@
iter_dependents_cb(zfs_handle_t *zhp, void *arg)
{
iter_dependents_arg_t *ida = arg;
- int err;
+ int err = 0;
boolean_t first = ida->first;
ida->first = B_FALSE;
if (zhp->zfs_type == ZFS_TYPE_SNAPSHOT) {
err = zfs_iter_clones(zhp, iter_dependents_cb, ida);
- } else {
+ } else if (zhp->zfs_type != ZFS_TYPE_BOOKMARK) {
iter_stack_frame_t isf;
iter_stack_frame_t *f;
@@ -452,8 +504,12 @@
}
ida->stack = isf.next;
}
+
if (!first && err == 0)
err = ida->func(zhp, ida->data);
+ else
+ zfs_close(zhp);
+
return (err);
}
Modified: trunk/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_mount.c
===================================================================
--- trunk/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_mount.c 2018-06-02 16:07:17 UTC (rev 10228)
+++ trunk/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_mount.c 2018-06-02 16:07:30 UTC (rev 10229)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*
* CDDL HEADER START
*
@@ -20,7 +21,11 @@
*/
/*
+ * Copyright 2015 Nexenta Systems, Inc. All rights reserved.
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014 by Delphix. All rights reserved.
+ * Copyright 2016 Igor Kozhukhov <ikozhukhov at gmail.com>
+ * Copyright 2017 RackTop Systems.
*/
/*
@@ -85,7 +90,7 @@
zfs_share_proto_t);
/*
- * The share protocols table must be in the same order as the zfs_share_prot_t
+ * The share protocols table must be in the same order as the zfs_share_proto_t
* enum in libzfs_impl.h
*/
typedef struct {
@@ -138,7 +143,7 @@
*tab = '\0';
if (strcmp(buf, mountpoint) == 0) {
-#ifdef sun
+#ifdef illumos
/*
* the protocol field is the third field
* skip over second field
@@ -171,7 +176,7 @@
return (SHARED_NOT_SHARED);
}
-#ifdef sun
+#ifdef illumos
/*
* Returns true if the specified directory is empty. If we can't open the
* directory at all, return true so that the mount can fail with a more
@@ -234,7 +239,7 @@
zfs_is_mountable(zfs_handle_t *zhp, char *buf, size_t buflen,
zprop_source_t *source)
{
- char sourceloc[ZFS_MAXNAMELEN];
+ char sourceloc[MAXNAMELEN];
zprop_source_t sourcetype;
if (!zfs_prop_valid_for_type(ZFS_PROP_MOUNTPOINT, zhp->zfs_type))
@@ -296,7 +301,7 @@
}
}
-#ifdef sun /* FreeBSD: overlay mounts are not checked. */
+#ifdef illumos /* FreeBSD: overlay mounts are not checked. */
/*
* Determine if the mountpoint is empty. If so, refuse to perform the
* mount. We don't perform this check if MS_OVERLAY is specified, which
@@ -474,7 +479,8 @@
if (!zfs_is_mounted(zhp, &mountpoint))
return (SHARED_NOT_SHARED);
- if (rc = is_shared(zhp->zfs_hdl, mountpoint, proto)) {
+ if ((rc = is_shared(zhp->zfs_hdl, mountpoint, proto))
+ != SHARED_NOT_SHARED) {
if (where != NULL)
*where = mountpoint;
else
@@ -506,7 +512,7 @@
* initialized in _zfs_init_libshare() are actually present.
*/
-#ifdef sun
+#ifdef illumos
static sa_handle_t (*_sa_init)(int);
static void (*_sa_fini)(sa_handle_t);
static sa_share_t (*_sa_find_share)(sa_handle_t, char *);
@@ -533,7 +539,7 @@
static void
_zfs_init_libshare(void)
{
-#ifdef sun
+#ifdef illumos
void *libshare;
char path[MAXPATHLEN];
char isa[MAXISALEN];
@@ -604,7 +610,7 @@
{
int ret = SA_OK;
-#ifdef sun
+#ifdef illumos
if (_sa_init == NULL)
ret = SA_CONFIG_ERR;
@@ -645,7 +651,7 @@
zfs_uninit_libshare(libzfs_handle_t *zhandle)
{
if (zhandle != NULL && zhandle->libzfs_sharehdl != NULL) {
-#ifdef sun
+#ifdef illumos
if (_sa_fini != NULL)
_sa_fini(zhandle->libzfs_sharehdl);
#endif
@@ -662,7 +668,7 @@
int
zfs_parse_options(char *options, zfs_share_proto_t proto)
{
-#ifdef sun
+#ifdef illumos
if (_sa_parse_legacy_options != NULL) {
return (_sa_parse_legacy_options(NULL, options,
proto_table[proto].p_name));
@@ -673,7 +679,7 @@
#endif
}
-#ifdef sun
+#ifdef illumos
/*
* zfs_sa_find_share(handle, path)
*
@@ -715,7 +721,7 @@
return (_sa_disable_share(share, proto));
return (SA_CONFIG_ERR);
}
-#endif /* sun */
+#endif /* illumos */
/*
* Share the given filesystem according to the options in the specified
@@ -736,16 +742,6 @@
if (!zfs_is_mountable(zhp, mountpoint, sizeof (mountpoint), NULL))
return (0);
-#ifdef sun
- if ((ret = zfs_init_libshare(hdl, SA_INIT_SHARE_API)) != SA_OK) {
- (void) zfs_error_fmt(hdl, EZFS_SHARENFSFAILED,
- dgettext(TEXT_DOMAIN, "cannot share '%s': %s"),
- zfs_get_name(zhp), _sa_errorstr != NULL ?
- _sa_errorstr(ret) : "");
- return (-1);
- }
-#endif
-
for (curr_proto = proto; *curr_proto != PROTO_END; curr_proto++) {
/*
* Return success if there are no share options.
@@ -756,6 +752,17 @@
strcmp(shareopts, "off") == 0)
continue;
+#ifdef illumos
+ ret = zfs_init_libshare(hdl, SA_INIT_SHARE_API);
+ if (ret != SA_OK) {
+ (void) zfs_error_fmt(hdl, EZFS_SHARENFSFAILED,
+ dgettext(TEXT_DOMAIN, "cannot share '%s': %s"),
+ zfs_get_name(zhp), _sa_errorstr != NULL ?
+ _sa_errorstr(ret) : "");
+ return (-1);
+ }
+#endif
+
/*
* If the 'zoned' property is set, then zfs_is_mountable()
* will have already bailed out if we are in the global zone.
@@ -765,7 +772,7 @@
if (zfs_prop_get_int(zhp, ZFS_PROP_ZONED))
continue;
-#ifdef sun
+#ifdef illumos
share = zfs_sa_find_share(hdl->libzfs_sharehdl, mountpoint);
if (share == NULL) {
/*
@@ -854,7 +861,7 @@
unshare_one(libzfs_handle_t *hdl, const char *name, const char *mountpoint,
zfs_share_proto_t proto)
{
-#ifdef sun
+#ifdef illumos
sa_share_t share;
int err;
char *mntpt;
@@ -868,7 +875,7 @@
/* make sure libshare initialized */
if ((err = zfs_init_libshare(hdl, SA_INIT_SHARE_API)) != SA_OK) {
free(mntpt); /* don't need the copy anymore */
- return (zfs_error_fmt(hdl, EZFS_SHARENFSFAILED,
+ return (zfs_error_fmt(hdl, proto_table[proto].p_unshare_err,
dgettext(TEXT_DOMAIN, "cannot unshare '%s': %s"),
name, _sa_errorstr(err)));
}
@@ -879,12 +886,13 @@
if (share != NULL) {
err = zfs_sa_disable_share(share, proto_table[proto].p_name);
if (err != SA_OK) {
- return (zfs_error_fmt(hdl, EZFS_UNSHARENFSFAILED,
+ return (zfs_error_fmt(hdl,
+ proto_table[proto].p_unshare_err,
dgettext(TEXT_DOMAIN, "cannot unshare '%s': %s"),
name, _sa_errorstr(err)));
}
} else {
- return (zfs_error_fmt(hdl, EZFS_UNSHARENFSFAILED,
+ return (zfs_error_fmt(hdl, proto_table[proto].p_unshare_err,
dgettext(TEXT_DOMAIN, "cannot unshare '%s': not found"),
name));
}
@@ -1070,6 +1078,17 @@
return (0);
}
+ /*
+ * If this filesystem is inconsistent and has a receive resume
+ * token, we can not mount it.
+ */
+ if (zfs_prop_get_int(zhp, ZFS_PROP_INCONSISTENT) &&
+ zfs_prop_get(zhp, ZFS_PROP_RECEIVE_RESUME_TOKEN,
+ NULL, 0, NULL, NULL, 0, B_TRUE) == 0) {
+ zfs_close(zhp);
+ return (0);
+ }
+
libzfs_add_handle(cbp, zhp);
if (zfs_iter_filesystems(zhp, mount_cb, cbp) != 0) {
zfs_close(zhp);
Modified: trunk/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_pool.c
===================================================================
--- trunk/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_pool.c 2018-06-02 16:07:17 UTC (rev 10228)
+++ trunk/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_pool.c 2018-06-02 16:07:30 UTC (rev 10229)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*
* CDDL HEADER START
*
@@ -21,8 +22,10 @@
/*
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
- * Copyright 2011 Nexenta Systems, Inc. All rights reserved.
- * Copyright (c) 2012 by Delphix. All rights reserved.
+ * Copyright (c) 2011, 2015 by Delphix. All rights reserved.
+ * Copyright (c) 2013, Joyent, Inc. All rights reserved.
+ * Copyright 2016 Nexenta Systems, Inc.
+ * Copyright 2016 Igor Kozhukhov <ikozhukhov at gmail.com>
*/
#include <sys/types.h>
@@ -48,8 +51,6 @@
static int read_efi_label(nvlist_t *config, diskaddr_t *sb);
-#define DISK_ROOT "/dev/dsk"
-#define RDISK_ROOT "/dev/rdsk"
#define BACKUP_SLICE "s2"
typedef struct prop_flags {
@@ -200,6 +201,9 @@
return (gettext("DEGRADED"));
case VDEV_STATE_HEALTHY:
return (gettext("ONLINE"));
+
+ default:
+ break;
}
return (gettext("UNKNOWN"));
@@ -239,7 +243,7 @@
*/
int
zpool_get_prop(zpool_handle_t *zhp, zpool_prop_t prop, char *buf, size_t len,
- zprop_source_t *srctype)
+ zprop_source_t *srctype, boolean_t literal)
{
uint64_t intval;
const char *strval;
@@ -255,7 +259,8 @@
break;
case ZPOOL_PROP_HEALTH:
- (void) strlcpy(buf, "FAULTED", len);
+ (void) strlcpy(buf,
+ zpool_pool_state_to_name(POOL_STATE_UNAVAIL), len);
break;
case ZPOOL_PROP_GUID:
@@ -271,9 +276,7 @@
(void) strlcpy(buf,
zpool_get_prop_string(zhp, prop, &src),
len);
- if (srctype != NULL)
- *srctype = src;
- return (0);
+ break;
}
/* FALLTHROUGH */
default:
@@ -304,21 +307,46 @@
case ZPOOL_PROP_ALLOCATED:
case ZPOOL_PROP_FREE:
case ZPOOL_PROP_FREEING:
+ case ZPOOL_PROP_LEAKED:
+ if (literal) {
+ (void) snprintf(buf, len, "%llu",
+ (u_longlong_t)intval);
+ } else {
+ (void) zfs_nicenum(intval, buf, len);
+ }
+ break;
case ZPOOL_PROP_EXPANDSZ:
- (void) zfs_nicenum(intval, buf, len);
+ if (intval == 0) {
+ (void) strlcpy(buf, "-", len);
+ } else if (literal) {
+ (void) snprintf(buf, len, "%llu",
+ (u_longlong_t)intval);
+ } else {
+ (void) zfs_nicenum(intval, buf, len);
+ }
break;
-
case ZPOOL_PROP_CAPACITY:
- (void) snprintf(buf, len, "%llu%%",
- (u_longlong_t)intval);
+ if (literal) {
+ (void) snprintf(buf, len, "%llu",
+ (u_longlong_t)intval);
+ } else {
+ (void) snprintf(buf, len, "%llu%%",
+ (u_longlong_t)intval);
+ }
break;
-
+ case ZPOOL_PROP_FRAGMENTATION:
+ if (intval == UINT64_MAX) {
+ (void) strlcpy(buf, "-", len);
+ } else {
+ (void) snprintf(buf, len, "%llu%%",
+ (u_longlong_t)intval);
+ }
+ break;
case ZPOOL_PROP_DEDUPRATIO:
(void) snprintf(buf, len, "%llu.%02llux",
(u_longlong_t)(intval / 100),
(u_longlong_t)(intval % 100));
break;
-
case ZPOOL_PROP_HEALTH:
verify(nvlist_lookup_nvlist(zpool_get_config(zhp, NULL),
ZPOOL_CONFIG_VDEV_TREE, &nvroot) == 0);
@@ -377,36 +405,13 @@
return (B_FALSE);
}
-/*
- * Inspect the configuration to determine if any of the devices contain
- * an EFI label.
- */
-static boolean_t
-pool_uses_efi(nvlist_t *config)
-{
-#ifdef sun
- nvlist_t **child;
- uint_t c, children;
-
- if (nvlist_lookup_nvlist_array(config, ZPOOL_CONFIG_CHILDREN,
- &child, &children) != 0)
- return (read_efi_label(config, NULL) >= 0);
-
- for (c = 0; c < children; c++) {
- if (pool_uses_efi(child[c]))
- return (B_TRUE);
- }
-#endif /* sun */
- return (B_FALSE);
-}
-
boolean_t
zpool_is_bootable(zpool_handle_t *zhp)
{
- char bootfs[ZPOOL_MAXNAMELEN];
+ char bootfs[ZFS_MAX_DATASET_NAME_LEN];
return (zpool_get_prop(zhp, ZPOOL_PROP_BOOTFS, bootfs,
- sizeof (bootfs), NULL) == 0 && strncmp(bootfs, "-",
+ sizeof (bootfs), NULL, B_FALSE) == 0 && strncmp(bootfs, "-",
sizeof (bootfs)) != 0);
}
@@ -428,7 +433,6 @@
char *slash, *check;
struct stat64 statbuf;
zpool_handle_t *zhp;
- nvlist_t *nvroot;
if (nvlist_alloc(&retprops, NV_UNIQUE_NAME, 0) != 0) {
(void) no_memory(hdl);
@@ -442,10 +446,9 @@
prop = zpool_name_to_prop(propname);
if (prop == ZPROP_INVAL && zpool_prop_feature(propname)) {
int err;
- zfeature_info_t *feature;
char *fname = strchr(propname, '@') + 1;
- err = zfeature_lookup_name(fname, &feature);
+ err = zfeature_lookup_name(fname, NULL);
if (err != 0) {
ASSERT3U(err, ==, ENOENT);
zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
@@ -548,23 +551,6 @@
(void) zfs_error(hdl, EZFS_OPENFAILED, errbuf);
goto error;
}
- verify(nvlist_lookup_nvlist(zpool_get_config(zhp, NULL),
- ZPOOL_CONFIG_VDEV_TREE, &nvroot) == 0);
-
-#ifdef sun
- /*
- * bootfs property cannot be set on a disk which has
- * been EFI labeled.
- */
- if (pool_uses_efi(nvroot)) {
- zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
- "property '%s' not supported on "
- "EFI labeled devices"), propname);
- (void) zfs_error(hdl, EZFS_POOL_NOTSUP, errbuf);
- zpool_close(zhp);
- goto error;
- }
-#endif /* sun */
zpool_close(zhp);
break;
@@ -645,6 +631,7 @@
goto error;
}
break;
+
case ZPOOL_PROP_READONLY:
if (!flags.import) {
zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
@@ -654,6 +641,21 @@
goto error;
}
break;
+
+ case ZPOOL_PROP_TNAME:
+ if (!flags.create) {
+ zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
+ "property '%s' can only be set at "
+ "creation time"), propname);
+ (void) zfs_error(hdl, EZFS_BADPROP, errbuf);
+ goto error;
+ }
+ break;
+
+ default:
+ zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
+ "property '%s'(%d) not defined"), propname, prop);
+ break;
}
}
@@ -806,7 +808,7 @@
if (entry->pl_prop != ZPROP_INVAL &&
zpool_get_prop(zhp, entry->pl_prop, buf, sizeof (buf),
- NULL) == 0) {
+ NULL, B_FALSE) == 0) {
if (strlen(buf) > entry->pl_width)
entry->pl_width = strlen(buf);
}
@@ -838,14 +840,14 @@
*/
if (supported) {
int ret;
- zfeature_info_t *fi;
+ spa_feature_t fid;
- ret = zfeature_lookup_name(feature, &fi);
+ ret = zfeature_lookup_name(feature, &fid);
if (ret != 0) {
(void) strlcpy(buf, "-", len);
return (ENOTSUP);
}
- feature = fi->fi_guid;
+ feature = spa_feature_table[fid].fi_guid;
}
if (nvlist_lookup_uint64(features, feature, &refcount) == 0)
@@ -962,6 +964,10 @@
"multiple '@' delimiters in name"));
break;
+ default:
+ zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
+ "(%d) not defined"), why);
+ break;
}
}
return (B_FALSE);
@@ -1071,12 +1077,9 @@
void
zpool_close(zpool_handle_t *zhp)
{
- if (zhp->zpool_config)
- nvlist_free(zhp->zpool_config);
- if (zhp->zpool_old_config)
- nvlist_free(zhp->zpool_old_config);
- if (zhp->zpool_props)
- nvlist_free(zhp->zpool_props);
+ nvlist_free(zhp->zpool_config);
+ nvlist_free(zhp->zpool_old_config);
+ nvlist_free(zhp->zpool_props);
free(zhp);
}
@@ -1140,8 +1143,8 @@
zfs_prop_to_name(ZFS_PROP_ZONED), &zonestr) == 0) &&
strcmp(zonestr, "on") == 0);
- if ((zc_fsprops = zfs_valid_proplist(hdl,
- ZFS_TYPE_FILESYSTEM, fsprops, zoned, NULL, msg)) == NULL) {
+ if ((zc_fsprops = zfs_valid_proplist(hdl, ZFS_TYPE_FILESYSTEM,
+ fsprops, zoned, NULL, NULL, msg)) == NULL) {
goto create_failed;
}
if (!zc_props &&
@@ -1177,6 +1180,21 @@
"one or more vdevs refer to the same device"));
return (zfs_error(hdl, EZFS_BADDEV, msg));
+ case ERANGE:
+ /*
+ * This happens if the record size is smaller or larger
+ * than the allowed size range, or not a power of 2.
+ *
+ * NOTE: although zfs_valid_proplist is called earlier,
+ * this case may have slipped through since the
+ * pool does not exist yet and it is therefore
+ * impossible to read properties e.g. max blocksize
+ * from the pool.
+ */
+ zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
+ "record size invalid"));
+ return (zfs_error(hdl, EZFS_BADPROP, msg));
+
case EOVERFLOW:
/*
* This occurs when one of the devices is below
@@ -1287,25 +1305,6 @@
return (zfs_error(hdl, EZFS_BADVERSION, msg));
}
- if (zpool_is_bootable(zhp) && nvlist_lookup_nvlist_array(nvroot,
- ZPOOL_CONFIG_SPARES, &spares, &nspares) == 0) {
- uint64_t s;
-
- for (s = 0; s < nspares; s++) {
- char *path;
-
- if (nvlist_lookup_string(spares[s], ZPOOL_CONFIG_PATH,
- &path) == 0 && pool_uses_efi(spares[s])) {
- zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
- "device '%s' contains an EFI label and "
- "cannot be used on root pools."),
- zpool_vdev_name(hdl, NULL, spares[s],
- B_FALSE));
- return (zfs_error(hdl, EZFS_POOL_NOTSUP, msg));
- }
- }
- }
-
if (zpool_get_prop_int(zhp, ZPOOL_PROP_VERSION, NULL) <
SPA_VERSION_L2CACHE &&
nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_L2CACHE,
@@ -1598,8 +1597,7 @@
ret = zpool_import_props(hdl, config, newname, props,
ZFS_IMPORT_NORMAL);
- if (props)
- nvlist_free(props);
+ nvlist_free(props);
return (ret);
}
@@ -1691,7 +1689,7 @@
thename = origname;
}
- if (props) {
+ if (props != NULL) {
uint64_t version;
prop_flags_t flags = { .create = B_FALSE, .import = B_TRUE };
@@ -1699,12 +1697,13 @@
&version) == 0);
if ((props = zpool_valid_proplist(hdl, origname,
- props, version, flags, errbuf)) == NULL) {
+ props, version, flags, errbuf)) == NULL)
return (-1);
- } else if (zcmd_write_src_nvlist(hdl, &zc, props) != 0) {
+ if (zcmd_write_src_nvlist(hdl, &zc, props) != 0) {
nvlist_free(props);
return (-1);
}
+ nvlist_free(props);
}
(void) strlcpy(zc.zc_name, thename, sizeof (zc.zc_name));
@@ -1713,11 +1712,11 @@
&zc.zc_guid) == 0);
if (zcmd_write_conf_nvlist(hdl, &zc, config) != 0) {
- nvlist_free(props);
+ zcmd_free_nvlists(&zc);
return (-1);
}
if (zcmd_alloc_dst_nvlist(hdl, &zc, zc.zc_nvlist_conf_size * 2) != 0) {
- nvlist_free(props);
+ zcmd_free_nvlists(&zc);
return (-1);
}
@@ -1733,6 +1732,9 @@
error = errno;
(void) zcmd_read_dst_nvlist(hdl, &zc, &nv);
+
+ zcmd_free_nvlists(&zc);
+
zpool_get_rewind_policy(config, &policy);
if (error) {
@@ -1809,7 +1811,12 @@
case EEXIST:
(void) zpool_standard_error(hdl, error, desc);
break;
-
+ case ENAMETOOLONG:
+ zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
+ "new name of at least one dataset is longer than "
+ "the maximum allowable length"));
+ (void) zfs_error(hdl, EZFS_NAMETOOLONG, desc);
+ break;
default:
(void) zpool_standard_error(hdl, error, desc);
zpool_explain_recover(hdl,
@@ -1838,9 +1845,6 @@
return (0);
}
- zcmd_free_nvlists(&zc);
- nvlist_free(props);
-
return (ret);
}
@@ -1892,6 +1896,7 @@
}
}
+#ifdef illumos
/*
* This provides a very minimal check whether a given string is likely a
* c#t#d# style string. Users of this are expected to do their own
@@ -1904,7 +1909,8 @@
* and the like.
*/
static int
-ctd_check_path(char *str) {
+ctd_check_path(char *str)
+{
/*
* If it starts with a slash, check the last component.
*/
@@ -1923,6 +1929,7 @@
}
return (CTD_CHECK(str));
}
+#endif
/*
* Find a vdev that matches the search criteria specified. We use the
@@ -1978,6 +1985,7 @@
*
* Otherwise, all other searches are simple string compares.
*/
+#ifdef illumos
if (strcmp(srchkey, ZPOOL_CONFIG_PATH) == 0 &&
ctd_check_path(val)) {
uint64_t wholedisk = 0;
@@ -2017,6 +2025,9 @@
break;
}
} else if (strcmp(srchkey, ZPOOL_CONFIG_TYPE) == 0 && val) {
+#else
+ if (strcmp(srchkey, ZPOOL_CONFIG_TYPE) == 0 && val) {
+#endif
char *type, *idx, *end, *p;
uint64_t id, vdev_id;
@@ -2273,6 +2284,7 @@
return (ret);
}
} else if (strcmp(type, VDEV_TYPE_MIRROR) == 0 ||
+ strcmp(type, VDEV_TYPE_RAIDZ) == 0 ||
strcmp(type, VDEV_TYPE_REPLACING) == 0 ||
(is_spare = (strcmp(type, VDEV_TYPE_SPARE) == 0))) {
nvlist_t **child;
@@ -2319,11 +2331,9 @@
return (EZFS_INVALCONFIG);
/*
- * root pool can not have EFI labeled disks and can only have
- * a single top-level vdev.
+ * root pool can only have a single top-level vdev.
*/
- if (strcmp(type, VDEV_TYPE_ROOT) != 0 || count != 1 ||
- pool_uses_efi(vdev_root))
+ if (strcmp(type, VDEV_TYPE_ROOT) != 0 || count != 1)
return (EZFS_POOL_INVALARG);
(void) vdev_get_physpaths(child[0], physpath, phypath_size, &rsz,
@@ -2354,7 +2364,7 @@
static int
zpool_relabel_disk(libzfs_handle_t *hdl, const char *name)
{
-#ifdef sun
+#ifdef illumos
char path[MAXPATHLEN];
char errbuf[1024];
int fd, error;
@@ -2364,7 +2374,7 @@
"efi_use_whole_disk")) == NULL)
return (-1);
- (void) snprintf(path, sizeof (path), "%s/%s", RDISK_ROOT, name);
+ (void) snprintf(path, sizeof (path), "%s/%s", ZFS_RDISK_ROOT, name);
if ((fd = open(path, O_RDWR | O_NDELAY)) < 0) {
zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "cannot "
@@ -2384,7 +2394,7 @@
"relabel '%s': unable to read disk capacity"), name);
return (zfs_error(hdl, EZFS_NOCAP, errbuf));
}
-#endif /* sun */
+#endif /* illumos */
return (0);
}
@@ -2440,7 +2450,7 @@
}
if (wholedisk) {
- pathname += strlen(DISK_ROOT) + 1;
+ pathname += strlen(ZFS_DISK_ROOT) + 1;
(void) zpool_relabel_disk(hdl, pathname);
}
}
@@ -2627,16 +2637,6 @@
(void) snprintf(msg, sizeof (msg), dgettext(TEXT_DOMAIN,
"cannot attach %s to %s"), new_disk, old_disk);
- /*
- * If this is a root pool, make sure that we're not attaching an
- * EFI labeled device.
- */
- if (rootpool && pool_uses_efi(nvroot)) {
- zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
- "EFI labeled devices are not supported on root pools."));
- return (zfs_error(hdl, EZFS_POOL_NOTSUP, msg));
- }
-
(void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name));
if ((tgt = zpool_find_vdev(zhp, old_disk, &avail_spare, &l2cache,
&islog)) == 0)
@@ -2926,8 +2926,7 @@
&children) != 0) {
zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
"Source pool is missing vdev tree"));
- if (zc_props)
- nvlist_free(zc_props);
+ nvlist_free(zc_props);
return (-1);
}
@@ -3075,10 +3074,8 @@
free(varray);
}
zcmd_free_nvlists(&zc);
- if (zc_props)
- nvlist_free(zc_props);
- if (newconfig)
- nvlist_free(newconfig);
+ nvlist_free(zc_props);
+ nvlist_free(newconfig);
if (freelist) {
nvlist_free(*newroot);
*newroot = NULL;
@@ -3302,8 +3299,10 @@
if (ret != 0)
return (NULL);
- if ((path = strdup(list[0].devname)) == NULL)
- return (NULL);
+ /*
+ * In a case the strdup() fails, we will just return NULL below.
+ */
+ path = strdup(list[0].devname);
devid_free_nmlist(list);
@@ -3316,6 +3315,7 @@
static char *
path_to_devid(const char *path)
{
+#ifdef have_devid
int fd;
ddi_devid_t devid;
char *minor, *ret;
@@ -3335,6 +3335,9 @@
(void) close(fd);
return (ret);
+#else
+ return (NULL);
+#endif
}
/*
@@ -3436,9 +3439,9 @@
devid_str_free(newdevid);
}
-#ifdef sun
- if (strncmp(path, "/dev/dsk/", 9) == 0)
- path += 9;
+#ifdef illumos
+ if (strncmp(path, ZFS_DISK_ROOTD, strlen(ZFS_DISK_ROOTD)) == 0)
+ path += strlen(ZFS_DISK_ROOTD);
if (nvlist_lookup_uint64(nv, ZPOOL_CONFIG_WHOLE_DISK,
&value) == 0 && value) {
@@ -3461,10 +3464,10 @@
}
return (tmp);
}
-#else /* !sun */
+#else /* !illumos */
if (strncmp(path, _PATH_DEV, sizeof(_PATH_DEV) - 1) == 0)
path += sizeof(_PATH_DEV) - 1;
-#endif /* !sun */
+#endif /* illumos */
} else {
verify(nvlist_lookup_string(nv, ZPOOL_CONFIG_TYPE, &path) == 0);
@@ -3498,9 +3501,9 @@
}
static int
-zbookmark_compare(const void *a, const void *b)
+zbookmark_mem_compare(const void *a, const void *b)
{
- return (memcmp(a, b, sizeof (zbookmark_t)));
+ return (memcmp(a, b, sizeof (zbookmark_phys_t)));
}
/*
@@ -3512,7 +3515,7 @@
{
zfs_cmd_t zc = { 0 };
uint64_t count;
- zbookmark_t *zb = NULL;
+ zbookmark_phys_t *zb = NULL;
int i;
/*
@@ -3525,7 +3528,7 @@
if (count == 0)
return (0);
if ((zc.zc_nvlist_dst = (uintptr_t)zfs_alloc(zhp->zpool_hdl,
- count * sizeof (zbookmark_t))) == (uintptr_t)NULL)
+ count * sizeof (zbookmark_phys_t))) == (uintptr_t)NULL)
return (-1);
zc.zc_nvlist_dst_size = count;
(void) strcpy(zc.zc_name, zhp->zpool_name);
@@ -3534,11 +3537,14 @@
&zc) != 0) {
free((void *)(uintptr_t)zc.zc_nvlist_dst);
if (errno == ENOMEM) {
+ void *dst;
+
count = zc.zc_nvlist_dst_size;
- if ((zc.zc_nvlist_dst = (uintptr_t)
- zfs_alloc(zhp->zpool_hdl, count *
- sizeof (zbookmark_t))) == (uintptr_t)NULL)
+ dst = zfs_alloc(zhp->zpool_hdl, count *
+ sizeof (zbookmark_phys_t));
+ if (dst == NULL)
return (-1);
+ zc.zc_nvlist_dst = (uintptr_t)dst;
} else {
return (-1);
}
@@ -3554,11 +3560,11 @@
* _not_ copied as part of the process. So we point the start of our
* array appropriate and decrement the total number of elements.
*/
- zb = ((zbookmark_t *)(uintptr_t)zc.zc_nvlist_dst) +
+ zb = ((zbookmark_phys_t *)(uintptr_t)zc.zc_nvlist_dst) +
zc.zc_nvlist_dst_size;
count -= zc.zc_nvlist_dst_size;
- qsort(zb, count, sizeof (zbookmark_t), zbookmark_compare);
+ qsort(zb, count, sizeof (zbookmark_phys_t), zbookmark_mem_compare);
verify(nvlist_alloc(nverrlistp, 0, KM_SLEEP) == 0);
@@ -3736,7 +3742,9 @@
return (0);
}
-#define HIS_BUF_LEN (128*1024)
+/* from spa_history.c: spa_history_create_obj() */
+#define HIS_BUF_LEN_DEF (128 << 10)
+#define HIS_BUF_LEN_MAX (1 << 30)
/*
* Retrieve the command history of a pool.
@@ -3744,14 +3752,18 @@
int
zpool_get_history(zpool_handle_t *zhp, nvlist_t **nvhisp)
{
- char buf[HIS_BUF_LEN];
+ char *buf;
+ uint64_t buflen = HIS_BUF_LEN_DEF;
uint64_t off = 0;
nvlist_t **records = NULL;
uint_t numrecords = 0;
int err, i;
+ buf = malloc(buflen);
+ if (buf == NULL)
+ return (ENOMEM);
do {
- uint64_t bytes_read = sizeof (buf);
+ uint64_t bytes_read = buflen;
uint64_t leftover;
if ((err = get_history(zhp, buf, &off, &bytes_read)) != 0)
@@ -3758,7 +3770,7 @@
break;
/* if nothing else was read in, we're at EOF, just return */
- if (!bytes_read)
+ if (bytes_read == 0)
break;
if ((err = zpool_history_unpack(buf, bytes_read,
@@ -3765,10 +3777,26 @@
&leftover, &records, &numrecords)) != 0)
break;
off -= leftover;
+ if (leftover == bytes_read) {
+ /*
+ * no progress made, because buffer is not big enough
+ * to hold this record; resize and retry.
+ */
+ buflen *= 2;
+ free(buf);
+ buf = NULL;
+ if ((buflen >= HIS_BUF_LEN_MAX) ||
+ ((buf = malloc(buflen)) == NULL)) {
+ err = ENOMEM;
+ break;
+ }
+ }
/* CONSTCOND */
} while (1);
+ free(buf);
+
if (!err) {
verify(nvlist_alloc(nvhisp, NV_UNIQUE_NAME, 0) == 0);
verify(nvlist_add_nvlist_array(*nvhisp, ZPOOL_HIST_RECORD,
@@ -3788,7 +3816,7 @@
zfs_cmd_t zc = { 0 };
boolean_t mounted = B_FALSE;
char *mntpnt = NULL;
- char dsname[MAXNAMELEN];
+ char dsname[ZFS_MAX_DATASET_NAME_LEN];
if (dsobj == 0) {
/* special case for the MOS */
@@ -3829,7 +3857,7 @@
free(mntpnt);
}
-#ifdef sun
+#ifdef illumos
/*
* Read the EFI label from the config, if a label does not exist then
* pass back the error to the caller. If the caller has passed a non-NULL
@@ -3847,7 +3875,7 @@
if (nvlist_lookup_string(config, ZPOOL_CONFIG_PATH, &path) != 0)
return (err);
- (void) snprintf(diskname, sizeof (diskname), "%s%s", RDISK_ROOT,
+ (void) snprintf(diskname, sizeof (diskname), "%s%s", ZFS_RDISK_ROOT,
strrchr(path, '/'));
if ((fd = open(diskname, O_RDONLY|O_NDELAY)) >= 0) {
struct dk_gpt *vtoc;
@@ -3894,7 +3922,7 @@
}
return (MAXOFFSET_T);
}
-#endif /* sun */
+#endif /* illumos */
/*
* Label an individual disk. The name provided is the short name,
@@ -3903,7 +3931,7 @@
int
zpool_label_disk(libzfs_handle_t *hdl, zpool_handle_t *zhp, const char *name)
{
-#ifdef sun
+#ifdef illumos
char path[MAXPATHLEN];
struct dk_gpt *vtoc;
int fd;
@@ -3919,13 +3947,6 @@
if (zhp) {
nvlist_t *nvroot;
- if (zpool_is_bootable(zhp)) {
- zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
- "EFI labeled devices are not supported on root "
- "pools."));
- return (zfs_error(hdl, EZFS_POOL_NOTSUP, errbuf));
- }
-
verify(nvlist_lookup_nvlist(zhp->zpool_config,
ZPOOL_CONFIG_VDEV_TREE, &nvroot) == 0);
@@ -3939,7 +3960,7 @@
start_block = NEW_START_BLOCK;
}
- (void) snprintf(path, sizeof (path), "%s/%s%s", RDISK_ROOT, name,
+ (void) snprintf(path, sizeof (path), "%s/%s%s", ZFS_RDISK_ROOT, name,
BACKUP_SLICE);
if ((fd = open(path, O_RDWR | O_NDELAY)) < 0) {
@@ -4008,7 +4029,7 @@
(void) close(fd);
efi_free(vtoc);
-#endif /* sun */
+#endif /* illumos */
return (0);
}
@@ -4020,9 +4041,7 @@
uint_t children, c;
verify(nvlist_lookup_string(config, ZPOOL_CONFIG_TYPE, &type) == 0);
- if (strcmp(type, VDEV_TYPE_RAIDZ) == 0 ||
- strcmp(type, VDEV_TYPE_FILE) == 0 ||
- strcmp(type, VDEV_TYPE_LOG) == 0 ||
+ if (strcmp(type, VDEV_TYPE_FILE) == 0 ||
strcmp(type, VDEV_TYPE_HOLE) == 0 ||
strcmp(type, VDEV_TYPE_MISSING) == 0) {
zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
@@ -4041,8 +4060,12 @@
}
/*
- * check if this zvol is allowable for use as a dump device; zero if
- * it is, > 0 if it isn't, < 0 if it isn't a zvol
+ * Check if this zvol is allowable for use as a dump device; zero if
+ * it is, > 0 if it isn't, < 0 if it isn't a zvol.
+ *
+ * Allowable storage configurations include mirrors, all raidz variants, and
+ * pools with log, cache, and spare devices. Pools which are backed by files or
+ * have missing/hole vdevs are not suitable.
*/
int
zvol_check_dump_config(char *arg)
@@ -4054,7 +4077,7 @@
uint_t toplevels;
libzfs_handle_t *hdl;
char errbuf[1024];
- char poolname[ZPOOL_MAXNAMELEN];
+ char poolname[ZFS_MAX_DATASET_NAME_LEN];
int pathlen = strlen(ZVOL_FULL_DEV_DIR);
int ret = 1;
@@ -4077,7 +4100,7 @@
"malformed dataset name"));
(void) zfs_error(hdl, EZFS_INVALIDNAME, errbuf);
return (1);
- } else if (p - volname >= ZFS_MAXNAMELEN) {
+ } else if (p - volname >= ZFS_MAX_DATASET_NAME_LEN) {
zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
"dataset name is too long"));
(void) zfs_error(hdl, EZFS_NAMETOOLONG, errbuf);
@@ -4104,12 +4127,6 @@
verify(nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_CHILDREN,
&top, &toplevels) == 0);
- if (toplevels != 1) {
- zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
- "'%s' has multiple top level vdevs"), poolname);
- (void) zfs_error(hdl, EZFS_DEVOVERFLOW, errbuf);
- goto out;
- }
if (!supported_dump_vdev_type(hdl, top[0], errbuf)) {
goto out;
@@ -4122,3 +4139,25 @@
libzfs_fini(hdl);
return (ret);
}
+
+int
+zpool_nextboot(libzfs_handle_t *hdl, uint64_t pool_guid, uint64_t dev_guid,
+ const char *command)
+{
+ zfs_cmd_t zc = { 0 };
+ nvlist_t *args;
+ char *packed;
+ size_t size;
+ int error;
+
+ args = fnvlist_alloc();
+ fnvlist_add_uint64(args, ZPOOL_CONFIG_POOL_GUID, pool_guid);
+ fnvlist_add_uint64(args, ZPOOL_CONFIG_GUID, dev_guid);
+ fnvlist_add_string(args, "command", command);
+ error = zcmd_write_src_nvlist(hdl, &zc, args);
+ if (error == 0)
+ error = ioctl(hdl->libzfs_fd, ZFS_IOC_NEXTBOOT, &zc);
+ zcmd_free_nvlists(&zc);
+ nvlist_free(args);
+ return (error);
+}
Modified: trunk/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_sendrecv.c
===================================================================
--- trunk/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_sendrecv.c 2018-06-02 16:07:17 UTC (rev 10228)
+++ trunk/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_sendrecv.c 2018-06-02 16:07:30 UTC (rev 10229)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*
* CDDL HEADER START
*
@@ -21,11 +22,13 @@
/*
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2012 by Delphix. All rights reserved.
+ * Copyright (c) 2011, 2015 by Delphix. All rights reserved.
* Copyright (c) 2012, Joyent, Inc. All rights reserved.
- * Copyright (c) 2012 Pawel Jakub Dawidek <pawel at dawidek.net>.
- * All rights reserved.
+ * Copyright (c) 2012 Pawel Jakub Dawidek. All rights reserved.
* Copyright (c) 2013 Steven Hartland. All rights reserved.
+ * Copyright 2015, OmniTI Computer Consulting, Inc. All rights reserved.
+ * Copyright (c) 2014 Integros [integros.com]
+ * Copyright 2016 Igor Kozhukhov <ikozhukhov at gmail.com>
*/
#include <assert.h>
@@ -45,11 +48,13 @@
#include <time.h>
#include <libzfs.h>
+#include <libzfs_core.h>
#include "zfs_namecheck.h"
#include "zfs_prop.h"
#include "zfs_fletcher.h"
#include "libzfs_impl.h"
+#include <zlib.h>
#include <sha2.h>
#include <sys/zio_checksum.h>
#include <sys/ddt.h>
@@ -63,8 +68,11 @@
/* We need to use something for ENODATA. */
#define ENODATA EIDRM
-static int zfs_receive_impl(libzfs_handle_t *, const char *, recvflags_t *,
- int, const char *, nvlist_t *, avl_tree_t *, char **, int, uint64_t *);
+static int zfs_receive_impl(libzfs_handle_t *, const char *, const char *,
+ recvflags_t *, int, const char *, nvlist_t *, avl_tree_t *, char **, int,
+ uint64_t *, const char *);
+static int guid_to_name(libzfs_handle_t *, const char *,
+ uint64_t, boolean_t, char *);
static const zio_cksum_t zero_cksum = { 0 };
@@ -187,10 +195,28 @@
}
static int
-cksum_and_write(const void *buf, uint64_t len, zio_cksum_t *zc, int outfd)
+dump_record(dmu_replay_record_t *drr, void *payload, int payload_len,
+ zio_cksum_t *zc, int outfd)
{
- fletcher_4_incremental_native(buf, len, zc);
- return (write(outfd, buf, len));
+ ASSERT3U(offsetof(dmu_replay_record_t, drr_u.drr_checksum.drr_checksum),
+ ==, sizeof (dmu_replay_record_t) - sizeof (zio_cksum_t));
+ fletcher_4_incremental_native(drr,
+ offsetof(dmu_replay_record_t, drr_u.drr_checksum.drr_checksum), zc);
+ if (drr->drr_type != DRR_BEGIN) {
+ ASSERT(ZIO_CHECKSUM_IS_ZERO(&drr->drr_u.
+ drr_checksum.drr_checksum));
+ drr->drr_u.drr_checksum.drr_checksum = *zc;
+ }
+ fletcher_4_incremental_native(&drr->drr_u.drr_checksum.drr_checksum,
+ sizeof (zio_cksum_t), zc);
+ if (write(outfd, drr, sizeof (*drr)) == -1)
+ return (errno);
+ if (payload_len != 0) {
+ fletcher_4_incremental_native(payload, payload_len, zc);
+ if (write(outfd, payload, payload_len) == -1)
+ return (errno);
+ }
+ return (0);
}
/*
@@ -214,18 +240,11 @@
cksummer(void *arg)
{
dedup_arg_t *dda = arg;
- char *buf = malloc(1<<20);
+ char *buf = zfs_alloc(dda->dedup_hdl, SPA_MAXBLOCKSIZE);
dmu_replay_record_t thedrr;
dmu_replay_record_t *drr = &thedrr;
- struct drr_begin *drrb = &thedrr.drr_u.drr_begin;
- struct drr_end *drre = &thedrr.drr_u.drr_end;
- struct drr_object *drro = &thedrr.drr_u.drr_object;
- struct drr_write *drrw = &thedrr.drr_u.drr_write;
- struct drr_spill *drrs = &thedrr.drr_u.drr_spill;
FILE *ofp;
int outfd;
- dmu_replay_record_t wbr_drr = {0};
- struct drr_write_byref *wbr_drrr = &wbr_drr.drr_u.drr_write_byref;
dedup_table_t ddt;
zio_cksum_t stream_cksum;
uint64_t physmem = sysconf(_SC_PHYS_PAGES) * sysconf(_SC_PAGESIZE);
@@ -232,10 +251,10 @@
uint64_t numbuckets;
ddt.max_ddt_size =
- MAX((physmem * MAX_DDT_PHYSMEM_PERCENT)/100,
- SMALLEST_POSSIBLE_MAX_DDT_MB<<20);
+ MAX((physmem * MAX_DDT_PHYSMEM_PERCENT) / 100,
+ SMALLEST_POSSIBLE_MAX_DDT_MB << 20);
- numbuckets = ddt.max_ddt_size/(sizeof (dedup_entry_t));
+ numbuckets = ddt.max_ddt_size / (sizeof (dedup_entry_t));
/*
* numbuckets must be a power of 2. Increase number to
@@ -251,20 +270,20 @@
ddt.numhashbits = high_order_bit(numbuckets) - 1;
ddt.ddt_full = B_FALSE;
- /* Initialize the write-by-reference block. */
- wbr_drr.drr_type = DRR_WRITE_BYREF;
- wbr_drr.drr_payloadlen = 0;
-
outfd = dda->outputfd;
ofp = fdopen(dda->inputfd, "r");
- while (ssread(drr, sizeof (dmu_replay_record_t), ofp) != 0) {
+ while (ssread(drr, sizeof (*drr), ofp) != 0) {
switch (drr->drr_type) {
case DRR_BEGIN:
{
- int fflags;
+ struct drr_begin *drrb = &drr->drr_u.drr_begin;
+ int fflags;
+ int sz = 0;
ZIO_SET_CHECKSUM(&stream_cksum, 0, 0, 0, 0);
+ ASSERT3U(drrb->drr_magic, ==, DMU_BACKUP_MAGIC);
+
/* set the DEDUP feature flag for this stream */
fflags = DMU_GET_FEATUREFLAGS(drrb->drr_versioninfo);
fflags |= (DMU_BACKUP_FEATURE_DEDUP |
@@ -271,35 +290,30 @@
DMU_BACKUP_FEATURE_DEDUPPROPS);
DMU_SET_FEATUREFLAGS(drrb->drr_versioninfo, fflags);
- if (cksum_and_write(drr, sizeof (dmu_replay_record_t),
- &stream_cksum, outfd) == -1)
- goto out;
- if (DMU_GET_STREAM_HDRTYPE(drrb->drr_versioninfo) ==
- DMU_COMPOUNDSTREAM && drr->drr_payloadlen != 0) {
- int sz = drr->drr_payloadlen;
+ if (drr->drr_payloadlen != 0) {
+ sz = drr->drr_payloadlen;
- if (sz > 1<<20) {
- free(buf);
- buf = malloc(sz);
+ if (sz > SPA_MAXBLOCKSIZE) {
+ buf = zfs_realloc(dda->dedup_hdl, buf,
+ SPA_MAXBLOCKSIZE, sz);
}
(void) ssread(buf, sz, ofp);
if (ferror(stdin))
perror("fread");
- if (cksum_and_write(buf, sz, &stream_cksum,
- outfd) == -1)
- goto out;
}
+ if (dump_record(drr, buf, sz, &stream_cksum,
+ outfd) != 0)
+ goto out;
break;
}
case DRR_END:
{
+ struct drr_end *drre = &drr->drr_u.drr_end;
/* use the recalculated checksum */
- ZIO_SET_CHECKSUM(&drre->drr_checksum,
- stream_cksum.zc_word[0], stream_cksum.zc_word[1],
- stream_cksum.zc_word[2], stream_cksum.zc_word[3]);
- if ((write(outfd, drr,
- sizeof (dmu_replay_record_t))) == -1)
+ drre->drr_checksum = stream_cksum;
+ if (dump_record(drr, NULL, 0, &stream_cksum,
+ outfd) != 0)
goto out;
break;
}
@@ -306,29 +320,25 @@
case DRR_OBJECT:
{
- if (cksum_and_write(drr, sizeof (dmu_replay_record_t),
- &stream_cksum, outfd) == -1)
- goto out;
+ struct drr_object *drro = &drr->drr_u.drr_object;
if (drro->drr_bonuslen > 0) {
(void) ssread(buf,
P2ROUNDUP((uint64_t)drro->drr_bonuslen, 8),
ofp);
- if (cksum_and_write(buf,
- P2ROUNDUP((uint64_t)drro->drr_bonuslen, 8),
- &stream_cksum, outfd) == -1)
- goto out;
}
+ if (dump_record(drr, buf,
+ P2ROUNDUP((uint64_t)drro->drr_bonuslen, 8),
+ &stream_cksum, outfd) != 0)
+ goto out;
break;
}
case DRR_SPILL:
{
- if (cksum_and_write(drr, sizeof (dmu_replay_record_t),
- &stream_cksum, outfd) == -1)
- goto out;
+ struct drr_spill *drrs = &drr->drr_u.drr_spill;
(void) ssread(buf, drrs->drr_length, ofp);
- if (cksum_and_write(buf, drrs->drr_length,
- &stream_cksum, outfd) == -1)
+ if (dump_record(drr, buf, drrs->drr_length,
+ &stream_cksum, outfd) != 0)
goto out;
break;
}
@@ -335,8 +345,8 @@
case DRR_FREEOBJECTS:
{
- if (cksum_and_write(drr, sizeof (dmu_replay_record_t),
- &stream_cksum, outfd) == -1)
+ if (dump_record(drr, NULL, 0, &stream_cksum,
+ outfd) != 0)
goto out;
break;
}
@@ -343,6 +353,7 @@
case DRR_WRITE:
{
+ struct drr_write *drrw = &drr->drr_u.drr_write;
dataref_t dataref;
(void) ssread(buf, drrw->drr_length, ofp);
@@ -380,7 +391,13 @@
if (ddt_update(dda->dedup_hdl, &ddt,
&drrw->drr_key.ddk_cksum, drrw->drr_key.ddk_prop,
&dataref)) {
+ dmu_replay_record_t wbr_drr = {0};
+ struct drr_write_byref *wbr_drrr =
+ &wbr_drr.drr_u.drr_write_byref;
+
/* block already present in stream */
+ wbr_drr.drr_type = DRR_WRITE_BYREF;
+
wbr_drrr->drr_object = drrw->drr_object;
wbr_drrr->drr_offset = drrw->drr_offset;
wbr_drrr->drr_length = drrw->drr_length;
@@ -400,34 +417,41 @@
wbr_drrr->drr_key.ddk_prop =
drrw->drr_key.ddk_prop;
- if (cksum_and_write(&wbr_drr,
- sizeof (dmu_replay_record_t), &stream_cksum,
- outfd) == -1)
+ if (dump_record(&wbr_drr, NULL, 0,
+ &stream_cksum, outfd) != 0)
goto out;
} else {
/* block not previously seen */
- if (cksum_and_write(drr,
- sizeof (dmu_replay_record_t), &stream_cksum,
- outfd) == -1)
+ if (dump_record(drr, buf, drrw->drr_length,
+ &stream_cksum, outfd) != 0)
goto out;
- if (cksum_and_write(buf,
- drrw->drr_length,
- &stream_cksum, outfd) == -1)
- goto out;
}
break;
}
+ case DRR_WRITE_EMBEDDED:
+ {
+ struct drr_write_embedded *drrwe =
+ &drr->drr_u.drr_write_embedded;
+ (void) ssread(buf,
+ P2ROUNDUP((uint64_t)drrwe->drr_psize, 8), ofp);
+ if (dump_record(drr, buf,
+ P2ROUNDUP((uint64_t)drrwe->drr_psize, 8),
+ &stream_cksum, outfd) != 0)
+ goto out;
+ break;
+ }
+
case DRR_FREE:
{
- if (cksum_and_write(drr, sizeof (dmu_replay_record_t),
- &stream_cksum, outfd) == -1)
+ if (dump_record(drr, NULL, 0, &stream_cksum,
+ outfd) != 0)
goto out;
break;
}
default:
- (void) printf("INVALID record type 0x%x\n",
+ (void) fprintf(stderr, "INVALID record type 0x%x\n",
drr->drr_type);
/* should never happen, so assert */
assert(B_FALSE);
@@ -557,13 +581,30 @@
* Routines for dealing with the giant nvlist of fs-nvlists, etc.
*/
typedef struct send_data {
+ /*
+ * assigned inside every recursive call,
+ * restored from *_save on return:
+ *
+ * guid of fromsnap snapshot in parent dataset
+ * txg of fromsnap snapshot in current dataset
+ * txg of tosnap snapshot in current dataset
+ */
+
uint64_t parent_fromsnap_guid;
+ uint64_t fromsnap_txg;
+ uint64_t tosnap_txg;
+
+ /* the nvlists get accumulated during depth-first traversal */
nvlist_t *parent_snaps;
nvlist_t *fss;
nvlist_t *snapprops;
+
+ /* send-receive configuration, does not change during traversal */
+ const char *fsname;
const char *fromsnap;
const char *tosnap;
boolean_t recursive;
+ boolean_t verbose;
/*
* The header nvlist is of the following format:
@@ -596,11 +637,23 @@
{
send_data_t *sd = arg;
uint64_t guid = zhp->zfs_dmustats.dds_guid;
+ uint64_t txg = zhp->zfs_dmustats.dds_creation_txg;
char *snapname;
nvlist_t *nv;
snapname = strrchr(zhp->zfs_name, '@')+1;
+ if (sd->tosnap_txg != 0 && txg > sd->tosnap_txg) {
+ if (sd->verbose) {
+ (void) fprintf(stderr, dgettext(TEXT_DOMAIN,
+ "skipping snapshot %s because it was created "
+ "after the destination snapshot (%s)\n"),
+ zhp->zfs_name, sd->tosnap);
+ }
+ zfs_close(zhp);
+ return (0);
+ }
+
VERIFY(0 == nvlist_add_uint64(sd->parent_snaps, snapname, guid));
/*
* NB: if there is no fromsnap here (it's a newly created fs in
@@ -694,6 +747,31 @@
}
/*
+ * returns snapshot creation txg
+ * and returns 0 if the snapshot does not exist
+ */
+static uint64_t
+get_snap_txg(libzfs_handle_t *hdl, const char *fs, const char *snap)
+{
+ char name[ZFS_MAX_DATASET_NAME_LEN];
+ uint64_t txg = 0;
+
+ if (fs == NULL || fs[0] == '\0' || snap == NULL || snap[0] == '\0')
+ return (txg);
+
+ (void) snprintf(name, sizeof (name), "%s@%s", fs, snap);
+ if (zfs_dataset_exists(hdl, name, ZFS_TYPE_SNAPSHOT)) {
+ zfs_handle_t *zhp = zfs_open(hdl, name, ZFS_TYPE_SNAPSHOT);
+ if (zhp != NULL) {
+ txg = zfs_prop_get_int(zhp, ZFS_PROP_CREATETXG);
+ zfs_close(zhp);
+ }
+ }
+
+ return (txg);
+}
+
+/*
* recursively generate nvlists describing datasets. See comment
* for the data structure send_data_t above for description of contents
* of the nvlist.
@@ -705,9 +783,48 @@
nvlist_t *nvfs, *nv;
int rv = 0;
uint64_t parent_fromsnap_guid_save = sd->parent_fromsnap_guid;
+ uint64_t fromsnap_txg_save = sd->fromsnap_txg;
+ uint64_t tosnap_txg_save = sd->tosnap_txg;
+ uint64_t txg = zhp->zfs_dmustats.dds_creation_txg;
uint64_t guid = zhp->zfs_dmustats.dds_guid;
+ uint64_t fromsnap_txg, tosnap_txg;
char guidstring[64];
+ fromsnap_txg = get_snap_txg(zhp->zfs_hdl, zhp->zfs_name, sd->fromsnap);
+ if (fromsnap_txg != 0)
+ sd->fromsnap_txg = fromsnap_txg;
+
+ tosnap_txg = get_snap_txg(zhp->zfs_hdl, zhp->zfs_name, sd->tosnap);
+ if (tosnap_txg != 0)
+ sd->tosnap_txg = tosnap_txg;
+
+ /*
+ * on the send side, if the current dataset does not have tosnap,
+ * perform two additional checks:
+ *
+ * - skip sending the current dataset if it was created later than
+ * the parent tosnap
+ * - return error if the current dataset was created earlier than
+ * the parent tosnap
+ */
+ if (sd->tosnap != NULL && tosnap_txg == 0) {
+ if (sd->tosnap_txg != 0 && txg > sd->tosnap_txg) {
+ if (sd->verbose) {
+ (void) fprintf(stderr, dgettext(TEXT_DOMAIN,
+ "skipping dataset %s: snapshot %s does "
+ "not exist\n"), zhp->zfs_name, sd->tosnap);
+ }
+ } else {
+ (void) fprintf(stderr, dgettext(TEXT_DOMAIN,
+ "cannot send %s@%s%s: snapshot %s@%s does not "
+ "exist\n"), sd->fsname, sd->tosnap, sd->recursive ?
+ dgettext(TEXT_DOMAIN, " recursively") : "",
+ zhp->zfs_name, sd->tosnap);
+ rv = -1;
+ }
+ goto out;
+ }
+
VERIFY(0 == nvlist_alloc(&nvfs, NV_UNIQUE_NAME, 0));
VERIFY(0 == nvlist_add_string(nvfs, "name", zhp->zfs_name));
VERIFY(0 == nvlist_add_uint64(nvfs, "parentfromsnap",
@@ -716,8 +833,10 @@
if (zhp->zfs_dmustats.dds_origin[0]) {
zfs_handle_t *origin = zfs_open(zhp->zfs_hdl,
zhp->zfs_dmustats.dds_origin, ZFS_TYPE_SNAPSHOT);
- if (origin == NULL)
- return (-1);
+ if (origin == NULL) {
+ rv = -1;
+ goto out;
+ }
VERIFY(0 == nvlist_add_uint64(nvfs, "origin",
origin->zfs_dmustats.dds_guid));
}
@@ -748,7 +867,10 @@
if (sd->recursive)
rv = zfs_iter_filesystems(zhp, send_iterate_fs, sd);
+out:
sd->parent_fromsnap_guid = parent_fromsnap_guid_save;
+ sd->fromsnap_txg = fromsnap_txg_save;
+ sd->tosnap_txg = tosnap_txg_save;
zfs_close(zhp);
return (rv);
@@ -756,7 +878,8 @@
static int
gather_nvlist(libzfs_handle_t *hdl, const char *fsname, const char *fromsnap,
- const char *tosnap, boolean_t recursive, nvlist_t **nvlp, avl_tree_t **avlp)
+ const char *tosnap, boolean_t recursive, boolean_t verbose,
+ nvlist_t **nvlp, avl_tree_t **avlp)
{
zfs_handle_t *zhp;
send_data_t sd = { 0 };
@@ -767,9 +890,11 @@
return (EZFS_BADTYPE);
VERIFY(0 == nvlist_alloc(&sd.fss, NV_UNIQUE_NAME, 0));
+ sd.fsname = fsname;
sd.fromsnap = fromsnap;
sd.tosnap = tosnap;
sd.recursive = recursive;
+ sd.verbose = verbose;
if ((error = send_iterate_fs(zhp, &sd)) != 0) {
nvlist_free(sd.fss);
@@ -796,10 +921,11 @@
/* these are all just the short snapname (the part after the @) */
const char *fromsnap;
const char *tosnap;
- char prevsnap[ZFS_MAXNAMELEN];
+ char prevsnap[ZFS_MAX_DATASET_NAME_LEN];
uint64_t prevsnap_obj;
boolean_t seenfrom, seento, replicate, doall, fromorigin;
- boolean_t verbose, dryrun, parsable, progress;
+ boolean_t verbose, dryrun, parsable, progress, embed_data, std_out;
+ boolean_t large_block;
int outfd;
boolean_t err;
nvlist_t *fss;
@@ -808,7 +934,7 @@
snapfilter_cb_t *filter_cb;
void *filter_cb_arg;
nvlist_t *debugnv;
- char holdtag[ZFS_MAXNAMELEN];
+ char holdtag[ZFS_MAX_DATASET_NAME_LEN];
int cleanup_fd;
uint64_t size;
} send_dump_data_t;
@@ -878,7 +1004,8 @@
*/
static int
dump_ioctl(zfs_handle_t *zhp, const char *fromsnap, uint64_t fromsnap_obj,
- boolean_t fromorigin, int outfd, nvlist_t *debugnv)
+ boolean_t fromorigin, int outfd, enum lzc_send_flags flags,
+ nvlist_t *debugnv)
{
zfs_cmd_t zc = { 0 };
libzfs_handle_t *hdl = zhp->zfs_hdl;
@@ -892,6 +1019,7 @@
zc.zc_obj = fromorigin;
zc.zc_sendobj = zfs_prop_get_int(zhp, ZFS_PROP_OBJSETID);
zc.zc_fromobj = fromsnap_obj;
+ zc.zc_flags = flags;
VERIFY(0 == nvlist_alloc(&thisdbg, NV_UNIQUE_NAME, 0));
if (fromsnap && fromsnap[0] != '\0') {
@@ -931,7 +1059,7 @@
case EIO:
case ENOLINK:
case ENOSPC:
-#ifdef sun
+#ifdef illumos
case ENOSTR:
#endif
case ENXIO:
@@ -973,17 +1101,14 @@
send_progress_thread(void *arg)
{
progress_arg_t *pa = arg;
-
zfs_cmd_t zc = { 0 };
zfs_handle_t *zhp = pa->pa_zhp;
libzfs_handle_t *hdl = zhp->zfs_hdl;
unsigned long long bytes;
char buf[16];
-
time_t t;
struct tm *tm;
- assert(zhp->zfs_type == ZFS_TYPE_SNAPSHOT);
(void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name));
if (!pa->pa_parsable)
@@ -1016,6 +1141,51 @@
}
}
+static void
+send_print_verbose(FILE *fout, const char *tosnap, const char *fromsnap,
+ uint64_t size, boolean_t parsable)
+{
+ if (parsable) {
+ if (fromsnap != NULL) {
+ (void) fprintf(fout, "incremental\t%s\t%s",
+ fromsnap, tosnap);
+ } else {
+ (void) fprintf(fout, "full\t%s",
+ tosnap);
+ }
+ } else {
+ if (fromsnap != NULL) {
+ if (strchr(fromsnap, '@') == NULL &&
+ strchr(fromsnap, '#') == NULL) {
+ (void) fprintf(fout, dgettext(TEXT_DOMAIN,
+ "send from @%s to %s"),
+ fromsnap, tosnap);
+ } else {
+ (void) fprintf(fout, dgettext(TEXT_DOMAIN,
+ "send from %s to %s"),
+ fromsnap, tosnap);
+ }
+ } else {
+ (void) fprintf(fout, dgettext(TEXT_DOMAIN,
+ "full send of %s"),
+ tosnap);
+ }
+ }
+
+ if (size != 0) {
+ if (parsable) {
+ (void) fprintf(fout, "\t%llu",
+ (longlong_t)size);
+ } else {
+ char buf[16];
+ zfs_nicenum(size, buf, sizeof (buf));
+ (void) fprintf(fout, dgettext(TEXT_DOMAIN,
+ " estimated size is %s"), buf);
+ }
+ }
+ (void) fprintf(fout, "\n");
+}
+
static int
dump_snapshot(zfs_handle_t *zhp, void *arg)
{
@@ -1026,6 +1196,7 @@
int err;
boolean_t isfromsnap, istosnap, fromorigin;
boolean_t exclude = B_FALSE;
+ FILE *fout = sdd->std_out ? stdout : stderr;
err = 0;
thissnap = strchr(zhp->zfs_name, '@') + 1;
@@ -1094,37 +1265,14 @@
(sdd->fromorigin || sdd->replicate);
if (sdd->verbose) {
- uint64_t size;
- err = estimate_ioctl(zhp, sdd->prevsnap_obj,
+ uint64_t size = 0;
+ (void) estimate_ioctl(zhp, sdd->prevsnap_obj,
fromorigin, &size);
- if (sdd->parsable) {
- if (sdd->prevsnap[0] != '\0') {
- (void) fprintf(stderr, "incremental\t%s\t%s",
- sdd->prevsnap, zhp->zfs_name);
- } else {
- (void) fprintf(stderr, "full\t%s",
- zhp->zfs_name);
- }
- } else {
- (void) fprintf(stderr, dgettext(TEXT_DOMAIN,
- "send from @%s to %s"),
- sdd->prevsnap, zhp->zfs_name);
- }
- if (err == 0) {
- if (sdd->parsable) {
- (void) fprintf(stderr, "\t%llu\n",
- (longlong_t)size);
- } else {
- char buf[16];
- zfs_nicenum(size, buf, sizeof (buf));
- (void) fprintf(stderr, dgettext(TEXT_DOMAIN,
- " estimated size is %s\n"), buf);
- }
- sdd->size += size;
- } else {
- (void) fprintf(stderr, "\n");
- }
+ send_print_verbose(fout, zhp->zfs_name,
+ sdd->prevsnap[0] ? sdd->prevsnap : NULL,
+ size, sdd->parsable);
+ sdd->size += size;
}
if (!sdd->dryrun) {
@@ -1137,15 +1285,21 @@
pa.pa_fd = sdd->outfd;
pa.pa_parsable = sdd->parsable;
- if (err = pthread_create(&tid, NULL,
- send_progress_thread, &pa)) {
+ if ((err = pthread_create(&tid, NULL,
+ send_progress_thread, &pa)) != 0) {
zfs_close(zhp);
return (err);
}
}
+ enum lzc_send_flags flags = 0;
+ if (sdd->large_block)
+ flags |= LZC_SEND_FLAG_LARGE_BLOCK;
+ if (sdd->embed_data)
+ flags |= LZC_SEND_FLAG_EMBED_DATA;
+
err = dump_ioctl(zhp, sdd->prevsnap, sdd->prevsnap_obj,
- fromorigin, sdd->outfd, sdd->debugnv);
+ fromorigin, sdd->outfd, flags, sdd->debugnv);
if (sdd->progress) {
(void) pthread_cancel(tid);
@@ -1329,6 +1483,233 @@
return (0);
}
+nvlist_t *
+zfs_send_resume_token_to_nvlist(libzfs_handle_t *hdl, const char *token)
+{
+ unsigned int version;
+ int nread;
+ unsigned long long checksum, packed_len;
+
+ /*
+ * Decode token header, which is:
+ * <token version>-<checksum of payload>-<uncompressed payload length>
+ * Note that the only supported token version is 1.
+ */
+ nread = sscanf(token, "%u-%llx-%llx-",
+ &version, &checksum, &packed_len);
+ if (nread != 3) {
+ zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
+ "resume token is corrupt (invalid format)"));
+ return (NULL);
+ }
+
+ if (version != ZFS_SEND_RESUME_TOKEN_VERSION) {
+ zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
+ "resume token is corrupt (invalid version %u)"),
+ version);
+ return (NULL);
+ }
+
+ /* convert hexadecimal representation to binary */
+ token = strrchr(token, '-') + 1;
+ int len = strlen(token) / 2;
+ unsigned char *compressed = zfs_alloc(hdl, len);
+ for (int i = 0; i < len; i++) {
+ nread = sscanf(token + i * 2, "%2hhx", compressed + i);
+ if (nread != 1) {
+ free(compressed);
+ zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
+ "resume token is corrupt "
+ "(payload is not hex-encoded)"));
+ return (NULL);
+ }
+ }
+
+ /* verify checksum */
+ zio_cksum_t cksum;
+ fletcher_4_native(compressed, len, NULL, &cksum);
+ if (cksum.zc_word[0] != checksum) {
+ free(compressed);
+ zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
+ "resume token is corrupt (incorrect checksum)"));
+ return (NULL);
+ }
+
+ /* uncompress */
+ void *packed = zfs_alloc(hdl, packed_len);
+ uLongf packed_len_long = packed_len;
+ if (uncompress(packed, &packed_len_long, compressed, len) != Z_OK ||
+ packed_len_long != packed_len) {
+ free(packed);
+ free(compressed);
+ zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
+ "resume token is corrupt (decompression failed)"));
+ return (NULL);
+ }
+
+ /* unpack nvlist */
+ nvlist_t *nv;
+ int error = nvlist_unpack(packed, packed_len, &nv, KM_SLEEP);
+ free(packed);
+ free(compressed);
+ if (error != 0) {
+ zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
+ "resume token is corrupt (nvlist_unpack failed)"));
+ return (NULL);
+ }
+ return (nv);
+}
+
+int
+zfs_send_resume(libzfs_handle_t *hdl, sendflags_t *flags, int outfd,
+ const char *resume_token)
+{
+ char errbuf[1024];
+ char *toname;
+ char *fromname = NULL;
+ uint64_t resumeobj, resumeoff, toguid, fromguid, bytes;
+ zfs_handle_t *zhp;
+ int error = 0;
+ char name[ZFS_MAX_DATASET_NAME_LEN];
+ enum lzc_send_flags lzc_flags = 0;
+
+ (void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN,
+ "cannot resume send"));
+
+ nvlist_t *resume_nvl =
+ zfs_send_resume_token_to_nvlist(hdl, resume_token);
+ if (resume_nvl == NULL) {
+ /*
+ * zfs_error_aux has already been set by
+ * zfs_send_resume_token_to_nvlist
+ */
+ return (zfs_error(hdl, EZFS_FAULT, errbuf));
+ }
+ if (flags->verbose) {
+ (void) fprintf(stderr, dgettext(TEXT_DOMAIN,
+ "resume token contents:\n"));
+ nvlist_print(stderr, resume_nvl);
+ }
+
+ if (nvlist_lookup_string(resume_nvl, "toname", &toname) != 0 ||
+ nvlist_lookup_uint64(resume_nvl, "object", &resumeobj) != 0 ||
+ nvlist_lookup_uint64(resume_nvl, "offset", &resumeoff) != 0 ||
+ nvlist_lookup_uint64(resume_nvl, "bytes", &bytes) != 0 ||
+ nvlist_lookup_uint64(resume_nvl, "toguid", &toguid) != 0) {
+ zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
+ "resume token is corrupt"));
+ return (zfs_error(hdl, EZFS_FAULT, errbuf));
+ }
+ fromguid = 0;
+ (void) nvlist_lookup_uint64(resume_nvl, "fromguid", &fromguid);
+
+ if (flags->embed_data || nvlist_exists(resume_nvl, "embedok"))
+ lzc_flags |= LZC_SEND_FLAG_EMBED_DATA;
+
+ if (guid_to_name(hdl, toname, toguid, B_FALSE, name) != 0) {
+ if (zfs_dataset_exists(hdl, toname, ZFS_TYPE_DATASET)) {
+ zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
+ "'%s' is no longer the same snapshot used in "
+ "the initial send"), toname);
+ } else {
+ zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
+ "'%s' used in the initial send no longer exists"),
+ toname);
+ }
+ return (zfs_error(hdl, EZFS_BADPATH, errbuf));
+ }
+ zhp = zfs_open(hdl, name, ZFS_TYPE_DATASET);
+ if (zhp == NULL) {
+ zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
+ "unable to access '%s'"), name);
+ return (zfs_error(hdl, EZFS_BADPATH, errbuf));
+ }
+
+ if (fromguid != 0) {
+ if (guid_to_name(hdl, toname, fromguid, B_TRUE, name) != 0) {
+ zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
+ "incremental source %#llx no longer exists"),
+ (longlong_t)fromguid);
+ return (zfs_error(hdl, EZFS_BADPATH, errbuf));
+ }
+ fromname = name;
+ }
+
+ if (flags->verbose) {
+ uint64_t size = 0;
+ error = lzc_send_space(zhp->zfs_name, fromname, &size);
+ if (error == 0)
+ size = MAX(0, (int64_t)(size - bytes));
+ send_print_verbose(stderr, zhp->zfs_name, fromname,
+ size, flags->parsable);
+ }
+
+ if (!flags->dryrun) {
+ progress_arg_t pa = { 0 };
+ pthread_t tid;
+ /*
+ * If progress reporting is requested, spawn a new thread to
+ * poll ZFS_IOC_SEND_PROGRESS at a regular interval.
+ */
+ if (flags->progress) {
+ pa.pa_zhp = zhp;
+ pa.pa_fd = outfd;
+ pa.pa_parsable = flags->parsable;
+
+ error = pthread_create(&tid, NULL,
+ send_progress_thread, &pa);
+ if (error != 0) {
+ zfs_close(zhp);
+ return (error);
+ }
+ }
+
+ error = lzc_send_resume(zhp->zfs_name, fromname, outfd,
+ lzc_flags, resumeobj, resumeoff);
+
+ if (flags->progress) {
+ (void) pthread_cancel(tid);
+ (void) pthread_join(tid, NULL);
+ }
+
+ char errbuf[1024];
+ (void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN,
+ "warning: cannot send '%s'"), zhp->zfs_name);
+
+ zfs_close(zhp);
+
+ switch (error) {
+ case 0:
+ return (0);
+ case EXDEV:
+ case ENOENT:
+ case EDQUOT:
+ case EFBIG:
+ case EIO:
+ case ENOLINK:
+ case ENOSPC:
+#ifdef illumos
+ case ENOSTR:
+#endif
+ case ENXIO:
+ case EPIPE:
+ case ERANGE:
+ case EFAULT:
+ case EROFS:
+ zfs_error_aux(hdl, strerror(errno));
+ return (zfs_error(hdl, EZFS_BADBACKUP, errbuf));
+
+ default:
+ return (zfs_standard_error(hdl, errno, errbuf));
+ }
+ }
+
+
+ zfs_close(zhp);
+
+ return (error);
+}
+
/*
* Generate a send stream for the dataset identified by the argument zhp.
*
@@ -1361,6 +1742,7 @@
int pipefd[2];
dedup_arg_t dda = { 0 };
int featureflags = 0;
+ FILE *fout;
(void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN,
"cannot send '%s'"), zhp->zfs_name);
@@ -1382,7 +1764,7 @@
if (flags->dedup && !flags->dryrun) {
featureflags |= (DMU_BACKUP_FEATURE_DEDUP |
DMU_BACKUP_FEATURE_DEDUPPROPS);
- if (err = pipe(pipefd)) {
+ if ((err = pipe(pipefd)) != 0) {
zfs_error_aux(zhp->zfs_hdl, strerror(errno));
return (zfs_error(zhp->zfs_hdl, EZFS_PIPEFAILED,
errbuf));
@@ -1390,7 +1772,7 @@
dda.outputfd = outfd;
dda.inputfd = pipefd[1];
dda.dedup_hdl = zhp->zfs_hdl;
- if (err = pthread_create(&tid, NULL, cksummer, &dda)) {
+ if ((err = pthread_create(&tid, NULL, cksummer, &dda)) != 0) {
(void) close(pipefd[0]);
(void) close(pipefd[1]);
zfs_error_aux(zhp->zfs_hdl, strerror(errno));
@@ -1420,7 +1802,8 @@
}
err = gather_nvlist(zhp->zfs_hdl, zhp->zfs_name,
- fromsnap, tosnap, flags->replicate, &fss, &fsavl);
+ fromsnap, tosnap, flags->replicate, flags->verbose,
+ &fss, &fsavl);
if (err)
goto err_out;
VERIFY(0 == nvlist_add_nvlist(hdrnv, "fss", fss));
@@ -1446,18 +1829,11 @@
sizeof (drr.drr_u.drr_begin.drr_toname),
"%s@%s", zhp->zfs_name, tosnap);
drr.drr_payloadlen = buflen;
- err = cksum_and_write(&drr, sizeof (drr), &zc, outfd);
- /* write header nvlist */
- if (err != -1 && packbuf != NULL) {
- err = cksum_and_write(packbuf, buflen, &zc,
- outfd);
- }
+ err = dump_record(&drr, packbuf, buflen, &zc, outfd);
free(packbuf);
- if (err == -1) {
- err = errno;
+ if (err != 0)
goto stderr_out;
- }
/* write end record */
bzero(&drr, sizeof (drr));
@@ -1489,10 +1865,15 @@
sdd.parsable = flags->parsable;
sdd.progress = flags->progress;
sdd.dryrun = flags->dryrun;
+ sdd.large_block = flags->largeblock;
+ sdd.embed_data = flags->embed_data;
sdd.filter_cb = filter_func;
sdd.filter_cb_arg = cb_arg;
if (debugnvp)
sdd.debugnv = *debugnvp;
+ if (sdd.verbose && sdd.dryrun)
+ sdd.std_out = B_TRUE;
+ fout = sdd.std_out ? stdout : stderr;
/*
* Some flags require that we place user holds on the datasets that are
@@ -1532,12 +1913,12 @@
if (flags->verbose) {
if (flags->parsable) {
- (void) fprintf(stderr, "size\t%llu\n",
+ (void) fprintf(fout, "size\t%llu\n",
(longlong_t)sdd.size);
} else {
char buf[16];
zfs_nicenum(sdd.size, buf, sizeof (buf));
- (void) fprintf(stderr, dgettext(TEXT_DOMAIN,
+ (void) fprintf(fout, dgettext(TEXT_DOMAIN,
"total estimated size is %s\n"), buf);
}
}
@@ -1619,6 +2000,63 @@
return (err);
}
+int
+zfs_send_one(zfs_handle_t *zhp, const char *from, int fd,
+ enum lzc_send_flags flags)
+{
+ int err;
+ libzfs_handle_t *hdl = zhp->zfs_hdl;
+
+ char errbuf[1024];
+ (void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN,
+ "warning: cannot send '%s'"), zhp->zfs_name);
+
+ err = lzc_send(zhp->zfs_name, from, fd, flags);
+ if (err != 0) {
+ switch (errno) {
+ case EXDEV:
+ zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
+ "not an earlier snapshot from the same fs"));
+ return (zfs_error(hdl, EZFS_CROSSTARGET, errbuf));
+
+ case ENOENT:
+ case ESRCH:
+ if (lzc_exists(zhp->zfs_name)) {
+ zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
+ "incremental source (%s) does not exist"),
+ from);
+ }
+ return (zfs_error(hdl, EZFS_NOENT, errbuf));
+
+ case EBUSY:
+ zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
+ "target is busy; if a filesystem, "
+ "it must not be mounted"));
+ return (zfs_error(hdl, EZFS_BUSY, errbuf));
+
+ case EDQUOT:
+ case EFBIG:
+ case EIO:
+ case ENOLINK:
+ case ENOSPC:
+#ifdef illumos
+ case ENOSTR:
+#endif
+ case ENXIO:
+ case EPIPE:
+ case ERANGE:
+ case EFAULT:
+ case EROFS:
+ zfs_error_aux(hdl, strerror(errno));
+ return (zfs_error(hdl, EZFS_BADBACKUP, errbuf));
+
+ default:
+ return (zfs_standard_error(hdl, errno, errbuf));
+ }
+ }
+ return (err != 0);
+}
+
/*
* Routines specific to "zfs recv"
*/
@@ -1631,6 +2069,8 @@
int rv;
int len = ilen;
+ assert(ilen <= SPA_MAXBLOCKSIZE);
+
do {
rv = read(fd, cp, len);
cp += rv;
@@ -1724,8 +2164,8 @@
if (err != 0 && strncmp(name + baselen, "recv-", 5) != 0) {
seq++;
- (void) snprintf(newname, ZFS_MAXNAMELEN, "%.*srecv-%u-%u",
- baselen, name, getpid(), seq);
+ (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) {
@@ -1810,6 +2250,7 @@
typedef struct guid_to_name_data {
uint64_t guid;
+ boolean_t bookmark_ok;
char *name;
char *skip;
} guid_to_name_data_t;
@@ -1818,14 +2259,17 @@
guid_to_name_cb(zfs_handle_t *zhp, void *arg)
{
guid_to_name_data_t *gtnd = arg;
+ const char *slash;
int err;
if (gtnd->skip != NULL &&
- strcmp(zhp->zfs_name, gtnd->skip) == 0) {
+ (slash = strrchr(zhp->zfs_name, '/')) != NULL &&
+ strcmp(slash + 1, gtnd->skip) == 0) {
+ zfs_close(zhp);
return (0);
}
- if (zhp->zfs_dmustats.dds_guid == gtnd->guid) {
+ if (zfs_prop_get_int(zhp, ZFS_PROP_GUID) == gtnd->guid) {
(void) strcpy(gtnd->name, zhp->zfs_name);
zfs_close(zhp);
return (EEXIST);
@@ -1832,6 +2276,8 @@
}
err = zfs_iter_children(zhp, guid_to_name_cb, gtnd);
+ if (err != EEXIST && gtnd->bookmark_ok)
+ err = zfs_iter_bookmarks(zhp, guid_to_name_cb, gtnd);
zfs_close(zhp);
return (err);
}
@@ -1845,45 +2291,48 @@
*/
static int
guid_to_name(libzfs_handle_t *hdl, const char *parent, uint64_t guid,
- char *name)
+ boolean_t bookmark_ok, char *name)
{
- /* exhaustive search all local snapshots */
- char pname[ZFS_MAXNAMELEN];
+ char pname[ZFS_MAX_DATASET_NAME_LEN];
guid_to_name_data_t gtnd;
- int err = 0;
- zfs_handle_t *zhp;
- char *cp;
gtnd.guid = guid;
+ gtnd.bookmark_ok = bookmark_ok;
gtnd.name = name;
gtnd.skip = NULL;
- (void) strlcpy(pname, parent, sizeof (pname));
-
/*
- * Search progressively larger portions of the hierarchy. This will
+ * Search progressively larger portions of the hierarchy, starting
+ * with the filesystem specified by 'parent'. This will
* select the "most local" version of the origin snapshot in the case
* that there are multiple matching snapshots in the system.
*/
- while ((cp = strrchr(pname, '/')) != NULL) {
-
+ (void) strlcpy(pname, parent, sizeof (pname));
+ char *cp = strrchr(pname, '@');
+ if (cp == NULL)
+ cp = strchr(pname, '\0');
+ for (; cp != NULL; cp = strrchr(pname, '/')) {
/* Chop off the last component and open the parent */
*cp = '\0';
- zhp = make_dataset_handle(hdl, pname);
+ zfs_handle_t *zhp = make_dataset_handle(hdl, pname);
if (zhp == NULL)
continue;
-
- err = zfs_iter_children(zhp, guid_to_name_cb, >nd);
+ int err = guid_to_name_cb(zfs_handle_dup(zhp), >nd);
+ if (err != EEXIST)
+ err = zfs_iter_children(zhp, guid_to_name_cb, >nd);
+ if (err != EEXIST && bookmark_ok)
+ err = zfs_iter_bookmarks(zhp, guid_to_name_cb, >nd);
zfs_close(zhp);
if (err == EEXIST)
return (0);
/*
- * Remember the dataset that we already searched, so we
- * skip it next time through.
+ * Remember the last portion of the dataset so we skip it next
+ * time through (as we've already searched that portion of the
+ * hierarchy).
*/
- gtnd.skip = pname;
+ gtnd.skip = strrchr(pname, '/') + 1;
}
return (ENOENT);
@@ -1899,7 +2348,7 @@
{
nvlist_t *nvfs;
char *fsname, *snapname;
- char buf[ZFS_MAXNAMELEN];
+ char buf[ZFS_MAX_DATASET_NAME_LEN];
int rv;
zfs_handle_t *guid1hdl, *guid2hdl;
uint64_t create1, create2;
@@ -1950,7 +2399,7 @@
avl_tree_t *local_avl;
nvpair_t *fselem, *nextfselem;
char *fromsnap;
- char newname[ZFS_MAXNAMELEN];
+ char newname[ZFS_MAX_DATASET_NAME_LEN];
char guidname[32];
int error;
boolean_t needagain, progress, recursive;
@@ -1970,7 +2419,7 @@
VERIFY(0 == nvlist_alloc(&deleted, NV_UNIQUE_NAME, 0));
if ((error = gather_nvlist(hdl, tofs, fromsnap, NULL,
- recursive, &local_nv, &local_avl)) != 0)
+ recursive, B_FALSE, &local_nv, &local_avl)) != 0)
return (error);
/*
@@ -2069,7 +2518,7 @@
/* check for delete */
if (found == NULL) {
- char name[ZFS_MAXNAMELEN];
+ char name[ZFS_MAX_DATASET_NAME_LEN];
if (!flags->force)
continue;
@@ -2109,8 +2558,8 @@
/* check for different snapname */
if (strcmp(nvpair_name(snapelem),
stream_snapname) != 0) {
- char name[ZFS_MAXNAMELEN];
- char tryname[ZFS_MAXNAMELEN];
+ char name[ZFS_MAX_DATASET_NAME_LEN];
+ char tryname[ZFS_MAX_DATASET_NAME_LEN];
(void) snprintf(name, sizeof (name), "%s@%s",
fsname, nvpair_name(snapelem));
@@ -2192,7 +2641,7 @@
((flags->isprefix || strcmp(tofs, fsname) != 0) &&
(s1 != NULL) && (s2 != NULL) && strcmp(s1, s2) != 0)) {
nvlist_t *parent;
- char tryname[ZFS_MAXNAMELEN];
+ char tryname[ZFS_MAX_DATASET_NAME_LEN];
parent = fsavl_find(local_avl,
stream_parent_fromsnap_guid, NULL);
@@ -2258,9 +2707,10 @@
nvlist_t *stream_nv = NULL;
avl_tree_t *stream_avl = NULL;
char *fromsnap = NULL;
+ char *sendsnap = NULL;
char *cp;
- char tofs[ZFS_MAXNAMELEN];
- char sendfs[ZFS_MAXNAMELEN];
+ char tofs[ZFS_MAX_DATASET_NAME_LEN];
+ char sendfs[ZFS_MAX_DATASET_NAME_LEN];
char errbuf[1024];
dmu_replay_record_t drre;
int error;
@@ -2344,7 +2794,7 @@
nvlist_t *renamed = NULL;
nvpair_t *pair = NULL;
- (void) strlcpy(tofs, destname, ZFS_MAXNAMELEN);
+ (void) strlcpy(tofs, destname, sizeof (tofs));
if (flags->isprefix) {
struct drr_begin *drrb = &drr->drr_u.drr_begin;
int i;
@@ -2353,7 +2803,7 @@
cp = strrchr(drrb->drr_toname, '/');
if (cp == NULL) {
(void) strlcat(tofs, "/",
- ZFS_MAXNAMELEN);
+ sizeof (tofs));
i = 0;
} else {
i = (cp - drrb->drr_toname);
@@ -2363,7 +2813,7 @@
}
/* zfs_receive_one() will create_parents() */
(void) strlcat(tofs, &drrb->drr_toname[i],
- ZFS_MAXNAMELEN);
+ sizeof (tofs));
*strchr(tofs, '@') = '\0';
}
@@ -2405,9 +2855,17 @@
* zfs_receive_one().
*/
(void) strlcpy(sendfs, drr->drr_u.drr_begin.drr_toname,
- ZFS_MAXNAMELEN);
- if ((cp = strchr(sendfs, '@')) != NULL)
+ sizeof (sendfs));
+ if ((cp = strchr(sendfs, '@')) != NULL) {
*cp = '\0';
+ /*
+ * Find the "sendsnap", the final snapshot in a replication
+ * stream. zfs_receive_one() handles certain errors
+ * differently, depending on if the contained stream is the
+ * last one or not.
+ */
+ sendsnap = (cp + 1);
+ }
/* Finally, receive each contained stream */
do {
@@ -2418,9 +2876,9 @@
* zfs_receive_one() will take care of it (ie,
* recv_skip() and return 0).
*/
- error = zfs_receive_impl(hdl, destname, flags, fd,
+ error = zfs_receive_impl(hdl, destname, NULL, flags, fd,
sendfs, stream_nv, stream_avl, top_zfs, cleanup_fd,
- action_handlep);
+ action_handlep, sendsnap);
if (error == ENODATA) {
error = 0;
break;
@@ -2439,8 +2897,7 @@
out:
fsavl_destroy(stream_avl);
- if (stream_nv)
- nvlist_free(stream_nv);
+ nvlist_free(stream_nv);
if (softerr)
error = -2;
if (anyerr)
@@ -2465,7 +2922,7 @@
recv_skip(libzfs_handle_t *hdl, int fd, boolean_t byteswap)
{
dmu_replay_record_t *drr;
- void *buf = malloc(1<<20);
+ void *buf = zfs_alloc(hdl, SPA_MAXBLOCKSIZE);
char errbuf[1024];
(void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN,
@@ -2481,11 +2938,9 @@
switch (drr->drr_type) {
case DRR_BEGIN:
- /* NB: not to be used on v2 stream packages */
if (drr->drr_payloadlen != 0) {
- zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
- "invalid substream header"));
- return (zfs_error(hdl, EZFS_BADSTREAM, errbuf));
+ (void) recv_read(hdl, fd, buf,
+ drr->drr_payloadlen, B_FALSE, NULL);
}
break;
@@ -2514,12 +2969,22 @@
break;
case DRR_SPILL:
if (byteswap) {
- drr->drr_u.drr_write.drr_length =
+ drr->drr_u.drr_spill.drr_length =
BSWAP_64(drr->drr_u.drr_spill.drr_length);
}
(void) recv_read(hdl, fd, buf,
drr->drr_u.drr_spill.drr_length, B_FALSE, NULL);
break;
+ case DRR_WRITE_EMBEDDED:
+ if (byteswap) {
+ drr->drr_u.drr_write_embedded.drr_psize =
+ BSWAP_32(drr->drr_u.drr_write_embedded.
+ drr_psize);
+ }
+ (void) recv_read(hdl, fd, buf,
+ P2ROUNDUP(drr->drr_u.drr_write_embedded.drr_psize,
+ 8), B_FALSE, NULL);
+ break;
case DRR_WRITE_BYREF:
case DRR_FREEOBJECTS:
case DRR_FREE:
@@ -2536,15 +3001,49 @@
return (-1);
}
+static void
+recv_ecksum_set_aux(libzfs_handle_t *hdl, const char *target_snap,
+ boolean_t resumable)
+{
+ char target_fs[ZFS_MAX_DATASET_NAME_LEN];
+
+ zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
+ "checksum mismatch or incomplete stream"));
+
+ if (!resumable)
+ return;
+ (void) strlcpy(target_fs, target_snap, sizeof (target_fs));
+ *strchr(target_fs, '@') = '\0';
+ zfs_handle_t *zhp = zfs_open(hdl, target_fs,
+ ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME);
+ if (zhp == NULL)
+ return;
+
+ char token_buf[ZFS_MAXPROPLEN];
+ int error = zfs_prop_get(zhp, ZFS_PROP_RECEIVE_RESUME_TOKEN,
+ token_buf, sizeof (token_buf),
+ NULL, NULL, 0, B_TRUE);
+ if (error == 0) {
+ zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
+ "checksum mismatch or incomplete stream.\n"
+ "Partially received snapshot is saved.\n"
+ "A resuming stream can be generated on the sending "
+ "system by running:\n"
+ " zfs send -t %s"),
+ token_buf);
+ }
+ zfs_close(zhp);
+}
+
/*
* Restores a backup of tosnap from the file descriptor specified by infd.
*/
static int
zfs_receive_one(libzfs_handle_t *hdl, int infd, const char *tosnap,
- recvflags_t *flags, dmu_replay_record_t *drr,
- dmu_replay_record_t *drr_noswap, const char *sendfs,
- nvlist_t *stream_nv, avl_tree_t *stream_avl, char **top_zfs, int cleanup_fd,
- uint64_t *action_handlep)
+ const char *originsnap, recvflags_t *flags, dmu_replay_record_t *drr,
+ dmu_replay_record_t *drr_noswap, const char *sendfs, nvlist_t *stream_nv,
+ avl_tree_t *stream_avl, char **top_zfs, int cleanup_fd,
+ uint64_t *action_handlep, const char *finalsnap)
{
zfs_cmd_t zc = { 0 };
time_t begin_time;
@@ -2561,6 +3060,7 @@
nvlist_t *snapprops_nvlist = NULL;
zprop_errflags_t prop_errflags;
boolean_t recursive;
+ char *snapname = NULL;
begin_time = time(NULL);
@@ -2571,7 +3071,6 @@
ENOENT);
if (stream_avl != NULL) {
- char *snapname;
nvlist_t *fs = fsavl_find(stream_avl, drrb->drr_toguid,
&snapname);
nvlist_t *props;
@@ -2697,9 +3196,14 @@
/*
* Determine the name of the origin snapshot, store in zc_string.
*/
- if (drrb->drr_flags & DRR_FLAG_CLONE) {
+ if (originsnap) {
+ (void) strncpy(zc.zc_string, originsnap, sizeof (zc.zc_string));
+ if (flags->verbose)
+ (void) printf("using provided clone origin %s\n",
+ zc.zc_string);
+ } else if (drrb->drr_flags & DRR_FLAG_CLONE) {
if (guid_to_name(hdl, zc.zc_value,
- drrb->drr_fromguid, zc.zc_string) != 0) {
+ drrb->drr_fromguid, B_FALSE, zc.zc_string) != 0) {
zcmd_free_nvlists(&zc);
zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
"local origin for clone %s does not exist"),
@@ -2710,8 +3214,10 @@
(void) printf("found clone origin %s\n", zc.zc_string);
}
+ boolean_t resuming = DMU_GET_FEATUREFLAGS(drrb->drr_versioninfo) &
+ DMU_BACKUP_FEATURE_RESUMING;
stream_wantsnewfs = (drrb->drr_fromguid == 0 ||
- (drrb->drr_flags & DRR_FLAG_CLONE));
+ (drrb->drr_flags & DRR_FLAG_CLONE) || originsnap) && !resuming;
if (stream_wantsnewfs) {
/*
@@ -2727,10 +3233,10 @@
*cp = '\0';
if (cp &&
!zfs_dataset_exists(hdl, zc.zc_name, ZFS_TYPE_DATASET)) {
- char suffix[ZFS_MAXNAMELEN];
+ char suffix[ZFS_MAX_DATASET_NAME_LEN];
(void) strcpy(suffix, strrchr(zc.zc_value, '/'));
if (guid_to_name(hdl, zc.zc_name, parent_snapguid,
- zc.zc_value) == 0) {
+ B_FALSE, zc.zc_value) == 0) {
*strchr(zc.zc_value, '@') = '\0';
(void) strcat(zc.zc_value, suffix);
}
@@ -2754,10 +3260,10 @@
if ((flags->isprefix || (*(chopprefix = drrb->drr_toname +
strlen(sendfs)) != '\0' && *chopprefix != '@')) &&
!zfs_dataset_exists(hdl, zc.zc_name, ZFS_TYPE_DATASET)) {
- char snap[ZFS_MAXNAMELEN];
+ char snap[ZFS_MAX_DATASET_NAME_LEN];
(void) strcpy(snap, strchr(zc.zc_value, '@'));
if (guid_to_name(hdl, zc.zc_name, drrb->drr_fromguid,
- zc.zc_value) == 0) {
+ B_FALSE, zc.zc_value) == 0) {
*strchr(zc.zc_value, '@') = '\0';
(void) strcat(zc.zc_value, snap);
}
@@ -2771,11 +3277,12 @@
zfs_handle_t *zhp;
/*
- * Destination fs exists. Therefore this should either
- * be an incremental, or the stream specifies a new fs
- * (full stream or clone) and they want us to blow it
- * away (and have therefore specified -F and removed any
- * snapshots).
+ * Destination fs exists. It must be one of these cases:
+ * - an incremental send stream
+ * - the stream specifies a new fs (full stream or clone)
+ * and they want us to blow away the existing fs (and
+ * have therefore specified -F and removed any snapshots)
+ * - we are resuming a failed receive.
*/
if (stream_wantsnewfs) {
if (!flags->force) {
@@ -2830,6 +3337,18 @@
return (-1);
}
}
+
+ /*
+ * If we are resuming a newfs, set newfs here so that we will
+ * mount it if the recv succeeds this time. We can tell
+ * that it was a newfs on the first recv because the fs
+ * itself will be inconsistent (if the fs existed when we
+ * did the first recv, we would have received it into
+ * .../%recv).
+ */
+ if (resuming && zfs_prop_get_int(zhp, ZFS_PROP_INCONSISTENT))
+ newfs = B_TRUE;
+
zfs_close(zhp);
} else {
/*
@@ -2862,9 +3381,10 @@
newfs = B_TRUE;
}
- zc.zc_begin_record = drr_noswap->drr_u.drr_begin;
+ zc.zc_begin_record = *drr_noswap;
zc.zc_cookie = infd;
zc.zc_guid = flags->force;
+ zc.zc_resumable = flags->resumable;
if (flags->verbose) {
(void) printf("%s %s stream of %s into %s\n",
flags->dryrun ? "would receive" : "receiving",
@@ -2906,7 +3426,21 @@
ZPROP_N_MORE_ERRORS) == 0) {
trunc_prop_errs(intval);
break;
- } else {
+ } else if (snapname == NULL || finalsnap == NULL ||
+ strcmp(finalsnap, snapname) == 0 ||
+ strcmp(nvpair_name(prop_err),
+ zfs_prop_to_name(ZFS_PROP_REFQUOTA)) != 0) {
+ /*
+ * Skip the special case of, for example,
+ * "refquota", errors on intermediate
+ * snapshots leading up to a final one.
+ * That's why we have all of the checks above.
+ *
+ * See zfs_ioctl.c's extract_delay_props() for
+ * a list of props which can fail on
+ * intermediate snapshots, but shouldn't
+ * affect the overall receive.
+ */
(void) snprintf(tbuf, sizeof (tbuf),
dgettext(TEXT_DOMAIN,
"cannot receive %s property on %s"),
@@ -2949,7 +3483,7 @@
*/
*cp = '\0';
if (gather_nvlist(hdl, zc.zc_value, NULL, NULL, B_FALSE,
- &local_nv, &local_avl) == 0) {
+ B_FALSE, &local_nv, &local_avl) == 0) {
*cp = '@';
fs = fsavl_find(local_avl, drrb->drr_toguid, NULL);
fsavl_destroy(local_avl);
@@ -3001,8 +3535,7 @@
(void) zfs_error(hdl, EZFS_BADSTREAM, errbuf);
break;
case ECKSUM:
- zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
- "invalid stream (checksum mismatch)"));
+ recv_ecksum_set_aux(hdl, zc.zc_value, flags->resumable);
(void) zfs_error(hdl, EZFS_BADSTREAM, errbuf);
break;
case ENOTSUP:
@@ -3049,7 +3582,8 @@
}
if (clp) {
- err |= changelist_postfix(clp);
+ if (!flags->nomount)
+ err |= changelist_postfix(clp);
changelist_free(clp);
}
@@ -3089,9 +3623,10 @@
}
static int
-zfs_receive_impl(libzfs_handle_t *hdl, const char *tosnap, recvflags_t *flags,
- int infd, const char *sendfs, nvlist_t *stream_nv, avl_tree_t *stream_avl,
- char **top_zfs, int cleanup_fd, uint64_t *action_handlep)
+zfs_receive_impl(libzfs_handle_t *hdl, const char *tosnap,
+ const char *originsnap, recvflags_t *flags, int infd, const char *sendfs,
+ nvlist_t *stream_nv, avl_tree_t *stream_avl, char **top_zfs, int cleanup_fd,
+ uint64_t *action_handlep, const char *finalsnap)
{
int err;
dmu_replay_record_t drr, drr_noswap;
@@ -3110,6 +3645,12 @@
"(%s) does not exist"), tosnap);
return (zfs_error(hdl, EZFS_NOENT, errbuf));
}
+ if (originsnap &&
+ !zfs_dataset_exists(hdl, originsnap, ZFS_TYPE_DATASET)) {
+ zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "specified origin fs "
+ "(%s) does not exist"), originsnap);
+ return (zfs_error(hdl, EZFS_NOENT, errbuf));
+ }
/* read in the BEGIN record */
if (0 != (err = recv_read(hdl, infd, &drr, sizeof (drr), B_FALSE,
@@ -3169,7 +3710,7 @@
}
if (DMU_GET_STREAM_HDRTYPE(drrb->drr_versioninfo) == DMU_SUBSTREAM) {
- char nonpackage_sendfs[ZFS_MAXNAMELEN];
+ char nonpackage_sendfs[ZFS_MAX_DATASET_NAME_LEN];
if (sendfs == NULL) {
/*
* We were not called from zfs_receive_package(). Get
@@ -3177,19 +3718,21 @@
*/
char *cp;
(void) strlcpy(nonpackage_sendfs,
- drr.drr_u.drr_begin.drr_toname, ZFS_MAXNAMELEN);
+ drr.drr_u.drr_begin.drr_toname,
+ sizeof (nonpackage_sendfs));
if ((cp = strchr(nonpackage_sendfs, '@')) != NULL)
*cp = '\0';
sendfs = nonpackage_sendfs;
+ VERIFY(finalsnap == NULL);
}
- return (zfs_receive_one(hdl, infd, tosnap, flags,
- &drr, &drr_noswap, sendfs, stream_nv, stream_avl,
- top_zfs, cleanup_fd, action_handlep));
+ return (zfs_receive_one(hdl, infd, tosnap, originsnap, flags,
+ &drr, &drr_noswap, sendfs, stream_nv, stream_avl, top_zfs,
+ cleanup_fd, action_handlep, finalsnap));
} else {
assert(DMU_GET_STREAM_HDRTYPE(drrb->drr_versioninfo) ==
DMU_COMPOUNDSTREAM);
- return (zfs_receive_package(hdl, infd, tosnap, flags,
- &drr, &zcksum, top_zfs, cleanup_fd, action_handlep));
+ return (zfs_receive_package(hdl, infd, tosnap, flags, &drr,
+ &zcksum, top_zfs, cleanup_fd, action_handlep));
}
}
@@ -3197,22 +3740,29 @@
* Restores a backup of tosnap from the file descriptor specified by infd.
* Return 0 on total success, -2 if some things couldn't be
* destroyed/renamed/promoted, -1 if some things couldn't be received.
- * (-1 will override -2).
+ * (-1 will override -2, if -1 and the resumable flag was specified the
+ * transfer can be resumed if the sending side supports it).
*/
int
-zfs_receive(libzfs_handle_t *hdl, const char *tosnap, recvflags_t *flags,
- int infd, avl_tree_t *stream_avl)
+zfs_receive(libzfs_handle_t *hdl, const char *tosnap, nvlist_t *props,
+ recvflags_t *flags, int infd, avl_tree_t *stream_avl)
{
char *top_zfs = NULL;
int err;
int cleanup_fd;
uint64_t action_handle = 0;
+ char *originsnap = NULL;
+ if (props) {
+ err = nvlist_lookup_string(props, "origin", &originsnap);
+ if (err && err != ENOENT)
+ return (err);
+ }
cleanup_fd = open(ZFS_DEV, O_RDWR|O_EXCL);
VERIFY(cleanup_fd >= 0);
- err = zfs_receive_impl(hdl, tosnap, flags, infd, NULL, NULL,
- stream_avl, &top_zfs, cleanup_fd, &action_handle);
+ err = zfs_receive_impl(hdl, tosnap, originsnap, flags, infd, NULL, NULL,
+ stream_avl, &top_zfs, cleanup_fd, &action_handle, NULL);
VERIFY(0 == close(cleanup_fd));
Modified: trunk/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_status.c
===================================================================
--- trunk/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_status.c 2018-06-02 16:07:17 UTC (rev 10228)
+++ trunk/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_status.c 2018-06-02 16:07:30 UTC (rev 10229)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*
* CDDL HEADER START
*
@@ -73,57 +74,66 @@
/* ARGSUSED */
static int
-vdev_missing(uint64_t state, uint64_t aux, uint64_t errs)
+vdev_missing(vdev_stat_t *vs, uint_t vsc)
{
- return (state == VDEV_STATE_CANT_OPEN &&
- aux == VDEV_AUX_OPEN_FAILED);
+ return (vs->vs_state == VDEV_STATE_CANT_OPEN &&
+ vs->vs_aux == VDEV_AUX_OPEN_FAILED);
}
/* ARGSUSED */
static int
-vdev_faulted(uint64_t state, uint64_t aux, uint64_t errs)
+vdev_faulted(vdev_stat_t *vs, uint_t vsc)
{
- return (state == VDEV_STATE_FAULTED);
+ return (vs->vs_state == VDEV_STATE_FAULTED);
}
/* ARGSUSED */
static int
-vdev_errors(uint64_t state, uint64_t aux, uint64_t errs)
+vdev_errors(vdev_stat_t *vs, uint_t vsc)
{
- return (state == VDEV_STATE_DEGRADED || errs != 0);
+ return (vs->vs_state == VDEV_STATE_DEGRADED ||
+ vs->vs_read_errors != 0 || vs->vs_write_errors != 0 ||
+ vs->vs_checksum_errors != 0);
}
/* ARGSUSED */
static int
-vdev_broken(uint64_t state, uint64_t aux, uint64_t errs)
+vdev_broken(vdev_stat_t *vs, uint_t vsc)
{
- return (state == VDEV_STATE_CANT_OPEN);
+ return (vs->vs_state == VDEV_STATE_CANT_OPEN);
}
/* ARGSUSED */
static int
-vdev_offlined(uint64_t state, uint64_t aux, uint64_t errs)
+vdev_offlined(vdev_stat_t *vs, uint_t vsc)
{
- return (state == VDEV_STATE_OFFLINE);
+ return (vs->vs_state == VDEV_STATE_OFFLINE);
}
/* ARGSUSED */
static int
-vdev_removed(uint64_t state, uint64_t aux, uint64_t errs)
+vdev_removed(vdev_stat_t *vs, uint_t vsc)
{
- return (state == VDEV_STATE_REMOVED);
+ return (vs->vs_state == VDEV_STATE_REMOVED);
}
+static int
+vdev_non_native_ashift(vdev_stat_t *vs, uint_t vsc)
+{
+ return (VDEV_STAT_VALID(vs_physical_ashift, vsc) &&
+ vs->vs_configured_ashift < vs->vs_physical_ashift);
+}
+
/*
* Detect if any leaf devices that have seen errors or could not be opened.
*/
static boolean_t
-find_vdev_problem(nvlist_t *vdev, int (*func)(uint64_t, uint64_t, uint64_t))
+find_vdev_problem(nvlist_t *vdev, int (*func)(vdev_stat_t *, uint_t),
+ boolean_t ignore_replacing)
{
nvlist_t **child;
vdev_stat_t *vs;
- uint_t c, children;
- char *type;
+ uint_t c, vsc, children;
/*
* Ignore problems within a 'replacing' vdev, since we're presumably in
@@ -131,23 +141,25 @@
* out again. We'll pick up the fact that a resilver is happening
* later.
*/
- verify(nvlist_lookup_string(vdev, ZPOOL_CONFIG_TYPE, &type) == 0);
- if (strcmp(type, VDEV_TYPE_REPLACING) == 0)
- return (B_FALSE);
+ if (ignore_replacing == B_TRUE) {
+ char *type;
+ verify(nvlist_lookup_string(vdev, ZPOOL_CONFIG_TYPE,
+ &type) == 0);
+ if (strcmp(type, VDEV_TYPE_REPLACING) == 0)
+ return (B_FALSE);
+ }
+
if (nvlist_lookup_nvlist_array(vdev, ZPOOL_CONFIG_CHILDREN, &child,
&children) == 0) {
for (c = 0; c < children; c++)
- if (find_vdev_problem(child[c], func))
+ if (find_vdev_problem(child[c], func, ignore_replacing))
return (B_TRUE);
} else {
verify(nvlist_lookup_uint64_array(vdev, ZPOOL_CONFIG_VDEV_STATS,
- (uint64_t **)&vs, &c) == 0);
+ (uint64_t **)&vs, &vsc) == 0);
- if (func(vs->vs_state, vs->vs_aux,
- vs->vs_read_errors +
- vs->vs_write_errors +
- vs->vs_checksum_errors))
+ if (func(vs, vsc) != 0)
return (B_TRUE);
}
@@ -157,7 +169,7 @@
if (nvlist_lookup_nvlist_array(vdev, ZPOOL_CONFIG_L2CACHE, &child,
&children) == 0) {
for (c = 0; c < children; c++)
- if (find_vdev_problem(child[c], func))
+ if (find_vdev_problem(child[c], func, ignore_replacing))
return (B_TRUE);
}
@@ -270,15 +282,15 @@
* Bad devices in non-replicated config.
*/
if (vs->vs_state == VDEV_STATE_CANT_OPEN &&
- find_vdev_problem(nvroot, vdev_faulted))
+ find_vdev_problem(nvroot, vdev_faulted, B_TRUE))
return (ZPOOL_STATUS_FAULTED_DEV_NR);
if (vs->vs_state == VDEV_STATE_CANT_OPEN &&
- find_vdev_problem(nvroot, vdev_missing))
+ find_vdev_problem(nvroot, vdev_missing, B_TRUE))
return (ZPOOL_STATUS_MISSING_DEV_NR);
if (vs->vs_state == VDEV_STATE_CANT_OPEN &&
- find_vdev_problem(nvroot, vdev_broken))
+ find_vdev_problem(nvroot, vdev_broken, B_TRUE))
return (ZPOOL_STATUS_CORRUPT_LABEL_NR);
/*
@@ -300,32 +312,38 @@
/*
* Missing devices in a replicated config.
*/
- if (find_vdev_problem(nvroot, vdev_faulted))
+ if (find_vdev_problem(nvroot, vdev_faulted, B_TRUE))
return (ZPOOL_STATUS_FAULTED_DEV_R);
- if (find_vdev_problem(nvroot, vdev_missing))
+ if (find_vdev_problem(nvroot, vdev_missing, B_TRUE))
return (ZPOOL_STATUS_MISSING_DEV_R);
- if (find_vdev_problem(nvroot, vdev_broken))
+ if (find_vdev_problem(nvroot, vdev_broken, B_TRUE))
return (ZPOOL_STATUS_CORRUPT_LABEL_R);
/*
* Devices with errors
*/
- if (!isimport && find_vdev_problem(nvroot, vdev_errors))
+ if (!isimport && find_vdev_problem(nvroot, vdev_errors, B_TRUE))
return (ZPOOL_STATUS_FAILING_DEV);
/*
* Offlined devices
*/
- if (find_vdev_problem(nvroot, vdev_offlined))
+ if (find_vdev_problem(nvroot, vdev_offlined, B_TRUE))
return (ZPOOL_STATUS_OFFLINE_DEV);
/*
* Removed device
*/
- if (find_vdev_problem(nvroot, vdev_removed))
+ if (find_vdev_problem(nvroot, vdev_removed, B_TRUE))
return (ZPOOL_STATUS_REMOVED_DEV);
/*
+ * Suboptimal, but usable, ashift configuration.
+ */
+ if (find_vdev_problem(nvroot, vdev_non_native_ashift, B_FALSE))
+ return (ZPOOL_STATUS_NON_NATIVE_ASHIFT);
+
+ /*
* Outdated, but usable, version
*/
if (SPA_VERSION_IS_SUPPORTED(version) && version != SPA_VERSION)
Modified: trunk/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_util.c
===================================================================
--- trunk/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_util.c 2018-06-02 16:07:17 UTC (rev 10228)
+++ trunk/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_util.c 2018-06-02 16:07:30 UTC (rev 10229)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*
* CDDL HEADER START
*
@@ -21,7 +22,9 @@
/*
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2012 by Delphix. All rights reserved.
+ * Copyright (c) 2013, Joyent, Inc. All rights reserved.
+ * Copyright (c) 2011, 2015 by Delphix. All rights reserved.
+ * Copyright 2016 Igor Kozhukhov <ikozhukhov at gmail.com>
*/
/*
@@ -46,6 +49,7 @@
#include <sys/mnttab.h>
#include <sys/mntent.h>
#include <sys/types.h>
+#include <libcmdutils.h>
#include <libzfs.h>
#include <libzfs_core.h>
@@ -54,7 +58,6 @@
#include "zfs_prop.h"
#include "zfeature_common.h"
-int aok;
int
libzfs_errno(libzfs_handle_t *hdl)
@@ -369,6 +372,7 @@
case ENOSPC:
case EDQUOT:
zfs_verror(hdl, EZFS_NOSPC, fmt, ap);
+ va_end(ap);
return (-1);
case EEXIST:
@@ -468,6 +472,7 @@
case ENOSPC:
case EDQUOT:
zfs_verror(hdl, EZFS_NOSPC, fmt, ap);
+ va_end(ap);
return (-1);
case EAGAIN:
@@ -572,42 +577,7 @@
void
zfs_nicenum(uint64_t num, char *buf, size_t buflen)
{
- uint64_t n = num;
- int index = 0;
- char u;
-
- while (n >= 1024) {
- n /= 1024;
- index++;
- }
-
- u = " KMGTPE"[index];
-
- if (index == 0) {
- (void) snprintf(buf, buflen, "%llu", n);
- } else if ((num & ((1ULL << 10 * index) - 1)) == 0) {
- /*
- * If this is an even multiple of the base, always display
- * without any decimal precision.
- */
- (void) snprintf(buf, buflen, "%llu%c", n, u);
- } else {
- /*
- * We want to choose a precision that reflects the best choice
- * for fitting in 5 characters. This can get rather tricky when
- * we have numbers that are very close to an order of magnitude.
- * For example, when displaying 10239 (which is really 9.999K),
- * we want only a single place of precision for 10.0K. We could
- * develop some complex heuristics for this, but it's much
- * easier just to try each combination in turn.
- */
- int i;
- for (i = 2; i >= 0; i--) {
- if (snprintf(buf, buflen, "%.*f%c", i,
- (double)num / (1ULL << 10 * index), u) <= 5)
- break;
- }
- }
+ nicenum(num, buf, buflen);
}
void
@@ -684,7 +654,7 @@
(void) fclose(hdl->libzfs_sharetab);
zfs_uninit_libshare(hdl);
zpool_free_handles(hdl);
-#ifdef sun
+#ifdef illumos
libzfs_fru_clear(hdl, B_TRUE);
#endif
namespace_clear(hdl);
@@ -736,7 +706,7 @@
return (NULL);
}
-#ifdef sun
+#ifdef illumos
rewind(hdl->libzfs_mnttab);
while ((ret = getextmntent(hdl->libzfs_mnttab, &entry, 0)) == 0) {
if (makedevice(entry.mnt_major, entry.mnt_minor) ==
@@ -756,7 +726,7 @@
strerror(errno));
}
}
-#endif /* sun */
+#endif /* illumos */
if (ret != 0) {
return (NULL);
}
@@ -780,8 +750,9 @@
if (len == 0)
len = 16 * 1024;
zc->zc_nvlist_dst_size = len;
- if ((zc->zc_nvlist_dst = (uint64_t)(uintptr_t)
- zfs_alloc(hdl, zc->zc_nvlist_dst_size)) == 0)
+ zc->zc_nvlist_dst =
+ (uint64_t)(uintptr_t)zfs_alloc(hdl, zc->zc_nvlist_dst_size);
+ if (zc->zc_nvlist_dst == 0)
return (-1);
return (0);
@@ -796,9 +767,9 @@
zcmd_expand_dst_nvlist(libzfs_handle_t *hdl, zfs_cmd_t *zc)
{
free((void *)(uintptr_t)zc->zc_nvlist_dst);
- if ((zc->zc_nvlist_dst = (uint64_t)(uintptr_t)
- zfs_alloc(hdl, zc->zc_nvlist_dst_size))
- == 0)
+ zc->zc_nvlist_dst =
+ (uint64_t)(uintptr_t)zfs_alloc(hdl, zc->zc_nvlist_dst_size);
+ if (zc->zc_nvlist_dst == 0)
return (-1);
return (0);
@@ -813,6 +784,9 @@
free((void *)(uintptr_t)zc->zc_nvlist_conf);
free((void *)(uintptr_t)zc->zc_nvlist_src);
free((void *)(uintptr_t)zc->zc_nvlist_dst);
+ zc->zc_nvlist_conf = NULL;
+ zc->zc_nvlist_src = NULL;
+ zc->zc_nvlist_dst = NULL;
}
static int
@@ -1004,7 +978,7 @@
const char *source, const char *recvd_value)
{
int i;
- const char *str;
+ const char *str = NULL;
char buf[128];
/*
@@ -1056,6 +1030,10 @@
case ZPROP_SRC_RECEIVED:
str = "received";
break;
+
+ default:
+ str = NULL;
+ assert(!"unhandled zprop_source_t");
}
break;
@@ -1266,6 +1244,16 @@
"use 'none' to disable quota/refquota"));
goto error;
}
+
+ /*
+ * Special handling for "*_limit=none". In this case it's not
+ * 0 but UINT64_MAX.
+ */
+ if ((type & ZFS_TYPE_DATASET) && isnone &&
+ (prop == ZFS_PROP_FILESYSTEM_LIMIT ||
+ prop == ZFS_PROP_SNAPSHOT_LIMIT)) {
+ *ivalp = UINT64_MAX;
+ }
break;
case PROP_TYPE_INDEX:
Modified: trunk/cddl/contrib/opensolaris/lib/libzfs_core/common/libzfs_core.c
===================================================================
--- trunk/cddl/contrib/opensolaris/lib/libzfs_core/common/libzfs_core.c 2018-06-02 16:07:17 UTC (rev 10228)
+++ trunk/cddl/contrib/opensolaris/lib/libzfs_core/common/libzfs_core.c 2018-06-02 16:07:30 UTC (rev 10229)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*
* CDDL HEADER START
*
@@ -20,8 +21,9 @@
*/
/*
- * Copyright (c) 2012 by Delphix. All rights reserved.
+ * Copyright (c) 2012, 2014 by Delphix. All rights reserved.
* Copyright (c) 2013 Steven Hartland. All rights reserved.
+ * Copyright (c) 2014 Integros [integros.com]
*/
/*
@@ -217,11 +219,11 @@
}
int
-lzc_create(const char *fsname, dmu_objset_type_t type, nvlist_t *props)
+lzc_create(const char *fsname, enum lzc_dataset_type type, nvlist_t *props)
{
int error;
nvlist_t *args = fnvlist_alloc();
- fnvlist_add_int32(args, "type", type);
+ fnvlist_add_int32(args, "type", (dmu_objset_type_t)type);
if (props != NULL)
fnvlist_add_nvlist(args, "props", props);
error = lzc_ioctl(ZFS_IOC_CREATE, fsname, args, NULL);
@@ -264,7 +266,7 @@
nvpair_t *elem;
nvlist_t *args;
int error;
- char pool[MAXNAMELEN];
+ char pool[ZFS_MAX_DATASET_NAME_LEN];
*errlist = NULL;
@@ -316,7 +318,7 @@
nvpair_t *elem;
nvlist_t *args;
int error;
- char pool[MAXNAMELEN];
+ char pool[ZFS_MAX_DATASET_NAME_LEN];
/* determine the pool name */
elem = nvlist_next_nvpair(snaps, NULL);
@@ -343,7 +345,7 @@
nvlist_t *args;
nvlist_t *result;
int err;
- char fs[MAXNAMELEN];
+ char fs[ZFS_MAX_DATASET_NAME_LEN];
char *atp;
/* determine the fs name */
@@ -408,7 +410,7 @@
int
lzc_hold(nvlist_t *holds, int cleanup_fd, nvlist_t **errlist)
{
- char pool[MAXNAMELEN];
+ char pool[ZFS_MAX_DATASET_NAME_LEN];
nvlist_t *args;
nvpair_t *elem;
int error;
@@ -455,7 +457,7 @@
int
lzc_release(nvlist_t *holds, nvlist_t **errlist)
{
- char pool[MAXNAMELEN];
+ char pool[ZFS_MAX_DATASET_NAME_LEN];
nvpair_t *elem;
/* determine the pool name */
@@ -486,18 +488,57 @@
}
/*
- * If fromsnap is NULL, a full (non-incremental) stream will be sent.
+ * Generate a zfs send stream for the specified snapshot and write it to
+ * the specified file descriptor.
+ *
+ * "snapname" is the full name of the snapshot to send (e.g. "pool/fs at snap")
+ *
+ * If "from" is NULL, a full (non-incremental) stream will be sent.
+ * If "from" is non-NULL, it must be the full name of a snapshot or
+ * bookmark to send an incremental from (e.g. "pool/fs at earlier_snap" or
+ * "pool/fs#earlier_bmark"). If non-NULL, the specified snapshot or
+ * bookmark must represent an earlier point in the history of "snapname").
+ * It can be an earlier snapshot in the same filesystem or zvol as "snapname",
+ * or it can be the origin of "snapname"'s filesystem, or an earlier
+ * snapshot in the origin, etc.
+ *
+ * "fd" is the file descriptor to write the send stream to.
+ *
+ * If "flags" contains LZC_SEND_FLAG_LARGE_BLOCK, the stream is permitted
+ * to contain DRR_WRITE records with drr_length > 128K, and DRR_OBJECT
+ * records with drr_blksz > 128K.
+ *
+ * If "flags" contains LZC_SEND_FLAG_EMBED_DATA, the stream is permitted
+ * to contain DRR_WRITE_EMBEDDED records with drr_etype==BP_EMBEDDED_TYPE_DATA,
+ * which the receiving system must support (as indicated by support
+ * for the "embedded_data" feature).
*/
int
-lzc_send(const char *snapname, const char *fromsnap, int fd)
+lzc_send(const char *snapname, const char *from, int fd,
+ enum lzc_send_flags flags)
{
+ return (lzc_send_resume(snapname, from, fd, flags, 0, 0));
+}
+
+int
+lzc_send_resume(const char *snapname, const char *from, int fd,
+ enum lzc_send_flags flags, uint64_t resumeobj, uint64_t resumeoff)
+{
nvlist_t *args;
int err;
args = fnvlist_alloc();
fnvlist_add_int32(args, "fd", fd);
- if (fromsnap != NULL)
- fnvlist_add_string(args, "fromsnap", fromsnap);
+ if (from != NULL)
+ fnvlist_add_string(args, "fromsnap", from);
+ if (flags & LZC_SEND_FLAG_LARGE_BLOCK)
+ fnvlist_add_boolean(args, "largeblockok");
+ if (flags & LZC_SEND_FLAG_EMBED_DATA)
+ fnvlist_add_boolean(args, "embedok");
+ if (resumeobj != 0 || resumeoff != 0) {
+ fnvlist_add_uint64(args, "resume_object", resumeobj);
+ fnvlist_add_uint64(args, "resume_offset", resumeoff);
+ }
err = lzc_ioctl(ZFS_IOC_SEND_NEW, snapname, args, NULL);
nvlist_free(args);
return (err);
@@ -504,10 +545,22 @@
}
/*
- * If fromsnap is NULL, a full (non-incremental) stream will be estimated.
+ * "from" can be NULL, a snapshot, or a bookmark.
+ *
+ * If from is NULL, a full (non-incremental) stream will be estimated. This
+ * is calculated very efficiently.
+ *
+ * If from is a snapshot, lzc_send_space uses the deadlists attached to
+ * each snapshot to efficiently estimate the stream size.
+ *
+ * If from is a bookmark, the indirect blocks in the destination snapshot
+ * are traversed, looking for blocks with a birth time since the creation TXG of
+ * the snapshot this bookmark was created from. This will result in
+ * significantly more I/O and be less efficient than a send space estimation on
+ * an equivalent snapshot.
*/
int
-lzc_send_space(const char *snapname, const char *fromsnap, uint64_t *spacep)
+lzc_send_space(const char *snapname, const char *from, uint64_t *spacep)
{
nvlist_t *args;
nvlist_t *result;
@@ -514,8 +567,8 @@
int err;
args = fnvlist_alloc();
- if (fromsnap != NULL)
- fnvlist_add_string(args, "fromsnap", fromsnap);
+ if (from != NULL)
+ fnvlist_add_string(args, "from", from);
err = lzc_ioctl(ZFS_IOC_SEND_SPACE, snapname, args, &result);
nvlist_free(args);
if (err == 0)
@@ -543,22 +596,10 @@
return (0);
}
-/*
- * The simplest receive case: receive from the specified fd, creating the
- * specified snapshot. Apply the specified properties a "received" properties
- * (which can be overridden by locally-set properties). If the stream is a
- * clone, its origin snapshot must be specified by 'origin'. The 'force'
- * flag will cause the target filesystem to be rolled back or destroyed if
- * necessary to receive.
- *
- * Return 0 on success or an errno on failure.
- *
- * Note: this interface does not work on dedup'd streams
- * (those with DMU_BACKUP_FEATURE_DEDUP).
- */
-int
-lzc_receive(const char *snapname, nvlist_t *props, const char *origin,
- boolean_t force, int fd)
+static int
+recv_impl(const char *snapname, nvlist_t *props, const char *origin,
+ boolean_t force, boolean_t resumable, int fd,
+ const dmu_replay_record_t *begin_record)
{
/*
* The receive ioctl is still legacy, so we need to construct our own
@@ -568,7 +609,6 @@
char *atp;
char *packed = NULL;
size_t size;
- dmu_replay_record_t drr;
int error;
ASSERT3S(g_refcount, >, 0);
@@ -604,10 +644,14 @@
(void) strlcpy(zc.zc_string, origin, sizeof (zc.zc_string));
/* zc_begin_record is non-byteswapped BEGIN record */
- error = recv_read(fd, &drr, sizeof (drr));
- if (error != 0)
- goto out;
- zc.zc_begin_record = drr.drr_u.drr_begin;
+ if (begin_record == NULL) {
+ error = recv_read(fd, &zc.zc_begin_record,
+ sizeof (zc.zc_begin_record));
+ if (error != 0)
+ goto out;
+ } else {
+ zc.zc_begin_record = *begin_record;
+ }
/* zc_cookie is fd to read from */
zc.zc_cookie = fd;
@@ -615,6 +659,8 @@
/* zc guid is force flag */
zc.zc_guid = force;
+ zc.zc_resumable = resumable;
+
/* zc_cleanup_fd is unused */
zc.zc_cleanup_fd = -1;
@@ -628,3 +674,176 @@
free((void*)(uintptr_t)zc.zc_nvlist_dst);
return (error);
}
+
+/*
+ * The simplest receive case: receive from the specified fd, creating the
+ * specified snapshot. Apply the specified properties as "received" properties
+ * (which can be overridden by locally-set properties). If the stream is a
+ * clone, its origin snapshot must be specified by 'origin'. The 'force'
+ * flag will cause the target filesystem to be rolled back or destroyed if
+ * necessary to receive.
+ *
+ * Return 0 on success or an errno on failure.
+ *
+ * Note: this interface does not work on dedup'd streams
+ * (those with DMU_BACKUP_FEATURE_DEDUP).
+ */
+int
+lzc_receive(const char *snapname, nvlist_t *props, const char *origin,
+ boolean_t force, int fd)
+{
+ return (recv_impl(snapname, props, origin, force, B_FALSE, fd, NULL));
+}
+
+/*
+ * Like lzc_receive, but if the receive fails due to premature stream
+ * termination, the intermediate state will be preserved on disk. In this
+ * case, ECKSUM will be returned. The receive may subsequently be resumed
+ * with a resuming send stream generated by lzc_send_resume().
+ */
+int
+lzc_receive_resumable(const char *snapname, nvlist_t *props, const char *origin,
+ boolean_t force, int fd)
+{
+ return (recv_impl(snapname, props, origin, force, B_TRUE, fd, NULL));
+}
+
+/*
+ * Like lzc_receive, but allows the caller to read the begin record and then to
+ * pass it in. That could be useful if the caller wants to derive, for example,
+ * the snapname or the origin parameters based on the information contained in
+ * the begin record.
+ * The begin record must be in its original form as read from the stream,
+ * in other words, it should not be byteswapped.
+ *
+ * The 'resumable' parameter allows to obtain the same behavior as with
+ * lzc_receive_resumable.
+ */
+int
+lzc_receive_with_header(const char *snapname, nvlist_t *props,
+ const char *origin, boolean_t force, boolean_t resumable, int fd,
+ const dmu_replay_record_t *begin_record)
+{
+ if (begin_record == NULL)
+ return (EINVAL);
+ return (recv_impl(snapname, props, origin, force, resumable, fd,
+ begin_record));
+}
+
+/*
+ * Roll back this filesystem or volume to its most recent snapshot.
+ * If snapnamebuf is not NULL, it will be filled in with the name
+ * of the most recent snapshot.
+ *
+ * Return 0 on success or an errno on failure.
+ */
+int
+lzc_rollback(const char *fsname, char *snapnamebuf, int snapnamelen)
+{
+ nvlist_t *args;
+ nvlist_t *result;
+ int err;
+
+ args = fnvlist_alloc();
+ err = lzc_ioctl(ZFS_IOC_ROLLBACK, fsname, args, &result);
+ nvlist_free(args);
+ if (err == 0 && snapnamebuf != NULL) {
+ const char *snapname = fnvlist_lookup_string(result, "target");
+ (void) strlcpy(snapnamebuf, snapname, snapnamelen);
+ }
+ return (err);
+}
+
+/*
+ * Creates bookmarks.
+ *
+ * The bookmarks nvlist maps from name of the bookmark (e.g. "pool/fs#bmark") to
+ * the name of the snapshot (e.g. "pool/fs at snap"). All the bookmarks and
+ * snapshots must be in the same pool.
+ *
+ * The returned results nvlist will have an entry for each bookmark that failed.
+ * The value will be the (int32) error code.
+ *
+ * The return value will be 0 if all bookmarks were created, otherwise it will
+ * be the errno of a (undetermined) bookmarks that failed.
+ */
+int
+lzc_bookmark(nvlist_t *bookmarks, nvlist_t **errlist)
+{
+ nvpair_t *elem;
+ int error;
+ char pool[ZFS_MAX_DATASET_NAME_LEN];
+
+ /* determine the pool name */
+ elem = nvlist_next_nvpair(bookmarks, NULL);
+ if (elem == NULL)
+ return (0);
+ (void) strlcpy(pool, nvpair_name(elem), sizeof (pool));
+ pool[strcspn(pool, "/#")] = '\0';
+
+ error = lzc_ioctl(ZFS_IOC_BOOKMARK, pool, bookmarks, errlist);
+
+ return (error);
+}
+
+/*
+ * Retrieve bookmarks.
+ *
+ * Retrieve the list of bookmarks for the given file system. The props
+ * parameter is an nvlist of property names (with no values) that will be
+ * returned for each bookmark.
+ *
+ * The following are valid properties on bookmarks, all of which are numbers
+ * (represented as uint64 in the nvlist)
+ *
+ * "guid" - globally unique identifier of the snapshot it refers to
+ * "createtxg" - txg when the snapshot it refers to was created
+ * "creation" - timestamp when the snapshot it refers to was created
+ *
+ * The format of the returned nvlist as follows:
+ * <short name of bookmark> -> {
+ * <name of property> -> {
+ * "value" -> uint64
+ * }
+ * }
+ */
+int
+lzc_get_bookmarks(const char *fsname, nvlist_t *props, nvlist_t **bmarks)
+{
+ return (lzc_ioctl(ZFS_IOC_GET_BOOKMARKS, fsname, props, bmarks));
+}
+
+/*
+ * Destroys bookmarks.
+ *
+ * The keys in the bmarks nvlist are the bookmarks to be destroyed.
+ * They must all be in the same pool. Bookmarks are specified as
+ * <fs>#<bmark>.
+ *
+ * Bookmarks that do not exist will be silently ignored.
+ *
+ * The return value will be 0 if all bookmarks that existed were destroyed.
+ *
+ * Otherwise the return value will be the errno of a (undetermined) bookmark
+ * that failed, no bookmarks will be destroyed, and the errlist will have an
+ * entry for each bookmarks that failed. The value in the errlist will be
+ * the (int32) error code.
+ */
+int
+lzc_destroy_bookmarks(nvlist_t *bmarks, nvlist_t **errlist)
+{
+ nvpair_t *elem;
+ int error;
+ char pool[ZFS_MAX_DATASET_NAME_LEN];
+
+ /* determine the pool name */
+ elem = nvlist_next_nvpair(bmarks, NULL);
+ if (elem == NULL)
+ return (0);
+ (void) strlcpy(pool, nvpair_name(elem), sizeof (pool));
+ pool[strcspn(pool, "/#")] = '\0';
+
+ error = lzc_ioctl(ZFS_IOC_DESTROY_BOOKMARKS, pool, bmarks, errlist);
+
+ return (error);
+}
Modified: trunk/cddl/contrib/opensolaris/lib/libzfs_core/common/libzfs_core.h
===================================================================
--- trunk/cddl/contrib/opensolaris/lib/libzfs_core/common/libzfs_core.h 2018-06-02 16:07:17 UTC (rev 10228)
+++ trunk/cddl/contrib/opensolaris/lib/libzfs_core/common/libzfs_core.h 2018-06-02 16:07:30 UTC (rev 10229)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*
* CDDL HEADER START
*
@@ -20,7 +21,7 @@
*/
/*
- * Copyright (c) 2012 by Delphix. All rights reserved.
+ * Copyright (c) 2012, 2014 by Delphix. All rights reserved.
* Copyright (c) 2013 by Martin Matuska <mm at FreeBSD.org>. All rights reserved.
*/
@@ -30,7 +31,6 @@
#include <libnvpair.h>
#include <sys/param.h>
#include <sys/types.h>
-#include <sys/fs/zfs.h>
#ifdef __cplusplus
extern "C" {
@@ -39,27 +39,50 @@
int libzfs_core_init(void);
void libzfs_core_fini(void);
-int lzc_snapshot(nvlist_t *snaps, nvlist_t *props, nvlist_t **errlist);
-int lzc_create(const char *fsname, dmu_objset_type_t type, nvlist_t *props);
-int lzc_clone(const char *fsname, const char *origin, nvlist_t *props);
-int lzc_destroy_snaps(nvlist_t *snaps, boolean_t defer, nvlist_t **errlist);
+/*
+ * NB: this type should be kept binary compatible with dmu_objset_type_t.
+ */
+enum lzc_dataset_type {
+ LZC_DATSET_TYPE_ZFS = 2,
+ LZC_DATSET_TYPE_ZVOL
+};
-int lzc_snaprange_space(const char *firstsnap, const char *lastsnap,
- uint64_t *usedp);
+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_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 **);
+int lzc_destroy_bookmarks(nvlist_t *, nvlist_t **);
-int lzc_hold(nvlist_t *holds, int cleanup_fd, nvlist_t **errlist);
-int lzc_release(nvlist_t *holds, nvlist_t **errlist);
-int lzc_get_holds(const char *snapname, nvlist_t **holdsp);
+int lzc_snaprange_space(const char *, const char *, uint64_t *);
-int lzc_send(const char *snapname, const char *fromsnap, int fd);
-int lzc_receive(const char *snapname, nvlist_t *props, const char *origin,
- boolean_t force, int fd);
-int lzc_send_space(const char *snapname, const char *fromsnap,
- uint64_t *result);
+int lzc_hold(nvlist_t *, int, nvlist_t **);
+int lzc_release(nvlist_t *, nvlist_t **);
+int lzc_get_holds(const char *, nvlist_t **);
-boolean_t lzc_exists(const char *dataset);
+enum lzc_send_flags {
+ LZC_SEND_FLAG_EMBED_DATA = 1 << 0,
+ LZC_SEND_FLAG_LARGE_BLOCK = 1 << 1
+};
+int lzc_send(const char *, const char *, int, enum lzc_send_flags);
+int lzc_send_resume(const char *, const char *, int,
+ enum lzc_send_flags, uint64_t, uint64_t);
+int lzc_send_space(const char *, const char *, uint64_t *);
+struct dmu_replay_record;
+
+int lzc_receive(const char *, nvlist_t *, const char *, boolean_t, int);
+int lzc_receive_resumable(const char *, nvlist_t *, const char *,
+ boolean_t, int);
+int lzc_receive_with_header(const char *, nvlist_t *, const char *, boolean_t,
+ boolean_t, int, const struct dmu_replay_record *);
+
+boolean_t lzc_exists(const char *);
+
+int lzc_rollback(const char *, char *, int);
+
#ifdef __cplusplus
}
#endif
Modified: trunk/cddl/contrib/opensolaris/lib/libzfs_core/common/libzfs_core_compat.c
===================================================================
--- trunk/cddl/contrib/opensolaris/lib/libzfs_core/common/libzfs_core_compat.c 2018-06-02 16:07:17 UTC (rev 10228)
+++ trunk/cddl/contrib/opensolaris/lib/libzfs_core/common/libzfs_core_compat.c 2018-06-02 16:07:30 UTC (rev 10229)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*
* CDDL HEADER START
*
Modified: trunk/cddl/contrib/opensolaris/lib/libzfs_core/common/libzfs_core_compat.h
===================================================================
--- trunk/cddl/contrib/opensolaris/lib/libzfs_core/common/libzfs_core_compat.h 2018-06-02 16:07:17 UTC (rev 10228)
+++ trunk/cddl/contrib/opensolaris/lib/libzfs_core/common/libzfs_core_compat.h 2018-06-02 16:07:30 UTC (rev 10229)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*
* CDDL HEADER START
*
Modified: trunk/cddl/contrib/opensolaris/lib/libzpool/common/kernel.c
===================================================================
--- trunk/cddl/contrib/opensolaris/lib/libzpool/common/kernel.c 2018-06-02 16:07:17 UTC (rev 10228)
+++ trunk/cddl/contrib/opensolaris/lib/libzpool/common/kernel.c 2018-06-02 16:07:30 UTC (rev 10229)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*
* CDDL HEADER START
*
@@ -20,6 +21,8 @@
*/
/*
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2015 by Delphix. All rights reserved.
+ * Copyright (c) 2013, Joyent, Inc. All rights reserved.
*/
#include <assert.h>
@@ -29,6 +32,7 @@
#include <stdlib.h>
#include <string.h>
#include <zlib.h>
+#include <libgen.h>
#include <sys/spa.h>
#include <sys/stat.h>
#include <sys/processor.h>
@@ -42,7 +46,9 @@
* Emulation of kernel services in userland.
*/
+#ifndef __FreeBSD__
int aok;
+#endif
uint64_t physmem;
vnode_t *rootdir = (vnode_t *)0xabcd1234;
char hw_serial[HW_HOSTID_LEN];
@@ -50,6 +56,9 @@
kmutex_t cpu_lock;
#endif
+/* If set, all blocks read will be copied to the specified directory. */
+char *vn_dumpdir = NULL;
+
struct utsname utsname = {
"userland", "libzpool", "1", "1", "na"
};
@@ -349,6 +358,49 @@
return (1);
}
+/*ARGSUSED*/
+clock_t
+cv_timedwait_hires(kcondvar_t *cv, kmutex_t *mp, hrtime_t tim, hrtime_t res,
+ int flag)
+{
+ int error;
+ timespec_t ts;
+ hrtime_t delta;
+
+ ASSERT(flag == 0 || flag == CALLOUT_FLAG_ABSOLUTE);
+
+top:
+ delta = tim;
+ if (flag & CALLOUT_FLAG_ABSOLUTE)
+ delta -= gethrtime();
+
+ if (delta <= 0)
+ return (-1);
+
+ clock_gettime(CLOCK_REALTIME, &ts);
+ ts.tv_sec += delta / NANOSEC;
+ ts.tv_nsec += delta % NANOSEC;
+ if (ts.tv_nsec >= NANOSEC) {
+ ts.tv_sec++;
+ ts.tv_nsec -= NANOSEC;
+ }
+
+ ASSERT(mutex_owner(mp) == curthread);
+ mp->m_owner = NULL;
+ error = pthread_cond_timedwait(cv, &mp->m_lock, &ts);
+ mp->m_owner = curthread;
+
+ if (error == ETIMEDOUT)
+ return (-1);
+
+ if (error == EINTR)
+ goto top;
+
+ ASSERT(error == 0);
+
+ return (1);
+}
+
void
cv_signal(kcondvar_t *cv)
{
@@ -378,6 +430,7 @@
vn_open(char *path, int x1, int flags, int mode, vnode_t **vpp, int x2, int x3)
{
int fd;
+ int dump_fd;
vnode_t *vp;
int old_umask;
char realpath[MAXPATHLEN];
@@ -426,6 +479,17 @@
if (flags & FCREAT)
(void) umask(old_umask);
+ if (vn_dumpdir != NULL) {
+ char dumppath[MAXPATHLEN];
+ (void) snprintf(dumppath, sizeof (dumppath),
+ "%s/%s", vn_dumpdir, basename(realpath));
+ dump_fd = open64(dumppath, O_CREAT | O_WRONLY, 0666);
+ if (dump_fd == -1)
+ return (errno);
+ } else {
+ dump_fd = -1;
+ }
+
if (fd == -1)
return (errno);
@@ -441,6 +505,7 @@
vp->v_fd = fd;
vp->v_size = st.st_size;
vp->v_path = spa_strdup(path);
+ vp->v_dump_fd = dump_fd;
return (0);
}
@@ -467,12 +532,17 @@
/*ARGSUSED*/
int
vn_rdwr(int uio, vnode_t *vp, void *addr, ssize_t len, offset_t offset,
- int x1, int x2, rlim64_t x3, void *x4, ssize_t *residp)
+ int x1, int x2, rlim64_t x3, void *x4, ssize_t *residp)
{
ssize_t iolen, split;
if (uio == UIO_READ) {
iolen = pread64(vp->v_fd, addr, len, offset);
+ if (vp->v_dump_fd != -1) {
+ int status =
+ pwrite64(vp->v_dump_fd, addr, iolen, offset);
+ ASSERT(status != -1);
+ }
} else {
/*
* To simulate partial disk writes, we split writes into two
@@ -499,6 +569,8 @@
vn_close(vnode_t *vp, int openflag, cred_t *cr, kthread_t *td)
{
close(vp->v_fd);
+ if (vp->v_dump_fd != -1)
+ close(vp->v_dump_fd);
spa_strfree(vp->v_path);
umem_free(vp, sizeof (vnode_t));
}
@@ -591,6 +663,12 @@
dprintf_print_all = 1;
}
+int
+sysctl_handle_64(SYSCTL_HANDLER_ARGS)
+{
+ return (0);
+}
+
/*
* =========================================================================
* debug printfs
@@ -620,7 +698,7 @@
if (dprintf_find_string("pid"))
(void) printf("%d ", getpid());
if (dprintf_find_string("tid"))
- (void) printf("%u ", thr_self());
+ (void) printf("%ul ", thr_self());
#if 0
if (dprintf_find_string("cpu"))
(void) printf("%u ", getcpuid());
@@ -650,11 +728,9 @@
void
vpanic(const char *fmt, va_list adx)
{
- (void) fprintf(stderr, "error: ");
- (void) vfprintf(stderr, fmt, adx);
- (void) fprintf(stderr, "\n");
-
- abort(); /* think of it as a "user-level crash dump" */
+ char buf[512];
+ (void) vsnprintf(buf, 512, fmt, adx);
+ assfail(buf, NULL, 0);
}
void
@@ -759,20 +835,17 @@
/*
* Find highest one bit set.
* Returns bit number + 1 of highest bit that is set, otherwise returns 0.
- * High order bit is 31 (or 63 in _LP64 kernel).
*/
int
-highbit(ulong_t i)
+highbit64(uint64_t i)
{
- register int h = 1;
+ int h = 1;
if (i == 0)
return (0);
-#ifdef _LP64
- if (i & 0xffffffff00000000ul) {
+ if (i & 0xffffffff00000000ULL) {
h += 32; i >>= 32;
}
-#endif
if (i & 0xffff0000) {
h += 16; i >>= 16;
}
@@ -1084,3 +1157,50 @@
return (0);
}
#endif
+
+#ifdef illumos
+void
+bioinit(buf_t *bp)
+{
+ bzero(bp, sizeof (buf_t));
+}
+
+void
+biodone(buf_t *bp)
+{
+ if (bp->b_iodone != NULL) {
+ (*(bp->b_iodone))(bp);
+ return;
+ }
+ ASSERT((bp->b_flags & B_DONE) == 0);
+ bp->b_flags |= B_DONE;
+}
+
+void
+bioerror(buf_t *bp, int error)
+{
+ ASSERT(bp != NULL);
+ ASSERT(error >= 0);
+
+ if (error != 0) {
+ bp->b_flags |= B_ERROR;
+ } else {
+ bp->b_flags &= ~B_ERROR;
+ }
+ bp->b_error = error;
+}
+
+
+int
+geterror(struct buf *bp)
+{
+ int error = 0;
+
+ if (bp->b_flags & B_ERROR) {
+ error = bp->b_error;
+ if (!error)
+ error = EIO;
+ }
+ return (error);
+}
+#endif
Modified: trunk/cddl/contrib/opensolaris/lib/libzpool/common/sys/zfs_context.h
===================================================================
--- trunk/cddl/contrib/opensolaris/lib/libzpool/common/sys/zfs_context.h 2018-06-02 16:07:17 UTC (rev 10228)
+++ trunk/cddl/contrib/opensolaris/lib/libzpool/common/sys/zfs_context.h 2018-06-02 16:07:30 UTC (rev 10229)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*
* CDDL HEADER START
*
@@ -20,9 +21,12 @@
*/
/*
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2013 by Delphix. All rights reserved.
+ * Copyright (c) 2012, 2016 by Delphix. All rights reserved.
* Copyright (c) 2012, Joyent, Inc. All rights reserved.
*/
+/*
+ * Copyright 2011 Nexenta Systems, Inc. All rights reserved.
+ */
#ifndef _SYS_ZFS_CONTEXT_H
#define _SYS_ZFS_CONTEXT_H
@@ -62,6 +66,7 @@
#include <inttypes.h>
#include <fsshare.h>
#include <pthread.h>
+#include <sched.h>
#include <sys/debug.h>
#include <sys/note.h>
#include <sys/types.h>
@@ -131,8 +136,18 @@
/*
* DTrace SDT probes have different signatures in userland than they do in
- * kernel. If they're being used in kernel code, re-define them out of
+ * the kernel. If they're being used in kernel code, re-define them out of
* existence for their counterparts in libzpool.
+ *
+ * Here's an example of how to use the set-error probes in userland:
+ * zfs$target:::set-error /arg0 == EBUSY/ {stack();}
+ *
+ * Here's an example of how to use DTRACE_PROBE probes in userland:
+ * If there is a probe declared as follows:
+ * DTRACE_PROBE2(zfs__probe_name, uint64_t, blkid, dnode_t *, dn);
+ * Then you can use it as follows:
+ * zfs$target:::probe2 /copyinstr(arg0) == "zfs__probe_name"/
+ * {printf("%u %p\n", arg1, arg2);}
*/
#ifdef DTRACE_PROBE
@@ -201,6 +216,8 @@
*/
#define curthread ((void *)(uintptr_t)thr_self())
+#define kpreempt(x) sched_yield()
+
typedef struct kthread kthread_t;
#define thread_create(stk, stksize, func, arg, len, pp, state, pri) \
@@ -308,11 +325,14 @@
typedef cond_t kcondvar_t;
#define CV_DEFAULT USYNC_THREAD
+#define CALLOUT_FLAG_ABSOLUTE 0x2
extern void cv_init(kcondvar_t *cv, char *name, int type, void *arg);
extern void cv_destroy(kcondvar_t *cv);
extern void cv_wait(kcondvar_t *cv, kmutex_t *mp);
extern clock_t cv_timedwait(kcondvar_t *cv, kmutex_t *mp, clock_t abstime);
+extern clock_t cv_timedwait_hires(kcondvar_t *cvp, kmutex_t *mp, hrtime_t tim,
+ hrtime_t res, int flag);
extern void cv_signal(kcondvar_t *cv);
extern void cv_broadcast(kcondvar_t *cv);
@@ -330,9 +350,9 @@
#define KM_SLEEP UMEM_NOFAIL
#define KM_PUSHPAGE KM_SLEEP
#define KM_NOSLEEP UMEM_DEFAULT
-#define KM_NODEBUG 0
#define KMC_NODEBUG UMC_NODEBUG
#define KMC_NOTOUCH 0 /* not needed for userland caches */
+#define KM_NODEBUG 0
#define kmem_alloc(_s, _f) umem_alloc(_s, _f)
#define kmem_zalloc(_s, _f) umem_zalloc(_s, _f)
#define kmem_free(_b, _s) umem_free(_b, _s)
@@ -365,6 +385,16 @@
typedef uintptr_t taskqid_t;
typedef void (task_func_t)(void *);
+typedef struct taskq_ent {
+ struct taskq_ent *tqent_next;
+ struct taskq_ent *tqent_prev;
+ task_func_t *tqent_func;
+ void *tqent_arg;
+ uintptr_t tqent_flags;
+} taskq_ent_t;
+
+#define TQENT_FLAG_PREALLOC 0x1 /* taskq_dispatch_ent used */
+
#define TASKQ_PREPOPULATE 0x0001
#define TASKQ_CPR_SAFE 0x0002 /* Use CPR safe protocol */
#define TASKQ_DYNAMIC 0x0004 /* Use dynamic thread scheduling */
@@ -376,6 +406,7 @@
#define TQ_NOQUEUE 0x02 /* Do not enqueue if can't dispatch */
#define TQ_FRONT 0x08 /* Queue in front */
+
extern taskq_t *system_taskq;
extern taskq_t *taskq_create(const char *, int, pri_t, int, int, uint_t);
@@ -384,6 +415,8 @@
#define taskq_create_sysdc(a, b, d, e, p, dc, f) \
(taskq_create(a, b, maxclsyspri, d, e, f))
extern taskqid_t taskq_dispatch(taskq_t *, task_func_t, void *, uint_t);
+extern void taskq_dispatch_ent(taskq_t *, task_func_t, void *, uint_t,
+ taskq_ent_t *);
extern void taskq_destroy(taskq_t *);
extern void taskq_wait(taskq_t *);
extern int taskq_member(taskq_t *, void *);
@@ -403,8 +436,10 @@
uint64_t v_size;
int v_fd;
char *v_path;
+ int v_dump_fd;
} vnode_t;
+extern char *vn_dumpdir;
#define AV_SCANSTAMP_SZ 32 /* length of anti-virus scanstamp */
typedef struct xoptattr {
@@ -484,14 +519,6 @@
#define vn_lock(vp, type)
#define VOP_UNLOCK(vp, type)
-#ifdef VFS_LOCK_GIANT
-#undef VFS_LOCK_GIANT
-#endif
-#define VFS_LOCK_GIANT(mp) 0
-#ifdef VFS_UNLOCK_GIANT
-#undef VFS_UNLOCK_GIANT
-#endif
-#define VFS_UNLOCK_GIANT(vfslocked)
extern int vn_open(char *path, int x1, int oflags, int mode, vnode_t **vpp,
int x2, int x3);
@@ -545,7 +572,7 @@
extern uint64_t physmem;
-extern int highbit(ulong_t i);
+extern int highbit64(uint64_t i);
extern int random_get_bytes(uint8_t *ptr, size_t len);
extern int random_get_pseudo_bytes(uint8_t *ptr, size_t len);
@@ -553,8 +580,9 @@
extern void kernel_fini(void);
struct spa;
-extern void nicenum(uint64_t num, char *buf);
+extern void nicenum(uint64_t num, char *buf, size_t);
extern void show_pool_stats(struct spa *);
+extern int set_global_var(char *arg);
typedef struct callb_cpr {
kmutex_t *cc_lockp;
@@ -630,13 +658,6 @@
extern int zfs_secpolicy_destroy_perms(const char *name, cred_t *cr);
extern zoneid_t getzoneid(void);
/* Random compatibility stuff. */
-#define lbolt (gethrtime() >> 23)
-#define lbolt64 (gethrtime() >> 23)
-
-extern uint64_t physmem;
-
-#define gethrestime_sec() time(NULL)
-
#define pwrite64(d, p, n, o) pwrite(d, p, n, o)
#define readdir64(d) readdir(d)
#define SIGPENDING(td) (0)
@@ -667,11 +688,55 @@
#define SX_SYSINIT(name, lock, desc)
+#define SYSCTL_HANDLER_ARGS struct sysctl_oid *oidp, void *arg1, \
+ intptr_t arg2, struct sysctl_req *req
+
+/*
+ * This describes the access space for a sysctl request. This is needed
+ * so that we can use the interface from the kernel or from user-space.
+ */
+struct sysctl_req {
+ struct thread *td; /* used for access checking */
+ int lock; /* wiring state */
+ void *oldptr;
+ size_t oldlen;
+ size_t oldidx;
+ int (*oldfunc)(struct sysctl_req *, const void *, size_t);
+ void *newptr;
+ size_t newlen;
+ size_t newidx;
+ int (*newfunc)(struct sysctl_req *, void *, size_t);
+ size_t validlen;
+ int flags;
+};
+
+SLIST_HEAD(sysctl_oid_list, sysctl_oid);
+
+/*
+ * This describes one "oid" in the MIB tree. Potentially more nodes can
+ * be hidden behind it, expanded by the handler.
+ */
+struct sysctl_oid {
+ struct sysctl_oid_list *oid_parent;
+ SLIST_ENTRY(sysctl_oid) oid_link;
+ int oid_number;
+ u_int oid_kind;
+ void *oid_arg1;
+ intptr_t oid_arg2;
+ const char *oid_name;
+ int (*oid_handler)(SYSCTL_HANDLER_ARGS);
+ const char *oid_fmt;
+ int oid_refcnt;
+ u_int oid_running;
+ const char *oid_descr;
+};
+
#define SYSCTL_DECL(...)
#define SYSCTL_NODE(...)
#define SYSCTL_INT(...)
#define SYSCTL_UINT(...)
#define SYSCTL_ULONG(...)
+#define SYSCTL_PROC(...)
#define SYSCTL_QUAD(...)
#define SYSCTL_UQUAD(...)
#ifdef TUNABLE_INT
@@ -683,6 +748,8 @@
#define TUNABLE_ULONG(...)
#define TUNABLE_QUAD(...)
+int sysctl_handle_64(SYSCTL_HANDLER_ARGS);
+
/* Errors */
#ifndef ERESTART
@@ -719,6 +786,38 @@
extern int cyclic_reprogram(cyclic_id_t, hrtime_t);
#endif /* illumos */
+#ifdef illumos
+/*
+ * Buf structure
+ */
+#define B_BUSY 0x0001
+#define B_DONE 0x0002
+#define B_ERROR 0x0004
+#define B_READ 0x0040 /* read when I/O occurs */
+#define B_WRITE 0x0100 /* non-read pseudo-flag */
+
+typedef struct buf {
+ int b_flags;
+ size_t b_bcount;
+ union {
+ caddr_t b_addr;
+ } b_un;
+
+ lldaddr_t _b_blkno;
+#define b_lblkno _b_blkno._f
+ size_t b_resid;
+ size_t b_bufsize;
+ int (*b_iodone)(struct buf *);
+ int b_error;
+ void *b_private;
+} buf_t;
+
+extern void bioinit(buf_t *);
+extern void biodone(buf_t *);
+extern void bioerror(buf_t *, int);
+extern int geterror(buf_t *);
+#endif
+
#ifdef __cplusplus
}
#endif
Modified: trunk/cddl/contrib/opensolaris/lib/libzpool/common/taskq.c
===================================================================
--- trunk/cddl/contrib/opensolaris/lib/libzpool/common/taskq.c 2018-06-02 16:07:17 UTC (rev 10228)
+++ trunk/cddl/contrib/opensolaris/lib/libzpool/common/taskq.c 2018-06-02 16:07:30 UTC (rev 10229)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*
* CDDL HEADER START
*
@@ -22,6 +23,11 @@
* Copyright 2010 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
+/*
+ * Copyright 2011 Nexenta Systems, Inc. All rights reserved.
+ * Copyright 2012 Garrett D'Amore <garrett at damore.org>. All rights reserved.
+ * Copyright (c) 2014 by Delphix. All rights reserved.
+ */
#include <sys/zfs_context.h>
@@ -28,16 +34,11 @@
int taskq_now;
taskq_t *system_taskq;
-typedef struct task {
- struct task *task_next;
- struct task *task_prev;
- task_func_t *task_func;
- void *task_arg;
-} task_t;
-
#define TASKQ_ACTIVE 0x00010000
+#define TASKQ_NAMELEN 31
struct taskq {
+ char tq_name[TASKQ_NAMELEN + 1];
kmutex_t tq_lock;
krwlock_t tq_threadlock;
kcondvar_t tq_dispatch_cv;
@@ -51,18 +52,18 @@
int tq_maxalloc;
kcondvar_t tq_maxalloc_cv;
int tq_maxalloc_wait;
- task_t *tq_freelist;
- task_t tq_task;
+ taskq_ent_t *tq_freelist;
+ taskq_ent_t tq_task;
};
-static task_t *
+static taskq_ent_t *
task_alloc(taskq_t *tq, int tqflags)
{
- task_t *t;
+ taskq_ent_t *t;
int rv;
again: if ((t = tq->tq_freelist) != NULL && tq->tq_nalloc >= tq->tq_minalloc) {
- tq->tq_freelist = t->task_next;
+ tq->tq_freelist = t->tqent_next;
} else {
if (tq->tq_nalloc >= tq->tq_maxalloc) {
if (!(tqflags & KM_SLEEP))
@@ -87,7 +88,7 @@
}
mutex_exit(&tq->tq_lock);
- t = kmem_alloc(sizeof (task_t), tqflags & KM_SLEEP);
+ t = kmem_alloc(sizeof (taskq_ent_t), tqflags & KM_SLEEP);
mutex_enter(&tq->tq_lock);
if (t != NULL)
@@ -97,15 +98,15 @@
}
static void
-task_free(taskq_t *tq, task_t *t)
+task_free(taskq_t *tq, taskq_ent_t *t)
{
if (tq->tq_nalloc <= tq->tq_minalloc) {
- t->task_next = tq->tq_freelist;
+ t->tqent_next = tq->tq_freelist;
tq->tq_freelist = t;
} else {
tq->tq_nalloc--;
mutex_exit(&tq->tq_lock);
- kmem_free(t, sizeof (task_t));
+ kmem_free(t, sizeof (taskq_ent_t));
mutex_enter(&tq->tq_lock);
}
@@ -116,7 +117,7 @@
taskqid_t
taskq_dispatch(taskq_t *tq, task_func_t func, void *arg, uint_t tqflags)
{
- task_t *t;
+ taskq_ent_t *t;
if (taskq_now) {
func(arg);
@@ -130,16 +131,17 @@
return (0);
}
if (tqflags & TQ_FRONT) {
- t->task_next = tq->tq_task.task_next;
- t->task_prev = &tq->tq_task;
+ t->tqent_next = tq->tq_task.tqent_next;
+ t->tqent_prev = &tq->tq_task;
} else {
- t->task_next = &tq->tq_task;
- t->task_prev = tq->tq_task.task_prev;
+ t->tqent_next = &tq->tq_task;
+ t->tqent_prev = tq->tq_task.tqent_prev;
}
- t->task_next->task_prev = t;
- t->task_prev->task_next = t;
- t->task_func = func;
- t->task_arg = arg;
+ t->tqent_next->tqent_prev = t;
+ t->tqent_prev->tqent_next = t;
+ t->tqent_func = func;
+ t->tqent_arg = arg;
+ t->tqent_flags = 0;
cv_signal(&tq->tq_dispatch_cv);
mutex_exit(&tq->tq_lock);
return (1);
@@ -146,10 +148,42 @@
}
void
+taskq_dispatch_ent(taskq_t *tq, task_func_t func, void *arg, uint_t flags,
+ taskq_ent_t *t)
+{
+ ASSERT(func != NULL);
+ ASSERT(!(tq->tq_flags & TASKQ_DYNAMIC));
+
+ /*
+ * Mark it as a prealloc'd task. This is important
+ * to ensure that we don't free it later.
+ */
+ t->tqent_flags |= TQENT_FLAG_PREALLOC;
+ /*
+ * Enqueue the task to the underlying queue.
+ */
+ mutex_enter(&tq->tq_lock);
+
+ if (flags & TQ_FRONT) {
+ t->tqent_next = tq->tq_task.tqent_next;
+ t->tqent_prev = &tq->tq_task;
+ } else {
+ t->tqent_next = &tq->tq_task;
+ t->tqent_prev = tq->tq_task.tqent_prev;
+ }
+ t->tqent_next->tqent_prev = t;
+ t->tqent_prev->tqent_next = t;
+ t->tqent_func = func;
+ t->tqent_arg = arg;
+ cv_signal(&tq->tq_dispatch_cv);
+ mutex_exit(&tq->tq_lock);
+}
+
+void
taskq_wait(taskq_t *tq)
{
mutex_enter(&tq->tq_lock);
- while (tq->tq_task.task_next != &tq->tq_task || tq->tq_active != 0)
+ while (tq->tq_task.tqent_next != &tq->tq_task || tq->tq_active != 0)
cv_wait(&tq->tq_wait_cv, &tq->tq_lock);
mutex_exit(&tq->tq_lock);
}
@@ -158,11 +192,12 @@
taskq_thread(void *arg)
{
taskq_t *tq = arg;
- task_t *t;
+ taskq_ent_t *t;
+ boolean_t prealloc;
mutex_enter(&tq->tq_lock);
while (tq->tq_flags & TASKQ_ACTIVE) {
- if ((t = tq->tq_task.task_next) == &tq->tq_task) {
+ if ((t = tq->tq_task.tqent_next) == &tq->tq_task) {
if (--tq->tq_active == 0)
cv_broadcast(&tq->tq_wait_cv);
cv_wait(&tq->tq_dispatch_cv, &tq->tq_lock);
@@ -169,16 +204,20 @@
tq->tq_active++;
continue;
}
- t->task_prev->task_next = t->task_next;
- t->task_next->task_prev = t->task_prev;
+ t->tqent_prev->tqent_next = t->tqent_next;
+ t->tqent_next->tqent_prev = t->tqent_prev;
+ t->tqent_next = NULL;
+ t->tqent_prev = NULL;
+ prealloc = t->tqent_flags & TQENT_FLAG_PREALLOC;
mutex_exit(&tq->tq_lock);
rw_enter(&tq->tq_threadlock, RW_READER);
- t->task_func(t->task_arg);
+ t->tqent_func(t->tqent_arg);
rw_exit(&tq->tq_threadlock);
mutex_enter(&tq->tq_lock);
- task_free(tq, t);
+ if (!prealloc)
+ task_free(tq, t);
}
tq->tq_nthreads--;
cv_broadcast(&tq->tq_wait_cv);
@@ -212,13 +251,14 @@
cv_init(&tq->tq_dispatch_cv, NULL, CV_DEFAULT, NULL);
cv_init(&tq->tq_wait_cv, NULL, CV_DEFAULT, NULL);
cv_init(&tq->tq_maxalloc_cv, NULL, CV_DEFAULT, NULL);
+ (void) strncpy(tq->tq_name, name, TASKQ_NAMELEN + 1);
tq->tq_flags = flags | TASKQ_ACTIVE;
tq->tq_active = nthreads;
tq->tq_nthreads = nthreads;
tq->tq_minalloc = minalloc;
tq->tq_maxalloc = maxalloc;
- tq->tq_task.task_next = &tq->tq_task;
- tq->tq_task.task_prev = &tq->tq_task;
+ tq->tq_task.tqent_next = &tq->tq_task;
+ tq->tq_task.tqent_prev = &tq->tq_task;
tq->tq_threadlist = kmem_alloc(nthreads * sizeof (thread_t), KM_SLEEP);
if (flags & TASKQ_PREPOPULATE) {
Modified: trunk/cddl/contrib/opensolaris/lib/libzpool/common/util.c
===================================================================
--- trunk/cddl/contrib/opensolaris/lib/libzpool/common/util.c 2018-06-02 16:07:17 UTC (rev 10228)
+++ trunk/cddl/contrib/opensolaris/lib/libzpool/common/util.c 2018-06-02 16:07:30 UTC (rev 10229)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*
* CDDL HEADER START
*
@@ -20,6 +21,7 @@
*/
/*
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016 by Delphix. All rights reserved.
*/
#include <assert.h>
@@ -31,38 +33,12 @@
#include <sys/spa.h>
#include <sys/fs/zfs.h>
#include <sys/refcount.h>
+#include <dlfcn.h>
/*
* Routines needed by more than one client of libzpool.
*/
-void
-nicenum(uint64_t num, char *buf)
-{
- uint64_t n = num;
- int index = 0;
- char u;
-
- while (n >= 1024) {
- n = (n + (1024 / 2)) / 1024; /* Round up or down */
- index++;
- }
-
- u = " KMGTPE"[index];
-
- if (index == 0) {
- (void) sprintf(buf, "%llu", (u_longlong_t)n);
- } else if (n < 10 && (num & (num - 1)) != 0) {
- (void) sprintf(buf, "%.2f%c",
- (double)num / (1ULL << 10 * index), u);
- } else if (n < 100 && (num & (num - 1)) != 0) {
- (void) sprintf(buf, "%.1f%c",
- (double)num / (1ULL << 10 * index), u);
- } else {
- (void) sprintf(buf, "%llu%c", (u_longlong_t)n, u);
- }
-}
-
static void
show_vdev_stats(const char *desc, const char *ctype, nvlist_t *nv, int indent)
{
@@ -95,20 +71,22 @@
sec = MAX(1, vs->vs_timestamp / NANOSEC);
- nicenum(vs->vs_alloc, used);
- nicenum(vs->vs_space - vs->vs_alloc, avail);
- nicenum(vs->vs_ops[ZIO_TYPE_READ] / sec, rops);
- nicenum(vs->vs_ops[ZIO_TYPE_WRITE] / sec, wops);
- nicenum(vs->vs_bytes[ZIO_TYPE_READ] / sec, rbytes);
- nicenum(vs->vs_bytes[ZIO_TYPE_WRITE] / sec, wbytes);
- nicenum(vs->vs_read_errors, rerr);
- nicenum(vs->vs_write_errors, werr);
- nicenum(vs->vs_checksum_errors, cerr);
+ nicenum(vs->vs_alloc, used, sizeof (used));
+ nicenum(vs->vs_space - vs->vs_alloc, avail, sizeof (avail));
+ nicenum(vs->vs_ops[ZIO_TYPE_READ] / sec, rops, sizeof (rops));
+ nicenum(vs->vs_ops[ZIO_TYPE_WRITE] / sec, wops, sizeof (wops));
+ nicenum(vs->vs_bytes[ZIO_TYPE_READ] / sec, rbytes,
+ sizeof (rbytes));
+ nicenum(vs->vs_bytes[ZIO_TYPE_WRITE] / sec, wbytes,
+ sizeof (wbytes));
+ nicenum(vs->vs_read_errors, rerr, sizeof (rerr));
+ nicenum(vs->vs_write_errors, werr, sizeof (werr));
+ nicenum(vs->vs_checksum_errors, cerr, sizeof (cerr));
(void) printf("%*s%s%*s%*s%*s %5s %5s %5s %5s %5s %5s %5s\n",
indent, "",
prefix,
- indent + strlen(prefix) - 25 - (vs->vs_space ? 0 : 12),
+ (int)(indent + strlen(prefix) - 25 - (vs->vs_space ? 0 : 12)),
desc,
vs->vs_space ? 6 : 0, vs->vs_space ? used : "",
vs->vs_space ? 6 : 0, vs->vs_space ? avail : "",
@@ -153,3 +131,58 @@
nvlist_free(config);
}
+
+/*
+ * Sets given global variable in libzpool to given unsigned 32-bit value.
+ * arg: "<variable>=<value>"
+ */
+int
+set_global_var(char *arg)
+{
+ void *zpoolhdl;
+ char *varname = arg, *varval;
+ u_longlong_t val;
+
+#ifndef _LITTLE_ENDIAN
+ /*
+ * On big endian systems changing a 64-bit variable would set the high
+ * 32 bits instead of the low 32 bits, which could cause unexpected
+ * results.
+ */
+ fprintf(stderr, "Setting global variables is only supported on "
+ "little-endian systems\n", varname);
+ return (ENOTSUP);
+#endif
+ if ((varval = strchr(arg, '=')) != NULL) {
+ *varval = '\0';
+ varval++;
+ val = strtoull(varval, NULL, 0);
+ if (val > UINT32_MAX) {
+ fprintf(stderr, "Value for global variable '%s' must "
+ "be a 32-bit unsigned integer\n", varname);
+ return (EOVERFLOW);
+ }
+ } else {
+ return (EINVAL);
+ }
+
+ zpoolhdl = dlopen("libzpool.so", RTLD_LAZY);
+ if (zpoolhdl != NULL) {
+ uint32_t *var;
+ var = dlsym(zpoolhdl, varname);
+ if (var == NULL) {
+ fprintf(stderr, "Global variable '%s' does not exist "
+ "in libzpool.so\n", varname);
+ return (EINVAL);
+ }
+ *var = (uint32_t)val;
+
+ dlclose(zpoolhdl);
+ } else {
+ fprintf(stderr, "Failed to open libzpool.so to set global "
+ "variable\n");
+ return (EIO);
+ }
+
+ return (0);
+}
Modified: trunk/cddl/contrib/opensolaris/lib/pyzfs/common/allow.py
===================================================================
--- trunk/cddl/contrib/opensolaris/lib/pyzfs/common/allow.py 2018-06-02 16:07:17 UTC (rev 10228)
+++ trunk/cddl/contrib/opensolaris/lib/pyzfs/common/allow.py 2018-06-02 16:07:30 UTC (rev 10229)
@@ -20,6 +20,7 @@
# CDDL HEADER END
#
# Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2013 by Delphix. All rights reserved.
#
"""This module implements the "zfs allow" and "zfs unallow" subcommands.
@@ -219,6 +220,7 @@
hold=_("Allows adding a user hold to a snapshot"),
release=_("Allows releasing a user hold which\n\t\t\t\tmight destroy the snapshot"),
diff=_("Allows lookup of paths within a dataset,\n\t\t\t\tgiven an object number. Ordinary users need this\n\t\t\t\tin order to use zfs diff"),
+ bookmark="",
)
perms_other = dict(
Property changes on: trunk/cddl/contrib/opensolaris/lib/pyzfs/common/allow.py
___________________________________________________________________
Added: mnbsd:nokeywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Modified: trunk/cddl/contrib/opensolaris/lib/pyzfs/common/ioctl.c
===================================================================
--- trunk/cddl/contrib/opensolaris/lib/pyzfs/common/ioctl.c 2018-06-02 16:07:17 UTC (rev 10228)
+++ trunk/cddl/contrib/opensolaris/lib/pyzfs/common/ioctl.c 2018-06-02 16:07:30 UTC (rev 10229)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*
* CDDL HEADER START
*
More information about the Midnightbsd-cvs
mailing list