Commit dd2a345f authored by Dave Gilbert's avatar Dave Gilbert Committed by Linus Torvalds

Display all possible partitions when the root filesystem failed to mount

Display all possible partitions when the root filesystem is not mounted.
This helps to track spell'o's and missing drivers.

Updated to work with newer kernels.

Example output:

VFS: Cannot open root device "foobar" or unknown-block(0,0)
Please append a correct "root=" boot option; here are the available partitions:
0800    8388608 sda driver: sd
  0801     192748 sda1
  0802    8193150 sda2
0810    4194304 sdb driver: sd
Kernel panic - not syncing: VFS: Unable to mount root fs on unknown-block(0,0)

[akpm@linux-foundation.org: cleanups, fix printk warnings]
Signed-off-by: default avatarJan Engelhardt <jengelh@gmx.de>
Cc: Dave Gilbert <linux@treblig.org>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent 0e7d18b5
...@@ -213,6 +213,59 @@ struct gendisk *get_gendisk(dev_t dev, int *part) ...@@ -213,6 +213,59 @@ struct gendisk *get_gendisk(dev_t dev, int *part)
return kobj ? to_disk(kobj) : NULL; return kobj ? to_disk(kobj) : NULL;
} }
/*
* print a full list of all partitions - intended for places where the root
* filesystem can't be mounted and thus to give the victim some idea of what
* went wrong
*/
void __init printk_all_partitions(void)
{
int n;
struct gendisk *sgp;
mutex_lock(&block_subsys_lock);
/* For each block device... */
list_for_each_entry(sgp, &block_subsys.list, kobj.entry) {
char buf[BDEVNAME_SIZE];
/*
* Don't show empty devices or things that have been surpressed
*/
if (get_capacity(sgp) == 0 ||
(sgp->flags & GENHD_FL_SUPPRESS_PARTITION_INFO))
continue;
/*
* Note, unlike /proc/partitions, I am showing the numbers in
* hex - the same format as the root= option takes.
*/
printk("%02x%02x %10llu %s",
sgp->major, sgp->first_minor,
(unsigned long long)get_capacity(sgp) >> 1,
disk_name(sgp, 0, buf));
if (sgp->driverfs_dev != NULL &&
sgp->driverfs_dev->driver != NULL)
printk(" driver: %s\n",
sgp->driverfs_dev->driver->name);
else
printk(" (driver?)\n");
/* now show the partitions */
for (n = 0; n < sgp->minors - 1; ++n) {
if (sgp->part[n] == NULL)
continue;
if (sgp->part[n]->nr_sects == 0)
continue;
printk(" %02x%02x %10llu %s\n",
sgp->major, n + 1 + sgp->first_minor,
(unsigned long long)sgp->part[n]->nr_sects >> 1,
disk_name(sgp, n + 1, buf));
} /* partition subloop */
} /* Block device loop */
mutex_unlock(&block_subsys_lock);
return;
}
#ifdef CONFIG_PROC_FS #ifdef CONFIG_PROC_FS
/* iterator */ /* iterator */
static void *part_start(struct seq_file *part, loff_t *pos) static void *part_start(struct seq_file *part, loff_t *pos)
......
...@@ -413,6 +413,7 @@ char *disk_name (struct gendisk *hd, int part, char *buf); ...@@ -413,6 +413,7 @@ char *disk_name (struct gendisk *hd, int part, char *buf);
extern int rescan_partitions(struct gendisk *disk, struct block_device *bdev); extern int rescan_partitions(struct gendisk *disk, struct block_device *bdev);
extern void add_partition(struct gendisk *, int, sector_t, sector_t, int); extern void add_partition(struct gendisk *, int, sector_t, sector_t, int);
extern void delete_partition(struct gendisk *, int); extern void delete_partition(struct gendisk *, int);
extern void printk_all_partitions(void);
extern struct gendisk *alloc_disk_node(int minors, int node_id); extern struct gendisk *alloc_disk_node(int minors, int node_id);
extern struct gendisk *alloc_disk(int minors); extern struct gendisk *alloc_disk(int minors);
......
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
#include <linux/root_dev.h> #include <linux/root_dev.h>
#include <linux/security.h> #include <linux/security.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/genhd.h>
#include <linux/mount.h> #include <linux/mount.h>
#include <linux/device.h> #include <linux/device.h>
#include <linux/init.h> #include <linux/init.h>
...@@ -308,17 +309,21 @@ void __init mount_block_root(char *name, int flags) ...@@ -308,17 +309,21 @@ void __init mount_block_root(char *name, int flags)
/* /*
* Allow the user to distinguish between failed sys_open * Allow the user to distinguish between failed sys_open
* and bad superblock on root device. * and bad superblock on root device.
* and give them a list of the available devices
*/ */
#ifdef CONFIG_BLOCK #ifdef CONFIG_BLOCK
__bdevname(ROOT_DEV, b); __bdevname(ROOT_DEV, b);
#endif #endif
printk("VFS: Cannot open root device \"%s\" or %s\n", printk("VFS: Cannot open root device \"%s\" or %s\n",
root_device_name, b); root_device_name, b);
printk("Please append a correct \"root=\" boot option\n"); printk("Please append a correct \"root=\" boot option; here are the available partitions:\n");
printk_all_partitions();
panic("VFS: Unable to mount root fs on %s", b); panic("VFS: Unable to mount root fs on %s", b);
} }
printk("List of all partitions:\n");
printk_all_partitions();
printk("No filesystem could mount root, tried: "); printk("No filesystem could mount root, tried: ");
for (p = fs_names; *p; p += strlen(p)+1) for (p = fs_names; *p; p += strlen(p)+1)
printk(" %s", p); printk(" %s", p);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment