diff --git a/module/os/windows/zfs/zfs_ioctl_os.c b/module/os/windows/zfs/zfs_ioctl_os.c index 880686b1c051..64f465b8b5d1 100644 --- a/module/os/windows/zfs/zfs_ioctl_os.c +++ b/module/os/windows/zfs/zfs_ioctl_os.c @@ -90,6 +90,31 @@ zfs_vfs_ref(zfsvfs_t **zfvp) return (error); } +/* + * Returns the actual usable pool size adjusting the slop space which + * is same as reported by "zfs list" cmd. + * + * See the comment above spa_get_slop_space() for more details. + */ +static uint64_t +spa_get_usable_dspace(spa_t *spa) +{ + uint64_t poolsize = 0; + + if (spa != NULL) { + uint64_t space = metaslab_class_get_dspace(spa_normal_class(spa)); + uint64_t resv = spa_get_slop_space(spa); + + poolsize = (space >= resv) ? (space - resv) : 0; + + TraceEvent(TRACE_VERBOSE, + "%s:%d: total_dspace: %llu, slop_space: %llu, poolsize: %llu, spa_dedup_dspace: %llu\n", + __func__, __LINE__, space, resv, poolsize, spa->spa_dedup_dspace); + } + + return (poolsize); +} + extern kstat_t* perf_arc_ksp; extern uint64_t getL2ArcAllocSize(arc_stats_t* arc_ptr); NTSTATUS zpool_zfs_get_metrics(PDEVICE_OBJECT DeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp) @@ -150,13 +175,17 @@ NTSTATUS zpool_zfs_get_metrics(PDEVICE_OBJECT DeviceObject, PIRP Irp, PIO_STACK_ vdev_get_stats(spa_perf->spa_root_vdev, &vs); perf->zpool_dedup_ratio = ddt_get_pool_dedup_ratio(spa_perf); const char* healthState = spa_state_to_name(spa_perf); + + // SSV-22900: get the actual usable spa pool size. + uint64_t pool_size = spa_get_usable_dspace(spa_perf); + uint64_t pool_alloc = (pool_size >= perf->available) ? (pool_size - perf->available) : 0; + 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; + perf->zpool_allocated = pool_alloc; + perf->zpool_size = pool_size; strcpy(perf->zpoolHealthState, healthState); - } else perf->zfs_volSize = getZvolSize(perf->name); diff --git a/module/zfs/ddt.c b/module/zfs/ddt.c index 7b0b1d896761..479e5a3ad625 100644 --- a/module/zfs/ddt.c +++ b/module/zfs/ddt.c @@ -503,7 +503,7 @@ ddt_get_dedup_histogram(spa_t *spa, ddt_histogram_t *ddh) { for (enum zio_checksum c = 0; c < ZIO_CHECKSUM_FUNCTIONS; c++) { ddt_t *ddt = spa->spa_ddt[c]; - for (enum ddt_type type = 0; type < DDT_TYPES; type++) { + for (enum ddt_type type = 0; type < DDT_TYPES && ddt; type++) { for (enum ddt_class class = 0; class < DDT_CLASSES; class++) { ddt_histogram_add(ddh, diff --git a/module/zfs/spa_misc.c b/module/zfs/spa_misc.c index 3ef05aa73db0..e6b8cc4b3d4b 100644 --- a/module/zfs/spa_misc.c +++ b/module/zfs/spa_misc.c @@ -1802,8 +1802,22 @@ spa_get_worst_case_asize(spa_t *spa, uint64_t lsize) uint64_t spa_get_slop_space(spa_t *spa) { - uint64_t space = spa_get_dspace(spa); - uint64_t slop = MIN(space >> spa_slop_shift, spa_max_slop); + uint64_t space = 0; + uint64_t slop = 0; + + /* + * Make sure spa_dedup_dspace has been set. + */ + if (spa->spa_dedup_dspace == ~0ULL) + spa_update_dspace(spa); + + /* + * spa_get_dspace() includes the space only logically "used" by + * deduplicated data, so since it's not useful to reserve more + * space with more deduplicated data, we subtract that out here. + */ + space = spa_get_dspace(spa) - spa->spa_dedup_dspace; + slop = MIN(space >> spa_slop_shift, spa_max_slop); /* * Subtract the embedded log space, but no more than half the (3.2%)