diff options
author | joerg <joerg@FreeBSD.org> | 2003-02-05 21:02:56 +0000 |
---|---|---|
committer | joerg <joerg@FreeBSD.org> | 2003-02-05 21:02:56 +0000 |
commit | 4e7a2a1e8b5ca1511c5a619a13225b52e1ac7bd9 (patch) | |
tree | 9d1a642f7d546e85a510663b002951545e03f4ec /sys/dev/vinum | |
parent | 2ccf73eb01bcca438145c8d1af38f97eee8e4136 (diff) | |
download | FreeBSD-src-4e7a2a1e8b5ca1511c5a619a13225b52e1ac7bd9.zip FreeBSD-src-4e7a2a1e8b5ca1511c5a619a13225b52e1ac7bd9.tar.gz |
Finally make vinum ready for the root filesystem in FreeBSD 5.x. (A
similar patch has been in 4.x for a while, but is more hacky there.)
For this to work, vinum has to be loaded early (e. g. from
boot/loader), for obvious reasons. If the kernel env variable
(aka. loader variable) "vinum.autostart" is set, vinum then asks the
sysctl kern.disks for all available disks in the system, and scans
them for possible vinum headers.
For statically compiled kernels, this behaviour can be obtained even
without boot/loader by using "options VINUM_AUTOSTART" (though this is
not the recommended way).
Alternatively, the 4.x way to specify "vinum.drives" is also supported.
No further hacks (like the 4.x "vinum.root" variable) are needed,
since in 5.x, mountroot() asks back at the drivers to have them
resolve the name of the root FS into a dev_t (using the dev_clone
eventhandler).
(The MFC reminder below is for a partial MFC for vinum.autostart, the
rest is already there in 4.x.)
Timed out on: grog
MFC after: 2 weeks
Diffstat (limited to 'sys/dev/vinum')
-rw-r--r-- | sys/dev/vinum/vinum.c | 82 | ||||
-rw-r--r-- | sys/dev/vinum/vinumhdr.h | 1 | ||||
-rw-r--r-- | sys/dev/vinum/vinumio.c | 29 |
3 files changed, 90 insertions, 22 deletions
diff --git a/sys/dev/vinum/vinum.c b/sys/dev/vinum/vinum.c index ac98a5e..84056ff 100644 --- a/sys/dev/vinum/vinum.c +++ b/sys/dev/vinum/vinum.c @@ -66,6 +66,8 @@ STATIC void vinumattach(void *); STATIC int vinum_modevent(module_t mod, modeventtype_t type, void *unused); +STATIC void vinum_clone(void *arg, char *name, int namelen, dev_t *dev); + struct _vinum_conf vinum_conf; /* configuration information */ dev_t vinum_daemon_dev; @@ -79,6 +81,10 @@ dev_t vinum_super_dev; void vinumattach(void *dummy) { + int i, rv; + char *cp, *cp1, *cp2, **drives, *drivep; + size_t alloclen; + /* modload should prevent multiple loads, so this is worth a panic */ if ((vinum_conf.flags & VF_LOADED) != 0) panic("vinum: already loaded"); @@ -135,6 +141,63 @@ vinumattach(void *dummy) bzero(SD, sizeof(struct sd) * INITIAL_SUBDISKS); vinum_conf.subdisks_allocated = INITIAL_SUBDISKS; /* number of sd slots allocated */ vinum_conf.subdisks_used = 0; /* and number in use */ + + EVENTHANDLER_REGISTER(dev_clone, vinum_clone, 0, 1000); + + /* + * See if the loader has passed us any of the + * autostart options. + */ + cp = drivep = NULL; +#ifndef VINUM_AUTOSTART + if ((cp = getenv("vinum.autostart")) != NULL) { + freeenv(cp); + cp = NULL; +#endif + rv = kernel_sysctlbyname(&thread0, "kern.disks", + NULL, NULL, + NULL, 0, + &alloclen); + if (rv) + log(LOG_NOTICE, + "sysctlbyname(\"kern.disks\") failed, rv = %d\n", + rv); + else { + drivep = malloc(alloclen, M_TEMP, 0 /* M_WAITOK */); + (void)kernel_sysctlbyname(&thread0, "kern.disks", + drivep, &alloclen, + NULL, 0, + NULL); + goto start; + } +#ifndef VINUM_AUTOSTART + } else +#endif + if ((cp = getenv("vinum.drives")) != NULL) { + start: + for (cp1 = cp? cp: drivep, i = 0, drives = 0; + *cp1 != '\0'; + i++) { + cp2 = cp1; + while (*cp1 != '\0' && *cp1 != ',' && *cp1 != ' ') + cp1++; + if (*cp1 != '\0') + *cp1++ = '\0'; + drives = realloc(drives, + (unsigned long)((i + 1) * sizeof(char *)), + M_TEMP, 0 /* M_WAITOK */); + drives[i] = cp2; + } + if (i == 0) + goto bailout; + rv = vinum_scandisk(drives, i); + if (rv) + log(LOG_NOTICE, "vinum_scandisk() returned %d\n", rv); + bailout: + freeenv(cp); + free(drives, M_TEMP); + free(drivep, M_TEMP); + } } /* @@ -492,6 +555,25 @@ vinumsize(dev_t dev) return size; } +void +vinum_clone(void *arg, char *name, int namelen, dev_t *dev) +{ + struct volume *vol; + int i; + + if (*dev != NODEV) + return; + if (strncmp(name, "vinum/", sizeof("vinum/") - 1) != 0) + return; + + name += sizeof("vinum/") - 1; + if ((i = find_volume(name, 0)) == -1) + return; + + vol = &VOL[i]; + *dev = vol->dev; +} + /* Local Variables: */ /* fill-column: 50 */ /* End: */ diff --git a/sys/dev/vinum/vinumhdr.h b/sys/dev/vinum/vinumhdr.h index 95aa6fe..3fda4f1 100644 --- a/sys/dev/vinum/vinumhdr.h +++ b/sys/dev/vinum/vinumhdr.h @@ -49,6 +49,7 @@ #include <sys/conf.h> #include <sys/mount.h> #include <sys/vnode.h> +#include <sys/sysctl.h> #endif #include <sys/errno.h> #include <sys/dkstat.h> diff --git a/sys/dev/vinum/vinumio.c b/sys/dev/vinum/vinumio.c index 14284ae..38500d8 100644 --- a/sys/dev/vinum/vinumio.c +++ b/sys/dev/vinum/vinumio.c @@ -50,32 +50,21 @@ static int drivecmp(const void *va, const void *vb); int open_drive(struct drive *drive, struct thread *td, int verbose) { - struct nameidata nd; struct cdevsw *dsw; /* pointer to cdevsw entry */ - int error; if (drive->flags & VF_OPEN) /* open already, */ return EBUSY; /* don't do it again */ - NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_SYSSPACE, drive->devicename, - curthread); - error = namei(&nd); - if (error) - return (error); - if (!vn_isdisk(nd.ni_vp, &error)) { - NDFREE(&nd, 0); - return (error); - } - drive->dev = udev2dev(nd.ni_vp->v_rdev->si_udev, 0); - NDFREE(&nd, 0); - - if (drive->dev == NULL) /* didn't find anything */ - return ENODEV; + drive->dev = getdiskbyname(drive->devicename); + if (drive->dev == NODEV) /* didn't find anything */ + return ENOENT; drive->dev->si_iosize_max = DFLTPHYS; dsw = devsw(drive->dev); - if (dsw == NULL) + if (dsw == NULL) /* sanity, should not happen */ drive->lasterror = ENOENT; + else if ((dsw->d_flags & D_DISK) == 0) + drive->lasterror = ENOTBLK; else drive->lasterror = (dsw->d_open) (drive->dev, FWRITE | FREAD, 0, NULL); @@ -145,11 +134,7 @@ set_drive_parms(struct drive *drive) int init_drive(struct drive *drive, int verbose) { - if (drive->devicename[0] != '/') { - drive->lasterror = EINVAL; - log(LOG_ERR, "vinum: Can't open drive without drive name\n"); - return EINVAL; - } + drive->lasterror = open_drive(drive, curthread, verbose); /* open the drive */ if (drive->lasterror) return drive->lasterror; |