Skip to content

Commit efbca44

Browse files
author
Paul Dagnelie
committed
mav feedback
Signed-off-by: Paul Dagnelie <[email protected]>
1 parent e35834b commit efbca44

File tree

8 files changed

+123
-83
lines changed

8 files changed

+123
-83
lines changed

cmd/zdb/zdb.c

Lines changed: 6 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -5563,37 +5563,21 @@ dump_label(const char *dev)
55635563
if (dump_opt['l'] > 2)
55645564
nvlist_print(stdout, toc);
55655565

5566-
uint32_t conf_size, toc_size, bootenv_size;
5567-
if (nvlist_lookup_uint32(toc, VDEV_TOC_TOC_SIZE,
5568-
&toc_size) != 0) {
5569-
if (!dump_opt['q'])
5570-
(void) printf("failed to read size of "
5571-
"TOC of label %d\n", l);
5572-
error = B_TRUE;
5573-
continue;
5574-
}
5575-
int err;
5576-
if ((err = nvlist_lookup_uint32(toc,
5577-
VDEV_TOC_BOOT_REGION, &bootenv_size)) != 0) {
5578-
if (!dump_opt['q'])
5579-
(void) printf("failed to read size of "
5580-
"bootenv of label %d %s\n", l,
5581-
strerror(err));
5582-
error = B_TRUE;
5583-
continue;
5584-
}
5585-
if (nvlist_lookup_uint32(toc, VDEV_TOC_VDEV_CONFIG,
5586-
&conf_size) != 0) {
5566+
uint32_t conf_size, conf_off;
5567+
if (!vdev_toc_get_secinfo(toc, VDEV_TOC_VDEV_CONFIG,
5568+
&conf_size, &conf_off)) {
55875569
if (!dump_opt['q'])
55885570
(void) printf("failed to read size of "
55895571
"vdev config of label %d\n", l);
55905572
error = B_TRUE;
5573+
fnvlist_free(toc);
55915574
continue;
55925575
}
5576+
fnvlist_free(toc);
55935577
buf = alloca(conf_size);
55945578
buflen = conf_size;
55955579
uint64_t phys_off = label->label_offset +
5596-
VDEV_LARGE_PAD_SIZE + toc_size + bootenv_size;
5580+
VDEV_LARGE_PAD_SIZE + conf_off;
55975581
if (pread64(fd, buf, conf_size, phys_off) !=
55985582
conf_size) {
55995583
if (!dump_opt['q'])

cmd/zhack.c

Lines changed: 21 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -960,25 +960,29 @@ zhack_repair_one_label_large(const zhack_repair_op_t op, const int fd,
960960
}
961961

962962
uint32_t bootenv_size, vc_size, sc_size;
963-
if ((err = nvlist_lookup_uint32(toc, VDEV_TOC_BOOT_REGION,
964-
&bootenv_size)) || (err = nvlist_lookup_uint32(toc,
965-
VDEV_TOC_VDEV_CONFIG, &vc_size)) || (err = nvlist_lookup_uint32(toc,
966-
VDEV_TOC_POOL_CONFIG, &sc_size))) {
963+
uint32_t bootenv_offset, vc_offset, sc_offset;
964+
if (!vdev_toc_get_secinfo(toc, VDEV_TOC_BOOT_REGION,
965+
&bootenv_size, &bootenv_offset) || !vdev_toc_get_secinfo(toc,
966+
VDEV_TOC_VDEV_CONFIG, &vc_size, &vc_offset) ||
967+
!vdev_toc_get_secinfo(toc, VDEV_TOC_POOL_CONFIG, &sc_size,
968+
&sc_offset)) {
969+
fnvlist_free(toc);
967970
(void) fprintf(stderr,
968971
"error: TOC missing core fields %d\n", l);
969972
goto out;
970973
}
974+
fnvlist_free(toc);
971975
bootenv = malloc(bootenv_size);
972976
zio_eck_t *bootenv_eck = (zio_eck_t *)(bootenv + bootenv_size) - 1;
973977
vdev_config = malloc(vc_size);
974978
zio_eck_t *vc_eck = (zio_eck_t *)(vdev_config + vc_size) - 1;
975979
spa_config = malloc(sc_size);
976980
zio_eck_t *sc_eck = (zio_eck_t *)(spa_config + sc_size) - 1;
977981

978-
uint64_t offset = label_offset + VDEV_TOC_SIZE;
982+
uint64_t base_offset = label_offset;
979983
if (bootenv_size != 0) {
980984
if ((err = zhack_repair_read(fd, bootenv,
981-
bootenv_size, offset, l)))
985+
bootenv_size, base_offset + bootenv_offset, l)))
982986
goto out;
983987
if (byteswap) {
984988
byteswap_uint64_array(&bootenv_eck->zec_cksum,
@@ -988,15 +992,15 @@ zhack_repair_one_label_large(const zhack_repair_op_t op, const int fd,
988992
}
989993
if ((op & ZHACK_REPAIR_OP_CKSUM) == 0 &&
990994
zhack_repair_test_cksum(byteswap, bootenv, bootenv_size,
991-
bootenv_eck, offset, l) != 0) {
995+
bootenv_eck, base_offset + bootenv_offset, l) != 0) {
992996
(void) fprintf(stderr, "It would appear checksums are "
993997
"corrupted. Try zhack repair label -c <device>\n");
994998
goto out;
995999
}
9961000
}
9971001

998-
offset += bootenv_size;
999-
if ((err = zhack_repair_read(fd, vdev_config, vc_size, offset, l)))
1002+
if ((err = zhack_repair_read(fd, vdev_config, vc_size,
1003+
base_offset + vc_offset, l)))
10001004
goto out;
10011005

10021006
if (byteswap) {
@@ -1006,13 +1010,13 @@ zhack_repair_one_label_large(const zhack_repair_op_t op, const int fd,
10061010
}
10071011
if ((op & ZHACK_REPAIR_OP_CKSUM) == 0 &&
10081012
zhack_repair_test_cksum(byteswap, vdev_config, vc_size,
1009-
vc_eck, offset, l) != 0) {
1013+
vc_eck, base_offset + vc_offset, l) != 0) {
10101014
(void) fprintf(stderr, "It would appear checksums are "
10111015
"corrupted. Try zhack repair label -c <device>\n");
10121016
goto out;
10131017
}
1014-
offset += vc_size;
1015-
if ((err = zhack_repair_read(fd, spa_config, sc_size, offset, l)))
1018+
if ((err = zhack_repair_read(fd, spa_config, sc_size,
1019+
base_offset + sc_offset, l)))
10161020
goto out;
10171021

10181022
if (byteswap) {
@@ -1022,7 +1026,7 @@ zhack_repair_one_label_large(const zhack_repair_op_t op, const int fd,
10221026
}
10231027
if ((op & ZHACK_REPAIR_OP_CKSUM) == 0 &&
10241028
zhack_repair_test_cksum(byteswap, spa_config, sc_size,
1025-
sc_eck, offset, l) != 0) {
1029+
sc_eck, base_offset + sc_offset, l) != 0) {
10261030
(void) fprintf(stderr, "It would appear checksums are "
10271031
"corrupted. Try zhack repair label -c <device>\n");
10281032
goto out;
@@ -1071,21 +1075,17 @@ zhack_repair_one_label_large(const zhack_repair_op_t op, const int fd,
10711075
label_offset, labels_repaired);
10721076
}
10731077

1074-
offset = label_offset;
10751078
if (zhack_repair_write_label(l, fd, byteswap, toc_data, toc_eck,
1076-
offset, VDEV_TOC_SIZE))
1079+
base_offset, VDEV_TOC_SIZE))
10771080
labels_repaired[l] |= REPAIR_LABEL_STATUS_CKSUM;
1078-
offset += VDEV_TOC_SIZE;
10791081
if (zhack_repair_write_label(l, fd, byteswap, bootenv, bootenv_eck,
1080-
offset, bootenv_size))
1082+
base_offset + bootenv_offset, bootenv_size))
10811083
labels_repaired[l] |= REPAIR_LABEL_STATUS_CKSUM;
1082-
offset += bootenv_size;
10831084
if (zhack_repair_write_label(l, fd, byteswap, vdev_config, vc_eck,
1084-
offset, vc_size))
1085+
base_offset + vc_offset, vc_size))
10851086
labels_repaired[l] |= REPAIR_LABEL_STATUS_CKSUM;
1086-
offset += vc_size;
10871087
if (zhack_repair_write_label(l, fd, byteswap, spa_config, sc_eck,
1088-
offset, sc_size))
1088+
base_offset + sc_offset, sc_size))
10891089
labels_repaired[l] |= REPAIR_LABEL_STATUS_CKSUM;
10901090

10911091
fsync(fd);

include/sys/vdev_impl.h

Lines changed: 45 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -575,9 +575,10 @@ typedef struct vdev_label {
575575
* config, etc). The sub-nvlist contains relevant information, mostly offset
576576
* and size.
577577
*
578-
* Each sub-section is protected with an embedded checksum. In the event that a
579-
* sub-section is larger than 16MiB, it will be split in 16MiB - sizeof
580-
* (zio_eck_t) chunks, which will each have their own checksum.
578+
* Currently, each sub-section is protected with an embedded checksum. In the
579+
* event that a sub-section is larger than 16MiB, it will be split in
580+
* 16MiB - sizeof (zio_eck_t) chunks, which will each have their own checksum.
581+
* Future sub-sections may have their own checksum mechanisms (or none at all).
581582
*/
582583
#define VDEV_LARGE_PAD_SIZE (1 << 24) // 16MiB
583584
#define VDEV_LARGE_DATA_SIZE ((1 << 27) - VDEV_LARGE_PAD_SIZE)
@@ -588,22 +589,57 @@ typedef struct vdev_label {
588589
#define VDEV_RESERVE_OFFSET (VDEV_LARGE_LABEL_SIZE * 2)
589590
#define VDEV_RESERVE_SIZE (1 << 29) // 512MiB
590591

591-
#define VDEV_TOC_SIZE (1 << 13)
592+
#define VDEV_TOC_SIZE (1 << 15)
593+
594+
/*
595+
* Each section in the label has its entry in the "sections" nvlist. This can
596+
* store any necessary data, but will usually contain at least these two
597+
* fields, representing the size and offset of the section.
598+
*/
599+
#define VDEV_SECTION_SIZE "section_size"
600+
#define VDEV_SECTION_OFFSET "section_offset"
592601

593602
/*
594603
* While the data part of the TOC is always VDEV_TOC_SIZE, the actual write
595604
* gets rounded up to the ashift. We don't know the ashift yet early in import,
596605
* when we need to read this info.
597606
*/
598607
#define VDEV_TOC_TOC_SIZE "toc_size"
599-
/* The size of the section that stores the boot region */
608+
#define VDEV_TOC_SECTIONS "sections"
609+
610+
/* The section that stores the boot region */
600611
#define VDEV_TOC_BOOT_REGION "boot_region"
601-
/* The size of the section that stores the vdev config */
612+
/* The section that stores the vdev config */
602613
#define VDEV_TOC_VDEV_CONFIG "vdev_config"
603-
/* The size of the section that stores the pool config */
614+
/* The section that stores the pool config */
604615
#define VDEV_TOC_POOL_CONFIG "pool_config"
605-
/* The size of the section that stores auxilliary uberblocks */
606-
#define VDEV_TOC_AUX_UBERBLOCK "aux_uberblock"
616+
617+
static inline boolean_t
618+
vdev_toc_get_secinfo(nvlist_t *toc, const char *section, uint32_t *size,
619+
uint32_t *offset)
620+
{
621+
nvlist_t *sections, *secinfo;
622+
if (nvlist_lookup_nvlist(toc, VDEV_TOC_SECTIONS, &sections) != 0)
623+
return (B_FALSE);
624+
if (nvlist_lookup_nvlist(sections, section, &secinfo) != 0)
625+
return (B_FALSE);
626+
if (nvlist_lookup_uint32(secinfo, VDEV_SECTION_SIZE, size) != 0)
627+
return (B_FALSE);
628+
if (nvlist_lookup_uint32(secinfo, VDEV_SECTION_OFFSET, offset) != 0)
629+
return (B_FALSE);
630+
return (B_TRUE);
631+
}
632+
633+
static inline void
634+
vdev_toc_add_secinfo(nvlist_t *sections, const char *section, uint32_t size,
635+
uint32_t offset)
636+
{
637+
nvlist_t *secinfo = fnvlist_alloc();
638+
fnvlist_add_uint32(secinfo, VDEV_SECTION_SIZE, size);
639+
fnvlist_add_uint32(secinfo, VDEV_SECTION_OFFSET, offset);
640+
fnvlist_add_nvlist(sections, section, secinfo);
641+
fnvlist_free(secinfo);
642+
}
607643

608644
/*
609645
* vdev_dirty() flags

lib/libzfs/libzfs.abi

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -639,7 +639,7 @@
639639
<elf-symbol name='fletcher_4_superscalar_ops' size='128' type='object-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
640640
<elf-symbol name='libzfs_config_ops' size='16' type='object-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
641641
<elf-symbol name='sa_protocol_names' size='16' type='object-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
642-
<elf-symbol name='spa_feature_table' size='2632' type='object-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
642+
<elf-symbol name='spa_feature_table' size='2688' type='object-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
643643
<elf-symbol name='zfeature_checks_disable' size='4' type='object-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
644644
<elf-symbol name='zfs_deleg_perm_tab' size='528' type='object-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
645645
<elf-symbol name='zfs_history_event_names' size='328' type='object-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
@@ -9616,8 +9616,8 @@
96169616
</function-decl>
96179617
</abi-instr>
96189618
<abi-instr address-size='64' path='module/zcommon/zfeature_common.c' language='LANG_C99'>
9619-
<array-type-def dimensions='1' type-id='83f29ca2' size-in-bits='21056' id='fd43354e'>
9620-
<subrange length='47' type-id='7359adad' id='8f8900fe'/>
9619+
<array-type-def dimensions='1' type-id='83f29ca2' size-in-bits='21504' id='bd288d11'>
9620+
<subrange length='48' type-id='7359adad' id='8f6d2a81'/>
96219621
</array-type-def>
96229622
<enum-decl name='zfeature_flags' id='6db816a4'>
96239623
<underlying-type type-id='9cac1fee'/>
@@ -9695,7 +9695,7 @@
96959695
<pointer-type-def type-id='611586a1' size-in-bits='64' id='2e243169'/>
96969696
<qualified-type-def type-id='eaa32e2f' const='yes' id='83be723c'/>
96979697
<pointer-type-def type-id='83be723c' size-in-bits='64' id='7acd98a2'/>
9698-
<var-decl name='spa_feature_table' type-id='fd43354e' mangled-name='spa_feature_table' visibility='default' elf-symbol-id='spa_feature_table'/>
9698+
<var-decl name='spa_feature_table' type-id='bd288d11' mangled-name='spa_feature_table' visibility='default' elf-symbol-id='spa_feature_table'/>
96999699
<var-decl name='zfeature_checks_disable' type-id='c19b74c3' mangled-name='zfeature_checks_disable' visibility='default' elf-symbol-id='zfeature_checks_disable'/>
97009700
<function-decl name='opendir' visibility='default' binding='global' size-in-bits='64'>
97019701
<parameter type-id='80f4b756'/>

module/zfs/vdev_label.c

Lines changed: 43 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -852,15 +852,12 @@ vdev_label_read_config(vdev_t *vd, uint64_t txg)
852852

853853
if (zio_wait(zio[l]) == 0 && nvlist_unpack(
854854
(char *)vp[l], VDEV_TOC_SIZE, &toc, 0) == 0) {
855-
uint32_t bootconf_size;
856-
if (nvlist_lookup_uint32(toc,
857-
VDEV_TOC_BOOT_REGION, &bootconf_size) != 0)
855+
uint32_t off;
856+
if (!vdev_toc_get_secinfo(toc,
857+
VDEV_TOC_VDEV_CONFIG,
858+
&vp_size[l], &off))
858859
continue;
859-
if (nvlist_lookup_uint32(toc,
860-
VDEV_TOC_VDEV_CONFIG, &vp_size[l]) != 0)
861-
continue;
862-
vp_off[l] = VDEV_LARGE_PAD_SIZE + toc_size +
863-
bootconf_size;
860+
vp_off[l] = VDEV_LARGE_PAD_SIZE + off;
864861
fnvlist_free(toc);
865862
}
866863
}
@@ -1321,9 +1318,14 @@ vdev_label_init(vdev_t *vd, uint64_t crtxg, vdev_labeltype_t reason)
13211318
NV_ENCODE_XDR, KM_SLEEP));
13221319
fnvlist_free(spa_config);
13231320
fnvlist_add_uint32(toc, VDEV_TOC_TOC_SIZE, writesize);
1324-
fnvlist_add_uint32(toc, VDEV_TOC_BOOT_REGION, 0);
1325-
fnvlist_add_uint32(toc, VDEV_TOC_VDEV_CONFIG, vp_size);
1326-
fnvlist_add_uint32(toc, VDEV_TOC_POOL_CONFIG, sc_buflen);
1321+
1322+
nvlist_t *sections = fnvlist_alloc();
1323+
vdev_toc_add_secinfo(sections, VDEV_TOC_VDEV_CONFIG, vp_size,
1324+
writesize);
1325+
vdev_toc_add_secinfo(sections, VDEV_TOC_POOL_CONFIG, sc_buflen,
1326+
writesize + vp_size);
1327+
fnvlist_add_nvlist(toc, VDEV_TOC_SECTIONS, sections);
1328+
fnvlist_free(sections);
13271329

13281330
if (ub_abd2 == NULL)
13291331
ub_abd2 = abd_alloc_linear(SPA_MAXBLOCKSIZE, B_TRUE);
@@ -1457,18 +1459,22 @@ vdev_label_read_bootenv_impl(zio_t *zio, vdev_t *vd, int flags)
14571459
continue;
14581460
}
14591461
nvlist_t *toc;
1460-
uint32_t bootenv_size;
14611462
if (!nvlist_unpack(abd_to_buf(toc_abds[l]), toc_size,
1462-
&toc, KM_SLEEP) || !nvlist_lookup_uint32(toc,
1463-
VDEV_TOC_BOOT_REGION, &bootenv_size)) {
1463+
&toc, KM_SLEEP)) {
14641464
abd_free(toc_abds[l]);
14651465
continue;
14661466
}
14671467
abd_free(toc_abds[l]);
1468+
uint32_t bootenv_size, bootenv_offset;
1469+
if (!vdev_toc_get_secinfo(toc, VDEV_TOC_BOOT_REGION,
1470+
&bootenv_size, &bootenv_offset)) {
1471+
fnvlist_free(toc);
1472+
continue;
1473+
}
14681474

14691475
vdev_label_read(zio, vd, l, B_FALSE,
14701476
abd_alloc_linear(bootenv_size, B_FALSE),
1471-
VDEV_LARGE_PAD_SIZE + toc_size, bootenv_size,
1477+
VDEV_LARGE_PAD_SIZE + bootenv_offset, bootenv_size,
14721478
vdev_label_read_bootenv_done, zio, flags);
14731479
}
14741480
} else {
@@ -1662,18 +1668,23 @@ vdev_label_write_bootenv(vdev_t *vd, nvlist_t *env)
16621668
continue;
16631669
}
16641670
nvlist_t *toc;
1665-
uint32_t bootenv_size;
1671+
uint32_t bootenv_size, bootenv_offset;
16661672
if (!(error = nvlist_unpack(abd_to_buf(toc_abds[l]),
1667-
toc_size, &toc, KM_SLEEP)) ||
1668-
(error = !nvlist_lookup_uint32(toc,
1669-
VDEV_TOC_BOOT_REGION, &bootenv_size))) {
1673+
toc_size, &toc, KM_SLEEP))) {
16701674
all_writeable = B_FALSE;
16711675
continue;
16721676
}
1677+
if (!vdev_toc_get_secinfo(toc, VDEV_TOC_BOOT_REGION,
1678+
&bootenv_size, &bootenv_offset)) {
1679+
fnvlist_free(toc);
1680+
all_writeable = B_FALSE;
1681+
continue;
1682+
}
1683+
fnvlist_free(toc);
16731684

16741685
if (new_abd_size == bootenv_size) {
16751686
vdev_label_write(zio, vd, l, B_TRUE, abd,
1676-
VDEV_LARGE_PAD_SIZE + toc_size,
1687+
VDEV_LARGE_PAD_SIZE + bootenv_offset,
16771688
new_abd_size, NULL, NULL, flags);
16781689
} else {
16791690
all_writeable = B_FALSE;
@@ -2170,9 +2181,18 @@ vdev_label_sync_large(vdev_t *vd, zio_t *zio, uint64_t *good_writes,
21702181
size_t writesize = P2ROUNDUP(toc_buflen, 1 << vd->vdev_ashift);
21712182
nvlist_t *toc = fnvlist_alloc();
21722183
fnvlist_add_uint32(toc, VDEV_TOC_TOC_SIZE, writesize);
2173-
fnvlist_add_uint32(toc, VDEV_TOC_BOOT_REGION, bootenv_size);
2174-
fnvlist_add_uint32(toc, VDEV_TOC_VDEV_CONFIG, vdev_config_size);
2175-
fnvlist_add_uint32(toc, VDEV_TOC_POOL_CONFIG, pool_config_size);
2184+
2185+
nvlist_t *sections = fnvlist_alloc();
2186+
if (bootenv_size != 0) {
2187+
vdev_toc_add_secinfo(sections, VDEV_TOC_BOOT_REGION,
2188+
bootenv_size, writesize);
2189+
}
2190+
vdev_toc_add_secinfo(sections, VDEV_TOC_VDEV_CONFIG, vdev_config_size,
2191+
writesize + bootenv_size);
2192+
vdev_toc_add_secinfo(sections, VDEV_TOC_POOL_CONFIG, pool_config_size,
2193+
writesize + bootenv_size + vdev_config_size);
2194+
fnvlist_add_nvlist(toc, VDEV_TOC_SECTIONS, sections);
2195+
fnvlist_free(sections);
21762196

21772197
ASSERT3U(fnvlist_size(toc) + sizeof (zio_eck_t), <=, VDEV_TOC_SIZE);
21782198

tests/zfs-tests/tests/functional/large_label/large_label_001_pos.ksh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ log_assert "Verify that new label works for basic pool operation"
4242
log_onexit cleanup
4343

4444
mntpnt="$TESTDIR1"
45-
log_must truncate --size=2T $mntpnt/dsk0
45+
log_must truncate -s 2T $mntpnt/dsk0
4646

4747
DSK="$mntpnt/dsk"
4848

tests/zfs-tests/tests/functional/large_label/large_label_002_pos.ksh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ log_assert "Verify that new label works for more advanced pool operations"
4343
log_onexit cleanup
4444

4545
mntpnt="$TESTDIR1"
46-
log_must truncate --size=2T $mntpnt/dsk{0,1,2,3,4,5,6,7}
46+
log_must truncate -s 2T $mntpnt/dsk{0,1,2,3,4,5,6,7}
4747

4848
DSK="$mntpnt/dsk"
4949

0 commit comments

Comments
 (0)