]> granicus.if.org Git - zfs/commitdiff
OpenZFS 6939 - add sysevents to zfs core for commands
authorDave Eddy <dave@daveeddy.com>
Tue, 30 May 2017 18:39:17 +0000 (11:39 -0700)
committerBrian Behlendorf <behlendorf1@llnl.gov>
Thu, 13 Jul 2017 04:28:13 +0000 (21:28 -0700)
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

include/sys/fm/util.h
include/sys/fs/zfs.h
include/sys/spa.h
include/sys/sysevent.h
include/sys/sysevent/eventdefs.h
module/zfs/dsl_scan.c
module/zfs/spa.c
module/zfs/spa_config.c
module/zfs/spa_history.c
module/zfs/vdev.c
module/zfs/zfs_fm.c

index 6ee31764bfac651e5c661a488bfb20b2906c11fe..ff54b05bb6afd0d61c18a741defb36bc24308e5f 100644 (file)
@@ -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 **);
index b634635c8df846a33baa3d0f6e7828e72f8c03e0..9fbcfbef3b259218a0465182bf63fc7c49d2ba82 100644 (file)
@@ -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
 }
index 33f3a78056d1f7839db8df39abf744ba88494ac1..dd86aad40fe7e2321fd0b738ca279bc13eb59a0b 100644 (file)
@@ -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 {                           \
index 2922e3072c7391d7068bba57cc1434c3dbdfd276..6510297d601fe1d0db7a7959b471db0d9a64bfbd 100644 (file)
 #ifndef _SYS_SYSEVENT_H
 #define        _SYS_SYSEVENT_H
 
+#include <sys/nvpair.h>
+
+typedef struct sysevent {
+       nvlist_t *resource;
+} sysevent_t;
+
 #endif
index eadaaef58b210480e1aa6003dd6480062ac61a37..fc2687842ccd6581baeb64eae7a95ff983857030 100644 (file)
@@ -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.
index 369ccd8a7f435af690de099c862ee9dde6309e2e..74cbce0d393e379d3a36a1390c49b67e6df00f60 100644 (file)
@@ -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 <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,
                    &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);
index d759ce718b43b8f5bac41be519219c86dcb3f56d..52420194c5368def95b739e431be5bb99f13ec3e 100644 (file)
@@ -30,6 +30,7 @@
  * Copyright 2016 Toomas Soome <tsoome@me.com>
  * Copyright (c) 2016 Actifio, Inc. All rights reserved.
  * Copyright (c) 2017 Datto Inc.
+ * Copyright 2017 Joyent, Inc.
  */
 
 /*
@@ -77,6 +78,8 @@
 #include <sys/zvol.h>
 
 #ifdef _KERNEL
+#include <sys/fm/protocol.h>
+#include <sys/fm/util.h>
 #include <sys/bootprops.h>
 #include <sys/callb.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 */
 };
 
+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)
index 0240da2b964386864804ebe7017ef91b6a3cb173..2715898cc09e7aac2659e3ce65bfd4fa4fd666f8 100644 (file)
@@ -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 <sys/spa.h>
@@ -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);
 }
 
 /*
index 4ae74c28401a7453fcb8209d8b16eaee5aff4ffe..6dfc927b285f88be5cd7e581f5a3e07b744e3038 100644 (file)
@@ -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 <sys/spa.h>
@@ -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));
index 1bca227dbb8ebbaae583c258d930eb6ce5cbaf20..df07d893dba2eee2d93331346862fa47cf8854e3 100644 (file)
@@ -25,6 +25,7 @@
  * Copyright 2017 Nexenta Systems, Inc.
  * Copyright (c) 2014 Integros [integros.com]
  * Copyright 2016 Toomas Soome <tsoome@me.com>
+ * Copyright 2017 Joyent, Inc.
  */
 
 #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 ||
            (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);
        }
 
        /*
index fedceee19af9ef4182e0220625f85acf55031f2f..3986b3959dea9221eb7680be04b6cdf255d6fa3b 100644 (file)
  * 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);
-               }
+       /* 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);
+#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 */