#include <sys/time.h>
#include <sys/zfs_ioctl.h>
-int zevent_len_max = 0;
-int zevent_cols = 80;
-int zevent_console = 0;
+int zfs_zevent_len_max = 0;
+int zfs_zevent_cols = 80;
+int zfs_zevent_console = 0;
static int zevent_len_cur = 0;
static int zevent_waiters = 0;
console_printf("\n");
if (nvlist_lookup_string(nvl, FM_CLASS, &class) == 0)
- c = fm_printf(0, c, zevent_cols, "%s", class);
+ c = fm_printf(0, c, zfs_zevent_cols, "%s", class);
- if (fm_nvprintr(nvl, 0, c, zevent_cols) != 0)
+ if (fm_nvprintr(nvl, 0, c, zfs_zevent_cols) != 0)
console_printf("\n");
console_printf("\n");
{
zevent_t *ev;
- ev = kmem_zalloc(sizeof(zevent_t), KM_SLEEP);
+ ev = kmem_zalloc(sizeof(zevent_t), KM_PUSHPAGE);
if (ev == NULL)
return NULL;
static void
zfs_zevent_insert(zevent_t *ev)
{
- mutex_enter(&zevent_lock);
+ ASSERT(MUTEX_HELD(&zevent_lock));
list_insert_head(&zevent_list, ev);
- if (zevent_len_cur >= zevent_len_max)
+
+ if (zevent_len_cur >= zfs_zevent_len_max)
zfs_zevent_drain(list_tail(&zevent_list));
else
zevent_len_cur++;
-
- mutex_exit(&zevent_lock);
}
/*
return;
}
- if (zevent_console)
+ if (zfs_zevent_console)
fm_nvprint(nvl);
ev = zfs_zevent_alloc();
ev->ev_nvl = nvl;
ev->ev_detector = detector;
ev->ev_cb = cb;
+
+ mutex_enter(&zevent_lock);
zfs_zevent_insert(ev);
cv_broadcast(&zevent_cv);
+ mutex_exit(&zevent_lock);
}
static int
}
/*
- * Get the next zevent in the stream and place a copy in 'event'.
+ * Get the next zevent in the stream and place a copy in 'event'. This
+ * may fail with ENOMEM if the encoded nvlist size exceeds the passed
+ * 'event_size'. In this case the stream pointer is not advanced and
+ * and 'event_size' is set to the minimum required buffer size.
*/
int
-zfs_zevent_next(zfs_zevent_t *ze, nvlist_t **event, uint64_t *dropped)
+zfs_zevent_next(zfs_zevent_t *ze, nvlist_t **event, uint64_t *event_size,
+ uint64_t *dropped)
{
zevent_t *ev;
- int error;
+ size_t size;
+ int error = 0;
mutex_enter(&zevent_lock);
if (ze->ze_zevent == NULL) {
error = ENOENT;
goto out;
}
+ }
- list_remove(&ze->ze_zevent->ev_ze_list, ze);
+ VERIFY(nvlist_size(ev->ev_nvl, &size, NV_ENCODE_NATIVE) == 0);
+ if (size > *event_size) {
+ *event_size = size;
+ error = ENOMEM;
+ goto out;
}
+ if (ze->ze_zevent)
+ list_remove(&ze->ze_zevent->ev_ze_list, ze);
+
ze->ze_zevent = ev;
list_insert_head(&ev->ev_ze_list, ze);
nvlist_dup(ev->ev_nvl, event, KM_SLEEP);
static void *
i_fm_alloc(nv_alloc_t *nva, size_t size)
{
- return (kmem_zalloc(size, KM_SLEEP));
+ return (kmem_zalloc(size, KM_PUSHPAGE));
}
/* ARGSUSED */
nv_alloc_t *nvhdl;
if (nva == NULL) {
- nvhdl = kmem_zalloc(sizeof (nv_alloc_t), KM_SLEEP);
+ nvhdl = kmem_zalloc(sizeof (nv_alloc_t), KM_PUSHPAGE);
if (nv_alloc_init(nvhdl, &fm_mem_alloc_ops, NULL, 0) != 0) {
kmem_free(nvhdl, sizeof (nv_alloc_t));
uint64_t
fm_ena_generate(uint64_t timestamp, uchar_t format)
{
- return (fm_ena_generate_cpu(timestamp, getcpuid(), format));
+ uint64_t ena;
+
+ kpreempt_disable();
+ ena = fm_ena_generate_cpu(timestamp, getcpuid(), format);
+ kpreempt_enable();
+
+ return (ena);
}
uint64_t
zevent_len_cur = 0;
zevent_flags = 0;
- if (zevent_len_max == 0)
- zevent_len_max = ERPT_MAX_ERRS * MAX(max_ncpus, 4);
+ if (zfs_zevent_len_max == 0)
+ zfs_zevent_len_max = ERPT_MAX_ERRS * MAX(max_ncpus, 4);
/* Initialize zevent allocation and generation kstats */
fm_ksp = kstat_create("zfs", 0, "fm", "misc", KSTAT_TYPE_NAMED,
int count;
zfs_zevent_drain_all(&count);
- cv_broadcast(&zevent_cv);
mutex_enter(&zevent_lock);
+ cv_broadcast(&zevent_cv);
+
zevent_flags |= ZEVENT_SHUTDOWN;
while (zevent_waiters > 0) {
mutex_exit(&zevent_lock);
}
}
-module_param(zevent_len_max, int, 0644);
-MODULE_PARM_DESC(zevent_len_max, "Maximum event queue length");
+module_param(zfs_zevent_len_max, int, 0644);
+MODULE_PARM_DESC(zfs_zevent_len_max, "Max event queue length");
-module_param(zevent_cols, int, 0644);
-MODULE_PARM_DESC(zevent_cols, "Maximum event column width");
+module_param(zfs_zevent_cols, int, 0644);
+MODULE_PARM_DESC(zfs_zevent_cols, "Max event column width");
-module_param(zevent_console, int, 0644);
-MODULE_PARM_DESC(zevent_console, "Log events to the console");
+module_param(zfs_zevent_console, int, 0644);
+MODULE_PARM_DESC(zfs_zevent_console, "Log events to the console");
#endif /* _KERNEL */