OpenZFS 6939 - add sysevents to zfs core for commands

Authored by: Dave Eddy <dave@daveeddy.com>
Reviewed by: Patrick Mooney <patrick.mooney@joyent.com>
Reviewed by: Joshua M. Clulow <jmc@joyent.com>
Reviewed by: Josh Wilsdon <jwilsdon@joyent.com>
Reviewed by: Matthew Ahrens <mahrens@delphix.com>
Reviewed by: George Wilson <george.wilson@delphix.com>
Reviewed by: Richard Elling <Richard.Elling@RichardElling.com>
Reviewed by: Alan Somers <asomers@gmail.com>
Reviewed by: Andrew Stormont <andyjstormont@gmail.com>
Approved by: Matthew Ahrens <mahrens@delphix.com>
Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov>
Reviewed-by: George Melikov <mail@gmelikov.ru>
Ported-by: Giuseppe Di Natale <dinatale2@llnl.gov>

OpenZFS-issue: https://www.illumos.org/issues/6939
OpenZFS-commit: https://github.com/openzfs/openzfs/commit/ce1577b
Closes #6328
This commit is contained in:
Dave Eddy 2017-05-30 11:39:17 -07:00 committed by Brian Behlendorf
parent 314be68aa9
commit 12fa0466df
11 changed files with 234 additions and 53 deletions

View File

@ -93,6 +93,7 @@ typedef struct zfs_zevent {
extern void fm_init(void); extern void fm_init(void);
extern void fm_fini(void); extern void fm_fini(void);
extern void fm_nvprint(nvlist_t *); extern void fm_nvprint(nvlist_t *);
extern void zfs_zevent_post_cb(nvlist_t *nvl, nvlist_t *detector);
extern int zfs_zevent_post(nvlist_t *, nvlist_t *, zevent_cb_t *); extern int zfs_zevent_post(nvlist_t *, nvlist_t *, zevent_cb_t *);
extern void zfs_zevent_drain_all(int *); extern void zfs_zevent_drain_all(int *);
extern int zfs_zevent_fd_hold(int, minor_t *, zfs_zevent_t **); extern int zfs_zevent_fd_hold(int, minor_t *, zfs_zevent_t **);

View File

@ -23,7 +23,8 @@
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2011, 2014 by Delphix. All rights reserved. * Copyright (c) 2011, 2014 by Delphix. All rights reserved.
* Copyright 2011 Nexenta Systems, Inc. All rights reserved. * Copyright 2011 Nexenta Systems, Inc. All rights reserved.
* Copyright (c) 2013, Joyent, Inc. All rights reserved. * Copyright (c) 2013, 2017 Joyent, Inc. All rights reserved.
* Copyright (c) 2014 Integros [integros.com]
* Copyright (c) 2017 Datto Inc. * Copyright (c) 2017 Datto Inc.
*/ */
@ -1146,11 +1147,45 @@ typedef enum {
* ZFS_EV_POOL_GUID DATA_TYPE_UINT64 * ZFS_EV_POOL_GUID DATA_TYPE_UINT64
* ZFS_EV_VDEV_PATH DATA_TYPE_STRING (optional) * ZFS_EV_VDEV_PATH DATA_TYPE_STRING (optional)
* ZFS_EV_VDEV_GUID DATA_TYPE_UINT64 * ZFS_EV_VDEV_GUID DATA_TYPE_UINT64
*
* ESC_ZFS_HISTORY_EVENT
*
* ZFS_EV_POOL_NAME DATA_TYPE_STRING
* ZFS_EV_POOL_GUID DATA_TYPE_UINT64
* ZFS_EV_HIST_TIME DATA_TYPE_UINT64 (optional)
* ZFS_EV_HIST_CMD DATA_TYPE_STRING (optional)
* ZFS_EV_HIST_WHO DATA_TYPE_UINT64 (optional)
* ZFS_EV_HIST_ZONE DATA_TYPE_STRING (optional)
* ZFS_EV_HIST_HOST DATA_TYPE_STRING (optional)
* ZFS_EV_HIST_TXG DATA_TYPE_UINT64 (optional)
* ZFS_EV_HIST_INT_EVENT DATA_TYPE_UINT64 (optional)
* ZFS_EV_HIST_INT_STR DATA_TYPE_STRING (optional)
* ZFS_EV_HIST_INT_NAME DATA_TYPE_STRING (optional)
* ZFS_EV_HIST_IOCTL DATA_TYPE_STRING (optional)
* ZFS_EV_HIST_DSNAME DATA_TYPE_STRING (optional)
* ZFS_EV_HIST_DSID DATA_TYPE_UINT64 (optional)
*
* The ZFS_EV_HIST_* members will correspond to the ZPOOL_HIST_* members in the
* history log nvlist. The keynames will be free of any spaces or other
* characters that could be potentially unexpected to consumers of the
* sysevents.
*/ */
#define ZFS_EV_POOL_NAME "pool_name" #define ZFS_EV_POOL_NAME "pool_name"
#define ZFS_EV_POOL_GUID "pool_guid" #define ZFS_EV_POOL_GUID "pool_guid"
#define ZFS_EV_VDEV_PATH "vdev_path" #define ZFS_EV_VDEV_PATH "vdev_path"
#define ZFS_EV_VDEV_GUID "vdev_guid" #define ZFS_EV_VDEV_GUID "vdev_guid"
#define ZFS_EV_HIST_TIME "history_time"
#define ZFS_EV_HIST_CMD "history_command"
#define ZFS_EV_HIST_WHO "history_who"
#define ZFS_EV_HIST_ZONE "history_zone"
#define ZFS_EV_HIST_HOST "history_hostname"
#define ZFS_EV_HIST_TXG "history_txg"
#define ZFS_EV_HIST_INT_EVENT "history_internal_event"
#define ZFS_EV_HIST_INT_STR "history_internal_str"
#define ZFS_EV_HIST_INT_NAME "history_internal_name"
#define ZFS_EV_HIST_IOCTL "history_ioctl"
#define ZFS_EV_HIST_DSNAME "history_dsname"
#define ZFS_EV_HIST_DSID "history_dsid"
#ifdef __cplusplus #ifdef __cplusplus
} }

View File

@ -24,6 +24,8 @@
* Copyright 2011 Nexenta Systems, Inc. All rights reserved. * Copyright 2011 Nexenta Systems, Inc. All rights reserved.
* Copyright (c) 2014 Spectra Logic Corporation, All rights reserved. * Copyright (c) 2014 Spectra Logic Corporation, All rights reserved.
* Copyright 2013 Saso Kiselkov. All rights reserved. * Copyright 2013 Saso Kiselkov. All rights reserved.
* Copyright (c) 2014 Integros [integros.com]
* Copyright 2017 Joyent, Inc.
* Copyright (c) 2017 Datto Inc. * Copyright (c) 2017 Datto Inc.
*/ */
@ -882,10 +884,11 @@ struct zbookmark_phys;
extern void spa_log_error(spa_t *spa, zio_t *zio); extern void spa_log_error(spa_t *spa, zio_t *zio);
extern void zfs_ereport_post(const char *class, spa_t *spa, vdev_t *vd, extern void zfs_ereport_post(const char *class, spa_t *spa, vdev_t *vd,
zio_t *zio, uint64_t stateoroffset, uint64_t length); zio_t *zio, uint64_t stateoroffset, uint64_t length);
extern nvlist_t *zfs_event_create(spa_t *spa, vdev_t *vd, const char *type,
const char *name, nvlist_t *aux);
extern void zfs_post_remove(spa_t *spa, vdev_t *vd); extern void zfs_post_remove(spa_t *spa, vdev_t *vd);
extern void zfs_post_state_change(spa_t *spa, vdev_t *vd, uint64_t laststate); extern void zfs_post_state_change(spa_t *spa, vdev_t *vd, uint64_t laststate);
extern void zfs_post_autoreplace(spa_t *spa, vdev_t *vd); extern void zfs_post_autoreplace(spa_t *spa, vdev_t *vd);
extern void zfs_post_sysevent(spa_t *spa, vdev_t *vd, const char *name);
extern uint64_t spa_get_errlog_size(spa_t *spa); extern uint64_t spa_get_errlog_size(spa_t *spa);
extern int spa_get_errlog(spa_t *spa, void *uaddr, size_t *count); extern int spa_get_errlog(spa_t *spa, void *uaddr, size_t *count);
extern void spa_errlog_rotate(spa_t *spa); extern void spa_errlog_rotate(spa_t *spa);
@ -909,7 +912,8 @@ extern void spa_prop_clear_bootfs(spa_t *spa, uint64_t obj, dmu_tx_t *tx);
extern void spa_configfile_set(spa_t *, nvlist_t *, boolean_t); extern void spa_configfile_set(spa_t *, nvlist_t *, boolean_t);
/* asynchronous event notification */ /* asynchronous event notification */
extern void spa_event_notify(spa_t *spa, vdev_t *vdev, const char *name); extern void spa_event_notify(spa_t *spa, vdev_t *vdev, nvlist_t *hist_nvl,
const char *name);
#ifdef ZFS_DEBUG #ifdef ZFS_DEBUG
#define dprintf_bp(bp, fmt, ...) do { \ #define dprintf_bp(bp, fmt, ...) do { \

View File

@ -27,4 +27,10 @@
#ifndef _SYS_SYSEVENT_H #ifndef _SYS_SYSEVENT_H
#define _SYS_SYSEVENT_H #define _SYS_SYSEVENT_H
#include <sys/nvpair.h>
typedef struct sysevent {
nvlist_t *resource;
} sysevent_t;
#endif #endif

View File

@ -21,6 +21,7 @@
/* /*
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright 2015 Nexenta Systems, Inc. All rights reserved. * Copyright 2015 Nexenta Systems, Inc. All rights reserved.
* Copyright 2017 Joyent, Inc.
*/ */
#ifndef _SYS_SYSEVENT_EVENTDEFS_H #ifndef _SYS_SYSEVENT_EVENTDEFS_H
@ -112,6 +113,7 @@ extern "C" {
#define ESC_ZFS_VDEV_AUTOEXPAND "vdev_autoexpand" #define ESC_ZFS_VDEV_AUTOEXPAND "vdev_autoexpand"
#define ESC_ZFS_BOOTFS_VDEV_ATTACH "bootfs_vdev_attach" #define ESC_ZFS_BOOTFS_VDEV_ATTACH "bootfs_vdev_attach"
#define ESC_ZFS_POOL_REGUID "pool_reguid" #define ESC_ZFS_POOL_REGUID "pool_reguid"
#define ESC_ZFS_HISTORY_EVENT "history_event"
/* /*
* datalink subclass definitions. * datalink subclass definitions.

View File

@ -23,6 +23,7 @@
* Copyright (c) 2011, 2016 by Delphix. All rights reserved. * Copyright (c) 2011, 2016 by Delphix. All rights reserved.
* Copyright 2016 Gary Mills * Copyright 2016 Gary Mills
* Copyright (c) 2017 Datto Inc. * Copyright (c) 2017 Datto Inc.
* Copyright 2017 Joyent, Inc.
*/ */
#include <sys/dsl_scan.h> #include <sys/dsl_scan.h>
@ -249,9 +250,10 @@ dsl_scan_setup_sync(void *arg, dmu_tx_t *tx)
if (vdev_resilver_needed(spa->spa_root_vdev, if (vdev_resilver_needed(spa->spa_root_vdev,
&scn->scn_phys.scn_min_txg, &scn->scn_phys.scn_max_txg)) { &scn->scn_phys.scn_min_txg, &scn->scn_phys.scn_max_txg)) {
spa_event_notify(spa, NULL, ESC_ZFS_RESILVER_START); spa_event_notify(spa, NULL, NULL,
ESC_ZFS_RESILVER_START);
} else { } else {
spa_event_notify(spa, NULL, ESC_ZFS_SCRUB_START); spa_event_notify(spa, NULL, NULL, ESC_ZFS_SCRUB_START);
} }
spa->spa_scrub_started = B_TRUE; spa->spa_scrub_started = B_TRUE;
@ -360,7 +362,8 @@ dsl_scan_done(dsl_scan_t *scn, boolean_t complete, dmu_tx_t *tx)
vdev_dtl_reassess(spa->spa_root_vdev, tx->tx_txg, vdev_dtl_reassess(spa->spa_root_vdev, tx->tx_txg,
complete ? scn->scn_phys.scn_max_txg : 0, B_TRUE); complete ? scn->scn_phys.scn_max_txg : 0, B_TRUE);
if (complete) { if (complete) {
spa_event_notify(spa, NULL, scn->scn_phys.scn_min_txg ? spa_event_notify(spa, NULL, NULL,
scn->scn_phys.scn_min_txg ?
ESC_ZFS_RESILVER_FINISH : ESC_ZFS_SCRUB_FINISH); ESC_ZFS_RESILVER_FINISH : ESC_ZFS_SCRUB_FINISH);
} }
spa_errlog_rotate(spa); spa_errlog_rotate(spa);

View File

@ -30,6 +30,7 @@
* Copyright 2016 Toomas Soome <tsoome@me.com> * Copyright 2016 Toomas Soome <tsoome@me.com>
* Copyright (c) 2016 Actifio, Inc. All rights reserved. * Copyright (c) 2016 Actifio, Inc. All rights reserved.
* Copyright (c) 2017 Datto Inc. * Copyright (c) 2017 Datto Inc.
* Copyright 2017 Joyent, Inc.
*/ */
/* /*
@ -77,6 +78,8 @@
#include <sys/zvol.h> #include <sys/zvol.h>
#ifdef _KERNEL #ifdef _KERNEL
#include <sys/fm/protocol.h>
#include <sys/fm/util.h>
#include <sys/bootprops.h> #include <sys/bootprops.h>
#include <sys/callb.h> #include <sys/callb.h>
#include <sys/cpupart.h> #include <sys/cpupart.h>
@ -146,6 +149,9 @@ const zio_taskq_info_t zio_taskqs[ZIO_TYPES][ZIO_TASKQ_TYPES] = {
{ ZTI_ONE, ZTI_NULL, ZTI_ONE, ZTI_NULL }, /* IOCTL */ { ZTI_ONE, ZTI_NULL, ZTI_ONE, ZTI_NULL }, /* IOCTL */
}; };
static sysevent_t *spa_event_create(spa_t *spa, vdev_t *vd, nvlist_t *hist_nvl,
const char *name);
static void spa_event_post(sysevent_t *ev);
static void spa_sync_version(void *arg, dmu_tx_t *tx); static void spa_sync_version(void *arg, dmu_tx_t *tx);
static void spa_sync_props(void *arg, dmu_tx_t *tx); static void spa_sync_props(void *arg, dmu_tx_t *tx);
static boolean_t spa_has_active_shared_spare(spa_t *spa); static boolean_t spa_has_active_shared_spare(spa_t *spa);
@ -801,7 +807,7 @@ spa_change_guid(spa_t *spa)
if (error == 0) { if (error == 0) {
spa_config_sync(spa, B_FALSE, B_TRUE); spa_config_sync(spa, B_FALSE, B_TRUE);
spa_event_notify(spa, NULL, ESC_ZFS_POOL_REGUID); spa_event_notify(spa, NULL, NULL, ESC_ZFS_POOL_REGUID);
} }
mutex_exit(&spa_namespace_lock); mutex_exit(&spa_namespace_lock);
@ -1701,7 +1707,7 @@ spa_check_removed(vdev_t *vd)
if (vd->vdev_ops->vdev_op_leaf && vdev_is_dead(vd) && if (vd->vdev_ops->vdev_op_leaf && vdev_is_dead(vd) &&
!vd->vdev_ishole) { !vd->vdev_ishole) {
zfs_post_autoreplace(vd->vdev_spa, vd); zfs_post_autoreplace(vd->vdev_spa, vd);
spa_event_notify(vd->vdev_spa, vd, ESC_ZFS_VDEV_CHECK); spa_event_notify(vd->vdev_spa, vd, NULL, ESC_ZFS_VDEV_CHECK);
} }
} }
@ -3998,7 +4004,7 @@ spa_create(const char *pool, nvlist_t *nvroot, nvlist_t *props,
txg_wait_synced(spa->spa_dsl_pool, txg); txg_wait_synced(spa->spa_dsl_pool, txg);
spa_config_sync(spa, B_FALSE, B_TRUE); spa_config_sync(spa, B_FALSE, B_TRUE);
spa_event_notify(spa, NULL, ESC_ZFS_POOL_CREATE); spa_event_notify(spa, NULL, NULL, ESC_ZFS_POOL_CREATE);
spa_history_log_version(spa, "create"); spa_history_log_version(spa, "create");
@ -4062,7 +4068,7 @@ spa_import(char *pool, nvlist_t *config, nvlist_t *props, uint64_t flags)
spa_configfile_set(spa, props, B_FALSE); spa_configfile_set(spa, props, B_FALSE);
spa_config_sync(spa, B_FALSE, B_TRUE); spa_config_sync(spa, B_FALSE, B_TRUE);
spa_event_notify(spa, NULL, ESC_ZFS_POOL_IMPORT); spa_event_notify(spa, NULL, NULL, ESC_ZFS_POOL_IMPORT);
mutex_exit(&spa_namespace_lock); mutex_exit(&spa_namespace_lock);
return (0); return (0);
@ -4189,7 +4195,7 @@ spa_import(char *pool, nvlist_t *config, nvlist_t *props, uint64_t flags)
spa_history_log_version(spa, "import"); spa_history_log_version(spa, "import");
spa_event_notify(spa, NULL, ESC_ZFS_POOL_IMPORT); spa_event_notify(spa, NULL, NULL, ESC_ZFS_POOL_IMPORT);
zvol_create_minors(spa, pool, B_TRUE); zvol_create_minors(spa, pool, B_TRUE);
@ -4390,7 +4396,7 @@ spa_export_common(char *pool, int new_state, nvlist_t **oldconfig,
} }
export_spa: export_spa:
spa_event_notify(spa, NULL, ESC_ZFS_POOL_DESTROY); spa_event_notify(spa, NULL, NULL, ESC_ZFS_POOL_DESTROY);
if (spa->spa_state != POOL_STATE_UNINITIALIZED) { if (spa->spa_state != POOL_STATE_UNINITIALIZED) {
spa_unload(spa); spa_unload(spa);
@ -4546,7 +4552,7 @@ spa_vdev_add(spa_t *spa, nvlist_t *nvroot)
mutex_enter(&spa_namespace_lock); mutex_enter(&spa_namespace_lock);
spa_config_update(spa, SPA_CONFIG_UPDATE_POOL); spa_config_update(spa, SPA_CONFIG_UPDATE_POOL);
spa_event_notify(spa, NULL, ESC_ZFS_VDEV_ADD); spa_event_notify(spa, NULL, NULL, ESC_ZFS_VDEV_ADD);
mutex_exit(&spa_namespace_lock); mutex_exit(&spa_namespace_lock);
return (0); return (0);
@ -4727,7 +4733,7 @@ spa_vdev_attach(spa_t *spa, uint64_t guid, nvlist_t *nvroot, int replacing)
if (newvd->vdev_isspare) { if (newvd->vdev_isspare) {
spa_spare_activate(newvd); spa_spare_activate(newvd);
spa_event_notify(spa, newvd, ESC_ZFS_VDEV_SPARE); spa_event_notify(spa, newvd, NULL, ESC_ZFS_VDEV_SPARE);
} }
oldvdpath = spa_strdup(oldvd->vdev_path); oldvdpath = spa_strdup(oldvd->vdev_path);
@ -4747,9 +4753,9 @@ spa_vdev_attach(spa_t *spa, uint64_t guid, nvlist_t *nvroot, int replacing)
dsl_resilver_restart(spa->spa_dsl_pool, dtl_max_txg); dsl_resilver_restart(spa->spa_dsl_pool, dtl_max_txg);
if (spa->spa_bootfs) if (spa->spa_bootfs)
spa_event_notify(spa, newvd, ESC_ZFS_BOOTFS_VDEV_ATTACH); spa_event_notify(spa, newvd, NULL, ESC_ZFS_BOOTFS_VDEV_ATTACH);
spa_event_notify(spa, newvd, ESC_ZFS_VDEV_ATTACH); spa_event_notify(spa, newvd, NULL, ESC_ZFS_VDEV_ATTACH);
/* /*
* Commit the config * Commit the config
@ -4963,7 +4969,7 @@ spa_vdev_detach(spa_t *spa, uint64_t guid, uint64_t pguid, int replace_done)
vd->vdev_detached = B_TRUE; vd->vdev_detached = B_TRUE;
vdev_dirty(tvd, VDD_DTL, vd, txg); vdev_dirty(tvd, VDD_DTL, vd, txg);
spa_event_notify(spa, vd, ESC_ZFS_VDEV_REMOVE); spa_event_notify(spa, vd, NULL, ESC_ZFS_VDEV_REMOVE);
/* hang on to the spa before we release the lock */ /* hang on to the spa before we release the lock */
spa_open_ref(spa, FTAG); spa_open_ref(spa, FTAG);
@ -5449,6 +5455,7 @@ int
spa_vdev_remove(spa_t *spa, uint64_t guid, boolean_t unspare) spa_vdev_remove(spa_t *spa, uint64_t guid, boolean_t unspare)
{ {
vdev_t *vd; vdev_t *vd;
sysevent_t *ev = NULL;
metaslab_group_t *mg; metaslab_group_t *mg;
nvlist_t **spares, **l2cache, *nv; nvlist_t **spares, **l2cache, *nv;
uint64_t txg = 0; uint64_t txg = 0;
@ -5474,7 +5481,8 @@ spa_vdev_remove(spa_t *spa, uint64_t guid, boolean_t unspare)
if (vd == NULL || unspare) { if (vd == NULL || unspare) {
if (vd == NULL) if (vd == NULL)
vd = spa_lookup_by_guid(spa, guid, B_TRUE); vd = spa_lookup_by_guid(spa, guid, B_TRUE);
spa_event_notify(spa, vd, ESC_ZFS_VDEV_REMOVE_AUX); ev = spa_event_create(spa, vd, NULL,
ESC_ZFS_VDEV_REMOVE_AUX);
spa_vdev_remove_aux(spa->spa_spares.sav_config, spa_vdev_remove_aux(spa->spa_spares.sav_config,
ZPOOL_CONFIG_SPARES, spares, nspares, nv); ZPOOL_CONFIG_SPARES, spares, nspares, nv);
spa_load_spares(spa); spa_load_spares(spa);
@ -5490,7 +5498,7 @@ spa_vdev_remove(spa_t *spa, uint64_t guid, boolean_t unspare)
* Cache devices can always be removed. * Cache devices can always be removed.
*/ */
vd = spa_lookup_by_guid(spa, guid, B_TRUE); vd = spa_lookup_by_guid(spa, guid, B_TRUE);
spa_event_notify(spa, vd, ESC_ZFS_VDEV_REMOVE_AUX); ev = spa_event_create(spa, vd, NULL, ESC_ZFS_VDEV_REMOVE_AUX);
spa_vdev_remove_aux(spa->spa_l2cache.sav_config, spa_vdev_remove_aux(spa->spa_l2cache.sav_config,
ZPOOL_CONFIG_L2CACHE, l2cache, nl2cache, nv); ZPOOL_CONFIG_L2CACHE, l2cache, nl2cache, nv);
spa_load_l2cache(spa); spa_load_l2cache(spa);
@ -5531,7 +5539,7 @@ spa_vdev_remove(spa_t *spa, uint64_t guid, boolean_t unspare)
/* /*
* Clean up the vdev namespace. * Clean up the vdev namespace.
*/ */
spa_event_notify(spa, vd, ESC_ZFS_VDEV_REMOVE_DEV); ev = spa_event_create(spa, vd, NULL, ESC_ZFS_VDEV_REMOVE_DEV);
spa_vdev_remove_from_namespace(spa, vd); spa_vdev_remove_from_namespace(spa, vd);
} else if (vd != NULL) { } else if (vd != NULL) {
@ -5549,6 +5557,9 @@ spa_vdev_remove(spa_t *spa, uint64_t guid, boolean_t unspare)
if (!locked) if (!locked)
error = spa_vdev_exit(spa, NULL, txg, error); error = spa_vdev_exit(spa, NULL, txg, error);
if (ev)
spa_event_post(ev);
return (error); return (error);
} }
@ -5831,7 +5842,7 @@ spa_async_autoexpand(spa_t *spa, vdev_t *vd)
if (!vd->vdev_ops->vdev_op_leaf || vd->vdev_physpath == NULL) if (!vd->vdev_ops->vdev_op_leaf || vd->vdev_physpath == NULL)
return; return;
spa_event_notify(vd->vdev_spa, vd, ESC_ZFS_VDEV_AUTOEXPAND); spa_event_notify(vd->vdev_spa, vd, NULL, ESC_ZFS_VDEV_AUTOEXPAND);
} }
static void static void
@ -6944,6 +6955,33 @@ spa_has_active_shared_spare(spa_t *spa)
return (B_FALSE); return (B_FALSE);
} }
static sysevent_t *
spa_event_create(spa_t *spa, vdev_t *vd, nvlist_t *hist_nvl, const char *name)
{
sysevent_t *ev = NULL;
#ifdef _KERNEL
nvlist_t *resource;
resource = zfs_event_create(spa, vd, FM_SYSEVENT_CLASS, name, hist_nvl);
if (resource) {
ev = kmem_alloc(sizeof (sysevent_t), KM_SLEEP);
ev->resource = resource;
}
#endif
return (ev);
}
static void
spa_event_post(sysevent_t *ev)
{
#ifdef _KERNEL
if (ev) {
zfs_zevent_post(ev->resource, NULL, zfs_zevent_post_cb);
kmem_free(ev, sizeof (*ev));
}
#endif
}
/* /*
* Post a zevent corresponding to the given sysevent. The 'name' must be one * Post a zevent corresponding to the given sysevent. The 'name' must be one
* of the event definitions in sys/sysevent/eventdefs.h. The payload will be * of the event definitions in sys/sysevent/eventdefs.h. The payload will be
@ -6952,9 +6990,9 @@ spa_has_active_shared_spare(spa_t *spa)
* or zdb as real changes. * or zdb as real changes.
*/ */
void void
spa_event_notify(spa_t *spa, vdev_t *vd, const char *name) spa_event_notify(spa_t *spa, vdev_t *vd, nvlist_t *hist_nvl, const char *name)
{ {
zfs_post_sysevent(spa, vd, name); spa_event_post(spa_event_create(spa, vd, hist_nvl, name));
} }
#if defined(_KERNEL) && defined(HAVE_SPL) #if defined(_KERNEL) && defined(HAVE_SPL)

View File

@ -23,6 +23,7 @@
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright 2011 Nexenta Systems, Inc. All rights reserved. * Copyright 2011 Nexenta Systems, Inc. All rights reserved.
* Copyright (c) 2011, 2015 by Delphix. All rights reserved. * Copyright (c) 2011, 2015 by Delphix. All rights reserved.
* Copyright 2017 Joyent, Inc.
*/ */
#include <sys/spa.h> #include <sys/spa.h>
@ -330,7 +331,7 @@ spa_config_sync(spa_t *target, boolean_t removing, boolean_t postsysevent)
spa_config_generation++; spa_config_generation++;
if (postsysevent) if (postsysevent)
spa_event_notify(target, NULL, ESC_ZFS_CONFIG_SYNC); spa_event_notify(target, NULL, NULL, ESC_ZFS_CONFIG_SYNC);
} }
/* /*

View File

@ -22,6 +22,8 @@
/* /*
* Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2011, 2015 by Delphix. All rights reserved. * Copyright (c) 2011, 2015 by Delphix. All rights reserved.
* Copyright (c) 2014 Integros [integros.com]
* Copyright 2017 Joyent, Inc.
*/ */
#include <sys/spa.h> #include <sys/spa.h>
@ -191,6 +193,71 @@ spa_history_zone(void)
#endif #endif
} }
/*
* Post a history sysevent.
*
* The nvlist_t* passed into this function will be transformed into a new
* nvlist where:
*
* 1. Nested nvlists will be flattened to a single level
* 2. Keys will have their names normalized (to remove any problematic
* characters, such as whitespace)
*
* The nvlist_t passed into this function will duplicated and should be freed
* by caller.
*
*/
static void
spa_history_log_notify(spa_t *spa, nvlist_t *nvl)
{
nvlist_t *hist_nvl = fnvlist_alloc();
uint64_t uint64;
char *string;
if (nvlist_lookup_string(nvl, ZPOOL_HIST_CMD, &string) == 0)
fnvlist_add_string(hist_nvl, ZFS_EV_HIST_CMD, string);
if (nvlist_lookup_string(nvl, ZPOOL_HIST_INT_NAME, &string) == 0)
fnvlist_add_string(hist_nvl, ZFS_EV_HIST_INT_NAME, string);
if (nvlist_lookup_string(nvl, ZPOOL_HIST_ZONE, &string) == 0)
fnvlist_add_string(hist_nvl, ZFS_EV_HIST_ZONE, string);
if (nvlist_lookup_string(nvl, ZPOOL_HIST_HOST, &string) == 0)
fnvlist_add_string(hist_nvl, ZFS_EV_HIST_HOST, string);
if (nvlist_lookup_string(nvl, ZPOOL_HIST_DSNAME, &string) == 0)
fnvlist_add_string(hist_nvl, ZFS_EV_HIST_DSNAME, string);
if (nvlist_lookup_string(nvl, ZPOOL_HIST_INT_STR, &string) == 0)
fnvlist_add_string(hist_nvl, ZFS_EV_HIST_INT_STR, string);
if (nvlist_lookup_string(nvl, ZPOOL_HIST_IOCTL, &string) == 0)
fnvlist_add_string(hist_nvl, ZFS_EV_HIST_IOCTL, string);
if (nvlist_lookup_string(nvl, ZPOOL_HIST_INT_NAME, &string) == 0)
fnvlist_add_string(hist_nvl, ZFS_EV_HIST_INT_NAME, string);
if (nvlist_lookup_uint64(nvl, ZPOOL_HIST_DSID, &uint64) == 0)
fnvlist_add_uint64(hist_nvl, ZFS_EV_HIST_DSID, uint64);
if (nvlist_lookup_uint64(nvl, ZPOOL_HIST_TXG, &uint64) == 0)
fnvlist_add_uint64(hist_nvl, ZFS_EV_HIST_TXG, uint64);
if (nvlist_lookup_uint64(nvl, ZPOOL_HIST_TIME, &uint64) == 0)
fnvlist_add_uint64(hist_nvl, ZFS_EV_HIST_TIME, uint64);
if (nvlist_lookup_uint64(nvl, ZPOOL_HIST_WHO, &uint64) == 0)
fnvlist_add_uint64(hist_nvl, ZFS_EV_HIST_WHO, uint64);
if (nvlist_lookup_uint64(nvl, ZPOOL_HIST_INT_EVENT, &uint64) == 0)
fnvlist_add_uint64(hist_nvl, ZFS_EV_HIST_INT_EVENT, uint64);
spa_event_notify(spa, NULL, hist_nvl, ESC_ZFS_HISTORY_EVENT);
nvlist_free(hist_nvl);
}
/* /*
* Write out a history event. * Write out a history event.
*/ */
@ -254,6 +321,22 @@ spa_history_log_sync(void *arg, dmu_tx_t *tx)
fnvlist_lookup_string(nvl, ZPOOL_HIST_INT_NAME), fnvlist_lookup_string(nvl, ZPOOL_HIST_INT_NAME),
fnvlist_lookup_string(nvl, ZPOOL_HIST_INT_STR)); fnvlist_lookup_string(nvl, ZPOOL_HIST_INT_STR));
} }
/*
* The history sysevent is posted only for internal history
* messages to show what has happened, not how it happened. For
* example, the following command:
*
* # zfs destroy -r tank/foo
*
* will result in one sysevent posted per dataset that is
* destroyed as a result of the command - which could be more
* than one event in total. By contrast, if the sysevent was
* posted as a result of the ZPOOL_HIST_CMD key being present
* it would result in only one sysevent being posted with the
* full command line arguments, requiring the consumer to know
* how to parse and understand zfs(1M) command invocations.
*/
spa_history_log_notify(spa, nvl);
} else if (nvlist_exists(nvl, ZPOOL_HIST_IOCTL)) { } else if (nvlist_exists(nvl, ZPOOL_HIST_IOCTL)) {
zfs_dbgmsg("ioctl %s", zfs_dbgmsg("ioctl %s",
fnvlist_lookup_string(nvl, ZPOOL_HIST_IOCTL)); fnvlist_lookup_string(nvl, ZPOOL_HIST_IOCTL));

View File

@ -25,6 +25,7 @@
* Copyright 2017 Nexenta Systems, Inc. * Copyright 2017 Nexenta Systems, Inc.
* Copyright (c) 2014 Integros [integros.com] * Copyright (c) 2014 Integros [integros.com]
* Copyright 2016 Toomas Soome <tsoome@me.com> * Copyright 2016 Toomas Soome <tsoome@me.com>
* Copyright 2017 Joyent, Inc.
*/ */
#include <sys/zfs_context.h> #include <sys/zfs_context.h>
@ -2657,7 +2658,7 @@ vdev_online(spa_t *spa, uint64_t guid, uint64_t flags, vdev_state_t *newstate)
if (wasoffline || if (wasoffline ||
(oldstate < VDEV_STATE_DEGRADED && (oldstate < VDEV_STATE_DEGRADED &&
vd->vdev_state >= VDEV_STATE_DEGRADED)) vd->vdev_state >= VDEV_STATE_DEGRADED))
spa_event_notify(spa, vd, ESC_ZFS_VDEV_ONLINE); spa_event_notify(spa, vd, NULL, ESC_ZFS_VDEV_ONLINE);
return (spa_vdev_state_exit(spa, vd, 0)); return (spa_vdev_state_exit(spa, vd, 0));
} }
@ -2821,7 +2822,7 @@ vdev_clear(spa_t *spa, vdev_t *vd)
if (vd->vdev_aux == NULL && !vdev_is_dead(vd)) if (vd->vdev_aux == NULL && !vdev_is_dead(vd))
spa_async_request(spa, SPA_ASYNC_RESILVER); spa_async_request(spa, SPA_ASYNC_RESILVER);
spa_event_notify(spa, vd, ESC_ZFS_VDEV_CLEAR); spa_event_notify(spa, vd, NULL, ESC_ZFS_VDEV_CLEAR);
} }
/* /*

View File

@ -102,7 +102,7 @@
* ereport with information about the differences. * ereport with information about the differences.
*/ */
#ifdef _KERNEL #ifdef _KERNEL
static void void
zfs_zevent_post_cb(nvlist_t *nvl, nvlist_t *detector) zfs_zevent_post_cb(nvlist_t *nvl, nvlist_t *detector)
{ {
if (nvl) if (nvl)
@ -904,19 +904,25 @@ zfs_ereport_post_checksum(spa_t *spa, vdev_t *vd,
#endif #endif
} }
static void /*
zfs_post_common(spa_t *spa, vdev_t *vd, const char *type, const char *name, * The 'sysevent.fs.zfs.*' events are signals posted to notify user space of
* change in the pool. All sysevents are listed in sys/sysevent/eventdefs.h
* and are designed to be consumed by the ZFS Event Daemon (ZED). For
* additional details refer to the zed(8) man page.
*/
nvlist_t *
zfs_event_create(spa_t *spa, vdev_t *vd, const char *type, const char *name,
nvlist_t *aux) nvlist_t *aux)
{ {
nvlist_t *resource = NULL;
#ifdef _KERNEL #ifdef _KERNEL
nvlist_t *resource;
char class[64]; char class[64];
if (spa_load_state(spa) == SPA_LOAD_TRYIMPORT) if (spa_load_state(spa) == SPA_LOAD_TRYIMPORT)
return; return (NULL);
if ((resource = fm_nvlist_create(NULL)) == NULL) if ((resource = fm_nvlist_create(NULL)) == NULL)
return; return (NULL);
(void) snprintf(class, sizeof (class), "%s.%s.%s", type, (void) snprintf(class, sizeof (class), "%s.%s.%s", type,
ZFS_ERROR_CLASS, name); ZFS_ERROR_CLASS, name);
@ -949,16 +955,30 @@ zfs_post_common(spa_t *spa, vdev_t *vd, const char *type, const char *name,
VERIFY0(nvlist_add_string(resource, VERIFY0(nvlist_add_string(resource,
FM_EREPORT_PAYLOAD_ZFS_VDEV_ENC_SYSFS_PATH, FM_EREPORT_PAYLOAD_ZFS_VDEV_ENC_SYSFS_PATH,
vd->vdev_enc_sysfs_path)); vd->vdev_enc_sysfs_path));
/* also copy any optional payload data */
if (aux) {
nvpair_t *elem = NULL;
while ((elem = nvlist_next_nvpair(aux, elem)) != NULL)
(void) nvlist_add_nvpair(resource, elem);
}
} }
zfs_zevent_post(resource, NULL, zfs_zevent_post_cb); /* also copy any optional payload data */
if (aux) {
nvpair_t *elem = NULL;
while ((elem = nvlist_next_nvpair(aux, elem)) != NULL)
(void) nvlist_add_nvpair(resource, elem);
}
#endif
return (resource);
}
static void
zfs_post_common(spa_t *spa, vdev_t *vd, const char *type, const char *name,
nvlist_t *aux)
{
#ifdef _KERNEL
nvlist_t *resource;
resource = zfs_event_create(spa, vd, type, name, aux);
if (resource)
zfs_zevent_post(resource, NULL, zfs_zevent_post_cb);
#endif #endif
} }
@ -1025,23 +1045,10 @@ zfs_post_state_change(spa_t *spa, vdev_t *vd, uint64_t laststate)
#endif #endif
} }
/*
* The 'sysevent.fs.zfs.*' events are signals posted to notify user space of
* change in the pool. All sysevents are listed in sys/sysevent/eventdefs.h
* and are designed to be consumed by the ZFS Event Daemon (ZED). For
* additional details refer to the zed(8) man page.
*/
void
zfs_post_sysevent(spa_t *spa, vdev_t *vd, const char *name)
{
zfs_post_common(spa, vd, FM_SYSEVENT_CLASS, name, NULL);
}
#if defined(_KERNEL) && defined(HAVE_SPL) #if defined(_KERNEL) && defined(HAVE_SPL)
EXPORT_SYMBOL(zfs_ereport_post); EXPORT_SYMBOL(zfs_ereport_post);
EXPORT_SYMBOL(zfs_ereport_post_checksum); EXPORT_SYMBOL(zfs_ereport_post_checksum);
EXPORT_SYMBOL(zfs_post_remove); EXPORT_SYMBOL(zfs_post_remove);
EXPORT_SYMBOL(zfs_post_autoreplace); EXPORT_SYMBOL(zfs_post_autoreplace);
EXPORT_SYMBOL(zfs_post_state_change); EXPORT_SYMBOL(zfs_post_state_change);
EXPORT_SYMBOL(zfs_post_sysevent);
#endif /* _KERNEL */ #endif /* _KERNEL */