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 *);

Reply via email to