Index: head/sys/boot/zfs/zfsimpl.c =================================================================== --- head/sys/boot/zfs/zfsimpl.c +++ head/sys/boot/zfs/zfsimpl.c @@ -60,6 +60,7 @@ "org.open-zfs:large_blocks", "org.illumos:sha512", "org.illumos:skein", + "org.zfsonlinux:large_dnode", NULL }; @@ -420,7 +421,7 @@ psize = size; } - /*printf("ZFS: reading %d bytes at 0x%jx to %p\n", psize, (uintmax_t)offset, buf);*/ + /*printf("ZFS: reading %zu bytes at 0x%jx to %p\n", psize, (uintmax_t)offset, buf);*/ rc = vdev->v_phys_read(vdev, vdev->v_read_priv, offset, buf, psize); if (rc) return (rc); @@ -2280,7 +2281,7 @@ sahdrp = (sa_hdr_phys_t *)DN_BONUS(dn); else { if ((dn->dn_flags & DNODE_FLAG_SPILL_BLKPTR) != 0) { - blkptr_t *bp = &dn->dn_spill; + blkptr_t *bp = DN_SPILL_BLKPTR(dn); int error; size = BP_GET_LSIZE(bp); @@ -2330,7 +2331,7 @@ if ((dn->dn_flags & DNODE_FLAG_SPILL_BLKPTR) == 0) return (EIO); - bp = &dn->dn_spill; + bp = DN_SPILL_BLKPTR(dn); size = BP_GET_LSIZE(bp); buf = zfs_alloc(size); Index: head/sys/cddl/boot/zfs/zfsimpl.h =================================================================== --- head/sys/cddl/boot/zfs/zfsimpl.h +++ head/sys/cddl/boot/zfs/zfsimpl.h @@ -859,10 +859,19 @@ /* * Derived constants. */ -#define DNODE_SIZE (1 << DNODE_SHIFT) -#define DN_MAX_NBLKPTR ((DNODE_SIZE - DNODE_CORE_SIZE) >> SPA_BLKPTRSHIFT) -#define DN_MAX_BONUSLEN (DNODE_SIZE - DNODE_CORE_SIZE - (1 << SPA_BLKPTRSHIFT)) -#define DN_MAX_OBJECT (1ULL << DN_MAX_OBJECT_SHIFT) +#define DNODE_MIN_SIZE (1 << DNODE_SHIFT) +#define DNODE_MAX_SIZE (1 << DNODE_BLOCK_SHIFT) +#define DNODE_BLOCK_SIZE (1 << DNODE_BLOCK_SHIFT) +#define DNODE_MIN_SLOTS (DNODE_MIN_SIZE >> DNODE_SHIFT) +#define DNODE_MAX_SLOTS (DNODE_MAX_SIZE >> DNODE_SHIFT) +#define DN_BONUS_SIZE(dnsize) ((dnsize) - DNODE_CORE_SIZE - \ + (1 << SPA_BLKPTRSHIFT)) +#define DN_SLOTS_TO_BONUSLEN(slots) DN_BONUS_SIZE((slots) << DNODE_SHIFT) +#define DN_OLD_MAX_BONUSLEN (DN_BONUS_SIZE(DNODE_MIN_SIZE)) +#define DN_MAX_NBLKPTR ((DNODE_MIN_SIZE - DNODE_CORE_SIZE) >> \ + SPA_BLKPTRSHIFT) +#define DN_MAX_OBJECT (1ULL << DN_MAX_OBJECT_SHIFT) +#define DN_ZERO_BONUSLEN (DN_BONUS_SIZE(DNODE_MAX_SIZE) + 1) #define DNODES_PER_BLOCK_SHIFT (DNODE_BLOCK_SHIFT - DNODE_SHIFT) #define DNODES_PER_BLOCK (1ULL << DNODES_PER_BLOCK_SHIFT) @@ -898,7 +907,8 @@ uint8_t dn_flags; /* DNODE_FLAG_* */ uint16_t dn_datablkszsec; /* data block size in 512b sectors */ uint16_t dn_bonuslen; /* length of dn_bonus */ - uint8_t dn_pad2[4]; + uint8_t dn_extra_slots; /* # of subsequent slots consumed */ + uint8_t dn_pad2[3]; /* accounting is protected by dn_dirty_mtx */ uint64_t dn_maxblkid; /* largest allocated block ID */ @@ -906,10 +916,39 @@ uint64_t dn_pad3[4]; - blkptr_t dn_blkptr[1]; - uint8_t dn_bonus[DN_MAX_BONUSLEN - sizeof (blkptr_t)]; - blkptr_t dn_spill; + /* + * The tail region is 448 bytes for a 512 byte dnode, and + * correspondingly larger for larger dnode sizes. The spill + * block pointer, when present, is always at the end of the tail + * region. There are three ways this space may be used, using + * a 512 byte dnode for this diagram: + * + * 0 64 128 192 256 320 384 448 (offset) + * +---------------+---------------+---------------+-------+ + * | dn_blkptr[0] | dn_blkptr[1] | dn_blkptr[2] | / | + * +---------------+---------------+---------------+-------+ + * | dn_blkptr[0] | dn_bonus[0..319] | + * +---------------+-----------------------+---------------+ + * | dn_blkptr[0] | dn_bonus[0..191] | dn_spill | + * +---------------+-----------------------+---------------+ + */ + union { + blkptr_t dn_blkptr[1+DN_OLD_MAX_BONUSLEN/sizeof (blkptr_t)]; + struct { + blkptr_t __dn_ignore1; + uint8_t dn_bonus[DN_OLD_MAX_BONUSLEN]; + }; + struct { + blkptr_t __dn_ignore2; + uint8_t __dn_ignore3[DN_OLD_MAX_BONUSLEN - + sizeof (blkptr_t)]; + blkptr_t dn_spill; + }; + }; } dnode_phys_t; + +#define DN_SPILL_BLKPTR(dnp) (blkptr_t *)((char *)(dnp) + \ + (((dnp)->dn_extra_slots + 1) << DNODE_SHIFT) - (1 << SPA_BLKPTRSHIFT)) typedef enum dmu_object_byteswap { DMU_BSWAP_UINT8,