aboutsummaryrefslogtreecommitdiffstats
path: root/init
diff options
context:
space:
mode:
authorWill Drewry <wad@chromium.org>2010-08-31 16:47:07 -0400
committerJens Axboe <jaxboe@fusionio.com>2010-09-15 10:14:03 -0400
commitb5af921ec02333e943efb59aca4f56b78fc0e100 (patch)
treefcf966ccbee9c5f8b8f652100f033bc781b91b91 /init
parenteec7ecfede74bb996060efefd5c157acd5794e8a (diff)
init: add support for root devices specified by partition UUID
This is the third patch in a series which adds support for storing partition metadata, optionally, off of the hd_struct. One major use for that data is being able to resolve partition by other identities than just the index on a block device. Device enumeration varies by platform and there's a benefit to being able to use something like EFI GPT's GUIDs to determine the correct block device and partition to mount as the root. This change adds that support to root= by adding support for the following syntax: root=PARTUUID=hex-uuid Signed-off-by: Will Drewry <wad@chromium.org> Signed-off-by: Jens Axboe <jaxboe@fusionio.com>
Diffstat (limited to 'init')
-rw-r--r--init/do_mounts.c66
1 files changed, 66 insertions, 0 deletions
diff --git a/init/do_mounts.c b/init/do_mounts.c
index 02e3ca4fc527..804f9c6ba216 100644
--- a/init/do_mounts.c
+++ b/init/do_mounts.c
@@ -58,6 +58,60 @@ static int __init readwrite(char *str)
58__setup("ro", readonly); 58__setup("ro", readonly);
59__setup("rw", readwrite); 59__setup("rw", readwrite);
60 60
61/**
62 * match_dev_by_uuid - callback for finding a partition using its uuid
63 * @dev: device passed in by the caller
64 * @data: opaque pointer to a 36 byte char array with a UUID
65 *
66 * Returns 1 if the device matches, and 0 otherwise.
67 */
68static int __init match_dev_by_uuid(struct device *dev, void *data)
69{
70 u8 *uuid = data;
71 struct hd_struct *part = dev_to_part(dev);
72
73 if (!part->info)
74 goto no_match;
75
76 if (memcmp(uuid, part->info->uuid, sizeof(part->info->uuid)))
77 goto no_match;
78
79 return 1;
80no_match:
81 return 0;
82}
83
84
85/**
86 * devt_from_partuuid - looks up the dev_t of a partition by its UUID
87 * @uuid: 36 byte char array containing a hex ascii UUID
88 *
89 * The function will return the first partition which contains a matching
90 * UUID value in its partition_meta_info struct. This does not search
91 * by filesystem UUIDs.
92 *
93 * Returns the matching dev_t on success or 0 on failure.
94 */
95static dev_t __init devt_from_partuuid(char *uuid_str)
96{
97 dev_t res = 0;
98 struct device *dev = NULL;
99 u8 uuid[16];
100
101 /* Pack the requested UUID in the expected format. */
102 part_pack_uuid(uuid_str, uuid);
103
104 dev = class_find_device(&block_class, NULL, uuid, &match_dev_by_uuid);
105 if (!dev)
106 goto done;
107
108 res = dev->devt;
109 put_device(dev);
110
111done:
112 return res;
113}
114
61/* 115/*
62 * Convert a name into device number. We accept the following variants: 116 * Convert a name into device number. We accept the following variants:
63 * 117 *
@@ -68,6 +122,8 @@ __setup("rw", readwrite);
68 * of partition - device number of disk plus the partition number 122 * of partition - device number of disk plus the partition number
69 * 5) /dev/<disk_name>p<decimal> - same as the above, that form is 123 * 5) /dev/<disk_name>p<decimal> - same as the above, that form is
70 * used when disk name of partitioned disk ends on a digit. 124 * used when disk name of partitioned disk ends on a digit.
125 * 6) PARTUUID=00112233-4455-6677-8899-AABBCCDDEEFF representing the
126 * unique id of a partition if the partition table provides it.
71 * 127 *
72 * If name doesn't have fall into the categories above, we return (0,0). 128 * If name doesn't have fall into the categories above, we return (0,0).
73 * block_class is used to check if something is a disk name. If the disk 129 * block_class is used to check if something is a disk name. If the disk
@@ -82,6 +138,16 @@ dev_t name_to_dev_t(char *name)
82 dev_t res = 0; 138 dev_t res = 0;
83 int part; 139 int part;
84 140
141 if (strncmp(name, "PARTUUID=", 9) == 0) {
142 name += 9;
143 if (strlen(name) != 36)
144 goto fail;
145 res = devt_from_partuuid(name);
146 if (!res)
147 goto fail;
148 goto done;
149 }
150
85 if (strncmp(name, "/dev/", 5) != 0) { 151 if (strncmp(name, "/dev/", 5) != 0) {
86 unsigned maj, min; 152 unsigned maj, min;
87 153