[PATCH 14/19] block: add early_lookup_bdev_by_type_uuid()
From: Vincent Mailhol
Date: Mon Jun 15 2026 - 12:23:36 EST
Add early_lookup_bdev_by_type_uuid() to find the root block device by
its GPT type UUID on the disk containing the active EFI System
Partition.
DPS [1] requires OS partition discovery to be limited to the disk
containing the active EFI System Partition. Reuse the existing block
class lookup and UUID matching callback to identify that disk, then do a
second lookup constrained to it. If the disk contains several partitions
with a matching type UUID, use the first match, following the DPS
discovery rule.
Extend struct uuidcmp with the new disk field so that it can be used in
the new match_dev_by_type_uuid() callback function.
Update devt_from_partuuid() to initialize cmp with a designated
initializer so that the new cmp.disk field is zero-initialized. This is
not strictly needed, but keeps the code cleaner.
[1] The Discoverable Partitions Specification (DPS)
Link: https://uapi-group.org/specifications/specs/discoverable_partitions_specification/
Signed-off-by: Vincent Mailhol <mailhol@xxxxxxxxxx>
---
block/early-lookup.c | 67 +++++++++++++++++++++++++++++++++++++++++++++++---
include/linux/blkdev.h | 4 +++
2 files changed, 68 insertions(+), 3 deletions(-)
diff --git a/block/early-lookup.c b/block/early-lookup.c
index 3fb57f7d2b12..cd10785e70ac 100644
--- a/block/early-lookup.c
+++ b/block/early-lookup.c
@@ -5,10 +5,12 @@
*/
#include <linux/blkdev.h>
#include <linux/ctype.h>
+#include <linux/uuid.h>
struct uuidcmp {
const char *uuid;
int len;
+ struct gendisk *disk;
};
/**
@@ -45,13 +47,11 @@ static int __init match_dev_by_uuid(struct device *dev, const void *data)
*/
static int __init devt_from_partuuid(const char *uuid_str, dev_t *devt)
{
- struct uuidcmp cmp;
+ struct uuidcmp cmp = { .uuid = uuid_str };
struct device *dev = NULL;
int offset = 0;
char *slash;
- cmp.uuid = uuid_str;
-
slash = strchr(uuid_str, '/');
/* Check for optional partition number offset attributes. */
if (slash) {
@@ -252,6 +252,67 @@ int __init early_lookup_bdev(const char *name, dev_t *devt)
return devt_from_devnum(name, devt);
}
+#ifdef CONFIG_DPS_ROOT_AUTO_DISCOVERY
+/**
+ * match_dev_by_type_uuid - callback for finding a partition using its type UUID
+ * @dev: device passed in by the caller
+ * @data: opaque pointer to the desired struct uuidcmp to match
+ *
+ * Returns: 1 if the device matches, and 0 otherwise.
+ */
+static int __init match_dev_by_type_uuid(struct device *dev, const void *data)
+{
+ struct block_device *bdev = dev_to_bdev(dev);
+ const struct uuidcmp *cmp = data;
+
+ return bdev->bd_disk == cmp->disk && bdev->bd_meta_info &&
+ !strcasecmp(cmp->uuid, bdev->bd_meta_info->type_uuid);
+}
+
+/**
+ * early_lookup_bdev_by_type_uuid - look up a partition by its type UUID
+ * @type_uuid: partition type UUID to search for
+ * @efi_partuuid: partition UUID identifying the active EFI partition
+ * @devt: matching dev_t result
+ *
+ * This helper follows the Discoverable Partitions Specification rules. It uses
+ * @efi_partuuid to find the disk containing the active EFI System Partition,
+ * then searches only partitions on that disk for the partition type UUID
+ * specified by @type_uuid.
+ *
+ * Returns: 0 on success or a negative error code on failure.
+ */
+int __init early_lookup_bdev_by_type_uuid(const char *type_uuid,
+ const char *efi_partuuid, dev_t *devt)
+{
+ struct uuidcmp efi_cmp = {
+ .uuid = efi_partuuid,
+ .len = UUID_STRING_LEN,
+ };
+ struct uuidcmp type_cmp = {
+ .uuid = type_uuid,
+ };
+ struct device *efi_dev;
+ struct device *type_dev;
+
+ efi_dev = class_find_device(&block_class, NULL, &efi_cmp,
+ &match_dev_by_uuid);
+ if (!efi_dev)
+ return -ENODEV;
+
+ type_cmp.disk = dev_to_disk(efi_dev);
+ type_dev = class_find_device(&block_class, NULL, &type_cmp,
+ &match_dev_by_type_uuid);
+ put_device(efi_dev);
+ if (!type_dev)
+ return -ENODEV;
+
+ *devt = type_dev->devt;
+ put_device(type_dev);
+ return 0;
+}
+#endif
+
static char __init *bdevt_str(dev_t devt, char *buf)
{
if (MAJOR(devt) <= 0xff && MINOR(devt) <= 0xff) {
diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h
index 8ce85d21a1f4..c2b7d07c92e7 100644
--- a/include/linux/blkdev.h
+++ b/include/linux/blkdev.h
@@ -1800,6 +1800,10 @@ void sync_bdevs(bool wait);
void bdev_statx(const struct path *path, struct kstat *stat, u32 request_mask);
void printk_all_partitions(void);
int __init early_lookup_bdev(const char *pathname, dev_t *dev);
+#ifdef CONFIG_DPS_ROOT_AUTO_DISCOVERY
+int __init early_lookup_bdev_by_type_uuid(const char *type_uuid,
+ const char *efi_partuuid, dev_t *dev);
+#endif
#else
static inline void invalidate_bdev(struct block_device *bdev)
{
--
2.53.0