summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorjoerg <joerg@FreeBSD.org>2003-02-05 21:02:56 +0000
committerjoerg <joerg@FreeBSD.org>2003-02-05 21:02:56 +0000
commit4e7a2a1e8b5ca1511c5a619a13225b52e1ac7bd9 (patch)
tree9d1a642f7d546e85a510663b002951545e03f4ec
parent2ccf73eb01bcca438145c8d1af38f97eee8e4136 (diff)
downloadFreeBSD-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
-rw-r--r--sys/conf/options1
-rw-r--r--sys/dev/vinum/vinum.c82
-rw-r--r--sys/dev/vinum/vinumhdr.h1
-rw-r--r--sys/dev/vinum/vinumio.c29
4 files changed, 91 insertions, 22 deletions
diff --git a/sys/conf/options b/sys/conf/options
index 47e4ec8..4ec220d 100644
--- a/sys/conf/options
+++ b/sys/conf/options
@@ -550,6 +550,7 @@ UKBD_DFLT_KEYMAP opt_ukbd.h
# Vinum options
VINUMDEBUG opt_vinum.h
+VINUM_AUTOSTART opt_vinum.h
# Embedded system options
INIT_PATH opt_init_path.h
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;
OpenPOWER on IntegriCloud