From 1e69b23b895102cd3f37de07e5ff10e29c003da1 Mon Sep 17 00:00:00 2001 From: Michael Shalayeff Date: Mon, 28 Aug 2006 02:50:15 +0000 Subject: properly detect failed drives and do not crash bioctl; krw@ testing --- sys/dev/ic/ciss.c | 53 ++++++++++++++++++++++++++++++++++------------------ sys/dev/ic/cissreg.h | 6 ++++-- 2 files changed, 39 insertions(+), 20 deletions(-) (limited to 'sys/dev') diff --git a/sys/dev/ic/ciss.c b/sys/dev/ic/ciss.c index f3ee1bb4d6f..a0f65a95665 100644 --- a/sys/dev/ic/ciss.c +++ b/sys/dev/ic/ciss.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ciss.c,v 1.17 2006/08/28 01:32:06 mickey Exp $ */ +/* $OpenBSD: ciss.c,v 1.18 2006/08/28 02:50:14 mickey Exp $ */ /* * Copyright (c) 2005,2006 Michael Shalayeff @@ -1077,7 +1077,6 @@ ciss_ioctl(struct device *dev, u_long cmd, caddr_t addr) case BIOCDISK: bd = (struct bioc_disk *)addr; - pdid = sc->scratch; if (bd->bd_volid > sc->maxunits) { error = EINVAL; break; @@ -1087,27 +1086,45 @@ ciss_ioctl(struct device *dev, u_long cmd, caddr_t addr) error = EINVAL; break; } - if ((error = ciss_pdid(sc, ldp->tgts[pd], pdid, SCSI_POLL))) - break; - if (pdid->config & CISS_PD_SPARE) - bd->bd_status = BIOC_SDHOTSPARE; - else if (pdid->present & CISS_PD_PRESENT) - bd->bd_status = BIOC_SDONLINE; - else - bd->bd_status = BIOC_SDINVALID; - bd->bd_size = (u_int64_t)letoh32(pdid->nblocks) * - letoh16(pdid->blksz); - bd->bd_channel = pdid->bus; - bd->bd_target = pdid->target; - bd->bd_lun = 0; - strlcpy(bd->bd_vendor, pdid->model, sizeof(bd->bd_vendor)); - strlcpy(bd->bd_serial, pdid->serial, sizeof(bd->bd_serial)); - bd->bd_procdev[0] = '\0'; ldstat = sc->scratch; if ((error = ciss_ldstat(sc, bd->bd_volid, ldstat))) break; + bd->bd_status = -1; if (ldstat->bigrebuild == ldp->tgts[pd]) bd->bd_status = BIOC_SDREBUILD; + if (ciss_bitset(ldp->tgts[pd] & 0x7f, ldstat->bigfailed)) { + bd->bd_status = BIOC_SDFAILED; + bd->bd_size = 0; + bd->bd_channel = (ldp->tgts[pd] & 0x7f) / sc->ndrives; + bd->bd_target = ldp->tgts[pd] % sc->ndrives; + bd->bd_lun = 0; + bd->bd_vendor[0] = '\0'; + bd->bd_serial[0] = '\0'; + bd->bd_procdev[0] = '\0'; + } else { + pdid = sc->scratch; + if ((error = ciss_pdid(sc, ldp->tgts[pd], pdid, + SCSI_POLL))) + break; + if (bd->bd_status < 0) { + if (pdid->config & CISS_PD_SPARE) + bd->bd_status = BIOC_SDHOTSPARE; + else if (pdid->present & CISS_PD_PRESENT) + bd->bd_status = BIOC_SDONLINE; + else + bd->bd_status = BIOC_SDINVALID; + } + bd->bd_size = (u_int64_t)letoh32(pdid->nblocks) * + letoh16(pdid->blksz); + bd->bd_channel = pdid->bus; + bd->bd_target = pdid->target; + bd->bd_lun = 0; + strlcpy(bd->bd_vendor, pdid->model, + sizeof(bd->bd_vendor)); + strlcpy(bd->bd_serial, pdid->serial, + sizeof(bd->bd_serial)); + bd->bd_procdev[0] = '\0'; + } break; case BIOCBLINK: diff --git a/sys/dev/ic/cissreg.h b/sys/dev/ic/cissreg.h index 55b7cefa3c4..5fb7afd018f 100644 --- a/sys/dev/ic/cissreg.h +++ b/sys/dev/ic/cissreg.h @@ -1,4 +1,4 @@ -/* $OpenBSD: cissreg.h,v 1.5 2006/08/27 20:51:09 mickey Exp $ */ +/* $OpenBSD: cissreg.h,v 1.6 2006/08/28 02:50:14 mickey Exp $ */ /* * Copyright (c) 2005,2006 Michael Shalayeff @@ -46,6 +46,8 @@ #define CISS_CMD_LDMAP 0xc2 #define CISS_CMD_PDMAP 0xc3 +#define ciss_bitset(d, v) ((v)[(d) >> 3] & (1 << ((d) & 7))) + struct ciss_softc; struct ciss_config { @@ -189,7 +191,7 @@ struct ciss_ldstat { u_int8_t rebldfail; /* rebuild failure */ #define CISS_LD_RBLD_READ 0x01 /* read faild */ #define CISS_LD_RBLD_WRITE 0x02 /* write fail */ - u_int8_t bigfail[16]; /* bigmap vers of some of the above */ + u_int8_t bigfailed[16]; /* bigmap vers of same of the above */ u_int8_t bigremapcnt[256]; u_int8_t bigreplaced[16]; u_int8_t bigspare[16]; -- cgit v1.2.3