* [PATCH v2 1/7] block: store GPT partition type UUID
2026-10-25 13:03 [PATCH v2 0/7] init: discoverable root partitions Vincent Mailhol
@ 2026-10-25 13:03 ` Vincent Mailhol
2026-10-25 13:03 ` [PATCH v2 2/7] init: add DPS root partition type UUID definitions Vincent Mailhol
` (5 subsequent siblings)
6 siblings, 0 replies; 10+ messages in thread
From: Vincent Mailhol @ 2026-10-25 13:03 UTC (permalink / raw)
To: Jens Axboe, Davidlohr Bueso, Alexander Viro, Christian Brauner,
Jan Kara
Cc: linux-kernel, linux-block, linux-efi, linux-fsdevel, Dave Hansen,
James Bottomley, Helge Deller, Matthew Wilcox, Vincent Mailhol
DPS [1] identifies OS partitions by GPT partition type UUID.
Keep that UUID in struct partition_meta_info and populate it while
scanning GPT partition tables so early root discovery can use it.
[1] The Discoverable Partitions Specification (DPS)
Link: https://uapi-group.org/specifications/specs/discoverable_partitions_specification/
Signed-off-by: Vincent Mailhol <mailhol@kernel.org>
---
block/partitions/efi.c | 1 +
include/linux/blkdev.h | 1 +
2 files changed, 2 insertions(+)
diff --git a/block/partitions/efi.c b/block/partitions/efi.c
index 9865d59093fa..4a3835ed9561 100644
--- a/block/partitions/efi.c
+++ b/block/partitions/efi.c
@@ -742,6 +742,7 @@ int efi_partition(struct parsed_partitions *state)
info = &state->parts[i + 1].info;
efi_guid_to_str(&ptes[i].unique_partition_guid, info->uuid);
+ efi_guid_to_str(&ptes[i].partition_type_guid, info->type_uuid);
/* Naively convert UTF16-LE to 7 bits. */
label_max = min(ARRAY_SIZE(info->volname) - 1,
diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h
index d003a9d2d1f6..b99a59cd1120 100644
--- a/include/linux/blkdev.h
+++ b/include/linux/blkdev.h
@@ -67,6 +67,7 @@ extern const struct class block_class;
struct partition_meta_info {
char uuid[PARTITION_META_INFO_UUIDLTH];
+ char type_uuid[PARTITION_META_INFO_UUIDLTH];
u8 volname[PARTITION_META_INFO_VOLNAMELTH];
};
--
2.55.0
^ permalink raw reply related [flat|nested] 10+ messages in thread* [PATCH v2 2/7] init: add DPS root partition type UUID definitions
2026-10-25 13:03 [PATCH v2 0/7] init: discoverable root partitions Vincent Mailhol
2026-10-25 13:03 ` [PATCH v2 1/7] block: store GPT partition type UUID Vincent Mailhol
@ 2026-10-25 13:03 ` Vincent Mailhol
2026-10-25 13:13 ` sashiko-bot
2026-10-25 13:03 ` [PATCH v2 3/7] init: factor out root device lookup into lookup_root_device() Vincent Mailhol
` (4 subsequent siblings)
6 siblings, 1 reply; 10+ messages in thread
From: Vincent Mailhol @ 2026-10-25 13:03 UTC (permalink / raw)
To: Jens Axboe, Davidlohr Bueso, Alexander Viro, Christian Brauner,
Jan Kara
Cc: linux-kernel, linux-block, linux-efi, linux-fsdevel, Dave Hansen,
James Bottomley, Helge Deller, Matthew Wilcox, Vincent Mailhol
DPS [1] assigns a native root partition type UUID to each supported
architecture. Add a hidden DPS_ROOT_PARTITION_TYPE_UUID string symbol
and populate it from the architecture selected in Kconfig. Only
architectures with EFI support in the kernel are added.
Gate the symbol on EFI and EFI_PARTITION because discovery needs block
devices, EFI runtime services and GPT partition parsing.
Derive the hidden DPS_ROOT_AUTO_DISCOVERY boolean from whether
DPS_ROOT_PARTITION_TYPE_UUID is nonempty.
[1] The Discoverable Partitions Specification (DPS)
Link: https://uapi-group.org/specifications/specs/discoverable_partitions_specification/
Signed-off-by: Vincent Mailhol <mailhol@kernel.org>
---
init/Kconfig | 14 ++++++++++++++
1 file changed, 14 insertions(+)
diff --git a/init/Kconfig b/init/Kconfig
index b31aa298c4fe..133854355697 100644
--- a/init/Kconfig
+++ b/init/Kconfig
@@ -2166,6 +2166,20 @@ config ARCH_HAS_PREPARE_SYNC_CORE_CMD
config ARCH_HAS_SYNC_CORE_BEFORE_USERMODE
bool
+config DPS_ROOT_PARTITION_TYPE_UUID
+ depends on EFI && EFI_PARTITION
+ string
+ default "69dad710-2ce4-4e3c-b16c-21a1d49abed3" if ARM
+ default "b921b045-1df0-41c3-af44-4c6f280d3fae" if ARM64
+ default "77055800-792c-4f94-b39a-98c91b762bb6" if LOONGARCH
+ default "72ec70a6-cf74-40e6-bd49-4bda08e8f224" if RISCV && 64BIT
+ default "60d5a7fe-8e7d-435c-b714-3dd8162144e1" if RISCV
+ default "4f68bce3-e8cd-4db1-96e7-fbcaf984b709" if X86_64
+ default "44479540-f297-41b2-9af7-d131d5f0458a" if X86
+
+config DPS_ROOT_AUTO_DISCOVERY
+ def_bool DPS_ROOT_PARTITION_TYPE_UUID != ""
+
# It may be useful for an architecture to override the definitions of the
# SYSCALL_DEFINE() and __SYSCALL_DEFINEx() macros in <linux/syscalls.h>
# and the COMPAT_ variants in <linux/compat.h>, in particular to use a
--
2.55.0
^ permalink raw reply related [flat|nested] 10+ messages in thread* Re: [PATCH v2 2/7] init: add DPS root partition type UUID definitions
2026-10-25 13:03 ` [PATCH v2 2/7] init: add DPS root partition type UUID definitions Vincent Mailhol
@ 2026-10-25 13:13 ` sashiko-bot
2026-10-25 15:45 ` Vincent Mailhol
0 siblings, 1 reply; 10+ messages in thread
From: sashiko-bot @ 2026-10-25 13:13 UTC (permalink / raw)
To: Vincent Mailhol, Jens Axboe, Davidlohr Bueso, Alexander Viro,
Christian Brauner, Jan Kara
Cc: linux-efi, Dave Hansen, James Bottomley, Helge Deller,
Matthew Wilcox
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [Medium] init: DPS_ROOT_PARTITION_TYPE_UUID sets 64-bit UUID on 32-bit LOONGARCH
--
commit 109ce0d2c6fc812a6bc94f72e97807013dc5fc56
Author: Vincent Mailhol <mailhol@kernel.org>
init: add DPS root partition type UUID definitions
This commit adds the hidden DPS_ROOT_PARTITION_TYPE_UUID string Kconfig
symbol populated with the Discoverable Partitions Specification root
partition type UUIDs for EFI-supported architectures, along with the
derived DPS_ROOT_AUTO_DISCOVERY boolean symbol.
Link: https://uapi-group.org/specifications/specs/discoverable_partitions_specification/
> diff --git a/init/Kconfig b/init/Kconfig
> index b31aa298c4fe5..133854355697b 100644
> --- a/init/Kconfig
> +++ b/init/Kconfig
> @@ -2166,6 +2166,20 @@ config ARCH_HAS_PREPARE_SYNC_CORE_CMD
> config ARCH_HAS_SYNC_CORE_BEFORE_USERMODE
> bool
>
> +config DPS_ROOT_PARTITION_TYPE_UUID
> + depends on EFI && EFI_PARTITION
> + string
> + default "69dad710-2ce4-4e3c-b16c-21a1d49abed3" if ARM
> + default "b921b045-1df0-41c3-af44-4c6f280d3fae" if ARM64
> + default "77055800-792c-4f94-b39a-98c91b762bb6" if LOONGARCH
[Severity: Medium]
Should the LOONGARCH default also depend on 64BIT, matching the RISCV &&
64BIT check on the next line?
The UUID 77055800-792c-4f94-b39a-98c91b762bb6 is defined by the
Discoverable Partitions Specification specifically for 64-bit LoongArch
(SD_GPT_ROOT_LOONGARCH64), and the specification does not define a root
partition type UUID for 32-bit LoongArch.
In arch/loongarch/Kconfig, config LOONGARCH unconditionally selects EFI and
supports both 32-bit and 64-bit kernel builds (such as
arch/loongarch/configs/loongson32_defconfig):
arch/loongarch/Kconfig:
config LOONGARCH
...
select EFI
select GENERIC_ATOMIC64 if 32BIT
...
config 32BIT
bool "32-bit kernel"
config 64BIT
bool "64-bit kernel"
When building a 32-bit LoongArch kernel (CONFIG_LOONGARCH=y, CONFIG_32BIT=y,
CONFIG_EFI=y, and CONFIG_EFI_PARTITION=y), DPS_ROOT_PARTITION_TYPE_UUID gets
populated with the 64-bit LoongArch UUID and DPS_ROOT_AUTO_DISCOVERY is
enabled. Because a 32-bit LoongArch kernel sets elf_check_arch to
elf32_check_arch in arch/loongarch/include/asm/elf.h and only loads
ELFCLASS32 binaries, wouldn't early_lookup_dps_root() auto-discover and
mount a 64-bit LoongArch root partition when root= is omitted, and then fail
to execute its 64-bit userspace?
--
Sashiko AI review · https://sashiko.dev/#/patchset/20261025-discoverable-root_partitions-v2-0-fb77d0821fab@kernel.org?part=2
^ permalink raw reply [flat|nested] 10+ messages in thread* Re: [PATCH v2 2/7] init: add DPS root partition type UUID definitions
2026-10-25 13:13 ` sashiko-bot
@ 2026-10-25 15:45 ` Vincent Mailhol
0 siblings, 0 replies; 10+ messages in thread
From: Vincent Mailhol @ 2026-10-25 15:45 UTC (permalink / raw)
To: sashiko-reviews, Jens Axboe, Davidlohr Bueso, Alexander Viro,
Christian Brauner, Jan Kara
Cc: linux-efi, Dave Hansen, James Bottomley, Helge Deller,
Matthew Wilcox
On 25/10/2026 at 14:13, sashiko-bot@kernel.org wrote:
> Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
> - [Medium] init: DPS_ROOT_PARTITION_TYPE_UUID sets 64-bit UUID on 32-bit LOONGARCH
> --
>
> commit 109ce0d2c6fc812a6bc94f72e97807013dc5fc56
> Author: Vincent Mailhol <mailhol@kernel.org>
>
> init: add DPS root partition type UUID definitions
>
> This commit adds the hidden DPS_ROOT_PARTITION_TYPE_UUID string Kconfig
> symbol populated with the Discoverable Partitions Specification root
> partition type UUIDs for EFI-supported architectures, along with the
> derived DPS_ROOT_AUTO_DISCOVERY boolean symbol.
>
> Link: https://uapi-group.org/specifications/specs/discoverable_partitions_specification/
>
>> diff --git a/init/Kconfig b/init/Kconfig
>> index b31aa298c4fe5..133854355697b 100644
>> --- a/init/Kconfig
>> +++ b/init/Kconfig
>> @@ -2166,6 +2166,20 @@ config ARCH_HAS_PREPARE_SYNC_CORE_CMD
>> config ARCH_HAS_SYNC_CORE_BEFORE_USERMODE
>> bool
>>
>> +config DPS_ROOT_PARTITION_TYPE_UUID
>> + depends on EFI && EFI_PARTITION
>> + string
>> + default "69dad710-2ce4-4e3c-b16c-21a1d49abed3" if ARM
>> + default "b921b045-1df0-41c3-af44-4c6f280d3fae" if ARM64
>> + default "77055800-792c-4f94-b39a-98c91b762bb6" if LOONGARCH
>
> [Severity: Medium]
> Should the LOONGARCH default also depend on 64BIT, matching the RISCV &&
> 64BIT check on the next line?
>
> The UUID 77055800-792c-4f94-b39a-98c91b762bb6 is defined by the
> Discoverable Partitions Specification specifically for 64-bit LoongArch
> (SD_GPT_ROOT_LOONGARCH64), and the specification does not define a root
> partition type UUID for 32-bit LoongArch.
I see. I overlooked the 32-bit LoongArch case because DPS only defines
partition type UUIDs for LoongArch64. I will add a 64BIT guard in v3:
default "77055800-792c-4f94-b39a-98c91b762bb6" if LOONGARCH && 64BIT
I will wait for further review comments before posting v3.
> In arch/loongarch/Kconfig, config LOONGARCH unconditionally selects EFI and
> supports both 32-bit and 64-bit kernel builds (such as
> arch/loongarch/configs/loongson32_defconfig):
>
> arch/loongarch/Kconfig:
> config LOONGARCH
> ...
> select EFI
> select GENERIC_ATOMIC64 if 32BIT
> ...
> config 32BIT
> bool "32-bit kernel"
>
> config 64BIT
> bool "64-bit kernel"
>
> When building a 32-bit LoongArch kernel (CONFIG_LOONGARCH=y, CONFIG_32BIT=y,
> CONFIG_EFI=y, and CONFIG_EFI_PARTITION=y), DPS_ROOT_PARTITION_TYPE_UUID gets
> populated with the 64-bit LoongArch UUID and DPS_ROOT_AUTO_DISCOVERY is
> enabled. Because a 32-bit LoongArch kernel sets elf_check_arch to
> elf32_check_arch in arch/loongarch/include/asm/elf.h and only loads
> ELFCLASS32 binaries, wouldn't early_lookup_dps_root() auto-discover and
> mount a 64-bit LoongArch root partition when root= is omitted, and then fail
> to execute its 64-bit userspace?
Yours sincerely,
Vincent Mailhol
^ permalink raw reply [flat|nested] 10+ messages in thread
* [PATCH v2 3/7] init: factor out root device lookup into lookup_root_device()
2026-10-25 13:03 [PATCH v2 0/7] init: discoverable root partitions Vincent Mailhol
2026-10-25 13:03 ` [PATCH v2 1/7] block: store GPT partition type UUID Vincent Mailhol
2026-10-25 13:03 ` [PATCH v2 2/7] init: add DPS root partition type UUID definitions Vincent Mailhol
@ 2026-10-25 13:03 ` Vincent Mailhol
2026-10-25 13:03 ` [PATCH v2 4/7] init: discover root by DPS partition type UUID Vincent Mailhol
` (3 subsequent siblings)
6 siblings, 0 replies; 10+ messages in thread
From: Vincent Mailhol @ 2026-10-25 13:03 UTC (permalink / raw)
To: Jens Axboe, Davidlohr Bueso, Alexander Viro, Christian Brauner,
Jan Kara
Cc: linux-kernel, linux-block, linux-efi, linux-fsdevel, Dave Hansen,
James Bottomley, Helge Deller, Matthew Wilcox, Vincent Mailhol
DPS root detection will also need to work if root_wait is set, meaning
that wait_for_root() needs to handle the DPS logic.
Move the early_lookup_bdev() calls and the rootwait error handling into
the new lookup_root_device() so later changes can extend the lookup
policy without duplicating the rootwait retry logic.
While at it, reword the error message to add the "VFS: " prefix.
Signed-off-by: Vincent Mailhol <mailhol@kernel.org>
---
init/do_mounts.c | 23 +++++++++++++++--------
1 file changed, 15 insertions(+), 8 deletions(-)
diff --git a/init/do_mounts.c b/init/do_mounts.c
index 95e0b3a0f711..b9814d0cc5a6 100644
--- a/init/do_mounts.c
+++ b/init/do_mounts.c
@@ -402,6 +402,18 @@ void __init mount_root(char *root_device_name)
}
}
+static int __init lookup_root_device(const char *root_device_name, dev_t *dev)
+{
+ int err;
+
+ err = early_lookup_bdev(root_device_name, dev);
+ if (err == -EINVAL && root_wait) {
+ pr_err("VFS: root= is invalid; disabling rootwait.\n");
+ root_wait = 0;
+ }
+ return err;
+}
+
/* wait for any asynchronous scanning to complete */
static void __init wait_for_root(char *root_device_name)
{
@@ -415,7 +427,7 @@ static void __init wait_for_root(char *root_device_name)
end = ktime_add_ms(ktime_get_raw(), root_wait);
while (!driver_probe_done() ||
- early_lookup_bdev(root_device_name, &ROOT_DEV) < 0) {
+ lookup_root_device(root_device_name, &ROOT_DEV) < 0) {
msleep(5);
if (root_wait > 0 && ktime_after(ktime_get_raw(), end))
break;
@@ -440,14 +452,9 @@ static dev_t __init parse_root_device(char *root_device_name)
if (strcmp(root_device_name, "/dev/ram") == 0)
return Root_RAM0;
- error = early_lookup_bdev(root_device_name, &dev);
- if (error) {
- if (error == -EINVAL && root_wait) {
- pr_err("Disabling rootwait; root= is invalid.\n");
- root_wait = 0;
- }
+ error = lookup_root_device(root_device_name, &dev);
+ if (error)
return 0;
- }
return dev;
}
--
2.55.0
^ permalink raw reply related [flat|nested] 10+ messages in thread* [PATCH v2 4/7] init: discover root by DPS partition type UUID
2026-10-25 13:03 [PATCH v2 0/7] init: discoverable root partitions Vincent Mailhol
` (2 preceding siblings ...)
2026-10-25 13:03 ` [PATCH v2 3/7] init: factor out root device lookup into lookup_root_device() Vincent Mailhol
@ 2026-10-25 13:03 ` Vincent Mailhol
2026-10-25 13:03 ` [PATCH v2 5/7] block: skip partitions with DPS no-auto GPT attribute Vincent Mailhol
` (2 subsequent siblings)
6 siblings, 0 replies; 10+ messages in thread
From: Vincent Mailhol @ 2026-10-25 13:03 UTC (permalink / raw)
To: Jens Axboe, Davidlohr Bueso, Alexander Viro, Christian Brauner,
Jan Kara
Cc: linux-kernel, linux-block, linux-efi, linux-fsdevel, Dave Hansen,
James Bottomley, Helge Deller, Matthew Wilcox, Vincent Mailhol
When root= and ROOT_DEV are not set, discover the root block device
using the architecture's DPS root partition type UUID. Preserve explicit
root selection and an existing ROOT_DEV supplied by the boot protocol.
DPS [1] restricts discovery to the disk containing the active EFI System
Partition. Read LoaderDevicePartUUID from the Boot Loader Interface to
identify that disk and cache the UUID for subsequent lookup attempts.
Add early_lookup_bdev_by_type_uuid() to select the first matching
partition. The EFI System Partition may become visible before the root
partition has been registered. Hold the disk's open_mutex during lookup
so partition scanning finishes before returning -ENODEV.
Add early_lookup_dps_root() and have lookup_root_device() call it when
root= is absent. early_lookup_bdev() is kept unchanged so other callers
cannot trigger root discovery inadvertently. Return -EINVAL if the EFI
variable cannot be read or does not contain a valid UUID, so
lookup_root_device() disables rootwait. Return -EAGAIN if the EFI
partition is not available yet so rootwait can retry. Return -ENODEV if
its disk has no matching root partition. In that case, have
lookup_root_device() disable rootwait, clear the device number and
return zero to stop retries.
[1] The Discoverable Partitions Specification (DPS)
Link: https://uapi-group.org/specifications/specs/discoverable_partitions_specification/
Signed-off-by: Vincent Mailhol <mailhol@kernel.org>
---
block/early-lookup.c | 115 +++++++++++++++++++++++++++++++++++++++++++++++--
include/linux/blkdev.h | 10 +++++
init/do_mounts.c | 25 +++++++++--
3 files changed, 143 insertions(+), 7 deletions(-)
diff --git a/block/early-lookup.c b/block/early-lookup.c
index 3fb57f7d2b12..a1cb67eab4a0 100644
--- a/block/early-lookup.c
+++ b/block/early-lookup.c
@@ -5,10 +5,14 @@
*/
#include <linux/blkdev.h>
#include <linux/ctype.h>
+#include <linux/efi.h>
+#include <linux/ucs2_string.h>
+#include <linux/uuid.h>
struct uuidcmp {
const char *uuid;
int len;
+ struct gendisk *disk;
};
/**
@@ -45,13 +49,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 +254,113 @@ int __init early_lookup_bdev(const char *name, dev_t *devt)
return devt_from_devnum(name, devt);
}
+#ifdef CONFIG_DPS_ROOT_AUTO_DISCOVERY
+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);
+}
+
+/*
+ * Search the ESP's disk for an eligible partition of the requested type.
+ * Return -EAGAIN until the ESP is available, or -ENODEV if no match exists.
+ */
+static int __init early_lookup_bdev_by_type_uuid(const char *type_uuid,
+ const char *esp_partuuid,
+ dev_t *devt)
+{
+ struct uuidcmp esp_cmp = {
+ .uuid = esp_partuuid,
+ .len = UUID_STRING_LEN,
+ };
+ struct uuidcmp type_cmp = {
+ .uuid = type_uuid,
+ };
+ struct device *esp_dev;
+ struct device *type_dev;
+
+ esp_dev = class_find_device(&block_class, NULL, &esp_cmp,
+ &match_dev_by_uuid);
+ if (!esp_dev)
+ return -EAGAIN;
+
+ type_cmp.disk = dev_to_disk(esp_dev);
+ scoped_guard(mutex, &type_cmp.disk->open_mutex)
+ type_dev = class_find_device(&block_class, NULL, &type_cmp,
+ &match_dev_by_type_uuid);
+ put_device(esp_dev);
+ if (!type_dev)
+ return -ENODEV;
+
+ *devt = type_dev->devt;
+ pr_info("VFS: Discovered root partition /dev/%pg with GPT type UUID %s\n",
+ dev_to_bdev(type_dev), type_uuid);
+ put_device(type_dev);
+ return 0;
+}
+
+static int __init efi_get_esp_partuuid(char *partuuid, size_t size)
+{
+ static efi_guid_t loader_guid __initdata = LINUX_EFI_LOADER_ENTRY_GUID;
+ efi_char16_t partuuid_ucs2[UUID_STRING_LEN + 1] = {};
+ unsigned long partuuid_ucs2_size = sizeof(partuuid_ucs2);
+ efi_status_t status;
+
+ if (!efi_rt_services_supported(EFI_RT_SUPPORTED_GET_VARIABLE))
+ return -EOPNOTSUPP;
+
+ status = efi.get_variable(L"LoaderDevicePartUUID", &loader_guid, NULL,
+ &partuuid_ucs2_size, partuuid_ucs2);
+ if (status != EFI_SUCCESS)
+ return efi_status_to_err(status);
+
+ if (ucs2_as_utf8((u8 *)partuuid, partuuid_ucs2, size) != UUID_STRING_LEN ||
+ !uuid_is_valid(partuuid))
+ return -EINVAL;
+
+ return 0;
+}
+
+/**
+ * early_lookup_dps_root - discover the root device by DPS partition type UUID
+ * @dev: receives the discovered device number
+ *
+ * Return: 0 on success, -EINVAL if the ESP partition UUID cannot be read or
+ * is invalid, -EAGAIN if the EFI partition is not yet available, or -ENODEV
+ * if no matching root exists.
+ * With DPS disabled, return 0 and set @dev to zero.
+ */
+int __init early_lookup_dps_root(dev_t *dev)
+{
+ static const char root_type_uuids[][UUID_STRING_LEN + 1] __initconst = {
+ CONFIG_DPS_ROOT_PARTITION_TYPE_UUID,
+ };
+ static char esp_partuuid[UUID_STRING_LEN + 1] __initdata;
+ int err;
+
+ if (!esp_partuuid[0]) {
+ err = efi_get_esp_partuuid(esp_partuuid, sizeof(esp_partuuid));
+ if (err) {
+ pr_err("VFS: Unable to get EFI partition UUID: %pe, skipping root partition discovery\n",
+ ERR_PTR(err));
+ return -EINVAL;
+ }
+ }
+
+ for (int i = 0; i < ARRAY_SIZE(root_type_uuids); i++) {
+ err = early_lookup_bdev_by_type_uuid(root_type_uuids[i],
+ esp_partuuid, dev);
+ if (err != -ENODEV)
+ return err;
+ }
+
+ return -ENODEV;
+}
+#endif /* CONFIG_DPS_ROOT_AUTO_DISCOVERY */
+
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 b99a59cd1120..52bd5683da77 100644
--- a/include/linux/blkdev.h
+++ b/include/linux/blkdev.h
@@ -1746,6 +1746,16 @@ static inline int early_lookup_bdev(const char *pathname, dev_t *dev)
}
#endif /* CONFIG_BLOCK */
+#ifdef CONFIG_DPS_ROOT_AUTO_DISCOVERY
+int __init early_lookup_dps_root(dev_t *dev);
+#else
+static inline int early_lookup_dps_root(dev_t *dev)
+{
+ *dev = 0;
+ return 0;
+}
+#endif
+
int bdev_freeze(struct block_device *bdev);
int bdev_thaw(struct block_device *bdev);
int bdev_deny_freeze(struct block_device *bdev);
diff --git a/init/do_mounts.c b/init/do_mounts.c
index b9814d0cc5a6..0dd9d2a6c00b 100644
--- a/init/do_mounts.c
+++ b/init/do_mounts.c
@@ -406,10 +406,24 @@ static int __init lookup_root_device(const char *root_device_name, dev_t *dev)
{
int err;
- err = early_lookup_bdev(root_device_name, dev);
+ if (root_device_name[0]) {
+ err = early_lookup_bdev(root_device_name, dev);
+ if (err == -EINVAL && root_wait) {
+ pr_err("VFS: root= is invalid; disabling rootwait.\n");
+ root_wait = 0;
+ }
+ return err;
+ }
+
+ err = early_lookup_dps_root(dev);
if (err == -EINVAL && root_wait) {
- pr_err("VFS: root= is invalid; disabling rootwait.\n");
+ pr_err("VFS: Root discovery is unavailable; disabling rootwait.\n");
root_wait = 0;
+ } else if (err == -ENODEV) {
+ pr_err("VFS: No discoverable root partition found; aborting.\n");
+ root_wait = 0;
+ *dev = 0;
+ return 0;
}
return err;
}
@@ -422,7 +436,10 @@ static void __init wait_for_root(char *root_device_name)
if (ROOT_DEV != 0)
return;
- pr_info("Waiting for root device %s...\n", root_device_name);
+ if (root_device_name[0])
+ pr_info("Waiting for root device %s...\n", root_device_name);
+ else if (IS_ENABLED(CONFIG_DPS_ROOT_AUTO_DISCOVERY))
+ pr_info("Waiting for discoverable root partition...\n");
end = ktime_add_ms(ktime_get_raw(), root_wait);
@@ -480,7 +497,7 @@ void __init prepare_namespace(void)
md_run_setup();
- if (saved_root_name[0])
+ if (saved_root_name[0] || !ROOT_DEV)
ROOT_DEV = parse_root_device(saved_root_name);
initrd_load();
--
2.55.0
^ permalink raw reply related [flat|nested] 10+ messages in thread* [PATCH v2 5/7] block: skip partitions with DPS no-auto GPT attribute
2026-10-25 13:03 [PATCH v2 0/7] init: discoverable root partitions Vincent Mailhol
` (3 preceding siblings ...)
2026-10-25 13:03 ` [PATCH v2 4/7] init: discover root by DPS partition type UUID Vincent Mailhol
@ 2026-10-25 13:03 ` Vincent Mailhol
2026-10-25 13:03 ` [PATCH v2 6/7] init: add secondary DPS root partition type UUID Vincent Mailhol
2026-10-25 13:03 ` [PATCH v2 7/7] docs: document discoverable root partitions Vincent Mailhol
6 siblings, 0 replies; 10+ messages in thread
From: Vincent Mailhol @ 2026-10-25 13:03 UTC (permalink / raw)
To: Jens Axboe, Davidlohr Bueso, Alexander Viro, Christian Brauner,
Jan Kara
Cc: linux-kernel, linux-block, linux-efi, linux-fsdevel, Dave Hansen,
James Bottomley, Helge Deller, Matthew Wilcox, Vincent Mailhol
DPS [1] defines GPT attribute bit 63 as no-auto. Partitions with this
bit set must not be used by automatic discovery.
Store the GPT attributes in partition_meta_info and check
GPT_ATTR_NO_AUTO_DISCOVERY when matching a root partition by type UUID.
[1] The Discoverable Partitions Specification (DPS)
Link: https://uapi-group.org/specifications/specs/discoverable_partitions_specification/
Signed-off-by: Vincent Mailhol <mailhol@kernel.org>
---
block/early-lookup.c | 1 +
block/partitions/efi.c | 1 +
include/linux/blkdev.h | 4 ++++
3 files changed, 6 insertions(+)
diff --git a/block/early-lookup.c b/block/early-lookup.c
index a1cb67eab4a0..6c9664eeeb1b 100644
--- a/block/early-lookup.c
+++ b/block/early-lookup.c
@@ -261,6 +261,7 @@ static int __init match_dev_by_type_uuid(struct device *dev, const void *data)
const struct uuidcmp *cmp = data;
return bdev->bd_disk == cmp->disk && bdev->bd_meta_info &&
+ !(bdev->bd_meta_info->gpt_attr & GPT_ATTR_NO_AUTO_DISCOVERY) &&
!strcasecmp(cmp->uuid, bdev->bd_meta_info->type_uuid);
}
diff --git a/block/partitions/efi.c b/block/partitions/efi.c
index 4a3835ed9561..ed5e2f21ad85 100644
--- a/block/partitions/efi.c
+++ b/block/partitions/efi.c
@@ -741,6 +741,7 @@ int efi_partition(struct parsed_partitions *state)
state->parts[i + 1].flags = ADDPART_FLAG_RAID;
info = &state->parts[i + 1].info;
+ info->gpt_attr = le64_to_cpu(ptes[i].attributes);
efi_guid_to_str(&ptes[i].unique_partition_guid, info->uuid);
efi_guid_to_str(&ptes[i].partition_type_guid, info->type_uuid);
diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h
index 52bd5683da77..629ddf1b8b7a 100644
--- a/include/linux/blkdev.h
+++ b/include/linux/blkdev.h
@@ -5,6 +5,7 @@
#ifndef _LINUX_BLKDEV_H
#define _LINUX_BLKDEV_H
+#include <linux/bits.h>
#include <linux/types.h>
#include <linux/blk_types.h>
#include <linux/blk_plug.h>
@@ -65,10 +66,13 @@ extern const struct class block_class;
*/
#define PARTITION_META_INFO_UUIDLTH (UUID_STRING_LEN + 1)
+#define GPT_ATTR_NO_AUTO_DISCOVERY BIT_U64(63)
+
struct partition_meta_info {
char uuid[PARTITION_META_INFO_UUIDLTH];
char type_uuid[PARTITION_META_INFO_UUIDLTH];
u8 volname[PARTITION_META_INFO_VOLNAMELTH];
+ u64 gpt_attr;
};
/**
--
2.55.0
^ permalink raw reply related [flat|nested] 10+ messages in thread* [PATCH v2 6/7] init: add secondary DPS root partition type UUID
2026-10-25 13:03 [PATCH v2 0/7] init: discoverable root partitions Vincent Mailhol
` (4 preceding siblings ...)
2026-10-25 13:03 ` [PATCH v2 5/7] block: skip partitions with DPS no-auto GPT attribute Vincent Mailhol
@ 2026-10-25 13:03 ` Vincent Mailhol
2026-10-25 13:03 ` [PATCH v2 7/7] docs: document discoverable root partitions Vincent Mailhol
6 siblings, 0 replies; 10+ messages in thread
From: Vincent Mailhol @ 2026-10-25 13:03 UTC (permalink / raw)
To: Jens Axboe, Davidlohr Bueso, Alexander Viro, Christian Brauner,
Jan Kara
Cc: linux-kernel, linux-block, linux-efi, linux-fsdevel, Dave Hansen,
James Bottomley, Helge Deller, Matthew Wilcox, Vincent Mailhol
Some 64-bit architectures can run 32-bit user space. For those
configurations, also allow DPS root discovery to use the compatible
32-bit root partition type UUID as a fallback.
Add a secondary root partition type UUID Kconfig symbol and include it
in the DPS root lookup when it is defined.
Try the secondary UUID only when the native lookup returns -ENODEV.
Suggested-by: Dave Hansen <dave.hansen@intel.com>
Link: https://lore.kernel.org/r/03be57ae-0e41-4b8a-adc5-bdd85ccce951@intel.com
Signed-off-by: Vincent Mailhol <mailhol@kernel.org>
---
block/early-lookup.c | 3 +++
init/Kconfig | 7 +++++++
2 files changed, 10 insertions(+)
diff --git a/block/early-lookup.c b/block/early-lookup.c
index 6c9664eeeb1b..b37daa105619 100644
--- a/block/early-lookup.c
+++ b/block/early-lookup.c
@@ -338,6 +338,9 @@ int __init early_lookup_dps_root(dev_t *dev)
{
static const char root_type_uuids[][UUID_STRING_LEN + 1] __initconst = {
CONFIG_DPS_ROOT_PARTITION_TYPE_UUID,
+#ifdef CONFIG_DPS_ROOT_PARTITION_TYPE_UUID_SECONDARY
+ CONFIG_DPS_ROOT_PARTITION_TYPE_UUID_SECONDARY,
+#endif
};
static char esp_partuuid[UUID_STRING_LEN + 1] __initdata;
int err;
diff --git a/init/Kconfig b/init/Kconfig
index 133854355697..b605e2e1f94c 100644
--- a/init/Kconfig
+++ b/init/Kconfig
@@ -2177,6 +2177,13 @@ config DPS_ROOT_PARTITION_TYPE_UUID
default "4f68bce3-e8cd-4db1-96e7-fbcaf984b709" if X86_64
default "44479540-f297-41b2-9af7-d131d5f0458a" if X86
+config DPS_ROOT_PARTITION_TYPE_UUID_SECONDARY
+ depends on DPS_ROOT_PARTITION_TYPE_UUID != "" && COMPAT
+ string
+ default "69dad710-2ce4-4e3c-b16c-21a1d49abed3" if ARM64
+ default "60d5a7fe-8e7d-435c-b714-3dd8162144e1" if RISCV
+ default "44479540-f297-41b2-9af7-d131d5f0458a" if X86_64 && IA32_EMULATION
+
config DPS_ROOT_AUTO_DISCOVERY
def_bool DPS_ROOT_PARTITION_TYPE_UUID != ""
--
2.55.0
^ permalink raw reply related [flat|nested] 10+ messages in thread* [PATCH v2 7/7] docs: document discoverable root partitions
2026-10-25 13:03 [PATCH v2 0/7] init: discoverable root partitions Vincent Mailhol
` (5 preceding siblings ...)
2026-10-25 13:03 ` [PATCH v2 6/7] init: add secondary DPS root partition type UUID Vincent Mailhol
@ 2026-10-25 13:03 ` Vincent Mailhol
6 siblings, 0 replies; 10+ messages in thread
From: Vincent Mailhol @ 2026-10-25 13:03 UTC (permalink / raw)
To: Jens Axboe, Davidlohr Bueso, Alexander Viro, Christian Brauner,
Jan Kara
Cc: linux-kernel, linux-block, linux-efi, linux-fsdevel, Dave Hansen,
James Bottomley, Helge Deller, Matthew Wilcox, Vincent Mailhol,
Jonathan Corbet, Shuah Khan, Randy Dunlap, linux-doc
Document the automatic root block device discovery feature.
Signed-off-by: Vincent Mailhol <mailhol@kernel.org>
---
Cc: Jonathan Corbet <corbet@lwn.net>
Cc: Shuah Khan <skhan@linuxfoundation.org>
Cc: Randy Dunlap <rdunlap@infradead.org>
Cc: linux-doc@vger.kernel.org
---
Documentation/admin-guide/discoverable-root.rst | 40 +++++++++++++++++++++++++
Documentation/admin-guide/index.rst | 1 +
Documentation/admin-guide/kernel-parameters.txt | 5 ++++
3 files changed, 46 insertions(+)
diff --git a/Documentation/admin-guide/discoverable-root.rst b/Documentation/admin-guide/discoverable-root.rst
new file mode 100644
index 000000000000..f4f35cdb39fe
--- /dev/null
+++ b/Documentation/admin-guide/discoverable-root.rst
@@ -0,0 +1,40 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+.. _discoverable_root:
+
+Discoverable root partitions
+============================
+
+On EFI systems, the kernel can discover the root block device from GPT partition
+type UUID metadata on the disk containing the active EFI System Partition.
+
+This follows the `Discoverable Partitions Specification`_ which defines a list
+of architecture-specific root partition type UUIDs.
+
+An initramfs providing an early userspace ``init``, a ``root=`` kernel
+command-line option, or a root device supplied through the boot protocol takes
+precedence over this automatic root partition discovery.
+
+Automatic discovery uses the Boot Loader Interface ``LoaderDevicePartUUID`` EFI
+variable to identify the partition whose disk is searched. This variable is
+provided by the boot loader or, when the kernel is booted directly by EFI
+firmware, by the Linux EFI stub.
+
+The kernel first searches for the native root partition type UUID. On
+architectures that can run compatible 32-bit user space, the matching 32-bit
+root partition type UUID may be used as a fallback if no partition with the
+native type UUID is found. If multiple partitions on that disk match the
+selected type UUID, the kernel selects the first match in block device
+enumeration order, but this may change. Systems should not expose multiple
+eligible root partitions.
+
+Partitions marked with the DPS ``no-auto`` GPT attribute are skipped. This
+allows a partition with an otherwise discoverable type UUID to opt out from
+automatic discovery.
+
+The DPS read-only attribute is not enforced by kernel root discovery. The
+root filesystem is mounted read-only by default unless ``rw`` is specified,
+and user space remains responsible for later remount policy.
+
+.. _Discoverable Partitions Specification:
+ https://uapi-group.org/specifications/specs/discoverable_partitions_specification/
diff --git a/Documentation/admin-guide/index.rst b/Documentation/admin-guide/index.rst
index cd28dfe91b06..0d9c2796ae09 100644
--- a/Documentation/admin-guide/index.rst
+++ b/Documentation/admin-guide/index.rst
@@ -50,6 +50,7 @@ Booting the kernel
bootconfig
kernel-parameters
+ discoverable-root
efi-stub
initrd
diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt
index 03636d799837..75884ef72755 100644
--- a/Documentation/admin-guide/kernel-parameters.txt
+++ b/Documentation/admin-guide/kernel-parameters.txt
@@ -6732,6 +6732,11 @@ Kernel parameters
ramdisk, "nfs" and "cifs" for root on a network file
system, or "mtd" and "ubi" for mounting from raw flash.
+ If this option is omitted, the kernel may try to
+ discover the root block device from the GPT partition
+ type UUID metadata when additional requirements are met.
+ See Documentation/admin-guide/discoverable-root.rst.
+
rootdelay= [KNL] Delay (in seconds) to pause before attempting to
mount the root filesystem
--
2.55.0
^ permalink raw reply related [flat|nested] 10+ messages in thread