diff options
author | grog <grog@FreeBSD.org> | 2003-05-01 01:28:42 +0000 |
---|---|---|
committer | grog <grog@FreeBSD.org> | 2003-05-01 01:28:42 +0000 |
commit | 9902c31983f2fa774f7521969f80ac8bfa0fb6da (patch) | |
tree | 84100d3fa83e50d5b31ed901e5f7c39ab08805a5 /sys | |
parent | 45949ccde13fb04ed597a5aef80b678ba16bcab7 (diff) | |
download | FreeBSD-src-9902c31983f2fa774f7521969f80ac8bfa0fb6da.zip FreeBSD-src-9902c31983f2fa774f7521969f80ac8bfa0fb6da.tar.gz |
Rewrite minor number decoding. Now we have only three types of
object: subdisks, plexes and volumes. The encoding for plexes and
subdisks no longer reflects the object to which they belong. The
super devices are high-order volume numbers. This gives vastly more
potential volumes (4 million instead of 256).
Remove an unnecessary goto.
vinumopen: Return EINVAL, not ENXIO, on an attempt to open a
referenced plex.
Diffstat (limited to 'sys')
-rw-r--r-- | sys/dev/vinum/vinum.c | 240 |
1 files changed, 110 insertions, 130 deletions
diff --git a/sys/dev/vinum/vinum.c b/sys/dev/vinum/vinum.c index 96065dc..9c82124 100644 --- a/sys/dev/vinum/vinum.c +++ b/sys/dev/vinum/vinum.c @@ -35,7 +35,7 @@ * otherwise) arising in any way out of the use of this software, even if * advised of the possibility of such damage. * - * $Id: vinum.c,v 1.34 2001/05/22 04:07:22 grog Exp grog $ + * $Id: vinum.c,v 1.41 2003/04/28 06:15:36 grog Exp grog $ * $FreeBSD$ */ @@ -54,23 +54,21 @@ extern struct mc malloced[]; struct cdevsw vinum_cdevsw = { - .d_open = vinumopen, - .d_close = vinumclose, - .d_read = physread, - .d_write = physwrite, - .d_ioctl = vinumioctl, - .d_strategy = vinumstrategy, - .d_name = "vinum", - .d_maj = VINUM_CDEV_MAJOR, - .d_flags = D_DISK + .d_open = vinumopen, + .d_close = vinumclose, + .d_read = physread, + .d_write = physwrite, + .d_ioctl = vinumioctl, + .d_strategy = vinumstrategy, + .d_name = "vinum", + .d_maj = VINUM_CDEV_MAJOR, + .d_flags = D_DISK }; /* Called by main() during pseudo-device attachment. */ -STATIC void vinumattach(void *); - +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); +STATIC void vinum_clone(void *arg, char *name, int namelen, dev_t * dev); struct _vinum_conf vinum_conf; /* configuration information */ @@ -90,8 +88,7 @@ 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 */ +/* modload should prevent multiple loads, so this is worth a panic */ if ((vinum_conf.flags & VF_LOADED) != 0) panic("vinum: already loaded"); @@ -106,13 +103,13 @@ vinumattach(void *dummy) dqend = NULL; vinum_daemon_dev = make_dev(&vinum_cdevsw, - VINUM_DAEMON_DEV, + VINUM_DAEMON_MINOR, UID_ROOT, GID_WHEEL, S_IRUSR | S_IWUSR, "vinum/controld"); vinum_super_dev = make_dev(&vinum_cdevsw, - VINUM_SUPERDEV, + VINUM_SUPERDEV_MINOR, UID_ROOT, GID_WHEEL, S_IRUSR | S_IWUSR, @@ -147,12 +144,11 @@ 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 */ - dev_clone_tag = EVENTHANDLER_REGISTER(dev_clone, vinum_clone, 0, 1000); /* - * See if the loader has passed us any of the - * autostart options. + * See if the loader has passed us any of the autostart + * options. */ cp = drivep = NULL; #ifndef VINUM_AUTOSTART @@ -160,50 +156,47 @@ vinumattach(void *dummy) freeenv(cp); cp = NULL; #endif - rv = kernel_sysctlbyname(&thread0, "kern.disks", - NULL, NULL, - NULL, 0, - &alloclen); + + rv = kernel_sysctlbyname(&thread0, "kern.disks", NULL, + NULL, NULL, 0, &alloclen); if (rv) log(LOG_NOTICE, - "sysctlbyname(\"kern.disks\") failed, rv = %d\n", + "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); + drivep = malloc(alloclen, M_TEMP, M_WAITOK); + 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; + 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, M_WAITOK); + drives[i] = cp2; + } + if (i != 0) { 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); } + freeenv(cp); + free(drives, M_TEMP); + free(drivep, M_TEMP); + } } /* @@ -291,6 +284,7 @@ free_vinum(int cleardrive) Free(VOL); } bzero(&vinum_conf, sizeof(vinum_conf)); + vinum_conf.version = VINUMVERSION; /* reinstate version number */ } STATIC int @@ -375,6 +369,23 @@ vinumopen(dev_t dev, /* First, decide what we're looking at */ switch (DEVTYPE(dev)) { case VINUM_VOLUME_TYPE: + /* + * The super device and daemon device are the last two + * volume numbers, so check for them first. + */ + if ((devminor == VINUM_DAEMON_MINOR) /* daemon device */ + ||(devminor == VINUM_SUPERDEV_MINOR)) { /* or normal super device */ + error = suser(td); /* are we root? */ + + if (error == 0) { /* yes, can do */ + if (devminor == VINUM_DAEMON_MINOR) /* daemon device */ + vinum_conf.flags |= VF_DAEMONOPEN; /* we're open */ + else /* superdev */ + vinum_conf.flags |= VF_OPEN; /* we're open */ + } + return error; + } + /* Must be a real volume. Check. */ index = Volno(dev); if (index >= vinum_conf.volumes_allocated) return ENXIO; /* no such device */ @@ -397,19 +408,16 @@ vinumopen(dev_t dev, } case VINUM_PLEX_TYPE: - if (Volno(dev) >= vinum_conf.volumes_allocated) - return ENXIO; - /* FALLTHROUGH */ - - case VINUM_RAWPLEX_TYPE: index = Plexno(dev); /* get plex index in vinum_conf */ if (index >= vinum_conf.plexes_allocated) return ENXIO; /* no such device */ plex = &PLEX[index]; switch (plex->state) { - case plex_referenced: case plex_unallocated: + return ENXIO; + + case plex_referenced: return EINVAL; default: @@ -418,51 +426,31 @@ vinumopen(dev_t dev, } case VINUM_SD_TYPE: - if ((Volno(dev) >= vinum_conf.volumes_allocated) /* no such volume */ - ||(Plexno(dev) >= vinum_conf.plexes_allocated)) /* or no such plex */ - return ENXIO; /* no such device */ - - /* FALLTHROUGH */ - - case VINUM_RAWSD_TYPE: + case VINUM_SD2_TYPE: index = Sdno(dev); /* get the subdisk number */ - if ((index >= vinum_conf.subdisks_allocated) /* not a valid SD entry */ - ||(SD[index].state < sd_init)) /* or SD is not real */ + if (index >= vinum_conf.subdisks_allocated) /* not a valid SD entry */ return ENXIO; /* no such device */ sd = &SD[index]; /* - * Opening a subdisk is always a special operation, so we - * ignore the state as long as it represents a real subdisk + * Opening a subdisk is always a special operation, so + * we ignore the state as long as it represents a real + * subdisk. */ switch (sd->state) { case sd_unallocated: + return ENXIO; + case sd_uninit: + case sd_referenced: return EINVAL; default: sd->flags |= VF_OPEN; /* note we're open */ return 0; } - - case VINUM_SUPERDEV_TYPE: - error = suser(td); /* are we root? */ - if (error == 0) { /* yes, can do */ - if (devminor == VINUM_DAEMON_DEV) /* daemon device */ - vinum_conf.flags |= VF_DAEMONOPEN; /* we're open */ - else if (devminor == VINUM_SUPERDEV) - vinum_conf.flags |= VF_OPEN; /* we're open */ - else - error = ENODEV; /* nothing, maybe a debug mismatch */ - } - return error; - - /* Vinum drives are disks. We already have a disk - * driver, so don't handle them here */ - case VINUM_DRIVE_TYPE: - default: - return ENODEV; /* don't know what to do with these */ } + return 0; /* to keep the compiler happy */ } /* ARGSUSED */ @@ -477,10 +465,30 @@ vinumclose(dev_t dev, int devminor; devminor = minor(dev); - index = Volno(dev); /* First, decide what we're looking at */ switch (DEVTYPE(dev)) { case VINUM_VOLUME_TYPE: + /* + * The super device and daemon device are the last two + * volume numbers, so check for them first. + */ + if ((devminor == VINUM_DAEMON_MINOR) /* daemon device */ + ||(devminor == VINUM_SUPERDEV_MINOR)) { /* or normal super device */ + /* + * don't worry about whether we're root: + * nobody else would get this far. + */ + if (devminor == VINUM_SUPERDEV_MINOR) /* normal superdev */ + vinum_conf.flags &= ~VF_OPEN; /* no longer open */ + else { /* the daemon device */ + vinum_conf.flags &= ~VF_DAEMONOPEN; /* no longer open */ + if (vinum_conf.flags & VF_STOPPING) /* we're trying to stop, */ + wakeup(&vinumclose); /* we can continue now */ + } + return 0; + } + /* Real volume */ + index = Volno(dev); if (index >= vinum_conf.volumes_allocated) return ENXIO; /* no such device */ vol = &VOL[index]; @@ -506,65 +514,37 @@ vinumclose(dev_t dev, return ENXIO; /* FALLTHROUGH */ - case VINUM_RAWPLEX_TYPE: - index = Plexno(dev); /* get plex index in vinum_conf */ - if (index >= vinum_conf.plexes_allocated) - return ENXIO; /* no such device */ - PLEX[index].flags &= ~VF_OPEN; /* reset our flags */ - return 0; - case VINUM_SD_TYPE: if ((Volno(dev) >= vinum_conf.volumes_allocated) || /* no such volume */ (Plexno(dev) >= vinum_conf.plexes_allocated)) /* or no such plex */ return ENXIO; /* no such device */ /* FALLTHROUGH */ - case VINUM_RAWSD_TYPE: - index = Sdno(dev); /* get the subdisk number */ - if (index >= vinum_conf.subdisks_allocated) - return ENXIO; /* no such device */ - SD[index].flags &= ~VF_OPEN; /* reset our flags */ - return 0; - - case VINUM_SUPERDEV_TYPE: - /* - * don't worry about whether we're root: - * nobody else would get this far. - */ - if (devminor == VINUM_SUPERDEV) /* normal superdev */ - vinum_conf.flags &= ~VF_OPEN; /* no longer open */ - else if (devminor == VINUM_DAEMON_DEV) { /* the daemon device */ - vinum_conf.flags &= ~VF_DAEMONOPEN; /* no longer open */ - if (vinum_conf.flags & VF_STOPPING) /* we're stopping, */ - wakeup(&vinumclose); /* we can continue stopping now */ - } - return 0; - - case VINUM_DRIVE_TYPE: default: return ENODEV; /* don't know what to do with these */ } } void -vinum_clone(void *arg, char *name, int namelen, dev_t *dev) +vinum_clone(void *arg, char *name, int namelen, dev_t * dev) { - struct volume *vol; - int i; + struct volume *vol; + int i; - if (*dev != NODEV) - return; - if (strncmp(name, "vinum/", sizeof("vinum/") - 1) != 0) - return; + 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; + name += sizeof("vinum/") - 1; + if ((i = find_volume(name, 0)) == -1) + return; - vol = &VOL[i]; - *dev = vol->dev; + vol = &VOL[i]; + *dev = vol->dev; } + /* Local Variables: */ -/* fill-column: 50 */ +/* fill-column: 60 */ /* End: */ |