Skip to contentSkip to conversation

HP storage works support take 2

PATCH In review Mike Christie 2 participants 3 messages Jun 12, 2005

Subsystems (2)
lore
Share & tools
lore
#0 lore raw

PATCH 1/1 HP storage works support take 2

This should fix some bugs.

drivers/md/dm-hp-sw.c +160 -0
diff -Naurp linux-2.6.12-rc5.orig/drivers/md/dm-hp-sw.c linux-2.6.12-rc5/drivers/md/dm-hp-sw.c
@@ -0,0 +1,160 @@
+/*
+ * Copyright (C) 2005 Mike Christie, All rights reserved.
+ *
+ * This file is released under the GPL.
+ *
+ * Basic, very basic, support for HP StorageWorks and FSC FibreCat
+ */
+#include <scsi/scsi.h>
+#include <scsi/scsi_cmnd.h>
+
+#include "dm.h"
+#include "dm-hw-handler.h"
+
+struct hp_sw_handler {
+	unsigned char sense[SCSI_SENSE_BUFFERSIZE];
+};
+
+static void hp_sw_endio(struct request *rq)
+{
+	struct path *path = rq->end_io_data;
+
+	/*
+	 * TODO: something.. we have the sense and scsi bytes
+	 */
+	if (rq->errors) {
+		DMINFO("hp_sw: START_STOP completed %d", rq->errors);
+		dm_pg_init_complete(path, MP_FAIL_PATH);
+	} else
+		dm_pg_init_complete(path, 0);
+
+	blk_put_request(rq);
+}
+
+static struct request *hp_sw_get_request(struct hp_sw_handler *h,
+					struct path *path)
+{
+	struct request *rq;
+	struct block_device *bdev = path->dev->bdev;
+	struct request_queue *q = bdev_get_queue(bdev);
+
+	rq = blk_get_request(q, READ, __GFP_WAIT);
+	if (!rq)
+		return NULL;
+
+	rq->end_io = hp_sw_endio;
+	rq->end_io_data = path;
+	rq->rq_disk = bdev->bd_contains->bd_disk;
+	rq->sense = h->sense;
+	memset(rq->sense, 0, SCSI_SENSE_BUFFERSIZE);
+	rq->sense_len = 0;
+	/*
+	 * TODO: make me configurable
+	 */
+	rq->timeout = 30;
+	rq->flags |= (REQ_BLOCK_PC | REQ_FAILFAST | REQ_NOMERGE);
+
+	memset(&rq->cmd, 0, BLK_MAX_CDB);
+	rq->cmd[0] = START_STOP;
+	/* Start spin cycle */
+	rq->cmd[4] = 1;
+	rq->cmd_len = COMMAND_SIZE(rq->cmd[0]);
+
+	return rq;
+}
+
+static void hp_sw_pg_init(struct hw_handler *hwh, unsigned bypassed,
+			   struct path *path)
+{
+	struct request *rq;
+	struct request_queue *q = bdev_get_queue(path->dev->bdev);
+
+	/*
+	 * We can either blindly init the pg (then look at the sense),
+	 * or we can send some commands to get the state here (then
+	 * possibly send the fo cmnd), or we can also have the
+	 * initial state passed into us and then get an update here.
+	 */
+	if (!q) {
+		DMERR("hp_sw: no queue!");
+		goto fail_path;
+	}
+
+	if (blk_get_queue(q))
+		goto fail_path;
+
+	rq = hp_sw_get_request(hwh->context, path);
+	if (!rq) {
+		DMERR("hp_sw: could not allocate request for START_STOP");
+		goto rel_queue;
+	}
+
+	DMINFO("hp_sw: queueing START_STOP command");
+	elv_add_request(q, rq, ELEVATOR_INSERT_FRONT, 1);
+	blk_put_queue(q);
+	return;
+
+rel_queue:
+	blk_put_queue(q);
+fail_path:
+	dm_pg_init_complete(path, MP_FAIL_PATH);
+}
+
+static int hp_sw_create(struct hw_handler *hwh, unsigned argc, char **argv)
+{
+	struct hp_sw_handler *h;
+
+	h = kmalloc(sizeof(*h), GFP_KERNEL);
+	if (!h) {
+		DMERR("hp_sw: could not allocate hw_handler");
+		return -ENOMEM;
+	}
+
+	hwh->context = h;
+	return 0;
+}
+
+static void hp_sw_destroy(struct hw_handler *hwh)
+{
+	struct hp_sw_handler *h = hwh->context;
+
+	kfree(h);
+	hwh->context = NULL;
+}
+
+static struct hw_handler_type hp_sw_hwh = {
+	.name = "hp_sw",
+	.module = THIS_MODULE,
+	.create = hp_sw_create,
+	.destroy = hp_sw_destroy,
+	.pg_init = hp_sw_pg_init,
+};
+
+static int __init hp_sw_init(void)
+{
+	int r;
+
+	r = dm_register_hw_handler(&hp_sw_hwh);
+	if (r < 0)
+		DMERR("hp_sw: register failed %d", r);
+
+	DMINFO("hp_sw version 0.1 loaded");
+
+	return r;
+}
+
+static void __exit hp_sw_exit(void)
+{
+	int r;
+
+	r = dm_unregister_hw_handler(&hp_sw_hwh);
+	if (r < 0)
+		DMERR("hp_sw: unregister failed %d", r);
+}
+
+module_init(hp_sw_init);
+module_exit(hp_sw_exit);
+
+MODULE_DESCRIPTION("HP StorageWorks and FSC FibreCat support for dm-multipath");
+MODULE_AUTHOR("Mike Christie <[email protected]>");
+MODULE_LICENSE("GPL");
drivers/md/Kconfig +9 -0
diff -Naurp linux-2.6.12-rc5.orig/drivers/md/Kconfig linux-2.6.12-rc5/drivers/md/Kconfig
@@ -236,5 +236,14 @@ config DM_MULTIPATH_EMC
 	---help---
 	  Multipath support for EMC CX/AX series hardware.
 
+config DM_MULTIPATH_HP_SW
+	tristate "HP StorageWorks and FSC FibreCat (EXPERIMENTAL)"
+	depends on DM_MULTIPATH && BLK_DEV_DM && EXPERIMENTAL
+	---help---
+	  Multipath support for HP StorageWorks and FSC FibreCat.
+          This was created with no knowledge of the HW other than
+          that it uses a START_STOP command for failover so it
+          is marked EXPERIMENTAL.
+
 endmenu
 
drivers/md/Makefile +1 -0
diff -Naurp linux-2.6.12-rc5.orig/drivers/md/Makefile linux-2.6.12-rc5/drivers/md/Makefile
@@ -33,6 +33,7 @@ obj-$(CONFIG_BLK_DEV_DM)	+= dm-mod.o
 obj-$(CONFIG_DM_CRYPT)		+= dm-crypt.o
 obj-$(CONFIG_DM_MULTIPATH)	+= dm-multipath.o dm-round-robin.o
 obj-$(CONFIG_DM_MULTIPATH_EMC)	+= dm-emc.o
+obj-$(CONFIG_DM_MULTIPATH_HP_SW) += dm-hp-sw.o
 obj-$(CONFIG_DM_SNAPSHOT)	+= dm-snapshot.o
 obj-$(CONFIG_DM_MIRROR)		+= dm-mirror.o
 obj-$(CONFIG_DM_ZERO)		+= dm-zero.o
#1 lore raw

I told you I tried this simple fix, without success.

It is not enough, as it still hangs the kernel upon first io submited to the map.

I verified this even without any hardware, with ram disks. Here is a sample table :

[root@s64p17bibrn mce-dm-sstart]# dmsetup table toto: 0 1000 multipath 1 queue_if_no_path 1 hp_sw 2 1 round-robin 0 1 1 1:2 1000 round-robin 0 1 1 1:2 1000
[root@s64p17bibrn mce-dm-sstart]# dd if=/dev/mapper/toto of=/dev/null bs=512 count=1

<HANG>

Regards,
cvaroqui

Quoted 203 lines · Mike Christie

This should fix some bugs.

diff -Naurp linux-2.6.12-rc5.orig/drivers/md/dm-hp-sw.c linux-2.6.12-rc5/drivers/md/dm-hp-sw.c

drivers/md/dm-hp-sw.c +160 -0
@@ -0,0 +1,160 @@
+/*
+ * Copyright (C) 2005 Mike Christie, All rights reserved.
+ *
+ * This file is released under the GPL.
+ *
+ * Basic, very basic, support for HP StorageWorks and FSC FibreCat
+ */
+#include <scsi/scsi.h>
+#include <scsi/scsi_cmnd.h>
+
+#include "dm.h"
+#include "dm-hw-handler.h"
+
+struct hp_sw_handler {
+	unsigned char sense[SCSI_SENSE_BUFFERSIZE];
+};
+
+static void hp_sw_endio(struct request *rq)
+{
+	struct path *path = rq->end_io_data;
+
+	/*
+	 * TODO: something.. we have the sense and scsi bytes
+	 */
+	if (rq->errors) {
+		DMINFO("hp_sw: START_STOP completed %d", rq->errors);
+		dm_pg_init_complete(path, MP_FAIL_PATH);
+	} else
+		dm_pg_init_complete(path, 0);
+
+	blk_put_request(rq);
+}
+
+static struct request *hp_sw_get_request(struct hp_sw_handler *h,
+					struct path *path)
+{
+	struct request *rq;
+	struct block_device *bdev = path->dev->bdev;
+	struct request_queue *q = bdev_get_queue(bdev);
+
+	rq = blk_get_request(q, READ, __GFP_WAIT);
+	if (!rq)
+		return NULL;
+
+	rq->end_io = hp_sw_endio;
+	rq->end_io_data = path;
+	rq->rq_disk = bdev->bd_contains->bd_disk;
+	rq->sense = h->sense;
+	memset(rq->sense, 0, SCSI_SENSE_BUFFERSIZE);
+	rq->sense_len = 0;
+	/*
+	 * TODO: make me configurable
+	 */
+	rq->timeout = 30;
+	rq->flags |= (REQ_BLOCK_PC | REQ_FAILFAST | REQ_NOMERGE);
+
+	memset(&rq->cmd, 0, BLK_MAX_CDB);
+	rq->cmd[0] = START_STOP;
+	/* Start spin cycle */
+	rq->cmd[4] = 1;
+	rq->cmd_len = COMMAND_SIZE(rq->cmd[0]);
+
+	return rq;
+}
+
+static void hp_sw_pg_init(struct hw_handler *hwh, unsigned bypassed,
+			   struct path *path)
+{
+	struct request *rq;
+	struct request_queue *q = bdev_get_queue(path->dev->bdev);
+
+	/*
+	 * We can either blindly init the pg (then look at the sense),
+	 * or we can send some commands to get the state here (then
+	 * possibly send the fo cmnd), or we can also have the
+	 * initial state passed into us and then get an update here.
+	 */
+	if (!q) {
+		DMERR("hp_sw: no queue!");
+		goto fail_path;
+	}
+
+	if (blk_get_queue(q))
+		goto fail_path;
+
+	rq = hp_sw_get_request(hwh->context, path);
+	if (!rq) {
+		DMERR("hp_sw: could not allocate request for START_STOP");
+		goto rel_queue;
+	}
+
+	DMINFO("hp_sw: queueing START_STOP command");
+	elv_add_request(q, rq, ELEVATOR_INSERT_FRONT, 1);
+	blk_put_queue(q);
+	return;
+
+rel_queue:
+	blk_put_queue(q);
+fail_path:
+	dm_pg_init_complete(path, MP_FAIL_PATH);
+}
+
+static int hp_sw_create(struct hw_handler *hwh, unsigned argc, char **argv)
+{
+	struct hp_sw_handler *h;
+
+	h = kmalloc(sizeof(*h), GFP_KERNEL);
+	if (!h) {
+		DMERR("hp_sw: could not allocate hw_handler");
+		return -ENOMEM;
+	}
+
+	hwh->context = h;
+	return 0;
+}
+
+static void hp_sw_destroy(struct hw_handler *hwh)
+{
+	struct hp_sw_handler *h = hwh->context;
+
+	kfree(h);
+	hwh->context = NULL;
+}
+
+static struct hw_handler_type hp_sw_hwh = {
+	.name = "hp_sw",
+	.module = THIS_MODULE,
+	.create = hp_sw_create,
+	.destroy = hp_sw_destroy,
+	.pg_init = hp_sw_pg_init,
+};
+
+static int __init hp_sw_init(void)
+{
+	int r;
+
+	r = dm_register_hw_handler(&hp_sw_hwh);
+	if (r < 0)
+		DMERR("hp_sw: register failed %d", r);
+
+	DMINFO("hp_sw version 0.1 loaded");
+
+	return r;
+}
+
+static void __exit hp_sw_exit(void)
+{
+	int r;
+
+	r = dm_unregister_hw_handler(&hp_sw_hwh);
+	if (r < 0)
+		DMERR("hp_sw: unregister failed %d", r);
+}
+
+module_init(hp_sw_init);
+module_exit(hp_sw_exit);
+
+MODULE_DESCRIPTION("HP StorageWorks and FSC FibreCat support for dm-multipath");
+MODULE_AUTHOR("Mike Christie <[email protected]>");
+MODULE_LICENSE("GPL");

diff -Naurp linux-2.6.12-rc5.orig/drivers/md/Kconfig linux-2.6.12-rc5/drivers/md/Kconfig

drivers/md/Kconfig +9 -0
@@ -236,5 +236,14 @@ config DM_MULTIPATH_EMC
 	---help---
 	  Multipath support for EMC CX/AX series hardware.
 
+config DM_MULTIPATH_HP_SW
+	tristate "HP StorageWorks and FSC FibreCat (EXPERIMENTAL)"
+	depends on DM_MULTIPATH && BLK_DEV_DM && EXPERIMENTAL
+	---help---
+	  Multipath support for HP StorageWorks and FSC FibreCat.
+          This was created with no knowledge of the HW other than
+          that it uses a START_STOP command for failover so it
+          is marked EXPERIMENTAL.
+
 endmenu
 

diff -Naurp linux-2.6.12-rc5.orig/drivers/md/Makefile linux-2.6.12-rc5/drivers/md/Makefile

drivers/md/Makefile +1 -1
@@ -33,6 +33,7 @@ obj-$(CONFIG_BLK_DEV_DM)	+= dm-mod.o
 obj-$(CONFIG_DM_CRYPT)		+= dm-crypt.o
 obj-$(CONFIG_DM_MULTIPATH)	+= dm-multipath.o dm-round-robin.o
 obj-$(CONFIG_DM_MULTIPATH_EMC)	+= dm-emc.o
+obj-$(CONFIG_DM_MULTIPATH_HP_SW) += dm-hp-sw.o
 obj-$(CONFIG_DM_SNAPSHOT)	+= dm-snapshot.o
 obj-$(CONFIG_DM_MIRROR)		+= dm-mirror.o
 obj-$(CONFIG_DM_ZERO)		+= dm-zero.o
 
 
--

dm-devel mailing list
[email protected]
https://www.redhat.com/mailman/listinfo/dm-devel

Signature · 1 line
christophe varoqui <[email protected]>
#2 lore raw
Quoted 1 line · christophe varoqui

I told you I tried this simple fix, without success.

That fix is necessary. If the context does not get set then we will hit a null pointer reference like in your oops you reported.

In the mail you sent you said it hung on module load. I verified that and it worked here.

Quoted 4 lines

It is not enough, as it still hangs the kernel upon first io submited to the map.

this is news to me. I will test out your table when I get a chance.

Quoted 219 lines

I verified this even without any hardware, with ram disks. Here is a sample table :

[root@s64p17bibrn mce-dm-sstart]# dmsetup table toto: 0 1000 multipath 1 queue_if_no_path 1 hp_sw 2 1 round-robin 0 1 1 1:2 1000 round-robin 0 1 1 1:2 1000
[root@s64p17bibrn mce-dm-sstart]# dd if=/dev/mapper/toto of=/dev/null bs=512 count=1

<HANG>

Regards,
cvaroqui

Quoted 203 lines · Mike Christie

This should fix some bugs.

diff -Naurp linux-2.6.12-rc5.orig/drivers/md/dm-hp-sw.c linux-2.6.12-rc5/drivers/md/dm-hp-sw.c

drivers/md/dm-hp-sw.c +160 -0
@@ -0,0 +1,160 @@
+/*
+ * Copyright (C) 2005 Mike Christie, All rights reserved.
+ *
+ * This file is released under the GPL.
+ *
+ * Basic, very basic, support for HP StorageWorks and FSC FibreCat
+ */
+#include <scsi/scsi.h>
+#include <scsi/scsi_cmnd.h>
+
+#include "dm.h"
+#include "dm-hw-handler.h"
+
+struct hp_sw_handler {
+	unsigned char sense[SCSI_SENSE_BUFFERSIZE];
+};
+
+static void hp_sw_endio(struct request *rq)
+{
+	struct path *path = rq->end_io_data;
+
+	/*
+	 * TODO: something.. we have the sense and scsi bytes
+	 */
+	if (rq->errors) {
+		DMINFO("hp_sw: START_STOP completed %d", rq->errors);
+		dm_pg_init_complete(path, MP_FAIL_PATH);
+	} else
+		dm_pg_init_complete(path, 0);
+
+	blk_put_request(rq);
+}
+
+static struct request *hp_sw_get_request(struct hp_sw_handler *h,
+					struct path *path)
+{
+	struct request *rq;
+	struct block_device *bdev = path->dev->bdev;
+	struct request_queue *q = bdev_get_queue(bdev);
+
+	rq = blk_get_request(q, READ, __GFP_WAIT);
+	if (!rq)
+		return NULL;
+
+	rq->end_io = hp_sw_endio;
+	rq->end_io_data = path;
+	rq->rq_disk = bdev->bd_contains->bd_disk;
+	rq->sense = h->sense;
+	memset(rq->sense, 0, SCSI_SENSE_BUFFERSIZE);
+	rq->sense_len = 0;
+	/*
+	 * TODO: make me configurable
+	 */
+	rq->timeout = 30;
+	rq->flags |= (REQ_BLOCK_PC | REQ_FAILFAST | REQ_NOMERGE);
+
+	memset(&rq->cmd, 0, BLK_MAX_CDB);
+	rq->cmd[0] = START_STOP;
+	/* Start spin cycle */
+	rq->cmd[4] = 1;
+	rq->cmd_len = COMMAND_SIZE(rq->cmd[0]);
+
+	return rq;
+}
+
+static void hp_sw_pg_init(struct hw_handler *hwh, unsigned bypassed,
+			   struct path *path)
+{
+	struct request *rq;
+	struct request_queue *q = bdev_get_queue(path->dev->bdev);
+
+	/*
+	 * We can either blindly init the pg (then look at the sense),
+	 * or we can send some commands to get the state here (then
+	 * possibly send the fo cmnd), or we can also have the
+	 * initial state passed into us and then get an update here.
+	 */
+	if (!q) {
+		DMERR("hp_sw: no queue!");
+		goto fail_path;
+	}
+
+	if (blk_get_queue(q))
+		goto fail_path;
+
+	rq = hp_sw_get_request(hwh->context, path);
+	if (!rq) {
+		DMERR("hp_sw: could not allocate request for START_STOP");
+		goto rel_queue;
+	}
+
+	DMINFO("hp_sw: queueing START_STOP command");
+	elv_add_request(q, rq, ELEVATOR_INSERT_FRONT, 1);
+	blk_put_queue(q);
+	return;
+
+rel_queue:
+	blk_put_queue(q);
+fail_path:
+	dm_pg_init_complete(path, MP_FAIL_PATH);
+}
+
+static int hp_sw_create(struct hw_handler *hwh, unsigned argc, char **argv)
+{
+	struct hp_sw_handler *h;
+
+	h = kmalloc(sizeof(*h), GFP_KERNEL);
+	if (!h) {
+		DMERR("hp_sw: could not allocate hw_handler");
+		return -ENOMEM;
+	}
+
+	hwh->context = h;
+	return 0;
+}
+
+static void hp_sw_destroy(struct hw_handler *hwh)
+{
+	struct hp_sw_handler *h = hwh->context;
+
+	kfree(h);
+	hwh->context = NULL;
+}
+
+static struct hw_handler_type hp_sw_hwh = {
+	.name = "hp_sw",
+	.module = THIS_MODULE,
+	.create = hp_sw_create,
+	.destroy = hp_sw_destroy,
+	.pg_init = hp_sw_pg_init,
+};
+
+static int __init hp_sw_init(void)
+{
+	int r;
+
+	r = dm_register_hw_handler(&hp_sw_hwh);
+	if (r < 0)
+		DMERR("hp_sw: register failed %d", r);
+
+	DMINFO("hp_sw version 0.1 loaded");
+
+	return r;
+}
+
+static void __exit hp_sw_exit(void)
+{
+	int r;
+
+	r = dm_unregister_hw_handler(&hp_sw_hwh);
+	if (r < 0)
+		DMERR("hp_sw: unregister failed %d", r);
+}
+
+module_init(hp_sw_init);
+module_exit(hp_sw_exit);
+
+MODULE_DESCRIPTION("HP StorageWorks and FSC FibreCat support for dm-multipath");
+MODULE_AUTHOR("Mike Christie <[email protected]>");
+MODULE_LICENSE("GPL");

diff -Naurp linux-2.6.12-rc5.orig/drivers/md/Kconfig linux-2.6.12-rc5/drivers/md/Kconfig

drivers/md/Kconfig +9 -0
@@ -236,5 +236,14 @@ config DM_MULTIPATH_EMC
 	---help---
 	  Multipath support for EMC CX/AX series hardware.
 
+config DM_MULTIPATH_HP_SW
+	tristate "HP StorageWorks and FSC FibreCat (EXPERIMENTAL)"
+	depends on DM_MULTIPATH && BLK_DEV_DM && EXPERIMENTAL
+	---help---
+	  Multipath support for HP StorageWorks and FSC FibreCat.
+          This was created with no knowledge of the HW other than
+          that it uses a START_STOP command for failover so it
+          is marked EXPERIMENTAL.
+

endmenu

diff -Naurp linux-2.6.12-rc5.orig/drivers/md/Makefile linux-2.6.12-rc5/drivers/md/Makefile

drivers/md/Makefile +0 -0
@@ -33,6 +33,7 @@ obj-$(CONFIG_BLK_DEV_DM)	+= dm-mod.o

obj-$(CONFIG_DM_CRYPT) += dm-crypt.o
obj-$(CONFIG_DM_MULTIPATH) += dm-multipath.o dm-round-robin.o
obj-$(CONFIG_DM_MULTIPATH_EMC) += dm-emc.o
+obj-$(CONFIG_DM_MULTIPATH_HP_SW) += dm-hp-sw.o
obj-$(CONFIG_DM_SNAPSHOT) += dm-snapshot.o
obj-$(CONFIG_DM_MIRROR) += dm-mirror.o
obj-$(CONFIG_DM_ZERO) += dm-zero.o

--
dm-devel mailing list
[email protected]
https://www.redhat.com/mailman/listinfo/dm-devel