From c5f227a5f10399d7031b5c2c081c5ec662957cfd Mon Sep 17 00:00:00 2001 From: Jorgen Lundman Date: Wed, 20 May 2020 20:08:58 +0900 Subject: [PATCH] Upstream: Add snapshot and zvol events For kernel to send snapshot mount/unmount events to zed. For kernel to send symlink creates/removes on zvol plumbing. (/dev/run/dsk/zvol/$pool/$zvol -> /dev/diskX) If zed misses the ENODEV, all errors after are EINVAL. Treat any error as kernel module failure. Signed-off-by: Jorgen Lundman --- cmd/zed/agents/zfs_retire.c | 1 + cmd/zed/zed.c | 2 +- cmd/zed/zed_conf.c | 1 + cmd/zed/zed_exec.c | 2 ++ include/sys/fm/fs/zfs.h | 9 +++++++ include/sys/spa.h | 2 ++ include/sys/zio.h | 2 ++ module/zfs/zfs_fm.c | 52 +++++++++++++++++++++++++++++++++++++ 8 files changed, 70 insertions(+), 1 deletion(-) diff --git a/cmd/zed/agents/zfs_retire.c b/cmd/zed/agents/zfs_retire.c index 1563f5d2792c..6c009bdc1235 100644 --- a/cmd/zed/agents/zfs_retire.c +++ b/cmd/zed/agents/zfs_retire.c @@ -41,6 +41,7 @@ #include #include #include +#include #include "zfs_agents.h" #include "fmd_api.h" diff --git a/cmd/zed/zed.c b/cmd/zed/zed.c index 0aa03fded468..e45176c00bf2 100644 --- a/cmd/zed/zed.c +++ b/cmd/zed/zed.c @@ -291,7 +291,7 @@ main(int argc, char *argv[]) rv = zed_event_service(&zcp); /* ENODEV: When kernel module is unloaded (osx) */ - if (rv == ENODEV) + if (rv != 0) break; } diff --git a/cmd/zed/zed_conf.c b/cmd/zed/zed_conf.c index 2cf2311dbb42..59935102f123 100644 --- a/cmd/zed/zed_conf.c +++ b/cmd/zed/zed_conf.c @@ -22,6 +22,7 @@ #include #include #include +#include #include #include #include diff --git a/cmd/zed/zed_exec.c b/cmd/zed/zed_exec.c index 1eecfa0a92c4..03dcd03aceb7 100644 --- a/cmd/zed/zed_exec.c +++ b/cmd/zed/zed_exec.c @@ -26,6 +26,8 @@ #include #include #include +#include + #include "zed_exec.h" #include "zed_log.h" #include "zed_strings.h" diff --git a/include/sys/fm/fs/zfs.h b/include/sys/fm/fs/zfs.h index 6491606d328b..cd080c8ee667 100644 --- a/include/sys/fm/fs/zfs.h +++ b/include/sys/fm/fs/zfs.h @@ -110,6 +110,10 @@ extern "C" { #define FM_EREPORT_PAYLOAD_ZFS_BAD_CLEARED_BITS "bad_cleared_bits" #define FM_EREPORT_PAYLOAD_ZFS_BAD_SET_HISTOGRAM "bad_set_histogram" #define FM_EREPORT_PAYLOAD_ZFS_BAD_CLEARED_HISTOGRAM "bad_cleared_histogram" +#define FM_EREPORT_PAYLOAD_ZFS_SNAPSHOT_NAME "snapshot_name" +#define FM_EREPORT_PAYLOAD_ZFS_DEVICE_NAME "device_name" +#define FM_EREPORT_PAYLOAD_ZFS_RAW_DEVICE_NAME "raw_name" +#define FM_EREPORT_PAYLOAD_ZFS_VOLUME "volume" #define FM_EREPORT_FAILMODE_WAIT "wait" #define FM_EREPORT_FAILMODE_CONTINUE "continue" @@ -119,6 +123,11 @@ extern "C" { #define FM_RESOURCE_AUTOREPLACE "autoreplace" #define FM_RESOURCE_STATECHANGE "statechange" +#define FM_RESOURCE_ZFS_SNAPSHOT_MOUNT "snapshot_mount" +#define FM_RESOURCE_ZFS_SNAPSHOT_UNMOUNT "snapshot_unmount" +#define FM_RESOURCE_ZVOL_CREATE_SYMLINK "zvol_create" +#define FM_RESOURCE_ZVOL_REMOVE_SYMLINK "zvol_remove" + #ifdef __cplusplus } #endif diff --git a/include/sys/spa.h b/include/sys/spa.h index 08eba250d3a3..67724a68f0e8 100644 --- a/include/sys/spa.h +++ b/include/sys/spa.h @@ -1168,6 +1168,8 @@ 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, nvlist_t *hist_nvl, const char *name); +extern void zfs_ereport_zvol_post(const char *subclass, const char *name, + const char *device_name, const char *raw_name); /* waiting for pool activities to complete */ extern int spa_wait(const char *pool, zpool_wait_activity_t activity, diff --git a/include/sys/zio.h b/include/sys/zio.h index 2d34481f6be6..5b606eaf8d50 100644 --- a/include/sys/zio.h +++ b/include/sys/zio.h @@ -673,6 +673,8 @@ extern int zfs_ereport_post_checksum(spa_t *spa, vdev_t *vd, struct zio_bad_cksum *info); void zio_vsd_default_cksum_report(zio_t *zio, zio_cksum_report_t *zcr); +extern void zfs_ereport_snapshot_post(const char *subclass, spa_t *spa, + const char *name); /* Called from spa_sync(), but primarily an injection handler */ extern void spa_handle_ignored_writes(spa_t *spa); diff --git a/module/zfs/zfs_fm.c b/module/zfs/zfs_fm.c index 60e631567a89..007f31b4e7b3 100644 --- a/module/zfs/zfs_fm.c +++ b/module/zfs/zfs_fm.c @@ -1444,6 +1444,58 @@ zfs_ereport_fini(void) mutex_destroy(&recent_events_lock); } +void +zfs_ereport_snapshot_post(const char *subclass, spa_t *spa, const char *name) +{ + nvlist_t *aux; + + aux = fm_nvlist_create(NULL); + nvlist_add_string(aux, FM_EREPORT_PAYLOAD_ZFS_SNAPSHOT_NAME, name); + + zfs_post_common(spa, NULL, FM_RSRC_CLASS, subclass, aux); + fm_nvlist_destroy(aux, FM_NVA_FREE); +} + +/* + * Post when a event when a zvol is created or removed + * + * This is currently only used by macOS, since it uses the event to create + * symlinks between the volume name (mypool/myvol) and the actual /dev + * device (/dev/disk3). For example: + * + * /var/run/zfs/dsk/mypool/myvol -> /dev/disk3 + * + * name: The full name of the zvol ("mypool/myvol") + * dev_name: The full /dev name for the zvol ("/dev/disk3") + * raw_name: The raw /dev name for the zvol ("/dev/rdisk3") + */ +void +zfs_ereport_zvol_post(const char *subclass, const char *name, + const char *dev_name, const char *raw_name) +{ + nvlist_t *aux; + char *r; + + boolean_t locked = mutex_owned(&spa_namespace_lock); + if (!locked) mutex_enter(&spa_namespace_lock); + spa_t *spa = spa_lookup(name); + if (!locked) mutex_exit(&spa_namespace_lock); + + if (spa == NULL) + return; + + aux = fm_nvlist_create(NULL); + nvlist_add_string(aux, FM_EREPORT_PAYLOAD_ZFS_DEVICE_NAME, dev_name); + nvlist_add_string(aux, FM_EREPORT_PAYLOAD_ZFS_RAW_DEVICE_NAME, + raw_name); + r = strchr(name, '/'); + if (r && r[1]) + nvlist_add_string(aux, FM_EREPORT_PAYLOAD_ZFS_VOLUME, &r[1]); + + zfs_post_common(spa, NULL, FM_RSRC_CLASS, subclass, aux); + fm_nvlist_destroy(aux, FM_NVA_FREE); +} + EXPORT_SYMBOL(zfs_ereport_post); EXPORT_SYMBOL(zfs_ereport_is_valid); EXPORT_SYMBOL(zfs_ereport_post_checksum);