diff options
-rw-r--r-- | sys/scsi/mpath.c | 98 | ||||
-rw-r--r-- | sys/scsi/mpath_emc.c | 11 | ||||
-rw-r--r-- | sys/scsi/mpath_hds.c | 5 | ||||
-rw-r--r-- | sys/scsi/mpath_rdac.c | 11 | ||||
-rw-r--r-- | sys/scsi/mpath_sym.c | 6 | ||||
-rw-r--r-- | sys/scsi/mpathvar.h | 4 |
6 files changed, 100 insertions, 35 deletions
diff --git a/sys/scsi/mpath.c b/sys/scsi/mpath.c index f7c88dcb6bf..78d839d04cb 100644 --- a/sys/scsi/mpath.c +++ b/sys/scsi/mpath.c @@ -1,4 +1,4 @@ -/* $OpenBSD: mpath.c,v 1.27 2013/08/26 06:54:32 dlg Exp $ */ +/* $OpenBSD: mpath.c,v 1.28 2013/08/26 07:29:45 dlg Exp $ */ /* * Copyright (c) 2009 David Gwynne <dlg@openbsd.org> @@ -42,15 +42,20 @@ void mpath_shutdown(void *); TAILQ_HEAD(mpath_paths, mpath_path); +struct mpath_group { + TAILQ_ENTRY(mpath_group) g_entry; + struct mpath_paths g_paths; + u_int g_id; +}; +TAILQ_HEAD(mpath_groups, mpath_group); + struct mpath_dev { struct mutex d_mtx; struct scsi_xfer_list d_xfers; - struct mpath_paths d_paths; + struct mpath_groups d_groups; struct mpath_path *d_next_path; - u_int d_path_count; - const struct mpath_ops *d_ops; struct devid *d_id; }; @@ -146,6 +151,7 @@ mpath_probe(struct scsi_link *link) struct mpath_path * mpath_next_path(struct mpath_dev *d, int next) { + struct mpath_group *g; struct mpath_path *p; if (d == NULL) @@ -154,8 +160,10 @@ mpath_next_path(struct mpath_dev *d, int next) p = d->d_next_path; if (p != NULL && next == MPATH_NEXT) { d->d_next_path = TAILQ_NEXT(p, p_entry); - if (d->d_next_path == NULL) - d->d_next_path = TAILQ_FIRST(&d->d_paths); + if (d->d_next_path == NULL) { + g = TAILQ_FIRST(&d->d_groups); + d->d_next_path = TAILQ_FIRST(&g->g_paths); + } } return (p); @@ -307,6 +315,7 @@ mpath_minphys(struct buf *bp, struct scsi_link *link) { struct mpath_softc *sc = link->adapter_softc; struct mpath_dev *d = sc->sc_devs[link->target]; + struct mpath_group *g; struct mpath_path *p; #ifdef DIAGNOSTIC @@ -314,8 +323,14 @@ mpath_minphys(struct buf *bp, struct scsi_link *link) panic("mpath_minphys against nonexistant device"); #endif - TAILQ_FOREACH(p, &d->d_paths, p_entry) - p->p_link->adapter->scsi_minphys(bp, p->p_link); + mtx_enter(&d->d_mtx); + TAILQ_FOREACH(g, &d->d_groups, g_entry) { + TAILQ_FOREACH(p, &g->g_paths, p_entry) { + /* XXX crossing layers with mutex held */ + p->p_link->adapter->scsi_minphys(bp, p->p_link); + } + } + mtx_leave(&d->d_mtx); } int @@ -334,11 +349,12 @@ mpath_path_probe(struct scsi_link *link) } int -mpath_path_attach(struct mpath_path *p, const struct mpath_ops *ops) +mpath_path_attach(struct mpath_path *p, u_int g_id, const struct mpath_ops *ops) { struct mpath_softc *sc = mpath; struct scsi_link *link = p->p_link; struct mpath_dev *d = NULL; + struct mpath_group *g; int newdev = 0, addxsh = 0; int target; @@ -367,13 +383,12 @@ mpath_path_attach(struct mpath_path *p, const struct mpath_ops *ops) if (target >= MPATH_BUSWIDTH) return (ENXIO); - d = malloc(sizeof(*d), M_DEVBUF, - M_WAITOK | M_CANFAIL | M_ZERO); + d = malloc(sizeof(*d), M_DEVBUF, M_WAITOK | M_CANFAIL | M_ZERO); if (d == NULL) return (ENOMEM); mtx_init(&d->d_mtx, IPL_BIO); - TAILQ_INIT(&d->d_paths); + TAILQ_INIT(&d->d_groups); SIMPLEQ_INIT(&d->d_xfers); d->d_id = devid_copy(link->id); d->d_ops = ops; @@ -390,17 +405,44 @@ mpath_path_attach(struct mpath_path *p, const struct mpath_ops *ops) link->id = devid_copy(d->d_id); } + TAILQ_FOREACH(g, &d->d_groups, g_entry) { + if (g->g_id == g_id) + break; + } + + if (g == NULL) { + g = malloc(sizeof(*g), M_DEVBUF, + M_WAITOK | M_CANFAIL | M_ZERO); + if (g == NULL) { + if (newdev) + free(d, M_DEVBUF); + + return (ENOMEM); + } + + TAILQ_INIT(&g->g_paths); + g->g_id = g_id; + + mtx_enter(&d->d_mtx); + TAILQ_INSERT_TAIL(&d->d_groups, g, g_entry); + mtx_leave(&d->d_mtx); + } + p->p_dev = d; + mtx_enter(&d->d_mtx); - if (TAILQ_EMPTY(&d->d_paths)) + + if (d->d_next_path == NULL) d->d_next_path = p; - TAILQ_INSERT_TAIL(&d->d_paths, p, p_entry); - d->d_path_count++; + + TAILQ_INSERT_TAIL(&g->g_paths, p, p_entry); + if (!SIMPLEQ_EMPTY(&d->d_xfers)) addxsh = 1; + mtx_leave(&d->d_mtx); - if (newdev && mpath != NULL) + if (newdev) scsi_probe_target(mpath->sc_scsibus, target); else if (addxsh) scsi_xsh_add(&p->p_xsh); @@ -412,6 +454,7 @@ int mpath_path_detach(struct mpath_path *p) { struct mpath_dev *d = p->p_dev; + struct mpath_group *g; struct mpath_path *np = NULL; #ifdef DIAGNOSTIC @@ -421,11 +464,17 @@ mpath_path_detach(struct mpath_path *p) p->p_dev = NULL; mtx_enter(&d->d_mtx); - TAILQ_REMOVE(&d->d_paths, p, p_entry); + g = TAILQ_FIRST(&d->d_groups); + + TAILQ_REMOVE(&g->g_paths, p, p_entry); if (d->d_next_path == p) - d->d_next_path = TAILQ_FIRST(&d->d_paths); + d->d_next_path = TAILQ_FIRST(&g->g_paths); + + if (TAILQ_EMPTY(&g->g_paths)) { + TAILQ_REMOVE(&d->d_groups, g, g_entry); + free(g, M_DEVBUF); + } - d->d_path_count--; if (!SIMPLEQ_EMPTY(&d->d_xfers)) np = d->d_next_path; mtx_leave(&d->d_mtx); @@ -443,6 +492,7 @@ mpath_bootdv(struct device *dev) { struct mpath_softc *sc = mpath; struct mpath_dev *d; + struct mpath_group *g; struct mpath_path *p; int target; @@ -453,10 +503,12 @@ mpath_bootdv(struct device *dev) if ((d = sc->sc_devs[target]) == NULL) continue; - TAILQ_FOREACH(p, &d->d_paths, p_entry) { - if (p->p_link->device_softc == dev) { - return (scsi_get_link(mpath->sc_scsibus, - target, 0)->device_softc); + TAILQ_FOREACH(g, &d->d_groups, g_entry) { + TAILQ_FOREACH(p, &g->g_paths, p_entry) { + if (p->p_link->device_softc == dev) { + return (scsi_get_link(mpath->sc_scsibus, + target, 0)->device_softc); + } } } } diff --git a/sys/scsi/mpath_emc.c b/sys/scsi/mpath_emc.c index aa55f875a67..1d61690f29f 100644 --- a/sys/scsi/mpath_emc.c +++ b/sys/scsi/mpath_emc.c @@ -1,4 +1,4 @@ -/* $OpenBSD: mpath_emc.c,v 1.8 2011/07/11 01:02:48 dlg Exp $ */ +/* $OpenBSD: mpath_emc.c,v 1.9 2013/08/26 07:29:45 dlg Exp $ */ /* * Copyright (c) 2011 David Gwynne <dlg@openbsd.org> @@ -171,10 +171,13 @@ emc_attach(struct device *parent, struct device *self, void *aux) printf("%s: %s %s SP-%c port %d\n", DEVNAME(sc), model, serial, sc->sc_sp + 'A', sc->sc_port); - if (sc->sc_lun_state == EMC_SP_INFO_LUN_STATE_OWNED) { - if (mpath_path_attach(&sc->sc_path, &emc_mpath_ops) != 0) - printf("%s: unable to attach path\n", DEVNAME(sc)); + if (sc->sc_lun_state != EMC_SP_INFO_LUN_STATE_OWNED) { + /* XXX add failover support */ + return; } + + if (mpath_path_attach(&sc->sc_path, sc->sc_sp, &emc_mpath_ops) != 0) + printf("%s: unable to attach path\n", DEVNAME(sc)); } int diff --git a/sys/scsi/mpath_hds.c b/sys/scsi/mpath_hds.c index 8eb1c046fc7..59628f28bed 100644 --- a/sys/scsi/mpath_hds.c +++ b/sys/scsi/mpath_hds.c @@ -1,4 +1,4 @@ -/* $OpenBSD: mpath_hds.c,v 1.6 2011/07/11 01:02:48 dlg Exp $ */ +/* $OpenBSD: mpath_hds.c,v 1.7 2013/08/26 07:29:45 dlg Exp $ */ /* * Copyright (c) 2011 David Gwynne <dlg@openbsd.org> @@ -172,7 +172,8 @@ hds_attach(struct device *parent, struct device *self, void *aux) if (!preferred) return; - if (mpath_path_attach(&sc->sc_path, &hds_mpath_ops) != 0) + /* XXX id isnt real, needs to come from hds_info */ + if (mpath_path_attach(&sc->sc_path, 0, &hds_mpath_ops) != 0) printf("%s: unable to attach path\n", DEVNAME(sc)); } diff --git a/sys/scsi/mpath_rdac.c b/sys/scsi/mpath_rdac.c index 52904778d0e..6e9f2835f4a 100644 --- a/sys/scsi/mpath_rdac.c +++ b/sys/scsi/mpath_rdac.c @@ -1,4 +1,4 @@ -/* $OpenBSD: mpath_rdac.c,v 1.8 2013/08/26 07:21:18 dlg Exp $ */ +/* $OpenBSD: mpath_rdac.c,v 1.9 2013/08/26 07:29:45 dlg Exp $ */ /* * Copyright (c) 2010 David Gwynne <dlg@openbsd.org> @@ -201,6 +201,7 @@ rdac_attach(struct device *parent, struct device *self, void *aux) struct rdac_softc *sc = (struct rdac_softc *)self; struct scsi_attach_args *sa = aux; struct scsi_link *link = sa->sa_sc_link; + int id; printf("\n"); @@ -217,7 +218,13 @@ rdac_attach(struct device *parent, struct device *self, void *aux) if (rdac_c9(sc) != 0) return; - if (mpath_path_attach(&sc->sc_path, &rdac_mpath_ops) != 0) + id = rdac_groupid(sc); + if (id == -1) { + /* error printed by rdac_groupid */ + return; + } + + if (mpath_path_attach(&sc->sc_path, id, &rdac_mpath_ops) != 0) printf("%s: unable to attach path\n", DEVNAME(sc)); } diff --git a/sys/scsi/mpath_sym.c b/sys/scsi/mpath_sym.c index ccbca1fafce..778423eb6f4 100644 --- a/sys/scsi/mpath_sym.c +++ b/sys/scsi/mpath_sym.c @@ -1,4 +1,4 @@ -/* $OpenBSD: mpath_sym.c,v 1.9 2013/06/10 03:56:43 dlg Exp $ */ +/* $OpenBSD: mpath_sym.c,v 1.10 2013/08/26 07:29:45 dlg Exp $ */ /* * Copyright (c) 2010 David Gwynne <dlg@openbsd.org> @@ -142,6 +142,7 @@ sym_attach(struct device *parent, struct device *self, void *aux) struct scsi_inquiry_data *inq = sa->sa_inqbuf; const struct mpath_ops *ops = &sym_mpath_sym_ops; struct sym_device *s; + u_int id = 0; int i; printf("\n"); @@ -153,6 +154,7 @@ sym_attach(struct device *parent, struct device *self, void *aux) if (bcmp(s->vendor, inq->vendor, strlen(s->vendor)) == 0 && bcmp(s->product, inq->product, strlen(s->product)) == 0) { ops = &sym_mpath_asym_ops; + id = sc->sc_dev.dv_unit; break; } } @@ -164,7 +166,7 @@ sym_attach(struct device *parent, struct device *self, void *aux) scsi_xsh_set(&sc->sc_path.p_xsh, link, sym_mpath_start); sc->sc_path.p_link = link; - if (mpath_path_attach(&sc->sc_path, ops) != 0) + if (mpath_path_attach(&sc->sc_path, id, ops) != 0) printf("%s: unable to attach path\n", DEVNAME(sc)); } diff --git a/sys/scsi/mpathvar.h b/sys/scsi/mpathvar.h index a4c7ca4171f..45a858dacc0 100644 --- a/sys/scsi/mpathvar.h +++ b/sys/scsi/mpathvar.h @@ -1,4 +1,4 @@ -/* $OpenBSD: mpathvar.h,v 1.4 2013/06/10 04:16:33 dlg Exp $ */ +/* $OpenBSD: mpathvar.h,v 1.5 2013/08/26 07:29:45 dlg Exp $ */ /* * Copyright (c) 2010 David Gwynne <dlg@openbsd.org> @@ -47,7 +47,7 @@ struct mpath_path { }; int mpath_path_probe(struct scsi_link *); -int mpath_path_attach(struct mpath_path *, +int mpath_path_attach(struct mpath_path *, u_int, const struct mpath_ops *); void mpath_path_state(struct mpath_path *, int); int mpath_path_detach(struct mpath_path *); |