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.
This commit is contained in:
grog 2003-05-01 01:28:42 +00:00
parent 45949ccde1
commit 9902c31983

View File

@ -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: */