diff --git a/include/sys/fm/util.h b/include/sys/fm/util.h index 6ee31764b..ff54b05bb 100644 --- a/include/sys/fm/util.h +++ b/include/sys/fm/util.h @@ -93,6 +93,7 @@ typedef struct zfs_zevent { extern void fm_init(void); extern void fm_fini(void); 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 void zfs_zevent_drain_all(int *); extern int zfs_zevent_fd_hold(int, minor_t *, zfs_zevent_t **); diff --git a/include/sys/fs/zfs.h b/include/sys/fs/zfs.h index b634635c8..9fbcfbef3 100644 --- a/include/sys/fs/zfs.h +++ b/include/sys/fs/zfs.h @@ -23,7 +23,8 @@ * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2011, 2014 by Delphix. 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. */ @@ -1146,11 +1147,45 @@ typedef enum { * ZFS_EV_POOL_GUID DATA_TYPE_UINT64 * ZFS_EV_VDEV_PATH DATA_TYPE_STRING (optional) * 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_GUID "pool_guid" #define ZFS_EV_VDEV_PATH "vdev_path" #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 } diff --git a/include/sys/spa.h b/include/sys/spa.h index 33f3a7805..dd86aad40 100644 --- a/include/sys/spa.h +++ b/include/sys/spa.h @@ -24,6 +24,8 @@ * Copyright 2011 Nexenta Systems, Inc. All rights reserved. * Copyright (c) 2014 Spectra Logic Corporation, 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. */ @@ -882,10 +884,11 @@ struct zbookmark_phys; 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, 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_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_sysevent(spa_t *spa, vdev_t *vd, const char *name); extern uint64_t spa_get_errlog_size(spa_t *spa); extern int spa_get_errlog(spa_t *spa, void *uaddr, size_t *count); 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); /* 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 #define dprintf_bp(bp, fmt, ...) do { \ diff --git a/include/sys/sysevent.h b/include/sys/sysevent.h index 2922e3072..6510297d6 100644 --- a/include/sys/sysevent.h +++ b/include/sys/sysevent.h @@ -27,4 +27,10 @@ #ifndef _SYS_SYSEVENT_H #define _SYS_SYSEVENT_H +#include + +typedef struct sysevent { + nvlist_t *resource; +} sysevent_t; + #endif diff --git a/include/sys/sysevent/eventdefs.h b/include/sys/sysevent/eventdefs.h index eadaaef58..fc2687842 100644 --- a/include/sys/sysevent/eventdefs.h +++ b/include/sys/sysevent/eventdefs.h @@ -21,6 +21,7 @@ /* * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. * Copyright 2015 Nexenta Systems, Inc. All rights reserved. + * Copyright 2017 Joyent, Inc. */ #ifndef _SYS_SYSEVENT_EVENTDEFS_H @@ -112,6 +113,7 @@ extern "C" { #define ESC_ZFS_VDEV_AUTOEXPAND "vdev_autoexpand" #define ESC_ZFS_BOOTFS_VDEV_ATTACH "bootfs_vdev_attach" #define ESC_ZFS_POOL_REGUID "pool_reguid" +#define ESC_ZFS_HISTORY_EVENT "history_event" /* * datalink subclass definitions. diff --git a/module/zfs/dsl_scan.c b/module/zfs/dsl_scan.c index 369ccd8a7..74cbce0d3 100644 --- a/module/zfs/dsl_scan.c +++ b/module/zfs/dsl_scan.c @@ -23,6 +23,7 @@ * Copyright (c) 2011, 2016 by Delphix. All rights reserved. * Copyright 2016 Gary Mills * Copyright (c) 2017 Datto Inc. + * Copyright 2017 Joyent, Inc. */ #include @@ -249,9 +250,10 @@ dsl_scan_setup_sync(void *arg, dmu_tx_t *tx) if (vdev_resilver_needed(spa->spa_root_vdev, &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 { - 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; @@ -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, complete ? scn->scn_phys.scn_max_txg : 0, B_TRUE); 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); } spa_errlog_rotate(spa); diff --git a/module/zfs/spa.c b/module/zfs/spa.c index d759ce718..52420194c 100644 --- a/module/zfs/spa.c +++ b/module/zfs/spa.c @@ -30,6 +30,7 @@ * Copyright 2016 Toomas Soome * Copyright (c) 2016 Actifio, Inc. All rights reserved. * Copyright (c) 2017 Datto Inc. + * Copyright 2017 Joyent, Inc. */ /* @@ -77,6 +78,8 @@ #include #ifdef _KERNEL +#include +#include #include #include #include @@ -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 */ }; +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_props(void *arg, dmu_tx_t *tx); static boolean_t spa_has_active_shared_spare(spa_t *spa); @@ -801,7 +807,7 @@ spa_change_guid(spa_t *spa) if (error == 0) { 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); @@ -1701,7 +1707,7 @@ spa_check_removed(vdev_t *vd) if (vd->vdev_ops->vdev_op_leaf && vdev_is_dead(vd) && !vd->vdev_ishole) { 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); 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"); @@ -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_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); 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_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); @@ -4390,7 +4396,7 @@ spa_export_common(char *pool, int new_state, nvlist_t **oldconfig, } 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) { spa_unload(spa); @@ -4546,7 +4552,7 @@ spa_vdev_add(spa_t *spa, nvlist_t *nvroot) mutex_enter(&spa_namespace_lock); 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); return (0); @@ -4727,7 +4733,7 @@ spa_vdev_attach(spa_t *spa, uint64_t guid, nvlist_t *nvroot, int replacing) if (newvd->vdev_isspare) { 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); @@ -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); 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 @@ -4963,7 +4969,7 @@ spa_vdev_detach(spa_t *spa, uint64_t guid, uint64_t pguid, int replace_done) vd->vdev_detached = B_TRUE; 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 */ spa_open_ref(spa, FTAG); @@ -5449,6 +5455,7 @@ int spa_vdev_remove(spa_t *spa, uint64_t guid, boolean_t unspare) { vdev_t *vd; + sysevent_t *ev = NULL; metaslab_group_t *mg; nvlist_t **spares, **l2cache, *nv; 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) 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, ZPOOL_CONFIG_SPARES, spares, nspares, nv); 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. */ 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, ZPOOL_CONFIG_L2CACHE, l2cache, nl2cache, nv); 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. */ - 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); } else if (vd != NULL) { @@ -5549,6 +5557,9 @@ spa_vdev_remove(spa_t *spa, uint64_t guid, boolean_t unspare) if (!locked) error = spa_vdev_exit(spa, NULL, txg, error); + if (ev) + spa_event_post(ev); + 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) 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 @@ -6944,6 +6955,33 @@ spa_has_active_shared_spare(spa_t *spa) 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 * 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. */ 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) diff --git a/module/zfs/spa_config.c b/module/zfs/spa_config.c index 0240da2b9..2715898cc 100644 --- a/module/zfs/spa_config.c +++ b/module/zfs/spa_config.c @@ -23,6 +23,7 @@ * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. * Copyright 2011 Nexenta Systems, Inc. All rights reserved. * Copyright (c) 2011, 2015 by Delphix. All rights reserved. + * Copyright 2017 Joyent, Inc. */ #include @@ -330,7 +331,7 @@ spa_config_sync(spa_t *target, boolean_t removing, boolean_t postsysevent) spa_config_generation++; if (postsysevent) - spa_event_notify(target, NULL, ESC_ZFS_CONFIG_SYNC); + spa_event_notify(target, NULL, NULL, ESC_ZFS_CONFIG_SYNC); } /* diff --git a/module/zfs/spa_history.c b/module/zfs/spa_history.c index 4ae74c284..6dfc927b2 100644 --- a/module/zfs/spa_history.c +++ b/module/zfs/spa_history.c @@ -22,6 +22,8 @@ /* * Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2011, 2015 by Delphix. All rights reserved. + * Copyright (c) 2014 Integros [integros.com] + * Copyright 2017 Joyent, Inc. */ #include @@ -191,6 +193,71 @@ spa_history_zone(void) #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. */ @@ -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_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)) { zfs_dbgmsg("ioctl %s", fnvlist_lookup_string(nvl, ZPOOL_HIST_IOCTL)); diff --git a/module/zfs/vdev.c b/module/zfs/vdev.c index 1bca227db..df07d893d 100644 --- a/module/zfs/vdev.c +++ b/module/zfs/vdev.c @@ -25,6 +25,7 @@ * Copyright 2017 Nexenta Systems, Inc. * Copyright (c) 2014 Integros [integros.com] * Copyright 2016 Toomas Soome + * Copyright 2017 Joyent, Inc. */ #include @@ -2657,7 +2658,7 @@ vdev_online(spa_t *spa, uint64_t guid, uint64_t flags, vdev_state_t *newstate) if (wasoffline || (oldstate < 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)); } @@ -2821,7 +2822,7 @@ vdev_clear(spa_t *spa, vdev_t *vd) if (vd->vdev_aux == NULL && !vdev_is_dead(vd)) 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); } /* diff --git a/module/zfs/zfs_fm.c b/module/zfs/zfs_fm.c index fedceee19..3986b3959 100644 --- a/module/zfs/zfs_fm.c +++ b/module/zfs/zfs_fm.c @@ -102,7 +102,7 @@ * ereport with information about the differences. */ #ifdef _KERNEL -static void +void zfs_zevent_post_cb(nvlist_t *nvl, nvlist_t *detector) { if (nvl) @@ -904,19 +904,25 @@ zfs_ereport_post_checksum(spa_t *spa, vdev_t *vd, #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 *resource = NULL; #ifdef _KERNEL - nvlist_t *resource; char class[64]; if (spa_load_state(spa) == SPA_LOAD_TRYIMPORT) - return; + return (NULL); if ((resource = fm_nvlist_create(NULL)) == NULL) - return; + return (NULL); (void) snprintf(class, sizeof (class), "%s.%s.%s", type, 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, FM_EREPORT_PAYLOAD_ZFS_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 } @@ -1025,23 +1045,10 @@ zfs_post_state_change(spa_t *spa, vdev_t *vd, uint64_t laststate) #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) EXPORT_SYMBOL(zfs_ereport_post); EXPORT_SYMBOL(zfs_ereport_post_checksum); EXPORT_SYMBOL(zfs_post_remove); EXPORT_SYMBOL(zfs_post_autoreplace); EXPORT_SYMBOL(zfs_post_state_change); -EXPORT_SYMBOL(zfs_post_sysevent); #endif /* _KERNEL */