bdev_gpt: add new SPDK partition type for off-by-one fix
The gpt bdev module has an off-by-one error. When it calculates the size of the partition, it simply does "end - start", when really it should be "end - start + 1". We cannot just fix it by changing the math here, any consumers of the partition may have put down metadata on the partition based on the old size. So instead add a new SPDK partition type. SPDK will keep the existing off-by-one behavior when it finds the old partition type, but will use the correct math when finding the new partition type. Fixes issue #2801. Signed-off-by: Jim Harris <james.r.harris@intel.com> Change-Id: I48eb48c781f1968b59e52b4477ca45e9c81eac11 Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/16298 Tested-by: SPDK CI Jenkins <sys_sgci@intel.com> Reviewed-by: Aleksey Marchuk <alexeymar@nvidia.com> Reviewed-by: Paul Luse <paul.e.luse@intel.com> Reviewed-by: Mike Gerdts <mgerdts@nvidia.com> Reviewed-by: Tomasz Zawadzki <tomasz.zawadzki@intel.com>
This commit is contained in:
parent
40e8ee2a48
commit
3a39d90b03
@ -43,3 +43,18 @@ With the removal of this deprecation, calls to vbdev modules' `examine_disk()` a
|
|||||||
`examine_config()` callbacks will happen only on the app thread. This means that vbdev module
|
`examine_config()` callbacks will happen only on the app thread. This means that vbdev module
|
||||||
maintainers will not need to make any changes to examine callbacks that call `spdk_bdev_register()`
|
maintainers will not need to make any changes to examine callbacks that call `spdk_bdev_register()`
|
||||||
on the same thread as the examine callback uses.
|
on the same thread as the examine callback uses.
|
||||||
|
|
||||||
|
### gpt
|
||||||
|
|
||||||
|
### `old_gpt_guid`
|
||||||
|
|
||||||
|
Deprecated the SPDK partition type GUID `7c5222bd-8f5d-4087-9c00-bf9843c7b58c`. Partitions of this
|
||||||
|
type have bdevs created that are one block less than the actual size of the partition. Existing
|
||||||
|
partitions using the deprecated GUID can continue to use that GUID; support for the deprecated GUID
|
||||||
|
will remain in SPDK indefinitely, and will continue to exhibit the off-by-one bug so that on-disk
|
||||||
|
metadata layouts based on the incorrect size are not affected.
|
||||||
|
|
||||||
|
See GitHub issue [2801](https://github.com/spdk/spdk/issues/2801) for additional details on the bug.
|
||||||
|
|
||||||
|
New SPDK partition types should use GUID `6527994e-2c5a-4eec-9613-8f5944074e8b` which will create
|
||||||
|
a bdev of the correct size.
|
||||||
|
@ -274,7 +274,7 @@ possibly multiple virtual bdevs.
|
|||||||
|
|
||||||
### SPDK GPT partition table {#bdev_ug_gpt}
|
### SPDK GPT partition table {#bdev_ug_gpt}
|
||||||
|
|
||||||
The SPDK partition type GUID is `7c5222bd-8f5d-4087-9c00-bf9843c7b58c`. Existing SPDK bdevs
|
The SPDK partition type GUID is `6527994e-2c5a-4eec-9613-8f5944074e8b`. Existing SPDK bdevs
|
||||||
can be exposed as Linux block devices via NBD and then can be partitioned with
|
can be exposed as Linux block devices via NBD and then can be partitioned with
|
||||||
standard partitioning tools. After partitioning, the bdevs will need to be deleted and
|
standard partitioning tools. After partitioning, the bdevs will need to be deleted and
|
||||||
attached again for the GPT bdev module to see any changes. NBD kernel module must be
|
attached again for the GPT bdev module to see any changes. NBD kernel module must be
|
||||||
@ -312,7 +312,7 @@ parted -s /dev/nbd0 mkpart MyPartition '0%' '50%'
|
|||||||
|
|
||||||
# Change the partition type to the SPDK GUID.
|
# Change the partition type to the SPDK GUID.
|
||||||
# sgdisk is part of the gdisk package.
|
# sgdisk is part of the gdisk package.
|
||||||
sgdisk -t 1:7c5222bd-8f5d-4087-9c00-bf9843c7b58c /dev/nbd0
|
sgdisk -t 1:6527994e-2c5a-4eec-9613-8f5944074e8b /dev/nbd0
|
||||||
|
|
||||||
# Stop the NBD device (stop exporting /dev/nbd0).
|
# Stop the NBD device (stop exporting /dev/nbd0).
|
||||||
rpc.py nbd_stop_disk /dev/nbd0
|
rpc.py nbd_stop_disk /dev/nbd0
|
||||||
|
@ -13,8 +13,24 @@
|
|||||||
#include "spdk/stdinc.h"
|
#include "spdk/stdinc.h"
|
||||||
|
|
||||||
#include "spdk/gpt_spec.h"
|
#include "spdk/gpt_spec.h"
|
||||||
|
#include "spdk/log.h"
|
||||||
|
|
||||||
|
#define SPDK_GPT_PART_TYPE_GUID SPDK_GPT_GUID(0x6527994e, 0x2c5a, 0x4eec, 0x9613, 0x8f5944074e8b)
|
||||||
|
|
||||||
|
/* PART_TYPE_GUID_OLD partitions will be constructed as bdevs with one fewer block than expected.
|
||||||
|
* See GitHub issue #2801.
|
||||||
|
*/
|
||||||
|
#ifdef REGISTER_GUID_DEPRECATION
|
||||||
|
/* Register the deprecation in the header file, to make it clear to readers that this GUID
|
||||||
|
* shouldn't be used for new SPDK GPT partitions. We will never actually log this deprecation
|
||||||
|
* though, since we are not recommending that users try to migrate existing partitions with the
|
||||||
|
* old GUID to the new GUID. Wrap it in this REGISTER_GUID_DEPRECATION flag to avoid defining
|
||||||
|
* this deprecation in multiple compilation units.
|
||||||
|
*/
|
||||||
|
SPDK_LOG_DEPRECATION_REGISTER(old_gpt_guid, "old gpt guid", "Never", 0)
|
||||||
|
#endif
|
||||||
|
#define SPDK_GPT_PART_TYPE_GUID_OLD SPDK_GPT_GUID(0x7c5222bd, 0x8f5d, 0x4087, 0x9c00, 0xbf9843c7b58c)
|
||||||
|
|
||||||
#define SPDK_GPT_PART_TYPE_GUID SPDK_GPT_GUID(0x7c5222bd, 0x8f5d, 0x4087, 0x9c00, 0xbf9843c7b58c)
|
|
||||||
#define SPDK_GPT_BUFFER_SIZE 32768 /* 32KB */
|
#define SPDK_GPT_BUFFER_SIZE 32768 /* 32KB */
|
||||||
#define SPDK_GPT_GUID_EQUAL(x,y) (memcmp(x, y, sizeof(struct spdk_gpt_guid)) == 0)
|
#define SPDK_GPT_GUID_EQUAL(x,y) (memcmp(x, y, sizeof(struct spdk_gpt_guid)) == 0)
|
||||||
|
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
* each partition.
|
* each partition.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#define REGISTER_GUID_DEPRECATION
|
||||||
#include "gpt.h"
|
#include "gpt.h"
|
||||||
|
|
||||||
#include "spdk/endian.h"
|
#include "spdk/endian.h"
|
||||||
@ -313,12 +314,26 @@ vbdev_gpt_create_bdevs(struct gpt_base *gpt_base)
|
|||||||
p = &gpt->partitions[i];
|
p = &gpt->partitions[i];
|
||||||
uint64_t lba_start = from_le64(&p->starting_lba);
|
uint64_t lba_start = from_le64(&p->starting_lba);
|
||||||
uint64_t lba_end = from_le64(&p->ending_lba);
|
uint64_t lba_end = from_le64(&p->ending_lba);
|
||||||
|
uint64_t partition_size = lba_end - lba_start + 1;
|
||||||
|
|
||||||
if (!SPDK_GPT_GUID_EQUAL(&gpt->partitions[i].part_type_guid,
|
if (lba_start == 0) {
|
||||||
&SPDK_GPT_PART_TYPE_GUID) ||
|
|
||||||
lba_start == 0) {
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (SPDK_GPT_GUID_EQUAL(&gpt->partitions[i].part_type_guid,
|
||||||
|
&SPDK_GPT_PART_TYPE_GUID_OLD)) {
|
||||||
|
/* GitHub issue #2801 - we continue to report these partitions with
|
||||||
|
* off-by-one sizing error to ensure we don't break layouts based
|
||||||
|
* on that smaller size. */
|
||||||
|
partition_size -= 1;
|
||||||
|
} else if (!SPDK_GPT_GUID_EQUAL(&gpt->partitions[i].part_type_guid,
|
||||||
|
&SPDK_GPT_PART_TYPE_GUID)) {
|
||||||
|
/* Partition type isn't TYPE_GUID or TYPE_GUID_OLD, so this isn't
|
||||||
|
* an SPDK parition. Continue to the next partition.
|
||||||
|
*/
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if (lba_start < head_lba_start || lba_end > head_lba_end) {
|
if (lba_start < head_lba_start || lba_end > head_lba_end) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -339,7 +354,7 @@ vbdev_gpt_create_bdevs(struct gpt_base *gpt_base)
|
|||||||
}
|
}
|
||||||
|
|
||||||
rc = spdk_bdev_part_construct(&d->part, gpt_base->part_base, name,
|
rc = spdk_bdev_part_construct(&d->part, gpt_base->part_base, name,
|
||||||
lba_start, lba_end - lba_start, "GPT Disk");
|
lba_start, partition_size, "GPT Disk");
|
||||||
free(name);
|
free(name);
|
||||||
if (rc) {
|
if (rc) {
|
||||||
SPDK_ERRLOG("could not construct bdev part\n");
|
SPDK_ERRLOG("could not construct bdev part\n");
|
||||||
|
@ -361,12 +361,25 @@ block_in_use() {
|
|||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get_spdk_gpt_old() {
|
||||||
|
local spdk_guid
|
||||||
|
|
||||||
|
[[ -e $rootdir/module/bdev/gpt/gpt.h ]] || return 1
|
||||||
|
|
||||||
|
GPT_H="$rootdir/module/bdev/gpt/gpt.h"
|
||||||
|
IFS="()" read -r _ spdk_guid _ < <(grep -w SPDK_GPT_PART_TYPE_GUID_OLD "$GPT_H")
|
||||||
|
spdk_guid=${spdk_guid//, /-} spdk_guid=${spdk_guid//0x/}
|
||||||
|
|
||||||
|
echo "$spdk_guid"
|
||||||
|
}
|
||||||
|
|
||||||
get_spdk_gpt() {
|
get_spdk_gpt() {
|
||||||
local spdk_guid
|
local spdk_guid
|
||||||
|
|
||||||
[[ -e $rootdir/module/bdev/gpt/gpt.h ]] || return 1
|
[[ -e $rootdir/module/bdev/gpt/gpt.h ]] || return 1
|
||||||
|
|
||||||
IFS="()" read -r _ spdk_guid _ < <(grep SPDK_GPT_PART_TYPE_GUID "$rootdir/module/bdev/gpt/gpt.h")
|
GPT_H="$rootdir/module/bdev/gpt/gpt.h"
|
||||||
|
IFS="()" read -r _ spdk_guid _ < <(grep -w SPDK_GPT_PART_TYPE_GUID "$GPT_H")
|
||||||
spdk_guid=${spdk_guid//, /-} spdk_guid=${spdk_guid//0x/}
|
spdk_guid=${spdk_guid//, /-} spdk_guid=${spdk_guid//0x/}
|
||||||
|
|
||||||
echo "$spdk_guid"
|
echo "$spdk_guid"
|
||||||
|
@ -40,6 +40,7 @@ def is_spdk_gpt(block, entry):
|
|||||||
disk_lbsize = lbsize(block)
|
disk_lbsize = lbsize(block)
|
||||||
gpt_sig = 0x5452415020494645 # EFI PART
|
gpt_sig = 0x5452415020494645 # EFI PART
|
||||||
spdk_guid = [0x7c5222bd, 0x8f5d, 0x4087, 0x9c00, 0xbf9843c7b58c]
|
spdk_guid = [0x7c5222bd, 0x8f5d, 0x4087, 0x9c00, 0xbf9843c7b58c]
|
||||||
|
spdk_guid2 = [0x6527994e, 0x2c5a, 0x4eec, 0x9613, 0x8f5944074e8b]
|
||||||
|
|
||||||
if readb(block_path, disk_lbsize, 8) != gpt_sig:
|
if readb(block_path, disk_lbsize, 8) != gpt_sig:
|
||||||
print("No valid GPT data, bailing")
|
print("No valid GPT data, bailing")
|
||||||
@ -56,7 +57,7 @@ def is_spdk_gpt(block, entry):
|
|||||||
readb(block_path, part_entry_lba + 10, 8, ">Q") >> 16
|
readb(block_path, part_entry_lba + 10, 8, ">Q") >> 16
|
||||||
]
|
]
|
||||||
|
|
||||||
return guid == spdk_guid
|
return guid == spdk_guid or guid == spdk_guid2
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
|
@ -121,9 +121,10 @@ function setup_gpt_conf() {
|
|||||||
# Create gpt partition table
|
# Create gpt partition table
|
||||||
parted -s "$gpt_nvme" mklabel gpt mkpart SPDK_TEST_first '0%' '50%' mkpart SPDK_TEST_second '50%' '100%'
|
parted -s "$gpt_nvme" mklabel gpt mkpart SPDK_TEST_first '0%' '50%' mkpart SPDK_TEST_second '50%' '100%'
|
||||||
# change the GUID to SPDK GUID value
|
# change the GUID to SPDK GUID value
|
||||||
|
SPDK_GPT_OLD_GUID=$(get_spdk_gpt_old)
|
||||||
SPDK_GPT_GUID=$(get_spdk_gpt)
|
SPDK_GPT_GUID=$(get_spdk_gpt)
|
||||||
sgdisk -t "1:$SPDK_GPT_GUID" "$gpt_nvme"
|
sgdisk -t "1:$SPDK_GPT_GUID" "$gpt_nvme"
|
||||||
sgdisk -t "2:$SPDK_GPT_GUID" "$gpt_nvme"
|
sgdisk -t "2:$SPDK_GPT_OLD_GUID" "$gpt_nvme"
|
||||||
"$rootdir/scripts/setup.sh"
|
"$rootdir/scripts/setup.sh"
|
||||||
"$rpc_py" bdev_get_bdevs
|
"$rpc_py" bdev_get_bdevs
|
||||||
setup_nvme_conf
|
setup_nvme_conf
|
||||||
|
Loading…
Reference in New Issue
Block a user