[dm-devel] [PATCH 9/9] scsi_dh: add scsi device handler to dm
Chandra Seetharaman
sekharan at us.ibm.com
Thu Jan 24 00:32:35 UTC 2008
Subject: scsi_dh: add scsi device handler to dm
From: Mike Anderson <andmike at linux.vnet.ibm.com>
This patch adds a dm hardware handler that can control SCSI device
handlers.
SCSI Hardware handler for a specific device type can be invokes by using
this handler.
For example, to use the lsi_rdac SCSI hardware handler, one would specify
hardware_handler "2 scsi_dh lsi_rdac"
in the device section of /etc/multipath.conf.
Signed-off-by: Mike Anderson <andmike at linux.vnet.ibm.com>
Signed-off-by: Chandra Seetharaman <sekharan at us.ibm.com>
---
drivers/md/Kconfig | 6 6 + 0 - 0 !
drivers/md/Makefile | 2 2 + 0 - 0 !
drivers/md/dm-mpath-scsi-dh.c | 185 185 + 0 - 0 !
3 files changed, 193 insertions(+)
Index: linux-2.6.24-rc8/drivers/md/Kconfig
===================================================================
--- linux-2.6.24-rc8.orig/drivers/md/Kconfig
+++ linux-2.6.24-rc8/drivers/md/Kconfig
@@ -273,6 +273,12 @@ config DM_MULTIPATH_HP
---help---
Multipath support for HP MSA (Active/Passive) series hardware.
+config DM_MULTIPATH_SCSI_DH
+ tristate "SCSI Device Handler support (EXPERIMENTAL)"
+ depends on DM_MULTIPATH && BLK_DEV_DM && EXPERIMENTAL
+ ---help---
+ Multipath support for SCSI Device Handlers.
+
config DM_DELAY
tristate "I/O delaying target (EXPERIMENTAL)"
depends on BLK_DEV_DM && EXPERIMENTAL
Index: linux-2.6.24-rc8/drivers/md/Makefile
===================================================================
--- linux-2.6.24-rc8.orig/drivers/md/Makefile
+++ linux-2.6.24-rc8/drivers/md/Makefile
@@ -9,6 +9,7 @@ dm-snapshot-objs := dm-snap.o dm-excepti
dm-mirror-objs := dm-log.o dm-raid1.o
dm-rdac-objs := dm-mpath-rdac.o
dm-hp-sw-objs := dm-mpath-hp-sw.o
+dm-scsi-dh-objs := dm-mpath-scsi-dh.o
md-mod-objs := md.o bitmap.o
raid456-objs := raid5.o raid6algos.o raid6recov.o raid6tables.o \
raid6int1.o raid6int2.o raid6int4.o \
@@ -38,6 +39,7 @@ obj-$(CONFIG_DM_MULTIPATH) += dm-multipa
obj-$(CONFIG_DM_MULTIPATH_EMC) += dm-emc.o
obj-$(CONFIG_DM_MULTIPATH_HP) += dm-hp-sw.o
obj-$(CONFIG_DM_MULTIPATH_RDAC) += dm-rdac.o
+obj-$(CONFIG_DM_MULTIPATH_SCSI_DH) += dm-scsi-dh.o
obj-$(CONFIG_DM_SNAPSHOT) += dm-snapshot.o
obj-$(CONFIG_DM_MIRROR) += dm-mirror.o
obj-$(CONFIG_DM_ZERO) += dm-zero.o
Index: linux-2.6.24-rc8/drivers/md/dm-mpath-scsi-dh.c
===================================================================
--- /dev/null
+++ linux-2.6.24-rc8/drivers/md/dm-mpath-scsi-dh.c
@@ -0,0 +1,185 @@
+/*
+ * SCSI Device handler
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Copyright IBM Corporation, 2007
+ * Author: Mike Anderson <andmike at linux.vnet.ibm.com>
+ */
+
+#define DM_MSG_PREFIX "multipath scsi_dh"
+
+#include "dm.h"
+#include "dm-hw-handler.h"
+
+struct scsi_dh_context {
+ char *hw_handler_name;
+ struct dm_path *path;
+};
+
+static int scsi_dh_create(struct hw_handler *hwh, unsigned argc, char **argv)
+{
+ struct scsi_dh_context *c;
+
+ c = kzalloc(sizeof(*c), GFP_KERNEL);
+ if (!c)
+ return -ENOMEM;
+ if (argc == 1) {
+ c->hw_handler_name = kstrdup(argv[0], GFP_KERNEL);
+ if (c->hw_handler_name)
+ request_module("scsi_dh_%s", c->hw_handler_name);
+ }
+
+ hwh->context = c;
+
+ return 0;
+}
+
+static void scsi_dh_destroy(struct hw_handler *hwh)
+{
+ struct scsi_dh_context *c = hwh->context;
+ kfree(c->hw_handler_name);
+ kfree(c);
+ hwh->context = NULL;
+ return;
+}
+
+static unsigned scsi_dh_error(struct hw_handler *hwh, struct bio *bio)
+{
+ /* Try default handler */
+ return dm_scsi_err_handler(hwh, bio);
+}
+
+
+static void pg_init_done(struct request *req, int err)
+{
+ struct scsi_dh_context *c = req->end_io_data;
+ int ret = 0;
+
+ if (blkerr_transport_err(req->errors)) {
+ /*
+ * Old dm behavior had us fail a path on any error.
+ * In future patches, since we have finer grained errors now,
+ * we do not have to fail the path on the first transient
+ * error.
+ */
+ ret = MP_FAIL_PATH;
+ goto out;
+ }
+
+ /* device or driver problems */
+ switch (req->errors) {
+ case BLKERR_OK:
+ break;
+ case BLKERR_NOSYS:
+ if (!c->hw_handler_name)
+ break;
+ DMERR("Cannot failover device because hw-%s may not be "
+ "loaded.", c->hw_handler_name);
+ /*
+ * Fail path for now, so we do not ping poing
+ */
+ ret = MP_FAIL_PATH;
+ break;
+ case BLKERR_DEV_TEMP_BUSY:
+ /*
+ * Probably doing something like FW upgrade on the
+ * controller so try the other pg.
+ */
+ ret = MP_BYPASS_PG;
+ break;
+ /* TODO: For BLKERR_RETRY we should wait a couple seconds */
+ case BLKERR_RETRY:
+ case BLKERR_IMM_RETRY:
+ case BLKERR_RES_TEMP_UNAVAIL:
+ break;
+ default:
+ /*
+ * We probably do not want to fail the path for a device
+ * error, but this is what the old dm did. In future
+ * patches we can do more advanced handling.
+ */
+ ret = MP_FAIL_PATH;
+ }
+
+out:
+ dm_pg_init_complete(c->path, ret);
+ __blk_put_request(req->q, req);
+ return;
+}
+
+static void scsi_dh_pg_init(struct hw_handler *hwh, unsigned bypassed,
+ struct dm_path *path)
+{
+ struct scsi_dh_context *c = hwh->context;
+ struct request *req;
+
+ req = blk_get_request(bdev_get_queue(path->dev->bdev), 1, GFP_NOIO);
+ if (!req) {
+ /* FIXME: Add retry */
+ dm_pg_init_complete(path, MP_FAIL_PATH);
+ return;
+ }
+
+ req->cmd[0] = REQ_LB_OP_TRANSITION;
+ req->cmd_type = REQ_TYPE_LINUX_BLOCK;
+ c->path = path;
+ req->end_io_data = c;
+ /* TODO: does this need to be configurable or is it HW specific? */
+ req->retries = 5;
+ blk_execute_rq_nowait(req->q, NULL, req, 1, pg_init_done);
+}
+
+#define SCSI_DH_NAME "scsi_dh"
+#define SCSI_DH_VER "0.1"
+
+static struct hw_handler_type scsi_dh_handler = {
+ .name = SCSI_DH_NAME,
+ .module = THIS_MODULE,
+ .create = scsi_dh_create,
+ .destroy = scsi_dh_destroy,
+ .pg_init = scsi_dh_pg_init,
+ .error = scsi_dh_error,
+};
+
+static int __init scsi_dh_init(void)
+{
+ int r;
+
+ r = dm_register_hw_handler(&scsi_dh_handler);
+ if (r < 0) {
+ DMERR("%s: register failed %d", SCSI_DH_NAME, r);
+ return r;
+ }
+
+ DMINFO("%s: version %s loaded", SCSI_DH_NAME, SCSI_DH_VER);
+ return 0;
+}
+
+static void __exit scsi_dh_exit(void)
+{
+ int r = dm_unregister_hw_handler(&scsi_dh_handler);
+
+ if (r < 0)
+ DMERR("%s: unregister failed %d", SCSI_DH_NAME, r);
+}
+
+module_init(scsi_dh_init);
+module_exit(scsi_dh_exit);
+
+MODULE_DESCRIPTION("DM Multipath SCSI Device Handler support");
+MODULE_AUTHOR("Mike Anderson <andmike at linux.vnet.ibm.com");
+MODULE_LICENSE("GPL");
+MODULE_VERSION(SCSI_DH_VER);
--
----------------------------------------------------------------------
Chandra Seetharaman | Be careful what you choose....
- sekharan at us.ibm.com | .......you may get it.
----------------------------------------------------------------------
More information about the dm-devel
mailing list