summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sys/scsi/mpath.c98
-rw-r--r--sys/scsi/mpath_emc.c11
-rw-r--r--sys/scsi/mpath_hds.c5
-rw-r--r--sys/scsi/mpath_rdac.c11
-rw-r--r--sys/scsi/mpath_sym.c6
-rw-r--r--sys/scsi/mpathvar.h4
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 *);