Spdk/scripts/spdk-gpt.py
Jim Harris 3a39d90b03 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>
2023-01-24 17:19:35 +00:00

76 lines
2.3 KiB
Python
Executable File

#!/usr/bin/env python3
# SPDX-License-Identifier: BSD-3-Clause
# Copyright (C) 2021 Intel Corporation
# All rights reserved.
#
import argparse
import os
import stat
import struct
def block_exists(block):
return os.path.exists(block) and stat.S_ISBLK(os.stat(block).st_mode)
def lbsize(block):
if not os.path.exists("/sys/block/%s/queue/logical_block_size" % block):
return 512
with open("/sys/block/%s/queue/logical_block_size" % block) as lbs:
return int(lbs.read())
def readb(block, offset, length, format="Q"):
b = os.open(block, os.O_RDONLY)
os.lseek(b, offset, os.SEEK_SET)
data = os.read(b, length)
os.close(b)
return struct.unpack(format, data)[0]
def is_spdk_gpt(block, entry):
block_path = "/dev/" + block
if not block_exists(block_path):
print("%s is not a block device" % block)
return False
disk_lbsize = lbsize(block)
gpt_sig = 0x5452415020494645 # EFI PART
spdk_guid = [0x7c5222bd, 0x8f5d, 0x4087, 0x9c00, 0xbf9843c7b58c]
spdk_guid2 = [0x6527994e, 0x2c5a, 0x4eec, 0x9613, 0x8f5944074e8b]
if readb(block_path, disk_lbsize, 8) != gpt_sig:
print("No valid GPT data, bailing")
return False
part_entry_lba = disk_lbsize * readb(block_path, disk_lbsize + 72, 8)
part_entry_lba = part_entry_lba + (entry - 1) * 128
guid = [
readb(block_path, part_entry_lba, 4, "I"),
readb(block_path, part_entry_lba + 4, 2, "H"),
readb(block_path, part_entry_lba + 6, 2, "H"),
readb(block_path, part_entry_lba + 8, 2, ">H"),
readb(block_path, part_entry_lba + 10, 8, ">Q") >> 16
]
return guid == spdk_guid or guid == spdk_guid2
if __name__ == "__main__":
parser = argparse.ArgumentParser(description='Checks if SPDK GUID is present on given block device')
parser.add_argument('block', type=str, help='block device to check')
parser.add_argument('-e', '--entry', dest='entry', help='GPT partition entry',
required=False, type=int, default=1)
args = parser.parse_args()
try:
if is_spdk_gpt(args.block.replace("/dev/", ""), args.entry):
exit(0)
exit(1)
except Exception as e:
print("Failed to read GPT data from %s (%s)" % (args.block, e))
exit(1)