mirror of
https://git.proxmox.com/git/mirror_zfs.git
synced 2026-05-23 02:44:41 +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:
@@ -458,6 +458,7 @@ _LIBZFS_H nvlist_t *zpool_get_config(zpool_handle_t *, nvlist_t **);
|
||||
_LIBZFS_H nvlist_t *zpool_get_features(zpool_handle_t *);
|
||||
_LIBZFS_H int zpool_refresh_stats(zpool_handle_t *, boolean_t *);
|
||||
_LIBZFS_H int zpool_get_errlog(zpool_handle_t *, nvlist_t **);
|
||||
_LIBZFS_H void zpool_add_propname(zpool_handle_t *, const char *);
|
||||
|
||||
/*
|
||||
* Import and export functions
|
||||
@@ -504,6 +505,8 @@ _LIBZFS_H int zpool_checkpoint(zpool_handle_t *);
|
||||
_LIBZFS_H int zpool_discard_checkpoint(zpool_handle_t *);
|
||||
_LIBZFS_H boolean_t zpool_is_draid_spare(const char *);
|
||||
|
||||
_LIBZFS_H int zpool_prefetch(zpool_handle_t *, zpool_prefetch_type_t);
|
||||
|
||||
/*
|
||||
* Basic handle manipulations. These functions do not create or destroy the
|
||||
* underlying datasets, only the references to them.
|
||||
|
||||
@@ -148,6 +148,9 @@ _LIBZFS_CORE_H int lzc_pool_checkpoint_discard(const char *);
|
||||
_LIBZFS_CORE_H int lzc_wait(const char *, zpool_wait_activity_t, boolean_t *);
|
||||
_LIBZFS_CORE_H int lzc_wait_tag(const char *, zpool_wait_activity_t, uint64_t,
|
||||
boolean_t *);
|
||||
|
||||
_LIBZFS_CORE_H int lzc_pool_prefetch(const char *, zpool_prefetch_type_t);
|
||||
|
||||
_LIBZFS_CORE_H int lzc_wait_fs(const char *, zfs_wait_activity_t, boolean_t *);
|
||||
|
||||
_LIBZFS_CORE_H int lzc_set_bootenv(const char *, const nvlist_t *);
|
||||
|
||||
@@ -250,6 +250,16 @@ typedef struct arc_buf_info {
|
||||
enum zio_compress abi_l2arc_compress;
|
||||
} arc_buf_info_t;
|
||||
|
||||
/*
|
||||
* Flags returned by arc_cached; describes which part of the arc
|
||||
* the block is cached in.
|
||||
*/
|
||||
#define ARC_CACHED_EMBEDDED (1U << 0)
|
||||
#define ARC_CACHED_IN_L1 (1U << 1)
|
||||
#define ARC_CACHED_IN_MRU (1U << 2)
|
||||
#define ARC_CACHED_IN_MFU (1U << 3)
|
||||
#define ARC_CACHED_IN_L2 (1U << 4)
|
||||
|
||||
void arc_space_consume(uint64_t space, arc_space_type_t type);
|
||||
void arc_space_return(uint64_t space, arc_space_type_t type);
|
||||
boolean_t arc_is_metadata(arc_buf_t *buf);
|
||||
@@ -310,6 +320,7 @@ zio_t *arc_write(zio_t *pio, spa_t *spa, uint64_t txg, blkptr_t *bp,
|
||||
arc_prune_t *arc_add_prune_callback(arc_prune_func_t *func, void *priv);
|
||||
void arc_remove_prune_callback(arc_prune_t *p);
|
||||
void arc_freed(spa_t *spa, const blkptr_t *bp);
|
||||
int arc_cached(spa_t *spa, const blkptr_t *bp);
|
||||
|
||||
void arc_flush(spa_t *spa, boolean_t retry);
|
||||
void arc_tempreserve_clear(uint64_t reserve);
|
||||
|
||||
+3
-1
@@ -236,6 +236,7 @@ extern void ddt_get_dedup_stats(spa_t *spa, ddt_stat_t *dds_total);
|
||||
|
||||
extern uint64_t ddt_get_dedup_dspace(spa_t *spa);
|
||||
extern uint64_t ddt_get_pool_dedup_ratio(spa_t *spa);
|
||||
extern int ddt_get_pool_dedup_cached(spa_t *spa, uint64_t *psize);
|
||||
|
||||
extern ddt_t *ddt_select(spa_t *spa, const blkptr_t *bp);
|
||||
extern void ddt_enter(ddt_t *ddt);
|
||||
@@ -243,8 +244,9 @@ extern void ddt_exit(ddt_t *ddt);
|
||||
extern void ddt_init(void);
|
||||
extern void ddt_fini(void);
|
||||
extern ddt_entry_t *ddt_lookup(ddt_t *ddt, const blkptr_t *bp, boolean_t add);
|
||||
extern void ddt_prefetch(spa_t *spa, const blkptr_t *bp);
|
||||
extern void ddt_remove(ddt_t *ddt, ddt_entry_t *dde);
|
||||
extern void ddt_prefetch(spa_t *spa, const blkptr_t *bp);
|
||||
extern void ddt_prefetch_all(spa_t *spa);
|
||||
|
||||
extern boolean_t ddt_class_contains(spa_t *spa, ddt_class_t max_class,
|
||||
const blkptr_t *bp);
|
||||
|
||||
@@ -47,6 +47,7 @@ typedef struct {
|
||||
const ddt_key_t *ddk);
|
||||
void (*ddt_op_prefetch)(objset_t *os, uint64_t object,
|
||||
const ddt_key_t *ddk);
|
||||
void (*ddt_op_prefetch_all)(objset_t *os, uint64_t object);
|
||||
int (*ddt_op_update)(objset_t *os, uint64_t object,
|
||||
const ddt_key_t *ddk, const ddt_phys_t *phys, size_t psize,
|
||||
dmu_tx_t *tx);
|
||||
|
||||
@@ -505,6 +505,12 @@ void dmu_object_set_checksum(objset_t *os, uint64_t object, uint8_t checksum,
|
||||
void dmu_object_set_compress(objset_t *os, uint64_t object, uint8_t compress,
|
||||
dmu_tx_t *tx);
|
||||
|
||||
/*
|
||||
* Get an estimated cache size for an object. Caller must expect races.
|
||||
*/
|
||||
int dmu_object_cached_size(objset_t *os, uint64_t object,
|
||||
uint64_t *l1sz, uint64_t *l2sz);
|
||||
|
||||
void dmu_write_embedded(objset_t *os, uint64_t object, uint64_t offset,
|
||||
void *data, uint8_t etype, uint8_t comp, int uncompressed_size,
|
||||
int compressed_size, int byteorder, dmu_tx_t *tx);
|
||||
@@ -903,6 +909,8 @@ void dmu_prefetch(objset_t *os, uint64_t object, int64_t level, uint64_t offset,
|
||||
void dmu_prefetch_by_dnode(dnode_t *dn, int64_t level, uint64_t offset,
|
||||
uint64_t len, enum zio_priority pri);
|
||||
void dmu_prefetch_dnode(objset_t *os, uint64_t object, enum zio_priority pri);
|
||||
int dmu_prefetch_wait(objset_t *os, uint64_t object, uint64_t offset,
|
||||
uint64_t size);
|
||||
|
||||
typedef struct dmu_object_info {
|
||||
/* All sizes are in bytes unless otherwise indicated. */
|
||||
|
||||
@@ -260,6 +260,7 @@ typedef enum {
|
||||
ZPOOL_PROP_BCLONERATIO,
|
||||
ZPOOL_PROP_DEDUP_TABLE_SIZE,
|
||||
ZPOOL_PROP_DEDUP_TABLE_QUOTA,
|
||||
ZPOOL_PROP_DEDUPCACHED,
|
||||
ZPOOL_NUM_PROPS
|
||||
} zpool_prop_t;
|
||||
|
||||
@@ -1517,6 +1518,7 @@ typedef enum zfs_ioc {
|
||||
ZFS_IOC_VDEV_GET_PROPS, /* 0x5a55 */
|
||||
ZFS_IOC_VDEV_SET_PROPS, /* 0x5a56 */
|
||||
ZFS_IOC_POOL_SCRUB, /* 0x5a57 */
|
||||
ZFS_IOC_POOL_PREFETCH, /* 0x5a58 */
|
||||
|
||||
/*
|
||||
* Per-platform (Optional) - 8/128 numbers reserved.
|
||||
@@ -1648,6 +1650,11 @@ typedef enum {
|
||||
ZFS_WAIT_NUM_ACTIVITIES
|
||||
} zfs_wait_activity_t;
|
||||
|
||||
typedef enum {
|
||||
ZPOOL_PREFETCH_NONE = 0,
|
||||
ZPOOL_PREFETCH_DDT
|
||||
} zpool_prefetch_type_t;
|
||||
|
||||
/*
|
||||
* Bookmark name values.
|
||||
*/
|
||||
@@ -1686,6 +1693,17 @@ typedef enum {
|
||||
*/
|
||||
#define ZPOOL_HIDDEN_ARGS "hidden_args"
|
||||
|
||||
/*
|
||||
* The following is used when invoking ZFS_IOC_POOL_GET_PROPS.
|
||||
*/
|
||||
#define ZPOOL_GET_PROPS_NAMES "get_props_names"
|
||||
|
||||
/*
|
||||
* Opt-in property names used with ZPOOL_GET_PROPS_NAMES.
|
||||
* For example, properties that are hidden or expensive to compute.
|
||||
*/
|
||||
#define ZPOOL_DEDUPCACHED_PROP_NAME "dedupcached"
|
||||
|
||||
/*
|
||||
* The following are names used when invoking ZFS_IOC_POOL_INITIALIZE.
|
||||
*/
|
||||
@@ -1725,6 +1743,11 @@ typedef enum {
|
||||
#define ZFS_WAIT_ACTIVITY "wait_activity"
|
||||
#define ZFS_WAIT_WAITED "wait_waited"
|
||||
|
||||
/*
|
||||
* The following are names used when invoking ZFS_IOC_POOL_PREFETCH.
|
||||
*/
|
||||
#define ZPOOL_PREFETCH_TYPE "prefetch_type"
|
||||
|
||||
/*
|
||||
* Flags for ZFS_IOC_VDEV_SET_STATE
|
||||
*/
|
||||
|
||||
@@ -1198,6 +1198,8 @@ extern void spa_boot_init(void);
|
||||
/* properties */
|
||||
extern int spa_prop_set(spa_t *spa, nvlist_t *nvp);
|
||||
extern int spa_prop_get(spa_t *spa, nvlist_t **nvp);
|
||||
extern int spa_prop_get_nvlist(spa_t *spa, char **props,
|
||||
unsigned int n_props, nvlist_t **outnvl);
|
||||
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);
|
||||
|
||||
|
||||
@@ -225,6 +225,7 @@ int zap_lookup_uint64(objset_t *os, uint64_t zapobj, const uint64_t *key,
|
||||
int key_numints, uint64_t integer_size, uint64_t num_integers, void *buf);
|
||||
int zap_contains(objset_t *ds, uint64_t zapobj, const char *name);
|
||||
int zap_prefetch(objset_t *os, uint64_t zapobj, const char *name);
|
||||
int zap_prefetch_object(objset_t *os, uint64_t zapobj);
|
||||
int zap_prefetch_uint64(objset_t *os, uint64_t zapobj, const uint64_t *key,
|
||||
int key_numints);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user