From: Christoph Hellwig <hch@lst.de>
To: Jens Axboe <axboe@kernel.dk>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>,
"Rafael J. Wysocki" <rafael@kernel.org>,
Mike Snitzer <snitzer@kernel.org>,
Joern Engel <joern@lazybastard.org>,
Miquel Raynal <miquel.raynal@bootlin.com>,
Richard Weinberger <richard@nod.at>,
Vignesh Raghavendra <vigneshr@ti.com>,
Pavel Machek <pavel@ucw.cz>,
Loic Poulain <loic.poulain@linaro.org>,
dm-devel@redhat.com, linux-kernel@vger.kernel.org,
linux-block@vger.kernel.org, linux-mtd@lists.infradead.org,
linux-pm@vger.kernel.org
Subject: [PATCH 15/24] block: move the code to do early boot lookup of block devices to block/
Date: Wed, 31 May 2023 14:55:26 +0200 [thread overview]
Message-ID: <20230531125535.676098-16-hch@lst.de> (raw)
In-Reply-To: <20230531125535.676098-1-hch@lst.de>
Create a new block/early-lookup.c to keep the early block device lookup
code instead of having this code sit with the early mount code.
Signed-off-by: Christoph Hellwig <hch@lst.de>
---
.../admin-guide/kernel-parameters.txt | 4 +-
block/Makefile | 2 +-
block/early-lookup.c | 224 ++++++++++++++++++
init/do_mounts.c | 219 -----------------
4 files changed, 227 insertions(+), 222 deletions(-)
create mode 100644 block/early-lookup.c
diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt
index a6bc31349cbb76..911c54829c7c59 100644
--- a/Documentation/admin-guide/kernel-parameters.txt
+++ b/Documentation/admin-guide/kernel-parameters.txt
@@ -5453,8 +5453,8 @@
root= [KNL] Root filesystem
Usually this a a block device specifier of some kind,
- see the early_lookup_bdev comment in init/do_mounts.c
- for details.
+ see the early_lookup_bdev comment in
+ block/early-lookup.c for details.
Alternatively this can be "ram" for the legacy initial
ramdisk, "nfs" and "cifs" for root on a network file
system, or "mtd" and "ubi" for mounting from raw flash.
diff --git a/block/Makefile b/block/Makefile
index b31b05390749a1..46ada9dc8bbfe2 100644
--- a/block/Makefile
+++ b/block/Makefile
@@ -9,7 +9,7 @@ obj-y := bdev.o fops.o bio.o elevator.o blk-core.o blk-sysfs.o \
blk-lib.o blk-mq.o blk-mq-tag.o blk-stat.o \
blk-mq-sysfs.o blk-mq-cpumap.o blk-mq-sched.o ioctl.o \
genhd.o ioprio.o badblocks.o partitions/ blk-rq-qos.o \
- disk-events.o blk-ia-ranges.o
+ disk-events.o blk-ia-ranges.o early-lookup.o
obj-$(CONFIG_BOUNCE) += bounce.o
obj-$(CONFIG_BLK_DEV_BSG_COMMON) += bsg.o
diff --git a/block/early-lookup.c b/block/early-lookup.c
new file mode 100644
index 00000000000000..9fc30d039508af
--- /dev/null
+++ b/block/early-lookup.c
@@ -0,0 +1,224 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Code for looking up block devices in the early boot code before mounting the
+ * root file system. Unfortunately currently also abused in a few other places.
+ */
+#include <linux/blkdev.h>
+#include <linux/ctype.h>
+
+struct uuidcmp {
+ const char *uuid;
+ int len;
+};
+
+/**
+ * match_dev_by_uuid - callback for finding a partition using its 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 match_dev_by_uuid(struct device *dev, const void *data)
+{
+ struct block_device *bdev = dev_to_bdev(dev);
+ const struct uuidcmp *cmp = data;
+
+ if (!bdev->bd_meta_info ||
+ strncasecmp(cmp->uuid, bdev->bd_meta_info->uuid, cmp->len))
+ return 0;
+ return 1;
+}
+
+/**
+ * devt_from_partuuid - looks up the dev_t of a partition by its UUID
+ * @uuid_str: char array containing ascii UUID
+ *
+ * The function will return the first partition which contains a matching
+ * UUID value in its partition_meta_info struct. This does not search
+ * by filesystem UUIDs.
+ *
+ * If @uuid_str is followed by a "/PARTNROFF=%d", then the number will be
+ * extracted and used as an offset from the partition identified by the UUID.
+ *
+ * Returns the matching dev_t on success or 0 on failure.
+ */
+static int devt_from_partuuid(const char *uuid_str, dev_t *devt)
+{
+ struct uuidcmp cmp;
+ 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) {
+ char c = 0;
+
+ /* Explicitly fail on poor PARTUUID syntax. */
+ if (sscanf(slash + 1, "PARTNROFF=%d%c", &offset, &c) != 1)
+ goto out_invalid;
+ cmp.len = slash - uuid_str;
+ } else {
+ cmp.len = strlen(uuid_str);
+ }
+
+ if (!cmp.len)
+ goto out_invalid;
+
+ dev = class_find_device(&block_class, NULL, &cmp, &match_dev_by_uuid);
+ if (!dev)
+ return -ENODEV;
+
+ if (offset) {
+ /*
+ * Attempt to find the requested partition by adding an offset
+ * to the partition number found by UUID.
+ */
+ *devt = part_devt(dev_to_disk(dev),
+ dev_to_bdev(dev)->bd_partno + offset);
+ } else {
+ *devt = dev->devt;
+ }
+
+ put_device(dev);
+ return 0;
+
+out_invalid:
+ pr_err("VFS: PARTUUID= is invalid.\n"
+ "Expected PARTUUID=<valid-uuid-id>[/PARTNROFF=%%d]\n");
+ return -EINVAL;
+}
+
+/**
+ * match_dev_by_label - callback for finding a partition using its label
+ * @dev: device passed in by the caller
+ * @data: opaque pointer to the label to match
+ *
+ * Returns 1 if the device matches, and 0 otherwise.
+ */
+static int match_dev_by_label(struct device *dev, const void *data)
+{
+ struct block_device *bdev = dev_to_bdev(dev);
+ const char *label = data;
+
+ if (!bdev->bd_meta_info || strcmp(label, bdev->bd_meta_info->volname))
+ return 0;
+ return 1;
+}
+
+static int devt_from_partlabel(const char *label, dev_t *devt)
+{
+ struct device *dev;
+
+ dev = class_find_device(&block_class, NULL, label, &match_dev_by_label);
+ if (!dev)
+ return -ENODEV;
+ *devt = dev->devt;
+ put_device(dev);
+ return 0;
+}
+
+static int devt_from_devname(const char *name, dev_t *devt)
+{
+ int part;
+ char s[32];
+ char *p;
+
+ if (strlen(name) > 31)
+ return -EINVAL;
+ strcpy(s, name);
+ for (p = s; *p; p++) {
+ if (*p == '/')
+ *p = '!';
+ }
+
+ *devt = blk_lookup_devt(s, 0);
+ if (*devt)
+ return 0;
+
+ /*
+ * Try non-existent, but valid partition, which may only exist after
+ * opening the device, like partitioned md devices.
+ */
+ while (p > s && isdigit(p[-1]))
+ p--;
+ if (p == s || !*p || *p == '0')
+ return -EINVAL;
+
+ /* try disk name without <part number> */
+ part = simple_strtoul(p, NULL, 10);
+ *p = '\0';
+ *devt = blk_lookup_devt(s, part);
+ if (*devt)
+ return 0;
+
+ /* try disk name without p<part number> */
+ if (p < s + 2 || !isdigit(p[-2]) || p[-1] != 'p')
+ return -EINVAL;
+ p[-1] = '\0';
+ *devt = blk_lookup_devt(s, part);
+ if (*devt)
+ return 0;
+ return -EINVAL;
+}
+
+static int devt_from_devnum(const char *name, dev_t *devt)
+{
+ unsigned maj, min, offset;
+ char *p, dummy;
+
+ if (sscanf(name, "%u:%u%c", &maj, &min, &dummy) == 2 ||
+ sscanf(name, "%u:%u:%u:%c", &maj, &min, &offset, &dummy) == 3) {
+ *devt = MKDEV(maj, min);
+ if (maj != MAJOR(*devt) || min != MINOR(*devt))
+ return -EINVAL;
+ } else {
+ *devt = new_decode_dev(simple_strtoul(name, &p, 16));
+ if (*p)
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+/*
+ * Convert a name into device number. We accept the following variants:
+ *
+ * 1) <hex_major><hex_minor> device number in hexadecimal represents itself
+ * no leading 0x, for example b302.
+ * 3) /dev/<disk_name> represents the device number of disk
+ * 4) /dev/<disk_name><decimal> represents the device number
+ * of partition - device number of disk plus the partition number
+ * 5) /dev/<disk_name>p<decimal> - same as the above, that form is
+ * used when disk name of partitioned disk ends on a digit.
+ * 6) PARTUUID=00112233-4455-6677-8899-AABBCCDDEEFF representing the
+ * unique id of a partition if the partition table provides it.
+ * The UUID may be either an EFI/GPT UUID, or refer to an MSDOS
+ * partition using the format SSSSSSSS-PP, where SSSSSSSS is a zero-
+ * filled hex representation of the 32-bit "NT disk signature", and PP
+ * is a zero-filled hex representation of the 1-based partition number.
+ * 7) PARTUUID=<UUID>/PARTNROFF=<int> to select a partition in relation to
+ * a partition with a known unique id.
+ * 8) <major>:<minor> major and minor number of the device separated by
+ * a colon.
+ * 9) PARTLABEL=<name> with name being the GPT partition label.
+ * MSDOS partitions do not support labels!
+ *
+ * If name doesn't have fall into the categories above, we return (0,0).
+ * block_class is used to check if something is a disk name. If the disk
+ * name contains slashes, the device name has them replaced with
+ * bangs.
+ */
+int early_lookup_bdev(const char *name, dev_t *devt)
+{
+ if (strncmp(name, "PARTUUID=", 9) == 0)
+ return devt_from_partuuid(name + 9, devt);
+ if (strncmp(name, "PARTLABEL=", 10) == 0)
+ return devt_from_partlabel(name + 10, devt);
+ if (strncmp(name, "/dev/", 5) == 0)
+ return devt_from_devname(name + 5, devt);
+ return devt_from_devnum(name, devt);
+}
+EXPORT_SYMBOL_GPL(early_lookup_bdev);
diff --git a/init/do_mounts.c b/init/do_mounts.c
index 0b36a5f39ee8e2..780546a6cbfb6f 100644
--- a/init/do_mounts.c
+++ b/init/do_mounts.c
@@ -59,225 +59,6 @@ static int __init readwrite(char *str)
__setup("ro", readonly);
__setup("rw", readwrite);
-#ifdef CONFIG_BLOCK
-struct uuidcmp {
- const char *uuid;
- int len;
-};
-
-/**
- * match_dev_by_uuid - callback for finding a partition using its 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 match_dev_by_uuid(struct device *dev, const void *data)
-{
- struct block_device *bdev = dev_to_bdev(dev);
- const struct uuidcmp *cmp = data;
-
- if (!bdev->bd_meta_info ||
- strncasecmp(cmp->uuid, bdev->bd_meta_info->uuid, cmp->len))
- return 0;
- return 1;
-}
-
-/**
- * devt_from_partuuid - looks up the dev_t of a partition by its UUID
- * @uuid_str: char array containing ascii UUID
- *
- * The function will return the first partition which contains a matching
- * UUID value in its partition_meta_info struct. This does not search
- * by filesystem UUIDs.
- *
- * If @uuid_str is followed by a "/PARTNROFF=%d", then the number will be
- * extracted and used as an offset from the partition identified by the UUID.
- *
- * Returns the matching dev_t on success or 0 on failure.
- */
-static int devt_from_partuuid(const char *uuid_str, dev_t *devt)
-{
- struct uuidcmp cmp;
- 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) {
- char c = 0;
-
- /* Explicitly fail on poor PARTUUID syntax. */
- if (sscanf(slash + 1, "PARTNROFF=%d%c", &offset, &c) != 1)
- goto out_invalid;
- cmp.len = slash - uuid_str;
- } else {
- cmp.len = strlen(uuid_str);
- }
-
- if (!cmp.len)
- goto out_invalid;
-
- dev = class_find_device(&block_class, NULL, &cmp, &match_dev_by_uuid);
- if (!dev)
- return -ENODEV;
-
- if (offset) {
- /*
- * Attempt to find the requested partition by adding an offset
- * to the partition number found by UUID.
- */
- *devt = part_devt(dev_to_disk(dev),
- dev_to_bdev(dev)->bd_partno + offset);
- } else {
- *devt = dev->devt;
- }
-
- put_device(dev);
- return 0;
-
-out_invalid:
- pr_err("VFS: PARTUUID= is invalid.\n"
- "Expected PARTUUID=<valid-uuid-id>[/PARTNROFF=%%d]\n");
- return -EINVAL;
-}
-
-/**
- * match_dev_by_label - callback for finding a partition using its label
- * @dev: device passed in by the caller
- * @data: opaque pointer to the label to match
- *
- * Returns 1 if the device matches, and 0 otherwise.
- */
-static int match_dev_by_label(struct device *dev, const void *data)
-{
- struct block_device *bdev = dev_to_bdev(dev);
- const char *label = data;
-
- if (!bdev->bd_meta_info || strcmp(label, bdev->bd_meta_info->volname))
- return 0;
- return 1;
-}
-
-static int devt_from_partlabel(const char *label, dev_t *devt)
-{
- struct device *dev;
-
- dev = class_find_device(&block_class, NULL, label, &match_dev_by_label);
- if (!dev)
- return -ENODEV;
- *devt = dev->devt;
- put_device(dev);
- return 0;
-}
-
-static int devt_from_devname(const char *name, dev_t *devt)
-{
- int part;
- char s[32];
- char *p;
-
- if (strlen(name) > 31)
- return -EINVAL;
- strcpy(s, name);
- for (p = s; *p; p++) {
- if (*p == '/')
- *p = '!';
- }
-
- *devt = blk_lookup_devt(s, 0);
- if (*devt)
- return 0;
-
- /*
- * Try non-existent, but valid partition, which may only exist after
- * opening the device, like partitioned md devices.
- */
- while (p > s && isdigit(p[-1]))
- p--;
- if (p == s || !*p || *p == '0')
- return -EINVAL;
-
- /* try disk name without <part number> */
- part = simple_strtoul(p, NULL, 10);
- *p = '\0';
- *devt = blk_lookup_devt(s, part);
- if (*devt)
- return 0;
-
- /* try disk name without p<part number> */
- if (p < s + 2 || !isdigit(p[-2]) || p[-1] != 'p')
- return -EINVAL;
- p[-1] = '\0';
- *devt = blk_lookup_devt(s, part);
- if (*devt)
- return 0;
- return -EINVAL;
-}
-
-static int devt_from_devnum(const char *name, dev_t *devt)
-{
- unsigned maj, min, offset;
- char *p, dummy;
-
- if (sscanf(name, "%u:%u%c", &maj, &min, &dummy) == 2 ||
- sscanf(name, "%u:%u:%u:%c", &maj, &min, &offset, &dummy) == 3) {
- *devt = MKDEV(maj, min);
- if (maj != MAJOR(*devt) || min != MINOR(*devt))
- return -EINVAL;
- } else {
- *devt = new_decode_dev(simple_strtoul(name, &p, 16));
- if (*p)
- return -EINVAL;
- }
-
- return 0;
-}
-
-/*
- * Convert a name into device number. We accept the following variants:
- *
- * 1) <hex_major><hex_minor> device number in hexadecimal represents itself
- * no leading 0x, for example b302.
- * 3) /dev/<disk_name> represents the device number of disk
- * 4) /dev/<disk_name><decimal> represents the device number
- * of partition - device number of disk plus the partition number
- * 5) /dev/<disk_name>p<decimal> - same as the above, that form is
- * used when disk name of partitioned disk ends on a digit.
- * 6) PARTUUID=00112233-4455-6677-8899-AABBCCDDEEFF representing the
- * unique id of a partition if the partition table provides it.
- * The UUID may be either an EFI/GPT UUID, or refer to an MSDOS
- * partition using the format SSSSSSSS-PP, where SSSSSSSS is a zero-
- * filled hex representation of the 32-bit "NT disk signature", and PP
- * is a zero-filled hex representation of the 1-based partition number.
- * 7) PARTUUID=<UUID>/PARTNROFF=<int> to select a partition in relation to
- * a partition with a known unique id.
- * 8) <major>:<minor> major and minor number of the device separated by
- * a colon.
- * 9) PARTLABEL=<name> with name being the GPT partition label.
- * MSDOS partitions do not support labels!
- *
- * If name doesn't have fall into the categories above, we return (0,0).
- * block_class is used to check if something is a disk name. If the disk
- * name contains slashes, the device name has them replaced with
- * bangs.
- */
-int early_lookup_bdev(const char *name, dev_t *devt)
-{
- if (strncmp(name, "PARTUUID=", 9) == 0)
- return devt_from_partuuid(name + 9, devt);
- if (strncmp(name, "PARTLABEL=", 10) == 0)
- return devt_from_partlabel(name + 10, devt);
- if (strncmp(name, "/dev/", 5) == 0)
- return devt_from_devname(name + 5, devt);
- return devt_from_devnum(name, devt);
-}
-EXPORT_SYMBOL_GPL(early_lookup_bdev);
-#endif
-
static int __init root_dev_setup(char *line)
{
strscpy(saved_root_name, line, sizeof(saved_root_name));
--
2.39.2
next prev parent reply other threads:[~2023-05-31 12:58 UTC|newest]
Thread overview: 38+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-05-31 12:55 fix the name_to_dev_t mess v2 Christoph Hellwig
2023-05-31 12:55 ` [PATCH 01/24] driver core: return bool from driver_probe_done Christoph Hellwig
2023-06-05 17:22 ` Jens Axboe
2023-05-31 12:55 ` [PATCH 02/24] PM: hibernate: factor out a helper to find the resume device Christoph Hellwig
2023-05-31 12:55 ` [PATCH 03/24] PM: hibernate: remove the global snapshot_test variable Christoph Hellwig
2023-05-31 12:55 ` [PATCH 04/24] PM: hibernate: move finding the resume device out of software_resume Christoph Hellwig
2023-08-03 8:27 ` Vlastimil Babka
2023-08-04 10:31 ` Christoph Hellwig
2023-08-04 13:30 ` Greg Kroah-Hartman
2023-08-05 13:07 ` Linux regression tracking #adding (Thorsten Leemhuis)
2023-05-31 12:55 ` [PATCH 05/24] init: remove pointless Root_* values Christoph Hellwig
2023-05-31 12:55 ` [PATCH 06/24] init: rename mount_block_root to mount_root_generic Christoph Hellwig
2023-05-31 12:55 ` [PATCH 07/24] init: refactor mount_root Christoph Hellwig
2023-05-31 12:55 ` [PATCH 08/24] init: pass root_device_name explicitly Christoph Hellwig
2023-06-24 0:08 ` Guenter Roeck
2023-06-26 7:53 ` Christoph Hellwig
2023-06-26 14:50 ` Guenter Roeck
2023-06-27 10:38 ` Max Filippov
2023-05-31 12:55 ` [PATCH 09/24] init: don't remove the /dev/ prefix from error messages Christoph Hellwig
2023-05-31 12:55 ` [PATCH 10/24] init: handle ubi/mtd root mounting like all other root types Christoph Hellwig
2023-05-31 12:55 ` [PATCH 11/24] init: factor the root_wait logic in prepare_namespace into a helper Christoph Hellwig
2023-05-31 12:55 ` [PATCH 12/24] init: move the nfs/cifs/ram special cases out of name_to_dev_t Christoph Hellwig
2023-05-31 12:55 ` [PATCH 13/24] init: improve the name_to_dev_t interface Christoph Hellwig
2023-05-31 12:55 ` [PATCH 14/24] init: clear root_wait on all invalid root= strings Christoph Hellwig
2023-05-31 12:55 ` Christoph Hellwig [this message]
2023-05-31 12:55 ` [PATCH 16/24] block: move more code to early-lookup.c Christoph Hellwig
2023-05-31 12:55 ` [PATCH 17/24] dm-snap: simplify the origin_dev == cow_dev check in snapshot_ctr Christoph Hellwig
2023-05-31 12:55 ` [PATCH 18/24] dm: open code dm_get_dev_t in dm_init_init Christoph Hellwig
2023-05-31 12:55 ` [PATCH 19/24] dm: remove dm_get_dev_t Christoph Hellwig
2023-05-31 12:55 ` [PATCH 20/24] dm: only call early_lookup_bdev from early boot context Christoph Hellwig
2023-05-31 12:55 ` [PATCH 21/24] PM: hibernate: don't use early_lookup_bdev in resume_store Christoph Hellwig
2023-05-31 12:55 ` [PATCH 22/24] mtd: block2mtd: factor the early block device open logic into a helper Christoph Hellwig
2023-05-31 12:55 ` [PATCH 23/24] mtd: block2mtd: don't call early_lookup_bdev after the system is running Christoph Hellwig
2023-05-31 12:55 ` [PATCH 24/24] block: mark early_lookup_bdev as __init Christoph Hellwig
-- strict thread matches above, loose matches on Subject: below --
2023-05-23 7:45 fix the name_to_dev_t mess Christoph Hellwig
2023-05-23 7:45 ` [PATCH 15/24] block: move the code to do early boot lookup of block devices to block/ Christoph Hellwig
2023-05-24 4:58 ` Randy Dunlap
2023-05-24 4:59 ` Randy Dunlap
2023-05-24 6:08 ` Christoph Hellwig
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20230531125535.676098-16-hch@lst.de \
--to=hch@lst.de \
--cc=axboe@kernel.dk \
--cc=dm-devel@redhat.com \
--cc=gregkh@linuxfoundation.org \
--cc=joern@lazybastard.org \
--cc=linux-block@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-mtd@lists.infradead.org \
--cc=linux-pm@vger.kernel.org \
--cc=loic.poulain@linaro.org \
--cc=miquel.raynal@bootlin.com \
--cc=pavel@ucw.cz \
--cc=rafael@kernel.org \
--cc=richard@nod.at \
--cc=snitzer@kernel.org \
--cc=vigneshr@ti.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).