diff options
author | Marco Peereboom <marco@cvs.openbsd.org> | 2009-04-28 02:54:54 +0000 |
---|---|---|
committer | Marco Peereboom <marco@cvs.openbsd.org> | 2009-04-28 02:54:54 +0000 |
commit | 79864f575f55228e833b092a58c379a6bbc368b2 (patch) | |
tree | 45553a15acc4623249865051383e6c2d7282ec1e /sys/dev/softraid.c | |
parent | 515173ac8b20fbcd368970ed09ec04f274b68f3c (diff) |
Part one of partial bringup volumes. Plenty of rope to kill your data
use with caution...
Diffstat (limited to 'sys/dev/softraid.c')
-rw-r--r-- | sys/dev/softraid.c | 117 |
1 files changed, 86 insertions, 31 deletions
diff --git a/sys/dev/softraid.c b/sys/dev/softraid.c index a24bdcd2dc8..56078b97784 100644 --- a/sys/dev/softraid.c +++ b/sys/dev/softraid.c @@ -1,4 +1,4 @@ -/* $OpenBSD: softraid.c,v 1.128 2009/04/26 17:04:53 marco Exp $ */ +/* $OpenBSD: softraid.c,v 1.129 2009/04/28 02:54:53 marco Exp $ */ /* * Copyright (c) 2007 Marco Peereboom <marco@peereboom.us> * Copyright (c) 2008 Chris Kuethe <ckuethe@openbsd.org> @@ -54,6 +54,7 @@ #include <dev/rndvar.h> /* #define SR_FANCY_STATS */ +/* #define SR_UNIT_TEST */ #ifdef SR_DEBUG #define SR_FANCY_STATS @@ -189,7 +190,7 @@ sr_meta_attach(struct sr_discipline *sd, int force) struct sr_softc *sc = sd->sd_sc; struct sr_chunk_head *cl; struct sr_chunk *ch_entry; - int rv = 1, i; + int rv = 1, i = 0; DNPRINTF(SR_D_META, "%s: sr_meta_attach(%d)\n", DEVNAME(sc)); @@ -213,15 +214,23 @@ sr_meta_attach(struct sr_discipline *sd, int force) } } - if (smd[sd->sd_meta_type].smd_attach(sd, force)) - goto bad; - - /* fill out chunk array */ + /* we have a valid list now create an array index */ cl = &sd->sd_vol.sv_chunk_list; + SLIST_FOREACH(ch_entry, cl, src_link) { + i++; + } + sd->sd_vol.sv_chunks = malloc(sizeof(struct sr_chunk *) * i, + M_DEVBUF, M_WAITOK | M_ZERO); + + /* fill out chunk array */ i = 0; SLIST_FOREACH(ch_entry, cl, src_link) sd->sd_vol.sv_chunks[i++] = ch_entry; + /* attach metadata */ + if (smd[sd->sd_meta_type].smd_attach(sd, force)) + goto bad; + rv = 0; bad: return (rv); @@ -633,7 +642,7 @@ sr_meta_read(struct sr_discipline *sd) struct sr_meta_driver *s; struct sr_meta_opt *om; void *fm = NULL; - int no_disk = 0; + int no_disk = 0, got_meta = 0; DNPRINTF(SR_D_META, "%s: sr_meta_read\n", DEVNAME(sc)); @@ -644,9 +653,18 @@ sr_meta_read(struct sr_discipline *sd) cp = (struct sr_meta_chunk *)(sm + 1); SLIST_FOREACH(ch_entry, cl, src_link) { - /* read and translate */ - if (s->smd_read(sd, ch_entry->src_dev_mm, sm, fm)) { - /* XXX mark disk offline */ + /* skip disks that are offline */ + if (ch_entry->src_meta.scm_status == BIOC_SDOFFLINE) { + DNPRINTF(SR_D_META, + "%s: %s chunk marked offline, spoofing status\n", + DEVNAME(sc), ch_entry->src_devname); + cp++; /* adjust chunk pointer to match failure */ + continue; + } else if (s->smd_read(sd, ch_entry->src_dev_mm, sm, fm)) { + /* read and translate */ + /* XXX mark chunk offline, elsewhere!! */ + ch_entry->src_meta.scm_status = BIOC_SDOFFLINE; + cp++; /* adjust chunk pointer to match failure */ DNPRINTF(SR_D_META, "%s: sr_meta_read failed\n", DEVNAME(sc)); continue; @@ -666,9 +684,11 @@ sr_meta_read(struct sr_discipline *sd) goto done; } - /* assume chunk 0 contains metadata */ - if (no_disk == 0) + /* assume first chunk contains metadata */ + if (got_meta == 0) { bcopy(sm, sd->sd_meta, sizeof(*sd->sd_meta)); + got_meta = 1; + } bcopy(cp, &ch_entry->src_meta, sizeof(ch_entry->src_meta)); @@ -1050,9 +1070,10 @@ sr_meta_native_attach(struct sr_discipline *sd, int force) struct sr_softc *sc = sd->sd_sc; struct sr_chunk_head *cl = &sd->sd_vol.sv_chunk_list; struct sr_metadata *md = NULL; - struct sr_chunk *ch_entry; + struct sr_chunk *ch_entry, *ch_next; struct sr_uuid uuid; - int sr, not_sr, rv = 1, d, expected = -1; + u_int64_t version = 0; + int sr, not_sr, rv = 1, d, expected = -1, old_meta = 0; DNPRINTF(SR_D_META, "%s: sr_meta_native_attach\n", DEVNAME(sc)); @@ -1078,6 +1099,8 @@ sr_meta_native_attach(struct sr_discipline *sd, int force) if (d == 0) { bcopy(&md->ssdi.ssd_uuid, &uuid, sizeof uuid); expected = md->ssdi.ssd_chunk_no; + version = md->ssd_ondisk; + d++; continue; } else if (bcmp(&md->ssdi.ssd_uuid, &uuid, sizeof uuid)) { @@ -1085,10 +1108,12 @@ sr_meta_native_attach(struct sr_discipline *sd, int force) DEVNAME(sc)); goto bad; } + if (md->ssd_ondisk != version) { + old_meta++; + version = MAX(md->ssd_ondisk, version); + } } else not_sr++; - - d++; } if (sr && not_sr) { @@ -1096,6 +1121,25 @@ sr_meta_native_attach(struct sr_discipline *sd, int force) DEVNAME(sc)); goto bad; } + + /* mixed metadata versions; mark bad disks offline */ + if (old_meta) { + d = 0; + for (ch_entry = SLIST_FIRST(cl); ch_entry != SLIST_END(cl); + ch_entry = ch_next, d++) { + ch_next = SLIST_NEXT(ch_entry, src_link); + + /* XXX do we want to read this again? */ + if (sr_meta_native_read(sd, ch_entry->src_dev_mm, md, + NULL)) + printf("%s: could not read native metadata\n", + DEVNAME(sc)); + if (md->ssd_ondisk != version) + sd->sd_vol.sv_chunks[d]->src_meta.scm_status = + BIOC_SDOFFLINE; + } + } + if (expected != sr && !force && expected != -1) { /* XXX make this smart so that we can bring up degraded disks */ printf("%s: not all chunks were provided\n", DEVNAME(sc)); @@ -1706,18 +1750,33 @@ sr_ioctl_setstate(struct sr_softc *sc, struct bioc_setstate *bs) int rv = EINVAL; #ifdef SR_UNIT_TEST - int i, vol, state; + int i, vol, state, found, tg; struct sr_discipline *sd; + struct sr_chunk *ch_entry; + struct sr_chunk_head *cl; + + if (bs->bs_other_id_type == BIOC_SSOTHER_UNUSED) + goto done; for (i = 0, vol = -1; i < SR_MAXSCSIBUS; i++) { /* XXX this will not work when we stagger disciplines */ if (sc->sc_dis[i]) vol++; - if (vol != bs->bs_channel) + if (vol != bs->bs_volid) continue; + sd = sc->sc_dis[i]; - sd = sc->sc_dis[vol]; - if (bs->bs_target >= sd->sd_meta->ssdi.ssd_chunk_no) + found = 0; + tg = 0; + cl = &sd->sd_vol.sv_chunk_list; + SLIST_FOREACH(ch_entry, cl, src_link) { + if (ch_entry->src_dev_mm == bs->bs_other_id) { + found = 1; + break; + } + tg++; + } + if (found == 0) goto done; switch (bs->bs_status) { @@ -1738,10 +1797,7 @@ sr_ioctl_setstate(struct sr_softc *sc, struct bioc_setstate *bs) goto done; } - printf("status change for %u:%u -> %u %u\n", - bs->bs_channel, bs->bs_target, bs->bs_status, state); - - sd->sd_set_chunk_state(sd, bs->bs_target, bs->bs_status); + sd->sd_set_chunk_state(sd, tg, bs->bs_status); rv = 0; @@ -1787,10 +1843,6 @@ sr_ioctl_createraid(struct sr_softc *sc, struct bioc_createraid *bc, int user) cl = &sd->sd_vol.sv_chunk_list; SLIST_INIT(cl); - /* we have a valid list now create an array index */ - sd->sd_vol.sv_chunks = malloc(sizeof(struct sr_chunk *) * no_chunk, - M_DEVBUF, M_WAITOK | M_ZERO); - sd->sd_meta_type = sr_meta_probe(sd, dt, no_chunk); if (sd->sd_meta_type == SR_META_F_INVALID) { printf("%s: invalid metadata format\n", DEVNAME(sc)); @@ -1972,11 +2024,11 @@ sr_ioctl_createraid(struct sr_softc *sc, struct bioc_createraid *bc, int user) "assemble it\n"); goto unwind; } - printf("%s: not yet partial bringup\n", DEVNAME(sc)); - goto unwind; + printf("%s: trying to bring up %s degraded\n", DEVNAME(sc), + sd->sd_meta->ssd_devname); } - /* XXX metadata SHALL be fully filled in at this point */ + /* metadata SHALL be fully filled in at this point */ switch (bc->bc_level) { case 0: @@ -2099,6 +2151,9 @@ sr_ioctl_createraid(struct sr_softc *sc, struct bioc_createraid *bc, int user) goto unwind; if (disk) { + /* set volume status */ + sd->sd_set_vol_state(sd); + /* setup scsi midlayer */ sd->sd_link.openings = sd->sd_max_wu; sd->sd_link.device = &sr_dev; |