diff --git a/include/sys/fs/zfs.h b/include/sys/fs/zfs.h index 9aea72f6f674..da9bb47c47dd 100644 --- a/include/sys/fs/zfs.h +++ b/include/sys/fs/zfs.h @@ -891,6 +891,22 @@ typedef enum vdev_state { VDEV_STATE_HEALTHY /* Presumed good */ } vdev_state_t; +/* + * zpool state str to int for IOCTL - ZPOOL_ZFS_GET_METRICS_DATA + */ +enum zpool_state_dmc { + UNKNOWN = 0, + UNAVAIL = 1, + ONLINE = 2, + OFFLINE = 3, + DEGRADED = 4, + FAULTED = 5, + REMOVED = 6, + SPLIT = 7, + TRANSITIONING = 8, + SUSPENDED = 9 +}; + #define VDEV_STATE_ONLINE VDEV_STATE_HEALTHY /* diff --git a/include/sys/zfs_ioctl.h b/include/sys/zfs_ioctl.h index 7b6f7f6def5b..1e0a1163322f 100644 --- a/include/sys/zfs_ioctl.h +++ b/include/sys/zfs_ioctl.h @@ -592,7 +592,7 @@ typedef struct { unsigned __int64 zpool_dedup_ratio; unsigned __int64 zfs_volSize; - char zpoolHealthState[MAXNAMELEN]; + int zpoolHealthState; char name[MAXNAMELEN]; }zpool_zfs_metrics; @@ -665,10 +665,11 @@ extern void zfs_unmount_snap(const char *); extern void zfs_destroy_unmount_origin(const char *); extern int getzfsvfs_impl(struct objset *, struct zfsvfs **); extern int getzfsvfs(const char *, struct zfsvfs **); -extern int getUsedData(char * name); -extern int getCompressRatio(char* name); -extern int getAvail(char* name); +extern uint64_t getUsedData(char * name); +extern uint64_t getCompressRatio(char* name); +extern uint64_t getAvail(char* name); extern uint64_t getZvolSize(char* name); +extern int spa_state_to_name_as_per_dmc(spa_t* spa); extern void latency_stats(uint64_t *histo, unsigned int buckets, stat_pair* lat); diff --git a/module/os/windows/zfs/zfs_ioctl_os.c b/module/os/windows/zfs/zfs_ioctl_os.c index 27ac94e3e047..d142e09c04f9 100644 --- a/module/os/windows/zfs/zfs_ioctl_os.c +++ b/module/os/windows/zfs/zfs_ioctl_os.c @@ -90,6 +90,7 @@ zfs_vfs_ref(zfsvfs_t **zfvp) NTSTATUS zpool_zfs_get_metrics(PDEVICE_OBJECT DeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp) { + Irp->IoStatus.Information = 0; if (IrpSp->Parameters.DeviceIoControl.OutputBufferLength < sizeof(zpool_zfs_metrics)) { Irp->IoStatus.Information = sizeof(zpool_zfs_metrics); return STATUS_BUFFER_TOO_SMALL; @@ -106,6 +107,13 @@ NTSTATUS zpool_zfs_get_metrics(PDEVICE_OBJECT DeviceObject, PIRP Irp, PIO_STACK_ is_zpool = 0; } + + perf->zpool_dedup_ratio = 0; + perf->zpoolHealthState = 0; + perf->zpool_allocated = 0; + perf->zpool_size = 0; + perf->zfs_volSize = 0; + perf->used = getUsedData(perf->name); perf->compress_ratio = getCompressRatio(perf->name); perf->available = getAvail(perf->name); @@ -122,13 +130,12 @@ NTSTATUS zpool_zfs_get_metrics(PDEVICE_OBJECT DeviceObject, PIRP Irp, PIO_STACK_ spa_config_enter(spa_perf, SCL_ALL, FTAG, RW_READER); vdev_get_stats_ex(spa_perf->spa_root_vdev, &vs, &vsx); perf->zpool_dedup_ratio = ddt_get_pool_dedup_ratio(spa_perf); - const char* healthState = spa_state_to_name(spa_perf); + perf->zpoolHealthState = spa_state_to_name_as_per_dmc(spa_perf); spa_config_exit(spa_perf, SCL_ALL, FTAG); mutex_exit(&spa_namespace_lock); perf->zpool_allocated = vs.vs_alloc; perf->zpool_size = vs.vs_space; - strcpy(perf->zpoolHealthState, healthState); } else diff --git a/module/zfs/spa_misc.c b/module/zfs/spa_misc.c index e4d8dc435666..b6bc432778a0 100644 --- a/module/zfs/spa_misc.c +++ b/module/zfs/spa_misc.c @@ -2744,6 +2744,54 @@ spa_state_to_name(spa_t *spa) return ("UNKNOWN"); } +/* + * Return the pool state int value as per enum zpool_state_dmc. + */ +int +spa_state_to_name_as_per_dmc(spa_t* spa) +{ + ASSERT3P(spa, != , NULL); + /* + * it is possible for the spa to exist, without root vdev + * as the spa transitions during import/export + */ + vdev_t* rvd = spa->spa_root_vdev; + if (rvd == NULL) { + return TRANSITIONING; + } + vdev_state_t state = rvd->vdev_state; + vdev_aux_t aux = rvd->vdev_stat.vs_aux; + + if (spa_suspended(spa) && + (spa_get_failmode(spa) != ZIO_FAILURE_MODE_CONTINUE)) + return SUSPENDED; + + switch (state) { + case VDEV_STATE_CLOSED: + case VDEV_STATE_OFFLINE: + return OFFLINE; + case VDEV_STATE_REMOVED: + return REMOVED; + case VDEV_STATE_CANT_OPEN: + if (aux == VDEV_AUX_CORRUPT_DATA || aux == VDEV_AUX_BAD_LOG) + return FAULTED; + else if (aux == VDEV_AUX_SPLIT_POOL) + return SPLIT; + else + return UNAVAIL; + case VDEV_STATE_FAULTED: + return FAULTED; + case VDEV_STATE_DEGRADED: + return DEGRADED; + case VDEV_STATE_HEALTHY: + return ONLINE; + default: + break; + } + + return UNKNOWN; +} + boolean_t spa_top_vdevs_spacemap_addressable(spa_t *spa) { diff --git a/module/zfs/zfs_ioctl.c b/module/zfs/zfs_ioctl.c index f7c3ee2d55e6..b1f8b4d2b3a7 100644 --- a/module/zfs/zfs_ioctl.c +++ b/module/zfs/zfs_ioctl.c @@ -2144,12 +2144,12 @@ zfs_ioc_objset_stats(zfs_cmd_t *zc) } -static int +static uint64_t getUsedData(char* name) { int error; objset_t* os; - uint64_t val; + uint64_t val = 0; error = dmu_objset_hold(name, FTAG, &os); if (error == 0) { dsl_dataset_t* ds = os->os_dsl_dataset; @@ -2159,12 +2159,12 @@ getUsedData(char* name) return val; } -static int +static uint64_t getCompressRatio(char* name) { int error; objset_t* os; - uint64_t val; + uint64_t val = 0; error = dmu_objset_hold(name, FTAG, &os); if (error == 0) { dsl_dataset_t* ds = os->os_dsl_dataset; @@ -2174,12 +2174,12 @@ getCompressRatio(char* name) return val; } -static int +static uint64_t getAvail(char* name) { int error; objset_t* os; - uint64_t val; + uint64_t val = 0; error = dmu_objset_hold(name, FTAG, &os); if (error == 0) { dsl_dataset_t* ds = os->os_dsl_dataset; @@ -2193,9 +2193,9 @@ static uint64_t getZvolSize(char* name) { int error; - uint64_t val; + uint64_t val = 0; objset_t* os; - uint64_t volSize; + uint64_t volSize = 0; error = dmu_objset_hold(name, FTAG, &os); if (error == 0) { zap_lookup(os, ZVOL_ZAP_OBJ, "size", 8, 1, &val); @@ -2205,7 +2205,6 @@ getZvolSize(char* name) return volSize; } - /* * inputs: * zc_name name of filesystem