summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authordlg <dlg@openbsd.org>2011-07-11 01:02:48 +0000
committerdlg <dlg@openbsd.org>2011-07-11 01:02:48 +0000
commitc32a5b15a2680a9ab66c4f6811decbf93cf3b75c (patch)
treef25c34efdd418851e18b613953a7f56ea3fe9420
parentdisks report trim^Wunmap^Wif theyre thin provisioned via a bit in (diff)
downloadwireguard-openbsd-c32a5b15a2680a9ab66c4f6811decbf93cf3b75c.tar.xz
wireguard-openbsd-c32a5b15a2680a9ab66c4f6811decbf93cf3b75c.zip
support "failover" style access to volumes, ie, only use one active
path when talking to an array until it goes away, then you fail over to the next active path. im using this to talk to ses(4) in my dell, and allows us to support arrays that have multiple controllers but have no way of reporting which one is active. using the MRU semantic means we can talk to them without them flipping the active role between its controllers all the time. claudios transtec iscsi box is like this.
-rw-r--r--sys/scsi/mpath.c26
-rw-r--r--sys/scsi/mpath_emc.c8
-rw-r--r--sys/scsi/mpath_hds.c10
-rw-r--r--sys/scsi/mpath_rdac.c8
-rw-r--r--sys/scsi/mpath_sym.c47
-rw-r--r--sys/scsi/mpathvar.h11
6 files changed, 79 insertions, 31 deletions
diff --git a/sys/scsi/mpath.c b/sys/scsi/mpath.c
index 799d8d2ed9a..9e50a970fe6 100644
--- a/sys/scsi/mpath.c
+++ b/sys/scsi/mpath.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: mpath.c,v 1.23 2011/07/08 22:09:27 matthew Exp $ */
+/* $OpenBSD: mpath.c,v 1.24 2011/07/11 01:02:48 dlg Exp $ */
/*
* Copyright (c) 2009 David Gwynne <dlg@openbsd.org>
@@ -58,6 +58,7 @@ struct mpath_dev {
u_int d_path_count;
+ const struct mpath_ops *d_ops;
struct devid *d_id;
};
@@ -89,7 +90,7 @@ void mpath_cmd(struct scsi_xfer *);
void mpath_minphys(struct buf *, struct scsi_link *);
int mpath_probe(struct scsi_link *);
-struct mpath_path *mpath_next_path(struct mpath_dev *);
+struct mpath_path *mpath_next_path(struct mpath_dev *, int);
void mpath_done(struct scsi_xfer *);
struct scsi_adapter mpath_switch = {
@@ -161,7 +162,7 @@ mpath_probe(struct scsi_link *link)
}
struct mpath_path *
-mpath_next_path(struct mpath_dev *d)
+mpath_next_path(struct mpath_dev *d, int next)
{
struct mpath_path *p;
@@ -169,7 +170,7 @@ mpath_next_path(struct mpath_dev *d)
panic("%s: d is NULL", __func__);
p = d->d_next_path;
- if (p != NULL) {
+ 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);
@@ -194,7 +195,7 @@ mpath_cmd(struct scsi_xfer *xs)
if (ISSET(xs->flags, SCSI_POLL)) {
mtx_enter(&d->d_mtx);
- p = mpath_next_path(d);
+ p = mpath_next_path(d, d->d_ops->op_schedule);
mtx_leave(&d->d_mtx);
if (p == NULL) {
mpath_xs_stuffup(xs);
@@ -232,7 +233,7 @@ mpath_cmd(struct scsi_xfer *xs)
mtx_enter(&d->d_mtx);
SIMPLEQ_INSERT_TAIL(&d->d_ccbs, ccb, c_entry);
- p = mpath_next_path(d);
+ p = mpath_next_path(d, d->d_ops->op_schedule);
mtx_leave(&d->d_mtx);
if (p != NULL)
@@ -294,11 +295,15 @@ mpath_done(struct scsi_xfer *mxs)
struct mpath_ccb *ccb = xs->io;
struct mpath_dev *d = mpath_devs[link->target];
struct mpath_path *p;
+ int next = d->d_ops->op_schedule;
- if (mxs->error == XS_RESET || mxs->error == XS_SELTIMEOUT) {
+ switch (mxs->error) {
+ case XS_SELTIMEOUT: /* physical path is gone, try the next */
+ next = MPATH_NEXT;
+ case XS_RESET:
mtx_enter(&d->d_mtx);
SIMPLEQ_INSERT_HEAD(&d->d_ccbs, ccb, c_entry);
- p = mpath_next_path(d);
+ p = mpath_next_path(d, next);
mtx_leave(&d->d_mtx);
scsi_xs_put(mxs);
@@ -363,7 +368,7 @@ mpath_path_probe(struct scsi_link *link)
}
int
-mpath_path_attach(struct mpath_path *p)
+mpath_path_attach(struct mpath_path *p, const struct mpath_ops *ops)
{
struct scsi_link *link = p->p_link;
struct mpath_dev *d = NULL;
@@ -381,7 +386,7 @@ mpath_path_attach(struct mpath_path *p)
if ((d = mpath_devs[target]) == NULL)
continue;
- if (DEVID_CMP(d->d_id, link->id))
+ if (DEVID_CMP(d->d_id, link->id) && d->d_ops == ops)
break;
d = NULL;
@@ -404,6 +409,7 @@ mpath_path_attach(struct mpath_path *p)
TAILQ_INIT(&d->d_paths);
SIMPLEQ_INIT(&d->d_ccbs);
d->d_id = devid_copy(link->id);
+ d->d_ops = ops;
mpath_devs[target] = d;
newdev = 1;
diff --git a/sys/scsi/mpath_emc.c b/sys/scsi/mpath_emc.c
index 240f62ef571..aa55f875a67 100644
--- a/sys/scsi/mpath_emc.c
+++ b/sys/scsi/mpath_emc.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: mpath_emc.c,v 1.7 2011/07/03 15:47:18 matthew Exp $ */
+/* $OpenBSD: mpath_emc.c,v 1.8 2011/07/11 01:02:48 dlg Exp $ */
/*
* Copyright (c) 2011 David Gwynne <dlg@openbsd.org>
@@ -94,11 +94,12 @@ int emc_mpath_checksense(struct scsi_xfer *);
int emc_mpath_online(struct scsi_link *);
int emc_mpath_offline(struct scsi_link *);
-struct mpath_ops emc_mpath_ops = {
+const struct mpath_ops emc_mpath_ops = {
"emc",
emc_mpath_checksense,
emc_mpath_online,
emc_mpath_offline,
+ MPATH_ROUNDROBIN
};
struct emc_device {
@@ -156,7 +157,6 @@ emc_attach(struct device *parent, struct device *self, void *aux)
/* init path */
scsi_xsh_set(&sc->sc_path.p_xsh, link, emc_mpath_start);
sc->sc_path.p_link = link;
- sc->sc_path.p_ops = &emc_mpath_ops;
if (emc_sp_info(sc)) {
printf("%s: unable to get sp info\n", DEVNAME(sc));
@@ -172,7 +172,7 @@ emc_attach(struct device *parent, struct device *self, void *aux)
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) != 0)
+ if (mpath_path_attach(&sc->sc_path, &emc_mpath_ops) != 0)
printf("%s: unable to attach path\n", DEVNAME(sc));
}
}
diff --git a/sys/scsi/mpath_hds.c b/sys/scsi/mpath_hds.c
index 2c0aae8e334..8eb1c046fc7 100644
--- a/sys/scsi/mpath_hds.c
+++ b/sys/scsi/mpath_hds.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: mpath_hds.c,v 1.5 2011/07/03 15:47:18 matthew Exp $ */
+/* $OpenBSD: mpath_hds.c,v 1.6 2011/07/11 01:02:48 dlg Exp $ */
/*
* Copyright (c) 2011 David Gwynne <dlg@openbsd.org>
@@ -89,11 +89,12 @@ int hds_mpath_checksense(struct scsi_xfer *);
int hds_mpath_online(struct scsi_link *);
int hds_mpath_offline(struct scsi_link *);
-struct mpath_ops hds_mpath_ops = {
+const struct mpath_ops hds_mpath_ops = {
"hds",
hds_mpath_checksense,
hds_mpath_online,
- hds_mpath_offline
+ hds_mpath_offline,
+ MPATH_ROUNDROBIN
};
struct hds_device {
@@ -152,7 +153,6 @@ hds_attach(struct device *parent, struct device *self, void *aux)
/* init path */
scsi_xsh_set(&sc->sc_path.p_xsh, link, hds_mpath_start);
sc->sc_path.p_link = link;
- sc->sc_path.p_ops = &hds_mpath_ops;
if (hds_inquiry(link, &sc->sc_mode) != 0) {
printf("%s: unable to query controller mode\n");
@@ -172,7 +172,7 @@ hds_attach(struct device *parent, struct device *self, void *aux)
if (!preferred)
return;
- if (mpath_path_attach(&sc->sc_path) != 0)
+ if (mpath_path_attach(&sc->sc_path, &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 6420e942e4a..21c7d0692d2 100644
--- a/sys/scsi/mpath_rdac.c
+++ b/sys/scsi/mpath_rdac.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: mpath_rdac.c,v 1.6 2011/07/03 15:47:18 matthew Exp $ */
+/* $OpenBSD: mpath_rdac.c,v 1.7 2011/07/11 01:02:48 dlg Exp $ */
/*
* Copyright (c) 2010 David Gwynne <dlg@openbsd.org>
@@ -146,11 +146,12 @@ int rdac_mpath_checksense(struct scsi_xfer *);
int rdac_mpath_online(struct scsi_link *);
int rdac_mpath_offline(struct scsi_link *);
-struct mpath_ops rdac_mpath_ops = {
+const struct mpath_ops rdac_mpath_ops = {
"rdac",
rdac_mpath_checksense,
rdac_mpath_online,
rdac_mpath_offline,
+ MPATH_ROUNDROBIN
};
int rdac_c8(struct rdac_softc *);
@@ -208,7 +209,6 @@ rdac_attach(struct device *parent, struct device *self, void *aux)
/* init path */
scsi_xsh_set(&sc->sc_path.p_xsh, link, rdac_mpath_start);
sc->sc_path.p_link = link;
- sc->sc_path.p_ops = &rdac_mpath_ops;
if (rdac_c8(sc) != 0)
return;
@@ -216,7 +216,7 @@ rdac_attach(struct device *parent, struct device *self, void *aux)
if (rdac_c9(sc) != 0)
return;
- if (mpath_path_attach(&sc->sc_path) != 0)
+ if (mpath_path_attach(&sc->sc_path, &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 8839540a991..461370c1047 100644
--- a/sys/scsi/mpath_sym.c
+++ b/sys/scsi/mpath_sym.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: mpath_sym.c,v 1.5 2011/07/03 15:47:18 matthew Exp $ */
+/* $OpenBSD: mpath_sym.c,v 1.6 2011/07/11 01:02:48 dlg Exp $ */
/*
* Copyright (c) 2010 David Gwynne <dlg@openbsd.org>
@@ -65,11 +65,20 @@ int sym_mpath_checksense(struct scsi_xfer *);
int sym_mpath_online(struct scsi_link *);
int sym_mpath_offline(struct scsi_link *);
-struct mpath_ops sym_mpath_ops = {
+const struct mpath_ops sym_mpath_sym_ops = {
"sym",
sym_mpath_checksense,
sym_mpath_online,
- sym_mpath_offline
+ sym_mpath_offline,
+ MPATH_ROUNDROBIN
+};
+
+const struct mpath_ops sym_mpath_asym_ops = {
+ "sym",
+ sym_mpath_checksense,
+ sym_mpath_online,
+ sym_mpath_offline,
+ MPATH_MRU
};
struct sym_device {
@@ -84,6 +93,13 @@ struct sym_device sym_devices[] = {
{ "FUJITSU ", "MBD" }
};
+struct sym_device asym_devices[] = {
+/* " vendor " " device " */
+/* "01234567" "0123456789012345" */
+ { "DELL ", "MD1220 " },
+ { "Transtec", "PROVIGO1100" }
+};
+
int
sym_match(struct device *parent, void *match, void *aux)
{
@@ -102,6 +118,13 @@ sym_match(struct device *parent, void *match, void *aux)
bcmp(s->product, inq->product, strlen(s->product)) == 0)
return (3);
}
+ for (i = 0; i < nitems(asym_devices); i++) {
+ s = &asym_devices[i];
+
+ if (bcmp(s->vendor, inq->vendor, strlen(s->vendor)) == 0 &&
+ bcmp(s->product, inq->product, strlen(s->product)) == 0)
+ return (3);
+ }
return (0);
}
@@ -112,18 +135,32 @@ sym_attach(struct device *parent, struct device *self, void *aux)
struct sym_softc *sc = (struct sym_softc *)self;
struct scsi_attach_args *sa = aux;
struct scsi_link *link = sa->sa_sc_link;
+ struct scsi_inquiry_data *inq = sa->sa_inqbuf;
+ const struct mpath_ops *ops = &sym_mpath_sym_ops;
+ struct sym_device *s;
+ int i;
printf("\n");
+ /* check if we're an assymetric access device */
+ for (i = 0; i < nitems(asym_devices); i++) {
+ s = &asym_devices[i];
+
+ if (bcmp(s->vendor, inq->vendor, strlen(s->vendor)) == 0 &&
+ bcmp(s->product, inq->product, strlen(s->product)) == 0) {
+ ops = &sym_mpath_asym_ops;
+ break;
+ }
+ }
+
/* init link */
link->device_softc = sc;
/* init path */
scsi_xsh_set(&sc->sc_path.p_xsh, link, sym_mpath_start);
sc->sc_path.p_link = link;
- sc->sc_path.p_ops = &sym_mpath_ops;
- if (mpath_path_attach(&sc->sc_path) != 0)
+ if (mpath_path_attach(&sc->sc_path, ops) != 0)
printf("%s: unable to attach path\n", DEVNAME(sc));
}
diff --git a/sys/scsi/mpathvar.h b/sys/scsi/mpathvar.h
index bff517ea52d..b826ff34e90 100644
--- a/sys/scsi/mpathvar.h
+++ b/sys/scsi/mpathvar.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: mpathvar.h,v 1.2 2011/04/28 10:43:36 dlg Exp $ */
+/* $OpenBSD: mpathvar.h,v 1.3 2011/07/11 01:02:48 dlg Exp $ */
/*
* Copyright (c) 2010 David Gwynne <dlg@openbsd.org>
@@ -27,13 +27,17 @@ struct mpath_ops {
int (*op_checksense)(struct scsi_xfer *);
int (*op_online)(struct scsi_link *);
int (*op_offline)(struct scsi_link *);
+ int op_schedule;
};
+#define MPATH_ROUNDROBIN 0 /* use all active paths */
+#define MPATH_NEXT MPATH_ROUNDROBIN
+#define MPATH_MRU 1 /* use most recently used path */
+
struct mpath_path {
/* the path driver must set these */
struct scsi_xshandler p_xsh;
struct scsi_link *p_link;
- struct mpath_ops *p_ops;
int p_gid;
/* the follwoing are private to mpath.c */
@@ -43,7 +47,8 @@ struct mpath_path {
};
int mpath_path_probe(struct scsi_link *);
-int mpath_path_attach(struct mpath_path *);
+int mpath_path_attach(struct mpath_path *,
+ const struct mpath_ops *);
void mpath_path_state(struct mpath_path *, int);
int mpath_path_detach(struct mpath_path *);