|
@@ -28,7 +28,7 @@ int __initdata rd_doload; /* 1 = load RAM disk, 0 = don't load */
|
|
|
int root_mountflags = MS_RDONLY | MS_SILENT;
|
|
|
static char * __initdata root_device_name;
|
|
|
static char __initdata saved_root_name[64];
|
|
|
-static int __initdata root_wait;
|
|
|
+static int root_wait;
|
|
|
|
|
|
dev_t ROOT_DEV;
|
|
|
|
|
@@ -85,12 +85,15 @@ no_match:
|
|
|
|
|
|
/**
|
|
|
* devt_from_partuuid - looks up the dev_t of a partition by its UUID
|
|
|
- * @uuid: 36 byte char array containing a hex ascii UUID
|
|
|
+ * @uuid: min 36 byte char array containing a hex 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 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 dev_t devt_from_partuuid(char *uuid_str)
|
|
@@ -98,6 +101,28 @@ static dev_t devt_from_partuuid(char *uuid_str)
|
|
|
dev_t res = 0;
|
|
|
struct device *dev = NULL;
|
|
|
u8 uuid[16];
|
|
|
+ struct gendisk *disk;
|
|
|
+ struct hd_struct *part;
|
|
|
+ int offset = 0;
|
|
|
+
|
|
|
+ if (strlen(uuid_str) < 36)
|
|
|
+ goto done;
|
|
|
+
|
|
|
+ /* Check for optional partition number offset attributes. */
|
|
|
+ if (uuid_str[36]) {
|
|
|
+ char c = 0;
|
|
|
+ /* Explicitly fail on poor PARTUUID syntax. */
|
|
|
+ if (sscanf(&uuid_str[36],
|
|
|
+ "/PARTNROFF=%d%c", &offset, &c) != 1) {
|
|
|
+ printk(KERN_ERR "VFS: PARTUUID= is invalid.\n"
|
|
|
+ "Expected PARTUUID=<valid-uuid-id>[/PARTNROFF=%%d]\n");
|
|
|
+ if (root_wait)
|
|
|
+ printk(KERN_ERR
|
|
|
+ "Disabling rootwait; root= is invalid.\n");
|
|
|
+ root_wait = 0;
|
|
|
+ goto done;
|
|
|
+ }
|
|
|
+ }
|
|
|
|
|
|
/* Pack the requested UUID in the expected format. */
|
|
|
part_pack_uuid(uuid_str, uuid);
|
|
@@ -107,8 +132,21 @@ static dev_t devt_from_partuuid(char *uuid_str)
|
|
|
goto done;
|
|
|
|
|
|
res = dev->devt;
|
|
|
- put_device(dev);
|
|
|
|
|
|
+ /* Attempt to find the partition by offset. */
|
|
|
+ if (!offset)
|
|
|
+ goto no_offset;
|
|
|
+
|
|
|
+ res = 0;
|
|
|
+ disk = part_to_disk(dev_to_part(dev));
|
|
|
+ part = disk_get_part(disk, dev_to_part(dev)->partno + offset);
|
|
|
+ if (part) {
|
|
|
+ res = part_devt(part);
|
|
|
+ put_device(part_to_dev(part));
|
|
|
+ }
|
|
|
+
|
|
|
+no_offset:
|
|
|
+ put_device(dev);
|
|
|
done:
|
|
|
return res;
|
|
|
}
|
|
@@ -126,6 +164,8 @@ done:
|
|
|
* 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.
|
|
|
+ * 7) PARTUUID=<UUID>/PARTNROFF=<int> to select a partition in relation to
|
|
|
+ * a partition with a known unique id.
|
|
|
*
|
|
|
* 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
|
|
@@ -143,8 +183,6 @@ dev_t name_to_dev_t(char *name)
|
|
|
#ifdef CONFIG_BLOCK
|
|
|
if (strncmp(name, "PARTUUID=", 9) == 0) {
|
|
|
name += 9;
|
|
|
- if (strlen(name) != 36)
|
|
|
- goto fail;
|
|
|
res = devt_from_partuuid(name);
|
|
|
if (!res)
|
|
|
goto fail;
|