the subject line says it all, but happy to explain further if
required.
Index: mpath.c
===================================================================
RCS file: /cvs/src/sys/scsi/mpath.c,v
retrieving revision 1.21
diff -u -p -r1.21 mpath.c
--- mpath.c 27 Apr 2011 05:22:24 -0000 1.21
+++ mpath.c 15 Jun 2011 08:03:06 -0000
@@ -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;
@@ -403,6 +408,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;
Index: mpath_emc.c
===================================================================
RCS file: /cvs/src/sys/scsi/mpath_emc.c,v
retrieving revision 1.5
diff -u -p -r1.5 mpath_emc.c
--- mpath_emc.c 15 Jun 2011 01:10:50 -0000 1.5
+++ mpath_emc.c 15 Jun 2011 08:03:06 -0000
@@ -94,11 +94,12 @@ int emc_mpath_checksense(struct scsi_xf
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
/* 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
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));
}
}
Index: mpath_hds.c
===================================================================
RCS file: /cvs/src/sys/scsi/mpath_hds.c,v
retrieving revision 1.4
diff -u -p -r1.4 mpath_hds.c
--- mpath_hds.c 15 Jun 2011 01:44:14 -0000 1.4
+++ mpath_hds.c 15 Jun 2011 08:03:06 -0000
@@ -89,11 +89,12 @@ int hds_mpath_checksense(struct scsi_xf
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
/* 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
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));
}
Index: mpath_rdac.c
===================================================================
RCS file: /cvs/src/sys/scsi/mpath_rdac.c,v
retrieving revision 1.5
diff -u -p -r1.5 mpath_rdac.c
--- mpath_rdac.c 15 Jun 2011 01:47:41 -0000 1.5
+++ mpath_rdac.c 15 Jun 2011 08:03:06 -0000
@@ -146,11 +146,12 @@ int rdac_mpath_checksense(struct scsi_x
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, struc
/* 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, struc
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));
}
Index: mpath_sym.c
===================================================================
RCS file: /cvs/src/sys/scsi/mpath_sym.c,v
retrieving revision 1.4
diff -u -p -r1.4 mpath_sym.c
--- mpath_sym.c 15 Jun 2011 01:51:44 -0000 1.4
+++ mpath_sym.c 15 Jun 2011 08:03:06 -0000
@@ -65,11 +65,20 @@ int sym_mpath_checksense(struct scsi_xf
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_LRU
};
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 *m
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
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));
}
Index: mpathvar.h
===================================================================
RCS file: /cvs/src/sys/scsi/mpathvar.h,v
retrieving revision 1.2
diff -u -p -r1.2 mpathvar.h
--- mpathvar.h 28 Apr 2011 10:43:36 -0000 1.2
+++ mpathvar.h 15 Jun 2011 08:03:06 -0000
@@ -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
+#define MPATH_NEXT MPATH_ROUNDROBIN
+#define MPATH_LRU 1
+
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 *);