On Fri, 31 Jul 2026 at 15:40, Alexey Charkov <[email protected]> wrote: > > Add a test that runs gpt_fill_header() and gpt_fill_pte() over a range of > block sizes and checks that the partition entry array is sized and placed > consistently, in particular that the backup array ends exactly where the > backup GPT header begins. > > Neither function performs any block I/O, so the test builds a synthetic > struct blk_desc rather than needing a block device with a configurable > block size. The expected array size is taken from the GPT header fields > rather than from GPT_ENTRY_NUMBERS, so the test still holds for builds > with a non-default CONFIG_EFI_PARTITION_ENTRIES_NUMBERS, such as > ARCH_SUNXI with 56 entries. > > Without the preceding fixes this fails on the first block size other than > 512: > > test/dm/part.c:313, dm_test_part_gpt_blksz(): > entry_lba + pte_blks == first_lba: Expected 0x12 (18), got 0x22 (34) > > Signed-off-by: Alexey Charkov <[email protected]> > ---
Acked-by: Ilias Apalodimas <[email protected]> > test/dm/part.c | 100 > +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ > 1 file changed, 100 insertions(+) > > diff --git a/test/dm/part.c b/test/dm/part.c > index ad37d7f406f4..4b48322fb807 100644 > --- a/test/dm/part.c > +++ b/test/dm/part.c > @@ -5,6 +5,8 @@ > > #include <dm.h> > #include <env.h> > +#include <malloc.h> > +#include <memalign.h> > #include <mmc.h> > #include <part.h> > #include <part_efi.h> > @@ -248,3 +250,101 @@ static int dm_test_part_get_info_by_uuid(struct > unit_test_state *uts) > return 0; > } > DM_TEST(dm_test_part_get_info_by_uuid, UTF_SCAN_PDATA | UTF_SCAN_FDT); > + > +/* > + * Check that the GPT layout adapts to the block size of the device. Neither > + * gpt_fill_header() nor gpt_fill_pte() does any block I/O, so a synthetic > + * descriptor is enough here; partition_entries_offset() reads the device > tree > + * '/config' node, which is available without scanning for devices. > + */ > +static int dm_test_part_gpt_blksz(struct unit_test_state *uts) > +{ > + static const struct { > + unsigned long blksz; > + lbaint_t lba; > + } cases[] = { > + { 512, 0x2000 }, /* 4MB, the traditional 34-block > layout */ > + { 1024, 0x1000 }, > + { 2048, 0x800 }, > + { 4096, 0x400 }, /* 4K native media, e.g. UFS */ > + { 8192, 0x200 }, > + { 16384, 0x100 }, /* the array fits in a single > block... */ > + { 32768, 0x40 }, /* ...on a device smaller than 34 > blocks */ > + }; > + > + char str_disk_guid[UUID_STR_LEN + 1] = > + "8d60b397-1bb6-4d33-80ee-b1587d24c2f8"; > + struct disk_partition part; > + struct blk_desc desc; > + gpt_header gpt_h; > + gpt_entry *gpt_e; > + int i; > + > + gpt_e = calloc(GPT_ENTRY_NUMBERS, sizeof(gpt_entry)); > + ut_assertnonnull(gpt_e); > + > + for (i = 0; i < ARRAY_SIZE(cases); i++) { > + u64 entry_lba, first_lba, last_lba; > + u32 pte_blks; > + > + memset(&desc, '\0', sizeof(desc)); > + memset(&gpt_h, '\0', sizeof(gpt_h)); > + desc.blksz = cases[i].blksz; > + desc.log2blksz = LOG2(desc.blksz); > + desc.lba = cases[i].lba; > + > + ut_assertok(gpt_fill_header(&desc, &gpt_h, str_disk_guid, 1)); > + > + /* > + * Size the array with BLOCK_CNT() rather than the > + * DIV_ROUND_UP() that gpt_pte_blocks() uses, so that this > + * checks the layout instead of restating the implementation. > + */ > + pte_blks = BLOCK_CNT(le32_to_cpu(gpt_h.num_partition_entries) > * > + > le32_to_cpu(gpt_h.sizeof_partition_entry), > + (&desc)); > + entry_lba = le64_to_cpu(gpt_h.partition_entry_lba); > + first_lba = le64_to_cpu(gpt_h.first_usable_lba); > + last_lba = le64_to_cpu(gpt_h.last_usable_lba); > + > + ut_asserteq_64(1, le64_to_cpu(gpt_h.my_lba)); > + ut_asserteq_64(desc.lba - 1, > le64_to_cpu(gpt_h.alternate_lba)); > + > + /* the primary array ends where the usable area begins */ > + ut_assert(entry_lba >= 2); > + ut_asserteq_64(entry_lba + pte_blks, first_lba); > + ut_assert(first_lba < last_lba); > + > + /* > + * write_gpt_table() puts the backup array at > + * last_usable_lba + 1, so it has to end exactly where the > + * backup header begins > + */ > + ut_asserteq_64(le64_to_cpu(gpt_h.alternate_lba), > + last_lba + 1 + pte_blks); > + > + /* a partition with no start and no size fills the disk */ > + memset(&part, '\0', sizeof(part)); > + disk_partition_set_uuid(&part, str_disk_guid); > + ut_assertok(gpt_fill_pte(&desc, &gpt_h, gpt_e, &part, 1)); > + ut_asserteq_64(first_lba, le64_to_cpu(gpt_e[0].starting_lba)); > + ut_asserteq_64(last_lba, le64_to_cpu(gpt_e[0].ending_lba)); > + > + /* a partition overlapping the entry array is rejected */ > + part.start = entry_lba; > + part.size = 1; > + ut_asserteq(-ENOSPC, > + gpt_fill_pte(&desc, &gpt_h, gpt_e, &part, 1)); > + > + /* so is one running past the end of the usable area */ > + part.start = first_lba; > + part.size = last_lba - first_lba + 2; > + ut_asserteq(-E2BIG, > + gpt_fill_pte(&desc, &gpt_h, gpt_e, &part, 1)); > + } > + > + free(gpt_e); > + > + return 0; > +} > +DM_TEST(dm_test_part_gpt_blksz, 0); > > -- > 2.54.0 >
