diff options
author | Marco Peereboom <marco@cvs.openbsd.org> | 2007-03-27 04:05:23 +0000 |
---|---|---|
committer | Marco Peereboom <marco@cvs.openbsd.org> | 2007-03-27 04:05:23 +0000 |
commit | f5afe7c7ef5c9ed63bd49c183bf0f2a7cf3da563 (patch) | |
tree | b8153cb1df25b19551d187d72126cf970161a441 /sys | |
parent | ff5ed9bf6291bcdcb17187e5623b03036250ff9e (diff) |
First stab at state transition code for volumes and chunks.
Minor cleanup as well.
prodded by jordan
Diffstat (limited to 'sys')
-rw-r--r-- | sys/dev/softraid.c | 264 | ||||
-rw-r--r-- | sys/dev/softraidvar.h | 7 |
2 files changed, 250 insertions, 21 deletions
diff --git a/sys/dev/softraid.c b/sys/dev/softraid.c index 5e995ffc367..4ece30730e6 100644 --- a/sys/dev/softraid.c +++ b/sys/dev/softraid.c @@ -1,4 +1,4 @@ -/* $OpenBSD: softraid.c,v 1.8 2007/03/26 01:44:06 tedu Exp $ */ +/* $OpenBSD: softraid.c,v 1.9 2007/03/27 04:05:22 marco Exp $ */ /* * Copyright (c) 2007 Marco Peereboom <marco@peereboom.us> * @@ -49,13 +49,14 @@ #ifdef SR_DEBUG uint32_t sr_debug = 0 /* | SR_D_CMD */ - | SR_D_MISC + /* | SR_D_MISC */ /* | SR_D_INTR */ - /* | SR_D_IOCTL*/ + /* | SR_D_IOCTL */ /* | SR_D_CCB */ - /* | SR_D_WU */ - /* | SR_D_META*/ - | SR_D_DIS + /* | SR_D_WU */ + /* | SR_D_META */ + /* | SR_D_DIS */ + | SR_D_STATE ; #endif @@ -83,6 +84,8 @@ int sr_ioctl(struct device *, u_long, caddr_t); int sr_ioctl_inq(struct sr_softc *, struct bioc_inq *); int sr_ioctl_vol(struct sr_softc *, struct bioc_vol *); int sr_ioctl_disk(struct sr_softc *, struct bioc_disk *); +int sr_ioctl_setstate(struct sr_softc *, + struct bioc_setstate *); int sr_ioctl_createraid(struct sr_softc *, struct bioc_createraid *); int sr_parse_chunks(struct sr_softc *, char *, @@ -112,6 +115,9 @@ int sr_raid1_request_sense( struct sr_workunit *); int sr_raid1_start_stop(struct sr_workunit *); int sr_raid1_sync(struct sr_workunit *); void sr_raid1_intr(struct buf *); +void sr_raid1_set_chunk_state(struct sr_discipline *, + int, int); +void sr_raid1_set_vol_state(struct sr_discipline *); struct scsi_adapter sr_switch = { sr_scsi_cmd, sr_minphys, NULL, NULL, sr_scsi_ioctl @@ -521,7 +527,7 @@ sr_ioctl(struct device *dev, u_long cmd, caddr_t addr) case BIOCSETSTATE: DNPRINTF(SR_D_IOCTL, "setstate\n"); - /*rv = sr_ioctl_setstate(sc, (struct bioc_setstate *)addr); */ + rv = sr_ioctl_setstate(sc, (struct bioc_setstate *)addr); break; case BIOCCREATERAID: @@ -562,7 +568,7 @@ int sr_ioctl_vol(struct sr_softc *sc, struct bioc_vol *bv) { int i, vol, rv = EINVAL; - struct sr_volume *mv; + struct sr_volume *sv; for (i = 0, vol = -1; i < SR_MAXSCSIBUS; i++) { /* XXX this will not work when we stagger disciplines */ @@ -571,14 +577,14 @@ sr_ioctl_vol(struct sr_softc *sc, struct bioc_vol *bv) if (vol != bv->bv_volid) continue; - mv = &sc->sc_dis[i]->sd_vol; - bv->bv_status = mv->sv_meta.svm_status; - bv->bv_size = mv->sv_meta.svm_size; - bv->bv_level = mv->sv_meta.svm_level; - bv->bv_nodisk = mv->sv_meta.svm_no_chunk; - strlcpy(bv->bv_dev, mv->sv_meta.svm_devname, + sv = &sc->sc_dis[i]->sd_vol; + bv->bv_status = sv->sv_meta.svm_status; + bv->bv_size = sv->sv_meta.svm_size; + bv->bv_level = sv->sv_meta.svm_level; + bv->bv_nodisk = sv->sv_meta.svm_no_chunk; + strlcpy(bv->bv_dev, sv->sv_meta.svm_devname, sizeof(bv->bv_dev)); - strlcpy(bv->bv_vendor, mv->sv_meta.svm_vendor, + strlcpy(bv->bv_vendor, sv->sv_meta.svm_vendor, sizeof(bv->bv_vendor)); rv = 0; break; @@ -591,7 +597,7 @@ int sr_ioctl_disk(struct sr_softc *sc, struct bioc_disk *bd) { int i, vol, rv = EINVAL; - struct sr_chunk *mc; + struct sr_chunk *src; for (i = 0, vol = -1; i < SR_MAXSCSIBUS; i++) { /* XXX this will not work when we stagger disciplines */ @@ -600,11 +606,12 @@ sr_ioctl_disk(struct sr_softc *sc, struct bioc_disk *bd) if (vol != bd->bd_volid) continue; - mc = sc->sc_dis[i]->sd_vol.sv_chunks[bd->bd_diskid]; - bd->bd_status = mc->src_meta.scm_status; - bd->bd_size = mc->src_meta.scm_size; + src = sc->sc_dis[i]->sd_vol.sv_chunks[bd->bd_diskid]; + bd->bd_status = src->src_meta.scm_status; + bd->bd_size = src->src_meta.scm_size; + bd->bd_channel = i; bd->bd_target = bd->bd_diskid; - strlcpy(bd->bd_vendor, mc->src_meta.scm_devname, + strlcpy(bd->bd_vendor, src->src_meta.scm_devname, sizeof(bd->bd_vendor)); rv = 0; break; @@ -614,6 +621,17 @@ sr_ioctl_disk(struct sr_softc *sc, struct bioc_disk *bd) } int +sr_ioctl_setstate(struct sr_softc *sc, struct bioc_setstate *bs) +{ + int rv = EINVAL; + +#ifdef SR_UNIT_TEST +#endif + + return (rv); +} + +int sr_ioctl_createraid(struct sr_softc *sc, struct bioc_createraid *bc) { char *devl; @@ -692,6 +710,8 @@ sr_ioctl_createraid(struct sr_softc *sc, struct bioc_createraid *bc) sd->sd_scsi_start_stop = sr_raid1_start_stop; sd->sd_scsi_sync = sr_raid1_sync; sd->sd_scsi_rw = sr_raid1_rw; + sd->sd_set_chunk_state = sr_raid1_set_chunk_state; + sd->sd_set_vol_state = sr_raid1_set_vol_state; break; default: goto unwind; @@ -1306,3 +1326,207 @@ sr_raid1_intr(struct buf *bp) sr_put_wu(wu); } } + +void +sr_raid1_set_chunk_state(struct sr_discipline *sd, int c, int new_state) +{ + int old_state, s; + + DNPRINTF(SR_D_STATE, "%s: %s: %s: sr_raid1_set_chunk_state %d -> %d\n", + DEVNAME(sd->sd_sc), sd->sd_vol.sv_meta.svm_devname, + sd->sd_vol.sv_chunks[c]->src_meta.scm_devname, c, new_state); + + /* ok to go to splbio since this only happens in error path */ + s = splbio(); + old_state = sd->sd_vol.sv_chunks[c]->src_meta.scm_status; + + /* there is a race on status here but we don't care for now */ + switch (old_state) { + case BIOC_SDONLINE: + switch (new_state) { + case BIOC_SDOFFLINE: + break; + case BIOC_SDFAILED: + break; + case BIOC_SDSCRUB: + break; + default: + goto die; + } + break; + + case BIOC_SDOFFLINE: + if (new_state == BIOC_SDREBUILD) { + ; + } else + goto die; + break; + + case BIOC_SDFAILED: + if (new_state == BIOC_SDREBUILD) { + ; + } else + goto die; + break; + + case BIOC_SDSCRUB: + switch (new_state) { + case BIOC_SDONLINE: + break; + case BIOC_SDFAILED: + break; + default: + goto die; + } + break; + + case BIOC_SDREBUILD: + switch (new_state) { + case BIOC_SDONLINE: + break; + case BIOC_SDFAILED: + break; + default: + goto die; + } + break; + + case BIOC_SDHOTSPARE: + if (new_state == BIOC_SDREBUILD) { + ; + } else + goto die; + break; + + default: +die: + splx(s); /* XXX */ + panic("%s: %s: %s: invalid chunk state transition " + "%d -> %d\n", DEVNAME(sd->sd_sc), + sd->sd_vol.sv_meta.svm_devname, + sd->sd_vol.sv_chunks[c]->src_meta.scm_devname, + old_state, new_state); + /* NOTREACHED */ + } + + sd->sd_vol.sv_chunks[c]->src_meta.scm_status = new_state; + sd->sd_set_vol_state(sd); + + splx(s); +} + +void +sr_raid1_set_vol_state(struct sr_discipline *sd) +{ + int states[SR_MAX_STATES]; + int new_state, i, s, nd; + int old_state = sd->sd_vol.sv_meta.svm_status; + + nd = sd->sd_vol.sv_meta.svm_no_chunk; + + for (i = 0; i < nd; i++) + states[i] = 0; + + for (i = 0; i < nd; i++) { + s = sd->sd_vol.sv_chunks[i]->src_meta.scm_status; + if (s > SR_MAX_STATES) + panic("%s: %s: %s: invalid chunk state", + DEVNAME(sd->sd_sc), + sd->sd_vol.sv_meta.svm_devname, + sd->sd_vol.sv_chunks[i]->src_meta.scm_devname); + states[s]++; + } + + if (states[BIOC_SVONLINE] == nd) + new_state = BIOC_SVONLINE; + else if (states[BIOC_SVSCRUB] != 0) + new_state = BIOC_SVSCRUB; + else if (states[BIOC_SVBUILDING] != 0) + new_state = BIOC_SVBUILDING; + else if (states[BIOC_SVREBUILD] != 0) + new_state = BIOC_SVREBUILD; + else if (states[BIOC_SVDEGRADED] != 0) + new_state = BIOC_SVDEGRADED; + else if (states[BIOC_SVONLINE] == 0) + new_state = BIOC_SVOFFLINE; + else { + printf("old_state = %d, ", old_state); + for (i = 0; i < SR_MAX_STATES; i++) + printf("%d = %d, ", i, + sd->sd_vol.sv_chunks[i]->src_meta.scm_status); + panic("invalid new_state"); + } + + DNPRINTF(SR_D_STATE, "%s: %s: sr_raid1_set_vol_state %d -> %d\n", + DEVNAME(sd->sd_sc), sd->sd_vol.sv_meta.svm_devname, + old_state, new_state); + + switch (old_state) { + case BIOC_SVONLINE: + switch (new_state) { + case BIOC_SVOFFLINE: + case BIOC_SVDEGRADED: + break; + default: + goto die; + } + break; + + case BIOC_SVOFFLINE: + /* XXX this might be a little too much */ + goto die; + + case BIOC_SVSCRUB: + switch (new_state) { + case BIOC_SVONLINE: + case BIOC_SVOFFLINE: + case BIOC_SVDEGRADED: + case BIOC_SVSCRUB: /* can go to same state */ + break; + default: + goto die; + } + break; + + case BIOC_SVBUILDING: + switch (new_state) { + case BIOC_SVONLINE: + case BIOC_SVOFFLINE: + case BIOC_SVBUILDING: /* can go to the same state */ + break; + default: + goto die; + } + break; + + case BIOC_SVREBUILD: + switch (new_state) { + case BIOC_SVONLINE: + case BIOC_SVOFFLINE: + case BIOC_SVREBUILD: /* can go to the same state */ + break; + default: + goto die; + } + break; + + case BIOC_SVDEGRADED: + switch (new_state) { + case BIOC_SVOFFLINE: + case BIOC_SVREBUILD: + case BIOC_SVDEGRADED: /* can go to the same state */ + break; + default: + goto die; + } + break; + + default: +die: + panic("%s: %s: invalid volume state transition " + "%d -> %d\n", DEVNAME(sd->sd_sc), + sd->sd_vol.sv_meta.svm_devname, + old_state, new_state); + /* NOTREACHED */ + } +} diff --git a/sys/dev/softraidvar.h b/sys/dev/softraidvar.h index 313f28b5b19..c78a662034b 100644 --- a/sys/dev/softraidvar.h +++ b/sys/dev/softraidvar.h @@ -1,4 +1,4 @@ -/* $OpenBSD: softraidvar.h,v 1.3 2007/03/19 22:33:15 dlg Exp $ */ +/* $OpenBSD: softraidvar.h,v 1.4 2007/03/27 04:05:22 marco Exp $ */ /* * Copyright (c) 2006 Marco Peereboom <sro@peereboom.us> * @@ -40,6 +40,7 @@ extern u_int32_t sr_debug; #define SR_D_WU 0x0020 #define SR_D_META 0x0040 #define SR_D_DIS 0x0080 +#define SR_D_STATE 0x0100 #else #define DPRINTF(x...) #define DNPRINTF(n,x...) @@ -48,6 +49,7 @@ extern u_int32_t sr_debug; #define SR_MAXFER MAXPHYS #define SR_MAX_LD 1 #define SR_MAX_CMDS 16 +#define SR_MAX_STATES 6 /* forward define to prevent dependency goo */ struct sr_softc; @@ -222,6 +224,9 @@ struct sr_discipline { int (*sd_shutdown_volume)(void *); int (*sd_free_resources)(struct sr_discipline *); int (*sd_quiesce_io)(struct sr_discipline *); + void (*sd_set_chunk_state)(struct sr_discipline *, + int, int); + void (*sd_set_vol_state)(struct sr_discipline *); /* SCSI emulation */ struct scsi_sense_data sd_scsi_sense; |