HP storage works support take 2
Subsystems (2)
PATCH 1/1 HP storage works support take 2
This should fix some bugs.
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" );
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
drivers/md/Makefile +1 -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
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.clinux-2.6.12-rc5/drivers/md/dm-hp-sw.cdrivers/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. + endmenudiff -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]>
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_path1hp_sw2 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,
cvaroquiQuoted 203 lines · Mike Christie
This should fix some bugs.
diff -Naurp
linux-2.6.12-rc5.orig/drivers/md/dm-hp-sw.clinux-2.6.12-rc5/drivers/md/dm-hp-sw.cdrivers/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.oobj-$(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