2023-06-30 03:35:18 +00:00
|
|
|
/*
|
|
|
|
* CDDL HEADER START
|
|
|
|
*
|
|
|
|
* The contents of this file are subject to the terms of the
|
|
|
|
* Common Development and Distribution License (the "License").
|
|
|
|
* You may not use this file except in compliance with the License.
|
|
|
|
*
|
|
|
|
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
|
|
|
|
* or https://opensource.org/licenses/CDDL-1.0.
|
|
|
|
* See the License for the specific language governing permissions
|
|
|
|
* and limitations under the License.
|
|
|
|
*
|
|
|
|
* When distributing Covered Code, include this CDDL HEADER in each
|
|
|
|
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
|
|
|
|
* If applicable, add the following below this CDDL HEADER, with the
|
|
|
|
* fields enclosed by brackets "[]" replaced with your own identifying
|
|
|
|
* information: Portions Copyright [yyyy] [name of copyright owner]
|
|
|
|
*
|
|
|
|
* CDDL HEADER END
|
|
|
|
*/
|
|
|
|
/*
|
|
|
|
* Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
|
|
|
|
* Copyright (c) 2016 by Delphix. All rights reserved.
|
|
|
|
* Copyright (c) 2023, Klara Inc.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#ifndef _SYS_DDT_IMPL_H
|
|
|
|
#define _SYS_DDT_IMPL_H
|
|
|
|
|
|
|
|
#include <sys/ddt.h>
|
|
|
|
|
|
|
|
#ifdef __cplusplus
|
|
|
|
extern "C" {
|
|
|
|
#endif
|
|
|
|
|
ddt: add FDT feature and support for legacy and new on-disk formats
This is the supporting infrastructure for the upcoming dedup features.
Traditionally, dedup objects live directly in the MOS root. While their
details vary (checksum, type and class), they are all the same "kind" of
thing - a store of dedup entries.
The new features are more varied than that, and are better thought of as
a set of related stores for the overall state of a dedup table.
This adds a new feature flag, SPA_FEATURE_FAST_DEDUP. Enabling this will
cause new DDTs to be created as a ZAP in the MOS root, named
DDT-<checksum>. The is used as the root object for the normal type/class
store objects, but will also be a place for any storage required by new
features.
This commit adds two new fields to ddt_t, for version and flags. These
are intended to describe the structure and features of the overall dedup
table, and are stored as-is in the DDT root. In this commit, flags are
always zero, but the intent is that they can be used to hang optional
logic or state onto for new dedup features. Version is always 1.
For a "legacy" dedup table, where no DDT root directory exists, the
version will be 0.
ddt_configure() is expected to determine the version and flags features
currently in operation based on whether or not the fast_dedup feature is
enabled, and from what's available on disk. In this way, its possible to
support both old and new tables.
This also provides a migration path. A legacy setup can be upgraded to
FDT by creating the DDT root ZAP, moving the existing objects into it,
and setting version and flags appropriately. There's no support for that
here, but it would be straightforward to add later and allows the
possibility that newer features could be applied to existing dedup
tables.
Reviewed-by: Alexander Motin <mav@FreeBSD.org>
Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov>
Co-authored-by: Allan Jude <allan@klarasystems.com>
Signed-off-by: Rob Norris <rob.norris@klarasystems.com>
Sponsored-by: Klara, Inc.
Sponsored-by: iXsystems, Inc.
Closes #15892
2023-06-20 02:06:13 +00:00
|
|
|
/* DDT version numbers */
|
|
|
|
#define DDT_VERSION_LEGACY (0)
|
|
|
|
#define DDT_VERSION_FDT (1)
|
|
|
|
|
|
|
|
/* Names of interesting objects in the DDT root dir */
|
|
|
|
#define DDT_DIR_VERSION "version"
|
|
|
|
#define DDT_DIR_FLAGS "flags"
|
|
|
|
|
2023-07-03 12:16:04 +00:00
|
|
|
/* Fill a lightweight entry from a live entry. */
|
|
|
|
#define DDT_ENTRY_TO_LIGHTWEIGHT(ddt, dde, ddlwe) do { \
|
|
|
|
memset((ddlwe), 0, sizeof (*ddlwe)); \
|
|
|
|
(ddlwe)->ddlwe_key = (dde)->dde_key; \
|
|
|
|
(ddlwe)->ddlwe_type = (dde)->dde_type; \
|
|
|
|
(ddlwe)->ddlwe_class = (dde)->dde_class; \
|
|
|
|
(ddlwe)->ddlwe_nphys = DDT_NPHYS(ddt); \
|
|
|
|
for (int p = 0; p < (ddlwe)->ddlwe_nphys; p++) \
|
|
|
|
(ddlwe)->ddlwe_phys[p] = (dde)->dde_phys[p]; \
|
|
|
|
} while (0)
|
|
|
|
|
2023-06-30 03:35:18 +00:00
|
|
|
/*
|
|
|
|
* Ops vector to access a specific DDT object type.
|
|
|
|
*/
|
2023-07-03 02:43:37 +00:00
|
|
|
typedef struct {
|
2023-06-30 03:35:18 +00:00
|
|
|
char ddt_op_name[32];
|
|
|
|
int (*ddt_op_create)(objset_t *os, uint64_t *object, dmu_tx_t *tx,
|
|
|
|
boolean_t prehash);
|
|
|
|
int (*ddt_op_destroy)(objset_t *os, uint64_t object, dmu_tx_t *tx);
|
2023-07-03 13:28:46 +00:00
|
|
|
int (*ddt_op_lookup)(objset_t *os, uint64_t object,
|
|
|
|
const ddt_key_t *ddk, ddt_phys_t *phys, size_t psize);
|
|
|
|
int (*ddt_op_contains)(objset_t *os, uint64_t object,
|
|
|
|
const ddt_key_t *ddk);
|
2023-06-30 03:35:18 +00:00
|
|
|
void (*ddt_op_prefetch)(objset_t *os, uint64_t object,
|
2023-07-03 13:28:46 +00:00
|
|
|
const ddt_key_t *ddk);
|
2024-07-26 16:16:18 +00:00
|
|
|
void (*ddt_op_prefetch_all)(objset_t *os, uint64_t object);
|
2023-07-03 13:28:46 +00:00
|
|
|
int (*ddt_op_update)(objset_t *os, uint64_t object,
|
|
|
|
const ddt_key_t *ddk, const ddt_phys_t *phys, size_t psize,
|
2023-06-30 03:35:18 +00:00
|
|
|
dmu_tx_t *tx);
|
2023-07-03 13:28:46 +00:00
|
|
|
int (*ddt_op_remove)(objset_t *os, uint64_t object,
|
|
|
|
const ddt_key_t *ddk, dmu_tx_t *tx);
|
|
|
|
int (*ddt_op_walk)(objset_t *os, uint64_t object, uint64_t *walk,
|
|
|
|
ddt_key_t *ddk, ddt_phys_t *phys, size_t psize);
|
2023-06-30 03:35:18 +00:00
|
|
|
int (*ddt_op_count)(objset_t *os, uint64_t object, uint64_t *count);
|
|
|
|
} ddt_ops_t;
|
|
|
|
|
|
|
|
extern const ddt_ops_t ddt_zap_ops;
|
|
|
|
|
|
|
|
extern void ddt_stat_update(ddt_t *ddt, ddt_entry_t *dde, uint64_t neg);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* These are only exposed so that zdb can access them. Try not to use them
|
|
|
|
* outside of the DDT implementation proper, and if you do, consider moving
|
|
|
|
* them up.
|
|
|
|
*/
|
2024-02-19 10:19:32 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Enough room to expand DMU_POOL_DDT format for all possible DDT
|
|
|
|
* checksum/class/type combinations.
|
|
|
|
*/
|
|
|
|
#define DDT_NAMELEN 32
|
2023-06-30 03:35:18 +00:00
|
|
|
|
2023-07-03 05:16:02 +00:00
|
|
|
extern uint64_t ddt_phys_total_refcnt(const ddt_t *ddt, const ddt_entry_t *dde);
|
2023-06-30 03:35:18 +00:00
|
|
|
|
|
|
|
extern void ddt_key_fill(ddt_key_t *ddk, const blkptr_t *bp);
|
|
|
|
|
|
|
|
extern void ddt_stat_add(ddt_stat_t *dst, const ddt_stat_t *src, uint64_t neg);
|
|
|
|
|
2023-07-03 02:32:53 +00:00
|
|
|
extern void ddt_object_name(ddt_t *ddt, ddt_type_t type, ddt_class_t clazz,
|
|
|
|
char *name);
|
|
|
|
extern int ddt_object_walk(ddt_t *ddt, ddt_type_t type, ddt_class_t clazz,
|
2023-07-03 12:16:04 +00:00
|
|
|
uint64_t *walk, ddt_lightweight_entry_t *ddlwe);
|
2023-07-03 02:32:53 +00:00
|
|
|
extern int ddt_object_count(ddt_t *ddt, ddt_type_t type, ddt_class_t clazz,
|
|
|
|
uint64_t *count);
|
|
|
|
extern int ddt_object_info(ddt_t *ddt, ddt_type_t type, ddt_class_t clazz,
|
|
|
|
dmu_object_info_t *);
|
2023-06-30 03:35:18 +00:00
|
|
|
|
|
|
|
#ifdef __cplusplus
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#endif /* _SYS_DDT_H */
|