From 57fd506c57ccc5f3d6580bbd2a9f7a1bd879ceb4 Mon Sep 17 00:00:00 2001 From: Mike Gerdts Date: Mon, 27 Mar 2023 12:24:05 -0500 Subject: [PATCH] bdev_gpt: use unique partition GUID as bdev UUID In releases of SPDK prior to v23.01, GPT bdevs had a random UUID. This ended with commit a1c7ae2d3f4ebf5037ecb4295731d715a50146a0, which is OK because a non-persistent UUID is not all that useful. Per Table 5.6 in Section 5.3.3 of UEFI Spec 2.3, each partition has a 16-byte UniquePartitionGUID: GUID that is unique for every partition entry. Every partition ever created will have a unique GUID. This GUID must be assigned when the GPT Partition Entry is created. The GPT Partition Entry is created whenever the NumberOfPartitionEntries in the GPT Header is increased to include a larger range of addresses. With this change, GPT bdevs use this unique partition GUID as the bdev's UUID. Signed-off-by: Mike Gerdts Change-Id: Id8e8aa9e7903d31f199e8cfdb487e45ce1524d7b Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/17351 Tested-by: SPDK CI Jenkins Reviewed-by: Ben Walker Reviewed-by: Jim Harris Community-CI: Mellanox Build Bot --- CHANGELOG.md | 4 ++++ module/bdev/gpt/vbdev_gpt.c | 30 ++++++++++++++++++++++++++++-- test/bdev/blockdev.sh | 36 ++++++++++++++++++++++++++++++++++-- 3 files changed, 66 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index bb9e045bb..00687802d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,6 +17,10 @@ multiple readers. New function `spdk_env_get_main_core` was added. +### gpt + +GPT bdevs now use the GPT Unique Partition ID as the bdev's UUID. + ### lvol New API `spdk_lvol_iter_immediate_clones` was added to iterate the clones of an lvol. diff --git a/module/bdev/gpt/vbdev_gpt.c b/module/bdev/gpt/vbdev_gpt.c index 785efedaa..fa364844e 100644 --- a/module/bdev/gpt/vbdev_gpt.c +++ b/module/bdev/gpt/vbdev_gpt.c @@ -219,6 +219,29 @@ vbdev_gpt_submit_request(struct spdk_io_channel *_ch, struct spdk_bdev_io *bdev_ } } +static void +gpt_guid_to_uuid(const struct spdk_gpt_guid *guid, struct spdk_uuid *uuid) +{ +#pragma pack(push, 1) + struct tmp_uuid { + uint32_t b0; + uint16_t b4; + uint16_t b6; + uint16_t b8; + uint16_t b10; + uint32_t b12; + } *ret = (struct tmp_uuid *)uuid; +#pragma pack(pop) + SPDK_STATIC_ASSERT(sizeof(*ret) == sizeof(*uuid), "wrong size"); + + ret->b0 = from_be32(&guid->raw[0]); + ret->b4 = from_be16(&guid->raw[4]); + ret->b6 = from_be16(&guid->raw[6]); + ret->b8 = from_le16(&guid->raw[8]); + ret->b10 = from_le16(&guid->raw[10]); + ret->b12 = from_le32(&guid->raw[12]); +} + static void write_guid(struct spdk_json_write_ctx *w, const struct spdk_gpt_guid *guid) { @@ -315,6 +338,7 @@ vbdev_gpt_create_bdevs(struct gpt_base *gpt_base) uint64_t lba_start = from_le64(&p->starting_lba); uint64_t lba_end = from_le64(&p->ending_lba); uint64_t partition_size = lba_end - lba_start + 1; + struct spdk_bdev_part_construct_opts opts; if (lba_start == 0) { continue; @@ -353,8 +377,10 @@ vbdev_gpt_create_bdevs(struct gpt_base *gpt_base) return -1; } - rc = spdk_bdev_part_construct(&d->part, gpt_base->part_base, name, - lba_start, partition_size, "GPT Disk"); + spdk_bdev_part_construct_opts_init(&opts, sizeof(opts)); + gpt_guid_to_uuid(&p->unique_partition_guid, &opts.uuid); + rc = spdk_bdev_part_construct_ext(&d->part, gpt_base->part_base, name, lba_start, + partition_size, "GPT Disk", &opts); free(name); if (rc) { SPDK_ERRLOG("could not construct bdev part\n"); diff --git a/test/bdev/blockdev.sh b/test/bdev/blockdev.sh index 25ff4d764..25ac403b5 100755 --- a/test/bdev/blockdev.sh +++ b/test/bdev/blockdev.sh @@ -117,13 +117,20 @@ function setup_gpt_conf() { fi done if [[ -n $gpt_nvme ]]; then + # These Unique Partition GUIDs were randomly generated for testing and are distinct + # from the Partition Type GUIDs (SPDK_GPT_OLD_GUID and SPDK_GPT_GUID) which have + # special meaning to SPDK. See section 5.3.3 of UEFI Spec 2.3 for the distinction + # between Unique Partition GUID and Partition Type GUID. + typeset -g g_unique_partguid=6f89f330-603b-4116-ac73-2ca8eae53030 + typeset -g g_unique_partguid_old=abf1734f-66e5-4c0f-aa29-4021d4d307df + # Create gpt partition table parted -s "$gpt_nvme" mklabel gpt mkpart SPDK_TEST_first '0%' '50%' mkpart SPDK_TEST_second '50%' '100%' # Change the partition type GUIDs to SPDK partition type values SPDK_GPT_OLD_GUID=$(get_spdk_gpt_old) SPDK_GPT_GUID=$(get_spdk_gpt) - sgdisk -t "1:$SPDK_GPT_GUID" "$gpt_nvme" - sgdisk -t "2:$SPDK_GPT_OLD_GUID" "$gpt_nvme" + sgdisk -t "1:$SPDK_GPT_GUID" -u "1:$g_unique_partguid" "$gpt_nvme" + sgdisk -t "2:$SPDK_GPT_OLD_GUID" -u "2:$g_unique_partguid_old" "$gpt_nvme" "$rootdir/scripts/setup.sh" "$rpc_py" bdev_get_bdevs setup_nvme_conf @@ -609,6 +616,27 @@ function stat_test_suite() { trap - SIGINT SIGTERM EXIT } +function bdev_gpt_uuid() { + local bdev + + start_spdk_tgt + + "$rpc_py" load_config -j "$conf_file" + "$rpc_py" bdev_wait_for_examine + + bdev=$("$rpc_py" bdev_get_bdevs -b "$g_unique_partguid") + [[ "$(jq -r 'length' <<< "$bdev")" == "1" ]] + [[ "$(jq -r '.[0].aliases[0]' <<< "$bdev")" == "$g_unique_partguid" ]] + [[ "$(jq -r '.[0].driver_specific.gpt.unique_partition_guid' <<< "$bdev")" == "$g_unique_partguid" ]] + + bdev=$("$rpc_py" bdev_get_bdevs -b "$g_unique_partguid_old") + [[ "$(jq -r 'length' <<< "$bdev")" == "1" ]] + [[ "$(jq -r '.[0].aliases[0]' <<< "$bdev")" == "$g_unique_partguid_old" ]] + [[ "$(jq -r '.[0].driver_specific.gpt.unique_partition_guid' <<< "$bdev")" == "$g_unique_partguid_old" ]] + + killprocess "$spdk_tgt_pid" +} + # Initial bdev creation and configuration #----------------------------------------------------- QOS_DEV_1="Malloc_0" @@ -743,6 +771,10 @@ if [[ $test_type == bdev ]]; then run_test "bdev_stat" stat_test_suite "$env_ctx" fi +if [[ $test_type == gpt ]]; then + run_test "bdev_gpt_uuid" bdev_gpt_uuid +fi + # Temporarily disabled - infinite loop # if [ $RUN_NIGHTLY -eq 1 ]; then # run_test "bdev_reset" $rootdir/build/examples/bdevperf --json "$conf_file" -q 16 -w reset -o 4096 -t 60 "$env_ctx"