diff options
author | Kay Sievers <kay.sievers@vrfy.org> | 2008-05-06 16:31:33 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2008-05-14 13:37:57 -0400 |
commit | 30f2f0eb4bd2c43d10a8b0d872c6e5ad8f31c9a0 (patch) | |
tree | deb8d2a749cd737d9abead1b4cc8321d00dbaee4 | |
parent | 9604006d283fb67dda5ee9e0e15b7cc6c62e1557 (diff) |
block: do_mounts - accept root=<non-existant partition>
Some devices, like md, may create partitions only at first access,
so allow root= to be set to a valid non-existant partition of an
existing disk. This applies only to non-initramfs root mounting.
This fixes a regression from 2.6.24 which did allow this to happen and
broke some users machines :(
Acked-by: Neil Brown <neilb@suse.de>
Tested-by: Joao Luis Meloni Assirati <assirati@nonada.if.usp.br>
Cc: stable <stable@kernel.org>
Signed-off-by: Kay Sievers <kay.sievers@vrfy.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
-rw-r--r-- | block/genhd.c | 9 | ||||
-rw-r--r-- | include/linux/genhd.h | 4 | ||||
-rw-r--r-- | init/do_mounts.c | 27 |
3 files changed, 34 insertions, 6 deletions
diff --git a/block/genhd.c b/block/genhd.c index fda9c7a63c29..129ad939f9dd 100644 --- a/block/genhd.c +++ b/block/genhd.c | |||
@@ -653,7 +653,7 @@ void genhd_media_change_notify(struct gendisk *disk) | |||
653 | EXPORT_SYMBOL_GPL(genhd_media_change_notify); | 653 | EXPORT_SYMBOL_GPL(genhd_media_change_notify); |
654 | #endif /* 0 */ | 654 | #endif /* 0 */ |
655 | 655 | ||
656 | dev_t blk_lookup_devt(const char *name) | 656 | dev_t blk_lookup_devt(const char *name, int part) |
657 | { | 657 | { |
658 | struct device *dev; | 658 | struct device *dev; |
659 | dev_t devt = MKDEV(0, 0); | 659 | dev_t devt = MKDEV(0, 0); |
@@ -661,7 +661,11 @@ dev_t blk_lookup_devt(const char *name) | |||
661 | mutex_lock(&block_class_lock); | 661 | mutex_lock(&block_class_lock); |
662 | list_for_each_entry(dev, &block_class.devices, node) { | 662 | list_for_each_entry(dev, &block_class.devices, node) { |
663 | if (strcmp(dev->bus_id, name) == 0) { | 663 | if (strcmp(dev->bus_id, name) == 0) { |
664 | devt = dev->devt; | 664 | struct gendisk *disk = dev_to_disk(dev); |
665 | |||
666 | if (part < disk->minors) | ||
667 | devt = MKDEV(MAJOR(dev->devt), | ||
668 | MINOR(dev->devt) + part); | ||
665 | break; | 669 | break; |
666 | } | 670 | } |
667 | } | 671 | } |
@@ -669,7 +673,6 @@ dev_t blk_lookup_devt(const char *name) | |||
669 | 673 | ||
670 | return devt; | 674 | return devt; |
671 | } | 675 | } |
672 | |||
673 | EXPORT_SYMBOL(blk_lookup_devt); | 676 | EXPORT_SYMBOL(blk_lookup_devt); |
674 | 677 | ||
675 | struct gendisk *alloc_disk(int minors) | 678 | struct gendisk *alloc_disk(int minors) |
diff --git a/include/linux/genhd.h b/include/linux/genhd.h index e9874e7fcdf9..ae7aec3cabee 100644 --- a/include/linux/genhd.h +++ b/include/linux/genhd.h | |||
@@ -525,7 +525,7 @@ struct unixware_disklabel { | |||
525 | #define ADDPART_FLAG_RAID 1 | 525 | #define ADDPART_FLAG_RAID 1 |
526 | #define ADDPART_FLAG_WHOLEDISK 2 | 526 | #define ADDPART_FLAG_WHOLEDISK 2 |
527 | 527 | ||
528 | extern dev_t blk_lookup_devt(const char *name); | 528 | extern dev_t blk_lookup_devt(const char *name, int part); |
529 | extern char *disk_name (struct gendisk *hd, int part, char *buf); | 529 | extern char *disk_name (struct gendisk *hd, int part, char *buf); |
530 | 530 | ||
531 | extern int rescan_partitions(struct gendisk *disk, struct block_device *bdev); | 531 | extern int rescan_partitions(struct gendisk *disk, struct block_device *bdev); |
@@ -553,7 +553,7 @@ static inline struct block_device *bdget_disk(struct gendisk *disk, int index) | |||
553 | 553 | ||
554 | static inline void printk_all_partitions(void) { } | 554 | static inline void printk_all_partitions(void) { } |
555 | 555 | ||
556 | static inline dev_t blk_lookup_devt(const char *name) | 556 | static inline dev_t blk_lookup_devt(const char *name, int part) |
557 | { | 557 | { |
558 | dev_t devt = MKDEV(0, 0); | 558 | dev_t devt = MKDEV(0, 0); |
559 | return devt; | 559 | return devt; |
diff --git a/init/do_mounts.c b/init/do_mounts.c index 3885e70e7759..660c1e50c91b 100644 --- a/init/do_mounts.c +++ b/init/do_mounts.c | |||
@@ -76,6 +76,7 @@ dev_t name_to_dev_t(char *name) | |||
76 | char s[32]; | 76 | char s[32]; |
77 | char *p; | 77 | char *p; |
78 | dev_t res = 0; | 78 | dev_t res = 0; |
79 | int part; | ||
79 | 80 | ||
80 | if (strncmp(name, "/dev/", 5) != 0) { | 81 | if (strncmp(name, "/dev/", 5) != 0) { |
81 | unsigned maj, min; | 82 | unsigned maj, min; |
@@ -106,7 +107,31 @@ dev_t name_to_dev_t(char *name) | |||
106 | for (p = s; *p; p++) | 107 | for (p = s; *p; p++) |
107 | if (*p == '/') | 108 | if (*p == '/') |
108 | *p = '!'; | 109 | *p = '!'; |
109 | res = blk_lookup_devt(s); | 110 | res = blk_lookup_devt(s, 0); |
111 | if (res) | ||
112 | goto done; | ||
113 | |||
114 | /* | ||
115 | * try non-existant, but valid partition, which may only exist | ||
116 | * after revalidating the disk, like partitioned md devices | ||
117 | */ | ||
118 | while (p > s && isdigit(p[-1])) | ||
119 | p--; | ||
120 | if (p == s || !*p || *p == '0') | ||
121 | goto fail; | ||
122 | |||
123 | /* try disk name without <part number> */ | ||
124 | part = simple_strtoul(p, NULL, 10); | ||
125 | *p = '\0'; | ||
126 | res = blk_lookup_devt(s, part); | ||
127 | if (res) | ||
128 | goto done; | ||
129 | |||
130 | /* try disk name without p<part number> */ | ||
131 | if (p < s + 2 || !isdigit(p[-2]) || p[-1] != 'p') | ||
132 | goto fail; | ||
133 | p[-1] = '\0'; | ||
134 | res = blk_lookup_devt(s, part); | ||
110 | if (res) | 135 | if (res) |
111 | goto done; | 136 | goto done; |
112 | 137 | ||