diff options
-rw-r--r-- | sys/dev/softraid.c | 168 | ||||
-rw-r--r-- | sys/dev/softraidvar.h | 19 |
2 files changed, 97 insertions, 90 deletions
diff --git a/sys/dev/softraid.c b/sys/dev/softraid.c index 3184189a57c..d01b2ce5e4c 100644 --- a/sys/dev/softraid.c +++ b/sys/dev/softraid.c @@ -1,4 +1,4 @@ -/* $OpenBSD: softraid.c,v 1.231 2011/06/20 09:16:05 matthew Exp $ */ +/* $OpenBSD: softraid.c,v 1.232 2011/06/23 17:20:16 matthew Exp $ */ /* * Copyright (c) 2007, 2008, 2009 Marco Peereboom <marco@peereboom.us> * Copyright (c) 2008 Chris Kuethe <ckuethe@openbsd.org> @@ -87,7 +87,8 @@ struct cfdriver softraid_cd = { /* scsi & discipline */ void sr_scsi_cmd(struct scsi_xfer *); -void sr_minphys(struct buf *bp, struct scsi_link *sl); +void sr_minphys(struct buf *, struct scsi_link *); +int sr_scsi_probe(struct scsi_link *); void sr_copy_internal_data(struct scsi_xfer *, void *, size_t); int sr_scsi_ioctl(struct scsi_link *, u_long, @@ -167,7 +168,7 @@ extern void (*softraid_disk_attach)(struct disk *, int); /* scsi glue */ struct scsi_adapter sr_switch = { - sr_scsi_cmd, sr_minphys, NULL, NULL, sr_scsi_ioctl + sr_scsi_cmd, sr_minphys, sr_scsi_probe, NULL, sr_scsi_ioctl }; /* native metadata format */ @@ -1632,6 +1633,7 @@ void sr_attach(struct device *parent, struct device *self, void *aux) { struct sr_softc *sc = (void *)self; + struct scsibus_attach_args saa; DNPRINTF(SR_D_MISC, "\n%s: sr_attach", DEVNAME(sc)); @@ -1656,6 +1658,18 @@ sr_attach(struct device *parent, struct device *self, void *aux) printf("\n"); + sc->sc_link.adapter_softc = sc; + sc->sc_link.adapter = &sr_switch; + sc->sc_link.adapter_target = SR_MAX_LD; + sc->sc_link.adapter_buswidth = SR_MAX_LD; + sc->sc_link.luns = 1; + + bzero(&saa, sizeof(saa)); + saa.saa_sc_link = &sc->sc_link; + + sc->sc_scsibus = (struct scsibus_softc *)config_found(&sc->sc_dev, + &saa, scsiprint); + softraid_disk_attach = sr_disk_attach; sr_boot_assembly(sc); @@ -1910,19 +1924,10 @@ sr_scsi_cmd(struct scsi_xfer *xs) DNPRINTF(SR_D_CMD, "%s: sr_scsi_cmd: scsibus%d xs: %p " "flags: %#x\n", DEVNAME(sc), link->scsibus, xs, xs->flags); - sd = sc->sc_dis[link->scsibus]; + sd = sc->sc_dis[link->target]; if (sd == NULL) { - s = splhigh(); - sd = sc->sc_attach_dis; - splx(s); - - DNPRINTF(SR_D_CMD, "%s: sr_scsi_cmd: attaching %p\n", - DEVNAME(sc), sd); - if (sd == NULL) { - printf("%s: sr_scsi_cmd NULL discipline\n", - DEVNAME(sc)); - goto stuffup; - } + printf("%s: sr_scsi_cmd NULL discipline\n", DEVNAME(sc)); + goto stuffup; } if (sd->sd_deleted) { @@ -1948,19 +1953,6 @@ sr_scsi_cmd(struct scsi_xfer *xs) wu->swu_dis = sd; wu->swu_xs = xs; - /* the midlayer will query LUNs so report sense to stop scanning */ - if (link->target != 0 || link->lun != 0) { - DNPRINTF(SR_D_CMD, "%s: bad target:lun %d:%d\n", - DEVNAME(sc), link->target, link->lun); - sd->sd_scsi_sense.error_code = SSD_ERRCODE_CURRENT | - SSD_ERRCODE_VALID; - sd->sd_scsi_sense.flags = SKEY_ILLEGAL_REQUEST; - sd->sd_scsi_sense.add_sense_code = 0x25; - sd->sd_scsi_sense.add_sense_code_qual = 0x00; - sd->sd_scsi_sense.extra_len = 4; - goto stuffup; - } - switch (xs->cmd->opcode) { case READ_COMMAND: case READ_BIG: @@ -2036,6 +2028,28 @@ stuffup: complete: sr_scsi_done(sd, xs); } + +int +sr_scsi_probe(struct scsi_link *link) +{ + struct sr_softc *sc = link->adapter_softc; + struct sr_discipline *sd; + + KASSERT(link->target < SR_MAX_LD && link->lun == 0); + + sd = sc->sc_dis[link->target]; + if (sd == NULL) + return (ENODEV); + + link->pool = &sd->sd_iopool; + if (sd->sd_openings) + link->openings = sd->sd_openings(sd); + else + link->openings = sd->sd_max_wu; + + return (0); +} + int sr_scsi_ioctl(struct scsi_link *link, u_long cmd, caddr_t addr, int flag) { @@ -2124,7 +2138,7 @@ sr_ioctl_inq(struct sr_softc *sc, struct bioc_inq *bi) { int i, vol, disk; - for (i = 0, vol = 0, disk = 0; i < SR_MAXSCSIBUS; i++) + 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++; @@ -2146,7 +2160,7 @@ sr_ioctl_vol(struct sr_softc *sc, struct bioc_vol *bv) struct sr_chunk *hotspare; daddr64_t rb, sz; - for (i = 0, vol = -1; i < SR_MAXSCSIBUS; i++) { + 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++; @@ -2213,7 +2227,7 @@ sr_ioctl_disk(struct sr_softc *sc, struct bioc_disk *bd) int i, vol, rv = EINVAL, id; struct sr_chunk *src, *hotspare; - for (i = 0, vol = -1; i < SR_MAXSCSIBUS; i++) { + 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++; @@ -2286,7 +2300,7 @@ sr_ioctl_setstate(struct sr_softc *sc, struct bioc_setstate *bs) goto done; } - for (i = 0, vol = -1; i < SR_MAXSCSIBUS; i++) { + 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++; @@ -2350,7 +2364,7 @@ sr_chunk_in_use(struct sr_softc *sc, dev_t dev) int i, c; /* See if chunk is already in use. */ - for (i = 0; i < SR_MAXSCSIBUS; i++) { + for (i = 0; i < SR_MAX_LD; i++) { if (sc->sc_dis[i] == NULL) continue; sd = sc->sc_dis[i]; @@ -2825,13 +2839,13 @@ int sr_ioctl_createraid(struct sr_softc *sc, struct bioc_createraid *bc, int user) { dev_t *dt; - int i, s, no_chunk, rv = EINVAL, vol; + int i, no_chunk, rv = EINVAL, target, vol; int no_meta, updatemeta = 0; struct sr_chunk_head *cl; struct sr_discipline *sd = NULL; struct sr_chunk *ch_entry; - struct device *dev, *dev2; - struct scsibus_attach_args saa; + struct scsi_link *link; + struct device *dev; char devname[32]; DNPRINTF(SR_D_IOCTL, "%s: sr_ioctl_createraid(%d)\n", @@ -3024,52 +3038,52 @@ sr_ioctl_createraid(struct sr_softc *sc, struct bioc_createraid *bc, int user) goto unwind; } - /* setup scsi midlayer */ + /* setup scsi iopool */ mtx_init(&sd->sd_wu_mtx, IPL_BIO); scsi_iopool_init(&sd->sd_iopool, sd, sr_wu_get, sr_wu_put); - if (sd->sd_openings) - sd->sd_link.openings = sd->sd_openings(sd); - else - sd->sd_link.openings = sd->sd_max_wu; - sd->sd_link.device_softc = sc; - sd->sd_link.adapter_softc = sc; - sd->sd_link.adapter = &sr_switch; - sd->sd_link.adapter_target = SR_MAX_LD; - sd->sd_link.adapter_buswidth = 1; - sd->sd_link.pool = &sd->sd_iopool; - bzero(&saa, sizeof(saa)); - saa.saa_sc_link = &sd->sd_link; /* * we passed all checks return ENXIO if volume can't be created */ rv = ENXIO; + /* + * Find a free target. + * + * XXX: We reserve sd_target == 0 to indicate the + * discipline is not linked into sc->sc_dis, so begin + * the search with target = 1. + */ + for (target = 1; target < SR_MAX_LD; target++) + if (sc->sc_dis[target] == NULL) + break; + if (target == SR_MAX_LD) { + printf("%s: no free target for %s\n", DEVNAME(sc), + sd->sd_meta->ssd_devname); + goto unwind; + } + /* clear sense data */ bzero(&sd->sd_scsi_sense, sizeof(sd->sd_scsi_sense)); - /* use temporary discipline pointer */ - s = splhigh(); - sc->sc_attach_dis = sd; - splx(s); - dev2 = config_found(&sc->sc_dev, &saa, scsiprint); - s = splhigh(); - sc->sc_attach_dis = NULL; - splx(s); - TAILQ_FOREACH(dev, &alldevs, dv_list) - if (dev->dv_parent == dev2) - break; - if (dev == NULL) + /* attach disclipline and kick midlayer to probe it */ + sd->sd_target = target; + sc->sc_dis[target] = sd; + if (scsi_probe_lun(sc->sc_scsibus, target, 0) != 0) { + printf("%s: scsi_probe_lun failed\n", DEVNAME(sc)); + sc->sc_dis[target] = NULL; + sd->sd_target = 0; goto unwind; + } + link = scsi_get_link(sc->sc_scsibus, target, 0); + dev = link->device_softc; DNPRINTF(SR_D_IOCTL, "%s: sr device added: %s on scsibus%d\n", DEVNAME(sc), dev->dv_xname, sd->sd_link.scsibus); - sc->sc_dis[sd->sd_link.scsibus] = sd; - for (i = 0, vol = -1; i <= sd->sd_link.scsibus; i++) + for (i = 0, vol = -1; i <= sd->sd_target; i++) if (sc->sc_dis[i]) vol++; - sd->sd_scsibus_dev = dev2; rv = 0; if (updatemeta) { @@ -3145,7 +3159,7 @@ sr_ioctl_deleteraid(struct sr_softc *sc, struct bioc_deleteraid *dr) DNPRINTF(SR_D_IOCTL, "%s: sr_ioctl_deleteraid %s\n", DEVNAME(sc), dr->bd_dev); - for (i = 0; i < SR_MAXSCSIBUS; i++) + 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, @@ -3178,7 +3192,7 @@ sr_ioctl_discipline(struct sr_softc *sc, struct bioc_discipline *bd) DNPRINTF(SR_D_IOCTL, "%s: sr_ioctl_discipline %s\n", DEVNAME(sc), bd->bd_dev); - for (i = 0; i < SR_MAXSCSIBUS; i++) + 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, @@ -3207,7 +3221,7 @@ 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_MAXSCSIBUS; i++) + 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, @@ -3338,7 +3352,6 @@ sr_discipline_free(struct sr_discipline *sd) struct sr_softc *sc; struct sr_meta_opt_head *omh; struct sr_meta_opt_item *omi, *omi_next; - int i; if (!sd) return; @@ -3363,11 +3376,10 @@ sr_discipline_free(struct sr_discipline *sd) free(omi, M_DEVBUF); } - for (i = 0; i < SR_MAXSCSIBUS; i++) - if (sc->sc_dis[i] == sd) { - sc->sc_dis[i] = NULL; - break; - } + if (sd->sd_target != 0) { + KASSERT(sc->sc_dis[sd->sd_target] == sd); + sc->sc_dis[sd->sd_target] = NULL; + } explicit_bzero(sd, sizeof *sd); free(sd, M_DEVBUF); @@ -3403,8 +3415,8 @@ sr_discipline_shutdown(struct sr_discipline *sd) sr_sensors_delete(sd); #endif /* SMALL_KERNEL */ - if (sd->sd_scsibus_dev) - config_detach(sd->sd_scsibus_dev, DETACH_FORCE); + if (sd->sd_target != 0) + scsi_detach_lun(sc->sc_scsibus, sd->sd_target, 0, DETACH_FORCE); sr_chunks_unwind(sc, &sd->sd_vol.sv_chunk_list); @@ -3722,7 +3734,7 @@ sr_already_assembled(struct sr_discipline *sd) struct sr_softc *sc = sd->sd_sc; int i; - for (i = 0; i < SR_MAXSCSIBUS; i++) + 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, @@ -4095,7 +4107,7 @@ sr_sensors_refresh(void *arg) DNPRINTF(SR_D_STATE, "%s: sr_sensors_refresh\n", DEVNAME(sc)); - for (i = 0, vol = -1; i < SR_MAXSCSIBUS; i++) { + 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; @@ -4150,7 +4162,7 @@ sr_print_stats(void) return; } - for (i = 0, vol = -1; i < SR_MAXSCSIBUS; i++) { + 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; diff --git a/sys/dev/softraidvar.h b/sys/dev/softraidvar.h index 821173f5fbd..d1b1baedf47 100644 --- a/sys/dev/softraidvar.h +++ b/sys/dev/softraidvar.h @@ -1,4 +1,4 @@ -/* $OpenBSD: softraidvar.h,v 1.99 2011/04/05 19:52:02 krw Exp $ */ +/* $OpenBSD: softraidvar.h,v 1.100 2011/06/23 17:20:16 matthew Exp $ */ /* * Copyright (c) 2006 Marco Peereboom <marco@peereboom.us> * Copyright (c) 2008 Chris Kuethe <ckuethe@openbsd.org> @@ -274,7 +274,7 @@ extern u_int32_t sr_debug; #endif #define SR_MAXFER MAXPHYS -#define SR_MAX_LD 1 +#define SR_MAX_LD 256 #define SR_MAX_CMDS 16 #define SR_MAX_STATES 7 #define SR_VM_IGNORE_DIRTY 1 @@ -470,8 +470,7 @@ struct sr_discipline { #define SR_MD_RAID4 7 #define SR_MD_RAID6 8 char sd_name[10]; /* human readable dis name */ - u_int8_t sd_scsibus; /* scsibus discipline uses */ - struct scsi_link sd_link; /* link to midlayer */ + u_int16_t sd_target; /* scsibus target discipline uses */ u_int32_t sd_capabilities; #define SR_CAP_SYSTEM_DISK 0x00000001 @@ -578,18 +577,14 @@ struct sr_softc { struct ksensordev sc_sensordev; int sc_sensors_running; - /* - * during scsibus attach this is the discipline that is in use - * this variable is protected by sc_lock and splhigh - */ - struct sr_discipline *sc_attach_dis; + struct scsi_link sc_link; /* scsi prototype link */ + struct scsibus_softc *sc_scsibus; /* * XXX expensive, alternative would be nice but has to be cheap - * since the scsibus lookup happens on each IO + * since the target lookup happens on each IO */ -#define SR_MAXSCSIBUS 256 - struct sr_discipline *sc_dis[SR_MAXSCSIBUS]; /* scsibus is u_int8_t */ + struct sr_discipline *sc_dis[SR_MAX_LD]; }; /* hotplug */ |