summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexander Yurchenko <grange@cvs.openbsd.org>2009-03-20 20:11:08 +0000
committerAlexander Yurchenko <grange@cvs.openbsd.org>2009-03-20 20:11:08 +0000
commit82675978e6f894ab126d76920de1045d8f9de2e1 (patch)
tree179f474ea492ae0db76be1237c5f078c4da69199
parent1976785ddb6c34fcd759947c0d773834f864f507 (diff)
Detect unused and hot-spare drives.
-rw-r--r--sys/dev/pci/ips.c56
1 files changed, 44 insertions, 12 deletions
diff --git a/sys/dev/pci/ips.c b/sys/dev/pci/ips.c
index 0d751598050..e7156380848 100644
--- a/sys/dev/pci/ips.c
+++ b/sys/dev/pci/ips.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ips.c,v 1.81 2009/03/20 19:48:41 grange Exp $ */
+/* $OpenBSD: ips.c,v 1.82 2009/03/20 20:11:07 grange Exp $ */
/*
* Copyright (c) 2006, 2007, 2009 Alexander Yurchenko <grange@openbsd.org>
@@ -1135,7 +1135,7 @@ ips_ioctl_vol(struct ips_softc *sc, struct bioc_vol *bv)
struct ips_rblstat *rblstat = &sc->sc_info->rblstat;
struct ips_ld *ld;
int vid = bv->bv_volid;
- struct device *dev;
+ struct device *dv;
int rebuild = 0;
u_int32_t total = 0, done = 0;
@@ -1170,8 +1170,22 @@ ips_ioctl_vol(struct ips_softc *sc, struct bioc_vol *bv)
bv->bv_level = di->drive[vid].raid;
bv->bv_nodisk = ld->chunkcnt;
- dev = sc->sc_scsibus->sc_link[vid][0]->device_softc;
- strlcpy(bv->bv_dev, dev->dv_xname, sizeof(bv->bv_dev));
+ /* Associate all unused and spare drives with first volume */
+ if (vid == 0) {
+ struct ips_dev *dev;
+ int chan, target;
+
+ for (chan = 0; chan < IPS_MAXCHANS; chan++)
+ for (target = 0; target < IPS_MAXTARGETS; target++) {
+ dev = &conf->dev[chan][target];
+ if (dev->state && !(dev->state &
+ IPS_DVS_MEMBER))
+ bv->bv_nodisk++;
+ }
+ }
+
+ dv = sc->sc_scsibus->sc_link[vid][0]->device_softc;
+ strlcpy(bv->bv_dev, dv->dv_xname, sizeof(bv->bv_dev));
strlcpy(bv->bv_vendor, "IBM", sizeof(bv->bv_vendor));
DPRINTF(IPS_D_INFO, ("%s: ips_ioctl_vol: vid %d, state 0x%02x, "
@@ -1190,28 +1204,46 @@ ips_ioctl_disk(struct ips_softc *sc, struct bioc_disk *bd)
struct ips_chunk *chunk;
struct ips_dev *dev;
int vid = bd->bd_volid, did = bd->bd_diskid;
+ int chan, target, i;
if (vid >= sc->sc_nunits)
return (EINVAL);
ld = &conf->ld[vid];
- if (did >= ld->chunkcnt)
- return (EINVAL);
- chunk = &ld->chunk[did];
+ if (did >= ld->chunkcnt) {
+ /* Probably unused or spare drives */
+ if (vid != 0)
+ return (EINVAL);
+
+ i = ld->chunkcnt;
+ for (chan = 0; chan < IPS_MAXCHANS; chan++)
+ for (target = 0; target < IPS_MAXTARGETS; target++) {
+ dev = &conf->dev[chan][target];
+ if (dev->state && !(dev->state &
+ IPS_DVS_MEMBER))
+ if (i++ == did)
+ goto out;
+ }
+ } else {
+ chunk = &ld->chunk[did];
+ chan = chunk->channel;
+ target = chunk->target;
+ }
- if (chunk->channel >= IPS_MAXCHANS || chunk->target >= IPS_MAXTARGETS)
+out:
+ if (chan >= IPS_MAXCHANS || target >= IPS_MAXTARGETS)
return (EINVAL);
- dev = &conf->dev[chunk->channel][chunk->target];
+ dev = &conf->dev[chan][target];
- bd->bd_channel = chunk->channel;
- bd->bd_target = chunk->target;
+ bd->bd_channel = chan;
+ bd->bd_target = target;
bd->bd_lun = 0;
bd->bd_size = (u_quad_t)letoh32(chunk->seccnt) * IPS_SECSZ;
bzero(bd->bd_vendor, sizeof(bd->bd_vendor));
memcpy(bd->bd_vendor, dev->devid, MIN(sizeof(bd->bd_vendor),
sizeof(dev->devid)));
- strlcpy(bd->bd_procdev, sc->sc_pt[chunk->channel].pt_procdev,
+ strlcpy(bd->bd_procdev, sc->sc_pt[chan].pt_procdev,
sizeof(bd->bd_procdev));
if (dev->state & IPS_DVS_READY) {