mirror of
https://git.proxmox.com/git/mirror_zfs.git
synced 2026-05-24 11:18:52 +03:00
ddt: add support for prefetching tables into the ARC
This change adds a new `zpool prefetch -t ddt $pool` command which causes a pool's DDT to be loaded into the ARC. The primary goal is to remove the need to "warm" a pool's cache before deduplication stops slowing write performance. It may also provide a way to reload portions of a DDT if they have been flushed due to inactivity. Sponsored-by: iXsystems, Inc. Sponsored-by: Catalogics, Inc. Sponsored-by: Klara, Inc. Reviewed-by: Alexander Motin <mav@FreeBSD.org> Reviewed-by: Tony Hutter <hutter2@llnl.gov> Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov> Signed-off-by: Allan Jude <allan@klarasystems.com> Signed-off-by: Will Andrews <will.andrews@klarasystems.com> Signed-off-by: Fred Weigel <fred.weigel@klarasystems.com> Signed-off-by: Rob Norris <rob.norris@klarasystems.com> Signed-off-by: Don Brady <don.brady@klarasystems.com> Co-authored-by: Will Andrews <will.andrews@klarasystems.com> Co-authored-by: Don Brady <don.brady@klarasystems.com> Closes #15890
This commit is contained in:
+89
-17
@@ -38,7 +38,7 @@
|
||||
* Copyright (c) 2017 Open-E, Inc. All Rights Reserved.
|
||||
* Copyright (c) 2019 Datto Inc.
|
||||
* Copyright (c) 2019, 2020 by Christian Schwarz. All rights reserved.
|
||||
* Copyright (c) 2019, 2021, 2024, Klara Inc.
|
||||
* Copyright (c) 2019, 2021, 2023, 2024, Klara Inc.
|
||||
* Copyright (c) 2019, Allan Jude
|
||||
* Copyright 2024 Oxide Computer Company
|
||||
*/
|
||||
@@ -3009,34 +3009,51 @@ zfs_ioc_pool_set_props(zfs_cmd_t *zc)
|
||||
return (error);
|
||||
}
|
||||
|
||||
static int
|
||||
zfs_ioc_pool_get_props(zfs_cmd_t *zc)
|
||||
{
|
||||
spa_t *spa;
|
||||
int error;
|
||||
nvlist_t *nvp = NULL;
|
||||
/*
|
||||
* innvl: {
|
||||
* "get_props_names": [ "prop1", "prop2", ..., "propN" ]
|
||||
* }
|
||||
*/
|
||||
|
||||
if ((error = spa_open(zc->zc_name, &spa, FTAG)) != 0) {
|
||||
static const zfs_ioc_key_t zfs_keys_get_props[] = {
|
||||
{ ZPOOL_GET_PROPS_NAMES, DATA_TYPE_STRING_ARRAY, ZK_OPTIONAL },
|
||||
};
|
||||
|
||||
static int
|
||||
zfs_ioc_pool_get_props(const char *pool, nvlist_t *innvl, nvlist_t *outnvl)
|
||||
{
|
||||
nvlist_t *nvp = outnvl;
|
||||
spa_t *spa;
|
||||
char **props = NULL;
|
||||
unsigned int n_props = 0;
|
||||
int error;
|
||||
|
||||
if (nvlist_lookup_string_array(innvl, ZPOOL_GET_PROPS_NAMES,
|
||||
&props, &n_props) != 0) {
|
||||
props = NULL;
|
||||
}
|
||||
|
||||
if ((error = spa_open(pool, &spa, FTAG)) != 0) {
|
||||
/*
|
||||
* If the pool is faulted, there may be properties we can still
|
||||
* get (such as altroot and cachefile), so attempt to get them
|
||||
* anyway.
|
||||
*/
|
||||
mutex_enter(&spa_namespace_lock);
|
||||
if ((spa = spa_lookup(zc->zc_name)) != NULL)
|
||||
if ((spa = spa_lookup(pool)) != NULL) {
|
||||
error = spa_prop_get(spa, &nvp);
|
||||
if (error == 0 && props != NULL)
|
||||
error = spa_prop_get_nvlist(spa, props, n_props,
|
||||
&nvp);
|
||||
}
|
||||
mutex_exit(&spa_namespace_lock);
|
||||
} else {
|
||||
error = spa_prop_get(spa, &nvp);
|
||||
if (error == 0 && props != NULL)
|
||||
error = spa_prop_get_nvlist(spa, props, n_props, &nvp);
|
||||
spa_close(spa, FTAG);
|
||||
}
|
||||
|
||||
if (error == 0 && zc->zc_nvlist_dst != 0)
|
||||
error = put_nvlist(zc, nvp);
|
||||
else
|
||||
error = SET_ERROR(EFAULT);
|
||||
|
||||
nvlist_free(nvp);
|
||||
return (error);
|
||||
}
|
||||
|
||||
@@ -4031,6 +4048,52 @@ zfs_ioc_pool_discard_checkpoint(const char *poolname, nvlist_t *innvl,
|
||||
return (spa_checkpoint_discard(poolname));
|
||||
}
|
||||
|
||||
/*
|
||||
* Loads specific types of data for the given pool
|
||||
*
|
||||
* innvl: {
|
||||
* "prefetch_type" -> int32_t
|
||||
* }
|
||||
*
|
||||
* outnvl: empty
|
||||
*/
|
||||
static const zfs_ioc_key_t zfs_keys_pool_prefetch[] = {
|
||||
{ZPOOL_PREFETCH_TYPE, DATA_TYPE_INT32, 0},
|
||||
};
|
||||
|
||||
static int
|
||||
zfs_ioc_pool_prefetch(const char *poolname, nvlist_t *innvl, nvlist_t *outnvl)
|
||||
{
|
||||
(void) outnvl;
|
||||
|
||||
int error;
|
||||
spa_t *spa;
|
||||
int32_t type;
|
||||
|
||||
/*
|
||||
* Currently, only ZPOOL_PREFETCH_DDT is supported
|
||||
*/
|
||||
if (nvlist_lookup_int32(innvl, ZPOOL_PREFETCH_TYPE, &type) != 0 ||
|
||||
type != ZPOOL_PREFETCH_DDT) {
|
||||
return (EINVAL);
|
||||
}
|
||||
|
||||
error = spa_open(poolname, &spa, FTAG);
|
||||
if (error != 0)
|
||||
return (error);
|
||||
|
||||
hrtime_t start_time = gethrtime();
|
||||
|
||||
ddt_prefetch_all(spa);
|
||||
|
||||
zfs_dbgmsg("pool '%s': loaded ddt into ARC in %llu ms", spa->spa_name,
|
||||
(u_longlong_t)NSEC2MSEC(gethrtime() - start_time));
|
||||
|
||||
spa_close(spa, FTAG);
|
||||
|
||||
return (error);
|
||||
}
|
||||
|
||||
/*
|
||||
* inputs:
|
||||
* zc_name name of dataset to destroy
|
||||
@@ -7283,6 +7346,12 @@ zfs_ioctl_init(void)
|
||||
zfs_keys_pool_discard_checkpoint,
|
||||
ARRAY_SIZE(zfs_keys_pool_discard_checkpoint));
|
||||
|
||||
zfs_ioctl_register("zpool_prefetch",
|
||||
ZFS_IOC_POOL_PREFETCH, zfs_ioc_pool_prefetch,
|
||||
zfs_secpolicy_config, POOL_NAME,
|
||||
POOL_CHECK_SUSPENDED, B_TRUE, B_TRUE,
|
||||
zfs_keys_pool_prefetch, ARRAY_SIZE(zfs_keys_pool_prefetch));
|
||||
|
||||
zfs_ioctl_register("initialize", ZFS_IOC_POOL_INITIALIZE,
|
||||
zfs_ioc_pool_initialize, zfs_secpolicy_config, POOL_NAME,
|
||||
POOL_CHECK_SUSPENDED | POOL_CHECK_READONLY, B_TRUE, B_TRUE,
|
||||
@@ -7328,6 +7397,11 @@ zfs_ioctl_init(void)
|
||||
POOL_CHECK_NONE, B_TRUE, B_TRUE,
|
||||
zfs_keys_pool_scrub, ARRAY_SIZE(zfs_keys_pool_scrub));
|
||||
|
||||
zfs_ioctl_register("get_props", ZFS_IOC_POOL_GET_PROPS,
|
||||
zfs_ioc_pool_get_props, zfs_secpolicy_read, POOL_NAME,
|
||||
POOL_CHECK_NONE, B_FALSE, B_FALSE,
|
||||
zfs_keys_get_props, ARRAY_SIZE(zfs_keys_get_props));
|
||||
|
||||
/* IOCTLS that use the legacy function signature */
|
||||
|
||||
zfs_ioctl_register_legacy(ZFS_IOC_POOL_FREEZE, zfs_ioc_pool_freeze,
|
||||
@@ -7383,8 +7457,6 @@ zfs_ioctl_init(void)
|
||||
|
||||
zfs_ioctl_register_pool(ZFS_IOC_POOL_STATS, zfs_ioc_pool_stats,
|
||||
zfs_secpolicy_read, B_FALSE, POOL_CHECK_NONE);
|
||||
zfs_ioctl_register_pool(ZFS_IOC_POOL_GET_PROPS, zfs_ioc_pool_get_props,
|
||||
zfs_secpolicy_read, B_FALSE, POOL_CHECK_NONE);
|
||||
|
||||
zfs_ioctl_register_pool(ZFS_IOC_ERROR_LOG, zfs_ioc_error_log,
|
||||
zfs_secpolicy_inject, B_FALSE, POOL_CHECK_SUSPENDED);
|
||||
|
||||
Reference in New Issue
Block a user