Pass lists of possible root devices and their names up to the

machine-independent code and try mounting the devices in the
lists instead of guessing alternative root devices in a machine-
dependent way.

autoconf.c:
Reject preposterous slice numbers instead of silently converting
them to COMPATIBILITY_SLICE.

Don't forget to force slice = COMPATIBILITY_SLICE in the floppy
device name.

Eliminated most magic numbers and magic device names in setroot().

Fixed dozens of style bugs.

vfs_conf.c:
Put the actual root device name instead of "root_device" in the
mount struct if the actual name is available.  This is useful after
booting with -s.  If it were set in all cases then it could be used
to do mount(8)'s ROOTSLICE_HUNT and fsck(8)'s hotroot guess better.
This commit is contained in:
Bruce Evans 1998-06-09 12:52:35 +00:00
parent 6fe173c87b
commit 1afde994e9
5 changed files with 155 additions and 121 deletions

View File

@ -34,7 +34,7 @@
* SUCH DAMAGE.
*
* from: @(#)autoconf.c 7.1 (Berkeley) 5/9/91
* $Id: autoconf.c,v 1.96 1998/05/06 22:14:40 julian Exp $
* $Id: autoconf.c,v 1.97 1998/05/12 17:33:58 bde Exp $
*/
/*
@ -56,9 +56,10 @@
#include <sys/systm.h>
#include <sys/conf.h>
#include <sys/disklabel.h>
#include <sys/diskslice.h> /* for BASE_SLICE, MAX_SLICES */
#include <sys/diskslice.h>
#include <sys/reboot.h>
#include <sys/kernel.h>
#include <sys/malloc.h>
#include <sys/mount.h>
#include <sys/sysctl.h>
@ -70,7 +71,7 @@
#include <machine/smp.h>
#endif /* APIC_IO */
#include <i386/isa/icu.h> /* For interrupts */
#include <i386/isa/icu.h>
#include "isa.h"
#if NISA > 0
@ -137,7 +138,6 @@ static struct {
static int find_cdrom_root __P((void));
static int
find_cdrom_root()
{
@ -383,7 +383,7 @@ cpu_rootconf()
setconf();
}
#endif
#endif /* !SLICE */
void
cpu_dumpconf()
@ -432,69 +432,73 @@ setdumpdev(dev)
u_long bootdev = 0; /* not a dev_t - encoding is different */
/* Name lookup for bootable majors XXX extend me */
static char *devname[] = {
"wd",
"wfd",
#define FDMAJOR 2
"fd",
"wt",
"sd",
"st",
"cd",
};
#define PARTITIONMASK 0x7
#define PARTITIONSHIFT 3
#define FDUNITSHIFT 6
#define RAW_PART 2
/*
* Attempt to find the device from which we were booted.
* If we can do so, and not instructed not to do so,
* change rootdev to correspond to the load device.
* set rootdevs[] and rootdevnames[] to correspond to the
* boot device(s).
*/
static void
setroot()
{
int majdev, mindev, unit, part, adaptor, slice;
dev_t orootdev;
char *sname, partname[2];
int majdev, mindev, unit, slice, part;
dev_t newrootdev;
char partname[2];
char *sname;
/*printf("howto %x bootdev %x ", boothowto, bootdev);*/
if (boothowto & RB_DFLTROOT ||
(bootdev & B_MAGICMASK) != (u_long)B_DEVMAGIC)
if (boothowto & RB_DFLTROOT || (bootdev & B_MAGICMASK) != B_DEVMAGIC)
return;
majdev = B_TYPE(bootdev);
adaptor = B_ADAPTOR(bootdev);
unit = B_UNIT(bootdev);
slice = B_SLICE(bootdev);
if ((slice < BASE_SLICE) || (slice >= MAX_SLICES))
majdev = B_TYPE(bootdev);
if (bdevsw[majdev] == NULL)
return;
unit = B_UNIT(bootdev);
slice = B_SLICE(bootdev);
if (slice == WHOLE_DISK_SLICE)
slice = COMPATIBILITY_SLICE;
if (majdev > sizeof(devname) / sizeof(devname[0]))
if (slice < 0 || slice >= MAX_SLICES)
return;
/*
* XXX kludge for inconsistent unit numbering and lack of slice
* support for floppies.
*/
if (majdev == FDMAJOR) {
slice = COMPATIBILITY_SLICE;
part = RAW_PART;
mindev = unit << FDUNITSHIFT;
}
else {
part = (bootdev >> B_PARTITIONSHIFT) & B_PARTITIONMASK;
} else {
part = B_PARTITION(bootdev);
mindev = dkmakeminor(unit, slice, part);
}
orootdev = rootdev;
rootdev = makedev(majdev, mindev);
newrootdev = makedev(majdev, mindev);
rootdevs[0] = newrootdev;
sname = dsname(bdevsw[majdev]->d_name, unit, slice, part, partname);
rootdevnames[0] = malloc(strlen(sname) + 2, M_DEVBUF, M_NOWAIT);
sprintf(rootdevnames[0], "%s%s", sname, partname);
/*
* If the original rootdev is the same as the one
* just calculated modulo the slice number, don't print an otherwise
* confusing diagnostic.
* For properly dangerously dedicated disks (ones with a historical
* bogus partition table), the boot blocks will give slice = 4, but
* the kernel will only provide the compatibility slice since it
* knows that slice 4 is not a real slice. Arrange to try mounting
* the compatibility slice as root if mounting the slice passed by
* the boot blocks fails. This handles the dangerously dedicated
* case and perhaps others.
*/
if ((rootdev & ~0xff0000) == (orootdev & ~0xff0000))
if (slice == COMPATIBILITY_SLICE)
return;
sname = dsname(devname[majdev], unit, slice, part, partname);
printf("changing root device to %s%s\n", sname, partname);
slice = COMPATIBILITY_SLICE;
rootdevs[1] = dkmodslice(newrootdev, slice);
sname = dsname(bdevsw[majdev]->d_name, unit, slice, part, partname);
rootdevnames[1] = malloc(strlen(sname) + 2, M_DEVBUF, M_NOWAIT);
sprintf(rootdevnames[1], "%s%s", sname, partname);
}
#endif
#endif /* !SLICE */
static int
sysctl_kern_dumpdev SYSCTL_HANDLER_ARGS

View File

@ -34,7 +34,7 @@
* SUCH DAMAGE.
*
* from: @(#)autoconf.c 7.1 (Berkeley) 5/9/91
* $Id: autoconf.c,v 1.96 1998/05/06 22:14:40 julian Exp $
* $Id: autoconf.c,v 1.97 1998/05/12 17:33:58 bde Exp $
*/
/*
@ -56,9 +56,10 @@
#include <sys/systm.h>
#include <sys/conf.h>
#include <sys/disklabel.h>
#include <sys/diskslice.h> /* for BASE_SLICE, MAX_SLICES */
#include <sys/diskslice.h>
#include <sys/reboot.h>
#include <sys/kernel.h>
#include <sys/malloc.h>
#include <sys/mount.h>
#include <sys/sysctl.h>
@ -70,7 +71,7 @@
#include <machine/smp.h>
#endif /* APIC_IO */
#include <i386/isa/icu.h> /* For interrupts */
#include <i386/isa/icu.h>
#include "isa.h"
#if NISA > 0
@ -137,7 +138,6 @@ static struct {
static int find_cdrom_root __P((void));
static int
find_cdrom_root()
{
@ -383,7 +383,7 @@ cpu_rootconf()
setconf();
}
#endif
#endif /* !SLICE */
void
cpu_dumpconf()
@ -432,69 +432,73 @@ setdumpdev(dev)
u_long bootdev = 0; /* not a dev_t - encoding is different */
/* Name lookup for bootable majors XXX extend me */
static char *devname[] = {
"wd",
"wfd",
#define FDMAJOR 2
"fd",
"wt",
"sd",
"st",
"cd",
};
#define PARTITIONMASK 0x7
#define PARTITIONSHIFT 3
#define FDUNITSHIFT 6
#define RAW_PART 2
/*
* Attempt to find the device from which we were booted.
* If we can do so, and not instructed not to do so,
* change rootdev to correspond to the load device.
* set rootdevs[] and rootdevnames[] to correspond to the
* boot device(s).
*/
static void
setroot()
{
int majdev, mindev, unit, part, adaptor, slice;
dev_t orootdev;
char *sname, partname[2];
int majdev, mindev, unit, slice, part;
dev_t newrootdev;
char partname[2];
char *sname;
/*printf("howto %x bootdev %x ", boothowto, bootdev);*/
if (boothowto & RB_DFLTROOT ||
(bootdev & B_MAGICMASK) != (u_long)B_DEVMAGIC)
if (boothowto & RB_DFLTROOT || (bootdev & B_MAGICMASK) != B_DEVMAGIC)
return;
majdev = B_TYPE(bootdev);
adaptor = B_ADAPTOR(bootdev);
unit = B_UNIT(bootdev);
slice = B_SLICE(bootdev);
if ((slice < BASE_SLICE) || (slice >= MAX_SLICES))
majdev = B_TYPE(bootdev);
if (bdevsw[majdev] == NULL)
return;
unit = B_UNIT(bootdev);
slice = B_SLICE(bootdev);
if (slice == WHOLE_DISK_SLICE)
slice = COMPATIBILITY_SLICE;
if (majdev > sizeof(devname) / sizeof(devname[0]))
if (slice < 0 || slice >= MAX_SLICES)
return;
/*
* XXX kludge for inconsistent unit numbering and lack of slice
* support for floppies.
*/
if (majdev == FDMAJOR) {
slice = COMPATIBILITY_SLICE;
part = RAW_PART;
mindev = unit << FDUNITSHIFT;
}
else {
part = (bootdev >> B_PARTITIONSHIFT) & B_PARTITIONMASK;
} else {
part = B_PARTITION(bootdev);
mindev = dkmakeminor(unit, slice, part);
}
orootdev = rootdev;
rootdev = makedev(majdev, mindev);
newrootdev = makedev(majdev, mindev);
rootdevs[0] = newrootdev;
sname = dsname(bdevsw[majdev]->d_name, unit, slice, part, partname);
rootdevnames[0] = malloc(strlen(sname) + 2, M_DEVBUF, M_NOWAIT);
sprintf(rootdevnames[0], "%s%s", sname, partname);
/*
* If the original rootdev is the same as the one
* just calculated modulo the slice number, don't print an otherwise
* confusing diagnostic.
* For properly dangerously dedicated disks (ones with a historical
* bogus partition table), the boot blocks will give slice = 4, but
* the kernel will only provide the compatibility slice since it
* knows that slice 4 is not a real slice. Arrange to try mounting
* the compatibility slice as root if mounting the slice passed by
* the boot blocks fails. This handles the dangerously dedicated
* case and perhaps others.
*/
if ((rootdev & ~0xff0000) == (orootdev & ~0xff0000))
if (slice == COMPATIBILITY_SLICE)
return;
sname = dsname(devname[majdev], unit, slice, part, partname);
printf("changing root device to %s%s\n", sname, partname);
slice = COMPATIBILITY_SLICE;
rootdevs[1] = dkmodslice(newrootdev, slice);
sname = dsname(bdevsw[majdev]->d_name, unit, slice, part, partname);
rootdevnames[1] = malloc(strlen(sname) + 2, M_DEVBUF, M_NOWAIT);
sprintf(rootdevnames[1], "%s%s", sname, partname);
}
#endif
#endif /* !SLICE */
static int
sysctl_kern_dumpdev SYSCTL_HANDLER_ARGS

View File

@ -32,7 +32,7 @@
* SUCH DAMAGE.
*
* @(#)vfs_conf.c 8.8 (Berkeley) 3/31/94
* $Id: vfs_conf.c,v 1.23 1998/04/19 23:31:57 julian Exp $
* $Id: vfs_conf.c,v 1.24 1998/04/20 03:57:30 julian Exp $
*/
/*
@ -71,15 +71,16 @@ MALLOC_DEFINE(M_MOUNT, "mount", "vfs mount struct");
/*
* These define the root filesystem, device, and root filesystem type.
*/
static struct mount *rootfs;
dev_t rootdevs[] = { NODEV, NODEV };
char *rootdevnames[2];
struct vnode *rootvnode;
char *mountrootfsname;
#ifdef SLICE
char rootdevice[32];
#endif /* SLICE */
#endif
#ifdef BOOTP
extern void bootpc_init __P((void));
#endif /* BOOTP */
#endif
/*
* vfs_init() will set maxvfsconf
@ -119,8 +120,9 @@ static void
vfs_mountrootfs(void *unused)
{
struct mount *mp;
int err = 0;
int i, err;
struct proc *p = curproc; /* XXX */
dev_t orootdev;
#ifdef BOOTP
bootpc_init();
@ -138,20 +140,30 @@ vfs_mountrootfs(void *unused)
/*
* Attempt the mount
*/
err = VFS_MOUNT(mp, NULL, NULL, NULL, p);
/*
* rootdev may be bogus (slice field may be incorrect for disks)
* If slice field is nonzero, clear and retry.
*
* XXX Implicit knowledge of device minor number layout.
* This is placeholder code until saner root mounts arrive with
* DEVFS.
*/
if ((err == ENXIO) && (rootdev & 0xff0000)) {
rootdev &= ~0xff0000;
err = ENXIO;
orootdev = rootdev;
if (rootdevs[0] == NODEV)
rootdevs[0] = rootdev;
for (i = 0; i < sizeof(rootdevs) / sizeof(rootdevs[0]); i++) {
if (rootdevs[i] == NODEV)
break;
rootdev = rootdevs[i];
if (rootdev != orootdev) {
printf("changing root device to %s\n", rootdevnames[i]);
orootdev = rootdev;
}
strncpy(mp->mnt_stat.f_mntfromname,
rootdevnames[i] ? rootdevnames[i] : ROOTNAME, MNAMELEN - 1);
err = VFS_MOUNT(mp, NULL, NULL, NULL, p);
if (err != ENXIO)
break;
}
if (err) {
/*
* XXX should ask the user for the name in some cases.
* Why do we call vfs_unbusy() here and not after ENXIO
* is returned above?
*/
vfs_unbusy(mp, p);
/*
* free mount struct before failing

View File

@ -32,7 +32,7 @@
* SUCH DAMAGE.
*
* @(#)vfs_conf.c 8.8 (Berkeley) 3/31/94
* $Id: vfs_conf.c,v 1.23 1998/04/19 23:31:57 julian Exp $
* $Id: vfs_conf.c,v 1.24 1998/04/20 03:57:30 julian Exp $
*/
/*
@ -71,15 +71,16 @@ MALLOC_DEFINE(M_MOUNT, "mount", "vfs mount struct");
/*
* These define the root filesystem, device, and root filesystem type.
*/
static struct mount *rootfs;
dev_t rootdevs[] = { NODEV, NODEV };
char *rootdevnames[2];
struct vnode *rootvnode;
char *mountrootfsname;
#ifdef SLICE
char rootdevice[32];
#endif /* SLICE */
#endif
#ifdef BOOTP
extern void bootpc_init __P((void));
#endif /* BOOTP */
#endif
/*
* vfs_init() will set maxvfsconf
@ -119,8 +120,9 @@ static void
vfs_mountrootfs(void *unused)
{
struct mount *mp;
int err = 0;
int i, err;
struct proc *p = curproc; /* XXX */
dev_t orootdev;
#ifdef BOOTP
bootpc_init();
@ -138,20 +140,30 @@ vfs_mountrootfs(void *unused)
/*
* Attempt the mount
*/
err = VFS_MOUNT(mp, NULL, NULL, NULL, p);
/*
* rootdev may be bogus (slice field may be incorrect for disks)
* If slice field is nonzero, clear and retry.
*
* XXX Implicit knowledge of device minor number layout.
* This is placeholder code until saner root mounts arrive with
* DEVFS.
*/
if ((err == ENXIO) && (rootdev & 0xff0000)) {
rootdev &= ~0xff0000;
err = ENXIO;
orootdev = rootdev;
if (rootdevs[0] == NODEV)
rootdevs[0] = rootdev;
for (i = 0; i < sizeof(rootdevs) / sizeof(rootdevs[0]); i++) {
if (rootdevs[i] == NODEV)
break;
rootdev = rootdevs[i];
if (rootdev != orootdev) {
printf("changing root device to %s\n", rootdevnames[i]);
orootdev = rootdev;
}
strncpy(mp->mnt_stat.f_mntfromname,
rootdevnames[i] ? rootdevnames[i] : ROOTNAME, MNAMELEN - 1);
err = VFS_MOUNT(mp, NULL, NULL, NULL, p);
if (err != ENXIO)
break;
}
if (err) {
/*
* XXX should ask the user for the name in some cases.
* Why do we call vfs_unbusy() here and not after ENXIO
* is returned above?
*/
vfs_unbusy(mp, p);
/*
* free mount struct before failing

View File

@ -36,7 +36,7 @@
* SUCH DAMAGE.
*
* @(#)systm.h 8.7 (Berkeley) 3/29/95
* $Id: systm.h,v 1.70 1998/02/24 02:01:11 bde Exp $
* $Id: systm.h,v 1.71 1998/06/07 17:13:04 dfr Exp $
*/
#ifndef _SYS_SYSTM_H_
@ -67,6 +67,8 @@ extern dev_t dumpdev; /* dump device */
extern long dumplo; /* offset into dumpdev */
extern dev_t rootdev; /* root device */
extern dev_t rootdevs[2]; /* possible root devices */
extern char *rootdevnames[2]; /* names of possible root devices */
extern struct vnode *rootvp; /* vnode equivalent to above */
extern struct vnode *swapdev_vp;/* vnode for swap device */