diff options
| -rw-r--r-- | block/genhd.c | 53 | ||||
| -rw-r--r-- | include/linux/genhd.h | 1 | ||||
| -rw-r--r-- | init/do_mounts.c | 7 |
3 files changed, 60 insertions, 1 deletions
diff --git a/block/genhd.c b/block/genhd.c index b566444089..93a2cf6545 100644 --- a/block/genhd.c +++ b/block/genhd.c | |||
| @@ -213,6 +213,59 @@ struct gendisk *get_gendisk(dev_t dev, int *part) | |||
| 213 | return kobj ? to_disk(kobj) : NULL; | 213 | return kobj ? to_disk(kobj) : NULL; |
| 214 | } | 214 | } |
| 215 | 215 | ||
| 216 | /* | ||
| 217 | * print a full list of all partitions - intended for places where the root | ||
| 218 | * filesystem can't be mounted and thus to give the victim some idea of what | ||
| 219 | * went wrong | ||
| 220 | */ | ||
| 221 | void __init printk_all_partitions(void) | ||
| 222 | { | ||
| 223 | int n; | ||
| 224 | struct gendisk *sgp; | ||
| 225 | |||
| 226 | mutex_lock(&block_subsys_lock); | ||
| 227 | /* For each block device... */ | ||
| 228 | list_for_each_entry(sgp, &block_subsys.list, kobj.entry) { | ||
| 229 | char buf[BDEVNAME_SIZE]; | ||
| 230 | /* | ||
| 231 | * Don't show empty devices or things that have been surpressed | ||
| 232 | */ | ||
| 233 | if (get_capacity(sgp) == 0 || | ||
| 234 | (sgp->flags & GENHD_FL_SUPPRESS_PARTITION_INFO)) | ||
| 235 | continue; | ||
| 236 | |||
| 237 | /* | ||
| 238 | * Note, unlike /proc/partitions, I am showing the numbers in | ||
| 239 | * hex - the same format as the root= option takes. | ||
| 240 | */ | ||
| 241 | printk("%02x%02x %10llu %s", | ||
| 242 | sgp->major, sgp->first_minor, | ||
| 243 | (unsigned long long)get_capacity(sgp) >> 1, | ||
| 244 | disk_name(sgp, 0, buf)); | ||
| 245 | if (sgp->driverfs_dev != NULL && | ||
| 246 | sgp->driverfs_dev->driver != NULL) | ||
| 247 | printk(" driver: %s\n", | ||
| 248 | sgp->driverfs_dev->driver->name); | ||
| 249 | else | ||
| 250 | printk(" (driver?)\n"); | ||
| 251 | |||
| 252 | /* now show the partitions */ | ||
| 253 | for (n = 0; n < sgp->minors - 1; ++n) { | ||
| 254 | if (sgp->part[n] == NULL) | ||
| 255 | continue; | ||
| 256 | if (sgp->part[n]->nr_sects == 0) | ||
| 257 | continue; | ||
| 258 | printk(" %02x%02x %10llu %s\n", | ||
| 259 | sgp->major, n + 1 + sgp->first_minor, | ||
| 260 | (unsigned long long)sgp->part[n]->nr_sects >> 1, | ||
| 261 | disk_name(sgp, n + 1, buf)); | ||
| 262 | } /* partition subloop */ | ||
| 263 | } /* Block device loop */ | ||
| 264 | |||
| 265 | mutex_unlock(&block_subsys_lock); | ||
| 266 | return; | ||
| 267 | } | ||
| 268 | |||
| 216 | #ifdef CONFIG_PROC_FS | 269 | #ifdef CONFIG_PROC_FS |
| 217 | /* iterator */ | 270 | /* iterator */ |
| 218 | static void *part_start(struct seq_file *part, loff_t *pos) | 271 | static void *part_start(struct seq_file *part, loff_t *pos) |
diff --git a/include/linux/genhd.h b/include/linux/genhd.h index 2c65da7cab..f589559cf0 100644 --- a/include/linux/genhd.h +++ b/include/linux/genhd.h | |||
| @@ -413,6 +413,7 @@ char *disk_name (struct gendisk *hd, int part, char *buf); | |||
| 413 | extern int rescan_partitions(struct gendisk *disk, struct block_device *bdev); | 413 | extern int rescan_partitions(struct gendisk *disk, struct block_device *bdev); |
| 414 | extern void add_partition(struct gendisk *, int, sector_t, sector_t, int); | 414 | extern void add_partition(struct gendisk *, int, sector_t, sector_t, int); |
| 415 | extern void delete_partition(struct gendisk *, int); | 415 | extern void delete_partition(struct gendisk *, int); |
| 416 | extern void printk_all_partitions(void); | ||
| 416 | 417 | ||
| 417 | extern struct gendisk *alloc_disk_node(int minors, int node_id); | 418 | extern struct gendisk *alloc_disk_node(int minors, int node_id); |
| 418 | extern struct gendisk *alloc_disk(int minors); | 419 | extern struct gendisk *alloc_disk(int minors); |
diff --git a/init/do_mounts.c b/init/do_mounts.c index 3f57ed4599..46fe407fb0 100644 --- a/init/do_mounts.c +++ b/init/do_mounts.c | |||
| @@ -7,6 +7,7 @@ | |||
| 7 | #include <linux/root_dev.h> | 7 | #include <linux/root_dev.h> |
| 8 | #include <linux/security.h> | 8 | #include <linux/security.h> |
| 9 | #include <linux/delay.h> | 9 | #include <linux/delay.h> |
| 10 | #include <linux/genhd.h> | ||
| 10 | #include <linux/mount.h> | 11 | #include <linux/mount.h> |
| 11 | #include <linux/device.h> | 12 | #include <linux/device.h> |
| 12 | #include <linux/init.h> | 13 | #include <linux/init.h> |
| @@ -308,17 +309,21 @@ retry: | |||
| 308 | /* | 309 | /* |
| 309 | * Allow the user to distinguish between failed sys_open | 310 | * Allow the user to distinguish between failed sys_open |
| 310 | * and bad superblock on root device. | 311 | * and bad superblock on root device. |
| 312 | * and give them a list of the available devices | ||
| 311 | */ | 313 | */ |
| 312 | #ifdef CONFIG_BLOCK | 314 | #ifdef CONFIG_BLOCK |
| 313 | __bdevname(ROOT_DEV, b); | 315 | __bdevname(ROOT_DEV, b); |
| 314 | #endif | 316 | #endif |
| 315 | printk("VFS: Cannot open root device \"%s\" or %s\n", | 317 | printk("VFS: Cannot open root device \"%s\" or %s\n", |
| 316 | root_device_name, b); | 318 | root_device_name, b); |
| 317 | printk("Please append a correct \"root=\" boot option\n"); | 319 | printk("Please append a correct \"root=\" boot option; here are the available partitions:\n"); |
| 318 | 320 | ||
| 321 | printk_all_partitions(); | ||
| 319 | panic("VFS: Unable to mount root fs on %s", b); | 322 | panic("VFS: Unable to mount root fs on %s", b); |
| 320 | } | 323 | } |
| 321 | 324 | ||
| 325 | printk("List of all partitions:\n"); | ||
| 326 | printk_all_partitions(); | ||
| 322 | printk("No filesystem could mount root, tried: "); | 327 | printk("No filesystem could mount root, tried: "); |
| 323 | for (p = fs_names; *p; p += strlen(p)+1) | 328 | for (p = fs_names; *p; p += strlen(p)+1) |
| 324 | printk(" %s", p); | 329 | printk(" %s", p); |
