aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDave Gilbert <linux@treblig.org>2007-05-09 05:33:24 -0400
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-05-09 15:30:48 -0400
commitdd2a345f8f002845636dbf5d2d768bb5cd8a5f59 (patch)
tree9ddbe34d18cf97496f4d3d582ed127fee0d96a01
parent0e7d18b57c39bedcbd181e3c06d13572b33e5380 (diff)
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: Jan Engelhardt <jengelh@gmx.de> Cc: Dave Gilbert <linux@treblig.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r--block/genhd.c53
-rw-r--r--include/linux/genhd.h1
-rw-r--r--init/do_mounts.c7
3 files changed, 60 insertions, 1 deletions
diff --git a/block/genhd.c b/block/genhd.c
index b5664440896c..93a2cf654597 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 */
221void __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 */
218static void *part_start(struct seq_file *part, loff_t *pos) 271static void *part_start(struct seq_file *part, loff_t *pos)
diff --git a/include/linux/genhd.h b/include/linux/genhd.h
index 2c65da7cabb2..f589559cf070 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);
413extern int rescan_partitions(struct gendisk *disk, struct block_device *bdev); 413extern int rescan_partitions(struct gendisk *disk, struct block_device *bdev);
414extern void add_partition(struct gendisk *, int, sector_t, sector_t, int); 414extern void add_partition(struct gendisk *, int, sector_t, sector_t, int);
415extern void delete_partition(struct gendisk *, int); 415extern void delete_partition(struct gendisk *, int);
416extern void printk_all_partitions(void);
416 417
417extern struct gendisk *alloc_disk_node(int minors, int node_id); 418extern struct gendisk *alloc_disk_node(int minors, int node_id);
418extern struct gendisk *alloc_disk(int minors); 419extern struct gendisk *alloc_disk(int minors);
diff --git a/init/do_mounts.c b/init/do_mounts.c
index 3f57ed4599d6..46fe407fb03e 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);