aboutsummaryrefslogtreecommitdiff
path: root/sys/cddl
diff options
context:
space:
mode:
Diffstat (limited to 'sys/cddl')
-rw-r--r--sys/cddl/contrib/opensolaris/uts/common/fs/zfs/vdev_geom.c114
-rw-r--r--sys/cddl/dev/dtrace/powerpc/dtrace_isa.c57
-rw-r--r--sys/cddl/dev/fbt/powerpc/fbt_isa.c4
-rw-r--r--sys/cddl/dev/profile/profile.c60
4 files changed, 118 insertions, 117 deletions
diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/vdev_geom.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/vdev_geom.c
index 22b48e823060..c6e30301c623 100644
--- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/vdev_geom.c
+++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/vdev_geom.c
@@ -49,6 +49,16 @@ struct g_class zfs_vdev_class = {
.attrchanged = vdev_geom_attrchanged,
};
+struct consumer_vdev_elem {
+ SLIST_ENTRY(consumer_vdev_elem) elems;
+ vdev_t *vd;
+};
+
+SLIST_HEAD(consumer_priv_t, consumer_vdev_elem);
+_Static_assert(sizeof(((struct g_consumer*)NULL)->private)
+ == sizeof(struct consumer_priv_t*),
+ "consumer_priv_t* can't be stored in g_consumer.private");
+
DECLARE_GEOM_CLASS(zfs_vdev_class, zfs_vdev);
SYSCTL_DECL(_vfs_zfs_vdev);
@@ -85,21 +95,16 @@ vdev_geom_set_rotation_rate(vdev_t *vd, struct g_consumer *cp)
}
static void
-vdev_geom_set_physpath(struct g_consumer *cp, boolean_t do_null_update)
+vdev_geom_set_physpath(vdev_t *vd, struct g_consumer *cp,
+ boolean_t do_null_update)
{
boolean_t needs_update = B_FALSE;
- vdev_t *vd;
char *physpath;
int error, physpath_len;
- if (g_access(cp, 1, 0, 0) != 0)
- return;
-
- vd = cp->private;
physpath_len = MAXPATHLEN;
physpath = g_malloc(physpath_len, M_WAITOK|M_ZERO);
error = g_io_getattr("GEOM::physpath", cp, &physpath_len, physpath);
- g_access(cp, -1, 0, 0);
if (error == 0) {
char *old_physpath;
@@ -130,37 +135,40 @@ vdev_geom_set_physpath(struct g_consumer *cp, boolean_t do_null_update)
static void
vdev_geom_attrchanged(struct g_consumer *cp, const char *attr)
{
- vdev_t *vd;
char *old_physpath;
+ struct consumer_priv_t *priv;
+ struct consumer_vdev_elem *elem;
int error;
- vd = cp->private;
- if (vd == NULL)
+ priv = (struct consumer_priv_t*)&cp->private;
+ if (SLIST_EMPTY(priv))
return;
- if (strcmp(attr, "GEOM::rotation_rate") == 0) {
- vdev_geom_set_rotation_rate(vd, cp);
- return;
- }
-
- if (strcmp(attr, "GEOM::physpath") == 0) {
- vdev_geom_set_physpath(cp, /*do_null_update*/B_TRUE);
- return;
+ SLIST_FOREACH(elem, priv, elems) {
+ vdev_t *vd = elem->vd;
+ if (strcmp(attr, "GEOM::rotation_rate") == 0) {
+ vdev_geom_set_rotation_rate(vd, cp);
+ return;
+ }
+ if (strcmp(attr, "GEOM::physpath") == 0) {
+ vdev_geom_set_physpath(vd, cp, /*null_update*/B_TRUE);
+ return;
+ }
}
}
static void
vdev_geom_orphan(struct g_consumer *cp)
{
- vdev_t *vd;
+ struct consumer_priv_t *priv;
+ struct consumer_vdev_elem *elem;
g_topology_assert();
- vd = cp->private;
- if (vd == NULL) {
+ priv = (struct consumer_priv_t*)&cp->private;
+ if (SLIST_EMPTY(priv))
/* Vdev close in progress. Ignore the event. */
return;
- }
/*
* Orphan callbacks occur from the GEOM event thread.
@@ -176,8 +184,12 @@ vdev_geom_orphan(struct g_consumer *cp)
* async removal support to invoke a close on this
* vdev once it is safe to do so.
*/
- vd->vdev_remove_wanted = B_TRUE;
- spa_async_request(vd->vdev_spa, SPA_ASYNC_REMOVE);
+ SLIST_FOREACH(elem, priv, elems) {
+ vdev_t *vd = elem->vd;
+
+ vd->vdev_remove_wanted = B_TRUE;
+ spa_async_request(vd->vdev_spa, SPA_ASYNC_REMOVE);
+ }
}
static struct g_consumer *
@@ -265,21 +277,8 @@ vdev_geom_attach(struct g_provider *pp, vdev_t *vd)
}
}
- /*
- * BUG: cp may already belong to a vdev. This could happen if:
- * 1) That vdev is a shared spare, or
- * 2) We are trying to reopen a missing vdev and we are scanning by
- * guid. In that case, we'll ultimately fail to open this consumer,
- * but not until after setting the private field.
- * The solution is to:
- * 1) Don't set the private field until after the open succeeds, and
- * 2) Set it to a linked list of vdevs, not just a single vdev
- */
- cp->private = vd;
- if (vd != NULL) {
+ if (vd != NULL)
vd->vdev_tsd = cp;
- vdev_geom_set_physpath(cp, /*do_null_update*/B_FALSE);
- }
cp->flags |= G_CF_DIRECT_SEND | G_CF_DIRECT_RECEIVE;
return (cp);
@@ -289,16 +288,12 @@ static void
vdev_geom_detach(struct g_consumer *cp, boolean_t open_for_read)
{
struct g_geom *gp;
- vdev_t *vd;
g_topology_assert();
ZFS_LOG(1, "Detaching from %s.",
cp->provider && cp->provider->name ? cp->provider->name : "NULL");
- vd = cp->private;
- cp->private = NULL;
-
gp = cp->geom;
if (open_for_read)
g_access(cp, -1, 0, -1);
@@ -324,16 +319,26 @@ static void
vdev_geom_close_locked(vdev_t *vd)
{
struct g_consumer *cp;
+ struct consumer_priv_t *priv;
+ struct consumer_vdev_elem *elem, *elem_temp;
g_topology_assert();
cp = vd->vdev_tsd;
- vd->vdev_tsd = NULL;
vd->vdev_delayed_close = B_FALSE;
if (cp == NULL)
return;
ZFS_LOG(1, "Closing access to %s.", cp->provider->name);
+ KASSERT(cp->private != NULL, ("%s: cp->private is NULL", __func__));
+ priv = (struct consumer_priv_t*)&cp->private;
+ vd->vdev_tsd = NULL;
+ SLIST_FOREACH_SAFE(elem, priv, elems, elem_temp) {
+ if (elem->vd == vd) {
+ SLIST_REMOVE(priv, elem, consumer_vdev_elem, elems);
+ g_free(elem);
+ }
+ }
vdev_geom_detach(cp, B_TRUE);
}
@@ -870,11 +875,27 @@ vdev_geom_open(vdev_t *vd, uint64_t *psize, uint64_t *max_psize,
cp = NULL;
}
}
+ if (cp != NULL) {
+ struct consumer_priv_t *priv;
+ struct consumer_vdev_elem *elem;
+
+ priv = (struct consumer_priv_t*)&cp->private;
+ if (cp->private == NULL)
+ SLIST_INIT(priv);
+ elem = g_malloc(sizeof(*elem), M_WAITOK|M_ZERO);
+ elem->vd = vd;
+ SLIST_INSERT_HEAD(priv, elem, elems);
+ }
/* Fetch initial physical path information for this device. */
- if (cp != NULL)
+ if (cp != NULL) {
vdev_geom_attrchanged(cp, "GEOM::physpath");
+ /* Set other GEOM characteristics */
+ vdev_geom_set_physpath(vd, cp, /*do_null_update*/B_FALSE);
+ vdev_geom_set_rotation_rate(vd, cp);
+ }
+
g_topology_unlock();
PICKUP_GIANT();
if (cp == NULL) {
@@ -905,11 +926,6 @@ skip_open:
*/
vd->vdev_nowritecache = B_FALSE;
- /*
- * Determine the device's rotation rate.
- */
- vdev_geom_set_rotation_rate(vd, cp);
-
return (0);
}
diff --git a/sys/cddl/dev/dtrace/powerpc/dtrace_isa.c b/sys/cddl/dev/dtrace/powerpc/dtrace_isa.c
index 950e9ac60987..c6c72a3ceb1f 100644
--- a/sys/cddl/dev/dtrace/powerpc/dtrace_isa.c
+++ b/sys/cddl/dev/dtrace/powerpc/dtrace_isa.c
@@ -38,6 +38,7 @@
#include <machine/frame.h>
#include <machine/md_var.h>
+#include <machine/psl.h>
#include <machine/reg.h>
#include <machine/stack.h>
@@ -54,16 +55,19 @@
#ifdef __powerpc64__
#define OFFSET 4 /* Account for the TOC reload slot */
+#define FRAME_OFFSET 48
#else
#define OFFSET 0
+#define FRAME_OFFSET 8
#endif
#define INKERNEL(x) ((x) <= VM_MAX_KERNEL_ADDRESS && \
(x) >= VM_MIN_KERNEL_ADDRESS)
static __inline int
-dtrace_sp_inkernel(uintptr_t sp, int aframes)
+dtrace_sp_inkernel(uintptr_t sp)
{
+ struct trapframe *frame;
vm_offset_t callpc;
#ifdef __powerpc64__
@@ -77,14 +81,15 @@ dtrace_sp_inkernel(uintptr_t sp, int aframes)
/*
* trapexit() and asttrapexit() are sentinels
* for kernel stack tracing.
- *
- * Special-case this for 'aframes == 0', because fbt sets aframes to the
- * trap callchain depth, so we want to break out of it.
*/
- if ((callpc + OFFSET == (vm_offset_t) &trapexit ||
- callpc + OFFSET == (vm_offset_t) &asttrapexit) &&
- aframes != 0)
- return (0);
+ if (callpc + OFFSET == (vm_offset_t) &trapexit ||
+ callpc + OFFSET == (vm_offset_t) &asttrapexit) {
+ if (sp == 0)
+ return (0);
+ frame = (struct trapframe *)(sp + FRAME_OFFSET);
+
+ return ((frame->srr1 & PSL_PR) == 0);
+ }
return (1);
}
@@ -93,6 +98,7 @@ static __inline uintptr_t
dtrace_next_sp(uintptr_t sp)
{
vm_offset_t callpc;
+ struct trapframe *frame;
#ifdef __powerpc64__
callpc = *(vm_offset_t *)(sp + RETURN_OFFSET64);
@@ -103,18 +109,13 @@ dtrace_next_sp(uintptr_t sp)
/*
* trapexit() and asttrapexit() are sentinels
* for kernel stack tracing.
- *
- * Special-case this for 'aframes == 0', because fbt sets aframes to the
- * trap callchain depth, so we want to break out of it.
*/
if ((callpc + OFFSET == (vm_offset_t) &trapexit ||
- callpc + OFFSET == (vm_offset_t) &asttrapexit))
- /* Access the trap frame */
-#ifdef __powerpc64__
- return (*(uintptr_t *)sp + 48 + sizeof(register_t));
-#else
- return (*(uintptr_t *)sp + 8 + sizeof(register_t));
-#endif
+ callpc + OFFSET == (vm_offset_t) &asttrapexit)) {
+ /* Access the trap frame */
+ frame = (struct trapframe *)(sp + FRAME_OFFSET);
+ return (*(uintptr_t *)(frame->fixreg[1]));
+ }
return (*(uintptr_t*)sp);
}
@@ -122,6 +123,7 @@ dtrace_next_sp(uintptr_t sp)
static __inline uintptr_t
dtrace_get_pc(uintptr_t sp)
{
+ struct trapframe *frame;
vm_offset_t callpc;
#ifdef __powerpc64__
@@ -133,18 +135,13 @@ dtrace_get_pc(uintptr_t sp)
/*
* trapexit() and asttrapexit() are sentinels
* for kernel stack tracing.
- *
- * Special-case this for 'aframes == 0', because fbt sets aframes to the
- * trap callchain depth, so we want to break out of it.
*/
if ((callpc + OFFSET == (vm_offset_t) &trapexit ||
- callpc + OFFSET == (vm_offset_t) &asttrapexit))
- /* Access the trap frame */
-#ifdef __powerpc64__
- return (*(uintptr_t *)sp + 48 + offsetof(struct trapframe, lr));
-#else
- return (*(uintptr_t *)sp + 8 + offsetof(struct trapframe, lr));
-#endif
+ callpc + OFFSET == (vm_offset_t) &asttrapexit)) {
+ /* Access the trap frame */
+ frame = (struct trapframe *)(sp + FRAME_OFFSET);
+ return (frame->srr0);
+ }
return (callpc);
}
@@ -176,7 +173,7 @@ dtrace_getpcstack(pc_t *pcstack, int pcstack_limit, int aframes,
if (sp <= osp)
break;
- if (!dtrace_sp_inkernel(sp, aframes))
+ if (!dtrace_sp_inkernel(sp))
break;
callpc = dtrace_get_pc(sp);
@@ -537,7 +534,7 @@ dtrace_getstackdepth(int aframes)
if (sp <= osp)
break;
- if (!dtrace_sp_inkernel(sp, aframes))
+ if (!dtrace_sp_inkernel(sp))
break;
if (aframes == 0)
diff --git a/sys/cddl/dev/fbt/powerpc/fbt_isa.c b/sys/cddl/dev/fbt/powerpc/fbt_isa.c
index cea849e31d36..502d427da57a 100644
--- a/sys/cddl/dev/fbt/powerpc/fbt_isa.c
+++ b/sys/cddl/dev/fbt/powerpc/fbt_isa.c
@@ -37,7 +37,7 @@
#include "fbt.h"
-#define FBT_PATCHVAL 0x7c810808
+#define FBT_PATCHVAL 0x7ffff808
#define FBT_MFLR_R0 0x7c0802a6
#define FBT_MTLR_R0 0x7c0803a6
#define FBT_BLR 0x4e800020
@@ -127,7 +127,7 @@ fbt_provide_module_function(linker_file_t lf, int symindx,
return (0);
#endif
- if (fbt_excluded(name) == 0)
+ if (fbt_excluded(name))
return (0);
instr = (uint32_t *) symval->value;
diff --git a/sys/cddl/dev/profile/profile.c b/sys/cddl/dev/profile/profile.c
index 3b584246d14e..55ea9850e26d 100644
--- a/sys/cddl/dev/profile/profile.c
+++ b/sys/cddl/dev/profile/profile.c
@@ -266,37 +266,43 @@ sbt_to_nsec(sbintime_t sbt)
}
static void
-profile_fire(void *arg)
+profile_probe(profile_probe_t *prof, hrtime_t late)
{
- profile_probe_percpu_t *pcpu = arg;
- profile_probe_t *prof = pcpu->profc_probe;
- hrtime_t late;
+ struct thread *td;
struct trapframe *frame;
uintfptr_t pc, upc;
-#ifdef illumos
- late = gethrtime() - pcpu->profc_expected;
-#else
- late = sbt_to_nsec(sbinuptime() - pcpu->profc_expected);
-#endif
-
- pc = 0;
- upc = 0;
+ td = curthread;
+ pc = upc = 0;
/*
- * td_intr_frame can be unset if this is a catch up event
- * after waking up from idle sleep.
- * This can only happen on a CPU idle thread.
+ * td_intr_frame can be unset if this is a catch-up event upon waking up
+ * from idle sleep. This can only happen on a CPU idle thread. Use a
+ * representative arg0 value in this case so that one of the probe
+ * arguments is non-zero.
*/
- frame = curthread->td_intr_frame;
+ frame = td->td_intr_frame;
if (frame != NULL) {
if (TRAPF_USERMODE(frame))
upc = TRAPF_PC(frame);
else
pc = TRAPF_PC(frame);
- }
+ } else if (TD_IS_IDLETHREAD(td))
+ pc = (uintfptr_t)&cpu_idle;
+
dtrace_probe(prof->prof_id, pc, upc, late, 0, 0);
+}
+static void
+profile_fire(void *arg)
+{
+ profile_probe_percpu_t *pcpu = arg;
+ profile_probe_t *prof = pcpu->profc_probe;
+ hrtime_t late;
+
+ late = sbt_to_nsec(sbinuptime() - pcpu->profc_expected);
+
+ profile_probe(prof, late);
pcpu->profc_expected += pcpu->profc_interval;
callout_schedule_sbt_curcpu(&pcpu->profc_cyclic,
pcpu->profc_expected, 0, C_DIRECT_EXEC | C_ABSOLUTE);
@@ -306,26 +312,8 @@ static void
profile_tick(void *arg)
{
profile_probe_t *prof = arg;
- struct trapframe *frame;
- uintfptr_t pc, upc;
-
- pc = 0;
- upc = 0;
-
- /*
- * td_intr_frame can be unset if this is a catch up event
- * after waking up from idle sleep.
- * This can only happen on a CPU idle thread.
- */
- frame = curthread->td_intr_frame;
- if (frame != NULL) {
- if (TRAPF_USERMODE(frame))
- upc = TRAPF_PC(frame);
- else
- pc = TRAPF_PC(frame);
- }
- dtrace_probe(prof->prof_id, pc, upc, 0, 0, 0);
+ profile_probe(prof, 0);
prof->prof_expected += prof->prof_interval;
callout_schedule_sbt(&prof->prof_cyclic,
prof->prof_expected, 0, C_DIRECT_EXEC | C_ABSOLUTE);