Implement dynamic gang header sizes

ZFS gang block headers are currently fixed at 512 bytes. This is
increasingly wasteful in the era of larger disk sector sizes. This PR
allows any size allocation to work as a gang header. It also contains
supporting changes to ZDB to make gang headers easier to work with.

Sponsored-by: Klara, Inc.
Sponsored-by: Wasabi Technology, Inc.
Reviewed-by: Alexander Motin <mav@FreeBSD.org>
Reviewed-by: Tony Hutter <hutter2@llnl.gov>
Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov>
Reviewed-by: Rob Norris <rob.norris@klarasystems.com>
Reviewed-by: Allan Jude <allan@klarasystems.com>
Signed-off-by: Paul Dagnelie <paul.dagnelie@klarasystems.com>
Closes #17004
This commit is contained in:
Paul Dagnelie
2025-01-23 16:26:09 -08:00
committed by Brian Behlendorf
parent e845be28e7
commit a981cb69e4
18 changed files with 387 additions and 72 deletions
+1 -1
View File
@@ -148,7 +148,7 @@ extern uint64_t vdev_psize_to_asize(vdev_t *vd, uint64_t psize);
static inline uint64_t
vdev_gang_header_asize(vdev_t *vd)
{
return (vdev_psize_to_asize_txg(vd, SPA_GANGBLOCKSIZE, 0));
return (vdev_psize_to_asize_txg(vd, SPA_OLD_GANGBLOCKSIZE, 0));
}
extern int vdev_fault(spa_t *spa, uint64_t guid, vdev_aux_t aux);
+31 -14
View File
@@ -59,21 +59,36 @@ typedef struct zio_eck {
/*
* Gang block headers are self-checksumming and contain an array
* of block pointers.
* of block pointers. The old gang block size has enough room for 3 blkptrs,
* while new gang blocks can store more.
*
* Layout:
* +--------+--------+--------+-----+---------+-----------+
* | | | | | | |
* | blkptr | blkptr | blkptr | ... | padding | zio_eck_t |
* | 1 | 2 | 3 | | | |
* +--------+--------+--------+-----+---------+-----------+
* 128B 128B 128B 88B 40B
*/
#define SPA_GANGBLOCKSIZE SPA_MINBLOCKSIZE
#define SPA_GBH_NBLKPTRS ((SPA_GANGBLOCKSIZE - \
sizeof (zio_eck_t)) / sizeof (blkptr_t))
#define SPA_GBH_FILLER ((SPA_GANGBLOCKSIZE - \
sizeof (zio_eck_t) - \
(SPA_GBH_NBLKPTRS * sizeof (blkptr_t))) /\
sizeof (uint64_t))
#define SPA_OLD_GANGBLOCKSIZE SPA_MINBLOCKSIZE
typedef void zio_gbh_phys_t;
typedef struct zio_gbh {
blkptr_t zg_blkptr[SPA_GBH_NBLKPTRS];
uint64_t zg_filler[SPA_GBH_FILLER];
zio_eck_t zg_tail;
} zio_gbh_phys_t;
static inline uint64_t
gbh_nblkptrs(uint64_t size) {
ASSERT(IS_P2ALIGNED(size, sizeof (blkptr_t)));
return ((size - sizeof (zio_eck_t)) / sizeof (blkptr_t));
}
static inline zio_eck_t *
gbh_eck(zio_gbh_phys_t *gbh, uint64_t size) {
ASSERT(IS_P2ALIGNED(size, sizeof (blkptr_t)));
return ((zio_eck_t *)((uintptr_t)gbh + size - sizeof (zio_eck_t)));
}
static inline blkptr_t *
gbh_bp(zio_gbh_phys_t *gbh, int bp) {
return (&((blkptr_t *)gbh)[bp]);
}
enum zio_checksum {
ZIO_CHECKSUM_INHERIT = 0,
@@ -398,7 +413,9 @@ typedef struct zio_vsd_ops {
typedef struct zio_gang_node {
zio_gbh_phys_t *gn_gbh;
struct zio_gang_node *gn_child[SPA_GBH_NBLKPTRS];
uint64_t gn_gangblocksize;
uint64_t gn_allocsize;
struct zio_gang_node *gn_child[];
} zio_gang_node_t;
typedef zio_t *zio_gang_issue_func_t(zio_t *zio, blkptr_t *bp,
+1
View File
@@ -87,6 +87,7 @@ typedef enum spa_feature {
SPA_FEATURE_FAST_DEDUP,
SPA_FEATURE_LONGNAME,
SPA_FEATURE_LARGE_MICROZAP,
SPA_FEATURE_DYNAMIC_GANG_HEADER,
SPA_FEATURES
} spa_feature_t;