From b5af921ec02333e943efb59aca4f56b78fc0e100 Mon Sep 17 00:00:00 2001 From: Will Drewry Date: Tue, 31 Aug 2010 15:47:07 -0500 Subject: 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 Signed-off-by: Jens Axboe --- init/do_mounts.c | 66 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 66 insertions(+) (limited to 'init') diff --git a/init/do_mounts.c b/init/do_mounts.c index 02e3ca4fc52..804f9c6ba21 100644 --- a/init/do_mounts.c +++ b/init/do_mounts.c @@ -58,6 +58,60 @@ static int __init readwrite(char *str) __setup("ro", readonly); __setup("rw", readwrite); +/** + * match_dev_by_uuid - callback for finding a partition using its uuid + * @dev: device passed in by the caller + * @data: opaque pointer to a 36 byte char array with a UUID + * + * Returns 1 if the device matches, and 0 otherwise. + */ +static int __init match_dev_by_uuid(struct device *dev, void *data) +{ + u8 *uuid = data; + struct hd_struct *part = dev_to_part(dev); + + if (!part->info) + goto no_match; + + if (memcmp(uuid, part->info->uuid, sizeof(part->info->uuid))) + goto no_match; + + return 1; +no_match: + return 0; +} + + +/** + * devt_from_partuuid - looks up the dev_t of a partition by its UUID + * @uuid: 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. + * + * Returns the matching dev_t on success or 0 on failure. + */ +static dev_t __init devt_from_partuuid(char *uuid_str) +{ + dev_t res = 0; + struct device *dev = NULL; + u8 uuid[16]; + + /* Pack the requested UUID in the expected format. */ + part_pack_uuid(uuid_str, uuid); + + dev = class_find_device(&block_class, NULL, uuid, &match_dev_by_uuid); + if (!dev) + goto done; + + res = dev->devt; + put_device(dev); + +done: + return res; +} + /* * Convert a name into device number. We accept the following variants: * @@ -68,6 +122,8 @@ __setup("rw", readwrite); * of partition - device number of disk plus the partition number * 5) /dev/p - 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. * * 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 @@ -82,6 +138,16 @@ dev_t name_to_dev_t(char *name) dev_t res = 0; int part; + if (strncmp(name, "PARTUUID=", 9) == 0) { + name += 9; + if (strlen(name) != 36) + goto fail; + res = devt_from_partuuid(name); + if (!res) + goto fail; + goto done; + } + if (strncmp(name, "/dev/", 5) != 0) { unsigned maj, min; -- cgit v1.2.3 From 38b6f45a97bbb8536cc7d095b577f580bd4d643e Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Thu, 16 Sep 2010 08:33:54 +0200 Subject: core: match_dev_by_uuid() should not be marked __init It is also called outside the scope of init functions. Stephen reports: WARNING: init/mounts.o(.text+0x21a): Section mismatch in reference from the function name_to_dev_t() to the function .init.text:match_dev_by_uuid() The function name_to_dev_t() references the function __init match_dev_by_uuid(). This is often because name_to_dev_t lacks a __init annotation or the annotation of match_dev_by_uuid is wrong. Reported-by: Stephen Rothwell Signed-off-by: Jens Axboe --- init/do_mounts.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'init') diff --git a/init/do_mounts.c b/init/do_mounts.c index 804f9c6ba21..b7fc83994f3 100644 --- a/init/do_mounts.c +++ b/init/do_mounts.c @@ -65,7 +65,7 @@ __setup("rw", readwrite); * * Returns 1 if the device matches, and 0 otherwise. */ -static int __init match_dev_by_uuid(struct device *dev, void *data) +static int match_dev_by_uuid(struct device *dev, void *data) { u8 *uuid = data; struct hd_struct *part = dev_to_part(dev); -- cgit v1.2.3 From e43473b7f223ec866f7db273697e76c337c390f9 Mon Sep 17 00:00:00 2001 From: Vivek Goyal Date: Wed, 15 Sep 2010 17:06:35 -0400 Subject: blkio: Core implementation of throttle policy o Actual implementation of throttling policy in block layer. Currently it implements READ and WRITE bytes per second throttling logic. IOPS throttling comes in later patches. Signed-off-by: Vivek Goyal Signed-off-by: Jens Axboe --- init/Kconfig | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'init') diff --git a/init/Kconfig b/init/Kconfig index 2de5b1cbadd..950ba26f723 100644 --- a/init/Kconfig +++ b/init/Kconfig @@ -634,11 +634,14 @@ config BLK_CGROUP Currently, CFQ IO scheduler uses it to recognize task groups and control disk bandwidth allocation (proportional time slice allocation) - to such task groups. + to such task groups. It is also used by bio throttling logic in + block layer to implement upper limit in IO rates on a device. This option only enables generic Block IO controller infrastructure. - One needs to also enable actual IO controlling logic in CFQ for it - to take effect. (CONFIG_CFQ_GROUP_IOSCHED=y). + One needs to also enable actual IO controlling logic/policy. For + enabling proportional weight division of disk bandwidth in CFQ seti + CONFIG_CFQ_GROUP_IOSCHED=y and for enabling throttling policy set + CONFIG_BLK_THROTTLE=y. See Documentation/cgroups/blkio-controller.txt for more information. -- cgit v1.2.3 From 6d0aed7a38d06284db2a0e46c0a072b0c1c3299b Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Fri, 17 Sep 2010 10:00:46 +0200 Subject: do_mounts: only enable PARTUUID for CONFIG_BLOCK When CONFIG_BLOCK is not enabled: init/do_mounts.c:71: error: implicit declaration of function 'dev_to_part' init/do_mounts.c:71: warning: initialization makes pointer from integer without a cast init/do_mounts.c:73: error: dereferencing pointer to incomplete type init/do_mounts.c:76: error: dereferencing pointer to incomplete type init/do_mounts.c:76: error: dereferencing pointer to incomplete type init/do_mounts.c:102: error: implicit declaration of function 'part_pack_uuid' init/do_mounts.c:104: error: 'block_class' undeclared (first use in this function) Reported-by: Randy Dunlap Signed-off-by: Jens Axboe --- init/do_mounts.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'init') diff --git a/init/do_mounts.c b/init/do_mounts.c index b7fc83994f3..42db0551c3a 100644 --- a/init/do_mounts.c +++ b/init/do_mounts.c @@ -58,6 +58,7 @@ static int __init readwrite(char *str) __setup("ro", readonly); __setup("rw", readwrite); +#ifdef CONFIG_BLOCK /** * match_dev_by_uuid - callback for finding a partition using its uuid * @dev: device passed in by the caller @@ -111,6 +112,7 @@ static dev_t __init devt_from_partuuid(char *uuid_str) done: return res; } +#endif /* * Convert a name into device number. We accept the following variants: @@ -138,6 +140,7 @@ dev_t name_to_dev_t(char *name) dev_t res = 0; int part; +#ifdef CONFIG_BLOCK if (strncmp(name, "PARTUUID=", 9) == 0) { name += 9; if (strlen(name) != 36) @@ -147,6 +150,7 @@ dev_t name_to_dev_t(char *name) goto fail; goto done; } +#endif if (strncmp(name, "/dev/", 5) != 0) { unsigned maj, min; -- cgit v1.2.3