diff options
-rw-r--r-- | sys/dev/softraid.c | 212 | ||||
-rw-r--r-- | sys/dev/softraid_raid0.c | 108 | ||||
-rw-r--r-- | sys/dev/softraid_raid1.c | 198 | ||||
-rw-r--r-- | sys/dev/softraidvar.h | 20 |
4 files changed, 325 insertions, 213 deletions
diff --git a/sys/dev/softraid.c b/sys/dev/softraid.c index 6bdbecf4e25..b03137755e2 100644 --- a/sys/dev/softraid.c +++ b/sys/dev/softraid.c @@ -1,4 +1,4 @@ -/* $OpenBSD: softraid.c,v 1.95 2008/01/24 17:50:17 marco Exp $ */ +/* $OpenBSD: softraid.c,v 1.96 2008/01/24 19:58:08 marco Exp $ */ /* * Copyright (c) 2007 Marco Peereboom <marco@peereboom.us> * @@ -107,7 +107,6 @@ void sr_print_uuid(struct sr_uuid *, int); u_int32_t sr_checksum(char *, u_int32_t *, u_int32_t); int sr_clear_metadata(struct sr_discipline *); int sr_save_metadata(struct sr_discipline *, u_int32_t); -void sr_save_metadata_callback(void *, void *); int sr_boot_assembly(struct sr_softc *); int sr_already_assembled(struct sr_discipline *); int sr_validate_metadata(struct sr_softc *, dev_t, @@ -886,8 +885,8 @@ sr_ioctl_createraid(struct sr_softc *sc, struct bioc_createraid *bc, int user) sd->sd_scsi_start_stop = sr_raid_start_stop; sd->sd_scsi_sync = sr_raid_sync; sd->sd_scsi_rw = sr_raid0_rw; - sd->sd_set_chunk_state = sr_raid_set_chunk_state; - sd->sd_set_vol_state = sr_raid_set_vol_state; + sd->sd_set_chunk_state = sr_raid0_set_chunk_state; + sd->sd_set_vol_state = sr_raid0_set_vol_state; break; case 1: /* fill out discipline members */ @@ -905,8 +904,8 @@ sr_ioctl_createraid(struct sr_softc *sc, struct bioc_createraid *bc, int user) sd->sd_scsi_start_stop = sr_raid_start_stop; sd->sd_scsi_sync = sr_raid_sync; sd->sd_scsi_rw = sr_raid1_rw; - sd->sd_set_chunk_state = sr_raid_set_chunk_state; - sd->sd_set_vol_state = sr_raid_set_vol_state; + sd->sd_set_chunk_state = sr_raid1_set_chunk_state; + sd->sd_set_vol_state = sr_raid1_set_vol_state; break; #ifdef CRYPTO case 'C': @@ -925,8 +924,9 @@ sr_ioctl_createraid(struct sr_softc *sc, struct bioc_createraid *bc, int user) sd->sd_scsi_start_stop = sr_raid_start_stop; sd->sd_scsi_sync = sr_raid_sync; sd->sd_scsi_rw = sr_crypto_rw; - sd->sd_set_chunk_state = sr_raid_set_chunk_state; - sd->sd_set_vol_state = sr_raid_set_vol_state; + /* XXX reuse raid 1 functions for now FIXME */ + sd->sd_set_chunk_state = sr_raid1_set_chunk_state; + sd->sd_set_vol_state = sr_raid1_set_vol_state; break; #endif default: @@ -1555,202 +1555,6 @@ sr_raid_startwu(struct sr_workunit *wu) } } -void -sr_raid_set_chunk_state(struct sr_discipline *sd, int c, int new_state) -{ - int old_state, s; - - DNPRINTF(SR_D_STATE, "%s: %s: %s: sr_raid_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; - - /* multiple IOs to the same chunk that fail will come through here */ - if (old_state == new_state) - goto done; - - switch (old_state) { - case BIOC_SDONLINE: - switch (new_state) { - case BIOC_SDOFFLINE: - break; - case BIOC_SDSCRUB: - break; - default: - goto die; - } - break; - - case BIOC_SDOFFLINE: - if (new_state == BIOC_SDREBUILD) { - ; - } else - goto die; - break; - - case BIOC_SDSCRUB: - if (new_state == BIOC_SDONLINE) { - ; - } else - goto die; - break; - - case BIOC_SDREBUILD: - if (new_state == BIOC_SDONLINE) { - ; - } else - 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); - - sd->sd_must_flush = 1; - workq_add_task(NULL, 0, sr_save_metadata_callback, sd, NULL); -done: - splx(s); -} - -void -sr_raid_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; - - DNPRINTF(SR_D_STATE, "%s: %s: sr_raid_set_vol_state\n", - DEVNAME(sd->sd_sc), sd->sd_vol.sv_meta.svm_devname); - - nd = sd->sd_vol.sv_meta.svm_no_chunk; - - for (i = 0; i < SR_MAX_STATES; 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_SDONLINE] == nd) - new_state = BIOC_SVONLINE; - else if (states[BIOC_SDONLINE] == 0) - new_state = BIOC_SVOFFLINE; - else if (states[BIOC_SDSCRUB] != 0) - new_state = BIOC_SVSCRUB; - else if (states[BIOC_SDREBUILD] != 0) - new_state = BIOC_SVREBUILD; - else if (states[BIOC_SDOFFLINE] != 0) - new_state = BIOC_SVDEGRADED; - else { - printf("old_state = %d, ", old_state); - for (i = 0; i < nd; 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_raid_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 */ - } - - sd->sd_vol.sv_meta.svm_status = new_state; -} - u_int32_t sr_checksum(char *s, u_int32_t *p, u_int32_t size) { diff --git a/sys/dev/softraid_raid0.c b/sys/dev/softraid_raid0.c index 2e2f7dbe6f6..66cd5f4b975 100644 --- a/sys/dev/softraid_raid0.c +++ b/sys/dev/softraid_raid0.c @@ -1,4 +1,4 @@ -/* $OpenBSD: softraid_raid0.c,v 1.4 2008/01/24 17:50:17 marco Exp $ */ +/* $OpenBSD: softraid_raid0.c,v 1.5 2008/01/24 19:58:08 marco Exp $ */ /* * Copyright (c) 2008 Marco Peereboom <marco@peereboom.us> * @@ -92,6 +92,112 @@ sr_raid0_free_resources(struct sr_discipline *sd) return (rv); } +void +sr_raid0_set_chunk_state(struct sr_discipline *sd, int c, int new_state) +{ + int old_state, s; + + DNPRINTF(SR_D_STATE, "%s: %s: %s: sr_raid_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; + + /* multiple IOs to the same chunk that fail will come through here */ + if (old_state == new_state) + goto done; + + switch (old_state) { + case BIOC_SDONLINE: + if (new_state == BIOC_SDOFFLINE) + break; + else + goto die; + break; + + case BIOC_SDOFFLINE: + goto die; + + 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); + + sd->sd_must_flush = 1; + workq_add_task(NULL, 0, sr_save_metadata_callback, sd, NULL); +done: + splx(s); +} + +void +sr_raid0_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; + + DNPRINTF(SR_D_STATE, "%s: %s: sr_raid_set_vol_state\n", + DEVNAME(sd->sd_sc), sd->sd_vol.sv_meta.svm_devname); + + nd = sd->sd_vol.sv_meta.svm_no_chunk; + + for (i = 0; i < SR_MAX_STATES; 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_SDONLINE] == nd) + new_state = BIOC_SVONLINE; + else + new_state = BIOC_SVOFFLINE; + + DNPRINTF(SR_D_STATE, "%s: %s: sr_raid_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: + if (new_state == BIOC_SVOFFLINE) + break; + else + goto die; + break; + + case BIOC_SVOFFLINE: + /* XXX this might be a little too much */ + goto die; + + 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 */ + } + + sd->sd_vol.sv_meta.svm_status = new_state; +} + int sr_raid0_rw(struct sr_workunit *wu) { diff --git a/sys/dev/softraid_raid1.c b/sys/dev/softraid_raid1.c index 6e20c959802..933c5d57a54 100644 --- a/sys/dev/softraid_raid1.c +++ b/sys/dev/softraid_raid1.c @@ -1,4 +1,4 @@ -/* $OpenBSD: softraid_raid1.c,v 1.2 2008/01/24 17:50:17 marco Exp $ */ +/* $OpenBSD: softraid_raid1.c,v 1.3 2008/01/24 19:58:08 marco Exp $ */ /* * Copyright (c) 2007 Marco Peereboom <marco@peereboom.us> * @@ -86,6 +86,202 @@ sr_raid1_free_resources(struct sr_discipline *sd) return (rv); } +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_raid_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; + + /* multiple IOs to the same chunk that fail will come through here */ + if (old_state == new_state) + goto done; + + switch (old_state) { + case BIOC_SDONLINE: + switch (new_state) { + case BIOC_SDOFFLINE: + break; + case BIOC_SDSCRUB: + break; + default: + goto die; + } + break; + + case BIOC_SDOFFLINE: + if (new_state == BIOC_SDREBUILD) { + ; + } else + goto die; + break; + + case BIOC_SDSCRUB: + if (new_state == BIOC_SDONLINE) { + ; + } else + goto die; + break; + + case BIOC_SDREBUILD: + if (new_state == BIOC_SDONLINE) { + ; + } else + 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); + + sd->sd_must_flush = 1; + workq_add_task(NULL, 0, sr_save_metadata_callback, sd, NULL); +done: + 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; + + DNPRINTF(SR_D_STATE, "%s: %s: sr_raid_set_vol_state\n", + DEVNAME(sd->sd_sc), sd->sd_vol.sv_meta.svm_devname); + + nd = sd->sd_vol.sv_meta.svm_no_chunk; + + for (i = 0; i < SR_MAX_STATES; 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_SDONLINE] == nd) + new_state = BIOC_SVONLINE; + else if (states[BIOC_SDONLINE] == 0) + new_state = BIOC_SVOFFLINE; + else if (states[BIOC_SDSCRUB] != 0) + new_state = BIOC_SVSCRUB; + else if (states[BIOC_SDREBUILD] != 0) + new_state = BIOC_SVREBUILD; + else if (states[BIOC_SDOFFLINE] != 0) + new_state = BIOC_SVDEGRADED; + else { + printf("old_state = %d, ", old_state); + for (i = 0; i < nd; 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_raid_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 */ + } + + sd->sd_vol.sv_meta.svm_status = new_state; +} + int sr_raid1_rw(struct sr_workunit *wu) { diff --git a/sys/dev/softraidvar.h b/sys/dev/softraidvar.h index 3bd4d3e6c81..a9bd161007f 100644 --- a/sys/dev/softraidvar.h +++ b/sys/dev/softraidvar.h @@ -1,4 +1,4 @@ -/* $OpenBSD: softraidvar.h,v 1.37 2008/01/24 13:58:14 marco Exp $ */ +/* $OpenBSD: softraidvar.h,v 1.38 2008/01/24 19:58:08 marco Exp $ */ /* * Copyright (c) 2006 Marco Peereboom <marco@peereboom.us> * @@ -359,6 +359,10 @@ void sr_free_wu(struct sr_discipline *); struct sr_workunit *sr_get_wu(struct sr_discipline *); void sr_put_wu(struct sr_workunit *); +/* misc functions */ +int32_t sr_validate_stripsize(u_int32_t); +void sr_save_metadata_callback(void *, void *); + /* discipline functions */ int sr_raid_inquiry(struct sr_workunit *); int sr_raid_read_cap(struct sr_workunit *); @@ -366,17 +370,16 @@ int sr_raid_tur(struct sr_workunit *); int sr_raid_request_sense( struct sr_workunit *); int sr_raid_start_stop(struct sr_workunit *); int sr_raid_sync(struct sr_workunit *); -void sr_raid_set_chunk_state(struct sr_discipline *, - int, int); -void sr_raid_set_vol_state(struct sr_discipline *); void sr_raid_startwu(struct sr_workunit *); -int32_t sr_validate_stripsize(u_int32_t); /* raid 0 */ int sr_raid0_alloc_resources(struct sr_discipline *); int sr_raid0_free_resources(struct sr_discipline *); int sr_raid0_rw(struct sr_workunit *); void sr_raid0_intr(struct buf *); +void sr_raid0_set_chunk_state(struct sr_discipline *, + int, int); +void sr_raid0_set_vol_state(struct sr_discipline *); /* raid 1 */ int sr_raid1_alloc_resources(struct sr_discipline *); @@ -384,10 +387,13 @@ int sr_raid1_free_resources(struct sr_discipline *); int sr_raid1_rw(struct sr_workunit *); void sr_raid1_intr(struct buf *); void sr_raid1_recreate_wu(struct sr_workunit *); +void sr_raid1_set_chunk_state(struct sr_discipline *, + int, int); +void sr_raid1_set_vol_state(struct sr_discipline *); /* crypto discipline */ -struct cryptop * sr_crypto_getcryptop(struct sr_workunit *, int); -void * sr_crypto_putcryptop(struct cryptop *); +struct cryptop *sr_crypto_getcryptop(struct sr_workunit *, int); +void *sr_crypto_putcryptop(struct cryptop *); int sr_crypto_alloc_resources(struct sr_discipline *); int sr_crypto_free_resources(struct sr_discipline *); int sr_crypto_rw(struct sr_workunit *); |