summaryrefslogtreecommitdiffstats
path: root/sys/dev/softraid.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/dev/softraid.c')
-rw-r--r--sys/dev/softraid.c235
1 files changed, 100 insertions, 135 deletions
diff --git a/sys/dev/softraid.c b/sys/dev/softraid.c
index 79fc8acaad6..387c35d8f77 100644
--- a/sys/dev/softraid.c
+++ b/sys/dev/softraid.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: softraid.c,v 1.288 2013/01/18 23:19:44 jsing Exp $ */
+/* $OpenBSD: softraid.c,v 1.289 2013/03/05 10:24:00 jsing Exp $ */
/*
* Copyright (c) 2007, 2008, 2009 Marco Peereboom <marco@peereboom.us>
* Copyright (c) 2008 Chris Kuethe <ckuethe@openbsd.org>
@@ -1498,30 +1498,30 @@ void
sr_map_root(void)
{
struct sr_softc *sc = softraid0;
+ struct sr_discipline *sd;
struct sr_meta_opt_item *omi;
struct sr_meta_boot *sbm;
u_char duid[8];
- int i, j;
+ int i;
+
+ DNPRINTF(SR_D_MISC, "%s: sr_map_root\n", DEVNAME(sc));
if (sc == NULL)
return;
- DNPRINTF(SR_D_MISC, "%s: sr_map_root\n", DEVNAME(sc));
bzero(duid, sizeof(duid));
if (bcmp(rootduid, duid, sizeof(duid)) == 0) {
DNPRINTF(SR_D_MISC, "%s: root duid is zero\n", DEVNAME(sc));
return;
}
- for (i = 0; i < SR_MAX_LD; i++) {
- if (sc->sc_dis[i] == NULL)
- continue;
- SLIST_FOREACH(omi, &sc->sc_dis[i]->sd_meta_opt, omi_link) {
+ TAILQ_FOREACH(sd, &sc->sc_dis_list, sd_link) {
+ SLIST_FOREACH(omi, &sd->sd_meta_opt, omi_link) {
if (omi->omi_som->som_type != SR_OPT_BOOT)
continue;
sbm = (struct sr_meta_boot *)omi->omi_som;
- for (j = 0; j < SR_MAX_BOOT_DISKS; j++) {
- if (bcmp(rootduid, sbm->sbm_boot_duid[j],
+ for (i = 0; i < SR_MAX_BOOT_DISKS; i++) {
+ if (bcmp(rootduid, sbm->sbm_boot_duid[i],
sizeof(rootduid)) == 0) {
bcopy(sbm->sbm_root_duid, rootduid,
sizeof(rootduid));
@@ -1788,6 +1788,7 @@ sr_attach(struct device *parent, struct device *self, void *aux)
rw_init(&sc->sc_hs_lock, "sr_hs_lock");
SLIST_INIT(&sr_hotplug_callbacks);
+ TAILQ_INIT(&sc->sc_dis_list);
SLIST_INIT(&sc->sc_hotspare_list);
#if NBIO > 0
@@ -2528,14 +2529,13 @@ sr_bio_ioctl(struct device *dev, u_long cmd, caddr_t addr)
int
sr_ioctl_inq(struct sr_softc *sc, struct bioc_inq *bi)
{
- int i, vol, disk;
+ struct sr_discipline *sd;
+ int vol = 0, disk = 0;
- for (i = 0, vol = 0, disk = 0; i < SR_MAX_LD; i++)
- /* XXX this will not work when we stagger disciplines */
- if (sc->sc_dis[i]) {
- vol++;
- disk += sc->sc_dis[i]->sd_meta->ssdi.ssd_chunk_no;
- }
+ TAILQ_FOREACH(sd, &sc->sc_dis_list, sd_link) {
+ vol++;
+ disk += sd->sd_meta->ssdi.ssd_chunk_no;
+ }
strlcpy(bi->bi_dev, sc->sc_dev.dv_xname, sizeof(bi->bi_dev));
bi->bi_novol = vol + sc->sc_hotspare_no;
@@ -2547,22 +2547,16 @@ sr_ioctl_inq(struct sr_softc *sc, struct bioc_inq *bi)
int
sr_ioctl_vol(struct sr_softc *sc, struct bioc_vol *bv)
{
- int i, vol, rv = EINVAL;
+ int vol = -1, rv = EINVAL;
struct sr_discipline *sd;
struct sr_chunk *hotspare;
daddr64_t rb, sz;
- for (i = 0, vol = -1; i < SR_MAX_LD; i++) {
- /* XXX this will not work when we stagger disciplines */
- if (sc->sc_dis[i])
- vol++;
+ TAILQ_FOREACH(sd, &sc->sc_dis_list, sd_link) {
+ vol++;
if (vol != bv->bv_volid)
continue;
- if (sc->sc_dis[i] == NULL)
- goto done;
-
- sd = sc->sc_dis[i];
bv->bv_status = sd->sd_vol_status;
bv->bv_size = sd->sd_meta->ssdi.ssd_size << DEV_BSHIFT;
bv->bv_level = sd->sd_meta->ssdi.ssd_level;
@@ -2616,28 +2610,25 @@ done:
int
sr_ioctl_disk(struct sr_softc *sc, struct bioc_disk *bd)
{
- int i, vol, rv = EINVAL, id;
+ struct sr_discipline *sd;
struct sr_chunk *src, *hotspare;
+ int vol = -1, rv = EINVAL;
+
+ if (bd->bd_diskid < 0)
+ goto done;
- for (i = 0, vol = -1; i < SR_MAX_LD; i++) {
- /* XXX this will not work when we stagger disciplines */
- if (sc->sc_dis[i])
- vol++;
+ TAILQ_FOREACH(sd, &sc->sc_dis_list, sd_link) {
+ vol++;
if (vol != bd->bd_volid)
continue;
- if (sc->sc_dis[i] == NULL)
- goto done;
-
- id = bd->bd_diskid;
-
- if (id < sc->sc_dis[i]->sd_meta->ssdi.ssd_chunk_no)
- src = sc->sc_dis[i]->sd_vol.sv_chunks[id];
+ if (bd->bd_diskid < sd->sd_meta->ssdi.ssd_chunk_no)
+ src = sd->sd_vol.sv_chunks[bd->bd_diskid];
#ifdef CRYPTO
- else if (id == sc->sc_dis[i]->sd_meta->ssdi.ssd_chunk_no &&
- sc->sc_dis[i]->sd_meta->ssdi.ssd_level == 'C' &&
- sc->sc_dis[i]->mds.mdd_crypto.key_disk != NULL)
- src = sc->sc_dis[i]->mds.mdd_crypto.key_disk;
+ else if (bd->bd_diskid == sd->sd_meta->ssdi.ssd_chunk_no &&
+ sd->sd_meta->ssdi.ssd_level == 'C' &&
+ sd->mds.mdd_crypto.key_disk != NULL)
+ src = sd->mds.mdd_crypto.key_disk;
#endif
else
break;
@@ -2645,7 +2636,7 @@ sr_ioctl_disk(struct sr_softc *sc, struct bioc_disk *bd)
bd->bd_status = src->src_meta.scm_status;
bd->bd_size = src->src_meta.scmi.scm_size << DEV_BSHIFT;
bd->bd_channel = vol;
- bd->bd_target = id;
+ bd->bd_target = bd->bd_diskid;
strlcpy(bd->bd_vendor, src->src_meta.scmi.scm_devname,
sizeof(bd->bd_vendor));
rv = 0;
@@ -2679,8 +2670,8 @@ int
sr_ioctl_setstate(struct sr_softc *sc, struct bioc_setstate *bs)
{
int rv = EINVAL;
- int i, vol, found, c;
- struct sr_discipline *sd = NULL;
+ int vol = -1, found, c;
+ struct sr_discipline *sd;
struct sr_chunk *ch_entry;
struct sr_chunk_head *cl;
@@ -2692,14 +2683,10 @@ sr_ioctl_setstate(struct sr_softc *sc, struct bioc_setstate *bs)
goto done;
}
- for (i = 0, vol = -1; i < SR_MAX_LD; i++) {
- /* XXX this will not work when we stagger disciplines */
- if (sc->sc_dis[i])
- vol++;
- if (vol != bs->bs_volid)
- continue;
- sd = sc->sc_dis[i];
- break;
+ TAILQ_FOREACH(sd, &sc->sc_dis_list, sd_link) {
+ vol++;
+ if (vol == bs->bs_volid)
+ break;
}
if (sd == NULL)
goto done;
@@ -2752,7 +2739,7 @@ sr_chunk_in_use(struct sr_softc *sc, dev_t dev)
{
struct sr_discipline *sd;
struct sr_chunk *chunk;
- int i, c;
+ int i;
DNPRINTF(SR_D_MISC, "%s: sr_chunk_in_use(%d)\n", DEVNAME(sc), dev);
@@ -2760,12 +2747,9 @@ sr_chunk_in_use(struct sr_softc *sc, dev_t dev)
return BIOC_SDINVALID;
/* See if chunk is already in use. */
- for (i = 0; i < SR_MAX_LD; i++) {
- if (sc->sc_dis[i] == NULL)
- continue;
- sd = sc->sc_dis[i];
- for (c = 0; c < sd->sd_meta->ssdi.ssd_chunk_no; c++) {
- chunk = sd->sd_vol.sv_chunks[c];
+ TAILQ_FOREACH(sd, &sc->sc_dis_list, sd_link) {
+ for (i = 0; i < sd->sd_meta->ssdi.ssd_chunk_no; i++) {
+ chunk = sd->sd_vol.sv_chunks[i];
if (chunk->src_dev_mm == dev)
return chunk->src_meta.scm_status;
}
@@ -3408,6 +3392,7 @@ sr_ioctl_createraid(struct sr_softc *sc, struct bioc_createraid *bc,
}
/* Metadata MUST be fully populated by this point. */
+ TAILQ_INSERT_TAIL(&sc->sc_dis_list, sd, sd_link);
/* Allocate all resources. */
if ((rv = sd->sd_alloc_resources(sd)))
@@ -3475,6 +3460,7 @@ sr_ioctl_createraid(struct sr_softc *sc, struct bioc_createraid *bc,
DNPRINTF(SR_D_IOCTL, "%s: sr device added: %s at target %d\n",
DEVNAME(sc), dev->dv_xname, sd->sd_target);
+ /* XXX - Count volumes, not targets. */
for (i = 0, vol = -1; i <= sd->sd_target; i++)
if (sc->sc_dis[i])
vol++;
@@ -3534,27 +3520,21 @@ unwind:
}
int
-sr_ioctl_deleteraid(struct sr_softc *sc, struct bioc_deleteraid *dr)
+sr_ioctl_deleteraid(struct sr_softc *sc, struct bioc_deleteraid *bd)
{
- struct sr_discipline *sd = NULL;
+ struct sr_discipline *sd;
int rv = 1;
- int i;
DNPRINTF(SR_D_IOCTL, "%s: sr_ioctl_deleteraid %s\n", DEVNAME(sc),
dr->bd_dev);
- for (i = 0; i < SR_MAX_LD; i++)
- if (sc->sc_dis[i]) {
- if (!strncmp(sc->sc_dis[i]->sd_meta->ssd_devname,
- dr->bd_dev,
- sizeof(sc->sc_dis[i]->sd_meta->ssd_devname))) {
- sd = sc->sc_dis[i];
- break;
- }
- }
-
+ TAILQ_FOREACH(sd, &sc->sc_dis_list, sd_link) {
+ if (!strncmp(sd->sd_meta->ssd_devname, bd->bd_dev,
+ sizeof(sd->sd_meta->ssd_devname)))
+ break;
+ }
if (sd == NULL) {
- sr_error(sc, "volume %s not found", dr->bd_dev);
+ sr_error(sc, "volume %s not found", bd->bd_dev);
goto bad;
}
@@ -3570,27 +3550,28 @@ bad:
int
sr_ioctl_discipline(struct sr_softc *sc, struct bioc_discipline *bd)
{
- struct sr_discipline *sd = NULL;
- int i, rv = 1;
+ struct sr_discipline *sd;
+ int rv = 1;
/* Dispatch a discipline specific ioctl. */
DNPRINTF(SR_D_IOCTL, "%s: sr_ioctl_discipline %s\n", DEVNAME(sc),
bd->bd_dev);
- for (i = 0; i < SR_MAX_LD; i++)
- if (sc->sc_dis[i]) {
- if (!strncmp(sc->sc_dis[i]->sd_meta->ssd_devname,
- bd->bd_dev,
- sizeof(sc->sc_dis[i]->sd_meta->ssd_devname))) {
- sd = sc->sc_dis[i];
- break;
- }
- }
+ TAILQ_FOREACH(sd, &sc->sc_dis_list, sd_link) {
+ if (!strncmp(sd->sd_meta->ssd_devname, bd->bd_dev,
+ sizeof(sd->sd_meta->ssd_devname)))
+ break;
+ }
+ if (sd == NULL) {
+ sr_error(sc, "volume %s not found", bd->bd_dev);
+ goto bad;
+ }
- if (sd && sd->sd_ioctl_handler)
+ if (sd->sd_ioctl_handler)
rv = sd->sd_ioctl_handler(sd, bd);
+bad:
return (rv);
}
@@ -3598,7 +3579,7 @@ int
sr_ioctl_installboot(struct sr_softc *sc, struct bioc_installboot *bb)
{
void *bootblk = NULL, *bootldr = NULL;
- struct sr_discipline *sd = NULL;
+ struct sr_discipline *sd;
struct sr_chunk *chunk;
struct sr_meta_opt_item *omi;
struct sr_meta_boot *sbm;
@@ -3611,18 +3592,15 @@ sr_ioctl_installboot(struct sr_softc *sc, struct bioc_installboot *bb)
DNPRINTF(SR_D_IOCTL, "%s: sr_ioctl_installboot %s\n", DEVNAME(sc),
bb->bb_dev);
- for (i = 0; i < SR_MAX_LD; i++)
- if (sc->sc_dis[i]) {
- if (!strncmp(sc->sc_dis[i]->sd_meta->ssd_devname,
- bb->bb_dev,
- sizeof(sc->sc_dis[i]->sd_meta->ssd_devname))) {
- sd = sc->sc_dis[i];
- break;
- }
- }
-
- if (sd == NULL)
+ TAILQ_FOREACH(sd, &sc->sc_dis_list, sd_link) {
+ if (!strncmp(sd->sd_meta->ssd_devname, bb->bb_dev,
+ sizeof(sd->sd_meta->ssd_devname)))
+ break;
+ }
+ if (sd == NULL) {
+ sr_error(sc, "volume %s not found", bb->bb_dev);
goto done;
+ }
bzero(duid, sizeof(duid));
TAILQ_FOREACH(dk, &disklist, dk_link)
@@ -3782,6 +3760,7 @@ void
sr_discipline_free(struct sr_discipline *sd)
{
struct sr_softc *sc;
+ struct sr_discipline *sdtmp1, *sdtmp2;
struct sr_meta_opt_head *som;
struct sr_meta_opt_item *omi, *omi_next;
@@ -3815,6 +3794,13 @@ sr_discipline_free(struct sr_discipline *sd)
sc->sc_dis[sd->sd_target] = NULL;
}
+ TAILQ_FOREACH_SAFE(sdtmp1, &sc->sc_dis_list, sd_link, sdtmp2) {
+ if (sdtmp1 == sd) {
+ TAILQ_REMOVE(&sc->sc_dis_list, sd, sd_link);
+ break;
+ }
+ }
+
explicit_bzero(sd, sizeof *sd);
free(sd, M_DEVBUF);
}
@@ -3865,8 +3851,7 @@ sr_discipline_shutdown(struct sr_discipline *sd, int meta_save)
if (sd->sd_workq)
workq_destroy(sd->sd_workq);
- if (sd)
- sr_discipline_free(sd);
+ sr_discipline_free(sd);
splx(s);
}
@@ -4318,14 +4303,14 @@ int
sr_already_assembled(struct sr_discipline *sd)
{
struct sr_softc *sc = sd->sd_sc;
- int i;
+ struct sr_discipline *sdtmp;
- for (i = 0; i < SR_MAX_LD; i++)
- if (sc->sc_dis[i])
- if (!bcmp(&sd->sd_meta->ssdi.ssd_uuid,
- &sc->sc_dis[i]->sd_meta->ssdi.ssd_uuid,
- sizeof(sd->sd_meta->ssdi.ssd_uuid)))
- return (1);
+ TAILQ_FOREACH(sdtmp, &sc->sc_dis_list, sd_link) {
+ if (!bcmp(&sd->sd_meta->ssdi.ssd_uuid,
+ &sdtmp->sd_meta->ssdi.ssd_uuid,
+ sizeof(sd->sd_meta->ssdi.ssd_uuid)))
+ return (1);
+ }
return (0);
}
@@ -4360,14 +4345,13 @@ sr_shutdownhook(void *arg)
void
sr_shutdown(struct sr_softc *sc)
{
- int i;
+ struct sr_discipline *sd;
DNPRINTF(SR_D_MISC, "%s: sr_shutdown\n", DEVNAME(sc));
- /* XXX this will not work when we stagger disciplines */
- for (i = 0; i < SR_MAX_LD; i++)
- if (sc->sc_dis[i])
- sr_discipline_shutdown(sc->sc_dis[i], 1);
+ /* Shutdown disciplines in reverse attach order. */
+ while ((sd = TAILQ_LAST(&sc->sc_dis_list, sr_discipline_list)) != NULL)
+ sr_discipline_shutdown(sd, 1);
}
int
@@ -4689,16 +4673,10 @@ sr_sensors_refresh(void *arg)
struct sr_softc *sc = arg;
struct sr_volume *sv;
struct sr_discipline *sd;
- int i, vol;
DNPRINTF(SR_D_STATE, "%s: sr_sensors_refresh\n", DEVNAME(sc));
- for (i = 0, vol = -1; i < SR_MAX_LD; i++) {
- /* XXX this will not work when we stagger disciplines */
- if (!sc->sc_dis[i])
- continue;
-
- sd = sc->sc_dis[i];
+ TAILQ_FOREACH(sd, &sc->sc_dis_list, sd_link) {
sv = &sd->sd_vol;
switch(sd->sd_vol_status) {
@@ -4732,29 +4710,16 @@ void sr_print_stats(void);
void
sr_print_stats(void)
{
- struct sr_softc *sc;
+ struct sr_softc *sc = softraid0;
struct sr_discipline *sd;
- int i, vol;
- for (i = 0; i < softraid_cd.cd_ndevs; i++)
- if (softraid_cd.cd_devs[i]) {
- sc = softraid_cd.cd_devs[i];
- /* we'll only have one softc */
- break;
- }
-
- if (!sc) {
+ if (sc == NULL) {
printf("no softraid softc found\n");
return;
}
- for (i = 0, vol = -1; i < SR_MAX_LD; i++) {
- /* XXX this will not work when we stagger disciplines */
- if (!sc->sc_dis[i])
- continue;
-
- sd = sc->sc_dis[i];
- printf("%s: ios pending: %d collisions %llu\n",
+ TAILQ_FOREACH(sd, &sc->sc_dis_list, sd_link) {
+ printf("%s: ios pending %d, collisions %llu\n",
sd->sd_meta->ssd_devname,
sd->sd_wu_pending,
sd->sd_wu_collisions);