summaryrefslogtreecommitdiff
path: root/usr/src/common
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src/common')
-rw-r--r--usr/src/common/brand/lx/lx_signum.c244
-rw-r--r--usr/src/common/brand/lx/lx_signum.h81
-rw-r--r--usr/src/common/brand/lx/lx_syscall.h47
-rw-r--r--usr/src/common/ctf/ctf_create.c2
-rw-r--r--usr/src/common/ctf/ctf_hash.c160
-rw-r--r--usr/src/common/ctf/ctf_impl.h6
-rw-r--r--usr/src/common/ctf/ctf_types.c64
-rw-r--r--usr/src/common/fs/bootfsops.c329
-rw-r--r--usr/src/common/util/string.c7
-rw-r--r--usr/src/common/util/string.h1
-rw-r--r--usr/src/common/util/strtolctype.h4
-rw-r--r--usr/src/common/zfs/zfs_prop.c17
-rw-r--r--usr/src/common/zfs/zfs_prop.h2
13 files changed, 957 insertions, 7 deletions
diff --git a/usr/src/common/brand/lx/lx_signum.c b/usr/src/common/brand/lx/lx_signum.c
new file mode 100644
index 0000000000..08ab453885
--- /dev/null
+++ b/usr/src/common/brand/lx/lx_signum.c
@@ -0,0 +1,244 @@
+/*
+ * 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 2010 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ * Copyright (c) 2014, Joyent, Inc. All rights reserved.
+ */
+
+#include <sys/signal.h>
+#include <lx_signum.h>
+
+/*
+ * Delivering signals to a Linux process is complicated by differences in
+ * signal numbering, stack structure and contents, and the action taken when a
+ * signal handler exits. In addition, many signal-related structures, such as
+ * sigset_ts, vary between Solaris and Linux.
+ *
+ * The simplest transformation that must be done when sending signals is to
+ * translate between Linux and Solaris signal numbers.
+ *
+ * These are the major signal number differences between Linux and Solaris:
+ *
+ * ====================================
+ * | Number | Linux | Solaris |
+ * | ====== | ========= | ========== |
+ * | 7 | SIGBUS | SIGEMT |
+ * | 10 | SIGUSR1 | SIGBUS |
+ * | 12 | SIGUSR2 | SIGSYS |
+ * | 16 | SIGSTKFLT | SIGUSR1 |
+ * | 17 | SIGCHLD | SIGUSR2 |
+ * | 18 | SIGCONT | SIGCHLD |
+ * | 19 | SIGSTOP | SIGPWR |
+ * | 20 | SIGTSTP | SIGWINCH |
+ * | 21 | SIGTTIN | SIGURG |
+ * | 22 | SIGTTOU | SIGPOLL |
+ * | 23 | SIGURG | SIGSTOP |
+ * | 24 | SIGXCPU | SIGTSTP |
+ * | 25 | SIGXFSZ | SIGCONT |
+ * | 26 | SIGVTALARM | SIGTTIN |
+ * | 27 | SIGPROF | SIGTTOU |
+ * | 28 | SIGWINCH | SIGVTALARM |
+ * | 29 | SIGPOLL | SIGPROF |
+ * | 30 | SIGPWR | SIGXCPU |
+ * | 31 | SIGSYS | SIGXFSZ |
+ * ====================================
+ *
+ * Not every Linux signal maps to a Solaris signal, nor does every Solaris
+ * signal map to a Linux counterpart. However, when signals do map, the
+ * mapping is unique.
+ *
+ * One mapping issue is that Linux supports 33 real time signals, with SIGRTMIN
+ * typically starting at or near 32 (SIGRTMIN) and proceeding to 64 (SIGRTMAX)
+ * (SIGRTMIN is "at or near" 32 because glibc usually "steals" one ore more of
+ * these signals for its own internal use, adjusting SIGRTMIN and SIGRTMAX as
+ * needed.) Conversely, Solaris actively uses signals 32-40 for other purposes
+ * and supports exactly 32 real time signals, in the range 41 (SIGRTMIN)
+ * to 72 (SIGRTMAX).
+ *
+ * At present, attempting to translate a Linux signal equal to 63
+ * will generate an error (we allow SIGRTMAX because a program
+ * should be able to send SIGRTMAX without getting an EINVAL, though obviously
+ * anything that loops through the signals from SIGRTMIN to SIGRTMAX will
+ * fail.)
+ *
+ * Similarly, attempting to translate a native Solaris signal in the range
+ * 32-40 will also generate an error as we don't want to support the receipt of
+ * those signals from the Solaris global zone.
+ */
+
+/*
+ * Linux to Solaris signal map
+ *
+ * Usage: solaris_signal = ltos_signum[lx_signal];
+ */
+const int
+ltos_signo[LX_NSIG + 1] = {
+ 0,
+ SIGHUP,
+ SIGINT,
+ SIGQUIT,
+ SIGILL,
+ SIGTRAP,
+ SIGABRT,
+ SIGBUS,
+ SIGFPE,
+ SIGKILL,
+ SIGUSR1,
+ SIGSEGV,
+ SIGUSR2,
+ SIGPIPE,
+ SIGALRM,
+ SIGTERM,
+ SIGEMT, /* 16: Linux SIGSTKFLT; use Solaris SIGEMT */
+ SIGCHLD,
+ SIGCONT,
+ SIGSTOP,
+ SIGTSTP,
+ SIGTTIN,
+ SIGTTOU,
+ SIGURG,
+ SIGXCPU,
+ SIGXFSZ,
+ SIGVTALRM,
+ SIGPROF,
+ SIGWINCH,
+ SIGPOLL,
+ SIGPWR,
+ SIGSYS,
+ _SIGRTMIN, /* 32: Linux SIGRTMIN */
+ _SIGRTMIN + 1,
+ _SIGRTMIN + 2,
+ _SIGRTMIN + 3,
+ _SIGRTMIN + 4,
+ _SIGRTMIN + 5,
+ _SIGRTMIN + 6,
+ _SIGRTMIN + 7,
+ _SIGRTMIN + 8,
+ _SIGRTMIN + 9,
+ _SIGRTMIN + 10,
+ _SIGRTMIN + 11,
+ _SIGRTMIN + 12,
+ _SIGRTMIN + 13,
+ _SIGRTMIN + 14,
+ _SIGRTMIN + 15,
+ _SIGRTMIN + 16,
+ _SIGRTMIN + 17,
+ _SIGRTMIN + 18,
+ _SIGRTMIN + 19,
+ _SIGRTMIN + 20,
+ _SIGRTMIN + 21,
+ _SIGRTMIN + 22,
+ _SIGRTMIN + 23,
+ _SIGRTMIN + 24,
+ _SIGRTMIN + 25,
+ _SIGRTMIN + 26,
+ _SIGRTMIN + 27,
+ _SIGRTMIN + 28,
+ _SIGRTMIN + 29,
+ _SIGRTMIN + 30,
+ -1, /* 63: Linux SIGRTMIN + 31, or SIGRTMAX - 1 */
+ _SIGRTMAX, /* 64: Linux SIGRTMAX */
+};
+
+/*
+ * Solaris to Linux signal map
+ *
+ * Usage: lx_signal = stol_signo[solaris_signal];
+ */
+const int
+stol_signo[NSIG] = {
+ 0,
+ LX_SIGHUP,
+ LX_SIGINT,
+ LX_SIGQUIT,
+ LX_SIGILL,
+ LX_SIGTRAP,
+ LX_SIGABRT,
+ LX_SIGSTKFLT, /* 7: Solaris SIGEMT; use for LX_SIGSTKFLT */
+ LX_SIGFPE,
+ LX_SIGKILL,
+ LX_SIGBUS,
+ LX_SIGSEGV,
+ LX_SIGSYS,
+ LX_SIGPIPE,
+ LX_SIGALRM,
+ LX_SIGTERM,
+ LX_SIGUSR1,
+ LX_SIGUSR2,
+ LX_SIGCHLD,
+ LX_SIGPWR,
+ LX_SIGWINCH,
+ LX_SIGURG,
+ LX_SIGPOLL,
+ LX_SIGSTOP,
+ LX_SIGTSTP,
+ LX_SIGCONT,
+ LX_SIGTTIN,
+ LX_SIGTTOU,
+ LX_SIGVTALRM,
+ LX_SIGPROF,
+ LX_SIGXCPU,
+ LX_SIGXFSZ,
+ -1, /* 32: Solaris SIGWAITING */
+ -1, /* 33: Solaris SIGLWP */
+ -1, /* 34: Solaris SIGFREEZE */
+ -1, /* 35: Solaris SIGTHAW */
+ -1, /* 36: Solaris SIGCANCEL */
+ -1, /* 37: Solaris SIGLOST */
+ -1, /* 38: Solaris SIGXRES */
+ -1, /* 39: Solaris SIGJVM1 */
+ -1, /* 40: Solaris SIGJVM2 */
+ -1, /* 41: Solaris SIGINFO */
+ LX_SIGRTMIN, /* 42: Solaris _SIGRTMIN */
+ LX_SIGRTMIN + 1,
+ LX_SIGRTMIN + 2,
+ LX_SIGRTMIN + 3,
+ LX_SIGRTMIN + 4,
+ LX_SIGRTMIN + 5,
+ LX_SIGRTMIN + 6,
+ LX_SIGRTMIN + 7,
+ LX_SIGRTMIN + 8,
+ LX_SIGRTMIN + 9,
+ LX_SIGRTMIN + 10,
+ LX_SIGRTMIN + 11,
+ LX_SIGRTMIN + 12,
+ LX_SIGRTMIN + 13,
+ LX_SIGRTMIN + 14,
+ LX_SIGRTMIN + 15,
+ LX_SIGRTMIN + 16,
+ LX_SIGRTMIN + 17,
+ LX_SIGRTMIN + 18,
+ LX_SIGRTMIN + 19,
+ LX_SIGRTMIN + 20,
+ LX_SIGRTMIN + 21,
+ LX_SIGRTMIN + 22,
+ LX_SIGRTMIN + 23,
+ LX_SIGRTMIN + 24,
+ LX_SIGRTMIN + 25,
+ LX_SIGRTMIN + 26,
+ LX_SIGRTMIN + 27,
+ LX_SIGRTMIN + 28,
+ LX_SIGRTMIN + 29,
+ LX_SIGRTMIN + 30,
+ LX_SIGRTMAX, /* 73: Solaris _SIGRTMAX */
+};
diff --git a/usr/src/common/brand/lx/lx_signum.h b/usr/src/common/brand/lx/lx_signum.h
new file mode 100644
index 0000000000..f410500925
--- /dev/null
+++ b/usr/src/common/brand/lx/lx_signum.h
@@ -0,0 +1,81 @@
+/*
+ * 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 2006 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ * Copyright 2014 Joyent, Inc. All rights reserved.
+ */
+
+#ifndef _LX_SIGNUM_H
+#define _LX_SIGNUM_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define LX_SIGHUP 1
+#define LX_SIGINT 2
+#define LX_SIGQUIT 3
+#define LX_SIGILL 4
+#define LX_SIGTRAP 5
+#define LX_SIGABRT 6
+#define LX_SIGIOT 6
+#define LX_SIGBUS 7
+#define LX_SIGFPE 8
+#define LX_SIGKILL 9
+#define LX_SIGUSR1 10
+#define LX_SIGSEGV 11
+#define LX_SIGUSR2 12
+#define LX_SIGPIPE 13
+#define LX_SIGALRM 14
+#define LX_SIGTERM 15
+#define LX_SIGSTKFLT 16
+#define LX_SIGCHLD 17
+#define LX_SIGCONT 18
+#define LX_SIGSTOP 19
+#define LX_SIGTSTP 20
+#define LX_SIGTTIN 21
+#define LX_SIGTTOU 22
+#define LX_SIGURG 23
+#define LX_SIGXCPU 24
+#define LX_SIGXFSZ 25
+#define LX_SIGVTALRM 26
+#define LX_SIGPROF 27
+#define LX_SIGWINCH 28
+#define LX_SIGIO 29
+#define LX_SIGPOLL LX_SIGIO
+#define LX_SIGPWR 30
+#define LX_SIGSYS 31
+#define LX_SIGUNUSED 31
+
+#define LX_NSIG 64 /* Linux _NSIG */
+
+#define LX_SIGRTMIN 32
+#define LX_SIGRTMAX LX_NSIG
+
+extern const int ltos_signo[];
+extern const int stol_signo[];
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _LX_SIGNUM_H */
diff --git a/usr/src/common/brand/lx/lx_syscall.h b/usr/src/common/brand/lx/lx_syscall.h
new file mode 100644
index 0000000000..7bfc0537c9
--- /dev/null
+++ b/usr/src/common/brand/lx/lx_syscall.h
@@ -0,0 +1,47 @@
+/*
+ * 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 2014 Joyent, Inc. All rights reserved.
+ */
+
+#ifndef _LX_SYSCALL_H
+#define _LX_SYSCALL_H
+
+#include <sys/lx_brand.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * The br_scall_args field of lx_lwp_data is going to be populated with
+ * pointers to structs. The types of these structs should be defined in this
+ * header file. These are Linux specific arguments to system calls that don't
+ * exist in illumos. Each section should be labelled with which system call it
+ * belongs to.
+ */
+
+/* arguments for waitpid(2) */
+/* see comments in usr/src/lib/brand/lx/lx_brand/common/wait.c */
+#define LX_WNOTHREAD 0x20000000 /* Do not wait on siblings' children */
+#define LX_WALL 0x40000000 /* Wait on all children */
+#define LX_WCLONE 0x80000000 /* Wait only on clone children */
+typedef struct lx_waitid_args {
+ int waitid_flags;
+} lx_waitid_args_t;
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _LX_SYSCALL_H */
diff --git a/usr/src/common/ctf/ctf_create.c b/usr/src/common/ctf/ctf_create.c
index 239d166f44..f9feca81cf 100644
--- a/usr/src/common/ctf/ctf_create.c
+++ b/usr/src/common/ctf/ctf_create.c
@@ -574,7 +574,7 @@ ctf_dtd_lookup(ctf_file_t *fp, ctf_id_t type)
int
ctf_discard(ctf_file_t *fp)
{
- ctf_dtdef_t *dtd, *ntd;
+ ctf_dtdef_t *dtd, *ntd = NULL;
if (!(fp->ctf_flags & LCTF_RDWR))
return (ctf_set_errno(fp, ECTF_RDONLY));
diff --git a/usr/src/common/ctf/ctf_hash.c b/usr/src/common/ctf/ctf_hash.c
index b10a7618f6..e68fe8e516 100644
--- a/usr/src/common/ctf/ctf_hash.c
+++ b/usr/src/common/ctf/ctf_hash.c
@@ -25,9 +25,8 @@
* Use is subject to license terms.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
-
#include <ctf_impl.h>
+#include <sys/debug.h>
static const ushort_t _CTF_EMPTY[1] = { 0 };
@@ -176,3 +175,160 @@ ctf_hash_destroy(ctf_hash_t *hp)
hp->h_chains = NULL;
}
}
+
+int
+ctf_idhash_create(ctf_idhash_t *ihp, ulong_t nelems)
+{
+ if (nelems > USHRT_MAX)
+ return (EOVERFLOW);
+
+ /*
+ * If the hash table is going to be empty, don't bother allocating any
+ * memory and make the only bucket point to a zero so lookups fail.
+ */
+ if (nelems == 0) {
+ bzero(ihp, sizeof (ctf_idhash_t));
+ ihp->ih_buckets = (ushort_t *)_CTF_EMPTY;
+ ihp->ih_nbuckets = 1;
+ return (0);
+ }
+
+ ihp->ih_nbuckets = 211; /* use a prime number of hash buckets */
+ ihp->ih_nelems = nelems + 1; /* we use index zero as a sentinel */
+ ihp->ih_free = 1; /* first free element is index 1 */
+
+ ihp->ih_buckets = ctf_alloc(sizeof (ushort_t) * ihp->ih_nbuckets);
+ ihp->ih_chains = ctf_alloc(sizeof (ctf_ihelem_t) * ihp->ih_nelems);
+
+ if (ihp->ih_buckets == NULL || ihp->ih_chains == NULL) {
+ ctf_idhash_destroy(ihp);
+ return (EAGAIN);
+ }
+
+ bzero(ihp->ih_buckets, sizeof (ushort_t) * ihp->ih_nbuckets);
+ bzero(ihp->ih_chains, sizeof (ctf_ihelem_t) * ihp->ih_nelems);
+
+ return (0);
+}
+
+void
+ctf_idhash_clear(ctf_idhash_t *ihp)
+{
+ /* Nothing to do for a sentinel hash */
+ if (ihp->ih_nbuckets == 1) {
+ ASSERT(ihp->ih_buckets == (ushort_t *)_CTF_EMPTY);
+ return;
+ }
+
+ ihp->ih_free = 1;
+ bzero(ihp->ih_buckets, sizeof (ushort_t) * ihp->ih_nbuckets);
+ bzero(ihp->ih_chains, sizeof (ctf_ihelem_t) * ihp->ih_nelems);
+}
+
+uint_t
+ctf_idhash_size(const ctf_idhash_t *hp)
+{
+ return (hp->ih_nelems ? hp->ih_nelems - 1 : 0);
+}
+
+static ulong_t
+ctf_idhash_compute(ctf_id_t id)
+{
+ return (id);
+}
+
+int
+ctf_idhash_insert(ctf_idhash_t *ihp, ushort_t type, ushort_t value)
+{
+ ctf_ihelem_t *ihep = &ihp->ih_chains[ihp->ih_free];
+ ulong_t h;
+
+ if (ihp->ih_free >= ihp->ih_nelems)
+ return (EOVERFLOW);
+
+ ihep->ih_type = type;
+ ihep->ih_value = value;
+ h = ctf_idhash_compute(type) % ihp->ih_nbuckets;
+ ihep->ih_next = ihp->ih_buckets[h];
+ ihp->ih_buckets[h] = ihp->ih_free++;
+
+ return (0);
+}
+
+int
+ctf_idhash_define(ctf_idhash_t *ihp, ushort_t type, ushort_t value)
+{
+ ctf_ihelem_t *hep = ctf_idhash_lookup(ihp, type);
+
+ if (hep == NULL)
+ return (ctf_idhash_insert(ihp, type, value));
+
+ hep->ih_value = value;
+ return (0);
+}
+
+
+ctf_ihelem_t *
+ctf_idhash_lookup(ctf_idhash_t *ihp, ushort_t key)
+{
+ ctf_ihelem_t *ihep;
+ ushort_t i;
+
+ ulong_t h = ctf_idhash_compute(key) % ihp->ih_nbuckets;
+
+ for (i = ihp->ih_buckets[h]; i != 0; i = ihep->ih_next) {
+ ihep = &ihp->ih_chains[i];
+
+ if (ihep->ih_type == key)
+ return (ihep);
+ }
+
+ return (NULL);
+}
+
+void
+ctf_idhash_destroy(ctf_idhash_t *ihp)
+{
+ if (ihp->ih_buckets != NULL && ihp->ih_nbuckets != 1) {
+ ctf_free(ihp->ih_buckets, sizeof (ushort_t) * ihp->ih_nbuckets);
+ ihp->ih_buckets = NULL;
+ }
+
+ if (ihp->ih_chains != NULL) {
+ ctf_free(ihp->ih_chains, sizeof (ctf_helem_t) * ihp->ih_nelems);
+ ihp->ih_chains = NULL;
+ }
+}
+
+/*ARGSUSED*/
+int
+ctf_idhash_iter_init(ctf_idhash_t *ihp, ctf_idhash_iter_t **iterp)
+{
+
+ *iterp = ctf_alloc(sizeof (ctf_idhash_iter_t));
+ if (*iterp == NULL)
+ return (ENOMEM);
+
+ if (ihp->ih_free == 0)
+ (*iterp)->cii_id = 0;
+ else
+ (*iterp)->cii_id = 1;
+
+ return (0);
+}
+
+const ctf_ihelem_t *
+ctf_idhash_iter(ctf_idhash_t *ihp, ctf_idhash_iter_t *iter)
+{
+ if (iter->cii_id >= ihp->ih_free)
+ return (NULL);
+
+ return (&ihp->ih_chains[iter->cii_id++]);
+}
+
+/*ARGSUSED*/
+void
+ctf_idhash_iter_fini(ctf_idhash_t *ihp, ctf_idhash_iter_t *iter)
+{
+ ctf_free(iter, sizeof (ctf_idhash_iter_t));
+}
diff --git a/usr/src/common/ctf/ctf_impl.h b/usr/src/common/ctf/ctf_impl.h
index f56fa6a005..42aec80a43 100644
--- a/usr/src/common/ctf/ctf_impl.h
+++ b/usr/src/common/ctf/ctf_impl.h
@@ -25,7 +25,7 @@
* Use is subject to license terms.
*/
/*
- * Copyright (c) 2012, Joyent, Inc. All rights reserved.
+ * Copyright (c) 2014, Joyent, Inc. All rights reserved.
*/
#ifndef _CTF_IMPL_H
@@ -77,6 +77,10 @@ typedef struct ctf_hash {
uint_t h_free; /* index of next free hash element */
} ctf_hash_t;
+struct ctf_idhash_iter {
+ int cii_id; /* Current iteration id */
+};
+
typedef struct ctf_strs {
const char *cts_strs; /* base address of string table */
size_t cts_len; /* size of string table in bytes */
diff --git a/usr/src/common/ctf/ctf_types.c b/usr/src/common/ctf/ctf_types.c
index ab1b9ff14b..93168f25cb 100644
--- a/usr/src/common/ctf/ctf_types.c
+++ b/usr/src/common/ctf/ctf_types.c
@@ -26,6 +26,7 @@
*/
#include <ctf_impl.h>
+#include <sys/debug.h>
ssize_t
ctf_get_ctt_size(const ctf_file_t *fp, const ctf_type_t *tp, ssize_t *sizep,
@@ -868,3 +869,66 @@ ctf_type_visit(ctf_file_t *fp, ctf_id_t type, ctf_visit_f *func, void *arg)
{
return (ctf_type_rvisit(fp, type, func, arg, "", 0, 0));
}
+
+int
+ctf_func_info_by_id(ctf_file_t *fp, ctf_id_t type, ctf_funcinfo_t *fip)
+{
+ ctf_file_t *ofp = fp;
+ const ctf_type_t *tp;
+ const ushort_t *dp;
+ int nargs;
+ ssize_t increment;
+
+ if ((tp = ctf_lookup_by_id(&fp, type)) == NULL)
+ return (CTF_ERR); /* errno is set for us */
+
+ if (LCTF_INFO_KIND(fp, tp->ctt_info) != CTF_K_FUNCTION)
+ return (ctf_set_errno(ofp, ECTF_NOTFUNC));
+
+ fip->ctc_return = tp->ctt_type;
+ nargs = LCTF_INFO_VLEN(fp, tp->ctt_info);
+ fip->ctc_argc = nargs;
+ fip->ctc_flags = 0;
+
+ /* dp should now point to the first argument */
+ if (nargs != 0) {
+ (void) ctf_get_ctt_size(fp, tp, NULL, &increment);
+ dp = (ushort_t *)((uintptr_t)fp->ctf_buf +
+ fp->ctf_txlate[CTF_TYPE_TO_INDEX(type)] + increment);
+ if (dp[nargs - 1] == 0) {
+ fip->ctc_flags |= CTF_FUNC_VARARG;
+ fip->ctc_argc--;
+ }
+ }
+
+ return (0);
+}
+
+int
+ctf_func_args_by_id(ctf_file_t *fp, ctf_id_t type, uint_t argc, ctf_id_t *argv)
+{
+ ctf_file_t *ofp = fp;
+ const ctf_type_t *tp;
+ const ushort_t *dp;
+ int nargs;
+ ssize_t increment;
+
+ if ((tp = ctf_lookup_by_id(&fp, type)) == NULL)
+ return (CTF_ERR); /* errno is set for us */
+
+ if (LCTF_INFO_KIND(fp, tp->ctt_info) != CTF_K_FUNCTION)
+ return (ctf_set_errno(ofp, ECTF_NOTFUNC));
+
+ nargs = LCTF_INFO_VLEN(fp, tp->ctt_info);
+ (void) ctf_get_ctt_size(fp, tp, NULL, &increment);
+ dp = (ushort_t *)((uintptr_t)fp->ctf_buf +
+ fp->ctf_txlate[CTF_TYPE_TO_INDEX(type)] +
+ increment);
+ if (nargs != 0 && dp[nargs - 1] == 0)
+ nargs--;
+
+ for (nargs = MIN(argc, nargs); nargs != 0; nargs--)
+ *argv++ = *dp++;
+
+ return (0);
+}
diff --git a/usr/src/common/fs/bootfsops.c b/usr/src/common/fs/bootfsops.c
new file mode 100644
index 0000000000..5a693b80e5
--- /dev/null
+++ b/usr/src/common/fs/bootfsops.c
@@ -0,0 +1,329 @@
+/*
+ * 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 2013 Joyent, Inc. All rights reserved.
+ */
+
+#include <sys/bootconf.h>
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/vnode.h>
+#include <sys/fs/ufs_fsdir.h>
+#include <sys/fs/ufs_fs.h>
+#include <sys/fs/ufs_inode.h>
+#include <sys/sysmacros.h>
+#include <sys/bootvfs.h>
+#include <sys/bootinfo.h>
+#include <sys/filep.h>
+
+#ifdef _BOOT
+#include "../common/util.h"
+#else
+#include <sys/sunddi.h>
+#endif
+
+#define MAX_FILES MAX_BOOT_MODULES
+#define MAX_FDS 256
+
+extern void *bkmem_alloc(size_t);
+extern void bkmem_free(void *, size_t);
+
+/*
+ * TODO: Replace these declarations with inclusion of the ordinary userland
+ * bootfs headers once they're available.
+ */
+typedef struct bfile {
+ char bf_name[MAXPATHLEN];
+ caddr_t bf_addr;
+ size_t bf_size;
+ struct bfile *bf_next;
+ uint64_t bf_ino;
+} bfile_t;
+
+typedef struct bf_fd {
+ bfile_t *fd_file;
+ off_t fd_pos;
+} bf_fd_t;
+
+static bfile_t *head;
+static uint_t init_done;
+static bf_fd_t fds[MAX_FDS];
+
+static char cpath[MAXPATHLEN]; /* For canonicalising filenames */
+
+static void bbootfs_closeall(int);
+
+static void
+canonicalise(const char *fn, char *out)
+{
+ const char *p;
+ char *q, *s;
+ char *last;
+ char *oc;
+ int is_slash = 0;
+ static char scratch[MAXPATHLEN];
+
+ if (fn == NULL) {
+ *out = '\0';
+ return;
+ }
+
+ /*
+ * Remove leading slashes and condense all multiple slashes into one.
+ */
+ p = fn;
+ while (*p == '/')
+ ++p;
+
+ for (q = scratch; *p != '\0'; p++) {
+ if (*p == '/' && !is_slash) {
+ *q++ = '/';
+ is_slash = 1;
+ } else if (*p != '/') {
+ *q++ = *p;
+ is_slash = 0;
+ }
+ }
+ *q = '\0';
+
+ if (strncmp(scratch, "system/boot/", 12) == 0 ||
+ strcmp(scratch, "system/boot") == 0) {
+ s = scratch + 12;
+ } else {
+ s = scratch;
+ }
+
+ for (last = strsep(&s, "/"), q = oc = out; last != NULL;
+ last = strsep(&s, "/")) {
+ if (strcmp(last, ".") == 0)
+ continue;
+ if (strcmp(last, "..") == 0) {
+ for (oc = q; oc > out && *oc != '/'; oc--)
+ ;
+ q = oc;
+ continue;
+ }
+ if (q > out)
+ *q++ = '/';
+ q += snprintf(q, MAXPATHLEN - (q - out), "%s", last);
+ }
+
+ *q = '\0';
+}
+
+/* ARGSUSED */
+static int
+bbootfs_mountroot(char *str)
+{
+ return (-1);
+}
+
+static int
+bbootfs_unmountroot(void)
+{
+ return (-1);
+}
+
+static int
+bbootfs_init(void)
+{
+ bfile_t *fp;
+ char propname[32];
+ uint64_t propval;
+ uint_t i;
+
+ for (i = 0; i < MAX_FILES; i++) {
+ (void) snprintf(propname, sizeof (propname),
+ "module-name-%u", i);
+ if (do_bsys_getproplen(NULL, propname) < 0)
+ break;
+
+ if ((fp = bkmem_alloc(sizeof (bfile_t))) == NULL) {
+ bbootfs_closeall(1);
+ return (-1);
+ }
+
+ (void) do_bsys_getprop(NULL, propname, cpath);
+ canonicalise(cpath, fp->bf_name);
+
+ (void) snprintf(propname, sizeof (propname),
+ "module-addr-%u", i);
+ if (do_bsys_getproplen(NULL, propname) != sizeof (uint64_t)) {
+ bkmem_free(fp, sizeof (bfile_t));
+ continue;
+ }
+ (void) do_bsys_getprop(NULL, propname, &propval);
+ fp->bf_addr = (void *)(uintptr_t)propval;
+
+ (void) snprintf(propname, sizeof (propname),
+ "module-size-%u", i);
+ if (do_bsys_getproplen(NULL, propname) != sizeof (uint64_t)) {
+ bkmem_free(fp, sizeof (bfile_t));
+ continue;
+ }
+ (void) do_bsys_getprop(NULL, propname, &propval);
+ fp->bf_size = (size_t)propval;
+ fp->bf_ino = i;
+
+ fp->bf_next = head;
+ head = fp;
+ }
+
+ return (0);
+}
+
+/*ARGSUSED*/
+static int
+bbootfs_open(char *fn, int flags)
+{
+ uint_t i;
+ bfile_t *fp;
+
+ if (!init_done) {
+ if (bbootfs_init() != 0)
+ return (-1);
+
+ init_done = 1;
+ }
+
+ canonicalise(fn, cpath);
+
+ for (fp = head; fp != NULL; fp = fp->bf_next) {
+ if (strcmp(fp->bf_name, cpath) == 0)
+ break;
+ }
+
+ if (fp == NULL)
+ return (-1);
+
+ for (i = 0; i < MAX_FDS; i++) {
+ if (fds[i].fd_file == NULL) {
+ fds[i].fd_file = fp;
+ fds[i].fd_pos = 0;
+ return (i);
+ }
+ }
+
+ return (-1);
+}
+
+static int
+bbootfs_close(int fd)
+{
+ if (fds[fd].fd_file == NULL)
+ return (-1);
+
+ fds[fd].fd_file = NULL;
+ fds[fd].fd_pos = 0;
+
+ return (0);
+}
+
+static ssize_t
+bbootfs_read(int fd, caddr_t buf, size_t size)
+{
+ ssize_t len;
+ bf_fd_t *fdp = &fds[fd];
+
+ if (fdp->fd_file == NULL)
+ return (-1);
+
+ if (fdp->fd_pos >= fdp->fd_file->bf_size)
+ return (-1);
+
+ if (fdp->fd_pos + size > fdp->fd_file->bf_size)
+ len = fdp->fd_file->bf_size - fdp->fd_pos;
+ else
+ len = size;
+
+ bcopy(fdp->fd_file->bf_addr + fdp->fd_pos, buf, len);
+
+ fdp->fd_pos += len;
+
+ return (len);
+}
+
+static off_t
+bbootfs_lseek(int fd, off_t addr, int whence)
+{
+ bf_fd_t *fdp = &fds[fd];
+
+ if (fdp->fd_file == NULL)
+ return (-1);
+
+ switch (whence) {
+ case SEEK_CUR:
+ fdp->fd_pos += addr;
+ break;
+ case SEEK_SET:
+ fdp->fd_pos = addr;
+ break;
+ case SEEK_END:
+ fdp->fd_pos = fdp->fd_file->bf_size;
+ break;
+ default:
+ return (-1);
+ }
+
+ return (0);
+}
+
+static int
+bbootfs_fstat(int fd, struct bootstat *bsp)
+{
+ bf_fd_t *fdp = &fds[fd];
+
+ if (fdp->fd_file == NULL)
+ return (-1);
+
+ bsp->st_dev = 1;
+ bsp->st_ino = fdp->fd_file->bf_ino;
+ bsp->st_mode = 0444;
+ bsp->st_nlink = 1;
+ bsp->st_uid = bsp->st_gid = 0;
+ bsp->st_rdev = 0;
+ bsp->st_size = fdp->fd_file->bf_size;
+ bsp->st_blksize = 1;
+ bsp->st_blocks = fdp->fd_file->bf_size;
+ (void) strcpy(bsp->st_fstype, "bootfs");
+
+ return (0);
+}
+
+/* ARGSUSED */
+static void
+bbootfs_closeall(int flag)
+{
+ bfile_t *fp;
+
+ while (head != NULL) {
+ fp = head;
+ head = head->bf_next;
+
+ bkmem_free(fp, sizeof (bfile_t));
+ }
+
+ init_done = 0;
+}
+
+struct boot_fs_ops bbootfs_ops = {
+ "bootfs",
+ bbootfs_mountroot,
+ bbootfs_unmountroot,
+ bbootfs_open,
+ bbootfs_close,
+ bbootfs_read,
+ bbootfs_lseek,
+ bbootfs_fstat,
+ bbootfs_closeall,
+ NULL
+};
diff --git a/usr/src/common/util/string.c b/usr/src/common/util/string.c
index d54b58d59c..80a076c436 100644
--- a/usr/src/common/util/string.c
+++ b/usr/src/common/util/string.c
@@ -21,6 +21,7 @@
/*
* Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
+ * Copyright 2014 Joyent, Inc. All rights reserved.
*/
/*
@@ -264,7 +265,7 @@ next_fmt:
if (sign && pad == '0')
ADDCHAR('-');
- while (width-- > sign)
+ while ((!left_align) && (width-- > sign))
ADDCHAR(pad);
if (sign && pad == ' ')
ADDCHAR('-');
@@ -280,6 +281,10 @@ next_fmt:
ADDCHAR(*sp);
}
+ /* add left-alignment padding */
+ while (width-- > sign)
+ ADDCHAR(' ');
+
if (c == 'b' && ul != 0) {
int any = 0;
c = *bs++;
diff --git a/usr/src/common/util/string.h b/usr/src/common/util/string.h
index 052eeab4a4..f7acd734bd 100644
--- a/usr/src/common/util/string.h
+++ b/usr/src/common/util/string.h
@@ -61,6 +61,7 @@ extern char *strncpy(char *, const char *, size_t);
extern char *strrchr(const char *, int c);
extern char *strstr(const char *, const char *);
extern char *strpbrk(const char *, const char *);
+extern char *strsep(char **, const char *);
extern char *strncat(char *, const char *, size_t);
extern size_t strlcat(char *, const char *, size_t);
extern size_t strlcpy(char *, const char *, size_t);
diff --git a/usr/src/common/util/strtolctype.h b/usr/src/common/util/strtolctype.h
index 5675e42be7..535c014d1f 100644
--- a/usr/src/common/util/strtolctype.h
+++ b/usr/src/common/util/strtolctype.h
@@ -44,7 +44,7 @@ extern "C" {
* safe in probe context.
*/
-#if defined(_KERNEL) && !defined(_BOOT)
+#if defined(_KERNEL) || defined(_BOOT)
#define isalnum(ch) (isalpha(ch) || isdigit(ch))
#define isalpha(ch) (isupper(ch) || islower(ch))
@@ -56,7 +56,7 @@ extern "C" {
#define isxdigit(ch) (isdigit(ch) || ((ch) >= 'a' && (ch) <= 'f') || \
((ch) >= 'A' && (ch) <= 'F'))
-#endif /* _KERNEL && !_BOOT */
+#endif /* _KERNEL || _BOOT */
#define DIGIT(x) \
(isdigit(x) ? (x) - '0' : islower(x) ? (x) + 10 - 'a' : (x) + 10 - 'A')
diff --git a/usr/src/common/zfs/zfs_prop.c b/usr/src/common/zfs/zfs_prop.c
index e145b1c866..54aaa027dd 100644
--- a/usr/src/common/zfs/zfs_prop.c
+++ b/usr/src/common/zfs/zfs_prop.c
@@ -444,6 +444,23 @@ zfs_prop_delegatable(zfs_prop_t prop)
return (pd->pd_attr != PROP_READONLY);
}
+boolean_t
+zfs_prop_cacheable(zfs_prop_t prop)
+{
+ /*
+ * It'd be nice if each prop had a flags field which could have flag
+ * like PROP_CACHEABLE, but since zprop_attr_t is an enum and this
+ * setting is orthogonal to the concepts of PROP_READONLY, etc., we have
+ * this function.
+ */
+ return (prop == ZFS_PROP_VERSION ||
+ prop == ZFS_PROP_NORMALIZE ||
+ prop == ZFS_PROP_UTF8ONLY ||
+ prop == ZFS_PROP_CASE ||
+ prop == ZFS_PROP_VOLSIZE ||
+ prop == ZFS_PROP_VOLBLOCKSIZE);
+}
+
/*
* Given a zfs dataset property name, returns the corresponding property ID.
*/
diff --git a/usr/src/common/zfs/zfs_prop.h b/usr/src/common/zfs/zfs_prop.h
index a63262311b..1796642c68 100644
--- a/usr/src/common/zfs/zfs_prop.h
+++ b/usr/src/common/zfs/zfs_prop.h
@@ -21,6 +21,7 @@
/*
* Copyright 2010 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
+ * Copyright (c) 2012, Joyent, Inc. All rights reserved.
*/
#ifndef _ZFS_PROP_H
@@ -86,6 +87,7 @@ typedef struct {
void zfs_prop_init(void);
zprop_type_t zfs_prop_get_type(zfs_prop_t);
boolean_t zfs_prop_delegatable(zfs_prop_t prop);
+boolean_t zfs_prop_cacheable(zfs_prop_t prop);
zprop_desc_t *zfs_prop_get_table(void);
/*